omniroute 3.4.7 → 3.4.8

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 (256) hide show
  1. package/app/.next/BUILD_ID +1 -1
  2. package/app/.next/build-manifest.json +3 -3
  3. package/app/.next/prerender-manifest.json +3 -3
  4. package/app/.next/server/app/(dashboard)/dashboard/agents/page_client-reference-manifest.js +1 -1
  5. package/app/.next/server/app/(dashboard)/dashboard/analytics/page_client-reference-manifest.js +1 -1
  6. package/app/.next/server/app/(dashboard)/dashboard/api-manager/page_client-reference-manifest.js +1 -1
  7. package/app/.next/server/app/(dashboard)/dashboard/audit/page_client-reference-manifest.js +1 -1
  8. package/app/.next/server/app/(dashboard)/dashboard/auto-combo/page_client-reference-manifest.js +1 -1
  9. package/app/.next/server/app/(dashboard)/dashboard/cache/page_client-reference-manifest.js +1 -1
  10. package/app/.next/server/app/(dashboard)/dashboard/cli-tools/page_client-reference-manifest.js +1 -1
  11. package/app/.next/server/app/(dashboard)/dashboard/combos/page_client-reference-manifest.js +1 -1
  12. package/app/.next/server/app/(dashboard)/dashboard/costs/page_client-reference-manifest.js +1 -1
  13. package/app/.next/server/app/(dashboard)/dashboard/endpoint/page_client-reference-manifest.js +1 -1
  14. package/app/.next/server/app/(dashboard)/dashboard/health/page_client-reference-manifest.js +1 -1
  15. package/app/.next/server/app/(dashboard)/dashboard/limits/page_client-reference-manifest.js +1 -1
  16. package/app/.next/server/app/(dashboard)/dashboard/logs/page_client-reference-manifest.js +1 -1
  17. package/app/.next/server/app/(dashboard)/dashboard/media/page_client-reference-manifest.js +1 -1
  18. package/app/.next/server/app/(dashboard)/dashboard/memory/page_client-reference-manifest.js +1 -1
  19. package/app/.next/server/app/(dashboard)/dashboard/onboarding/page_client-reference-manifest.js +1 -1
  20. package/app/.next/server/app/(dashboard)/dashboard/page_client-reference-manifest.js +1 -1
  21. package/app/.next/server/app/(dashboard)/dashboard/playground/page_client-reference-manifest.js +1 -1
  22. package/app/.next/server/app/(dashboard)/dashboard/providers/[id]/page_client-reference-manifest.js +1 -1
  23. package/app/.next/server/app/(dashboard)/dashboard/providers/new/page_client-reference-manifest.js +1 -1
  24. package/app/.next/server/app/(dashboard)/dashboard/providers/page_client-reference-manifest.js +1 -1
  25. package/app/.next/server/app/(dashboard)/dashboard/search-tools/page_client-reference-manifest.js +1 -1
  26. package/app/.next/server/app/(dashboard)/dashboard/settings/page_client-reference-manifest.js +1 -1
  27. package/app/.next/server/app/(dashboard)/dashboard/settings/pricing/page_client-reference-manifest.js +1 -1
  28. package/app/.next/server/app/(dashboard)/dashboard/skills/page_client-reference-manifest.js +1 -1
  29. package/app/.next/server/app/(dashboard)/dashboard/translator/page_client-reference-manifest.js +1 -1
  30. package/app/.next/server/app/400/page_client-reference-manifest.js +1 -1
  31. package/app/.next/server/app/401/page_client-reference-manifest.js +1 -1
  32. package/app/.next/server/app/403/page_client-reference-manifest.js +1 -1
  33. package/app/.next/server/app/408/page_client-reference-manifest.js +1 -1
  34. package/app/.next/server/app/429/page_client-reference-manifest.js +1 -1
  35. package/app/.next/server/app/500/page_client-reference-manifest.js +1 -1
  36. package/app/.next/server/app/502/page_client-reference-manifest.js +1 -1
  37. package/app/.next/server/app/503/page_client-reference-manifest.js +1 -1
  38. package/app/.next/server/app/_global-error.html +1 -1
  39. package/app/.next/server/app/_global-error.rsc +1 -1
  40. package/app/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  41. package/app/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  42. package/app/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  43. package/app/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  44. package/app/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  45. package/app/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  46. package/app/.next/server/app/api/system/version/route.js.nft.json +1 -1
  47. package/app/.next/server/app/api/v1/api/chat/route.js +15 -15
  48. package/app/.next/server/app/api/v1/api/chat/route.js.nft.json +1 -1
  49. package/app/.next/server/app/api/v1/audio/speech/route.js +11 -11
  50. package/app/.next/server/app/api/v1/audio/speech/route.js.nft.json +1 -1
  51. package/app/.next/server/app/api/v1/audio/transcriptions/route.js +5 -5
  52. package/app/.next/server/app/api/v1/audio/transcriptions/route.js.nft.json +1 -1
  53. package/app/.next/server/app/api/v1/chat/completions/route.js +14 -14
  54. package/app/.next/server/app/api/v1/chat/completions/route.js.nft.json +1 -1
  55. package/app/.next/server/app/api/v1/completions/route.js +14 -14
  56. package/app/.next/server/app/api/v1/completions/route.js.nft.json +1 -1
  57. package/app/.next/server/app/api/v1/images/generations/route.js +10 -10
  58. package/app/.next/server/app/api/v1/images/generations/route.js.nft.json +1 -1
  59. package/app/.next/server/app/api/v1/messages/route.js +16 -16
  60. package/app/.next/server/app/api/v1/messages/route.js.nft.json +1 -1
  61. package/app/.next/server/app/api/v1/models/route.js +5 -5
  62. package/app/.next/server/app/api/v1/models/route.js.nft.json +1 -1
  63. package/app/.next/server/app/api/v1/moderations/route.js +9 -9
  64. package/app/.next/server/app/api/v1/moderations/route.js.nft.json +1 -1
  65. package/app/.next/server/app/api/v1/music/generations/route.js +10 -10
  66. package/app/.next/server/app/api/v1/providers/[provider]/chat/completions/route.js +16 -16
  67. package/app/.next/server/app/api/v1/providers/[provider]/chat/completions/route.js.nft.json +1 -1
  68. package/app/.next/server/app/api/v1/providers/[provider]/embeddings/route.js +7 -7
  69. package/app/.next/server/app/api/v1/providers/[provider]/embeddings/route.js.nft.json +1 -1
  70. package/app/.next/server/app/api/v1/providers/[provider]/images/generations/route.js +10 -10
  71. package/app/.next/server/app/api/v1/providers/[provider]/images/generations/route.js.nft.json +1 -1
  72. package/app/.next/server/app/api/v1/rerank/route.js +9 -9
  73. package/app/.next/server/app/api/v1/rerank/route.js.nft.json +1 -1
  74. package/app/.next/server/app/api/v1/responses/[...path]/route.js +16 -16
  75. package/app/.next/server/app/api/v1/responses/[...path]/route.js.nft.json +1 -1
  76. package/app/.next/server/app/api/v1/responses/route.js +16 -16
  77. package/app/.next/server/app/api/v1/responses/route.js.nft.json +1 -1
  78. package/app/.next/server/app/api/v1/route.js +5 -5
  79. package/app/.next/server/app/api/v1/route.js.nft.json +1 -1
  80. package/app/.next/server/app/api/v1/search/analytics/route.js +7 -7
  81. package/app/.next/server/app/api/v1/search/analytics/route.js.nft.json +1 -1
  82. package/app/.next/server/app/api/v1/videos/generations/route.js +10 -10
  83. package/app/.next/server/app/api/v1beta/models/[...path]/route.js +14 -14
  84. package/app/.next/server/app/api/v1beta/models/[...path]/route.js.nft.json +1 -1
  85. package/app/.next/server/app/callback/page_client-reference-manifest.js +1 -1
  86. package/app/.next/server/app/docs/page_client-reference-manifest.js +1 -1
  87. package/app/.next/server/app/forbidden/page_client-reference-manifest.js +1 -1
  88. package/app/.next/server/app/forgot-password/page_client-reference-manifest.js +1 -1
  89. package/app/.next/server/app/landing/page_client-reference-manifest.js +1 -1
  90. package/app/.next/server/app/login/page_client-reference-manifest.js +1 -1
  91. package/app/.next/server/app/maintenance/page_client-reference-manifest.js +1 -1
  92. package/app/.next/server/app/offline/page_client-reference-manifest.js +1 -1
  93. package/app/.next/server/app/page_client-reference-manifest.js +1 -1
  94. package/app/.next/server/app/privacy/page_client-reference-manifest.js +1 -1
  95. package/app/.next/server/app/status/page_client-reference-manifest.js +1 -1
  96. package/app/.next/server/app/terms/page_client-reference-manifest.js +1 -1
  97. package/app/.next/server/chunks/{[root-of-the-server]__0nxyldc._.js → [root-of-the-server]__0-zca2p._.js} +1 -1
  98. package/app/.next/server/chunks/{[root-of-the-server]__0urvs3.._.js → [root-of-the-server]__01hbf~_._.js} +1 -1
  99. package/app/.next/server/chunks/[root-of-the-server]__01ojood._.js +1 -1
  100. package/app/.next/server/chunks/[root-of-the-server]__030_-af._.js +1 -1
  101. package/app/.next/server/chunks/{[root-of-the-server]__0j~-yu1._.js → [root-of-the-server]__03l6k3k._.js} +1 -1
  102. package/app/.next/server/chunks/{[root-of-the-server]__01b8762._.js → [root-of-the-server]__05~jdzu._.js} +1 -1
  103. package/app/.next/server/chunks/{[root-of-the-server]__07eee_s._.js → [root-of-the-server]__08~6j3q._.js} +1 -1
  104. package/app/.next/server/chunks/[root-of-the-server]__0a8ozdb._.js +1 -1
  105. package/app/.next/server/chunks/[root-of-the-server]__0bd4ccn._.js +2 -2
  106. package/app/.next/server/chunks/{[root-of-the-server]__0_a98vk._.js → [root-of-the-server]__0d6bqbw._.js} +1 -1
  107. package/app/.next/server/chunks/{[root-of-the-server]__0_c_.ye._.js → [root-of-the-server]__0f2rz58._.js} +1 -1
  108. package/app/.next/server/chunks/[root-of-the-server]__0jp3yj4._.js +1 -1
  109. package/app/.next/server/chunks/{[root-of-the-server]__06stuoz._.js → [root-of-the-server]__0jvnjwl._.js} +1 -1
  110. package/app/.next/server/chunks/[root-of-the-server]__0mj7x5~._.js +1 -1
  111. package/app/.next/server/chunks/[root-of-the-server]__0n-~kvf._.js +1 -1
  112. package/app/.next/server/chunks/{[root-of-the-server]__0-y3k-t._.js → [root-of-the-server]__0nzi7ym._.js} +1 -1
  113. package/app/.next/server/chunks/[root-of-the-server]__0ofxxzh._.js +2 -2
  114. package/app/.next/server/chunks/{[root-of-the-server]__0uu3t5x._.js → [root-of-the-server]__0pd~24c._.js} +2 -2
  115. package/app/.next/server/chunks/[root-of-the-server]__0s1dq3.._.js +1 -1
  116. package/app/.next/server/chunks/[root-of-the-server]__0tsl88m._.js +1 -1
  117. package/app/.next/server/chunks/[root-of-the-server]__0u5-mph._.js +1 -1
  118. package/app/.next/server/chunks/{[root-of-the-server]__0vi3.0k._.js → [root-of-the-server]__0uryxsh._.js} +1 -1
  119. package/app/.next/server/chunks/{[root-of-the-server]__0lwc40h._.js → [root-of-the-server]__0v1kwmx._.js} +1 -1
  120. package/app/.next/server/chunks/{[root-of-the-server]__04y3b4q._.js → [root-of-the-server]__0vt49c9._.js} +1 -1
  121. package/app/.next/server/chunks/{[root-of-the-server]__0pylsu2._.js → [root-of-the-server]__0vy97gy._.js} +2 -2
  122. package/app/.next/server/chunks/{[root-of-the-server]__0~s45~f._.js → [root-of-the-server]__0wd~o5b._.js} +1 -1
  123. package/app/.next/server/chunks/[root-of-the-server]__0x5yxjy._.js +2 -2
  124. package/app/.next/server/chunks/{[root-of-the-server]__0vmajf6._.js → [root-of-the-server]__0x_hqjb._.js} +1 -1
  125. package/app/.next/server/chunks/[root-of-the-server]__0~0hd.s._.js +2 -2
  126. package/app/.next/server/chunks/{[root-of-the-server]__10~-ypp._.js → [root-of-the-server]__11ptf~3._.js} +1 -1
  127. package/app/.next/server/chunks/_00.pgsp._.js +1 -1
  128. package/app/.next/server/chunks/_013gowh._.js +1 -1
  129. package/app/.next/server/chunks/{_0ucpa5q._.js → _02._8wx._.js} +1 -1
  130. package/app/.next/server/chunks/_036lxbr._.js +1 -1
  131. package/app/.next/server/chunks/_05reh6o._.js +1 -1
  132. package/app/.next/server/chunks/{_0-~thzo._.js → _083_x9z._.js} +2 -2
  133. package/app/.next/server/chunks/_083a5zg._.js +1 -1
  134. package/app/.next/server/chunks/{_004r3br._.js → _08cwbl2._.js} +2 -2
  135. package/app/.next/server/chunks/_0a3.3sc._.js +1 -1
  136. package/app/.next/server/chunks/_0c.abwr._.js +1 -1
  137. package/app/.next/server/chunks/_0dfpto1._.js +1 -1
  138. package/app/.next/server/chunks/_0due8oe._.js +1 -1
  139. package/app/.next/server/chunks/_0h-j8c2._.js +1 -1
  140. package/app/.next/server/chunks/_0vx-r0i._.js +2 -2
  141. package/app/.next/server/chunks/_0w4f3bm._.js +1 -1
  142. package/app/.next/server/chunks/_10.rw9f._.js +1 -1
  143. package/app/.next/server/chunks/open-sse_0dawtxk._.js +2 -2
  144. package/app/.next/server/chunks/open-sse_0p~.88y._.js +1 -1
  145. package/app/.next/server/chunks/open-sse_0sthby3._.js +1 -1
  146. package/app/.next/server/chunks/src_0cbm0~g._.js +1 -1
  147. package/app/.next/server/chunks/src_shared_utils_apiKey_ts_0gzf59_._.js +1 -1
  148. package/app/.next/server/chunks/src_shared_utils_apiKey_ts_12~h.oz._.js +1 -1
  149. package/app/.next/server/chunks/ssr/_008ht2n._.js +1 -1
  150. package/app/.next/server/chunks/ssr/_0oo1f90._.js +1 -1
  151. package/app/.next/server/chunks/ssr/src_04s-8a5._.js +1 -1
  152. package/app/.next/server/chunks/ssr/src_0vjsxxr._.js +1 -1
  153. package/app/.next/server/chunks/ssr/src_shared_utils_apiKey_ts_0l8g1z8._.js +1 -1
  154. package/app/.next/server/middleware-build-manifest.js +3 -3
  155. package/app/.next/server/pages/500.html +1 -1
  156. package/app/.next/server/server-reference-manifest.js +1 -1
  157. package/app/.next/server/server-reference-manifest.json +1 -1
  158. package/app/.next/static/chunks/0ipwpwjb2g0uv.js +1 -0
  159. package/app/.next/static/chunks/0~c--kcvaumm~.js +1 -0
  160. package/app/.next/static/chunks/{02q7h~xz7j6i3.js → 0~v1trn07bitv.js} +1 -1
  161. package/app/CHANGELOG.md +12 -0
  162. package/app/bin/reset-password.mjs +3 -1
  163. package/app/docs/openapi.yaml +1 -1
  164. package/app/open-sse/config/registryUtils.ts +1 -0
  165. package/app/open-sse/config/videoRegistry.ts +1 -3
  166. package/app/open-sse/executors/antigravity.ts +22 -12
  167. package/app/open-sse/executors/gemini-cli.ts +3 -1
  168. package/app/open-sse/executors/qoder.ts +1 -8
  169. package/app/open-sse/handlers/audioSpeech.ts +1 -0
  170. package/app/open-sse/handlers/chatCore.ts +2 -1
  171. package/app/open-sse/handlers/embeddings.ts +1 -0
  172. package/app/open-sse/handlers/imageGeneration.ts +6 -2
  173. package/app/open-sse/handlers/musicGeneration.ts +9 -2
  174. package/app/open-sse/handlers/search.ts +1 -0
  175. package/app/open-sse/handlers/videoGeneration.ts +11 -3
  176. package/app/open-sse/mcp-server/index.ts +0 -1
  177. package/app/open-sse/package.json +1 -1
  178. package/app/open-sse/services/claudeCodeCompatible.ts +2 -2
  179. package/app/open-sse/services/modelCapabilities.ts +3 -4
  180. package/app/open-sse/services/qoderCli.ts +5 -2
  181. package/app/open-sse/services/tokenRefresh.ts +3 -1
  182. package/app/open-sse/services/usage.ts +13 -9
  183. package/app/open-sse/services/workflowFSM.ts +298 -61
  184. package/app/open-sse/translator/index.ts +5 -1
  185. package/app/open-sse/translator/response/gemini-to-openai.ts +5 -1
  186. package/app/open-sse/utils/progressTracker.ts +4 -1
  187. package/app/open-sse/utils/stream.ts +7 -1
  188. package/app/open-sse/utils/streamPayloadCollector.ts +5 -1
  189. package/app/package-lock.json +3 -3
  190. package/app/package.json +1 -1
  191. package/app/scripts/check-route-validation.mjs +3 -1
  192. package/app/scripts/i18n/apply-priority-overrides.mjs +7 -1
  193. package/app/scripts/prepublish.mjs +2 -2
  194. package/app/scripts/run-protocol-clients-tests.mjs +7 -1
  195. package/app/src/app/(dashboard)/dashboard/analytics/components/DiversityScoreCard.tsx +1 -1
  196. package/app/src/app/(dashboard)/dashboard/auto-combo/page.tsx +0 -1
  197. package/app/src/app/(dashboard)/dashboard/media/MediaPageClient.tsx +9 -3
  198. package/app/src/app/(dashboard)/dashboard/providers/[id]/page.tsx +25 -23
  199. package/app/src/app/(dashboard)/dashboard/search-tools/components/SearchHistory.tsx +3 -1
  200. package/app/src/app/api/auth/status/route.ts +1 -3
  201. package/app/src/app/api/mcp/sse/route.ts +2 -2
  202. package/app/src/app/api/mcp/status/route.ts +1 -2
  203. package/app/src/app/api/mcp/stream/route.ts +5 -3
  204. package/app/src/app/api/openapi/spec/route.ts +4 -1
  205. package/app/src/app/api/openapi/try/route.ts +4 -1
  206. package/app/src/app/api/providers/[id]/models/route.ts +4 -4
  207. package/app/src/app/api/providers/[id]/sync-models/route.ts +9 -3
  208. package/app/src/app/api/settings/auto-disable-accounts/route.ts +6 -1
  209. package/app/src/app/api/skills/[id]/route.ts +4 -1
  210. package/app/src/app/api/v1/issues/report/route.ts +9 -1
  211. package/app/src/app/api/v1beta/models/route.ts +8 -6
  212. package/app/src/app/api/webhooks/[id]/route.ts +9 -7
  213. package/app/src/domain/fallbackPolicy.ts +0 -1
  214. package/app/src/domain/modelAvailability.ts +0 -1
  215. package/app/src/domain/providerExpiration.ts +2 -6
  216. package/app/src/lib/db/models.ts +23 -13
  217. package/app/src/lib/evals/evalRunner.ts +0 -1
  218. package/app/src/lib/evals/scheduler.ts +2 -6
  219. package/app/src/lib/oauth/services/antigravity.ts +6 -1
  220. package/app/src/lib/oauth/services/kiro.ts +12 -2
  221. package/app/src/lib/oauth/services/oauth.ts +10 -2
  222. package/app/src/lib/oauth/utils/server.ts +4 -1
  223. package/app/src/lib/plugins/index.ts +2 -8
  224. package/app/src/lib/usageAnalytics.ts +5 -1
  225. package/app/src/mitm/manager.js +1 -1
  226. package/app/src/mitm/manager.ts +1 -1
  227. package/app/src/shared/components/Button.tsx +0 -1
  228. package/app/src/shared/components/Card.tsx +0 -2
  229. package/app/src/shared/components/FilterBar.tsx +4 -12
  230. package/app/src/shared/components/Input.tsx +1 -1
  231. package/app/src/shared/components/Modal.tsx +0 -1
  232. package/app/src/shared/components/NotificationToast.tsx +1 -3
  233. package/app/src/shared/components/Select.tsx +1 -1
  234. package/app/src/shared/components/Sidebar.tsx +3 -3
  235. package/app/src/shared/components/ThemeToggle.tsx +7 -1
  236. package/app/src/shared/constants/cliCompatProviders.ts +0 -1
  237. package/app/src/shared/constants/errorCodes.ts +114 -19
  238. package/app/src/shared/utils/apiKey.ts +2 -4
  239. package/app/src/shared/utils/fetchTimeout.ts +0 -1
  240. package/app/src/shared/utils/inputSanitizer.ts +8 -4
  241. package/app/src/shared/utils/requestTimeout.ts +5 -1
  242. package/app/src/sse/handlers/chat.ts +1 -0
  243. package/app/src/sse/services/auth.ts +8 -3
  244. package/app/src/sse/services/streamState.ts +5 -1
  245. package/app/src/store/notificationStore.ts +3 -7
  246. package/app/tests/unit/t20-t22-provider-headers.test.mjs +3 -1
  247. package/bin/reset-password.mjs +3 -1
  248. package/open-sse/mcp-server/__tests__/glmCodingProviderConfig.test.ts +5 -1
  249. package/open-sse/mcp-server/index.ts +0 -1
  250. package/package.json +1 -1
  251. package/app/.next/server/chunks/_0-jnvci._.js +0 -19
  252. package/app/.next/static/chunks/0l88mho31mflv.js +0 -1
  253. package/app/.next/static/chunks/0wt-4zl7_gil8.js +0 -1
  254. /package/app/.next/static/{ri1SkwBU-ygQ2qIDe8jf2 → 1dZBzAZ8QsddVCQRQtqjg}/_buildManifest.js +0 -0
  255. /package/app/.next/static/{ri1SkwBU-ygQ2qIDe8jf2 → 1dZBzAZ8QsddVCQRQtqjg}/_clientMiddlewareManifest.js +0 -0
  256. /package/app/.next/static/{ri1SkwBU-ygQ2qIDe8jf2 → 1dZBzAZ8QsddVCQRQtqjg}/_ssgManifest.js +0 -0
