@shipit-ai/cli 1.170.0 → 1.171.0-pr15.c970346

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 (251) hide show
  1. package/apis/json-schema/ClaudeCodeProxyConfig.yaml +20 -0
  2. package/apis/json-schema/LiteLLMProxyConfig.yaml +4 -1
  3. package/apis/json-schema/LiteLLMProxyRoutingMode.yaml +8 -0
  4. package/dist/packages/core/src/domain/generated/output.d.ts +35 -1
  5. package/dist/packages/core/src/domain/generated/output.d.ts.map +1 -1
  6. package/dist/packages/core/src/domain/generated/output.js +6 -0
  7. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.d.ts +5 -0
  8. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.d.ts.map +1 -1
  9. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.js +38 -1
  10. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/055-add-litellm-proxy-agent-config.d.ts +15 -0
  11. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/055-add-litellm-proxy-agent-config.d.ts.map +1 -0
  12. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/055-add-litellm-proxy-agent-config.js +32 -0
  13. package/dist/packages/core/src/infrastructure/repositories/sqlite-settings.repository.d.ts.map +1 -1
  14. package/dist/packages/core/src/infrastructure/repositories/sqlite-settings.repository.js +36 -5
  15. package/dist/packages/core/src/infrastructure/services/agents/common/agent-executor-provider.service.d.ts.map +1 -1
  16. package/dist/packages/core/src/infrastructure/services/agents/common/agent-executor-provider.service.js +7 -1
  17. package/dist/packages/core/src/infrastructure/services/agents/common/executors/claude-code-executor.service.d.ts +4 -1
  18. package/dist/packages/core/src/infrastructure/services/agents/common/executors/claude-code-executor.service.d.ts.map +1 -1
  19. package/dist/packages/core/src/infrastructure/services/agents/common/executors/claude-code-executor.service.js +53 -0
  20. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.d.ts.map +1 -1
  21. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.js +5 -0
  22. package/dist/src/presentation/web/components/features/plugins/plugins-page-client.d.ts.map +1 -1
  23. package/dist/src/presentation/web/components/features/plugins/plugins-page-client.js +11 -2
  24. package/dist/src/presentation/web/components/features/settings/feature-flags-settings-section.d.ts.map +1 -1
  25. package/dist/src/presentation/web/components/features/settings/feature-flags-settings-section.js +3 -1
  26. package/dist/src/presentation/web/components/features/settings/litellm-proxy-routing-section.d.ts +6 -0
  27. package/dist/src/presentation/web/components/features/settings/litellm-proxy-routing-section.d.ts.map +1 -0
  28. package/dist/src/presentation/web/components/features/settings/litellm-proxy-routing-section.js +69 -0
  29. package/dist/src/presentation/web/components/features/settings/litellm-proxy-routing-section.stories.d.ts +16 -0
  30. package/dist/src/presentation/web/components/features/settings/litellm-proxy-routing-section.stories.d.ts.map +1 -0
  31. package/dist/src/presentation/web/components/features/settings/litellm-proxy-routing-section.stories.js +64 -0
  32. package/dist/src/presentation/web/components/features/settings/litellm-proxy-settings-section.d.ts.map +1 -1
  33. package/dist/src/presentation/web/components/features/settings/litellm-proxy-settings-section.js +5 -8
  34. package/dist/src/presentation/web/components/features/settings/settings-page-client.d.ts.map +1 -1
  35. package/dist/src/presentation/web/components/features/settings/settings-page-client.js +2 -1
  36. package/dist/src/presentation/web/components/features/skills/skills-page-client.d.ts.map +1 -1
  37. package/dist/src/presentation/web/components/features/skills/skills-page-client.js +6 -2
  38. package/dist/src/presentation/web/components/features/tools/tools-page-client.d.ts.map +1 -1
  39. package/dist/src/presentation/web/components/features/tools/tools-page-client.js +23 -4
  40. package/dist/translations/ar/web.json +18 -1
  41. package/dist/translations/de/web.json +18 -1
  42. package/dist/translations/en/web.json +18 -1
  43. package/dist/translations/es/web.json +18 -1
  44. package/dist/translations/fr/web.json +18 -1
  45. package/dist/translations/he/web.json +18 -1
  46. package/dist/translations/pt/web.json +18 -1
  47. package/dist/translations/ru/web.json +18 -1
  48. package/dist/tsconfig.build.tsbuildinfo +1 -1
  49. package/package.json +1 -1
  50. package/web/.next/BUILD_ID +1 -1
  51. package/web/.next/build-manifest.json +3 -3
  52. package/web/.next/fallback-build-manifest.json +3 -3
  53. package/web/.next/prerender-manifest.json +3 -3
  54. package/web/.next/required-server-files.js +3 -3
  55. package/web/.next/required-server-files.json +3 -3
  56. package/web/.next/server/app/(dashboard)/@drawer/adopt/page/server-reference-manifest.json +29 -29
  57. package/web/.next/server/app/(dashboard)/@drawer/adopt/page.js.nft.json +1 -1
  58. package/web/.next/server/app/(dashboard)/@drawer/adopt/page_client-reference-manifest.js +1 -1
  59. package/web/.next/server/app/(dashboard)/@drawer/chat/page/server-reference-manifest.json +27 -27
  60. package/web/.next/server/app/(dashboard)/@drawer/chat/page.js.nft.json +1 -1
  61. package/web/.next/server/app/(dashboard)/@drawer/chat/page_client-reference-manifest.js +1 -1
  62. package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +31 -31
  63. package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  64. package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  65. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +37 -37
  66. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  67. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  68. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +37 -37
  69. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  70. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  71. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page/server-reference-manifest.json +28 -28
  72. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page.js.nft.json +1 -1
  73. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page_client-reference-manifest.js +1 -1
  74. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +28 -28
  75. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  76. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  77. package/web/.next/server/app/(dashboard)/chat/page/server-reference-manifest.json +27 -27
  78. package/web/.next/server/app/(dashboard)/chat/page.js.nft.json +1 -1
  79. package/web/.next/server/app/(dashboard)/chat/page_client-reference-manifest.js +1 -1
  80. package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +31 -31
  81. package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  82. package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  83. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +37 -37
  84. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  85. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  86. package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +37 -37
  87. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  88. package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  89. package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +27 -27
  90. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  91. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  92. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page/server-reference-manifest.json +28 -28
  93. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page.js.nft.json +1 -1
  94. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page_client-reference-manifest.js +1 -1
  95. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +28 -28
  96. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  97. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  98. package/web/.next/server/app/_global-error.html +1 -1
  99. package/web/.next/server/app/_global-error.rsc +1 -1
  100. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  101. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  102. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  103. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  104. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  105. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +6 -6
  106. package/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  107. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  108. package/web/.next/server/app/api/attachments/preview/route.js.nft.json +1 -1
  109. package/web/.next/server/app/api/dialog/pick-files/route.js.nft.json +1 -1
  110. package/web/.next/server/app/api/evidence/route.js.nft.json +1 -1
  111. package/web/.next/server/app/api/graph-data/route.js.nft.json +1 -1
  112. package/web/.next/server/app/api/interactive/chat/[featureId]/messages/route.js.nft.json +1 -1
  113. package/web/.next/server/app/plugins/page/server-reference-manifest.json +15 -15
  114. package/web/.next/server/app/plugins/page.js.nft.json +1 -1
  115. package/web/.next/server/app/plugins/page_client-reference-manifest.js +1 -1
  116. package/web/.next/server/app/settings/page/server-reference-manifest.json +12 -12
  117. package/web/.next/server/app/settings/page.js.nft.json +1 -1
  118. package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  119. package/web/.next/server/app/skills/page/server-reference-manifest.json +11 -11
  120. package/web/.next/server/app/skills/page.js.nft.json +1 -1
  121. package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  122. package/web/.next/server/app/tools/page/server-reference-manifest.json +11 -11
  123. package/web/.next/server/app/tools/page.js.nft.json +1 -1
  124. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  125. package/web/.next/server/app/version/page/server-reference-manifest.json +6 -6
  126. package/web/.next/server/app/version/page.js.nft.json +1 -1
  127. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  128. package/web/.next/server/chunks/11es_next_dist_esm_build_templates_app-route_067cwst.js +1 -1
  129. package/web/.next/server/chunks/11es_next_dist_esm_build_templates_app-route_067cwst.js.map +1 -1
  130. package/web/.next/server/chunks/[root-of-the-server]__0tb~wwk._.js +1 -1
  131. package/web/.next/server/chunks/ssr/0j.8_web_components_common_control-center-drawer_create-drawer-client_tsx_0g70fc5._.js +1 -1
  132. package/web/.next/server/chunks/ssr/0j.8_web_components_common_control-center-drawer_create-drawer-client_tsx_0g70fc5._.js.map +1 -1
  133. package/web/.next/server/chunks/ssr/0j.8_web_components_common_control-center-drawer_feature-drawer-client_tsx_104cna.._.js +2 -2
  134. package/web/.next/server/chunks/ssr/0j.8_web_components_common_control-center-drawer_feature-drawer-client_tsx_104cna.._.js.map +1 -1
  135. package/web/.next/server/chunks/ssr/0ukq_presentation_web_components_features_settings_settings-page-client_tsx_0j1uius._.js +1 -1
  136. package/web/.next/server/chunks/ssr/0ukq_presentation_web_components_features_settings_settings-page-client_tsx_0j1uius._.js.map +1 -1
  137. package/web/.next/server/chunks/ssr/11y9_components_common_control-center-drawer_repository-drawer-client_tsx_09z.znp._.js +1 -1
  138. package/web/.next/server/chunks/ssr/11y9_components_common_control-center-drawer_repository-drawer-client_tsx_09z.znp._.js.map +1 -1
  139. package/web/.next/server/chunks/ssr/[root-of-the-server]__0.5ojmt._.js +1 -1
  140. package/web/.next/server/chunks/ssr/[root-of-the-server]__0.5ojmt._.js.map +1 -1
  141. package/web/.next/server/chunks/ssr/[root-of-the-server]__05_qc0n._.js +1 -1
  142. package/web/.next/server/chunks/ssr/[root-of-the-server]__05_qc0n._.js.map +1 -1
  143. package/web/.next/server/chunks/ssr/{[root-of-the-server]__0~v1~b9._.js → [root-of-the-server]__0dec29w._.js} +2 -2
  144. package/web/.next/server/chunks/ssr/{[root-of-the-server]__0~v1~b9._.js.map → [root-of-the-server]__0dec29w._.js.map} +1 -1
  145. package/web/.next/server/chunks/ssr/[root-of-the-server]__0ge~xny._.js +1 -1
  146. package/web/.next/server/chunks/ssr/[root-of-the-server]__0ge~xny._.js.map +1 -1
  147. package/web/.next/server/chunks/ssr/[root-of-the-server]__0qda~yi._.js +1 -1
  148. package/web/.next/server/chunks/ssr/[root-of-the-server]__0qda~yi._.js.map +1 -1
  149. package/web/.next/server/chunks/ssr/[root-of-the-server]__0rv1gci._.js +1 -1
  150. package/web/.next/server/chunks/ssr/[root-of-the-server]__0tq2syh._.js +1 -1
  151. package/web/.next/server/chunks/ssr/[root-of-the-server]__0t~u8sd._.js +1 -1
  152. package/web/.next/server/chunks/ssr/[root-of-the-server]__0t~u8sd._.js.map +1 -1
  153. package/web/.next/server/chunks/ssr/[root-of-the-server]__10tll_l._.js +1 -1
  154. package/web/.next/server/chunks/ssr/[root-of-the-server]__10tll_l._.js.map +1 -1
  155. package/web/.next/server/chunks/ssr/[root-of-the-server]__122xqm6._.js +1 -1
  156. package/web/.next/server/chunks/ssr/[root-of-the-server]__122xqm6._.js.map +1 -1
  157. package/web/.next/server/chunks/ssr/[root-of-the-server]__12j29w-._.js +1 -1
  158. package/web/.next/server/chunks/ssr/[root-of-the-server]__12j29w-._.js.map +1 -1
  159. package/web/.next/server/chunks/ssr/_01sesw0._.js +1 -1
  160. package/web/.next/server/chunks/ssr/_01sesw0._.js.map +1 -1
  161. package/web/.next/server/chunks/ssr/_069y.js._.js +2 -2
  162. package/web/.next/server/chunks/ssr/_069y.js._.js.map +1 -1
  163. package/web/.next/server/chunks/ssr/_083k45~._.js +1 -1
  164. package/web/.next/server/chunks/ssr/_083k45~._.js.map +1 -1
  165. package/web/.next/server/chunks/ssr/_0__4si~._.js +1 -1
  166. package/web/.next/server/chunks/ssr/_0__4si~._.js.map +1 -1
  167. package/web/.next/server/chunks/ssr/_0_m17kl._.js +1 -1
  168. package/web/.next/server/chunks/ssr/_0_m17kl._.js.map +1 -1
  169. package/web/.next/server/chunks/ssr/{_0_17.-n._.js → _0cbt_pe._.js} +2 -2
  170. package/web/.next/server/chunks/ssr/{_0_17.-n._.js.map → _0cbt_pe._.js.map} +1 -1
  171. package/web/.next/server/chunks/ssr/_0d4miu.._.js +1 -1
  172. package/web/.next/server/chunks/ssr/_0d4miu.._.js.map +1 -1
  173. package/web/.next/server/chunks/ssr/_0e8ern9._.js +1 -1
  174. package/web/.next/server/chunks/ssr/_0e8ern9._.js.map +1 -1
  175. package/web/.next/server/chunks/ssr/_0kaec~c._.js +3 -0
  176. package/web/.next/server/chunks/ssr/_0kaec~c._.js.map +1 -0
  177. package/web/.next/server/chunks/ssr/{_069ybyi._.js → _0m48x1h._.js} +2 -2
  178. package/web/.next/server/chunks/ssr/{_069ybyi._.js.map → _0m48x1h._.js.map} +1 -1
  179. package/web/.next/server/chunks/ssr/{_0kt18~b._.js → _0o.xc6x._.js} +2 -2
  180. package/web/.next/server/chunks/ssr/_0o.xc6x._.js.map +1 -0
  181. package/web/.next/server/chunks/ssr/_0p3~u8u._.js +2 -2
  182. package/web/.next/server/chunks/ssr/_0p3~u8u._.js.map +1 -1
  183. package/web/.next/server/chunks/ssr/_0r.3n~3._.js +1 -1
  184. package/web/.next/server/chunks/ssr/_0r.3n~3._.js.map +1 -1
  185. package/web/.next/server/chunks/ssr/_0t59q8r._.js +1 -1
  186. package/web/.next/server/chunks/ssr/_0t59q8r._.js.map +1 -1
  187. package/web/.next/server/chunks/ssr/_0tcccbb._.js.map +1 -1
  188. package/web/.next/server/chunks/ssr/_0u3d8.n._.js +1 -1
  189. package/web/.next/server/chunks/ssr/_0u3d8.n._.js.map +1 -1
  190. package/web/.next/server/chunks/ssr/_0vyfc4b._.js +1 -1
  191. package/web/.next/server/chunks/ssr/_0vyfc4b._.js.map +1 -1
  192. package/web/.next/server/chunks/ssr/_0w-_hww._.js +1 -1
  193. package/web/.next/server/chunks/ssr/_0w-_hww._.js.map +1 -1
  194. package/web/.next/server/chunks/ssr/_0zk-h5w._.js +1 -1
  195. package/web/.next/server/chunks/ssr/_0zk-h5w._.js.map +1 -1
  196. package/web/.next/server/chunks/ssr/{_0.ra89t._.js → _0zny-z9._.js} +2 -2
  197. package/web/.next/server/chunks/ssr/{_0.ra89t._.js.map → _0zny-z9._.js.map} +1 -1
  198. package/web/.next/server/chunks/ssr/_0~7lwu_._.js +1 -1
  199. package/web/.next/server/chunks/ssr/_0~7lwu_._.js.map +1 -1
  200. package/web/.next/server/chunks/ssr/_10joy2y._.js +1 -1
  201. package/web/.next/server/chunks/ssr/_10joy2y._.js.map +1 -1
  202. package/web/.next/server/chunks/ssr/_1161g9x._.js +1 -1
  203. package/web/.next/server/chunks/ssr/_1161g9x._.js.map +1 -1
  204. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_plugins_page_actions_0rdndum.js +1 -1
  205. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_plugins_page_actions_0rdndum.js.map +1 -1
  206. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_05m2q~u.js +1 -1
  207. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_05m2q~u.js.map +1 -1
  208. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_0.6zk.t.js +1 -1
  209. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_0.6zk.t.js.map +1 -1
  210. package/web/.next/server/chunks/ssr/src_presentation_web_app_actions_approve-feature_ts_0pjb_re._.js +1 -1
  211. package/web/.next/server/chunks/ssr/src_presentation_web_app_actions_open-ide_ts_0w2wqvu._.js +1 -1
  212. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_0l3oxx9._.js +1 -1
  213. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_0l3oxx9._.js.map +1 -1
  214. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_tools_tools-page-client_tsx_0aji.op._.js +1 -1
  215. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_tools_tools-page-client_tsx_0aji.op._.js.map +1 -1
  216. package/web/.next/server/middleware-build-manifest.js +3 -3
  217. package/web/.next/server/pages/500.html +1 -1
  218. package/web/.next/server/server-reference-manifest.js +1 -1
  219. package/web/.next/server/server-reference-manifest.json +55 -55
  220. package/web/.next/static/chunks/{0e.8n42~fpeqa.js → 0-dctejfh1ezj.js} +1 -1
  221. package/web/.next/static/chunks/0.s8cxri-_s9l.js +1 -0
  222. package/web/.next/static/chunks/{0nkujbu62z1jl.js → 012cnd7koqv6d.js} +1 -1
  223. package/web/.next/static/chunks/{0xzs6jdtkmbic.js → 01g-te343sxtc.js} +1 -1
  224. package/web/.next/static/chunks/{024vi1xxw5ccj.js → 05dq99wvihfwi.js} +1 -1
  225. package/web/.next/static/chunks/{0lwuepa24tqxy.js → 090gtsza1mtrd.js} +1 -1
  226. package/web/.next/static/chunks/{01zrwm.x3kpdo.js → 09h2zlstyosub.js} +1 -1
  227. package/web/.next/static/chunks/0inayq2zzadja.js +1 -0
  228. package/web/.next/static/chunks/0ko94op41qicn.js +1 -0
  229. package/web/.next/static/chunks/{09lcrhxslt-u8.js → 0kpksxtwl63iz.js} +1 -1
  230. package/web/.next/static/chunks/{0~4c6tnw7xnnl.js → 0lyqifogcd.ij.js} +1 -1
  231. package/web/.next/static/chunks/{0rb5cx51f5u8h.js → 0n30.8gk3k2.o.js} +1 -1
  232. package/web/.next/static/chunks/{0xo.hi4px83w2.js → 0nfd9bvcnbcgl.js} +1 -1
  233. package/web/.next/static/chunks/{0vq.b40jzhi7r.js → 0otq6yl_182dz.js} +3 -3
  234. package/web/.next/static/chunks/0ug478hm-8bog.js +5 -0
  235. package/web/.next/static/chunks/{043zp6fpfaz07.js → 0wspznee0_85_.js} +3 -3
  236. package/web/.next/static/chunks/{16jgc8hqxrp.u.js → 0ycq.dtttlbkt.js} +1 -1
  237. package/web/.next/static/chunks/{0dprl~vdhvhk7.js → 0zcsek9321fgg.js} +1 -1
  238. package/web/.next/static/chunks/10rtagfoabp3b.js +1 -0
  239. package/web/.next/static/chunks/182d0llxjxbzx.js +1 -0
  240. package/web/.next/server/chunks/ssr/_0kt18~b._.js.map +0 -1
  241. package/web/.next/server/chunks/ssr/_12uy.45._.js +0 -3
  242. package/web/.next/server/chunks/ssr/_12uy.45._.js.map +0 -1
  243. package/web/.next/static/chunks/0aq9-lg.5r.nk.js +0 -5
  244. package/web/.next/static/chunks/0jt5jzg88skg5.js +0 -1
  245. package/web/.next/static/chunks/0lz-oq74e_ciu.js +0 -1
  246. package/web/.next/static/chunks/0tdbctvrma.oi.js +0 -1
  247. package/web/.next/static/chunks/0wd.i4f822qoa.js +0 -1
  248. package/web/.next/static/chunks/13q1peb_t9vj8.js +0 -1
  249. /package/web/.next/static/{kDUolP-Zj2jCRleGJJGX0 → wv5eRhjSpKv_GUi67gN3a}/_buildManifest.js +0 -0
  250. /package/web/.next/static/{kDUolP-Zj2jCRleGJJGX0 → wv5eRhjSpKv_GUi67gN3a}/_clientMiddlewareManifest.js +0 -0
  251. /package/web/.next/static/{kDUolP-Zj2jCRleGJJGX0 → wv5eRhjSpKv_GUi67gN3a}/_ssgManifest.js +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"plugins-page-client.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/plugins/plugins-page-client.tsx"],"names":[],"mappings":"AAqBA,MAAM,WAAW,sBAAsB;IACrC,eAAe,EAAE,OAAO,CAAC;IACzB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,wBAAgB,iBAAiB,CAAC,EAAE,eAAe,EAAE,YAAY,EAAE,EAAE,sBAAsB,2CA0M1F"}
