@shipit-ai/cli 1.173.2 → 1.174.1-pr20.dba624c

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 (212) hide show
  1. package/dist/packages/core/src/infrastructure/services/mcp-server-browser/mcp-server-browser.service.js +46 -1
  2. package/dist/packages/core/src/infrastructure/services/tool-installer/tools/codex-cli.json +1 -1
  3. package/dist/src/presentation/web/components/features/mcp-servers/mcp-connect-instructions.d.ts.map +1 -1
  4. package/dist/src/presentation/web/components/features/mcp-servers/mcp-connect-instructions.js +1 -3
  5. package/dist/src/presentation/web/components/features/mcp-servers/mcp-server-card.d.ts.map +1 -1
  6. package/dist/src/presentation/web/components/features/mcp-servers/mcp-server-card.js +2 -8
  7. package/dist/src/presentation/web/components/features/mcp-servers/mcp-server-detail-drawer.d.ts.map +1 -1
  8. package/dist/src/presentation/web/components/features/mcp-servers/mcp-server-detail-drawer.js +5 -4
  9. package/dist/src/presentation/web/components/features/mcp-servers/mcp-server-icon.d.ts +45 -0
  10. package/dist/src/presentation/web/components/features/mcp-servers/mcp-server-icon.d.ts.map +1 -0
  11. package/dist/src/presentation/web/components/features/mcp-servers/mcp-server-icon.js +138 -0
  12. package/dist/src/presentation/web/components/features/mcp-servers/mcp-servers-page-client.d.ts.map +1 -1
  13. package/dist/src/presentation/web/components/features/mcp-servers/mcp-servers-page-client.js +7 -6
  14. package/dist/src/presentation/web/components/features/mcp-servers/vendor-brand-icons.d.ts +29 -0
  15. package/dist/src/presentation/web/components/features/mcp-servers/vendor-brand-icons.d.ts.map +1 -0
  16. package/dist/src/presentation/web/components/features/mcp-servers/vendor-brand-icons.js +25 -0
  17. package/dist/tsconfig.build.tsbuildinfo +1 -1
  18. package/package.json +6 -6
  19. package/web/.next/BUILD_ID +1 -1
  20. package/web/.next/build-manifest.json +3 -3
  21. package/web/.next/fallback-build-manifest.json +3 -3
  22. package/web/.next/prerender-manifest.json +3 -3
  23. package/web/.next/required-server-files.js +3 -3
  24. package/web/.next/required-server-files.json +3 -3
  25. package/web/.next/server/app/(dashboard)/@drawer/adopt/page/server-reference-manifest.json +29 -29
  26. package/web/.next/server/app/(dashboard)/@drawer/adopt/page.js.nft.json +1 -1
  27. package/web/.next/server/app/(dashboard)/@drawer/adopt/page_client-reference-manifest.js +1 -1
  28. package/web/.next/server/app/(dashboard)/@drawer/chat/page/server-reference-manifest.json +27 -27
  29. package/web/.next/server/app/(dashboard)/@drawer/chat/page.js.nft.json +1 -1
  30. package/web/.next/server/app/(dashboard)/@drawer/chat/page_client-reference-manifest.js +1 -1
  31. package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +31 -31
  32. package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  33. package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  34. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +37 -37
  35. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  36. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  37. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +37 -37
  38. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  39. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  40. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page/server-reference-manifest.json +28 -28
  41. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page.js.nft.json +1 -1
  42. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page_client-reference-manifest.js +1 -1
  43. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +28 -28
  44. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  45. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  46. package/web/.next/server/app/(dashboard)/chat/page/server-reference-manifest.json +27 -27
  47. package/web/.next/server/app/(dashboard)/chat/page.js.nft.json +1 -1
  48. package/web/.next/server/app/(dashboard)/chat/page_client-reference-manifest.js +1 -1
  49. package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +31 -31
  50. package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  51. package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  52. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +37 -37
  53. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  54. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  55. package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +37 -37
  56. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  57. package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  58. package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +27 -27
  59. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  60. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  61. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page/server-reference-manifest.json +28 -28
  62. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page.js.nft.json +1 -1
  63. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page_client-reference-manifest.js +1 -1
  64. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +28 -28
  65. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  66. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  67. package/web/.next/server/app/_global-error.html +1 -1
  68. package/web/.next/server/app/_global-error.rsc +1 -1
  69. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  70. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  71. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  72. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  73. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  74. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +6 -6
  75. package/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  76. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  77. package/web/.next/server/app/api/attachments/preview/route.js.nft.json +1 -1
  78. package/web/.next/server/app/api/dialog/pick-files/route.js.nft.json +1 -1
  79. package/web/.next/server/app/api/evidence/route.js.nft.json +1 -1
  80. package/web/.next/server/app/api/graph-data/route.js.nft.json +1 -1
  81. package/web/.next/server/app/api/interactive/chat/[featureId]/messages/route.js.nft.json +1 -1
  82. package/web/.next/server/app/mcp-servers/page/server-reference-manifest.json +13 -13
  83. package/web/.next/server/app/mcp-servers/page.js.nft.json +1 -1
  84. package/web/.next/server/app/mcp-servers/page_client-reference-manifest.js +1 -1
  85. package/web/.next/server/app/plugins/page/server-reference-manifest.json +15 -15
  86. package/web/.next/server/app/plugins/page.js.nft.json +1 -1
  87. package/web/.next/server/app/plugins/page_client-reference-manifest.js +1 -1
  88. package/web/.next/server/app/settings/page/server-reference-manifest.json +12 -12
  89. package/web/.next/server/app/settings/page.js.nft.json +1 -1
  90. package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  91. package/web/.next/server/app/skills/page/server-reference-manifest.json +11 -11
  92. package/web/.next/server/app/skills/page.js.nft.json +1 -1
  93. package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  94. package/web/.next/server/app/tools/page/server-reference-manifest.json +11 -11
  95. package/web/.next/server/app/tools/page.js.nft.json +1 -1
  96. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  97. package/web/.next/server/app/version/page/server-reference-manifest.json +6 -6
  98. package/web/.next/server/app/version/page.js.nft.json +1 -1
  99. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  100. package/web/.next/server/chunks/[root-of-the-server]__0tb~wwk._.js +1 -1
  101. package/web/.next/server/chunks/ssr/0j.8_web_components_common_control-center-drawer_create-drawer-client_tsx_0g70fc5._.js +1 -1
  102. package/web/.next/server/chunks/ssr/0j.8_web_components_common_control-center-drawer_create-drawer-client_tsx_0g70fc5._.js.map +1 -1
  103. package/web/.next/server/chunks/ssr/0j.8_web_components_common_control-center-drawer_feature-drawer-client_tsx_104cna.._.js +2 -2
  104. package/web/.next/server/chunks/ssr/0j.8_web_components_common_control-center-drawer_feature-drawer-client_tsx_104cna.._.js.map +1 -1
  105. package/web/.next/server/chunks/ssr/0j.8_web_components_features_mcp-servers_mcp-servers-page-client_tsx_0dda8ih._.js +2 -2
  106. package/web/.next/server/chunks/ssr/0j.8_web_components_features_mcp-servers_mcp-servers-page-client_tsx_0dda8ih._.js.map +1 -1
  107. package/web/.next/server/chunks/ssr/0ukq_presentation_web_components_features_settings_settings-page-client_tsx_0j1uius._.js +1 -1
  108. package/web/.next/server/chunks/ssr/0ukq_presentation_web_components_features_settings_settings-page-client_tsx_0j1uius._.js.map +1 -1
  109. package/web/.next/server/chunks/ssr/11y9_components_common_control-center-drawer_repository-drawer-client_tsx_09z.znp._.js +1 -1
  110. package/web/.next/server/chunks/ssr/11y9_components_common_control-center-drawer_repository-drawer-client_tsx_09z.znp._.js.map +1 -1
  111. package/web/.next/server/chunks/ssr/[root-of-the-server]__0.5ojmt._.js +1 -1
  112. package/web/.next/server/chunks/ssr/[root-of-the-server]__0.5ojmt._.js.map +1 -1
  113. package/web/.next/server/chunks/ssr/[root-of-the-server]__05_qc0n._.js +1 -1
  114. package/web/.next/server/chunks/ssr/[root-of-the-server]__05_qc0n._.js.map +1 -1
  115. package/web/.next/server/chunks/ssr/[root-of-the-server]__0ge~xny._.js +1 -1
  116. package/web/.next/server/chunks/ssr/[root-of-the-server]__0ge~xny._.js.map +1 -1
  117. package/web/.next/server/chunks/ssr/[root-of-the-server]__0mwao26._.js +1 -1
  118. package/web/.next/server/chunks/ssr/[root-of-the-server]__0mwao26._.js.map +1 -1
  119. package/web/.next/server/chunks/ssr/[root-of-the-server]__0qda~yi._.js +1 -1
  120. package/web/.next/server/chunks/ssr/[root-of-the-server]__0qda~yi._.js.map +1 -1
  121. package/web/.next/server/chunks/ssr/[root-of-the-server]__0rv1gci._.js +1 -1
  122. package/web/.next/server/chunks/ssr/[root-of-the-server]__0tq2syh._.js +1 -1
  123. package/web/.next/server/chunks/ssr/[root-of-the-server]__0t~u8sd._.js +1 -1
  124. package/web/.next/server/chunks/ssr/[root-of-the-server]__0t~u8sd._.js.map +1 -1
  125. package/web/.next/server/chunks/ssr/[root-of-the-server]__10tll_l._.js +1 -1
  126. package/web/.next/server/chunks/ssr/[root-of-the-server]__10tll_l._.js.map +1 -1
  127. package/web/.next/server/chunks/ssr/[root-of-the-server]__12j29w-._.js +1 -1
  128. package/web/.next/server/chunks/ssr/[root-of-the-server]__12j29w-._.js.map +1 -1
  129. package/web/.next/server/chunks/ssr/{_0~d-l61._.js → _01.73dm._.js} +2 -2
  130. package/web/.next/server/chunks/ssr/{_0~d-l61._.js.map → _01.73dm._.js.map} +1 -1
  131. package/web/.next/server/chunks/ssr/_01sesw0._.js +1 -1
  132. package/web/.next/server/chunks/ssr/_01sesw0._.js.map +1 -1
  133. package/web/.next/server/chunks/ssr/_069y.js._.js +2 -2
  134. package/web/.next/server/chunks/ssr/_069y.js._.js.map +1 -1
  135. package/web/.next/server/chunks/ssr/{_1031n_-._.js → _083k45~._.js} +2 -2
  136. package/web/.next/server/chunks/ssr/{_1031n_-._.js.map → _083k45~._.js.map} +1 -1
  137. package/web/.next/server/chunks/ssr/_0__4si~._.js +1 -1
  138. package/web/.next/server/chunks/ssr/_0__4si~._.js.map +1 -1
  139. package/web/.next/server/chunks/ssr/_0_m17kl._.js +1 -1
  140. package/web/.next/server/chunks/ssr/_0_m17kl._.js.map +1 -1
  141. package/web/.next/server/chunks/ssr/{_09b301s._.js → _0ajzmj-._.js} +2 -2
  142. package/web/.next/server/chunks/ssr/{_09b301s._.js.map → _0ajzmj-._.js.map} +1 -1
  143. package/web/.next/server/chunks/ssr/_0d4miu.._.js +1 -1
  144. package/web/.next/server/chunks/ssr/_0d4miu.._.js.map +1 -1
  145. package/web/.next/server/chunks/ssr/_0e8ern9._.js +1 -1
  146. package/web/.next/server/chunks/ssr/_0e8ern9._.js.map +1 -1
  147. package/web/.next/server/chunks/ssr/_0fswe4r._.js +1 -1
  148. package/web/.next/server/chunks/ssr/_0fswe4r._.js.map +1 -1
  149. package/web/.next/server/chunks/ssr/{_0u09c2.._.js → _0mbb.7k._.js} +2 -2
  150. package/web/.next/server/chunks/ssr/{_0u09c2.._.js.map → _0mbb.7k._.js.map} +1 -1
  151. package/web/.next/server/chunks/ssr/_0p3~u8u._.js +2 -2
  152. package/web/.next/server/chunks/ssr/_0p3~u8u._.js.map +1 -1
  153. package/web/.next/server/chunks/ssr/_0r.3n~3._.js +1 -1
  154. package/web/.next/server/chunks/ssr/_0r.3n~3._.js.map +1 -1
  155. package/web/.next/server/chunks/ssr/_0t59q8r._.js +1 -1
  156. package/web/.next/server/chunks/ssr/_0t59q8r._.js.map +1 -1
  157. package/web/.next/server/chunks/ssr/{_096x3u~._.js → _0vq0c0x._.js} +2 -2
  158. package/web/.next/server/chunks/ssr/{_096x3u~._.js.map → _0vq0c0x._.js.map} +1 -1
  159. package/web/.next/server/chunks/ssr/_0vyfc4b._.js +1 -1
  160. package/web/.next/server/chunks/ssr/_0vyfc4b._.js.map +1 -1
  161. package/web/.next/server/chunks/ssr/_0w-_hww._.js +1 -1
  162. package/web/.next/server/chunks/ssr/_0w-_hww._.js.map +1 -1
  163. package/web/.next/server/chunks/ssr/_0zk-h5w._.js +1 -1
  164. package/web/.next/server/chunks/ssr/_0zk-h5w._.js.map +1 -1
  165. package/web/.next/server/chunks/ssr/_0~7lwu_._.js +1 -1
  166. package/web/.next/server/chunks/ssr/_0~7lwu_._.js.map +1 -1
  167. package/web/.next/server/chunks/ssr/_0~g5-.e._.js +3 -0
  168. package/web/.next/server/chunks/ssr/_0~g5-.e._.js.map +1 -0
  169. package/web/.next/server/chunks/ssr/_1161g9x._.js +1 -1
  170. package/web/.next/server/chunks/ssr/_1161g9x._.js.map +1 -1
  171. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_mcp-servers_page_actions_0d.r4q..js +1 -1
  172. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_mcp-servers_page_actions_0d.r4q..js.map +1 -1
  173. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_plugins_page_actions_0rdndum.js +1 -1
  174. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_plugins_page_actions_0rdndum.js.map +1 -1
  175. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_05m2q~u.js +1 -1
  176. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_05m2q~u.js.map +1 -1
  177. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_0.6zk.t.js +1 -1
  178. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_0.6zk.t.js.map +1 -1
  179. package/web/.next/server/chunks/ssr/src_presentation_web_app_actions_approve-feature_ts_0pjb_re._.js +1 -1
  180. package/web/.next/server/chunks/ssr/src_presentation_web_app_actions_open-ide_ts_0w2wqvu._.js +1 -1
  181. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_0l3oxx9._.js +1 -1
  182. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_0l3oxx9._.js.map +1 -1
  183. package/web/.next/server/middleware-build-manifest.js +3 -3
  184. package/web/.next/server/pages/500.html +1 -1
  185. package/web/.next/server/server-reference-manifest.js +1 -1
  186. package/web/.next/server/server-reference-manifest.json +57 -57
  187. package/web/.next/static/chunks/{0whqmoyf3zd67.js → 0-m4rnec155i1.js} +1 -1
  188. package/web/.next/static/chunks/02940.vqpqt~w.js +8 -0
  189. package/web/.next/static/chunks/{0t~1ohqb2m7ma.js → 094xbjw.1t41_.js} +1 -1
  190. package/web/.next/static/chunks/{0ul697ie_gsw9.js → 0_bfubsp9neaf.js} +1 -1
  191. package/web/.next/static/chunks/0a~-dbzk6tkpw.css +1 -0
  192. package/web/.next/static/chunks/{159n33nvplqug.js → 0g304jt8qhu-~.js} +1 -1
  193. package/web/.next/static/chunks/{0pb77veci.7gd.js → 0k4d8i58i.mo0.js} +1 -1
  194. package/web/.next/static/chunks/0lb_dekd7d4xu.js +1 -0
  195. package/web/.next/static/chunks/{08w-qt8wfe5u..js → 0lc14m5evyhuu.js} +1 -1
  196. package/web/.next/static/chunks/{07kpqi8hle98h.js → 0lt_ok~0hysqu.js} +1 -1
  197. package/web/.next/static/chunks/{06_a861w0tkp6.js → 0nct2gnbj84mf.js} +1 -1
  198. package/web/.next/static/chunks/{0xee.1sl6c~24.js → 0nm97zmm.ri8o.js} +1 -1
  199. package/web/.next/static/chunks/{10p0lo4adb2~5.js → 0y~7z3sw~k~a3.js} +1 -1
  200. package/web/.next/static/chunks/{0mekjif_lg0-r.js → 0~5w460yes32a.js} +2 -2
  201. package/web/.next/static/chunks/{10j-adknfho63.js → 10rtagfoabp3b.js} +1 -1
  202. package/web/.next/static/chunks/{0~9hrc9~63dvr.js → 13wohdlnw9eid.js} +1 -1
  203. package/web/.next/static/chunks/{050mn~oci41h6.js → 15qu-.zhd9f48.js} +3 -3
  204. package/web/public/icons/tools/openai.svg +1 -0
  205. package/web/.next/server/chunks/ssr/_0vm01xk._.js +0 -3
  206. package/web/.next/server/chunks/ssr/_0vm01xk._.js.map +0 -1
  207. package/web/.next/static/chunks/0h2nh2s2b3ma2.css +0 -1
  208. package/web/.next/static/chunks/14ixmk5pm1-rc.js +0 -8
  209. package/web/.next/static/chunks/167z9~gq-q~oy.js +0 -1
  210. /package/web/.next/static/{q4u94V1z_KGlqS1uxSgT2 → MgGhOZyXLY0dmh1EnLE2U}/_buildManifest.js +0 -0
  211. /package/web/.next/static/{q4u94V1z_KGlqS1uxSgT2 → MgGhOZyXLY0dmh1EnLE2U}/_clientMiddlewareManifest.js +0 -0
  212. /package/web/.next/static/{q4u94V1z_KGlqS1uxSgT2 → MgGhOZyXLY0dmh1EnLE2U}/_ssgManifest.js +0 -0
