thursday-agent 0.2.0 → 0.3.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 (535) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-path-routes-manifest.json +5 -2
  3. package/.next/build-manifest.json +3 -3
  4. package/.next/prerender-manifest.json +5 -5
  5. package/.next/routes-manifest.json +24 -6
  6. package/.next/server/app/_global-error/page.js +2 -2
  7. package/.next/server/app/_global-error/page.js.nft.json +1 -1
  8. package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  9. package/.next/server/app/_global-error.html +1 -1
  10. package/.next/server/app/_global-error.rsc +2 -2
  11. package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  12. package/.next/server/app/_global-error.segments/_full.segment.rsc +2 -2
  13. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  14. package/.next/server/app/_not-found/page.js +2 -2
  15. package/.next/server/app/_not-found/page.js.nft.json +1 -1
  16. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  17. package/.next/server/app/_not-found.html +1 -1
  18. package/.next/server/app/_not-found.rsc +14 -14
  19. package/.next/server/app/_not-found.segments/_full.segment.rsc +14 -14
  20. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +12 -12
  21. package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  22. package/.next/server/app/api/artifact/route.js +3 -3
  23. package/.next/server/app/api/artifact/route.js.nft.json +1 -1
  24. package/.next/server/app/api/bot/memory/files/route/app-paths-manifest.json +3 -0
  25. package/.next/server/app/api/bot/memory/files/route.js +10 -0
  26. package/.next/server/app/api/bot/memory/files/route.js.nft.json +1 -0
  27. package/.next/server/app/api/bot/memory/files/route_client-reference-manifest.js +3 -0
  28. package/.next/server/app/api/bot/memory/route/app-paths-manifest.json +3 -0
  29. package/.next/server/app/api/bot/memory/route.js +14 -0
  30. package/.next/server/app/api/bot/{notes → memory}/route.js.nft.json +1 -1
  31. package/.next/server/app/api/bot/memory/route_client-reference-manifest.js +3 -0
  32. package/.next/server/app/api/bot/route.js +6 -6
  33. package/.next/server/app/api/bot/route.js.nft.json +1 -1
  34. package/.next/server/app/api/bot/task/[id]/route.js +8 -8
  35. package/.next/server/app/api/bot/task/[id]/route.js.nft.json +1 -1
  36. package/.next/server/app/api/bot/task/route.js +8 -8
  37. package/.next/server/app/api/bot/task/route.js.nft.json +1 -1
  38. package/.next/server/app/api/config/route.js +5 -5
  39. package/.next/server/app/api/config/route.js.nft.json +1 -1
  40. package/.next/server/app/api/events/route.js +4 -5
  41. package/.next/server/app/api/events/route.js.nft.json +1 -1
  42. package/.next/server/app/api/file/[...path]/route.js +3 -3
  43. package/.next/server/app/api/file/[...path]/route.js.nft.json +1 -1
  44. package/.next/server/app/api/llm-model/catalog/route.js +9 -8
  45. package/.next/server/app/api/llm-model/catalog/route.js.nft.json +1 -1
  46. package/.next/server/app/api/llm-model/credits/route/app-paths-manifest.json +3 -0
  47. package/.next/server/app/api/llm-model/credits/route/build-manifest.json +12 -0
  48. package/.next/server/app/api/llm-model/credits/route/server-reference-manifest.json +4 -0
  49. package/.next/server/app/api/llm-model/credits/route.js +16 -0
  50. package/.next/server/app/api/llm-model/credits/route.js.map +5 -0
  51. package/.next/server/app/api/llm-model/credits/route.js.nft.json +1 -0
  52. package/.next/server/app/api/llm-model/credits/route_client-reference-manifest.js +3 -0
  53. package/.next/server/app/api/llm-model/route.js +10 -8
  54. package/.next/server/app/api/llm-model/route.js.nft.json +1 -1
  55. package/.next/server/app/api/llm-model/subscription/route/app-paths-manifest.json +3 -0
  56. package/.next/server/app/api/llm-model/subscription/route/build-manifest.json +12 -0
  57. package/.next/server/app/api/llm-model/subscription/route/server-reference-manifest.json +4 -0
  58. package/.next/server/app/api/llm-model/subscription/route.js +15 -0
  59. package/.next/server/app/api/llm-model/subscription/route.js.map +5 -0
  60. package/.next/server/app/api/llm-model/subscription/route.js.nft.json +1 -0
  61. package/.next/server/app/api/llm-model/subscription/route_client-reference-manifest.js +3 -0
  62. package/.next/server/app/api/mcp/[name]/route.js +4 -4
  63. package/.next/server/app/api/mcp/[name]/route.js.nft.json +1 -1
  64. package/.next/server/app/api/mcp/oauth/callback/route.js +5 -5
  65. package/.next/server/app/api/mcp/oauth/callback/route.js.nft.json +1 -1
  66. package/.next/server/app/api/mcp/route.js +4 -4
  67. package/.next/server/app/api/mcp/route.js.nft.json +1 -1
  68. package/.next/server/app/api/mcp/tools/route.js +4 -4
  69. package/.next/server/app/api/mcp/tools/route.js.nft.json +1 -1
  70. package/.next/server/app/api/memory/edit/route/app-paths-manifest.json +3 -0
  71. package/.next/server/app/api/memory/edit/route/build-manifest.json +12 -0
  72. package/.next/server/app/api/memory/edit/route/server-reference-manifest.json +4 -0
  73. package/.next/server/app/api/memory/edit/route.js +24 -0
  74. package/.next/server/app/api/memory/edit/route.js.map +5 -0
  75. package/.next/server/app/api/memory/edit/route.js.nft.json +1 -0
  76. package/.next/server/app/api/memory/{tidy → edit}/route_client-reference-manifest.js +1 -1
  77. package/.next/server/app/api/memory/route.js +6 -7
  78. package/.next/server/app/api/memory/route.js.nft.json +1 -1
  79. package/.next/server/app/api/skills/[source]/[name]/route.js +3 -3
  80. package/.next/server/app/api/skills/[source]/[name]/route.js.nft.json +1 -1
  81. package/.next/server/app/api/skills/route.js +3 -3
  82. package/.next/server/app/api/skills/route.js.nft.json +1 -1
  83. package/.next/server/app/api/thursday/call/route.js +9 -7
  84. package/.next/server/app/api/thursday/call/route.js.nft.json +1 -1
  85. package/.next/server/app/api/thursday/skills/route.js +9 -7
  86. package/.next/server/app/api/thursday/skills/route.js.nft.json +1 -1
  87. package/.next/server/app/api/thursday/tool-call/route.js +17 -15
  88. package/.next/server/app/api/thursday/tool-call/route.js.nft.json +1 -1
  89. package/.next/server/app/api/workspace/route.js +4 -5
  90. package/.next/server/app/api/workspace/route.js.nft.json +1 -1
  91. package/.next/server/app/artifact/[...path]/page/server-reference-manifest.json +1 -1
  92. package/.next/server/app/artifact/[...path]/page.js +5 -6
  93. package/.next/server/app/artifact/[...path]/page.js.nft.json +1 -1
  94. package/.next/server/app/artifact/[...path]/page_client-reference-manifest.js +1 -1
  95. package/.next/server/app/favicon.ico/route.js +3 -4
  96. package/.next/server/app/favicon.ico/route.js.nft.json +1 -1
  97. package/.next/server/app/favicon.ico.body +0 -0
  98. package/.next/server/app/page/server-reference-manifest.json +57 -90
  99. package/.next/server/app/page.js +10 -10
  100. package/.next/server/app/page.js.nft.json +1 -1
  101. package/.next/server/app/page_client-reference-manifest.js +1 -1
  102. package/.next/server/app-paths-manifest.json +5 -2
  103. package/.next/server/chunks/[externals]__0dzuk6_._.js +3 -0
  104. package/.next/server/chunks/[root-of-the-server]__01dkp4a._.js +3 -0
  105. package/.next/server/chunks/[root-of-the-server]__02va5wz._.js +1 -1
  106. package/.next/server/chunks/[root-of-the-server]__02xjoto._.js +3 -0
  107. package/.next/server/chunks/[root-of-the-server]__04q--0f._.js +8 -0
  108. package/.next/server/chunks/[root-of-the-server]__0bl-e63._.js +3 -0
  109. package/.next/server/chunks/[root-of-the-server]__0ce8nf8._.js +5 -0
  110. package/.next/server/chunks/[root-of-the-server]__0ffbg85._.js +3 -0
  111. package/.next/server/chunks/[root-of-the-server]__0j7z0r3._.js +12 -0
  112. package/.next/server/chunks/[root-of-the-server]__0jq4ohy._.js +8 -0
  113. package/.next/server/chunks/[root-of-the-server]__0ls6_8y._.js +8 -0
  114. package/.next/server/chunks/[root-of-the-server]__0ncs9uu._.js +3 -0
  115. package/.next/server/chunks/[root-of-the-server]__0pa2n68._.js +3 -0
  116. package/.next/server/chunks/[root-of-the-server]__0q0vvt2._.js +5 -0
  117. package/.next/server/chunks/[root-of-the-server]__1-ga0kh._.js +5 -0
  118. package/.next/server/chunks/[root-of-the-server]__11n256_._.js +5 -0
  119. package/.next/server/chunks/[root-of-the-server]__12cabg9._.js +3 -0
  120. package/.next/server/chunks/[root-of-the-server]__1339jnv._.js +8 -0
  121. package/.next/server/chunks/[root-of-the-server]__15bjnu5._.js +5 -0
  122. package/.next/server/chunks/[root-of-the-server]__18_teo8._.js +8 -0
  123. package/.next/server/chunks/[root-of-the-server]__1_04mcf._.js +5 -0
  124. package/.next/server/chunks/[root-of-the-server]__1anc1p9._.js +3 -0
  125. package/.next/server/chunks/[root-of-the-server]__1ccon1w._.js +5 -5
  126. package/.next/server/chunks/[root-of-the-server]__1fizn31._.js +3 -0
  127. package/.next/server/chunks/[root-of-the-server]__1llj3-b._.js +3 -0
  128. package/.next/server/chunks/[root-of-the-server]__1orn-5b._.js +11 -0
  129. package/.next/server/chunks/[root-of-the-server]__1p8m3f4._.js +3 -0
  130. package/.next/server/chunks/[root-of-the-server]__1wa1k7r._.js +8 -0
  131. package/.next/server/chunks/_0-73of8._.js +5 -5
  132. package/.next/server/chunks/_0-fjql4._.js +26 -0
  133. package/.next/server/chunks/_00xh_q0._.js +27 -0
  134. package/.next/server/chunks/{_0pppbb5._.js → _03kp0jp._.js} +163 -36
  135. package/.next/server/chunks/_051qh8u._.js +3 -0
  136. package/.next/server/chunks/{node_modules_next_04q-o58._.js → _05dla15._.js} +2 -2
  137. package/.next/server/chunks/_05h2cii._.js +1 -1
  138. package/.next/server/chunks/_0c9j6rb._.js +49 -0
  139. package/.next/server/chunks/_0fzqt2y._.js +130 -0
  140. package/.next/server/chunks/{_0vnutv9._.js → _0ioz3nd._.js} +1 -1
  141. package/.next/server/chunks/_0iwfby5._.js +3 -0
  142. package/.next/server/chunks/_0mecv0f._.js +26 -0
  143. package/.next/server/chunks/_0mh8j4m._.js +3 -0
  144. package/.next/server/chunks/_0n74zsf._.js +4 -4
  145. package/.next/server/chunks/_0obojvv._.js +3 -0
  146. package/.next/server/chunks/_0recufk._.js +49 -0
  147. package/.next/server/chunks/_0rnf-6n._.js +4 -4
  148. package/.next/server/chunks/_0sb7tlz._.js +3 -0
  149. package/.next/server/chunks/_0u10wmw._.js +5 -5
  150. package/.next/server/chunks/_0u4aiy2._.js +3 -0
  151. package/.next/server/chunks/_0wp4le3._.js +1 -1
  152. package/.next/server/chunks/_0y5fg-x._.js +1 -1
  153. package/.next/server/chunks/_1230wbx._.js +10 -0
  154. package/.next/server/chunks/_12nheja._.js +3 -0
  155. package/.next/server/chunks/_13510xh._.js +3 -0
  156. package/.next/server/chunks/_15hq89o._.js +1 -1
  157. package/.next/server/chunks/_17l5ygt._.js +49 -0
  158. package/.next/server/chunks/_18-1wcc._.js +5 -5
  159. package/.next/server/chunks/_1_5mnq4._.js +4 -4
  160. package/.next/server/chunks/_1_9mjx-._.js +3 -0
  161. package/.next/server/chunks/_1d0j961._.js +6 -0
  162. package/.next/server/chunks/_1d5zmy8._.js +1 -1
  163. package/.next/server/chunks/_1drgfx4._.js +4 -4
  164. package/.next/server/chunks/_1f46eie._.js +3 -0
  165. package/.next/server/chunks/_1h5_8sk._.js +3 -0
  166. package/.next/server/chunks/_1hdnxb7._.js +3 -0
  167. package/.next/server/chunks/_1j8k_j5._.js +3 -0
  168. package/.next/server/chunks/_1krd9rf._.js +3 -0
  169. package/.next/server/chunks/_1nc0eui._.js +11 -0
  170. package/.next/server/chunks/_1nula3v._.js +3 -0
  171. package/.next/server/chunks/_1pf4qe-._.js +3 -0
  172. package/.next/server/chunks/_1php4eq._.js +1 -1
  173. package/.next/server/chunks/_1qxheoa._.js +3 -0
  174. package/.next/server/chunks/_1x6kd1r._.js +3 -0
  175. package/.next/server/chunks/_1yuv4vp._.js +1 -1
  176. package/.next/server/chunks/_1zjrdag._.js +3 -0
  177. package/.next/server/chunks/_next-internal_server_app_api_bot_memory_files_route_actions_1_xd_8f.js +3 -0
  178. package/.next/server/chunks/_next-internal_server_app_api_bot_memory_route_actions_1a8xfr7.js +3 -0
  179. package/.next/server/chunks/_next-internal_server_app_api_llm-model_credits_route_actions_0v424pb.js +3 -0
  180. package/.next/server/chunks/_next-internal_server_app_api_llm-model_subscription_route_actions_0-udcm5.js +3 -0
  181. package/.next/server/chunks/_next-internal_server_app_api_memory_edit_route_actions_02sfnmr.js +3 -0
  182. package/.next/server/chunks/config_ts_1g4sz5o._.js +1 -1
  183. package/.next/server/chunks/features_0rpfxbk._.js +3 -0
  184. package/.next/server/chunks/features_1qf3cei._.js +3 -0
  185. package/.next/server/chunks/features_bot_0zt92oh._.js +3 -0
  186. package/.next/server/chunks/features_bot_bot_query_ts_12mgkl2._.js +3 -0
  187. package/.next/server/chunks/features_memory_1uqvksn._.js +6 -0
  188. package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_0a1rd09._.js → node_modules_consola_dist_chunks_prompt_mjs_0i7cvml._.js} +1 -1
  189. package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_06067w6._.js → node_modules_consola_dist_chunks_prompt_mjs_0icqaqw._.js} +1 -1
  190. package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_096ais_._.js → node_modules_consola_dist_chunks_prompt_mjs_0r28-sm._.js} +1 -1
  191. package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_02s3hjt._.js → node_modules_consola_dist_chunks_prompt_mjs_0v_7drq._.js} +1 -1
  192. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1xoq2rl._.js +3 -0
  193. package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_0tvkfgh._.js → node_modules_consola_dist_chunks_prompt_mjs_1y49572._.js} +1 -1
  194. package/.next/server/chunks/ssr/[root-of-the-server]__09q9med._.js +1 -1
  195. package/.next/server/chunks/ssr/{[root-of-the-server]__1qfqvmg._.js → [root-of-the-server]__0_69wqr._.js} +2 -2
  196. package/.next/server/chunks/ssr/[root-of-the-server]__0hg5gib._.js +1 -1
  197. package/.next/server/chunks/ssr/[root-of-the-server]__0i8ie7f._.js +3 -0
  198. package/.next/server/chunks/ssr/{[root-of-the-server]__0jsmmb-._.js → [root-of-the-server]__0mz33a7._.js} +1 -1
  199. package/.next/server/chunks/ssr/[root-of-the-server]__0tbkdlx._.js +3 -0
  200. package/.next/server/chunks/ssr/[root-of-the-server]__0vnmv-s._.js +3 -0
  201. package/.next/server/chunks/ssr/{[root-of-the-server]__0f6s48x._.js → [root-of-the-server]__0xpcv9w._.js} +3 -3
  202. package/.next/server/chunks/ssr/[root-of-the-server]__0xtssj3._.js +1 -1
  203. package/.next/server/chunks/ssr/[root-of-the-server]__0zkv7z_._.js +3 -0
  204. package/.next/server/chunks/ssr/[root-of-the-server]__10-dz5o._.js +57 -0
  205. package/.next/server/chunks/ssr/[root-of-the-server]__15_uhip._.js +3 -0
  206. package/.next/server/chunks/ssr/[root-of-the-server]__16jc196._.js +1 -1
  207. package/.next/server/chunks/ssr/{[root-of-the-server]__0m1b5ky._.js → [root-of-the-server]__1cyjywu._.js} +1 -1
  208. package/.next/server/chunks/ssr/[root-of-the-server]__1eh7hid._.js +3 -0
  209. package/.next/server/chunks/ssr/[root-of-the-server]__1gtlw6v._.js +43 -0
  210. package/.next/server/chunks/ssr/[root-of-the-server]__1mzi-ju._.js +1 -1
  211. package/.next/server/chunks/ssr/[root-of-the-server]__1ox7hbk._.js +4 -0
  212. package/.next/server/chunks/ssr/[root-of-the-server]__1pduf5n._.js +3 -0
  213. package/.next/server/chunks/ssr/{_1mznrxk._.js → _001_ms1._.js} +3 -3
  214. package/.next/server/chunks/ssr/_01_6m32._.js +3 -0
  215. package/.next/server/chunks/ssr/_01n3o0m._.js +3 -0
  216. package/.next/server/chunks/ssr/_07uchnc._.js +3 -0
  217. package/.next/server/chunks/ssr/_0ap2fzn._.js +3 -0
  218. package/.next/server/chunks/ssr/_0c-ql2m._.js +3 -0
  219. package/.next/server/chunks/ssr/_0h42fze._.js +3 -0
  220. package/.next/server/chunks/ssr/_0h7zdni._.js +1 -1
  221. package/.next/server/chunks/ssr/_0i_6q1w._.js +41 -0
  222. package/.next/server/chunks/ssr/_0kbkmar._.js +3 -0
  223. package/.next/server/chunks/ssr/{_077-g6s._.js → _0mb8zc8._.js} +3 -3
  224. package/.next/server/chunks/ssr/_0mo2w06._.js +3 -0
  225. package/.next/server/chunks/ssr/{_13punpm._.js → _0q0zan6._.js} +2 -2
  226. package/.next/server/chunks/ssr/{_040sk32._.js → _0u2jv_x._.js} +76 -82
  227. package/.next/server/chunks/ssr/_0y0tiht._.js +4 -0
  228. package/.next/server/chunks/ssr/_0zhoc3r._.js +3 -0
  229. package/.next/server/chunks/ssr/_1-teee5._.js +3 -3
  230. package/.next/server/chunks/ssr/_13fke0x._.js +3 -0
  231. package/.next/server/chunks/ssr/{_1lip4th._.js → _13z3f85._.js} +2 -2
  232. package/.next/server/chunks/ssr/_14_lw10._.js +3 -0
  233. package/.next/server/chunks/ssr/_15j2_8f._.js +3 -0
  234. package/.next/server/chunks/ssr/{_09ja_w1._.js → _1eoqg_g._.js} +2 -2
  235. package/.next/server/chunks/ssr/_1sji22n._.js +3 -0
  236. package/.next/server/chunks/ssr/_1spzm8z._.js +3 -0
  237. package/.next/server/chunks/ssr/{_0x_nu5e._.js → _1vi_uo7._.js} +2 -2
  238. package/.next/server/chunks/ssr/_1vyd1ji._.js +1 -1
  239. package/.next/server/chunks/ssr/{_1m3bsfr._.js → _1xvgn77._.js} +2 -2
  240. package/.next/server/chunks/ssr/_20kd_n0._.js +42 -0
  241. package/.next/server/chunks/ssr/features_bot_1s_-2vj._.js +3 -0
  242. package/.next/server/chunks/ssr/features_config_components_config-setting_tsx_0xfwqdg._.js +1 -1
  243. package/.next/server/chunks/ssr/features_connectors_components_mcp-setting_tsx_0jmbgvp._.js +1 -1
  244. package/.next/server/chunks/ssr/lib_date-like_ts_02is0pw._.js +3 -0
  245. package/.next/server/chunks/ssr/{node_modules_18_dk7_._.js → node_modules_063xwpp._.js} +1 -1
  246. package/.next/server/chunks/ssr/{node_modules_01qnv-a._.js → node_modules_0bvraul._.js} +1 -1
  247. package/.next/server/chunks/ssr/{node_modules_0n1kj4p._.js → node_modules_0eu1va6._.js} +1 -1
  248. package/.next/server/chunks/ssr/{node_modules_0kl7-tn._.js → node_modules_0h50b8n._.js} +1 -1
  249. package/.next/server/chunks/ssr/{node_modules_0_n241r._.js → node_modules_0h5hnr1._.js} +1 -1
  250. package/.next/server/chunks/ssr/{node_modules_0lrjk5t._.js → node_modules_0h7u60n._.js} +1 -1
  251. package/.next/server/chunks/ssr/{node_modules_0ndvxub._.js → node_modules_0lm7_vm._.js} +1 -1
  252. package/.next/server/chunks/ssr/{node_modules_13r44jq._.js → node_modules_0mwym0g._.js} +1 -1
  253. package/.next/server/chunks/ssr/{node_modules_17lrt3y._.js → node_modules_0rjg6t1._.js} +1 -1
  254. package/.next/server/chunks/ssr/node_modules_0x3-ply._.js +3 -0
  255. package/.next/server/chunks/ssr/{node_modules_004qlr4._.js → node_modules_0y_cded._.js} +1 -1
  256. package/.next/server/chunks/ssr/{node_modules_0kxz4gt._.js → node_modules_0z5tsu8._.js} +1 -1
  257. package/.next/server/chunks/ssr/{node_modules_0iz1rzd._.js → node_modules_0zp9r92._.js} +1 -1
  258. package/.next/server/chunks/ssr/{node_modules_19dp7ko._.js → node_modules_1-hc6uv._.js} +1 -1
  259. package/.next/server/chunks/ssr/{node_modules_1q0p85z._.js → node_modules_113tz0l._.js} +1 -1
  260. package/.next/server/chunks/ssr/{node_modules_1toafc-._.js → node_modules_124bue5._.js} +1 -1
  261. package/.next/server/chunks/ssr/node_modules_17bwo43._.js +55 -0
  262. package/.next/server/chunks/ssr/{node_modules_08d8bke._.js → node_modules_1_n3ztw._.js} +1 -1
  263. package/.next/server/chunks/ssr/{node_modules_1dwguw_._.js → node_modules_1bc7gu8._.js} +1 -1
  264. package/.next/server/chunks/ssr/{node_modules_20yebtj._.js → node_modules_1bgb6-f._.js} +1 -1
  265. package/.next/server/chunks/ssr/{node_modules_1n5ygqe._.js → node_modules_1h4a4pp._.js} +1 -1
  266. package/.next/server/chunks/ssr/{node_modules_04n7mjs._.js → node_modules_1i7u1ia._.js} +1 -1
  267. package/.next/server/chunks/ssr/{node_modules_1hn8z1f._.js → node_modules_1juq3hs._.js} +1 -1
  268. package/.next/server/chunks/ssr/{node_modules_1xyd7ov._.js → node_modules_1l0qtdu._.js} +1 -1
  269. package/.next/server/chunks/ssr/{node_modules_0m93zeg._.js → node_modules_1t9cyee._.js} +1 -1
  270. package/.next/server/chunks/ssr/{node_modules_09xhur7._.js → node_modules_1uuj9x1._.js} +1 -1
  271. package/.next/server/chunks/ssr/{node_modules_1hd-5tv._.js → node_modules_1vqb6po._.js} +1 -1
  272. package/.next/server/chunks/ssr/{node_modules_1zu988w._.js → node_modules_1xx28h1._.js} +1 -1
  273. package/.next/server/chunks/ssr/{node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_0m9a4y0._.js → node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_0d3skpl._.js} +1 -1
  274. package/.next/server/chunks/ssr/{node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_13w_wy9._.js → node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_0i44kk5._.js} +1 -1
  275. package/.next/server/chunks/ssr/node_modules_@vercel_oidc_dist_0qe30a_._.js +3 -0
  276. package/.next/server/chunks/ssr/{node_modules_next_dist_0w6mzq5._.js → node_modules_next_dist_0drixxt._.js} +4 -4
  277. package/.next/server/chunks/ssr/node_modules_next_dist_1n3w9lb._.js +2 -2
  278. package/.next/server/instrumentation.js +1 -1
  279. package/.next/server/middleware-build-manifest.js +3 -3
  280. package/.next/server/pages/404.html +1 -1
  281. package/.next/server/pages/500.html +1 -1
  282. package/.next/server/server-reference-manifest.js +1 -1
  283. package/.next/server/server-reference-manifest.json +58 -91
  284. package/.next/static/chunks/{31ttnjt6g35a0.js → 0ev4hyghq0mbb.js} +1 -1
  285. package/.next/static/chunks/0r5qcctujhxli.js +1 -0
  286. package/.next/static/chunks/0tmgrnlje14-s.js +3 -0
  287. package/.next/static/chunks/0x79tx04dxbpp.js +1 -0
  288. package/.next/static/chunks/0xzgvc0fkdb6t.js +1 -0
  289. package/.next/static/chunks/10teww7wt-f6h.js +1 -0
  290. package/.next/static/chunks/14hgtsjg-kael.css +1 -0
  291. package/.next/static/chunks/17donp69y4do7.js +40 -0
  292. package/.next/static/chunks/{3_h9txt3tq8t8.js → 1dkjg87pxk0n9.js} +1 -1
  293. package/.next/static/chunks/1ekc7ul556kbl.js +1 -0
  294. package/.next/static/chunks/{3ard_noqapnw1.js → 1grhjo7a5a0_-.js} +1 -1
  295. package/.next/static/chunks/1kq8h8wi_e0bc.js +53 -0
  296. package/.next/static/chunks/1okqiww3pnwka.js +1 -0
  297. package/.next/static/chunks/26-pr2c9ro222.js +1 -0
  298. package/.next/static/chunks/{18vhba44l1fc9.js → 280t0_e99i276.js} +1 -1
  299. package/.next/static/chunks/28cizcdaabd4h.js +1 -0
  300. package/.next/static/chunks/2a0k6jlq0_v1u.js +2 -0
  301. package/.next/static/chunks/2fzs9fm8yarvq.js +1 -0
  302. package/.next/static/chunks/2h0sd2vumhb15.js +1 -0
  303. package/.next/static/chunks/2hw2f6zmt7fmt.js +1 -0
  304. package/.next/static/chunks/2t4vhi3m8ahya.js +1 -0
  305. package/.next/static/chunks/2tigdtz3dpcy8.js +1 -0
  306. package/.next/static/chunks/3111pj5wnjgos.js +1 -0
  307. package/.next/static/chunks/{07kl352c-lvcz.js → 3agpgkwaa321p.js} +1 -1
  308. package/.next/static/chunks/3cfi_q6d_wtci.js +1 -0
  309. package/.next/static/chunks/3ok9_x74rip3v.js +1 -0
  310. package/.next/static/chunks/3xk7yqgomx7yq.js +1 -0
  311. package/.next/static/chunks/3xpbkl66ssib5.js +38 -0
  312. package/.next/static/media/favicon.37o1pjldwi2uc.ico +0 -0
  313. package/README.md +6 -4
  314. package/app/api/bot/memory/files/route.ts +14 -0
  315. package/app/api/bot/memory/route.ts +5 -0
  316. package/app/api/events/app-event.ts +3 -5
  317. package/app/api/llm-model/credits/route.ts +11 -0
  318. package/app/api/llm-model/route.ts +6 -1
  319. package/app/api/llm-model/subscription/route.ts +11 -0
  320. package/app/api/memory/edit/route.ts +7 -0
  321. package/app/api/memory/route.ts +21 -0
  322. package/app/api/query-key.ts +19 -4
  323. package/bin/thursday.mjs +3 -0
  324. package/components/ui/shiny-text.tsx +48 -134
  325. package/database/migrations/{20260909060813_optimal_sabretooth → 20260910173049_numerous_spirit}/migration.sql +24 -34
  326. package/database/migrations/{20260909060813_optimal_sabretooth → 20260910173049_numerous_spirit}/snapshot.json +71 -145
  327. package/database/migrations/20260911030320_opposite_jack_power/migration.sql +1 -0
  328. package/database/migrations/{20260909063821_bitter_tenebrous → 20260911030320_opposite_jack_power}/snapshot.json +57 -184
  329. package/features/ai/chatgpt.ts +617 -0
  330. package/features/ai/components/chatgpt-sign-in.tsx +66 -0
  331. package/features/ai/components/model-picker.tsx +17 -1
  332. package/features/ai/components/provider-icon.tsx +1 -0
  333. package/features/ai/load-tools.ts +58 -42
  334. package/features/ai/model.schema.ts +232 -34
  335. package/features/ai/model.ts +169 -24
  336. package/features/ai/prompts/bot.prompt.ts +156 -65
  337. package/features/ai/prompts/memory-edit.prompt.ts +33 -0
  338. package/features/ai/prompts/prompt-helper.ts +45 -26
  339. package/features/ai/prompts/thursday.prompt.ts +40 -17
  340. package/features/ai/tools/bot.tool.ts +35 -52
  341. package/features/ai/tools/connected.ts +17 -4
  342. package/features/ai/tools/memory.tool.ts +133 -72
  343. package/features/ai/tools/search.tool.ts +136 -47
  344. package/features/ai/tools/tool-name.ts +2 -5
  345. package/features/ai/tools/workspace.tool.ts +2 -1
  346. package/features/bot/bot.action.ts +8 -18
  347. package/features/bot/bot.memory.ts +89 -0
  348. package/features/bot/bot.query.ts +37 -57
  349. package/features/bot/bot.run.ts +507 -241
  350. package/features/bot/bot.runner.ts +410 -114
  351. package/features/bot/bot.schema.ts +79 -19
  352. package/features/bot/bot.seed.ts +89 -16
  353. package/features/bot/components/bot-mark.tsx +122 -20
  354. package/features/bot/components/bot-room.tsx +159 -130
  355. package/features/bot/components/bot-setting.tsx +790 -402
  356. package/features/bot/components/bot-tool.tsx +2 -6
  357. package/features/bot/components/mark-palette.tsx +54 -0
  358. package/features/bot/components/path-chips.tsx +1 -1
  359. package/features/bot/components/task-badge.tsx +26 -6
  360. package/features/bot/components/task-reply.tsx +22 -33
  361. package/features/bot/components/task-setting.tsx +20 -17
  362. package/features/bot/task.query.ts +215 -28
  363. package/features/bot/task.store.ts +53 -9
  364. package/features/config/components/config-setting.tsx +265 -34
  365. package/features/config/components/models-badge.tsx +42 -0
  366. package/features/config/config.action.ts +12 -0
  367. package/features/config/config.const.ts +38 -2
  368. package/features/connectors/mcp.manager.ts +10 -2
  369. package/features/intro/components/intro.tsx +47 -46
  370. package/features/memory/components/memory-edit.tsx +338 -0
  371. package/features/memory/components/memory-setting.tsx +75 -77
  372. package/features/memory/memory.action.ts +3 -43
  373. package/features/memory/memory.edit.ts +87 -0
  374. package/features/memory/memory.query.ts +24 -42
  375. package/features/memory/memory.schema.ts +29 -106
  376. package/features/settings/components/settings.tsx +2 -0
  377. package/features/settings/settings.alert.ts +3 -1
  378. package/features/thursday/components/ascii-orb.tsx +106 -90
  379. package/features/thursday/components/boot.tsx +7 -0
  380. package/features/thursday/components/call-log.tsx +219 -92
  381. package/features/thursday/components/face.tsx +6 -4
  382. package/features/thursday/components/tab-state.tsx +97 -0
  383. package/features/thursday/components/thursday-mark.tsx +4 -1
  384. package/features/thursday/components/thursday-setting.tsx +17 -47
  385. package/features/thursday/components/thursday.tsx +208 -95
  386. package/features/thursday/thursday.action.ts +12 -17
  387. package/features/thursday/thursday.query.ts +61 -70
  388. package/features/thursday/thursday.schema.ts +20 -7
  389. package/features/thursday/tool-line.ts +85 -11
  390. package/features/thursday/use-thursday.ts +86 -59
  391. package/features/workspace/components/file-view.tsx +4 -2
  392. package/features/workspace/workspace.ts +110 -26
  393. package/lib/limits.ts +1 -1
  394. package/lib/oauth-page.ts +27 -0
  395. package/lib/realtime/openai.ts +2 -2
  396. package/lib/realtime/realtime.protocol.ts +1 -1
  397. package/lib/realtime/realtime.tap.ts +122 -0
  398. package/lib/sandbox.ts +59 -36
  399. package/package.json +1 -1
  400. package/skills/browser/SKILL.md +55 -34
  401. package/.next/server/app/api/bot/notes/route/app-paths-manifest.json +0 -3
  402. package/.next/server/app/api/bot/notes/route.js +0 -14
  403. package/.next/server/app/api/bot/notes/route_client-reference-manifest.js +0 -3
  404. package/.next/server/app/api/memory/tidy/route/app-paths-manifest.json +0 -3
  405. package/.next/server/app/api/memory/tidy/route.js +0 -22
  406. package/.next/server/app/api/memory/tidy/route.js.nft.json +0 -1
  407. package/.next/server/chunks/0d-b_next_dist_server_app-render_after-task-async-storage_external_0-exn7p.js +0 -3
  408. package/.next/server/chunks/[root-of-the-server]__0-npkh_._.js +0 -3
  409. package/.next/server/chunks/[root-of-the-server]__005var5._.js +0 -3
  410. package/.next/server/chunks/[root-of-the-server]__019dx9f._.js +0 -5
  411. package/.next/server/chunks/[root-of-the-server]__02_2sm-._.js +0 -5
  412. package/.next/server/chunks/[root-of-the-server]__04_8spk._.js +0 -3
  413. package/.next/server/chunks/[root-of-the-server]__05luceg._.js +0 -3
  414. package/.next/server/chunks/[root-of-the-server]__06t77t4._.js +0 -11
  415. package/.next/server/chunks/[root-of-the-server]__0bed6hu._.js +0 -8
  416. package/.next/server/chunks/[root-of-the-server]__0cro2dz._.js +0 -5
  417. package/.next/server/chunks/[root-of-the-server]__0dupqt7._.js +0 -5
  418. package/.next/server/chunks/[root-of-the-server]__0emr6go._.js +0 -3
  419. package/.next/server/chunks/[root-of-the-server]__0le4d-p._.js +0 -3
  420. package/.next/server/chunks/[root-of-the-server]__0m8ywyo._.js +0 -10
  421. package/.next/server/chunks/[root-of-the-server]__0nfuugi._.js +0 -5
  422. package/.next/server/chunks/[root-of-the-server]__0p32jfz._.js +0 -12
  423. package/.next/server/chunks/[root-of-the-server]__0phdgco._.js +0 -8
  424. package/.next/server/chunks/[root-of-the-server]__0wvgrsl._.js +0 -3
  425. package/.next/server/chunks/[root-of-the-server]__10qshki._.js +0 -3
  426. package/.next/server/chunks/[root-of-the-server]__11j52t0._.js +0 -5
  427. package/.next/server/chunks/[root-of-the-server]__1692zrv._.js +0 -3
  428. package/.next/server/chunks/[root-of-the-server]__16thabu._.js +0 -3
  429. package/.next/server/chunks/[root-of-the-server]__173nhwf._.js +0 -8
  430. package/.next/server/chunks/[root-of-the-server]__1_aoyr9._.js +0 -3
  431. package/.next/server/chunks/[root-of-the-server]__1bn73ih._.js +0 -10
  432. package/.next/server/chunks/[root-of-the-server]__1bqhuh9._.js +0 -8
  433. package/.next/server/chunks/[root-of-the-server]__1cqizfq._.js +0 -5
  434. package/.next/server/chunks/[root-of-the-server]__1e-ci13._.js +0 -3
  435. package/.next/server/chunks/[root-of-the-server]__1fboj2j._.js +0 -3
  436. package/.next/server/chunks/[root-of-the-server]__1lr7j9t._.js +0 -5
  437. package/.next/server/chunks/[root-of-the-server]__1oli73c._.js +0 -3
  438. package/.next/server/chunks/[root-of-the-server]__1txedx6._.js +0 -8
  439. package/.next/server/chunks/[root-of-the-server]__1untqv8._.js +0 -5
  440. package/.next/server/chunks/[root-of-the-server]__1zgpz1w._.js +0 -3
  441. package/.next/server/chunks/_00_584r._.js +0 -293
  442. package/.next/server/chunks/_012yhfm._.js +0 -39
  443. package/.next/server/chunks/_06mxlgn._.js +0 -3
  444. package/.next/server/chunks/_07rtlxv._.js +0 -3
  445. package/.next/server/chunks/_0a351g7._.js +0 -6
  446. package/.next/server/chunks/_0kjjmag._.js +0 -3
  447. package/.next/server/chunks/_0nn99o2._.js +0 -3
  448. package/.next/server/chunks/_0zuzmt_._.js +0 -39
  449. package/.next/server/chunks/_106co2o._.js +0 -3
  450. package/.next/server/chunks/_12bbv5i._.js +0 -100
  451. package/.next/server/chunks/_15q1pig._.js +0 -3
  452. package/.next/server/chunks/_19wg5yn._.js +0 -138
  453. package/.next/server/chunks/_1bt95p9._.js +0 -55
  454. package/.next/server/chunks/_1cbk7ms._.js +0 -26
  455. package/.next/server/chunks/_1drv2et._.js +0 -40
  456. package/.next/server/chunks/_1ic3bew._.js +0 -5
  457. package/.next/server/chunks/_1mxn_lb._.js +0 -3
  458. package/.next/server/chunks/_1rysr-r._.js +0 -10
  459. package/.next/server/chunks/_1u3rwbr._.js +0 -3
  460. package/.next/server/chunks/_1x7p319._.js +0 -6
  461. package/.next/server/chunks/_next-internal_server_app_api_bot_notes_route_actions_0qcsyu7.js +0 -3
  462. package/.next/server/chunks/_next-internal_server_app_api_memory_tidy_route_actions_0_cfuom.js +0 -3
  463. package/.next/server/chunks/features_bot_task_query_ts_11xuzl3._.js +0 -3
  464. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_0gzvgfv._.js +0 -3
  465. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_0vorg6w._.js +0 -3
  466. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1tpvamf._.js +0 -3
  467. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1vmaq9f._.js +0 -3
  468. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1y9-wcr._.js +0 -3
  469. package/.next/server/chunks/ssr/[externals]_node_crypto_1kn79-7._.js +0 -3
  470. package/.next/server/chunks/ssr/[root-of-the-server]__0iuoa-r._.js +0 -3
  471. package/.next/server/chunks/ssr/[root-of-the-server]__0un-erv._.js +0 -4
  472. package/.next/server/chunks/ssr/[root-of-the-server]__1-mnhyd._.js +0 -92
  473. package/.next/server/chunks/ssr/[root-of-the-server]__1bww500._.js +0 -3
  474. package/.next/server/chunks/ssr/[root-of-the-server]__1vcdast._.js +0 -3
  475. package/.next/server/chunks/ssr/[root-of-the-server]__1xwnu-h._.js +0 -3
  476. package/.next/server/chunks/ssr/_0-mc7ro._.js +0 -3
  477. package/.next/server/chunks/ssr/_01p5r6-._.js +0 -3
  478. package/.next/server/chunks/ssr/_03webdr._.js +0 -3
  479. package/.next/server/chunks/ssr/_09-0k3z._.js +0 -3
  480. package/.next/server/chunks/ssr/_0f_b_9s._.js +0 -3
  481. package/.next/server/chunks/ssr/_0fafgvl._.js +0 -3
  482. package/.next/server/chunks/ssr/_0sf1isi._.js +0 -3
  483. package/.next/server/chunks/ssr/_0su6_08._.js +0 -3
  484. package/.next/server/chunks/ssr/_0ti51xc._.js +0 -3
  485. package/.next/server/chunks/ssr/_0w5bgak._.js +0 -3
  486. package/.next/server/chunks/ssr/_0y84qo6._.js +0 -3
  487. package/.next/server/chunks/ssr/_1ciyoo3._.js +0 -3
  488. package/.next/server/chunks/ssr/_1e-dgz0._.js +0 -4
  489. package/.next/server/chunks/ssr/_1fq7zgb._.js +0 -3
  490. package/.next/server/chunks/ssr/_1g6l4uj._.js +0 -3
  491. package/.next/server/chunks/ssr/_1ruzehw._.js +0 -3
  492. package/.next/server/chunks/ssr/features_bot_components_bot-setting_tsx_01ajft6._.js +0 -4
  493. package/.next/server/chunks/ssr/features_config_components_14jqgy4._.js +0 -3
  494. package/.next/server/chunks/ssr/features_memory_components_memory-setting_tsx_0oa43sw._.js +0 -4
  495. package/.next/server/chunks/ssr/node_modules_zod_v4_classic_external_15fmmz3.js +0 -55
  496. package/.next/static/chunks/05b6nx_o3_f_n.js +0 -1
  497. package/.next/static/chunks/0dmns-gi0raa4.js +0 -1
  498. package/.next/static/chunks/0f9sq-7q_yxyl.js +0 -1
  499. package/.next/static/chunks/0oc4_xoia77dg.css +0 -1
  500. package/.next/static/chunks/0pheo8m3a-rzi.js +0 -1
  501. package/.next/static/chunks/19i8h2t-5evjx.js +0 -1
  502. package/.next/static/chunks/1c5fcj473025q.js +0 -1
  503. package/.next/static/chunks/1pi_hbmjw-f-z.js +0 -1
  504. package/.next/static/chunks/1twt6k09vg4np.js +0 -1
  505. package/.next/static/chunks/1ytnip8wdng93.js +0 -1
  506. package/.next/static/chunks/28gotuisldmom.js +0 -1
  507. package/.next/static/chunks/2998p0y7k1c8z.js +0 -3
  508. package/.next/static/chunks/29gyb3nubj51j.js +0 -53
  509. package/.next/static/chunks/2l233xfycjpd8.js +0 -1
  510. package/.next/static/chunks/2p5n7pa3c40t-.js +0 -2
  511. package/.next/static/chunks/2ru1q132af7h7.js +0 -1
  512. package/.next/static/chunks/2t8wqycwg3y04.js +0 -2
  513. package/.next/static/chunks/2uxum7qbyeyxd.js +0 -1
  514. package/.next/static/chunks/32z_ypgtchw48.js +0 -1
  515. package/.next/static/chunks/33pyjb3xd1iez.js +0 -1
  516. package/.next/static/chunks/3omud5xunrk1f.js +0 -1
  517. package/.next/static/chunks/42dnrkbph9e-1.js +0 -1
  518. package/.next/static/media/favicon.2vob68tjqpejf.ico +0 -0
  519. package/database/migrations/20260909063821_bitter_tenebrous/migration.sql +0 -1
  520. package/features/ai/prompts/memory-tidy.prompt.ts +0 -129
  521. package/features/ai/tools/tidy.tool.ts +0 -22
  522. package/features/bot/bot.notes.ts +0 -120
  523. package/features/memory/components/memory-tidy.tsx +0 -395
  524. package/features/memory/memory.tidy.ts +0 -332
  525. package/features/memory/tidy.query.ts +0 -135
  526. package/features/thursday/use-call-title.ts +0 -31
  527. /package/.next/server/app/api/bot/{notes → memory/files}/route/build-manifest.json +0 -0
  528. /package/.next/server/app/api/bot/{notes → memory/files}/route/server-reference-manifest.json +0 -0
  529. /package/.next/server/app/api/bot/{notes → memory/files}/route.js.map +0 -0
  530. /package/.next/server/app/api/{memory/tidy → bot/memory}/route/build-manifest.json +0 -0
  531. /package/.next/server/app/api/{memory/tidy → bot/memory}/route/server-reference-manifest.json +0 -0
  532. /package/.next/server/app/api/{memory/tidy → bot/memory}/route.js.map +0 -0
  533. /package/.next/static/{YR4NWcDDuzwLbTTU7U7Vr → x1cCqY0kWpR_VcYx_lWO5}/_buildManifest.js +0 -0
  534. /package/.next/static/{YR4NWcDDuzwLbTTU7U7Vr → x1cCqY0kWpR_VcYx_lWO5}/_clientMiddlewareManifest.js +0 -0
  535. /package/.next/static/{YR4NWcDDuzwLbTTU7U7Vr → x1cCqY0kWpR_VcYx_lWO5}/_ssgManifest.js +0 -0