1
+ {"version":3,"file":"plugins-page-client.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/plugins/plugins-page-client.tsx"],"names":[],"mappings":"AAqBA,MAAM,WAAW,sBAAsB;IACrC,eAAe,EAAE,OAAO,CAAC;IACzB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,wBAAgB,iBAAiB,CAAC,EAAE,eAAe,EAAE,YAAY,EAAE,EAAE,sBAAsB,2CAiP1F"}
@@ -19,6 +19,7 @@ export function PluginsPageClient({ proxyConfigured, isClaudeCode }) {
19
19
  const [, startTransition] = useTransition();
20
20
  const [searchQuery, setSearchQuery] = useState('');
21
21
  const [activeCategory, setActiveCategory] = useState(null);
22
+ const [statusFilter, setStatusFilter] = useState(null);
22
23
  const [selectedPlugin, setSelectedPlugin] = useState(null);
23
24
  const [plugins, setPlugins] = useState([]);
24
25
  const [installedPlugins, setInstalledPlugins] = useState([]);
@@ -47,6 +48,13 @@ export function PluginsPageClient({ proxyConfigured, isClaudeCode }) {
47
48
  return plugins.filter((p) => {
48
49
  if (activeCategory && p.category !== activeCategory)
49
50
  return false;
51
+ if (statusFilter) {
52
+ const isInstalled = !!installedPlugins.find((ip) => ip.id.startsWith(`${p.name}@`));
53
+ if (statusFilter === 'installed' && !isInstalled)
54
+ return false;
55
+ if (statusFilter === 'not-installed' && isInstalled)
56
+ return false;
57
+ }
50
58
  if (query) {
51
59
  const matchesName = p.name.toLowerCase().includes(query);
52
60
  const matchesDescription = p.description.toLowerCase().includes(query);
@@ -55,7 +63,7 @@ export function PluginsPageClient({ proxyConfigured, isClaudeCode }) {
55
63
  }
56
64
  return true;
57
65
  });
58
- }, [plugins, searchQuery, activeCategory]);
66
+ }, [plugins, searchQuery, activeCategory, statusFilter, installedPlugins]);
59
67
  const getInstalled = (pluginName) => installedPlugins.find((ip) => ip.id.startsWith(`${pluginName}@`));
