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
@@ -27,16 +27,15 @@ import { Bubble, BubbleContent } from "@/components/ui/bubble";
27
27
  import { Button } from "@/components/ui/button";
28
28
  import { FoldedText } from "@/components/ui/folded-text";
29
29
  import { Markdown } from "@/components/ui/markdown";
30
- import ShinyText from "@/components/ui/shiny-text";
30
+ import { ShinyText, type ShinyTone } from "@/components/ui/shiny-text";
31
31
  import { Textarea } from "@/components/ui/textarea";
32
32
  import { toast } from "@/components/ui/toast";
33
- import { BOT_RUN } from "@/config";
34
- import { markReportedAction, startTaskAction } from "@/features/bot/bot.action";
33
+ import { startTaskAction } from "@/features/bot/bot.action";
35
34
  import {
36
35
  type Bot,
37
36
  type BotIcon,
38
37
  DEFAULT_BOT,
39
- isBudgetAsk,
38
+ isAppStop,
40
39
  TASK_CONTINUE,
41
40
  } from "@/features/bot/bot.schema";
42
41
  import { BotMark } from "@/features/bot/components/bot-mark";
@@ -46,8 +45,7 @@ import { TaskReply, useAnswerTask } from "@/features/bot/components/task-reply";
46
45
  import { openSettings } from "@/features/settings/settings.store";
47
46
  import { ThursdayMark } from "@/features/thursday/components/thursday-mark";
48
47
  import { FileViewer } from "@/features/workspace/components/file-view";
49
- import { shortAgo, toDate } from "@/lib/date-like";
50
- import { unwrapResult } from "@/lib/protocol/result";
48
+ import { shortAgo } from "@/lib/date-like";
51
49
  import { useServerAction } from "@/lib/protocol/use-server-action";
52
50
  import { revalidate, useServerRoute } from "@/lib/protocol/use-server-route";
53
51
  import {
@@ -71,6 +69,7 @@ import {
71
69
  type TaskViewStatus,
72
70
  threadItems,
73
71
  useBotTasks,
72
+ useSeenOnDetail,
74
73
  } from "../task.store";
75
74
  import { BotTool } from "./bot-tool";
76
75
 
@@ -178,41 +177,23 @@ export const BotRoom = memo(function BotRoom() {
178
177
  }
179
178
  }, [tasks, handoff]);
180
179
 
181
- // Opening a finished thread marks it reported. The key includes updatedAt: a
182
- // follow-up request finishes again and that result is unread. markReported does not
183
- // move `updatedAt`, so the set only bridges the gap until the next poll.
184
- const marked = useRef(new Set<string>());
185
- useEffect(() => {
186
- if (!current || current.relayed) return;
187
- if (current.status !== "done" && current.status !== "failed") return;
188
- const key = `${current.id}@${toDate(current.updatedAt).getTime()}`;
189
- if (marked.current.has(key)) return;
190
- marked.current.add(key);
191
- // unwrapResult folds Result failures and rejections into one path; on failure
192
- // release the key so the task can be marked again.
193
- void markReportedAction([current.id])
194
- .then(unwrapResult)
195
- .then(() => revalidate(queryKey.tasks))
196
- .catch((cause) => {
197
- marked.current.delete(key);
198
- toast.add({
199
- type: "error",
200
- title: "Could not mark the task as read",
201
- description: errorToString(cause),
202
- });
203
- });
204
- }, [current]);
180
+ // Reading a thread is reading its ending; that is what clears its dot.
181
+ useSeenOnDetail(open ? current : null);
205
182
 
206
183
  const busy = tasks.filter((entry) => entry.status === "working").length;
207
184
  const attention = newest.filter(needsYou);
208
185
  const pending = attention.length;
186
+ const unread = newest.filter(isUnread);
187
+ const failed = unread.filter((entry) => entry.status === "failed").length;
209
188
 
210
189
  const closeCompose = useCallback(() => setComposing(false), []);
211
190
 