@@ -134,17 +134,62 @@ async function fetchJson(endpoint, options) {
134
134
  });
135
135
  if (!res.ok)
136
136
  return null;
137
+ const contentType = res.headers.get('content-type')?.toLowerCase() ?? '';
137
138
  const text = await res.text();
138
139
  if (text.length > MAX_RESPONSE_SIZE)
139
140
  return null;
141
+ // MCP Streamable HTTP transport may return either application/json
142
+ // or text/event-stream. SSE responses look like:
143
+ // event: message
144
+ // data: {"jsonrpc":"2.0","id":1,"result":{"tools":[...]}}
145
+ //
146
+ // We extract the first `data:` line's payload and parse that as JSON.
147
+ // If the content type is JSON, we parse directly.
148
+ if (contentType.includes('text/event-stream')) {
149
+ return parseSseFirstDataEvent(text);
150
+ }
140
151
  try {
141
152
  return JSON.parse(text);
142
153
  }
143
154
  catch {
144
- return null;
155
+ // Some servers omit the content-type header but return SSE anyway.
156
+ // Try SSE parsing as a fallback before giving up.
157
+ return parseSseFirstDataEvent(text);
145
158
  }
146
159
  }
147
160
  finally {
148
161
  clearTimeout(timeout);
149
162
  }