60
68
  const handleInstall = (pluginName) => {
61
69
  startTransition(async () => {
@@ -108,8 +116,9 @@ export function PluginsPageClient({ proxyConfigured, isClaudeCode }) {
108
116
  if (plugins.length === 0) {
109
117
  return (_jsxs("div", { className: "flex flex-col gap-8 p-8", children: [_jsx(PageHeader, { eyebrow: "Developer Portal", title: t('plugins.title') }), _jsx(EmptyState, { icon: _jsx(Blocks, { className: "size-10" }), title: t('plugins.emptyState') })] }));
110
118
  }
111
- return (_jsxs("div", { className: "flex flex-col gap-8 p-8", children: [_jsx(PageHeader, { eyebrow: "Developer Portal", title: t('plugins.title') }), _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('plugins.searchPlaceholder'), value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), className: "ps-9", "data-testid": "plugin-search" })] }), _jsxs("div", { className: "flex flex-wrap gap-2", children: [_jsx(Button, { variant: activeCategory === null ? 'default' : 'outline', size: "sm", onClick: () => setActiveCategory(null), children: t('plugins.allCategories') }), categories.map((cat) => (_jsx(Button, { variant: activeCategory === cat ? 'default' : 'outline', size: "sm", onClick: () => setActiveCategory(cat === activeCategory ? null : cat), children: cat }, cat)))] }), filteredPlugins.length > 0 ? (_jsx("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3", children: filteredPlugins.map((plugin) => (_jsx(PluginCard, { plugin: plugin, installed: getInstalled(plugin.name), onSelect: setSelectedPlugin, onToggle: handleToggle }, plugin.name))) })) : (_jsx(EmptyState, { icon: _jsx(Search, { className: "size-10" }), title: t('plugins.emptyState'), action: _jsx(Button, { variant: "outline", onClick: () => {
119
+ return (_jsxs("div", { className: "flex flex-col gap-8 p-8", children: [_jsx(PageHeader, { eyebrow: "Developer Portal", title: t('plugins.title') }), _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('plugins.searchPlaceholder'), value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), className: "ps-9", "data-testid": "plugin-search" })] }), _jsxs("div", { className: "flex flex-wrap items-center gap-4", children: [_jsxs("div", { className: "flex flex-wrap gap-2", children: [_jsx(Button, { variant: activeCategory === null ? 'default' : 'outline', size: "sm", onClick: () => setActiveCategory(null), children: t('plugins.allCategories') }), categories.map((cat) => (_jsx(Button, { variant: activeCategory === cat ? 'default' : 'outline', size: "sm", onClick: () => setActiveCategory(cat === activeCategory ? null : cat), children: cat }, cat)))] }), _jsx("div", { className: "bg-border h-6 w-px" }), _jsxs("div", { className: "flex flex-wrap gap-2", children: [_jsx(Button, { variant: statusFilter === null ? 'default' : 'outline', size: "sm", onClick: () => setStatusFilter(null), children: "All Status" }), _jsx(Button, { variant: statusFilter === 'installed' ? 'default' : 'outline', size: "sm", onClick: () => setStatusFilter(statusFilter === 'installed' ? null : 'installed'), children: t('plugins.installed') }), _jsx(Button, { variant: statusFilter === 'not-installed' ? 'default' : 'outline', size: "sm", onClick: () => setStatusFilter(statusFilter === 'not-installed' ? null : 'not-installed'), children: t('plugins.notInstalled') })] })] }), filteredPlugins.length > 0 ? (_jsx("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3", children: filteredPlugins.map((plugin) => (_jsx(PluginCard, { plugin: plugin, installed: getInstalled(plugin.name), onSelect: setSelectedPlugin, onToggle: handleToggle }, plugin.name))) })) : (_jsx(EmptyState, { icon: _jsx(Search, { className: "size-10" }), title: t('plugins.emptyState'), action: _jsx(Button, { variant: "outline", onClick: () => {
112
120
  setSearchQuery('');
113
121
  setActiveCategory(null);
122
+ setStatusFilter(null);
114
123
  }, children: t('plugins.clearFilters') }) })), _jsx(PluginDetailDrawer, { plugin: selectedPlugin, installed: selectedPlugin ? getInstalled(selectedPlugin.name) : undefined, open: !!selectedPlugin, onClose: () => setSelectedPlugin(null), onInstall: handleInstall, onUninstall: handleUninstall })] }));
115
124
  }
