@jonathanleelx/meddle 0.5.0-beta.22 → 0.5.0-beta.24

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 (114) hide show
  1. package/CONFIG_STRUCTURE.md +1 -0
  2. package/README.md +16 -0
  3. package/bin/commands/route/active.js +14 -1
  4. package/bin/commands/route/add.js +27 -30
  5. package/bin/commands/route/delete.js +31 -30
  6. package/bin/commands/route/index.js +4 -0
  7. package/bin/commands/route/list.js +2 -2
  8. package/bin/commands/route/show.js +10 -1
  9. package/bin/commands/route/update.js +32 -30
  10. package/bin/lib/api-client.js +14 -2
  11. package/bin/lib/file-access.js +39 -1
  12. package/bin/lib/rule-file-edit.js +263 -0
  13. package/bin/lib/ruleset-readonly.js +61 -0
  14. package/dist/core/mock-handler.d.ts +0 -6
  15. package/dist/core/mock-handler.d.ts.map +1 -1
  16. package/dist/core/mock-handler.js +101 -11
  17. package/dist/core/mock-handler.js.map +1 -1
  18. package/dist/core/rule-file-edit.d.ts +81 -0
  19. package/dist/core/rule-file-edit.d.ts.map +1 -0
  20. package/dist/core/rule-file-edit.js +243 -0
  21. package/dist/core/rule-file-edit.js.map +1 -0
  22. package/dist/core/static-server.d.ts.map +1 -1
  23. package/dist/core/static-server.js +15 -13
  24. package/dist/core/static-server.js.map +1 -1
  25. package/dist/server/agent/tools.d.ts.map +1 -1
  26. package/dist/server/agent/tools.js +18 -17
  27. package/dist/server/agent/tools.js.map +1 -1
  28. package/dist/server/app-info.d.ts +14 -0
  29. package/dist/server/app-info.d.ts.map +1 -1
  30. package/dist/server/app-info.js +33 -1
  31. package/dist/server/app-info.js.map +1 -1
  32. package/dist/server/config.d.ts.map +1 -1
  33. package/dist/server/config.js +51 -9
  34. package/dist/server/config.js.map +1 -1
  35. package/dist/server/index.d.ts.map +1 -1
  36. package/dist/server/index.js +1 -0
  37. package/dist/server/index.js.map +1 -1
  38. package/dist/server/rule-files.d.ts +23 -0
  39. package/dist/server/rule-files.d.ts.map +1 -1
  40. package/dist/server/rule-files.js +169 -81
  41. package/dist/server/rule-files.js.map +1 -1
  42. package/dist/server/ruleset-lock.d.ts +62 -0
  43. package/dist/server/ruleset-lock.d.ts.map +1 -0
  44. package/dist/server/ruleset-lock.js +234 -0
  45. package/dist/server/ruleset-lock.js.map +1 -0
  46. package/mcp-server.js +87 -88
  47. package/package.json +1 -1
  48. package/web/dist/assets/{checkbox-v2kzp7K8.js → checkbox-CQyFsZzS.js} +1 -1
  49. package/web/dist/assets/detail-panel-D56nCma2.js +4 -0
  50. package/web/dist/assets/dist-BQN0rzUS.js +1 -0
  51. package/web/dist/assets/dist-DLQKRjuW.js +5 -0
  52. package/web/dist/assets/es2015-DPJTBYa9.js +41 -0
  53. package/web/dist/assets/{global-panel-shell-D32I98dR.js → global-panel-shell-SKPshqTf.js} +2 -2
  54. package/web/dist/assets/health-panel-CvI-VsvG.js +1 -0
  55. package/web/dist/assets/index-C6dPxxT3.css +2 -0
  56. package/web/dist/assets/index-Dcm171u1.js +21 -0
  57. package/web/dist/assets/mobile-proxy-panel-cpkvsdBT.js +8 -0
  58. package/web/dist/assets/mock-config-CtZ866iI.js +1 -0
  59. package/web/dist/assets/mock-editor-panel-CweYBdeM.js +20 -0
  60. package/web/dist/assets/{mocks-file-missing-note-DmrrCBYY.js → mocks-file-missing-note-C-QJ8Bpm.js} +1 -1
  61. package/web/dist/assets/{monaco-editor-6oLiu4W6.js → monaco-editor-Cge8h-Ca.js} +2 -2
  62. package/web/dist/assets/pane-bar-Dvi-MHuB.js +1 -0
  63. package/web/dist/assets/{pane-split-DYB05onX.js → pane-split-ChCHxR7K.js} +1 -1
  64. package/web/dist/assets/panel-heading-Crmy9fo0.js +1 -0
  65. package/web/dist/assets/plugin-code-editor-VaL2lVyD.js +2 -0
  66. package/web/dist/assets/plugin-config-DSiOk77l.js +2 -0
  67. package/web/dist/assets/{plugin-generator-Ba4hP5rg.js → plugin-generator-iAksMY2Q.js} +2 -2
  68. package/web/dist/assets/plugin-test-dialog-Cx6ifDnm.js +7 -0
  69. package/web/dist/assets/route-preview-T0s6si4V.js +1 -0
  70. package/web/dist/assets/{rule-ai-assistant-panel-CQTsZMJu.js → rule-ai-assistant-panel-DzfobTWM.js} +2 -2
  71. package/web/dist/assets/rule-config-ESpfkJg6.js +15 -0
  72. package/web/dist/assets/{rule-overview-panel-CmWdMs4I.js → rule-overview-panel-BswSByar.js} +1 -1
  73. package/web/dist/assets/settings-panel-Cj-1Z8Ow.js +1 -0
  74. package/web/dist/assets/{switch-DpLnRvOJ.js → switch-94vgsMHm.js} +1 -1
  75. package/web/dist/assets/toast-9yeTf7d9.js +1 -0
  76. package/web/dist/assets/use-mocks-file-status-BUIUJ4oQ.js +1 -0
  77. package/web/dist/index.html +11 -10
  78. package/web/dist/assets/detail-panel-DK7pM43g.js +0 -4
  79. package/web/dist/assets/dist-BNcjMpca.js +0 -1
  80. package/web/dist/assets/dist-DD7AvbXP.js +0 -1
  81. package/web/dist/assets/dist-UcOFuoN0.js +0 -5
  82. package/web/dist/assets/es2015-CRmLuA2o.js +0 -41
  83. package/web/dist/assets/health-panel-Dw7qdFVS.js +0 -1
  84. package/web/dist/assets/index-CYUNdxqh.css +0 -2
  85. package/web/dist/assets/index-CkoYwomI.js +0 -18
  86. package/web/dist/assets/mobile-proxy-panel-DtiDkpAa.js +0 -8
  87. package/web/dist/assets/mock-config-C3jSpNNu.js +0 -1
  88. package/web/dist/assets/mock-editor-panel-ByCYWJjO.js +0 -20
  89. package/web/dist/assets/panel-heading-BS8loc49.js +0 -1
  90. package/web/dist/assets/plugin-code-editor-DGzCBEpg.js +0 -2
  91. package/web/dist/assets/plugin-config-NVw234EF.js +0 -2
  92. package/web/dist/assets/plugin-test-dialog-B4ojc2_9.js +0 -7
  93. package/web/dist/assets/route-preview-BspvfNdW.js +0 -1
  94. package/web/dist/assets/rule-config-DDOeMRXa.js +0 -15
  95. package/web/dist/assets/settings-panel-aB0ojA9D.js +0 -1
  96. /package/web/dist/assets/{ai-config-store-B_VpGvwx.js → ai-config-store-C8D_PUGV.js} +0 -0
  97. /package/web/dist/assets/{alert-BmsRCcSL.js → alert-B514Frte.js} +0 -0
  98. /package/web/dist/assets/{babel-D1quDdNt.js → babel-bwZm0qi3.js} +0 -0
  99. /package/web/dist/assets/{body-diff-view-ByCHr9bv.js → body-diff-view-SfLCLzs9.js} +0 -0
  100. /package/web/dist/assets/{clipboard-DUgC_tNv.js → clipboard-Bt1qY01V.js} +0 -0
  101. /package/web/dist/assets/{dist-Bq2klZ3g.js → dist-Bsv9ad5F.js} +0 -0
  102. /package/web/dist/assets/{dist-BCvvYbmI.js → dist-fzPL-8F9.js} +0 -0
  103. /package/web/dist/assets/{dist-YM3jbhT-.js → dist-wv9ebJK_.js} +0 -0
  104. /package/web/dist/assets/{editor-pane-actions-DN-pxFsl.js → editor-pane-actions-_ckwcCII.js} +0 -0
  105. /package/web/dist/assets/{estree--Vq99DGn.js → estree-MatbZDwq.js} +0 -0
  106. /package/web/dist/assets/{html-D2PZBPnP.js → html-CCrsbFYX.js} +0 -0
  107. /package/web/dist/assets/{postcss-DfIslWug.js → postcss-BxN7Gr8n.js} +0 -0
  108. /package/web/dist/assets/{standalone-D-fjaAIs.js → standalone-DsnFnsqM.js} +0 -0
  109. /package/web/dist/assets/{syntax-highlight-EJCxGikd.js → syntax-highlight-BFgN_C0Y.js} +0 -0
  110. /package/web/dist/assets/{table-C3mgEjkP.js → table-DaXD6jJv.js} +0 -0
  111. /package/web/dist/assets/{textarea-BjWF0pk4.js → textarea-9wB8Hsz-.js} +0 -0
  112. /package/web/dist/assets/{wand-sparkles-DDGjzjnX.js → wand-sparkles-Bmt4dDOf.js} +0 -0
  113. /package/web/dist/assets/{wifi-QkTcTrED.js → wifi-Cjj_Br1u.js} +0 -0
  114. /package/web/dist/assets/{zap-CEVoVkAg.js → zap-BuOtogAv.js} +0 -0