150
163
  }
164
+ /**
165
+ * Extract the first `data: ...` payload from a Server-Sent Events response
166
+ * body and parse it as JSON. Returns null if no valid data line is found.
167
+ *
168
+ * Handles:
169
+ * event: message
170
+ * data: {"jsonrpc":"2.0",...}
171
+ *
172
+ * And multi-line data fields (per SSE spec — though rare for MCP).
173
+ */
174
+ function parseSseFirstDataEvent(body) {
175
+ const lines = body.split(/\r?\n/);
176
+ const dataParts = [];
177
+ for (const line of lines) {
178
+ if (line.startsWith('data:')) {
179
+ // Strip the "data:" prefix and any single leading space.
180
+ dataParts.push(line.slice(5).replace(/^ /, ''));
181
+ }
182
+ else if (line === '' && dataParts.length > 0) {
183
+ // Empty line terminates the first SSE event — stop collecting.
184
+ break;
185
+ }
186
+ }
187
+ if (dataParts.length === 0)
188
+ return null;
189
+ try {
190
+ return JSON.parse(dataParts.join('\n'));
191
+ }
192
+ catch {
193
+ return null;
194
+ }
195
+ }
@@ -6,7 +6,7 @@
6
6
  "author": "OpenAI",
7
7
  "website": "https://github.com/openai/codex",
8
8
  "platforms": ["linux", "darwin", "win32"],
9
- "iconUrl": "https://cdn.simpleicons.org/openai",
9
+ "iconUrl": "/icons/tools/openai.svg",
10
10
  "binary": "codex",
11
11
  "packageManager": "npm",
12
12
  "commands": {
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-connect-instructions.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/mcp-servers/mcp-connect-instructions.tsx"],"names":[],"mappings":"AAOA,UAAU,2BAA2B;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,KAAK,QAAQ,GAAG,aAAa,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;AAgBlF;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAkFjG;AAED,wBAAgB,sBAAsB,CAAC,EAAE,YAAY,EAAE,UAAU,EAAE,EAAE,2BAA2B,2CA6D/F"}
1
+ {"version":3,"file":"mcp-connect-instructions.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/mcp-servers/mcp-connect-instructions.tsx"],"names":[],"mappings":"AAOA,UAAU,2BAA2B;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,KAAK,QAAQ,GAAG,aAAa,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;AAgBlF;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAkFjG;AAED,wBAAgB,sBAAsB,CAAC,EAAE,YAAY,EAAE,UAAU,EAAE,EAAE,2BAA2B,2CAkE/F"}
@@ -102,7 +102,5 @@ export function McpConnectInstructions({ proxyBaseUrl, serverName }) {
102
102
  // Clipboard not available (e.g., insecure context) — silently ignore.
103
103
  }
104
104
  };
