@jonathanleelx/meddle 0.5.0-beta.1 → 0.5.0-beta.11

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 (111) hide show
  1. package/README.md +2 -0
  2. package/bin/commands/mock/add.js +25 -3
  3. package/bin/commands/mock/index.js +8 -4
  4. package/bin/commands/mock/list.js +1 -0
  5. package/bin/commands/mock/update.js +23 -4
  6. package/bin/commands/update.js +4 -0
  7. package/bin/lib/update-check.js +67 -6
  8. package/dist/core/h2-pool.d.ts +1 -0
  9. package/dist/core/h2-pool.d.ts.map +1 -1
  10. package/dist/core/h2-pool.js +79 -23
  11. package/dist/core/h2-pool.js.map +1 -1
  12. package/dist/core/mock-handler.d.ts.map +1 -1
  13. package/dist/core/mock-handler.js +12 -14
  14. package/dist/core/mock-handler.js.map +1 -1
  15. package/dist/core/mock-utils.d.ts +30 -0
  16. package/dist/core/mock-utils.d.ts.map +1 -0
  17. package/dist/core/mock-utils.js +117 -0
  18. package/dist/core/mock-utils.js.map +1 -0
  19. package/dist/core/plugin-intercept.d.ts.map +1 -1
  20. package/dist/core/plugin-intercept.js +1 -0
  21. package/dist/core/plugin-intercept.js.map +1 -1
  22. package/dist/core/remote-access.d.ts +11 -0
  23. package/dist/core/remote-access.d.ts.map +1 -1
  24. package/dist/core/remote-access.js +32 -0
  25. package/dist/core/remote-access.js.map +1 -1
  26. package/dist/core/types.d.ts +4 -1
  27. package/dist/core/types.d.ts.map +1 -1
  28. package/dist/helpers.d.ts +8 -1
  29. package/dist/helpers.d.ts.map +1 -1
  30. package/dist/helpers.js +22 -5
  31. package/dist/helpers.js.map +1 -1
  32. package/dist/plugins/builtin/mock-plugin.d.ts.map +1 -1
  33. package/dist/plugins/builtin/mock-plugin.js +6 -5
  34. package/dist/plugins/builtin/mock-plugin.js.map +1 -1
  35. package/dist/server/agent/tools.d.ts.map +1 -1
  36. package/dist/server/agent/tools.js +4 -0
  37. package/dist/server/agent/tools.js.map +1 -1
  38. package/dist/server/index.d.ts +1 -0
  39. package/dist/server/index.d.ts.map +1 -1
  40. package/dist/server/index.js.map +1 -1
  41. package/dist/server/mocks.d.ts.map +1 -1
  42. package/dist/server/mocks.js +1 -0
  43. package/dist/server/mocks.js.map +1 -1
  44. package/dist/server/rule-files.d.ts +44 -0
  45. package/dist/server/rule-files.d.ts.map +1 -1
  46. package/dist/server/rule-files.js +93 -0
  47. package/dist/server/rule-files.js.map +1 -1
  48. package/index.js +7 -8
  49. package/mcp-server.js +3 -0
  50. package/package.json +3 -2
  51. package/plugins/builtin/mock-plugin.ts +9 -5
  52. package/web/dist/assets/{checkbox-7NvTvLBs.js → checkbox-C5E3KITf.js} +1 -1
  53. package/web/dist/assets/{code-fixer-DoYxwBWb.js → code-fixer-Bbz_Rlzx.js} +2 -2
  54. package/web/dist/assets/detail-panel-SO3wZGmE.js +4 -0
  55. package/web/dist/assets/{dist-CxdY_A67.js → dist-C8RHq5At.js} +1 -1
  56. package/web/dist/assets/{dist-B8XUKgXe.js → dist-DoE7uybN.js} +1 -1
  57. package/web/dist/assets/{es2015-CfXu88Y7.js → es2015-DG46NGN7.js} +1 -1
  58. package/web/dist/assets/{global-panel-shell-Dq8vMdMI.js → global-panel-shell-czRfHl6X.js} +2 -2
  59. package/web/dist/assets/health-panel-B1nzvjHe.js +1 -0
  60. package/web/dist/assets/index-ChDOPlV_.js +18 -0
  61. package/web/dist/assets/index-bfV7sxx5.css +2 -0
  62. package/web/dist/assets/mobile-proxy-panel-By90SSuO.js +8 -0
  63. package/web/dist/assets/mock-config-8d2upIWY.js +1 -0
  64. package/web/dist/assets/mock-editor-panel-BzWl9IR3.js +1 -0
  65. package/web/dist/assets/{monaco-editor-CHNSCVe0.js → monaco-editor-BQUxbjIX.js} +1 -1
  66. package/web/dist/assets/plugin-code-editor-B38R8_va.js +2 -0
  67. package/web/dist/assets/plugin-config-BLTqZSgU.js +1 -0
  68. package/web/dist/assets/{plugin-generator-CojssHdE.js → plugin-generator-E5zcpf48.js} +2 -2
  69. package/web/dist/assets/plugin-test-dialog-BnYV2F3L.js +7 -0
  70. package/web/dist/assets/{route-preview-BecifYSe.js → route-preview-F0FExfHC.js} +1 -1
  71. package/web/dist/assets/{rule-ai-assistant-panel-LWDaNQKt.js → rule-ai-assistant-panel-D98DyECu.js} +2 -2
  72. package/web/dist/assets/rule-config-CKzf2Bdl.js +15 -0
  73. package/web/dist/assets/rule-overview-panel-8RHOtrPS.js +1 -0
  74. package/web/dist/assets/{select-C5thwxXQ.js → select-BavfGQkS.js} +1 -1
  75. package/web/dist/assets/settings-panel-BquHT2tt.js +1 -0
  76. package/web/dist/assets/{switch-C-Xk56TK.js → switch-Bes_YiJu.js} +1 -1
  77. package/web/dist/assets/table-2-BR5e3z8m.js +1 -0
  78. package/web/dist/index.html +10 -10
  79. package/web/dist/assets/detail-panel-vwvLpmzz.js +0 -4
  80. package/web/dist/assets/health-panel-CVQcuI1d.js +0 -1
  81. package/web/dist/assets/index-DJ5BnqEk.js +0 -18
  82. package/web/dist/assets/index-PcoCj3ST.css +0 -2
  83. package/web/dist/assets/mobile-proxy-panel-DMJRIDMK.js +0 -8
  84. package/web/dist/assets/mock-config-BTdHrudB.js +0 -1
  85. package/web/dist/assets/mock-editor-panel-ztb1w__0.js +0 -1
  86. package/web/dist/assets/plugin-code-editor-C_h_-lKr.js +0 -2
  87. package/web/dist/assets/plugin-config-B5tDGCq-.js +0 -1
  88. package/web/dist/assets/plugin-test-dialog-iWeHVCGW.js +0 -7
  89. package/web/dist/assets/rule-config-CLte-qNZ.js +0 -15
  90. package/web/dist/assets/settings-panel-Bx_qz1RQ.js +0 -1
  91. /package/web/dist/assets/{ai-config-store-DQXVJVn_.js → ai-config-store-C8D_PUGV.js} +0 -0
  92. /package/web/dist/assets/{alert-Bve02Ufr.js → alert-DCvlZAiv.js} +0 -0
  93. /package/web/dist/assets/{babel-DsprIpXZ.js → babel-DCr4VA1c.js} +0 -0
  94. /package/web/dist/assets/{body-diff-view-D7dCWajG.js → body-diff-view-B-4XWmL6.js} +0 -0
  95. /package/web/dist/assets/{clipboard-Dz6MgwV-.js → clipboard-VhPXNN5m.js} +0 -0
  96. /package/web/dist/assets/{dist-Cn0y0IRn.js → dist-Blyulj4_.js} +0 -0
  97. /package/web/dist/assets/{dist-DZJ9SMlJ.js → dist-Bsv9ad5F.js} +0 -0
  98. /package/web/dist/assets/{dist-Bb9TeEub.js → dist-CEd_wnRC.js} +0 -0
  99. /package/web/dist/assets/{dist-D5Dj17P8.js → dist-Ce4ujolc.js} +0 -0
  100. /package/web/dist/assets/{dist-C5nMErq8.js → dist-DWmDaXVN.js} +0 -0
  101. /package/web/dist/assets/{estree-BP7k0NIt.js → estree-qO_m2Qaw.js} +0 -0
  102. /package/web/dist/assets/{file-system-access-DK7FI6pN.js → file-system-access-_og-Tg9o.js} +0 -0
  103. /package/web/dist/assets/{html-6FIWbqxX.js → html-VDGahtyk.js} +0 -0
  104. /package/web/dist/assets/{postcss-Dnf30fQU.js → postcss-BUm8EKMw.js} +0 -0
  105. /package/web/dist/assets/{standalone-CjxtLKw-.js → standalone-Bj8SSd8Q.js} +0 -0
  106. /package/web/dist/assets/{syntax-highlight-BHsSDUha.js → syntax-highlight-Dk0-ewLI.js} +0 -0
  107. /package/web/dist/assets/{table-DymgLlcc.js → table-nW7uQVcl.js} +0 -0
  108. /package/web/dist/assets/{textarea-vuxJwU0x.js → textarea-BSI0rnW6.js} +0 -0
  109. /package/web/dist/assets/{wand-sparkles-wkul5vje.js → wand-sparkles-CJ7fSnom.js} +0 -0
  110. /package/web/dist/assets/{wifi-D9M35Ajj.js → wifi-CCLKyySQ.js} +0 -0
  111. /package/web/dist/assets/{zap-Djo4cgux.js → zap-DR-xiUMe.js} +0 -0