@@ -1,4 +1,5 @@
1
1
  import { z } from "zod";
2
+ import { BOT_RUN } from "@/config";
2
3
  import {
3
4
  REALTIME_PROVIDERS,
4
5
  type SpeachModelProviderId,
@@ -8,6 +9,7 @@ import {
8
9
 
9
10
  export const textModelProviderSchema = z.enum([
10
11
  "openai",
12
+ "chatgpt",
11
13
  "anthropic",
12
14
  "google",
13
15
  "xai",
@@ -42,7 +44,46 @@ export const MODEL_TIERS = ["small", "mid", "large"] as const;
42
44
  export type ModelTier = (typeof MODEL_TIERS)[number];
43
45
 
44
46
  /** One model worth offering, as the picker reads it. */
45
- export type SuggestModel = { id: string; label: string; tier: ModelTier };
47
+ export type SuggestModel = {
48
+ id: string;
49
+ label: string;
50
+ tier: ModelTier;
51
+ /**
52
+ * Context window in tokens, from the gateway's catalog for the same model. Only
53
+ * the gateway can be asked at run time (readGatewayCatalog), so a provider used
54
+ * directly reads its window here instead of guessing. Null where the gateway
55
+ * does not carry the model: the run falls back to `BOT_RUN.compactAt`.
56
+ */
57
+ context?: number | null;
58
+ };
59
+
60
+ /**
61
+ * A model's context window where the app can know it: the gateway's catalog row
62
+ * for a gateway model, else the window stamped on a directly used provider's
63
+ * shelf (`SuggestModel.context`). Null when neither says. Pure, so the settings
64
+ * screen and a run (ai/model compactBudget) read the same number.
65
+ */
66
+ export function contextWindowOf(
67
+ provider: TextModelProviderId,
68
+ model: string,
69
+ catalog: readonly GatewayModel[] = [],
70
+ ): number | null {
71
+ if (provider === "vercel-ai-gateway") {
72
+ return catalog.find((row) => row.id === model)?.contextWindow ?? null;
73
+ }
74
+ const shelf = TEXT_MODEL_PROVIDERS[provider].suggestModels;
75
+ return shelf.find((row) => row.id === model)?.context ?? null;
76
+ }
77
+
78
+ /**
79
+ * Where a run on a model with this window summarises itself, in tokens:
80
+ * `BOT_RUN.compactHeadroom` of the window, or `BOT_RUN.compactAt` when the window
81
+ * is unknown. What a bot's settings fill in, and what a run falls back to.
82
+ */
83
+ export const compactAtFor = (window: number | null | undefined): number =>
84
+ window && window > 0
85
+ ? Math.round(window * BOT_RUN.compactHeadroom)
86
+ : BOT_RUN.compactAt;
46
87
 
47
88
  /** Providers that make non-text media. Kept apart from the text providers: the key is the same, but a text provider does not necessarily draw (Anthropic). */
48
89
  export const mediaModelProviderSchema = z.enum([
@@ -72,7 +113,7 @@ export type MediaModelRef = z.infer<typeof mediaModelRefSchema>;
72
113
  * Suggested media models per provider and kind, cheapest first; the head runs when only the
73
114
  * provider is known. Suggestions, not a validation list. Ids follow each sdk's own spelling, so
74
115
  * the gateway names the same model differently (`spacexai/…`). An empty list means the provider
75
- * cannot make that kind (OpenAI has no video model).
116
+ * cannot make that kind for a model the sdk cannot build as well as one that does not exist.
76
117
  */
77
118
  export const MEDIA_MODEL_PROVIDERS: Record<
78
119
  MediaModelProviderId,
@@ -88,9 +129,18 @@ export const MEDIA_MODEL_PROVIDERS: Record<
88
129
  models: {
89
130
  image: [
90
131
  { id: "gpt-image-1-mini", label: "GPT Image 1 mini", tier: "small" },
91
- { id: "gpt-image-1.5", label: "GPT Image 1.5", tier: "mid" },
92
- { id: "gpt-image-2", label: "GPT Image 2", tier: "large" },
132
+ {
133
+ id: "gpt-image-2.5-flare",
134
+ label: "GPT Image 2.5 Flare",
135
+ tier: "mid",
136
+ },
137
+ {
138
+ id: "gpt-image-2.5-sunburst",
139
+ label: "GPT Image 2.5 Sunburst",
140
+ tier: "large",
141
+ },
93
142
  ],
143
+ // Sora exists, but the sdk's OpenAI provider has no video model (model.ts buildVideoModel)
94
144
  video: [],
95
145
  speech: [
96
146
  { id: "tts-1", label: "TTS 1", tier: "small" },
@@ -98,13 +148,12 @@ export const MEDIA_MODEL_PROVIDERS: Record<
98
148
  { id: "tts-1-hd", label: "TTS 1 HD", tier: "large" },
99
149
  ],
100
150
  transcription: [
101
- { id: "whisper-1", label: "Whisper", tier: "small" },
102
151
  {
103
152
  id: "gpt-4o-mini-transcribe",
104
153
  label: "4o mini Transcribe",
105
154
  tier: "small",
106
155
  },
107
- { id: "gpt-4o-transcribe", label: "4o Transcribe", tier: "mid" },
156
+ { id: "gpt-transcribe", label: "GPT Transcribe", tier: "mid" },
108
157
  ],
109
158
  },
110
159
  },
@@ -114,17 +163,17 @@ export const MEDIA_MODEL_PROVIDERS: Record<
114
163
  models: {
115
164
  image: [
116
165
  {
117
- id: "gemini-2.5-flash-image",
118
- label: "2.5 Flash Image",
166
+ id: "gemini-3.1-flash-lite-image",
167
+ label: "3.1 Flash Lite Image",
119
168
  tier: "small",
120
169
  },
121
170
  {
122
- id: "gemini-3.1-flash-image-preview",
171
+ id: "gemini-3.1-flash-image",
123
172
  label: "3.1 Flash Image",
124
173
  tier: "mid",
125
174
  },
126
175
  {
127
- id: "gemini-3-pro-image-preview",
176
+ id: "gemini-3-pro-image",
128
177
  label: "3 Pro Image",
129
178
  tier: "large",
130
179
  },
@@ -140,7 +189,7 @@ export const MEDIA_MODEL_PROVIDERS: Record<
140
189
  label: "Veo 3.1 Fast",
141
190
  tier: "mid",
142
191
  },
143
- { id: "veo-3.1-generate", label: "Veo 3.1", tier: "large" },
192
+ { id: "veo-3.1-generate-preview", label: "Veo 3.1", tier: "large" },
144
193
  ],
145
194
  speech: [
146
195
  {
@@ -175,8 +224,8 @@ export const MEDIA_MODEL_PROVIDERS: Record<
175
224
  image: [
176
225
  { id: "grok-imagine-image", label: "Grok Imagine", tier: "small" },
177
226
  {
178
- id: "grok-imagine-image-pro",
179
- label: "Grok Imagine Pro",
227
+ id: "grok-imagine-image-2.0",
228
+ label: "Grok Imagine 2.0",
180
229
  tier: "mid",
181
230
  },
182
231
  ],
@@ -230,7 +279,11 @@ export const MEDIA_MODEL_PROVIDERS: Record<
230
279
  label: "Gemini 3 Pro Image",
231
280
  tier: "large",
232
281
  },
233
- { id: "openai/gpt-image-2", label: "GPT Image 2", tier: "large" },
282
+ {
283
+ id: "openai/gpt-image-2.5-sunburst",
284
+ label: "GPT Image 2.5 Sunburst",
285
+ tier: "large",
286
+ },
234
287
  ],
235
288
  video: [
236
289
  {
@@ -344,13 +397,15 @@ export function parseMediaModel(
344
397
 
345
398
  /**
346
399
  * Suggested text models per provider, cheapest first. Suggestions, not a validation list;
347
- * `defaultModelOf` and `cheapestModelOf` read tiers, not positions.
400
+ * `defaultModelOf` reads tiers, not positions.
348
401
  */
349
402
  export const TEXT_MODEL_PROVIDERS: Record<
350
403
  TextModelProviderId,
351
404
  {
352
405
  label: string;
353
406
  apiKeyName: string;
407
+ /** Reached by signing in to an account rather than a pasted key; `apiKeyName` is where the sign-in is kept. */
408
+ signIn?: true;
354
409
  suggestModels: SuggestModel[];
355
410
  }
356
411
  > = {
@@ -358,19 +413,85 @@ export const TEXT_MODEL_PROVIDERS: Record<
358
413
  label: "Open AI",
359
414
  apiKeyName: "OPENAI_API_KEY",
360
415
  suggestModels: [
361
- { id: "gpt-5.6-luna", label: "5.6 Luna", tier: "small" },
362
- { id: "gpt-5.6-terra", label: "5.6 Terra", tier: "mid" },
363
- { id: "gpt-5.6-sol", label: "5.6 Sol", tier: "large" },
364
- { id: "gpt-6-astra", label: "6 Astra", tier: "large" },
416
+ {
417
+ id: "gpt-5.6-luna",
418
+ label: "5.6 Luna",
419
+ tier: "small",
420
+ context: 1_050_000,
421
+ },
422
+ {
423
+ id: "gpt-5.6-terra",
424
+ label: "5.6 Terra",
425
+ tier: "mid",
426
+ context: 1_050_000,
427
+ },
428
+ {
429
+ id: "gpt-5.6-sol",
430
+ label: "5.6 Sol",
431
+ tier: "large",
432
+ context: 1_050_000,
433
+ },
434
+ {
435
+ id: "gpt-6-astra",
436
+ label: "6 Astra",
437
+ tier: "large",
438
+ context: 1_050_000,
439
+ },
440
+ ],
441
+ },
442
+ /**
443
+ * The Codex models a ChatGPT plan carries, reached by signing in (ai/chatgpt). Which ones a
444
+ * plan opens differs — a Free plan lists Luna, Terra and 5.5 — and the backend caps every
445
+ * window at 272k, whatever the same model takes over the API.
446
+ */
447
+ chatgpt: {
448
+ label: "GPT Subscription",
449
+ apiKeyName: "CHATGPT_SIGN_IN",
450
+ signIn: true,
451
+ suggestModels: [
452
+ {
453
+ id: "gpt-5.6-luna",
454
+ label: "5.6 Luna",
455
+ tier: "small",
456
+ context: 272_000,
457
+ },
458
+ {
459
+ id: "gpt-5.6-terra",
460
+ label: "5.6 Terra",
461
+ tier: "mid",
462
+ context: 272_000,
463
+ },
464
+ {
465
+ id: "gpt-5.6-sol",
466
+ label: "5.6 Sol",
467
+ tier: "large",
468
+ context: 272_000,
469
+ },
470
+ {
471
+ id: "gpt-6-astra",
472
+ label: "6 Astra",
473
+ tier: "large",
474
+ context: 272_000,
475
+ },
365
476
  ],
366
477
  },
367
478
  anthropic: {
368
479
  label: "Claude",
369
480
  apiKeyName: "ANTHROPIC_API_KEY",
370
481
  suggestModels: [
371
- { id: "claude-haiku-4-5-20251001", label: "Haiku 4.5", tier: "small" },
372
- { id: "claude-sonnet-5", label: "Sonnet 5", tier: "mid" },
373
- { id: "claude-opus-5", label: "Opus 5", tier: "large" },
482
+ { id: "claude-haiku-4-5", label: "Haiku 4.5", tier: "small" },
483
+ {
484
+ id: "claude-sonnet-5",
485
+ label: "Sonnet 5",
486
+ tier: "mid",
487
+ context: 1_000_000,
488
+ },
489
+ {
490
+ id: "claude-opus-5",
491
+ label: "Opus 5",
492
+ tier: "large",
493
+ context: 1_000_000,
494
+ },
374
495
  { id: "claude-fable-5-1", label: "Fable 5.1", tier: "large" },
375
496
  ],
376
497
  },
@@ -378,13 +499,26 @@ export const TEXT_MODEL_PROVIDERS: Record<
378
499
  label: "Gemini",
379
500
  apiKeyName: "GOOGLE_GENERATIVE_AI_API_KEY",
380
501
  suggestModels: [
381
- { id: "gemini-3.8-flash", label: "3.8 Flash", tier: "mid" },
502
+ {
503
+ id: "gemini-3.5-flash-lite",
504
+ label: "3.5 Flash Lite",
505
+ tier: "small",
506
+ context: 1_000_000,
507
+ },
508
+ {
509
+ id: "gemini-3.8-flash",
510
+ label: "3.8 Flash",
511
+ tier: "mid",
512
+ context: 1_000_000,
513
+ },
382
514
  ],
383
515
  },
384
516
  xai: {
385
517
  label: "xAI",
386
518
  apiKeyName: "XAI_API_KEY",
387
- suggestModels: [{ id: "grok-4.6", label: "Grok 4.6", tier: "large" }],
519
+ suggestModels: [
520
+ { id: "grok-4.6", label: "Grok 4.6", tier: "large", context: 500_000 },
521
+ ],
388
522
  },
389
523
  /**
390
524
  * Cross-vendor shelf, cheapest first, shown until the live catalog arrives. Vendor names are
@@ -400,24 +534,55 @@ export const TEXT_MODEL_PROVIDERS: Record<
400
534
  label: "Gemini 3.8 Flash",
401
535
  tier: "small",
402
536
  },
403
- { id: "openai/gpt-5.6-luna", label: "GPT 5.6 Luna", tier: "small" },
537
+ {
538
+ id: "openai/gpt-5.6-luna",
539
+ label: "GPT 5.6 Luna",
540
+ tier: "small",
541
+ context: 1_050_000,
542
+ },
404
543
  { id: "zai/glm-5.3", label: "GLM 5.3", tier: "mid" },
405
- { id: "spacexai/grok-4.6", label: "Grok 4.6", tier: "mid" },
544
+ {
545
+ id: "spacexai/grok-4.6",
546
+ label: "Grok 4.6",
547
+ tier: "mid",
548
+ context: 500_000,
549
+ },
406
550
  {
407
551
  id: "anthropic/claude-sonnet-5",
408
552
  label: "Claude Sonnet 5",
409
553
  tier: "mid",
410
554
  },
411
- { id: "openai/gpt-5.6-terra", label: "GPT 5.6 Terra", tier: "mid" },
555
+ {
556
+ id: "openai/gpt-5.6-terra",
557
+ label: "GPT 5.6 Terra",
558
+ tier: "mid",
559
+ context: 1_050_000,
560
+ },
412
561
  { id: "moonshotai/kimi-k3", label: "Kimi K3", tier: "mid" },
413
- { id: "openai/gpt-5.6-sol", label: "GPT 5.6 Sol", tier: "large" },
414
- { id: "anthropic/claude-opus-5", label: "Claude Opus 5", tier: "large" },
562
+ {
563
+ id: "openai/gpt-5.6-sol",
564
+ label: "GPT 5.6 Sol",
565
+ tier: "large",
566
+ context: 1_050_000,
567
+ },
568
+ {
569
+ id: "anthropic/claude-opus-5",
570
+ label: "Claude Opus 5",
571
+ tier: "large",
572
+ context: 1_000_000,
573
+ },
574
+ {
575
+ id: "openai/gpt-6-astra",
576
+ label: "GPT 6 Astra",
577
+ tier: "large",
578
+ context: 1_050_000,
579
+ },
415
580
  ],
416
581
  },
417
582
  };
418
583
 
419
584
  /** A provider's model at one tier, or its first one when it has none at that size. */
420
- export const modelOfTier = (
585
+ const modelOfTier = (
421
586
  provider: { suggestModels: SuggestModel[] },
422
587
  tier: ModelTier,
423
588
  ): string | undefined =>
@@ -430,10 +595,6 @@ export const modelOfTier = (
430
595
  export const defaultModelOf = (provider: { suggestModels: SuggestModel[] }) =>
431
596
  modelOfTier(provider, "mid");
432
597
 
433
- /** The cheapest model of a provider; what `web_search` runs on (model.ts resolveSearchModel). */
434
- export const cheapestModelOf = (provider: { suggestModels: SuggestModel[] }) =>
435
- modelOfTier(provider, "small");
436
-
437
598
  /**
438
599
  * The speech-to-speech backends. `models` and `voices` are suggestion lists, not validation
439
600
  * lists (the api takes more, e.g. a cloned voice id); the first model is the default. Written
@@ -536,8 +697,30 @@ export type AiProvider = {
536
697
  apiKeyName: string;
537
698
  hasKey: boolean;
538
699
  suggestModels: SuggestModel[];
700
+ /** Signs in to an account instead of taking a key (TEXT_MODEL_PROVIDERS `signIn`). */
701
+ signIn?: true;
702
+ /** The plan the signed-in account is on, as the provider names it; sign-in providers only. */
703
+ plan?: string | null;
539
704
  };
540
705
 
706
+ /**
707
+ * What a GPT Subscription sign-in has used (ai/chatgpt readChatGptUsage): the tightest window of
708
+ * its plan and when it frees up, with `plan` as the backend names it now. `refused` is a sign-in
709
+ * the plan turned away, in its own words.
710
+ */
711
+ export type SubscriptionUsage =
712
+ | {
713
+ plan: string | null;
714
+ usedPercent: number;
715
+ /** ISO; null when the backend did not say. */
716
+ resetsAt: string | null;
717
+ /** The window is used up: jobs on it stop until it resets. */
718
+ spent: boolean;
719
+ /** Spent, or past `CHATGPT_USAGE_HIGH`: amber on its row. */
720
+ high: boolean;
721
+ }
722
+ | { refused: string };
723
+
541
724
  /** What a gateway row can be picked as: text, one of the studio kinds, or a word this app offers nowhere (embedding, reranking, realtime). */
542
725
  export const GATEWAY_TEXT = "language";
543
726
 
@@ -571,4 +754,19 @@ export type GatewayModel = {
571
754
  price: GatewayPrice;
572
755
  /** The gateway has dated its retirement. */
573
756
  retiring: boolean;
757
+ /** Context window in tokens; null when the gateway did not say. What a run compacts against (bot.run). */
758
+ contextWindow: number | null;
574
759
  };
760
+
761
+ /**
762
+ * What is left on the gateway key (ai/model `readGatewayCredits`). A key the gateway turns
763
+ * away is not a failed read: `refused` carries its words, drawn on the key's row and dialog.
764
+ */
765
+ export type GatewayCredits =
766
+ | {
767
+ /** USD. */
768
+ balance: number;
769
+ /** At or under `GATEWAY_LOW_CREDIT` (config): amber, it waits on a top-up. */
770
+ low: boolean;
771
+ }
772
+ | { refused: string };
@@ -8,10 +8,13 @@ import {
8
8
  type experimental_generateVideo,
9
9
  type ImageModel,
10
10
  type LanguageModel,
11
+ NoOutputGeneratedError,
12
+ RetryError,
11
13
  type SpeechModel,
12
14
  type ToolSet,
13
15
  type TranscriptionModel,
14
16
  } from "ai";
17
+ import { GATEWAY_LOW_CREDIT } from "@/config";
15
18
  import {
16
19
  DEFAULT_MODEL_KEY,
17
20
  MEDIA_MODEL_KEYS,
@@ -20,11 +23,14 @@ import { readConfig } from "@/features/config/config.query";
20
23
  import { logger } from "@/lib/logger";
21
24
  import { publicError } from "@/lib/public-error";
22
25
  import { clip, errorToString } from "@/lib/utils";
26
+ import { chatGptModel } from "./chatgpt";
23
27
  import {
24
28
  canMakeKind,
25
- cheapestModelOf,
29
+ compactAtFor,
30
+ contextWindowOf,
26
31
  defaultModelOf,
27
32
  GATEWAY_TEXT,
33
+ type GatewayCredits,
28
34
  type GatewayModel,
29
35
  type GatewayPrice,
30
36
  MEDIA_MODEL_PROVIDERS,
@@ -67,6 +73,92 @@ export function modelErrorToString(cause: unknown): string {
67
73
  return `${cause.message}${status}${said}`;
68
74
  }
69
75
 
76
+ /**
77
+ * What a failed model call means for the run that made it (bot.runner): `transient`
78
+ * is trouble a moment fixes — a rate limit, an overload, a dropped connection, a call
79
+ * that went quiet; `overflow` is a context the model refused as too long, which a
80
+ * compaction fixes; anything else is `fatal`, a person's to act on (a key, the credit,
81
+ * a model id). The sdk wraps retries and causes, so the whole chain is read.
82
+ */
83
+ export type ModelFailure = "transient" | "overflow" | "fatal";
84
+
85
+ /** Connection failures by the code Node or undici gives them. */
86
+ const NETWORK_CODES = new Set([
87
+ "ECONNRESET",
88
+ "ECONNREFUSED",
89
+ "ETIMEDOUT",
90
+ "EPIPE",
91
+ "ENOTFOUND",
92
+ "EAI_AGAIN",
93
+ "ENETUNREACH",
94
+ "EHOSTUNREACH",
95
+ "UND_ERR_SOCKET",
96
+ "UND_ERR_CLOSED",
97
+ "UND_ERR_CONNECT_TIMEOUT",
98
+ "UND_ERR_HEADERS_TIMEOUT",
99
+ "UND_ERR_BODY_TIMEOUT",
100
+ ]);
101
+
102
+ /**
103
+ * How providers word a context too long for the model; the sdk has no error class for
104
+ * it. Read off a 400 or a 413, or off an error with no status of its own — a retry
105
+ * wrapper repeats the words of the one it wraps.
106
+ */
107
+ const TOO_LONG =
108
+ /context[ _-]?(length|window)|maximum context|prompt is too long|too many (input )?tokens|input token count|exceeds? the (maximum|model'?s?) (context|input|prompt|number of tokens)|maximum prompt length|request (entity )?too large/i;
109
+
110
+ export function modelFailureOf(cause: unknown): ModelFailure {
111
+ let transient = false;
112
+ for (const error of causeChain(cause)) {
113
+ const { statusCode, isRetryable, code, name, message } = error as {
114
+ statusCode?: unknown;
115
+ isRetryable?: unknown;
116
+ code?: unknown;
117
+ name?: unknown;
118
+ message?: unknown;
119
+ };
120
+ const body = APICallError.isInstance(error)
121
+ ? (error.responseBody ?? "")
122
+ : "";
123
+ if (
124
+ (statusCode === undefined || statusCode === 400 || statusCode === 413) &&
125
+ TOO_LONG.test(`${String(message ?? "")} ${body}`)
126
+ ) {
127
+ return "overflow";
128
+ }
129
+ if (
130
+ isRetryable === true ||
131
+ name === "TimeoutError" ||
132
+ NoOutputGeneratedError.isInstance(error) ||
133
+ (typeof statusCode === "number" &&
134
+ (statusCode === 408 ||
135
+ statusCode === 409 ||
136
+ statusCode === 429 ||
137
+ statusCode >= 500)) ||
138
+ (typeof code === "string" && NETWORK_CODES.has(code))
139
+ ) {
140
+ transient = true;
141
+ }
142
+ }
143
+ return transient ? "transient" : "fatal";
144
+ }
145
+
146
+ /** An error and everything it wraps — its `cause`, each attempt of a retry. */
147
+ function causeChain(cause: unknown): object[] {
148
+ const chain: object[] = [];
149
+ const queue: unknown[] = [cause];
150
+ while (queue.length && chain.length < 12) {
151
+ const next = queue.shift();
152
+ if (typeof next !== "object" || next === null || chain.includes(next)) {
153
+ continue;
154
+ }
155
+ chain.push(next);
156
+ if (RetryError.isInstance(next)) queue.push(...next.errors);
157
+ if ("cause" in next) queue.push(next.cause);
158
+ }
159
+ return chain;
160
+ }
161
+
70
162
  /** A resolved model. Provider-native tools (web search) are built off the provider instance, not the model, so both come out of one switch. */
71
163
  export type TextModel = {
72
164
  ref: TextModelRef;
@@ -86,6 +178,9 @@ export function buildTextModel(ref: TextModelRef, apiKey: string): TextModel {
86
178
  searchTools: { search: openai.tools.webSearch() },
87
179
  };
88
180
  }
181
+ case "chatgpt":
182
+ // Signs every request with the stored sign-in itself (ai/chatgpt), so no key is passed
183
+ return { ref, model: chatGptModel(ref.model), searchTools: null };
89
184
  case "anthropic": {
90
185
  const anthropic = createAnthropic({ apiKey });
91
186
  return {
@@ -143,6 +238,7 @@ type CatalogRow = {
143
238
  deprecated_at?: number | null;
144
239
  modalities?: { output?: string[] | null } | null;
145
240
  pricing?: Record<string, unknown> | null;
241
+ context_window?: number | null;
146
242
  };
147
243
 
148
244
  /** USD per 1M tokens from the gateway's per-token string. Null is "it did not say", never zero. */
@@ -244,6 +340,10 @@ export async function readGatewayCatalog(): Promise<GatewayModel[]> {
244
340
  tags: row.tags ?? [],
245
341
  price: priceOfGatewayModel(row),
246
342
  retiring: Boolean(row.deprecated_at),
343
+ contextWindow:
344
+ typeof row.context_window === "number" && row.context_window > 0
345
+ ? row.context_window
346
+ : null,
247
347
  }),
248
348
  )
249
349
  .sort((a, b) => a.id.localeCompare(b.id));
@@ -252,6 +352,66 @@ export async function readGatewayCatalog(): Promise<GatewayModel[]> {
252
352
  return list;
253
353
  }
254
354
 
355
+ /** Unlike the listing, this answers only to a key. */
356
+ const GATEWAY_CREDITS_URL = "https://ai-gateway.vercel.sh/v1/credits";
357
+
358
+ /**
359
+ * What is left on the gateway key. The gateway is the one provider that tells this to the key
360
+ * a user typed; the others keep a balance behind an admin key. A key it turns away is a state
361
+ * of that key, not a failed read, so it comes back as `refused` in the gateway's own words.
362
+ */
363
+ export async function readGatewayCredits(): Promise<GatewayCredits | null> {
364
+ const apiKey = await readConfig(
365
+ TEXT_MODEL_PROVIDERS["vercel-ai-gateway"].apiKeyName,
366
+ );
367
+ if (!apiKey) return null;
368
+
369
+ const response = await fetch(GATEWAY_CREDITS_URL, {
370
+ headers: { accept: "application/json", authorization: `Bearer ${apiKey}` },
371
+ }).catch((cause: unknown) => {
372
+ logger.warn({ cause }, "gateway credits unreachable");
373
+ publicError("Could not reach the gateway");
374
+ });
375
+
376
+ const body = (await response.json().catch(() => null)) as {
377
+ balance?: string;
378
+ error?: { message?: string };
379
+ } | null;
380
+ const said = clip(body?.error?.message ?? "", PROVIDER_BODY_MAX);
381
+
382
+ if (response.status === 401 || response.status === 403)
383
+ return { refused: said || `The gateway answered ${response.status}` };
384
+ if (!response.ok)
385
+ publicError(
386
+ `The gateway answered ${response.status}${said ? `: ${said}` : ""}`,
387
+ );
388
+
389
+ const balance = Number(body?.balance);
390
+ if (!body?.balance || !Number.isFinite(balance))
391
+ publicError("The gateway did not say what is left");
392
+ return { balance, low: balance <= GATEWAY_LOW_CREDIT };
393
+ }
394
+
395
+ /**
396
+ * Where a run summarises itself, in tokens (bot.run): what the bot's owner set,
397
+ * else the model's own window worked out the same way the settings screen does
398
+ * (model.schema compactAtFor). An unknown window falls back to `BOT_RUN.compactAt`,
399
+ * which assumes the window a current model carries.
400
+ */
401
+ export async function compactBudget(
402
+ ref: TextModelRef,
403
+ /** What the bot's owner set, if anything (bot.compactAt); it wins. */
404
+ chosen?: number | null,
405
+ ): Promise<number> {
406
+ if (chosen && chosen > 0) return chosen;
407
+ // Never worth failing a run over: an unreachable catalog is a fallback, not an error
408
+ const catalog =
409
+ ref.provider === "vercel-ai-gateway"
410
+ ? await readGatewayCatalog().catch(() => [])
411
+ : [];
412
+ return compactAtFor(contextWindowOf(ref.provider, ref.model, catalog));
413
+ }
414
+
255
415
  /**
256
416
  * The gateway shelf as a set of ids. Null means it could not be asked, which is not "not there":
257
417
  * callers keep the written rows. Only existence is checked; the gateway prices image and video
@@ -280,9 +440,15 @@ async function callableRows<T extends { id: string }>(
280
440
  }
281
441
 
282
442
  export async function getTextModel(ref: TextModelRef): Promise<TextModel> {
283
- const { label, apiKeyName } = TEXT_MODEL_PROVIDERS[ref.provider];
443
+ const { label, apiKeyName, signIn } = TEXT_MODEL_PROVIDERS[ref.provider];
284
444
  const apiKey = await readConfig(apiKeyName);
285
- if (!apiKey) publicError(`No ${label} key — add one in Config.`);
445
+ if (!apiKey) {
446
+ publicError(
447
+ signIn
448
+ ? `${label} is not signed in — sign in from Config.`
449
+ : `No ${label} key — add one in Config.`,
450
+ );
451
+ }
286
452
  return buildTextModel(ref, apiKey);
287
453
  }
288
454
 
@@ -340,27 +506,6 @@ export async function resolveDefaultModel(
340
506
  publicError("No model key is set — add one in Config");
341
507
  }
342
508
 
343
- /**
344
- * The model a search runs on: this run's own when it has a native search, else the first
345
- * search-capable provider with a key, else null (the tool drops off the list).
346
- */
347
- export async function resolveSearchModel(
348
- run?: TextModel | null,
349
- ): Promise<TextModel | null> {
350
- if (run?.searchTools) return run;
351
-
352
- for (const provider of TEXT_MODEL_PROVIDER_LIST) {
353
- const apiKey = await readConfig(provider.apiKeyName);
354
- // The smallest one it has: this call reads pages and hands back a
355
- // paragraph, and nobody upstream can tell what it ran on
356
- const model = cheapestModelOf(provider);
357
- if (!apiKey || !model) continue;
358
- const candidate = buildTextModel({ provider: provider.id, model }, apiKey);
359
- if (candidate.searchTools) return candidate;
360
- }
361
- return null;
362
- }
363
-
364
509
  /** The sdk declares this one but does not export it — read off the function that takes it. */
365
510
  type VideoModel = Parameters<typeof experimental_generateVideo>[0]["model"];
366
511