105
- return (_jsxs("div", { className: "space-y-3", children: [_jsx("div", { className: "flex flex-wrap gap-1", role: "tablist", children: CLIENTS.map((client) => (_jsx("button", { type: "button", role: "tab", "aria-selected": activeClient === client.id, onClick: () => setActiveClient(client.id), className: activeClient === client.id
106
- ? 'bg-primary text-primary-foreground rounded-md px-2.5 py-1 text-xs font-medium'
107
- : 'border-border hover:bg-muted rounded-md border px-2.5 py-1 text-xs', children: client.label }, client.id))) }), _jsxs("div", { className: "relative", children: [_jsx("pre", { className: "bg-muted max-h-64 overflow-auto rounded-md p-3 pr-10 font-mono text-[11px] leading-relaxed", children: _jsx("code", { children: snippet }) }), _jsx(Button, { type: "button", variant: "ghost", size: "icon", className: "absolute top-1 right-1 h-7 w-7", onClick: handleCopy, "aria-label": t('mcpServers.connect.copy'), children: copied ? (_jsx(Check, { className: "text-primary h-3.5 w-3.5" })) : (_jsx(Copy, { className: "h-3.5 w-3.5" })) })] }), _jsx("p", { className: "text-muted-foreground text-xs", children: t('mcpServers.connect.replaceKey') })] }));
105
+ return (_jsxs("div", { className: "space-y-3", children: [_jsx("div", { className: "flex flex-wrap gap-1.5 rounded-lg border border-slate-200/60 bg-slate-50/50 p-1 dark:border-slate-700/50 dark:bg-slate-900/40", role: "tablist", "aria-label": t('mcpServers.connect.title'), children: CLIENTS.map((client) => (_jsx("button", { type: "button", role: "tab", "aria-selected": activeClient === client.id, onClick: () => setActiveClient(client.id), "data-state": activeClient === client.id ? 'active' : 'inactive', className: "data-[state=active]:bg-card data-[state=active]:text-primary text-muted-foreground hover:text-foreground rounded-md px-2.5 py-1 text-xs font-medium transition-all data-[state=active]:shadow-sm data-[state=active]:ring-1 data-[state=active]:ring-slate-200/70 dark:data-[state=active]:ring-slate-700/50", children: client.label }, client.id))) }), _jsxs("div", { className: "editorial-shadow group relative overflow-hidden rounded-xl border border-slate-200/60 bg-slate-50/60 dark:border-slate-700/50 dark:bg-slate-900/60", children: [_jsxs("div", { className: "flex items-center justify-between border-b border-slate-200/60 bg-slate-100/40 px-3 py-2 dark:border-slate-700/50 dark:bg-slate-900/40", children: [_jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx("span", { className: "size-2 rounded-full bg-slate-300 dark:bg-slate-600", "aria-hidden": true }), _jsx("span", { className: "size-2 rounded-full bg-slate-300 dark:bg-slate-600", "aria-hidden": true }), _jsx("span", { className: "size-2 rounded-full bg-slate-300 dark:bg-slate-600", "aria-hidden": true })] }), _jsx(Button, { type: "button", variant: "ghost", size: "icon", className: "size-6 shrink-0", onClick: handleCopy, "aria-label": t('mcpServers.connect.copy'), children: copied ? _jsx(Check, { className: "text-primary size-3" }) : _jsx(Copy, { className: "size-3" }) })] }), _jsx("pre", { className: "max-h-64 overflow-auto p-3 font-mono text-[11px] leading-relaxed", children: _jsx("code", { children: snippet }) })] }), _jsx("p", { className: "text-muted-foreground text-xs", children: t('mcpServers.connect.replaceKey') })] }));
108
106
  }
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-server-card.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/mcp-servers/mcp-server-card.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gFAAgF,CAAC;AAEpH,UAAU,kBAAkB;IAC1B,MAAM,EAAE,aAAa,CAAC;IACtB,QAAQ,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;CAC3C;AAQD,wBAAgB,aAAa,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,kBAAkB,2CAyCrE"}
1
+ {"version":3,"file":"mcp-server-card.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/mcp-servers/mcp-server-card.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gFAAgF,CAAC;AAEpH,UAAU,kBAAkB;IAC1B,MAAM,EAAE,aAAa,CAAC;IACtB,QAAQ,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;CAC3C;AAED,wBAAgB,aAAa,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,kBAAkB,2CAkDrE"}
@@ -3,20 +3,14 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useTranslation } from 'react-i18next';
4
4
  import { Card } from '../../ui/card.js';
5
5
  import { Badge } from '../../ui/badge.js';
