@jonathanleelx/meddle 0.5.0-beta.19 → 0.5.0-beta.20

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.
Files changed (37) hide show
  1. package/dist/core/mock-handler.d.ts +7 -0
  2. package/dist/core/mock-handler.d.ts.map +1 -1
  3. package/dist/core/mock-handler.js +136 -7
  4. package/dist/core/mock-handler.js.map +1 -1
  5. package/dist/server/mocks.js +3 -3
  6. package/dist/server/mocks.js.map +1 -1
  7. package/package.json +1 -1
  8. package/web/dist/assets/{detail-panel-DyvoHlCG.js → detail-panel-CO_7xRlW.js} +3 -3
  9. package/web/dist/assets/{global-panel-shell-BJaQ_VLp.js → global-panel-shell-dKKTLNpP.js} +3 -3
  10. package/web/dist/assets/{health-panel-BnxNCGvw.js → health-panel-CUEWcU8g.js} +1 -1
  11. package/web/dist/assets/{index-Bu3zaxzE.js → index-B9-_OFNJ.js} +2 -2
  12. package/web/dist/assets/{mobile-proxy-panel-BxJ8OmLu.js → mobile-proxy-panel-smm4Pg7o.js} +2 -2
  13. package/web/dist/assets/mock-config-BA0GNr6q.js +1 -0
  14. package/web/dist/assets/mock-editor-panel-ttVorhGI.js +20 -0
  15. package/web/dist/assets/{mocks-file-missing-note-B8TTBWtG.js → mocks-file-missing-note-DBYZjOpC.js} +1 -1
  16. package/web/dist/assets/{monaco-editor-DeJNlo9k.js → monaco-editor-DH2CE6FN.js} +1 -1
  17. package/web/dist/assets/{pane-split-Db1aWKUO.js → pane-split-40_YQZ0-.js} +1 -1
  18. package/web/dist/assets/{panel-heading-BAI_lNmT.js → panel-heading-BaLG_KAE.js} +1 -1
  19. package/web/dist/assets/plugin-code-editor-B2Sc5Ngy.js +2 -0
  20. package/web/dist/assets/plugin-config-nnVWs8jW.js +2 -0
  21. package/web/dist/assets/plugin-generator-B2CAEqPa.js +2 -0
  22. package/web/dist/assets/plugin-test-dialog-BU0As6z0.js +7 -0
  23. package/web/dist/assets/{route-preview-BZ3vhvsc.js → route-preview-Do3jsXLI.js} +1 -1
  24. package/web/dist/assets/{rule-ai-assistant-panel-DfivYxZH.js → rule-ai-assistant-panel-g-UkLb_B.js} +2 -2
  25. package/web/dist/assets/rule-config-Bzw8J0q1.js +15 -0
  26. package/web/dist/assets/rule-overview-panel-DIBRGnrb.js +1 -0
  27. package/web/dist/assets/settings-panel-CrvG4M_b.js +1 -0
  28. package/web/dist/index.html +1 -1
  29. package/web/dist/assets/mock-config-Dp2D5iiv.js +0 -1
  30. package/web/dist/assets/mock-editor-panel-zqouxTGb.js +0 -20
  31. package/web/dist/assets/plugin-code-editor-CQqpaaCR.js +0 -2
  32. package/web/dist/assets/plugin-config-CjcRhSZm.js +0 -2
  33. package/web/dist/assets/plugin-generator-Cr_gk3Tp.js +0 -2
  34. package/web/dist/assets/plugin-test-dialog-B5mVM3XE.js +0 -7
  35. package/web/dist/assets/rule-config-DSX8bBHe.js +0 -15
  36. package/web/dist/assets/rule-overview-panel-D5gY3akK.js +0 -1
  37. package/web/dist/assets/settings-panel-Bfzfsovk.js +0 -1
