@circuitwall/jarela 2.3.0 → 2.5.0

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 (290) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/app-path-routes-manifest.json +5 -5
  3. package/.next/standalone/.next/build-manifest.json +2 -2
  4. package/.next/standalone/.next/prerender-manifest.json +4 -4
  5. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  6. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  7. package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
  8. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  9. package/.next/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  10. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  11. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  12. package/.next/standalone/.next/server/app/_not-found.html +14 -2
  13. package/.next/standalone/.next/server/app/_not-found.rsc +16 -4
  14. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +16 -4
  15. package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +16 -4
  16. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  17. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  18. package/.next/standalone/.next/server/app/api/v1/access/[identity]/route.js +7 -0
  19. package/.next/standalone/.next/server/app/api/v1/access/route.js +7 -0
  20. package/.next/standalone/.next/server/app/api/v1/agents/[id]/compact/route.js +7 -0
  21. package/.next/standalone/.next/server/app/api/v1/agents/[id]/display-filters/route.js +17 -5
  22. package/.next/standalone/.next/server/app/api/v1/agents/[id]/route.js +7 -0
  23. package/.next/standalone/.next/server/app/api/v1/agents/[id]/thread/route.js +17 -5
  24. package/.next/standalone/.next/server/app/api/v1/agents/route.js +7 -0
  25. package/.next/standalone/.next/server/app/api/v1/allowed-sites/[hostname]/route.js +7 -0
  26. package/.next/standalone/.next/server/app/api/v1/allowed-sites/route.js +7 -0
  27. package/.next/standalone/.next/server/app/api/v1/artifacts/lifecycle/route.js +7 -0
  28. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/chats/route.js +26 -32
  29. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/chats/route.js.nft.json +1 -1
  30. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/ignores/[remote_jid]/route.js +18 -7
  31. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/ignores/route.js +18 -7
  32. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/lookup/route.js +26 -32
  33. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/lookup/route.js.nft.json +1 -1
  34. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/pair/route.js +27 -33
  35. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/pair/route.js.nft.json +1 -1
  36. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/route.js +26 -32
  37. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/route.js.nft.json +1 -1
  38. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/routes/[route_id]/route.js +28 -12
  39. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/routes/route.js +28 -12
  40. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/status/route.js +26 -32
  41. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/status/route.js.nft.json +1 -1
  42. package/.next/standalone/.next/server/app/api/v1/bridges/kinds/route.js +9 -2
  43. package/.next/standalone/.next/server/app/api/v1/bridges/kinds/route.js.nft.json +1 -1
  44. package/.next/standalone/.next/server/app/api/v1/bridges/route.js +19 -7
  45. package/.next/standalone/.next/server/app/api/v1/bridges/route.js.nft.json +1 -1
  46. package/.next/standalone/.next/server/app/api/v1/dashboard/metrics/route.js +17 -5
  47. package/.next/standalone/.next/server/app/api/v1/dashboard/pricing/route.js +7 -0
  48. package/.next/standalone/.next/server/app/api/v1/dashboard/pricing-task/route.js +1 -1
  49. package/.next/standalone/.next/server/app/api/v1/documents/search/route.js +7 -0
  50. package/.next/standalone/.next/server/app/api/v1/documents/settings/route.js +7 -0
  51. package/.next/standalone/.next/server/app/api/v1/documents/sources/[id]/route.js +1 -1
  52. package/.next/standalone/.next/server/app/api/v1/documents/sources/route.js +1 -1
  53. package/.next/standalone/.next/server/app/api/v1/env-sync/allowlist/route.js +7 -0
  54. package/.next/standalone/.next/server/app/api/v1/env-sync/route.js +7 -0
  55. package/.next/standalone/.next/server/app/api/v1/events/route.js +26 -32
  56. package/.next/standalone/.next/server/app/api/v1/events/route.js.nft.json +1 -1
  57. package/.next/standalone/.next/server/app/api/v1/extension/agents/route.js +1 -1
  58. package/.next/standalone/.next/server/app/api/v1/extension/browser/activate/route.js +7 -0
  59. package/.next/standalone/.next/server/app/api/v1/extension/browser/foreground/route.js +7 -0
  60. package/.next/standalone/.next/server/app/api/v1/extension/browser/history/route.js +7 -0
  61. package/.next/standalone/.next/server/app/api/v1/extension/browser/poll/route.js +7 -0
  62. package/.next/standalone/.next/server/app/api/v1/extension/browser/progress/route.js +7 -0
  63. package/.next/standalone/.next/server/app/api/v1/extension/browser/result/route.js +7 -0
  64. package/.next/standalone/.next/server/app/api/v1/extension/browser/retry/route.js +7 -0
  65. package/.next/standalone/.next/server/app/api/v1/extension/browser/status/route.js +7 -0
  66. package/.next/standalone/.next/server/app/api/v1/extension/browser/tabs/route.js +7 -0
  67. package/.next/standalone/.next/server/app/api/v1/extension/fill/route.js +1 -1
  68. package/.next/standalone/.next/server/app/api/v1/extension/refine/route.js +1 -1
  69. package/.next/standalone/.next/server/app/api/v1/extension/turn/route.js +1 -1
  70. package/.next/standalone/.next/server/app/api/v1/extensions/route.js +1 -1
  71. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/config/route.js +1 -1
  72. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/route.js +1 -1
  73. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/secrets/route.js +1 -1
  74. package/.next/standalone/.next/server/app/api/v1/harnesses/[id]/route.js +7 -0
  75. package/.next/standalone/.next/server/app/api/v1/harnesses/default/route.js +7 -0
  76. package/.next/standalone/.next/server/app/api/v1/harnesses/route.js +7 -0
  77. package/.next/standalone/.next/server/app/api/v1/health/route.js +17 -5
  78. package/.next/standalone/.next/server/app/api/v1/integrations/[name]/route.js +7 -0
  79. package/.next/standalone/.next/server/app/api/v1/integrations/gmail/oauth/callback/route.js +7 -0
  80. package/.next/standalone/.next/server/app/api/v1/integrations/gmail/oauth/start/route.js +7 -0
  81. package/.next/standalone/.next/server/app/api/v1/integrations/gmail/oauth/status/route.js +7 -0
  82. package/.next/standalone/.next/server/app/api/v1/integrations/outlook/oauth/callback/route.js +7 -0
  83. package/.next/standalone/.next/server/app/api/v1/integrations/outlook/oauth/start/route.js +7 -0
  84. package/.next/standalone/.next/server/app/api/v1/integrations/outlook/oauth/status/route.js +7 -0
  85. package/.next/standalone/.next/server/app/api/v1/integrations/route.js +7 -0
  86. package/.next/standalone/.next/server/app/api/v1/lifecycle/adoption/route.js +17 -5
  87. package/.next/standalone/.next/server/app/api/v1/maps/embed/route.js +7 -0
  88. package/.next/standalone/.next/server/app/api/v1/mcp-servers/[name]/route.js +17 -5
  89. package/.next/standalone/.next/server/app/api/v1/mcp-servers/route.js +17 -5
  90. package/.next/standalone/.next/server/app/api/v1/memory/[namespace]/[key]/route.js +7 -0
  91. package/.next/standalone/.next/server/app/api/v1/memory/policy/route.js +7 -0
  92. package/.next/standalone/.next/server/app/api/v1/memory/route.js +7 -0
  93. package/.next/standalone/.next/server/app/api/v1/memory/search/route.js +7 -0
  94. package/.next/standalone/.next/server/app/api/v1/models/[name]/compact-threads/route.js +7 -0
  95. package/.next/standalone/.next/server/app/api/v1/models/[name]/route.js +7 -0
  96. package/.next/standalone/.next/server/app/api/v1/models/route.js +7 -0
  97. package/.next/standalone/.next/server/app/api/v1/packages/defaults/[id]/route.js +28 -4
  98. package/.next/standalone/.next/server/app/api/v1/packages/reload/route.js +28 -4
  99. package/.next/standalone/.next/server/app/api/v1/packages/route.js +28 -4
  100. package/.next/standalone/.next/server/app/api/v1/page-capture/route.js +1 -1
  101. package/.next/standalone/.next/server/app/api/v1/pending-actions/[id]/approve/route.js +27 -12
  102. package/.next/standalone/.next/server/app/api/v1/profile/location/route.js +7 -0
  103. package/.next/standalone/.next/server/app/api/v1/profile/route.js +7 -0
  104. package/.next/standalone/.next/server/app/api/v1/providers/[provider]/models/route.js +585 -58
  105. package/.next/standalone/.next/server/app/api/v1/providers/[provider]/probe/route.js +7 -0
  106. package/.next/standalone/.next/server/app/api/v1/providers/github-copilot/auth/route.js +7 -0
  107. package/.next/standalone/.next/server/app/api/v1/providers/route.js +7 -0
  108. package/.next/standalone/.next/server/app/api/v1/proxy-config/route.js +7 -0
  109. package/.next/standalone/.next/server/app/api/v1/redaction/init/route.js +7 -0
  110. package/.next/standalone/.next/server/app/api/v1/redaction/route.js +7 -0
  111. package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/[id]/route.js +17 -5
  112. package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/[id]/run/route.js +1 -1
  113. package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/route.js +7 -0
  114. package/.next/standalone/.next/server/app/api/v1/security/idle-timeout/route.js +7 -0
  115. package/.next/standalone/.next/server/app/api/v1/security/pin/route.js +7 -0
  116. package/.next/standalone/.next/server/app/api/v1/security/state/route.js +7 -0
  117. package/.next/standalone/.next/server/app/api/v1/security/unlock/route.js +7 -0
  118. package/.next/standalone/.next/server/app/api/v1/security/verify-pin/route.js +7 -0
  119. package/.next/standalone/.next/server/app/api/v1/skills/[id]/route.js +7 -0
  120. package/.next/standalone/.next/server/app/api/v1/skills/repos/[id]/route.js +7 -0
  121. package/.next/standalone/.next/server/app/api/v1/skills/repos/route.js +7 -0
  122. package/.next/standalone/.next/server/app/api/v1/skills/route.js +7 -0
  123. package/.next/standalone/.next/server/app/api/v1/tasks/[agent_id]/route.js +7 -0
  124. package/.next/standalone/.next/server/app/api/v1/tasks/route.js +7 -0
  125. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/activity/route.js +7 -0
  126. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/context-pin/route.js +12 -6
  127. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/route.js +125 -26
  128. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/run/route.js +1 -2
  129. package/.next/standalone/.next/server/app/api/v1/threads/route.js +17 -5
  130. package/.next/standalone/.next/server/app/api/v1/tools/route.js +1 -1
  131. package/.next/standalone/.next/server/app/api/v1/update/apply/route.js.nft.json +1 -1
  132. package/.next/standalone/.next/server/app/api/v1/voice/transcribe/route.js +17 -5
  133. package/.next/standalone/.next/server/app/api/v1/voice/tts/route.js +17 -5
  134. package/.next/standalone/.next/server/app/api/v1/watchers/[id]/route.js +17 -5
  135. package/.next/standalone/.next/server/app/api/v1/watchers/[id]/run/route.js +1 -1
  136. package/.next/standalone/.next/server/app/api/v1/watchers/route.js +1 -1
  137. package/.next/standalone/.next/server/app/page.js +27323 -27034
  138. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  139. package/.next/standalone/.next/server/app/setup/page.js +8 -0
  140. package/.next/standalone/.next/server/app/setup/page_client-reference-manifest.js +1 -1
  141. package/.next/standalone/.next/server/app-paths-manifest.json +5 -5
  142. package/.next/standalone/.next/server/chunks/1388.js +106 -36
  143. package/.next/standalone/.next/server/chunks/2068.js +47 -10
  144. package/.next/standalone/.next/server/chunks/210.js +6 -6
  145. package/.next/standalone/.next/server/chunks/2447.js +10 -5
  146. package/.next/standalone/.next/server/chunks/2653.js +80 -1
  147. package/.next/standalone/.next/server/chunks/3042.js +10 -8
  148. package/.next/standalone/.next/server/chunks/{4540.js → 309.js} +104 -38
  149. package/.next/standalone/.next/server/chunks/{2350.js → 3272.js} +104 -37
  150. package/.next/standalone/.next/server/chunks/3524.js +150 -67
  151. package/.next/standalone/.next/server/chunks/3566.js +1 -1
  152. package/.next/standalone/.next/server/chunks/4189.js +1 -1
  153. package/.next/standalone/.next/server/chunks/4596.js +28 -4
  154. package/.next/standalone/.next/server/chunks/46.js +91 -31
  155. package/.next/standalone/.next/server/chunks/466.js +53 -7
  156. package/.next/standalone/.next/server/chunks/4955.js +30 -3
  157. package/.next/standalone/.next/server/chunks/5585.js +28 -4
  158. package/.next/standalone/.next/server/chunks/5908.js +63 -42
  159. package/.next/standalone/.next/server/chunks/6142.js +10 -2
  160. package/.next/standalone/.next/server/chunks/8461.js +10 -8
  161. package/.next/standalone/.next/server/chunks/9032.js +5 -5
  162. package/.next/standalone/.next/server/chunks/9164.js +487 -177
  163. package/.next/standalone/.next/server/chunks/9304.js +51 -12
  164. package/.next/standalone/.next/server/chunks/{423.js → 9590.js} +84 -24
  165. package/.next/standalone/.next/server/middleware-build-manifest.js +2 -2
  166. package/.next/standalone/.next/server/middleware.js +89 -21
  167. package/.next/standalone/.next/server/pages/404.html +14 -2
  168. package/.next/standalone/.next/server/pages/500.html +1 -1
  169. package/.next/standalone/.next/server/preview-props.json +3 -3
  170. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  171. package/.next/standalone/.next/static/chunks/{1395-e4a99912b8f83044.js → 1395-bfe1f3ef760c0f50.js} +54 -8
  172. package/.next/standalone/.next/static/chunks/app/{layout-9bc0b10127cb7d42.js → layout-7b24ad13faa3944b.js} +69 -2
  173. package/.next/standalone/.next/static/chunks/app/{page-213a623b37226452.js → page-2ef8d75d40eb4311.js} +10643 -10295
  174. package/.next/standalone/.next/static/css/c160ea862133acd2.css +5 -0
  175. package/.next/standalone/docs/adoption/changesets.json +2805 -0
  176. package/.next/standalone/package.json +1 -1
  177. package/CHANGELOG.md +52 -0
  178. package/api/client.models.test.ts +10 -0
  179. package/api/client.startup.test.ts +129 -0
  180. package/api/client.ts +51 -9
  181. package/api/thread-metadata.test.ts +72 -0
  182. package/api/types.ts +6 -3
  183. package/app/api/v1/providers/[provider]/models/route.test.ts +216 -6
  184. package/app/api/v1/providers/[provider]/models/route.ts +259 -40
  185. package/app/api/v1/threads/[thread_id]/route.ts +26 -23
  186. package/app/api/v1/threads/[thread_id]/run/route.ts +0 -1
  187. package/app/globals.css +119 -29
  188. package/app/layout.tsx +12 -0
  189. package/components/agents/AgentsPanel.tsx +5 -13
  190. package/components/chat/ChatView.tsx +9 -18
  191. package/components/chat/InputBar.tsx +1 -1
  192. package/components/chat/MessageBubble.tsx +13 -1
  193. package/components/chat/MessageList.test.tsx +45 -4
  194. package/components/chat/MessageList.tsx +123 -89
  195. package/components/chat/ToolList.tsx +88 -84
  196. package/components/chat/useThreadActivity.test.tsx +2 -2
  197. package/components/chat/useThreadActivity.ts +2 -2
  198. package/components/chat/useThreadData.ts +1 -30
  199. package/components/chat/useThreadMetadataPolling.test.tsx +128 -0
  200. package/components/chat/useThreadMetadataPolling.ts +50 -0
  201. package/components/chat/useUserProfileAndAgent.test.tsx +31 -0
  202. package/components/chat/useUserProfileAndAgent.ts +13 -2
  203. package/components/dashboard/DashboardPanel.tsx +1 -1
  204. package/components/dashboard/Series.tsx +34 -21
  205. package/components/dashboard/SummaryCards.tsx +1 -1
  206. package/components/integrations/NetworkSection.tsx +2 -2
  207. package/components/layout/AppShell.tsx +22 -7
  208. package/components/layout/MenuPanel.tsx +14 -24
  209. package/components/profile/ProfilePanel.tsx +2 -2
  210. package/components/settings/AppearancePanel.tsx +70 -3
  211. package/components/settings/SettingsPanel.tsx +2 -2
  212. package/components/tools/ToolsPanel.tsx +2 -7
  213. package/components/ui/AppearancePreferences.test.tsx +68 -0
  214. package/components/ui/BootScreen.test.tsx +44 -0
  215. package/components/ui/BootScreen.tsx +24 -11
  216. package/components/ui/NotificationStatus.test.tsx +2 -2
  217. package/components/ui/NotificationStatus.tsx +5 -5
  218. package/components/ui/SubTabBar.tsx +2 -3
  219. package/contexts/ThemeContext.tsx +84 -1
  220. package/hooks/useAgentSession.test.ts +12 -1
  221. package/hooks/useAgentSession.ts +6 -4
  222. package/hooks/useUrlSync.test.ts +13 -0
  223. package/hooks/useUrlSync.ts +0 -4
  224. package/lib/agents/citation-checker.test.ts +40 -2
  225. package/lib/agents/citation-checker.ts +56 -11
  226. package/lib/agents/context-boundary.ts +5 -6
  227. package/lib/agents/instruction-edits.test.ts +120 -0
  228. package/lib/agents/instruction-edits.ts +65 -42
  229. package/lib/agents/prepare/request.ts +0 -2
  230. package/lib/agents/prepare/system-prompt.test.ts +10 -0
  231. package/lib/agents/prepare/system-prompt.ts +8 -2
  232. package/lib/agents/proposals.test.ts +76 -0
  233. package/lib/agents/proposals.ts +13 -5
  234. package/lib/agents/run-thread.auto-boundary.test.ts +125 -5
  235. package/lib/agents/run-thread.ts +24 -9
  236. package/lib/agents/sqlite-checkpoint-saver.test.ts +91 -0
  237. package/lib/agents/warm-summary-background.ts +22 -2
  238. package/lib/agents/warm-topics.test.ts +155 -1
  239. package/lib/agents/warm-topics.ts +27 -7
  240. package/lib/bridges/dispatcher.ts +1 -0
  241. package/lib/bridges/message-role.test.ts +81 -0
  242. package/lib/bridges/message-role.ts +23 -10
  243. package/lib/bridges/types.ts +6 -0
  244. package/lib/bridges/whatsapp-link.test.ts +32 -0
  245. package/lib/bridges/whatsapp-link.ts +21 -0
  246. package/lib/bridges/whatsapp.inbound.test.ts +239 -0
  247. package/lib/bridges/whatsapp.sender.test.ts +80 -1
  248. package/lib/bridges/whatsapp.ts +76 -38
  249. package/lib/db/migrations.test.ts +61 -0
  250. package/lib/db/migrations.ts +13 -0
  251. package/lib/embeddings/performance.test.ts +114 -0
  252. package/lib/pricing/snapshot.test.ts +70 -0
  253. package/lib/pricing/snapshot.ts +10 -2
  254. package/lib/proxy/dispatcher.test.ts +119 -1
  255. package/lib/proxy/dispatcher.ts +22 -9
  256. package/lib/stores/agent-configs.ts +10 -5
  257. package/lib/stores/bridges.test.ts +81 -0
  258. package/lib/stores/bridges.ts +9 -8
  259. package/lib/stores/dashboard-metrics-cache.test.ts +99 -0
  260. package/lib/stores/dashboard-metrics.ts +30 -4
  261. package/lib/stores/message-embedding-jobs.test.ts +27 -0
  262. package/lib/stores/message-embedding-jobs.ts +5 -3
  263. package/lib/stores/message-usage.test.ts +21 -1
  264. package/lib/stores/pricing-cache.test.ts +31 -0
  265. package/lib/stores/pricing.ts +3 -0
  266. package/lib/stores/proxy-config.test.ts +120 -0
  267. package/lib/stores/proxy-config.ts +22 -4
  268. package/lib/stores/threads.ts +12 -8
  269. package/lib/tools/communications/calendar.test.ts +43 -2
  270. package/lib/tools/communications/calendar.ts +2 -0
  271. package/lib/tools/communications/gmail.test.ts +51 -1
  272. package/lib/tools/communications/gmail.ts +44 -2
  273. package/lib/tools/communications/outlook-calendar.ts +2 -0
  274. package/lib/tools/communications/outlook.test.ts +33 -2
  275. package/lib/tools/communications/outlook.ts +2 -0
  276. package/lib/tools/filesystem/edit-match.test.ts +133 -0
  277. package/lib/tools/filesystem/edit-match.ts +7 -2
  278. package/lib/tools/packages/default-packages.test.ts +21 -0
  279. package/lib/tools/packages/optional-package.test.ts +72 -0
  280. package/lib/tools/packages/optional-package.ts +33 -4
  281. package/lib/tools/support/result-refs.test.ts +131 -0
  282. package/lib/tools/support/result-refs.ts +41 -9
  283. package/lib/ui/navigate.test.ts +13 -0
  284. package/lib/ui/navigate.ts +10 -2
  285. package/lib/utils/source-link.test.ts +51 -0
  286. package/lib/utils/source-link.ts +45 -0
  287. package/package.json +1 -1
  288. package/.next/standalone/.next/static/css/312542a5725ba0d5.css +0 -5
  289. /package/.next/standalone/.next/static/{bMRK5y3ruT7c3WtBfCQOG → 544OFJV-q0RC6Gjgje4LT}/_buildManifest.js +0 -0
  290. /package/.next/standalone/.next/static/{bMRK5y3ruT7c3WtBfCQOG → 544OFJV-q0RC6Gjgje4LT}/_ssgManifest.js +0 -0