6
- import { Server, Wifi, Terminal } from 'lucide-react';
7
- const TRANSPORT_ICONS = {
8
- http: Server,
9
- sse: Wifi,
10
- stdio: Terminal,
11
- };
6
+ import { McpServerIcon } from './mcp-server-icon.js';
12
7
  export function McpServerCard({ server, onSelect }) {
13
8
  const { t } = useTranslation('web');
14
- const TransportIcon = TRANSPORT_ICONS[server.transport] ?? Server;
15
9
  const description = server.mcp_info?.description ?? '';
16
10
  return (_jsxs(Card, { className: "cursor-pointer p-5 transition-all duration-300 hover:scale-[1.02] hover:shadow-md hover:ring-slate-300 dark:hover:ring-slate-600", role: "button", tabIndex: 0, onClick: () => onSelect(server), onKeyDown: (e) => {
17
11
  if (e.key === 'Enter' || e.key === ' ') {
18
12
  e.preventDefault();
19
13
  onSelect(server);
20
14
  }
21
- }, children: [_jsxs("div", { className: "flex items-start justify-between gap-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(TransportIcon, { className: "text-muted-foreground h-4 w-4 shrink-0" }), _jsx("h3", { className: "text-sm font-semibold", children: server.name })] }), _jsx(Badge, { variant: "outline", className: "shrink-0 text-xs", children: t(`mcpServers.transport.${server.transport}`, server.transport.toUpperCase()) })] }), description ? (_jsx("p", { className: "text-muted-foreground mt-2 line-clamp-2 text-xs", children: description })) : null, _jsx("div", { className: "mt-3 flex items-center gap-2", children: server.auth_type && server.auth_type !== 'none' ? (_jsx(Badge, { variant: "secondary", className: "text-xs", children: t(`mcpServers.authType.${server.auth_type}`, server.auth_type) })) : null })] }));
15
+ }, "data-testid": `mcp-server-card-${server.server_name}`, children: [_jsxs("div", { className: "flex items-start gap-3", children: [_jsx("div", { className: "flex size-11 shrink-0 items-center justify-center rounded-lg bg-slate-100 ring-1 ring-slate-200/50 dark:bg-slate-800 dark:ring-slate-700/50", children: _jsx(McpServerIcon, { serverName: server.server_name, url: server.url, transport: server.transport, size: "md" }) }), _jsx("h3", { className: "text-foreground mt-2 min-w-0 flex-1 truncate text-sm leading-tight font-bold tracking-tight", children: server.name })] }), description ? (_jsx("p", { className: "text-muted-foreground mt-3 line-clamp-2 text-xs leading-relaxed", children: description })) : null, _jsxs("div", { className: "mt-4 flex flex-wrap items-center gap-1.5", children: [_jsx(Badge, { variant: "outline", children: t(`mcpServers.transport.${server.transport}`, server.transport.toUpperCase()) }), server.auth_type && server.auth_type !== 'none' ? (_jsx(Badge, { variant: "secondary", children: t(`mcpServers.authType.${server.auth_type}`, server.auth_type) })) : null] })] }));
22
16
  }
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-server-detail-drawer.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/mcp-servers/mcp-server-detail-drawer.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EACV,aAAa,EAEd,MAAM,gFAAgF,CAAC;AAExF,UAAU,0BAA0B;IAClC,MAAM,EAAE,aAAa,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAYD,wBAAgB,qBAAqB,CAAC,EACpC,MAAM,EACN,YAAY,EACZ,IAAI,EACJ,OAAO,GACR,EAAE,0BAA0B,kDA6G5B"}
1
+ {"version":3,"file":"mcp-server-detail-drawer.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/mcp-servers/mcp-server-detail-drawer.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EACV,aAAa,EAEd,MAAM,gFAAgF,CAAC;AAExF,UAAU,0BAA0B;IAClC,MAAM,EAAE,aAAa,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAYD,wBAAgB,qBAAqB,CAAC,EACpC,MAAM,EACN,YAAY,EACZ,IAAI,EACJ,OAAO,GACR,EAAE,0BAA0B,kDA2J5B"}
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
3
3
  import { useEffect, useState, useCallback } from 'react';
4
4
  import { useTranslation } from 'react-i18next';
5
5
  import { BaseDrawer } from '../../common/base-drawer/index.js';
@@ -10,6 +10,7 @@ import { Button } from '../../ui/button.js';
10
10
  import { RefreshCw } from 'lucide-react';
11
11
  import { McpToolList } from './mcp-tool-list.js';
12
12
  import { McpConnectInstructions } from './mcp-connect-instructions.js';
13
+ import { McpServerIcon } from './mcp-server-icon.js';
13
14
  import { fetchMcpServerToolsAction } from '../../../app/actions/fetch-mcp-server-tools.js';
14
15
  function isValidDisplayUrl(url) {
15
16
  if (!url)
@@ -56,13 +57,13 @@ export function McpServerDetailDrawer({ server, proxyBaseUrl, open, onClose, })
56
57
  const handleRefresh = useCallback(() => {
57
58
  if (!server)
58
59
  return;
59
- // Clear the cached server name to force a re-fetch on the next render
60
- // and call loadTools directly for immediate feedback.
60
+ // Clear the cached server name to force a re-fetch and call loadTools
61
+ // directly for immediate feedback.
61
62
  setLoadedServerName(null);
62
63
  loadTools(server.server_name);
63
64
  }, [server, loadTools]);
64
65
  if (!server)
65
66
  return null;
66
67
  const description = server.mcp_info?.description ?? '';
67
- return (_jsxs(BaseDrawer, { open: open, onClose: onClose, children: [_jsx(DrawerTitle, { children: server.name }), description ? _jsx(DrawerDescription, { children: description }) : null, _jsx(Separator, { className: "my-4" }), _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: "text-muted-foreground text-xs", children: t('mcpServers.detail.serverName') }), _jsx("span", { className: "font-mono text-xs", children: server.server_name })] }), isValidDisplayUrl(server.url) ? (_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: "text-muted-foreground text-xs", children: t('mcpServers.detail.url') }), _jsx("span", { className: "max-w-[200px] truncate font-mono text-xs", children: server.url })] })) : null, _jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: "text-muted-foreground text-xs", children: t('mcpServers.detail.transport') }), _jsx(Badge, { variant: "outline", className: "text-xs", children: t(`mcpServers.transport.${server.transport}`, server.transport.toUpperCase()) })] }), server.auth_type && server.auth_type !== 'none' ? (_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: "text-muted-foreground text-xs", children: t('mcpServers.detail.authType') }), _jsx(Badge, { variant: "secondary", className: "text-xs", children: t(`mcpServers.authType.${server.auth_type}`, server.auth_type) })] })) : null] }), _jsx(Separator, { className: "my-4" }), _jsxs("div", { className: "mb-3 flex items-center justify-between", children: [_jsx("h3", { className: "text-sm font-semibold", children: t('mcpServers.tools.title') }), _jsx(Button, { type: "button", variant: "ghost", size: "icon", className: "h-7 w-7", onClick: handleRefresh, disabled: loadingTools, "aria-label": t('mcpServers.tools.refresh'), "data-testid": "mcp-tools-refresh", children: _jsx(RefreshCw, { className: `h-3.5 w-3.5 ${loadingTools ? 'animate-spin' : ''}` }) })] }), loadingTools ? (_jsxs("p", { className: "text-muted-foreground text-sm", children: [t('accessibility.loading'), "..."] })) : toolError ? (_jsx("p", { className: "text-destructive text-sm", children: toolError })) : (_jsx(McpToolList, { tools: tools, serverName: server.server_name })), _jsx(Separator, { className: "my-4" }), _jsx("h3", { className: "mb-3 text-sm font-semibold", children: t('mcpServers.connect.title') }), _jsx(McpConnectInstructions, { proxyBaseUrl: proxyBaseUrl, serverName: server.server_name })] }));
68
+ return (_jsx(BaseDrawer, { open: open, onClose: onClose, "data-testid": "mcp-server-detail-drawer", children: _jsxs("div", { className: "flex flex-col gap-6 overflow-y-auto p-6", children: [_jsxs("div", { className: "space-y-2", children: [_jsxs("span", { className: "text-[10px] font-bold tracking-[0.2em] text-slate-400 uppercase", children: [t(`mcpServers.transport.${server.transport}`, server.transport.toUpperCase()), " \u00B7 MCP Server"] }), _jsxs("div", { className: "flex items-start gap-3", children: [_jsx("div", { className: "flex size-12 shrink-0 items-center justify-center rounded-lg bg-slate-100 ring-1 ring-slate-200/50 dark:bg-slate-800 dark:ring-slate-700/50", children: _jsx(McpServerIcon, { serverName: server.server_name, url: server.url, transport: server.transport, size: "lg" }) }), _jsx(DrawerTitle, { className: "text-foreground mt-2 text-lg font-bold tracking-tight", children: server.name })] }), description ? (_jsx(DrawerDescription, { className: "text-muted-foreground text-sm leading-relaxed", children: description })) : null] }), _jsx(Separator, {}), _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: "text-muted-foreground text-xs font-medium", children: t('mcpServers.detail.serverName') }), _jsx("span", { className: "font-mono text-xs", children: server.server_name })] }), isValidDisplayUrl(server.url) ? (_jsxs("div", { className: "flex items-center justify-between gap-4", children: [_jsx("span", { className: "text-muted-foreground shrink-0 text-xs font-medium", children: t('mcpServers.detail.url') }), _jsx("span", { className: "truncate font-mono text-xs", title: server.url, children: server.url })] })) : null, _jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: "text-muted-foreground text-xs font-medium", children: t('mcpServers.detail.transport') }), _jsx(Badge, { variant: "outline", children: t(`mcpServers.transport.${server.transport}`, server.transport.toUpperCase()) })] }), server.auth_type && server.auth_type !== 'none' ? (_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: "text-muted-foreground text-xs font-medium", children: t('mcpServers.detail.authType') }), _jsx(Badge, { variant: "secondary", children: t(`mcpServers.authType.${server.auth_type}`, server.auth_type) })] })) : null] }), _jsx(Separator, {}), _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("h3", { className: "text-foreground text-sm font-bold tracking-tight", children: t('mcpServers.tools.title') }), _jsx(Button, { type: "button", variant: "ghost", size: "icon", className: "size-7", onClick: handleRefresh, disabled: loadingTools, "aria-label": t('mcpServers.tools.refresh'), "data-testid": "mcp-tools-refresh", children: _jsx(RefreshCw, { className: `size-3.5 ${loadingTools ? 'animate-spin' : ''}` }) })] }), loadingTools ? (_jsxs("p", { className: "text-muted-foreground text-sm", children: [t('accessibility.loading'), "..."] })) : toolError ? (_jsx("p", { className: "text-destructive text-sm", children: toolError })) : (_jsx(McpToolList, { tools: tools, serverName: server.server_name }))] }), _jsx(Separator, {}), _jsxs("div", { className: "space-y-3", children: [_jsx("h3", { className: "text-foreground text-sm font-bold tracking-tight", children: t('mcpServers.connect.title') }), _jsx(McpConnectInstructions, { proxyBaseUrl: proxyBaseUrl, serverName: server.server_name })] })] }) }));
68
69
  }