@@ -0,0 +1 @@
1
+ import{c as e,d as t,p as n,t as r}from"./button-BFNlGZ5p.js";import"./dist-CFZ4xMSF.js";import{t as i}from"./refresh-cw-BfLoHqg5.js";import{t as ee}from"./table-2-DvGHhMm4.js";import{Ct as a,G as o,H as s,K as c,Ot as l,U as u,V as d,W as f,dt as p,et as m,it as h,m as g,nt as _,q as v,rt as te,tt as y,yt as b}from"./index-B9-_OFNJ.js";import{a as x,i as S,n as C,o as w,r as T,t as E}from"./table-C3mgEjkP.js";var D=n(t(),1),O=e(),k=`border-l-2 border-l-transparent`,A=`text-muted-foreground opacity-75`;function j(e){return e.length>0?e.map(e=>`!${e}`).join(` `):`—`}function M({rules:e,activeFileName:t,onLocateRule:n,onSelectFile:M}){let[N,ne]=(0,D.useState)(null),[P,F]=(0,D.useState)(!0),[I,L]=(0,D.useState)(null),[R,z]=(0,D.useState)(`merged`),[B,V]=(0,D.useState)(``),H=(0,D.useDeferredValue)(B),U=(0,D.useCallback)(async()=>{F(!0),L(null);try{let e=await fetch(`/api/rule-files/overview`);if(!e.ok)throw Error(`加载失败(${e.status})`);ne(await e.json())}catch(e){L(e instanceof Error?e.message:`加载失败`)}finally{F(!1)}},[]);(0,D.useEffect)(()=>{U()},[U]);let W=(0,D.useMemo)(()=>N?.perFileRules.find(e=>e.name===t)??null,[N,t]),G=(0,D.useMemo)(()=>{if(!W||W.error)return!1;let t=W.rules.map(e=>({rule:e.rawRule,target:e.rawTarget,enabled:e.enabled,exclusions:e.exclusions}));return g(e)!==g(t)},[W,e]),K=(0,D.useMemo)(()=>{let e=new Map;for(let t of N?.conflicts??[])e.set(t.pattern,t);return e},[N]),q=(0,D.useCallback)(e=>{let t=H.trim().toLowerCase();return t?e.some(e=>e&&e.toLowerCase().includes(t)):!0},[H]),J=(0,D.useMemo)(()=>(N?.mergedRules??[]).map(e=>({winner:e,shadowed:K.get(e.pattern)?.shadowed??[]})).filter(({winner:e,shadowed:t})=>q([e.rawRule,e.rawTarget,e.file])||t.some(e=>q([e.rawRule,e.rawTarget,e.file]))),[N,K,q]),Y=N?.mergedRules.length??0,X=N?.conflicts.reduce((e,t)=>e+t.shadowed.length,0)??0,Z=(0,D.useMemo)(()=>(N?.perFileRules??[]).map(e=>({...e,matched:e.rules.filter(t=>q([t.rawRule,t.rawTarget,e.name]))})).filter(e=>e.error!=null||q([e.name])||e.matched.length>0),[N,q]),re=N?.perFileRules.reduce((e,t)=>e+t.rules.length,0)??0,ie=Z.reduce((e,t)=>e+t.matched.length,0),Q=(0,D.useCallback)((e,t,r)=>{n(e,t,r)},[n]),ae=(0,D.useCallback)((e,t)=>{(e.key===`Enter`||e.key===` `)&&(e.preventDefault(),M(t))},[M]),oe=()=>{if(P)return(0,O.jsxs)(`div`,{className:`flex min-h-0 flex-1 flex-col gap-2 p-2`,children:[(0,O.jsx)(h,{className:`h-8 w-full`}),(0,O.jsx)(h,{className:`h-8 w-full`}),(0,O.jsx)(h,{className:`h-8 w-3/4`})]});if(I)return(0,O.jsxs)(s,{className:`min-h-0 flex-1`,children:[(0,O.jsxs)(o,{children:[(0,O.jsx)(c,{variant:`icon`,children:(0,O.jsx)(p,{})}),(0,O.jsx)(v,{children:`加载失败`}),(0,O.jsx)(f,{children:I})]}),(0,O.jsx)(u,{children:(0,O.jsxs)(r,{variant:`outline`,onClick:()=>void U(),children:[(0,O.jsx)(i,{"data-icon":`inline-start`}),`重试`]})})]});let e=(N?.files.length??0)>0,t=N?.perFileRules.some(e=>e.rules.length>0||e.error!=null)??!1,n=H.trim().length>0;return e?t?R===`merged`&&!n&&(N?.mergedRules.length??0)===0?(0,O.jsx)(s,{className:`min-h-0 flex-1`,children:(0,O.jsxs)(o,{children:[(0,O.jsx)(c,{variant:`icon`,children:(0,O.jsx)(a,{})}),(0,O.jsx)(v,{children:`没有生效中的规则`}),(0,O.jsx)(f,{children:`规则全部被禁用,或没有启用任何规则文件;切换到「按文件」查看全部规则`})]})}):n&&R===`merged`&&J.length===0||n&&R===`files`&&Z.every(e=>e.matched.length===0&&e.error==null)?$():R===`merged`?se():ce():(0,O.jsx)(s,{className:`min-h-0 flex-1`,children:(0,O.jsxs)(o,{children:[(0,O.jsx)(c,{variant:`icon`,children:(0,O.jsx)(l,{})}),(0,O.jsx)(v,{children:`所有规则文件都是空的`}),(0,O.jsx)(f,{children:`还没有任何路由规则,先去路由规则页添加一条吧`})]})}):(0,O.jsx)(s,{className:`min-h-0 flex-1`,children:(0,O.jsxs)(o,{children:[(0,O.jsx)(c,{variant:`icon`,children:(0,O.jsx)(ee,{})}),(0,O.jsx)(v,{children:`还没有规则文件`}),(0,O.jsx)(f,{children:`在路由规则页点击「+」创建第一个规则文件`})]})})},$=()=>(0,O.jsxs)(s,{className:`min-h-0 flex-1`,children:[(0,O.jsxs)(o,{children:[(0,O.jsx)(c,{variant:`icon`,children:(0,O.jsx)(b,{})}),(0,O.jsx)(v,{children:`无匹配结果`}),(0,O.jsxs)(f,{children:[`没有找到符合「`,H.trim(),`」的规则`]})]}),(0,O.jsx)(u,{children:(0,O.jsx)(r,{variant:`outline`,onClick:()=>V(``),children:`清空筛选`})})]}),se=()=>(0,O.jsxs)(`div`,{className:`flex min-h-0 flex-1 flex-col overflow-hidden rounded-md border`,children:[(0,O.jsx)(`div`,{className:`meddle-thin-scroll shrink-0 overflow-x-auto bg-card`,children:(0,O.jsxs)(E,{className:`table-fixed`,children:[(0,O.jsxs)(`colgroup`,{children:[(0,O.jsx)(`col`,{style:{width:`6rem`}}),(0,O.jsx)(`col`,{}),(0,O.jsx)(`col`,{style:{width:`8rem`}}),(0,O.jsx)(`col`,{})]}),(0,O.jsx)(x,{children:(0,O.jsxs)(w,{children:[(0,O.jsx)(S,{children:`来源`}),(0,O.jsx)(S,{children:`规则`}),(0,O.jsx)(S,{className:`hidden md:table-cell`,children:`排除`}),(0,O.jsx)(S,{children:`目标`})]})})]})}),(0,O.jsx)(d,{className:`min-h-0 flex-1`,children:(0,O.jsxs)(E,{className:`table-fixed`,children:[(0,O.jsxs)(`colgroup`,{children:[(0,O.jsx)(`col`,{style:{width:`6rem`}}),(0,O.jsx)(`col`,{}),(0,O.jsx)(`col`,{style:{width:`8rem`}}),(0,O.jsx)(`col`,{})]}),(0,O.jsx)(C,{children:J.map(({winner:e,shadowed:t})=>(0,O.jsxs)(D.Fragment,{children:[(0,O.jsxs)(w,{className:`${k} cursor-pointer`,onClick:()=>Q(e.file,e.rawRule,e.rawTarget),title:`点击定位到该规则`,children:[(0,O.jsx)(T,{className:`truncate text-xs text-muted-foreground`,children:e.file}),(0,O.jsxs)(T,{className:`break-all font-mono text-xs`,children:[e.rawRule,t.length>0&&(0,O.jsx)(_,{variant:`default`,className:`ml-2 px-1 py-0 text-[10px]`,title:`同名规则最终生效的定义`,children:`生效`})]}),(0,O.jsx)(T,{className:`hidden break-all font-mono text-xs text-muted-foreground md:table-cell`,children:j(e.exclusions)}),(0,O.jsx)(T,{className:`break-all font-mono text-xs`,children:e.rawTarget})]}),t.map((t,n)=>(0,O.jsxs)(w,{className:`${k} cursor-pointer ${A}`,onClick:()=>Q(t.file,t.rawRule,t.rawTarget),title:`点击定位到该规则`,children:[(0,O.jsx)(T,{className:`truncate text-xs`,children:t.file}),(0,O.jsx)(T,{className:`break-all font-mono text-xs`,children:(0,O.jsxs)(`span`,{className:`inline-flex flex-wrap items-center gap-1.5`,children:[t.rawRule,(0,O.jsx)(_,{variant:`destructive`,className:`px-1 py-0 text-[10px]`,title:`已被 ${e.file} 中的同名规则覆盖,实际不生效`,children:`已被覆盖`})]})}),(0,O.jsx)(T,{className:`hidden break-all font-mono text-xs md:table-cell`,children:`—`}),(0,O.jsx)(T,{className:`break-all font-mono text-xs`,children:t.rawTarget})]},`merged-shadowed-${n}`))]},`merged-group-${e.pattern}`))})]})})]}),ce=()=>(0,O.jsxs)(`div`,{className:`flex min-h-0 flex-1 flex-col overflow-hidden rounded-md border`,children:[(0,O.jsx)(`div`,{className:`meddle-thin-scroll shrink-0 overflow-x-auto bg-card`,children:(0,O.jsxs)(E,{className:`table-fixed`,children:[(0,O.jsxs)(`colgroup`,{children:[(0,O.jsx)(`col`,{style:{width:`3.5rem`}}),(0,O.jsx)(`col`,{}),(0,O.jsx)(`col`,{style:{width:`8rem`}}),(0,O.jsx)(`col`,{})]}),(0,O.jsx)(x,{children:(0,O.jsxs)(w,{children:[(0,O.jsx)(S,{children:`状态`}),(0,O.jsx)(S,{children:`规则`}),(0,O.jsx)(S,{className:`hidden md:table-cell`,children:`排除`}),(0,O.jsx)(S,{children:`目标`})]})})]})}),(0,O.jsx)(d,{className:`min-h-0 flex-1`,children:(0,O.jsxs)(E,{className:`table-fixed`,children:[(0,O.jsxs)(`colgroup`,{children:[(0,O.jsx)(`col`,{style:{width:`3.5rem`}}),(0,O.jsx)(`col`,{}),(0,O.jsx)(`col`,{style:{width:`8rem`}}),(0,O.jsx)(`col`,{})]}),(0,O.jsx)(C,{children:Z.map(e=>(0,O.jsxs)(D.Fragment,{children:[(0,O.jsx)(w,{className:`hover:bg-accent/60`,children:(0,O.jsx)(T,{colSpan:4,className:`cursor-pointer bg-muted/50 p-2 align-middle`,role:`button`,tabIndex:0,onClick:()=>M(e.name),onKeyDown:t=>ae(t,e.name),title:`点击切换到该规则文件`,children:(0,O.jsxs)(`span`,{className:`flex flex-wrap items-center gap-2 font-medium`,children:[e.name,(0,O.jsx)(_,{variant:e.enabled?`default`:`secondary`,className:`px-1 py-0 text-[10px]`,children:e.enabled?`启用`:`禁用`}),(0,O.jsx)(_,{variant:`secondary`,className:`px-1 py-0 text-[10px]`,children:e.rules.length})]})})}),e.error&&(0,O.jsx)(w,{className:`text-destructive`,children:(0,O.jsx)(T,{colSpan:4,className:`p-2 text-xs`,children:(0,O.jsxs)(`span`,{className:`flex items-center gap-2`,children:[(0,O.jsx)(p,{className:`h-3.5 w-3.5 shrink-0`}),`读取失败:`,e.error]})})}),e.matched.map((t,n)=>(0,O.jsxs)(w,{className:`cursor-pointer ${t.enabled?``:`opacity-60`}`,onClick:()=>Q(e.name,t.rawRule,t.rawTarget),title:`点击定位到该规则`,children:[(0,O.jsx)(T,{children:(0,O.jsx)(_,{variant:t.enabled?`default`:`secondary`,className:`px-1 py-0 text-[10px]`,children:t.enabled?`启用`:`禁用`})}),(0,O.jsx)(T,{className:`break-all font-mono text-xs`,children:t.rawRule}),(0,O.jsx)(T,{className:`hidden break-all font-mono text-xs text-muted-foreground md:table-cell`,children:j(t.exclusions)}),(0,O.jsx)(T,{className:`break-all font-mono text-xs ${t.enabled?``:`line-through`}`,children:t.rawTarget})]},`file-rule-${n}`))]},`file-group-${e.name}`))})]})})]}),le=R===`merged`?Y+X:re,ue=R===`merged`?J.reduce((e,t)=>e+1+t.shadowed.length,0):ie;return(0,O.jsxs)(`div`,{className:`app-panel-content flex h-full flex-col gap-3`,children:[(0,O.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,O.jsxs)(m,{type:`single`,value:R,onValueChange:e=>{e&&z(e)},variant:`outline`,size:`sm`,className:`bg-background`,"aria-label":`总览视图`,children:[(0,O.jsx)(y,{value:`merged`,children:`生效规则`}),(0,O.jsx)(y,{value:`files`,children:`按文件`})]}),(0,O.jsxs)(`div`,{className:`relative min-w-40 flex-1`,children:[(0,O.jsx)(b,{className:`pointer-events-none absolute top-1/2 left-2 h-4 w-4 -translate-y-1/2 text-muted-foreground`}),(0,O.jsx)(te,{value:B,onChange:e=>V(e.target.value),placeholder:`搜索规则 / 目标 / 文件名`,className:`h-8 pl-8`,"aria-label":`搜索规则`})]}),(0,O.jsx)(r,{type:`button`,variant:`ghost`,size:`icon-sm`,onClick:()=>void U(),disabled:P,"aria-label":`刷新总览`,title:`刷新`,children:(0,O.jsx)(i,{})})]}),G&&(0,O.jsxs)(`div`,{className:`flex items-center gap-2 rounded-md border border-amber-200 bg-amber-50 px-3 py-2 text-xs text-amber-800`,children:[(0,O.jsx)(p,{className:`h-3.5 w-3.5 shrink-0`}),(0,O.jsxs)(`span`,{children:[`「`,t,`」有未保存修改,此处展示的是代理当前使用的`,(0,O.jsx)(`b`,{children:`已保存内容`})]})]}),!P&&!I&&(N?.files.length??0)>0&&(0,O.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-2 text-xs text-muted-foreground`,children:[(0,O.jsxs)(`span`,{children:[ue,` / `,le,` 条`,R===`merged`&&H.trim()===``&&X>0?`,其中 ${X} 条被同名规则覆盖`:``]}),R===`merged`&&(0,O.jsx)(`span`,{children:`按代理实际生效顺序排列(后定义覆盖先定义)`}),R===`files`&&(0,O.jsx)(`span`,{children:`点击文件名切换到该文件`})]}),oe()]})}export{M as RuleOverviewPanel};
@@ -0,0 +1 @@
1
+ import{c as e,d as t,p as n,t as r,u as i}from"./button-BFNlGZ5p.js";import"./dist-CFZ4xMSF.js";import{t as ee}from"./check-BkfHQ6re.js";import{t as a}from"./circle-alert-zMagrFuI.js";import{t as o}from"./circle-x-BEkinhez.js";import{t as s}from"./plus-ixZQRprm.js";import{t as te}from"./refresh-cw-BfLoHqg5.js";import{t as ne}from"./rotate-ccw-CRguJya4.js";import{t as re}from"./smartphone-D4Q7cQfm.js";import"./es2015-CRmLuA2o.js";import{t as ie}from"./switch-DpLnRvOJ.js";import{a as c,c as ae,l as oe,n as se,o as ce,r as l,s as le,t as ue}from"./ai-config-store-B_VpGvwx.js";import{$ as u,A as d,D as de,E as fe,Et as pe,F as f,Ft as p,I as me,J as he,L as m,Mt as h,O as ge,P as _e,Q as ve,S as g,T as ye,Tt as be,X as xe,Y as Se,Z as _,_ as Ce,_t as we,b as Te,bt as v,c as Ee,et as y,ft as De,g as Oe,h as ke,ht as Ae,k as je,l as Me,nt as b,rt as x,s as Ne,tt as S,u as Pe,v as C,vt as Fe,w,x as Ie,y as T}from"./index-B9-_OFNJ.js";import{n as Le,r as Re,t as ze}from"./alert-BmsRCcSL.js";import{i as Be,n as Ve}from"./mocks-file-missing-note-DBYZjOpC.js";var He=i(`eye-off`,[[`path`,{d:`M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49`,key:`ct8e1f`}],[`path`,{d:`M14.084 14.158a3 3 0 0 1-4.242-4.242`,key:`151rxh`}],[`path`,{d:`M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143`,key:`13bj9a`}],[`path`,{d:`m2 2 20 20`,key:`1ooewy`}]]),Ue=i(`eye`,[[`path`,{d:`M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0`,key:`1nclc0`}],[`circle`,{cx:`12`,cy:`12`,r:`3`,key:`1v7zrd`}]]),We=i(`stethoscope`,[[`path`,{d:`M11 2v2`,key:`1539x4`}],[`path`,{d:`M5 2v2`,key:`1yf1q8`}],[`path`,{d:`M5 3H4a2 2 0 0 0-2 2v4a6 6 0 0 0 12 0V5a2 2 0 0 0-2-2h-1`,key:`rb5t3r`}],[`path`,{d:`M8 15a6 6 0 0 0 12 0v-3`,key:`x18d4x`}],[`circle`,{cx:`20`,cy:`10`,r:`2`,key:`ts1r5v`}]]),E=n(t(),1);async function Ge(){try{let e=await fetch(`/api/version`);if(!e.ok)return null;let t=await e.json();return t&&typeof t==`object`&&typeof t.version==`string`&&t.version.trim()||null}catch{return null}}var D=e(),Ke=[{value:`75`,label:`75%`,scale:.75},{value:`90`,label:`90%`,scale:.9},{value:`100`,label:`100%`,scale:1},{value:`110`,label:`110%`,scale:1.1},{value:`125`,label:`125%`,scale:1.25},{value:`150`,label:`150%`,scale:1.5}],qe=[{value:`auto`,label:`自动`,color:`linear-gradient(135deg, oklch(0.623 0.214 259.815), oklch(0.606 0.25 292.717))`},{value:`neutral`,label:`中性`,color:`oklch(0.556 0 0)`},{value:`blue`,label:`蓝色`,color:`oklch(0.623 0.214 259.815)`},{value:`violet`,label:`紫色`,color:`oklch(0.606 0.25 292.717)`},{value:`green`,label:`绿色`,color:`oklch(0.627 0.194 149.214)`},{value:`orange`,label:`橙色`,color:`oklch(0.646 0.222 41.116)`},{value:`rose`,label:`玫红`,color:`oklch(0.645 0.246 16.439)`}],O=`app-panel-content mt-0`,k=`app-field-group`,A=`app-section`,j=e=>{if(!e)return`100`;let t={small:`90`,medium:`100`,large:`110`};return e in t?t[e]:Ke.some(t=>t.value===e)?e:`100`};function Je({open:e=!1,onOpenChange:t,embedded:n=!1}){let{theme:i,accentColor:Je,setTheme:Ye,setAccentColor:Xe,setZoom:M}=ke(),[N,Ze]=(0,E.useState)(`preferences`),[P,F]=(0,E.useState)(()=>l()),[I,Qe]=(0,E.useState)(!1),[L,R]=(0,E.useState)(!1),[z,B]=(0,E.useState)(null),[$e,V]=(0,E.useState)(``),[H,U]=(0,E.useState)(null),[W,et]=(0,E.useState)(``),{status:G,refresh:K}=Pe(),[tt,nt]=(0,E.useState)([]),[q,J]=(0,E.useState)({}),[Y,rt]=(0,E.useState)(``),[X,it]=(0,E.useState)(``),[Z,at]=(0,E.useState)(null),[Q,ot]=(0,E.useState)(!1),[st,ct]=(0,E.useState)(null);(0,E.useEffect)(()=>{let e=!1;return Ge().then(t=>{e||ct(t)}),()=>{e=!0}},[]);let[$,lt]=(0,E.useState)(()=>j(Oe().fontSize)),[ut,dt]=(0,E.useState)(!1);(0,E.useEffect)(()=>{Ce().then(e=>{let t=j(e.fontSize);lt(t),M(parseInt(t,10)/100),dt(!0)}).catch(()=>{dt(!0)})},[M]),(0,E.useEffect)(()=>{if(!ut)return;let e=j($);M(parseInt(e,10)/100),C({fontSize:e}).catch(console.error)},[M,ut,$]),(0,E.useEffect)(()=>{(e||n)&&(Ce().then(e=>{F(e.aiConfig),et(e.mocksFilePath||``),J(e.clientAliases||{})}).catch(()=>{F(l())}),B(null),V(``),fetch(`/api/rule-files`).then(e=>e.json()).then(e=>{Array.isArray(e)&&nt(e)}).catch(()=>{}))},[e,n]);let ft=e=>{let t=c(e);F({...P,provider:e,baseUrl:t.baseUrl,model:t.model})},pt=async()=>{R(!0);try{await C({aiConfig:P}),ae(P),B(`success`),V(`AI 配置保存成功`),T.success(`AI 配置保存成功`)}catch(e){let t=e instanceof Error?e.message:`保存失败`;B(`error`),V(t),T.error(t)}finally{R(!1)}},mt=()=>{le(),F(l()),B(null),V(``)},ht=async()=>{if(!ce(P)){B(`error`),V(`请填写完整的配置信息`);return}R(!0),B(null),V(`测试中...`);try{let e=P.baseUrl,t={"Content-Type":`application/json`},n;P.provider===`anthropic`?(t[`x-api-key`]=P.apiKey,t[`anthropic-version`]=`2023-06-01`,n={model:P.model,max_tokens:100,system:`You are a helpful assistant.`,messages:[{role:`user`,content:`Say "test successful"`}],temperature:.3}):(t.Authorization=`Bearer ${P.apiKey}`,n={model:P.model,messages:[{role:`system`,content:`You are a helpful assistant.`},{role:`user`,content:`Say "test successful"`}],temperature:.3,max_tokens:100});let r=await fetch(e,{method:`POST`,headers:t,body:JSON.stringify(n)});if(!r.ok){let e=await r.text();throw Error(`API错误 (${r.status}): ${e}`)}let i=await r.json();if(P.provider===`anthropic`){if(!i.content?.[0]?.text)throw Error(`API响应格式不正确`)}else if(!i.choices?.[0]?.message?.content)throw Error(`API响应格式不正确`);B(`success`),V(`连接测试成功! API配置正常`)}catch(e){B(`error`),V(e instanceof Error?e.message:`测试失败`)}finally{R(!1)}},gt=(0,E.useCallback)(async()=>{try{let e=await fetch(`/api/refresh-config`,{method:`POST`});if(e.ok){let t=await e.json();K(),B(`success`),V(t.message||`配置已刷新`),setTimeout(()=>{B(null),V(``)},2e3)}else{let t=await e.json();B(`error`),V(t.error||`刷新配置失败`),setTimeout(()=>{B(null),V(``)},2e3)}}catch(e){console.error(`刷新配置失败:`,e),B(`error`),V(`刷新配置失败`),setTimeout(()=>{B(null),V(``)},2e3)}},[K]),_t=(0,E.useCallback)(async()=>{ot(!0),at(null);try{let e=await fetch(`/api/config-doctor`);e.ok?at(await e.json()):(B(`error`),V(`诊断失败`),setTimeout(()=>{B(null),V(``)},2e3))}catch(e){console.error(`诊断失败:`,e),B(`error`),V(`诊断失败`),setTimeout(()=>{B(null),V(``)},2e3)}finally{ot(!1)}},[]),vt=()=>{let e=Y.trim(),t=X.trim();!e||!t||(J(n=>({...n,[e]:t})),rt(``),it(``))},yt=async()=>{R(!0);try{await C({clientAliases:q}),B(`success`),V(`客户端名称已保存,新请求立即生效`),T.success(`客户端名称保存成功`)}catch(e){let t=e instanceof Error?e.message:`保存失败`;B(`error`),V(t),T.error(t)}finally{R(!1)}},bt=async()=>{R(!0);try{await C({mocksFilePath:W}),K(),B(`success`),V(`Mock 文件路径已更新,已切换到新文件`),T.success(`Mock 文件路径保存成功`),setTimeout(()=>{B(null),V(``)},3e3)}catch(e){let t=e instanceof Error?e.message:`保存失败`;B(`error`),V(t),T.error(t)}finally{R(!1)}};Te({active:(e||n)&&N!==`preferences`,enabled:!L,priority:Ie.panel,onSave:()=>{if(N===`config`)return bt();if(N===`clients`)return yt();if(N===`ai`)return pt()}});let xt=(0,D.jsxs)(D.Fragment,{children:[!n&&(0,D.jsxs)(ge,{className:`px-6 pt-6 pb-4`,children:[(0,D.jsxs)(je,{className:`flex items-center gap-2`,children:[(0,D.jsx)(Fe,{className:`h-5 w-5`}),`系统设置`]}),(0,D.jsx)(de,{children:`管理系统偏好、配置和 AI 功能`})]}),(0,D.jsxs)(_e,{value:N,onValueChange:e=>Ze(e),orientation:`vertical`,className:`min-h-0 flex-1 gap-0`,children:[(0,D.jsxs)(me,{"aria-label":`设置分类`,className:`h-full w-14 shrink-0 self-stretch justify-start gap-1 rounded-none border-r bg-muted/25 p-2 group-data-[orientation=vertical]/tabs:!h-full sm:w-44 sm:p-3`,children:[(0,D.jsxs)(m,{value:`preferences`,className:`h-9 w-full flex-none justify-start px-2.5 sm:px-3`,children:[(0,D.jsx)(Fe,{}),(0,D.jsx)(`span`,{className:`hidden sm:inline`,children:`偏好设置`})]}),(0,D.jsxs)(m,{value:`config`,className:`h-9 w-full flex-none justify-start px-2.5 sm:px-3`,children:[(0,D.jsx)(h,{}),(0,D.jsx)(`span`,{className:`hidden sm:inline`,children:`配置文件`})]}),(0,D.jsxs)(m,{value:`clients`,className:`h-9 w-full flex-none justify-start px-2.5 sm:px-3`,children:[(0,D.jsx)(re,{}),(0,D.jsx)(`span`,{className:`hidden sm:inline`,children:`客户端`})]}),(0,D.jsxs)(m,{value:`ai`,className:`h-9 w-full flex-none justify-start px-2.5 sm:px-3`,children:[(0,D.jsx)(we,{}),(0,D.jsx)(`span`,{className:`hidden sm:inline`,children:`AI 配置`})]})]}),(0,D.jsxs)(f,{value:`preferences`,className:O,children:[(0,D.jsxs)(`div`,{className:k,children:[(0,D.jsx)(d,{className:`text-sm`,children:`主题`}),(0,D.jsxs)(he,{value:i,onValueChange:e=>Ye(e),children:[(0,D.jsx)(ve,{children:(0,D.jsx)(u,{placeholder:`选择主题`})}),(0,D.jsx)(Se,{children:(0,D.jsxs)(xe,{children:[(0,D.jsx)(_,{value:`system`,children:(0,D.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,D.jsx)(pe,{className:`size-4`}),`跟随系统`]})}),(0,D.jsx)(_,{value:`light`,children:(0,D.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,D.jsx)(Ae,{className:`size-4`}),`浅色模式`]})}),(0,D.jsx)(_,{value:`dark`,children:(0,D.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,D.jsx)(be,{className:`size-4`}),`深色模式`]})})]})})]})]}),(0,D.jsxs)(`div`,{className:`flex flex-col gap-3`,children:[(0,D.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,D.jsx)(d,{className:`text-sm`,children:`强调色`}),(0,D.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`统一按钮、状态、选中项和焦点样式。自动模式会根据明暗主题选择合适的颜色。`})]}),(0,D.jsx)(y,{type:`single`,value:Je,onValueChange:e=>{e&&Xe(e)},variant:`outline`,spacing:1,className:`flex-wrap justify-start`,"aria-label":`强调色`,children:qe.map(e=>(0,D.jsxs)(S,{value:e.value,"aria-label":e.label,children:[e.value===`auto`?(0,D.jsx)(we,{"data-icon":`inline-start`}):(0,D.jsx)(`span`,{className:`size-3 rounded-full border border-foreground/10`,style:{background:e.color}}),e.label]},e.value))})]}),(0,D.jsxs)(`div`,{className:k,children:[(0,D.jsx)(d,{className:`text-sm`,children:`缩放比例`}),(0,D.jsxs)(he,{value:$,onValueChange:lt,children:[(0,D.jsx)(ve,{children:(0,D.jsx)(u,{placeholder:`选择缩放比例`})}),(0,D.jsx)(Se,{children:(0,D.jsx)(xe,{children:Ke.map(e=>(0,D.jsx)(_,{value:e.value,children:e.label},e.value))})})]})]}),(0,D.jsx)(w,{}),(0,D.jsxs)(`div`,{className:k,children:[(0,D.jsx)(`h3`,{className:`text-sm font-medium`,children:`关于`}),(0,D.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Meddle - HTTP 调试代理工具`}),(0,D.jsxs)(`p`,{className:`text-xs text-muted-foreground`,"data-testid":`settings-app-version`,children:[`版本: `,st??`—`]})]})]}),(0,D.jsxs)(f,{value:`config`,className:O,children:[(0,D.jsxs)(`div`,{className:A,children:[(0,D.jsx)(d,{className:`text-sm font-medium`,children:`路由规则文件`}),(0,D.jsxs)(`div`,{className:k,children:[(0,D.jsxs)(`div`,{className:`flex items-center gap-2 p-3 bg-muted rounded-md`,children:[(0,D.jsx)(h,{className:`h-4 w-4 text-muted-foreground shrink-0`}),(0,D.jsx)(`span`,{className:`text-xs font-mono truncate flex-1`,children:`~/.meddle/route-rules/`})]}),tt.length>0?(0,D.jsx)(`div`,{className:`space-y-2`,children:tt.map(e=>(0,D.jsxs)(`div`,{className:`flex items-center gap-2 rounded-md border px-3 py-2.5 text-sm`,children:[(0,D.jsx)(b,{variant:e.enabled?`default`:`secondary`,className:`text-[10px]`,children:e.enabled?`已启用`:`未启用`}),(0,D.jsxs)(`span`,{className:`flex-1 truncate text-xs`,children:[e.name,`.txt`]}),(0,D.jsxs)(`span`,{className:`text-xs text-muted-foreground`,children:[e.ruleCount,` 条规则`]})]},e.name))}):(0,D.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`暂无规则文件`}),(0,D.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`规则文件存放于 ~/.meddle/route-rules/ 目录,纯文本格式。在"路由规则"页面管理。`})]})]}),(0,D.jsx)(w,{}),(0,D.jsxs)(`div`,{className:A,children:[(0,D.jsx)(d,{className:`text-sm font-medium`,children:`Mock 规则文件`}),(0,D.jsxs)(`div`,{className:k,children:[(0,D.jsxs)(`div`,{className:`flex items-center gap-2 p-3 bg-muted rounded-md`,children:[(0,D.jsx)(h,{className:`h-4 w-4 text-muted-foreground shrink-0`}),(0,D.jsx)(`span`,{className:`text-xs font-mono truncate flex-1`,children:W||`默认: ~/.meddle/mocks.json`})]}),(0,D.jsxs)(`div`,{className:k,children:[(0,D.jsx)(d,{htmlFor:`mocksPath`,className:`text-xs text-muted-foreground`,children:`自定义 Mock 规则文件路径(留空使用默认)`}),(0,D.jsxs)(`div`,{className:`flex gap-2`,children:[(0,D.jsx)(x,{id:`mocksPath`,value:W,onChange:e=>et(e.target.value),placeholder:`如: /path/to/my-mocks.json`,className:`flex-1 h-8 text-sm font-mono`}),(0,D.jsxs)(g,{variant:`outline`,size:`sm`,onClick:bt,disabled:L,className:`h-8`,children:[(0,D.jsx)(v,{"data-icon":`inline-start`,className:`h-3 w-3`}),`应用`]})]}),(0,D.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`必须是 JSON 格式的 Mock 规则文件`}),Ee(G)?(0,D.jsx)(Ve,{testId:`settings-mocks-file-invalid`,location:Ne(G.parseError)}):Me(G)?(0,D.jsx)(Be,{testId:`settings-mocks-file-missing`}):null]})]})]}),(0,D.jsx)(w,{}),(0,D.jsxs)(`div`,{className:k,children:[(0,D.jsx)(`h3`,{className:`text-sm font-medium`,children:`操作`}),(0,D.jsxs)(`div`,{className:`flex gap-2`,children:[(0,D.jsxs)(r,{variant:`outline`,size:`sm`,onClick:gt,children:[(0,D.jsx)(te,{className:`h-4 w-4 mr-1`}),`重新加载配置`]}),(0,D.jsxs)(r,{variant:`outline`,size:`sm`,onClick:_t,disabled:Q,children:[(0,D.jsx)(We,{className:`h-4 w-4 mr-1`}),Q?`诊断中...`:`诊断配置`]})]}),(0,D.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`点击重新加载可应用修改后的配置文件,点击诊断配置可检查配置有效性`})]}),Z&&(0,D.jsxs)(`div`,{className:A,children:[(0,D.jsx)(w,{}),(0,D.jsxs)(`div`,{children:[(0,D.jsxs)(`h3`,{className:`mb-4 flex items-center gap-2 text-sm font-medium`,children:[(0,D.jsx)(We,{className:`h-4 w-4`}),`诊断结果`]}),(0,D.jsxs)(`div`,{className:`mb-3 p-3 rounded-md border ${Z.status===`ok`?`bg-green-50 dark:bg-green-950/20 border-green-200 dark:border-green-900`:Z.status===`warning`?`bg-yellow-50 dark:bg-yellow-950/20 border-yellow-200 dark:border-yellow-900`:`bg-red-50 dark:bg-red-950/20 border-red-200 dark:border-red-900`}`,children:[Z.status===`ok`&&(0,D.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,D.jsx)(p,{className:`h-5 w-5 text-green-600 dark:text-green-400`}),(0,D.jsx)(`span`,{className:`text-sm font-medium text-green-700 dark:text-green-300`,children:`所有检查通过!配置正常。`})]}),Z.status===`warning`&&(0,D.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,D.jsx)(a,{className:`h-5 w-5 text-yellow-600 dark:text-yellow-400`}),(0,D.jsxs)(`span`,{className:`text-sm font-medium text-yellow-700 dark:text-yellow-300`,children:[`发现 `,Z.warnings.length,` 个警告`]})]}),Z.status===`error`&&(0,D.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,D.jsx)(o,{className:`h-5 w-5 text-red-600 dark:text-red-400`}),(0,D.jsxs)(`span`,{className:`text-sm font-medium text-red-700 dark:text-red-300`,children:[`发现 `,Z.errors.length,` 个错误`]})]})]}),(0,D.jsx)(`div`,{className:k,children:Z.checks.map((e,t)=>(0,D.jsx)(`div`,{className:`p-2 rounded border bg-card`,children:(0,D.jsxs)(`div`,{className:`flex items-start gap-2`,children:[(0,D.jsx)(p,{className:`h-4 w-4 text-green-600 dark:text-green-400 mt-0.5 shrink-0`}),(0,D.jsxs)(`div`,{className:`flex-1 min-w-0`,children:[(0,D.jsx)(`div`,{className:`text-sm font-medium`,children:e.name}),(0,D.jsx)(`div`,{className:`text-xs text-muted-foreground font-mono truncate`,children:e.path}),e.details&&(0,D.jsxs)(`div`,{className:`text-xs text-muted-foreground mt-1`,children:[e.details.totalFiles!==void 0&&`${e.details.enabledFiles}/${e.details.totalFiles} 个文件已启用`,e.details.totalRules!==void 0&&` · ${e.details.totalRules} 条规则`,e.details.rules!==void 0&&`${e.details.rules} 条规则`,e.details.total!==void 0&&`${e.details.total} 条规则 (${e.details.enabled} 已启用)`,e.details.size!==void 0&&` · ${e.details.size} bytes`]})]})]})},t))}),Z.warnings&&Z.warnings.length>0&&(0,D.jsxs)(`div`,{className:`mt-3 space-y-1`,children:[(0,D.jsx)(`div`,{className:`text-xs font-medium text-yellow-700 dark:text-yellow-300`,children:`警告:`}),Z.warnings.map((e,t)=>(0,D.jsxs)(`div`,{className:`flex items-start gap-2 text-xs text-yellow-600 dark:text-yellow-400`,children:[(0,D.jsx)(a,{className:`h-3 w-3 mt-0.5 shrink-0`}),(0,D.jsx)(`span`,{children:e})]},t))]}),Z.errors&&Z.errors.length>0&&(0,D.jsxs)(`div`,{className:`mt-3 space-y-1`,children:[(0,D.jsx)(`div`,{className:`text-xs font-medium text-red-700 dark:text-red-300`,children:`错误:`}),Z.errors.map((e,t)=>(0,D.jsxs)(`div`,{className:`flex items-start gap-2 text-xs text-red-600 dark:text-red-400`,children:[(0,D.jsx)(o,{className:`h-3 w-3 mt-0.5 shrink-0`}),(0,D.jsx)(`span`,{children:e})]},t))]})]})]})]}),(0,D.jsxs)(f,{value:`clients`,className:O,children:[(0,D.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,D.jsxs)(`h3`,{className:`text-sm font-medium flex items-center gap-2`,children:[(0,D.jsx)(re,{className:`h-4 w-4`}),`远程客户端名称`]}),(0,D.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`将日志中的客户端 IP 映射为设备名称。保存后新请求立即生效,无需重启代理。`})]}),(0,D.jsx)(`div`,{className:k,children:Object.entries(q).length===0?(0,D.jsx)(`div`,{className:`rounded-md border border-dashed p-4 text-center text-xs text-muted-foreground`,children:`尚未配置设备名称`}):Object.entries(q).map(([e,t])=>(0,D.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,D.jsx)(x,{value:e,readOnly:!0,className:`h-8 flex-1 font-mono text-xs bg-muted/40`,"aria-label":`客户端 IP ${e}`}),(0,D.jsx)(x,{value:t,onChange:t=>{let n=t.target.value;J(t=>({...t,[e]:n}))},className:`h-8 flex-1 text-sm`,"aria-label":`${e} 的设备名称`}),(0,D.jsx)(r,{variant:`ghost`,size:`icon-sm`,className:`text-muted-foreground hover:text-destructive`,onClick:()=>{J(t=>{let n={...t};return delete n[e],n})},title:`删除设备名称`,"aria-label":`删除设备名称`,children:(0,D.jsx)(De,{className:`h-4 w-4`})})]},e))}),(0,D.jsx)(w,{}),(0,D.jsxs)(`div`,{className:k,children:[(0,D.jsx)(d,{className:`text-sm`,children:`添加设备`}),(0,D.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,D.jsx)(x,{value:Y,onChange:e=>rt(e.target.value),placeholder:`客户端 IP,例如 10.13.232.187`,className:`h-8 flex-1 font-mono text-xs`}),(0,D.jsx)(x,{value:X,onChange:e=>it(e.target.value),onKeyDown:e=>{e.key===`Enter`&&vt()},placeholder:`设备名称,例如 iPhone`,className:`h-8 flex-1 text-sm`}),(0,D.jsxs)(r,{variant:`outline`,size:`sm`,className:`h-8`,onClick:vt,disabled:!Y.trim()||!X.trim(),children:[(0,D.jsx)(s,{className:`h-4 w-4 mr-1`}),`添加`]})]})]}),(0,D.jsxs)(g,{onClick:yt,disabled:L,children:[(0,D.jsx)(v,{"data-icon":`inline-start`,className:`h-4 w-4`}),L?`保存中...`:`保存客户端名称`]})]}),(0,D.jsxs)(f,{value:`ai`,className:O,children:[(0,D.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,D.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,D.jsx)(d,{className:`text-sm`,children:`启用 AI 功能`}),(0,D.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`启用智能代码修复功能`})]}),(0,D.jsx)(ie,{checked:P.enabled,onCheckedChange:e=>F({...P,enabled:e}),"aria-label":`启用 AI 功能`})]}),(0,D.jsx)(w,{}),(0,D.jsxs)(`div`,{className:A,children:[(0,D.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,D.jsx)(d,{className:`text-sm`,children:`AI 模型配置`}),(0,D.jsxs)(r,{variant:`outline`,size:`sm`,onClick:()=>{U({name:``,provider:`openai`,apiKey:``,baseUrl:`https://api.openai.com/v1/chat/completions`,model:`gpt-4o-mini`})},children:[(0,D.jsx)(s,{className:`h-4 w-4 mr-1`}),`添加模型`]})]}),(0,D.jsx)(`div`,{className:k,children:P.models&&P.models.length>0?P.models.map(e=>(0,D.jsx)(`div`,{className:`p-3 rounded-md border ${P.activeModelId===e.id?`border-primary bg-primary/5`:`border-border`}`,children:(0,D.jsxs)(`div`,{className:`flex items-start justify-between`,children:[(0,D.jsxs)(`div`,{className:`flex-1`,children:[(0,D.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,D.jsx)(`span`,{className:`font-medium text-sm`,children:e.name}),P.activeModelId===e.id&&(0,D.jsx)(b,{variant:`default`,className:`text-xs`,children:`当前使用`})]}),(0,D.jsxs)(`p`,{className:`text-xs text-muted-foreground mt-1`,children:[e.provider===`openai`?`OpenAI`:`Anthropic`,` - `,e.model]})]}),(0,D.jsxs)(`div`,{className:`flex gap-1`,children:[P.activeModelId!==e.id&&(0,D.jsxs)(r,{variant:`ghost`,size:`xs`,onClick:()=>F(oe(P,e.id)),children:[(0,D.jsx)(ee,{className:`h-3 w-3 mr-1`}),`使用`]}),(0,D.jsx)(r,{variant:`ghost`,size:`icon-sm`,onClick:()=>F(se(P,e.id)),className:`text-destructive`,"aria-label":`删除模型`,children:(0,D.jsx)(De,{className:`h-3 w-3`})})]})]})},e.id)):(0,D.jsx)(`p`,{className:`text-xs text-muted-foreground italic py-4 text-center`,children:`暂无模型配置,点击"添加模型"创建`})}),H&&(0,D.jsxs)(`div`,{className:`space-y-5 rounded-md border border-primary bg-primary/5 p-4`,children:[(0,D.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,D.jsx)(d,{className:`text-sm font-medium`,children:`新增模型`}),(0,D.jsx)(r,{variant:`ghost`,size:`icon-xs`,onClick:()=>U(null),"aria-label":`关闭新增模型表单`,children:(0,D.jsx)(o,{className:`h-4 w-4`})})]}),(0,D.jsxs)(`div`,{className:k,children:[(0,D.jsx)(d,{htmlFor:`newModelName`,className:`text-xs`,children:`模型名称`}),(0,D.jsx)(x,{id:`newModelName`,value:H.name||``,onChange:e=>U({...H,name:e.target.value}),placeholder:`如:GPT-4o Mini`,className:`h-8 text-sm`})]}),(0,D.jsxs)(`div`,{className:k,children:[(0,D.jsx)(d,{className:`text-xs`,children:`服务商`}),(0,D.jsxs)(y,{type:`single`,value:H.provider,onValueChange:e=>{if(e===`openai`){let e=c(`openai`);U({...H,provider:`openai`,baseUrl:e.baseUrl,model:e.model})}else if(e===`anthropic`){let e=c(`anthropic`);U({...H,provider:`anthropic`,baseUrl:e.baseUrl,model:e.model})}},variant:`outline`,size:`sm`,spacing:0,children:[(0,D.jsx)(S,{value:`openai`,children:`OpenAI`}),(0,D.jsx)(S,{value:`anthropic`,children:`Anthropic`})]})]}),(0,D.jsxs)(`div`,{className:k,children:[(0,D.jsx)(d,{htmlFor:`newModelApiKey`,className:`text-xs`,children:`API Key`}),(0,D.jsx)(x,{id:`newModelApiKey`,type:I?`text`:`password`,value:H.apiKey||``,onChange:e=>U({...H,apiKey:e.target.value}),placeholder:`输入 API Key`,className:`h-8 text-sm`})]}),(0,D.jsxs)(`div`,{className:k,children:[(0,D.jsx)(d,{htmlFor:`newModelModel`,className:`text-xs`,children:`模型`}),(0,D.jsx)(x,{id:`newModelModel`,value:H.model||``,onChange:e=>U({...H,model:e.target.value}),placeholder:`模型名称`,className:`h-8 text-sm`})]}),(0,D.jsxs)(`div`,{className:k,children:[(0,D.jsx)(d,{htmlFor:`newModelBaseUrl`,className:`text-xs`,children:`API 端点`}),(0,D.jsx)(x,{id:`newModelBaseUrl`,value:H.baseUrl||``,onChange:e=>U({...H,baseUrl:e.target.value}),placeholder:`API 端点`,className:`h-8 text-sm`})]}),(0,D.jsxs)(`div`,{className:`flex justify-end gap-2 pt-2`,children:[(0,D.jsx)(r,{variant:`outline`,size:`xs`,onClick:()=>U(null),children:`取消`}),(0,D.jsxs)(r,{size:`xs`,onClick:()=>{H.name&&H.apiKey&&H.model&&H.baseUrl&&(F(ue(P,H)),U(null))},disabled:!H.name||!H.apiKey||!H.model||!H.baseUrl,children:[(0,D.jsx)(s,{className:`h-3 w-3 mr-1`}),`添加`]})]})]})]}),(0,D.jsx)(w,{}),(0,D.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,D.jsx)(d,{className:`text-sm`,children:`传统配置(向后兼容)`}),(0,D.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`如果未配置多模型,将使用此配置`})]}),(0,D.jsxs)(`div`,{className:k,children:[(0,D.jsx)(d,{className:`text-xs`,children:`AI 服务商`}),(0,D.jsxs)(y,{type:`single`,value:P.provider,onValueChange:e=>{(e===`openai`||e===`anthropic`)&&ft(e)},variant:`outline`,size:`sm`,spacing:0,children:[(0,D.jsx)(S,{value:`openai`,children:`OpenAI`}),(0,D.jsx)(S,{value:`anthropic`,children:`Anthropic`})]})]}),(0,D.jsxs)(`div`,{className:k,children:[(0,D.jsx)(d,{htmlFor:`apiKey`,className:`text-xs`,children:`API Key`}),(0,D.jsxs)(`div`,{className:`flex gap-2`,children:[(0,D.jsx)(x,{id:`apiKey`,type:I?`text`:`password`,value:P.apiKey,onChange:e=>F({...P,apiKey:e.target.value}),placeholder:`输入 API Key`,className:`flex-1 h-8 text-sm`}),(0,D.jsx)(r,{variant:`outline`,size:`icon-sm`,onClick:()=>Qe(!I),"aria-label":I?`隐藏 API Key`:`显示 API Key`,children:I?(0,D.jsx)(He,{className:`h-4 w-4`}):(0,D.jsx)(Ue,{className:`h-4 w-4`})})]})]}),(0,D.jsxs)(`div`,{className:k,children:[(0,D.jsx)(d,{htmlFor:`model`,className:`text-xs`,children:`模型`}),(0,D.jsx)(x,{id:`model`,value:P.model,onChange:e=>F({...P,model:e.target.value}),placeholder:`模型名称`,className:`h-8 text-sm`})]}),(0,D.jsxs)(`div`,{className:k,children:[(0,D.jsx)(d,{htmlFor:`baseUrl`,className:`text-xs`,children:`API 端点`}),(0,D.jsx)(x,{id:`baseUrl`,value:P.baseUrl,onChange:e=>F({...P,baseUrl:e.target.value}),placeholder:P.provider===`openai`?`https://api.openai.com/v1/chat/completions`:`https://api.anthropic.com/v1/messages`,className:`h-8 text-sm`})]}),$e&&(0,D.jsxs)(ze,{variant:z===`error`?`destructive`:`default`,children:[z===`success`?(0,D.jsx)(p,{}):z===`error`?(0,D.jsx)(o,{}):(0,D.jsx)(a,{}),(0,D.jsx)(Re,{children:z===`success`?`操作成功`:z===`error`?`操作失败`:`处理中`}),(0,D.jsx)(Le,{children:$e})]}),(0,D.jsx)(w,{}),(0,D.jsxs)(`div`,{className:`flex justify-between`,children:[(0,D.jsxs)(r,{variant:`outline`,size:`sm`,onClick:mt,children:[(0,D.jsx)(ne,{className:`h-4 w-4 mr-1`}),`重置`]}),(0,D.jsxs)(`div`,{className:`flex gap-2`,children:[(0,D.jsx)(r,{variant:`outline`,size:`sm`,onClick:ht,disabled:!ce(P)||L,children:`测试连接`}),(0,D.jsxs)(g,{size:`sm`,onClick:pt,disabled:L,children:[(0,D.jsx)(v,{"data-icon":`inline-start`,className:`h-4 w-4`}),L?`保存中...`:`保存`]})]})]})]})]})]});return n?(0,D.jsx)(`div`,{"data-testid":`settings-fullwidth`,className:`app-workspace-content flex h-full min-h-0 w-full flex-col overflow-hidden p-0`,children:(0,D.jsx)(`div`,{className:`flex min-h-0 flex-1 flex-col overflow-hidden rounded-md border bg-card`,children:xt})}):(0,D.jsx)(ye,{open:e,onOpenChange:t,children:(0,D.jsx)(fe,{className:`p-0 flex flex-col`,resizable:!0,defaultWidth:600,storageKey:`settings-panel`,children:xt})})}export{Je as SettingsPanel};
@@ -5,7 +5,7 @@
5
5
  <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <title>web</title>