@@ -1 +1 @@
1
- {"version":3,"file":"feature-flags-settings-section.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/settings/feature-flags-settings-section.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,QAAQ,EAAgB,MAAM,yCAAyC,CAAC;AAGtF,MAAM,WAAW,gCAAgC;IAC/C,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED,wBAAgB,2BAA2B,CAAC,EAAE,QAAQ,EAAE,EAAE,gCAAgC,2CA6IzF"}
1
+ {"version":3,"file":"feature-flags-settings-section.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/settings/feature-flags-settings-section.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,QAAQ,EAAgB,MAAM,yCAAyC,CAAC;AAGtF,MAAM,WAAW,gCAAgC;IAC/C,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED,wBAAgB,2BAA2B,CAAC,EAAE,QAAQ,EAAE,EAAE,gCAAgC,2CAkJzF"}
@@ -56,7 +56,9 @@ export function FeatureFlagsSettingsSection({ settings }) {
56
56
  const newFlags = { ...flags, reactFileManager: v };
57
57
  setFlags(newFlags);
58
58
  save({ featureFlags: newFlags });
59
- } }), _jsx(SwitchRow, { label: t('settings.featureFlags.plugins'), description: t('settings.featureFlags.pluginsDescription'), tooltip: "Enables the Plugins page for browsing and managing Claude Code plugins from a LiteLLM marketplace.", id: "flag-plugins", testId: "switch-flag-plugins", checked: flags.plugins, onChange: (v) => {
59
+ } }), _jsx(SwitchRow, { label: t('settings.featureFlags.plugins'), description: settings.litellmProxy?.baseUrl
60
+ ? t('settings.featureFlags.pluginsDescription')
61
+ : `${t('settings.featureFlags.pluginsDescription')} — ${t('plugins.noProxy')}`, tooltip: "Enables the Plugins page for browsing and managing Claude Code plugins from a LiteLLM marketplace. Requires a LiteLLM proxy URL to be configured.", id: "flag-plugins", testId: "switch-flag-plugins", checked: flags.plugins, disabled: !settings.litellmProxy?.baseUrl, onChange: (v) => {
60
62
  const newFlags = { ...flags, plugins: v };
61
63
  setFlags(newFlags);
62
64
  save({ featureFlags: newFlags });
@@ -0,0 +1,6 @@
1
+ import type { Settings } from '../../../../../../packages/core/src/domain/generated/output.js';
2
+ export interface LiteLLMProxyRoutingSectionProps {
3
+ settings: Settings;
4
+ }
5
+ export declare function LiteLLMProxyRoutingSection({ settings }: LiteLLMProxyRoutingSectionProps): import("react/jsx-runtime").JSX.Element;
6
+ //# sourceMappingURL=litellm-proxy-routing-section.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"litellm-proxy-routing-section.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/settings/litellm-proxy-routing-section.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yCAAyC,CAAC;AAaxE,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED,wBAAgB,0BAA0B,CAAC,EAAE,QAAQ,EAAE,EAAE,+BAA+B,2CAwLvF"}
@@ -0,0 +1,69 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useState, useTransition } from 'react';
4
+ import { Route } from 'lucide-react';
5
+ import { toast } from 'sonner';
6
+ import { useTranslation } from 'react-i18next';
7
+ import { updateSettingsAction } from '../../../app/actions/update-settings.js';
8
+ import { LiteLLMProxyRoutingMode } from '../../../../../../packages/core/src/domain/generated/output.js';
9
+ import { SettingsSection, SettingsRow } from './settings-section-utils.js';
10
+ import { Input } from '../../ui/input.js';
11
+ import { Textarea } from '../../ui/textarea.js';
12
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '../../ui/select.js';
13
+ export function LiteLLMProxyRoutingSection({ settings }) {
14
+ const { t } = useTranslation('web');
15
+ const [, startTransition] = useTransition();
16
+ const cc = settings.litellmProxy?.claudeCode;
17
+ const [routingMode, setRoutingMode] = useState(cc?.routingMode ?? LiteLLMProxyRoutingMode.direct);
18
+ const [customHeaders, setCustomHeaders] = useState(cc?.customHeaders ?? '');
19
+ const [sonnetModel, setSonnetModel] = useState(cc?.sonnetModel ?? '');
20
+ const [haikuModel, setHaikuModel] = useState(cc?.haikuModel ?? '');
21
+ const [opusModel, setOpusModel] = useState(cc?.opusModel ?? '');
22
+ const originalCustomHeaders = cc?.customHeaders ?? '';
23
+ const originalSonnetModel = cc?.sonnetModel ?? '';
24
+ const originalHaikuModel = cc?.haikuModel ?? '';
25
+ const originalOpusModel = cc?.opusModel ?? '';
26
+ const showProxyFields = routingMode !== LiteLLMProxyRoutingMode.direct;
27
+ function save(payload) {
28
+ startTransition(async () => {
29
+ const result = await updateSettingsAction(payload);
30
+ if (!result.success) {
31
+ toast.error(result.error ?? t('settings.failedToSave'));
32
+ }
33
+ });
34
+ }
35
+ function buildPayload(overrides) {
36
+ return {
37
+ litellmProxy: {
38
+ claudeCode: {
39
+ routingMode: overrides?.routingMode ?? routingMode,
40
+ customHeaders: overrides?.customHeaders ?? customHeaders,
41
+ sonnetModel: overrides?.sonnetModel ?? sonnetModel,
42
+ haikuModel: overrides?.haikuModel ?? haikuModel,
43
+ opusModel: overrides?.opusModel ?? opusModel,
44
+ },
45
+ },
46
+ };
47
+ }
48
+ function handleModeChange(value) {
49
+ setRoutingMode(value);
50
+ save(buildPayload({ routingMode: value }));
51
+ }
52
+ return (_jsxs(SettingsSection, { icon: Route, title: t('settings.litellmProxy.routing.title'), description: t('settings.litellmProxy.routing.description'), testId: "litellm-proxy-routing-section", tooltip: t('settings.litellmProxy.routing.hint'), children: [_jsx(SettingsRow, { label: t('settings.litellmProxy.routing.mode'), description: t('settings.litellmProxy.routing.modeDescription'), htmlFor: "litellm-routing-mode", children: _jsxs(Select, { value: routingMode, onValueChange: handleModeChange, children: [_jsx(SelectTrigger, { id: "litellm-routing-mode", "data-testid": "litellm-routing-mode-select", className: "w-48 text-xs", children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: LiteLLMProxyRoutingMode.direct, children: t('settings.litellmProxy.routing.modeDirect') }), _jsx(SelectItem, { value: LiteLLMProxyRoutingMode.proxy, children: t('settings.litellmProxy.routing.modeProxy') }), _jsx(SelectItem, { value: LiteLLMProxyRoutingMode.passthrough, children: t('settings.litellmProxy.routing.modePassthrough') })] })] }) }), routingMode === LiteLLMProxyRoutingMode.passthrough && (_jsx(SettingsRow, { label: "", description: t('settings.litellmProxy.routing.passthroughHelp'), children: _jsx("span", {}) })), showProxyFields ? (_jsxs(_Fragment, { children: [_jsx(SettingsRow, { label: t('settings.litellmProxy.routing.customHeaders'), description: t('settings.litellmProxy.routing.customHeadersDescription'), htmlFor: "litellm-custom-headers", children: _jsx(Textarea, { id: "litellm-custom-headers", "data-testid": "litellm-custom-headers-input", placeholder: 'x-litellm-customer-id: my-user\nx-litellm-tags: project:acme', value: customHeaders, onChange: (e) => setCustomHeaders(e.target.value), onBlur: () => {
53
+ if (customHeaders !== originalCustomHeaders) {
54
+ save(buildPayload({ customHeaders }));
55
+ }
56
+ }, rows: 3, className: "w-64 text-xs" }) }), _jsx(SettingsRow, { label: t('settings.litellmProxy.routing.sonnetModel'), description: t('settings.litellmProxy.routing.modelOverrideDescription'), htmlFor: "litellm-sonnet-model", children: _jsx(Input, { id: "litellm-sonnet-model", "data-testid": "litellm-sonnet-model-input", type: "text", placeholder: "claude-sonnet-4-6", value: sonnetModel, onChange: (e) => setSonnetModel(e.target.value), onBlur: () => {
57
+ if (sonnetModel !== originalSonnetModel) {
58
+ save(buildPayload({ sonnetModel }));
59
+ }
60
+ }, className: "w-64 text-xs" }) }), _jsx(SettingsRow, { label: t('settings.litellmProxy.routing.haikuModel'), htmlFor: "litellm-haiku-model", children: _jsx(Input, { id: "litellm-haiku-model", "data-testid": "litellm-haiku-model-input", type: "text", placeholder: "claude-haiku-4-5", value: haikuModel, onChange: (e) => setHaikuModel(e.target.value), onBlur: () => {
61
+ if (haikuModel !== originalHaikuModel) {
62
+ save(buildPayload({ haikuModel }));
63
+ }
64
+ }, className: "w-64 text-xs" }) }), _jsx(SettingsRow, { label: t('settings.litellmProxy.routing.opusModel'), htmlFor: "litellm-opus-model", children: _jsx(Input, { id: "litellm-opus-model", "data-testid": "litellm-opus-model-input", type: "text", placeholder: "claude-opus-4-6", value: opusModel, onChange: (e) => setOpusModel(e.target.value), onBlur: () => {
65
+ if (opusModel !== originalOpusModel) {
66
+ save(buildPayload({ opusModel }));
67
+ }
68
+ }, className: "w-64 text-xs" }) })] })) : null] }));
69
+ }
@@ -0,0 +1,16 @@
1
+ import type { StoryObj } from '@storybook/react-vite';
2
+ import { LiteLLMProxyRoutingSection } from './litellm-proxy-routing-section.js';
3
+ declare const meta: {
4
+ title: string;
5
+ component: typeof LiteLLMProxyRoutingSection;
6
+ tags: string[];
7
+ parameters: {
8
+ layout: string;
9
+ };
10
+ };
11
+ export default meta;
12
+ type Story = StoryObj<typeof meta>;
13
+ export declare const DirectMode: Story;
14
+ export declare const ProxyMode: Story;
15
+ export declare const PassthroughMode: Story;
16
+ //# sourceMappingURL=litellm-proxy-routing-section.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"litellm-proxy-routing-section.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/settings/litellm-proxy-routing-section.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAa7E,QAAA,MAAM,IAAI;;;;;;;CAOyC,CAAC;AAEpD,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,UAAU,EAAE,KAYxB,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,KAgBvB,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAa7B,CAAC"}
@@ -0,0 +1,64 @@
1
+ import { LiteLLMProxyRoutingSection } from './litellm-proxy-routing-section.js';
2
+ import { createDefaultSettings } from '../../../../../../packages/core/src/domain/factories/settings-defaults.factory.js';
3
+ import { LiteLLMProxyRoutingMode } from '../../../../../../packages/core/src/domain/generated/output.js';
4
+ const baseSettings = {
5
+ ...createDefaultSettings(),
6
+ litellmProxy: {
7
+ baseUrl: 'http://localhost:4000',
8
+ apiKey: 'sk-litellm-proxy-key-1234',
9
+ marketplaceEnabled: true,
10
+ },
11
+ };
12
+ const meta = {
13
+ title: 'Features/Settings/LiteLLMProxyRoutingSection',
14
+ component: LiteLLMProxyRoutingSection,
15
+ tags: ['autodocs'],
16
+ parameters: {
17
+ layout: 'padded',
18
+ },
19
+ };
20
+ export default meta;
21
+ export const DirectMode = {
22
+ args: {
23
+ settings: {
24
+ ...baseSettings,
25
+ litellmProxy: {
26
+ ...baseSettings.litellmProxy,
27
+ claudeCode: {
28
+ routingMode: LiteLLMProxyRoutingMode.direct,
29
+ },
30
+ },
31
+ },
32
+ },
33
+ };
34
+ export const ProxyMode = {
35
+ args: {
36
+ settings: {
37
+ ...baseSettings,
38
+ litellmProxy: {
39
+ ...baseSettings.litellmProxy,
40
+ claudeCode: {
41
+ routingMode: LiteLLMProxyRoutingMode.proxy,
42
+ customHeaders: 'x-litellm-customer-id: user-123\nx-litellm-tags: project:acme',
43
+ sonnetModel: 'claude-sonnet-4-6',
44
+ haikuModel: 'claude-haiku-4-5',
45
+ opusModel: 'claude-opus-4-6',
46
+ },
47
+ },
48
+ },
49
+ },
50
+ };
51
+ export const PassthroughMode = {
52
+ args: {
53
+ settings: {
54
+ ...baseSettings,
55
+ litellmProxy: {
56
+ ...baseSettings.litellmProxy,
57
+ claudeCode: {
58
+ routingMode: LiteLLMProxyRoutingMode.passthrough,
59
+ sonnetModel: 'claude-sonnet-4-6',
60
+ },
61
+ },
62
+ },
63
+ },
64
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"litellm-proxy-settings-section.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/settings/litellm-proxy-settings-section.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yCAAyC,CAAC;AAKxE,MAAM,WAAW,gCAAgC;IAC/C,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED,wBAAgB,2BAA2B,CAAC,EAAE,QAAQ,EAAE,EAAE,gCAAgC,2CAiJzF"}
1
+ {"version":3,"file":"litellm-proxy-settings-section.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/settings/litellm-proxy-settings-section.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yCAAyC,CAAC;AAKxE,MAAM,WAAW,gCAAgC;IAC/C,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED,wBAAgB,2BAA2B,CAAC,EAAE,QAAQ,EAAE,EAAE,gCAAgC,2CA+HzF"}
@@ -6,7 +6,7 @@ import { toast } from 'sonner';
6
6
  import { useTranslation } from 'react-i18next';