@@ -884,9 +884,7 @@ export default function ProviderDetailPage() {
884
884
  const isOAuth = providerSupportsOAuth && !providerSupportsPat;
885
885
  const registryModels = getModelsByProviderId(providerId);
886
886
  // For Gemini: always use synced API models (empty if no keys added yet)
887
- const models = providerId === "gemini"
888
- ? syncedAvailableModels
889
- : registryModels;
887
+ const models = providerId === "gemini" ? syncedAvailableModels : registryModels;
890
888
  const providerAlias = getProviderAlias(providerId);
891
889
  const isManagedAvailableModelsProvider = isCompatible || providerId === "openrouter";
892
890
  const isSearchProvider = providerId.endsWith("-search");
@@ -2050,23 +2048,24 @@ export default function ProviderDetailPage() {
2050
2048
  );
2051
2049
  }
2052
2050
 
2053
- const importButton = providerId === "gemini" ? null : (
2054
- <div className="flex items-center gap-2 mb-4">
2055
- <Button
2056
- size="sm"
2057
- variant="secondary"
2058
- icon="download"
2059
- onClick={handleImportModels}
2060
- disabled={!canImportModels || importingModels}
2061
- >
2062
- {importingModels ? t("importingModels") : t("importFromModels")}
2063
- </Button>
2064
- {autoSyncToggle}
2065
- {!canImportModels && (
2066
- <span className="text-xs text-text-muted">{t("addConnectionToImport")}</span>
2067
- )}
2068
- </div>
2069
- );
2051
+ const importButton =
2052
+ providerId === "gemini" ? null : (
2053
+ <div className="flex items-center gap-2 mb-4">
2054
+ <Button
2055
+ size="sm"
2056
+ variant="secondary"
2057
+ icon="download"
2058
+ onClick={handleImportModels}
2059
+ disabled={!canImportModels || importingModels}
2060
+ >
2061
+ {importingModels ? t("importingModels") : t("importFromModels")}
2062
+ </Button>
2063
+ {autoSyncToggle}
2064
+ {!canImportModels && (
2065
+ <span className="text-xs text-text-muted">{t("addConnectionToImport")}</span>
2066
+ )}
2067
+ </div>
2068
+ );
2070
2069
 