@@ -0,0 +1,45 @@
1
+ import { type ComponentType } from 'react';
2
+ interface McpServerIconProps {
3
+ serverName: string;
4
+ url?: string;
5
+ transport: string;
6
+ className?: string;
7
+ size?: 'sm' | 'md' | 'lg';
8
+ }
9
+ type BrandIconComponent = ComponentType<{
10
+ className?: string;
11
+ size?: number;
12
+ }>;
13
+ export type VendorResolution = {
14
+ kind: 'inline';
15
+ component: BrandIconComponent;
16
+ } | {
17
+ kind: 'simpleicons';
18
+ slug: string;
19
+ } | {
20
+ kind: 'none';
21
+ };
22
+ /**
23
+ * Resolve a vendor icon for an MCP server by matching name and URL against
24
+ * the VENDOR_MAP patterns. Returns an inline component, a SimpleIcons slug,
25
+ * or 'none' (caller falls back to transport icon).
26
+ *
27
+ * Exported for unit testing.
28
+ */
29
+ export declare function resolveVendorMapping(serverName: string, url?: string): VendorResolution;
30
+ /**
31
+ * Renders an MCP server's brand icon when recognizable, falling back to the
32
+ * transport-type icon otherwise.
33
+ *
34
+ * Resolution order:
35
+ * 1. Inline brand SVG (Microsoft, Azure, DeepWiki, Firecrawl, AWS)
36
+ * 2. SimpleIcons CDN image (GitHub, Stripe, Postgres, etc.)
37
+ * 3. Transport fallback (Server/Wifi/Terminal from lucide-react)
38
+ *
39
+ * For SimpleIcons images, we handle `onError` by swapping to the transport
40
+ * fallback — this protects against SimpleIcons slug changes without breaking
41
+ * the UI.
42
+ */
43
+ export declare function McpServerIcon({ serverName, url, transport, className, size, }: McpServerIconProps): import("react/jsx-runtime").JSX.Element;
44
+ export {};
45
+ //# sourceMappingURL=mcp-server-icon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-server-icon.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/mcp-servers/mcp-server-icon.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAY,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAYrD,UAAU,kBAAkB;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;CAC3B;AAED,KAAK,kBAAkB,GAAG,aAAa,CAAC;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AA4F/E,MAAM,MAAM,gBAAgB,GACxB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,kBAAkB,CAAA;CAAE,GACjD;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACrC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAErB;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,gBAAgB,CASvF;AAoBD;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,EAC5B,UAAU,EACV,GAAG,EACH,SAAS,EACT,SAAS,EACT,IAAW,GACZ,EAAE,kBAAkB,2CA6BpB"}
@@ -0,0 +1,138 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { useState } from 'react';
4
+ import { Server, Wifi, Terminal } from 'lucide-react';
5
+ import { MicrosoftIcon, MicrosoftLearnIcon, AzureIcon, FirecrawlIcon, DeepWikiIcon, AwsIcon, } from './vendor-brand-icons.js';
6
+ /**
7
+ * Vendor icon resolution map.
8
+ *
9
+ * Priority rules:
10
+ * 1. More-specific patterns FIRST (e.g. `microsoft_learn` before `microsoft`,
11
+ * `github_copilot` before plain `github`).
12
+ * 2. Inline SVG brand icons take priority over SimpleIcons when both are
13
+ * available — inline icons are guaranteed to render and have no CDN
14
+ * dependency.
15
+ * 3. Verified slugs only. Every SimpleIcons slug in this file must return
16
+ * HTTP 200 from https://cdn.simpleicons.org/{slug} as of the last audit.
17
+ *
18
+ * When no vendor matches, the `McpServerIcon` component falls back to the
19
+ * transport-type Lucide icon (Server/Wifi/Terminal).
20
+ *
21
+ * Exported `resolveVendorMapping` is the source of truth for tests.
22
+ */
23
+ const VENDOR_MAP = [
24
+ // Microsoft (SimpleIcons removed all MS icons for legal reasons — use inline)
25
+ { match: /microsoft[_-]?learn|learn\.microsoft/, inlineIcon: MicrosoftLearnIcon },
26
+ { match: /foundry|ai\.azure|azure[_-]?foundry|bedrock[_-]?agentcore/, inlineIcon: AzureIcon },
27
+ { match: /\bazure\b/, inlineIcon: AzureIcon },
28
+ { match: /microsoft|\.microsoft\./, inlineIcon: MicrosoftIcon },
29
+ // GitHub / Copilot (SimpleIcons has these)
30
+ { match: /github[_-]?copilot|\bcopilot\b/, simpleIconSlug: 'githubcopilot' },
31
+ { match: /github|api\.github/, simpleIconSlug: 'github' },
32
+ { match: /gitlab/, simpleIconSlug: 'gitlab' },
33
+ { match: /bitbucket/, simpleIconSlug: 'bitbucket' },
34
+ // AI / LLM vendors
35
+ { match: /anthropic|\bclaude\b/, simpleIconSlug: 'anthropic' },
36
+ { match: /gemini|google[_-]?ai/, simpleIconSlug: 'googlegemini' },
37
+ { match: /perplexity/, simpleIconSlug: 'perplexity' },
38
+ // Documentation / knowledge (DeepWiki gets its own distinct mark)
39
+ { match: /deepwiki|deep[_-]?wiki/, inlineIcon: DeepWikiIcon },
40
+ { match: /notion/, simpleIconSlug: 'notion' },
41
+ { match: /confluence/, simpleIconSlug: 'confluence' },
42
+ { match: /readthedocs/, simpleIconSlug: 'readthedocs' },
43
+ { match: /mintlify/, simpleIconSlug: 'mintlify' },
44
+ // Web scraping / crawling (inline for Firecrawl — no SimpleIcons)
45
+ { match: /firecrawl/, inlineIcon: FirecrawlIcon },
46
+ // Cloud / infra
47
+ { match: /\baws\b|amazon[_-]?web|bedrock/, inlineIcon: AwsIcon },
48
+ { match: /cloudflare/, simpleIconSlug: 'cloudflare' },
49
+ { match: /vercel/, simpleIconSlug: 'vercel' },
50
+ { match: /netlify/, simpleIconSlug: 'netlify' },
51
+ { match: /digitalocean/, simpleIconSlug: 'digitalocean' },
52
+ { match: /railway/, simpleIconSlug: 'railway' },
53
+ // Databases
54
+ { match: /postgres/, simpleIconSlug: 'postgresql' },
55
+ { match: /mongodb/, simpleIconSlug: 'mongodb' },
56
+ { match: /\bredis\b/, simpleIconSlug: 'redis' },
57
+ { match: /mysql/, simpleIconSlug: 'mysql' },
58
+ { match: /sqlite/, simpleIconSlug: 'sqlite' },
59
+ { match: /supabase/, simpleIconSlug: 'supabase' },
60
+ { match: /planetscale/, simpleIconSlug: 'planetscale' },
61
+ // Productivity / collaboration
62
+ { match: /slack/, simpleIconSlug: 'slack' },
63
+ { match: /discord/, simpleIconSlug: 'discord' },
64
+ { match: /linear/, simpleIconSlug: 'linear' },
65
+ { match: /jira|atlassian/, simpleIconSlug: 'jira' },
66
+ { match: /asana/, simpleIconSlug: 'asana' },
67
+ { match: /zapier/, simpleIconSlug: 'zapier' },
68
+ // Observability
69
+ { match: /datadog/, simpleIconSlug: 'datadog' },
70
+ { match: /sentry/, simpleIconSlug: 'sentry' },
71
+ { match: /grafana/, simpleIconSlug: 'grafana' },
72
+ { match: /newrelic/, simpleIconSlug: 'newrelic' },
73
+ // Payments / commerce
74
+ { match: /stripe/, simpleIconSlug: 'stripe' },
75
+ { match: /shopify/, simpleIconSlug: 'shopify' },
76
+ ];
77
+ /**
78
+ * Resolve a vendor icon for an MCP server by matching name and URL against
79
+ * the VENDOR_MAP patterns. Returns an inline component, a SimpleIcons slug,
80
+ * or 'none' (caller falls back to transport icon).
81
+ *
82
+ * Exported for unit testing.
83
+ */
84
+ export function resolveVendorMapping(serverName, url) {
85
+ const haystack = `${serverName} ${url ?? ''}`.toLowerCase();
86
+ for (const entry of VENDOR_MAP) {
87
+ if (entry.match.test(haystack)) {
88
+ if (entry.inlineIcon)
89
+ return { kind: 'inline', component: entry.inlineIcon };
90
+ if (entry.simpleIconSlug)
91
+ return { kind: 'simpleicons', slug: entry.simpleIconSlug };
92
+ }
93
+ }
94
+ return { kind: 'none' };
95
+ }
96
+ const TRANSPORT_FALLBACKS = {
97
+ http: Server,
98
+ sse: Wifi,
99
+ stdio: Terminal,
100
+ };
101
+ const SIZE_CLASSES = {
102
+ sm: 'size-4',
103
+ md: 'size-5',
104
+ lg: 'size-6',
105
+ };
106
+ const SIZE_PIXELS = {
107
+ sm: 16,
108
+ md: 20,
109
+ lg: 24,
110
+ };
111
+ /**
112
+ * Renders an MCP server's brand icon when recognizable, falling back to the
113
+ * transport-type icon otherwise.
114
+ *
115
+ * Resolution order:
116
+ * 1. Inline brand SVG (Microsoft, Azure, DeepWiki, Firecrawl, AWS)
117
+ * 2. SimpleIcons CDN image (GitHub, Stripe, Postgres, etc.)
118
+ * 3. Transport fallback (Server/Wifi/Terminal from lucide-react)
119
+ *
120
+ * For SimpleIcons images, we handle `onError` by swapping to the transport
121
+ * fallback — this protects against SimpleIcons slug changes without breaking
122
+ * the UI.
123
+ */
124
+ export function McpServerIcon({ serverName, url, transport, className, size = 'sm', }) {
125
+ const [imageFailed, setImageFailed] = useState(false);
126
+ const resolution = resolveVendorMapping(serverName, url);
127
+ const FallbackIcon = TRANSPORT_FALLBACKS[transport] ?? Server;
128
+ const sizeClass = SIZE_CLASSES[size];
129
+ const sizePx = SIZE_PIXELS[size];
130
+ if (resolution.kind === 'inline') {
131
+ const Brand = resolution.component;
132
+ return _jsx(Brand, { className: `${sizeClass} shrink-0 ${className ?? ''}`, size: sizePx });
133
+ }
134
+ if (resolution.kind === 'simpleicons' && !imageFailed) {
135
+ return (_jsx("img", { src: `https://cdn.simpleicons.org/${resolution.slug}`, alt: "", width: sizePx, height: sizePx, className: `${sizeClass} shrink-0 ${className ?? ''}`, onError: () => setImageFailed(true) }));
136
+ }
137
+ return (_jsx(FallbackIcon, { className: `text-muted-foreground ${sizeClass} shrink-0 ${className ?? ''}` }));
138
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-servers-page-client.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/mcp-servers/mcp-servers-page-client.tsx"],"names":[],"mappings":"AAaA,UAAU,yBAAyB;IACjC,eAAe,EAAE,OAAO,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;CACtB;AAID,wBAAgB,oBAAoB,CAAC,EAAE,eAAe,EAAE,YAAY,EAAE,EAAE,yBAAyB,2CAwHhG"}
1
+ {"version":3,"file":"mcp-servers-page-client.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/mcp-servers/mcp-servers-page-client.tsx"],"names":[],"mappings":"AAcA,UAAU,yBAAyB;IACjC,eAAe,EAAE,OAAO,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;CACtB;AAID,wBAAgB,oBAAoB,CAAC,EAAE,eAAe,EAAE,YAAY,EAAE,EAAE,yBAAyB,2CA2IhG"}
@@ -4,8 +4,9 @@ import { useState, useEffect, useMemo } from 'react';
4
4
  import { useTranslation } from 'react-i18next';