@@ -510,6 +510,266 @@ module.exports = require("node:async_hooks");
510
510
 
511
511
  module.exports = require("next/dist/server/app-render/action-async-storage.external.js");
512
512
 
513
+ /***/ }),
514
+
515
+ /***/ 23619:
516
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
517
+
518
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
519
+ /* harmony export */ AT: () => (/* binding */ thinkingReductionParams),
520
+ /* harmony export */ _8: () => (/* binding */ modelCapabilities),
521
+ /* harmony export */ ne: () => (/* binding */ modelThinksByDefault)
522
+ /* harmony export */ });
523
+ /* unused harmony exports modelSupportsImages, isProviderClassified */
524
+ /**
525
+ * Static per-provider classification of which model ids accept image inputs.
526
+ *
527
+ * Used purely to surface UI hints — "this agent's model can read WhatsApp
528
+ * images" — so a user can pick a vision-capable model BEFORE pointing a
529
+ * bridge route at an agent. The runtime never enforces this: the bridge
530
+ * always forwards whatever payload it captured, and the provider returns
531
+ * whatever ignore/error behaviour the upstream model chose if it isn't
532
+ * actually multi-modal.
533
+ *
534
+ * Patterns intentionally err on the *generous* side. A false positive just
535
+ * means the user sees no warning for a model that quietly ignores images;
536
+ * a false negative would mean users see a scary warning on a model that
537
+ * actually works fine. We update the patterns as new model families ship.
538
+ *
539
+ * NOTE: this module is intentionally free of server-only imports so the
540
+ * BridgeEditor / AgentEditor UIs can import it directly.
541
+ */ const PATTERNS = {
542
+ // OpenAI — every modern flagship is multi-modal; only the legacy
543
+ // gpt-3.5-* / text-davinci-* / o3-mini-text family stay text-only.
544
+ openai: [
545
+ /^gpt-4o/i,
546
+ /^gpt-4\.1/i,
547
+ /^gpt-4-turbo/i,
548
+ /^gpt-4-vision/i,
549
+ /^gpt-5/i,
550
+ /^chatgpt-4o/i,
551
+ /^o[134](?:-|$)/i
552
+ ],
553
+ // Anthropic — Claude 3 onwards is vision-native across all tiers.
554
+ anthropic: [
555
+ /^claude-3/i,
556
+ /^claude-sonnet/i,
557
+ /^claude-opus/i,
558
+ /^claude-haiku-4/i,
559
+ /^claude-[45](?:-|$)/i
560
+ ],
561
+ // Google — Gemini 1.5+ are multi-modal; legacy gemini-pro is text-only,
562
+ // but gemini-pro-vision was the explicit vision SKU before 1.5.
563
+ gemini: [
564
+ /^gemini-(1\.5|2|3)/i,
565
+ /^gemini-pro-vision/i
566
+ ],
567
+ // GitHub Copilot — proxies vision-capable models from OpenAI / Anthropic /
568
+ // Google. Mirror those families (the actual capability is gated server-
569
+ // side by Copilot; we just don't warn).
570
+ "github-copilot": [
571
+ /^gpt-4o/i,
572
+ /^gpt-4\.1/i,
573
+ /^gpt-5/i,
574
+ /^o[134](?:-|$)/i,
575
+ /^claude-3/i,
576
+ /^claude-sonnet/i,
577
+ /^claude-opus/i,
578
+ /^claude-haiku-4/i,
579
+ /^claude-[45](?:-|$)/i,
580
+ /^gemini-(1\.5|2|3)/i
581
+ ],
582
+ // DeepSeek V4.1 Flash is multimodal (`deepseek-v4-flash` is a legacy alias for it);
583
+ // V4 Pro and Cohere chat SKUs are text-only.
584
+ deepseek: [
585
+ /^deepseek-(?:v4-)?flash/i
586
+ ],
587
+ cohere: [],
588
+ // LangChain pass-through could be anything; treat as unknown (handled
589
+ // separately below) rather than yes/no.
590
+ langchain: [],
591
+ // Tests assume the mock accepts images.
592
+ mock: [
593
+ /.*/
594
+ ]
595
+ };
596
+ /**
597
+ * Returns true when the given (provider, model_id) pair is known to accept
598
+ * image inputs. Unknown providers / models return false — call
599
+ * `isProviderClassified` if you want to distinguish "definitely no" from
600
+ * "we don't recognize this".
601
+ */ function modelSupportsImages(provider, modelId) {
602
+ const pats = PATTERNS[provider.toLowerCase()] ?? [];
603
+ return pats.some((re)=>re.test(modelId));
604
+ }
605
+ /**
606
+ * True when we have an explicit capability list for the provider. Used by
607
+ * the UI to soften the warning copy ("might not support images") for
608
+ * pass-through providers like `langchain` or unknown external ones.
609
+ */ function isProviderClassified(provider) {
610
+ return provider.toLowerCase() in PATTERNS;
611
+ }
612
+ // ── extended capabilities for badge rendering ────────────────────────────────
613
+ // Mirrors CatalogModel["capabilities"] so saved ModelConfigs can render the
614
+ // same icon set the catalog browser uses. Heuristics err on the conservative
615
+ // side for audio (vanilla gpt-4o is NOT audio-capable — only *-audio-preview /
616
+ // *-realtime are) and generous side for files (PDF / document input).
617
+ const AUDIO_PATTERNS = {
618
+ openai: [
619
+ /audio/i,
620
+ /realtime/i
621
+ ],
622
+ gemini: [
623
+ /^gemini-(1\.5|2|3)/i
624
+ ],
625
+ anthropic: [],
626
+ "github-copilot": [
627
+ /audio/i,
628
+ /realtime/i,
629
+ /^gemini-(1\.5|2|3)/i
630
+ ],
631
+ deepseek: [],
632
+ cohere: [],
633
+ langchain: [],
634
+ mock: [
635
+ /.*/
636
+ ]
637
+ };
638
+ const FILES_PATTERNS = {
639
+ // PDF / document upload support.
640
+ openai: [
641
+ /^gpt-4o/i,
642
+ /^gpt-4\.1/i,
643
+ /^gpt-4-turbo/i,
644
+ /^gpt-5/i,
645
+ /^o[134](?:-|$)/i,
646
+ /^chatgpt-4o/i
647
+ ],
648
+ anthropic: [
649
+ /^claude-3/i,
650
+ /^claude-sonnet/i,
651
+ /^claude-opus/i,
652
+ /^claude-haiku-4/i,
653
+ /^claude-[45](?:-|$)/i
654
+ ],
655
+ gemini: [
656
+ /^gemini-(1\.5|2|3)/i
657
+ ],
658
+ "github-copilot": [
659
+ /^gpt-4o/i,
660
+ /^gpt-4\.1/i,
661
+ /^gpt-5/i,
662
+ /^o[134](?:-|$)/i,
663
+ /^claude-3/i,
664
+ /^claude-sonnet/i,
665
+ /^claude-opus/i,
666
+ /^claude-haiku-4/i,
667
+ /^claude-[45](?:-|$)/i,
668
+ /^gemini-(1\.5|2|3)/i
669
+ ],
670
+ deepseek: [],
671
+ cohere: [],
672
+ langchain: [],
673
+ mock: [
674
+ /.*/
675
+ ]
676
+ };
677
+ const WEB_SEARCH_PATTERNS = {
678
+ // Built-in provider-side web tool.
679
+ anthropic: [
680
+ /^claude-3\.5/i,
681
+ /^claude-3\.7/i,
682
+ /^claude-sonnet/i,
683
+ /^claude-opus/i,
684
+ /^claude-haiku-4/i,
685
+ /^claude-[45](?:-|$)/i
686
+ ],
687
+ openai: [],
688
+ gemini: [],
689
+ "github-copilot": [],
690
+ deepseek: [],
691
+ cohere: [],
692
+ langchain: [],
693
+ mock: []
694
+ };
695
+ const JSON_MODE_PROVIDERS = new Set([
696
+ "openai",
697
+ "gemini",
698
+ "deepseek",
699
+ "mock"
700
+ ]);
701
+ // Models whose reasoning tokens are spent from the same max_tokens budget as the
702
+ // visible answer, so a tight output cap truncates them before they reply.
703
+ const THINKS_BY_DEFAULT = {
704
+ openai: [
705
+ /^gpt-5/i,
706
+ /^o[134](?:-|$)/i
707
+ ],
708
+ gemini: [
709
+ /^gemini-(2\.5|3)/i
710
+ ],
711
+ "github-copilot": [
712
+ /^gpt-5/i,
713
+ /^o[134](?:-|$)/i,
714
+ /^gemini-(2\.5|3)/i
715
+ ],
716
+ deepseek: [
717
+ /^deepseek-(?:v4|flash|reasoner)/i
718
+ ]
719
+ };
720
+ function modelThinksByDefault(provider, modelId) {
721
+ return (THINKS_BY_DEFAULT[provider.toLowerCase()] ?? []).some((re)=>re.test(modelId));
722
+ }
723
+ /**
724
+ * Request params that turn a default-thinking model's reasoning down. `off` is
725
+ * true only when the provider can disable it outright; OpenAI reasoning models
726
+ * can only be lowered, so they still reason a little. Null when the model has
727
+ * no known control, so nothing is sent.
728
+ */ function thinkingReductionParams(provider, modelId) {
729
+ const p = provider.toLowerCase();
730
+ if (p === "deepseek" && /^deepseek-(?:v4|flash)/i.test(modelId)) {
731
+ return {
732
+ params: {
733
+ thinking: {
734
+ type: "disabled"
735
+ }
736
+ },
737
+ off: true
738
+ };
739
+ }
740
+ // "low" is accepted by every OpenAI reasoning model; "minimal" is not on newer gpt-5 releases.
741
+ if (p === "openai" && /^(gpt-5|o[134](?:-|$))/i.test(modelId)) return {
742
+ params: {
743
+ reasoning_effort: "low"
744
+ },
745
+ off: false
746
+ };
747
+ return null;
748
+ }
749
+ function matchesAny(map, provider, modelId) {
750
+ const pats = map[provider.toLowerCase()] ?? [];
751
+ return pats.some((re)=>re.test(modelId));
752
+ }
753
+ /**
754
+ * Best-effort capability inference for a saved (provider, model_id) pair —
755
+ * used to render capability badges in surfaces that don't have a live
756
+ * catalog fetch (ModelsPanel, AgentEditor dropdowns, etc.).
757
+ */ function modelCapabilities(provider, modelId) {
758
+ const p = provider.toLowerCase();
759
+ // Reasoner-style models that don't expose tool calling.
760
+ const noTools = /^deepseek-reasoner/i.test(modelId);
761
+ return {
762
+ vision: modelSupportsImages(provider, modelId),
763
+ tools: isProviderClassified(p) && !noTools,
764
+ streaming: true,
765
+ json_mode: JSON_MODE_PROVIDERS.has(p),
766
+ web_search: matchesAny(WEB_SEARCH_PATTERNS, provider, modelId),
767
+ audio: matchesAny(AUDIO_PATTERNS, provider, modelId),
768
+ files: matchesAny(FILES_PATTERNS, provider, modelId)
769
+ };
770
+ }
771
+
772
+
513
773
  /***/ }),