7
7
  import { updateSettingsAction } from '../../../app/actions/update-settings.js';
8
8
  import { addMarketplaceAction } from '../../../app/actions/add-marketplace.js';
9
- import { SettingsSection, SettingsRow, SwitchRow } from './settings-section-utils.js';
9
+ import { SettingsSection, SettingsRow } from './settings-section-utils.js';
10
10
  import { Input } from '../../ui/input.js';
11
11
  import { Button } from '../../ui/button.js';
12
12
  export function LiteLLMProxySettingsSection({ settings }) {
@@ -14,7 +14,6 @@ export function LiteLLMProxySettingsSection({ settings }) {
14
14
  const [, startTransition] = useTransition();
15
15
  const [baseUrl, setBaseUrl] = useState(settings.litellmProxy?.baseUrl ?? '');
16
16
  const [apiKey, setApiKey] = useState(settings.litellmProxy?.apiKey ?? '');
17
- const [marketplaceEnabled, setMarketplaceEnabled] = useState(settings.litellmProxy?.marketplaceEnabled ?? false);
18
17
  const [testStatus, setTestStatus] = useState('idle');
19
18
  const [isTesting, setIsTesting] = useState(false);
20
19
  const originalBaseUrl = settings.litellmProxy?.baseUrl ?? '';
@@ -28,11 +27,12 @@ export function LiteLLMProxySettingsSection({ settings }) {
28
27
  });
29
28
  }
30
29
  function buildPayload(overrides) {
30
+ const url = overrides?.baseUrl ?? baseUrl;
31
31
  return {
32
32
  litellmProxy: {
33
- baseUrl: overrides?.baseUrl ?? baseUrl,
33
+ baseUrl: url,
34
34
  apiKey: overrides?.apiKey ?? apiKey,
35
- marketplaceEnabled: overrides?.marketplaceEnabled ?? marketplaceEnabled,
35
+ marketplaceEnabled: !!url,
36
36
  },
37
37
  };
38
38
  }
@@ -69,8 +69,5 @@ export function LiteLLMProxySettingsSection({ settings }) {
69
69
  }, className: "w-64 text-xs" }) }), _jsx(SettingsRow, { label: t('settings.litellmProxy.apiKey'), description: t('settings.litellmProxy.apiKeyDescription'), tooltip: "A virtual API key for authenticating with the LiteLLM proxy. Stored locally alongside other agent credentials.", htmlFor: "litellm-api-key", children: _jsx(Input, { id: "litellm-api-key", "data-testid": "litellm-api-key-input", type: "password", placeholder: "sk-...", value: apiKey, onChange: (e) => setApiKey(e.target.value), onBlur: () => {
70
70
  if (apiKey !== originalApiKey)
71
71
  save(buildPayload({ apiKey }));
72
- }, className: "w-64 text-xs" }) }), _jsx(SwitchRow, { label: t('settings.litellmProxy.marketplaceEnabled'), description: t('settings.litellmProxy.marketplaceEnabledDescription'), tooltip: "When enabled, the plugin marketplace will fetch its catalog from this LiteLLM proxy instead of using built-in defaults.", id: "litellm-marketplace-enabled", testId: "switch-litellm-marketplace-enabled", checked: marketplaceEnabled, onChange: (v) => {
73
- setMarketplaceEnabled(v);
74
- save(buildPayload({ marketplaceEnabled: v }));
75
- } }), _jsx(SettingsRow, { label: t('settings.litellmProxy.testConnection'), tooltip: "Attempt to connect to the proxy and fetch the marketplace catalog to verify the configuration is correct.", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Button, { variant: "outline", size: "sm", "data-testid": "litellm-test-connection-btn", disabled: !baseUrl || isTesting, onClick: handleTestConnection, className: "cursor-pointer text-xs", children: isTesting ? t('settings.saving') : t('settings.litellmProxy.testConnection') }), testStatus === 'success' && (_jsx(CheckCircle2, { className: "h-4 w-4 text-emerald-500", "data-testid": "litellm-test-success" })), testStatus === 'failed' && (_jsx(XCircle, { className: "text-destructive h-4 w-4", "data-testid": "litellm-test-failed" }))] }) })] }));
72
+ }, className: "w-64 text-xs" }) }), _jsx(SettingsRow, { label: t('settings.litellmProxy.testConnection'), tooltip: "Attempt to connect to the proxy and fetch the marketplace catalog to verify the configuration is correct.", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Button, { variant: "outline", size: "sm", "data-testid": "litellm-test-connection-btn", disabled: !baseUrl || isTesting, onClick: handleTestConnection, className: "cursor-pointer text-xs", children: isTesting ? t('settings.saving') : t('settings.litellmProxy.testConnection') }), testStatus === 'success' && (_jsx(CheckCircle2, { className: "h-4 w-4 text-emerald-500", "data-testid": "litellm-test-success" })), testStatus === 'failed' && (_jsx(XCircle, { className: "text-destructive h-4 w-4", "data-testid": "litellm-test-failed" }))] }) })] }));
76
73
  }
