thursday-agent 0.11.0 → 0.13.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 (492) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/build-manifest.json +3 -3
  3. package/.next/prerender-manifest.json +4 -4
  4. package/.next/server/app/_global-error/page.js.nft.json +1 -1
  5. package/.next/server/app/_global-error.html +1 -1
  6. package/.next/server/app/_global-error.rsc +1 -1
  7. package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  8. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  9. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  10. package/.next/server/app/_not-found/page.js +1 -1
  11. package/.next/server/app/_not-found/page.js.nft.json +1 -1
  12. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  13. package/.next/server/app/_not-found.html +1 -1
  14. package/.next/server/app/_not-found.rsc +18 -19
  15. package/.next/server/app/_not-found.segments/_full.segment.rsc +18 -19
  16. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +14 -15
  17. package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  18. package/.next/server/app/api/artifact/route.js +8 -8
  19. package/.next/server/app/api/artifact/route.js.nft.json +1 -1
  20. package/.next/server/app/api/bot/keep-working/route.js +7 -7
  21. package/.next/server/app/api/bot/keep-working/route.js.nft.json +1 -1
  22. package/.next/server/app/api/bot/memory/files/route.js.nft.json +1 -1
  23. package/.next/server/app/api/bot/memory/route.js +7 -7
  24. package/.next/server/app/api/bot/memory/route.js.nft.json +1 -1
  25. package/.next/server/app/api/bot/route.js +7 -7
  26. package/.next/server/app/api/bot/route.js.nft.json +1 -1
  27. package/.next/server/app/api/bot/thread/[id]/route.js +5 -5
  28. package/.next/server/app/api/bot/thread/[id]/route.js.nft.json +1 -1
  29. package/.next/server/app/api/bot/thread/route.js +3 -3
  30. package/.next/server/app/api/bot/thread/route.js.nft.json +1 -1
  31. package/.next/server/app/api/config/route.js +3 -3
  32. package/.next/server/app/api/config/route.js.nft.json +1 -1
  33. package/.next/server/app/api/events/route.js.nft.json +1 -1
  34. package/.next/server/app/api/favicon/[host]/route.js.nft.json +1 -1
  35. package/.next/server/app/api/file/[...path]/route.js +2 -2
  36. package/.next/server/app/api/file/[...path]/route.js.nft.json +1 -1
  37. package/.next/server/app/api/llm-model/catalog/route.js +4 -4
  38. package/.next/server/app/api/llm-model/catalog/route.js.nft.json +1 -1
  39. package/.next/server/app/api/llm-model/credits/route.js +4 -4
  40. package/.next/server/app/api/llm-model/credits/route.js.nft.json +1 -1
  41. package/.next/server/app/api/llm-model/route.js +6 -6
  42. package/.next/server/app/api/llm-model/route.js.nft.json +1 -1
  43. package/.next/server/app/api/llm-model/subscription/route.js +6 -6
  44. package/.next/server/app/api/llm-model/subscription/route.js.nft.json +1 -1
  45. package/.next/server/app/api/mcp/[name]/route.js +5 -5
  46. package/.next/server/app/api/mcp/[name]/route.js.nft.json +1 -1
  47. package/.next/server/app/api/mcp/oauth/callback/route.js +5 -5
  48. package/.next/server/app/api/mcp/oauth/callback/route.js.nft.json +1 -1
  49. package/.next/server/app/api/mcp/route.js +5 -5
  50. package/.next/server/app/api/mcp/route.js.nft.json +1 -1
  51. package/.next/server/app/api/mcp/tools/route.js +5 -5
  52. package/.next/server/app/api/mcp/tools/route.js.nft.json +1 -1
  53. package/.next/server/app/api/memory/edit/route.js +15 -14
  54. package/.next/server/app/api/memory/edit/route.js.nft.json +1 -1
  55. package/.next/server/app/api/memory/route.js +4 -4
  56. package/.next/server/app/api/memory/route.js.nft.json +1 -1
  57. package/.next/server/app/api/reach/route.js +13 -12
  58. package/.next/server/app/api/reach/route.js.nft.json +1 -1
  59. package/.next/server/app/api/routine/route.js +8 -9
  60. package/.next/server/app/api/routine/route.js.nft.json +1 -1
  61. package/.next/server/app/api/signins/route.js.nft.json +1 -1
  62. package/.next/server/app/api/skills/[source]/[name]/route.js +2 -2
  63. package/.next/server/app/api/skills/[source]/[name]/route.js.nft.json +1 -1
  64. package/.next/server/app/api/skills/route.js +2 -2
  65. package/.next/server/app/api/skills/route.js.nft.json +1 -1
  66. package/.next/server/app/api/thursday/call/route.js +6 -6
  67. package/.next/server/app/api/thursday/call/route.js.nft.json +1 -1
  68. package/.next/server/app/api/thursday/skills/route.js +6 -6
  69. package/.next/server/app/api/thursday/skills/route.js.nft.json +1 -1
  70. package/.next/server/app/api/thursday/text/route.js +14 -13
  71. package/.next/server/app/api/thursday/text/route.js.nft.json +1 -1
  72. package/.next/server/app/api/thursday/tool-call/route.js +15 -14
  73. package/.next/server/app/api/thursday/tool-call/route.js.nft.json +1 -1
  74. package/.next/server/app/api/workspace/files/route.js +10 -6
  75. package/.next/server/app/api/workspace/files/route.js.nft.json +1 -1
  76. package/.next/server/app/api/workspace/route.js +9 -4
  77. package/.next/server/app/api/workspace/route.js.nft.json +1 -1
  78. package/.next/server/app/artifact/[...path]/page/server-reference-manifest.json +2 -2
  79. package/.next/server/app/artifact/[...path]/page.js +5 -4
  80. package/.next/server/app/artifact/[...path]/page.js.nft.json +1 -1
  81. package/.next/server/app/artifact/[...path]/page_client-reference-manifest.js +1 -1
  82. package/.next/server/app/favicon.ico/route.js.nft.json +1 -1
  83. package/.next/server/app/manifest.webmanifest/route.js.nft.json +1 -1
  84. package/.next/server/app/page/server-reference-manifest.json +67 -56
  85. package/.next/server/app/page.js +10 -11
  86. package/.next/server/app/page.js.nft.json +1 -1
  87. package/.next/server/app/page_client-reference-manifest.js +1 -1
  88. package/.next/server/chunks/{[root-of-the-server]__0o49ztf._.js → [root-of-the-server]__0-k4_ie._.js} +2 -2
  89. package/.next/server/chunks/[root-of-the-server]__0209ah4._.js +6 -6
  90. package/.next/server/chunks/[root-of-the-server]__04wldw9._.js +1 -1
  91. package/.next/server/chunks/[root-of-the-server]__0h_x6q6._.js +2 -2
  92. package/.next/server/chunks/[root-of-the-server]__0i23tc1._.js +3 -0
  93. package/.next/server/chunks/[root-of-the-server]__0mrk2it._.js +1 -1
  94. package/.next/server/chunks/[root-of-the-server]__0nr-v8s._.js +1 -1
  95. package/.next/server/chunks/[root-of-the-server]__0paqm5y._.js +3 -0
  96. package/.next/server/chunks/[root-of-the-server]__0qog7sm._.js +8 -0
  97. package/.next/server/chunks/[root-of-the-server]__0sm5xvm._.js +1 -1
  98. package/.next/server/chunks/[root-of-the-server]__0yisc5v._.js +5 -0
  99. package/.next/server/chunks/[root-of-the-server]__1-swlkw._.js +3 -3
  100. package/.next/server/chunks/[root-of-the-server]__12iddfq._.js +2 -2
  101. package/.next/server/chunks/[root-of-the-server]__15p29m3._.js +3 -0
  102. package/.next/server/chunks/[root-of-the-server]__17ses32._.js +3 -0
  103. package/.next/server/chunks/[root-of-the-server]__18-2tsq._.js +2 -2
  104. package/.next/server/chunks/[root-of-the-server]__1cjxw0-._.js +1 -1
  105. package/.next/server/chunks/[root-of-the-server]__1gi2nns._.js +5 -0
  106. package/.next/server/chunks/[root-of-the-server]__1iauz8a._.js +3 -0
  107. package/.next/server/chunks/[root-of-the-server]__1k3j52n._.js +1 -1
  108. package/.next/server/chunks/{[root-of-the-server]__209k6pk._.js → [root-of-the-server]__1lb_pxg._.js} +2 -2
  109. package/.next/server/chunks/[root-of-the-server]__1ndi14y._.js +1 -1
  110. package/.next/server/chunks/[root-of-the-server]__1orn-5b._.js +1 -1
  111. package/.next/server/chunks/[root-of-the-server]__1xqsrqq._.js +5 -0
  112. package/.next/server/chunks/[root-of-the-server]__1ygplx1._.js +1 -1
  113. package/.next/server/chunks/[root-of-the-server]__2163i40._.js +5 -0
  114. package/.next/server/chunks/_0ci0abh._.js +3 -0
  115. package/.next/server/chunks/_0eauz4t._.js +1 -1
  116. package/.next/server/chunks/_0f6ts7z._.js +1 -1
  117. package/.next/server/chunks/_0fg-1oj._.js +5 -0
  118. package/.next/server/chunks/_0khihjk._.js +2 -2
  119. package/.next/server/chunks/_0n74zsf._.js +1 -1
  120. package/.next/server/chunks/_0na2fj1._.js +2 -2
  121. package/.next/server/chunks/_0oh_99-._.js +3 -0
  122. package/.next/server/chunks/_0x-ej3f._.js +24 -24
  123. package/.next/server/chunks/_0z3nz21._.js +3 -0
  124. package/.next/server/chunks/_10tkr26._.js +1 -1
  125. package/.next/server/chunks/_12-amdu._.js +2 -2
  126. package/.next/server/chunks/_136j09a._.js +1 -1
  127. package/.next/server/chunks/_15740dw._.js +1 -1
  128. package/.next/server/chunks/_18izeh1._.js +5 -0
  129. package/.next/server/chunks/_1_5mnq4._.js +1 -1
  130. package/.next/server/chunks/_1ajbhv6._.js +2 -2
  131. package/.next/server/chunks/_1dc_d1q._.js +2 -2
  132. package/.next/server/chunks/_1drgfx4._.js +1 -1
  133. package/.next/server/chunks/_1e48czp._.js +2 -2
  134. package/.next/server/chunks/_1f06zo4._.js +3 -0
  135. package/.next/server/chunks/_1ic3bew._.js +2 -2
  136. package/.next/server/chunks/_1jn-aep._.js +2 -2
  137. package/.next/server/chunks/_1jn5btd._.js +6 -0
  138. package/.next/server/chunks/_1kg70wc._.js +2 -2
  139. package/.next/server/chunks/_1m2i5pt._.js +5 -0
  140. package/.next/server/chunks/_1ogqovh._.js +4 -4
  141. package/.next/server/chunks/_1qxheoa._.js +1 -1
  142. package/.next/server/chunks/_1ry6afh._.js +18 -0
  143. package/.next/server/chunks/_1taa4bs._.js +1 -1
  144. package/.next/server/chunks/_1tpr507._.js +1 -1
  145. package/.next/server/chunks/_1y8w80a._.js +1 -1
  146. package/.next/server/chunks/_1zxp-p6._.js +1 -1
  147. package/.next/server/chunks/_204744f._.js +5 -0
  148. package/.next/server/chunks/_20fsr_z._.js +1 -1
  149. package/.next/server/chunks/config_ts_1g4sz5o._.js +1 -1
  150. package/.next/server/chunks/features_0-cnt0l._.js +1 -1
  151. package/.next/server/chunks/features_0hdaci0._.js +1 -1
  152. package/.next/server/chunks/features_0p85gv6._.js +3 -0
  153. package/.next/server/chunks/{node_modules_zod_v4_0_v5xf5._.js → node_modules_zod_v4_01bha1c._.js} +2 -2
  154. package/.next/server/chunks/{node_modules_zod_v4_0q9hvql._.js → node_modules_zod_v4_0b99z6a._.js} +2 -2
  155. package/.next/server/chunks/{node_modules_zod_v4_1jg8iwg._.js → node_modules_zod_v4_1zz6lo1._.js} +2 -2
  156. package/.next/server/chunks/ssr/[root-of-the-server]__04upd5v._.js +3 -0
  157. package/.next/server/chunks/ssr/[root-of-the-server]__0dxszdt._.js +3 -0
  158. package/.next/server/chunks/ssr/[root-of-the-server]__0eezycw._.js +3 -0
  159. package/.next/server/chunks/ssr/[root-of-the-server]__0hpp3nw._.js +1 -1
  160. package/.next/server/chunks/ssr/[root-of-the-server]__0yngu44._.js +3 -0
  161. package/.next/server/chunks/ssr/[root-of-the-server]__16z72ny._.js +6 -0
  162. package/.next/server/chunks/ssr/[root-of-the-server]__1u_ry86._.js +3 -0
  163. package/.next/server/chunks/ssr/{[root-of-the-server]__1iwyp1e._.js → [root-of-the-server]__1unh_ew._.js} +1 -1
  164. package/.next/server/chunks/ssr/[root-of-the-server]__20re7ya._.js +3 -0
  165. package/.next/server/chunks/ssr/_00pgq9d._.js +5 -0
  166. package/.next/server/chunks/ssr/_07ke63g._.js +3 -0
  167. package/.next/server/chunks/ssr/_0agcbk7._.js +3 -0
  168. package/.next/server/chunks/ssr/_0e-gw2_._.js +3 -0
  169. package/.next/server/chunks/ssr/{_1ybo1hd._.js → _0f_om6y._.js} +3 -3
  170. package/.next/server/chunks/ssr/_0fqhhwi._.js +1 -1
  171. package/.next/server/chunks/ssr/{_026qnc9._.js → _0gpn71k._.js} +3 -3
  172. package/.next/server/chunks/ssr/_0iizjr9._.js +3 -0
  173. package/.next/server/chunks/ssr/_0ixvzo6._.js +75 -0
  174. package/.next/server/chunks/ssr/_0kkdx7t._.js +3 -0
  175. package/.next/server/chunks/ssr/_0lufvw7._.js +118 -0
  176. package/.next/server/chunks/ssr/_0vi6ky6._.js +115 -0
  177. package/.next/server/chunks/ssr/{_0ouzu9f._.js → _0yhji3e._.js} +2 -2
  178. package/.next/server/chunks/ssr/_0z38nha._.js +3 -0
  179. package/.next/server/chunks/ssr/{_1w2oba6._.js → _11nx2d4._.js} +2 -2
  180. package/.next/server/chunks/ssr/_12mijol._.js +2 -2
  181. package/.next/server/chunks/ssr/{_19ps4p3._.js → _150463c._.js} +8 -8
  182. package/.next/server/chunks/ssr/{_1bhy4yg._.js → _17d2ikl._.js} +2 -2
  183. package/.next/server/chunks/ssr/_19jez1a._.js +3 -0
  184. package/.next/server/chunks/ssr/_1blui1m._.js +3 -0
  185. package/.next/server/chunks/ssr/_1d423aj._.js +4 -4
  186. package/.next/server/chunks/ssr/{_1kd843u._.js → _1kbk28w._.js} +2 -2
  187. package/.next/server/chunks/ssr/_1kj_r9v._.js +3 -0
  188. package/.next/server/chunks/ssr/_1mqn9mc._.js +1 -1
  189. package/.next/server/chunks/ssr/_1myh7ss._.js +3 -0
  190. package/.next/server/chunks/ssr/_1neoj22._.js +1 -1
  191. package/.next/server/chunks/ssr/_1ou5sj0._.js +3 -0
  192. package/.next/server/chunks/ssr/_1p8xorg._.js +1 -1
  193. package/.next/server/chunks/ssr/_1tzacpl._.js +3 -0
  194. package/.next/server/chunks/ssr/_1xoch6f._.js +1 -1
  195. package/.next/server/chunks/ssr/_1yh5bj5._.js +1 -1
  196. package/.next/server/chunks/ssr/{_0btzccu._.js → _2021n9-._.js} +2 -2
  197. package/.next/server/chunks/ssr/{_1kq2ye_._.js → _20argo3._.js} +2 -2
  198. package/.next/server/chunks/ssr/features_bot_1ll3wp7._.js +3 -0
  199. package/.next/server/chunks/ssr/features_bot_1s_-2vj._.js +1 -1
  200. package/.next/server/chunks/ssr/features_bot_thread_query_ts_023eklt._.js +1 -1
  201. package/.next/server/chunks/ssr/features_config_1qxe5ur._.js +20 -0
  202. package/.next/server/chunks/ssr/features_connectors_components_mcp-setting_tsx_0jmbgvp._.js +3 -3
  203. package/.next/server/chunks/ssr/features_memory_components_memory-setting_tsx_0oa43sw._.js +1 -1
  204. package/.next/server/chunks/ssr/features_routine_components_routine-setting_tsx_055fknz._.js +1 -1
  205. package/.next/server/chunks/ssr/features_workspace_00jz2hu._.js +1 -1
  206. package/.next/server/chunks/ssr/{node_modules_18jn2qo._.js → node_modules_06e0wlv._.js} +1 -1
  207. package/.next/server/chunks/ssr/{node_modules_1rjt833._.js → node_modules_0cj26-9._.js} +1 -1
  208. package/.next/server/chunks/ssr/{node_modules_0yqy-0b._.js → node_modules_0d1rf5e._.js} +1 -1
  209. package/.next/server/chunks/ssr/{node_modules_1zqddke._.js → node_modules_0e86703._.js} +1 -1
  210. package/.next/server/chunks/ssr/{node_modules_09dj429._.js → node_modules_0es09am._.js} +1 -1
  211. package/.next/server/chunks/ssr/{node_modules_1c0pg3k._.js → node_modules_0gr_dzf._.js} +1 -1
  212. package/.next/server/chunks/ssr/{node_modules_1en2jx5._.js → node_modules_0gtcwz9._.js} +1 -1
  213. package/.next/server/chunks/ssr/{node_modules_0gmdur8._.js → node_modules_0hi9h8f._.js} +1 -1
  214. package/.next/server/chunks/ssr/{node_modules_1qe-oxg._.js → node_modules_0lkop0t._.js} +1 -1
  215. package/.next/server/chunks/ssr/{node_modules_1-53ebx._.js → node_modules_0nghisk._.js} +1 -1
  216. package/.next/server/chunks/ssr/{node_modules_02zt4az._.js → node_modules_0stovz0._.js} +1 -1
  217. package/.next/server/chunks/ssr/{node_modules_11bltzp._.js → node_modules_0we85kr._.js} +1 -1
  218. package/.next/server/chunks/ssr/{node_modules_00pocul._.js → node_modules_0ya7y1s._.js} +1 -1
  219. package/.next/server/chunks/ssr/{node_modules_1p-c8cr._.js → node_modules_0yrbwkj._.js} +1 -1
  220. package/.next/server/chunks/ssr/{node_modules_06i6bli._.js → node_modules_1-x70ie._.js} +1 -1
  221. package/.next/server/chunks/ssr/{node_modules_1-y9aho._.js → node_modules_12fd9g0._.js} +1 -1
  222. package/.next/server/chunks/ssr/{node_modules_1x6uwvn._.js → node_modules_12wxrgr._.js} +1 -1
  223. package/.next/server/chunks/ssr/{node_modules_1tzw5sn._.js → node_modules_139uu4q._.js} +1 -1
  224. package/.next/server/chunks/ssr/{node_modules_0rbaymq._.js → node_modules_14gpoe1._.js} +1 -1
  225. package/.next/server/chunks/ssr/{node_modules_05ojmcl._.js → node_modules_18fmji6._.js} +1 -1
  226. package/.next/server/chunks/ssr/{node_modules_0tf8_1e._.js → node_modules_19kkel8._.js} +1 -1
  227. package/.next/server/chunks/ssr/{node_modules_1_te3bu._.js → node_modules_1gcine1._.js} +1 -1
  228. package/.next/server/chunks/ssr/{node_modules_211zgim._.js → node_modules_1h4trkm._.js} +1 -1
  229. package/.next/server/chunks/ssr/{node_modules_0evjwh1._.js → node_modules_1mub_qu._.js} +1 -1
  230. package/.next/server/chunks/ssr/{node_modules_0auzgvx._.js → node_modules_1p78svs._.js} +1 -1
  231. package/.next/server/chunks/ssr/{node_modules_0j3te-1._.js → node_modules_1xp-7ep._.js} +1 -1
  232. package/.next/server/chunks/ssr/{node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_0y51bqj._.js → node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_0ay7_oi._.js} +1 -1
  233. package/.next/server/chunks/ssr/{node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_1sc114e._.js → node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_182ydq_._.js} +1 -1
  234. package/.next/server/middleware-build-manifest.js +3 -3
  235. package/.next/server/pages/404.html +1 -1
  236. package/.next/server/pages/500.html +1 -1
  237. package/.next/server/server-reference-manifest.js +1 -1
  238. package/.next/server/server-reference-manifest.json +69 -58
  239. package/.next/static/chunks/{39gj5vxz1zpm_.js → 01xjer0i_e5z5.js} +1 -1
  240. package/.next/static/chunks/{4440mws9jz3mt.js → 025bmrgeukcb2.js} +1 -1
  241. package/.next/static/chunks/03df16hs01-xi.js +1 -0
  242. package/.next/static/chunks/{1r4zajz14jp9-.js → 04e-e--5lk26x.js} +1 -1
  243. package/.next/static/chunks/0crocb7272z8k.js +1 -0
  244. package/.next/static/chunks/{03bhu4mk8en2q.js → 0dqsenl3uk_8z.js} +1 -1
  245. package/.next/static/chunks/0hhn8mf953761.js +1 -0
  246. package/.next/static/chunks/0n1o3k0z4m7c_.js +1 -0
  247. package/.next/static/chunks/0oe2zavre2a7d.css +1 -0
  248. package/.next/static/chunks/{1qzfgplyo18tc.js → 0oyz95sujd2c7.js} +1 -1
  249. package/.next/static/chunks/0srg9tv4105-i.js +1 -0
  250. package/.next/static/chunks/0t599wrclly7i.js +18 -0
  251. package/.next/static/chunks/{2-jn4xscbm-i2.js → 0u3ktztrzu1fa.js} +1 -1
  252. package/.next/static/chunks/{0r6nwxg4dv83t.js → 0u9ae9k_2g7k3.js} +1 -1
  253. package/.next/static/chunks/0x34bhth_sn35.js +1 -0
  254. package/.next/static/chunks/{0x_w4shtvrrfg.js → 0x_6z8vt8hyf4.js} +3 -3
  255. package/.next/static/chunks/{04imzjhvzw65d.js → 1_wstwzu1md-6.js} +2 -2
  256. package/.next/static/chunks/1aughn81slf90.js +1 -0
  257. package/.next/static/chunks/1g1j03h_l-e67.js +1 -0
  258. package/.next/static/chunks/1lp02y2nmddxg.js +1 -0
  259. package/.next/static/chunks/{35wdx3wt7cg4a.js → 1u5i-jti87jbo.js} +1 -1
  260. package/.next/static/chunks/211s4xjtecj2l.js +1 -0
  261. package/.next/static/chunks/2244-cat2jlvd.js +1 -0
  262. package/.next/static/chunks/{12scesro428m7.js → 2eev_i93slion.js} +1 -1
  263. package/.next/static/chunks/{3x6pggb-2kyrk.js → 2gocl3dq0_h1s.js} +1 -1
  264. package/.next/static/chunks/{3tz4dr0_8pq1-.js → 2m267diam_vib.js} +1 -1
  265. package/.next/static/chunks/{0hzbj7f48cmx0.js → 2o4dndk0d68do.js} +1 -1
  266. package/.next/static/chunks/{0ympuji_ufypd.js → 2sdwbfs1x5skp.js} +1 -1
  267. package/.next/static/chunks/2sjq4gsimlfqr.js +113 -0
  268. package/.next/static/chunks/{39vrqy1r_00jc.js → 2uleilh8ph06-.js} +1 -1
  269. package/.next/static/chunks/{0gljzv9fz1g7d.js → 2zchsg03a1pdp.js} +1 -1
  270. package/.next/static/chunks/32tmfirfjpulv.js +1 -0
  271. package/.next/static/chunks/{26-eblxwnykck.js → 337g9g_ux2gj-.js} +1 -1
  272. package/.next/static/chunks/376-s_i83irs-.js +1 -0
  273. package/.next/static/chunks/3blk-kpn39xr-.js +1 -0
  274. package/.next/static/chunks/3eieehp7wquyu.js +1 -0
  275. package/.next/static/chunks/3kc-e7pcj50ae.js +1 -0
  276. package/.next/static/chunks/3rwpyuo9nrrop.js +17 -0
  277. package/.next/static/chunks/3sf4l25l353ja.js +1 -0
  278. package/.next/static/chunks/{0zmrz4zfzm4dt.js → 3t9huugh-5_ps.js} +1 -1
  279. package/.next/static/chunks/3vz7m1w688juj.js +3 -0
  280. package/.next/static/chunks/{2kzwhbuobpkw3.js → 43q9cgbuw8krx.js} +2 -2
  281. package/.next/static/chunks/43skgt0h9woyu.js +1 -0
  282. package/app/api/events/app-event.client.ts +8 -2
  283. package/app/api/events/app-event.server.ts +7 -5
  284. package/app/api/events/app-event.ts +19 -8
  285. package/app/api/query-key.ts +13 -5
  286. package/bin/database.mjs +21 -11
  287. package/bin/thursday.mjs +5 -2
  288. package/components/ui/shiny-text.tsx +2 -2
  289. package/database/migrations/20260920024909_messy_baron_strucker/migration.sql +1 -0
  290. package/database/migrations/20260920024909_messy_baron_strucker/snapshot.json +1937 -0
  291. package/features/ai/components/model-picker.tsx +8 -2
  292. package/features/ai/model.schema.ts +26 -0
  293. package/features/artifact/components/artifact-setting.tsx +18 -24
  294. package/features/bot/bot.action.ts +3 -0
  295. package/features/bot/bot.runner.ts +25 -3
  296. package/features/bot/bot.seed.ts +98 -22
  297. package/features/bot/components/bot-badge.tsx +2 -2
  298. package/features/bot/components/bot-mark.tsx +12 -3
  299. package/features/bot/components/bot-room.tsx +36 -16
  300. package/features/bot/components/bot-setting.tsx +88 -34
  301. package/features/bot/components/crew-motion.ts +161 -0
  302. package/features/bot/components/mark-palette.tsx +3 -3
  303. package/features/bot/components/room-conversation.tsx +13 -8
  304. package/features/bot/components/room-list.tsx +9 -5
  305. package/features/bot/components/room-pill.tsx +171 -94
  306. package/features/bot/components/thread-badge.tsx +4 -4
  307. package/features/bot/components/thread-setting.tsx +58 -19
  308. package/features/bot/mark.const.ts +24 -0
  309. package/features/bot/thread.query.ts +32 -14
  310. package/features/bot/thread.store.ts +19 -16
  311. package/features/config/components/config-badge.tsx +7 -1
  312. package/features/config/components/config-setting.tsx +83 -214
  313. package/features/config/components/models-badge.tsx +5 -7
  314. package/features/config/components/voice-key.tsx +24 -1
  315. package/features/config/config.const.ts +9 -1
  316. package/features/connectors/components/mcp-setting.tsx +60 -29
  317. package/features/intro/components/intro.tsx +4 -18
  318. package/features/memory/components/memory-setting.tsx +11 -7
  319. package/features/reach/channel.ts +9 -1
  320. package/features/reach/components/reach-guide.tsx +606 -105
  321. package/features/reach/discord.ts +18 -3
  322. package/features/reach/reach.schema.ts +6 -0
  323. package/features/reach/reach.ts +55 -2
  324. package/features/reach/slack.ts +2 -1
  325. package/features/reach/telegram.ts +5 -1
  326. package/features/routine/components/routine-setting.tsx +46 -18
  327. package/features/settings/components/setting-ui.tsx +16 -58
  328. package/features/settings/components/settings.tsx +7 -4
  329. package/features/settings/settings.alert.ts +10 -9
  330. package/features/skills/components/skills-setting.tsx +78 -12
  331. package/features/skills/skills.action.ts +12 -0
  332. package/features/skills/skills.query.ts +24 -0
  333. package/features/thursday/components/call-log.tsx +19 -14
  334. package/features/thursday/components/side-captions.tsx +3 -2
  335. package/features/thursday/components/tab-state.tsx +5 -2
  336. package/features/thursday/components/thursday-setting.tsx +5 -6
  337. package/features/thursday/components/thursday.tsx +60 -29
  338. package/features/thursday/components/write-line.tsx +19 -5
  339. package/features/thursday/thursday.action.ts +4 -0
  340. package/features/thursday/thursday.query.ts +3 -2
  341. package/features/thursday/thursday.schema.ts +5 -0
  342. package/features/thursday/use-call-ring.ts +6 -1
  343. package/features/thursday/use-text-call.ts +25 -10
  344. package/features/thursday/use-thursday.ts +10 -1
  345. package/features/workspace/components/artifact-view.tsx +42 -33
  346. package/features/workspace/components/file-thumb.tsx +8 -4
  347. package/features/workspace/components/file-view.tsx +25 -2
  348. package/features/workspace/components/workspace-setting.tsx +27 -23
  349. package/features/workspace/workspace.query.ts +20 -1
  350. package/features/workspace/workspace.ts +14 -0
  351. package/guide/bots.md +27 -4
  352. package/guide/calls.md +7 -4
  353. package/guide/phone.md +23 -12
  354. package/guide/setup.md +24 -6
  355. package/guide/trouble.md +1 -1
  356. package/hooks/use-theme.ts +14 -0
  357. package/lib/protocol/events.client.ts +56 -14
  358. package/lib/protocol/events.server.ts +41 -12
  359. package/lib/utils.ts +1 -1
  360. package/package.json +1 -1
  361. package/scripts/reach-channels.test.mts +15 -2
  362. package/seed-skills/brief/daily-brief/SKILL.md +39 -0
  363. package/seed-skills/brief/daily-brief/page/brief.css +406 -0
  364. package/seed-skills/brief/daily-brief/references/brief.md +106 -0
  365. package/seed-skills/brief/daily-brief/references/preferences.md +67 -0
  366. package/seed-skills/brief/daily-brief/scripts/glance.mjs +128 -0
  367. package/seed-skills/brief/daily-brief/scripts/lib.mjs +182 -0
  368. package/seed-skills/brief/daily-brief/scripts/news.mjs +320 -0
  369. package/seed-skills/brief/daily-brief/scripts/page.mjs +322 -0
  370. package/seed-skills/brief/daily-brief/scripts/story.mjs +265 -0
  371. package/seed-skills/digest/README.md +20 -0
  372. package/seed-skills/digest/media-digest/SKILL.md +32 -0
  373. package/seed-skills/digest/media-digest/references/no-captions.md +20 -0
  374. package/seed-skills/digest/media-digest/references/page.md +56 -0
  375. package/seed-skills/digest/media-digest/references/reading.md +56 -0
  376. package/seed-skills/digest/media-digest/scripts/audio.mjs +232 -0
  377. package/seed-skills/digest/media-digest/scripts/digest.mjs +379 -0
  378. package/seed-skills/digest/media-digest/scripts/lib.mjs +284 -0
  379. package/seed-skills/digest/media-digest/scripts/part.mjs +16 -0
  380. package/seed-skills/digest/media-digest/scripts/text.mjs +287 -0
  381. package/seed-skills/digest/media-digest/scripts/yt.mjs +487 -0
  382. package/seed-skills/docs/README.md +32 -0
  383. package/seed-skills/docs/documents/SKILL.md +34 -0
  384. package/seed-skills/docs/documents/kit/package-lock.json +1596 -0
  385. package/seed-skills/docs/documents/kit/package.json +17 -0
  386. package/seed-skills/docs/documents/references/deck.md +63 -0
  387. package/seed-skills/docs/documents/references/invoice.md +64 -0
  388. package/seed-skills/docs/documents/references/pdf.md +59 -0
  389. package/seed-skills/docs/documents/references/print.md +43 -0
  390. package/seed-skills/docs/documents/references/sheets.md +49 -0
  391. package/seed-skills/docs/documents/references/translate.md +37 -0
  392. package/seed-skills/docs/documents/references/word.md +45 -0
  393. package/seed-skills/docs/documents/scripts/doc.mjs +123 -0
  394. package/seed-skills/docs/documents/scripts/lib/browser.mjs +259 -0
  395. package/seed-skills/docs/documents/scripts/lib/deck-chart.mjs +150 -0
  396. package/seed-skills/docs/documents/scripts/lib/deck.mjs +1132 -0
  397. package/seed-skills/docs/documents/scripts/lib/invoice.mjs +505 -0
  398. package/seed-skills/docs/documents/scripts/lib/kit.mjs +244 -0
  399. package/seed-skills/docs/documents/scripts/lib/pdf.mjs +645 -0
  400. package/seed-skills/docs/documents/scripts/lib/report.mjs +38 -0
  401. package/seed-skills/docs/documents/scripts/lib/sheet.mjs +523 -0
  402. package/seed-skills/docs/documents/scripts/lib/templates.mjs +34 -0
  403. package/seed-skills/docs/documents/scripts/lib/translate.mjs +691 -0
  404. package/seed-skills/docs/documents/scripts/lib/word.mjs +678 -0
  405. package/seed-skills/docs/documents/templates/letter.html +56 -0
  406. package/seed-skills/docs/documents/templates/print.css +219 -0
  407. package/seed-skills/docs/documents/templates/report.html +47 -0
  408. package/seed-skills/docs/documents/templates/resume.html +61 -0
  409. package/seed-skills/insta/instagram/references/post.md +31 -7
  410. package/seed-skills/trip/README.md +11 -0
  411. package/seed-skills/trip/travel/SKILL.md +40 -0
  412. package/seed-skills/trip/travel/page/itinerary.css +488 -0
  413. package/seed-skills/trip/travel/references/itinerary.md +70 -0
  414. package/seed-skills/trip/travel/references/plan.md +75 -0
  415. package/seed-skills/trip/travel/references/watch-and-book.md +39 -0
  416. package/seed-skills/trip/travel/scripts/flights.mjs +374 -0
  417. package/seed-skills/trip/travel/scripts/fx.mjs +57 -0
  418. package/seed-skills/trip/travel/scripts/hotels.mjs +356 -0
  419. package/seed-skills/trip/travel/scripts/itinerary.mjs +482 -0
  420. package/seed-skills/trip/travel/scripts/lib.mjs +120 -0
  421. package/seed-skills/trip/travel/scripts/selectors.mjs +78 -0
  422. package/seed-skills/trip/travel/scripts/watch.mjs +147 -0
  423. package/seed-skills/trip/travel/scripts/weather.mjs +150 -0
  424. package/seed-skills/tutor/picture-book/SKILL.md +6 -0
  425. package/seed-skills/tutor/picture-book/references/picture-book.md +22 -2
  426. package/.next/server/chunks/[root-of-the-server]__014ydvq._.js +0 -8
  427. package/.next/server/chunks/[root-of-the-server]__01d285y._.js +0 -5
  428. package/.next/server/chunks/[root-of-the-server]__04r4h-2._.js +0 -7
  429. package/.next/server/chunks/[root-of-the-server]__0ayldfn._.js +0 -5
  430. package/.next/server/chunks/[root-of-the-server]__0cfszwn._.js +0 -3
  431. package/.next/server/chunks/[root-of-the-server]__0npn_pn._.js +0 -3
  432. package/.next/server/chunks/[root-of-the-server]__0rqgb17._.js +0 -3
  433. package/.next/server/chunks/[root-of-the-server]__17weeeg._.js +0 -5
  434. package/.next/server/chunks/[root-of-the-server]__1ai5lme._.js +0 -8
  435. package/.next/server/chunks/[root-of-the-server]__1tg5got._.js +0 -3
  436. package/.next/server/chunks/_05v8k21._.js +0 -7
  437. package/.next/server/chunks/_0k6qjcf._.js +0 -5
  438. package/.next/server/chunks/_1d_enhu._.js +0 -3
  439. package/.next/server/chunks/_1jc5g4p._.js +0 -6
  440. package/.next/server/chunks/_1nfr-75._.js +0 -3
  441. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_0md6j0x._.js +0 -3
  442. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_14ih1vy._.js +0 -3
  443. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1d6ez5-._.js +0 -3
  444. package/.next/server/chunks/ssr/[root-of-the-server]__0m7u9j-._.js +0 -3
  445. package/.next/server/chunks/ssr/[root-of-the-server]__0tzekbl._.js +0 -68
  446. package/.next/server/chunks/ssr/[root-of-the-server]__1756892._.js +0 -3
  447. package/.next/server/chunks/ssr/[root-of-the-server]__1cz2rz5._.js +0 -3
  448. package/.next/server/chunks/ssr/[root-of-the-server]__1mzi-ju._.js +0 -3
  449. package/.next/server/chunks/ssr/[root-of-the-server]__1nqw56a._.js +0 -3
  450. package/.next/server/chunks/ssr/[root-of-the-server]__1w9hqq8._.js +0 -8
  451. package/.next/server/chunks/ssr/_05pl_u8._.js +0 -3
  452. package/.next/server/chunks/ssr/_097-ljd._.js +0 -4
  453. package/.next/server/chunks/ssr/_0evkpto._.js +0 -3
  454. package/.next/server/chunks/ssr/_0hjzb5o._.js +0 -3
  455. package/.next/server/chunks/ssr/_0lu1n_x._.js +0 -3
  456. package/.next/server/chunks/ssr/_0u7ko71._.js +0 -3
  457. package/.next/server/chunks/ssr/_0wd_o8-._.js +0 -3
  458. package/.next/server/chunks/ssr/_0ya0cb0._.js +0 -3
  459. package/.next/server/chunks/ssr/_10yyqtk._.js +0 -67
  460. package/.next/server/chunks/ssr/_12eyown._.js +0 -5
  461. package/.next/server/chunks/ssr/_132qkfz._.js +0 -5
  462. package/.next/server/chunks/ssr/_15zqt-t._.js +0 -3
  463. package/.next/server/chunks/ssr/_184327j._.js +0 -3
  464. package/.next/server/chunks/ssr/_1q683w8._.js +0 -20
  465. package/.next/server/chunks/ssr/_1tawxu2._.js +0 -3
  466. package/.next/server/chunks/ssr/_1xx4zlb._.js +0 -3
  467. package/.next/server/chunks/ssr/features_bot_0s11m4r._.js +0 -3
  468. package/.next/static/chunks/03-724sj0nk_z.js +0 -3
  469. package/.next/static/chunks/0c_g4-11sha-1.js +0 -1
  470. package/.next/static/chunks/0h0lythv1ql93.js +0 -1
  471. package/.next/static/chunks/0lwunwbl7u7pt.js +0 -1
  472. package/.next/static/chunks/0rn9nbg6aif9f.js +0 -17
  473. package/.next/static/chunks/0vlgzqo9ka90v.js +0 -1
  474. package/.next/static/chunks/11tlxkr7a_rpc.js +0 -1
  475. package/.next/static/chunks/16s2fx3890_jd.js +0 -65
  476. package/.next/static/chunks/1g9yyvculuxj2.js +0 -1
  477. package/.next/static/chunks/1s6m4cmbn7htf.js +0 -1
  478. package/.next/static/chunks/1wl9t1-3i-q8p.css +0 -1
  479. package/.next/static/chunks/2-asot3p1j3yg.js +0 -1
  480. package/.next/static/chunks/22h9gvclqtx_2.js +0 -1
  481. package/.next/static/chunks/23nfu5g4vl_m7.js +0 -1
  482. package/.next/static/chunks/2m6jd3586ijb-.js +0 -1
  483. package/.next/static/chunks/2ndw4w4u2x51r.js +0 -1
  484. package/.next/static/chunks/304q9p54tcgm1.js +0 -1
  485. package/.next/static/chunks/37unh9460im7v.js +0 -18
  486. package/.next/static/chunks/3dipmu0mptqum.js +0 -1
  487. package/.next/static/chunks/3gki-squw28yu.js +0 -1
  488. package/.next/static/chunks/3nnzdl_te20hv.js +0 -1
  489. package/features/reach/components/reach-state.tsx +0 -71
  490. /package/.next/static/{En1vUPazxcYjPjnnahcN5 → fiNGsQfna8qldl8wU8wqr}/_buildManifest.js +0 -0
  491. /package/.next/static/{En1vUPazxcYjPjnnahcN5 → fiNGsQfna8qldl8wU8wqr}/_clientMiddlewareManifest.js +0 -0
  492. /package/.next/static/{En1vUPazxcYjPjnnahcN5 → fiNGsQfna8qldl8wU8wqr}/_ssgManifest.js +0 -0