514
774
 
515
775
  /***/ 27910:
@@ -566,6 +826,91 @@ module.exports = require("node:http");
566
826
 
567
827
  module.exports = require("node:zlib");
568
828
 
829
+ /***/ }),
830
+
831
+ /***/ 39947:
832
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
833
+
834
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
835
+ /* harmony export */ Bm: () => (/* binding */ cachedJson),
836
+ /* harmony export */ HN: () => (/* binding */ notFoundResponse),
837
+ /* harmony export */ Jb: () => (/* binding */ validateBody),
838
+ /* harmony export */ K2: () => (/* binding */ createdResponse),
839
+ /* harmony export */ Ng: () => (/* binding */ noStoreJson),
840
+ /* harmony export */ yj: () => (/* binding */ errorResponse)
841
+ /* harmony export */ });
842
+ /* harmony import */ var next_server__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(23211);
843
+ // Shared HTTP response builders for app/api/v1/** route handlers.
844
+ //
845
+ // Goal: every error/success payload across the v1 surface has the same
846
+ // shape. Before this lived inline, response bodies drifted —
847
+ // `{error: "x"}` vs `{message: "x"}`, 400 vs 422 for the same condition,
848
+ // some routes returned Zod's raw issue array, others stringified it.
849
+
850
+ function errorResponse(message, status = 400) {
851
+ return next_server__WEBPACK_IMPORTED_MODULE_0__.NextResponse.json({
852
+ error: message
853
+ }, {
854
+ status
855
+ });
856
+ }
857
+ function notFoundResponse(message = "Not found") {
858
+ return errorResponse(message, 404);
859
+ }
860
+ function createdResponse(data) {
861
+ return next_server__WEBPACK_IMPORTED_MODULE_0__.NextResponse.json(data, {
862
+ status: 201
863
+ });
864
+ }
865
+ // Wrap a 200 JSON response with a private Cache-Control header. Use on safe
866
+ // GET endpoints that serve user-scoped data the client refetches often (panel
867
+ // mounts, navigation back/forward) but mutates rarely. The TTL is short
868
+ // enough that explicit mutations — which patch the client-side ApiClient
869
+ // cache in place — stay observably consistent without an extra roundtrip.
870
+ //
871
+ // swrSeconds (optional): stale-while-revalidate window. When set, the browser
872
+ // serves the cached response immediately and refreshes in the background,
873
+ // making navigation feel instant. Use for data that can tolerate brief
874
+ // staleness (tool list, agent configs, model list). Omit for real-time data
875
+ // (dashboard metrics, credential state).
876
+ function cachedJson(data, maxAgeSeconds, swrSeconds) {
877
+ const swr = swrSeconds ? `, stale-while-revalidate=${swrSeconds}` : "";
878
+ return next_server__WEBPACK_IMPORTED_MODULE_0__.NextResponse.json(data, {
879
+ headers: {
880
+ "Cache-Control": `private, max-age=${maxAgeSeconds}${swr}`
881
+ }
882
+ });
883
+ }
884
+ // Use for endpoints whose response contains live state that must never be
885
+ // served from cache — credentials, connection status, live config values.
886
+ function noStoreJson(data) {
887
+ return next_server__WEBPACK_IMPORTED_MODULE_0__.NextResponse.json(data, {
888
+ headers: {
889
+ "Cache-Control": "no-store"
890
+ }
891
+ });
892
+ }
893
+ // Validate a JSON request body against a zod schema.
894
+ // Returns either the parsed data or a 400 NextResponse explaining the issue.
895
+ // Caller pattern:
896
+ // const parsed = await validateBody(req, Schema);
897
+ // if (parsed instanceof NextResponse) return parsed;
898
+ // // use parsed.field
899
+ async function validateBody(req, schema) {
900
+ let raw;
901
+ try {
902
+ raw = await req.json();
903
+ } catch {
904
+ return errorResponse("Request body must be valid JSON", 400);
905
+ }
906
+ const parsed = schema.safeParse(raw);
907
+ if (!parsed.success) {
908
+ return errorResponse(parsed.error.issues[0]?.message ?? "invalid body", 400);
909
+ }
910
+ return parsed.data;
911
+ }
912
+
913
+
569
914
  /***/ }),