5
5
  import { AlertCircle, Search, Server } from 'lucide-react';
6
6
  import { Input } from '../../ui/input.js';
7
- import { Badge } from '../../ui/badge.js';
7
+ import { Button } from '../../ui/button.js';
8
8
  import { EmptyState } from '../../common/empty-state/index.js';
9
+ import { PageHeader } from '../../common/page-header/index.js';
9
10
  import { McpServerCard } from './mcp-server-card.js';
10
11
  import { McpServerDetailDrawer } from './mcp-server-detail-drawer.js';
11
12
  import { fetchMcpServersAction } from '../../../app/actions/fetch-mcp-servers.js';
@@ -47,12 +48,12 @@ export function McpServersPageClient({ proxyConfigured, proxyBaseUrl }) {
47
48
  });
48
49
  }, [servers, searchQuery, transportFilter]);
49
50
  if (!proxyConfigured) {
50
- return (_jsx("div", { className: "flex h-full items-center justify-center p-8", children: _jsx(EmptyState, { icon: _jsx(AlertCircle, { className: "h-8 w-8" }), title: t('mcpServers.noProxy') }) }));
51
+ return (_jsxs("div", { className: "flex flex-col gap-8 p-8", children: [_jsx(PageHeader, { eyebrow: "Developer Portal", title: t('mcpServers.title'), description: t('mcpServers.subtitle') }), _jsx(EmptyState, { icon: _jsx(AlertCircle, { className: "size-10" }), title: t('mcpServers.noProxy') })] }));
51
52
  }
52
53
  if (loading) {
53
- return (_jsx("div", { className: "flex h-full items-center justify-center p-8", children: _jsxs("p", { className: "text-muted-foreground", children: [t('accessibility.loading'), "..."] }) }));
54
+ return (_jsxs("div", { className: "flex flex-col gap-8 p-8", children: [_jsx(PageHeader, { eyebrow: "Developer Portal", title: t('mcpServers.title'), description: t('mcpServers.subtitle') }), _jsxs("div", { className: "text-muted-foreground text-center text-sm", children: [t('accessibility.loading'), "..."] })] }));
54
55
  }
55
- return (_jsxs("div", { className: "space-y-6 p-6", children: [_jsxs("div", { children: [_jsx("h1", { className: "text-2xl font-bold", children: t('mcpServers.title') }), error ? (_jsx("div", { className: "border-destructive/50 bg-destructive/10 mt-2 rounded-md border p-3", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(AlertCircle, { className: "text-destructive h-4 w-4" }), _jsx("p", { className: "text-destructive text-sm", children: error })] }) })) : null, _jsx("p", { className: "text-muted-foreground mt-1 text-sm", children: t('mcpServers.subtitle') })] }), _jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [_jsx(Input, { placeholder: t('mcpServers.searchPlaceholder'), value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), className: "max-w-xs" }), _jsx("div", { className: "flex gap-1", children: TRANSPORT_FILTERS.map((filter) => (_jsx(Badge, { variant: transportFilter === filter ? 'default' : 'outline', className: "cursor-pointer", onClick: () => setTransportFilter(filter), children: filter === 'all'
56
- ? t('mcpServers.filter.all')
57
- : t(`mcpServers.transport.${filter}`, filter.toUpperCase()) }, filter))) })] }), filtered.length === 0 ? (_jsx("div", { className: "flex items-center justify-center py-16", children: _jsx(EmptyState, { icon: servers.length === 0 ? _jsx(Server, { className: "h-8 w-8" }) : _jsx(Search, { className: "h-8 w-8" }), title: servers.length === 0 ? t('mcpServers.noServers') : t('mcpServers.noResults') }) })) : (_jsx("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3", children: filtered.map((server) => (_jsx(McpServerCard, { server: server, onSelect: setSelectedServer }, server.server_id))) })), _jsx(McpServerDetailDrawer, { server: selectedServer, proxyBaseUrl: proxyBaseUrl, open: !!selectedServer, onClose: () => setSelectedServer(null) })] }));
56
+ return (_jsxs("div", { className: "flex flex-col gap-8 p-8", children: [_jsx(PageHeader, { eyebrow: "Developer Portal", title: t('mcpServers.title'), description: t('mcpServers.subtitle') }), error ? (_jsxs("div", { role: "alert", className: "border-destructive/40 bg-destructive/10 editorial-shadow flex items-center gap-2 rounded-xl border px-4 py-3", children: [_jsx(AlertCircle, { className: "text-destructive size-4 shrink-0" }), _jsx("p", { className: "text-destructive text-sm font-medium", children: error })] })) : null, _jsxs("div", { className: "relative", children: [_jsx(Search, { className: "text-muted-foreground absolute top-1/2 left-3 size-4 -translate-y-1/2" }), _jsx(Input, { placeholder: t('mcpServers.searchPlaceholder'), value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), className: "ps-9", "data-testid": "mcp-servers-search" })] }), _jsx("div", { className: "flex flex-wrap gap-2", children: TRANSPORT_FILTERS.map((filter) => (_jsx(Button, { variant: transportFilter === filter ? 'default' : 'outline', size: "sm", onClick: () => setTransportFilter(filter), "data-testid": `mcp-servers-filter-${filter}`, children: filter === 'all'
57
+ ? t('mcpServers.filter.all')
58
+ : t(`mcpServers.transport.${filter}`, filter.toUpperCase()) }, filter))) }), filtered.length === 0 ? (_jsx(EmptyState, { icon: servers.length === 0 ? _jsx(Server, { className: "size-10" }) : _jsx(Search, { className: "size-10" }), title: servers.length === 0 ? t('mcpServers.noServers') : t('mcpServers.noResults') })) : (_jsx("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3", children: filtered.map((server) => (_jsx(McpServerCard, { server: server, onSelect: setSelectedServer }, server.server_id))) })), _jsx(McpServerDetailDrawer, { server: selectedServer, proxyBaseUrl: proxyBaseUrl, open: !!selectedServer, onClose: () => setSelectedServer(null) })] }));
58
59
  }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Inline brand icons for MCP server vendors that SimpleIcons either doesn't