@@ -1 +0,0 @@
1
- import{a as e,f as t,l as n,t as r,u as i}from"./button-BTToMaBW.js";import"./dist-C6eaYCUo.js";import{t as a}from"./circle-alert-Q8cZk9Rv.js";import{t as o}from"./circle-x-C9USji_R.js";import{t as s}from"./plus-tVxSydJ8.js";import{t as ee}from"./refresh-cw-CG3HaiQT.js";import{t as te}from"./rotate-ccw-CAYM6Vv0.js";import{t as c}from"./smartphone-DKeDuJTU.js";import{a as ne,i as l,n as re,o as ie,r as ae,t as oe}from"./select-C5thwxXQ.js";import"./es2015-CfXu88Y7.js";import{t as se}from"./switch-C-Xk56TK.js";import{a as u,c as ce,l as le,n as ue,o as d,r as f,s as de,t as fe}from"./ai-config-store-DQXVJVn_.js";import{$ as p,A as m,B as pe,G as me,H as he,J as ge,O as h,U as g,V as _,X as _e,Z as ve,_ as ye,at as be,b as v,c as xe,d as Se,f as Ce,g as we,h as Te,it as Ee,k as y,l as b,lt as x,m as S,mt as De,o as Oe,p as C,pt as w,s as ke,u as T,v as Ae,y as je,z as E}from"./index-DJ5BnqEk.js";import{n as Me,r as Ne,t as Pe}from"./alert-Bve02Ufr.js";var Fe=n(`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`}]]),Ie=n(`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`}]]),Le=n(`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`}]]),D=t(i(),1),O=e(),Re=[{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)`}],k=`app-panel-content mt-0`,A=`app-field-group`,j=`app-section`,M=e=>{if(!e)return`100`;let t={small:`90`,medium:`100`,large:`110`};return e in t?t[e]:Re.some(t=>t.value===e)?e:`100`};function Be({open:e=!1,onOpenChange:t,embedded:n=!1}){let{theme:i,accentColor:Be,setTheme:Ve,setAccentColor:He,setZoom:N}=Oe(),[P,Ue]=(0,D.useState)(`preferences`),[F,I]=(0,D.useState)(()=>f()),[L,We]=(0,D.useState)(!1),[R,z]=(0,D.useState)(!1),[B,V]=(0,D.useState)(null),[Ge,H]=(0,D.useState)(``),[U,W]=(0,D.useState)(null),[G,Ke]=(0,D.useState)(``),[qe,Je]=(0,D.useState)([]),[K,q]=(0,D.useState)({}),[J,Ye]=(0,D.useState)(``),[Y,Xe]=(0,D.useState)(``),[X,Z]=(0,D.useState)(null),[Ze,Qe]=(0,D.useState)(!1),[Q,$e]=(0,D.useState)(()=>M(ke().fontSize)),[et,tt]=(0,D.useState)(!1);(0,D.useEffect)(()=>{xe().then(e=>{let t=M(e.fontSize);$e(t),N(parseInt(t,10)/100),tt(!0)}).catch(()=>{tt(!0)})},[N]),(0,D.useEffect)(()=>{if(!et)return;let e=M(Q);N(parseInt(e,10)/100),b({fontSize:e}).catch(console.error)},[N,et,Q]),(0,D.useEffect)(()=>{(e||n)&&(xe().then(e=>{I(e.aiConfig),Ke(e.mocksFilePath||``),q(e.clientAliases||{})}).catch(()=>{I(f())}),V(null),H(``),fetch(`/api/rule-files`).then(e=>e.json()).then(e=>{Array.isArray(e)&&Je(e)}).catch(()=>{}))},[e,n]);let nt=e=>{let t=u(e);I({...F,provider:e,baseUrl:t.baseUrl,model:t.model})},rt=async()=>{z(!0);try{await b({aiConfig:F}),ce(F),V(`success`),H(`AI 配置保存成功`),T.success(`AI 配置保存成功`)}catch(e){let t=e instanceof Error?e.message:`保存失败`;V(`error`),H(t),T.error(t)}finally{z(!1)}},it=()=>{de(),I(f()),V(null),H(``)},at=async()=>{if(!d(F)){V(`error`),H(`请填写完整的配置信息`);return}z(!0),V(null),H(`测试中...`);try{let e=F.baseUrl,t={"Content-Type":`application/json`},n;F.provider===`anthropic`?(t[`x-api-key`]=F.apiKey,t[`anthropic-version`]=`2023-06-01`,n={model:F.model,max_tokens:100,system:`You are a helpful assistant.`,messages:[{role:`user`,content:`Say "test successful"`}],temperature:.3}):(t.Authorization=`Bearer ${F.apiKey}`,n={model:F.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(F.provider===`anthropic`){if(!i.content?.[0]?.text)throw Error(`API响应格式不正确`)}else if(!i.choices?.[0]?.message?.content)throw Error(`API响应格式不正确`);V(`success`),H(`连接测试成功! API配置正常`)}catch(e){V(`error`),H(e instanceof Error?e.message:`测试失败`)}finally{z(!1)}},ot=(0,D.useCallback)(async()=>{try{let e=await fetch(`/api/refresh-config`,{method:`POST`});if(e.ok){let t=await e.json();V(`success`),H(t.message||`配置已刷新`),setTimeout(()=>{V(null),H(``)},2e3)}else{let t=await e.json();V(`error`),H(t.error||`刷新配置失败`),setTimeout(()=>{V(null),H(``)},2e3)}}catch(e){console.error(`刷新配置失败:`,e),V(`error`),H(`刷新配置失败`),setTimeout(()=>{V(null),H(``)},2e3)}},[]),st=(0,D.useCallback)(async()=>{Qe(!0),Z(null);try{let e=await fetch(`/api/config-doctor`);e.ok?Z(await e.json()):(V(`error`),H(`诊断失败`),setTimeout(()=>{V(null),H(``)},2e3))}catch(e){console.error(`诊断失败:`,e),V(`error`),H(`诊断失败`),setTimeout(()=>{V(null),H(``)},2e3)}finally{Qe(!1)}},[]),ct=()=>{let e=J.trim(),t=Y.trim();!e||!t||(q(n=>({...n,[e]:t})),Ye(``),Xe(``))},lt=async()=>{z(!0);try{await b({clientAliases:K}),V(`success`),H(`客户端名称已保存,新请求立即生效`),T.success(`客户端名称保存成功`)}catch(e){let t=e instanceof Error?e.message:`保存失败`;V(`error`),H(t),T.error(t)}finally{z(!1)}},ut=async()=>{z(!0);try{await b({mocksFilePath:G}),V(`success`),H(`Mock 文件路径已更新,刷新页面后生效`),T.success(`Mock 文件路径保存成功`),setTimeout(()=>{V(null),H(``)},3e3)}catch(e){let t=e instanceof Error?e.message:`保存失败`;V(`error`),H(t),T.error(t)}finally{z(!1)}};Se({active:(e||n)&&P!==`preferences`,enabled:!R,priority:Ce.panel,onSave:()=>{if(P===`config`)return ut();if(P===`clients`)return lt();if(P===`ai`)return rt()}});let $=(0,O.jsxs)(O.Fragment,{children:[!n&&(0,O.jsxs)(Ae,{className:`px-6 pt-6 pb-4`,children:[(0,O.jsxs)(je,{className:`flex items-center gap-2`,children:[(0,O.jsx)(ve,{className:`h-5 w-5`}),`系统设置`]}),(0,O.jsx)(ye,{children:`管理系统偏好、配置和 AI 功能`})]}),(0,O.jsxs)(pe,{value:P,onValueChange:e=>Ue(e),orientation:`vertical`,className:`min-h-0 flex-1 gap-0`,children:[(0,O.jsxs)(he,{"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,O.jsxs)(g,{value:`preferences`,className:`h-9 w-full flex-none justify-start px-2.5 sm:px-3`,children:[(0,O.jsx)(ve,{}),(0,O.jsx)(`span`,{className:`hidden sm:inline`,children:`偏好设置`})]}),(0,O.jsxs)(g,{value:`config`,className:`h-9 w-full flex-none justify-start px-2.5 sm:px-3`,children:[(0,O.jsx)(x,{}),(0,O.jsx)(`span`,{className:`hidden sm:inline`,children:`配置文件`})]}),(0,O.jsxs)(g,{value:`clients`,className:`h-9 w-full flex-none justify-start px-2.5 sm:px-3`,children:[(0,O.jsx)(c,{}),(0,O.jsx)(`span`,{className:`hidden sm:inline`,children:`客户端`})]}),(0,O.jsxs)(g,{value:`ai`,className:`h-9 w-full flex-none justify-start px-2.5 sm:px-3`,children:[(0,O.jsx)(_e,{}),(0,O.jsx)(`span`,{className:`hidden sm:inline`,children:`AI 配置`})]})]}),(0,O.jsxs)(_,{value:`preferences`,className:k,children:[(0,O.jsxs)(`div`,{className:A,children:[(0,O.jsx)(v,{className:`text-sm`,children:`主题`}),(0,O.jsxs)(oe,{value:i,onValueChange:e=>Ve(e),children:[(0,O.jsx)(ne,{children:(0,O.jsx)(ie,{placeholder:`选择主题`})}),(0,O.jsx)(re,{children:(0,O.jsxs)(ae,{children:[(0,O.jsx)(l,{value:`system`,children:(0,O.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,O.jsx)(be,{className:`size-4`}),`跟随系统`]})}),(0,O.jsx)(l,{value:`light`,children:(0,O.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,O.jsx)(ge,{className:`size-4`}),`浅色模式`]})}),(0,O.jsx)(l,{value:`dark`,children:(0,O.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,O.jsx)(Ee,{className:`size-4`}),`深色模式`]})})]})})]})]}),(0,O.jsxs)(`div`,{className:`flex flex-col gap-3`,children:[(0,O.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,O.jsx)(v,{className:`text-sm`,children:`强调色`}),(0,O.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`统一按钮、状态、选中项和焦点样式。自动模式会根据明暗主题选择合适的颜色。`})]}),(0,O.jsx)(h,{type:`single`,value:Be,onValueChange:e=>{e&&He(e)},variant:`outline`,spacing:1,className:`flex-wrap justify-start`,"aria-label":`强调色`,children:ze.map(e=>(0,O.jsxs)(y,{value:e.value,"aria-label":e.label,children:[e.value===`auto`?(0,O.jsx)(_e,{"data-icon":`inline-start`}):(0,O.jsx)(`span`,{className:`size-3 rounded-full border border-foreground/10`,style:{background:e.color}}),e.label]},e.value))})]}),(0,O.jsxs)(`div`,{className:A,children:[(0,O.jsx)(v,{className:`text-sm`,children:`缩放比例`}),(0,O.jsxs)(oe,{value:Q,onValueChange:$e,children:[(0,O.jsx)(ne,{children:(0,O.jsx)(ie,{placeholder:`选择缩放比例`})}),(0,O.jsx)(re,{children:(0,O.jsx)(ae,{children:Re.map(e=>(0,O.jsx)(l,{value:e.value,children:e.label},e.value))})})]})]}),(0,O.jsx)(S,{}),(0,O.jsxs)(`div`,{className:A,children:[(0,O.jsx)(`h3`,{className:`text-sm font-medium`,children:`关于`}),(0,O.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Meddle - HTTP 调试代理工具`}),(0,O.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`版本: 1.0.0`})]})]}),(0,O.jsxs)(_,{value:`config`,className:k,children:[(0,O.jsxs)(`div`,{className:j,children:[(0,O.jsx)(v,{className:`text-sm font-medium`,children:`路由规则文件`}),(0,O.jsxs)(`div`,{className:A,children:[(0,O.jsxs)(`div`,{className:`flex items-center gap-2 p-3 bg-muted rounded-md`,children:[(0,O.jsx)(x,{className:`h-4 w-4 text-muted-foreground shrink-0`}),(0,O.jsx)(`span`,{className:`text-xs font-mono truncate flex-1`,children:`~/.meddle/route-rules/`})]}),qe.length>0?(0,O.jsx)(`div`,{className:`space-y-2`,children:qe.map(e=>(0,O.jsxs)(`div`,{className:`flex items-center gap-2 rounded-md border px-3 py-2.5 text-sm`,children:[(0,O.jsx)(E,{variant:e.enabled?`default`:`secondary`,className:`text-[10px]`,children:e.enabled?`已启用`:`未启用`}),(0,O.jsxs)(`span`,{className:`flex-1 truncate text-xs`,children:[e.name,`.txt`]}),(0,O.jsxs)(`span`,{className:`text-xs text-muted-foreground`,children:[e.ruleCount,` 条规则`]})]},e.name))}):(0,O.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`暂无规则文件`}),(0,O.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`规则文件存放于 ~/.meddle/route-rules/ 目录,纯文本格式。在"路由规则"页面管理。`})]})]}),(0,O.jsx)(S,{}),(0,O.jsxs)(`div`,{className:j,children:[(0,O.jsx)(v,{className:`text-sm font-medium`,children:`Mock 规则文件`}),(0,O.jsxs)(`div`,{className:A,children:[(0,O.jsxs)(`div`,{className:`flex items-center gap-2 p-3 bg-muted rounded-md`,children:[(0,O.jsx)(x,{className:`h-4 w-4 text-muted-foreground shrink-0`}),(0,O.jsx)(`span`,{className:`text-xs font-mono truncate flex-1`,children:G||`默认: ~/.meddle/mocks.json`})]}),(0,O.jsxs)(`div`,{className:A,children:[(0,O.jsx)(v,{htmlFor:`mocksPath`,className:`text-xs text-muted-foreground`,children:`自定义 Mock 规则文件路径(留空使用默认)`}),(0,O.jsxs)(`div`,{className:`flex gap-2`,children:[(0,O.jsx)(m,{id:`mocksPath`,value:G,onChange:e=>Ke(e.target.value),placeholder:`如: /path/to/my-mocks.json`,className:`flex-1 h-8 text-sm font-mono`}),(0,O.jsxs)(C,{variant:`outline`,size:`sm`,onClick:ut,disabled:R,className:`h-8`,children:[(0,O.jsx)(p,{"data-icon":`inline-start`,className:`h-3 w-3`}),`应用`]})]}),(0,O.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`必须是 JSON 格式的 Mock 规则文件`})]})]})]}),(0,O.jsx)(S,{}),(0,O.jsxs)(`div`,{className:A,children:[(0,O.jsx)(`h3`,{className:`text-sm font-medium`,children:`操作`}),(0,O.jsxs)(`div`,{className:`flex gap-2`,children:[(0,O.jsxs)(r,{variant:`outline`,size:`sm`,onClick:ot,children:[(0,O.jsx)(ee,{className:`h-4 w-4 mr-1`}),`重新加载配置`]}),(0,O.jsxs)(r,{variant:`outline`,size:`sm`,onClick:st,disabled:Ze,children:[(0,O.jsx)(Le,{className:`h-4 w-4 mr-1`}),Ze?`诊断中...`:`诊断配置`]})]}),(0,O.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`点击重新加载可应用修改后的配置文件,点击诊断配置可检查配置有效性`})]}),X&&(0,O.jsxs)(`div`,{className:j,children:[(0,O.jsx)(S,{}),(0,O.jsxs)(`div`,{children:[(0,O.jsxs)(`h3`,{className:`mb-4 flex items-center gap-2 text-sm font-medium`,children:[(0,O.jsx)(Le,{className:`h-4 w-4`}),`诊断结果`]}),(0,O.jsxs)(`div`,{className:`mb-3 p-3 rounded-md border ${X.status===`ok`?`bg-green-50 dark:bg-green-950/20 border-green-200 dark:border-green-900`:X.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:[X.status===`ok`&&(0,O.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,O.jsx)(w,{className:`h-5 w-5 text-green-600 dark:text-green-400`}),(0,O.jsx)(`span`,{className:`text-sm font-medium text-green-700 dark:text-green-300`,children:`所有检查通过!配置正常。`})]}),X.status===`warning`&&(0,O.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,O.jsx)(a,{className:`h-5 w-5 text-yellow-600 dark:text-yellow-400`}),(0,O.jsxs)(`span`,{className:`text-sm font-medium text-yellow-700 dark:text-yellow-300`,children:[`发现 `,X.warnings.length,` 个警告`]})]}),X.status===`error`&&(0,O.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,O.jsx)(o,{className:`h-5 w-5 text-red-600 dark:text-red-400`}),(0,O.jsxs)(`span`,{className:`text-sm font-medium text-red-700 dark:text-red-300`,children:[`发现 `,X.errors.length,` 个错误`]})]})]}),(0,O.jsx)(`div`,{className:A,children:X.checks.map((e,t)=>(0,O.jsx)(`div`,{className:`p-2 rounded border bg-card`,children:(0,O.jsxs)(`div`,{className:`flex items-start gap-2`,children:[(0,O.jsx)(w,{className:`h-4 w-4 text-green-600 dark:text-green-400 mt-0.5 shrink-0`}),(0,O.jsxs)(`div`,{className:`flex-1 min-w-0`,children:[(0,O.jsx)(`div`,{className:`text-sm font-medium`,children:e.name}),(0,O.jsx)(`div`,{className:`text-xs text-muted-foreground font-mono truncate`,children:e.path}),e.details&&(0,O.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))}),X.warnings&&X.warnings.length>0&&(0,O.jsxs)(`div`,{className:`mt-3 space-y-1`,children:[(0,O.jsx)(`div`,{className:`text-xs font-medium text-yellow-700 dark:text-yellow-300`,children:`警告:`}),X.warnings.map((e,t)=>(0,O.jsxs)(`div`,{className:`flex items-start gap-2 text-xs text-yellow-600 dark:text-yellow-400`,children:[(0,O.jsx)(a,{className:`h-3 w-3 mt-0.5 shrink-0`}),(0,O.jsx)(`span`,{children:e})]},t))]}),X.errors&&X.errors.length>0&&(0,O.jsxs)(`div`,{className:`mt-3 space-y-1`,children:[(0,O.jsx)(`div`,{className:`text-xs font-medium text-red-700 dark:text-red-300`,children:`错误:`}),X.errors.map((e,t)=>(0,O.jsxs)(`div`,{className:`flex items-start gap-2 text-xs text-red-600 dark:text-red-400`,children:[(0,O.jsx)(o,{className:`h-3 w-3 mt-0.5 shrink-0`}),(0,O.jsx)(`span`,{children:e})]},t))]})]})]})]}),(0,O.jsxs)(_,{value:`clients`,className:k,children:[(0,O.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,O.jsxs)(`h3`,{className:`text-sm font-medium flex items-center gap-2`,children:[(0,O.jsx)(c,{className:`h-4 w-4`}),`远程客户端名称`]}),(0,O.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`将日志中的客户端 IP 映射为设备名称。保存后新请求立即生效,无需重启代理。`})]}),(0,O.jsx)(`div`,{className:A,children:Object.entries(K).length===0?(0,O.jsx)(`div`,{className:`rounded-md border border-dashed p-4 text-center text-xs text-muted-foreground`,children:`尚未配置设备名称`}):Object.entries(K).map(([e,t])=>(0,O.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,O.jsx)(m,{value:e,readOnly:!0,className:`h-8 flex-1 font-mono text-xs bg-muted/40`,"aria-label":`客户端 IP ${e}`}),(0,O.jsx)(m,{value:t,onChange:t=>{let n=t.target.value;q(t=>({...t,[e]:n}))},className:`h-8 flex-1 text-sm`,"aria-label":`${e} 的设备名称`}),(0,O.jsx)(r,{variant:`ghost`,size:`sm`,className:`h-8 w-8 p-0 text-muted-foreground hover:text-destructive`,onClick:()=>{q(t=>{let n={...t};return delete n[e],n})},title:`删除设备名称`,children:(0,O.jsx)(me,{className:`h-4 w-4`})})]},e))}),(0,O.jsx)(S,{}),(0,O.jsxs)(`div`,{className:A,children:[(0,O.jsx)(v,{className:`text-sm`,children:`添加设备`}),(0,O.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,O.jsx)(m,{value:J,onChange:e=>Ye(e.target.value),placeholder:`客户端 IP,例如 10.13.232.187`,className:`h-8 flex-1 font-mono text-xs`}),(0,O.jsx)(m,{value:Y,onChange:e=>Xe(e.target.value),onKeyDown:e=>{e.key===`Enter`&&ct()},placeholder:`设备名称,例如 iPhone`,className:`h-8 flex-1 text-sm`}),(0,O.jsxs)(r,{variant:`outline`,size:`sm`,className:`h-8`,onClick:ct,disabled:!J.trim()||!Y.trim(),children:[(0,O.jsx)(s,{className:`h-4 w-4 mr-1`}),`添加`]})]})]}),(0,O.jsxs)(C,{onClick:lt,disabled:R,children:[(0,O.jsx)(p,{"data-icon":`inline-start`,className:`h-4 w-4`}),R?`保存中...`:`保存客户端名称`]})]}),(0,O.jsxs)(_,{value:`ai`,className:k,children:[(0,O.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,O.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,O.jsx)(v,{className:`text-sm`,children:`启用 AI 功能`}),(0,O.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`启用智能代码修复功能`})]}),(0,O.jsx)(se,{checked:F.enabled,onCheckedChange:e=>I({...F,enabled:e}),"aria-label":`启用 AI 功能`})]}),(0,O.jsx)(S,{}),(0,O.jsxs)(`div`,{className:j,children:[(0,O.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,O.jsx)(v,{className:`text-sm`,children:`AI 模型配置`}),(0,O.jsxs)(r,{variant:`outline`,size:`sm`,onClick:()=>{W({name:``,provider:`openai`,apiKey:``,baseUrl:`https://api.openai.com/v1/chat/completions`,model:`gpt-4o-mini`})},children:[(0,O.jsx)(s,{className:`h-4 w-4 mr-1`}),`添加模型`]})]}),(0,O.jsx)(`div`,{className:A,children:F.models&&F.models.length>0?F.models.map(e=>(0,O.jsx)(`div`,{className:`p-3 rounded-md border ${F.activeModelId===e.id?`border-primary bg-primary/5`:`border-border`}`,children:(0,O.jsxs)(`div`,{className:`flex items-start justify-between`,children:[(0,O.jsxs)(`div`,{className:`flex-1`,children:[(0,O.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,O.jsx)(`span`,{className:`font-medium text-sm`,children:e.name}),F.activeModelId===e.id&&(0,O.jsx)(E,{variant:`default`,className:`text-xs`,children:`当前使用`})]}),(0,O.jsxs)(`p`,{className:`text-xs text-muted-foreground mt-1`,children:[e.provider===`openai`?`OpenAI`:`Anthropic`,` - `,e.model]})]}),(0,O.jsxs)(`div`,{className:`flex gap-1`,children:[F.activeModelId!==e.id&&(0,O.jsxs)(r,{variant:`ghost`,size:`sm`,onClick:()=>I(le(F,e.id)),className:`h-7 text-xs`,children:[(0,O.jsx)(De,{className:`h-3 w-3 mr-1`}),`使用`]}),(0,O.jsx)(r,{variant:`ghost`,size:`sm`,onClick:()=>I(ue(F,e.id)),className:`h-7 w-7 p-0 text-destructive`,children:(0,O.jsx)(me,{className:`h-3 w-3`})})]})]})},e.id)):(0,O.jsx)(`p`,{className:`text-xs text-muted-foreground italic py-4 text-center`,children:`暂无模型配置,点击"添加模型"创建`})}),U&&(0,O.jsxs)(`div`,{className:`space-y-5 rounded-md border border-primary bg-primary/5 p-4`,children:[(0,O.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,O.jsx)(v,{className:`text-sm font-medium`,children:`新增模型`}),(0,O.jsx)(r,{variant:`ghost`,size:`sm`,onClick:()=>W(null),className:`h-6 w-6 p-0`,children:(0,O.jsx)(o,{className:`h-4 w-4`})})]}),(0,O.jsxs)(`div`,{className:A,children:[(0,O.jsx)(v,{htmlFor:`newModelName`,className:`text-xs`,children:`模型名称`}),(0,O.jsx)(m,{id:`newModelName`,value:U.name||``,onChange:e=>W({...U,name:e.target.value}),placeholder:`如:GPT-4o Mini`,className:`h-8 text-sm`})]}),(0,O.jsxs)(`div`,{className:A,children:[(0,O.jsx)(v,{className:`text-xs`,children:`服务商`}),(0,O.jsxs)(h,{type:`single`,value:U.provider,onValueChange:e=>{if(e===`openai`){let e=u(`openai`);W({...U,provider:`openai`,baseUrl:e.baseUrl,model:e.model})}else if(e===`anthropic`){let e=u(`anthropic`);W({...U,provider:`anthropic`,baseUrl:e.baseUrl,model:e.model})}},variant:`outline`,size:`sm`,spacing:0,children:[(0,O.jsx)(y,{value:`openai`,children:`OpenAI`}),(0,O.jsx)(y,{value:`anthropic`,children:`Anthropic`})]})]}),(0,O.jsxs)(`div`,{className:A,children:[(0,O.jsx)(v,{htmlFor:`newModelApiKey`,className:`text-xs`,children:`API Key`}),(0,O.jsx)(m,{id:`newModelApiKey`,type:L?`text`:`password`,value:U.apiKey||``,onChange:e=>W({...U,apiKey:e.target.value}),placeholder:`输入 API Key`,className:`h-8 text-sm`})]}),(0,O.jsxs)(`div`,{className:A,children:[(0,O.jsx)(v,{htmlFor:`newModelModel`,className:`text-xs`,children:`模型`}),(0,O.jsx)(m,{id:`newModelModel`,value:U.model||``,onChange:e=>W({...U,model:e.target.value}),placeholder:`模型名称`,className:`h-8 text-sm`})]}),(0,O.jsxs)(`div`,{className:A,children:[(0,O.jsx)(v,{htmlFor:`newModelBaseUrl`,className:`text-xs`,children:`API 端点`}),(0,O.jsx)(m,{id:`newModelBaseUrl`,value:U.baseUrl||``,onChange:e=>W({...U,baseUrl:e.target.value}),placeholder:`API 端点`,className:`h-8 text-sm`})]}),(0,O.jsxs)(`div`,{className:`flex justify-end gap-2 pt-2`,children:[(0,O.jsx)(r,{variant:`outline`,size:`sm`,onClick:()=>W(null),className:`h-7 text-xs`,children:`取消`}),(0,O.jsxs)(r,{size:`sm`,onClick:()=>{U.name&&U.apiKey&&U.model&&U.baseUrl&&(I(fe(F,U)),W(null))},disabled:!U.name||!U.apiKey||!U.model||!U.baseUrl,className:`h-7 text-xs`,children:[(0,O.jsx)(s,{className:`h-3 w-3 mr-1`}),`添加`]})]})]})]}),(0,O.jsx)(S,{}),(0,O.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,O.jsx)(v,{className:`text-sm`,children:`传统配置(向后兼容)`}),(0,O.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`如果未配置多模型,将使用此配置`})]}),(0,O.jsxs)(`div`,{className:A,children:[(0,O.jsx)(v,{className:`text-xs`,children:`AI 服务商`}),(0,O.jsxs)(h,{type:`single`,value:F.provider,onValueChange:e=>{(e===`openai`||e===`anthropic`)&&nt(e)},variant:`outline`,size:`sm`,spacing:0,children:[(0,O.jsx)(y,{value:`openai`,children:`OpenAI`}),(0,O.jsx)(y,{value:`anthropic`,children:`Anthropic`})]})]}),(0,O.jsxs)(`div`,{className:A,children:[(0,O.jsx)(v,{htmlFor:`apiKey`,className:`text-xs`,children:`API Key`}),(0,O.jsxs)(`div`,{className:`flex gap-2`,children:[(0,O.jsx)(m,{id:`apiKey`,type:L?`text`:`password`,value:F.apiKey,onChange:e=>I({...F,apiKey:e.target.value}),placeholder:`输入 API Key`,className:`flex-1 h-8 text-sm`}),(0,O.jsx)(r,{variant:`outline`,size:`icon`,onClick:()=>We(!L),className:`h-8 w-8`,children:L?(0,O.jsx)(Fe,{className:`h-4 w-4`}):(0,O.jsx)(Ie,{className:`h-4 w-4`})})]})]}),(0,O.jsxs)(`div`,{className:A,children:[(0,O.jsx)(v,{htmlFor:`model`,className:`text-xs`,children:`模型`}),(0,O.jsx)(m,{id:`model`,value:F.model,onChange:e=>I({...F,model:e.target.value}),placeholder:`模型名称`,className:`h-8 text-sm`})]}),(0,O.jsxs)(`div`,{className:A,children:[(0,O.jsx)(v,{htmlFor:`baseUrl`,className:`text-xs`,children:`API 端点`}),(0,O.jsx)(m,{id:`baseUrl`,value:F.baseUrl,onChange:e=>I({...F,baseUrl:e.target.value}),placeholder:F.provider===`openai`?`https://api.openai.com/v1/chat/completions`:`https://api.anthropic.com/v1/messages`,className:`h-8 text-sm`})]}),Ge&&(0,O.jsxs)(Pe,{variant:B===`error`?`destructive`:`default`,children:[B===`success`?(0,O.jsx)(w,{}):B===`error`?(0,O.jsx)(o,{}):(0,O.jsx)(a,{}),(0,O.jsx)(Ne,{children:B===`success`?`操作成功`:B===`error`?`操作失败`:`处理中`}),(0,O.jsx)(Me,{children:Ge})]}),(0,O.jsx)(S,{}),(0,O.jsxs)(`div`,{className:`flex justify-between`,children:[(0,O.jsxs)(r,{variant:`outline`,size:`sm`,onClick:it,children:[(0,O.jsx)(te,{className:`h-4 w-4 mr-1`}),`重置`]}),(0,O.jsxs)(`div`,{className:`flex gap-2`,children:[(0,O.jsx)(r,{variant:`outline`,size:`sm`,onClick:at,disabled:!d(F)||R,children:`测试连接`}),(0,O.jsxs)(C,{size:`sm`,onClick:rt,disabled:R,children:[(0,O.jsx)(p,{"data-icon":`inline-start`,className:`h-4 w-4`}),R?`保存中...`:`保存`]})]})]})]})]})]});return n?(0,O.jsx)(`div`,{className:`flex h-full min-h-0 flex-col`,children:$}):(0,O.jsx)(Te,{open:e,onOpenChange:t,children:(0,O.jsx)(we,{className:`p-0 flex flex-col`,resizable:!0,defaultWidth:600,storageKey:`settings-panel`,children:$})})}export{Be as SettingsPanel};