570
915
 
571
916
  /***/ 44708:
@@ -916,6 +1261,13 @@ module.exports = require("node:path");
916
1261
 
917
1262
  /***/ }),
918
1263
 
1264
+ /***/ 77030:
1265
+ /***/ ((module) => {
1266
+
1267
+ module.exports = require("node:net");
1268
+
1269
+ /***/ }),
1270
+
919
1271
  /***/ 77598:
920
1272
  /***/ ((module) => {
921
1273
 
@@ -967,18 +1319,26 @@ __webpack_require__.r(__webpack_exports__);
967
1319
  /* harmony export */ POST: () => (/* binding */ POST)
968
1320
  /* harmony export */ });
969
1321
  /* harmony import */ var next_server__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(23211);
1322
+ /* harmony import */ var zod__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(97377);
970
1323
  /* harmony import */ var _lib_providers__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(60034);
971
- /* harmony import */ var _lib_stores_model_config__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(80937);
972
- /* harmony import */ var _lib_providers_known_context_windows__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(45552);
973
- /* harmony import */ var _lib_utils_error__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(22032);
1324
+ /* harmony import */ var _lib_providers_capabilities__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(23619);
1325
+ /* harmony import */ var _lib_stores_model_config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(80937);
1326
+ /* harmony import */ var _lib_api_responses__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(39947);
1327
+ /* harmony import */ var _lib_providers_known_context_windows__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(45552);
1328
+ /* harmony import */ var _lib_utils_error__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(22032);
1329
+
974
1330
 