8
- <script type="module" crossorigin src="/assets/index-Bu3zaxzE.js"></script>
8
+ <script type="module" crossorigin src="/assets/index-B9-_OFNJ.js"></script>
9
9
  <link rel="modulepreload" crossorigin href="/assets/button-BFNlGZ5p.js">
10
10
  <link rel="modulepreload" crossorigin href="/assets/dist-CFZ4xMSF.js">
11
11
  <link rel="modulepreload" crossorigin href="/assets/dist-C-E2R2jk.js">
@@ -1 +0,0 @@
1
- import{c as e,d as t,p as n,t as r}from"./button-BFNlGZ5p.js";import"./dist-CFZ4xMSF.js";import{t as i}from"./code-DD-AYxxu.js";import{t as a}from"./checkbox-v2kzp7K8.js";import{t as o}from"./plus-ixZQRprm.js";import{A as s,At as c,_ as l,a as u,c as d,et as f,i as p,j as m,k as h,o as g,s as _,ut as v}from"./index-Bu3zaxzE.js";import"./syntax-highlight-EJCxGikd.js";import{a as y,i as b,n as x,o as S,r as C,t as w}from"./table-C3mgEjkP.js";import"./monaco-editor-DeJNlo9k.js";import{n as T}from"./editor-pane-actions-DN-pxFsl.js";import{MockEditorPanel as E}from"./mock-editor-panel-zqouxTGb.js";import{n as D,t as O}from"./pane-split-Db1aWKUO.js";import{r as k,t as A}from"./mocks-file-missing-note-B8TTBWtG.js";var j=n(t(),1),M=O({storageKey:`meddle-mock-list-width`,defaultPx:480,minPx:320,maxPx:640,editorMinPx:360});M.storageKey,M.defaultPx,M.minPx,M.maxPx,M.editorMinPx,M.clamp,M.load,M.save,M.widthFromPointer;var N=e(),P=`Mock 文件格式错误,修复后才能新增`;function F({mockRules:e,fetchMocks:t,createMock:n,updateMock:O,deleteMock:F,initialEditData:I,onInitialEditConsumed:L}){let[R,z]=(0,j.useState)({kind:`idle`}),[B,V]=(0,j.useState)(null),{status:H}=d(e.length);(0,j.useEffect)(()=>{t()},[t]);let U=g(H),W=(0,j.useRef)(U);(0,j.useEffect)(()=>{W.current=U,U&&z({kind:`idle`})},[U]);let G=(0,j.useCallback)(e=>{if(W.current){l.error(P);return}z({kind:`create`,initialData:e,nonce:Date.now()})},[]),K=(0,j.useCallback)(e=>{z({kind:`edit`,ruleId:e.id})},[]),q=(0,j.useCallback)(()=>{z({kind:`idle`})},[]);(0,j.useEffect)(()=>{let e=e=>{let t=e.detail;G(t?.initialData)};return window.addEventListener(p,e),()=>window.removeEventListener(p,e)},[G]),(0,j.useEffect)(()=>{I&&(G(I),L?.())},[I,L,G]);let J=(0,j.useMemo)(()=>{if(R.kind===`edit`)return e.find(e=>e.id===R.ruleId)},[R,e]);(0,j.useEffect)(()=>{R.kind===`edit`&&!J&&z({kind:`idle`})},[R.kind,J]);let Y=(0,j.useCallback)(async(e,t)=>{await O(e.id,{enabled:t})},[O]),X=(0,j.useCallback)(async e=>{window.confirm(`确定删除这条 Mock 规则?`)&&(await F(e)?(l.success(`已删除 Mock 规则`),R.kind===`edit`&&R.ruleId===e&&q()):l.error(`删除失败`))},[q,F,R]),Z=(0,j.useCallback)(()=>{t(),q()},[q,t]),Q=R.kind===`create`?`create-${R.nonce}`:R.kind===`edit`?`edit-${R.ruleId}`:`idle`;return(0,N.jsxs)(D,{testId:`mock-config-layout`,layout:`list-edit`,widthAttr:`mock-list-width`,split:M,listTestId:`mock-config-list`,panelTestId:`mock-config-edit`,separatorTestId:`mock-panel-separator`,separatorLabel:`调整 Mock 列表宽度`,list:(0,N.jsxs)(N.Fragment,{children:[(0,N.jsxs)(`div`,{className:`app-pane-bar flex shrink-0 items-center justify-between gap-2 border-b`,children:[(0,N.jsx)(`div`,{className:`text-[10px] font-medium uppercase tracking-wide text-muted-foreground`,children:`Mock 规则`}),U?(0,N.jsxs)(h,{children:[(0,N.jsx)(m,{asChild:!0,children:(0,N.jsx)(`span`,{tabIndex:0,"data-testid":`mock-config-create-wrapper`,"aria-label":P,children:(0,N.jsxs)(r,{variant:`outline`,size:`sm`,disabled:!0,"data-testid":`mock-config-create`,className:`pointer-events-none`,children:[(0,N.jsx)(o,{"data-icon":`inline-start`}),`新增规则`]})})}),(0,N.jsx)(s,{"data-testid":`mock-config-create-tooltip`,children:P})]}):(0,N.jsxs)(r,{variant:`outline`,size:`sm`,onClick:()=>G(),"data-testid":`mock-config-create`,children:[(0,N.jsx)(o,{"data-icon":`inline-start`}),`新增规则`]})]}),(0,N.jsx)(`div`,{className:`meddle-thin-scroll min-h-0 flex-1 overflow-x-hidden overflow-y-auto`,children:(0,N.jsxs)(w,{children:[(0,N.jsx)(y,{children:(0,N.jsxs)(S,{children:[(0,N.jsx)(b,{className:`w-12`,children:`启用`}),(0,N.jsx)(b,{className:`w-16`,children:`方法`}),(0,N.jsx)(b,{children:`名称 / 匹配`}),(0,N.jsx)(b,{className:`w-14`,children:`状态`}),(0,N.jsx)(b,{className:`w-14`,children:`延迟`}),(0,N.jsx)(b,{className:`w-12`})]})}),(0,N.jsx)(x,{children:e.length===0?(0,N.jsx)(S,{children:(0,N.jsx)(C,{colSpan:6,className:`py-8 text-center text-muted-foreground whitespace-normal`,children:g(H)?(0,N.jsx)(A,{path:H.path,location:u(H.parseError)}):_(H)?(0,N.jsx)(k,{path:H.path,children:`暂无 Mock 规则,点击「新增规则」或从流量详情一键创建`}):`暂无 Mock 规则,点击「新增规则」或从流量详情一键创建`})}):e.map(e=>{let t=R.kind===`edit`&&R.ruleId===e.id;return(0,N.jsxs)(S,{"data-testid":`mock-config-row-${e.id}`,"data-state":t?`selected`:void 0,className:`cursor-pointer`,onClick:()=>K(e),children:[(0,N.jsx)(C,{onClick:e=>e.stopPropagation(),children:(0,N.jsx)(a,{checked:e.enabled,onCheckedChange:t=>Y(e,t===!0),"aria-label":`启用 ${e.name||e.urlPattern}`})}),(0,N.jsx)(C,{children:(0,N.jsx)(f,{variant:`outline`,className:`text-xs`,children:e.method||`*`})}),(0,N.jsxs)(C,{className:`max-w-[220px]`,children:[(0,N.jsx)(`div`,{className:`truncate text-sm font-medium`,children:e.name||(0,N.jsx)(`span`,{className:`italic text-muted-foreground`,children:`未命名`})}),(0,N.jsx)(`div`,{className:`truncate font-mono text-xs text-muted-foreground`,title:e.urlPattern,children:e.urlPattern})]}),(0,N.jsx)(C,{children:(0,N.jsx)(f,{variant:e.statusCode>=400?`destructive`:e.statusCode>=300?`secondary`:`default`,children:e.statusCode})}),(0,N.jsx)(C,{className:`font-mono text-xs text-muted-foreground`,children:e.delay?`${e.delay}ms`:`0ms`}),(0,N.jsx)(C,{onClick:e=>e.stopPropagation(),children:(0,N.jsxs)(`div`,{className:`flex items-center gap-0.5`,children:[e.bodyType===`file`?(0,N.jsx)(c,{className:`size-3.5 text-muted-foreground`,"aria-hidden":!0}):(0,N.jsx)(i,{className:`size-3.5 text-muted-foreground`,"aria-hidden":!0}),(0,N.jsx)(r,{variant:`ghost`,size:`icon-sm`,onClick:()=>void X(e.id),className:`text-muted-foreground hover:text-destructive`,"aria-label":`删除 Mock 规则`,children:(0,N.jsx)(v,{})})]})})]},e.id)})})]})})]}),children:[(0,N.jsxs)(`div`,{className:`app-pane-bar flex shrink-0 flex-wrap items-center justify-between gap-x-3 gap-y-2 border-b`,children:[(0,N.jsx)(`div`,{className:`min-w-0 truncate text-[10px] font-medium uppercase tracking-wide text-muted-foreground`,children:R.kind===`create`?`编辑 Mock · 新建`:R.kind===`edit`?`编辑 Mock · ${J?.name||J?.urlPattern||R.ruleId}`:`编辑 Mock`}),(0,N.jsxs)(`div`,{className:`ml-auto flex min-w-0 max-w-full flex-wrap items-center justify-end gap-2`,children:[R.kind===`idle`?null:(0,N.jsx)(r,{variant:`ghost`,size:`sm`,onClick:q,children:`取消`}),(0,N.jsx)(`div`,{ref:V,"data-testid":`editor-pane-actions`,className:`contents`})]})]}),(0,N.jsx)(T,{host:B,children:(0,N.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto`,children:R.kind===`idle`?(0,N.jsxs)(`div`,{className:`flex h-full min-h-[240px] flex-col items-center justify-center gap-2 p-6 text-center text-sm text-muted-foreground`,children:[(0,N.jsx)(`p`,{children:`选择左侧规则进行编辑,或点击「新增规则」`}),(0,N.jsx)(`p`,{className:`text-xs`,children:`从流量详情「创建 Mock」会打开本编辑器并预填 URL / 方法 / Body`})]}):R.kind===`create`?(0,N.jsx)(E,{initialData:R.initialData,createMock:n,updateMock:O,onSaved:Z},Q):J?(0,N.jsx)(E,{rule:J,createMock:n,updateMock:O,onSaved:Z},Q):null})})]})}export{F as MockConfig};
@@ -1,20 +0,0 @@
1
- import{c as e,d as t,p as n,t as r}from"./button-BFNlGZ5p.js";import"./dist-CFZ4xMSF.js";import{t as i}from"./code-DD-AYxxu.js";import{n as a,t as o}from"./checkbox-v2kzp7K8.js";import{t as s}from"./plus-ixZQRprm.js";import{t as c}from"./wand-sparkles-DDGjzjnX.js";import{i as l,o as u,r as d}from"./ai-config-store-B_VpGvwx.js";import{F as f,Lt as p,M as m,O as h,P as g,S as _,Tt as v,_ as y,b,tt as x,ut as S,v as C,vt as ee,y as w}from"./index-Bu3zaxzE.js";import{i as T}from"./syntax-highlight-EJCxGikd.js";import{n as E}from"./monaco-editor-DeJNlo9k.js";import{i as D,t as O}from"./editor-pane-actions-DN-pxFsl.js";var k=n(t(),1);function A(e,t){let n=e;switch(t){case`json`:n=j(n),n=M(n);break;case`javascript`:n=N(n),n=P(n);break;case`html`:n=F(n);break;case`css`:n=I(n);break}return n}function j(e){let t=e.replace(/'/g,`"`);return t=t.replace(/([{,]\s*)([a-zA-Z_$][a-zA-Z0-9_$]*)\s*:/g,`$1"$2":`),t}function M(e){return e.replace(/,(\s*[}\]])/g,`$1`)}function N(e){let t={"{":`}`,"[":`]`,"(":`)`},n=[],r=!1,i=``;for(let a=0;a<e.length;a++){let o=e[a],s=a>0?e[a-1]:``;if((o===`"`||o===`'`||o==="`")&&s!==`\\`&&(r?o===i&&(r=!1):(r=!0,i=o)),!r){if(o in t)n.push(o);else if(Object.values(t).includes(o)){let e=Object.keys(t).find(e=>t[e]===o);n.length>0&&n[n.length-1]===e&&n.pop()}}}let a=e;for(;n.length>0;){let e=t[n.pop()];a+=e}return a}function P(e){let t=e,n={'"':0,"'":0,"`":0};for(let t of e)(t===`"`||t===`'`||t==="`")&&n[t]++;return n[`"`]%2!=0&&(t+=`"`),n[`'`]%2!=0&&(t+=`'`),n["`"]%2!=0&&(t+="`"),t}function F(e){let t=[],n=[`br`,`hr`,`img`,`input`,`link`,`meta`,`area`,`base`,`col`,`embed`,`param`,`source`,`track`,`wbr`],r=/<\/?([a-z][\w-]*)\b[^>]*>/gi,i;for(;(i=r.exec(e))!==null;){let e=i[0],r=i[1].toLowerCase(),a=e.endsWith(`/>`)||n.includes(r);e.startsWith(`</`)?t.length>0&&t[t.length-1]===r&&t.pop():a||t.push(r)}let a=e;for(;t.length>0;){let e=t.pop();a+=`</${e}>`}return a}function I(e){let t=0,n=!1,r=``;for(let i=0;i<e.length;i++){let a=e[i],o=i>0?e[i-1]:``;(a===`"`||a===`'`)&&o!==`\\`&&(n?a===r&&(n=!1):(n=!0,r=a)),n||(a===`{`?t++:a===`}`&&t--)}let i=e;for(;t>0;)i+=`
2
- }`,t--;return i}async function L(e,t=!1){if(!e.trim())return{fixed:e,method:`none`,success:!0};let n=T(e);if(!t&&n.valid)return{fixed:e,method:`none`,success:!0};let r=n.type?.toLowerCase();(!r||r===`text`)&&(r=R(e)),(!r||r===`text`)&&(r=`json`);let i=r,a=d();if(u(a))try{let t=l(a),n=await H(e,i,t?{provider:t.provider,apiKey:t.apiKey,baseUrl:t.baseUrl,model:t.model}:{provider:a.provider,apiKey:a.apiKey,baseUrl:a.baseUrl,model:a.model}),r=T(n);return r.valid?{fixed:n,method:`ai`,success:!0}:{fixed:n,method:`ai`,success:r.valid}}catch(e){console.warn(`AI修复失败:`,e)}let o=A(e,i);return{fixed:o,method:`rules`,success:T(o).valid}}function R(e){let t=e.trim();return t.startsWith(`{`)&&t.endsWith(`}`)||t.startsWith(`[`)&&t.endsWith(`]`)?`json`:t.startsWith(`<`)&&t.includes(`>`)?`html`:t.includes(`{`)&&t.includes(`}`)&&t.includes(`:`)?`css`:`text`}async function z(e,t,n){let r=`You are a code fixing assistant. Fix syntax errors in ${t.toUpperCase()} code. Return only the fixed code without explanations or markdown formatting.`,i=`Please fix the syntax errors in the following ${t.toUpperCase()} code. Return ONLY the fixed code without any explanations:
3
-
4
- ${e}`,a=await fetch(n.baseUrl,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${n.apiKey}`},body:JSON.stringify({model:n.model,messages:[{role:`system`,content:r},{role:`user`,content:i}],temperature:.3,max_tokens:2e3})});if(!a.ok){let e=await a.text();throw Error(`OpenAI API错误 (${a.status}): ${e}`)}let o=(await a.json()).choices?.[0]?.message?.content?.trim();if(!o)throw Error(`OpenAI返回了空结果`);return V(o)}async function B(e,t,n){let r=`You are a code fixing assistant. Fix syntax errors in ${t.toUpperCase()} code. Return only the fixed code without explanations or markdown formatting.`,i=`Please fix the syntax errors in the following ${t.toUpperCase()} code. Return ONLY the fixed code without any explanations:
5
-
6
- ${e}`,a=await fetch(n.baseUrl,{method:`POST`,headers:{"Content-Type":`application/json`,"x-api-key":n.apiKey,"anthropic-version":`2023-06-01`},body:JSON.stringify({model:n.model,max_tokens:2e3,system:r,messages:[{role:`user`,content:i}],temperature:.3})});if(!a.ok){let e=await a.text();throw Error(`Anthropic API错误 (${a.status}): ${e}`)}let o=(await a.json()).content?.[0]?.text?.trim();if(!o)throw Error(`Anthropic返回了空结果`);return V(o)}function V(e){let t=e.replace(/^```[a-z]*\n?/i,``).replace(/\n?```$/i,``).trim(),n=t.split(`
7
- `);return n.length>0&&!n[0].trim().match(/^[{<[a-z@]/i)&&(n.shift(),t=n.join(`
8
- `).trim()),t}async function H(e,t,n){return n.provider===`anthropic`?B(e,t,n):z(e,t,n)}function U(e){let t=e.trim();if(t.startsWith(`{`)&&t.endsWith(`}`)||t.startsWith(`[`)&&t.endsWith(`]`))try{return JSON.parse(t),`json`}catch{}return t.startsWith(`<!DOCTYPE`)||t.startsWith(`<html`)||/<[a-z][\s\S]*>/i.test(t)?`html`:/[a-z-]+\s*\{[\s\S]*\}/i.test(t)||/@(media|keyframes|import|font-face)/i.test(t)?`css`:/(function|const|let|var|class|import|export|=>)/i.test(t)?`javascript`:`unknown`}function W(e){let t=0,n=e.replace(/><>/g,`>
9
- <`).split(`
10
- `),r=[];for(let e of n){let n=e.trim();n&&(n.startsWith(`</`)&&(t=Math.max(0,t-1)),r.push(` `.repeat(t)+n),n.startsWith(`<`)&&!n.startsWith(`</`)&&!n.startsWith(`<?`)&&!n.endsWith(`/>`)&&(/<(area|base|br|col|embed|hr|img|input|link|meta|param|source|track|wbr)\b/i.test(n)||t++))}return r.join(`
11
- `)}function G(e){return e.replace(/\s*{\s*/g,` {
12
- `).replace(/\s*}\s*/g,`
13
- }
14
-
15
- `).replace(/\s*;\s*/g,`;
16
- `).trim()}function K(e){let t=0,n=[],r=0;for(;r<e.length;){let i=e[r],a=e[r+1];if(i===`/`&&a===`/`){let i=e.indexOf(`
17
- `,r);if(i===-1)break;n.push(` `.repeat(t)+e.slice(r,i).trim()),r=i+1;continue}if(i===`/`&&a===`*`){let i=e.indexOf(`*/`,r);if(i===-1)break;let a=e.slice(r,i+2);n.push(` `.repeat(t)+a),r=i+2;continue}if(i===`"`||i===`'`||i==="`"){let a=i,o=a;for(r++;r<e.length;)if(e[r]===`\\`&&r+1<e.length)o+=e[r]+e[r+1],r+=2;else if(e[r]===a){o+=a,r++;break}else o+=e[r],r++;n.push(` `.repeat(t)+o);continue}if(i===`{`){n.push(` `.repeat(t)+`{`),t++,r++;continue}if(i===`}`){t=Math.max(0,t-1),n.push(` `.repeat(t)+`}`),r++;continue}let o=``;for(;r<e.length&&e[r]!==`
18
- `&&!`{}`.includes(e[r]);)o+=e[r],r++;o.trim()&&n.push(` `.repeat(t)+o.trim()),e[r]===`
19
- `&&r++}return n.join(`
20
- `)}async function q(e,t){try{let n=p(()=>import(`./standalone-D-fjaAIs.js`),[]),r=t===`css`?[p(()=>import(`./postcss-DfIslWug.js`),[])]:t===`html`?[p(()=>import(`./html-D2PZBPnP.js`),[]),p(()=>import(`./babel-D1quDdNt.js`),[]),p(()=>import(`./estree--Vq99DGn.js`),[]),p(()=>import(`./postcss-DfIslWug.js`),[])]:[p(()=>import(`./babel-D1quDdNt.js`),[]),p(()=>import(`./estree--Vq99DGn.js`),[])],[i,...a]=await Promise.all([n,...r]);return(await i.format(e,{parser:t===`json`?`json-stringify`:t,plugins:a.map(e=>e.default),printWidth:80,tabWidth:2,useTabs:!1,semi:!0,singleQuote:!0,trailingComma:`es5`,bracketSpacing:!0,arrowParens:`always`})).trim()}catch(n){if(t===`json`)try{let t=JSON.parse(e);return JSON.stringify(t,null,2)}catch{throw Error(`JSON格式错误,无法解析`)}else if(t===`html`)return W(e);else if(t===`css`)return G(e);else if(t===`babel`)return K(e);let r=n instanceof Error?n.message:`未知错误`;throw Error(`格式化失败: ${r}`)}}async function J(e){let t=U(e);try{let n,r;switch(t){case`json`:n=await q(e,`json`),r=`JSON`;break;case`html`:n=await q(e,`html`),r=`HTML`;break;case`css`:n=await q(e,`css`),r=`CSS`;break;case`javascript`:n=await q(e,`babel`),r=`JavaScript`;break;default:n=e,r=`Unknown`}return{formatted:n,type:r}}catch(e){throw Error(`格式化失败: ${e instanceof Error?e.message:`未知错误`}`)}}var Y=e();function X(e){return typeof e==`string`?e:e==null?``:typeof e==`number`||typeof e==`boolean`?String(e):JSON.stringify(e)}function Z(e){if(!e.trim())return{entries:[],error:null};let t;try{t=JSON.parse(e)}catch{return{entries:[],error:`响应头 JSON 无法解析`}}return!t||typeof t!=`object`||Array.isArray(t)?{entries:[],error:`响应头必须是 JSON 对象`}:{entries:Object.entries(t).map(([e,t])=>({key:e,value:X(t)})),error:null}}function Q(e){let t={};for(let n of e){let e=n.key.trim();e&&(t[e]=n.value)}return JSON.stringify(t,null,2)}function te({value:e,onChange:t}){let n=(0,k.useRef)(0),i=e=>(n.current+=1,{id:`header-row-${n.current}`,key:e?.key??``,value:e?.value??``}),o=Z(e),[c,l]=(0,k.useState)(`list`),[u,d]=(0,k.useState)(()=>o.entries.map(e=>i(e))),[p,_]=(0,k.useState)(o.error),[v,y]=(0,k.useState)(180),b=(0,k.useCallback)(e=>{e.preventDefault();let t=e.clientY,n=v,r=e=>{y(Math.max(120,n+e.clientY-t))},i=()=>{document.removeEventListener(`mousemove`,r),document.removeEventListener(`mouseup`,i)};document.addEventListener(`mousemove`,r),document.addEventListener(`mouseup`,i)},[v]),C=e=>{d(e),_(null),t(Q(e))};return(0,Y.jsxs)(`div`,{className:`app-field-group`,children:[(0,Y.jsx)(m,{value:c,onValueChange:t=>{if(!(t!==`list`&&t!==`code`)){if(t===`list`){let t=Z(e);_(t.error),t.error||d(t.entries.map(e=>i(e)))}l(t)}},children:(0,Y.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-2`,children:[(0,Y.jsx)(h,{children:`响应头`}),(0,Y.jsxs)(g,{"aria-label":`响应头编辑视图`,children:[(0,Y.jsx)(f,{value:`list`,"data-testid":`mock-headers-view-list`,children:`列表`}),(0,Y.jsx)(f,{value:`code`,"data-testid":`mock-headers-view-code`,children:`代码`})]})]})}),c===`list`?p?(0,Y.jsxs)(`p`,{className:`text-xs text-red-600 dark:text-red-400`,"data-testid":`mock-headers-parse-error`,children:[p,`。请在代码视图中修正。`]}):(0,Y.jsxs)(`div`,{className:`flex flex-col gap-2`,"data-testid":`mock-headers-list`,children:[u.map((e,t)=>(0,Y.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,Y.jsx)(x,{value:e.key,onChange:t=>{C(u.map(n=>n.id===e.id?{...n,key:t.target.value}:n))},placeholder:`名称`,"aria-label":`响应头名称 ${t+1}`,className:`font-mono`}),(0,Y.jsx)(x,{value:e.value,onChange:t=>{C(u.map(n=>n.id===e.id?{...n,value:t.target.value}:n))},placeholder:`值`,"aria-label":`响应头值 ${t+1}`,className:`font-mono`}),(0,Y.jsx)(r,{type:`button`,variant:`ghost`,size:`icon-sm`,"aria-label":`删除响应头 ${t+1}`,onClick:()=>C(u.filter(t=>t.id!==e.id)),children:(0,Y.jsx)(S,{})})]},e.id)),(0,Y.jsxs)(r,{type:`button`,variant:`outline`,size:`sm`,className:`self-start`,onClick:()=>C([...u,i()]),children:[(0,Y.jsx)(s,{"data-icon":`inline-start`}),`添加`]})]}):(0,Y.jsxs)(`div`,{className:`group relative`,style:{height:`${v}px`},"data-testid":`mock-headers-code-frame`,children:[(0,Y.jsx)(E,{value:e,onChange:t,language:`json`,height:`flex`,className:`mock-headers-code`,placeholder:`{"Content-Type":"application/json"}`}),(0,Y.jsx)(`div`,{"data-testid":`mock-headers-resize`,role:`separator`,"aria-orientation":`horizontal`,"aria-label":`调整响应头编辑器高度`,"aria-valuenow":v,className:`absolute bottom-0 left-0 right-0 flex h-4 cursor-ns-resize items-center justify-center bg-gradient-to-t from-border/50 to-transparent opacity-0 transition-opacity group-hover:opacity-100`,onMouseDown:b,children:(0,Y.jsx)(a,{className:`h-4 w-4 text-muted-foreground`})})]})]})}var ne={name:``,urlPattern:``,query:``,method:`*`,statusCode:200,delay:0,bodyType:`inline`,headers:{},body:``,enabled:!0};function $({rule:e,initialData:t,createMock:n,updateMock:s,onSaved:l}){let f=(0,k.useMemo)(()=>e?{name:e.name,urlPattern:e.urlPattern,query:e.query||``,method:e.method,statusCode:e.statusCode,delay:e.delay||0,bodyType:e.bodyType||`inline`,headers:e.headers||{},body:e.body,enabled:e.enabled}:{...ne,...t},[t,e]),[p,m]=(0,k.useState)(f),[g,S]=(0,k.useState)(()=>JSON.stringify(f.headers||{},null,2)),[A,j]=(0,k.useState)(!1),[M,N]=(0,k.useState)(null),[P,F]=(0,k.useState)(null),[I,R]=(0,k.useState)(null),[z,B]=(0,k.useState)(!1),[V,H]=(0,k.useState)(!1),[U,W]=(0,k.useState)(300),G=u(d()),K=(0,k.useCallback)(e=>{if(!e.trim()){R(null);return}let t=T(e);R(t.valid?null:t.error||`内容格式错误`)},[]),q=(e,t)=>{m(n=>({...n,[e]:t})),e===`body`&&typeof t==`string`&&K(t)},X=(0,k.useCallback)(e=>{e.preventDefault();let t=e.clientY,n=U,r=e=>{let r=e.clientY-t;W(Math.max(150,n+r))},i=()=>{document.removeEventListener(`mousemove`,r),document.removeEventListener(`mouseup`,i)};document.addEventListener(`mousemove`,r),document.addEventListener(`mouseup`,i)},[U]),Z=async()=>{if(!(!p.body.trim()||V)){H(!0),F(null);try{let{formatted:e}=await J(p.body);q(`body`,e)}catch(e){F(e instanceof Error?e.message:`格式化失败`),window.setTimeout(()=>F(null),3e3)}finally{H(!1)}}},Q=async()=>{if(!(!p.body.trim()||z||!G)){B(!0),F(null);try{let e=await L(p.body,!0);if(!e.success)throw Error(`自动修复失败,请手动修正语法错误`);q(`body`,e.fixed),R(null)}catch(e){F(e instanceof Error?e.message:`修复失败`),window.setTimeout(()=>F(null),3e3)}finally{B(!1)}}},$=async()=>{if(!p.urlPattern.trim()){N(`请填写 URL 匹配`);return}if(p.bodyType===`inline`&&p.body.trim()){let e=T(p.body);if(!e.valid){R(e.error||`内容格式错误`);return}}j(!0),N(null);try{let t={};if(g.trim()){let e=JSON.parse(g);if(!e||typeof e!=`object`||Array.isArray(e))throw Error(`响应头必须是 JSON 对象`);t=Object.fromEntries(Object.entries(e).map(([e,t])=>[e,String(t)]))}let r={...p,headers:t},i=!1;if(i=e?await s(e.id,r):!!await n(r),!i)throw Error(`保存 Mock 规则失败`);y.success(e?`Mock 规则已更新`:`Mock 规则已创建`),l?.()}catch(e){let t=e instanceof Error?e.message:`保存失败`;N(t),y.error(t)}finally{j(!1)}};C({active:!0,enabled:!A&&!!p.urlPattern.trim(),priority:w.panel,onSave:$});let re=D();return(0,Y.jsxs)(`div`,{className:`flex h-full min-h-0 flex-col`,children:[(0,Y.jsxs)(`div`,{className:`app-panel-content`,children:[M&&(0,Y.jsx)(`div`,{className:`rounded-md border border-red-200 bg-red-50 px-3 py-2 text-sm text-red-700 dark:border-red-900 dark:bg-red-950/20 dark:text-red-300`,children:M}),(0,Y.jsxs)(`div`,{className:`grid gap-4 sm:grid-cols-2`,children:[(0,Y.jsxs)(`div`,{className:`app-field-group`,children:[(0,Y.jsx)(h,{children:`规则名称`}),(0,Y.jsx)(x,{value:p.name,onChange:e=>q(`name`,e.target.value),placeholder:`如:模拟欠费状态`})]}),(0,Y.jsxs)(`div`,{className:`app-field-group`,children:[(0,Y.jsx)(h,{children:`HTTP 方法`}),(0,Y.jsxs)(`select`,{value:p.method,onChange:e=>q(`method`,e.target.value),className:`flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm`,children:[(0,Y.jsx)(`option`,{value:`*`,children:`全部`}),(0,Y.jsx)(`option`,{value:`GET`,children:`GET`}),(0,Y.jsx)(`option`,{value:`POST`,children:`POST`}),(0,Y.jsx)(`option`,{value:`PUT`,children:`PUT`}),(0,Y.jsx)(`option`,{value:`DELETE`,children:`DELETE`}),(0,Y.jsx)(`option`,{value:`PATCH`,children:`PATCH`})]})]})]}),(0,Y.jsxs)(`div`,{className:`app-field-group`,children:[(0,Y.jsx)(h,{children:`URL 匹配(支持正则)`}),(0,Y.jsx)(x,{value:p.urlPattern,onChange:e=>q(`urlPattern`,e.target.value),placeholder:`如:/api/console/user/corp/.*`,className:`font-mono`})]}),(0,Y.jsxs)(`div`,{className:`app-field-group`,children:[(0,Y.jsx)(h,{children:`Query 匹配(可选)`}),(0,Y.jsx)(x,{value:p.query||``,onChange:e=>q(`query`,e.target.value),placeholder:`如:window_key=A`,className:`font-mono`})]}),(0,Y.jsxs)(`div`,{className:`grid gap-4 sm:grid-cols-2`,children:[(0,Y.jsxs)(`div`,{className:`app-field-group`,children:[(0,Y.jsx)(h,{children:`响应状态码`}),(0,Y.jsx)(x,{type:`number`,value:p.statusCode,onChange:e=>q(`statusCode`,parseInt(e.target.value)||200)})]}),(0,Y.jsxs)(`div`,{className:`app-field-group`,children:[(0,Y.jsx)(h,{children:`响应延迟 (ms)`}),(0,Y.jsx)(x,{type:`number`,value:p.delay,onChange:e=>q(`delay`,parseInt(e.target.value)||0)})]})]}),(0,Y.jsx)(te,{value:g,onChange:S}),(0,Y.jsxs)(`div`,{className:`app-field-group`,children:[(0,Y.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-2`,children:[(0,Y.jsx)(h,{children:`响应内容`}),(0,Y.jsxs)(`div`,{className:`flex flex-wrap items-center justify-end gap-2`,children:[P&&(0,Y.jsx)(`span`,{className:`max-w-[280px] truncate text-xs text-red-500`,title:P,children:P}),p.body.trim()&&(0,Y.jsxs)(r,{type:`button`,variant:`outline`,size:`xs`,onClick:Q,disabled:z||!G,title:G?`使用 AI 修复响应内容`:`AI 未配置或未启用`,children:[z?(0,Y.jsx)(v,{className:`mr-1 h-3 w-3 animate-spin`}):(0,Y.jsx)(c,{className:`mr-1 h-3 w-3`}),z?`修复中...`:`AI修复`]}),(0,Y.jsxs)(r,{type:`button`,variant:`ghost`,size:`xs`,onClick:Z,disabled:V||!p.body.trim(),title:`格式化响应内容`,children:[V?(0,Y.jsx)(v,{className:`mr-1 h-3 w-3 animate-spin`}):(0,Y.jsx)(i,{className:`mr-1 h-3 w-3`}),V?`格式化中...`:`代码格式化`]})]})]}),(0,Y.jsxs)(`div`,{className:`relative group`,style:{height:`${U}px`},children:[(0,Y.jsx)(E,{value:p.body,onChange:e=>q(`body`,e),placeholder:`支持 JSON、HTML、JS、CSS 等响应内容`,height:`flex`}),(0,Y.jsx)(`div`,{className:`absolute bottom-0 left-0 right-0 h-4 cursor-ns-resize flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity bg-gradient-to-t from-border/50 to-transparent`,onMouseDown:X,children:(0,Y.jsx)(a,{className:`h-4 w-4 text-muted-foreground`})})]}),I&&(0,Y.jsxs)(`div`,{className:`flex items-start gap-2 p-2 rounded-md bg-red-50 dark:bg-red-950/20 border border-red-200 dark:border-red-900`,children:[(0,Y.jsx)(`span`,{className:`text-xs text-red-600 dark:text-red-400 font-medium`,children:`语法错误:`}),(0,Y.jsx)(`span`,{className:`text-xs text-red-600 dark:text-red-400 flex-1`,children:I})]})]}),(0,Y.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,Y.jsx)(o,{checked:p.enabled,onCheckedChange:e=>q(`enabled`,!!e)}),(0,Y.jsx)(h,{className:`text-sm`,children:`启用此规则`})]})]}),re?null:(0,Y.jsx)(_,{}),(0,Y.jsx)(O,{className:`flex justify-end gap-2 px-5 py-3`,children:(0,Y.jsxs)(b,{size:`sm`,onClick:$,disabled:A||!p.urlPattern.trim(),children:[A?(0,Y.jsx)(v,{"data-icon":`inline-start`,className:`animate-spin`}):(0,Y.jsx)(ee,{"data-icon":`inline-start`}),A?`保存中...`:`保存`]})})]})}export{$ as MockEditorPanel};
@@ -1,2 +0,0 @@
1
- import{c as e,d as t,p as n,t as r}from"./button-BFNlGZ5p.js";import"./dist-CFZ4xMSF.js";import{t as i}from"./pencil-line-CEZ7D-de.js";import{t as a}from"./rotate-ccw-CRguJya4.js";import{t as o}from"./zap-CEVoVkAg.js";import"./es2015-CRmLuA2o.js";import{i as s,o as c,r as ee}from"./ai-config-store-B_VpGvwx.js";import{C as l,Mt as te,O as ne,S as u,Tt as d,_ as f,b as p,et as m,v as h,vt as g,w as _,y as v}from"./index-Bu3zaxzE.js";import{n as y}from"./monaco-editor-DeJNlo9k.js";import{i as re,r as b,t as ie}from"./editor-pane-actions-DN-pxFsl.js";import{t as ae}from"./panel-heading-BAI_lNmT.js";import{t as oe}from"./textarea-BjWF0pk4.js";var x=n(t(),1),S=e();function C({open:e=!1,onOpenChange:t,embedded:n=!1,plainHeading:C=!1,filename:w,onSaved:T}){let[E,D]=(0,x.useState)(``),[O,k]=(0,x.useState)(``),[se,A]=(0,x.useState)(!1),[j,M]=(0,x.useState)(!1),[N,P]=(0,x.useState)(!1),[F,I]=(0,x.useState)(!1),[L,R]=(0,x.useState)(null),[z,B]=(0,x.useState)(``),[V,H]=(0,x.useState)(null),[U,W]=(0,x.useState)(!1),G=E!==O,K=ee(),q=s(K),ce=q?{provider:q.provider,apiKey:q.apiKey,baseUrl:q.baseUrl,model:q.model}:{provider:K.provider,apiKey:K.apiKey,baseUrl:K.baseUrl,model:K.model},J=c(K),Y=(0,x.useCallback)(async()=>{if(w){A(!0),R(null);try{let e=await fetch(`/api/plugins/custom/${encodeURIComponent(w)}/code`);if(!e.ok){let t=await e.json();throw Error(t.error||`读取插件代码失败`)}let t=await e.json();D(t.code),k(t.code)}catch(e){R(e instanceof Error?e.message:`读取失败`)}finally{A(!1)}}},[w]);(0,x.useEffect)(()=>{(e||n)&&w&&Y()},[e,n,w,Y]);let X=async()=>{M(!0),R(null);try{let e=await fetch(`/api/plugins/custom/${encodeURIComponent(w)}/code`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({code:E})});if(!e.ok){let t=await e.json();throw Error(t.error||`保存失败`)}k(E),window.dispatchEvent(new CustomEvent(`plugins-custom-updated`)),T?.(),f.success(`插件代码保存成功`)}catch(e){let t=e instanceof Error?e.message:`保存失败`;R(t),f.error(t)}finally{M(!1)}},le=async()=>{M(!0),P(!0),R(null);try{let e=await fetch(`/api/plugins/custom/${encodeURIComponent(w)}/code`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({code:E})});if(!e.ok){let t=await e.json();throw Error(t.error||`保存失败`)}if(k(E),!(await fetch(`/api/plugins/reload`,{method:`POST`})).ok)throw Error(`热加载失败`);T?.(),window.dispatchEvent(new CustomEvent(`plugins-custom-updated`)),f.success(`插件代码已保存并完成热加载`)}catch(e){let t=e instanceof Error?e.message:`操作失败`;R(t),f.error(t)}finally{M(!1),P(!1)}};h({active:e||n,enabled:G&&!j&&!F,priority:v.panel,onSave:X});let ue=()=>{D(O)},Z=()=>{G&&!confirm(`有未保存的修改,确定要关闭吗?`)||(W(!1),t?.(!1))},Q=re();b(Z);let de=async()=>{if(!z.trim()||!J)return;let e=E;W(!0),I(!0),R(null),H(`AI 正在根据补充需求更新代码...`);try{let e=await fetch(`/api/plugins/revise-stream`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({originalCode:E,instruction:z.trim(),requirement:{name:w.replace(/\.js$/i,``),description:`根据补充要求更新插件 ${w},保持 Meddle 插件结构和现有核心能力正确。`},aiConfig:ce})});if(!e.ok){let t=await e.json();throw Error(t.error||`AI 更新代码失败`)}let t=e.body?.getReader(),n=new TextDecoder;if(!t)throw Error(`无法读取 AI 更新流`);let r=``,i=``;for(;;){let{done:e,value:a}=await t.read();if(e)break;i+=n.decode(a,{stream:!0});let o=i.split(`
2
- `);i=o.pop()||``;for(let e of o){if(!e.startsWith(`data:`))continue;let t=e.slice(5).trim();if(t)try{let e=JSON.parse(t);if(e.status===`generating`)H(`AI 正在根据补充需求更新代码...`);else if(e.chunk)r=e.accumulated||`${r}${e.chunk}`,D(r),H(`生成中... ${r.length} 字符`);else if(e.status===`success`)r=e.revisedCode||r,D(r),H(`AI 已完成代码更新,请检查后保存。`);else if(e.error)throw Error(e.error)}catch(e){if(e instanceof Error&&e.message!==`Unexpected end of JSON input`)throw e}}}if(!r.trim())throw Error(`AI 未返回有效代码`)}catch(t){let n=t instanceof Error?t.message:`AI 更新代码失败`;D(e),R(n),H(`更新失败,已恢复原代码:${n}`)}finally{I(!1)}},$=(0,S.jsxs)(S.Fragment,{children:[C?null:(0,S.jsxs)(S.Fragment,{children:[(0,S.jsx)(ae,{className:`px-6 pt-6 pb-3`,title:(0,S.jsxs)(S.Fragment,{children:[(0,S.jsx)(te,{className:`h-5 w-5`}),w,G&&(0,S.jsx)(m,{variant:`outline`,className:`text-orange-600 border-orange-300`,children:`未保存`})]}),description:`查看和编辑插件源码,保存后需热加载才能生效`}),(0,S.jsx)(u,{})]}),(0,S.jsx)(`div`,{className:`flex min-h-0 flex-1 flex-col overflow-hidden px-4 py-3`,children:se?(0,S.jsxs)(`div`,{className:`flex flex-1 items-center justify-center gap-2 text-muted-foreground`,children:[(0,S.jsx)(d,{className:`h-5 w-5 animate-spin`}),(0,S.jsx)(`span`,{children:`加载中...`})]}):L&&!E?(0,S.jsx)(`div`,{className:`flex flex-1 items-center justify-center text-destructive`,children:L}):(0,S.jsx)(`div`,{className:`min-h-0 flex-1`,children:(0,S.jsx)(`div`,{className:`relative h-full min-h-[320px]`,children:(0,S.jsx)(y,{value:E,onChange:D,language:`javascript`,height:`flex`})})})}),(0,S.jsx)(`div`,{"aria-hidden":!U,className:[`overflow-hidden transition-[max-height,opacity] duration-200 ease-out`,U?`max-h-[260px] border-t opacity-100`:`max-h-0 border-t-0 opacity-0 pointer-events-none`].join(` `),children:(0,S.jsxs)(`div`,{className:`space-y-3 px-6 py-4`,children:[(0,S.jsxs)(`div`,{className:`flex items-start justify-between gap-3`,children:[(0,S.jsxs)(`div`,{className:`min-w-0`,children:[(0,S.jsxs)(`div`,{className:`flex items-center gap-2 text-sm font-medium`,children:[(0,S.jsx)(i,{className:`h-4 w-4`}),`AI 更新代码`]}),(0,S.jsx)(`p`,{className:`mt-1 text-xs text-muted-foreground`,children:`输入补充需求后,AI 会直接把结果写回当前编辑器。`})]}),(0,S.jsx)(r,{variant:`ghost`,size:`xs`,onClick:()=>W(!1),disabled:!U||F,children:`收起`})]}),(0,S.jsxs)(`div`,{className:`grid gap-3 md:grid-cols-[minmax(0,1fr)_auto] md:items-end`,children:[(0,S.jsxs)(`div`,{className:`app-field-group`,children:[(0,S.jsx)(ne,{htmlFor:`plugin-editor-extra-instruction`,children:`补充需求信息`}),(0,S.jsx)(oe,{id:`plugin-editor-extra-instruction`,value:z,onChange:e=>B(e.target.value),placeholder:`例如:补充 onBeforeResponse 对空 referer 的处理;保留现有 manifest 和 hook,不要改插件 id。`,className:`min-h-[88px] resize-none`,disabled:!U||F||j})]}),(0,S.jsx)(r,{size:`sm`,onClick:de,disabled:!U||!z.trim()||!J||F||j,title:J?`根据补充需求更新当前代码`:`AI 未配置或未启用`,children:F?(0,S.jsxs)(S.Fragment,{children:[(0,S.jsx)(d,{className:`h-4 w-4 mr-1 animate-spin`}),`更新中...`]}):(0,S.jsxs)(S.Fragment,{children:[(0,S.jsx)(i,{className:`h-4 w-4 mr-1`}),`更新代码`]})})]}),(0,S.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:V||(J?`生成结果会写回上方编辑器,请检查后再保存或热加载。`:`AI 未配置或未启用,请先在设置中配置 AI 服务。`)})]})}),L&&E&&(0,S.jsx)(`div`,{className:`px-6 py-2 text-sm text-destructive bg-destructive/10`,children:L}),Q?null:(0,S.jsx)(u,{}),(0,S.jsxs)(ie,{className:`px-6 py-3 flex justify-between items-center gap-2`,children:[(0,S.jsxs)(`div`,{className:Q?`contents`:`flex items-center gap-2`,children:[C&&G?(0,S.jsx)(m,{variant:`outline`,className:`text-orange-600 border-orange-300`,children:`未保存`}):null,(0,S.jsxs)(r,{variant:`ghost`,size:`sm`,onClick:ue,disabled:!G||j||F,title:`撤销修改`,children:[(0,S.jsx)(a,{className:`h-4 w-4 mr-1`}),`还原`]}),(0,S.jsxs)(r,{variant:`outline`,size:`sm`,onClick:()=>W(e=>!e),disabled:!E||j||F,title:J?`使用 AI 根据补充需求更新代码`:`AI 未配置或未启用`,children:[(0,S.jsx)(i,{className:`h-4 w-4 mr-1`}),`AI 更新代码`]})]}),(0,S.jsxs)(`div`,{className:Q?`contents`:`flex gap-2`,children:[Q?null:(0,S.jsx)(r,{variant:`outline`,size:`sm`,onClick:Z,disabled:j||F,children:`关闭`}),(0,S.jsxs)(p,{variant:`outline`,size:`sm`,onClick:X,disabled:!G||j||F,children:[j&&!N?(0,S.jsx)(d,{"data-icon":`inline-start`,className:`animate-spin`}):(0,S.jsx)(g,{"data-icon":`inline-start`}),`保存`]}),(0,S.jsxs)(r,{size:`sm`,onClick:le,disabled:!G||j||F,children:[N?(0,S.jsx)(d,{className:`h-4 w-4 mr-1 animate-spin`}):(0,S.jsx)(o,{className:`h-4 w-4 mr-1`}),`保存并热加载`]})]})]})]});return n?(0,S.jsx)(`div`,{className:`flex h-full min-h-0 flex-col`,children:$}):(0,S.jsx)(l,{open:e,onOpenChange:e=>{!e&&G&&!confirm(`有未保存的修改,确定要关闭吗?`)||(e||W(!1),t?.(e))},children:(0,S.jsx)(_,{className:`p-0 flex flex-col`,resizable:!0,defaultWidth:900,storageKey:`plugin-code-editor`,children:$})})}export{C as PluginCodeEditor};
@@ -1,2 +0,0 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/plugin-generator-Cr_gk3Tp.js","assets/button-BFNlGZ5p.js","assets/index-Bu3zaxzE.js","assets/dist-DD7AvbXP.js","assets/dist-CFZ4xMSF.js","assets/dist-C-E2R2jk.js","assets/dist-BCvvYbmI.js","assets/dist-Bq2klZ3g.js","assets/dist-LiAcI8CK.js","assets/dist-UcOFuoN0.js","assets/dist-BNcjMpca.js","assets/es2015-CRmLuA2o.js","assets/dist-CRmX_NvH.js","assets/dist-YM3jbhT-.js","assets/check-BkfHQ6re.js","assets/chevron-down-DHwUtL4O.js","assets/ai-config-store-B_VpGvwx.js","assets/index-D9jGD_NA.css","assets/circle-x-BEkinhez.js","assets/code-DD-AYxxu.js","assets/copy-BRnscYy1.js","assets/wand-sparkles-DDGjzjnX.js","assets/editor-pane-actions-DN-pxFsl.js","assets/panel-heading-BAI_lNmT.js","assets/textarea-BjWF0pk4.js","assets/plugin-code-editor-CQqpaaCR.js","assets/monaco-editor-DeJNlo9k.js","assets/pencil-line-CEZ7D-de.js","assets/rotate-ccw-CRguJya4.js","assets/zap-CEVoVkAg.js","assets/plugin-test-dialog-B5mVM3XE.js","assets/body-diff-view-ByCHr9bv.js","assets/arrow-right-BNum_060.js","assets/circle-alert-zMagrFuI.js","assets/refresh-cw-BfLoHqg5.js"])))=>i.map(i=>d[i]);
2
- import{c as e,d as t,p as n,t as r,u as i}from"./button-BFNlGZ5p.js";import"./dist-CFZ4xMSF.js";import{t as a}from"./refresh-cw-BfLoHqg5.js";import{t as o}from"./zap-CEVoVkAg.js";import"./es2015-CRmLuA2o.js";import{t as s}from"./switch-DpLnRvOJ.js";import{J as c,K as ee,Lt as l,St as u,Tt as d,X as te,Y as f,Z as p,dt as m,et as h,ht as ne,lt as re,mt as g,n as ie,q as ae,tt as oe,ut as _}from"./index-Bu3zaxzE.js";import{n as v}from"./editor-pane-actions-DN-pxFsl.js";import{n as se,t as y}from"./pane-split-Db1aWKUO.js";var ce=i(`shield-alert`,[[`path`,{d:`M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z`,key:`oel41y`}],[`path`,{d:`M12 8v4`,key:`1got3b`}],[`path`,{d:`M12 16h.01`,key:`1drbdi`}]]),b=i(`shield`,[[`path`,{d:`M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z`,key:`oel41y`}]]),x=i(`unplug`,[[`path`,{d:`m19 5 3-3`,key:`yk6iyv`}],[`path`,{d:`m2 22 3-3`,key:`19mgm9`}],[`path`,{d:`M6.3 20.3a2.4 2.4 0 0 0 3.4 0L12 18l-6-6-2.3 2.3a2.4 2.4 0 0 0 0 3.4Z`,key:`goz73y`}],[`path`,{d:`M7.5 13.5 10 11`,key:`7xgeeb`}],[`path`,{d:`M10.5 16.5 13 14`,key:`10btkg`}],[`path`,{d:`m12 6 6 6 2.3-2.3a2.4 2.4 0 0 0 0-3.4l-2.6-2.6a2.4 2.4 0 0 0-3.4 0Z`,key:`1snsnr`}]]),S=n(t(),1),C=y({storageKey:`meddle-plugin-list-width`,defaultPx:360,minPx:280,maxPx:560,editorMinPx:420});C.storageKey,C.defaultPx;var w=e(),le=(0,S.lazy)(()=>l(()=>import(`./plugin-generator-Cr_gk3Tp.js`).then(e=>({default:e.PluginGenerator})),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]))),T=(0,S.lazy)(()=>l(()=>import(`./plugin-code-editor-CQqpaaCR.js`).then(e=>({default:e.PluginCodeEditor})),__vite__mapDeps([25,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,26,27,28,29,22,23,24]))),E=(0,S.lazy)(()=>l(()=>import(`./plugin-test-dialog-B5mVM3XE.js`).then(e=>({default:e.PluginTestDialog})),__vite__mapDeps([30,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,26,31,32,33,18,27,34,21,22,23,24])));function D(){return(0,w.jsxs)(`div`,{className:`flex h-full min-h-[160px] items-center justify-center gap-2 text-sm text-muted-foreground`,children:[(0,w.jsx)(d,{className:`size-4 animate-spin`}),`加载编辑器...`]})}function O({plugins:e,pluginMode:t,switchPluginMode:n,fetchPlugins:i,startPlugin:l,stopPlugin:u,togglePlugin:g,thirdPartyPlugins:y,thirdPartySecurity:O,fetchThirdPartyPlugins:j,loadThirdPartyPlugin:M,unloadThirdPartyPlugin:pe}){let[P,F]=(0,S.useState)(!1),[I,L]=(0,S.useState)(``),[R,z]=(0,S.useState)(!1),[B,me]=(0,S.useState)([]),[V,H]=(0,S.useState)(!1),[U,W]=(0,S.useState)({kind:`idle`}),[he,ge]=(0,S.useState)(null),G=(0,S.useRef)(null),_e=(0,S.useCallback)(e=>{G.current=e},[]),ve=(0,S.useCallback)(()=>{if(G.current){G.current();return}W({kind:`idle`})},[]);(0,S.useEffect)(()=>{i(),j(),K()},[i,j]),(0,S.useEffect)(()=>{let e=()=>{K()};return window.addEventListener(`plugins-custom-updated`,e),()=>window.removeEventListener(`plugins-custom-updated`,e)},[]);let K=async()=>{try{me((await(await fetch(`/api/plugins/custom`)).json()).plugins||[])}catch(e){console.error(`加载自定义插件失败:`,e)}},ye=async(e,t)=>{if(confirm(`确定要删除插件 ${e} 吗?`))try{let n=await fetch(`/api/plugins/custom/${encodeURIComponent(e)}`,{method:`DELETE`});if(n.ok)W(n=>n.kind===`code`&&n.filename===e||n.kind===`test`&&(n.filename===e||t!==void 0&&n.pluginId===t)?{kind:`idle`}:n),await K();else{let e=await n.json();alert(e.error||`删除失败`)}}catch(e){console.error(`删除插件失败:`,e),alert(`删除失败`)}},q=async(e,t)=>{if(confirm(`插件文件已删除,确定要从内存卸载 ${t} 吗?`))try{let t=await fetch(`/api/plugins/custom/loaded/${encodeURIComponent(e)}/unload`,{method:`POST`});if(t.ok)W(t=>(t.kind===`test`||t.kind===`builtin`)&&t.pluginId===e?{kind:`idle`}:t),await i(),await K();else{let e=await t.json().catch(()=>({}));alert(e.error||`卸载失败`)}}catch(e){console.error(`卸载插件失败:`,e),alert(`卸载失败`)}},be=async()=>{H(!0);try{let e=await fetch(`/api/plugins/reload`,{method:`POST`});if(e.ok){let t=await e.json();alert(`成功热加载 ${t.count} 个插件!`),await i(),await K()}else{let t=await e.json();alert(t.error||`热加载失败`)}}catch(e){console.error(`热加载失败:`,e),alert(`热加载失败`)}finally{H(!1)}},xe=async e=>{F(!0);try{await l(e),await i()}finally{F(!1)}},Se=async e=>{F(!0);try{await u(e),await i()}finally{F(!1)}},Ce=async()=>{if(I.trim()){z(!0);try{await M(I),L(``),await j()}finally{z(!1)}}},J=async e=>{z(!0);try{await pe(e),await j(),U.kind===`third-party`&&U.pluginId===e&&W({kind:`idle`})}finally{z(!1)}},{builtinPlugins:Y,customRows:X}=ie(e,B,new Set(y.map(e=>e.id))),Z=U.kind===`builtin`?e.find(e=>e.id===U.pluginId):void 0,Q=Z?X.find(e=>e.fileDeleted&&e.pluginId===Z.id):void 0,$=U.kind===`third-party`?y.find(e=>e.id===U.pluginId):void 0,we=U.kind===`generate`?`编辑插件 · AI 生成`:U.kind===`code`?`编辑插件 · ${U.filename}`:U.kind===`test`?`编辑插件 · 测试 ${U.pluginName}`:U.kind===`builtin`?`编辑插件 · ${Z?.name||U.pluginId}`:U.kind===`third-party`?`编辑插件 · ${$?.name||U.pluginId}`:U.kind===`load-third-party`?`编辑插件 · 加载第三方`:`编辑插件`,Te=U.kind===`code`||U.kind===`generate`||U.kind===`test`;return(0,w.jsxs)(se,{testId:`plugin-config-layout`,layout:`list-edit`,widthAttr:`plugin-list-width`,split:C,listTestId:`plugin-config-list`,panelTestId:`plugin-config-edit`,separatorTestId:`plugin-panel-separator`,separatorLabel:`调整插件列表宽度`,list:(0,w.jsxs)(w.Fragment,{children:[(0,w.jsxs)(`div`,{className:`shrink-0 border-b`,children:[(0,w.jsxs)(`div`,{className:`app-pane-bar flex items-center justify-between gap-2`,children:[(0,w.jsx)(`div`,{className:`text-[10px] font-medium uppercase tracking-wide text-muted-foreground`,children:`插件`}),(0,w.jsxs)(`div`,{className:`flex items-center gap-1`,children:[(0,w.jsx)(r,{variant:`ghost`,size:`icon-sm`,onClick:()=>void K(),disabled:P||V,"aria-label":`刷新列表`,children:(0,w.jsx)(a,{})}),(0,w.jsx)(r,{variant:`ghost`,size:`icon-sm`,onClick:()=>void be(),disabled:P||V,"aria-label":`热加载插件`,children:V?(0,w.jsx)(d,{className:`animate-spin`}):(0,w.jsx)(o,{})}),(0,w.jsxs)(r,{variant:`outline`,size:`sm`,onClick:()=>W({kind:`generate`}),"data-testid":`plugin-config-generate`,children:[(0,w.jsx)(ne,{"data-icon":`inline-start`}),`AI 生成`]})]})]}),(0,w.jsxs)(`div`,{className:`flex items-center gap-2 px-[var(--ui-section-gap)] pb-[var(--ui-section-gap)]`,children:[(0,w.jsxs)(ee,{value:t,onValueChange:e=>n(e),children:[(0,w.jsx)(te,{className:`h-7 w-full text-xs`,"aria-label":`插件模式`,children:(0,w.jsx)(p,{})}),(0,w.jsx)(ae,{children:(0,w.jsxs)(c,{children:[(0,w.jsx)(f,{value:`off`,children:`关闭`}),(0,w.jsx)(f,{value:`on`,children:`开启`}),(0,w.jsx)(f,{value:`shadow`,children:`影子模式`})]})})]}),t===`off`?(0,w.jsx)(h,{variant:`destructive`,className:`shrink-0 text-xs`,children:`未生效`}):null]})]}),(0,w.jsxs)(`div`,{"data-plugin-row-list":``,className:`meddle-thin-scroll min-h-0 flex-1 overflow-x-hidden overflow-y-auto`,children:[(0,w.jsx)(k,{title:`内置插件`,children:Y.length===0?(0,w.jsx)(A,{children:`暂无内置插件`}):Y.map(e=>(0,w.jsx)(N,{testId:`plugin-config-row-builtin-${e.id}`,selected:U.kind===`builtin`&&U.pluginId===e.id,title:e.name,meta:e.version,onSelect:()=>W({kind:`builtin`,pluginId:e.id}),badge:(0,w.jsx)(h,{variant:e.state===`running`?`default`:`secondary`,children:e.state})},e.id))}),(0,w.jsx)(k,{title:`自定义插件`,children:X.length===0?(0,w.jsx)(A,{children:`暂无自定义插件,点击「AI 生成」`}):X.map(({filename:e,pluginId:t,loadedPlugin:n,fileDeleted:i})=>{let a=n?n.state!==`disabled`:!1,o=i?(U.kind===`builtin`||U.kind===`test`)&&U.pluginId===t:U.kind===`code`&&U.filename===e||U.kind===`test`&&(U.filename===e||U.pluginId===t),c=n?a?`已启用`:`已禁用`:`未加载`;return(0,w.jsx)(N,{testId:i?`plugin-config-row-custom-deleted-${t}`:`plugin-config-row-custom-${e}`,selected:o,title:e,meta:c,muted:!!n&&!a,onSelect:()=>W(i?{kind:`builtin`,pluginId:t}:{kind:`code`,filename:e}),badge:(0,w.jsxs)(w.Fragment,{children:[i?(0,w.jsxs)(`span`,{"data-testid":`plugin-file-deleted-label`,className:`mr-1 inline-flex items-center gap-1 text-xs text-muted-foreground`,children:[(0,w.jsx)(re,{"aria-hidden":`true`,className:`size-3.5 shrink-0`}),`文件已删除`]}):null,n?(0,w.jsx)(s,{checked:a,onCheckedChange:e=>g(n.id,e),"aria-label":`启用插件 ${e}`}):(0,w.jsx)(h,{variant:`outline`,children:`未加载`})]}),action:(0,w.jsxs)(`div`,{className:`flex items-center`,children:[n&&a&&!i&&(0,w.jsx)(r,{variant:`ghost`,size:`icon-sm`,onClick:()=>W({kind:`test`,pluginId:n.id,pluginName:n.name,hooks:n.hooks,filename:e}),"aria-label":`测试插件 ${n.name}`,children:(0,w.jsx)(m,{})}),i?(0,w.jsx)(r,{variant:`ghost`,size:`icon-sm`,onClick:()=>void q(t,e),"aria-label":`卸载插件 ${e}`,"aria-description":`文件已删除,仅从内存移除`,title:`卸载`,children:(0,w.jsx)(x,{})}):(0,w.jsx)(r,{variant:`ghost`,size:`icon-sm`,onClick:()=>void ye(e,n?.id),className:`text-destructive`,"aria-label":`删除插件 ${e}`,children:(0,w.jsx)(_,{})})]})},i?`loaded:${t}`:e)})}),(0,w.jsx)(k,{title:`第三方插件`,extra:(0,w.jsxs)(`span`,{className:`inline-flex items-center gap-1 normal-case tracking-normal`,children:[O.allowAll?(0,w.jsx)(b,{className:`size-3.5 text-primary`}):(0,w.jsx)(ce,{className:`size-3.5`}),O.allowAll?`已信任所有插件`:`已信任 ${O.trusted.length} 个`]}),action:(0,w.jsx)(r,{variant:`ghost`,size:`xs`,onClick:()=>W({kind:`load-third-party`}),"data-testid":`plugin-config-load`,children:`加载`}),children:y.length===0?(0,w.jsx)(A,{children:`暂无第三方插件`}):y.map(e=>(0,w.jsx)(N,{testId:`plugin-config-row-third-${e.id}`,selected:U.kind===`third-party`&&U.pluginId===e.id,title:e.name,meta:e.version,onSelect:()=>W({kind:`third-party`,pluginId:e.id}),badge:(0,w.jsx)(h,{variant:e.state===`running`?`default`:`secondary`,children:e.state})},e.id))})]})]}),children:[(0,w.jsxs)(`div`,{className:`app-pane-bar flex shrink-0 flex-wrap items-center justify-between gap-x-3 gap-y-2 border-b`,children:[(0,w.jsx)(`div`,{className:`min-w-0 truncate text-[10px] font-medium uppercase tracking-wide text-muted-foreground`,children:we}),(0,w.jsxs)(`div`,{className:`ml-auto flex min-w-0 max-w-full flex-wrap items-center justify-end gap-2`,children:[U.kind===`idle`?null:(0,w.jsx)(r,{variant:`ghost`,size:`sm`,onClick:ve,children:`取消`}),(0,w.jsx)(`div`,{ref:ge,"data-testid":`editor-pane-actions`,className:`contents`})]})]}),(0,w.jsx)(v,{host:he,registerDismiss:_e,children:(0,w.jsx)(`div`,{className:Te?`min-h-0 flex-1 overflow-hidden`:`min-h-0 flex-1 overflow-y-auto`,children:U.kind===`idle`?(0,w.jsxs)(`div`,{className:`flex h-full min-h-[240px] flex-col items-center justify-center gap-2 p-6 text-center text-sm text-muted-foreground`,children:[(0,w.jsx)(`p`,{children:`选择左侧插件进行编辑,或点击「AI 生成」`}),(0,w.jsx)(`p`,{className:`text-xs`,children:`自定义插件在右侧编辑代码;内置和第三方插件在右侧查看并操作`})]}):U.kind===`generate`?(0,w.jsx)(S.Suspense,{fallback:(0,w.jsx)(D,{}),children:(0,w.jsx)(le,{embedded:!0,plainHeading:!0,onOpenChange:e=>{e||W({kind:`idle`})},onPluginSaved:()=>{i(),K()}})}):U.kind===`code`?(0,w.jsx)(S.Suspense,{fallback:(0,w.jsx)(D,{}),children:(0,w.jsx)(T,{embedded:!0,plainHeading:!0,filename:U.filename,onOpenChange:e=>{e||W({kind:`idle`})},onSaved:()=>{i()}},U.filename)}):U.kind===`test`?(0,w.jsx)(S.Suspense,{fallback:(0,w.jsx)(D,{}),children:(0,w.jsx)(E,{embedded:!0,plainHeading:!0,pluginId:U.pluginId,pluginName:U.pluginName,hooks:U.hooks,filename:U.filename,onOpenChange:e=>{e||W({kind:`idle`})},onPluginFixed:()=>{i()}},U.pluginId)}):U.kind===`builtin`&&Z?(0,w.jsx)(de,{plugin:Z,...Q?{note:ue,onUnload:()=>void q(Q.pluginId,Q.filename)}:{},loading:P,onStart:()=>void xe(Z.id),onStop:()=>void Se(Z.id)}):U.kind===`third-party`&&$?(0,w.jsx)(fe,{plugin:$,loading:R,onUnload:()=>void J($.id)}):U.kind===`load-third-party`?(0,w.jsxs)(`div`,{className:`flex flex-col gap-[var(--ui-section-gap)] p-[var(--ui-section-gap)]`,children:[(0,w.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`输入插件文件或目录路径后加载。`}),(0,w.jsxs)(`div`,{className:`flex gap-2`,children:[(0,w.jsx)(oe,{value:I,onChange:e=>L(e.target.value),placeholder:`输入插件路径...`,className:`flex-1`,"aria-label":`第三方插件路径`}),(0,w.jsx)(r,{onClick:()=>void Ce(),disabled:R||!I.trim(),children:R?(0,w.jsx)(d,{className:`animate-spin`}):`加载`})]})]}):null})})]})}function k({title:e,extra:t,action:n,children:r}){return(0,w.jsxs)(`section`,{children:[(0,w.jsxs)(`div`,{className:`flex items-center justify-between gap-2 border-b px-[var(--ui-section-gap)] py-1.5 text-[10px] font-medium uppercase tracking-wide text-muted-foreground`,children:[(0,w.jsx)(`span`,{className:`truncate`,children:e}),(0,w.jsxs)(`span`,{className:`flex shrink-0 items-center gap-2`,children:[t,n]})]}),r]})}function A({children:e}){return(0,w.jsx)(`div`,{className:`px-[var(--ui-section-gap)] py-6 text-center text-sm text-muted-foreground`,children:e})}function j(e){let{key:t}=e;if(t!==`ArrowDown`&&t!==`ArrowUp`&&t!==`Home`&&t!==`End`)return;let n=e.currentTarget.closest(`[data-plugin-row-list]`);if(!n)return;let r=Array.from(n.querySelectorAll(`[data-plugin-row-trigger]`)),i=r.indexOf(e.currentTarget);if(i===-1||r.length===0)return;let a=t===`Home`?0:t===`End`?r.length-1:t===`ArrowDown`?Math.min(i+1,r.length-1):Math.max(i-1,0);e.preventDefault(),r[a]?.focus()}var M=`has-[[data-plugin-row-trigger]:focus-visible]:ring-[3px] has-[[data-plugin-row-trigger]:focus-visible]:ring-inset has-[[data-plugin-row-trigger]:focus-visible]:ring-ring/50`;function N({testId:e,selected:t,title:n,meta:r,muted:i,badge:a,action:o,onSelect:s}){return(0,w.jsxs)(`div`,{"data-testid":e,"data-state":t?`selected`:void 0,className:`flex w-full cursor-pointer items-center gap-2 border-b border-border/40 px-[var(--ui-section-gap)] py-2 text-left transition-colors outline-none hover:bg-muted/50 data-[state=selected]:bg-accent ${M} ${i?`opacity-60`:``}`,onClick:s,children:[(0,w.jsxs)(`button`,{type:`button`,"data-plugin-row-trigger":``,"data-testid":`${e}-trigger`,"aria-current":t?`true`:void 0,className:`min-w-0 flex-1 cursor-pointer text-left outline-none`,onKeyDown:j,children:[(0,w.jsx)(`span`,{className:`block truncate text-sm font-medium`,children:n}),r?(0,w.jsx)(`span`,{className:`block truncate text-xs text-muted-foreground`,children:r}):null]}),(0,w.jsxs)(`div`,{className:`flex shrink-0 items-center gap-1`,onClick:e=>e.stopPropagation(),onKeyDown:e=>e.stopPropagation(),children:[a,o]})]})}var ue=`插件文件已删除,无法编辑或测试。可以卸载它,或者恢复文件后重新加载`;function de({plugin:e,note:t,loading:n,onStart:i,onStop:a,onUnload:o}){return(0,w.jsxs)(`div`,{className:`flex flex-col gap-[var(--ui-section-gap)] p-[var(--ui-section-gap)]`,children:[(0,w.jsxs)(`div`,{children:[(0,w.jsx)(`div`,{className:`text-sm font-medium`,children:e.name}),(0,w.jsxs)(`div`,{className:`text-xs text-muted-foreground`,children:[e.id,` · `,e.version]})]}),t?(0,w.jsx)(`p`,{"data-testid":`plugin-detail-note`,className:`text-xs text-muted-foreground`,children:t}):null,(0,w.jsx)(`div`,{className:`flex flex-wrap gap-1`,children:e.hooks.length===0?(0,w.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:`无 hooks`}):e.hooks.map(e=>(0,w.jsx)(h,{variant:`secondary`,className:`text-xs`,children:e},e))}),(0,w.jsx)(`div`,{children:o?(0,w.jsxs)(r,{variant:`outline`,size:`sm`,onClick:o,disabled:n,"aria-label":`卸载插件 ${e.name}`,children:[(0,w.jsx)(x,{"data-icon":`inline-start`}),`卸载`]}):e.state===`running`?(0,w.jsxs)(r,{variant:`outline`,size:`sm`,onClick:a,disabled:n,"aria-label":`停止插件 ${e.name}`,children:[(0,w.jsx)(g,{"data-icon":`inline-start`}),`停止`]}):(0,w.jsxs)(r,{variant:`outline`,size:`sm`,onClick:i,disabled:n,"aria-label":`启动插件 ${e.name}`,children:[(0,w.jsx)(u,{"data-icon":`inline-start`}),`启动`]})})]})}function fe({plugin:e,loading:t,onUnload:n}){return(0,w.jsxs)(`div`,{className:`flex flex-col gap-[var(--ui-section-gap)] p-[var(--ui-section-gap)]`,children:[(0,w.jsxs)(`div`,{children:[(0,w.jsx)(`div`,{className:`text-sm font-medium`,children:e.name}),(0,w.jsxs)(`div`,{className:`text-xs text-muted-foreground`,children:[e.id,` · `,e.version,` · `,e.state]})]}),(0,w.jsx)(`div`,{children:(0,w.jsxs)(r,{variant:`outline`,size:`sm`,onClick:n,disabled:t,className:`text-destructive`,"aria-label":`卸载插件 ${e.name}`,children:[(0,w.jsx)(_,{"data-icon":`inline-start`}),`卸载`]})})]})}export{O as PluginConfig};
@@ -1,2 +0,0 @@
1
- import{c as e,d as t,p as n,t as r}from"./button-BFNlGZ5p.js";import"./dist-CFZ4xMSF.js";import{t as i}from"./check-BkfHQ6re.js";import{t as a}from"./circle-x-BEkinhez.js";import{t as o}from"./code-DD-AYxxu.js";import{t as s}from"./copy-BRnscYy1.js";import{t as ee}from"./wand-sparkles-DDGjzjnX.js";import"./es2015-CRmLuA2o.js";import{o as te,r as ne}from"./ai-config-store-B_VpGvwx.js";import{C as re,Nt as ie,O as c,S as l,Tt as u,_ as d,b as ae,et as f,ht as p,tt as m,v as oe,vt as se,w as ce,y as le}from"./index-Bu3zaxzE.js";import{i as ue,t as de}from"./editor-pane-actions-DN-pxFsl.js";import{t as fe}from"./panel-heading-BAI_lNmT.js";import{t as pe}from"./textarea-BjWF0pk4.js";var h=n(t(),1),g=e();function _({open:e=!1,onOpenChange:t,embedded:n=!1,plainHeading:_=!1,onPluginSaved:v}){let[y,b]=(0,h.useState)(``),[x,S]=(0,h.useState)(``),[C,me]=(0,h.useState)(``),[w,T]=(0,h.useState)(``),[E,D]=(0,h.useState)(!1),[O,k]=(0,h.useState)(!1),[A,j]=(0,h.useState)(``),[M,N]=(0,h.useState)(``),[P,F]=(0,h.useState)(null),[I,L]=(0,h.useState)(null),[R,z]=(0,h.useState)(``),[he,B]=(0,h.useState)(!1),[V,H]=(0,h.useState)(0),[U,W]=(0,h.useState)(0),[G,K]=(0,h.useState)(!1),[q,J]=(0,h.useState)(!1),Y=ne(),X=te(Y),ge=async()=>{if(!y.trim()||!x.trim()){L(`error`),z(`请填写插件名称和描述`);return}if(!X){L(`error`),z(`AI 配置未完成,请先配置 AI 服务`);return}D(!0),L(null),z(`正在连接 AI 服务...`),j(``),H(0),W(0);let e=Date.now(),t=0;try{let n={name:y,description:x,hooks:C.split(`,`).map(e=>e.trim()).filter(Boolean),permissions:w.split(`,`).map(e=>e.trim()).filter(Boolean)},r=await fetch(`/api/plugins/generate-stream`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({requirement:n,aiConfig:{provider:Y.provider,apiKey:Y.apiKey,baseUrl:Y.baseUrl,model:Y.model}})});if(!r.ok)throw Error(`请求失败: ${r.status}`);let i=r.body?.getReader(),a=new TextDecoder;if(!i)throw Error(`无法读取响应流`);let o=``;for(;;){let{done:n,value:r}=await i.read();if(n)break;o+=a.decode(r,{stream:!0});let s=o.split(`
2
- `);o=s.pop()||``;for(let n of s)if(!n.startsWith(`event:`)&&n.startsWith(`data:`)){let r=n.slice(5).trim();try{let n=JSON.parse(r);if(n.status===`generating`)z(`AI 正在生成代码...`),W(10);else if(n.chunk){t++;let r=n.accumulated||n.chunk;j(r),H(r.length),W(Math.min(90,10+t*2));let i=((Date.now()-e)/1e3).toFixed(1);z(`生成中... (${r.length} 字符, ${i}s)`)}else if(n.status===`success`){j(n.plugin.code),N(n.plugin.filename),F(n.plugin.manifest),H(n.plugin.code.length),W(100),L(`success`);let t=((Date.now()-e)/1e3).toFixed(1);z(`插件代码生成成功!(${n.plugin.code.length} 字符, ${t}s)`)}else if(n.error)throw Error(n.error)}catch(e){if(e instanceof Error&&e.message!==`Unexpected end of JSON input`)throw e}}}}catch(e){L(`error`),z(e instanceof Error?e.message:`生成失败`),W(0)}finally{D(!1)}},Z=async()=>{if(!A||!M){L(`error`),z(`没有可保存的插件代码`);return}k(!0),L(null),z(`正在保存插件...`);try{let e=await fetch(`/api/plugins/save`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({filename:M,code:A})});if(!e.ok){let t=await e.json();throw Error(t.error||`保存失败`)}await e.json(),L(`success`),z(`插件已保存!现在可以热加载并测试。`),K(!0),window.dispatchEvent(new CustomEvent(`plugins-custom-updated`)),d.success(`插件保存成功`),v&&v(),window.dispatchEvent(new CustomEvent(`plugins-custom-updated`))}catch(e){let t=e instanceof Error?e.message:`保存失败`;L(`error`),z(t),d.error(t)}finally{k(!1)}};oe({active:(e||n)&&!!A&&!G,enabled:!O&&!E&&!!M,priority:le.panel,onSave:Z});let _e=async()=>{A&&(await navigator.clipboard.writeText(A),B(!0),setTimeout(()=>B(!1),2e3))},ve=async()=>{J(!0);try{let e=await fetch(`/api/plugins/reload`,{method:`POST`});if(!e.ok){let t=await e.json();throw Error(t.error||`热加载失败`)}let n=await e.json();L(`success`),z(`成功热加载 ${n.count} 个插件!插件已激活,可以使用了。`),v&&v(),setTimeout(()=>{t?.(!1),Q()},3e3)}catch(e){L(`error`),z(e instanceof Error?e.message:`热加载失败`)}finally{J(!1)}},Q=()=>{b(``),S(``),me(``),T(``),j(``),N(``),F(null),L(null),z(``),B(!1),H(0),W(0),K(!1),J(!1)},$=ue(),ye=(0,g.jsxs)(g.Fragment,{children:[_?null:(0,g.jsxs)(g.Fragment,{children:[(0,g.jsx)(fe,{className:`px-6 pt-6 pb-4`,title:(0,g.jsxs)(g.Fragment,{children:[(0,g.jsx)(p,{className:`h-5 w-5`}),`AI 插件生成器`]}),description:`使用 AI 根据插件系统设计和您的需求自动生成自定义插件代码`}),(0,g.jsx)(l,{})]}),(0,g.jsxs)(`div`,{className:`app-panel-content`,children:[!X&&(0,g.jsx)(`div`,{className:`bg-yellow-50 dark:bg-yellow-950/20 border border-yellow-200 dark:border-yellow-900 rounded-md p-3`,children:(0,g.jsx)(`p`,{className:`text-sm text-yellow-700 dark:text-yellow-300`,children:`AI 功能未配置或未启用,请先在设置中配置 AI 服务`})}),(0,g.jsxs)(`div`,{className:`app-section`,children:[(0,g.jsxs)(`div`,{className:`app-field-group`,children:[(0,g.jsxs)(c,{htmlFor:`pluginName`,children:[`插件名称 `,(0,g.jsx)(`span`,{className:`text-red-500`,children:`*`})]}),(0,g.jsx)(m,{id:`pluginName`,value:y,onChange:e=>b(e.target.value),placeholder:`例如:请求日志分析器`,disabled:E||O})]}),(0,g.jsxs)(`div`,{className:`app-field-group`,children:[(0,g.jsxs)(c,{htmlFor:`pluginDescription`,children:[`插件描述 `,(0,g.jsx)(`span`,{className:`text-red-500`,children:`*`})]}),(0,g.jsx)(pe,{id:`pluginDescription`,value:x,onChange:e=>S(e.target.value),placeholder:`详细描述插件的功能,例如:分析HTTP请求日志,统计各个API的调用次数、响应时间等信息,并在控制台输出统计报告`,rows:4,disabled:E||O})]}),(0,g.jsxs)(`div`,{className:`app-field-group`,children:[(0,g.jsx)(c,{htmlFor:`hooks`,children:`需要的 Hooks(可选,用逗号分隔)`}),(0,g.jsx)(m,{id:`hooks`,value:C,onChange:e=>me(e.target.value),placeholder:`例如:onRequestStart, onAfterResponse`,disabled:E||O}),(0,g.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`可选:onRequestStart, onBeforeProxy, onBeforeResponse, onAfterResponse, onError`})]}),(0,g.jsxs)(`div`,{className:`app-field-group`,children:[(0,g.jsx)(c,{htmlFor:`permissions`,children:`需要的权限(可选,用逗号分隔)`}),(0,g.jsx)(m,{id:`permissions`,value:w,onChange:e=>T(e.target.value),placeholder:`例如:proxy:read, storage:write`,disabled:E||O}),(0,g.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`可选:proxy:read, proxy:write, response:shortcircuit, storage:read, storage:write`})]})]}),E&&U>0&&(0,g.jsxs)(`div`,{className:`app-field-group`,children:[(0,g.jsxs)(`div`,{className:`flex items-center justify-between text-sm`,children:[(0,g.jsx)(`span`,{className:`text-muted-foreground`,children:`生成进度`}),(0,g.jsxs)(`span`,{className:`font-medium`,children:[U,`%`]})]}),(0,g.jsx)(`div`,{className:`w-full bg-muted rounded-full h-2 overflow-hidden`,children:(0,g.jsx)(`div`,{className:`bg-primary h-full transition-all duration-300 ease-out`,style:{width:`${U}%`}})})]}),(A||E)&&(0,g.jsxs)(`div`,{className:`app-field-group`,children:[(0,g.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,g.jsxs)(c,{className:`flex items-center gap-2`,children:[(0,g.jsx)(o,{className:`h-4 w-4`}),E?`正在生成插件代码`:`生成的插件代码`]}),(0,g.jsxs)(`div`,{className:`flex items-center gap-2`,children:[V>0&&(0,g.jsxs)(`span`,{className:`text-xs text-muted-foreground`,children:[V,` 字符`]}),!E&&A&&(0,g.jsx)(r,{variant:`ghost`,size:`sm`,onClick:_e,className:`h-8`,children:he?(0,g.jsxs)(g.Fragment,{children:[(0,g.jsx)(i,{className:`h-4 w-4 mr-1`}),`已复制`]}):(0,g.jsxs)(g.Fragment,{children:[(0,g.jsx)(s,{className:`h-4 w-4 mr-1`}),`复制`]})})]})]}),(0,g.jsxs)(`div`,{className:`bg-muted rounded-md p-4 max-h-[400px] overflow-auto relative`,children:[E&&(0,g.jsx)(`div`,{className:`absolute top-2 right-2`,children:(0,g.jsx)(u,{className:`h-4 w-4 animate-spin text-muted-foreground`})}),(0,g.jsx)(`pre`,{className:`text-xs font-mono whitespace-pre-wrap break-all`,children:A||`等待 AI 响应...`})]}),P&&(0,g.jsxs)(`div`,{className:`bg-blue-50 dark:bg-blue-950/20 border border-blue-200 dark:border-blue-900 rounded-md p-3 space-y-2`,children:[(0,g.jsx)(`p`,{className:`text-sm font-medium text-blue-900 dark:text-blue-100`,children:`插件信息`}),(0,g.jsxs)(`div`,{className:`text-xs space-y-1 text-blue-700 dark:text-blue-300`,children:[(0,g.jsxs)(`div`,{children:[(0,g.jsx)(`strong`,{children:`ID:`}),` `,P.id]}),(0,g.jsxs)(`div`,{children:[(0,g.jsx)(`strong`,{children:`名称:`}),` `,P.name]}),(0,g.jsxs)(`div`,{children:[(0,g.jsx)(`strong`,{children:`版本:`}),` `,P.version]}),(0,g.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,g.jsx)(`strong`,{children:`Hooks:`}),(0,g.jsx)(`div`,{className:`flex flex-wrap gap-1`,children:P.hooks.map(e=>(0,g.jsx)(f,{variant:`secondary`,className:`text-xs`,children:e},e))})]}),(0,g.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,g.jsx)(`strong`,{children:`权限:`}),(0,g.jsx)(`div`,{className:`flex flex-wrap gap-1`,children:P.permissions.map(e=>(0,g.jsx)(f,{variant:`outline`,className:`text-xs`,children:e},e))})]})]})]})]}),R&&(0,g.jsxs)(`div`,{className:`flex items-start gap-2 p-3 rounded-md border ${I===`success`?`bg-green-50 dark:bg-green-950/20 border-green-200 dark:border-green-900`:I===`error`?`bg-red-50 dark:bg-red-950/20 border-red-200 dark:border-red-900`:`bg-blue-50 dark:bg-blue-950/20 border-blue-200 dark:border-blue-900`}`,children:[I===`success`&&(0,g.jsx)(ie,{className:`h-4 w-4 text-green-600 dark:text-green-400 mt-0.5`}),I===`error`&&(0,g.jsx)(a,{className:`h-4 w-4 text-red-600 dark:text-red-400 mt-0.5`}),E&&(0,g.jsx)(u,{className:`h-4 w-4 text-blue-600 dark:text-blue-400 mt-0.5 animate-spin`}),(0,g.jsx)(`span`,{className:`text-xs flex-1 ${I===`success`?`text-green-700 dark:text-green-300`:I===`error`?`text-red-700 dark:text-red-300`:`text-blue-700 dark:text-blue-300`}`,children:R})]})]}),$?null:(0,g.jsx)(l,{}),(0,g.jsxs)(de,{className:`px-6 py-4 flex justify-between gap-2`,children:[$?null:(0,g.jsx)(r,{variant:`outline`,size:`sm`,onClick:()=>{t?.(!1),Q()},disabled:E||O||q,children:G?`完成`:`取消`}),(0,g.jsx)(`div`,{className:$?`contents`:`flex gap-2`,children:A?G?(0,g.jsx)(r,{size:`sm`,onClick:ve,disabled:q,className:`bg-green-600 hover:bg-green-700`,children:q?(0,g.jsxs)(g.Fragment,{children:[(0,g.jsx)(u,{className:`h-4 w-4 mr-1 animate-spin`}),`加载中...`]}):(0,g.jsxs)(g.Fragment,{children:[(0,g.jsx)(p,{className:`h-4 w-4 mr-1`}),`热加载并测试`]})}):(0,g.jsxs)(g.Fragment,{children:[(0,g.jsx)(r,{variant:`outline`,size:`sm`,onClick:()=>{j(``),N(``),F(null),L(null),z(``)},disabled:E||O,children:`重新生成`}),(0,g.jsx)(ae,{size:`sm`,onClick:Z,disabled:O,children:O?(0,g.jsxs)(g.Fragment,{children:[(0,g.jsx)(u,{"data-icon":`inline-start`,className:`animate-spin`}),`保存中...`]}):(0,g.jsxs)(g.Fragment,{children:[(0,g.jsx)(se,{"data-icon":`inline-start`}),`保存插件`]})})]}):(0,g.jsx)(r,{size:`sm`,onClick:ge,disabled:!X||E||O||!y.trim()||!x.trim(),children:E?(0,g.jsxs)(g.Fragment,{children:[(0,g.jsx)(u,{className:`h-4 w-4 mr-1 animate-spin`}),`生成中...`]}):(0,g.jsxs)(g.Fragment,{children:[(0,g.jsx)(ee,{className:`h-4 w-4 mr-1`}),`生成插件`]})})})]})]});return n?(0,g.jsx)(`div`,{className:`flex h-full min-h-0 flex-col`,children:ye}):(0,g.jsx)(re,{open:e,onOpenChange:e=>{t?.(e),e||Q()},children:(0,g.jsx)(ce,{className:`p-0 flex flex-col`,resizable:!0,defaultWidth:900,storageKey:`plugin-generator`,children:ye})})}export{_ as PluginGenerator};
@@ -1,7 +0,0 @@
1
- import{c as e,d as t,p as n,t as r,u as i}from"./button-BFNlGZ5p.js";import"./dist-CFZ4xMSF.js";import{t as a}from"./arrow-right-BNum_060.js";import{t as o}from"./circle-alert-zMagrFuI.js";import{t as s}from"./circle-x-BEkinhez.js";import{t as ee}from"./pencil-line-CEZ7D-de.js";import{t as c}from"./refresh-cw-BfLoHqg5.js";import{t as te}from"./wand-sparkles-DDGjzjnX.js";import"./es2015-CRmLuA2o.js";import{i as ne,o as re,r as ie}from"./ai-config-store-B_VpGvwx.js";import{At as ae,C as oe,F as l,M as u,Mt as d,Nt as se,O as f,Ot as ce,P as p,S as m,Tt as h,et as g,ft as le,t as ue,tt as de,w as fe}from"./index-Bu3zaxzE.js";import{t as pe}from"./body-diff-view-ByCHr9bv.js";import{n as me,t as he}from"./monaco-editor-DeJNlo9k.js";import{i as ge,t as _e}from"./editor-pane-actions-DN-pxFsl.js";import{t as ve}from"./panel-heading-BAI_lNmT.js";import{t as ye}from"./textarea-BjWF0pk4.js";var be=i(`circle-play`,[[`path`,{d:`M9 9.003a1 1 0 0 1 1.517-.859l4.997 2.997a1 1 0 0 1 0 1.718l-4.997 2.997A1 1 0 0 1 9 14.996z`,key:`kmsa83`}],[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}]]),_=n(t(),1),v=e();function y(e){let t=new Map;return!e||typeof e!=`object`||Object.entries(e).forEach(([e,n])=>{t.set(e.toLowerCase(),{displayKey:e,value:n==null?``:String(n)})}),t}function b(e,t){let n=y(e),r=y(t);return Array.from(new Set([...n.keys(),...r.keys()])).sort().map(e=>{let t=n.get(e),i=r.get(e),a=t?.value??``,o=i?.value??``,s=`unchanged`;return!t&&i?s=`added`:t&&!i?s=`removed`:a!==o&&(s=`changed`),{key:e,displayKey:i?.displayKey??t?.displayKey??e,originalValue:a,modifiedValue:o,status:s}})}function x(e,t){let n=`rounded-md border px-2 py-1.5`;return e===`unchanged`?`${n} border-transparent`:e===`changed`?`${n} border-orange-300 bg-orange-500/10`:e===`added`?t===`modified`?`${n} border-green-300 bg-green-500/10`:`${n} border-transparent opacity-50`:e===`removed`?t===`original`?`${n} border-red-300 bg-red-500/10`:`${n} border-transparent opacity-50`:n}function xe({original:e,modified:t,mode:n=`split`}){let r=b(e,t);return n===`inline`?(0,v.jsx)(`div`,{className:`bg-muted/50 rounded-md p-2 text-xs font-mono max-h-[220px] overflow-auto space-y-1`,children:r.map(e=>(0,v.jsxs)(`div`,{className:`rounded-md border px-2 py-1.5 ${e.status===`unchanged`?`border-transparent`:e.status===`changed`?`border-orange-300 bg-orange-500/10`:e.status===`added`?`border-green-300 bg-green-500/10`:`border-red-300 bg-red-500/10`}`,children:[(0,v.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[(0,v.jsx)(`span`,{className:`text-muted-foreground`,children:e.displayKey}),(0,v.jsx)(g,{variant:`outline`,className:`h-5 px-1.5 text-[10px] font-normal`,children:e.status===`unchanged`?`未变`:e.status===`changed`?`修改`:e.status===`added`?`新增`:`删除`})]}),e.status===`changed`&&(0,v.jsxs)(`div`,{className:`mt-1 space-y-1`,children:[(0,v.jsxs)(`div`,{className:`text-red-700 dark:text-red-300`,children:[(0,v.jsx)(`span`,{className:`mr-1`,children:`-`}),e.originalValue||(0,v.jsx)(`span`,{className:`text-muted-foreground italic`,children:`(无)`})]}),(0,v.jsxs)(`div`,{className:`text-green-700 dark:text-green-300`,children:[(0,v.jsx)(`span`,{className:`mr-1`,children:`+`}),e.modifiedValue||(0,v.jsx)(`span`,{className:`text-muted-foreground italic`,children:`(无)`})]})]}),e.status===`added`&&(0,v.jsxs)(`div`,{className:`mt-1 text-green-700 dark:text-green-300`,children:[(0,v.jsx)(`span`,{className:`mr-1`,children:`+`}),e.modifiedValue||(0,v.jsx)(`span`,{className:`text-muted-foreground italic`,children:`(无)`})]}),e.status===`removed`&&(0,v.jsxs)(`div`,{className:`mt-1 text-red-700 dark:text-red-300`,children:[(0,v.jsx)(`span`,{className:`mr-1`,children:`-`}),e.originalValue||(0,v.jsx)(`span`,{className:`text-muted-foreground italic`,children:`(无)`})]}),e.status===`unchanged`&&(0,v.jsx)(`div`,{className:`mt-1`,children:e.modifiedValue||e.originalValue||(0,v.jsx)(`span`,{className:`text-muted-foreground italic`,children:`(无)`})})]},e.key))}):(0,v.jsxs)(`div`,{className:`grid grid-cols-2 gap-2`,children:[(0,v.jsxs)(`div`,{children:[(0,v.jsx)(`div`,{className:`text-[10px] text-muted-foreground mb-0.5`,children:`原始`}),(0,v.jsx)(`div`,{className:`bg-muted/50 rounded-md p-2 text-xs font-mono max-h-[220px] overflow-auto space-y-1`,children:r.map(e=>(0,v.jsxs)(`div`,{className:x(e.status,`original`),children:[(0,v.jsxs)(`span`,{className:`text-muted-foreground`,children:[e.displayKey,`:`]}),` `,e.originalValue||(0,v.jsx)(`span`,{className:`text-muted-foreground italic`,children:`(无)`})]},`original-${e.key}`))})]}),(0,v.jsxs)(`div`,{children:[(0,v.jsx)(`div`,{className:`text-[10px] text-muted-foreground mb-0.5`,children:`修改后`}),(0,v.jsx)(`div`,{className:`bg-muted/50 rounded-md p-2 text-xs font-mono max-h-[220px] overflow-auto space-y-1`,children:r.map(e=>(0,v.jsxs)(`div`,{className:x(e.status,`modified`),children:[(0,v.jsxs)(`span`,{className:`text-muted-foreground`,children:[e.displayKey,`:`]}),` `,e.modifiedValue||(0,v.jsx)(`span`,{className:`text-muted-foreground italic`,children:`(无)`})]},`modified-${e.key}`))})]})]})}function Se(e){switch(e){case`generating`:return`AI 正在流式生成修复代码`;case`saving`:return`正在保存修复后的插件代码`;case`reloading`:return`正在热加载插件`;case`retesting`:return`正在重新执行插件测试`;default:return``}}function Ce({open:e=!1,onOpenChange:t,embedded:n=!1,plainHeading:i=!1,pluginId:y,pluginName:b,hooks:x,filename:Ce,onPluginFixed:we}){let[S,Te]=(0,_.useState)(!1),[C,w]=(0,_.useState)(!1),[T,Ee]=(0,_.useState)(`https://365.wps.cn/home`),[E,De]=(0,_.useState)(`GET`),[D,O]=(0,_.useState)(`standalone`),[k,A]=(0,_.useState)(null),[j,Oe]=(0,_.useState)(`split`),[M,ke]=(0,_.useState)(`inline`),[N,P]=(0,_.useState)(null),[F,I]=(0,_.useState)(``),[L,R]=(0,_.useState)(``),[z,Ae]=(0,_.useState)(!1),[B,V]=(0,_.useState)(null),[H,U]=(0,_.useState)(``),[je,W]=(0,_.useState)(`normal`),[G,Me]=(0,_.useState)(``),[K,q]=(0,_.useState)(`idle`),J=ie(),Y=ne(J),Ne=Y?{provider:Y.provider,apiKey:Y.apiKey,baseUrl:Y.baseUrl,model:Y.model}:{provider:J.provider,apiKey:J.apiKey,baseUrl:J.baseUrl,model:J.model},X=re(J),Z=Ce||ue({id:y}),Pe=n||e,Q=(0,_.useCallback)(async()=>{if(!Z||!Pe){I(``),R(``),V(null);return}Ae(!0),V(null);try{let e=await fetch(`/api/plugins/custom/${encodeURIComponent(Z)}/code`);if(!e.ok){let t=await e.json();throw Error(t.error||`读取插件源码失败`)}let t=await e.json();I(t.code||``),!C&&!H&&R(t.code||``)}catch(e){I(``),R(``),V(e instanceof Error?e.message:`读取插件源码失败`)}finally{Ae(!1)}},[Z,C,H,Pe]);(0,_.useEffect)(()=>{Q()},[Q]);let $=(0,_.useMemo)(()=>{let e=[];return k?.error&&e.push({hookName:`test`,message:k.error}),Object.entries(k?.hookResults||{}).forEach(([t,n])=>{n?.status===`error`&&e.push({hookName:t,message:n.error||`未知错误`,stack:n.stack})}),k?.realRequest?.fetchError&&e.push({hookName:`fetch`,message:k.realRequest.fetchError}),e},[k]),Fe=$.length>0&&!!Z,Ie=!!L&&!!(H||K===`idle`&&L&&F&&L!==F),Le=async(e,t,n)=>{q(`saving`);let r=await fetch(`/api/plugins/custom/${encodeURIComponent(Z)}/code`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({code:e})});if(!r.ok){let e=await r.json();throw Error(e.error||`保存修复后的代码失败`)}q(`reloading`);let i=await fetch(`/api/plugins/reload`,{method:`POST`});if(!i.ok){let e=await i.json().catch(()=>({error:`热加载失败`}));throw Error(e.error||`热加载失败`)}I(e),U(e),W(`diff`),window.dispatchEvent(new CustomEvent(`plugins-custom-updated`)),we?.(),n&&(q(`retesting`),await Re()),P({status:`success`,message:t}),q(`idle`)},Re=async()=>{Te(!0),A(null),P(null);try{let e=await fetch(`/api/plugins/test`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({pluginId:y,url:T,method:E,integrated:D===`integrated`})});if(!e.ok){let t=await e.json();throw Error(t.error||`测试失败`)}A((await e.json()).results)}catch(e){A({error:e instanceof Error?e.message:`测试失败`})}finally{Te(!1)}},ze=async()=>{if(!(!Fe||!X)){w(!0),P(null),U(``),R(F);try{q(`generating`);let e={code:F};if(!e.code)throw Error(`插件源码为空,无法修复`);let t=$.map(e=>`Hook: ${e.hookName}\nError: ${e.message}${e.stack?`\nStack:\n${e.stack}`:``}`).join(`
2
-
3
- ---
4
-
5
- `),n=await fetch(`/api/plugins/fix-stream`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({originalCode:e.code,testError:t,requirement:{name:b,description:`修复插件 ${b} 在测试中的报错,并保持现有 hooks 行为正确。Hooks: ${x.join(`, `)}`,hooks:x},aiConfig:Ne})});if(!n.ok){let e=await n.json();throw Error(e.error||`AI 修复失败`)}let r=n.body?.getReader(),i=new TextDecoder;if(!r)throw Error(`无法读取 AI 修复流`);let a=``,o=``;for(;;){let{done:e,value:t}=await r.read();if(e)break;o+=i.decode(t,{stream:!0});let n=o.split(`
6
- `);o=n.pop()||``;for(let e of n){if(!e.startsWith(`data:`))continue;let t=e.slice(5).trim();if(t)try{let e=JSON.parse(t);if(e.status===`generating`)P({status:`success`,message:`AI 正在分析错误并生成修复代码...`});else if(e.chunk)a=e.accumulated||`${a}${e.chunk}`,U(a);else if(e.status===`success`)a=e.fixedCode||a,U(a);else if(e.error)throw Error(e.error)}catch(e){if(e instanceof Error&&e.message!==`Unexpected end of JSON input`)throw e}}}if(!a||typeof a!=`string`)throw Error(`AI 未返回有效代码`);P({status:`success`,message:`AI 已生成修复代码,正在保存、热加载并重新测试...`}),await Le(a,`AI 已修复插件代码并完成热加载,测试结果已刷新。`,!0)}catch(e){P({status:`error`,message:e instanceof Error?e.message:`AI 修复失败`})}finally{q(`idle`),w(!1)}}},Be=async()=>{if(!(!Z||!G.trim()||!X||C)){w(!0),P(null),U(``),R(F);try{q(`generating`);let e=await fetch(`/api/plugins/revise-stream`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({originalCode:F,instruction:G.trim(),requirement:{name:b,description:`根据额外要求更新插件 ${b},并保持 hooks 行为正确。Hooks: ${x.join(`, `)}`,hooks:x},aiConfig:Ne})});if(!e.ok){let t=await e.json();throw Error(t.error||`AI 更新代码失败`)}let t=e.body?.getReader(),n=new TextDecoder;if(!t)throw Error(`无法读取 AI 更新流`);let r=``,i=``;for(;;){let{done:e,value:a}=await t.read();if(e)break;i+=n.decode(a,{stream:!0});let o=i.split(`
7
- `);i=o.pop()||``;for(let e of o){if(!e.startsWith(`data:`))continue;let t=e.slice(5).trim();if(t)try{let e=JSON.parse(t);if(e.status===`generating`)P({status:`success`,message:`AI 正在根据额外要求更新插件代码...`});else if(e.chunk)r=e.accumulated||`${r}${e.chunk}`,U(r),W(`diff`);else if(e.status===`success`)r=e.revisedCode||r,U(r),W(`diff`);else if(e.error)throw Error(e.error)}catch(e){if(e instanceof Error&&e.message!==`Unexpected end of JSON input`)throw e}}}if(!r||typeof r!=`string`)throw Error(`AI 未返回有效代码`);P({status:`success`,message:`AI 已生成更新后的代码,正在保存并热加载...`}),await Le(r,`AI 已根据额外要求更新插件代码并完成热加载。`,!1),Me(``)}catch(e){P({status:`error`,message:e instanceof Error?e.message:`AI 更新代码失败`})}finally{q(`idle`),w(!1)}}},Ve=ge(),He=(0,v.jsxs)(v.Fragment,{children:[i?null:(0,v.jsxs)(v.Fragment,{children:[(0,v.jsx)(ve,{className:`px-6 pt-6 pb-4`,title:(0,v.jsxs)(v.Fragment,{children:[(0,v.jsx)(le,{className:`h-5 w-5`}),`测试插件: `,b]}),description:`发起真实 HTTP 请求,在请求/响应过程中运行插件代码`}),(0,v.jsx)(m,{})]}),(0,v.jsxs)(`div`,{className:`app-panel-content`,children:[(0,v.jsxs)(`div`,{className:`app-section`,children:[(0,v.jsxs)(`div`,{className:`app-field-group`,children:[(0,v.jsx)(f,{htmlFor:`testUrl`,children:`请求 URL`}),(0,v.jsx)(de,{id:`testUrl`,value:T,onChange:e=>Ee(e.target.value),placeholder:`https://example.com/page`,disabled:S})]}),(0,v.jsxs)(`div`,{className:`app-field-group`,children:[(0,v.jsx)(f,{children:`HTTP 方法`}),(0,v.jsx)(`div`,{className:`flex gap-2`,children:[`GET`,`POST`,`PUT`,`DELETE`].map(e=>(0,v.jsx)(r,{type:`button`,variant:E===e?`selected`:`outline`,size:`sm`,onClick:()=>De(e),disabled:S,children:e},e))})]}),(0,v.jsxs)(`div`,{className:`app-field-group`,children:[(0,v.jsx)(f,{children:`测试模式`}),(0,v.jsxs)(`div`,{className:`flex gap-2 flex-wrap`,children:[(0,v.jsx)(r,{type:`button`,variant:D===`standalone`?`selected`:`outline`,size:`sm`,onClick:()=>O(`standalone`),disabled:S,title:`直接请求 URL,不走路由与 Mock,便于排查插件自身逻辑`,children:`单独测试`}),(0,v.jsx)(r,{type:`button`,variant:D===`integrated`?`selected`:`outline`,size:`sm`,onClick:()=>O(`integrated`),disabled:S,title:`与真实代理一致:先路由解析、Mock 匹配,再请求,便于排查整体链路`,children:`集成测试`})]}),(0,v.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:D===`standalone`?`直接请求上述 URL,不经过路由规则和 Mock,适合验证插件逻辑。`:`先按路由规则解析目标、匹配 Mock,再请求,与经代理的真实请求一致,适合排查链路问题。`})]}),(0,v.jsx)(`div`,{className:`bg-blue-50 dark:bg-blue-950/20 border border-blue-200 dark:border-blue-900 rounded-md p-3`,children:(0,v.jsxs)(`p`,{className:`text-xs text-blue-700 dark:text-blue-300`,children:[(0,v.jsx)(`strong`,{children:`测试流程:`}),` 发起真实请求 → 获取服务器响应 → 运行插件 Hook(`,x.join(`, `),`)→ 展示对比结果`]})})]}),!!Z&&(0,v.jsxs)(`div`,{className:`space-y-3`,children:[(0,v.jsx)(m,{}),(0,v.jsxs)(`div`,{className:`space-y-2`,children:[(0,v.jsxs)(`div`,{className:`flex items-center justify-between gap-3`,children:[(0,v.jsxs)(`h3`,{className:`text-sm font-medium flex items-center gap-2`,children:[(0,v.jsx)(d,{className:`h-4 w-4`}),`插件代码`]}),(0,v.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,v.jsx)(u,{value:je,onValueChange:e=>W(e),children:(0,v.jsxs)(p,{className:`h-7`,children:[(0,v.jsx)(l,{value:`normal`,className:`px-2 text-xs`,children:`正常视图`}),(0,v.jsx)(l,{value:`diff`,className:`px-2 text-xs`,disabled:!Ie,children:`Diff 视图`})]})}),(0,v.jsx)(g,{variant:`outline`,className:`text-xs font-normal`,children:Z}),(0,v.jsx)(r,{size:`sm`,variant:`ghost`,onClick:Q,disabled:z||C,children:z?(0,v.jsxs)(v.Fragment,{children:[(0,v.jsx)(h,{className:`h-4 w-4 mr-1 animate-spin`}),`读取中`]}):(0,v.jsxs)(v.Fragment,{children:[(0,v.jsx)(c,{className:`h-4 w-4 mr-1`}),`刷新代码`]})})]})]}),B?(0,v.jsx)(`div`,{className:`rounded-md border border-red-200 bg-red-50/80 p-3 text-sm text-red-700 dark:border-red-900 dark:bg-red-950/20 dark:text-red-300`,children:B}):je===`diff`&&Ie?(0,v.jsxs)(`div`,{className:`space-y-2`,children:[(0,v.jsxs)(`div`,{className:`flex items-center justify-between gap-3`,children:[(0,v.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:`左侧是原代码,右侧是 AI 修复后的代码`}),K!==`idle`&&(0,v.jsx)(g,{variant:`outline`,className:`text-xs font-normal`,children:Se(K)})]}),(0,v.jsx)(he,{original:L||F,modified:H||F,language:`javascript`,minHeight:`320px`})]}):(0,v.jsx)(me,{value:C&&H?H:F,onChange:()=>{},language:`javascript`,readOnly:!0,minHeight:`260px`}),(0,v.jsxs)(`div`,{className:`space-y-2 pt-2`,children:[(0,v.jsx)(f,{htmlFor:`plugin-extra-instruction`,children:`额外信息`}),(0,v.jsx)(ye,{id:`plugin-extra-instruction`,value:G,onChange:e=>Me(e.target.value),placeholder:`例如:补充 onBeforeResponse 里对 JSON 响应的判空逻辑;保留现有 hooks 和 manifest,不要改插件 id。`,className:`min-h-[88px]`,disabled:C||z}),(0,v.jsxs)(`div`,{className:`flex items-center justify-between gap-3`,children:[(0,v.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`输入额外要求后,AI 会基于当前插件代码直接更新并热加载。`}),(0,v.jsx)(r,{size:`sm`,variant:`outline`,onClick:Be,disabled:!Z||!G.trim()||!X||C||z||!!B,children:C&&K!==`retesting`?(0,v.jsxs)(v.Fragment,{children:[(0,v.jsx)(h,{className:`h-4 w-4 mr-1 animate-spin`}),`AI 更新中...`]}):(0,v.jsxs)(v.Fragment,{children:[(0,v.jsx)(ee,{className:`h-4 w-4 mr-1`}),`根据额外信息更新代码`]})})]})]})]})]}),k&&(0,v.jsxs)(`div`,{className:`space-y-3`,children:[(0,v.jsx)(m,{}),k.error?(0,v.jsx)(`div`,{className:`bg-red-50 dark:bg-red-950/20 border border-red-200 dark:border-red-900 rounded-md p-3`,children:(0,v.jsxs)(`div`,{className:`flex items-start gap-2`,children:[(0,v.jsx)(s,{className:`h-4 w-4 text-red-600 mt-0.5 shrink-0`}),(0,v.jsx)(`span`,{className:`text-sm text-red-700 dark:text-red-300`,children:k.error})]})}):(0,v.jsxs)(v.Fragment,{children:[(0,v.jsxs)(`div`,{className:`flex flex-wrap gap-4 items-center rounded-md border bg-muted/20 px-3 py-2`,children:[(0,v.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,v.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:`Header 对比`}),(0,v.jsx)(u,{value:j,onValueChange:e=>Oe(e),children:(0,v.jsxs)(p,{className:`h-7`,children:[(0,v.jsx)(l,{value:`split`,className:`px-2 text-xs`,children:`分栏`}),(0,v.jsx)(l,{value:`inline`,className:`px-2 text-xs`,children:`行内`})]})})]}),(0,v.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,v.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:`Body 对比`}),(0,v.jsx)(u,{value:M,onValueChange:e=>ke(e),children:(0,v.jsxs)(p,{className:`h-7`,children:[(0,v.jsx)(l,{value:`inline`,className:`px-2 text-xs`,children:`行内`}),(0,v.jsx)(l,{value:`split`,className:`px-2 text-xs`,children:`分栏`})]})})]})]}),k.realRequest&&(0,v.jsxs)(`div`,{className:`space-y-2`,children:[(0,v.jsxs)(`h3`,{className:`text-sm font-medium flex items-center gap-2`,children:[(0,v.jsx)(ce,{className:`h-4 w-4`}),`真实请求`,k.realRequest.testMode&&(0,v.jsx)(g,{variant:`outline`,className:`text-xs font-normal`,children:k.realRequest.testMode===`integrated`?`集成测试`:`单独测试`})]}),(0,v.jsxs)(`div`,{className:`bg-muted/50 rounded-md p-3 text-xs space-y-1`,children:[(0,v.jsxs)(`div`,{className:`flex gap-2`,children:[(0,v.jsx)(g,{variant:`outline`,className:`text-xs`,children:k.realRequest.method}),(0,v.jsx)(`span`,{className:`font-mono break-all`,children:k.realRequest.url})]}),k.realRequest.fetchError?(0,v.jsxs)(`div`,{className:`text-red-600 flex items-center gap-1 mt-1`,children:[(0,v.jsx)(s,{className:`h-3 w-3`}),`请求失败: `,k.realRequest.fetchError]}):(0,v.jsxs)(`div`,{className:`text-muted-foreground space-y-0.5`,children:[(0,v.jsxs)(`div`,{children:[`耗时: `,k.realRequest.fetchDuration,`ms`,k.originalResponse&&(0,v.jsxs)(v.Fragment,{children:[` · 状态码: `,(0,v.jsx)(g,{variant:`outline`,className:`text-xs`,children:k.originalResponse.statusCode}),` · 响应大小: `,k.originalResponse.bodyLength,` 字符`]})]}),(k.realRequest.targetResolved||k.realRequest.usedMock)&&(0,v.jsxs)(`div`,{className:`flex flex-wrap gap-1 mt-1`,children:[k.realRequest.targetResolved&&(0,v.jsx)(g,{variant:`outline`,className:`text-xs text-blue-600 border-blue-300`,children:`路由已改写`}),k.realRequest.usedMock&&(0,v.jsx)(g,{variant:`outline`,className:`text-xs text-orange-600 border-orange-300`,children:`已使用 Mock`})]})]})]})]}),(0,v.jsxs)(`div`,{className:`space-y-2`,children:[(0,v.jsxs)(`h3`,{className:`text-sm font-medium flex items-center gap-2`,children:[(0,v.jsx)(le,{className:`h-4 w-4`}),`Hook 执行结果`]}),Object.keys(k.hookResults||{}).length===0?(0,v.jsx)(`div`,{className:`text-xs text-muted-foreground bg-muted/50 rounded-md p-3`,children:`没有 Hook 被执行`}):(0,v.jsx)(`div`,{className:`space-y-2`,children:Object.entries(k.hookResults||{}).map(([e,t])=>(0,v.jsxs)(`div`,{className:`border rounded-md p-3 ${t.status===`success`?`bg-green-50 dark:bg-green-950/20 border-green-200 dark:border-green-900`:`bg-red-50 dark:bg-red-950/20 border-red-200 dark:border-red-900`}`,children:[(0,v.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,v.jsxs)(`div`,{className:`flex items-center gap-2`,children:[t.status===`success`?(0,v.jsx)(se,{className:`h-4 w-4 text-green-600`}):(0,v.jsx)(s,{className:`h-4 w-4 text-red-600`}),(0,v.jsx)(`span`,{className:`font-medium text-sm`,children:e})]}),t.duration!==void 0&&(0,v.jsxs)(g,{variant:`outline`,className:`text-xs`,children:[t.duration,`ms`]})]}),t.status===`error`&&(0,v.jsxs)(`div`,{className:`mt-2 space-y-2`,children:[(0,v.jsxs)(`div`,{className:`rounded-md border border-red-200 bg-red-100/60 px-2 py-2 text-xs text-red-800 dark:border-red-900 dark:bg-red-950/20 dark:text-red-300`,children:[(0,v.jsx)(`div`,{className:`font-medium mb-1`,children:`错误原因`}),(0,v.jsx)(`pre`,{className:`font-mono whitespace-pre-wrap break-all`,children:t.error})]}),t.stack&&(0,v.jsxs)(`details`,{className:`rounded-md border border-red-200 bg-background/60 px-2 py-2 text-xs dark:border-red-900`,children:[(0,v.jsx)(`summary`,{className:`cursor-pointer text-red-700 dark:text-red-300`,children:`查看错误堆栈`}),(0,v.jsx)(`pre`,{className:`font-mono whitespace-pre-wrap break-all mt-2 text-muted-foreground`,children:t.stack})]})]}),t.targetChanged&&(0,v.jsxs)(`div`,{className:`text-xs text-blue-700 mt-1 flex items-center gap-1`,children:[(0,v.jsx)(a,{className:`h-3 w-3`}),`Target 已修改为: `,t.targetChanged]})]},e))})]}),$.length>0&&(0,v.jsxs)(`div`,{className:`space-y-2`,children:[(0,v.jsxs)(`div`,{className:`flex items-center justify-between gap-3`,children:[(0,v.jsxs)(`h3`,{className:`text-sm font-medium flex items-center gap-2`,children:[(0,v.jsx)(o,{className:`h-4 w-4 text-red-500`}),`错误详情`]}),(0,v.jsxs)(`div`,{className:`flex items-center gap-2`,children:[!X&&(0,v.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:`AI 未配置,无法自动修复`}),(0,v.jsx)(r,{size:`sm`,variant:`outline`,onClick:ze,disabled:!Fe||!X||C||S,children:C?(0,v.jsxs)(v.Fragment,{children:[(0,v.jsx)(h,{className:`h-4 w-4 mr-1 animate-spin`}),`AI 修复中...`]}):(0,v.jsxs)(v.Fragment,{children:[(0,v.jsx)(te,{className:`h-4 w-4 mr-1`}),`AI 修复并更新代码`]})})]})]}),(0,v.jsx)(`div`,{className:`space-y-2`,children:$.map((e,t)=>(0,v.jsxs)(`div`,{className:`rounded-md border border-red-200 bg-red-50/80 p-3 dark:border-red-900 dark:bg-red-950/20`,children:[(0,v.jsxs)(`div`,{className:`flex items-center gap-2 mb-2`,children:[(0,v.jsx)(g,{variant:`outline`,className:`text-xs`,children:e.hookName}),(0,v.jsx)(`span`,{className:`text-xs text-red-700 dark:text-red-300`,children:`错误原因`})]}),(0,v.jsx)(`pre`,{className:`text-xs font-mono whitespace-pre-wrap break-all text-red-800 dark:text-red-300`,children:e.message}),e.stack&&(0,v.jsxs)(`details`,{className:`mt-2 text-xs`,children:[(0,v.jsx)(`summary`,{className:`cursor-pointer text-muted-foreground`,children:`查看完整堆栈`}),(0,v.jsx)(`pre`,{className:`font-mono whitespace-pre-wrap break-all mt-2 text-muted-foreground`,children:e.stack})]})]},`${e.hookName}-${t}`))}),N&&(0,v.jsx)(`div`,{className:`rounded-md border px-3 py-2 text-sm ${N.status===`success`?`border-green-200 bg-green-50 text-green-700 dark:border-green-900 dark:bg-green-950/20 dark:text-green-300`:`border-red-200 bg-red-50 text-red-700 dark:border-red-900 dark:bg-red-950/20 dark:text-red-300`}`,children:(0,v.jsxs)(`div`,{className:`flex items-center gap-2`,children:[N.status===`success`?(0,v.jsx)(c,{className:`h-4 w-4`}):(0,v.jsx)(d,{className:`h-4 w-4`}),(0,v.jsx)(`span`,{children:N.message})]})})]}),(k.requestHeadersChanged||k.requestBodyChanged)&&k.originalRequest&&k.modifiedRequest&&(0,v.jsxs)(`div`,{className:`space-y-3`,children:[(0,v.jsxs)(`h3`,{className:`text-sm font-medium flex items-center gap-2`,children:[(0,v.jsx)(ae,{className:`h-4 w-4`}),`请求对比(已被插件修改)`]}),k.requestHeadersChanged&&(0,v.jsxs)(`div`,{className:`space-y-1`,children:[(0,v.jsx)(`div`,{className:`text-xs font-medium text-muted-foreground`,children:`Request Headers`}),(0,v.jsx)(xe,{original:k.originalRequest.headers,modified:k.modifiedRequest.headers,mode:j})]}),k.requestBodyChanged&&(0,v.jsxs)(`div`,{className:`space-y-1`,children:[(0,v.jsx)(`div`,{className:`text-xs font-medium text-muted-foreground`,children:`Request Body`}),(0,v.jsx)(pe,{original:k.originalRequest.body||``,modified:k.modifiedRequest.body||``,mode:M,maxHeight:`180px`})]})]}),k.responseHeadersChanged&&k.originalResponse?.headers&&k.modifiedResponse?.headers&&(0,v.jsxs)(`div`,{className:`space-y-2`,children:[(0,v.jsxs)(`h3`,{className:`text-sm font-medium flex items-center gap-2`,children:[(0,v.jsx)(o,{className:`h-4 w-4 text-orange-500`}),`Response Headers 对比(已被插件修改)`]}),(0,v.jsx)(xe,{original:k.originalResponse.headers,modified:k.modifiedResponse.headers,mode:j})]}),k.modifiedResponse&&k.originalResponse&&(0,v.jsxs)(`div`,{className:`space-y-2`,children:[(0,v.jsxs)(`h3`,{className:`text-sm font-medium flex items-center gap-2`,children:[k.modifiedResponse.bodyChanged?(0,v.jsx)(o,{className:`h-4 w-4 text-orange-500`}):(0,v.jsx)(se,{className:`h-4 w-4 text-muted-foreground`}),`响应 Body`,k.modifiedResponse.bodyChanged?(0,v.jsxs)(v.Fragment,{children:[(0,v.jsx)(g,{className:`text-xs bg-orange-100 text-orange-700 border-orange-300`,children:`已修改`}),(0,v.jsxs)(`span`,{className:`text-[10px] text-muted-foreground`,children:[`(差异 `,k.modifiedResponse.bodyLength-k.originalResponse.bodyLength>0?`+`:``,k.modifiedResponse.bodyLength-k.originalResponse.bodyLength,` 字符)`]})]}):(0,v.jsx)(g,{variant:`outline`,className:`text-xs text-muted-foreground`,children:`未变化`})]}),k.modifiedResponse.bodyChanged?(0,v.jsxs)(`div`,{className:`space-y-1`,children:[(0,v.jsx)(`p`,{className:`text-[10px] text-muted-foreground`,children:`绿色=新增行,红色=删除行。仅对比前约 2500 字符以保障性能。`}),(0,v.jsx)(pe,{original:k.originalResponse.bodyForDiff??k.originalResponse.bodyPreview??``,modified:k.modifiedResponse.bodyForDiff??k.modifiedResponse.bodyPreview??``,mode:M,maxHeight:`320px`})]}):(0,v.jsx)(`pre`,{className:`bg-muted/50 rounded-md p-2 text-xs font-mono max-h-[200px] overflow-auto whitespace-pre-wrap break-all`,children:k.originalResponse.bodyPreview})]}),k.shortCircuited&&k.shortCircuitResponse&&(0,v.jsxs)(`div`,{className:`space-y-2`,children:[(0,v.jsxs)(`h3`,{className:`text-sm font-medium flex items-center gap-2`,children:[(0,v.jsx)(o,{className:`h-4 w-4 text-blue-500`}),`插件短路了请求(未发起真实请求)`]}),(0,v.jsx)(`div`,{className:`bg-blue-50 dark:bg-blue-950/20 border border-blue-200 dark:border-blue-900 rounded-md p-3`,children:(0,v.jsxs)(`div`,{className:`text-xs`,children:[(0,v.jsxs)(`div`,{children:[`状态码: `,k.shortCircuitResponse.statusCode]}),(0,v.jsx)(`pre`,{className:`mt-2 font-mono whitespace-pre-wrap break-all max-h-[200px] overflow-auto`,children:k.shortCircuitResponse.body})]})})]}),k.logs&&k.logs.length>0&&(0,v.jsxs)(`div`,{className:`space-y-2`,children:[(0,v.jsx)(`h3`,{className:`text-sm font-medium`,children:`插件日志`}),(0,v.jsx)(`div`,{className:`bg-muted rounded-md p-3 max-h-[200px] overflow-auto`,children:(0,v.jsx)(`div`,{className:`space-y-1`,children:k.logs.map((e,t)=>(0,v.jsxs)(`div`,{className:`text-xs font-mono`,children:[(0,v.jsxs)(`span`,{className:`inline-block w-12 ${e.level===`error`?`text-red-600`:e.level===`warn`?`text-yellow-600`:e.level===`info`?`text-blue-600`:`text-muted-foreground`}`,children:[`[`,e.level,`]`]}),(0,v.jsx)(`span`,{className:`text-foreground`,children:e.message})]},t))})})]})]})]})]}),Ve?null:(0,v.jsx)(m,{}),(0,v.jsxs)(_e,{className:`px-6 py-4 flex justify-between gap-2`,children:[Ve?null:(0,v.jsx)(r,{variant:`outline`,size:`sm`,onClick:()=>t?.(!1),disabled:S,children:`关闭`}),(0,v.jsx)(r,{size:`sm`,onClick:Re,disabled:S,children:S?(0,v.jsxs)(v.Fragment,{children:[(0,v.jsx)(h,{className:`h-4 w-4 mr-1 animate-spin`}),`请求中...`]}):(0,v.jsxs)(v.Fragment,{children:[(0,v.jsx)(be,{className:`h-4 w-4 mr-1`}),`发起测试请求`]})})]})]});return n?(0,v.jsx)(`div`,{className:`flex h-full min-h-0 flex-col`,children:He}):(0,v.jsx)(oe,{open:e,onOpenChange:e=>t?.(e),children:(0,v.jsx)(fe,{className:`p-0 flex flex-col`,resizable:!0,defaultWidth:900,storageKey:`plugin-test`,children:He})})}export{Ce as PluginTestDialog};