@@ -1 +1 @@
1
- {"version":3,"file":"settings-page-client.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/settings/settings-page-client.tsx"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yCAAyC,CAAC;AACxE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAC/E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAC3E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAkBzE,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,QAAQ,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,iBAAiB,EAAE,CAAC;IACzC,gBAAgB,CAAC,EAAE,eAAe,EAAE,CAAC;IACrC,eAAe,CAAC,EAAE,cAAc,EAAE,CAAC;CACpC;AAED,wBAAgB,kBAAkB,CAAC,EACjC,QAAQ,EACR,YAAY,EACZ,UAAU,EACV,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,GAChB,EAAE,uBAAuB,2CA4JzB"}
1
+ {"version":3,"file":"settings-page-client.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/settings/settings-page-client.tsx"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yCAAyC,CAAC;AACxE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAC/E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAC3E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAkBzE,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,QAAQ,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,iBAAiB,EAAE,CAAC;IACzC,gBAAgB,CAAC,EAAE,eAAe,EAAE,CAAC;IACrC,eAAe,CAAC,EAAE,cAAc,EAAE,CAAC;CACpC;AAED,wBAAgB,kBAAkB,CAAC,EACjC,QAAQ,EACR,YAAY,EACZ,UAAU,EACV,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,GAChB,EAAE,uBAAuB,2CA+JzB"}
@@ -15,6 +15,7 @@ import { InteractiveAgentSettingsSection } from './interactive-agent-settings-se
15
15
  import { FabLayoutSettingsSection } from './fab-layout-settings-section.js';
16
16
  import { DatabaseSettingsSection } from './database-settings-section.js';
17
17
  import { LiteLLMProxySettingsSection } from './litellm-proxy-settings-section.js';
18
+ import { LiteLLMProxyRoutingSection } from './litellm-proxy-routing-section.js';
18
19
  const SECTIONS = [
19
20
  { id: 'agent', labelKey: 'settings.sections.agent', icon: Bot },
20
21
  { id: 'environment', labelKey: 'settings.sections.environment', icon: Terminal },
@@ -58,5 +59,5 @@ export function SettingsPageClient({ settings, shipitAiHome, dbFileSize, availab
58
59
  return (_jsxs("button", { type: "button", onClick: () => setActiveTab(tab.id), className: cn('flex cursor-pointer items-center gap-1 rounded-md px-2 py-1.5 text-[11px] font-bold transition-all', isActive
59
60
  ? 'bg-muted text-primary shadow-sm ring-1 ring-slate-200/70 dark:ring-slate-700/50'
60
61
  : 'text-muted-foreground hover:text-foreground hover:bg-accent/50'), children: [_jsx(TabIcon, { className: "h-3 w-3" }), _jsx("span", { className: "hidden sm:inline", children: t(tab.labelKey) })] }, tab.id));
61
- }) })] }), _jsxs("div", { className: "flex flex-col gap-3", children: [(activeTab === 'all' || activeTab === 'agent') && (_jsx("div", { id: "section-agent", className: "scroll-mt-18 rounded-lg", children: _jsx(AgentSettingsSection, { settings: settings }) })), (activeTab === 'all' || activeTab === 'environment') && (_jsx("div", { id: "section-environment", className: "scroll-mt-18 rounded-lg", children: _jsx(EnvironmentSettingsSection, { settings: settings, availableEditors: availableEditors, availableShells: availableShells, availableTerminals: availableTerminals }) })), (activeTab === 'all' || activeTab === 'workflow') && (_jsx("div", { id: "section-workflow", className: "scroll-mt-18 rounded-lg", children: _jsx(WorkflowSettingsSection, { settings: settings }) })), (activeTab === 'all' || activeTab === 'ci') && (_jsx("div", { id: "section-ci", className: "scroll-mt-18 rounded-lg", children: _jsx(CiSettingsSection, { settings: settings }) })), (activeTab === 'all' || activeTab === 'stage-timeouts') && (_jsx("div", { id: "section-stage-timeouts", className: "scroll-mt-18 rounded-lg", children: _jsx(StageTimeoutsSettingsSection, { settings: settings }) })), (activeTab === 'all' || activeTab === 'notifications') && (_jsx("div", { id: "section-notifications", className: "scroll-mt-18 rounded-lg", children: _jsx(NotificationSettingsSection, { settings: settings }) })), (activeTab === 'all' || activeTab === 'feature-flags') && (_jsx("div", { id: "section-feature-flags", className: "scroll-mt-18 rounded-lg", children: _jsx(FeatureFlagsSettingsSection, { settings: settings }) })), (activeTab === 'all' || activeTab === 'interactive-agent') && (_jsx("div", { id: "section-interactive-agent", className: "scroll-mt-18 rounded-lg", children: _jsx(InteractiveAgentSettingsSection, { settings: settings }) })), (activeTab === 'all' || activeTab === 'fab-layout') && (_jsx("div", { id: "section-fab-layout", className: "scroll-mt-18 rounded-lg", children: _jsx(FabLayoutSettingsSection, { settings: settings }) })), (activeTab === 'all' || activeTab === 'database') && (_jsx("div", { id: "section-database", className: "scroll-mt-18 rounded-lg", children: _jsx(DatabaseSettingsSection, { shipitAiHome: shipitAiHome, dbFileSize: dbFileSize }) })), (activeTab === 'all' || activeTab === 'litellm-proxy') && (_jsx("div", { id: "section-litellm-proxy", className: "scroll-mt-18 rounded-lg", children: _jsx(LiteLLMProxySettingsSection, { settings: settings }) }))] })] }));
62
+ }) })] }), _jsxs("div", { className: "flex flex-col gap-3", children: [(activeTab === 'all' || activeTab === 'agent') && (_jsx("div", { id: "section-agent", className: "scroll-mt-18 rounded-lg", children: _jsx(AgentSettingsSection, { settings: settings }) })), (activeTab === 'all' || activeTab === 'environment') && (_jsx("div", { id: "section-environment", className: "scroll-mt-18 rounded-lg", children: _jsx(EnvironmentSettingsSection, { settings: settings, availableEditors: availableEditors, availableShells: availableShells, availableTerminals: availableTerminals }) })), (activeTab === 'all' || activeTab === 'workflow') && (_jsx("div", { id: "section-workflow", className: "scroll-mt-18 rounded-lg", children: _jsx(WorkflowSettingsSection, { settings: settings }) })), (activeTab === 'all' || activeTab === 'ci') && (_jsx("div", { id: "section-ci", className: "scroll-mt-18 rounded-lg", children: _jsx(CiSettingsSection, { settings: settings }) })), (activeTab === 'all' || activeTab === 'stage-timeouts') && (_jsx("div", { id: "section-stage-timeouts", className: "scroll-mt-18 rounded-lg", children: _jsx(StageTimeoutsSettingsSection, { settings: settings }) })), (activeTab === 'all' || activeTab === 'notifications') && (_jsx("div", { id: "section-notifications", className: "scroll-mt-18 rounded-lg", children: _jsx(NotificationSettingsSection, { settings: settings }) })), (activeTab === 'all' || activeTab === 'feature-flags') && (_jsx("div", { id: "section-feature-flags", className: "scroll-mt-18 rounded-lg", children: _jsx(FeatureFlagsSettingsSection, { settings: settings }) })), (activeTab === 'all' || activeTab === 'interactive-agent') && (_jsx("div", { id: "section-interactive-agent", className: "scroll-mt-18 rounded-lg", children: _jsx(InteractiveAgentSettingsSection, { settings: settings }) })), (activeTab === 'all' || activeTab === 'fab-layout') && (_jsx("div", { id: "section-fab-layout", className: "scroll-mt-18 rounded-lg", children: _jsx(FabLayoutSettingsSection, { settings: settings }) })), (activeTab === 'all' || activeTab === 'database') && (_jsx("div", { id: "section-database", className: "scroll-mt-18 rounded-lg", children: _jsx(DatabaseSettingsSection, { shipitAiHome: shipitAiHome, dbFileSize: dbFileSize }) })), (activeTab === 'all' || activeTab === 'litellm-proxy') && (_jsxs("div", { id: "section-litellm-proxy", className: "scroll-mt-18 rounded-lg", children: [_jsx(LiteLLMProxySettingsSection, { settings: settings }), settings.litellmProxy?.baseUrl ? (_jsx(LiteLLMProxyRoutingSection, { settings: settings })) : null] }))] })] }));
62
63
  }