2071
2070
  if (models.length === 0) {
2072
2071
  return (
@@ -2401,7 +2400,9 @@ export default function ProviderDetailPage() {
2401
2400
  setShowEditModal(true);
2402
2401
  }}
2403
2402
  onDelete={() => handleDelete(conn.id)}
2404
- onReauth={conn.authType === "oauth" ? () => setShowOAuthModal(true) : undefined}
2403
+ onReauth={
2404
+ conn.authType === "oauth" ? () => setShowOAuthModal(true) : undefined
2405
+ }
2405
2406
  onRefreshToken={
2406
2407
  conn.authType === "oauth" ? () => handleRefreshToken(conn.id) : undefined
2407
2408
  }
@@ -4270,8 +4271,9 @@ function ConnectionRow({
4270
4271
  <span
4271
4272
  className={`text-xs truncate max-w-[300px] ${statusPresentation.errorTextClass}`}
4272
4273
  title={connection.lastError.replace(/<[^>]*>?/gm, "")}
4273
- dangerouslySetInnerHTML={{ __html: connection.lastError }}
4274
- />
4274
+ >
4275
+ {connection.lastError.replace(/<[^>]*>?/gm, "")}
4276
+ </span>
4275
4277
  )}
4276
4278
  <span className="text-xs text-text-muted">#{connection.priority}</span>
4277
4279
  {connection.globalPriority && (
@@ -58,7 +58,9 @@ export default function SearchHistory({ onReplay }: SearchHistoryProps) {
58
58
  <div className="text-xs text-text-main truncate">{entry.query}</div>
59
59
  <div className="flex justify-between mt-0.5">
60
60
  <span className="text-[10px] text-text-muted">{entry.provider}</span>
61
- <span className="text-[10px] text-text-muted">{timeAgo(entry.timestamp, locale)}</span>
61
+ <span className="text-[10px] text-text-muted">
62
+ {timeAgo(entry.timestamp, locale)}
63
+ </span>
62
64
  </div>
63
65
  </button>
64
66
  ))}
@@ -2,9 +2,7 @@ import { NextResponse } from "next/server";
2
2
  import { cookies } from "next/headers";
3
3
  import { jwtVerify } from "jose";
4
4
 
5
- const SECRET = process.env.JWT_SECRET
6
- ? new TextEncoder().encode(process.env.JWT_SECRET)
7
- : null;
5
+ const SECRET = process.env.JWT_SECRET ? new TextEncoder().encode(process.env.JWT_SECRET) : null;
8
6
 
9
7
  export async function GET() {
10
8
  try {
@@ -15,14 +15,14 @@ async function guardEnabled(): Promise<NextResponse | null> {
15
15
  if (!settings.mcpEnabled) {
16
16
  return NextResponse.json(
17
17
  { error: "MCP server is disabled. Enable it from the Endpoints page." },
18
- { status: 503 },
18
+ { status: 503 }
19
19
  );
20
20
  }
21
21
  const transport = (settings.mcpTransport as string) || "stdio";
22
22
  if (transport !== "sse") {
23
23
  return NextResponse.json(
24
24
  { error: `MCP transport is set to "${transport}", not "sse". Change it from Settings.` },
25
- { status: 400 },
25
+ { status: 400 }
26
26
  );
27
27
  }
28
28
  return null;
@@ -26,8 +26,7 @@ export async function GET() {
26
26
 
27
27
  // stdio uses heartbeat file; HTTP transports use in-process state
28
28
  const stdioOnline = isMcpHeartbeatOnline(heartbeat, { requireLivePid: true });
29
- const online =
30
- mcpTransport === "stdio" ? stdioOnline : httpStatus.online;
29
+ const online = mcpTransport === "stdio" ? stdioOnline : httpStatus.online;
31
30
 
32
31
  const lastCall = lastCallPage.entries[0] || null;
33
32
  const now = Date.now();
@@ -16,14 +16,16 @@ async function guardEnabled(): Promise<NextResponse | null> {
16
16
  if (!settings.mcpEnabled) {
17
17
  return NextResponse.json(
18
18
  { error: "MCP server is disabled. Enable it from the Endpoints page." },
19
- { status: 503 },
19
+ { status: 503 }
20
20
  );
21
21
  }
22
22
  const transport = (settings.mcpTransport as string) || "stdio";
23
23
  if (transport !== "streamable-http") {
24
24
  return NextResponse.json(
25
- { error: `MCP transport is set to "${transport}", not "streamable-http". Change it from Settings.` },
26
- { status: 400 },
25
+ {
26
+ error: `MCP transport is set to "${transport}", not "streamable-http". Change it from Settings.`,
27
+ },
28
+ { status: 400 }
27
29
  );
28
30
  }
29
31
  return null;
@@ -20,7 +20,10 @@ export async function GET() {
20
20
 
21
21
  let specPath = "";
22
22
  for (const p of candidates) {
23
- if (fs.existsSync(p)) { specPath = p; break; }
23
+ if (fs.existsSync(p)) {
24
+ specPath = p;
25
+ break;
26
+ }
24
27
  }
25
28
 
26
29
  if (!specPath) {
@@ -8,7 +8,10 @@ import { NextRequest, NextResponse } from "next/server";
8
8
  import { validateBody, isValidationFailure } from "@/shared/validation/helpers";
9
9
 
10
10
  const tryRequestSchema = z.object({
11
- method: z.enum(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]).optional().default("GET"),
11
+ method: z
12
+ .enum(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"])
13
+ .optional()
14
+ .default("GET"),
12
15
  path: z.string().min(1, "Path is required").startsWith("/", "Path must start with /"),
13
16
  headers: z.record(z.string(), z.string()).optional().default({}),
14
17
  body: z.any().optional(),
@@ -169,9 +169,7 @@ const PROVIDER_MODELS_CONFIG: Record<string, ProviderModelsConfigEntry> = {
169
169
  id: ((m.name as string) || (m.id as string) || "").replace(/^models\//, ""),
170
170
  name: (m.displayName as string) || ((m.name as string) || "").replace(/^models\//, ""),
171
171
  supportedEndpoints: endpoints,
172
- ...(typeof m.inputTokenLimit === "number"
173
- ? { inputTokenLimit: m.inputTokenLimit }
174
- : {}),
172
+ ...(typeof m.inputTokenLimit === "number" ? { inputTokenLimit: m.inputTokenLimit } : {}),
175
173
  ...(typeof m.outputTokenLimit === "number"
176
174
  ? { outputTokenLimit: m.outputTokenLimit }
177
175
  : {}),
@@ -747,7 +745,9 @@ export async function GET(
747
745
  }
748
746
 
749
747
  if (pageCount > 1) {
750
- console.log(`[models] ${provider}: fetched ${allModels.length} models across ${pageCount} pages`);
748
+ console.log(
749
+ `[models] ${provider}: fetched ${allModels.length} models across ${pageCount} pages`
750
+ );
751
751
  }
752
752
 
753
753
  return buildResponse({
@@ -1,6 +1,10 @@
1
1
  import { NextResponse } from "next/server";
2
2
  import { getProviderConnectionById } from "@/models";
3
- import { getCustomModels, replaceCustomModels, replaceSyncedAvailableModelsForConnection } from "@/lib/db/models";
3
+ import {
4
+ getCustomModels,
5
+ replaceCustomModels,
6
+ replaceSyncedAvailableModelsForConnection,
7
+ } from "@/lib/db/models";
4
8
  import {
5
9
  syncManagedAvailableModelAliases,
6
10
  usesManagedAvailableModels,
@@ -144,7 +148,7 @@ export async function POST(request: Request, { params }: { params: Promise<{ id:
144
148
 
145
149
  // Fetch models from the existing /api/providers/[id]/models endpoint
146
150
  const origin = new URL(request.url).origin;
147
- const modelsUrl = `${origin}/api/providers/${id}/models`;
151
+ const modelsUrl = `${origin}/api/providers/${encodeURIComponent(id)}/models`;
148
152
  const modelsRes = await fetch(modelsUrl, {
149
153
  method: "GET",
150
154
  headers: {
@@ -210,7 +214,9 @@ export async function POST(request: Request, { params }: { params: Promise<{ id:
210
214
  source: "api-sync" as const,
211
215
  ...(m.supportedEndpoints ? { supportedEndpoints: m.supportedEndpoints } : {}),
212
216
  ...(typeof m.inputTokenLimit === "number" ? { inputTokenLimit: m.inputTokenLimit } : {}),
213
- ...(typeof m.outputTokenLimit === "number" ? { outputTokenLimit: m.outputTokenLimit } : {}),
217
+ ...(typeof m.outputTokenLimit === "number"
218
+ ? { outputTokenLimit: m.outputTokenLimit }
219
+ : {}),
214
220
  ...(typeof m.description === "string" ? { description: m.description } : {}),
215
221
  ...(m.supportsThinking === true ? { supportsThinking: true } : {}),
216
222
  }));
@@ -25,7 +25,12 @@ export async function PUT(request: Request) {
25
25
  rawBody = await request.json();
26
26
  } catch {
27
27
  return NextResponse.json(
28
- { error: { message: "Invalid request", details: [{ field: "body", message: "Invalid JSON body" }] } },
28
+ {
29
+ error: {
30
+ message: "Invalid request",
31
+ details: [{ field: "body", message: "Invalid JSON body" }],
32
+ },
33
+ },
29
34
  { status: 400 }
30
35
  );
31
36
  }
@@ -18,7 +18,10 @@ export async function PUT(request: Request, props: { params: Promise<{ id: strin
18
18
  }
19
19
 
20
20
  const db = getDbInstance();
21
- db.prepare("UPDATE skills SET enabled = ? WHERE id = ?").run(validation.data.enabled ? 1 : 0, id);
21
+ db.prepare("UPDATE skills SET enabled = ? WHERE id = ?").run(
22
+ validation.data.enabled ? 1 : 0,
23
+ id
24
+ );
22
25
 
23
26
  await skillRegistry.loadFromDatabase();
24
27
 
@@ -39,7 +39,15 @@ export async function POST(request: Request) {
39
39
  return NextResponse.json({ error: validation.error }, { status: 400 });
40
40
  }
41
41
 
42
- const { title, provider, accountId, requestId, errorCode, details, labels = [] } = validation.data;
42
+ const {
43
+ title,
44
+ provider,
45
+ accountId,
46
+ requestId,
47
+ errorCode,
48
+ details,
49
+ labels = [],
50
+ } = validation.data;
43
51
 
44
52
  const repo = process.env.GITHUB_ISSUES_REPO;
45
53
  const token = process.env.GITHUB_ISSUES_TOKEN;
@@ -40,7 +40,10 @@ export async function GET() {
40
40
  // Gemini: always replace hardcoded entries with synced models (no fallback)
41
41
  // Always remove hardcoded gemini entries — even if sync returns empty
42
42
  for (let i = models.length - 1; i >= 0; i--) {
43
- if (typeof (models[i] as any).name === "string" && (models[i] as any).name.startsWith("models/gemini/")) {
43
+ if (
44
+ typeof (models[i] as any).name === "string" &&
45
+ (models[i] as any).name.startsWith("models/gemini/")
46
+ ) {
44
47
  models.splice(i, 1);
45
48
  }
46
49
  }
@@ -69,7 +72,8 @@ export async function GET() {
69
72
  // Skip Gemini — handled by syncedAvailableModels above
70
73
  if (providerId === "gemini") continue;
71
74
  for (const model of rawModels) {
72
- if (!model || typeof model !== "object" || typeof (model as any).id !== "string") continue;
75
+ if (!model || typeof model !== "object" || typeof (model as any).id !== "string")
76
+ continue;
73
77
  const m = model as Record<string, unknown>;
74
78
  if (m.isHidden === true) continue;
75
79
  models.push({
@@ -77,10 +81,8 @@ export async function GET() {
77
81
  displayName: m.name || m.id,
78
82
  ...(typeof m.description === "string" ? { description: m.description } : {}),
79
83
  supportedGenerationMethods: ["generateContent"],
80
- inputTokenLimit:
81
- typeof m.inputTokenLimit === "number" ? m.inputTokenLimit : 128000,
82
- outputTokenLimit:
83
- typeof m.outputTokenLimit === "number" ? m.outputTokenLimit : 8192,
84
+ inputTokenLimit: typeof m.inputTokenLimit === "number" ? m.inputTokenLimit : 128000,
85
+ outputTokenLimit: typeof m.outputTokenLimit === "number" ? m.outputTokenLimit : 8192,
84
86
  ...(m.supportsThinking === true ? { thinking: true } : {}),
85
87
  });
86
88
  }
@@ -10,13 +10,15 @@ import { NextResponse } from "next/server";
10
10
  import { getWebhook, updateWebhookRecord, deleteWebhook } from "@/lib/localDb";
11
11
  import { validateBody, isValidationFailure } from "@/shared/validation/helpers";
12
12
 
13
- const updateWebhookSchema = z.object({
14
- url: z.string().url("Invalid URL format").max(2000).optional(),
15
- events: z.array(z.string()).optional(),
16
- secret: z.string().max(500).optional(),
17
- description: z.string().max(1000).optional(),
18
- enabled: z.boolean().optional(),
19
- }).passthrough();
13
+ const updateWebhookSchema = z
14
+ .object({
15
+ url: z.string().url("Invalid URL format").max(2000).optional(),
16
+ events: z.array(z.string()).optional(),
17
+ secret: z.string().max(500).optional(),
18
+ description: z.string().max(1000).optional(),
19
+ enabled: z.boolean().optional(),
20
+ })
21
+ .passthrough();
20
22
 
21
23
  export async function GET(_: Request, { params }: { params: Promise<{ id: string }> }) {
22
24
  try {
@@ -10,7 +10,6 @@
10
10
  * @module domain/fallbackPolicy
11
11
  */
12
12
 
13
-
14
13
  import {
15
14
  saveFallbackChain,
16
15
  loadFallbackChain,
@@ -9,7 +9,6 @@
9
9
  * @module domain/modelAvailability
10
10
  */
11
11
 
12
-
13
12
  /**
14
13
  * @typedef {Object} UnavailableEntry
15
14
  * @property {string} provider
@@ -138,9 +138,7 @@ export function getAllExpirations(): ProviderExpiration[] {
138
138
  * Get connections that are expired or expiring soon.
139
139
  */
140
140
  export function getExpiringSoon(): ProviderExpiration[] {
141
- return getAllExpirations().filter(
142
- (e) => e.status === "expired" || e.status === "expiring_soon"
143
- );
141
+ return getAllExpirations().filter((e) => e.status === "expired" || e.status === "expiring_soon");
144
142
  }
145
143
 
146
144
  /**
@@ -229,9 +227,7 @@ export function detectExpirationFromResponse(
229
227
 
230
228
  // Rate limit headers may indicate reset times
231
229
  const resetHeader =
232
- headers["x-ratelimit-reset"] ||
233
- headers["x-ratelimit-reset-tokens"] ||
234
- headers["retry-after"];
230
+ headers["x-ratelimit-reset"] || headers["x-ratelimit-reset-tokens"] || headers["retry-after"];
235
231
 
236
232
  if (resetHeader && status === 429) {
237
233
  const resetTime = parseInt(resetHeader, 10);
@@ -420,23 +420,23 @@ export async function replaceCustomModels(
420
420
  ...(m.inputTokenLimit != null
421
421
  ? { inputTokenLimit: m.inputTokenLimit }
422
422
  : (prev as any)?.inputTokenLimit != null
423
- ? { inputTokenLimit: (prev as any).inputTokenLimit }
424
- : {}),
423
+ ? { inputTokenLimit: (prev as any).inputTokenLimit }
424
+ : {}),
425
425
  ...(m.outputTokenLimit != null
426
426
  ? { outputTokenLimit: m.outputTokenLimit }
427
427
  : (prev as any)?.outputTokenLimit != null
428
- ? { outputTokenLimit: (prev as any).outputTokenLimit }
429
- : {}),
428
+ ? { outputTokenLimit: (prev as any).outputTokenLimit }
429
+ : {}),
430
430
  ...(m.description != null
431
431
  ? { description: m.description }
432
432
  : (prev as any)?.description != null
433
- ? { description: (prev as any).description }
434
- : {}),
433
+ ? { description: (prev as any).description }
434
+ : {}),
435
435
  ...(m.supportsThinking != null
436
436
  ? { supportsThinking: m.supportsThinking }
437
437
  : (prev as any)?.supportsThinking != null
438
- ? { supportsThinking: (prev as any).supportsThinking }
439
- : {}),
438
+ ? { supportsThinking: (prev as any).supportsThinking }
439
+ : {}),
440
440
  // Preserve existing compat flags
441
441
  ...(prev && (prev as any).normalizeToolCallId !== undefined
442
442
  ? { normalizeToolCallId: (prev as any).normalizeToolCallId }
@@ -525,10 +525,14 @@ export interface SyncedAvailableModel {
525
525
  /**
526
526
  * Get all synced available models for a provider, unioned across all connections.
527
527
  */
528
- export async function getSyncedAvailableModels(providerId: string): Promise<SyncedAvailableModel[]> {
528
+ export async function getSyncedAvailableModels(
529
+ providerId: string
530
+ ): Promise<SyncedAvailableModel[]> {
529
531
  const db = getDbInstance();
530
532
  const rows = db
531
- .prepare("SELECT key, value FROM key_value WHERE namespace = 'syncedAvailableModels' AND key LIKE ?")
533
+ .prepare(
534
+ "SELECT key, value FROM key_value WHERE namespace = 'syncedAvailableModels' AND key LIKE ?"
535
+ )
532
536
  .all(`${providerId}:%`);
533
537
  const map = new Map<string, SyncedAvailableModel>();
534
538
  for (const row of rows) {
@@ -545,7 +549,9 @@ export async function getSyncedAvailableModels(providerId: string): Promise<Sync
545
549
  /**
546
550
  * Get all synced available models across all providers.
547
551
  */
548
- export async function getAllSyncedAvailableModels(): Promise<Record<string, SyncedAvailableModel[]>> {
552
+ export async function getAllSyncedAvailableModels(): Promise<
553
+ Record<string, SyncedAvailableModel[]>
554
+ > {
549
555
  const db = getDbInstance();
550
556
  const rows = db
551
557
  .prepare("SELECT key, value FROM key_value WHERE namespace = 'syncedAvailableModels'")
@@ -582,7 +588,9 @@ export async function replaceSyncedAvailableModelsForConnection(
582
588
  const db = getDbInstance();
583
589
  const key = `${providerId}:${connectionId}`;
584
590
  if (models.length === 0) {
585
- db.prepare("DELETE FROM key_value WHERE namespace = 'syncedAvailableModels' AND key = ?").run(key);
591
+ db.prepare("DELETE FROM key_value WHERE namespace = 'syncedAvailableModels' AND key = ?").run(
592
+ key
593
+ );
586
594
  } else {
587
595
  db.prepare(
588
596
  "INSERT OR REPLACE INTO key_value (namespace, key, value) VALUES ('syncedAvailableModels', ?, ?)"
@@ -603,7 +611,9 @@ export async function deleteSyncedAvailableModelsForConnection(
603
611
  ): Promise<SyncedAvailableModel[]> {
604
612
  const db = getDbInstance();
605
613
  const key = `${providerId}:${connectionId}`;
606
- db.prepare("DELETE FROM key_value WHERE namespace = 'syncedAvailableModels' AND key = ?").run(key);
614
+ db.prepare("DELETE FROM key_value WHERE namespace = 'syncedAvailableModels' AND key = ?").run(
615
+ key
616
+ );
607
617
  backupDbFile("pre-write");
608
618
  return getSyncedAvailableModels(providerId);
609
619
  }
@@ -8,7 +8,6 @@
8
8
  * @module lib/evals/evalRunner
9
9
  */
10
10
 
11
-
12
11
  /**
13
12
  * @typedef {Object} EvalCase
14
13
  * @property {string} id - Unique case ID
@@ -46,9 +46,7 @@ let _outputProvider: ((suiteId: string, caseId: string) => Promise<string>) | nu
46
46
  *
47
47
  * @param fn - Async function(suiteId, caseId) → actual output string
48
48
  */
49
- export function setOutputProvider(
50
- fn: (suiteId: string, caseId: string) => Promise<string>
51
- ): void {
49
+ export function setOutputProvider(fn: (suiteId: string, caseId: string) => Promise<string>): void {
52
50
  _outputProvider = fn;
53
51
  }
54
52
 
@@ -87,9 +85,7 @@ export function schedule(suiteId: string, intervalMs: number): ScheduledEval {
87
85
 
88
86
  _timers.set(suiteId, timer);
89
87
 
90
- console.log(
91
- `[EvalScheduler] Scheduled "${suiteId}" every ${Math.round(safeInterval / 1000)}s`
92
- );
88
+ console.log(`[EvalScheduler] Scheduled "${suiteId}" every ${Math.round(safeInterval / 1000)}s`);
93
89
 
94
90
  return entry;
95
91
  }
@@ -165,7 +165,12 @@ export class AntigravityService {
165
165
  /**
166
166
  * Complete onboarding flow with retry
167
167
  */
168
- async completeOnboarding(accessToken: string, projectId: string, tierId: string, maxRetries = 10) {
168
+ async completeOnboarding(
169
+ accessToken: string,
170
+ projectId: string,
171
+ tierId: string,
172
+ maxRetries = 10
173
+ ) {
169
174
  for (let i = 0; i < maxRetries; i++) {
170
175
  const result = await this.onboardUser(accessToken, projectId, tierId);
171
176
 
@@ -49,7 +49,12 @@ export class KiroService {
49
49
  /**
50
50
  * Start device authorization for AWS Builder ID or IDC
51
51
  */
52
- async startDeviceAuthorization(clientId: string, clientSecret: string, startUrl: string, region: string = "us-east-1") {
52
+ async startDeviceAuthorization(
53
+ clientId: string,
54
+ clientSecret: string,
55
+ startUrl: string,
56
+ region: string = "us-east-1"
57
+ ) {
53
58
  const endpoint = `https://oidc.${region}.amazonaws.com/device_authorization`;
54
59
 
55
60
  const response = await fetch(endpoint, {
@@ -83,7 +88,12 @@ export class KiroService {
83
88
  /**
84
89
  * Poll for token using device code (AWS Builder ID/IDC)
85
90
  */
86
- async pollDeviceToken(clientId: string, clientSecret: string, deviceCode: string, region: string = "us-east-1") {
91
+ async pollDeviceToken(
92
+ clientId: string,
93
+ clientSecret: string,
94
+ deviceCode: string,
95
+ region: string = "us-east-1"
96
+ ) {
87
97
  const endpoint = `https://oidc.${region}.amazonaws.com/token`;
88
98
 
89
99
  const response = await fetch(endpoint, {
@@ -17,7 +17,12 @@ export class OAuthService {
17
17
  /**
18
18
  * Build authorization URL
19
19
  */
20
- buildAuthUrl(redirectUri: string, state: string, codeChallenge: string, extraParams: Record<string, string> = {}) {
20
+ buildAuthUrl(
21
+ redirectUri: string,
22
+ state: string,
23
+ codeChallenge: string,
24
+ extraParams: Record<string, string> = {}
25
+ ) {
21
26
  const params = new URLSearchParams({
22
27
  client_id: this.config.clientId,
23
28
  response_type: "code",
@@ -129,7 +134,10 @@ export class OAuthService {
129
134
  /**
130
135
  * Complete OAuth flow
131
136
  */
132
- async authenticate(providerName: string, buildAuthUrlFn: (redirectUri: string, state: string, codeChallenge: string) => string) {
137
+ async authenticate(
138
+ providerName: string,
139
+ buildAuthUrlFn: (redirectUri: string, state: string, codeChallenge: string) => string
140
+ ) {
133
141
  // Generate PKCE
134
142
  const { codeVerifier, codeChallenge, state } = generatePKCE();
135
143
 
@@ -7,7 +7,10 @@ import { URL } from "url";
7
7
  * @param {number} fixedPort - Optional fixed port number (default: random)
8
8
  * @returns {Promise<{server: http.Server, port: number, close: Function}>}
9
9
  */
10
- export function startLocalServer(onCallback: (params: Record<string, string>) => void, fixedPort: number | null = null): Promise<{ server: any; port: number; close: () => void }> {
10
+ export function startLocalServer(
11
+ onCallback: (params: Record<string, string>) => void,
12
+ fixedPort: number | null = null
13
+ ): Promise<{ server: any; port: number; close: () => void }> {
11
14
  return new Promise((resolve, reject) => {
12
15
  const server = http.createServer((req, res) => {
13
16
  const url = new URL(req.url || "/", `http://localhost`);
@@ -51,15 +51,9 @@ export interface Plugin {
51
51
  /** Called before the chat handler */
52
52
  onRequest?: (ctx: PluginContext) => Promise<PluginResult | void> | PluginResult | void;
53
53
  /** Called after the chat handler */
54
- onResponse?: (
55
- ctx: PluginContext,
56
- response: any
57
- ) => Promise<any | void> | any | void;
54
+ onResponse?: (ctx: PluginContext, response: any) => Promise<any | void> | any | void;
58
55
  /** Called on handler error */
59
- onError?: (
60
- ctx: PluginContext,
61
- error: Error
62
- ) => Promise<any | void> | any | void;
56
+ onError?: (ctx: PluginContext, error: Error) => Promise<any | void> | any | void;
63
57
  }
64
58
 
65
59
  // ── Registry ──
@@ -72,7 +72,11 @@ function shortModelName(model: string) {
72
72
  * @param {Object} connectionMap - Map of connectionId → account name
73
73
  * @returns {Object} Analytics data
74
74
  */
75
- export async function computeAnalytics(history: any[], range = "30d", connectionMap: Record<string, string> = {}) {
75
+ export async function computeAnalytics(
76
+ history: any[],
77
+ range = "30d",
78
+ connectionMap: Record<string, string> = {}
79
+ ) {
76
80
  const { start, end } = getDateRange(range);
77
81
 
78
82
  // ---- Filtered entries ----
@@ -75,7 +75,7 @@ async function getMitmStatus() {
75
75
  let dnsConfigured = false;
76
76
  try {
77
77
  const hostsContent = fs_1.default.readFileSync("/etc/hosts", "utf-8");
78
- dnsConfigured = hostsContent.includes("daily-cloudcode-pa.googleapis.com");
78
+ dnsConfigured = /\bdaily-cloudcode-pa\.googleapis\.com\b/.test(hostsContent);
79
79
  }
80
80
  catch {
81
81
  // Ignore
@@ -69,7 +69,7 @@ export async function getMitmStatus() {
69
69
  let dnsConfigured = false;
70
70
  try {
71
71
  const hostsContent = fs.readFileSync("/etc/hosts", "utf-8");
72
- dnsConfigured = hostsContent.includes("daily-cloudcode-pa.googleapis.com");
72
+ dnsConfigured = /\bdaily-cloudcode-pa\.googleapis\.com\b/.test(hostsContent);
73
73
  } catch {
74
74
  // Ignore
75
75
  }
@@ -40,7 +40,6 @@ export default function Button({
40
40
  className,
41
41
  ...props
42
42
  }: ButtonProps) {
43
-
44
43
  return (
45
44
  <button
46
45
  type="button"