975
1331
 
976
1332
 
977
1333
 
978
1334
 
979
- // Live provider catalogs (OpenAI, GitHub Copilot) hit external APIs on every
980
- // call; static ones still cost JSON construction. Cache per-provider for a
981
- // short TTL so flipping panels / model browsers doesn't re-hit upstream.
1335
+
1336
+
1337
+ const CatalogBody = zod__WEBPACK_IMPORTED_MODULE_6__/* .object */ .Ikc({
1338
+ params: zod__WEBPACK_IMPORTED_MODULE_6__/* .record */ .g1P(zod__WEBPACK_IMPORTED_MODULE_6__/* .string */ .YjP(), zod__WEBPACK_IMPORTED_MODULE_6__/* .unknown */ .L5J()).optional()
1339
+ });
1340
+ // Live provider catalogs hit external APIs. Cache per-provider briefly so
1341
+ // opening the model browser repeatedly doesn't re-hit upstream.
982
1342
  const PROVIDER_CATALOG_TTL_MS = 10 * 60 * 1000;
983
1343
  const catalogCache = new Map();
984
1344
  async function getCachedCatalog(provider, force) {
@@ -1025,12 +1385,11 @@ function catalogErrorResponse(err) {
1025
1385
  // these responses since they're keyed on user-supplied secrets.
1026
1386
  async function POST(req, { params }) {
1027
1387
  const { provider } = await params;
1028
- let body = {};
1029
- try {
1030
- body = await req.json();
1031
- } catch {}
1388
+ const body = await (0,_lib_api_responses__WEBPACK_IMPORTED_MODULE_4__/* .validateBody */ .Jb)(req, CatalogBody);
1389
+ if (body instanceof next_server__WEBPACK_IMPORTED_MODULE_0__.NextResponse) return body;
1032
1390
  try {
1033
1391
  const models = await fetchCatalog(provider, body.params);
1392
+ catalogCache.delete(provider);
1034
1393
  return next_server__WEBPACK_IMPORTED_MODULE_0__.NextResponse.json(models, {
1035
1394
  headers: {
1036
1395
  "Cache-Control": "no-store"
@@ -1043,19 +1402,70 @@ async function POST(req, { params }) {
1043
1402
  async function fetchCatalog(provider, overrides) {
1044
1403
  switch(provider){
1045
1404
  case "openai":
1046
- return fetchOpenAICatalog();
1405
+ return fetchOpenAICatalog(overrides);
1047
1406
  case "github-copilot":
1048
1407
  return fetchGitHubCopilotCatalog();
1049
1408
  case "anthropic":
1050
- return anthropicKnownModels();
1409
+ return fetchAnthropicCatalog(overrides);
1051
1410
  case "gemini":
1052
- return geminiKnownModels();
1411
+ return fetchGeminiCatalog(overrides);
1053
1412
  case "deepseek":
1054
- return deepseekKnownModels();
1413
+ return fetchDeepseekCatalog(overrides);
1055
1414
  default:
1056
1415
  return fetchExternalCatalog(provider, overrides);
1057
1416
  }
1058
1417
  }
1418
+ const PROVIDER_API_KEY_ENV = {
1419
+ anthropic: "ANTHROPIC_API_KEY",
1420
+ openai: "OPENAI_API_KEY",
1421
+ gemini: "GEMINI_API_KEY",
1422
+ deepseek: "DEEPSEEK_API_KEY"
1423
+ };
1424
+ function catalogParamsCandidates(provider, overrides) {
1425
+ const envKey = process.env[PROVIDER_API_KEY_ENV[provider] ?? ""];
1426
+ const configs = (0,_lib_stores_model_config__WEBPACK_IMPORTED_MODULE_3__/* .listModelConfigs */ .D1)().filter((cfg)=>cfg.provider === provider);
1427
+ const candidates = configs.map((cfg)=>{
1428
+ const params = {
1429
+ ...(0,_lib_stores_model_config__WEBPACK_IMPORTED_MODULE_3__/* .getModelParams */ .mN)(cfg),
1430
+ ...overrides ?? {}
1431
+ };
1432
+ if (!params.api_key && envKey) params.api_key = envKey;
1433
+ return params;
1434
+ });
1435
+ if (overrides) {
1436
+ const params = {
1437
+ ...overrides
1438
+ };
1439
+ if (!params.api_key && envKey) params.api_key = envKey;
1440
+ candidates.push(params);
1441
+ }
1442
+ if (candidates.length === 0 && envKey) candidates.push({
1443
+ api_key: envKey
1444
+ });
1445
+ if (candidates.length === 0) candidates.push({});
1446
+ return candidates;
1447
+ }
1448
+ async function fetchConfiguredCatalog(provider, overrides, fetcher, fallback) {
1449
+ const candidates = catalogParamsCandidates(provider, overrides).filter((params)=>typeof params.api_key === "string" && params.api_key.length > 0);
1450
+ if (candidates.length === 0) return fallback();
1451
+ let lastErr;
1452
+ for (const params of candidates){
1453
+ try {
1454
+ return await fetcher(params, params.api_key);
1455
+ } catch (err) {
1456
+ lastErr = err;
1457
+ }
1458
+ }
1459
+ throw lastErr ?? new Error(`${provider} catalog request failed`);
1460
+ }
1461
+ async function requestCatalogJson(provider, url, init) {
1462
+ const res = await fetch(url, {
1463
+ ...init,
1464
+ signal: AbortSignal.timeout(15000)
1465
+ });
1466
+ if (!res.ok) throw new Error(`${provider} catalog error: ${res.status}`);
1467
+ return res.json();
1468
+ }
1059
1469
  async function fetchExternalCatalog(providerName, overrides) {
1060
1470
  let provider;
1061
1471
  try {
@@ -1070,9 +1480,9 @@ async function fetchExternalCatalog(providerName, overrides) {
1070
1480
  // row is misconfigured. Overrides are merged on top of each candidate,
1071
1481
  // then also tried standalone, so a freshly-typed api_key works before
1072
1482
  // the user has saved it.
1073
- const cfgs = (0,_lib_stores_model_config__WEBPACK_IMPORTED_MODULE_2__/* .listModelConfigs */ .D1)().filter((c)=>c.provider === providerName);
1483
+ const cfgs = (0,_lib_stores_model_config__WEBPACK_IMPORTED_MODULE_3__/* .listModelConfigs */ .D1)().filter((c)=>c.provider === providerName);
1074
1484
  const candidates = cfgs.map((c)=>({
1075
- ...(0,_lib_stores_model_config__WEBPACK_IMPORTED_MODULE_2__/* .getModelParams */ .mN)(c),
1485
+ ...(0,_lib_stores_model_config__WEBPACK_IMPORTED_MODULE_3__/* .getModelParams */ .mN)(c),
1076
1486
  ...overrides ?? {}
1077
1487
  }));
1078
1488
  if (overrides && Object.keys(overrides).length > 0) candidates.push(overrides);
@@ -1089,42 +1499,159 @@ async function fetchExternalCatalog(providerName, overrides) {
1089
1499
  throw lastErr ?? new Error(`${providerName}: no usable credentials for catalog`);
1090
1500
  }
1091
1501
  // ── OpenAI ────────────────────────────────────────────────────────────────────
1092
- async function fetchOpenAICatalog() {
1093
- const cfg = (0,_lib_stores_model_config__WEBPACK_IMPORTED_MODULE_2__/* .listModelConfigs */ .D1)().find((c)=>c.provider === "openai");
1094
- if (!cfg) throw new Error("No OpenAI model config found.");
1095
- const params = (0,_lib_stores_model_config__WEBPACK_IMPORTED_MODULE_2__/* .getModelParams */ .mN)(cfg);
1096
- const apiKey = params.api_key ?? process.env.OPENAI_API_KEY;
1097
- if (!apiKey) throw new Error("OpenAI: no api_key configured.");
1098
- const res = await fetch("https://api.openai.com/v1/models", {
1099
- headers: {
1100
- Authorization: `Bearer ${apiKey}`
1101
- }
1502
+ async function fetchOpenAICatalog(overrides) {
1503
+ return fetchConfiguredCatalog("openai", overrides, async (params, apiKey)=>{
1504
+ const url = endpointUrl(params.base_url, "https://api.openai.com/v1", "/models");
1505
+ const data = await requestCatalogJson("OpenAI", url, {
1506
+ headers: {
1507
+ ...params.extra_headers,
1508
+ Authorization: "Bearer " + apiKey
1509
+ }
1510
+ });
1511
+ const chatPrefixes = [
1512
+ "gpt-",
1513
+ "o1",
1514
+ "o3",
1515
+ "o4",
1516
+ "chatgpt-"
1517
+ ];
1518
+ return (data.data ?? []).filter((m)=>chatPrefixes.some((p)=>m.id.startsWith(p))).map((m)=>({
1519
+ id: m.id,
1520
+ context_length: (0,_lib_providers_known_context_windows__WEBPACK_IMPORTED_MODULE_5__/* .getKnownContextLength */ .zJ)("openai", m.id),
1521
+ max_output_tokens: (0,_lib_providers_known_context_windows__WEBPACK_IMPORTED_MODULE_5__/* .getKnownMaxOutputTokens */ .pN)("openai", m.id),
1522
+ hosted_on: "azure/openai",
1523
+ capabilities: {
1524
+ vision: m.id.includes("vision") || m.id.startsWith("gpt-4"),
1525
+ tools: true,
1526
+ streaming: true,
1527
+ json_mode: true,
1528
+ web_search: false,
1529
+ audio: m.id.includes("audio") || m.id.startsWith("gpt-4o") || m.id.startsWith("gpt-5"),
1530
+ files: m.id.startsWith("gpt-4") || m.id.startsWith("gpt-5") || m.id.startsWith("o")
1531
+ }
1532
+ })).sort((a, b)=>a.id.localeCompare(b.id));
1533
+ }, ()=>{
1534
+ throw new Error("OpenAI: no api_key configured.");
1102
1535
  });
1103
- if (!res.ok) throw new Error(`OpenAI catalog error: ${res.status}`);
1104
- const data = await res.json();
1105
- const chatPrefixes = [
1106
- "gpt-",
1107
- "o1",
1108
- "o3",
1109
- "o4",
1110
- "chatgpt-"
1111
- ];
1112
- const chatModels = data.data.filter((m)=>chatPrefixes.some((p)=>m.id.startsWith(p))).map((m)=>({
1113
- id: m.id,
1114
- context_length: (0,_lib_providers_known_context_windows__WEBPACK_IMPORTED_MODULE_3__/* .getKnownContextLength */ .zJ)("openai", m.id),
1115
- max_output_tokens: (0,_lib_providers_known_context_windows__WEBPACK_IMPORTED_MODULE_3__/* .getKnownMaxOutputTokens */ .pN)("openai", m.id),
1116
- hosted_on: "azure/openai",
1117
- capabilities: {
1118
- vision: m.id.includes("vision") || m.id.startsWith("gpt-4"),
1119
- tools: true,
1120
- streaming: true,
1121
- json_mode: true,
1122
- web_search: false,
1123
- audio: m.id.includes("audio") || m.id.startsWith("gpt-4o") || m.id.startsWith("gpt-5"),
1124
- files: m.id.startsWith("gpt-4") || m.id.startsWith("gpt-5") || m.id.startsWith("o")
1536
+ }
1537
+ async function fetchAnthropicCatalog(overrides) {
1538
+ return fetchConfiguredCatalog("anthropic", overrides, async (params, apiKey)=>{
1539
+ const url = endpointUrl(params.base_url, "https://api.anthropic.com", "/v1/models");
1540
+ url.searchParams.set("limit", "1000");
1541
+ const models = [];
1542
+ let afterId;
1543
+ do {
1544
+ const pageUrl = new URL(url);
1545
+ if (afterId) pageUrl.searchParams.set("after_id", afterId);
1546
+ const page = await requestCatalogJson("Anthropic", pageUrl, {
1547
+ headers: {
1548
+ ...params.extra_headers,
1549
+ "x-api-key": apiKey,
1550
+ "anthropic-version": "2023-06-01"
1551
+ }
1552
+ });
1553
+ models.push(...page.data ?? []);
1554
+ if (page.has_more && !page.last_id) throw new Error("Anthropic catalog response is missing its next-page cursor");
1555
+ if (page.has_more && page.last_id === afterId) throw new Error("Anthropic catalog pagination did not advance");
1556
+ afterId = page.has_more ? page.last_id ?? undefined : undefined;
1557
+ }while (afterId);
1558
+ return models.map((model)=>{
1559
+ const known = (0,_lib_providers_capabilities__WEBPACK_IMPORTED_MODULE_2__/* .modelCapabilities */ ._8)("anthropic", model.id);
1560
+ const vision = model.capabilities?.image_input?.supported ?? known.vision;
1561
+ return {
1562
+ id: model.id,
1563
+ context_length: model.max_input_tokens ?? (0,_lib_providers_known_context_windows__WEBPACK_IMPORTED_MODULE_5__/* .getKnownContextLength */ .zJ)("anthropic", model.id),
1564
+ max_output_tokens: model.max_tokens ?? (0,_lib_providers_known_context_windows__WEBPACK_IMPORTED_MODULE_5__/* .getKnownMaxOutputTokens */ .pN)("anthropic", model.id),
1565
+ hosted_on: "anthropic",
1566
+ capabilities: {
1567
+ vision,
1568
+ tools: known.tools,
1569
+ streaming: known.streaming,
1570
+ json_mode: model.capabilities?.structured_outputs?.supported ?? known.json_mode,
1571
+ web_search: model.capabilities?.server_tools?.web_search?.supported ?? known.web_search,
1572
+ audio: known.audio,
1573
+ files: model.capabilities?.pdf_input?.supported ?? known.files
1574
+ }
1575
+ };
1576
+ });
1577
+ }, anthropicKnownModels);
1578
+ }
1579
+ async function fetchGeminiCatalog(overrides) {
1580
+ return fetchConfiguredCatalog("gemini", overrides, async (params, apiKey)=>{
1581
+ const url = endpointUrl(params.gemini_native_base_url, "https://generativelanguage.googleapis.com/v1beta", "/models");
1582
+ url.searchParams.set("pageSize", "1000");
1583
+ const models = [];
1584
+ let pageToken;
1585
+ do {
1586
+ const pageUrl = new URL(url);
1587
+ if (pageToken) pageUrl.searchParams.set("pageToken", pageToken);
1588
+ const page = await requestCatalogJson("Gemini", pageUrl, {
1589
+ headers: {
1590
+ "x-goog-api-key": apiKey
1591
+ }
1592
+ });
1593
+ models.push(...page.models ?? []);
1594
+ if (page.nextPageToken && page.nextPageToken === pageToken) {
1595
+ throw new Error("Gemini catalog pagination did not advance");
1596
+ }
1597
+ pageToken = page.nextPageToken;
1598
+ }while (pageToken);
1599
+ return models.map((model)=>{
1600
+ const id = model.name.replace(/^models\//, "");
1601
+ if (!id.startsWith("gemini-") || !model.supportedGenerationMethods?.includes("generateContent")) return null;
1602
+ return {
1603
+ id,
1604
+ context_length: model.inputTokenLimit ?? (0,_lib_providers_known_context_windows__WEBPACK_IMPORTED_MODULE_5__/* .getKnownContextLength */ .zJ)("gemini", id),
1605
+ max_output_tokens: model.outputTokenLimit ?? (0,_lib_providers_known_context_windows__WEBPACK_IMPORTED_MODULE_5__/* .getKnownMaxOutputTokens */ .pN)("gemini", id),
1606
+ hosted_on: "google",
1607
+ capabilities: (0,_lib_providers_capabilities__WEBPACK_IMPORTED_MODULE_2__/* .modelCapabilities */ ._8)("gemini", id)
1608
+ };
1609
+ }).filter((model)=>model !== null).sort((a, b)=>a.id.localeCompare(b.id));
1610
+ }, geminiKnownModels);
1611
+ }
1612
+ async function fetchDeepseekCatalog(overrides) {
1613
+ return fetchConfiguredCatalog("deepseek", overrides, async (params, apiKey)=>{
1614
+ const url = endpointUrl(params.base_url, "https://api.deepseek.com", "/models");
1615
+ const data = await requestCatalogJson("DeepSeek", url, {
1616
+ headers: {
1617
+ ...params.extra_headers,
1618
+ Authorization: "Bearer " + apiKey
1125
1619
  }
1126
- })).sort((a, b)=>a.id.localeCompare(b.id));
1127
- return chatModels;
1620
+ });
1621
+ return (data.data ?? []).map((model)=>{
1622
+ const known = (0,_lib_providers_capabilities__WEBPACK_IMPORTED_MODULE_2__/* .modelCapabilities */ ._8)("deepseek", model.id);
1623
+ const vision = model.input_modalities?.includes("image") ?? known.vision;
1624
+ return {
1625
+ id: model.id,
1626
+ context_length: model.context_window ?? (0,_lib_providers_known_context_windows__WEBPACK_IMPORTED_MODULE_5__/* .getKnownContextLength */ .zJ)("deepseek", model.id),
1627
+ max_output_tokens: model.max_output_tokens ?? (0,_lib_providers_known_context_windows__WEBPACK_IMPORTED_MODULE_5__/* .getKnownMaxOutputTokens */ .pN)("deepseek", model.id),
1628
+ hosted_on: "deepseek",
1629
+ capabilities: {
1630
+ ...known,
1631
+ vision,
1632
+ audio: model.input_modalities?.includes("audio") ?? known.audio
1633
+ }
1634
+ };
1635
+ });
1636
+ }, deepseekKnownModels);
1637
+ }
1638
+ function endpointUrl(baseUrl, defaultBaseUrl, path) {
1639
+ const base = typeof baseUrl === "string" && baseUrl.trim() ? baseUrl.trim() : defaultBaseUrl;
1640
+ let url;
1641
+ try {
1642
+ url = new URL(base);
1643
+ } catch {
1644
+ throw new Error("Provider base URL must be a valid absolute URL");
1645
+ }
1646
+ if (url.protocol !== "https:" && url.protocol !== "http:") {
1647
+ throw new Error("Provider base URL must use HTTP or HTTPS");
1648
+ }
1649
+ const normalizedPath = url.pathname.replace(/\/+$/, "");
1650
+ const suffix = path === "/v1/models" && normalizedPath.endsWith("/v1") ? "/models" : path;
1651
+ url.pathname = `${normalizedPath}${suffix}` || "/";
1652
+ url.search = "";
1653
+ url.hash = "";
1654
+ return url;
1128
1655
  }
1129
1656
  // ── GitHub Copilot ────────────────────────────────────────────────────────────
1130
1657
  async function fetchGitHubCopilotCatalog() {
@@ -1142,9 +1669,9 @@ async function fetchGitHubCopilotCatalog() {
1142
1669
  }
1143
1670
  // 2. Look up a saved github-copilot model config for an explicit session
1144
1671
  // token or a non-PAT credential that supports exchange.
1145
- const cfg = (0,_lib_stores_model_config__WEBPACK_IMPORTED_MODULE_2__/* .listModelConfigs */ .D1)().find((c)=>c.provider === "github-copilot");
1672
+ const cfg = (0,_lib_stores_model_config__WEBPACK_IMPORTED_MODULE_3__/* .listModelConfigs */ .D1)().find((c)=>c.provider === "github-copilot");
1146
1673
  if (cfg) {
1147
- const params = (0,_lib_stores_model_config__WEBPACK_IMPORTED_MODULE_2__/* .getModelParams */ .mN)(cfg);
1674
+ const params = (0,_lib_stores_model_config__WEBPACK_IMPORTED_MODULE_3__/* .getModelParams */ .mN)(cfg);
1148
1675
  const sessionTok = params.copilot_session_token?.trim();
1149
1676
  if (sessionTok) {
1150
1677
  try {
@@ -1179,14 +1706,14 @@ async function fetchCopilotChatCatalog(sessionToken) {
1179
1706
  }
1180
1707
  });
1181
1708
  if (!res.ok) {
1182
- const body = await (0,_lib_utils_error__WEBPACK_IMPORTED_MODULE_4__/* .readErrorBody */ .N)(res);
1709
+ const body = await (0,_lib_utils_error__WEBPACK_IMPORTED_MODULE_7__/* .readErrorBody */ .N)(res);
1183
1710
  throw new Error(`GitHub Copilot catalog error: ${res.status} ${body}`);
1184
1711
  }
1185
1712
  const data = await res.json();
1186
1713
  return data.data.map((m)=>({
1187
1714
  id: m.id,
1188
- context_length: (0,_lib_providers_known_context_windows__WEBPACK_IMPORTED_MODULE_3__/* .getKnownContextLength */ .zJ)("github-copilot", m.id),
1189
- max_output_tokens: (0,_lib_providers_known_context_windows__WEBPACK_IMPORTED_MODULE_3__/* .getKnownMaxOutputTokens */ .pN)("github-copilot", m.id),
1715
+ context_length: (0,_lib_providers_known_context_windows__WEBPACK_IMPORTED_MODULE_5__/* .getKnownContextLength */ .zJ)("github-copilot", m.id),
1716
+ max_output_tokens: (0,_lib_providers_known_context_windows__WEBPACK_IMPORTED_MODULE_5__/* .getKnownMaxOutputTokens */ .pN)("github-copilot", m.id),
1190
1717
  hosted_on: "github",
1191
1718
  capabilities: {
1192
1719
  vision: m.capabilities?.supports?.vision ?? false,
@@ -1210,7 +1737,7 @@ async function exchangeCopilotSessionToken(githubToken) {
1210
1737
  }
1211
1738
  });
1212
1739
  if (!res.ok) {
1213
- const body = await (0,_lib_utils_error__WEBPACK_IMPORTED_MODULE_4__/* .readErrorBody */ .N)(res);
1740
+ const body = await (0,_lib_utils_error__WEBPACK_IMPORTED_MODULE_7__/* .readErrorBody */ .N)(res);
1214
1741
  throw new Error(`GitHub Copilot token exchange failed: ${res.status} ${body}`);
1215
1742
  }
1216
1743
  const json = await res.json();
@@ -1223,8 +1750,8 @@ function githubCopilotKnownModels() {
1223
1750
  // stored, exchange failed, etc.). Keep in sync with Copilot's current line-up.
1224
1751
  const v = (id, vision = false, tools = true)=>({
1225
1752
  id,
1226
- context_length: (0,_lib_providers_known_context_windows__WEBPACK_IMPORTED_MODULE_3__/* .getKnownContextLength */ .zJ)("github-copilot", id),
1227
- max_output_tokens: (0,_lib_providers_known_context_windows__WEBPACK_IMPORTED_MODULE_3__/* .getKnownMaxOutputTokens */ .pN)("github-copilot", id),
1753
+ context_length: (0,_lib_providers_known_context_windows__WEBPACK_IMPORTED_MODULE_5__/* .getKnownContextLength */ .zJ)("github-copilot", id),
1754
+ max_output_tokens: (0,_lib_providers_known_context_windows__WEBPACK_IMPORTED_MODULE_5__/* .getKnownMaxOutputTokens */ .pN)("github-copilot", id),
1228
1755
  hosted_on: "github",
1229
1756
  capabilities: {
1230
1757
  vision,