@@ -1 +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 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 de,A as fe,C as u,D as pe,Dt as me,E as he,Et as ge,F as _e,I as d,It as f,L as ve,Nt as p,O as ye,Q as m,R as h,S as be,T as g,X as xe,Y as Se,Z as Ce,_ as we,b as _,c as Te,d as Ee,et as De,g as Oe,gt as ke,it as v,j as y,k as Ae,l as je,nt as b,pt as Me,rt as x,s as Ne,tt as S,u as Pe,v as Fe,vt as Ie,x as Le,xt as C,y as w,yt as Re}from"./index-CkoYwomI.js";import{n as ze,r as Be,t as Ve}from"./alert-BmsRCcSL.js";import{i as He,o as Ue,r as We,t as Ge}from"./mocks-file-missing-note-DmrrCBYY.js";var Ke=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`}]]),qe=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`}]]),Je=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`}]]),T=n(t(),1);async function Ye(){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 E=e(),Xe=[{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}],Ze=[{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)`}],D=`app-panel-content mt-0`,O=`app-field-group`,k=`app-section`,A=e=>{if(!e)return`100`;let t={small:`90`,medium:`100`,large:`110`};return e in t?t[e]:Xe.some(t=>t.value===e)?e:`100`};function Qe({open:e=!1,onOpenChange:t,embedded:n=!1}){let{theme:i,accentColor:Qe,setTheme:$e,setAccentColor:et,setZoom:j}=Oe(),[M,tt]=(0,T.useState)(`preferences`),[N,P]=(0,T.useState)(()=>l()),[F,nt]=(0,T.useState)(!1),[I,L]=(0,T.useState)(!1),[R,z]=(0,T.useState)(null),[rt,B]=(0,T.useState)(``),[V,H]=(0,T.useState)(null),[U,W]=(0,T.useState)(``),{status:G,refresh:K}=Ee(),[it,at]=(0,T.useState)([]),[q,J]=(0,T.useState)({}),[Y,ot]=(0,T.useState)(``),[X,Z]=(0,T.useState)(``),[Q,st]=(0,T.useState)(null),[ct,lt]=(0,T.useState)(!1),[ut,dt]=(0,T.useState)(null);(0,T.useEffect)(()=>{let e=!1;return Ye().then(t=>{e||dt(t)}),()=>{e=!0}},[]);let[$,ft]=(0,T.useState)(()=>A(we().fontSize)),[pt,mt]=(0,T.useState)(!1);(0,T.useEffect)(()=>{Fe().then(e=>{let t=A(e.fontSize);ft(t),j(parseInt(t,10)/100),mt(!0)}).catch(()=>{mt(!0)})},[j]),(0,T.useEffect)(()=>{if(!pt)return;let e=A($);j(parseInt(e,10)/100),w({fontSize:e}).catch(console.error)},[j,pt,$]),(0,T.useEffect)(()=>{(e||n)&&(Fe().then(e=>{P(e.aiConfig),W(e.mocksFilePath||``),J(e.clientAliases||{})}).catch(()=>{P(l())}),z(null),B(``),fetch(`/api/rule-files`).then(e=>e.json()).then(e=>{Array.isArray(e)&&at(e)}).catch(()=>{}))},[e,n]);let ht=e=>{let t=c(e);P({...N,provider:e,baseUrl:t.baseUrl,model:t.model})},gt=async()=>{L(!0);try{await w({aiConfig:N}),ae(N),z(`success`),B(`AI 配置保存成功`),_.success(`AI 配置保存成功`)}catch(e){let t=e instanceof Error?e.message:`保存失败`;z(`error`),B(t),_.error(t)}finally{L(!1)}},_t=()=>{le(),P(l()),z(null),B(``)},vt=async()=>{if(!ce(N)){z(`error`),B(`请填写完整的配置信息`);return}L(!0),z(null),B(`测试中...`);try{let e=N.baseUrl,t={"Content-Type":`application/json`},n;N.provider===`anthropic`?(t[`x-api-key`]=N.apiKey,t[`anthropic-version`]=`2023-06-01`,n={model:N.model,max_tokens:100,system:`You are a helpful assistant.`,messages:[{role:`user`,content:`Say "test successful"`}],temperature:.3}):(t.Authorization=`Bearer ${N.apiKey}`,n={model:N.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(N.provider===`anthropic`){if(!i.content?.[0]?.text)throw Error(`API响应格式不正确`)}else if(!i.choices?.[0]?.message?.content)throw Error(`API响应格式不正确`);z(`success`),B(`连接测试成功! API配置正常`)}catch(e){z(`error`),B(e instanceof Error?e.message:`测试失败`)}finally{L(!1)}},yt=(0,T.useCallback)(async()=>{try{let e=await fetch(`/api/refresh-config`,{method:`POST`});if(e.ok){let t=await e.json();K(),z(`success`),B(t.message||`配置已刷新`),setTimeout(()=>{z(null),B(``)},2e3)}else{let t=await e.json();z(`error`),B(t.error||`刷新配置失败`),setTimeout(()=>{z(null),B(``)},2e3)}}catch(e){console.error(`刷新配置失败:`,e),z(`error`),B(`刷新配置失败`),setTimeout(()=>{z(null),B(``)},2e3)}},[K]),bt=(0,T.useCallback)(async()=>{lt(!0),st(null);try{let e=await fetch(`/api/config-doctor`);e.ok?st(await e.json()):(z(`error`),B(`诊断失败`),setTimeout(()=>{z(null),B(``)},2e3))}catch(e){console.error(`诊断失败:`,e),z(`error`),B(`诊断失败`),setTimeout(()=>{z(null),B(``)},2e3)}finally{lt(!1)}},[]),xt=()=>{let e=Y.trim(),t=X.trim();!e||!t||(J(n=>({...n,[e]:t})),ot(``),Z(``))},St=async()=>{L(!0);try{await w({clientAliases:q}),z(`success`),B(`客户端名称已保存,新请求立即生效`),_.success(`客户端名称保存成功`)}catch(e){let t=e instanceof Error?e.message:`保存失败`;z(`error`),B(t),_.error(t)}finally{L(!1)}},Ct=async()=>{L(!0);try{await w({mocksFilePath:U}),K(),z(`success`),B(`Mock 文件路径已更新,已切换到新文件`),_.success(`Mock 文件路径保存成功`),setTimeout(()=>{z(null),B(``)},3e3)}catch(e){let t=e instanceof Error?e.message:`保存失败`;z(`error`),B(t),_.error(t)}finally{L(!1)}};Le({active:(e||n)&&M!==`preferences`,enabled:!I,priority:be.panel,onSave:()=>{if(M===`config`)return Ct();if(M===`clients`)return St();if(M===`ai`)return gt()}});let wt=(0,E.jsxs)(E.Fragment,{children:[!n&&(0,E.jsxs)(Ae,{className:`px-6 pt-6 pb-4`,children:[(0,E.jsxs)(fe,{className:`flex items-center gap-2`,children:[(0,E.jsx)(Re,{className:`h-5 w-5`}),`系统设置`]}),(0,E.jsx)(ye,{children:`管理系统偏好、配置和 AI 功能`})]}),(0,E.jsxs)(_e,{value:M,onValueChange:e=>tt(e),orientation:`vertical`,className:`min-h-0 flex-1 gap-0`,children:[(0,E.jsxs)(ve,{"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,E.jsxs)(h,{value:`preferences`,className:`h-9 w-full flex-none justify-start px-2.5 sm:px-3`,children:[(0,E.jsx)(Re,{}),(0,E.jsx)(`span`,{className:`hidden sm:inline`,children:`偏好设置`})]}),(0,E.jsxs)(h,{value:`config`,className:`h-9 w-full flex-none justify-start px-2.5 sm:px-3`,children:[(0,E.jsx)(p,{}),(0,E.jsx)(`span`,{className:`hidden sm:inline`,children:`配置文件`})]}),(0,E.jsxs)(h,{value:`clients`,className:`h-9 w-full flex-none justify-start px-2.5 sm:px-3`,children:[(0,E.jsx)(re,{}),(0,E.jsx)(`span`,{className:`hidden sm:inline`,children:`客户端`})]}),(0,E.jsxs)(h,{value:`ai`,className:`h-9 w-full flex-none justify-start px-2.5 sm:px-3`,children:[(0,E.jsx)(Ie,{}),(0,E.jsx)(`span`,{className:`hidden sm:inline`,children:`AI 配置`})]})]}),(0,E.jsxs)(d,{value:`preferences`,className:D,children:[(0,E.jsxs)(`div`,{className:O,children:[(0,E.jsx)(y,{className:`text-sm`,children:`主题`}),(0,E.jsxs)(Se,{value:i,onValueChange:e=>$e(e),children:[(0,E.jsx)(de,{children:(0,E.jsx)(De,{placeholder:`选择主题`})}),(0,E.jsx)(xe,{children:(0,E.jsxs)(Ce,{children:[(0,E.jsx)(m,{value:`system`,children:(0,E.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,E.jsx)(me,{className:`size-4`}),`跟随系统`]})}),(0,E.jsx)(m,{value:`light`,children:(0,E.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,E.jsx)(ke,{className:`size-4`}),`浅色模式`]})}),(0,E.jsx)(m,{value:`dark`,children:(0,E.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,E.jsx)(ge,{className:`size-4`}),`深色模式`]})})]})})]})]}),(0,E.jsxs)(`div`,{className:`flex flex-col gap-3`,children:[(0,E.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,E.jsx)(y,{className:`text-sm`,children:`强调色`}),(0,E.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`统一按钮、状态、选中项和焦点样式。自动模式会根据明暗主题选择合适的颜色。`})]}),(0,E.jsx)(S,{type:`single`,value:Qe,onValueChange:e=>{e&&et(e)},variant:`outline`,spacing:1,className:`flex-wrap justify-start`,"aria-label":`强调色`,children:Ze.map(e=>(0,E.jsxs)(b,{value:e.value,"aria-label":e.label,children:[e.value===`auto`?(0,E.jsx)(Ie,{"data-icon":`inline-start`}):(0,E.jsx)(`span`,{className:`size-3 rounded-full border border-foreground/10`,style:{background:e.color}}),e.label]},e.value))})]}),(0,E.jsxs)(`div`,{className:O,children:[(0,E.jsx)(y,{className:`text-sm`,children:`缩放比例`}),(0,E.jsxs)(Se,{value:$,onValueChange:ft,children:[(0,E.jsx)(de,{children:(0,E.jsx)(De,{placeholder:`选择缩放比例`})}),(0,E.jsx)(xe,{children:(0,E.jsx)(Ce,{children:Xe.map(e=>(0,E.jsx)(m,{value:e.value,children:e.label},e.value))})})]})]}),(0,E.jsx)(g,{}),(0,E.jsxs)(`div`,{className:O,children:[(0,E.jsx)(`h3`,{className:`text-sm font-medium`,children:`关于`}),(0,E.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Meddle - HTTP 调试代理工具`}),(0,E.jsxs)(`p`,{className:`text-xs text-muted-foreground`,"data-testid":`settings-app-version`,children:[`版本: `,ut??`—`]})]})]}),(0,E.jsxs)(d,{value:`config`,className:D,children:[(0,E.jsxs)(`div`,{className:k,children:[(0,E.jsx)(y,{className:`text-sm font-medium`,children:`路由规则文件`}),(0,E.jsxs)(`div`,{className:O,children:[(0,E.jsxs)(`div`,{className:`flex items-center gap-2 p-3 bg-muted rounded-md`,children:[(0,E.jsx)(p,{className:`h-4 w-4 text-muted-foreground shrink-0`}),(0,E.jsx)(`span`,{className:`text-xs font-mono truncate flex-1`,children:`~/.meddle/route-rules/`})]}),it.length>0?(0,E.jsx)(`div`,{className:`space-y-2`,children:it.map(e=>(0,E.jsxs)(`div`,{className:`flex items-center gap-2 rounded-md border px-3 py-2.5 text-sm`,children:[(0,E.jsx)(x,{variant:e.enabled?`default`:`secondary`,className:`text-[10px]`,children:e.enabled?`已启用`:`未启用`}),(0,E.jsxs)(`span`,{className:`flex-1 truncate text-xs`,children:[e.name,`.txt`]}),(0,E.jsxs)(`span`,{className:`text-xs text-muted-foreground`,children:[e.ruleCount,` 条规则`]})]},e.name))}):(0,E.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`暂无规则文件`}),(0,E.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`规则文件存放于 ~/.meddle/route-rules/ 目录,纯文本格式。在"路由规则"页面管理。`})]})]}),(0,E.jsx)(g,{}),(0,E.jsxs)(`div`,{className:k,children:[(0,E.jsx)(y,{className:`text-sm font-medium`,children:`Mock 规则文件`}),(0,E.jsxs)(`div`,{className:O,children:[(0,E.jsx)(`span`,{"data-testid":`settings-mocks-file-current-label`,className:`text-xs text-muted-foreground`,children:`当前使用`}),(0,E.jsxs)(`div`,{className:`flex items-center gap-2 p-3 bg-muted rounded-md`,children:[(0,E.jsx)(p,{className:`h-4 w-4 text-muted-foreground shrink-0`}),(0,E.jsx)(`span`,{"data-testid":`settings-mocks-file-resolved`,className:`text-xs font-mono flex-1 wrap-anywhere`,title:G?.path,children:G?.path?(0,E.jsx)(Ge,{path:G.path}):U||`默认: ~/.meddle/mocks.json`})]}),(0,E.jsxs)(`div`,{className:O,children:[(0,E.jsx)(y,{htmlFor:`mocksPath`,className:`text-xs text-muted-foreground`,children:`自定义 Mock 规则文件路径(留空使用默认)`}),(0,E.jsxs)(`div`,{className:`flex gap-2`,children:[(0,E.jsx)(v,{id:`mocksPath`,value:U,onChange:e=>W(e.target.value),placeholder:`如: /path/to/my-mocks.json`,className:`flex-1 h-8 text-sm font-mono`}),(0,E.jsxs)(u,{variant:`outline`,size:`sm`,onClick:Ct,disabled:I,className:`h-8`,children:[(0,E.jsx)(C,{"data-icon":`inline-start`,className:`h-3 w-3`}),`应用`]})]}),G?.legacyMocksPath?(0,E.jsx)(He,{oldPath:G.legacyMocksPath.oldPath,newPath:G.legacyMocksPath.newPath,visible:je(U),onUseOldPath:()=>W(G.legacyMocksPath.oldPath)}):null,(0,E.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`必须是 JSON 格式的 Mock 规则文件。支持 ~ 表示用户主目录;相对路径相对于 Meddle 配置目录。`}),Te(G)?(0,E.jsx)(We,{testId:`settings-mocks-file-invalid`,location:Ne(G.parseError)}):Pe(G)&&!G.legacyMocksPath?(0,E.jsx)(Ue,{testId:`settings-mocks-file-missing`}):null]})]})]}),(0,E.jsx)(g,{}),(0,E.jsxs)(`div`,{className:O,children:[(0,E.jsx)(`h3`,{className:`text-sm font-medium`,children:`操作`}),(0,E.jsxs)(`div`,{className:`flex gap-2`,children:[(0,E.jsxs)(r,{variant:`outline`,size:`sm`,onClick:yt,children:[(0,E.jsx)(te,{className:`h-4 w-4 mr-1`}),`重新加载配置`]}),(0,E.jsxs)(r,{variant:`outline`,size:`sm`,onClick:bt,disabled:ct,children:[(0,E.jsx)(Je,{className:`h-4 w-4 mr-1`}),ct?`诊断中...`:`诊断配置`]})]}),(0,E.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`点击重新加载可应用修改后的配置文件,点击诊断配置可检查配置有效性`})]}),Q&&(0,E.jsxs)(`div`,{className:k,children:[(0,E.jsx)(g,{}),(0,E.jsxs)(`div`,{children:[(0,E.jsxs)(`h3`,{className:`mb-4 flex items-center gap-2 text-sm font-medium`,children:[(0,E.jsx)(Je,{className:`h-4 w-4`}),`诊断结果`]}),(0,E.jsxs)(`div`,{className:`mb-3 p-3 rounded-md border ${Q.status===`ok`?`bg-green-50 dark:bg-green-950/20 border-green-200 dark:border-green-900`:Q.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:[Q.status===`ok`&&(0,E.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,E.jsx)(f,{className:`h-5 w-5 text-green-600 dark:text-green-400`}),(0,E.jsx)(`span`,{className:`text-sm font-medium text-green-700 dark:text-green-300`,children:`所有检查通过!配置正常。`})]}),Q.status===`warning`&&(0,E.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,E.jsx)(a,{className:`h-5 w-5 text-yellow-600 dark:text-yellow-400`}),(0,E.jsxs)(`span`,{className:`text-sm font-medium text-yellow-700 dark:text-yellow-300`,children:[`发现 `,Q.warnings.length,` 个警告`]})]}),Q.status===`error`&&(0,E.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,E.jsx)(o,{className:`h-5 w-5 text-red-600 dark:text-red-400`}),(0,E.jsxs)(`span`,{className:`text-sm font-medium text-red-700 dark:text-red-300`,children:[`发现 `,Q.errors.length,` 个错误`]})]})]}),(0,E.jsx)(`div`,{className:O,children:Q.checks.map((e,t)=>(0,E.jsx)(`div`,{className:`p-2 rounded border bg-card`,children:(0,E.jsxs)(`div`,{className:`flex items-start gap-2`,children:[(0,E.jsx)(f,{className:`h-4 w-4 text-green-600 dark:text-green-400 mt-0.5 shrink-0`}),(0,E.jsxs)(`div`,{className:`flex-1 min-w-0`,children:[(0,E.jsx)(`div`,{className:`text-sm font-medium`,children:e.name}),(0,E.jsx)(`div`,{className:`text-xs text-muted-foreground font-mono truncate`,children:e.path}),e.details&&(0,E.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))}),Q.warnings&&Q.warnings.length>0&&(0,E.jsxs)(`div`,{className:`mt-3 space-y-1`,children:[(0,E.jsx)(`div`,{className:`text-xs font-medium text-yellow-700 dark:text-yellow-300`,children:`警告:`}),Q.warnings.map((e,t)=>(0,E.jsxs)(`div`,{className:`flex items-start gap-2 text-xs text-yellow-600 dark:text-yellow-400`,children:[(0,E.jsx)(a,{className:`h-3 w-3 mt-0.5 shrink-0`}),(0,E.jsx)(`span`,{children:e})]},t))]}),Q.errors&&Q.errors.length>0&&(0,E.jsxs)(`div`,{className:`mt-3 space-y-1`,children:[(0,E.jsx)(`div`,{className:`text-xs font-medium text-red-700 dark:text-red-300`,children:`错误:`}),Q.errors.map((e,t)=>(0,E.jsxs)(`div`,{className:`flex items-start gap-2 text-xs text-red-600 dark:text-red-400`,children:[(0,E.jsx)(o,{className:`h-3 w-3 mt-0.5 shrink-0`}),(0,E.jsx)(`span`,{children:e})]},t))]})]})]})]}),(0,E.jsxs)(d,{value:`clients`,className:D,children:[(0,E.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,E.jsxs)(`h3`,{className:`text-sm font-medium flex items-center gap-2`,children:[(0,E.jsx)(re,{className:`h-4 w-4`}),`远程客户端名称`]}),(0,E.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`将日志中的客户端 IP 映射为设备名称。保存后新请求立即生效,无需重启代理。`})]}),(0,E.jsx)(`div`,{className:O,children:Object.entries(q).length===0?(0,E.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,E.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,E.jsx)(v,{value:e,readOnly:!0,className:`h-8 flex-1 font-mono text-xs bg-muted/40`,"aria-label":`客户端 IP ${e}`}),(0,E.jsx)(v,{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,E.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,E.jsx)(Me,{className:`h-4 w-4`})})]},e))}),(0,E.jsx)(g,{}),(0,E.jsxs)(`div`,{className:O,children:[(0,E.jsx)(y,{className:`text-sm`,children:`添加设备`}),(0,E.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,E.jsx)(v,{value:Y,onChange:e=>ot(e.target.value),placeholder:`客户端 IP,例如 10.13.232.187`,className:`h-8 flex-1 font-mono text-xs`}),(0,E.jsx)(v,{value:X,onChange:e=>Z(e.target.value),onKeyDown:e=>{e.key===`Enter`&&xt()},placeholder:`设备名称,例如 iPhone`,className:`h-8 flex-1 text-sm`}),(0,E.jsxs)(r,{variant:`outline`,size:`sm`,className:`h-8`,onClick:xt,disabled:!Y.trim()||!X.trim(),children:[(0,E.jsx)(s,{className:`h-4 w-4 mr-1`}),`添加`]})]})]}),(0,E.jsxs)(u,{onClick:St,disabled:I,children:[(0,E.jsx)(C,{"data-icon":`inline-start`,className:`h-4 w-4`}),I?`保存中...`:`保存客户端名称`]})]}),(0,E.jsxs)(d,{value:`ai`,className:D,children:[(0,E.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,E.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,E.jsx)(y,{className:`text-sm`,children:`启用 AI 功能`}),(0,E.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`启用智能代码修复功能`})]}),(0,E.jsx)(ie,{checked:N.enabled,onCheckedChange:e=>P({...N,enabled:e}),"aria-label":`启用 AI 功能`})]}),(0,E.jsx)(g,{}),(0,E.jsxs)(`div`,{className:k,children:[(0,E.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,E.jsx)(y,{className:`text-sm`,children:`AI 模型配置`}),(0,E.jsxs)(r,{variant:`outline`,size:`sm`,onClick:()=>{H({name:``,provider:`openai`,apiKey:``,baseUrl:`https://api.openai.com/v1/chat/completions`,model:`gpt-4o-mini`})},children:[(0,E.jsx)(s,{className:`h-4 w-4 mr-1`}),`添加模型`]})]}),(0,E.jsx)(`div`,{className:O,children:N.models&&N.models.length>0?N.models.map(e=>(0,E.jsx)(`div`,{className:`p-3 rounded-md border ${N.activeModelId===e.id?`border-primary bg-primary/5`:`border-border`}`,children:(0,E.jsxs)(`div`,{className:`flex items-start justify-between`,children:[(0,E.jsxs)(`div`,{className:`flex-1`,children:[(0,E.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,E.jsx)(`span`,{className:`font-medium text-sm`,children:e.name}),N.activeModelId===e.id&&(0,E.jsx)(x,{variant:`default`,className:`text-xs`,children:`当前使用`})]}),(0,E.jsxs)(`p`,{className:`text-xs text-muted-foreground mt-1`,children:[e.provider===`openai`?`OpenAI`:`Anthropic`,` - `,e.model]})]}),(0,E.jsxs)(`div`,{className:`flex gap-1`,children:[N.activeModelId!==e.id&&(0,E.jsxs)(r,{variant:`ghost`,size:`xs`,onClick:()=>P(oe(N,e.id)),children:[(0,E.jsx)(ee,{className:`h-3 w-3 mr-1`}),`使用`]}),(0,E.jsx)(r,{variant:`ghost`,size:`icon-sm`,onClick:()=>P(se(N,e.id)),className:`text-destructive`,"aria-label":`删除模型`,children:(0,E.jsx)(Me,{className:`h-3 w-3`})})]})]})},e.id)):(0,E.jsx)(`p`,{className:`text-xs text-muted-foreground italic py-4 text-center`,children:`暂无模型配置,点击"添加模型"创建`})}),V&&(0,E.jsxs)(`div`,{className:`space-y-5 rounded-md border border-primary bg-primary/5 p-4`,children:[(0,E.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,E.jsx)(y,{className:`text-sm font-medium`,children:`新增模型`}),(0,E.jsx)(r,{variant:`ghost`,size:`icon-xs`,onClick:()=>H(null),"aria-label":`关闭新增模型表单`,children:(0,E.jsx)(o,{className:`h-4 w-4`})})]}),(0,E.jsxs)(`div`,{className:O,children:[(0,E.jsx)(y,{htmlFor:`newModelName`,className:`text-xs`,children:`模型名称`}),(0,E.jsx)(v,{id:`newModelName`,value:V.name||``,onChange:e=>H({...V,name:e.target.value}),placeholder:`如:GPT-4o Mini`,className:`h-8 text-sm`})]}),(0,E.jsxs)(`div`,{className:O,children:[(0,E.jsx)(y,{className:`text-xs`,children:`服务商`}),(0,E.jsxs)(S,{type:`single`,value:V.provider,onValueChange:e=>{if(e===`openai`){let e=c(`openai`);H({...V,provider:`openai`,baseUrl:e.baseUrl,model:e.model})}else if(e===`anthropic`){let e=c(`anthropic`);H({...V,provider:`anthropic`,baseUrl:e.baseUrl,model:e.model})}},variant:`outline`,size:`sm`,spacing:0,children:[(0,E.jsx)(b,{value:`openai`,children:`OpenAI`}),(0,E.jsx)(b,{value:`anthropic`,children:`Anthropic`})]})]}),(0,E.jsxs)(`div`,{className:O,children:[(0,E.jsx)(y,{htmlFor:`newModelApiKey`,className:`text-xs`,children:`API Key`}),(0,E.jsx)(v,{id:`newModelApiKey`,type:F?`text`:`password`,value:V.apiKey||``,onChange:e=>H({...V,apiKey:e.target.value}),placeholder:`输入 API Key`,className:`h-8 text-sm`})]}),(0,E.jsxs)(`div`,{className:O,children:[(0,E.jsx)(y,{htmlFor:`newModelModel`,className:`text-xs`,children:`模型`}),(0,E.jsx)(v,{id:`newModelModel`,value:V.model||``,onChange:e=>H({...V,model:e.target.value}),placeholder:`模型名称`,className:`h-8 text-sm`})]}),(0,E.jsxs)(`div`,{className:O,children:[(0,E.jsx)(y,{htmlFor:`newModelBaseUrl`,className:`text-xs`,children:`API 端点`}),(0,E.jsx)(v,{id:`newModelBaseUrl`,value:V.baseUrl||``,onChange:e=>H({...V,baseUrl:e.target.value}),placeholder:`API 端点`,className:`h-8 text-sm`})]}),(0,E.jsxs)(`div`,{className:`flex justify-end gap-2 pt-2`,children:[(0,E.jsx)(r,{variant:`outline`,size:`xs`,onClick:()=>H(null),children:`取消`}),(0,E.jsxs)(r,{size:`xs`,onClick:()=>{V.name&&V.apiKey&&V.model&&V.baseUrl&&(P(ue(N,V)),H(null))},disabled:!V.name||!V.apiKey||!V.model||!V.baseUrl,children:[(0,E.jsx)(s,{className:`h-3 w-3 mr-1`}),`添加`]})]})]})]}),(0,E.jsx)(g,{}),(0,E.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,E.jsx)(y,{className:`text-sm`,children:`传统配置(向后兼容)`}),(0,E.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`如果未配置多模型,将使用此配置`})]}),(0,E.jsxs)(`div`,{className:O,children:[(0,E.jsx)(y,{className:`text-xs`,children:`AI 服务商`}),(0,E.jsxs)(S,{type:`single`,value:N.provider,onValueChange:e=>{(e===`openai`||e===`anthropic`)&&ht(e)},variant:`outline`,size:`sm`,spacing:0,children:[(0,E.jsx)(b,{value:`openai`,children:`OpenAI`}),(0,E.jsx)(b,{value:`anthropic`,children:`Anthropic`})]})]}),(0,E.jsxs)(`div`,{className:O,children:[(0,E.jsx)(y,{htmlFor:`apiKey`,className:`text-xs`,children:`API Key`}),(0,E.jsxs)(`div`,{className:`flex gap-2`,children:[(0,E.jsx)(v,{id:`apiKey`,type:F?`text`:`password`,value:N.apiKey,onChange:e=>P({...N,apiKey:e.target.value}),placeholder:`输入 API Key`,className:`flex-1 h-8 text-sm`}),(0,E.jsx)(r,{variant:`outline`,size:`icon-sm`,onClick:()=>nt(!F),"aria-label":F?`隐藏 API Key`:`显示 API Key`,children:F?(0,E.jsx)(Ke,{className:`h-4 w-4`}):(0,E.jsx)(qe,{className:`h-4 w-4`})})]})]}),(0,E.jsxs)(`div`,{className:O,children:[(0,E.jsx)(y,{htmlFor:`model`,className:`text-xs`,children:`模型`}),(0,E.jsx)(v,{id:`model`,value:N.model,onChange:e=>P({...N,model:e.target.value}),placeholder:`模型名称`,className:`h-8 text-sm`})]}),(0,E.jsxs)(`div`,{className:O,children:[(0,E.jsx)(y,{htmlFor:`baseUrl`,className:`text-xs`,children:`API 端点`}),(0,E.jsx)(v,{id:`baseUrl`,value:N.baseUrl,onChange:e=>P({...N,baseUrl:e.target.value}),placeholder:N.provider===`openai`?`https://api.openai.com/v1/chat/completions`:`https://api.anthropic.com/v1/messages`,className:`h-8 text-sm`})]}),rt&&(0,E.jsxs)(Ve,{variant:R===`error`?`destructive`:`default`,children:[R===`success`?(0,E.jsx)(f,{}):R===`error`?(0,E.jsx)(o,{}):(0,E.jsx)(a,{}),(0,E.jsx)(Be,{children:R===`success`?`操作成功`:R===`error`?`操作失败`:`处理中`}),(0,E.jsx)(ze,{children:rt})]}),(0,E.jsx)(g,{}),(0,E.jsxs)(`div`,{className:`flex justify-between`,children:[(0,E.jsxs)(r,{variant:`outline`,size:`sm`,onClick:_t,children:[(0,E.jsx)(ne,{className:`h-4 w-4 mr-1`}),`重置`]}),(0,E.jsxs)(`div`,{className:`flex gap-2`,children:[(0,E.jsx)(r,{variant:`outline`,size:`sm`,onClick:vt,disabled:!ce(N)||I,children:`测试连接`}),(0,E.jsxs)(u,{size:`sm`,onClick:gt,disabled:I,children:[(0,E.jsx)(C,{"data-icon":`inline-start`,className:`h-4 w-4`}),I?`保存中...`:`保存`]})]})]})]})]})]});return n?(0,E.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,E.jsx)(`div`,{className:`flex min-h-0 flex-1 flex-col overflow-hidden rounded-md border bg-card`,children:wt})}):(0,E.jsx)(he,{open:e,onOpenChange:t,children:(0,E.jsx)(pe,{className:`p-0 flex flex-col`,resizable:!0,defaultWidth:600,storageKey:`settings-panel`,children:wt})})}export{Qe as SettingsPanel};