@@ -1 +1 @@
1
- {"version":3,"file":"skills-page-client.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/skills/skills-page-client.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAiB,SAAS,EAAE,MAAM,cAAc,CAAC;AAE7D,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,SAAS,EAAE,CAAC;CACrB;AAeD,wBAAgB,gBAAgB,CAAC,EAAE,MAAM,EAAE,EAAE,qBAAqB,2CAyFjE"}
1
+ {"version":3,"file":"skills-page-client.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/skills/skills-page-client.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAiB,SAAS,EAAe,MAAM,cAAc,CAAC;AAE1E,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,SAAS,EAAE,CAAC;CACrB;AAeD,wBAAgB,gBAAgB,CAAC,EAAE,MAAM,EAAE,EAAE,qBAAqB,2CAqHjE"}
@@ -24,6 +24,7 @@ function computeCategoryCounts(skills) {
24
24
  export function SkillsPageClient({ skills }) {
25
25
  const [searchQuery, setSearchQuery] = useState('');
26
26
  const [activeCategory, setActiveCategory] = useState(null);
27
+ const [sourceFilter, setSourceFilter] = useState(null);
27
28
  const [selectedSkill, setSelectedSkill] = useState(null);
28
29
  const categoryCounts = useMemo(() => computeCategoryCounts(skills), [skills]);
29
30
  const filteredSkills = useMemo(() => {
@@ -31,6 +32,8 @@ export function SkillsPageClient({ skills }) {
31
32
  return skills.filter((skill) => {
32
33
  if (activeCategory && skill.category !== activeCategory)
33
34
  return false;
35
+ if (sourceFilter && skill.source !== sourceFilter)
36
+ return false;
34
37
  if (query) {
35
38
  const matchesName = skill.name.toLowerCase().includes(query);
36
39
  const matchesDescription = skill.description.toLowerCase().includes(query);
@@ -39,14 +42,15 @@ export function SkillsPageClient({ skills }) {
39
42
  }
40
43
  return true;
41
44
  });
42
- }, [skills, searchQuery, activeCategory]);
45
+ }, [skills, searchQuery, activeCategory, sourceFilter]);
43
46
  const clearFilters = () => {
44
47
  setSearchQuery('');
45
48
  setActiveCategory(null);
49
+ setSourceFilter(null);
46
50
  };
47
51
  // No skills installed at all
48
52
  if (skills.length === 0) {
49
53
  return (_jsxs("div", { className: "flex flex-col gap-8 p-8", children: [_jsx(PageHeader, { eyebrow: "Developer Portal", title: "Skills", description: "Claude Code skills installed in this project" }), _jsx(EmptyState, { icon: _jsx(Puzzle, { className: "size-10" }), title: "No skills found", description: "No Claude Code skills are installed. Add skills to .claude/skills/ to get started." })] }));
50
54
  }
51
- return (_jsxs("div", { className: "flex flex-col gap-8 p-8", children: [_jsx(PageHeader, { eyebrow: "Developer Portal", title: "Skills", description: "Claude Code skills installed in this project" }), _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: "Search skills...", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), className: "ps-9" })] }), _jsx(CategoryFilter, { activeCategory: activeCategory, onCategoryChange: setActiveCategory, counts: categoryCounts }), filteredSkills.length > 0 ? (_jsx(SkillList, { skills: filteredSkills, onSkillSelect: setSelectedSkill })) : (_jsx(EmptyState, { icon: _jsx(Search, { className: "size-10" }), title: "No matching skills", description: "No skills match your current search and filter criteria.", action: _jsx(Button, { variant: "outline", onClick: clearFilters, children: "Clear filters" }) })), _jsx(SkillDetailDrawer, { skill: selectedSkill, onClose: () => setSelectedSkill(null) })] }));
55
+ return (_jsxs("div", { className: "flex flex-col gap-8 p-8", children: [_jsx(PageHeader, { eyebrow: "Developer Portal", title: "Skills", description: "Claude Code skills installed in this project" }), _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: "Search skills...", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), className: "ps-9" })] }), _jsx(CategoryFilter, { activeCategory: activeCategory, onCategoryChange: setActiveCategory, counts: categoryCounts }), _jsxs("div", { className: "flex flex-wrap gap-2", children: [_jsx(Button, { variant: sourceFilter === null ? 'default' : 'outline', size: "sm", onClick: () => setSourceFilter(null), children: "All Sources" }), _jsx(Button, { variant: sourceFilter === 'project' ? 'default' : 'outline', size: "sm", onClick: () => setSourceFilter('project'), children: "Project" }), _jsx(Button, { variant: sourceFilter === 'global' ? 'default' : 'outline', size: "sm", onClick: () => setSourceFilter('global'), children: "Global" })] }), filteredSkills.length > 0 ? (_jsx(SkillList, { skills: filteredSkills, onSkillSelect: setSelectedSkill })) : (_jsx(EmptyState, { icon: _jsx(Search, { className: "size-10" }), title: "No matching skills", description: "No skills match your current search and filter criteria.", action: _jsx(Button, { variant: "outline", onClick: clearFilters, children: "Clear filters" }) })), _jsx(SkillDetailDrawer, { skill: selectedSkill, onClose: () => setSelectedSkill(null) })] }));
52
56
  }
@@ -1 +1 @@
1
- {"version":3,"file":"tools-page-client.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/tools/tools-page-client.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iEAAiE,CAAC;AAEhG,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAYD,wBAAgB,eAAe,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,EAAE,oBAAoB,2CAkIvF"}
1
+ {"version":3,"file":"tools-page-client.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/tools/tools-page-client.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iEAAiE,CAAC;AAEhG,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAaD,wBAAgB,eAAe,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,EAAE,oBAAoB,2CAqLvF"}
@@ -1,8 +1,10 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useState, useCallback } from 'react';
4
- import { Wrench } from 'lucide-react';
3
+ import { useState, useCallback, useMemo } from 'react';
4
+ import { Wrench, Search } from 'lucide-react';
5
5
  import { Tabs, TabsContent, TabsList, TabsTrigger } from '../../ui/tabs.js';
6
+ import { Input } from '../../ui/input.js';
7
+ import { Button } from '../../ui/button.js';
6
8
  import { cn } from '../../../lib/utils.js';
7
9
  import { ToolCard } from './tool-card.js';
