@samanhappy/mcphub 1.0.39 → 1.0.40

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/dist/betterAuth.js +23 -0
  2. package/dist/betterAuth.js.map +1 -1
  3. package/dist/controllers/smartRoutingController.js +408 -0
  4. package/dist/controllers/smartRoutingController.js.map +1 -0
  5. package/dist/dao/CredentialBindingDao.js +5 -0
  6. package/dist/dao/CredentialBindingDao.js.map +1 -1
  7. package/dist/dao/CredentialBindingDaoDbImpl.js +7 -0
  8. package/dist/dao/CredentialBindingDaoDbImpl.js.map +1 -1
  9. package/dist/db/connection.js +38 -11
  10. package/dist/db/connection.js.map +1 -1
  11. package/dist/db/groupSchema.js +2 -2
  12. package/dist/db/groupSchema.js.map +1 -1
  13. package/dist/db/repositories/ActivityRepository.js +2 -2
  14. package/dist/db/repositories/ActivityRepository.js.map +1 -1
  15. package/dist/db/repositories/BaseRepository.js +4 -1
  16. package/dist/db/repositories/BaseRepository.js.map +1 -1
  17. package/dist/db/repositories/BearerKeyRepository.js +3 -1
  18. package/dist/db/repositories/BearerKeyRepository.js.map +1 -1
  19. package/dist/db/repositories/BuiltinPromptRepository.js +2 -2
  20. package/dist/db/repositories/BuiltinPromptRepository.js.map +1 -1
  21. package/dist/db/repositories/BuiltinResourceRepository.js +2 -2
  22. package/dist/db/repositories/BuiltinResourceRepository.js.map +1 -1
  23. package/dist/db/repositories/GroupRepository.js +2 -2
  24. package/dist/db/repositories/GroupRepository.js.map +1 -1
  25. package/dist/db/repositories/OAuthClientRepository.js +2 -2
  26. package/dist/db/repositories/OAuthClientRepository.js.map +1 -1
  27. package/dist/db/repositories/OAuthTokenRepository.js +3 -1
  28. package/dist/db/repositories/OAuthTokenRepository.js.map +1 -1
  29. package/dist/db/repositories/ServerRepository.js +2 -2
  30. package/dist/db/repositories/ServerRepository.js.map +1 -1
  31. package/dist/db/repositories/UserConfigRepository.js +2 -2
  32. package/dist/db/repositories/UserConfigRepository.js.map +1 -1
  33. package/dist/db/repositories/UserRepository.js +3 -1
  34. package/dist/db/repositories/UserRepository.js.map +1 -1
  35. package/dist/middlewares/auth.js +1 -1
  36. package/dist/middlewares/auth.js.map +1 -1
  37. package/dist/middlewares/index.js +8 -1
  38. package/dist/middlewares/index.js.map +1 -1
  39. package/dist/routes/index.js +4 -0
  40. package/dist/routes/index.js.map +1 -1
  41. package/dist/services/mcpOAuthProvider.js +7 -0
  42. package/dist/services/mcpOAuthProvider.js.map +1 -1
  43. package/dist/services/mcpService.js +93 -18
  44. package/dist/services/mcpService.js.map +1 -1
  45. package/dist/services/principalRuntimeService.js +1 -3
  46. package/dist/services/principalRuntimeService.js.map +1 -1
  47. package/dist/services/vectorSearchService.js +17 -7
  48. package/dist/services/vectorSearchService.js.map +1 -1
  49. package/dist/utils/serialization.js +14 -2
  50. package/dist/utils/serialization.js.map +1 -1
  51. package/dist/utils/serverConfigPersistence.js +12 -0
  52. package/dist/utils/serverConfigPersistence.js.map +1 -1
  53. package/dist/utils/upstreamError.js +60 -0
  54. package/dist/utils/upstreamError.js.map +1 -0
  55. package/dist/utils/withTimeout.js +25 -0
  56. package/dist/utils/withTimeout.js.map +1 -0
  57. package/frontend/dist/assets/{ActivityPage-CDKSVr2I.js → ActivityPage-B5DanW8q.js} +2 -2
  58. package/frontend/dist/assets/{ActivityPage-CDKSVr2I.js.map → ActivityPage-B5DanW8q.js.map} +1 -1
  59. package/frontend/dist/assets/CopyClientConfigDialog-C6U6_eyy.js +4 -0
  60. package/frontend/dist/assets/CopyClientConfigDialog-C6U6_eyy.js.map +1 -0
  61. package/frontend/dist/assets/{CredentialsPage-DMJE4uT2.js → CredentialsPage-CXK8Xkao.js} +2 -2
  62. package/frontend/dist/assets/{CredentialsPage-DMJE4uT2.js.map → CredentialsPage-CXK8Xkao.js.map} +1 -1
  63. package/frontend/dist/assets/{Dashboard-Dh_39img.js → Dashboard-LIC6BqIA.js} +2 -2
  64. package/frontend/dist/assets/{Dashboard-Dh_39img.js.map → Dashboard-LIC6BqIA.js.map} +1 -1
  65. package/frontend/dist/assets/{EndpointCopy-CQmwGXbD.js → EndpointCopy-CeZbEsF2.js} +2 -2
  66. package/frontend/dist/assets/{EndpointCopy-CQmwGXbD.js.map → EndpointCopy-CeZbEsF2.js.map} +1 -1
  67. package/frontend/dist/assets/{GroupsPage-BqscWSfR.js → GroupsPage-DwVaRIap.js} +2 -2
  68. package/frontend/dist/assets/{GroupsPage-BqscWSfR.js.map → GroupsPage-DwVaRIap.js.map} +1 -1
  69. package/frontend/dist/assets/{LoginPage-DcrwvgS6.js → LoginPage-CPqSMwWO.js} +2 -2
  70. package/frontend/dist/assets/{LoginPage-DcrwvgS6.js.map → LoginPage-CPqSMwWO.js.map} +1 -1
  71. package/frontend/dist/assets/{LogsPage--Blkr-Ni.js → LogsPage-eCHGem9T.js} +2 -2
  72. package/frontend/dist/assets/{LogsPage--Blkr-Ni.js.map → LogsPage-eCHGem9T.js.map} +1 -1
  73. package/frontend/dist/assets/{MarketPage-DWv18j4V.js → MarketPage-RqD2-rxq.js} +2 -2
  74. package/frontend/dist/assets/{MarketPage-DWv18j4V.js.map → MarketPage-RqD2-rxq.js.map} +1 -1
  75. package/frontend/dist/assets/{OAuthConsentPage-DCKZIMzE.js → OAuthConsentPage-DJITYpCM.js} +2 -2
  76. package/frontend/dist/assets/{OAuthConsentPage-DCKZIMzE.js.map → OAuthConsentPage-DJITYpCM.js.map} +1 -1
  77. package/frontend/dist/assets/{PromptsPage-DoVmnVnp.js → PromptsPage-DQ02iDOJ.js} +2 -2
  78. package/frontend/dist/assets/{PromptsPage-DoVmnVnp.js.map → PromptsPage-DQ02iDOJ.js.map} +1 -1
  79. package/frontend/dist/assets/{ResourcesPage-B8udCQQR.js → ResourcesPage-mUU0DVus.js} +2 -2
  80. package/frontend/dist/assets/{ResourcesPage-B8udCQQR.js.map → ResourcesPage-mUU0DVus.js.map} +1 -1
  81. package/frontend/dist/assets/ServersPage-DsS8j6tl.js +39 -0
  82. package/frontend/dist/assets/ServersPage-DsS8j6tl.js.map +1 -0
  83. package/frontend/dist/assets/SettingsPage-CIeF1sDE.js +12 -0
  84. package/frontend/dist/assets/SettingsPage-CIeF1sDE.js.map +1 -0
  85. package/frontend/dist/assets/{StatusDot-DgDU3plH.js → StatusDot-Bcv2BwIL.js} +2 -2
  86. package/frontend/dist/assets/{StatusDot-DgDU3plH.js.map → StatusDot-Bcv2BwIL.js.map} +1 -1
  87. package/frontend/dist/assets/{ToggleGroup-11yhmcwY.js → ToggleGroup-C_7sDUlr.js} +2 -2
  88. package/frontend/dist/assets/{ToggleGroup-11yhmcwY.js.map → ToggleGroup-C_7sDUlr.js.map} +1 -1
  89. package/frontend/dist/assets/{UsersPage-BqPEkoIX.js → UsersPage-ufaG2-Ag.js} +2 -2
  90. package/frontend/dist/assets/{UsersPage-BqPEkoIX.js.map → UsersPage-ufaG2-Ag.js.map} +1 -1
  91. package/frontend/dist/assets/{icons-vendor-Bk5sng-h.js → icons-vendor-CNEaJWqW.js} +78 -63
  92. package/frontend/dist/assets/icons-vendor-CNEaJWqW.js.map +1 -0
  93. package/frontend/dist/assets/index-C8aAOWR7.js +3 -0
  94. package/frontend/dist/assets/{index-DhzWX9nb.js.map → index-C8aAOWR7.js.map} +1 -1
  95. package/frontend/dist/assets/{resourceService-D-PRt7tB.js → resourceService-CN5cMjQ0.js} +2 -2
  96. package/frontend/dist/assets/{resourceService-D-PRt7tB.js.map → resourceService-CN5cMjQ0.js.map} +1 -1
  97. package/frontend/dist/assets/{useCostData-B-uSfiuA.js → useCostData-B9XzWVsV.js} +2 -2
  98. package/frontend/dist/assets/{useCostData-B-uSfiuA.js.map → useCostData-B9XzWVsV.js.map} +1 -1
  99. package/frontend/dist/assets/useSettingsData-J_hwKZA6.js +2 -0
  100. package/frontend/dist/assets/{useSettingsData-Bk1AwN5F.js.map → useSettingsData-J_hwKZA6.js.map} +1 -1
  101. package/frontend/dist/assets/{variableDetection-B7Ko56CL.js → variableDetection-Dxw0g2ON.js} +3 -3
  102. package/frontend/dist/assets/variableDetection-Dxw0g2ON.js.map +1 -0
  103. package/frontend/dist/index.html +2 -2
  104. package/package.json +1 -1
  105. package/frontend/dist/assets/CopyClientConfigDialog-DYiucK0d.js +0 -4
  106. package/frontend/dist/assets/CopyClientConfigDialog-DYiucK0d.js.map +0 -1
  107. package/frontend/dist/assets/ServersPage-OLpH1K1I.js +0 -39
  108. package/frontend/dist/assets/ServersPage-OLpH1K1I.js.map +0 -1
  109. package/frontend/dist/assets/SettingsPage-DlK0Jcta.js +0 -12
  110. package/frontend/dist/assets/SettingsPage-DlK0Jcta.js.map +0 -1
  111. package/frontend/dist/assets/icons-vendor-Bk5sng-h.js.map +0 -1
  112. package/frontend/dist/assets/index-DhzWX9nb.js +0 -3
  113. package/frontend/dist/assets/useSettingsData-Bk1AwN5F.js +0 -2
  114. package/frontend/dist/assets/variableDetection-B7Ko56CL.js.map +0 -1