3
+ * serve (Microsoft — removed for legal reasons), hasn't added yet (Firecrawl,
4
+ * DeepWiki), or where we want a project-specific treatment.
5
+ *
6
+ * Using inline SVG instead of remote image URLs because:
7
+ * - No network request, no 404 risk, no CORS
8
+ * - Uses `currentColor` where possible so brand marks adapt to dark mode
9
+ * - All paths are public brand marks simplified to their geometric essentials
10
+ * to avoid trademark ambiguity
11
+ */
12
+ interface BrandIconProps {
13
+ className?: string;
14
+ size?: number;
15
+ }
16
+ /** Microsoft four-square window mark (simplified from public brand guidelines). */
17
+ export declare function MicrosoftIcon({ className, size }: BrandIconProps): import("react/jsx-runtime").JSX.Element;
18
+ /** Microsoft Learn — book + graduation cap motif. */
19
+ export declare function MicrosoftLearnIcon({ className, size }: BrandIconProps): import("react/jsx-runtime").JSX.Element;
20
+ /** Azure / Foundry — stylized mountain triangles mark. */
21
+ export declare function AzureIcon({ className, size }: BrandIconProps): import("react/jsx-runtime").JSX.Element;
22
+ /** Firecrawl — flame mark. */
23
+ export declare function FirecrawlIcon({ className, size }: BrandIconProps): import("react/jsx-runtime").JSX.Element;
24
+ /** DeepWiki — stacked pages with magnifying lens motif. */
25
+ export declare function DeepWikiIcon({ className, size }: BrandIconProps): import("react/jsx-runtime").JSX.Element;
26
+ /** AWS — orange cube mark. */
27
+ export declare function AwsIcon({ className, size }: BrandIconProps): import("react/jsx-runtime").JSX.Element;
28
+ export {};
29
+ //# sourceMappingURL=vendor-brand-icons.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vendor-brand-icons.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/mcp-servers/vendor-brand-icons.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,UAAU,cAAc;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,mFAAmF;AACnF,wBAAgB,aAAa,CAAC,EAAE,SAAS,EAAE,IAAS,EAAE,EAAE,cAAc,2CAgBrE;AAED,qDAAqD;AACrD,wBAAgB,kBAAkB,CAAC,EAAE,SAAS,EAAE,IAAS,EAAE,EAAE,cAAc,2CAoB1E;AAED,0DAA0D;AAC1D,wBAAgB,SAAS,CAAC,EAAE,SAAS,EAAE,IAAS,EAAE,EAAE,cAAc,2CAcjE;AAED,8BAA8B;AAC9B,wBAAgB,aAAa,CAAC,EAAE,SAAS,EAAE,IAAS,EAAE,EAAE,cAAc,2CAiBrE;AAED,2DAA2D;AAC3D,wBAAgB,YAAY,CAAC,EAAE,SAAS,EAAE,IAAS,EAAE,EAAE,cAAc,2CA0BpE;AAED,8BAA8B;AAC9B,wBAAgB,OAAO,CAAC,EAAE,SAAS,EAAE,IAAS,EAAE,EAAE,cAAc,2CAiB/D"}
@@ -0,0 +1,25 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /** Microsoft four-square window mark (simplified from public brand guidelines). */
3
+ export function MicrosoftIcon({ className, size = 20 }) {
4
+ return (_jsxs("svg", { className: className, width: size, height: size, viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", children: [_jsx("rect", { x: "2", y: "2", width: "9", height: "9", fill: "#F25022" }), _jsx("rect", { x: "13", y: "2", width: "9", height: "9", fill: "#7FBA00" }), _jsx("rect", { x: "2", y: "13", width: "9", height: "9", fill: "#00A4EF" }), _jsx("rect", { x: "13", y: "13", width: "9", height: "9", fill: "#FFB900" })] }));
5
+ }
6
+ /** Microsoft Learn — book + graduation cap motif. */
7
+ export function MicrosoftLearnIcon({ className, size = 20 }) {
8
+ return (_jsxs("svg", { className: className, width: size, height: size, viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", children: [_jsx("path", { d: "M3 6a1 1 0 0 1 1-1h6a2 2 0 0 1 2 2v13a1 1 0 0 1-1.447.894L6 18.618V7H4a1 1 0 0 1-1-1Z", fill: "#0078D4" }), _jsx("path", { d: "M21 6a1 1 0 0 0-1-1h-6a2 2 0 0 0-2 2v13a1 1 0 0 0 1.447.894L18 18.618V7h2a1 1 0 0 0 1-1Z", fill: "#50E6FF" })] }));
9
+ }
10
+ /** Azure / Foundry — stylized mountain triangles mark. */
11
+ export function AzureIcon({ className, size = 20 }) {
12
+ return (_jsxs("svg", { className: className, width: size, height: size, viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", children: [_jsx("path", { d: "M12 4L2 20h7l3-5 3 5h7L12 4Z", fill: "#0089D6" }), _jsx("path", { d: "M12 4l-3 5h6l-3-5Z", fill: "#54AEF0" })] }));
13
+ }
14
+ /** Firecrawl — flame mark. */
15
+ export function FirecrawlIcon({ className, size = 20 }) {
16
+ return (_jsxs("svg", { className: className, width: size, height: size, viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", children: [_jsx("path", { d: "M12 2C12 2 6 8 6 13a6 6 0 0 0 12 0c0-2-1-4-2-5 0 2-1 3-2 3 0-3-2-6-2-9Z", fill: "#F26B21" }), _jsx("path", { d: "M12 11c0 2-1.5 3-1.5 5a1.5 1.5 0 0 0 3 0c0-1.5-1.5-2.5-1.5-5Z", fill: "#FFD166" })] }));
17
+ }
18
+ /** DeepWiki — stacked pages with magnifying lens motif. */
19
+ export function DeepWikiIcon({ className, size = 20 }) {
20
+ return (_jsxs("svg", { className: className, width: size, height: size, viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", children: [_jsx("rect", { x: "4", y: "3", width: "13", height: "16", rx: "1.5", fill: "#6366F1" }), _jsx("rect", { x: "7", y: "6", width: "7", height: "1.5", rx: "0.5", fill: "#E0E7FF" }), _jsx("rect", { x: "7", y: "9", width: "7", height: "1.5", rx: "0.5", fill: "#E0E7FF" }), _jsx("rect", { x: "7", y: "12", width: "4", height: "1.5", rx: "0.5", fill: "#E0E7FF" }), _jsx("circle", { cx: "17", cy: "17", r: "4", fill: "none", stroke: "#F59E0B", strokeWidth: "2" }), _jsx("line", { x1: "20", y1: "20", x2: "22", y2: "22", stroke: "#F59E0B", strokeWidth: "2", strokeLinecap: "round" })] }));
21
+ }
22
+ /** AWS — orange cube mark. */
23
+ export function AwsIcon({ className, size = 20 }) {
24
+ return (_jsxs("svg", { className: className, width: size, height: size, viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", children: [_jsx("path", { d: "M6 14.5c0 1 .5 1.8 1.3 2.2L12 19l4.7-2.3c.8-.4 1.3-1.2 1.3-2.2v-5c0-1-.5-1.8-1.3-2.2L12 5 7.3 7.3C6.5 7.7 6 8.5 6 9.5v5Z", fill: "#FF9900" }), _jsx("path", { d: "M12 5v14M6 9.5l6 3 6-3", stroke: "#232F3E", strokeWidth: "1.2", fill: "none" })] }));
25
+ }