8
10
  const TAB_FILTER = {
@@ -15,6 +17,8 @@ const TAB_FILTER = {
15
17
  export function ToolsPageClient({ tools: initialTools, className }) {
16
18
  const [tools, setTools] = useState(initialTools);
17
19
  const [activeTab, setActiveTab] = useState('all');
20
+ const [searchQuery, setSearchQuery] = useState('');
21
+ const [statusFilter, setStatusFilter] = useState(null);
18
22
  const refreshTools = useCallback(async () => {
19
23
  try {
20
24
  const res = await fetch('/api/tools');
@@ -27,9 +31,24 @@ export function ToolsPageClient({ tools: initialTools, className }) {
27
31
  // Silently ignore refresh errors; user can re-navigate to refresh
28
32
  }
29
33
  }, []);
30
- const filtered = tools.filter(TAB_FILTER[activeTab]);
34
+ const filtered = useMemo(() => {
35
+ const query = searchQuery.toLowerCase();
36
+ return tools.filter((tool) => {
37
+ if (!TAB_FILTER[activeTab](tool))
38
+ return false;
39
+ if (statusFilter && tool.status.status !== statusFilter)
40
+ return false;
41
+ if (query) {
42
+ const matchesName = tool.name.toLowerCase().includes(query);
43
+ const matchesSummary = tool.summary.toLowerCase().includes(query);
44
+ if (!matchesName && !matchesSummary)
45
+ return false;
46
+ }
47
+ return true;
48
+ });
49
+ }, [tools, activeTab, searchQuery, statusFilter]);
31
50
  const installedCount = tools.filter((t) => t.status.status === 'available').length;
32
- return (_jsxs("div", { "data-testid": "tools-page-client", className: cn('space-y-8', className), children: [_jsxs("div", { className: "space-y-1.5", children: [_jsx("div", { className: "flex items-center gap-2", children: _jsx("span", { className: "text-[10px] font-bold tracking-[0.2em] text-slate-400 uppercase", children: "Developer Portal" }) }), _jsxs("div", { className: "flex items-baseline gap-3", children: [_jsx("h1", { className: "text-foreground text-3xl font-black tracking-tight", children: "Tools" }), _jsxs("span", { className: "text-muted-foreground text-sm font-medium", children: [installedCount, " of ", tools.length, " installed"] })] })] }), _jsxs(Tabs, { value: activeTab, onValueChange: (value) => setActiveTab(value), "data-testid": "tools-page-tabs", children: [_jsxs(TabsList, { "data-editorial": "true", className: "bg-card editorial-shadow h-10 p-1", children: [_jsx(TabsTrigger, { value: "all", "data-testid": "tools-tab-all", className: "cursor-pointer px-4 text-xs font-bold", children: "All" }), _jsx(TabsTrigger, { value: "ide", "data-testid": "tools-tab-ide", className: "cursor-pointer px-4 text-xs font-bold", children: "IDEs" }), _jsx(TabsTrigger, { value: "cli-agent", "data-testid": "tools-tab-cli-agent", className: "cursor-pointer px-4 text-xs font-bold", children: "CLI Agents" }), _jsx(TabsTrigger, { value: "vcs", "data-testid": "tools-tab-vcs", className: "cursor-pointer px-4 text-xs font-bold", children: "Version Control" }), _jsx(TabsTrigger, { value: "terminal", "data-testid": "tools-tab-terminal", className: "cursor-pointer px-4 text-xs font-bold", children: "Terminals" })] }), _jsx(TabsContent, { value: activeTab, className: "mt-6", children: filtered.length === 0 ? (_jsxs("div", { "data-testid": "tools-page-empty", className: "text-muted-foreground flex flex-col items-center justify-center py-16 text-center", children: [_jsx(Wrench, { className: "mb-3 h-8 w-8 opacity-20" }), _jsx("p", { className: "text-sm", children: "No tools in this category." })] })) : (_jsx("div", { "data-testid": "tools-page-grid",
51
+ return (_jsxs("div", { "data-testid": "tools-page-client", className: cn('space-y-8', className), children: [_jsxs("div", { className: "space-y-1.5", children: [_jsx("div", { className: "flex items-center gap-2", children: _jsx("span", { className: "text-[10px] font-bold tracking-[0.2em] text-slate-400 uppercase", children: "Developer Portal" }) }), _jsxs("div", { className: "flex items-baseline gap-3", children: [_jsx("h1", { className: "text-foreground text-3xl font-black tracking-tight", children: "Tools" }), _jsxs("span", { className: "text-muted-foreground text-sm font-medium", children: [installedCount, " of ", tools.length, " installed"] })] })] }), _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: "Search tools...", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), className: "ps-9", "data-testid": "tool-search" })] }), _jsxs(Tabs, { value: activeTab, onValueChange: (value) => setActiveTab(value), "data-testid": "tools-page-tabs", children: [_jsxs(TabsList, { "data-editorial": "true", className: "bg-card editorial-shadow h-10 p-1", children: [_jsx(TabsTrigger, { value: "all", "data-testid": "tools-tab-all", className: "cursor-pointer px-4 text-xs font-bold", children: "All" }), _jsx(TabsTrigger, { value: "ide", "data-testid": "tools-tab-ide", className: "cursor-pointer px-4 text-xs font-bold", children: "IDEs" }), _jsx(TabsTrigger, { value: "cli-agent", "data-testid": "tools-tab-cli-agent", className: "cursor-pointer px-4 text-xs font-bold", children: "CLI Agents" }), _jsx(TabsTrigger, { value: "vcs", "data-testid": "tools-tab-vcs", className: "cursor-pointer px-4 text-xs font-bold", children: "Version Control" }), _jsx(TabsTrigger, { value: "terminal", "data-testid": "tools-tab-terminal", className: "cursor-pointer px-4 text-xs font-bold", children: "Terminals" })] }), _jsxs("div", { className: "mt-4 flex flex-wrap gap-2", "data-testid": "tools-status-filter", children: [_jsx(Button, { variant: statusFilter === null ? 'default' : 'outline', size: "sm", onClick: () => setStatusFilter(null), children: "All" }), _jsx(Button, { variant: statusFilter === 'available' ? 'default' : 'outline', size: "sm", onClick: () => setStatusFilter('available'), children: "Installed" }), _jsx(Button, { variant: statusFilter === 'missing' ? 'default' : 'outline', size: "sm", onClick: () => setStatusFilter('missing'), children: "Not Installed" })] }), _jsx(TabsContent, { value: activeTab, className: "mt-6", children: filtered.length === 0 ? (_jsxs("div", { "data-testid": "tools-page-empty", className: "text-muted-foreground flex flex-col items-center justify-center py-16 text-center", children: [_jsx(Wrench, { className: "mb-3 h-8 w-8 opacity-20" }), _jsx("p", { className: "text-sm", children: "No tools in this category." })] })) : (_jsx("div", { "data-testid": "tools-page-grid",
33
52
  // Editorial density: 3 columns max so cards stay wide enough to
34
53
  // give the Stitch "magazine" feel. Previously xl:grid-cols-4 which
35
54
  // squeezed cards and reduced background-vs-card contrast.
@@ -226,7 +226,24 @@
226
226
  "hint": "Connect to a LiteLLM proxy to browse and install Claude Code plugins from your organization's curated marketplace.",
227
227
  "testConnection": "Test Connection",
228
228
  "testSuccess": "Connection successful",
229
- "testFailed": "Connection failed"
229
+ "testFailed": "Connection failed",
230
+ "routing": {
231
+ "title": "Proxy Routing (Claude Code)",
232
+ "description": "Configure how Claude Code routes API traffic through LiteLLM",
233
+ "hint": "Control whether Claude Code uses the LiteLLM proxy for API requests. Supports full proxy routing, passthrough for Max/BYOK subscriptions, and model overrides.",
234
+ "mode": "Routing Mode",
235
+ "modeDescription": "How Claude Code routes API traffic",
236
+ "modeDirect": "Direct (own subscription)",
237
+ "modeProxy": "Proxy (full routing)",
238
+ "modePassthrough": "Passthrough (Max/BYOK)",
239
+ "passthroughHelp": "Passthrough mode requires the LiteLLM proxy to have forward_client_headers_to_llm_api or forward_llm_provider_auth_headers enabled.",
240
+ "customHeaders": "Custom Headers",
241
+ "customHeadersDescription": "Newline-separated headers for cost attribution (e.g., x-litellm-customer-id: user-123)",
242
+ "sonnetModel": "Sonnet Model Override",
243
+ "haikuModel": "Haiku Model Override",
244
+ "opusModel": "Opus Model Override",
245
+ "modelOverrideDescription": "Override the default model routed through LiteLLM"
246
+ }
230
247
  },
231
248
  "interactiveAgent": {
232
249
  "title": "الوكيل التفاعلي",
@@ -212,7 +212,24 @@
212
212
  "hint": "Connect to a LiteLLM proxy to browse and install Claude Code plugins from your organization's curated marketplace.",
213
213
  "testConnection": "Test Connection",
214
214
  "testSuccess": "Connection successful",
215
- "testFailed": "Connection failed"
215
+ "testFailed": "Connection failed",
216
+ "routing": {
217
+ "title": "Proxy Routing (Claude Code)",
218
+ "description": "Configure how Claude Code routes API traffic through LiteLLM",
219
+ "hint": "Control whether Claude Code uses the LiteLLM proxy for API requests. Supports full proxy routing, passthrough for Max/BYOK subscriptions, and model overrides.",
220
+ "mode": "Routing Mode",
221
+ "modeDescription": "How Claude Code routes API traffic",
222
+ "modeDirect": "Direct (own subscription)",
223
+ "modeProxy": "Proxy (full routing)",
224
+ "modePassthrough": "Passthrough (Max/BYOK)",
225
+ "passthroughHelp": "Passthrough mode requires the LiteLLM proxy to have forward_client_headers_to_llm_api or forward_llm_provider_auth_headers enabled.",
226
+ "customHeaders": "Custom Headers",
227
+ "customHeadersDescription": "Newline-separated headers for cost attribution (e.g., x-litellm-customer-id: user-123)",
228
+ "sonnetModel": "Sonnet Model Override",
229
+ "haikuModel": "Haiku Model Override",
230
+ "opusModel": "Opus Model Override",
231
+ "modelOverrideDescription": "Override the default model routed through LiteLLM"
232
+ }
216
233
  },
217
234
  "interactiveAgent": {
218
235
  "title": "Interaktiver Agent",
@@ -226,7 +226,24 @@
226
226
  "hint": "Connect to a LiteLLM proxy to browse and install Claude Code plugins from your organization's curated marketplace.",
227
227
  "testConnection": "Test Connection",
228
228
  "testSuccess": "Connection successful",
229
- "testFailed": "Connection failed"
229
+ "testFailed": "Connection failed",
230
+ "routing": {
231
+ "title": "Proxy Routing (Claude Code)",
232
+ "description": "Configure how Claude Code routes API traffic through LiteLLM",
233
+ "hint": "Control whether Claude Code uses the LiteLLM proxy for API requests. Supports full proxy routing, passthrough for Max/BYOK subscriptions, and model overrides.",
234
+ "mode": "Routing Mode",
235
+ "modeDescription": "How Claude Code routes API traffic",
236
+ "modeDirect": "Direct (own subscription)",
237
+ "modeProxy": "Proxy (full routing)",
238
+ "modePassthrough": "Passthrough (Max/BYOK)",
239
+ "passthroughHelp": "Passthrough mode requires the LiteLLM proxy to have forward_client_headers_to_llm_api or forward_llm_provider_auth_headers enabled.",
240
+ "customHeaders": "Custom Headers",
241
+ "customHeadersDescription": "Newline-separated headers for cost attribution (e.g., x-litellm-customer-id: user-123)",
242
+ "sonnetModel": "Sonnet Model Override",
243
+ "haikuModel": "Haiku Model Override",
244
+ "opusModel": "Opus Model Override",
245
+ "modelOverrideDescription": "Override the default model routed through LiteLLM"
246
+ }
230
247
  },
231
248
  "interactiveAgent": {
232
249
  "title": "Interactive Agent",
@@ -226,7 +226,24 @@
226
226
  "hint": "Connect to a LiteLLM proxy to browse and install Claude Code plugins from your organization's curated marketplace.",
227
227
  "testConnection": "Test Connection",
228
228
  "testSuccess": "Connection successful",
229
- "testFailed": "Connection failed"
229
+ "testFailed": "Connection failed",
230
+ "routing": {
231
+ "title": "Proxy Routing (Claude Code)",
232
+ "description": "Configure how Claude Code routes API traffic through LiteLLM",
233
+ "hint": "Control whether Claude Code uses the LiteLLM proxy for API requests. Supports full proxy routing, passthrough for Max/BYOK subscriptions, and model overrides.",
234
+ "mode": "Routing Mode",
235
+ "modeDescription": "How Claude Code routes API traffic",
236
+ "modeDirect": "Direct (own subscription)",
237
+ "modeProxy": "Proxy (full routing)",
238
+ "modePassthrough": "Passthrough (Max/BYOK)",
239
+ "passthroughHelp": "Passthrough mode requires the LiteLLM proxy to have forward_client_headers_to_llm_api or forward_llm_provider_auth_headers enabled.",
240
+ "customHeaders": "Custom Headers",
241
+ "customHeadersDescription": "Newline-separated headers for cost attribution (e.g., x-litellm-customer-id: user-123)",
242
+ "sonnetModel": "Sonnet Model Override",
243
+ "haikuModel": "Haiku Model Override",
244
+ "opusModel": "Opus Model Override",
245
+ "modelOverrideDescription": "Override the default model routed through LiteLLM"
246
+ }
230
247
  },
231
248
  "interactiveAgent": {
232
249
  "title": "Agente interactivo",
@@ -226,7 +226,24 @@
226
226
  "hint": "Connect to a LiteLLM proxy to browse and install Claude Code plugins from your organization's curated marketplace.",
227
227
  "testConnection": "Test Connection",
228
228
  "testSuccess": "Connection successful",
229
- "testFailed": "Connection failed"
229
+ "testFailed": "Connection failed",
230
+ "routing": {
231
+ "title": "Proxy Routing (Claude Code)",
232
+ "description": "Configure how Claude Code routes API traffic through LiteLLM",
233
+ "hint": "Control whether Claude Code uses the LiteLLM proxy for API requests. Supports full proxy routing, passthrough for Max/BYOK subscriptions, and model overrides.",
234
+ "mode": "Routing Mode",
235
+ "modeDescription": "How Claude Code routes API traffic",
236
+ "modeDirect": "Direct (own subscription)",
237
+ "modeProxy": "Proxy (full routing)",
238
+ "modePassthrough": "Passthrough (Max/BYOK)",
239
+ "passthroughHelp": "Passthrough mode requires the LiteLLM proxy to have forward_client_headers_to_llm_api or forward_llm_provider_auth_headers enabled.",
240
+ "customHeaders": "Custom Headers",
241
+ "customHeadersDescription": "Newline-separated headers for cost attribution (e.g., x-litellm-customer-id: user-123)",
242
+ "sonnetModel": "Sonnet Model Override",
243
+ "haikuModel": "Haiku Model Override",
244
+ "opusModel": "Opus Model Override",
245
+ "modelOverrideDescription": "Override the default model routed through LiteLLM"
246
+ }
230
247
  },
231
248
  "interactiveAgent": {
232
249
  "title": "Agent interactif",