212
191
  return (
213
- <div className="pointer-events-none absolute right-5 bottom-5 z-10 flex w-132 max-w-[calc(100vw-2.5rem)] flex-col items-end gap-2">
192
+ // As wide as the resting pill may grow: 80% of the window. The open room
193
+ // keeps its own 33rem inside it.
194
+ <div className="pointer-events-none absolute right-5 bottom-5 z-10 flex w-[min(80vw,calc(100vw-2.5rem))] flex-col items-end gap-2">
214
195
  {open ? (
215
- <div className="pointer-events-auto flex max-h-[min(44rem,78vh)] w-full animate-in flex-col overflow-hidden rounded-3xl bg-background/75 shadow-2xl shadow-black/6 ring-1 ring-border/50 backdrop-blur-xl fade-in slide-in-from-bottom-1 duration-200">
196
+ <div className="pointer-events-auto flex max-h-[min(44rem,78vh)] w-132 max-w-full animate-in flex-col overflow-hidden rounded-3xl bg-background/75 shadow-2xl shadow-black/6 ring-1 ring-border/50 backdrop-blur-xl fade-in slide-in-from-bottom-1 duration-200">
216
197
  {current ? (
217
198
  <>
218
199
  <ThreadHeader
@@ -267,6 +248,8 @@ export const BotRoom = memo(function BotRoom() {
267
248
  count={tasks.length}
268
249
  busy={busy}
269
250
  pending={pending}
251
+ unread={unread.length}
252
+ failed={failed}
270
253
  composing={composing}
271
254
  onCompose={() => setComposing(true)}
272
255
  onCloseCompose={closeCompose}
@@ -275,8 +258,10 @@ export const BotRoom = memo(function BotRoom() {
275
258
  setOpen(true);
276
259
  }}
277
260
  onOpen={() => {
278
- // A single waiting task opens straight into its thread.
279
- if (!picked && attention.length === 1) setPicked(attention[0].id);
261
+ // One thing to look at opens straight into its thread: a single
262
+ // question, or with none waiting, a single answer nobody has read.
263
+ const only = attention.length ? attention : unread;
264
+ if (!picked && only.length === 1) setPicked(only[0].id);
280
265
  setOpen(true);
281
266
  }}
282
267
  />
@@ -441,7 +426,7 @@ function crewOf(
441
426
  };
442
427
  }
443
428
 
444
- /** Blanks the question in the reply box when it already is the last thread line (budget stops). */
429
+ /** Blanks the question in the reply box when it already is the last thread line (stops the app made). */
445
430
  function askFor(task: TaskView): TaskView["ask"] {
446
431
  if (!task.ask?.question) return task.ask;
447
432
  const last = task.lines.at(-1);
@@ -451,46 +436,69 @@ function askFor(task: TaskView): TaskView["ask"] {
451
436
  }
452
437
 
453
438
  /**
454
- * A task that cannot move until the user answers: a question, or a budget stop.
439
+ * A task that cannot move until the user answers: a question, or a stop the app made.
455
440
  *
456
441
  * A finished job is not on this list. It has nothing for the user to do, and
457
- * counting it here made the chip hold itself open over a report nobody had to
458
- * act on. A report says itself once, in the sentence, and then it is a row in
442
+ * counting it here made the chip hold itself open over an answer nobody had to
443
+ * act on. An answer says itself once, in the sentence, and then it is a row in
459
444
  * the room like every other one.
460
445
  */
461
446
  const needsYou = (task: TaskView) => task.status === "waiting";
462
447
 
448
+ /** An ending nobody has opened. It needs the user too, to read rather than to answer. */
449
+ const isUnread = (task: TaskView) =>
450
+ (task.status === "done" || task.status === "failed") && !task.seen;
451
+
463
452
  /**
464
453
  * What the room itself is doing, and nothing else — the right side of the pill.
465
454
  *
466
- * Only `waiting on you` sweeps. A shine means something is happening right now,
467
- * which is what the words beside the faces are for; the spinner already says a
468
- * job is running, and two things sweeping in one pill read as a loading screen.
455
+ * What is still moving shines, like every other running line: a wait in amber,
456
+ * running jobs in muted ink beside the spinner. An ending does not an answer
457
+ * nobody has opened is something to read, not something happening.
469
458
  */
470
459
  function restingState({
471
460
  count,
472
461
  busy,
473
462
  pending,
463
+ unread,
464
+ failed,
474
465
  }: {
475
466
  count: number;
476
467
  busy: number;
477
468
  pending: number;
478
- }): { text: string; tone: string; shine: boolean } {
469
+ /** Endings nobody has opened, failures included. */
470
+ unread: number;
471
+ failed: number;
472
+ }): { text: string; tone: string; shine: ShinyTone | null } {
479
473
  if (pending > 0)
480
474
  return {
481
475
  text: pending === 1 ? "waiting on you" : `${pending} waiting on you`,
482
476
  tone: WAITING_INK,
483
- shine: true,
477
+ shine: "waiting",
478
+ };
479
+ // Unread outranks running: a job still going will say so again, and an answer
480
+ // left unopened will not.
481
+ if (failed > 0)
482
+ return {
483
+ text: failed === 1 ? "1 failed" : `${failed} failed`,
484
+ tone: "text-destructive",
485
+ shine: null,
486
+ };
487
+ if (unread > 0)
488
+ return {
489
+ text: unread === 1 ? "1 new answer" : `${unread} new answers`,
490
+ tone: WAITING_INK,
491
+ shine: null,
484
492
  };
485
493
  if (busy > 0)
486
494
  return {
487
495
  text: busy === 1 ? "working" : `${busy} running`,
488
496
  tone: "text-muted-foreground",
489
- shine: false,
497
+ shine: "muted",
490
498
  };
491
499
  if (count > 0)
492
- return { text: "all done", tone: "text-muted-foreground", shine: false };
493
- return { text: "no jobs yet", tone: "text-muted-foreground", shine: false };
500
+ return { text: "all done", tone: "text-muted-foreground", shine: null };
501
+ return { text: "no jobs yet", tone: "text-muted-foreground", shine: null };
494
502
  }
495
503
 
496
504
  /**
@@ -520,6 +528,8 @@ function Chip({
520
528
  count,
521
529
  busy,
522
530
  pending,
531
+ unread,
532
+ failed,
523
533
  composing,
524
534
  onCompose,
525
535
  onCloseCompose,
@@ -535,13 +545,15 @@ function Chip({
535
545
  count: number;
536
546
  busy: number;
537
547
  pending: number;
548
+ unread: number;
549
+ failed: number;
538
550
  composing: boolean;
539
551
  onCompose: () => void;
540
552
  onCloseCompose: () => void;
541
553
  onPick: (id: string) => void;
542
554
  onOpen: () => void;
543
555
  }) {
544
- const state = restingState({ count, busy, pending });
556
+ const state = restingState({ count, busy, pending, unread, failed });
545
557
  const grown = composing || pending > 0;
546
558
 
547
559
  return (
@@ -550,8 +562,10 @@ function Chip({
550
562
  // Not `overflow-hidden`: a hand-off bubble stands above the row, outside
551
563
  // this box. The growing part clips itself instead.
552
564
  "pointer-events-auto w-fit max-w-full bg-background/78 ring-1 ring-border/50 backdrop-blur-md transition-shadow duration-300",
565
+ // A card with questions in it keeps the room's width: only the resting
566
+ // row grows with the corner, and a reply's long lines would stretch it.
553
567
  grown
554
- ? "min-w-96 rounded-3xl shadow-lg shadow-black/8"
568
+ ? "max-w-[min(33rem,100%)] min-w-96 rounded-3xl shadow-lg shadow-black/8"
555
569
  : "rounded-full shadow-sm shadow-black/3",
556
570
  )}
557
571
  >
@@ -607,18 +621,12 @@ function Chip({
607
621
  the right. `ml-auto` keeps it there when the crew says nothing. */}
608
622
  <span className="ml-auto flex h-7 shrink-0 items-center gap-1.5">
609
623
  {state.shine ? (
610
- // Neither waiting nor running is a state at rest, but only one of
611
- // them needs you. The colours are classes because they differ per
612
- // theme, and ShinyText reads the variables they set.
613
- <span className="block [--rest:var(--color-amber-700)] [--shine:var(--color-amber-400)] dark:[--rest:var(--color-amber-400)] dark:[--shine:var(--color-amber-100)]">
614
- <ShinyText
615
- text={state.text}
616
- speed={2.6}
617
- color="var(--rest)"
618
- shineColor="var(--shine)"
619
- className="truncate text-[14px] leading-5 tracking-[-0.15px]"
620
- />
621
- </span>
624
+ <ShinyText
625
+ text={state.text}
626
+ tone={state.shine}
627
+ speed={2.6}
628
+ className="block truncate text-[14px] leading-5 tracking-[-0.15px]"
629
+ />
622
630
  ) : (
623
631
  <span
624
632
  key={state.text}
@@ -633,12 +641,14 @@ function Chip({
633
641
  {/* Always 16px, empty or not: a glyph that comes and goes moves the
634
642
  sentence's right end even when the sentence has not changed. */}
635
643
  <span className="grid size-4 shrink-0 place-items-center">
636
- {pending === 0 && busy > 0 && (
644
+ {pending === 0 && unread === 0 && busy > 0 && (
637
645
  <Loader2 className="size-4 animate-spin text-muted-foreground/70" />
638
646
  )}
639
- {pending === 0 && busy === 0 && count > 0 && (
640
- <Check className="size-4 text-muted-foreground/60" />
641
- )}
647
+ {pending === 0 &&
648
+ failed === 0 &&
649
+ (unread > 0 || (busy === 0 && count > 0)) && (
650
+ <Check className="size-4 text-muted-foreground/60" />
651
+ )}
642
652
  </span>
643
653
  </span>
644
654
  </button>
@@ -702,8 +712,13 @@ function Compose({ bots, onDone }: { bots?: Bot[]; onDone: () => void }) {
702
712
  });
703
713
 
704
714
  // A fresh install has no rows and still has a worker (bot.schema DEFAULT_BOT).
715
+ // Switched-off bots are left out for the same reason no model is shown one —
716
+ // but the fallback answers "no rows", not "every row off", so switching them
717
+ // all off leaves nothing to pick rather than conjuring a worker.
705
718
  const roster: BotRef[] = bots?.length
706
- ? bots.map((bot) => ({ name: bot.name, icon: bot.icon }))
719
+ ? bots
720
+ .filter((bot) => !bot.disabled)
721
+ .map((bot) => ({ name: bot.name, icon: bot.icon }))
707
722
  : [{ name: DEFAULT_BOT.name, icon: DEFAULT_BOT.icon }];
708
723
 
709
724
  const send = () => {
@@ -833,6 +848,9 @@ const GHOSTS: CrewFace[] = ["alto", "brio", "cinder", "delta"].map(
833
848
  /** A single face reads as one worker, not as a crew; below this the row is padded out. */
834
849
  const FLOOR = 3;
835
850
 
851
+ /** The awake halo, in the mark's own view-box units: about 2px of blur at 28px. */
852
+ const AWAKE_GLOW = 20;
853
+
836
854
  /**
837
855
  * The crew, and what each of them is doing.
838
856
  *
@@ -872,25 +890,12 @@ function Crew({
872
890
  face.standIn && "opacity-35",
873
891
  face.awake && "-translate-y-0.5 scale-110",
874
892
  )}
875
- style={{
876
- zIndex: crew.length - index,
877
- color: face.icon?.color ?? undefined,
878
- // The glow is the bot's own colour, so who is moving reads before
879
- // any word does. currentColor keeps it right when nobody chose one.
880
- filter: face.awake
881
- ? "drop-shadow(0 0 5px color-mix(in srgb, currentColor 55%, transparent))"
882
- : undefined,
883
- }}
893
+ style={{ zIndex: crew.length - index }}
884
894
  >
885
- <BotMark
886
- size={28}
887
- seed={face.name}
888
- vary={face.name}
889
- color={face.icon?.color}
890
- shape={face.icon?.shape}
891
- outline={face.icon?.outline}
892
- notify={face.waiting}
893
- />
895
+ {/* The halo is the mark's own (bot-mark `glow`), not a filter on
896
+ this box: a filter here also lands on the bubble above, which
897
+ came out tinted in the bot's colour and wearing its blur. */}
898
+ <CrewMark face={face} />
894
899
  {bubble && <HandoffBubble handoff={bubble} />}
895
900
  </span>
896
901
  {face.word && (
@@ -900,8 +905,6 @@ function Crew({
900
905
  <ShinyText
901
906
  text={face.word}
902
907
  speed={2.6}
903
- color="var(--muted-foreground)"
904
- shineColor="var(--foreground)"
905
908
  className="truncate text-[13px] leading-5 tracking-[-0.1px]"
906
909
  />
907
910
  </span>
@@ -926,6 +929,30 @@ function Crew({
926
929
  );
927
930
  }
928
931
 
932
+ /**
933
+ * One crew face. Awake, it wears a halo in its own colour, so who is moving
934
+ * reads before any word does; the options object is memoized because a new one
935
+ * every render re-derives the silhouette behind it.
936
+ */
937
+ function CrewMark({ face }: { face: CrewFace }) {
938
+ const glow = useMemo(
939
+ () => (face.awake ? { glow: AWAKE_GLOW } : undefined),
940
+ [face.awake],
941
+ );
942
+ return (
943
+ <BotMark
944
+ size={28}
945
+ seed={face.name}
946
+ vary={face.name}
947
+ color={face.icon?.color}
948
+ shape={face.icon?.shape}
949
+ outline={face.icon?.outline}
950
+ notify={face.waiting}
951
+ options={glow}
952
+ />
953
+ );
954
+ }
955
+
929
956
  /**
930
957
  * A hand-off, over the face it landed on. The mark at its head is whoever gave
931
958
  * it away — Thursday, another bot, or nobody at all when it was you.
@@ -1100,7 +1127,7 @@ const STATE_LOOK: Record<TaskViewStatus, string> = {
1100
1127
 
1101
1128
  function State({ task }: { task: TaskView }) {
1102
1129
  const look =
1103
- task.status === "done" && task.relayed
1130
+ task.status === "done" && task.seen
1104
1131
  ? "text-muted-foreground"
1105
1132
  : STATE_LOOK[task.status];
1106
1133
 
@@ -1109,8 +1136,6 @@ function State({ task }: { task: TaskView }) {
1109
1136
  <ShinyText
1110
1137
  text="working"
1111
1138
  speed={2.2}
1112
- color="var(--muted-foreground)"
1113
- shineColor="var(--foreground)"
1114
1139
  className="shrink-0 font-mono text-[10px]"
1115
1140
  />
1116
1141
  );
@@ -1224,18 +1249,17 @@ function TaskList({
1224
1249
 
1225
1250
  function TaskRow({ task, onPick }: { task: TaskView; onPick: () => void }) {
1226
1251
  const attention = needsYou(task);
1227
- // secondLine runs plainText over the whole report. Every sync rebuilds each TaskView
1252
+ // secondLine runs plainText over the whole answer. Every sync rebuilds each TaskView
1228
1253
  // (task.store), so depend on the fields that change the line, not on `task`.
1229
1254
  const last = task.lines.at(-1);
1230
1255
  const line = useMemo(
1231
1256
  () => secondLine(task),
1232
- [task.status, task.outcome, task.relayed, task.ask, last?.id],
1257
+ [task.status, task.outcome, task.seen, task.ask, last?.id],
1233
1258
  );
1234
1259
  const [answer, answering] = useAnswerTask();
1235
1260
  const [sending, setSending] = useState<string | null>(null);
1236
1261
  // Options are answered inline, without opening the thread.
1237
1262
  const options = task.status === "waiting" ? (task.ask?.options ?? []) : [];
1238
- const budget = isBudgetAsk(task.ask);
1239
1263
 
1240
1264
  return (
1241
1265
  // The row is not itself a button: the option buttons cannot nest inside one.
@@ -1287,8 +1311,6 @@ function TaskRow({ task, onPick }: { task: TaskView; onPick: () => void }) {
1287
1311
  <ShinyText
1288
1312
  text={line.text}
1289
1313
  speed={2.2}
1290
- color="var(--muted-foreground)"
1291
- shineColor="var(--foreground)"
1292
1314
  className={cn(
1293
1315
  "min-w-0 flex-1 truncate text-[12px] leading-4",
1294
1316
  line.tone,
@@ -1322,21 +1344,12 @@ function TaskRow({ task, onPick }: { task: TaskView; onPick: () => void }) {
1322
1344
  await answer(task, option);
1323
1345
  setSending(null);
1324
1346
  }}
1325
- className={cn(
1326
- "h-7 gap-1.5 rounded-full bg-background px-3 text-[12px]",
1327
- // A budget stop is not a question, so it does not take the waiting colour.
1328
- !budget && "border-amber-500/35",
1329
- )}
1347
+ className="h-7 gap-1.5 rounded-full border-amber-500/35 bg-background px-3 text-[12px]"
1330
1348
  >
1331
- {budget && option === TASK_CONTINUE && (
1349
+ {option === TASK_CONTINUE && (
1332
1350
  <ChevronsRight className="size-3.5 text-muted-foreground" />
1333
1351
  )}
1334
1352
  {option}
1335
- {budget && option === TASK_CONTINUE && (
1336
- <span className="font-mono text-[10px] text-muted-foreground">
1337
- +{BOT_RUN.steps} steps
1338
- </span>
1339
- )}
1340
1353
  </Button>
1341
1354
  ))}
1342
1355
  </div>
@@ -1348,29 +1361,28 @@ function TaskRow({ task, onPick }: { task: TaskView; onPick: () => void }) {
1348
1361
  /** Second row of a task line: the question, the outcome, or the bot's last step. */
1349
1362
  function secondLine(task: TaskView): { text: string; tone: string } {
1350
1363
  if (task.status === "waiting" && task.ask) {
1351
- // Budget stops are not questions; keep them out of the waiting colour.
1352
- if (isBudgetAsk(task.ask)) {
1353
- return {
1354
- text: plainText(task.outcome ?? task.ask.question),
1355
- tone: "text-muted-foreground",
1356
- };
1357
- }
1364
+ // A budget stop is not a question, but it waits on the user exactly as one
1365
+ // does, so it carries the waiting colour too; only the words differ.
1358
1366
  return {
1359
- text: task.ask.question,
1367
+ text: isAppStop(task.ask)
1368
+ ? plainText(task.outcome ?? task.ask.question)
1369
+ : task.ask.question,
1360
1370
  tone: WAITING_INK,
1361
1371
  };
1362
1372
  }
1363
1373
  // Reports are markdown; keep only the text.
1374
+ // An ending the user has opened steps back; red stays red, only quieter.
1375
+ const had = task.seen;
1364
1376
  if (task.status === "failed") {
1365
1377
  return {
1366
1378
  text: plainText(task.outcome ?? "Failed"),
1367
- tone: "text-destructive",
1379
+ tone: had ? "text-destructive/70" : "text-destructive",
1368
1380
  };
1369
1381
  }
1370
1382
  if (task.status === "done") {
1371
1383
  return {
1372
1384
  text: plainText(task.outcome ?? "Done"),
1373
- tone: task.relayed ? "text-muted-foreground" : "text-foreground",
1385
+ tone: had ? "text-muted-foreground" : "text-foreground",
1374
1386
  };
1375
1387
  }
1376
1388
  const last = lastSaid(task);
@@ -1434,20 +1446,37 @@ export function Conversation({
1434
1446
  <Group key={item.key} group={item.group} task={task} />
1435
1447
  ),
1436
1448
  )}
1437
- {task.status === "working" && task.lines.length === 0 && (
1438
- <ShinyText
1439
- text={`${task.bot.name} is taking it on…`}
1440
- speed={2.2}
1441
- color="var(--muted-foreground)"
1442
- shineColor="var(--foreground)"
1443
- className="block px-1 font-mono text-[10px]"
1444
- />
1445
- )}
1449
+ {task.status === "working" && <NextMove task={task} />}
1446
1450
  </div>
1447
1451
  </FileViewer>
1448
1452
  );
1449
1453
  }
1450
1454
 
1455
+ /**
1456
+ * The foot of a running thread while nothing on it is moving: the bot is
1457
+ * writing its next step. A tool mid-call already shines on its own row, so this
1458
+ * steps aside for it.
1459
+ */
1460
+ function NextMove({ task }: { task: TaskView }) {
1461
+ if (task.lines.some((line) => line.tool && line.tool.results === undefined)) {
1462
+ return null;
1463
+ }
1464
+ const last = task.lines.at(-1);
1465
+ // After a hand-off, in either direction, the move is the receiver's
1466
+ const who = last?.kind === "ask" && last.to ? last.to : last?.bot;
1467
+ return (
1468
+ <ShinyText
1469
+ text={
1470
+ who
1471
+ ? `${who.name} is on the next step…`
1472
+ : `${task.bot.name} is taking it on…`
1473
+ }
1474
+ speed={2.2}
1475
+ className="block px-1 font-mono text-[10px]"
1476
+ />
1477
+ );
1478
+ }
1479
+
1451
1480
  /** The delegated request, folded to three lines (FoldedText). */
1452
1481
  function Request({ task }: { task: TaskView }) {
1453
1482
  return (
@@ -1544,7 +1573,7 @@ function Turn({
1544
1573
  return (
1545
1574
  <div className={cn("flex gap-2.5", side === "end" && "flex-row-reverse")}>
1546
1575
  {mark}
1547
- {/* One cap on the turn's column, not one per block inside it: a report and
1576
+ {/* One cap on the turn's column, not one per block inside it: an answer and
1548
1577
  a one-line remark from the same bot then end on the same edge. The
1549
1578
  answering side hugs that edge, so the two sides face each other. */}
1550
1579
  <div
@@ -1636,7 +1665,7 @@ function Line({ line, taskId }: { line: Chatter; taskId: string }) {
1636
1665
  );
1637
1666
  }
1638
1667
 
1639
- // Passing remarks are muted; the report is the one thing here at full weight.
1668
+ // Passing remarks are muted; the answer is the one thing here at full weight.
1640
1669
  if (!isOutcome(line)) {
1641
1670
  return (
1642
1671
  <p className="px-1 text-[12.5px] leading-relaxed break-keep text-muted-foreground">
@@ -1669,7 +1698,7 @@ function Line({ line, taskId }: { line: Chatter; taskId: string }) {
1669
1698
  const failed = line.kind === "error";
1670
1699
 
1671
1700
  return (
1672
- // The report is not a card. It sits in a thread that is already in a box,
1701
+ // The answer is not a card. It sits in a thread that is already in a box,
1673
1702
  // in a section that is another: a fourth border reads as a second chat
1674
1703
  // window. What tells it from a passing remark is that it is the only prose
1675
1704
  // here at foreground weight, plus the files it names — and its copy button
@@ -1690,7 +1719,7 @@ function Line({ line, taskId }: { line: Chatter; taskId: string }) {
1690
1719
  {line.text}
1691
1720
  </Markdown>
1692
1721
  {/* The files it names, and the copy — one row, because the end of the
1693
- report is where a reader is when they want either. */}
1722
+ answer is where a reader is when they want either. */}
1694
1723
  <div className="mt-2 flex items-center gap-2">
1695
1724
  <PathChips text={line.text} className="min-w-0" />
1696
1725
  {!failed && (
@@ -1703,7 +1732,7 @@ function Line({ line, taskId }: { line: Chatter; taskId: string }) {
1703
1732
  );
1704
1733
  }
1705
1734
 
1706
- /** Copies the report. The icon confirms; a toast only reports failure. */
1735
+ /** Copies the answer. The icon confirms; a toast only reports failure. */
1707
1736
  function CopyReport({ text }: { text: string }) {
1708
1737
  const [copied, setCopied] = useState(false);
1709
1738
  const back = useRef<ReturnType<typeof setTimeout> | null>(null);
@@ -1718,7 +1747,7 @@ function CopyReport({ text }: { text: string }) {
1718
1747
  return (
1719
1748
  <button
1720
1749
  type="button"
1721
- aria-label="Copy the report"
1750
+ aria-label="Copy the answer"
1722
1751
  onClick={async () => {
1723
1752
  try {
1724
1753
  await navigator.clipboard.writeText(text);
@@ -1728,7 +1757,7 @@ function CopyReport({ text }: { text: string }) {
1728
1757
  } catch (cause) {
1729
1758
  toast.add({
1730
1759
  type: "error",
1731
- title: "Could not copy the report",
1760
+ title: "Could not copy the answer",
1732
1761
  description: errorToString(cause),
1733
1762
  });
1734
1763
  }