@@ -20,7 +20,11 @@ import type {
20
20
  MediaKind,
21
21
  TextModelProviderId,
22
22
  } from "../model.schema";
23
- import { canMakeKind, MEDIA_MODEL_PROVIDERS } from "../model.schema";
23
+ import {
24
+ canMakeKind,
25
+ MEDIA_MODEL_PROVIDERS,
26
+ TEXT_MODEL_PROVIDERS,
27
+ } from "../model.schema";
24
28
  import { ChatGptSignIn } from "./chatgpt-sign-in";
25
29
  import { ModelBrowser } from "./model-browser";
26
30
  import { ProviderIcon } from "./provider-icon";
@@ -312,7 +316,9 @@ function AskForKey({
312
316
  <Input
313
317
  value={value}
314
318
  onChange={(event) => setValue(event.target.value)}
315
- placeholder={provider.apiKeyName}
319
+ placeholder={
320
+ TEXT_MODEL_PROVIDERS[provider.id].keyLooks ?? "Paste the key"
321
+ }
316
322
  spellCheck={false}
317
323
  type="password"
318
324
  />
@@ -378,12 +378,18 @@ export const TEXT_MODEL_PROVIDERS: Record<
378
378
  apiKeyName: string;
379
379
  /** Reached by signing in to an account rather than a pasted key; `apiKeyName` is where the sign-in is kept. */
380
380
  signIn?: true;
381
+ /** Where a key is made: the link beside its field. */
382
+ keysAt?: string;
383
+ /** How a key begins, shown in its empty field in place of the setting's name. */
384
+ keyLooks?: string;
381
385
  suggestModels: SuggestModel[];
382
386
  }
383
387
  > = {
384
388
  openai: {
385
389
  label: "Open AI",
386
390
  apiKeyName: "OPENAI_API_KEY",
391
+ keysAt: "https://platform.openai.com/api-keys",
392
+ keyLooks: "sk-…",
387
393
  suggestModels: [
388
394
  {
389
395
  id: "gpt-5.6-luna",
@@ -450,6 +456,8 @@ export const TEXT_MODEL_PROVIDERS: Record<
450
456
  anthropic: {
451
457
  label: "Claude",
452
458
  apiKeyName: "ANTHROPIC_API_KEY",
459
+ keysAt: "https://platform.claude.com/settings/keys",
460
+ keyLooks: "sk-ant-…",
453
461
  suggestModels: [
454
462
  { id: "claude-haiku-4-5", label: "Haiku 4.5", tier: "small" },
455
463
  {
@@ -470,6 +478,8 @@ export const TEXT_MODEL_PROVIDERS: Record<
470
478
  google: {
471
479
  label: "Gemini",
472
480
  apiKeyName: "GOOGLE_GENERATIVE_AI_API_KEY",
481
+ keysAt: "https://aistudio.google.com/apikey",
482
+ keyLooks: "AIza…",
473
483
  suggestModels: [
474
484
  {
475
485
  id: "gemini-3.5-flash-lite",
@@ -488,6 +498,8 @@ export const TEXT_MODEL_PROVIDERS: Record<
488
498
  xai: {
489
499
  label: "xAI",
490
500
  apiKeyName: "XAI_API_KEY",
501
+ keysAt: "https://console.x.ai",
502
+ keyLooks: "xai-…",
491
503
  suggestModels: [
492
504
  { id: "grok-4.6", label: "Grok 4.6", tier: "large", context: 500_000 },
493
505
  ],
@@ -499,6 +511,8 @@ export const TEXT_MODEL_PROVIDERS: Record<
499
511
  "vercel-ai-gateway": {
500
512
  label: "Vercel AI GateWay",
501
513
  apiKeyName: "AI_GATEWAY_API_KEY",
514
+ keysAt:
515
+ "https://vercel.com/docs/ai-gateway/authentication-and-byok/authentication",
502
516
  suggestModels: [
503
517
  { id: "zai/glm-5.3-flash", label: "GLM 5.3 Flash", tier: "small" },
504
518
  {
@@ -554,6 +568,7 @@ export const TEXT_MODEL_PROVIDERS: Record<
554
568
  mistral: {
555
569
  label: "Mistral",
556
570
  apiKeyName: "MISTRAL_API_KEY",
571
+ keysAt: "https://console.mistral.ai/api-keys",
557
572
  suggestModels: [
558
573
  { id: "ministral-8b-latest", label: "Ministral 8B", tier: "small" },
559
574
  { id: "mistral-small-latest", label: "Small", tier: "mid" },
@@ -564,6 +579,8 @@ export const TEXT_MODEL_PROVIDERS: Record<
564
579
  deepseek: {
565
580
  label: "DeepSeek",
566
581
  apiKeyName: "DEEPSEEK_API_KEY",
582
+ keysAt: "https://platform.deepseek.com/api_keys",
583
+ keyLooks: "sk-…",
567
584
  suggestModels: [
568
585
  {
569
586
  id: "deepseek-flash",
@@ -583,6 +600,8 @@ export const TEXT_MODEL_PROVIDERS: Record<
583
600
  groq: {
584
601
  label: "Groq",
585
602
  apiKeyName: "GROQ_API_KEY",
603
+ keysAt: "https://console.groq.com/keys",
604
+ keyLooks: "gsk_…",
586
605
  suggestModels: [
587
606
  {
588
607
  id: "openai/gpt-oss-20b",
@@ -608,6 +627,8 @@ export const TEXT_MODEL_PROVIDERS: Record<
608
627
  cerebras: {
609
628
  label: "Cerebras",
610
629
  apiKeyName: "CEREBRAS_API_KEY",
630
+ keysAt: "https://cloud.cerebras.ai",
631
+ keyLooks: "csk-…",
611
632
  suggestModels: [
612
633
  {
613
634
  id: "qwen-3.8-27b",
@@ -626,6 +647,7 @@ export const TEXT_MODEL_PROVIDERS: Record<
626
647
  togetherai: {
627
648
  label: "Together",
628
649
  apiKeyName: "TOGETHER_AI_API_KEY",
650
+ keysAt: "https://api.together.ai/settings/api-keys",
629
651
  suggestModels: [
630
652
  {
631
653
  id: "Qwen/Qwen3.5-9B",
@@ -668,6 +690,8 @@ export const TEXT_MODEL_PROVIDERS: Record<
668
690
  fireworks: {
669
691
  label: "Fireworks",
670
692
  apiKeyName: "FIREWORKS_API_KEY",
693
+ keysAt: "https://app.fireworks.ai/account/api-keys",
694
+ keyLooks: "fw_…",
671
695
  suggestModels: [
672
696
  {
673
697
  id: "accounts/fireworks/models/glm-5p3-flash",
@@ -704,6 +728,7 @@ export const TEXT_MODEL_PROVIDERS: Record<
704
728
  deepinfra: {
705
729
  label: "DeepInfra",
706
730
  apiKeyName: "DEEPINFRA_API_KEY",
731
+ keysAt: "https://deepinfra.com/dash/api_keys",
707
732
  suggestModels: [
708
733
  {
709
734
  id: "deepseek-ai/DeepSeek-V4-Flash-0731",
@@ -740,6 +765,7 @@ export const TEXT_MODEL_PROVIDERS: Record<
740
765
  cohere: {
741
766
  label: "Cohere",
742
767
  apiKeyName: "COHERE_API_KEY",
768
+ keysAt: "https://dashboard.cohere.com/api-keys",
743
769
  suggestModels: [
744
770
  {
745
771
  id: "command-r7b-12-2024",
@@ -23,6 +23,7 @@ import type {
23
23
  import type { Bot } from "@/features/bot/bot.schema";
24
24
  import { BotMark } from "@/features/bot/components/bot-mark";
25
25
  import {
26
+ PICKED_ROW,
26
27
  SettingError,
27
28
  SettingFilter,
28
29
  SettingPanes,
@@ -90,7 +91,7 @@ export function ArtifactSetting() {
90
91
  <>
91
92
  <SettingRailNote>
92
93
  <span className="font-mono">
93
- <span className="font-medium text-foreground">artifacts</span>
94
+ <span className="font-medium text-foreground">finished</span>
94
95
  {` · ${countLine(entries, total, data?.files ?? 0)}`}
95
96
  </span>
96
97
  </SettingRailNote>
@@ -109,7 +110,7 @@ export function ArtifactSetting() {
109
110
  <SettingFilter
110
111
  value={filter}
111
112
  onChange={setFilter}
112
- placeholder="Filter artifacts"
113
+ placeholder="Filter files"
113
114
  className="mx-2 mb-1.5 w-auto"
114
115
  />
115
116
 
@@ -177,7 +178,7 @@ export function ArtifactSetting() {
177
178
  onPick={(row) => setReading({ row, file: null })}
178
179
  />
179
180
  ) : (
180
- <Nothing empty={total === 0} onReveal={() => reveal("artifacts")} />
181
+ <Nothing empty={total === 0} />
181
182
  )
182
183
  }
183
184
  />
@@ -211,13 +212,13 @@ function markOf(name: string, bots?: Bot[]) {
211
212
  };
212
213
  }
213
214
 
214
- /** `4 artifacts · 34 files`, and what is not on screen. Counts rows, so it is free. */
215
+ /** `4 results · 34 files`, and what is not on screen. Counts rows, so it is free. */
215
216
  function countLine(shown: Artifact[], total: number, files: number): string {
216
217
  if (total === 0) return "empty";
217
218
  const head =
218
219
  total > shown.length
219
- ? `${shown.length} of ${total.toLocaleString("en")} artifacts`
220
- : `${total} ${total === 1 ? "artifact" : "artifacts"}`;
220
+ ? `${shown.length} of ${total.toLocaleString("en")} results`
221
+ : `${total} ${total === 1 ? "result" : "results"}`;
221
222
  return files > total ? `${head} · ${files.toLocaleString("en")} files` : head;
222
223
  }
223
224
 
@@ -242,7 +243,7 @@ function BotRow({
242
243
  className={cn(
243
244
  "mx-2 flex h-9 items-center gap-2 rounded-md px-2 text-left text-[13px] outline-none focus-visible:ring-3 focus-visible:ring-ring/50 focus-visible:ring-inset",
244
245
  active
245
- ? "bg-secondary font-medium text-foreground"
246
+ ? cn(PICKED_ROW, "font-medium")
246
247
  : "text-muted-foreground hover:bg-muted/60 hover:text-foreground",
247
248
  )}
248
249
  >
@@ -341,12 +342,13 @@ function Reader({
341
342
  >
342
343
  <FolderOpen />
343
344
  </Button>
345
+ {/* set apart from Reveal beside it, and red on the way in: the file goes from disk */}
344
346
  <Button
345
347
  size="icon-sm"
346
348
  variant="ghost"
347
349
  aria-label="Delete"
348
350
  loading={removing}
349
- className="text-muted-foreground"
351
+ className="ml-1.5 text-muted-foreground hover:text-destructive"
350
352
  onClick={() => confirmRemove(open?.path ?? row.path)}
351
353
  >
352
354
  <Trash2 />
@@ -433,7 +435,7 @@ function Thumb({ file }: { file: ArtifactFile }) {
433
435
  path={file.path}
434
436
  bytes={file.bytes}
435
437
  glyph="size-5"
436
- className="aspect-4/3 w-full rounded-xl"
438
+ className="aspect-4/3 w-full rounded-xl ring-1 ring-foreground/5 ring-inset"
437
439
  />
438
440
  );
439
441
  }
@@ -487,13 +489,15 @@ function Shelf({
487
489
  path={row.path}
488
490
  bytes={row.bytes}
489
491
  glyph="size-5"
490
- className="aspect-4/3 w-full rounded-xl"
492
+ className="aspect-4/3 w-full rounded-xl ring-1 ring-foreground/5 ring-inset"
491
493
  />
492
494
  )}
493
495
  <span className="min-w-0 space-y-0.5 px-0.5">
494
496
  <span className="block truncate text-[13px]">{row.name}</span>
495
497
  <span className="block truncate font-mono text-[10.5px] text-muted-foreground">
496
- {row.kind === "set" ? `${row.count} files · ` : ""}
498
+ {row.kind === "set"
499
+ ? `${row.count} ${row.count === 1 ? "file" : "files"} · `
500
+ : ""}
497
501
  {shortAgo(row.at)}
498
502
  </span>
499
503
  </span>
@@ -506,25 +510,15 @@ function Shelf({
506
510
  );
507
511
  }
508
512
 
509
- /** The right pane with nothing to show: what lands here, and where it comes from. */
510
- function Nothing({
511
- empty,
512
- onReveal,
513
- }: {
514
- empty: boolean;
515
- onReveal: () => void;
516
- }) {
513
+ /** The right pane with nothing to show: what lands here, and where it comes from. Reveal folder is the footer's. */
514
+ function Nothing({ empty }: { empty: boolean }) {
517
515
  return (
518
- <div className="space-y-4 p-8">
516
+ <div className="p-8">
519
517
  <p className="max-w-lg text-sm leading-relaxed text-muted-foreground">
520
518
  {empty
521
519
  ? "Nothing finished yet. When a bot ends a job with something to hand over — a page, a report, a set of pictures — it lands here."
522
520
  : "Pick something on the left. Each bot's work is under its face; a folder it filled is one row, and opens as a sheet."}
523
521
  </p>
524
- <Button variant="outline" onClick={onReveal}>
525
- <FolderOpen />
526
- Reveal folder
527
- </Button>
528
522
  </div>
529
523
  );
530
524
  }
@@ -3,6 +3,7 @@
3
3
  import { z } from "zod";
4
4
  import { textModelProviderSchema } from "@/features/ai/model.schema";
5
5
  import { giveSeedSkills } from "@/features/skills/skills.discover";
6
+ import { removeBotFolder } from "@/features/workspace/workspace";
6
7
  import { serverAction } from "@/lib/protocol/server-action";
7
8
  import { publicError } from "@/lib/public-error";
8
9
  import {
@@ -82,6 +83,8 @@ export const createSeedBotsAction = serverAction(async (picks: unknown) => {
82
83
 
83
84
  export const deleteBotAction = serverAction(async (name: string) => {
84
85
  if (!(await deleteBot(name))) publicError("Bot not found");
86
+ // The row is not the whole bot: what it kept is on disk under its name
87
+ await removeBotFolder(name);
85
88
  });
86
89
 
87
90
  /** Switched off, no bot is shown its own memory. What is already written stays on disk. */
@@ -252,10 +252,15 @@ async function drive(work: RoomWork, signal: AbortSignal) {
252
252
  await finishRoomWork(work, final.text);
253
253
  const thread = await findThread(work.threadId);
254
254
  if (thread?.status === "done") {
255
+ // An answer is written for the screen; what says it elsewhere says it as words
256
+ const words = plainText(thread.outcome ?? "").slice(
257
+ 0,
258
+ FINISHED_NOTICE.words,
259
+ );
255
260
  // With a page open the page tells it (artifact-view): a notification it shows brings
256
261
  // Thursday forward when pressed, where the OS one opens the script runner behind it
257
262
  if (!presence.watching && !(await isAnyCallLive()))
258
- desktopNotify(thread.label, thread.outcome ?? "");
263
+ desktopNotify(thread.label, words);
259
264
  const files = await filesOnDisk(pathsIn(thread.outcome ?? ""), null);
260
265
  // A page to read leads the notice; the rest follow in the order they were written.
261
266
  const lead = files.findIndex(opensOnFinish);
@@ -264,7 +269,7 @@ async function drive(work: RoomWork, signal: AbortSignal) {
264
269
  threadId: thread.id,
265
270
  label: thread.label,
266
271
  bot: thread.bot,
267
- words: plainText(thread.outcome ?? "").slice(0, FINISHED_NOTICE.words),
272
+ words,
268
273
  paths:
269
274
  lead > 0
270
275
  ? [files[lead], ...files.filter((_, at) => at !== lead)]
@@ -507,13 +512,30 @@ async function removeLockedThread(id: string) {
507
512
  return removed;
508
513
  }
509
514
 
510
- export async function removeFinishedThreads(): Promise<number> {
515
+ /**
516
+ * Removes jobs that are over, with everything they held. With `endedBefore` only
517
+ * the ones that ended before then go, which is how the app clears by age
518
+ * (instrumentation, config HISTORY_KEEP); without it, all of them, which is the
519
+ * user pressing Clear finished. A job is taken under its lock and read again
520
+ * inside it, so one picked back up in that moment is left alone.
521
+ */
522
+ export async function removeFinishedThreads(
523
+ endedBefore?: Date,
524
+ ): Promise<number> {
525
+ const cutoff = endedBefore?.getTime();
526
+ // The same age a job's files are judged by (sweepJobFiles): a thread is only
527
+ // stamped `endedAt` on done and cancelled, so `updatedAt` stands in for the rest.
528
+ const over = (thread: { endedAt: Date | null; updatedAt: Date }) =>
529
+ cutoff === undefined ||
530
+ (thread.endedAt ?? thread.updatedAt).getTime() < cutoff;
511
531
  let removed = 0;
512
532
  for (const thread of await listThreadFolders()) {
513
533
  if (thread.status !== "done" && thread.status !== "cancelled") continue;
534
+ if (!over(thread)) continue;
514
535
  await threadLock(thread.id, async () => {
515
536
  const current = await findThread(thread.id);
516
537
  if (current?.status !== "done" && current?.status !== "cancelled") return;
538
+ if (!over(current)) return;
517
539
  if (await removeLockedThread(thread.id)) removed += 1;
518
540
  });
519
541
  }
@@ -48,27 +48,6 @@ export const BOT_SEEDS: BotSeed[] = [
48
48
  hint: "Takes whatever nobody else is for",
49
49
  systemPrompt: "",
50
50
  },
51
- {
52
- name: "Planner",
53
- description:
54
- "Any job that needs a team — decides what done means, assigns the parts, checks them, signs off",
55
- hint: "Runs the job: assigns, checks, decides",
56
- systemPrompt: `You run the team the way a chief executive runs a company: accountable for the result, not the one who produces it. A job comes in as a request and goes out as one finished result. Between the two you decide what done means, give each part to whoever on Bots is best placed for it, hold every part to what it was asked for, and make the calls nobody else can. A part is yours only when nobody on Bots fits it.
57
-
58
- **Decide what done means, first.** Before anything is handed out, send Thursday one \`${TOOL_NAMES.send_message}\` question holding everything only the user can decide — which one, how much, by when, in what form — with options where they fit. What you can find out, or the request already says, is not asked. After that, a doubt a reasonable choice settles is yours: decide, write \`Ruling: <what> — <why>\` in the plan, and keep going. Only what cannot be undone goes back to Thursday.
59
-
60
- **Staff it to its size.** A job one bot can do goes whole to that bot. Split only where parts run at the same time or need different strengths, and never let two parts write the same file at once.
61
-
62
- **The plan is the one record.** \`plan.md\` in the job's scratch folder holds the goal; the facts every part needs (the user's answers, names, dates, units); one line per part, \`- [ ] <what exists when done, and how it will be checked> — <who> → <path>\`; then rulings and misses. Read it before every decision and update it as each part lands. Send the checklist to Thursday as a \`message\` once it is written.
63
-
64
- **A brief is an assignment finished without asking you.** The goal and how it will be judged; the facts from \`plan.md\` it needs; the files to read; where to write — the part's own folder in scratch, the bot's own folder under \`artifacts/\` for what the user opens, \`projects/\` for code that outlives the job; what not to touch because another part owns it; what to send back — a few lines and the paths. Send every part that waits on nothing in the same step; a part that needs another's output goes out once that file exists.
65
-
66
- **Judge the work, not the report.** Open what a part wrote and test it against its line — values, units, names and dates agreeing across parts — then tick it. Short or wrong: back to the same bot once, saying exactly what. Short again: another bot or another way, never the same brief twice. A third miss stops that part: ask Thursday how to go on, with what was tried. Every miss goes in the plan.
67
-
68
- **Your memory is how the team gets better.** Keep a file for each: which bot did which kind of part well or badly; briefs that worked; jobs that come back and where their results live. Date each line, merge rather than add, delete what proved wrong. Never a job's contents — those stay in its files. The team changes: a bot you remember may be gone, so staff from Bots as it is now.
69
-
70
- **Sign off on one result.** Put the deliverable together from the part files. Your final text says what was done, where it is, who did which part, the rulings you made, and what is unverified and why.`,
71
- },
72
51
  {
73
52
  name: "Analyst",
74
53
  description:
@@ -106,6 +85,25 @@ Your final text gives the answer with its numbers, what is not solid, and the pa
106
85
  **Start where they are.** Your memory keeps what the user already knows and how they liked being taught: the level, a picture style, how many pages. Read it before the story, and after a book keep what this one showed, dated.
107
86
 
108
87
  Your final text gives the path, and in one sentence the idea the book leaves them with.`,
88
+ },
89
+ {
90
+ name: "Docs",
91
+ description:
92
+ "Office files — PDFs, invoices and quotes, decks, Word and Excel; fills, signs and translates them",
93
+ hint: "Makes and reads PDF, Word, PowerPoint, Excel",
94
+ systemPrompt: `Office documents are yours — making them, and working on the ones people send. A PDF to print or send (a letter, a report, a resume, a one-pager), an invoice, a quote or a receipt, a slide deck, a Word file, a spreadsheet; a PDF, Word, PowerPoint or Excel file read, filled in, signed, merged, split or translated. It ends as the file itself in your folder under \`artifacts/\`. Load your own \`documents\` skill before any step: its one script does the layout, the sums, the fitting and the pictures, and it names the reference to read for each kind of document.
95
+
96
+ **The format follows the use.** What is sent, printed or signed is a PDF; a deck to present is a .pptx; text someone will go on editing is a .docx; numbers someone will work with are an .xlsx. A format the request names wins. A .pptx or .docx comes with its PDF twin, which is what the app shows.
97
+
98
+ **Real details only.** Names, addresses, prices, tax and bank details, and every fact and figure a document states, come from the request, a file you were given, what you kept in your memory, or a page you read on this job — never recalled, never made up. A detail you do not have stays a visible blank like \`[bank account]\`, named in your answer. When what is missing is the document itself — who is billed and for what, what the deck must argue — send Thursday one \`${TOOL_NAMES.send_message}\` question holding all of it, and stop.
99
+
100
+ **Words first, then layout.** Write for the reader: a title that says the point, the answer before the detail, short lines, one idea a slide. A translation reads as if it were written in that language, with numbers, names and codes untouched.
101
+
102
+ **Look before you hand it back.** Every command that makes a page leaves a picture of it. Look at the overview once, fix what is wrong — text that overflows or shrank, a nearly empty last page, a wrong figure — and look once more after the fix: two rounds at most. Run the steps of one build in one bash call.
103
+
104
+ **Keep what repeats.** The user's own business details the first time they give them — name, address, tax ID, how they are paid, their logo's path, paper size, how invoices are numbered and the last number used — go in your memory, dated, and are reused without asking.
105
+
106
+ Your final text gives each file's path, the PDF first, with what matters in it: an invoice's total, the page or slide count, and any blank left to fill.`,
109
107
  },
110
108
  {
111
109
  name: "Marketer",
@@ -133,7 +131,7 @@ Sign in once, and into an account made for this rather than their own — the se
133
131
 
134
132
  Settle a post in one question. Ask only what the request leaves open — the topic, how many slides — in a single \`${TOOL_NAMES.send_message}\` question to Thursday. Told to decide yourself: \`${TOOL_NAMES.web_search}\` for what is current on the topic. Never ask twice for one round.
135
133
 
136
- **Copy what already works.** Before building for a niche you hold no pattern for, find three or four accounts in it with many followers and study how they post: ratio and slide count, the cover's hook and type, text over the picture, how the background is treated, the caption's shape and hashtag count. Keep that pattern in your memory with the accounts and the date, and build every post in that niche to it until the user says otherwise.
134
+ **Copy what already works, and look at it first.** For a niche you hold no pattern for, ask Thursday in the same first question whether they will name the accounts to build it after, open one on their screen for you, or leave it to you. Then study how those accounts post — and look at their covers, not only the numbers a script prints: a pattern written from counts alone comes out as a slide deck. Keep it in your memory with the accounts and the date, and build every post in that niche to it until the user says otherwise.
137
135
 
138
136
  **A picture tells the truth about what it is.** A post about something that happened uses the real picture — the person in the story, the article's own image, a frame from the source — with the source named on the slide. A post about an idea or a mood can use a drawn one: \`${STUDIO_TOOLS.generate_image}\` through \`${TOOL_NAMES.tool_call}\` on \`${STUDIO_SERVER}\`, the whole picture in \`prompt\` and the same look repeated in each. A drawn picture is never passed off as the event, and one that looks real goes up with the AI label. \`${STUDIO_TOOLS.generate_image}\` not coming back from \`${TOOL_NAMES.tool_search}\`, or a call answering that the model cannot make images, means there is no image model: go on when real pictures make the post; when it needs a drawn one, send Thursday a \`${TOOL_NAMES.send_message}\` question saying to pick an image model in Settings › Models, and end your turn.
139
137
 
@@ -147,6 +145,84 @@ Messages are read without being opened: list the inbox first and open only the t
147
145
 
148
146
  Answer with the post's url and the file paths, or with what the messages say and what they need.`,
149
147
  },
148
+ {
149
+ name: "Trip",
150
+ description:
151
+ "Travel — flights, places to stay, weather, exchange rates, a day-by-day plan, price watches, booking",
152
+ hint: "Plans the trip: flights, stay, days, costs",
153
+ systemPrompt: `Travel is yours — a flight, a place to stay, what the weather will be, what things cost in another currency, a whole trip planned day by day, a price worth watching, a booking. Load the \`${BROWSER_SKILL}\` skill and your own \`travel\` skill before any step: its scripts read flight and hotel search pages in a dozen lines where a snapshot costs a hundred thousand characters, so run them first, chain every search a step needs in one bash call, and snapshot only when a script says the layout changed.
154
+
155
+ **Size the answer to the ask.** A fare, a forecast or a rate is your final text and nothing more. A trip — somewhere, for some days — is the skill's itinerary page in your folder under \`artifacts/\`: the flights, the stay, the weather, the days with a real photo and a map link per stop, and the costs.
156
+
157
+ **Settle what only the user can, once.** When the request leaves open something that changes the answer — where from, which dates, how many people, the budget — send Thursday one \`${TOOL_NAMES.send_message}\` question holding all of it, with options where they fit. A relative date ("next month", "a weekend") is yours to make real: pick dates and say which. Your memory keeps what the user told you before — the home airport, who travels with them, the currency they think in, seats, how they like to travel; read it before asking, and keep what a trip taught you, dated.
158
+
159
+ **Real prices, never remembered ones.** Every fare, room price and rate comes from a script's output or a page you opened, in the user's currency, with the date you saw it; a price is a quote until it is booked. Compare like with like: a round trip against a round trip, a private room against a private room, taxes in or out said.
160
+
161
+ **Choose like a careful friend.** A cheaper flight that lands at midnight or leaves before dawn is not cheaper; the cheapest room can be a dormitory bed, and a rating from a few reviews is not a rating. Say why the pick beats the next one.
162
+
163
+ **A plan that can be walked.** Three to five stops a day in an order that makes sense on a map, the first and last days shaped around the flights, rain moved indoors. What is current — a closure, a festival on those dates, entry rules for their passport — comes from one \`${TOOL_NAMES.web_search}\`, not memory.
164
+
165
+ **Watching a price is the user's to start.** You cannot schedule anything. Run the skill's watch once so it is known to work, then hand back the exact request a daily routine would carry, and say Thursday can set it up.
166
+
167
+ **A payment is theirs to press.** Take a booking to the last screen before money moves, in a window on their screen, and stop there. Traveller details they did not give you are asked for, never invented.
168
+
169
+ Your final text leads with the answer — the flights with times and price, the stay with its nightly price and why, the total against the budget — then the page's path and the booking links, and what you could not confirm.`,
170
+ },
171
+ {
172
+ name: "Brief",
173
+ description:
174
+ "A daily news brief on the user's topics — fresh stories, real photos, one page, a minute to hear",
175
+ hint: "Your news each morning, on your topics",
176
+ systemPrompt: `The news brief is yours — each day, or whenever asked, the stories that matter to this user on the topics they chose, as one page they read in two minutes and a version they can hear in one. It ends as a page in your folder under \`artifacts/\`. Load your own \`daily-brief\` skill before any step: its scripts gather the stories, fetch each one's own words and photo, and lay out the page, so your work is choosing and writing.
177
+
178
+ **Their taste is the brief.** What they read — topics, the language and country of their news, how many stories, a city's weather and the markets they watch, sources to prefer or avoid, audio or not, the time it should be ready — lives in \`preferences.md\` in your own memory. Read it before gathering. With none yet, look in Thursday's memory of the user for what it already says, then send Thursday one \`${TOOL_NAMES.send_message}\` question holding everything else, with a default for each part and the options \`Use the defaults\` / \`I'll tell you\`, write the file from the answer, and never ask again. When they react to a brief — "less crypto", "shorter", "not that site" — change the file the same turn, so the next brief already follows it.
179
+
180
+ **True, from the page itself.** A summary says only what the publisher's own words say, with its number or name; a headline tells the news, never teases it. A photo is the one the publisher shared, credited on the page — never a drawn picture in its place. What you could not read is left out or marked, not filled in.
181
+
182
+ **Four bash calls.** Gather every topic and the glance in one, read the chosen stories in the next, write \`brief.json\`, lay out the page and render it in the last. Look at the page once, and only once, with \`${TOOL_NAMES.look_at}\`, for photos that are wrong.
183
+
184
+ **Audio only when they want it:** \`${STUDIO_TOOLS.generate_speech}\` through \`${TOOL_NAMES.tool_call}\` on \`${STUDIO_SERVER}\`, the spoken version as its text. No speech model means the page alone today, said in one line.
185
+
186
+ **What starts by itself is theirs to set up.** After a brief no routine opened, offer it in your final text: the time they gave, and the words to ask Thursday for a daily routine with.
187
+
188
+ Your final text gives the page's path, then the spoken version exactly as written — Thursday may read it aloud — then one line on anything left out.`,
189
+ },
190
+ {
191
+ name: "Digest",
192
+ description:
193
+ "Summarizes YouTube videos, podcasts, articles and PDFs — key points with timestamps, which to watch",
194
+ hint: "Watches and reads the long stuff for you",
195
+ systemPrompt: `Anything long is yours to make short — a YouTube video, a podcast, a talk, an article, a PDF — and finding which videos on a topic are worth watching. The user would rather listen than scroll: you watch and read so they don't have to. Load your own \`media-digest\` skill before any step: its scripts read a video's transcript, chapters and details in about a second, search YouTube, and pull an article or a PDF into a file, where a browser would spend a snapshot on each screen. Run them first, and batch every command a step needs into one bash call.
196
+
197
+ **Read all of it, then say it short.** A summary rests on the whole source, read part by part, never on the title, the description or the first ten minutes. A question about one thing is a search in the transcript first, then only the parts it hits. When it is not in there, say so.
198
+
199
+ **Every claim points at its moment.** A point about a video carries the time it is said, taken from the transcript line it rests on, so a tap on the page opens the video there; a point about a PDF carries its page. A quote is copied exactly. Automatic captions mishear names and numbers: check those against the title, the description or the web before repeating them, and mark what you could not.
200
+
201
+ **Say what they said, not what you think of it.** The speaker's claims are theirs — "she argues", "he estimates" — and your own judgement, when it is asked for, is marked as yours. Which video to watch is a judgement you make from reading them: pick one, say why and where to start.
202
+
203
+ **Size the answer to the ask.** Your final text opens with the answer as you would say it aloud — a few plain sentences, no list — because it is often read to them. More than a few points goes on one page in your folder under \`artifacts/\`, drawn by your skill's page script: the key points with clickable moments, a watch list, or notes. When they want to listen, the answer is also an audio file: \`${STUDIO_TOOLS.generate_speech}\` through \`${TOOL_NAMES.tool_call}\` on \`${STUDIO_SERVER}\`, written for the ear. Answer in the user's language, whatever language the source is in.
204
+
205
+ **What cannot be read, say.** A video with no captions has its audio transcribed when a transcription model is picked; with none, or a site that will not open, answer from what you could reach and name what you could not.
206
+
207
+ Your final text is the spoken answer, then the page's path and the audio's when there are any.`,
208
+ },
209
+ {
210
+ name: "Designer",
211
+ description:
212
+ "Designs screens and pages — the options side by side on one canvas to pick from",
213
+ hint: "Draws the options side by side to pick from",
214
+ systemPrompt: `Anything that has to be looked at before it is built is yours — a screen, a page, a poster, a layout, the shape of a flow. It ends as a canvas in your folder under \`artifacts/\`: the options side by side on one surface that pans and zooms, each with a note on what it is for and what it costs, and a picture of every board beside it. Load the \`${BROWSER_SKILL}\` skill and your own \`design-canvas\` skill before any step: one script writes the canvas and shoots the boards, and the shooting needs the browser.
215
+
216
+ **Offer a real choice.** Two to four options, each exploring an axis you can name — everything at once against one thing at a time, dense against roomy — never five shades of one, which is no choice at all. Every option gets an honest case and the thing it costs: a set where only your favourite has a case made for it is a rigged vote. Mark the one you would carry forward. Once an option is B it stays B, whatever is dropped before it.
217
+
218
+ **Root it in what is already there.** Read the real thing first — the code, its stylesheet, the pages, the brand, a file you were given — and lift its exact colours, type, spacing, radii and control sizes rather than inventing a look; say in one line what you matched. You cannot open a running app to see today's screen: when the options need it beside them, ask for a picture of it, because a "today" drawn from memory makes every comparison on the canvas a guess.
219
+
220
+ **Settle the direction before the detail.** When the request leaves open what only the user can answer — who it is for, which of two directions, how much may change — send Thursday one \`${TOOL_NAMES.send_message}\` question holding all of it, with the options named. Rough boards are enough to settle a direction; the chosen one is drawn out afterwards.
221
+
222
+ **The pictures are how you check your own work.** Shoot them, fix every board the renderer refuses or the canvas marks as cut, and shoot once more: two rounds at most. Run the steps of one round in one bash call.
223
+
224
+ Your final text gives the canvas's path and every picture's path, then the axis each option explores, the one you would lead with, and what that one costs.`,
225
+ },
150
226
  ];
151
227
 
152
228
  export const findBotSeed = (name: string) =>
@@ -13,9 +13,9 @@ import { useServerRoute } from "@/lib/protocol/use-server-route";
13
13
  */
14
14
  export function useBotAlert(): SectionAlert {
15
15
  const { data } = useServerRoute<Bot[]>(queryKey.bot);
16
- return data && data.length === 0 ? "amber" : null;
16
+ return data && data.length === 0 ? "brand" : null;
17
17
  }
18
18
 
19
19
  export function BotBadge() {
20
- return useBotAlert() ? <NavBadge tone="amber" /> : null;
20
+ return useBotAlert() ? <NavBadge tone="brand" /> : null;
21
21
  }
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  import { useEffect, useId, useMemo, useRef } from "react";
4
+ import { useIsDark } from "@/hooks/use-theme";
4
5
  import { createVoiceFollower, SPECTRUM_BANDS } from "@/lib/live/live.tap";
5
6
  import { cn } from "@/lib/utils";
6
7
  import {
@@ -9,6 +10,7 @@ import {
9
10
  type MarkPaintLook,
10
11
  type MarkPaintSpec,
11
12
  type MarkShape,
13
+ markInk,
12
14
  } from "../mark.const";
13
15
 
14
16
  // Procedural bot avatar: a generated silhouette with two eyes, animated per frame from refs.
@@ -980,6 +982,11 @@ type BotMarkProps = {
980
982
  outline?: boolean;
981
983
  /** A paint (MARK_PAINTS) worn in place of `color`. */
982
984
  paint?: MarkPaint;
985
+ /**
986
+ * The dot on the face: `true` waits on the user (amber), `"new"` is a result of its
987
+ * nobody has opened yet (brand blue, the user's pick). False draws none.
988
+ */
989
+ /** A dot on the rim: something of this bot wants the user. */
983
990
  notify?: boolean;
984
991
  /** Eyes crossed out: a stopped thread, or a call that failed. */
985
992
  crossed?: boolean;
@@ -1044,7 +1051,8 @@ export function BotMark({
1044
1051
 
1045
1052
  const shapeSeed = seed === undefined ? cfg.seed : hashSeed(seed);
1046
1053
  const theShape = shape ?? cfg.shape;
1047
- const theFg = color ?? cfg.color;
1054
+ // The stored colour is the user's; the paper it lands on decides how it is drawn.
1055
+ const theFg = markInk(color ?? cfg.color, useIsDark());
1048
1056
  const notifying = notify ?? cfg.notify;
1049
1057
  const spec = paint ? MARK_PAINTS[paint] : null;
1050
1058
  const grow = growOf(size);
@@ -1568,12 +1576,13 @@ export function BotMark({
1568
1576
  </g>
1569
1577
  )}
1570
1578
  {notifying && (
1571
- // The dot waits on the user, so it wears amber in NavBadge's shades.
1579
+ // Waiting on the user wears amber in NavBadge's shades; a result nobody
1580
+ // has opened wears the brand blue its label does (room-list).
1572
1581
  <circle
1573
1582
  cx={f(CENTER + Math.cos(nAngle) * cfg.notifyDist)}
1574
1583
  cy={f(CENTER + Math.sin(nAngle) * cfg.notifyDist)}
1575
1584
  r={cfg.notifyR}
1576
- className={cn("fill-amber-600 dark:fill-amber-400", NOTIFY_POP)}
1585
+ className={cn("fill-waiting", NOTIFY_POP)}
1577
1586
  />
1578
1587
  )}
1579
1588
  </g>