@@ -1,2 +1,2 @@
1
- import{r,j as e}from"./framework-vendor-_YL27Pfc.js";import{r as ee,t as te,v as ae,w as se,x as le}from"./index-DhzWX9nb.js";import{P as re}from"./Pagination-CLUvn47x.js";import{u as ie}from"./i18n-vendor-BMaj5qV8.js";import"./icons-vendor-Bk5sng-h.js";const I=["success","error"],ce=a=>I.includes(a),he=()=>{const{t:a}=ie(),[m,V]=r.useState([]),[n,$]=r.useState(null),[l,J]=r.useState(null),[i,U]=r.useState(null),[o,d]=r.useState(1),[j,G]=r.useState(10),[f,A]=r.useState(!0),[F,N]=r.useState(null),[c,H]=r.useState(null),[K,R]=r.useState(!1),[B,D]=r.useState({}),[p,w]=r.useState(""),[v,k]=r.useState(""),[x,S]=r.useState(""),[g,C]=r.useState(""),[y,L]=r.useState(""),[b,P]=r.useState(""),z=r.useCallback(async()=>{A(!0),N(null);try{const t={...B},[s,u,h]=await Promise.all([ee(o,j,t),te(t),ae()]);s!=null&&s.success&&Array.isArray(s.data)&&(V(s.data),s.pagination&&U(s.pagination)),u!=null&&u.success&&u.data&&$(u.data),h!=null&&h.success&&h.data&&J(h.data)}catch(t){console.error("Error fetching activity data:",t),N(a("activity.fetchError"))}finally{A(!1)}},[o,j,B,a]);r.useEffect(()=>{z()},[z]),r.useEffect(()=>{if(!i)return;const t=Math.max(1,i.totalPages||1);o>t&&d(t)},[i,o]);const W=async t=>{try{const s=await le(t.id);s!=null&&s.success&&s.data&&(H(s.data),R(!0))}catch(s){console.error("Error fetching activity details:",s)}},_=async()=>{var t;if(window.confirm(a("activity.confirmCleanup")))try{const s=await se(30);s!=null&&s.success&&(alert(a("activity.cleanupSuccess",{count:((t=s.data)==null?void 0:t.deletedCount)||0})),z())}catch(s){console.error("Error cleaning up activities:",s),alert(a("activity.cleanupError"))}},q=()=>{const t={};p&&(t.server=p),v&&(t.tool=v),x&&ce(x)&&(t.status=x),g&&(t.group=g),y&&(t.username=y),b&&(t.keyName=b),D(t),d(1)},O=()=>{w(""),k(""),S(""),C(""),L(""),P(""),D({}),d(1)},M=t=>t<1e3?`${t}ms`:t<6e4?`${(t/1e3).toFixed(2)}s`:`${(t/6e4).toFixed(2)}m`,E=t=>new Date(t).toLocaleString(),T=t=>{if(!t)return null;try{return JSON.parse(t)}catch{return t}},Q=()=>n?e.jsx("div",{className:"grid grid-cols-2 md:grid-cols-4 gap-3 mb-4",children:[{label:a("activity.totalCalls"),value:n.totalCalls,tone:"default"},{label:a("activity.successCount"),value:n.successCount,tone:"ok"},{label:a("activity.errorCount"),value:n.errorCount,tone:"err"},{label:a("activity.avgDuration"),value:M(n.avgDuration),tone:"default"}].map(t=>e.jsxs("div",{className:"hub-card",style:{padding:"12px 14px"},children:[e.jsx("div",{className:"text-[12px]",style:{color:"var(--hub-ink-3)"},children:t.label}),e.jsx("div",{className:"hub-num",style:{fontSize:22,fontWeight:500,lineHeight:1.1,marginTop:6,letterSpacing:"-0.02em",color:t.tone==="ok"?"oklch(0.4 0.13 145)":t.tone==="err"?"oklch(0.45 0.18 25)":"var(--hub-ink)"},children:t.value})]},t.label))}):null,X=()=>e.jsx("div",{className:"hub-card px-4 py-3 mb-4",children:e.jsxs("div",{className:"flex flex-wrap gap-3 items-end",children:[e.jsxs("div",{className:"flex-1 min-w-[140px]",children:[e.jsx("label",{className:"sr-only",htmlFor:"activity-server",children:a("activity.server")}),e.jsxs("div",{className:"relative",children:[e.jsx("input",{id:"activity-server",type:"text",value:p,onChange:t=>w(t.target.value),placeholder:a("activity.searchServer"),className:"hub-input pr-9",list:"server-options"}),p&&e.jsx("button",{onClick:()=>w(""),className:"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300","aria-label":a("common.clear"),type:"button",children:e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",clipRule:"evenodd"})})})]}),(l==null?void 0:l.servers)&&e.jsx("datalist",{id:"server-options",children:l.servers.map(t=>e.jsx("option",{value:t},t))})]}),e.jsxs("div",{className:"flex-1 min-w-[140px]",children:[e.jsx("label",{className:"sr-only",htmlFor:"activity-tool",children:a("activity.tool")}),e.jsxs("div",{className:"relative",children:[e.jsx("input",{id:"activity-tool",type:"text",value:v,onChange:t=>k(t.target.value),placeholder:a("activity.searchTool"),className:"hub-input pr-9",list:"tool-options"}),v&&e.jsx("button",{onClick:()=>k(""),className:"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300","aria-label":a("common.clear"),type:"button",children:e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",clipRule:"evenodd"})})})]}),(l==null?void 0:l.tools)&&e.jsx("datalist",{id:"tool-options",children:l.tools.map(t=>e.jsx("option",{value:t},t))})]}),e.jsxs("div",{className:"flex-1 min-w-[140px]",children:[e.jsx("label",{className:"sr-only",htmlFor:"activity-status",children:a("activity.status")}),e.jsxs("div",{className:"relative",children:[e.jsx("input",{id:"activity-status",type:"text",value:x,onChange:t=>S(t.target.value.toLowerCase()),placeholder:a("activity.searchStatus"),className:"hub-input pr-9",list:"activity-status-options"}),x&&e.jsx("button",{onClick:()=>S(""),className:"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300","aria-label":a("common.clear"),type:"button",children:e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",clipRule:"evenodd"})})})]}),e.jsx("datalist",{id:"activity-status-options",children:I.map(t=>e.jsx("option",{value:t},t))})]}),e.jsxs("div",{className:"flex-1 min-w-[140px]",children:[e.jsx("label",{className:"sr-only",htmlFor:"activity-group",children:a("activity.group")}),e.jsxs("div",{className:"relative",children:[e.jsx("input",{id:"activity-group",type:"text",value:g,onChange:t=>C(t.target.value),placeholder:a("activity.searchGroup"),className:"hub-input pr-9",list:"group-options"}),g&&e.jsx("button",{onClick:()=>C(""),className:"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300","aria-label":a("common.clear"),type:"button",children:e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",clipRule:"evenodd"})})})]}),(l==null?void 0:l.groups)&&e.jsx("datalist",{id:"group-options",children:l.groups.map(t=>e.jsx("option",{value:t},t))})]}),e.jsxs("div",{className:"flex-1 min-w-[140px]",children:[e.jsx("label",{className:"sr-only",htmlFor:"activity-username",children:a("activity.user")}),e.jsxs("div",{className:"relative",children:[e.jsx("input",{id:"activity-username",type:"text",value:y,onChange:t=>L(t.target.value),placeholder:a("activity.searchUsername"),className:"hub-input pr-9",list:"username-options"}),y&&e.jsx("button",{onClick:()=>L(""),className:"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300","aria-label":a("common.clear"),type:"button",children:e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",clipRule:"evenodd"})})})]}),(l==null?void 0:l.usernames)&&e.jsx("datalist",{id:"username-options",children:l.usernames.map(t=>e.jsx("option",{value:t},t))})]}),e.jsxs("div",{className:"flex-1 min-w-[140px]",children:[e.jsx("label",{className:"sr-only",htmlFor:"activity-keyname",children:a("activity.keyName")}),e.jsxs("div",{className:"relative",children:[e.jsx("input",{id:"activity-keyname",type:"text",value:b,onChange:t=>P(t.target.value),placeholder:a("activity.searchKeyName"),className:"hub-input pr-9",list:"keyname-options"}),b&&e.jsx("button",{onClick:()=>P(""),className:"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300","aria-label":a("common.clear"),type:"button",children:e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",clipRule:"evenodd"})})})]}),(l==null?void 0:l.keyNames)&&e.jsx("datalist",{id:"keyname-options",children:l.keyNames.map(t=>e.jsx("option",{value:t},t))})]}),e.jsxs("div",{className:"flex-shrink-0 flex items-center gap-2",children:[e.jsxs("button",{onClick:q,className:"hub-btn primary whitespace-nowrap",children:[e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-3.5 w-3.5",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z",clipRule:"evenodd"})}),a("common.search")]}),e.jsx("button",{onClick:O,className:"hub-btn whitespace-nowrap",children:a("common.clear")})]})]})}),Y=()=>m.length===0?e.jsx("div",{className:"hub-card p-10 text-center",style:{color:"var(--hub-ink-3)"},children:a("activity.noData")}):e.jsx("div",{className:"hub-card overflow-hidden",children:e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"min-w-full",children:[e.jsx("thead",{style:{background:"var(--hub-bg-2)"},children:e.jsx("tr",{children:[a("activity.timestamp"),a("activity.server"),a("activity.tool"),a("activity.duration"),a("activity.status"),a("activity.group"),a("activity.user"),a("activity.key"),a("activity.sourceIp"),a("common.actions")].map(t=>e.jsx("th",{className:"hub-mono",style:{padding:"9px 14px",textAlign:"left",fontSize:11,color:"var(--hub-ink-3)",textTransform:"uppercase",letterSpacing:"0.08em",fontWeight:500},children:t},t))})}),e.jsx("tbody",{children:m.map(t=>e.jsxs("tr",{className:"transition-colors hover:bg-[var(--hub-surface-hover)]",style:{borderTop:"1px solid var(--hub-line-2)"},children:[e.jsx("td",{className:"hub-mono whitespace-nowrap",style:{padding:"10px 14px",fontSize:12,color:"var(--hub-ink-2)"},children:E(t.timestamp)}),e.jsx("td",{style:{padding:"10px 14px"},children:e.jsx("span",{className:"hub-tag",children:t.server})}),e.jsx("td",{style:{padding:"10px 14px"},children:e.jsx("span",{className:"hub-tag accent",children:t.tool})}),e.jsx("td",{className:"hub-mono hub-num whitespace-nowrap",style:{padding:"10px 14px",fontSize:12,color:"var(--hub-ink-2)"},children:M(t.duration)}),e.jsx("td",{style:{padding:"10px 14px"},className:"whitespace-nowrap",children:e.jsxs("span",{className:`hub-status ${t.status==="success"?"ok":"err"}`,children:[e.jsx("span",{className:"hub-dot"}),t.status==="success"?a("activity.statusSuccess"):a("activity.statusError")]})}),e.jsx("td",{style:{padding:"10px 14px",fontSize:12,color:"var(--hub-ink-3)"},children:t.group||"—"}),e.jsx("td",{style:{padding:"10px 14px",fontSize:12,color:"var(--hub-ink-3)"},children:t.username||"—"}),e.jsx("td",{style:{padding:"10px 14px",fontSize:12,color:"var(--hub-ink-3)"},children:t.keyName||"—"}),e.jsx("td",{className:"hub-mono whitespace-nowrap",style:{padding:"10px 14px",fontSize:12,color:"var(--hub-ink-3)"},children:t.sourceIp||"—"}),e.jsx("td",{style:{padding:"10px 14px"},children:e.jsx("button",{onClick:()=>W(t),className:"hub-btn ghost sm",style:{color:"var(--hub-accent)"},children:a("common.view")})})]},t.id))})]})})}),Z=()=>{if(!K||!c)return null;const t=T(c.input),s=T(c.output);return e.jsx("div",{className:"fixed inset-0 bg-black/50 flex items-center justify-center z-50",children:e.jsxs("div",{className:"hub-card max-w-4xl w-full mx-4 max-h-[90vh] overflow-hidden",style:{boxShadow:"0 8px 24px rgba(0,0,0,0.12)"},children:[e.jsxs("div",{className:"flex items-center justify-between px-5 py-3",style:{borderBottom:"1px solid var(--hub-line-2)"},children:[e.jsx("h3",{className:"hub-card-title",children:a("activity.details")}),e.jsx("button",{onClick:()=>R(!1),className:"hub-icon-btn sm","aria-label":"close",children:e.jsx("svg",{className:"h-3.5 w-3.5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})})})]}),e.jsxs("div",{className:"px-6 py-4 overflow-y-auto max-h-[calc(90vh-120px)]",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-4 mb-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.timestamp")}),e.jsx("p",{className:"text-gray-900 dark:text-white",children:E(c.timestamp)})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.duration")}),e.jsx("p",{className:"text-gray-900 dark:text-white",children:M(c.duration)})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.server")}),e.jsx("p",{className:"text-gray-900 dark:text-white font-mono",children:c.server})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.tool")}),e.jsx("p",{className:"text-gray-900 dark:text-white font-mono",children:c.tool})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.status")}),e.jsx("span",{className:`px-2 py-1 rounded text-xs font-medium ${c.status==="success"?"bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200":"bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200"}`,children:c.status==="success"?a("activity.statusSuccess"):a("activity.statusError")})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.group")}),e.jsx("p",{className:"text-gray-900 dark:text-white",children:c.group||"-"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.user")}),e.jsx("p",{className:"text-gray-900 dark:text-white",children:c.username||"-"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.sourceIp")}),e.jsx("p",{className:"text-gray-900 dark:text-white font-mono",children:c.sourceIp||"-"})]}),c.keyName&&e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.key")}),e.jsx("p",{className:"text-gray-900 dark:text-white",children:c.keyName})]})]}),c.errorMessage&&e.jsxs("div",{className:"mb-4",children:[e.jsx("label",{className:"block text-sm font-medium text-red-500 mb-1",children:a("activity.errorMessage")}),e.jsx("div",{className:"bg-red-50 dark:bg-red-900/20 rounded p-3 text-sm text-red-800 dark:text-red-200",children:c.errorMessage})]}),t&&e.jsxs("div",{className:"mb-4",children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400 mb-1",children:a("activity.input")}),e.jsx("pre",{className:"bg-gray-100 dark:bg-gray-700 rounded p-3 text-sm overflow-x-auto max-h-64",children:typeof t=="string"?t:JSON.stringify(t,null,2)})]}),s&&e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400 mb-1",children:a("activity.output")}),e.jsx("pre",{className:"bg-gray-100 dark:bg-gray-700 rounded p-3 text-sm overflow-x-auto max-h-64",children:typeof s=="string"?s:JSON.stringify(s,null,2)})]})]})]})})};return e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-end justify-between gap-4 mb-6",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"hub-h1",children:a("activity.title")}),e.jsxs("p",{className:"hub-sub",children:[e.jsx("span",{className:"hub-num",children:(i==null?void 0:i.total)??m.length})," entries"]})]}),e.jsxs("button",{onClick:_,className:"hub-btn danger",children:[e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-3.5 w-3.5",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M9 2a1 1 0 00-.894.553L7.382 4H4a1 1 0 000 2v10a2 2 0 002 2h8a2 2 0 002-2V6a1 1 0 100-2h-3.382l-.724-1.447A1 1 0 0011 2H9zM7 8a1 1 0 012 0v6a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v6a1 1 0 102 0V8a1 1 0 00-1-1z",clipRule:"evenodd"})}),a("activity.cleanup")]})]}),F&&e.jsxs("div",{className:"hub-card flex items-center justify-between gap-3 mb-4",style:{padding:"10px 14px",borderColor:"oklch(0.85 0.1 25)",background:"oklch(0.97 0.03 25)",color:"oklch(0.4 0.18 25)"},children:[e.jsx("span",{className:"truncate text-[13px]",children:F}),e.jsx("button",{className:"hub-icon-btn sm",onClick:()=>N(null),"aria-label":"close",children:e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-3 w-3",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",clipRule:"evenodd"})})})]}),f&&m.length===0?e.jsx("div",{className:"hub-card p-10 text-center",style:{color:"var(--hub-ink-3)"},children:a("app.loading")}):e.jsxs(e.Fragment,{children:[Q(),X(),Y(),e.jsxs("div",{className:"flex items-center mt-6",children:[e.jsx("div",{className:"flex-[2] text-sm text-gray-500 dark:text-gray-400",children:i&&a("common.showing",{start:(i.page-1)*i.limit+1,end:Math.min(i.page*i.limit,i.total),total:i.total})}),e.jsx("div",{className:"flex-[4] flex justify-center",children:i&&i.totalPages>1&&e.jsx(re,{currentPage:o,totalPages:i.totalPages,onPageChange:d,disabled:f})}),e.jsxs("div",{className:"flex-[2] flex items-center justify-end space-x-2",children:[e.jsxs("label",{htmlFor:"perPage",className:"text-sm text-gray-500 dark:text-gray-400",children:[a("common.itemsPerPage"),":"]}),e.jsxs("select",{id:"perPage",value:j,onChange:t=>{G(Number(t.target.value)),d(1)},disabled:f,className:"border border-gray-300 dark:border-gray-600 rounded p-1 text-sm dark:bg-gray-700 dark:text-white outline-none disabled:opacity-50 disabled:cursor-not-allowed",children:[e.jsx("option",{value:10,children:"10"}),e.jsx("option",{value:20,children:"20"}),e.jsx("option",{value:50,children:"50"}),e.jsx("option",{value:100,children:"100"})]})]})]})]}),Z()]})};export{he as default};
2
- //# sourceMappingURL=ActivityPage-CDKSVr2I.js.map
1
+ import{r,j as e}from"./framework-vendor-_YL27Pfc.js";import{t as ee,v as te,w as ae,x as se,y as le}from"./index-C8aAOWR7.js";import{P as re}from"./Pagination-CLUvn47x.js";import{u as ie}from"./i18n-vendor-BMaj5qV8.js";import"./icons-vendor-CNEaJWqW.js";const I=["success","error"],ce=a=>I.includes(a),he=()=>{const{t:a}=ie(),[m,V]=r.useState([]),[n,$]=r.useState(null),[l,J]=r.useState(null),[i,U]=r.useState(null),[o,d]=r.useState(1),[j,G]=r.useState(10),[f,A]=r.useState(!0),[F,N]=r.useState(null),[c,H]=r.useState(null),[K,R]=r.useState(!1),[B,D]=r.useState({}),[p,w]=r.useState(""),[v,k]=r.useState(""),[x,S]=r.useState(""),[g,C]=r.useState(""),[y,L]=r.useState(""),[b,P]=r.useState(""),z=r.useCallback(async()=>{A(!0),N(null);try{const t={...B},[s,u,h]=await Promise.all([ee(o,j,t),te(t),ae()]);s!=null&&s.success&&Array.isArray(s.data)&&(V(s.data),s.pagination&&U(s.pagination)),u!=null&&u.success&&u.data&&$(u.data),h!=null&&h.success&&h.data&&J(h.data)}catch(t){console.error("Error fetching activity data:",t),N(a("activity.fetchError"))}finally{A(!1)}},[o,j,B,a]);r.useEffect(()=>{z()},[z]),r.useEffect(()=>{if(!i)return;const t=Math.max(1,i.totalPages||1);o>t&&d(t)},[i,o]);const W=async t=>{try{const s=await le(t.id);s!=null&&s.success&&s.data&&(H(s.data),R(!0))}catch(s){console.error("Error fetching activity details:",s)}},_=async()=>{var t;if(window.confirm(a("activity.confirmCleanup")))try{const s=await se(30);s!=null&&s.success&&(alert(a("activity.cleanupSuccess",{count:((t=s.data)==null?void 0:t.deletedCount)||0})),z())}catch(s){console.error("Error cleaning up activities:",s),alert(a("activity.cleanupError"))}},q=()=>{const t={};p&&(t.server=p),v&&(t.tool=v),x&&ce(x)&&(t.status=x),g&&(t.group=g),y&&(t.username=y),b&&(t.keyName=b),D(t),d(1)},O=()=>{w(""),k(""),S(""),C(""),L(""),P(""),D({}),d(1)},M=t=>t<1e3?`${t}ms`:t<6e4?`${(t/1e3).toFixed(2)}s`:`${(t/6e4).toFixed(2)}m`,E=t=>new Date(t).toLocaleString(),T=t=>{if(!t)return null;try{return JSON.parse(t)}catch{return t}},Q=()=>n?e.jsx("div",{className:"grid grid-cols-2 md:grid-cols-4 gap-3 mb-4",children:[{label:a("activity.totalCalls"),value:n.totalCalls,tone:"default"},{label:a("activity.successCount"),value:n.successCount,tone:"ok"},{label:a("activity.errorCount"),value:n.errorCount,tone:"err"},{label:a("activity.avgDuration"),value:M(n.avgDuration),tone:"default"}].map(t=>e.jsxs("div",{className:"hub-card",style:{padding:"12px 14px"},children:[e.jsx("div",{className:"text-[12px]",style:{color:"var(--hub-ink-3)"},children:t.label}),e.jsx("div",{className:"hub-num",style:{fontSize:22,fontWeight:500,lineHeight:1.1,marginTop:6,letterSpacing:"-0.02em",color:t.tone==="ok"?"oklch(0.4 0.13 145)":t.tone==="err"?"oklch(0.45 0.18 25)":"var(--hub-ink)"},children:t.value})]},t.label))}):null,X=()=>e.jsx("div",{className:"hub-card px-4 py-3 mb-4",children:e.jsxs("div",{className:"flex flex-wrap gap-3 items-end",children:[e.jsxs("div",{className:"flex-1 min-w-[140px]",children:[e.jsx("label",{className:"sr-only",htmlFor:"activity-server",children:a("activity.server")}),e.jsxs("div",{className:"relative",children:[e.jsx("input",{id:"activity-server",type:"text",value:p,onChange:t=>w(t.target.value),placeholder:a("activity.searchServer"),className:"hub-input pr-9",list:"server-options"}),p&&e.jsx("button",{onClick:()=>w(""),className:"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300","aria-label":a("common.clear"),type:"button",children:e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",clipRule:"evenodd"})})})]}),(l==null?void 0:l.servers)&&e.jsx("datalist",{id:"server-options",children:l.servers.map(t=>e.jsx("option",{value:t},t))})]}),e.jsxs("div",{className:"flex-1 min-w-[140px]",children:[e.jsx("label",{className:"sr-only",htmlFor:"activity-tool",children:a("activity.tool")}),e.jsxs("div",{className:"relative",children:[e.jsx("input",{id:"activity-tool",type:"text",value:v,onChange:t=>k(t.target.value),placeholder:a("activity.searchTool"),className:"hub-input pr-9",list:"tool-options"}),v&&e.jsx("button",{onClick:()=>k(""),className:"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300","aria-label":a("common.clear"),type:"button",children:e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",clipRule:"evenodd"})})})]}),(l==null?void 0:l.tools)&&e.jsx("datalist",{id:"tool-options",children:l.tools.map(t=>e.jsx("option",{value:t},t))})]}),e.jsxs("div",{className:"flex-1 min-w-[140px]",children:[e.jsx("label",{className:"sr-only",htmlFor:"activity-status",children:a("activity.status")}),e.jsxs("div",{className:"relative",children:[e.jsx("input",{id:"activity-status",type:"text",value:x,onChange:t=>S(t.target.value.toLowerCase()),placeholder:a("activity.searchStatus"),className:"hub-input pr-9",list:"activity-status-options"}),x&&e.jsx("button",{onClick:()=>S(""),className:"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300","aria-label":a("common.clear"),type:"button",children:e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",clipRule:"evenodd"})})})]}),e.jsx("datalist",{id:"activity-status-options",children:I.map(t=>e.jsx("option",{value:t},t))})]}),e.jsxs("div",{className:"flex-1 min-w-[140px]",children:[e.jsx("label",{className:"sr-only",htmlFor:"activity-group",children:a("activity.group")}),e.jsxs("div",{className:"relative",children:[e.jsx("input",{id:"activity-group",type:"text",value:g,onChange:t=>C(t.target.value),placeholder:a("activity.searchGroup"),className:"hub-input pr-9",list:"group-options"}),g&&e.jsx("button",{onClick:()=>C(""),className:"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300","aria-label":a("common.clear"),type:"button",children:e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",clipRule:"evenodd"})})})]}),(l==null?void 0:l.groups)&&e.jsx("datalist",{id:"group-options",children:l.groups.map(t=>e.jsx("option",{value:t},t))})]}),e.jsxs("div",{className:"flex-1 min-w-[140px]",children:[e.jsx("label",{className:"sr-only",htmlFor:"activity-username",children:a("activity.user")}),e.jsxs("div",{className:"relative",children:[e.jsx("input",{id:"activity-username",type:"text",value:y,onChange:t=>L(t.target.value),placeholder:a("activity.searchUsername"),className:"hub-input pr-9",list:"username-options"}),y&&e.jsx("button",{onClick:()=>L(""),className:"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300","aria-label":a("common.clear"),type:"button",children:e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",clipRule:"evenodd"})})})]}),(l==null?void 0:l.usernames)&&e.jsx("datalist",{id:"username-options",children:l.usernames.map(t=>e.jsx("option",{value:t},t))})]}),e.jsxs("div",{className:"flex-1 min-w-[140px]",children:[e.jsx("label",{className:"sr-only",htmlFor:"activity-keyname",children:a("activity.keyName")}),e.jsxs("div",{className:"relative",children:[e.jsx("input",{id:"activity-keyname",type:"text",value:b,onChange:t=>P(t.target.value),placeholder:a("activity.searchKeyName"),className:"hub-input pr-9",list:"keyname-options"}),b&&e.jsx("button",{onClick:()=>P(""),className:"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300","aria-label":a("common.clear"),type:"button",children:e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",clipRule:"evenodd"})})})]}),(l==null?void 0:l.keyNames)&&e.jsx("datalist",{id:"keyname-options",children:l.keyNames.map(t=>e.jsx("option",{value:t},t))})]}),e.jsxs("div",{className:"flex-shrink-0 flex items-center gap-2",children:[e.jsxs("button",{onClick:q,className:"hub-btn primary whitespace-nowrap",children:[e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-3.5 w-3.5",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z",clipRule:"evenodd"})}),a("common.search")]}),e.jsx("button",{onClick:O,className:"hub-btn whitespace-nowrap",children:a("common.clear")})]})]})}),Y=()=>m.length===0?e.jsx("div",{className:"hub-card p-10 text-center",style:{color:"var(--hub-ink-3)"},children:a("activity.noData")}):e.jsx("div",{className:"hub-card overflow-hidden",children:e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"min-w-full",children:[e.jsx("thead",{style:{background:"var(--hub-bg-2)"},children:e.jsx("tr",{children:[a("activity.timestamp"),a("activity.server"),a("activity.tool"),a("activity.duration"),a("activity.status"),a("activity.group"),a("activity.user"),a("activity.key"),a("activity.sourceIp"),a("common.actions")].map(t=>e.jsx("th",{className:"hub-mono",style:{padding:"9px 14px",textAlign:"left",fontSize:11,color:"var(--hub-ink-3)",textTransform:"uppercase",letterSpacing:"0.08em",fontWeight:500},children:t},t))})}),e.jsx("tbody",{children:m.map(t=>e.jsxs("tr",{className:"transition-colors hover:bg-[var(--hub-surface-hover)]",style:{borderTop:"1px solid var(--hub-line-2)"},children:[e.jsx("td",{className:"hub-mono whitespace-nowrap",style:{padding:"10px 14px",fontSize:12,color:"var(--hub-ink-2)"},children:E(t.timestamp)}),e.jsx("td",{style:{padding:"10px 14px"},children:e.jsx("span",{className:"hub-tag",children:t.server})}),e.jsx("td",{style:{padding:"10px 14px"},children:e.jsx("span",{className:"hub-tag accent",children:t.tool})}),e.jsx("td",{className:"hub-mono hub-num whitespace-nowrap",style:{padding:"10px 14px",fontSize:12,color:"var(--hub-ink-2)"},children:M(t.duration)}),e.jsx("td",{style:{padding:"10px 14px"},className:"whitespace-nowrap",children:e.jsxs("span",{className:`hub-status ${t.status==="success"?"ok":"err"}`,children:[e.jsx("span",{className:"hub-dot"}),t.status==="success"?a("activity.statusSuccess"):a("activity.statusError")]})}),e.jsx("td",{style:{padding:"10px 14px",fontSize:12,color:"var(--hub-ink-3)"},children:t.group||"—"}),e.jsx("td",{style:{padding:"10px 14px",fontSize:12,color:"var(--hub-ink-3)"},children:t.username||"—"}),e.jsx("td",{style:{padding:"10px 14px",fontSize:12,color:"var(--hub-ink-3)"},children:t.keyName||"—"}),e.jsx("td",{className:"hub-mono whitespace-nowrap",style:{padding:"10px 14px",fontSize:12,color:"var(--hub-ink-3)"},children:t.sourceIp||"—"}),e.jsx("td",{style:{padding:"10px 14px"},children:e.jsx("button",{onClick:()=>W(t),className:"hub-btn ghost sm",style:{color:"var(--hub-accent)"},children:a("common.view")})})]},t.id))})]})})}),Z=()=>{if(!K||!c)return null;const t=T(c.input),s=T(c.output);return e.jsx("div",{className:"fixed inset-0 bg-black/50 flex items-center justify-center z-50",children:e.jsxs("div",{className:"hub-card max-w-4xl w-full mx-4 max-h-[90vh] overflow-hidden",style:{boxShadow:"0 8px 24px rgba(0,0,0,0.12)"},children:[e.jsxs("div",{className:"flex items-center justify-between px-5 py-3",style:{borderBottom:"1px solid var(--hub-line-2)"},children:[e.jsx("h3",{className:"hub-card-title",children:a("activity.details")}),e.jsx("button",{onClick:()=>R(!1),className:"hub-icon-btn sm","aria-label":"close",children:e.jsx("svg",{className:"h-3.5 w-3.5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})})})]}),e.jsxs("div",{className:"px-6 py-4 overflow-y-auto max-h-[calc(90vh-120px)]",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-4 mb-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.timestamp")}),e.jsx("p",{className:"text-gray-900 dark:text-white",children:E(c.timestamp)})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.duration")}),e.jsx("p",{className:"text-gray-900 dark:text-white",children:M(c.duration)})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.server")}),e.jsx("p",{className:"text-gray-900 dark:text-white font-mono",children:c.server})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.tool")}),e.jsx("p",{className:"text-gray-900 dark:text-white font-mono",children:c.tool})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.status")}),e.jsx("span",{className:`px-2 py-1 rounded text-xs font-medium ${c.status==="success"?"bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200":"bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200"}`,children:c.status==="success"?a("activity.statusSuccess"):a("activity.statusError")})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.group")}),e.jsx("p",{className:"text-gray-900 dark:text-white",children:c.group||"-"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.user")}),e.jsx("p",{className:"text-gray-900 dark:text-white",children:c.username||"-"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.sourceIp")}),e.jsx("p",{className:"text-gray-900 dark:text-white font-mono",children:c.sourceIp||"-"})]}),c.keyName&&e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:a("activity.key")}),e.jsx("p",{className:"text-gray-900 dark:text-white",children:c.keyName})]})]}),c.errorMessage&&e.jsxs("div",{className:"mb-4",children:[e.jsx("label",{className:"block text-sm font-medium text-red-500 mb-1",children:a("activity.errorMessage")}),e.jsx("div",{className:"bg-red-50 dark:bg-red-900/20 rounded p-3 text-sm text-red-800 dark:text-red-200",children:c.errorMessage})]}),t&&e.jsxs("div",{className:"mb-4",children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400 mb-1",children:a("activity.input")}),e.jsx("pre",{className:"bg-gray-100 dark:bg-gray-700 rounded p-3 text-sm overflow-x-auto max-h-64",children:typeof t=="string"?t:JSON.stringify(t,null,2)})]}),s&&e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-500 dark:text-gray-400 mb-1",children:a("activity.output")}),e.jsx("pre",{className:"bg-gray-100 dark:bg-gray-700 rounded p-3 text-sm overflow-x-auto max-h-64",children:typeof s=="string"?s:JSON.stringify(s,null,2)})]})]})]})})};return e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-end justify-between gap-4 mb-6",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"hub-h1",children:a("activity.title")}),e.jsxs("p",{className:"hub-sub",children:[e.jsx("span",{className:"hub-num",children:(i==null?void 0:i.total)??m.length})," entries"]})]}),e.jsxs("button",{onClick:_,className:"hub-btn danger",children:[e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-3.5 w-3.5",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M9 2a1 1 0 00-.894.553L7.382 4H4a1 1 0 000 2v10a2 2 0 002 2h8a2 2 0 002-2V6a1 1 0 100-2h-3.382l-.724-1.447A1 1 0 0011 2H9zM7 8a1 1 0 012 0v6a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v6a1 1 0 102 0V8a1 1 0 00-1-1z",clipRule:"evenodd"})}),a("activity.cleanup")]})]}),F&&e.jsxs("div",{className:"hub-card flex items-center justify-between gap-3 mb-4",style:{padding:"10px 14px",borderColor:"oklch(0.85 0.1 25)",background:"oklch(0.97 0.03 25)",color:"oklch(0.4 0.18 25)"},children:[e.jsx("span",{className:"truncate text-[13px]",children:F}),e.jsx("button",{className:"hub-icon-btn sm",onClick:()=>N(null),"aria-label":"close",children:e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-3 w-3",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",clipRule:"evenodd"})})})]}),f&&m.length===0?e.jsx("div",{className:"hub-card p-10 text-center",style:{color:"var(--hub-ink-3)"},children:a("app.loading")}):e.jsxs(e.Fragment,{children:[Q(),X(),Y(),e.jsxs("div",{className:"flex items-center mt-6",children:[e.jsx("div",{className:"flex-[2] text-sm text-gray-500 dark:text-gray-400",children:i&&a("common.showing",{start:(i.page-1)*i.limit+1,end:Math.min(i.page*i.limit,i.total),total:i.total})}),e.jsx("div",{className:"flex-[4] flex justify-center",children:i&&i.totalPages>1&&e.jsx(re,{currentPage:o,totalPages:i.totalPages,onPageChange:d,disabled:f})}),e.jsxs("div",{className:"flex-[2] flex items-center justify-end space-x-2",children:[e.jsxs("label",{htmlFor:"perPage",className:"text-sm text-gray-500 dark:text-gray-400",children:[a("common.itemsPerPage"),":"]}),e.jsxs("select",{id:"perPage",value:j,onChange:t=>{G(Number(t.target.value)),d(1)},disabled:f,className:"border border-gray-300 dark:border-gray-600 rounded p-1 text-sm dark:bg-gray-700 dark:text-white outline-none disabled:opacity-50 disabled:cursor-not-allowed",children:[e.jsx("option",{value:10,children:"10"}),e.jsx("option",{value:20,children:"20"}),e.jsx("option",{value:50,children:"50"}),e.jsx("option",{value:100,children:"100"})]})]})]})]}),Z()]})};export{he as default};
2
+ //# sourceMappingURL=ActivityPage-B5DanW8q.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ActivityPage-CDKSVr2I.js","sources":["../../src/pages/ActivityPage.tsx"],"sourcesContent":["import React, { useState, useEffect, useCallback } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport {\n Activity,\n ActivityStats,\n ActivityFilter,\n ActivityFilterOptions,\n ActivityStatus,\n} from '@/types';\nimport {\n getActivities,\n getActivityById,\n getActivityStats,\n getActivityFilterOptions,\n deleteOldActivities,\n} from '@/services/activityService';\nimport Pagination from '@/components/ui/Pagination';\n\n// Pagination info type\ninterface PaginationInfo {\n page: number;\n limit: number;\n total: number;\n totalPages: number;\n hasNextPage: boolean;\n hasPrevPage: boolean;\n}\n\nconst STATUS_OPTIONS: ActivityStatus[] = ['success', 'error'];\n\nconst isValidStatus = (value: string): value is ActivityStatus =>\n STATUS_OPTIONS.includes(value as ActivityStatus);\n\nconst ActivityPage: React.FC = () => {\n const { t } = useTranslation();\n\n // State\n const [activities, setActivities] = useState<Activity[]>([]);\n const [stats, setStats] = useState<ActivityStats | null>(null);\n const [filterOptions, setFilterOptions] = useState<ActivityFilterOptions | null>(null);\n const [pagination, setPagination] = useState<PaginationInfo | null>(null);\n const [currentPage, setCurrentPage] = useState(1);\n const [itemsPerPage, setItemsPerPage] = useState(10);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [selectedActivity, setSelectedActivity] = useState<Activity | null>(null);\n const [showDetailModal, setShowDetailModal] = useState(false);\n\n // Filter state\n const [appliedFilters, setAppliedFilters] = useState<ActivityFilter>({});\n const [searchServer, setSearchServer] = useState('');\n const [searchTool, setSearchTool] = useState('');\n const [searchStatus, setSearchStatus] = useState<string>('');\n const [searchGroup, setSearchGroup] = useState('');\n const [searchUsername, setSearchUsername] = useState('');\n const [searchKeyName, setSearchKeyName] = useState('');\n\n // Fetch data\n const fetchData = useCallback(async () => {\n setIsLoading(true);\n setError(null);\n\n try {\n // Use appliedFilters directly for fetching\n const currentFilter = { ...appliedFilters };\n\n // Fetch activities, stats, and filter options in parallel\n const [activitiesRes, statsRes, optionsRes] = await Promise.all([\n getActivities(currentPage, itemsPerPage, currentFilter),\n getActivityStats(currentFilter),\n getActivityFilterOptions(),\n ]);\n\n if (activitiesRes?.success && Array.isArray(activitiesRes.data)) {\n setActivities(activitiesRes.data);\n if (activitiesRes.pagination) {\n setPagination(activitiesRes.pagination);\n }\n }\n\n if (statsRes?.success && statsRes.data) {\n setStats(statsRes.data);\n }\n\n if (optionsRes?.success && optionsRes.data) {\n setFilterOptions(optionsRes.data);\n }\n } catch (err) {\n console.error('Error fetching activity data:', err);\n setError(t('activity.fetchError'));\n } finally {\n setIsLoading(false);\n }\n }, [currentPage, itemsPerPage, appliedFilters, t]);\n\n useEffect(() => {\n fetchData();\n }, [fetchData]);\n\n useEffect(() => {\n if (!pagination) {\n return;\n }\n\n const totalPages = Math.max(1, pagination.totalPages || 1);\n if (currentPage > totalPages) {\n setCurrentPage(totalPages);\n }\n }, [pagination, currentPage]);\n\n // Handle view activity details\n const handleViewDetails = async (activity: Activity) => {\n try {\n const response = await getActivityById(activity.id);\n if (response?.success && response.data) {\n setSelectedActivity(response.data);\n setShowDetailModal(true);\n }\n } catch (err) {\n console.error('Error fetching activity details:', err);\n }\n };\n\n // Handle cleanup old activities\n const handleCleanup = async () => {\n if (!window.confirm(t('activity.confirmCleanup'))) {\n return;\n }\n\n try {\n const response = await deleteOldActivities(30);\n if (response?.success) {\n alert(t('activity.cleanupSuccess', { count: response.data?.deletedCount || 0 }));\n fetchData();\n }\n } catch (err) {\n console.error('Error cleaning up activities:', err);\n alert(t('activity.cleanupError'));\n }\n };\n\n // Handle search\n const handleSearch = () => {\n const filters: ActivityFilter = {};\n if (searchServer) filters.server = searchServer;\n if (searchTool) filters.tool = searchTool;\n if (searchStatus && isValidStatus(searchStatus)) {\n filters.status = searchStatus;\n }\n if (searchGroup) filters.group = searchGroup;\n if (searchUsername) filters.username = searchUsername;\n if (searchKeyName) filters.keyName = searchKeyName;\n\n setAppliedFilters(filters);\n setCurrentPage(1);\n };\n\n // Handle clear filters\n const handleClearFilters = () => {\n setSearchServer('');\n setSearchTool('');\n setSearchStatus('');\n setSearchGroup('');\n setSearchUsername('');\n setSearchKeyName('');\n setAppliedFilters({});\n setCurrentPage(1);\n };\n\n // Format duration\n const formatDuration = (ms: number): string => {\n if (ms < 1000) return `${ms}ms`;\n if (ms < 60000) return `${(ms / 1000).toFixed(2)}s`;\n return `${(ms / 60000).toFixed(2)}m`;\n };\n\n // Format timestamp\n const formatTimestamp = (timestamp: string): string => {\n return new Date(timestamp).toLocaleString();\n };\n\n // Parse JSON safely\n const safeParseJSON = (str: string | undefined): any => {\n if (!str) return null;\n try {\n return JSON.parse(str);\n } catch {\n return str;\n }\n };\n\n // Render stats cards\n const renderStats = () => {\n if (!stats) return null;\n\n return (\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-3 mb-4\">\n {[\n { label: t('activity.totalCalls'), value: stats.totalCalls, tone: 'default' as const },\n { label: t('activity.successCount'), value: stats.successCount, tone: 'ok' as const },\n { label: t('activity.errorCount'), value: stats.errorCount, tone: 'err' as const },\n {\n label: t('activity.avgDuration'),\n value: formatDuration(stats.avgDuration),\n tone: 'default' as const,\n },\n ].map((s) => (\n <div key={s.label} className=\"hub-card\" style={{ padding: '12px 14px' }}>\n <div className=\"text-[12px]\" style={{ color: 'var(--hub-ink-3)' }}>\n {s.label}\n </div>\n <div\n className=\"hub-num\"\n style={{\n fontSize: 22,\n fontWeight: 500,\n lineHeight: 1.1,\n marginTop: 6,\n letterSpacing: '-0.02em',\n color:\n s.tone === 'ok'\n ? 'oklch(0.4 0.13 145)'\n : s.tone === 'err'\n ? 'oklch(0.45 0.18 25)'\n : 'var(--hub-ink)',\n }}\n >\n {s.value}\n </div>\n </div>\n ))}\n </div>\n );\n };\n\n // Render filters\n const renderFilters = () => {\n return (\n <div className=\"hub-card px-4 py-3 mb-4\">\n <div className=\"flex flex-wrap gap-3 items-end\">\n <div className=\"flex-1 min-w-[140px]\">\n <label className=\"sr-only\" htmlFor=\"activity-server\">\n {t('activity.server')}\n </label>\n <div className=\"relative\">\n <input\n id=\"activity-server\"\n type=\"text\"\n value={searchServer}\n onChange={(e) => setSearchServer(e.target.value)}\n placeholder={t('activity.searchServer')}\n className=\"hub-input pr-9\"\n list=\"server-options\"\n />\n {searchServer && (\n <button\n onClick={() => setSearchServer('')}\n className=\"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300\"\n aria-label={t('common.clear')}\n type=\"button\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-4 w-4\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n )}\n </div>\n {filterOptions?.servers && (\n <datalist id=\"server-options\">\n {filterOptions.servers.map((s) => (\n <option key={s} value={s} />\n ))}\n </datalist>\n )}\n </div>\n <div className=\"flex-1 min-w-[140px]\">\n <label className=\"sr-only\" htmlFor=\"activity-tool\">\n {t('activity.tool')}\n </label>\n <div className=\"relative\">\n <input\n id=\"activity-tool\"\n type=\"text\"\n value={searchTool}\n onChange={(e) => setSearchTool(e.target.value)}\n placeholder={t('activity.searchTool')}\n className=\"hub-input pr-9\"\n list=\"tool-options\"\n />\n {searchTool && (\n <button\n onClick={() => setSearchTool('')}\n className=\"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300\"\n aria-label={t('common.clear')}\n type=\"button\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-4 w-4\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n )}\n </div>\n {filterOptions?.tools && (\n <datalist id=\"tool-options\">\n {filterOptions.tools.map((t) => (\n <option key={t} value={t} />\n ))}\n </datalist>\n )}\n </div>\n <div className=\"flex-1 min-w-[140px]\">\n <label className=\"sr-only\" htmlFor=\"activity-status\">\n {t('activity.status')}\n </label>\n <div className=\"relative\">\n <input\n id=\"activity-status\"\n type=\"text\"\n value={searchStatus}\n onChange={(e) => setSearchStatus(e.target.value.toLowerCase())}\n placeholder={t('activity.searchStatus')}\n className=\"hub-input pr-9\"\n list=\"activity-status-options\"\n />\n {searchStatus && (\n <button\n onClick={() => setSearchStatus('')}\n className=\"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300\"\n aria-label={t('common.clear')}\n type=\"button\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-4 w-4\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n )}\n </div>\n <datalist id=\"activity-status-options\">\n {STATUS_OPTIONS.map((status) => (\n <option key={status} value={status} />\n ))}\n </datalist>\n </div>\n <div className=\"flex-1 min-w-[140px]\">\n <label className=\"sr-only\" htmlFor=\"activity-group\">\n {t('activity.group')}\n </label>\n <div className=\"relative\">\n <input\n id=\"activity-group\"\n type=\"text\"\n value={searchGroup}\n onChange={(e) => setSearchGroup(e.target.value)}\n placeholder={t('activity.searchGroup')}\n className=\"hub-input pr-9\"\n list=\"group-options\"\n />\n {searchGroup && (\n <button\n onClick={() => setSearchGroup('')}\n className=\"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300\"\n aria-label={t('common.clear')}\n type=\"button\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-4 w-4\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n )}\n </div>\n {filterOptions?.groups && (\n <datalist id=\"group-options\">\n {filterOptions.groups.map((g) => (\n <option key={g} value={g} />\n ))}\n </datalist>\n )}\n </div>\n <div className=\"flex-1 min-w-[140px]\">\n <label className=\"sr-only\" htmlFor=\"activity-username\">\n {t('activity.user')}\n </label>\n <div className=\"relative\">\n <input\n id=\"activity-username\"\n type=\"text\"\n value={searchUsername}\n onChange={(e) => setSearchUsername(e.target.value)}\n placeholder={t('activity.searchUsername')}\n className=\"hub-input pr-9\"\n list=\"username-options\"\n />\n {searchUsername && (\n <button\n onClick={() => setSearchUsername('')}\n className=\"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300\"\n aria-label={t('common.clear')}\n type=\"button\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-4 w-4\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n )}\n </div>\n {filterOptions?.usernames && (\n <datalist id=\"username-options\">\n {filterOptions.usernames.map((username) => (\n <option key={username} value={username} />\n ))}\n </datalist>\n )}\n </div>\n <div className=\"flex-1 min-w-[140px]\">\n <label className=\"sr-only\" htmlFor=\"activity-keyname\">\n {t('activity.keyName')}\n </label>\n <div className=\"relative\">\n <input\n id=\"activity-keyname\"\n type=\"text\"\n value={searchKeyName}\n onChange={(e) => setSearchKeyName(e.target.value)}\n placeholder={t('activity.searchKeyName')}\n className=\"hub-input pr-9\"\n list=\"keyname-options\"\n />\n {searchKeyName && (\n <button\n onClick={() => setSearchKeyName('')}\n className=\"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300\"\n aria-label={t('common.clear')}\n type=\"button\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-4 w-4\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n )}\n </div>\n {filterOptions?.keyNames && (\n <datalist id=\"keyname-options\">\n {filterOptions.keyNames.map((k) => (\n <option key={k} value={k} />\n ))}\n </datalist>\n )}\n </div>\n <div className=\"flex-shrink-0 flex items-center gap-2\">\n <button onClick={handleSearch} className=\"hub-btn primary whitespace-nowrap\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-3.5 w-3.5\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z\"\n clipRule=\"evenodd\"\n />\n </svg>\n {t('common.search')}\n </button>\n <button onClick={handleClearFilters} className=\"hub-btn whitespace-nowrap\">\n {t('common.clear')}\n </button>\n </div>\n </div>\n </div>\n );\n };\n\n // Render activity table\n const renderActivityTable = () => {\n if (activities.length === 0) {\n return (\n <div className=\"hub-card p-10 text-center\" style={{ color: 'var(--hub-ink-3)' }}>\n {t('activity.noData')}\n </div>\n );\n }\n\n return (\n <div className=\"hub-card overflow-hidden\">\n <div className=\"overflow-x-auto\">\n <table className=\"min-w-full\">\n <thead style={{ background: 'var(--hub-bg-2)' }}>\n <tr>\n {[\n t('activity.timestamp'),\n t('activity.server'),\n t('activity.tool'),\n t('activity.duration'),\n t('activity.status'),\n t('activity.group'),\n t('activity.user'),\n t('activity.key'),\n t('activity.sourceIp'),\n t('common.actions'),\n ].map((label) => (\n <th\n key={label}\n className=\"hub-mono\"\n style={{\n padding: '9px 14px',\n textAlign: 'left',\n fontSize: 11,\n color: 'var(--hub-ink-3)',\n textTransform: 'uppercase',\n letterSpacing: '0.08em',\n fontWeight: 500,\n }}\n >\n {label}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {activities.map((activity) => (\n <tr\n key={activity.id}\n className=\"transition-colors hover:bg-[var(--hub-surface-hover)]\"\n style={{ borderTop: '1px solid var(--hub-line-2)' }}\n >\n <td\n className=\"hub-mono whitespace-nowrap\"\n style={{ padding: '10px 14px', fontSize: 12, color: 'var(--hub-ink-2)' }}\n >\n {formatTimestamp(activity.timestamp)}\n </td>\n <td style={{ padding: '10px 14px' }}>\n <span className=\"hub-tag\">{activity.server}</span>\n </td>\n <td style={{ padding: '10px 14px' }}>\n <span className=\"hub-tag accent\">{activity.tool}</span>\n </td>\n <td\n className=\"hub-mono hub-num whitespace-nowrap\"\n style={{ padding: '10px 14px', fontSize: 12, color: 'var(--hub-ink-2)' }}\n >\n {formatDuration(activity.duration)}\n </td>\n <td style={{ padding: '10px 14px' }} className=\"whitespace-nowrap\">\n <span\n className={`hub-status ${activity.status === 'success' ? 'ok' : 'err'}`}\n >\n <span className=\"hub-dot\" />\n {activity.status === 'success'\n ? t('activity.statusSuccess')\n : t('activity.statusError')}\n </span>\n </td>\n <td\n style={{ padding: '10px 14px', fontSize: 12, color: 'var(--hub-ink-3)' }}\n >\n {activity.group || '—'}\n </td>\n <td\n style={{ padding: '10px 14px', fontSize: 12, color: 'var(--hub-ink-3)' }}\n >\n {activity.username || '—'}\n </td>\n <td\n style={{ padding: '10px 14px', fontSize: 12, color: 'var(--hub-ink-3)' }}\n >\n {activity.keyName || '—'}\n </td>\n <td\n className=\"hub-mono whitespace-nowrap\"\n style={{ padding: '10px 14px', fontSize: 12, color: 'var(--hub-ink-3)' }}\n >\n {activity.sourceIp || '—'}\n </td>\n <td style={{ padding: '10px 14px' }}>\n <button\n onClick={() => handleViewDetails(activity)}\n className=\"hub-btn ghost sm\"\n style={{ color: 'var(--hub-accent)' }}\n >\n {t('common.view')}\n </button>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </div>\n );\n };\n\n // Render detail modal\n const renderDetailModal = () => {\n if (!showDetailModal || !selectedActivity) return null;\n\n const inputData = safeParseJSON(selectedActivity.input);\n const outputData = safeParseJSON(selectedActivity.output);\n\n return (\n <div className=\"fixed inset-0 bg-black/50 flex items-center justify-center z-50\">\n <div\n className=\"hub-card max-w-4xl w-full mx-4 max-h-[90vh] overflow-hidden\"\n style={{ boxShadow: '0 8px 24px rgba(0,0,0,0.12)' }}\n >\n <div\n className=\"flex items-center justify-between px-5 py-3\"\n style={{ borderBottom: '1px solid var(--hub-line-2)' }}\n >\n <h3 className=\"hub-card-title\">{t('activity.details')}</h3>\n <button\n onClick={() => setShowDetailModal(false)}\n className=\"hub-icon-btn sm\"\n aria-label=\"close\"\n >\n <svg className=\"h-3.5 w-3.5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </button>\n </div>\n <div className=\"px-6 py-4 overflow-y-auto max-h-[calc(90vh-120px)]\">\n <div className=\"grid grid-cols-2 gap-4 mb-4\">\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.timestamp')}\n </label>\n <p className=\"text-gray-900 dark:text-white\">\n {formatTimestamp(selectedActivity.timestamp)}\n </p>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.duration')}\n </label>\n <p className=\"text-gray-900 dark:text-white\">\n {formatDuration(selectedActivity.duration)}\n </p>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.server')}\n </label>\n <p className=\"text-gray-900 dark:text-white font-mono\">{selectedActivity.server}</p>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.tool')}\n </label>\n <p className=\"text-gray-900 dark:text-white font-mono\">{selectedActivity.tool}</p>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.status')}\n </label>\n <span\n className={`px-2 py-1 rounded text-xs font-medium ${\n selectedActivity.status === 'success'\n ? 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200'\n : 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200'\n }`}\n >\n {selectedActivity.status === 'success'\n ? t('activity.statusSuccess')\n : t('activity.statusError')}\n </span>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.group')}\n </label>\n <p className=\"text-gray-900 dark:text-white\">{selectedActivity.group || '-'}</p>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.user')}\n </label>\n <p className=\"text-gray-900 dark:text-white\">{selectedActivity.username || '-'}</p>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.sourceIp')}\n </label>\n <p className=\"text-gray-900 dark:text-white font-mono\">\n {selectedActivity.sourceIp || '-'}\n </p>\n </div>\n {selectedActivity.keyName && (\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.key')}\n </label>\n <p className=\"text-gray-900 dark:text-white\">{selectedActivity.keyName}</p>\n </div>\n )}\n </div>\n\n {selectedActivity.errorMessage && (\n <div className=\"mb-4\">\n <label className=\"block text-sm font-medium text-red-500 mb-1\">\n {t('activity.errorMessage')}\n </label>\n <div className=\"bg-red-50 dark:bg-red-900/20 rounded p-3 text-sm text-red-800 dark:text-red-200\">\n {selectedActivity.errorMessage}\n </div>\n </div>\n )}\n\n {inputData && (\n <div className=\"mb-4\">\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400 mb-1\">\n {t('activity.input')}\n </label>\n <pre className=\"bg-gray-100 dark:bg-gray-700 rounded p-3 text-sm overflow-x-auto max-h-64\">\n {typeof inputData === 'string' ? inputData : JSON.stringify(inputData, null, 2)}\n </pre>\n </div>\n )}\n\n {outputData && (\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400 mb-1\">\n {t('activity.output')}\n </label>\n <pre className=\"bg-gray-100 dark:bg-gray-700 rounded p-3 text-sm overflow-x-auto max-h-64\">\n {typeof outputData === 'string'\n ? outputData\n : JSON.stringify(outputData, null, 2)}\n </pre>\n </div>\n )}\n </div>\n </div>\n </div>\n );\n };\n\n return (\n <div>\n <div className=\"flex items-end justify-between gap-4 mb-6\">\n <div>\n <h1 className=\"hub-h1\">{t('activity.title')}</h1>\n <p className=\"hub-sub\">\n <span className=\"hub-num\">{pagination?.total ?? activities.length}</span> entries\n </p>\n </div>\n <button onClick={handleCleanup} className=\"hub-btn danger\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-3.5 w-3.5\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M9 2a1 1 0 00-.894.553L7.382 4H4a1 1 0 000 2v10a2 2 0 002 2h8a2 2 0 002-2V6a1 1 0 100-2h-3.382l-.724-1.447A1 1 0 0011 2H9zM7 8a1 1 0 012 0v6a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v6a1 1 0 102 0V8a1 1 0 00-1-1z\"\n clipRule=\"evenodd\"\n />\n </svg>\n {t('activity.cleanup')}\n </button>\n </div>\n\n {error && (\n <div\n className=\"hub-card flex items-center justify-between gap-3 mb-4\"\n style={{\n padding: '10px 14px',\n borderColor: 'oklch(0.85 0.1 25)',\n background: 'oklch(0.97 0.03 25)',\n color: 'oklch(0.4 0.18 25)',\n }}\n >\n <span className=\"truncate text-[13px]\">{error}</span>\n <button className=\"hub-icon-btn sm\" onClick={() => setError(null)} aria-label=\"close\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-3 w-3\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n </div>\n )}\n\n {isLoading && activities.length === 0 ? (\n <div className=\"hub-card p-10 text-center\" style={{ color: 'var(--hub-ink-3)' }}>\n {t('app.loading')}\n </div>\n ) : (\n <>\n {renderStats()}\n {renderFilters()}\n {renderActivityTable()}\n\n {/* Pagination */}\n <div className=\"flex items-center mt-6\">\n <div className=\"flex-[2] text-sm text-gray-500 dark:text-gray-400\">\n {pagination &&\n t('common.showing', {\n start: (pagination.page - 1) * pagination.limit + 1,\n end: Math.min(pagination.page * pagination.limit, pagination.total),\n total: pagination.total,\n })}\n </div>\n <div className=\"flex-[4] flex justify-center\">\n {pagination && pagination.totalPages > 1 && (\n <Pagination\n currentPage={currentPage}\n totalPages={pagination.totalPages}\n onPageChange={setCurrentPage}\n disabled={isLoading}\n />\n )}\n </div>\n <div className=\"flex-[2] flex items-center justify-end space-x-2\">\n <label htmlFor=\"perPage\" className=\"text-sm text-gray-500 dark:text-gray-400\">\n {t('common.itemsPerPage')}:\n </label>\n <select\n id=\"perPage\"\n value={itemsPerPage}\n onChange={(e) => {\n setItemsPerPage(Number(e.target.value));\n setCurrentPage(1);\n }}\n disabled={isLoading}\n className=\"border border-gray-300 dark:border-gray-600 rounded p-1 text-sm dark:bg-gray-700 dark:text-white outline-none disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n <option value={10}>10</option>\n <option value={20}>20</option>\n <option value={50}>50</option>\n <option value={100}>100</option>\n </select>\n </div>\n </div>\n </>\n )}\n\n {renderDetailModal()}\n </div>\n );\n};\n\nexport default ActivityPage;\n"],"names":["STATUS_OPTIONS","isValidStatus","value","ActivityPage","t","useTranslation","activities","setActivities","useState","stats","setStats","filterOptions","setFilterOptions","pagination","setPagination","currentPage","setCurrentPage","itemsPerPage","setItemsPerPage","isLoading","setIsLoading","error","setError","selectedActivity","setSelectedActivity","showDetailModal","setShowDetailModal","appliedFilters","setAppliedFilters","searchServer","setSearchServer","searchTool","setSearchTool","searchStatus","setSearchStatus","searchGroup","setSearchGroup","searchUsername","setSearchUsername","searchKeyName","setSearchKeyName","fetchData","useCallback","currentFilter","activitiesRes","statsRes","optionsRes","getActivities","getActivityStats","getActivityFilterOptions","err","useEffect","totalPages","handleViewDetails","activity","response","getActivityById","handleCleanup","deleteOldActivities","_a","handleSearch","filters","handleClearFilters","formatDuration","ms","formatTimestamp","timestamp","safeParseJSON","str","renderStats","jsx","s","jsxs","renderFilters","e","status","g","username","k","renderActivityTable","label","renderDetailModal","inputData","outputData","Fragment","Pagination"],"mappings":"8PA4BA,MAAMA,EAAmC,CAAC,UAAW,OAAO,EAEtDC,GAAiBC,GACrBF,EAAe,SAASE,CAAuB,EAE3CC,GAAyB,IAAM,CACnC,KAAM,CAAE,EAAAC,CAAA,EAAMC,GAAA,EAGR,CAACC,EAAYC,CAAa,EAAIC,EAAAA,SAAqB,CAAA,CAAE,EACrD,CAACC,EAAOC,CAAQ,EAAIF,EAAAA,SAA+B,IAAI,EACvD,CAACG,EAAeC,CAAgB,EAAIJ,EAAAA,SAAuC,IAAI,EAC/E,CAACK,EAAYC,CAAa,EAAIN,EAAAA,SAAgC,IAAI,EAClE,CAACO,EAAaC,CAAc,EAAIR,EAAAA,SAAS,CAAC,EAC1C,CAACS,EAAcC,CAAe,EAAIV,EAAAA,SAAS,EAAE,EAC7C,CAACW,EAAWC,CAAY,EAAIZ,EAAAA,SAAS,EAAI,EACzC,CAACa,EAAOC,CAAQ,EAAId,EAAAA,SAAwB,IAAI,EAChD,CAACe,EAAkBC,CAAmB,EAAIhB,EAAAA,SAA0B,IAAI,EACxE,CAACiB,EAAiBC,CAAkB,EAAIlB,EAAAA,SAAS,EAAK,EAGtD,CAACmB,EAAgBC,CAAiB,EAAIpB,EAAAA,SAAyB,CAAA,CAAE,EACjE,CAACqB,EAAcC,CAAe,EAAItB,EAAAA,SAAS,EAAE,EAC7C,CAACuB,EAAYC,CAAa,EAAIxB,EAAAA,SAAS,EAAE,EACzC,CAACyB,EAAcC,CAAe,EAAI1B,EAAAA,SAAiB,EAAE,EACrD,CAAC2B,EAAaC,CAAc,EAAI5B,EAAAA,SAAS,EAAE,EAC3C,CAAC6B,EAAgBC,CAAiB,EAAI9B,EAAAA,SAAS,EAAE,EACjD,CAAC+B,EAAeC,CAAgB,EAAIhC,EAAAA,SAAS,EAAE,EAG/CiC,EAAYC,EAAAA,YAAY,SAAY,CACxCtB,EAAa,EAAI,EACjBE,EAAS,IAAI,EAEb,GAAI,CAEF,MAAMqB,EAAgB,CAAE,GAAGhB,CAAA,EAGrB,CAACiB,EAAeC,EAAUC,CAAU,EAAI,MAAM,QAAQ,IAAI,CAC9DC,GAAchC,EAAaE,EAAc0B,CAAa,EACtDK,GAAiBL,CAAa,EAC9BM,GAAA,CAAyB,CAC1B,EAEGL,GAAA,MAAAA,EAAe,SAAW,MAAM,QAAQA,EAAc,IAAI,IAC5DrC,EAAcqC,EAAc,IAAI,EAC5BA,EAAc,YAChB9B,EAAc8B,EAAc,UAAU,GAItCC,GAAA,MAAAA,EAAU,SAAWA,EAAS,MAChCnC,EAASmC,EAAS,IAAI,EAGpBC,GAAA,MAAAA,EAAY,SAAWA,EAAW,MACpClC,EAAiBkC,EAAW,IAAI,CAEpC,OAASI,EAAK,CACZ,QAAQ,MAAM,gCAAiCA,CAAG,EAClD5B,EAASlB,EAAE,qBAAqB,CAAC,CACnC,QAAA,CACEgB,EAAa,EAAK,CACpB,CACF,EAAG,CAACL,EAAaE,EAAcU,EAAgBvB,CAAC,CAAC,EAEjD+C,EAAAA,UAAU,IAAM,CACdV,EAAA,CACF,EAAG,CAACA,CAAS,CAAC,EAEdU,EAAAA,UAAU,IAAM,CACd,GAAI,CAACtC,EACH,OAGF,MAAMuC,EAAa,KAAK,IAAI,EAAGvC,EAAW,YAAc,CAAC,EACrDE,EAAcqC,GAChBpC,EAAeoC,CAAU,CAE7B,EAAG,CAACvC,EAAYE,CAAW,CAAC,EAG5B,MAAMsC,EAAoB,MAAOC,GAAuB,CACtD,GAAI,CACF,MAAMC,EAAW,MAAMC,GAAgBF,EAAS,EAAE,EAC9CC,GAAA,MAAAA,EAAU,SAAWA,EAAS,OAChC/B,EAAoB+B,EAAS,IAAI,EACjC7B,EAAmB,EAAI,EAE3B,OAASwB,EAAK,CACZ,QAAQ,MAAM,mCAAoCA,CAAG,CACvD,CACF,EAGMO,EAAgB,SAAY,OAChC,GAAK,OAAO,QAAQrD,EAAE,yBAAyB,CAAC,EAIhD,GAAI,CACF,MAAMmD,EAAW,MAAMG,GAAoB,EAAE,EACzCH,GAAA,MAAAA,EAAU,UACZ,MAAMnD,EAAE,0BAA2B,CAAE,QAAOuD,EAAAJ,EAAS,OAAT,YAAAI,EAAe,eAAgB,CAAA,CAAG,CAAC,EAC/ElB,EAAA,EAEJ,OAASS,EAAK,CACZ,QAAQ,MAAM,gCAAiCA,CAAG,EAClD,MAAM9C,EAAE,uBAAuB,CAAC,CAClC,CACF,EAGMwD,EAAe,IAAM,CACzB,MAAMC,EAA0B,CAAA,EAC5BhC,MAAsB,OAASA,GAC/BE,MAAoB,KAAOA,GAC3BE,GAAgBhC,GAAcgC,CAAY,IAC5C4B,EAAQ,OAAS5B,GAEfE,MAAqB,MAAQA,GAC7BE,MAAwB,SAAWA,GACnCE,MAAuB,QAAUA,GAErCX,EAAkBiC,CAAO,EACzB7C,EAAe,CAAC,CAClB,EAGM8C,EAAqB,IAAM,CAC/BhC,EAAgB,EAAE,EAClBE,EAAc,EAAE,EAChBE,EAAgB,EAAE,EAClBE,EAAe,EAAE,EACjBE,EAAkB,EAAE,EACpBE,EAAiB,EAAE,EACnBZ,EAAkB,CAAA,CAAE,EACpBZ,EAAe,CAAC,CAClB,EAGM+C,EAAkBC,GAClBA,EAAK,IAAa,GAAGA,CAAE,KACvBA,EAAK,IAAc,IAAIA,EAAK,KAAM,QAAQ,CAAC,CAAC,IACzC,IAAIA,EAAK,KAAO,QAAQ,CAAC,CAAC,IAI7BC,EAAmBC,GAChB,IAAI,KAAKA,CAAS,EAAE,eAAA,EAIvBC,EAAiBC,GAAiC,CACtD,GAAI,CAACA,EAAK,OAAO,KACjB,GAAI,CACF,OAAO,KAAK,MAAMA,CAAG,CACvB,MAAQ,CACN,OAAOA,CACT,CACF,EAGMC,EAAc,IACb5D,EAGH6D,EAAAA,IAAC,MAAA,CAAI,UAAU,6CACZ,SAAA,CACC,CAAE,MAAOlE,EAAE,qBAAqB,EAAG,MAAOK,EAAM,WAAY,KAAM,SAAA,EAClE,CAAE,MAAOL,EAAE,uBAAuB,EAAG,MAAOK,EAAM,aAAc,KAAM,IAAA,EACtE,CAAE,MAAOL,EAAE,qBAAqB,EAAG,MAAOK,EAAM,WAAY,KAAM,KAAA,EAClE,CACE,MAAOL,EAAE,sBAAsB,EAC/B,MAAO2D,EAAetD,EAAM,WAAW,EACvC,KAAM,SAAA,CACR,EACA,IAAK8D,GACLC,EAAAA,KAAC,MAAA,CAAkB,UAAU,WAAW,MAAO,CAAE,QAAS,WAAA,EACxD,SAAA,CAAAF,EAAAA,IAAC,MAAA,CAAI,UAAU,cAAc,MAAO,CAAE,MAAO,kBAAA,EAC1C,SAAAC,EAAE,KAAA,CACL,EACAD,EAAAA,IAAC,MAAA,CACC,UAAU,UACV,MAAO,CACL,SAAU,GACV,WAAY,IACZ,WAAY,IACZ,UAAW,EACX,cAAe,UACf,MACEC,EAAE,OAAS,KACP,sBACAA,EAAE,OAAS,MACT,sBACA,gBAAA,EAGT,SAAAA,EAAE,KAAA,CAAA,CACL,CAAA,EArBQA,EAAE,KAsBZ,CACD,EACH,EAtCiB,KA2CfE,EAAgB,UAEjB,MAAA,CAAI,UAAU,0BACb,SAAAD,EAAAA,KAAC,MAAA,CAAI,UAAU,iCACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,uBACb,SAAA,CAAAF,EAAAA,IAAC,SAAM,UAAU,UAAU,QAAQ,kBAChC,SAAAlE,EAAE,iBAAiB,EACtB,EACAoE,EAAAA,KAAC,MAAA,CAAI,UAAU,WACb,SAAA,CAAAF,EAAAA,IAAC,QAAA,CACC,GAAG,kBACH,KAAK,OACL,MAAOzC,EACP,SAAW6C,GAAM5C,EAAgB4C,EAAE,OAAO,KAAK,EAC/C,YAAatE,EAAE,uBAAuB,EACtC,UAAU,iBACV,KAAK,gBAAA,CAAA,EAENyB,GACCyC,EAAAA,IAAC,SAAA,CACC,QAAS,IAAMxC,EAAgB,EAAE,EACjC,UAAU,0GACV,aAAY1B,EAAE,cAAc,EAC5B,KAAK,SAEL,SAAAkE,EAAAA,IAAC,MAAA,CACC,MAAM,6BACN,UAAU,UACV,QAAQ,YACR,KAAK,eAEL,SAAAA,EAAAA,IAAC,OAAA,CACC,SAAS,UACT,EAAE,qMACF,SAAS,SAAA,CAAA,CACX,CAAA,CACF,CAAA,CACF,EAEJ,GACC3D,GAAA,YAAAA,EAAe,UACd2D,EAAAA,IAAC,WAAA,CAAS,GAAG,iBACV,SAAA3D,EAAc,QAAQ,IAAK4D,GAC1BD,EAAAA,IAAC,SAAA,CAAe,MAAOC,CAAA,EAAVA,CAAa,CAC3B,CAAA,CACH,CAAA,EAEJ,EACAC,EAAAA,KAAC,MAAA,CAAI,UAAU,uBACb,SAAA,CAAAF,EAAAA,IAAC,SAAM,UAAU,UAAU,QAAQ,gBAChC,SAAAlE,EAAE,eAAe,EACpB,EACAoE,EAAAA,KAAC,MAAA,CAAI,UAAU,WACb,SAAA,CAAAF,EAAAA,IAAC,QAAA,CACC,GAAG,gBACH,KAAK,OACL,MAAOvC,EACP,SAAW2C,GAAM1C,EAAc0C,EAAE,OAAO,KAAK,EAC7C,YAAatE,EAAE,qBAAqB,EACpC,UAAU,iBACV,KAAK,cAAA,CAAA,EAEN2B,GACCuC,EAAAA,IAAC,SAAA,CACC,QAAS,IAAMtC,EAAc,EAAE,EAC/B,UAAU,0GACV,aAAY5B,EAAE,cAAc,EAC5B,KAAK,SAEL,SAAAkE,EAAAA,IAAC,MAAA,CACC,MAAM,6BACN,UAAU,UACV,QAAQ,YACR,KAAK,eAEL,SAAAA,EAAAA,IAAC,OAAA,CACC,SAAS,UACT,EAAE,qMACF,SAAS,SAAA,CAAA,CACX,CAAA,CACF,CAAA,CACF,EAEJ,GACC3D,GAAA,YAAAA,EAAe,QACd2D,EAAAA,IAAC,WAAA,CAAS,GAAG,eACV,SAAA3D,EAAc,MAAM,IAAKP,GACxBkE,EAAAA,IAAC,SAAA,CAAe,MAAOlE,CAAAA,EAAVA,CAAa,CAC3B,CAAA,CACH,CAAA,EAEJ,EACAoE,EAAAA,KAAC,MAAA,CAAI,UAAU,uBACb,SAAA,CAAAF,EAAAA,IAAC,SAAM,UAAU,UAAU,QAAQ,kBAChC,SAAAlE,EAAE,iBAAiB,EACtB,EACAoE,EAAAA,KAAC,MAAA,CAAI,UAAU,WACb,SAAA,CAAAF,EAAAA,IAAC,QAAA,CACC,GAAG,kBACH,KAAK,OACL,MAAOrC,EACP,SAAWyC,GAAMxC,EAAgBwC,EAAE,OAAO,MAAM,aAAa,EAC7D,YAAatE,EAAE,uBAAuB,EACtC,UAAU,iBACV,KAAK,yBAAA,CAAA,EAEN6B,GACCqC,EAAAA,IAAC,SAAA,CACC,QAAS,IAAMpC,EAAgB,EAAE,EACjC,UAAU,0GACV,aAAY9B,EAAE,cAAc,EAC5B,KAAK,SAEL,SAAAkE,EAAAA,IAAC,MAAA,CACC,MAAM,6BACN,UAAU,UACV,QAAQ,YACR,KAAK,eAEL,SAAAA,EAAAA,IAAC,OAAA,CACC,SAAS,UACT,EAAE,qMACF,SAAS,SAAA,CAAA,CACX,CAAA,CACF,CAAA,CACF,EAEJ,EACAA,EAAAA,IAAC,WAAA,CAAS,GAAG,0BACV,WAAe,IAAKK,GACnBL,EAAAA,IAAC,SAAA,CAAoB,MAAOK,CAAA,EAAfA,CAAuB,CACrC,CAAA,CACH,CAAA,EACF,EACAH,EAAAA,KAAC,MAAA,CAAI,UAAU,uBACb,SAAA,CAAAF,EAAAA,IAAC,SAAM,UAAU,UAAU,QAAQ,iBAChC,SAAAlE,EAAE,gBAAgB,EACrB,EACAoE,EAAAA,KAAC,MAAA,CAAI,UAAU,WACb,SAAA,CAAAF,EAAAA,IAAC,QAAA,CACC,GAAG,iBACH,KAAK,OACL,MAAOnC,EACP,SAAWuC,GAAMtC,EAAesC,EAAE,OAAO,KAAK,EAC9C,YAAatE,EAAE,sBAAsB,EACrC,UAAU,iBACV,KAAK,eAAA,CAAA,EAEN+B,GACCmC,EAAAA,IAAC,SAAA,CACC,QAAS,IAAMlC,EAAe,EAAE,EAChC,UAAU,0GACV,aAAYhC,EAAE,cAAc,EAC5B,KAAK,SAEL,SAAAkE,EAAAA,IAAC,MAAA,CACC,MAAM,6BACN,UAAU,UACV,QAAQ,YACR,KAAK,eAEL,SAAAA,EAAAA,IAAC,OAAA,CACC,SAAS,UACT,EAAE,qMACF,SAAS,SAAA,CAAA,CACX,CAAA,CACF,CAAA,CACF,EAEJ,GACC3D,GAAA,YAAAA,EAAe,SACd2D,EAAAA,IAAC,WAAA,CAAS,GAAG,gBACV,SAAA3D,EAAc,OAAO,IAAKiE,GACzBN,EAAAA,IAAC,SAAA,CAAe,MAAOM,CAAA,EAAVA,CAAa,CAC3B,CAAA,CACH,CAAA,EAEJ,EACAJ,EAAAA,KAAC,MAAA,CAAI,UAAU,uBACb,SAAA,CAAAF,EAAAA,IAAC,SAAM,UAAU,UAAU,QAAQ,oBAChC,SAAAlE,EAAE,eAAe,EACpB,EACAoE,EAAAA,KAAC,MAAA,CAAI,UAAU,WACb,SAAA,CAAAF,EAAAA,IAAC,QAAA,CACC,GAAG,oBACH,KAAK,OACL,MAAOjC,EACP,SAAWqC,GAAMpC,EAAkBoC,EAAE,OAAO,KAAK,EACjD,YAAatE,EAAE,yBAAyB,EACxC,UAAU,iBACV,KAAK,kBAAA,CAAA,EAENiC,GACCiC,EAAAA,IAAC,SAAA,CACC,QAAS,IAAMhC,EAAkB,EAAE,EACnC,UAAU,0GACV,aAAYlC,EAAE,cAAc,EAC5B,KAAK,SAEL,SAAAkE,EAAAA,IAAC,MAAA,CACC,MAAM,6BACN,UAAU,UACV,QAAQ,YACR,KAAK,eAEL,SAAAA,EAAAA,IAAC,OAAA,CACC,SAAS,UACT,EAAE,qMACF,SAAS,SAAA,CAAA,CACX,CAAA,CACF,CAAA,CACF,EAEJ,GACC3D,GAAA,YAAAA,EAAe,YACd2D,EAAAA,IAAC,WAAA,CAAS,GAAG,mBACV,SAAA3D,EAAc,UAAU,IAAKkE,GAC5BP,EAAAA,IAAC,SAAA,CAAsB,MAAOO,CAAA,EAAjBA,CAA2B,CACzC,CAAA,CACH,CAAA,EAEJ,EACAL,EAAAA,KAAC,MAAA,CAAI,UAAU,uBACb,SAAA,CAAAF,EAAAA,IAAC,SAAM,UAAU,UAAU,QAAQ,mBAChC,SAAAlE,EAAE,kBAAkB,EACvB,EACAoE,EAAAA,KAAC,MAAA,CAAI,UAAU,WACb,SAAA,CAAAF,EAAAA,IAAC,QAAA,CACC,GAAG,mBACH,KAAK,OACL,MAAO/B,EACP,SAAWmC,GAAMlC,EAAiBkC,EAAE,OAAO,KAAK,EAChD,YAAatE,EAAE,wBAAwB,EACvC,UAAU,iBACV,KAAK,iBAAA,CAAA,EAENmC,GACC+B,EAAAA,IAAC,SAAA,CACC,QAAS,IAAM9B,EAAiB,EAAE,EAClC,UAAU,0GACV,aAAYpC,EAAE,cAAc,EAC5B,KAAK,SAEL,SAAAkE,EAAAA,IAAC,MAAA,CACC,MAAM,6BACN,UAAU,UACV,QAAQ,YACR,KAAK,eAEL,SAAAA,EAAAA,IAAC,OAAA,CACC,SAAS,UACT,EAAE,qMACF,SAAS,SAAA,CAAA,CACX,CAAA,CACF,CAAA,CACF,EAEJ,GACC3D,GAAA,YAAAA,EAAe,WACd2D,EAAAA,IAAC,WAAA,CAAS,GAAG,kBACV,SAAA3D,EAAc,SAAS,IAAKmE,GAC3BR,EAAAA,IAAC,SAAA,CAAe,MAAOQ,CAAA,EAAVA,CAAa,CAC3B,CAAA,CACH,CAAA,EAEJ,EACAN,EAAAA,KAAC,MAAA,CAAI,UAAU,wCACb,SAAA,CAAAA,EAAAA,KAAC,SAAA,CAAO,QAASZ,EAAc,UAAU,oCACvC,SAAA,CAAAU,EAAAA,IAAC,MAAA,CACC,MAAM,6BACN,UAAU,cACV,QAAQ,YACR,KAAK,eAEL,SAAAA,EAAAA,IAAC,OAAA,CACC,SAAS,UACT,EAAE,mHACF,SAAS,SAAA,CAAA,CACX,CAAA,EAEDlE,EAAE,eAAe,CAAA,EACpB,EACAkE,MAAC,UAAO,QAASR,EAAoB,UAAU,4BAC5C,SAAA1D,EAAE,cAAc,CAAA,CACnB,CAAA,CAAA,CACF,CAAA,CAAA,CACF,CAAA,CACF,EAKE2E,EAAsB,IACtBzE,EAAW,SAAW,EAEtBgE,EAAAA,IAAC,MAAA,CAAI,UAAU,4BAA4B,MAAO,CAAE,MAAO,kBAAA,EACxD,SAAAlE,EAAE,iBAAiB,CAAA,CACtB,EAKFkE,EAAAA,IAAC,MAAA,CAAI,UAAU,2BACb,SAAAA,EAAAA,IAAC,MAAA,CAAI,UAAU,kBACb,SAAAE,EAAAA,KAAC,QAAA,CAAM,UAAU,aACf,SAAA,CAAAF,EAAAA,IAAC,SAAM,MAAO,CAAE,WAAY,iBAAA,EAC1B,eAAC,KAAA,CACE,SAAA,CACClE,EAAE,oBAAoB,EACtBA,EAAE,iBAAiB,EACnBA,EAAE,eAAe,EACjBA,EAAE,mBAAmB,EACrBA,EAAE,iBAAiB,EACnBA,EAAE,gBAAgB,EAClBA,EAAE,eAAe,EACjBA,EAAE,cAAc,EAChBA,EAAE,mBAAmB,EACrBA,EAAE,gBAAgB,CAAA,EAClB,IAAK4E,GACLV,EAAAA,IAAC,KAAA,CAEC,UAAU,WACV,MAAO,CACL,QAAS,WACT,UAAW,OACX,SAAU,GACV,MAAO,mBACP,cAAe,YACf,cAAe,SACf,WAAY,GAAA,EAGb,SAAAU,CAAA,EAZIA,CAAA,CAcR,EACH,CAAA,CACF,EACAV,EAAAA,IAAC,QAAA,CACE,SAAAhE,EAAW,IAAKgD,GACfkB,EAAAA,KAAC,KAAA,CAEC,UAAU,wDACV,MAAO,CAAE,UAAW,6BAAA,EAEpB,SAAA,CAAAF,EAAAA,IAAC,KAAA,CACC,UAAU,6BACV,MAAO,CAAE,QAAS,YAAa,SAAU,GAAI,MAAO,kBAAA,EAEnD,SAAAL,EAAgBX,EAAS,SAAS,CAAA,CAAA,EAErCgB,EAAAA,IAAC,KAAA,CAAG,MAAO,CAAE,QAAS,WAAA,EACpB,SAAAA,EAAAA,IAAC,OAAA,CAAK,UAAU,UAAW,SAAAhB,EAAS,OAAO,EAC7C,EACAgB,EAAAA,IAAC,KAAA,CAAG,MAAO,CAAE,QAAS,WAAA,EACpB,SAAAA,EAAAA,IAAC,OAAA,CAAK,UAAU,iBAAkB,SAAAhB,EAAS,KAAK,EAClD,EACAgB,EAAAA,IAAC,KAAA,CACC,UAAU,qCACV,MAAO,CAAE,QAAS,YAAa,SAAU,GAAI,MAAO,kBAAA,EAEnD,SAAAP,EAAeT,EAAS,QAAQ,CAAA,CAAA,EAEnCgB,MAAC,MAAG,MAAO,CAAE,QAAS,WAAA,EAAe,UAAU,oBAC7C,SAAAE,EAAAA,KAAC,OAAA,CACC,UAAW,cAAclB,EAAS,SAAW,UAAY,KAAO,KAAK,GAErE,SAAA,CAAAgB,EAAAA,IAAC,OAAA,CAAK,UAAU,SAAA,CAAU,EACzBhB,EAAS,SAAW,UACjBlD,EAAE,wBAAwB,EAC1BA,EAAE,sBAAsB,CAAA,CAAA,CAAA,EAEhC,EACAkE,EAAAA,IAAC,KAAA,CACC,MAAO,CAAE,QAAS,YAAa,SAAU,GAAI,MAAO,kBAAA,EAEnD,WAAS,OAAS,GAAA,CAAA,EAErBA,EAAAA,IAAC,KAAA,CACC,MAAO,CAAE,QAAS,YAAa,SAAU,GAAI,MAAO,kBAAA,EAEnD,WAAS,UAAY,GAAA,CAAA,EAExBA,EAAAA,IAAC,KAAA,CACC,MAAO,CAAE,QAAS,YAAa,SAAU,GAAI,MAAO,kBAAA,EAEnD,WAAS,SAAW,GAAA,CAAA,EAEvBA,EAAAA,IAAC,KAAA,CACC,UAAU,6BACV,MAAO,CAAE,QAAS,YAAa,SAAU,GAAI,MAAO,kBAAA,EAEnD,WAAS,UAAY,GAAA,CAAA,QAEvB,KAAA,CAAG,MAAO,CAAE,QAAS,aACpB,SAAAA,EAAAA,IAAC,SAAA,CACC,QAAS,IAAMjB,EAAkBC,CAAQ,EACzC,UAAU,mBACV,MAAO,CAAE,MAAO,mBAAA,EAEf,WAAE,aAAa,CAAA,CAAA,CAClB,CACF,CAAA,CAAA,EA7DKA,EAAS,EAAA,CA+DjB,CAAA,CACH,CAAA,CAAA,CACF,EACF,EACF,EAKE2B,EAAoB,IAAM,CAC9B,GAAI,CAACxD,GAAmB,CAACF,EAAkB,OAAO,KAElD,MAAM2D,EAAYf,EAAc5C,EAAiB,KAAK,EAChD4D,EAAahB,EAAc5C,EAAiB,MAAM,EAExD,OACE+C,EAAAA,IAAC,MAAA,CAAI,UAAU,kEACb,SAAAE,EAAAA,KAAC,MAAA,CACC,UAAU,8DACV,MAAO,CAAE,UAAW,6BAAA,EAEpB,SAAA,CAAAA,EAAAA,KAAC,MAAA,CACC,UAAU,8CACV,MAAO,CAAE,aAAc,6BAAA,EAEvB,SAAA,CAAAF,MAAC,KAAA,CAAG,UAAU,iBAAkB,SAAAlE,EAAE,kBAAkB,EAAE,EACtDkE,EAAAA,IAAC,SAAA,CACC,QAAS,IAAM5C,EAAmB,EAAK,EACvC,UAAU,kBACV,aAAW,QAEX,SAAA4C,EAAAA,IAAC,OAAI,UAAU,cAAc,KAAK,OAAO,QAAQ,YAAY,OAAO,eAClE,SAAAA,EAAAA,IAAC,OAAA,CACC,cAAc,QACd,eAAe,QACf,YAAa,EACb,EAAE,sBAAA,CAAA,CACJ,CACF,CAAA,CAAA,CACF,CAAA,CAAA,EAEFE,EAAAA,KAAC,MAAA,CAAI,UAAU,qDACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,8BACb,SAAA,CAAAA,OAAC,MAAA,CACC,SAAA,CAAAF,MAAC,QAAA,CAAM,UAAU,6DACd,SAAAlE,EAAE,oBAAoB,EACzB,QACC,IAAA,CAAE,UAAU,gCACV,SAAA6D,EAAgB1C,EAAiB,SAAS,CAAA,CAC7C,CAAA,EACF,SACC,MAAA,CACC,SAAA,CAAA+C,MAAC,QAAA,CAAM,UAAU,6DACd,SAAAlE,EAAE,mBAAmB,EACxB,QACC,IAAA,CAAE,UAAU,gCACV,SAAA2D,EAAexC,EAAiB,QAAQ,CAAA,CAC3C,CAAA,EACF,SACC,MAAA,CACC,SAAA,CAAA+C,MAAC,QAAA,CAAM,UAAU,6DACd,SAAAlE,EAAE,iBAAiB,EACtB,EACAkE,EAAAA,IAAC,IAAA,CAAE,UAAU,0CAA2C,WAAiB,MAAA,CAAO,CAAA,EAClF,SACC,MAAA,CACC,SAAA,CAAAA,MAAC,QAAA,CAAM,UAAU,6DACd,SAAAlE,EAAE,eAAe,EACpB,EACAkE,EAAAA,IAAC,IAAA,CAAE,UAAU,0CAA2C,WAAiB,IAAA,CAAK,CAAA,EAChF,SACC,MAAA,CACC,SAAA,CAAAA,MAAC,QAAA,CAAM,UAAU,6DACd,SAAAlE,EAAE,iBAAiB,EACtB,EACAkE,EAAAA,IAAC,OAAA,CACC,UAAW,yCACT/C,EAAiB,SAAW,UACxB,oEACA,2DACN,GAEC,WAAiB,SAAW,UACzBnB,EAAE,wBAAwB,EAC1BA,EAAE,sBAAsB,CAAA,CAAA,CAC9B,EACF,SACC,MAAA,CACC,SAAA,CAAAkE,MAAC,QAAA,CAAM,UAAU,6DACd,SAAAlE,EAAE,gBAAgB,EACrB,QACC,IAAA,CAAE,UAAU,gCAAiC,SAAAmB,EAAiB,OAAS,GAAA,CAAI,CAAA,EAC9E,SACC,MAAA,CACC,SAAA,CAAA+C,MAAC,QAAA,CAAM,UAAU,6DACd,SAAAlE,EAAE,eAAe,EACpB,QACC,IAAA,CAAE,UAAU,gCAAiC,SAAAmB,EAAiB,UAAY,GAAA,CAAI,CAAA,EACjF,SACC,MAAA,CACC,SAAA,CAAA+C,MAAC,QAAA,CAAM,UAAU,6DACd,SAAAlE,EAAE,mBAAmB,EACxB,QACC,IAAA,CAAE,UAAU,0CACV,SAAAmB,EAAiB,UAAY,GAAA,CAChC,CAAA,EACF,EACCA,EAAiB,SAChBiD,EAAAA,KAAC,MAAA,CACC,SAAA,CAAAF,MAAC,QAAA,CAAM,UAAU,6DACd,SAAAlE,EAAE,cAAc,EACnB,EACAkE,EAAAA,IAAC,IAAA,CAAE,UAAU,gCAAiC,WAAiB,OAAA,CAAQ,CAAA,CAAA,CACzE,CAAA,EAEJ,EAEC/C,EAAiB,cAChBiD,OAAC,MAAA,CAAI,UAAU,OACb,SAAA,CAAAF,MAAC,QAAA,CAAM,UAAU,8CACd,SAAAlE,EAAE,uBAAuB,EAC5B,EACAkE,EAAAA,IAAC,MAAA,CAAI,UAAU,kFACZ,WAAiB,YAAA,CACpB,CAAA,EACF,EAGDY,GACCV,EAAAA,KAAC,MAAA,CAAI,UAAU,OACb,SAAA,CAAAF,MAAC,QAAA,CAAM,UAAU,kEACd,SAAAlE,EAAE,gBAAgB,EACrB,EACAkE,EAAAA,IAAC,MAAA,CAAI,UAAU,4EACZ,SAAA,OAAOY,GAAc,SAAWA,EAAY,KAAK,UAAUA,EAAW,KAAM,CAAC,CAAA,CAChF,CAAA,EACF,EAGDC,UACE,MAAA,CACC,SAAA,CAAAb,MAAC,QAAA,CAAM,UAAU,kEACd,SAAAlE,EAAE,iBAAiB,EACtB,EACAkE,EAAAA,IAAC,MAAA,CAAI,UAAU,4EACZ,SAAA,OAAOa,GAAe,SACnBA,EACA,KAAK,UAAUA,EAAY,KAAM,CAAC,CAAA,CACxC,CAAA,CAAA,CACF,CAAA,CAAA,CAEJ,CAAA,CAAA,CAAA,EAEJ,CAEJ,EAEA,cACG,MAAA,CACC,SAAA,CAAAX,EAAAA,KAAC,MAAA,CAAI,UAAU,4CACb,SAAA,CAAAA,OAAC,MAAA,CACC,SAAA,CAAAF,MAAC,KAAA,CAAG,UAAU,SAAU,SAAAlE,EAAE,gBAAgB,EAAE,EAC5CoE,EAAAA,KAAC,IAAA,CAAE,UAAU,UACX,SAAA,CAAAF,MAAC,QAAK,UAAU,UAAW,UAAAzD,GAAA,YAAAA,EAAY,QAASP,EAAW,OAAO,EAAO,UAAA,CAAA,CAC3E,CAAA,EACF,EACAkE,EAAAA,KAAC,SAAA,CAAO,QAASf,EAAe,UAAU,iBACxC,SAAA,CAAAa,EAAAA,IAAC,MAAA,CACC,MAAM,6BACN,UAAU,cACV,QAAQ,YACR,KAAK,eAEL,SAAAA,EAAAA,IAAC,OAAA,CACC,SAAS,UACT,EAAE,8MACF,SAAS,SAAA,CAAA,CACX,CAAA,EAEDlE,EAAE,kBAAkB,CAAA,CAAA,CACvB,CAAA,EACF,EAECiB,GACCmD,EAAAA,KAAC,MAAA,CACC,UAAU,wDACV,MAAO,CACL,QAAS,YACT,YAAa,qBACb,WAAY,sBACZ,MAAO,oBAAA,EAGT,SAAA,CAAAF,EAAAA,IAAC,OAAA,CAAK,UAAU,uBAAwB,SAAAjD,EAAM,EAC9CiD,EAAAA,IAAC,SAAA,CAAO,UAAU,kBAAkB,QAAS,IAAMhD,EAAS,IAAI,EAAG,aAAW,QAC5E,SAAAgD,EAAAA,IAAC,MAAA,CACC,MAAM,6BACN,UAAU,UACV,QAAQ,YACR,KAAK,eAEL,SAAAA,EAAAA,IAAC,OAAA,CACC,SAAS,UACT,EAAE,qMACF,SAAS,SAAA,CAAA,CACX,CAAA,CACF,CACF,CAAA,CAAA,CAAA,EAIHnD,GAAab,EAAW,SAAW,EAClCgE,EAAAA,IAAC,OAAI,UAAU,4BAA4B,MAAO,CAAE,MAAO,kBAAA,EACxD,WAAE,aAAa,CAAA,CAClB,EAEAE,EAAAA,KAAAY,WAAA,CACG,SAAA,CAAAf,EAAA,EACAI,EAAA,EACAM,EAAA,EAGDP,EAAAA,KAAC,MAAA,CAAI,UAAU,yBACb,SAAA,CAAAF,MAAC,MAAA,CAAI,UAAU,oDACZ,SAAAzD,GACCT,EAAE,iBAAkB,CAClB,OAAQS,EAAW,KAAO,GAAKA,EAAW,MAAQ,EAClD,IAAK,KAAK,IAAIA,EAAW,KAAOA,EAAW,MAAOA,EAAW,KAAK,EAClE,MAAOA,EAAW,KAAA,CACnB,EACL,QACC,MAAA,CAAI,UAAU,+BACZ,SAAAA,GAAcA,EAAW,WAAa,GACrCyD,EAAAA,IAACe,GAAA,CACC,YAAAtE,EACA,WAAYF,EAAW,WACvB,aAAcG,EACd,SAAUG,CAAA,CAAA,EAGhB,EACAqD,EAAAA,KAAC,MAAA,CAAI,UAAU,mDACb,SAAA,CAAAA,EAAAA,KAAC,QAAA,CAAM,QAAQ,UAAU,UAAU,2CAChC,SAAA,CAAApE,EAAE,qBAAqB,EAAE,GAAA,EAC5B,EACAoE,EAAAA,KAAC,SAAA,CACC,GAAG,UACH,MAAOvD,EACP,SAAWyD,GAAM,CACfxD,EAAgB,OAAOwD,EAAE,OAAO,KAAK,CAAC,EACtC1D,EAAe,CAAC,CAClB,EACA,SAAUG,EACV,UAAU,gKAEV,SAAA,CAAAmD,EAAAA,IAAC,SAAA,CAAO,MAAO,GAAI,SAAA,KAAE,EACrBA,EAAAA,IAAC,SAAA,CAAO,MAAO,GAAI,SAAA,KAAE,EACrBA,EAAAA,IAAC,SAAA,CAAO,MAAO,GAAI,SAAA,KAAE,EACrBA,EAAAA,IAAC,SAAA,CAAO,MAAO,IAAK,SAAA,KAAA,CAAG,CAAA,CAAA,CAAA,CACzB,CAAA,CACF,CAAA,CAAA,CACF,CAAA,EACF,EAGDW,EAAA,CAAkB,EACrB,CAEJ"}
1
+ {"version":3,"file":"ActivityPage-B5DanW8q.js","sources":["../../src/pages/ActivityPage.tsx"],"sourcesContent":["import React, { useState, useEffect, useCallback } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport {\n Activity,\n ActivityStats,\n ActivityFilter,\n ActivityFilterOptions,\n ActivityStatus,\n} from '@/types';\nimport {\n getActivities,\n getActivityById,\n getActivityStats,\n getActivityFilterOptions,\n deleteOldActivities,\n} from '@/services/activityService';\nimport Pagination from '@/components/ui/Pagination';\n\n// Pagination info type\ninterface PaginationInfo {\n page: number;\n limit: number;\n total: number;\n totalPages: number;\n hasNextPage: boolean;\n hasPrevPage: boolean;\n}\n\nconst STATUS_OPTIONS: ActivityStatus[] = ['success', 'error'];\n\nconst isValidStatus = (value: string): value is ActivityStatus =>\n STATUS_OPTIONS.includes(value as ActivityStatus);\n\nconst ActivityPage: React.FC = () => {\n const { t } = useTranslation();\n\n // State\n const [activities, setActivities] = useState<Activity[]>([]);\n const [stats, setStats] = useState<ActivityStats | null>(null);\n const [filterOptions, setFilterOptions] = useState<ActivityFilterOptions | null>(null);\n const [pagination, setPagination] = useState<PaginationInfo | null>(null);\n const [currentPage, setCurrentPage] = useState(1);\n const [itemsPerPage, setItemsPerPage] = useState(10);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [selectedActivity, setSelectedActivity] = useState<Activity | null>(null);\n const [showDetailModal, setShowDetailModal] = useState(false);\n\n // Filter state\n const [appliedFilters, setAppliedFilters] = useState<ActivityFilter>({});\n const [searchServer, setSearchServer] = useState('');\n const [searchTool, setSearchTool] = useState('');\n const [searchStatus, setSearchStatus] = useState<string>('');\n const [searchGroup, setSearchGroup] = useState('');\n const [searchUsername, setSearchUsername] = useState('');\n const [searchKeyName, setSearchKeyName] = useState('');\n\n // Fetch data\n const fetchData = useCallback(async () => {\n setIsLoading(true);\n setError(null);\n\n try {\n // Use appliedFilters directly for fetching\n const currentFilter = { ...appliedFilters };\n\n // Fetch activities, stats, and filter options in parallel\n const [activitiesRes, statsRes, optionsRes] = await Promise.all([\n getActivities(currentPage, itemsPerPage, currentFilter),\n getActivityStats(currentFilter),\n getActivityFilterOptions(),\n ]);\n\n if (activitiesRes?.success && Array.isArray(activitiesRes.data)) {\n setActivities(activitiesRes.data);\n if (activitiesRes.pagination) {\n setPagination(activitiesRes.pagination);\n }\n }\n\n if (statsRes?.success && statsRes.data) {\n setStats(statsRes.data);\n }\n\n if (optionsRes?.success && optionsRes.data) {\n setFilterOptions(optionsRes.data);\n }\n } catch (err) {\n console.error('Error fetching activity data:', err);\n setError(t('activity.fetchError'));\n } finally {\n setIsLoading(false);\n }\n }, [currentPage, itemsPerPage, appliedFilters, t]);\n\n useEffect(() => {\n fetchData();\n }, [fetchData]);\n\n useEffect(() => {\n if (!pagination) {\n return;\n }\n\n const totalPages = Math.max(1, pagination.totalPages || 1);\n if (currentPage > totalPages) {\n setCurrentPage(totalPages);\n }\n }, [pagination, currentPage]);\n\n // Handle view activity details\n const handleViewDetails = async (activity: Activity) => {\n try {\n const response = await getActivityById(activity.id);\n if (response?.success && response.data) {\n setSelectedActivity(response.data);\n setShowDetailModal(true);\n }\n } catch (err) {\n console.error('Error fetching activity details:', err);\n }\n };\n\n // Handle cleanup old activities\n const handleCleanup = async () => {\n if (!window.confirm(t('activity.confirmCleanup'))) {\n return;\n }\n\n try {\n const response = await deleteOldActivities(30);\n if (response?.success) {\n alert(t('activity.cleanupSuccess', { count: response.data?.deletedCount || 0 }));\n fetchData();\n }\n } catch (err) {\n console.error('Error cleaning up activities:', err);\n alert(t('activity.cleanupError'));\n }\n };\n\n // Handle search\n const handleSearch = () => {\n const filters: ActivityFilter = {};\n if (searchServer) filters.server = searchServer;\n if (searchTool) filters.tool = searchTool;\n if (searchStatus && isValidStatus(searchStatus)) {\n filters.status = searchStatus;\n }\n if (searchGroup) filters.group = searchGroup;\n if (searchUsername) filters.username = searchUsername;\n if (searchKeyName) filters.keyName = searchKeyName;\n\n setAppliedFilters(filters);\n setCurrentPage(1);\n };\n\n // Handle clear filters\n const handleClearFilters = () => {\n setSearchServer('');\n setSearchTool('');\n setSearchStatus('');\n setSearchGroup('');\n setSearchUsername('');\n setSearchKeyName('');\n setAppliedFilters({});\n setCurrentPage(1);\n };\n\n // Format duration\n const formatDuration = (ms: number): string => {\n if (ms < 1000) return `${ms}ms`;\n if (ms < 60000) return `${(ms / 1000).toFixed(2)}s`;\n return `${(ms / 60000).toFixed(2)}m`;\n };\n\n // Format timestamp\n const formatTimestamp = (timestamp: string): string => {\n return new Date(timestamp).toLocaleString();\n };\n\n // Parse JSON safely\n const safeParseJSON = (str: string | undefined): any => {\n if (!str) return null;\n try {\n return JSON.parse(str);\n } catch {\n return str;\n }\n };\n\n // Render stats cards\n const renderStats = () => {\n if (!stats) return null;\n\n return (\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-3 mb-4\">\n {[\n { label: t('activity.totalCalls'), value: stats.totalCalls, tone: 'default' as const },\n { label: t('activity.successCount'), value: stats.successCount, tone: 'ok' as const },\n { label: t('activity.errorCount'), value: stats.errorCount, tone: 'err' as const },\n {\n label: t('activity.avgDuration'),\n value: formatDuration(stats.avgDuration),\n tone: 'default' as const,\n },\n ].map((s) => (\n <div key={s.label} className=\"hub-card\" style={{ padding: '12px 14px' }}>\n <div className=\"text-[12px]\" style={{ color: 'var(--hub-ink-3)' }}>\n {s.label}\n </div>\n <div\n className=\"hub-num\"\n style={{\n fontSize: 22,\n fontWeight: 500,\n lineHeight: 1.1,\n marginTop: 6,\n letterSpacing: '-0.02em',\n color:\n s.tone === 'ok'\n ? 'oklch(0.4 0.13 145)'\n : s.tone === 'err'\n ? 'oklch(0.45 0.18 25)'\n : 'var(--hub-ink)',\n }}\n >\n {s.value}\n </div>\n </div>\n ))}\n </div>\n );\n };\n\n // Render filters\n const renderFilters = () => {\n return (\n <div className=\"hub-card px-4 py-3 mb-4\">\n <div className=\"flex flex-wrap gap-3 items-end\">\n <div className=\"flex-1 min-w-[140px]\">\n <label className=\"sr-only\" htmlFor=\"activity-server\">\n {t('activity.server')}\n </label>\n <div className=\"relative\">\n <input\n id=\"activity-server\"\n type=\"text\"\n value={searchServer}\n onChange={(e) => setSearchServer(e.target.value)}\n placeholder={t('activity.searchServer')}\n className=\"hub-input pr-9\"\n list=\"server-options\"\n />\n {searchServer && (\n <button\n onClick={() => setSearchServer('')}\n className=\"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300\"\n aria-label={t('common.clear')}\n type=\"button\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-4 w-4\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n )}\n </div>\n {filterOptions?.servers && (\n <datalist id=\"server-options\">\n {filterOptions.servers.map((s) => (\n <option key={s} value={s} />\n ))}\n </datalist>\n )}\n </div>\n <div className=\"flex-1 min-w-[140px]\">\n <label className=\"sr-only\" htmlFor=\"activity-tool\">\n {t('activity.tool')}\n </label>\n <div className=\"relative\">\n <input\n id=\"activity-tool\"\n type=\"text\"\n value={searchTool}\n onChange={(e) => setSearchTool(e.target.value)}\n placeholder={t('activity.searchTool')}\n className=\"hub-input pr-9\"\n list=\"tool-options\"\n />\n {searchTool && (\n <button\n onClick={() => setSearchTool('')}\n className=\"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300\"\n aria-label={t('common.clear')}\n type=\"button\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-4 w-4\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n )}\n </div>\n {filterOptions?.tools && (\n <datalist id=\"tool-options\">\n {filterOptions.tools.map((t) => (\n <option key={t} value={t} />\n ))}\n </datalist>\n )}\n </div>\n <div className=\"flex-1 min-w-[140px]\">\n <label className=\"sr-only\" htmlFor=\"activity-status\">\n {t('activity.status')}\n </label>\n <div className=\"relative\">\n <input\n id=\"activity-status\"\n type=\"text\"\n value={searchStatus}\n onChange={(e) => setSearchStatus(e.target.value.toLowerCase())}\n placeholder={t('activity.searchStatus')}\n className=\"hub-input pr-9\"\n list=\"activity-status-options\"\n />\n {searchStatus && (\n <button\n onClick={() => setSearchStatus('')}\n className=\"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300\"\n aria-label={t('common.clear')}\n type=\"button\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-4 w-4\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n )}\n </div>\n <datalist id=\"activity-status-options\">\n {STATUS_OPTIONS.map((status) => (\n <option key={status} value={status} />\n ))}\n </datalist>\n </div>\n <div className=\"flex-1 min-w-[140px]\">\n <label className=\"sr-only\" htmlFor=\"activity-group\">\n {t('activity.group')}\n </label>\n <div className=\"relative\">\n <input\n id=\"activity-group\"\n type=\"text\"\n value={searchGroup}\n onChange={(e) => setSearchGroup(e.target.value)}\n placeholder={t('activity.searchGroup')}\n className=\"hub-input pr-9\"\n list=\"group-options\"\n />\n {searchGroup && (\n <button\n onClick={() => setSearchGroup('')}\n className=\"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300\"\n aria-label={t('common.clear')}\n type=\"button\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-4 w-4\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n )}\n </div>\n {filterOptions?.groups && (\n <datalist id=\"group-options\">\n {filterOptions.groups.map((g) => (\n <option key={g} value={g} />\n ))}\n </datalist>\n )}\n </div>\n <div className=\"flex-1 min-w-[140px]\">\n <label className=\"sr-only\" htmlFor=\"activity-username\">\n {t('activity.user')}\n </label>\n <div className=\"relative\">\n <input\n id=\"activity-username\"\n type=\"text\"\n value={searchUsername}\n onChange={(e) => setSearchUsername(e.target.value)}\n placeholder={t('activity.searchUsername')}\n className=\"hub-input pr-9\"\n list=\"username-options\"\n />\n {searchUsername && (\n <button\n onClick={() => setSearchUsername('')}\n className=\"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300\"\n aria-label={t('common.clear')}\n type=\"button\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-4 w-4\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n )}\n </div>\n {filterOptions?.usernames && (\n <datalist id=\"username-options\">\n {filterOptions.usernames.map((username) => (\n <option key={username} value={username} />\n ))}\n </datalist>\n )}\n </div>\n <div className=\"flex-1 min-w-[140px]\">\n <label className=\"sr-only\" htmlFor=\"activity-keyname\">\n {t('activity.keyName')}\n </label>\n <div className=\"relative\">\n <input\n id=\"activity-keyname\"\n type=\"text\"\n value={searchKeyName}\n onChange={(e) => setSearchKeyName(e.target.value)}\n placeholder={t('activity.searchKeyName')}\n className=\"hub-input pr-9\"\n list=\"keyname-options\"\n />\n {searchKeyName && (\n <button\n onClick={() => setSearchKeyName('')}\n className=\"absolute inset-y-0 right-2 flex items-center text-gray-400 hover:text-gray-600 dark:hover:text-gray-300\"\n aria-label={t('common.clear')}\n type=\"button\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-4 w-4\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n )}\n </div>\n {filterOptions?.keyNames && (\n <datalist id=\"keyname-options\">\n {filterOptions.keyNames.map((k) => (\n <option key={k} value={k} />\n ))}\n </datalist>\n )}\n </div>\n <div className=\"flex-shrink-0 flex items-center gap-2\">\n <button onClick={handleSearch} className=\"hub-btn primary whitespace-nowrap\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-3.5 w-3.5\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z\"\n clipRule=\"evenodd\"\n />\n </svg>\n {t('common.search')}\n </button>\n <button onClick={handleClearFilters} className=\"hub-btn whitespace-nowrap\">\n {t('common.clear')}\n </button>\n </div>\n </div>\n </div>\n );\n };\n\n // Render activity table\n const renderActivityTable = () => {\n if (activities.length === 0) {\n return (\n <div className=\"hub-card p-10 text-center\" style={{ color: 'var(--hub-ink-3)' }}>\n {t('activity.noData')}\n </div>\n );\n }\n\n return (\n <div className=\"hub-card overflow-hidden\">\n <div className=\"overflow-x-auto\">\n <table className=\"min-w-full\">\n <thead style={{ background: 'var(--hub-bg-2)' }}>\n <tr>\n {[\n t('activity.timestamp'),\n t('activity.server'),\n t('activity.tool'),\n t('activity.duration'),\n t('activity.status'),\n t('activity.group'),\n t('activity.user'),\n t('activity.key'),\n t('activity.sourceIp'),\n t('common.actions'),\n ].map((label) => (\n <th\n key={label}\n className=\"hub-mono\"\n style={{\n padding: '9px 14px',\n textAlign: 'left',\n fontSize: 11,\n color: 'var(--hub-ink-3)',\n textTransform: 'uppercase',\n letterSpacing: '0.08em',\n fontWeight: 500,\n }}\n >\n {label}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {activities.map((activity) => (\n <tr\n key={activity.id}\n className=\"transition-colors hover:bg-[var(--hub-surface-hover)]\"\n style={{ borderTop: '1px solid var(--hub-line-2)' }}\n >\n <td\n className=\"hub-mono whitespace-nowrap\"\n style={{ padding: '10px 14px', fontSize: 12, color: 'var(--hub-ink-2)' }}\n >\n {formatTimestamp(activity.timestamp)}\n </td>\n <td style={{ padding: '10px 14px' }}>\n <span className=\"hub-tag\">{activity.server}</span>\n </td>\n <td style={{ padding: '10px 14px' }}>\n <span className=\"hub-tag accent\">{activity.tool}</span>\n </td>\n <td\n className=\"hub-mono hub-num whitespace-nowrap\"\n style={{ padding: '10px 14px', fontSize: 12, color: 'var(--hub-ink-2)' }}\n >\n {formatDuration(activity.duration)}\n </td>\n <td style={{ padding: '10px 14px' }} className=\"whitespace-nowrap\">\n <span\n className={`hub-status ${activity.status === 'success' ? 'ok' : 'err'}`}\n >\n <span className=\"hub-dot\" />\n {activity.status === 'success'\n ? t('activity.statusSuccess')\n : t('activity.statusError')}\n </span>\n </td>\n <td\n style={{ padding: '10px 14px', fontSize: 12, color: 'var(--hub-ink-3)' }}\n >\n {activity.group || '—'}\n </td>\n <td\n style={{ padding: '10px 14px', fontSize: 12, color: 'var(--hub-ink-3)' }}\n >\n {activity.username || '—'}\n </td>\n <td\n style={{ padding: '10px 14px', fontSize: 12, color: 'var(--hub-ink-3)' }}\n >\n {activity.keyName || '—'}\n </td>\n <td\n className=\"hub-mono whitespace-nowrap\"\n style={{ padding: '10px 14px', fontSize: 12, color: 'var(--hub-ink-3)' }}\n >\n {activity.sourceIp || '—'}\n </td>\n <td style={{ padding: '10px 14px' }}>\n <button\n onClick={() => handleViewDetails(activity)}\n className=\"hub-btn ghost sm\"\n style={{ color: 'var(--hub-accent)' }}\n >\n {t('common.view')}\n </button>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </div>\n );\n };\n\n // Render detail modal\n const renderDetailModal = () => {\n if (!showDetailModal || !selectedActivity) return null;\n\n const inputData = safeParseJSON(selectedActivity.input);\n const outputData = safeParseJSON(selectedActivity.output);\n\n return (\n <div className=\"fixed inset-0 bg-black/50 flex items-center justify-center z-50\">\n <div\n className=\"hub-card max-w-4xl w-full mx-4 max-h-[90vh] overflow-hidden\"\n style={{ boxShadow: '0 8px 24px rgba(0,0,0,0.12)' }}\n >\n <div\n className=\"flex items-center justify-between px-5 py-3\"\n style={{ borderBottom: '1px solid var(--hub-line-2)' }}\n >\n <h3 className=\"hub-card-title\">{t('activity.details')}</h3>\n <button\n onClick={() => setShowDetailModal(false)}\n className=\"hub-icon-btn sm\"\n aria-label=\"close\"\n >\n <svg className=\"h-3.5 w-3.5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </button>\n </div>\n <div className=\"px-6 py-4 overflow-y-auto max-h-[calc(90vh-120px)]\">\n <div className=\"grid grid-cols-2 gap-4 mb-4\">\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.timestamp')}\n </label>\n <p className=\"text-gray-900 dark:text-white\">\n {formatTimestamp(selectedActivity.timestamp)}\n </p>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.duration')}\n </label>\n <p className=\"text-gray-900 dark:text-white\">\n {formatDuration(selectedActivity.duration)}\n </p>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.server')}\n </label>\n <p className=\"text-gray-900 dark:text-white font-mono\">{selectedActivity.server}</p>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.tool')}\n </label>\n <p className=\"text-gray-900 dark:text-white font-mono\">{selectedActivity.tool}</p>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.status')}\n </label>\n <span\n className={`px-2 py-1 rounded text-xs font-medium ${\n selectedActivity.status === 'success'\n ? 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200'\n : 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200'\n }`}\n >\n {selectedActivity.status === 'success'\n ? t('activity.statusSuccess')\n : t('activity.statusError')}\n </span>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.group')}\n </label>\n <p className=\"text-gray-900 dark:text-white\">{selectedActivity.group || '-'}</p>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.user')}\n </label>\n <p className=\"text-gray-900 dark:text-white\">{selectedActivity.username || '-'}</p>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.sourceIp')}\n </label>\n <p className=\"text-gray-900 dark:text-white font-mono\">\n {selectedActivity.sourceIp || '-'}\n </p>\n </div>\n {selectedActivity.keyName && (\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400\">\n {t('activity.key')}\n </label>\n <p className=\"text-gray-900 dark:text-white\">{selectedActivity.keyName}</p>\n </div>\n )}\n </div>\n\n {selectedActivity.errorMessage && (\n <div className=\"mb-4\">\n <label className=\"block text-sm font-medium text-red-500 mb-1\">\n {t('activity.errorMessage')}\n </label>\n <div className=\"bg-red-50 dark:bg-red-900/20 rounded p-3 text-sm text-red-800 dark:text-red-200\">\n {selectedActivity.errorMessage}\n </div>\n </div>\n )}\n\n {inputData && (\n <div className=\"mb-4\">\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400 mb-1\">\n {t('activity.input')}\n </label>\n <pre className=\"bg-gray-100 dark:bg-gray-700 rounded p-3 text-sm overflow-x-auto max-h-64\">\n {typeof inputData === 'string' ? inputData : JSON.stringify(inputData, null, 2)}\n </pre>\n </div>\n )}\n\n {outputData && (\n <div>\n <label className=\"block text-sm font-medium text-gray-500 dark:text-gray-400 mb-1\">\n {t('activity.output')}\n </label>\n <pre className=\"bg-gray-100 dark:bg-gray-700 rounded p-3 text-sm overflow-x-auto max-h-64\">\n {typeof outputData === 'string'\n ? outputData\n : JSON.stringify(outputData, null, 2)}\n </pre>\n </div>\n )}\n </div>\n </div>\n </div>\n );\n };\n\n return (\n <div>\n <div className=\"flex items-end justify-between gap-4 mb-6\">\n <div>\n <h1 className=\"hub-h1\">{t('activity.title')}</h1>\n <p className=\"hub-sub\">\n <span className=\"hub-num\">{pagination?.total ?? activities.length}</span> entries\n </p>\n </div>\n <button onClick={handleCleanup} className=\"hub-btn danger\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-3.5 w-3.5\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M9 2a1 1 0 00-.894.553L7.382 4H4a1 1 0 000 2v10a2 2 0 002 2h8a2 2 0 002-2V6a1 1 0 100-2h-3.382l-.724-1.447A1 1 0 0011 2H9zM7 8a1 1 0 012 0v6a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v6a1 1 0 102 0V8a1 1 0 00-1-1z\"\n clipRule=\"evenodd\"\n />\n </svg>\n {t('activity.cleanup')}\n </button>\n </div>\n\n {error && (\n <div\n className=\"hub-card flex items-center justify-between gap-3 mb-4\"\n style={{\n padding: '10px 14px',\n borderColor: 'oklch(0.85 0.1 25)',\n background: 'oklch(0.97 0.03 25)',\n color: 'oklch(0.4 0.18 25)',\n }}\n >\n <span className=\"truncate text-[13px]\">{error}</span>\n <button className=\"hub-icon-btn sm\" onClick={() => setError(null)} aria-label=\"close\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-3 w-3\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n </div>\n )}\n\n {isLoading && activities.length === 0 ? (\n <div className=\"hub-card p-10 text-center\" style={{ color: 'var(--hub-ink-3)' }}>\n {t('app.loading')}\n </div>\n ) : (\n <>\n {renderStats()}\n {renderFilters()}\n {renderActivityTable()}\n\n {/* Pagination */}\n <div className=\"flex items-center mt-6\">\n <div className=\"flex-[2] text-sm text-gray-500 dark:text-gray-400\">\n {pagination &&\n t('common.showing', {\n start: (pagination.page - 1) * pagination.limit + 1,\n end: Math.min(pagination.page * pagination.limit, pagination.total),\n total: pagination.total,\n })}\n </div>\n <div className=\"flex-[4] flex justify-center\">\n {pagination && pagination.totalPages > 1 && (\n <Pagination\n currentPage={currentPage}\n totalPages={pagination.totalPages}\n onPageChange={setCurrentPage}\n disabled={isLoading}\n />\n )}\n </div>\n <div className=\"flex-[2] flex items-center justify-end space-x-2\">\n <label htmlFor=\"perPage\" className=\"text-sm text-gray-500 dark:text-gray-400\">\n {t('common.itemsPerPage')}:\n </label>\n <select\n id=\"perPage\"\n value={itemsPerPage}\n onChange={(e) => {\n setItemsPerPage(Number(e.target.value));\n setCurrentPage(1);\n }}\n disabled={isLoading}\n className=\"border border-gray-300 dark:border-gray-600 rounded p-1 text-sm dark:bg-gray-700 dark:text-white outline-none disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n <option value={10}>10</option>\n <option value={20}>20</option>\n <option value={50}>50</option>\n <option value={100}>100</option>\n </select>\n </div>\n </div>\n </>\n )}\n\n {renderDetailModal()}\n </div>\n );\n};\n\nexport default ActivityPage;\n"],"names":["STATUS_OPTIONS","isValidStatus","value","ActivityPage","t","useTranslation","activities","setActivities","useState","stats","setStats","filterOptions","setFilterOptions","pagination","setPagination","currentPage","setCurrentPage","itemsPerPage","setItemsPerPage","isLoading","setIsLoading","error","setError","selectedActivity","setSelectedActivity","showDetailModal","setShowDetailModal","appliedFilters","setAppliedFilters","searchServer","setSearchServer","searchTool","setSearchTool","searchStatus","setSearchStatus","searchGroup","setSearchGroup","searchUsername","setSearchUsername","searchKeyName","setSearchKeyName","fetchData","useCallback","currentFilter","activitiesRes","statsRes","optionsRes","getActivities","getActivityStats","getActivityFilterOptions","err","useEffect","totalPages","handleViewDetails","activity","response","getActivityById","handleCleanup","deleteOldActivities","_a","handleSearch","filters","handleClearFilters","formatDuration","ms","formatTimestamp","timestamp","safeParseJSON","str","renderStats","jsx","s","jsxs","renderFilters","e","status","g","username","k","renderActivityTable","label","renderDetailModal","inputData","outputData","Fragment","Pagination"],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import{r as a,j as o}from"./framework-vendor-_YL27Pfc.js";import{c as P}from"./clipboard-BukcCPLt.js";import{j as L}from"./index-C8aAOWR7.js";import{u as R}from"./i18n-vendor-BMaj5qV8.js";import{X as H,C as J,q as K}from"./icons-vendor-CNEaJWqW.js";const w=(e,n)=>e&&e.trim()?e:n,ce=(e,n)=>{const s=w(e.description,n);return e.hasDescriptionOverride?{currentDescription:s,defaultDescription:w(e.defaultDescription,n),hasDescriptionOverride:!0}:{currentDescription:s,hasDescriptionOverride:!1}},A="generic-mcp-servers",F=[{id:"generic-mcp-servers"},{id:"claude-code"},{id:"cursor"},{id:"vscode"},{id:"codex"},{id:"opencode"},{id:"windsurf"},{id:"cherry-studio"},{id:"codebuddy"},{id:"qoder"},{id:"trae"},{id:"zcode"},{id:"workbuddy"},{id:"generic-http"}],M="<your-access-token>",O="mcphub-token",u=e=>!!e.url,p=e=>{const n=Object.entries(e.headers??{}).filter(([,s])=>s!==void 0);return n.length>0?Object.fromEntries(n):void 0},C=e=>{const n=Object.entries(e.env??{}).filter(([,s])=>s!==void 0);return n.length>0?Object.fromEntries(n):void 0},f=e=>{var t;const n=((t=e.args)==null?void 0:t.filter(i=>i!==void 0))??[],s=C(e);return{command:e.command??"",...n.length>0?{args:n}:{},...s?{env:s}:{}}},_=(e,n=!1)=>{if(!u(e))return n?{type:"stdio",...f(e)}:f(e);const s=p(e);return{type:e.type==="sse"?"sse":"http",url:e.url??"",...s?{headers:s}:{}}},z=e=>{const n=p(e);return{...e.type==="sse"?{type:"sse"}:{},url:e.url??"",...n?{headers:n}:{}}},v=(e,n,s)=>JSON.stringify({[e]:{[n]:s}},null,2),D=e=>v("mcpServers",e.name,u(e)?z(e):f(e)),U=(e,n)=>{const s=p(e),t=`Bearer ${M}`,i=(s==null?void 0:s.Authorization)===t,l=i?{...s,Authorization:`Bearer \${input:${O}}`}:s,d=u(e)?{type:e.type==="sse"?"sse":"http",url:e.url,...l?{headers:l}:{}}:{type:"stdio",...f(e)};return JSON.stringify({servers:{[e.name]:d},...i?{inputs:[{id:O,type:"promptString",description:n.tokenPromptDescription??"MCPHub access token",password:!0}]}:{}},null,2)},W=/^[A-Za-z0-9_-]+$/,N=e=>W.test(e)?e:JSON.stringify(e),h=e=>JSON.stringify(e),q=e=>`{ ${Object.entries(e).map(([n,s])=>`${N(n)} = ${h(s)}`).join(", ")} }`,Z=e=>{var l;const n=N(e.name),s=[`[mcp_servers.${n}]`];if(u(e)){s.push(`url = ${h(e.url??"")}`);const d=p(e);return d&&s.push(`http_headers = ${q(d)}`),s.join(`
2
+ `)}s.push(`command = ${h(e.command??"")}`);const t=((l=e.args)==null?void 0:l.filter(d=>d!==void 0))??[];t.length>0&&s.push(`args = [${t.map(h).join(", ")}]`);const i=C(e);if(i){s.push("",`[mcp_servers.${n}.env]`);for(const[d,b]of Object.entries(i))s.push(`${N(d)} = ${h(b)}`)}return s.join(`
3
+ `)},Q=e=>{var s;if(!u(e)){const t=C(e),i=((s=e.args)==null?void 0:s.filter(l=>l!==void 0))??[];return JSON.stringify({mcp:{[e.name]:{type:"local",command:[e.command??"",...i],...t?{environment:t}:{}}}},null,2)}const n=p(e);return JSON.stringify({mcp:{[e.name]:{type:"remote",url:e.url,...n?{headers:n}:{}}}},null,2)},V=e=>{const n={name:e.name,description:e.description??""},s=p(e),t=u(e)?{...n,type:e.type==="sse"?"sse":"streamableHttp",baseUrl:e.url,...s?{headers:s}:{}}:{...n,type:"stdio",...f(e)};return v("mcpServers",e.name,t)},X=/^[A-Za-z0-9._:@/=-]+$/,Y=e=>`'${e.replace(/'/g,"'\\''")}'`,S=e=>X.test(e)?e:Y(e),G=e=>{if(!u(e)||e.name.startsWith("-")||(e.url??"").startsWith("-"))return;const n=["claude","mcp","add","--transport",e.type==="sse"?"sse":"http",S(e.name),S(e.url??"")];for(const[s,t]of Object.entries(p(e)??{}))n.push("--header",S(`${s}: ${t}`));return n.join(" ")},m=e=>typeof e=="string"&&e.length>0?e:void 0,I=e=>{switch(e){case"stdio":case"sse":case"streamable-http":case"openapi":return e;default:return}},y=e=>{if(!e||typeof e!="object"||Array.isArray(e))return;const n=Object.entries(e).filter(s=>typeof s[1]=="string");return n.length>0?Object.fromEntries(n):void 0},g=e=>{if(!Array.isArray(e))return;const n=e.filter(s=>typeof s=="string");return n.length>0?n:void 0},le=(e,n)=>{const s=n??{};return{name:e,...I(s.type)?{type:I(s.type)}:{},...m(s.url)?{url:m(s.url)}:{},...y(s.headers)?{headers:y(s.headers)}:{},...m(s.command)?{command:m(s.command)}:{},...g(s.args)?{args:g(s.args)}:{},...y(s.env)?{env:y(s.env)}:{},...m(s.description)?{description:m(s.description)}:{}}},ee=(e,n,s)=>{switch(e){case"generic-mcp-servers":return D(n);case"generic-http":return JSON.stringify(u(n)?{type:"http",...z(n)}:f(n),null,2);case"vscode":return U(n,s);case"codex":return Z(n);case"opencode":return Q(n);case"cherry-studio":return V(n);case"claude-code":return v("mcpServers",n.name,_(n));case"codebuddy":return v("mcpServers",n.name,_(n,!0));default:return D(n)}},ne=(e,n,s={})=>{if(!n.url&&!n.command)return[];const t=[{kind:"config",text:ee(e,n,s)}];if(e==="claude-code"){const i=G(n);i&&t.push({kind:"command",text:i})}return t},de=({isOpen:e,onClose:n,target:s})=>{const{t}=R(),{showToast:i}=L(),[l,d]=a.useState(A),[b,x]=a.useState(null),E=a.useRef(null),T=a.useRef(null);a.useEffect(()=>{e||(x(null),d(A))},[e]),a.useEffect(()=>{var r;if(e)return T.current=document.activeElement instanceof HTMLElement?document.activeElement:null,(r=E.current)==null||r.focus(),()=>{var c;(c=T.current)==null||c.focus()}},[e]),a.useEffect(()=>{if(!e)return;const r=c=>{c.key==="Escape"&&n()};return document.addEventListener("keydown",r),()=>document.removeEventListener("keydown",r)},[e,n]);const j=a.useMemo(()=>s?ne(l,s,{tokenPromptDescription:t("clientConfig.tokenPrompt")}):[],[l,s,t]);if(!e||!s)return null;const B=async(r,c)=>{if(!await P(c)){i(t("common.copyFailed"),"error");return}x(r),i(t("common.copySuccess"),"success"),setTimeout(()=>x($=>$===r?null:$),1500)};return o.jsx("div",{className:"fixed inset-0 bg-black/50 z-[100] flex items-center justify-center p-4",onClick:r=>{r.target===r.currentTarget&&n()},children:o.jsxs("div",{ref:E,tabIndex:-1,className:"hub-card w-full max-w-2xl",role:"dialog","aria-modal":"true","aria-label":t("clientConfig.title"),children:[o.jsxs("div",{className:"flex items-start justify-between gap-3 px-4 py-3",style:{borderBottom:"1px solid var(--hub-line-2)"},children:[o.jsxs("div",{className:"min-w-0",children:[o.jsx("div",{className:"text-[14px] font-medium",style:{color:"var(--hub-ink)"},children:t("clientConfig.title")}),o.jsx("div",{className:"text-[12px] mt-0.5",style:{color:"var(--hub-ink-3)"},children:t("clientConfig.description",{name:s.name})})]}),o.jsx("button",{className:"hub-icon-btn sm",onClick:n,"aria-label":t("app.closeButton"),children:o.jsx(H,{size:13})})]}),j.length>0&&o.jsxs("div",{className:"px-4 pt-3",children:[o.jsx("div",{className:"flex flex-wrap gap-1",role:"tablist","aria-label":t("clientConfig.title"),children:F.map(r=>{const c=r.id===l;return o.jsx("button",{role:"tab","aria-selected":c,onClick:()=>d(r.id),className:"px-2.5 py-1 rounded-md text-[12px] transition-colors hover:bg-[var(--hub-surface-hover)]",style:{background:c?"var(--hub-surface)":"transparent",border:"1px solid "+(c?"var(--hub-line)":"transparent"),color:c?"var(--hub-ink)":"var(--hub-ink-2)"},children:t(`clientConfig.clients.${r.id}.label`)},r.id)})}),o.jsx("p",{className:"text-[12px] mt-3",style:{color:"var(--hub-ink-3)"},children:t(`clientConfig.clients.${l}.hint`)})]}),o.jsx("div",{className:"px-4 pb-4 pt-2 space-y-3 max-h-[60vh] overflow-auto",children:j.length===0?o.jsx("p",{className:"text-[12px]",style:{color:"var(--hub-ink-3)"},children:t("clientConfig.noTransport")}):j.map(r=>{const c=`${l}:${r.kind}`,k=b===c;return o.jsxs("div",{children:[o.jsxs("div",{className:"flex items-center justify-between mb-1",children:[o.jsx("span",{className:"text-[12px]",style:{color:"var(--hub-ink-2)"},children:t(r.kind==="command"?"clientConfig.commandBlock":"clientConfig.configBlock")}),o.jsxs("button",{className:"hub-btn sm",onClick:()=>void B(c,r.text),children:[k?o.jsx(J,{size:12,className:"text-[var(--hub-ok)]"}):o.jsx(K,{size:12}),t(k?"clientConfig.copied":"common.copy")]})]}),o.jsx("pre",{className:"hub-mono m-0 p-3 rounded-md overflow-auto",style:{background:"var(--hub-bg-2)",border:"1px solid var(--hub-line-2)",fontSize:12,lineHeight:1.5,color:"var(--hub-ink-2)",maxHeight:320},children:o.jsx("code",{children:r.text})})]},c)})}),o.jsx("div",{className:"flex justify-end px-4 py-3",style:{borderTop:"1px solid var(--hub-line-2)"},children:o.jsx("button",{className:"hub-btn",onClick:n,children:t("common.cancel")})})]})})};export{M as A,de as C,ce as g,le as t};
4
+ //# sourceMappingURL=CopyClientConfigDialog-C6U6_eyy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CopyClientConfigDialog-C6U6_eyy.js","sources":["../../src/utils/toolDescription.ts","../../src/utils/mcpClientSnippets.ts","../../src/components/ui/CopyClientConfigDialog.tsx"],"sourcesContent":["type ToolDescriptionSource = {\n description?: string;\n defaultDescription?: string;\n hasDescriptionOverride?: boolean;\n};\n\nexport interface ToolDescriptionInfo {\n currentDescription: string;\n defaultDescription?: string;\n hasDescriptionOverride: boolean;\n}\n\nconst normalizeDescription = (description: string | undefined, fallback: string): string => {\n return description && description.trim() ? description : fallback;\n};\n\nexport const getToolDescriptionInfo = (\n tool: ToolDescriptionSource,\n noDescriptionText: string,\n): ToolDescriptionInfo => {\n const currentDescription = normalizeDescription(tool.description, noDescriptionText);\n\n if (!tool.hasDescriptionOverride) {\n return {\n currentDescription,\n hasDescriptionOverride: false,\n };\n }\n\n return {\n currentDescription,\n defaultDescription: normalizeDescription(tool.defaultDescription, noDescriptionText),\n hasDescriptionOverride: true,\n };\n};\n","/**\n * Per-client MCP configuration presets for the copy actions (#1165).\n *\n * MCPHub hands out HTTP endpoints, so every preset describes the same target -\n * a name, an optional URL/headers pair (HTTP) or command/args/env triple\n * (stdio) - in the shape the selected client expects. Eleven of the fourteen\n * presets were verified against the upstream sources below (URLs re-checked\n * 2026-09, the month this file landed); the remaining three reuse the generic\n * `mcpServers` shape (or, for the generic-http escape hatch, the bare entry)\n * these copy actions always produced.\n *\n * Which clients document an explicit transport field, and which do not:\n * - Documents a transport field (the `type` key is written into the entry):\n * claude-code (`type: \"http\" | \"sse\" | \"stdio\"`; a remote entry with `url`\n * but no `type` is a configuration error per\n * https://code.claude.com/docs/en/mcp), vscode (`\"http\" | \"sse\" | \"stdio\"`,\n * final URL after the 2026-09 migration:\n * https://code.visualstudio.com/docs/agent-customization/mcp-servers),\n * codebuddy (`type` marked Required; fixed `\"http\"` for HTTP, `\"sse\"` for\n * SSE and `\"stdio\"` for stdio, per\n * https://www.codebuddy.ai/docs/cli/mcp), qoder (every remote\n * example carries `type`; for Streamable HTTP the doc says to configure the\n * URL the same way as SSE and the IDE auto-detects it, so the http target\n * deliberately keeps the bare `url` + `headers` shape rather than tagging\n * it `sse`; https://docs.qoder.com/zh/user-guide/chat/model-context-protocol),\n * cherry-studio (`baseUrl` + `'sse' | 'streamableHttp'`, strict schema),\n * opencode (`type: 'remote' | 'local'`).\n * - Field table does not list a transport key: cursor\n * (https://cursor.com/docs/mcp), trae (https://docs.trae.ai/ide/add-mcp-servers),\n * zcode (https://zcode.z.ai/en/docs/mcp-services), windsurf\n * (https://docs.windsurf.com/windsurf/cascade/mcp). The `type: \"sse\"` marker\n * the generic shape injects for SSE targets on these presets is added on\n * the assumption that unknown keys are ignored, not required by their\n * documented shape; it is kept because SSE upstreams must not be dialed as\n * streamable HTTP.\n * - Verified but the format carries no `type` key at all: codex (TOML;\n * `codex-rs/config/src/mcp_types.rs`,\n * https://github.com/openai/codex/blob/main/codex-rs/config/src/mcp_types.rs).\n * (The generic-http escape hatch, one of the three unverified presets, is not\n * a \"no `type`\" format: for a remote target it always writes an explicit\n * `type` - `\"http\"`, or `\"sse\"` for an SSE upstream.)\n *\n * Upstream sources used:\n * - Claude Code MCP configuration: https://code.claude.com/docs/en/mcp\n * - Cursor MCP docs: https://cursor.com/docs/mcp\n * - VS Code MCP configuration reference:\n * https://code.visualstudio.com/docs/agent-customization/mcp-servers\n * - Codex `codex-rs/config/src/mcp_types.rs`:\n * https://github.com/openai/codex/blob/main/codex-rs/config/src/mcp_types.rs\n * - OpenCode mcp-servers docs: https://opencode.ai/docs/mcp-servers/\n * - Cherry Studio `mcpProtocolInstall.ts`:\n * https://github.com/CherryHQ/cherry-studio/blob/main/src/shared/data/types/mcpProtocolInstall.ts\n * - CodeBuddy MCP CLI docs: https://www.codebuddy.ai/docs/cli/mcp\n * - Qoder MCP user guide:\n * https://docs.qoder.com/zh/user-guide/chat/model-context-protocol\n * - Trae MCP docs: https://docs.trae.ai/ide/add-mcp-servers\n * - Windsurf MCP docs: https://docs.windsurf.com/windsurf/cascade/mcp\n * - ZCode MCP docs: https://zcode.z.ai/en/docs/mcp-services\n */\n\nexport type ClientSnippetId =\n | 'generic-mcp-servers'\n | 'generic-http'\n | 'claude-code'\n | 'cursor'\n | 'vscode'\n | 'codex'\n | 'opencode'\n | 'windsurf'\n | 'cherry-studio'\n | 'codebuddy'\n | 'qoder'\n | 'trae'\n | 'zcode'\n | 'workbuddy';\n\nexport interface ClientSnippetPreset {\n id: ClientSnippetId;\n}\n\n/** Tab the dialog opens on; the shape the copy actions produced before. */\nexport const DEFAULT_CLIENT_SNIPPET_ID: ClientSnippetId = 'generic-mcp-servers';\n\n/**\n * Tabs shown in the copy dialog, most common clients first. The first entry is\n * the shape the copy actions produced before the presets existed, so the\n * default tab stays familiar; the bare HTTP entry is the escape hatch for\n * clients that wrap the entry in their own container.\n */\nexport const CLIENT_SNIPPET_PRESETS: readonly ClientSnippetPreset[] = [\n { id: 'generic-mcp-servers' },\n { id: 'claude-code' },\n { id: 'cursor' },\n { id: 'vscode' },\n { id: 'codex' },\n { id: 'opencode' },\n { id: 'windsurf' },\n { id: 'cherry-studio' },\n { id: 'codebuddy' },\n { id: 'qoder' },\n { id: 'trae' },\n { id: 'zcode' },\n { id: 'workbuddy' },\n { id: 'generic-http' },\n];\n\nexport interface ClientSnippetTarget {\n name: string;\n /** Stored transport type; `sse` is called out so clients do not misdial it as http. */\n type?: 'stdio' | 'sse' | 'streamable-http' | 'openapi';\n /** HTTP targets carry a URL (and usually an Authorization header). */\n url?: string;\n headers?: Record<string, string>;\n /** stdio targets carry a command instead. */\n command?: string;\n args?: string[];\n env?: Record<string, string>;\n description?: string;\n}\n\nexport interface ClientSnippetBlock {\n kind: 'config' | 'command';\n text: string;\n}\n\nexport interface ClientSnippetOptions {\n /** Description used by the VS Code token input prompt. */\n tokenPromptDescription?: string;\n}\n\n/** Placeholder MCPHub uses for snippets that need a token pasted in by hand. */\nexport const ACCESS_TOKEN_PLACEHOLDER = '<your-access-token>';\nconst TOKEN_INPUT_ID = 'mcphub-token';\n\nconst isHttpTarget = (target: ClientSnippetTarget): boolean => Boolean(target.url);\n\nconst definedHeaders = (target: ClientSnippetTarget): Record<string, string> | undefined => {\n const entries = Object.entries(target.headers ?? {}).filter(([, value]) => value !== undefined);\n return entries.length > 0 ? Object.fromEntries(entries) : undefined;\n};\n\nconst definedEnv = (target: ClientSnippetTarget): Record<string, string> | undefined => {\n const entries = Object.entries(target.env ?? {}).filter(([, value]) => value !== undefined);\n return entries.length > 0 ? Object.fromEntries(entries) : undefined;\n};\n\nconst stdioEntry = (target: ClientSnippetTarget): Record<string, unknown> => {\n const args = target.args?.filter((arg) => arg !== undefined) ?? [];\n const env = definedEnv(target);\n return {\n command: target.command ?? '',\n ...(args.length > 0 ? { args } : {}),\n ...(env ? { env } : {}),\n };\n};\n\n/**\n * HTTP/stdio entry for clients whose docs make the transport a required field.\n * Claude Code skips an entry that has a `url` but no `type` (it reads the\n * entry as stdio and reports a configuration error), and CodeBuddy's field\n * table marks `type` as Required, fixed to `\"http\"` for the HTTP form and\n * `\"sse\"` for the SSE form.\n *\n * Stdio targets differ between the two clients. Claude Code reads a type-less\n * entry as stdio (https://code.claude.com/docs/en/mcp), so its stdio shape\n * keeps the plain command/args/env form with no `type` key. CodeBuddy's docs\n * mark `type` as Required with the fixed value `\"stdio\"`\n * (https://www.codebuddy.ai/docs/cli/mcp), so its stdio shape writes\n * `\"type\": \"stdio\"`; pass `stdioType` only for CodeBuddy.\n */\nconst typedTransportEntry = (\n target: ClientSnippetTarget,\n stdioType: boolean = false,\n): Record<string, unknown> => {\n if (!isHttpTarget(target)) {\n return stdioType ? { type: 'stdio', ...stdioEntry(target) } : stdioEntry(target);\n }\n\n const headers = definedHeaders(target);\n return {\n type: target.type === 'sse' ? 'sse' : 'http',\n url: target.url ?? '',\n ...(headers ? { headers } : {}),\n };\n};\n\n// This helper feeds the generic `mcpServers` shape for the generic-mcp-servers,\n// qoder, cursor, windsurf, trae, zcode and workbuddy presets. Only qoder's\n// upstream docs carry a transport field for this shape; for the rest\n// (generic-mcp-servers, cursor, windsurf, trae, zcode, workbuddy) the\n// `type: \"sse\"` marker is added on the assumption that unknown keys are\n// ignored, so it is unverified against a field table. It is kept because an\n// SSE upstream must not be dialed as streamable HTTP.\nconst httpEntry = (target: ClientSnippetTarget): Record<string, unknown> => {\n const headers = definedHeaders(target);\n return {\n // Only `sse` is spelled out: it is the one HTTP transport a client might\n // otherwise misdial as streamable HTTP. Every other target keeps the bare\n // `url` + `headers` shape these presets always produced.\n ...(target.type === 'sse' ? { type: 'sse' } : {}),\n url: target.url ?? '',\n ...(headers ? { headers } : {}),\n };\n};\n\nconst withWrappedName = (\n wrapper: string,\n name: string,\n entry: Record<string, unknown>,\n): string => JSON.stringify({ [wrapper]: { [name]: entry } }, null, 2);\n\nconst jsonSnippet = (target: ClientSnippetTarget): string =>\n withWrappedName(\n 'mcpServers',\n target.name,\n isHttpTarget(target) ? httpEntry(target) : stdioEntry(target),\n );\n\n// VS Code wants the transport spelled out and can prompt for the token itself,\n// so the shared placeholder becomes an input reference plus an `inputs` entry.\nconst vscodeSnippet = (target: ClientSnippetTarget, options: ClientSnippetOptions): string => {\n const headers = definedHeaders(target);\n const placeholder = `Bearer ${ACCESS_TOKEN_PLACEHOLDER}`;\n const needsTokenInput = headers?.Authorization === placeholder;\n\n const body = needsTokenInput\n ? { ...headers, Authorization: `Bearer \\${input:${TOKEN_INPUT_ID}}` }\n : headers;\n\n const entry = isHttpTarget(target)\n ? {\n // VS Code distinguishes the SSE transport from streamable HTTP.\n type: target.type === 'sse' ? 'sse' : 'http',\n url: target.url,\n ...(body ? { headers: body } : {}),\n }\n : { type: 'stdio', ...stdioEntry(target) };\n\n return JSON.stringify(\n {\n servers: { [target.name]: entry },\n ...(needsTokenInput\n ? {\n inputs: [\n {\n id: TOKEN_INPUT_ID,\n type: 'promptString',\n description: options.tokenPromptDescription ?? 'MCPHub access token',\n password: true,\n },\n ],\n }\n : {}),\n },\n null,\n 2,\n );\n};\n\nconst TOML_BARE_KEY = /^[A-Za-z0-9_-]+$/;\n\nconst tomlKey = (key: string): string => (TOML_BARE_KEY.test(key) ? key : JSON.stringify(key));\nconst tomlValue = (value: string): string => JSON.stringify(value);\nconst tomlInlineTable = (entries: Record<string, string>): string =>\n `{ ${Object.entries(entries)\n .map(([key, value]) => `${tomlKey(key)} = ${tomlValue(value)}`)\n .join(', ')} }`;\n\n// Codex calls the header map `http_headers` (there is no `headers` key), and\n// needs quoted table keys for names that are not bare TOML keys - group names\n// may contain spaces or CJK. Note `#[schemars(deny_unknown_fields)]` in\n// `mcp_types.rs` only constrains the generated JSON Schema; the Rust struct\n// itself has no `#[serde(deny_unknown_fields)]`, so TOML parsing may silently\n// ignore unknown fields instead of rejecting them.\nconst codexSnippet = (target: ClientSnippetTarget): string => {\n const key = tomlKey(target.name);\n const lines = [`[mcp_servers.${key}]`];\n\n if (isHttpTarget(target)) {\n lines.push(`url = ${tomlValue(target.url ?? '')}`);\n const headers = definedHeaders(target);\n if (headers) {\n lines.push(`http_headers = ${tomlInlineTable(headers)}`);\n }\n return lines.join('\\n');\n }\n\n lines.push(`command = ${tomlValue(target.command ?? '')}`);\n const args = target.args?.filter((arg) => arg !== undefined) ?? [];\n if (args.length > 0) {\n lines.push(`args = [${args.map(tomlValue).join(', ')}]`);\n }\n const env = definedEnv(target);\n if (env) {\n lines.push('', `[mcp_servers.${key}.env]`);\n for (const [name, value] of Object.entries(env)) {\n lines.push(`${tomlKey(name)} = ${tomlValue(value)}`);\n }\n }\n return lines.join('\\n');\n};\n\nconst openCodeSnippet = (target: ClientSnippetTarget): string => {\n if (!isHttpTarget(target)) {\n const env = definedEnv(target);\n const args = target.args?.filter((arg) => arg !== undefined) ?? [];\n return JSON.stringify(\n {\n mcp: {\n [target.name]: {\n type: 'local',\n command: [target.command ?? '', ...args],\n ...(env ? { environment: env } : {}),\n },\n },\n },\n null,\n 2,\n );\n }\n\n const headers = definedHeaders(target);\n return JSON.stringify(\n {\n mcp: {\n [target.name]: {\n type: 'remote',\n url: target.url,\n ...(headers ? { headers } : {}),\n },\n },\n },\n null,\n 2,\n );\n};\n\n// Cherry Studio's `ProtocolMcpServerConfigSchema` is a strict object: remote\n// servers use `baseUrl` + `type: 'sse' | 'streamableHttp'` (no `url` key) and\n// stdio servers use command/args/env. The install-time metadata\n// (`installSource`, `isTrusted`, `installedAt`, `isActive: false`) belongs to\n// `ProtocolMcpServerInstallSchema`, the install *request* schema, not to this\n// hand-pasted config; an entry carrying `isActive` would not satisfy\n// `ProtocolMcpServerConfigSchema` (which has no such key).\nconst cherryStudioSnippet = (target: ClientSnippetTarget): string => {\n const base = {\n name: target.name,\n description: target.description ?? '',\n };\n\n const headers = definedHeaders(target);\n const entry = isHttpTarget(target)\n ? {\n ...base,\n // The schema accepts exactly two remote transports; keep SSE upstreams\n // spelled out so Cherry Studio does not dial them as streamable HTTP.\n type: target.type === 'sse' ? 'sse' : 'streamableHttp',\n baseUrl: target.url,\n ...(headers ? { headers } : {}),\n }\n : { ...base, type: 'stdio', ...stdioEntry(target) };\n\n return withWrappedName('mcpServers', target.name, entry);\n};\n\nconst CLI_SAFE = /^[A-Za-z0-9._:@/=-]+$/;\n\n// Single quotes are the only reliable POSIX quoting for a pasted command:\n// double quotes still let the shell expand `$(...)`, backticks and `${...}`\n// inside them. Within single quotes nothing is expanded, so the only character\n// needing special handling is `'` itself, escaped as `'\\''` (close quote,\n// escaped quote, reopen).\nconst shellQuote = (value: string): string => `'${value.replace(/'/g, \"'\\\\''\")}'`;\n\nconst cliArg = (value: string): string =>\n CLI_SAFE.test(value) ? value : shellQuote(value);\n\n// Claude Code's one-liner equivalent of the JSON block, in the documented\n// HTTP shape: `claude mcp add --transport <t> <name> <url> [--header ...]`.\n//\n// A positional that starts with `-` cannot be spelled safely in that shape:\n// shell quoting is gone by the time the CLI's tokenizer sees the value, and\n// the documented `--` separator belongs to the stdio form, so relying on it\n// for the HTTP form would be an unverified parsing assumption. Since\n// SERVER_NAME_PATTERN admits names like `-foo`, a name or URL starting with\n// a dash omits the command block outright - the JSON config block still\n// carries the full entry - rather than emitting a command the CLI would\n// misparse as one of its own options.\nconst claudeCodeCommand = (target: ClientSnippetTarget): string | undefined => {\n if (!isHttpTarget(target)) {\n return undefined;\n }\n\n if (target.name.startsWith('-') || (target.url ?? '').startsWith('-')) {\n return undefined;\n }\n\n const parts = [\n 'claude',\n 'mcp',\n 'add',\n '--transport',\n // SSE endpoints must not be dialed as streamable HTTP.\n target.type === 'sse' ? 'sse' : 'http',\n cliArg(target.name),\n cliArg(target.url ?? ''),\n ];\n for (const [name, value] of Object.entries(definedHeaders(target) ?? {})) {\n parts.push('--header', cliArg(`${name}: ${value}`));\n }\n return parts.join(' ');\n};\n\nconst asString = (value: unknown): string | undefined =>\n typeof value === 'string' && value.length > 0 ? value : undefined;\n\n/** Narrow a stored `type` to the four legal server types; anything else is dropped. */\nconst asServerType = (value: unknown): ClientSnippetTarget['type'] => {\n switch (value) {\n case 'stdio':\n case 'sse':\n case 'streamable-http':\n case 'openapi':\n return value;\n default:\n return undefined;\n }\n};\n\nconst asStringRecord = (value: unknown): Record<string, string> | undefined => {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return undefined;\n }\n\n const entries = Object.entries(value as Record<string, unknown>).filter(\n (entry): entry is [string, string] => typeof entry[1] === 'string',\n );\n return entries.length > 0 ? Object.fromEntries(entries) : undefined;\n};\n\nconst asStringArray = (value: unknown): string[] | undefined => {\n if (!Array.isArray(value)) {\n return undefined;\n }\n\n const items = value.filter((item): item is string => typeof item === 'string');\n return items.length > 0 ? items : undefined;\n};\n\n/**\n * Narrow a stored server configuration (the `mcp-settings/export` payload\n * carries MCPHub's internal fields too) down to what a client snippet needs.\n */\nexport const toClientSnippetTarget = (\n name: string,\n config: Record<string, unknown> | undefined,\n): ClientSnippetTarget => {\n const source = config ?? {};\n\n return {\n name,\n ...(asServerType(source.type) ? { type: asServerType(source.type) } : {}),\n ...(asString(source.url) ? { url: asString(source.url) } : {}),\n ...(asStringRecord(source.headers) ? { headers: asStringRecord(source.headers) } : {}),\n ...(asString(source.command) ? { command: asString(source.command) } : {}),\n ...(asStringArray(source.args) ? { args: asStringArray(source.args) } : {}),\n ...(asStringRecord(source.env) ? { env: asStringRecord(source.env) } : {}),\n ...(asString(source.description) ? { description: asString(source.description) } : {}),\n };\n};\n\nconst configSnippet = (\n id: ClientSnippetId,\n target: ClientSnippetTarget,\n options: ClientSnippetOptions,\n): string => {\n switch (id) {\n case 'generic-mcp-servers':\n return jsonSnippet(target);\n case 'generic-http':\n return JSON.stringify(\n isHttpTarget(target)\n ? { type: 'http', ...httpEntry(target) }\n : stdioEntry(target),\n null,\n 2,\n );\n case 'vscode':\n return vscodeSnippet(target, options);\n case 'codex':\n return codexSnippet(target);\n case 'opencode':\n return openCodeSnippet(target);\n case 'cherry-studio':\n return cherryStudioSnippet(target);\n case 'claude-code':\n return withWrappedName('mcpServers', target.name, typedTransportEntry(target));\n case 'codebuddy':\n // CodeBuddy's field table marks `type` as Required, fixed to `\"stdio\"`\n // for stdio entries, so unlike Claude Code it always carries the type.\n return withWrappedName('mcpServers', target.name, typedTransportEntry(target, true));\n default:\n return jsonSnippet(target);\n }\n};\n\nexport const buildClientSnippetBlocks = (\n id: ClientSnippetId,\n target: ClientSnippetTarget,\n options: ClientSnippetOptions = {},\n): ClientSnippetBlock[] => {\n // OpenAPI-backed servers carry neither a URL nor a command, so every preset\n // would degrade to filler like `command: \"\"`. Return no blocks and let the\n // dialog explain that there is no client-side transport to copy.\n if (!target.url && !target.command) {\n return [];\n }\n\n const blocks: ClientSnippetBlock[] = [{ kind: 'config', text: configSnippet(id, target, options) }];\n\n if (id === 'claude-code') {\n const command = claudeCodeCommand(target);\n if (command) {\n blocks.push({ kind: 'command', text: command });\n }\n }\n\n return blocks;\n};\n","import { useEffect, useMemo, useRef, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Check, Copy, X } from 'lucide-react';\nimport {\n buildClientSnippetBlocks,\n CLIENT_SNIPPET_PRESETS,\n DEFAULT_CLIENT_SNIPPET_ID,\n type ClientSnippetId,\n type ClientSnippetTarget,\n} from '@/utils/mcpClientSnippets';\nimport { copyText } from '@/utils/clipboard';\nimport { useToast } from '@/contexts/ToastContext';\n\ninterface CopyClientConfigDialogProps {\n isOpen: boolean;\n onClose: () => void;\n /** Target to render; `null` keeps the dialog closed. */\n target: ClientSnippetTarget | null;\n}\n\n/**\n * Per-client MCP configuration presets for the copy actions (#1165): one tab\n * per client, each with the path it belongs in and a ready-to-paste snippet.\n */\nconst CopyClientConfigDialog = ({ isOpen, onClose, target }: CopyClientConfigDialogProps) => {\n const { t } = useTranslation();\n const { showToast } = useToast();\n const [activeId, setActiveId] = useState<ClientSnippetId>(DEFAULT_CLIENT_SNIPPET_ID);\n const [copiedBlock, setCopiedBlock] = useState<string | null>(null);\n const dialogRef = useRef<HTMLDivElement>(null);\n const returnFocusRef = useRef<HTMLElement | null>(null);\n\n useEffect(() => {\n if (!isOpen) {\n setCopiedBlock(null);\n setActiveId(DEFAULT_CLIENT_SNIPPET_ID);\n }\n }, [isOpen]);\n\n // Like the other hand-rolled modals in this codebase the dialog does not trap\n // focus; it does move focus inside on open and hand it back to the trigger on\n // close, so keyboard users are not left behind on the page underneath.\n useEffect(() => {\n if (!isOpen) return;\n returnFocusRef.current =\n document.activeElement instanceof HTMLElement ? document.activeElement : null;\n dialogRef.current?.focus();\n\n return () => {\n returnFocusRef.current?.focus();\n };\n }, [isOpen]);\n\n useEffect(() => {\n if (!isOpen) return;\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') onClose();\n };\n document.addEventListener('keydown', onKeyDown);\n return () => document.removeEventListener('keydown', onKeyDown);\n }, [isOpen, onClose]);\n\n const blocks = useMemo(\n () =>\n target\n ? buildClientSnippetBlocks(activeId, target, {\n tokenPromptDescription: t('clientConfig.tokenPrompt'),\n })\n : [],\n [activeId, target, t],\n );\n\n if (!isOpen || !target) {\n return null;\n }\n\n const handleCopy = async (key: string, value: string) => {\n const ok = await copyText(value);\n if (!ok) {\n showToast(t('common.copyFailed'), 'error');\n return;\n }\n setCopiedBlock(key);\n showToast(t('common.copySuccess'), 'success');\n setTimeout(() => setCopiedBlock((current) => (current === key ? null : current)), 1500);\n };\n\n return (\n <div\n className=\"fixed inset-0 bg-black/50 z-[100] flex items-center justify-center p-4\"\n onClick={(event) => {\n if (event.target === event.currentTarget) onClose();\n }}\n >\n <div\n ref={dialogRef}\n tabIndex={-1}\n className=\"hub-card w-full max-w-2xl\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={t('clientConfig.title')}\n >\n <div\n className=\"flex items-start justify-between gap-3 px-4 py-3\"\n style={{ borderBottom: '1px solid var(--hub-line-2)' }}\n >\n <div className=\"min-w-0\">\n <div className=\"text-[14px] font-medium\" style={{ color: 'var(--hub-ink)' }}>\n {t('clientConfig.title')}\n </div>\n <div className=\"text-[12px] mt-0.5\" style={{ color: 'var(--hub-ink-3)' }}>\n {t('clientConfig.description', { name: target.name })}\n </div>\n </div>\n <button className=\"hub-icon-btn sm\" onClick={onClose} aria-label={t('app.closeButton')}>\n <X size={13} />\n </button>\n </div>\n\n {/* A target with neither URL nor command (OpenAPI-backed servers) has no\n transport, so every preset returns the same empty result: offering 14\n clickable tabs would only suggest the dialog is broken. The tab strip\n and its per-client hint are therefore hidden and only the explanation\n below is shown. */}\n {blocks.length > 0 && (\n <div className=\"px-4 pt-3\">\n <div\n className=\"flex flex-wrap gap-1\"\n role=\"tablist\"\n aria-label={t('clientConfig.title')}\n >\n {CLIENT_SNIPPET_PRESETS.map((preset) => {\n const active = preset.id === activeId;\n return (\n <button\n key={preset.id}\n role=\"tab\"\n aria-selected={active}\n onClick={() => setActiveId(preset.id)}\n className=\"px-2.5 py-1 rounded-md text-[12px] transition-colors hover:bg-[var(--hub-surface-hover)]\"\n style={{\n background: active ? 'var(--hub-surface)' : 'transparent',\n border: '1px solid ' + (active ? 'var(--hub-line)' : 'transparent'),\n color: active ? 'var(--hub-ink)' : 'var(--hub-ink-2)',\n }}\n >\n {t(`clientConfig.clients.${preset.id}.label`)}\n </button>\n );\n })}\n </div>\n\n <p className=\"text-[12px] mt-3\" style={{ color: 'var(--hub-ink-3)' }}>\n {t(`clientConfig.clients.${activeId}.hint`)}\n </p>\n </div>\n )}\n\n <div className=\"px-4 pb-4 pt-2 space-y-3 max-h-[60vh] overflow-auto\">\n {blocks.length === 0 ? (\n // OpenAPI-backed servers have no client-side transport to copy.\n <p className=\"text-[12px]\" style={{ color: 'var(--hub-ink-3)' }}>\n {t('clientConfig.noTransport')}\n </p>\n ) : (\n blocks.map((block) => {\n const key = `${activeId}:${block.kind}`;\n const copied = copiedBlock === key;\n return (\n <div key={key}>\n <div className=\"flex items-center justify-between mb-1\">\n <span className=\"text-[12px]\" style={{ color: 'var(--hub-ink-2)' }}>\n {t(\n block.kind === 'command'\n ? 'clientConfig.commandBlock'\n : 'clientConfig.configBlock',\n )}\n </span>\n <button\n className=\"hub-btn sm\"\n onClick={() => void handleCopy(key, block.text)}\n >\n {copied ? <Check size={12} className=\"text-[var(--hub-ok)]\" /> : <Copy size={12} />}\n {copied ? t('clientConfig.copied') : t('common.copy')}\n </button>\n </div>\n <pre\n className=\"hub-mono m-0 p-3 rounded-md overflow-auto\"\n style={{\n background: 'var(--hub-bg-2)',\n border: '1px solid var(--hub-line-2)',\n fontSize: 12,\n lineHeight: 1.5,\n color: 'var(--hub-ink-2)',\n maxHeight: 320,\n }}\n >\n <code>{block.text}</code>\n </pre>\n </div>\n );\n })\n )}\n </div>\n\n <div\n className=\"flex justify-end px-4 py-3\"\n style={{ borderTop: '1px solid var(--hub-line-2)' }}\n >\n <button className=\"hub-btn\" onClick={onClose}>\n {t('common.cancel')}\n </button>\n </div>\n </div>\n </div>\n );\n};\n\nexport default CopyClientConfigDialog;\n"],"names":["normalizeDescription","description","fallback","getToolDescriptionInfo","tool","noDescriptionText","currentDescription","DEFAULT_CLIENT_SNIPPET_ID","CLIENT_SNIPPET_PRESETS","ACCESS_TOKEN_PLACEHOLDER","TOKEN_INPUT_ID","isHttpTarget","target","definedHeaders","entries","value","definedEnv","stdioEntry","args","_a","arg","env","typedTransportEntry","stdioType","headers","httpEntry","withWrappedName","wrapper","name","entry","jsonSnippet","vscodeSnippet","options","placeholder","needsTokenInput","body","TOML_BARE_KEY","tomlKey","key","tomlValue","tomlInlineTable","codexSnippet","lines","openCodeSnippet","cherryStudioSnippet","base","CLI_SAFE","shellQuote","cliArg","claudeCodeCommand","parts","asString","asServerType","asStringRecord","asStringArray","items","item","toClientSnippetTarget","config","source","configSnippet","id","buildClientSnippetBlocks","blocks","command","CopyClientConfigDialog","isOpen","onClose","useTranslation","showToast","useToast","activeId","setActiveId","useState","copiedBlock","setCopiedBlock","dialogRef","useRef","returnFocusRef","useEffect","onKeyDown","event","useMemo","handleCopy","copyText","current","jsx","jsxs","X","preset","active","block","copied","Check","Copy"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{i as f,r as l,j as s}from"./framework-vendor-_YL27Pfc.js";import{e as b,f as v,h as j}from"./index-DhzWX9nb.js";import{u as p}from"./i18n-vendor-BMaj5qV8.js";import"./icons-vendor-Bk5sng-h.js";const N=({binding:a,onChange:d})=>{const{t:r}=p(),[o,u]=l.useState({}),[m,h]=l.useState(!1),[n,c]=l.useState(""),i=async t=>{h(!0),c("");try{const e=`/credentials/${encodeURIComponent(a.serverName)}`,x=t?await v(e):await j(e,{values:o});if(!x.success)throw new Error(x.message||r("credentials.failed"));u({}),c(r(t?"credentials.deleted":"credentials.saved")),await d()}catch(e){c(e instanceof Error?e.message:r("credentials.failed"))}finally{h(!1)}};return s.jsxs("form",{className:"hub-card p-5 space-y-4",onSubmit:t=>{t.preventDefault(),i(!1)},children:[s.jsxs("div",{className:"flex items-center justify-between gap-3",children:[s.jsx("h2",{className:"font-semibold",children:a.serverName}),s.jsx("span",{className:"hub-tag",children:r(a.configured?"credentials.configured":"credentials.required")})]}),s.jsx("p",{className:"text-sm text-[var(--hub-ink-3)]",children:r("credentials.writeOnly")}),a.credentialTemplate.map(t=>{const e=`${t.target}.${t.name}`;return s.jsxs("label",{className:"block space-y-1 text-sm",children:[s.jsxs("span",{className:"font-medium",children:[t.label||t.name," ",s.jsxs("span",{className:"hub-mono text-xs font-normal text-[var(--hub-ink-3)]",children:["(",e,")"]})]}),s.jsx("input",{type:"password",required:!0,autoComplete:"new-password",maxLength:16384,value:o[e]||"",placeholder:r(a.configuredSlots.includes(e)?"credentials.replaceValue":"credentials.enterValue"),className:"hub-input",onChange:x=>u({...o,[e]:x.target.value})})]},e)}),s.jsxs("div",{className:"flex flex-wrap gap-2",children:[s.jsx("button",{type:"submit",className:"hub-btn primary",disabled:m,children:r("credentials.save")}),s.jsx("button",{type:"button",className:"hub-btn danger",disabled:m||!a.updatedAt,onClick:()=>void i(!0),children:r("credentials.delete")})]}),n&&s.jsx("p",{role:"status",className:"text-sm text-[var(--hub-ink-2)]",children:n})]})};function k(){const{t:a}=p(),[d,r]=f(),[o,u]=l.useState([]),[m,h]=l.useState(!0),[n,c]=l.useState(""),i=l.useCallback(async()=>{try{const e=await b("/credentials");if(!e.success)throw new Error(e.message||a("credentials.failed"));u(e.data||[]),c("")}catch(e){c(e instanceof Error?e.message:a("credentials.failed"))}finally{h(!1)}},[a]);l.useEffect(()=>{i()},[i]);const t=o.filter(e=>!d.get("server")||e.serverName===d.get("server"));return s.jsxs("div",{className:"max-w-4xl mx-auto space-y-5",children:[s.jsxs("div",{children:[s.jsx("h1",{className:"hub-h1",children:a("credentials.title")}),s.jsx("p",{className:"hub-sub",children:a("credentials.description")})]}),d.has("server")&&s.jsx("button",{className:"hub-btn",onClick:()=>r({}),children:a("credentials.showAll")}),n&&s.jsx("div",{className:"hub-card px-4 py-3 text-sm",style:{color:"var(--hub-err)"},role:"alert",children:n}),m?s.jsx("div",{className:"hub-card p-10 text-center text-sm",style:{color:"var(--hub-ink-3)"},children:a("credentials.loading")}):!t.length&&!n?s.jsx("div",{className:"hub-card p-10 text-center text-sm",style:{color:"var(--hub-ink-3)"},children:a("credentials.empty")}):null,t.map(e=>s.jsx(N,{binding:e,onChange:i},e.serverName))]})}export{k as default};
2
- //# sourceMappingURL=CredentialsPage-DMJE4uT2.js.map
1
+ import{i as f,r as l,j as s}from"./framework-vendor-_YL27Pfc.js";import{e as b,f as v,h as j}from"./index-C8aAOWR7.js";import{u as p}from"./i18n-vendor-BMaj5qV8.js";import"./icons-vendor-CNEaJWqW.js";const N=({binding:a,onChange:d})=>{const{t:r}=p(),[o,u]=l.useState({}),[m,h]=l.useState(!1),[n,c]=l.useState(""),i=async t=>{h(!0),c("");try{const e=`/credentials/${encodeURIComponent(a.serverName)}`,x=t?await v(e):await j(e,{values:o});if(!x.success)throw new Error(x.message||r("credentials.failed"));u({}),c(r(t?"credentials.deleted":"credentials.saved")),await d()}catch(e){c(e instanceof Error?e.message:r("credentials.failed"))}finally{h(!1)}};return s.jsxs("form",{className:"hub-card p-5 space-y-4",onSubmit:t=>{t.preventDefault(),i(!1)},children:[s.jsxs("div",{className:"flex items-center justify-between gap-3",children:[s.jsx("h2",{className:"font-semibold",children:a.serverName}),s.jsx("span",{className:"hub-tag",children:r(a.configured?"credentials.configured":"credentials.required")})]}),s.jsx("p",{className:"text-sm text-[var(--hub-ink-3)]",children:r("credentials.writeOnly")}),a.credentialTemplate.map(t=>{const e=`${t.target}.${t.name}`;return s.jsxs("label",{className:"block space-y-1 text-sm",children:[s.jsxs("span",{className:"font-medium",children:[t.label||t.name," ",s.jsxs("span",{className:"hub-mono text-xs font-normal text-[var(--hub-ink-3)]",children:["(",e,")"]})]}),s.jsx("input",{type:"password",required:!0,autoComplete:"new-password",maxLength:16384,value:o[e]||"",placeholder:r(a.configuredSlots.includes(e)?"credentials.replaceValue":"credentials.enterValue"),className:"hub-input",onChange:x=>u({...o,[e]:x.target.value})})]},e)}),s.jsxs("div",{className:"flex flex-wrap gap-2",children:[s.jsx("button",{type:"submit",className:"hub-btn primary",disabled:m,children:r("credentials.save")}),s.jsx("button",{type:"button",className:"hub-btn danger",disabled:m||!a.updatedAt,onClick:()=>void i(!0),children:r("credentials.delete")})]}),n&&s.jsx("p",{role:"status",className:"text-sm text-[var(--hub-ink-2)]",children:n})]})};function k(){const{t:a}=p(),[d,r]=f(),[o,u]=l.useState([]),[m,h]=l.useState(!0),[n,c]=l.useState(""),i=l.useCallback(async()=>{try{const e=await b("/credentials");if(!e.success)throw new Error(e.message||a("credentials.failed"));u(e.data||[]),c("")}catch(e){c(e instanceof Error?e.message:a("credentials.failed"))}finally{h(!1)}},[a]);l.useEffect(()=>{i()},[i]);const t=o.filter(e=>!d.get("server")||e.serverName===d.get("server"));return s.jsxs("div",{className:"max-w-4xl mx-auto space-y-5",children:[s.jsxs("div",{children:[s.jsx("h1",{className:"hub-h1",children:a("credentials.title")}),s.jsx("p",{className:"hub-sub",children:a("credentials.description")})]}),d.has("server")&&s.jsx("button",{className:"hub-btn",onClick:()=>r({}),children:a("credentials.showAll")}),n&&s.jsx("div",{className:"hub-card px-4 py-3 text-sm",style:{color:"var(--hub-err)"},role:"alert",children:n}),m?s.jsx("div",{className:"hub-card p-10 text-center text-sm",style:{color:"var(--hub-ink-3)"},children:a("credentials.loading")}):!t.length&&!n?s.jsx("div",{className:"hub-card p-10 text-center text-sm",style:{color:"var(--hub-ink-3)"},children:a("credentials.empty")}):null,t.map(e=>s.jsx(N,{binding:e,onChange:i},e.serverName))]})}export{k as default};
2
+ //# sourceMappingURL=CredentialsPage-CXK8Xkao.js.map