thursday-agent 0.10.0 → 0.12.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 (308) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-path-routes-manifest.json +0 -1
  3. package/.next/build-manifest.json +3 -3
  4. package/.next/prerender-manifest.json +3 -3
  5. package/.next/routes-manifest.json +0 -6
  6. package/.next/server/app/_global-error/page.js.nft.json +1 -1
  7. package/.next/server/app/_global-error.html +1 -1
  8. package/.next/server/app/_global-error.rsc +1 -1
  9. package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  10. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  11. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  12. package/.next/server/app/_not-found/page.js.nft.json +1 -1
  13. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  14. package/.next/server/app/_not-found.html +1 -1
  15. package/.next/server/app/_not-found.rsc +2 -2
  16. package/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  17. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  18. package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  19. package/.next/server/app/api/artifact/route.js.nft.json +1 -1
  20. package/.next/server/app/api/bot/keep-working/route.js.nft.json +1 -1
  21. package/.next/server/app/api/bot/memory/files/route.js.nft.json +1 -1
  22. package/.next/server/app/api/bot/memory/route.js.nft.json +1 -1
  23. package/.next/server/app/api/bot/route.js.nft.json +1 -1
  24. package/.next/server/app/api/bot/thread/[id]/route.js.nft.json +1 -1
  25. package/.next/server/app/api/bot/thread/route.js.nft.json +1 -1
  26. package/.next/server/app/api/config/route.js.nft.json +1 -1
  27. package/.next/server/app/api/events/route.js.nft.json +1 -1
  28. package/.next/server/app/api/favicon/[host]/route.js.nft.json +1 -1
  29. package/.next/server/app/api/file/[...path]/route.js.nft.json +1 -1
  30. package/.next/server/app/api/llm-model/catalog/route.js.nft.json +1 -1
  31. package/.next/server/app/api/llm-model/credits/route.js.nft.json +1 -1
  32. package/.next/server/app/api/llm-model/route.js.nft.json +1 -1
  33. package/.next/server/app/api/llm-model/subscription/route.js.nft.json +1 -1
  34. package/.next/server/app/api/mcp/[name]/route.js.nft.json +1 -1
  35. package/.next/server/app/api/mcp/oauth/callback/route.js.nft.json +1 -1
  36. package/.next/server/app/api/mcp/route.js.nft.json +1 -1
  37. package/.next/server/app/api/mcp/tools/route.js.nft.json +1 -1
  38. package/.next/server/app/api/memory/edit/route.js.nft.json +1 -1
  39. package/.next/server/app/api/memory/route.js.nft.json +1 -1
  40. package/.next/server/app/api/reach/route.js +13 -13
  41. package/.next/server/app/api/reach/route.js.nft.json +1 -1
  42. package/.next/server/app/api/routine/route.js.nft.json +1 -1
  43. package/.next/server/app/api/signins/route.js +1 -1
  44. package/.next/server/app/api/signins/route.js.nft.json +1 -1
  45. package/.next/server/app/api/skills/[source]/[name]/route.js.nft.json +1 -1
  46. package/.next/server/app/api/skills/route.js.nft.json +1 -1
  47. package/.next/server/app/api/thursday/call/route.js.nft.json +1 -1
  48. package/.next/server/app/api/thursday/skills/route.js.nft.json +1 -1
  49. package/.next/server/app/api/thursday/text/route.js.nft.json +1 -1
  50. package/.next/server/app/api/thursday/tool-call/route.js +14 -15
  51. package/.next/server/app/api/thursday/tool-call/route.js.nft.json +1 -1
  52. package/.next/server/app/api/workspace/files/route.js.nft.json +1 -1
  53. package/.next/server/app/api/workspace/route.js.nft.json +1 -1
  54. package/.next/server/app/artifact/[...path]/page/server-reference-manifest.json +1 -1
  55. package/.next/server/app/artifact/[...path]/page.js.nft.json +1 -1
  56. package/.next/server/app/artifact/[...path]/page_client-reference-manifest.js +1 -1
  57. package/.next/server/app/favicon.ico/route.js.nft.json +1 -1
  58. package/.next/server/app/manifest.webmanifest/route.js.nft.json +1 -1
  59. package/.next/server/app/page/server-reference-manifest.json +56 -56
  60. package/.next/server/app/page.js +4 -4
  61. package/.next/server/app/page.js.nft.json +1 -1
  62. package/.next/server/app/page_client-reference-manifest.js +1 -1
  63. package/.next/server/app-paths-manifest.json +0 -1
  64. package/.next/server/chunks/[root-of-the-server]__014ydvq._.js +2 -2
  65. package/.next/server/chunks/[root-of-the-server]__0209ah4._.js +7 -5
  66. package/.next/server/chunks/[root-of-the-server]__04r4h-2._.js +4 -2
  67. package/.next/server/chunks/[root-of-the-server]__04wldw9._.js +1 -1
  68. package/.next/server/chunks/[root-of-the-server]__0542v_d._.js +3 -0
  69. package/.next/server/chunks/[root-of-the-server]__0cfszwn._.js +1 -1
  70. package/.next/server/chunks/[root-of-the-server]__0gewdg9._.js +2 -2
  71. package/.next/server/chunks/[root-of-the-server]__0mrk2it._.js +1 -1
  72. package/.next/server/chunks/[root-of-the-server]__0npn_pn._.js +1 -1
  73. package/.next/server/chunks/[root-of-the-server]__0nr-v8s._.js +1 -1
  74. package/.next/server/chunks/[root-of-the-server]__0rqgb17._.js +1 -1
  75. package/.next/server/chunks/[root-of-the-server]__1-swlkw._.js +2 -2
  76. package/.next/server/chunks/[root-of-the-server]__12iddfq._.js +1 -1
  77. package/.next/server/chunks/[root-of-the-server]__1ai5lme._.js +3 -3
  78. package/.next/server/chunks/[root-of-the-server]__1cjxw0-._.js +2 -2
  79. package/.next/server/chunks/{[root-of-the-server]__1fy2g82._.js → [root-of-the-server]__1k3j52n._.js} +1 -1
  80. package/.next/server/chunks/[root-of-the-server]__1kyjt5m._.js +3 -3
  81. package/.next/server/chunks/[root-of-the-server]__1tg5got._.js +1 -1
  82. package/.next/server/chunks/[root-of-the-server]__1ygplx1._.js +1 -1
  83. package/.next/server/chunks/_05v8k21._.js +3 -1
  84. package/.next/server/chunks/_0awtznl._.js +1 -1
  85. package/.next/server/chunks/_0f6ts7z._.js +1 -1
  86. package/.next/server/chunks/_0na2fj1._.js +1 -1
  87. package/.next/server/chunks/_0x-ej3f._.js +17 -17
  88. package/.next/server/chunks/_10tkr26._.js +1 -1
  89. package/.next/server/chunks/_12-amdu._.js +2 -2
  90. package/.next/server/chunks/_15740dw._.js +60 -0
  91. package/.next/server/chunks/_1dc_d1q._.js +3 -3
  92. package/.next/server/chunks/_1i350l5._.js +3 -1
  93. package/.next/server/chunks/_1jc5g4p._.js +2 -2
  94. package/.next/server/chunks/_1jn-aep._.js +4 -4
  95. package/.next/server/chunks/_1m88lkh._.js +11 -11
  96. package/.next/server/chunks/_1ogqovh._.js +4 -4
  97. package/.next/server/chunks/_1taa4bs._.js +1 -1
  98. package/.next/server/chunks/_1tpr507._.js +1 -1
  99. package/.next/server/chunks/_1uuucy-._.js +1 -1
  100. package/.next/server/chunks/_1zxp-p6._.js +1 -1
  101. package/.next/server/chunks/features_0rfvely._.js +5 -3
  102. package/.next/server/chunks/ssr/[root-of-the-server]__0a967km._.js +3 -0
  103. package/.next/server/chunks/ssr/{[root-of-the-server]__1se25x0._.js → [root-of-the-server]__0hpp3nw._.js} +29 -13
  104. package/.next/server/chunks/ssr/[root-of-the-server]__0tzekbl._.js +24 -60
  105. package/.next/server/chunks/ssr/{[root-of-the-server]__0tvavy9._.js → [root-of-the-server]__1iwyp1e._.js} +1 -1
  106. package/.next/server/chunks/ssr/[root-of-the-server]__1r77-88._.js +3 -0
  107. package/.next/server/chunks/ssr/[root-of-the-server]__1w9hqq8._.js +1 -1
  108. package/.next/server/chunks/ssr/_026qnc9._.js +1 -1
  109. package/.next/server/chunks/ssr/{_173siic._.js → _02c7o30._.js} +2 -2
  110. package/.next/server/chunks/ssr/_097-ljd._.js +1 -1
  111. package/.next/server/chunks/ssr/_0euzzf8._.js +3 -0
  112. package/.next/server/chunks/ssr/{_1u2jw0i._.js → _0fbi6om._.js} +3 -3
  113. package/.next/server/chunks/ssr/_0fqhhwi._.js +1 -1
  114. package/.next/server/chunks/ssr/_0igfcax._.js +20 -0
  115. package/.next/server/chunks/ssr/_0ld9_qq._.js +1 -1
  116. package/.next/server/chunks/ssr/_0nvh1h9._.js +3 -0
  117. package/.next/server/chunks/ssr/_0qmpw35._.js +3 -0
  118. package/.next/server/chunks/ssr/{_1yk6yak._.js → _0rmaf32._.js} +2 -2
  119. package/.next/server/chunks/ssr/_0uv-qs4._.js +3 -0
  120. package/.next/server/chunks/ssr/{_1doidrw._.js → _10f-jib._.js} +2 -2
  121. package/.next/server/chunks/ssr/{_05rxyf9._.js → _10mo72m._.js} +2 -2
  122. package/.next/server/chunks/ssr/_12mijol._.js +11 -11
  123. package/.next/server/chunks/ssr/_132qkfz._.js +1 -1
  124. package/.next/server/chunks/ssr/_15zqt-t._.js +1 -1
  125. package/.next/server/chunks/ssr/_16gfxpn._.js +3 -0
  126. package/.next/server/chunks/ssr/_184327j._.js +1 -1
  127. package/.next/server/chunks/ssr/{_1ng831c._.js → _18ujhhq._.js} +2 -2
  128. package/.next/server/chunks/ssr/_1d423aj._.js +7 -5
  129. package/.next/server/chunks/ssr/_1lx6w_o._.js +67 -0
  130. package/.next/server/chunks/ssr/_1mqn9mc._.js +1 -1
  131. package/.next/server/chunks/ssr/_1neoj22._.js +1 -1
  132. package/.next/server/chunks/ssr/{_19n08g5._.js → _1ntpny5._.js} +2 -2
  133. package/.next/server/chunks/ssr/{_0bp-_fi._.js → _1o1g4uk._.js} +3 -3
  134. package/.next/server/chunks/ssr/_1xoch6f._.js +1 -1
  135. package/.next/server/chunks/ssr/_1yh5bj5._.js +1 -1
  136. package/.next/server/chunks/ssr/{_0tg0vf8._.js → _2008vmi._.js} +8 -8
  137. package/.next/server/chunks/ssr/{features_bot_1yr-_pm._.js → features_bot_1n1s7bh._.js} +2 -2
  138. package/.next/server/chunks/ssr/features_connectors_components_mcp-setting_tsx_0jmbgvp._.js +1 -1
  139. package/.next/server/chunks/ssr/features_memory_components_memory-setting_tsx_0oa43sw._.js +1 -1
  140. package/.next/server/chunks/ssr/features_routine_components_routine-setting_tsx_055fknz._.js +1 -1
  141. package/.next/server/chunks/ssr/features_workspace_00jz2hu._.js +1 -1
  142. package/.next/server/chunks/ssr/{node_modules_1n0h9sf._.js → node_modules_0-x0zxm._.js} +1 -1
  143. package/.next/server/chunks/ssr/{node_modules_1xzo2wn._.js → node_modules_00nrzz_._.js} +1 -1
  144. package/.next/server/chunks/ssr/{node_modules_0511ha-._.js → node_modules_01ed0yi._.js} +1 -1
  145. package/.next/server/chunks/ssr/{node_modules_18woe20._.js → node_modules_01u4ea3._.js} +1 -1
  146. package/.next/server/chunks/ssr/{node_modules_1expacw._.js → node_modules_05b6e99._.js} +1 -1
  147. package/.next/server/chunks/ssr/{node_modules_0eb4rx7._.js → node_modules_07jp6tj._.js} +1 -1
  148. package/.next/server/chunks/ssr/{node_modules_0piws2a._.js → node_modules_0azd56x._.js} +1 -1
  149. package/.next/server/chunks/ssr/{node_modules_0f2k5l0._.js → node_modules_0b0iy01._.js} +1 -1
  150. package/.next/server/chunks/ssr/{node_modules_0wq4-ts._.js → node_modules_0fpnetd._.js} +1 -1
  151. package/.next/server/chunks/ssr/{node_modules_11hbkuj._.js → node_modules_0ky76fz._.js} +1 -1
  152. package/.next/server/chunks/ssr/{node_modules_048wmmj._.js → node_modules_0lautv3._.js} +1 -1
  153. package/.next/server/chunks/ssr/{node_modules_1dcbvfw._.js → node_modules_0m3_5ge._.js} +1 -1
  154. package/.next/server/chunks/ssr/{node_modules_0pk6i-e._.js → node_modules_0operbz._.js} +1 -1
  155. package/.next/server/chunks/ssr/{node_modules_1zkpek5._.js → node_modules_0ou0all._.js} +1 -1
  156. package/.next/server/chunks/ssr/{node_modules_04t200t._.js → node_modules_0ucridu._.js} +1 -1
  157. package/.next/server/chunks/ssr/{node_modules_08g12f-._.js → node_modules_0v_-uht._.js} +1 -1
  158. package/.next/server/chunks/ssr/{node_modules_1m2ho33._.js → node_modules_0yzmxfq._.js} +1 -1
  159. package/.next/server/chunks/ssr/{node_modules_1ksh9gy._.js → node_modules_19b0bir._.js} +1 -1
  160. package/.next/server/chunks/ssr/{node_modules_1qehmwm._.js → node_modules_1c2ikr9._.js} +1 -1
  161. package/.next/server/chunks/ssr/{node_modules_1_afpz7._.js → node_modules_1hv-j1l._.js} +1 -1
  162. package/.next/server/chunks/ssr/{node_modules_0cdu6jq._.js → node_modules_1iau_ea._.js} +1 -1
  163. package/.next/server/chunks/ssr/{node_modules_1zf46lp._.js → node_modules_1ma_y68._.js} +1 -1
  164. package/.next/server/chunks/ssr/{node_modules_0s1lwc9._.js → node_modules_1omg9xr._.js} +1 -1
  165. package/.next/server/chunks/ssr/{node_modules_1cxc8kn._.js → node_modules_1wgnj8q._.js} +1 -1
  166. package/.next/server/chunks/ssr/{node_modules_0zjqwz7._.js → node_modules_1wvf3oo._.js} +1 -1
  167. package/.next/server/chunks/ssr/{node_modules_1_ban4u._.js → node_modules_1z3sh11._.js} +1 -1
  168. package/.next/server/chunks/ssr/{node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_0avl8-1._.js → node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_0tmjn9w._.js} +1 -1
  169. package/.next/server/chunks/ssr/{node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_14oslro._.js → node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_1_e8c3o._.js} +1 -1
  170. package/.next/server/middleware-build-manifest.js +3 -3
  171. package/.next/server/pages/404.html +1 -1
  172. package/.next/server/pages/500.html +1 -1
  173. package/.next/server/server-reference-manifest.js +1 -1
  174. package/.next/server/server-reference-manifest.json +57 -57
  175. package/.next/static/chunks/09pkygbht7ki8.js +18 -0
  176. package/.next/static/chunks/0bm-nhblcmmj4.js +17 -0
  177. package/.next/static/chunks/{22shnca_6zfzs.js → 0hhza87hkbqaz.js} +1 -1
  178. package/.next/static/chunks/{19ojn4lomsk0r.js → 0mscosx0eh3ee.js} +1 -1
  179. package/.next/static/chunks/{3vynnr71ghvom.js → 0p50d-au6-3hx.js} +2 -2
  180. package/.next/static/chunks/{42890jqk049q1.js → 0p9jcyqkpq71f.js} +1 -1
  181. package/.next/static/chunks/{35kwn237o4wdn.js → 0qgn3u86jkbm7.js} +1 -1
  182. package/.next/static/chunks/{2d4z3er53ng8r.js → 0samf80yu2b17.js} +1 -1
  183. package/.next/static/chunks/{1pjygp7hqib6j.js → 1czfknd4luo6t.js} +1 -1
  184. package/.next/static/chunks/{09120tms63y21.js → 1jz8n0mhtdzr8.js} +1 -1
  185. package/.next/static/chunks/206laxm6maiz2.js +1 -0
  186. package/.next/static/chunks/{24dst4mgurbsh.js → 2_c7mu6x1lu49.js} +1 -1
  187. package/.next/static/chunks/{2ky81z-jgvasc.js → 2h-tlhb2ffhkk.js} +1 -1
  188. package/.next/static/chunks/{0oz3rs47yy3p8.js → 2i5_w8olnrvo0.js} +2 -2
  189. package/.next/static/chunks/{1mwee7xvitlp9.js → 2m8iqwc6sykln.js} +1 -1
  190. package/.next/static/chunks/{0o980477kfqez.js → 2r6xnyg7ezyxr.js} +1 -1
  191. package/.next/static/chunks/33fyp-byw48ju.js +65 -0
  192. package/.next/static/chunks/{2ndw4w4u2x51r.js → 35yd_27d9ylra.js} +1 -1
  193. package/.next/static/chunks/{3exjsi8pfdvzj.js → 3ag1i3__yl94f.js} +1 -1
  194. package/.next/static/chunks/{3obf9n3cxj99k.js → 3jvldk2wvwbge.js} +1 -1
  195. package/.next/static/chunks/3m_ejzg-xn21r.css +1 -0
  196. package/.next/static/chunks/{0w20wnnfrscq7.js → 3s-jpd3ky49-n.js} +1 -1
  197. package/.next/static/chunks/40ij3wsn3vt7h.js +1 -0
  198. package/README.md +1 -1
  199. package/app/api/thursday/tool-call/route.ts +1 -15
  200. package/docs/images/demo-still.jpg +0 -0
  201. package/docs/live-calls.md +19 -11
  202. package/features/ai/components/model-picker.tsx +8 -2
  203. package/features/ai/model.schema.ts +26 -0
  204. package/features/ai/prompts/live.prompt.ts +51 -26
  205. package/features/ai/prompts/prompt-helper.ts +1 -9
  206. package/features/ai/prompts/thursday.prompt.ts +8 -2
  207. package/features/bot/bot.run.ts +9 -3
  208. package/features/bot/bot.seed.ts +35 -91
  209. package/features/bot/components/bot-room.tsx +3 -12
  210. package/features/bot/components/room-list.tsx +1 -1
  211. package/features/bot/components/room-pill.tsx +44 -55
  212. package/features/bot/seed-bots.ts +2 -2
  213. package/features/config/components/config-badge.tsx +6 -0
  214. package/features/config/components/config-setting.tsx +20 -1
  215. package/features/config/components/models-badge.tsx +5 -7
  216. package/features/config/components/voice-key.tsx +24 -1
  217. package/features/config/config.const.ts +7 -0
  218. package/features/intro/components/intro.tsx +4 -19
  219. package/features/reach/reach.ts +2 -2
  220. package/features/settings/components/setting-ui.tsx +14 -5
  221. package/features/settings/components/settings.tsx +3 -1
  222. package/features/settings/settings.alert.ts +12 -11
  223. package/features/signins/signins.query.ts +66 -1
  224. package/features/thursday/components/side-captions.tsx +31 -8
  225. package/features/thursday/components/tab-state.tsx +5 -2
  226. package/features/thursday/components/thursday.tsx +158 -68
  227. package/features/thursday/components/write-line.tsx +37 -17
  228. package/features/thursday/thursday.action.ts +4 -20
  229. package/features/thursday/thursday.schema.ts +0 -9
  230. package/features/thursday/thursday.store.ts +11 -15
  231. package/features/thursday/thursday.text.ts +10 -8
  232. package/features/thursday/tool-line.ts +17 -6
  233. package/features/thursday/use-call-ring.ts +1 -5
  234. package/features/thursday/use-text-call.ts +37 -21
  235. package/features/thursday/use-thursday.ts +14 -44
  236. package/features/workspace/workspace.ts +4 -2
  237. package/guide/bots.md +12 -2
  238. package/guide/calls.md +9 -6
  239. package/guide/setup.md +4 -1
  240. package/lib/live/live.session.ts +0 -39
  241. package/package.json +1 -1
  242. package/scripts/live-session.test.mts +19 -26
  243. package/seed-skills/analyst/README.md +3 -4
  244. package/seed-skills/analyst/data-report/SKILL.md +5 -4
  245. package/seed-skills/insta/instagram/SKILL.md +5 -2
  246. package/seed-skills/insta/instagram/references/post.md +2 -2
  247. package/seed-skills/insta/instagram/scripts/compose.mjs +5 -1
  248. package/seed-skills/insta/instagram/scripts/inbox.mjs +5 -1
  249. package/seed-skills/insta/instagram/scripts/lib.mjs +12 -70
  250. package/seed-skills/insta/instagram/scripts/media.mjs +1 -1
  251. package/seed-skills/insta/instagram/scripts/profile.mjs +6 -2
  252. package/seed-skills/insta/instagram/scripts/read.mjs +5 -1
  253. package/seed-skills/insta/instagram/scripts/search.mjs +6 -2
  254. package/seed-skills/insta/instagram/scripts/sheet.mjs +31 -88
  255. package/seed-skills/insta/instagram/templates/carousel.html +1 -1
  256. package/seed-skills/tutor/picture-book/SKILL.md +16 -0
  257. package/seed-skills/tutor/picture-book/book/book.css +181 -0
  258. package/seed-skills/tutor/picture-book/book/book.html +33 -0
  259. package/seed-skills/tutor/picture-book/book/book.js +60 -0
  260. package/seed-skills/tutor/picture-book/references/picture-book.md +104 -0
  261. package/seed-skills/tutor/picture-book/scripts/book-video.mjs +177 -0
  262. package/seed-skills/tutor/picture-book/scripts/book.mjs +98 -0
  263. package/skills/browser/SKILL.md +13 -4
  264. package/skills/browser/references/scripts.md +55 -0
  265. package/{seed-skills/insta/instagram → skills/browser}/scripts/render.mjs +1 -1
  266. package/skills/browser/scripts/session.mjs +105 -0
  267. package/skills/browser/scripts/sheet.mjs +97 -0
  268. package/{seed-skills/insta/instagram → skills/browser}/scripts/webimage.mjs +1 -1
  269. package/skills/interactive-page/SKILL.md +4 -3
  270. package/{seed-skills/analyst/data-report → skills/interactive-page}/scripts/chart.mjs +3 -3
  271. package/skills/interactive-page/scripts/page.mjs +1 -0
  272. package/.next/server/app/api/probe/route/app-paths-manifest.json +0 -3
  273. package/.next/server/app/api/probe/route/build-manifest.json +0 -12
  274. package/.next/server/app/api/probe/route/server-reference-manifest.json +0 -4
  275. package/.next/server/app/api/probe/route.js +0 -10
  276. package/.next/server/app/api/probe/route.js.map +0 -5
  277. package/.next/server/app/api/probe/route.js.nft.json +0 -1
  278. package/.next/server/app/api/probe/route_client-reference-manifest.js +0 -3
  279. package/.next/server/chunks/[root-of-the-server]__012s2o8._.js +0 -3
  280. package/.next/server/chunks/[root-of-the-server]__0z0hc1f._.js +0 -4
  281. package/.next/server/chunks/[root-of-the-server]__1v7-zke._.js +0 -5
  282. package/.next/server/chunks/_0whlpyi._.js +0 -4
  283. package/.next/server/chunks/_next-internal_server_app_api_probe_route_actions_0cqd30j.js +0 -3
  284. package/.next/server/chunks/ssr/[root-of-the-server]__0cxqzfc._.js +0 -103
  285. package/.next/server/chunks/ssr/[root-of-the-server]__1-d2tgh._.js +0 -3
  286. package/.next/server/chunks/ssr/_070nv1_._.js +0 -3
  287. package/.next/server/chunks/ssr/_0hlxij-._.js +0 -3
  288. package/.next/server/chunks/ssr/_0p9pmxe._.js +0 -3
  289. package/.next/server/chunks/ssr/_0s41irp._.js +0 -3
  290. package/.next/server/chunks/ssr/_157yfrk._.js +0 -3
  291. package/.next/server/chunks/ssr/_17v-33v._.js +0 -20
  292. package/.next/server/chunks/ssr/_1flsjeo._.js +0 -3
  293. package/.next/static/chunks/03kgfyrli_0gz.js +0 -1
  294. package/.next/static/chunks/1p764d75_0lhv.js +0 -18
  295. package/.next/static/chunks/25zq8gzhbdsr7.js +0 -1
  296. package/.next/static/chunks/2qod5tqlpz8b7.js +0 -17
  297. package/.next/static/chunks/30skcjexa57zn.js +0 -101
  298. package/.next/static/chunks/3qq4o8w2rv_e9.css +0 -1
  299. package/lib/probe.server.ts +0 -17
  300. package/lib/probe.ts +0 -55
  301. package/seed-skills/mail/mail/SKILL.md +0 -37
  302. package/seed-skills/mail/mail/recipes/gmail.mjs +0 -448
  303. package/seed-skills/mail/mail/references/recipes.md +0 -55
  304. package/seed-skills/mail/mail/scripts/mail.mjs +0 -202
  305. /package/.next/static/{Ar5V4kMdL4CE1trx8anrH → QSe0rTdXU5kh5BBzr2XBB}/_buildManifest.js +0 -0
  306. /package/.next/static/{Ar5V4kMdL4CE1trx8anrH → QSe0rTdXU5kh5BBzr2XBB}/_clientMiddlewareManifest.js +0 -0
  307. /package/.next/static/{Ar5V4kMdL4CE1trx8anrH → QSe0rTdXU5kh5BBzr2XBB}/_ssgManifest.js +0 -0
  308. /package/{seed-skills/insta/instagram → skills/browser}/scripts/image-size.mjs +0 -0
@@ -0,0 +1 @@
1
+ (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,616816,e=>{"use strict";var t=e.i(843476),r=e.i(375775),n=e.i(689664),a=e.i(263676),l=e.i(271645),i=e.i(798120),s=e.i(167881),o=e.i(23750),u=e.i(968978),c=e.i(149666),h=e.i(265402),f=e.i(609856),d=e.i(283653),m=e.i(647163),g=e.i(722560),p=e.i(992112);function y({provider:e,saved:r,autoFocus:n,dense:a,plain:l,value:i,ready:s,saving:o,onValue:c,onSubmit:h}){return(0,t.jsxs)("div",{className:"space-y-2",children:[!l&&(0,t.jsxs)("span",{className:"flex items-center gap-2 px-0.5 text-muted-foreground",children:[(0,t.jsx)(u.ProviderIcon,{provider:e.id,className:"size-4 shrink-0"}),(0,t.jsx)("span",{className:(0,m.cn)("font-mono",a?"text-[11px]":"text-[12.5px]"),children:e.label})]}),(0,t.jsx)(x,{provider:e,saved:r,autoFocus:n,dense:a,mark:l,value:i,ready:s,saving:o,onValue:c,onSubmit:h})]})}function x({provider:e,saved:r,autoFocus:a,dense:l,mark:i,value:c,ready:h,saving:f,onValue:d,onSubmit:g}){let p=c.trim().startsWith("xai-")||c.trim().startsWith("sk-ant-");return(0,t.jsxs)("form",{onSubmit:e=>{e.preventDefault(),g()},className:(0,m.cn)("flex items-center gap-3 rounded-2xl border bg-muted/40 px-4 transition-colors",l?"h-11 rounded-xl px-3":"h-14",r||h?"border-foreground bg-transparent":"border-border"),children:[i&&(0,t.jsx)(u.ProviderIcon,{provider:e.id,className:"size-4 shrink-0 text-muted-foreground"}),(0,t.jsx)(o.Input,{autoFocus:a,type:"password","aria-label":"OpenAI API key",autoComplete:"off",value:c,spellCheck:!1,placeholder:r?"Replace it":"sk-…",onChange:e=>d(e.target.value),className:(0,m.cn)("min-w-0 flex-1 border-0 bg-transparent px-0 font-mono shadow-none focus-visible:ring-0 dark:bg-transparent",l?"h-7 text-[13px]":"h-9 text-[15px]")}),c?(0,t.jsx)(s.Button,{type:"submit",size:"sm",variant:p?"outline":"default",loading:f,disabled:!h,className:(0,m.cn)("shrink-0",l?"h-7 px-3":"h-9 px-4"),children:p?`Not ${e.label}?`:"Save"}):r&&(0,t.jsx)("span",{className:(0,m.cn)("grid shrink-0 animate-in place-items-center rounded-full bg-foreground text-background zoom-in-50 duration-300",l?"size-5":"size-7"),children:(0,t.jsx)(n.Check,{className:l?"size-3":"size-4"})})]})}e.s(["GetKeyLink",0,function(){let e=h.TEXT_MODEL_PROVIDERS[c.LIVE_PROVIDER.id].keysAt;return e?(0,t.jsxs)("a",{href:e,target:"_blank",rel:"noreferrer",className:"flex items-center gap-2.5 text-[13px] font-medium text-foreground no-underline",children:[(0,t.jsxs)("span",{className:"flex h-7.5 shrink-0 items-center gap-1.5 rounded-full bg-muted px-3.5 whitespace-nowrap transition-colors hover:bg-accent",children:["Get a key",(0,t.jsx)(r.ArrowUpRight,{className:"size-3.5"})]}),(0,t.jsx)("span",{className:"truncate font-mono text-[11px] font-normal text-muted-foreground/70",children:e.replace(/^https:\/\//,"")})]}):null},"KEY_MIN",0,8,"KeyInput",0,x,"VoiceKeys",0,function({ref:e,autoFocus:r,dense:n=!1,plain:o=!1,onCancel:u,onSaved:h,className:x}){let{data:M}=(0,d.useServerRoute)(i.queryKey.config),[O,A]=(0,l.useState)({}),[b,E]=(0,l.useState)(null),[S,_]=(0,l.useState)(null),[w]=(0,f.useServerAction)(g.setConfigAction,{errorMessage:!1,onError:e=>_(e??"That key was not saved."),onOk:()=>{(0,d.revalidate)(i.queryKey.config),(0,d.revalidate)(i.queryKey.llmModel)}}),N=e=>(O[e]?.trim().length??0)>=8,v=async e=>{let t=e.apiKeyName;if(!N(t)||b)return!1;_(null),E(t);try{return await w(t,O[t]),A(e=>({...e,[t]:""})),h?.(e.id),!0}catch{return!1}finally{E(null)}};return(0,l.useImperativeHandle)(e,()=>({pending:()=>N(c.LIVE_PROVIDER.apiKeyName),flush:async()=>!N(c.LIVE_PROVIDER.apiKeyName)||v(c.LIVE_PROVIDER)})),(0,t.jsxs)("div",{className:(0,m.cn)("w-full",n?"space-y-2":"space-y-4",x),children:[n&&!o&&(0,t.jsxs)("div",{className:"flex h-6 items-center justify-between gap-2",children:[(0,t.jsx)("span",{className:"px-0.5 font-mono text-[11px] text-muted-foreground",children:"Voice key"}),u&&(0,t.jsx)(s.Button,{type:"button",size:"icon",variant:"ghost","aria-label":"Not now",onClick:u,className:"-my-1 size-6",children:(0,t.jsx)(a.X,{className:"size-3.5"})})]}),(0,t.jsx)(y,{provider:c.LIVE_PROVIDER,saved:(0,p.isConfigSet)(M,c.LIVE_PROVIDER.apiKeyName),autoFocus:r,dense:n,plain:o,value:O[c.LIVE_PROVIDER.apiKeyName]??"",ready:N(c.LIVE_PROVIDER.apiKeyName),saving:b===c.LIVE_PROVIDER.apiKeyName,onValue:e=>{_(null),A(t=>({...t,[c.LIVE_PROVIDER.apiKeyName]:e}))},onSubmit:()=>void v(c.LIVE_PROVIDER)}),S&&(0,t.jsx)("p",{className:(0,m.cn)("px-0.5 leading-5 break-words",n?"text-xs":"text-center text-[13px]",m.WAITING_INK),children:S}),!o&&(0,t.jsx)("p",{className:(0,m.cn)("px-0.5 font-mono text-muted-foreground",n?"text-[11px]":"pt-1 text-center text-[12.5px]"),children:n?"Live voice and reasoning share this OpenAI API key.":"Live uses an OpenAI API key, billed separately from ChatGPT. Stored on this machine, in this app's database."})]})}])},333495,e=>{"use strict";var t=e.i(843476),r=e.i(271645),n=e.i(41533),a=e.i(218080),l=e.i(567334);let i=[235,235,235];function s(e){let t=[[],[],[],[],[]],r=0;for(let n of Array.from(e.toUpperCase())){let e=l.LETTERS[n];if(e){if(t[0].length)for(let e of t)e.push(-1);e.forEach((e,n)=>{for(let a of e)t[n].push("#"===a?r:-1)})," "!==n&&r++}}return t}let o=s("ERROR");function u(e,t,r,n,a){return e+(t-e)*Math.min(1,a/(t>e?r:n))}function c(e,t,r,n,a,l){let i=Math.floor(t/(n*l)+e[0].length/2),s=Math.floor(r/(a*l)+e.length/2);return s<0||s>=e.length?-1:e[s][i]??-1}function h(e,t,r,n){let a=e=>Math.max(1,Math.min(3,Math.floor(625.6/(e[0].length*t)),Math.floor(421.6/(e.length*r)))),l=s(n),i=3>a(l)?function(e){let t=Array.from(e.trim()),r=t.flatMap((e,t)=>" "===e?[t]:[]);if(!r.length)return null;let n=t.length/2,a=r.reduce((e,t)=>Math.abs(t-n)<Math.abs(e-n)?t:e),l=s(t.slice(0,a).join("")),i=s(t.slice(a+1).join(""));if(!l[0].length||!i[0].length)return null;let o=Math.max(-1,...l.flat())+1,u=Math.max(l[0].length,i[0].length),c=(e,t)=>{let r=Math.floor((u-e.length)/2);return[...Array(r).fill(-1),...e.map(e=>e<0?e:e+t),...Array(u-e.length-r).fill(-1)]},h=()=>Array(u).fill(-1);return[...l.map(e=>c(e,0)),h(),h(),...i.map(e=>c(e,o))]}(n):null,o=i&&a(i)>a(l)?i:l,u=a(o),h=0;for(let n of e)n.word=c(o,n.dx,n.dy,t,r,u),h=Math.max(h,n.word+1);return h}function f({className:e,mode:s="idle",charset:d=n.ASCII_FACE.charset,fontSize:m=n.ASCII_FACE.fontSize.default,density:g=n.ASCII_FACE.density.default,size:p=680,color:y=i,getSpectrum:x,word:M=null}){let O=(0,r.useRef)(null),A=(0,r.useRef)(null),b=(0,r.useRef)([]),E=(0,r.useRef)(null),S=(0,r.useRef)(d),_=(0,r.useRef)({cur:[...y],target:y}),w=(0,r.useRef)(0),N=(0,r.useRef)(x);N.current=x;let v=(0,r.useRef)({phrase:0,bob:0,bobVel:0,amp:[,,,,].fill(0),phase:Array.from({length:4},(e,t)=>2.1*t),spin:0,rings:[]}),L=(0,r.useRef)({mode:s,start:0}),R=(0,r.useRef)(performance.now()),I=(0,r.useRef)({scale:.3,lift:0,gather:0,comet:0,speech:0,err:0,word:0}),T=(0,r.useRef)(null),k=(0,r.useRef)({cw:1,ch:1});return(0,r.useEffect)(()=>{let e=O.current;if(!e)return;let t=.95*m/g,r=1.25*m/g,n=680/p,a=t*n,i=r*n,s=Math.max(1,Math.floor(625.6/(o[0].length*a)));w.current=p,k.current={cw:a,ch:i};let u=[],f=Math.ceil(p/t),d=Math.ceil(p/r);for(let e=0;e<d;e++)for(let h=0;h<f;h++){let f=h*t,d=e*r,m=(f-p/2)*n,g=(d-p/2)*n,y=Math.hypot(m,g),x=c(o,m,g,a,i,s);x<0&&y>328||u.push({x:f+t/2,y:d+r/2,dx:m,dy:g,dist:y,angle:Math.atan2(g,m),seed:(0,l.hash)(h,e),grain:(0,l.hash)(5.7*h+19,2.3*e+53),gap:.05+.3*(0,l.hash)(7.3*h+11,3.1*e+5),emoji:(0,l.hash)(2.7*h+31,5.9*e+17)<l.EMOJI_RATIO,speck:(0,l.hash)(4.1*h+23,6.3*e+41),letter:x,word:-1})}b.current=u,T.current&&h(u,a,i,T.current.text),E.current={ascii:Array.from({length:l.RAMP.length},()=>new Int32Array(u.length)),emoji:Array.from({length:l.RAMP.length},()=>new Int32Array(u.length)),asciiN:new Int32Array(l.RAMP.length),emojiN:new Int32Array(l.RAMP.length),glyph:Array(u.length)};let y=Math.min(2,window.devicePixelRatio||1);e.width=p*y,e.height=p*y,e.style.width=`${p}px`,e.style.height=`${p}px`;let x=e.getContext("2d");return x&&(x.setTransform(y,0,0,y,0,0),x.font=`700 ${m}px ui-monospace,SFMono-Regular,Menlo,monospace`,x.textAlign="center",x.textBaseline="middle",A.current=x),()=>{x?.clearRect(0,0,p,p),b.current=[],E.current=null}},[m,g,p]),(0,r.useEffect)(()=>{S.current=d},[d]),(0,r.useEffect)(()=>{_.current.target=y},[y]),(0,r.useEffect)(()=>{L.current.mode!==s&&(L.current={mode:s,start:.001*performance.now()})},[s]),(0,r.useEffect)(()=>{if(!M||Date.now()-M.at>(M.hold??3.4)*1e3)return;let{cw:e,ch:t}=k.current,r=performance.now(),n=r-R.current<600?.11*M.text.length+.3+.45:0;T.current={text:M.text,start:.001*r-n,letters:h(b.current,e,t,M.text),hold:M.hold??3.4}},[M]),(0,r.useEffect)(()=>{let e=0,t=(0,a.createVoiceFollower)(),r=Array(a.SPECTRUM_BANDS).fill(0),n=.001*performance.now(),i=0,s=0,o=a=>{let c=.001*a,h=Math.min(.05,Math.max(0,c-n));n=c;let f=A.current,d=E.current;if(!f||!d){e=requestAnimationFrame(o);return}let m=S.current,g=w.current;d.asciiN.fill(0),d.emojiN.fill(0);let p=N.current?.();if(!p||p.length<2){for(let e=0;e<r.length;e++){let t=.5*Math.sin(1.7*c+1.7*e)+.3*Math.sin(.8*c+.6*e)+.2*Math.sin(3*c+2.9*e);r[e]=.5*t+.5}p=r}let y=v.current,x=t.read(p,h);y.phrase=x.phrase,x.onset>0&&(y.bobVel+=.06*x.onset,y.rings.push({born:c,power:x.onset}),y.rings.length>5&&y.rings.shift()),y.bobVel+=-(.012*y.bob)-.09*y.bobVel,y.bob+=y.bobVel,i+=h;for(let e=0;e<4;e++){let t=Math.floor(e*x.bands.length/4),r=Math.max(t+1,Math.floor((e+1)*x.bands.length/4)),n=0;for(let e=t;e<r;e++)n+=x.bands[e];n/=r-t;let a=.7+.6*(0,l.hash)((.9*c|0)+31*e,e);y.amp[e]+=(n*a-y.amp[e])*(.05+.02*e),y.phase[e]+=h*(.9+.5*e)*(e%2?-1:1)}for(y.spin+=h*(1.1+.9*y.phrase);y.rings.length>0&&c-y.rings[0].born>.7;)y.rings.shift();let M=L.current,O=T.current,R=O?c-O.start:0,k=null!==O&&"error"!==M.mode&&R<O.hold+.08*O.letters+.45+.35+.9?{scale:0,lift:0,gather:0,comet:0,speech:0,err:0,word:1}:function(e,t){let r={scale:1,lift:0,gather:0,comet:0,speech:0,err:0,word:0};switch(e){case"idle":return r;case"connecting":{let e=1-Math.exp(-t/1.3);return{...r,scale:.45+.55*e,lift:.06*e,gather:1}}case"speaking":return{...r,speech:1};case"working":return{...r,scale:0,comet:1};case"ending":return{...r,scale:0};case"error":return{...r,scale:0,err:1}}}(M.mode,c-M.start),j=I.current;j.scale=u(j.scale,k.scale,.45,"ending"===M.mode?.4:.7,h),j.lift=u(j.lift,k.lift,.22,.4,h),j.gather=u(j.gather,k.gather,.3,.95,h),j.comet=u(j.comet,k.comet,.45,.9,h),j.speech=u(j.speech,k.speech,.5,.75,h),"error"===M.mode&&(j.err<=.01&&(s=0),s+=h),j.err=u(j.err,k.err,.5,.6,h),j.word=u(j.word,k.word,.35,.5,h);let P=j.err>.5,C=j.word>.5,V="emojiOnly"===m?l.EMOJI_CHAR_RATE:l.CHAR_RATE,D=b.current;for(let e=0;e<D.length;e++){let t=D[e],r=function(e,t,r,n,a,i,s){let o,u,c,h,f=i.scale>.02?function(e,t,r=0,n=1){let a=170*Math.max(.02,n),i=1-(0,l.smoothstep)(.55*a,a,e.dist);return(.58+r+.2*Math.sin(.05*e.dist-.4*t)+.07*Math.sin(.35*t))*i}(e,t,i.lift,i.scale)*(1-.6*i.speech):0;return i.gather>.01&&(f+=function(e,t,r){let n=170*r;if(e.speck>=.55||e.dist<.8*n)return 0;let a=Math.min(55,Math.floor((e.angle+Math.PI)/(2*Math.PI)*56)),i=(.7*t+(0,l.hash)(a,5.3))%1,s=e.dist-(n+(320-n)*(1-i)**1.25)-(e.grain-.5)*16;return Math.exp(-(s*s)/260)*(0,l.smoothstep)(0,.2,i)*(1-i)*1.1}(e,t,i.scale)*i.gather),i.comet>.01&&(f+=(u=Math.exp(-((o=e.dist-210)*o)/1100),u*Math.exp(-((h=Math.atan2(Math.sin(c=e.angle-3*t),Math.cos(c)))*h)/(h<0?2.8:.16))*i.comet)),i.speech>.01&&(f+=function(e,t,r,n){var a;let l=170+40*r.phrase+85*r.bob;for(let t=0;t<4;t++)l+=28*r.amp[t]*Math.sin((t+2)*(e.angle+r.spin)+r.phase[t]);let i=170+(((a=l)<=205?Math.max(110,a):205+30*Math.tanh((a-205)/30))-170)*n,s=(e.grain-.5)*20+20*Math.sin(5*e.angle+.9*t+6.283*e.seed)*.3,o=e.dist-(i+s),u=Math.exp(-(o*o)/800)+.5*Math.exp(-(e.dist*e.dist)/6e3);if(e.dist<i&&(u+=.22*(1-e.dist/i)**.6*(.75+.25*Math.sin(.05*e.dist-1.2*t))),e.speck<.22){let n=90*(.6+.9*e.grain);for(let a=0;a<r.rings.length;a++){let l=r.rings[a],s=t-l.born,o=e.dist-(i+6+s*n);u+=Math.exp(-(o*o)/500)*l.power*Math.max(0,1-s/.7)}}return u}(e,t,s,i.speech)*i.speech),i.err>.01&&(f+=function(e,t,r){if(e.letter<0)return 0;let n=r%9.2,a=.12*e.seed;return Math.max(0,(0,l.smoothstep)(0,1,(n-.65*e.letter-a)/.8)-(0,l.smoothstep)(0,1,(n-5.6-.5*e.letter-a)/.7))*(.86+.14*Math.sin(3.5*t+6*e.seed))}(e,t,r)*i.err),i.word>.01&&(f+=function(e,t,r,n){if(e.word<0)return 0;let a=.45*e.seed,i=(0,l.smoothstep)(0,1,(r-.11*e.word-a)/.3),s=r-n-.08*e.word-a,o=(0,l.smoothstep)(0,1,s/.35),u=.2*(1-(0,l.smoothstep)(0,1,(s-.35)/.9));return Math.max(i-o,i>.5?u*o:0)*((i>0&&i<1||o>0&&u>0)&&.35>(0,l.hash)(Math.floor(14*t)+97*e.seed,31*e.grain)?.25:1)*(.86+.14*Math.sin(3.5*t+6*e.seed))}(e,t,n,a)*i.word),f}(t,c,s,R,O?.hold??3.4,j,y);!(P&&t.letter>=0||C&&t.word>=0)&&((r*=(.66+.72*t.grain)*(.8+.4*(0,l.hash)(Math.floor(.05*t.dx+.5*c),Math.floor(.05*t.dy-.3*c))))>.3&&(0,l.hash)(31.7*Math.floor(1.6*c),613*t.seed)>.992&&(r=Math.max(r,.9)),r<t.gap+.05*Math.sin(.28*c+6.283*t.seed)&&(r=0));let n=(r=r<0?0:r>1?1:r)*(l.RAMP.length-1)|0;if(0===n)continue;let a=i*V+7*t.seed|0;if("emojiOnly"===m||"emoji"===m&&t.emoji&&n>=l.EMOJI_MIN_LEVEL){let r=((t.seed*l.EMOJI_POOL.length|0)+a)%l.EMOJI_POOL.length;d.glyph[e]=l.EMOJI_POOL[r],d.emoji[n][d.emojiN[n]++]=e}else{let r=l.RAMP[n],i=((t.seed*r.length|0)+a)%r.length;d.glyph[e]=r[i],d.ascii[n][d.asciiN[n]++]=e}}f.clearRect(0,0,g,g);let $=b.current,K=l.RAMP.length-1,F=_.current;for(let e=0;e<3;e++)F.cur[e]+=(F.target[e]-F.cur[e])*.05;f.fillStyle=`rgb(${0|F.cur[0]},${0|F.cur[1]},${0|F.cur[2]})`;for(let e=1;e<=K;e++){let t=d.asciiN[e];if(0===t)continue;f.globalAlpha=l.ALPHA_TOP*(e/K);let r=d.ascii[e];for(let e=0;e<t;e++){let t=$[r[e]];f.fillText(d.glyph[r[e]],t.x,t.y)}}for(let e=1;e<=K;e++){let t=d.emojiN[e];if(0===t)continue;f.globalAlpha=.35+e/K*.65;let r=d.emoji[e];for(let e=0;e<t;e++){let t=$[r[e]];f.fillText(d.glyph[r[e]],t.x,t.y)}}f.globalAlpha=1,e=requestAnimationFrame(o)};return e=requestAnimationFrame(o),()=>cancelAnimationFrame(e)},[]),(0,t.jsx)("canvas",{ref:O,className:e,"aria-hidden":!0,style:{display:"block",pointerEvents:"none"}})}var d=e.i(922521),m=e.i(647163);let g={ending:"ending",idle:"idle",connecting:"connecting",listening:"idle",speaking:"speaking",working:"working",delegating:"working"},p=[247,247,247],y=[10,10,10];function x({status:e,failed:r,word:n,size:a,getSpectrum:l,look:i,className:s}){let o="dark"===(0,d.useResolvedTheme)();return(0,t.jsx)(f,{mode:r?"error":g[e],word:n,size:a,color:o?p:y,getSpectrum:l,charset:i.charset,fontSize:i.fontSize,density:i.density,className:s})}let M=(0,r.memo)(function({look:e,status:n="idle",size:a=448,className:l,...i}){let s=(0,r.useRef)(null),[o,u]=(0,r.useState)(a),[c,h]=(0,r.useState)(!1);return(0,r.useEffect)(()=>{let e=s.current;if(!e)return;let t=new ResizeObserver(([e])=>{let t=Math.round(e.contentRect.width);t>0&&u(t)});return t.observe(e),()=>t.disconnect()},[]),(0,r.useEffect)(()=>{let e=requestAnimationFrame(()=>h(!0));return()=>cancelAnimationFrame(e)},[]),(0,t.jsx)("div",{ref:s,className:(0,m.cn)("aspect-square transition-opacity duration-700 ease-out",c?"opacity-100":"opacity-0",l),children:(0,t.jsx)(x,{...i,look:e,status:n,size:o})})});e.s(["Face",0,M],333495)},67045,e=>{"use strict";let t,r;var n=e.i(768834);let a=e=>t=>{try{let r=e(t);if(r instanceof Promise)return r;return{then:e=>a(e)(r),catch(e){return this}}}catch(e){return{then(e){return this},catch:t=>a(t)(e)}}};var l=e.i(149666),i=e.i(265402),s=e.i(671228);let o=l.LiveSettingsSchema.extend({wake:s.WakeSchema.catch(s.WAKE_DEFAULT),hotkey:s.HotkeySchema.catch(s.HOTKEY_DEFAULT),callBack:s.CallBackSchema.catch(s.CALL_BACK_DEFAULT),captionView:s.CaptionViewSchema.catch("sides"),textModel:i.textModelRefSchema.nullable().catch(null)}),u={...l.LIVE_DEFAULTS,wake:s.WAKE_DEFAULT,hotkey:s.HOTKEY_DEFAULT,callBack:s.CALL_BACK_DEFAULT,captionView:"sides",textModel:null},c=(0,n.create)()((t=e=>({...u,patch:t=>e(t)}),r={name:"thursday.settings",version:1,migrate:(e,t)=>t<1&&e&&"object"==typeof e?{...e,webSearch:!0}:e,merge:(e,t)=>{let r=o.safeParse((0,l.migrateLiveSettings)(e)),n=r.success?r.data:u;return{...t,...n}}},(e,n,l)=>{let i,s={storage:function(e){let t;try{t=e()}catch(e){return}return{getItem:e=>{var r;let n=e=>null===e?null:JSON.parse(e,void 0),a=null!=(r=t.getItem(e))?r:null;return a instanceof Promise?a.then(n):n(a)},setItem:(e,r)=>t.setItem(e,JSON.stringify(r,void 0)),removeItem:e=>t.removeItem(e)}}(()=>window.localStorage),partialize:e=>e,version:0,merge:(e,t)=>({...t,...e}),...r},o=!1,u=0,c=new Set,h=new Set,f=s.storage;if(!f)return t((...t)=>{console.warn(`[zustand persist middleware] Unable to update item '${s.name}', the given storage is currently unavailable.`),e(...t)});let d=()=>{let e=s.partialize({...n()});return f.setItem(s.name,{state:e,version:s.version})},m=l.setState;l.setState=(e,t)=>(m(e,t),d());let g=t((...t)=>(e(...t),d()));l.getInitialState=()=>g;let p=()=>{var t,r;if(!f)return;let l=++u;o=!1,c.forEach(e=>{var t;return e(null!=(t=n())?t:g)});let m=(null==(r=s.onRehydrateStorage)?void 0:r.call(s,null!=(t=n())?t:g))||void 0;return a(f.getItem.bind(f))(s.name).then(e=>{if(e)if("number"!=typeof e.version||e.version===s.version)return[!1,e.state];else{if(s.migrate){let t=s.migrate(e.state,e.version);return t instanceof Promise?t.then(e=>[!0,e]):[!0,t]}console.error("State loaded from storage couldn't be migrated since no migrate function was provided")}return[!1,void 0]}).then(t=>{var r;if(l!==u)return;let[a,o]=t;if(e(i=s.merge(o,null!=(r=n())?r:g),!0),a)return d()}).then(()=>{l===u&&(null==m||m(n(),void 0),i=n(),o=!0,h.forEach(e=>e(i)))}).catch(e=>{l===u&&(null==m||m(void 0,e))})};return l.persist={setOptions:e=>{s={...s,...e},e.storage&&(f=e.storage)},clearStorage:()=>{++u,null==f||f.removeItem(s.name)},getOptions:()=>s,rehydrate:()=>p(),hasHydrated:()=>o,onHydrate:e=>(c.add(e),()=>{c.delete(e)}),onFinishHydration:e=>(h.add(e),()=>{h.delete(e)})},s.skipHydration||p(),i||g}));e.s(["thursdaySettings",0,()=>l.LiveSettingsSchema.parse(c.getState()),"useThursdayStore",0,c],67045)},561540,e=>{"use strict";var t=e.i(213377);let r={[t.TOOL_NAMES.memory_recall]:"Checking your notes",[t.TOOL_NAMES.memory_remember]:"Noting that down",[t.TOOL_NAMES.memory_forget]:"Forgetting that",[t.TOOL_NAMES.memory_conversation]:"Reading back an earlier call",[t.TOOL_NAMES.bash]:"Doing it on this computer",[t.TOOL_NAMES.web_search]:"Searching the web",[t.TOOL_NAMES.load_skill]:"Reading how to do this",[t.TOOL_NAMES.look_at]:"Looking at the picture",[t.TOOL_NAMES.end_call]:"Ending the call",[t.TOOL_NAMES.routine]:"Checking your routines"};function n(e){if(!e)return null;try{let t=JSON.parse(e);if(t&&"object"==typeof t&&!Array.isArray(t))return t}catch{}return null}let a=new Set([t.TOOL_NAMES.thread_tell,t.TOOL_NAMES.thread_answer,t.TOOL_NAMES.thread_status,t.TOOL_NAMES.thread_show,t.TOOL_NAMES.thread_cancel,t.TOOL_NAMES.thread_seen]);function l(e,r){if(e!==t.TOOL_NAMES.web_search)return null;try{let e=JSON.parse(r),t=Array.isArray(e.sources)?e.sources.flatMap(e=>e&&"object"==typeof e&&"string"==typeof e.url?[e]:[]):[];return{query:"string"==typeof e.query?e.query:null,sources:t}}catch{return null}}e.s(["searchOf",0,l,"searchQueryOf",0,function(e){let t=n(e)?.query;return"string"==typeof t&&t.trim()?t.trim():null},"searchSourcesOf",0,function(e){let r=n(e);return r?l(t.TOOL_NAMES.web_search,JSON.stringify(r))?.sources??[]:[]},"startedLabel",0,function(e,r){if(e!==t.TOOL_NAMES.thread_start)return null;try{let e=JSON.parse(r);return"string"==typeof e.label?e.label:null}catch{return null}},"toolBot",0,function(e,r,l,i){let s=n(r);if(!s)return null;if(e===t.TOOL_NAMES.thread_start)return"string"==typeof s.bot&&s.bot.trim()?s.bot.trim():null;if(!a.has(e))return null;let o="string"==typeof s.thread?s.thread.trim():"";if(!o||"all"===o.toLowerCase())return null;let u=o.toLowerCase(),c=l?.find(e=>e.id===o)??l?.find(e=>e.label.toLowerCase()===u);return c?e===t.TOOL_NAMES.thread_answer?c.room.questions[0]?.bot??c.bot:c.bot:function(e){let t=n(e);if(!t)return null;if("string"==typeof t.bot&&t.bot.trim())return t.bot.trim();let r=t.answered;return"string"==typeof r?.bot?r.bot:null}(i)},"toolLine",0,function(e,a,l=null){let i;if(e===t.TOOL_NAMES.tool_search||e===t.TOOL_NAMES.tool_call)return"Reaching a connected service";let s=n(a);return(s&&function(e,r,n){if(e===t.TOOL_NAMES.memory_remember){let e="string"==typeof r.path?r.path.trim():"",t=function(e){if(!Array.isArray(e.facts))return null;let t=e.facts.map(e=>e&&"object"==typeof e&&"string"==typeof e.text?e.text.trim():"").filter(Boolean);return t.length?{text:t[0],more:t.length-1}:null}(r);if(!e)return null;if(!t)return`Noting that under ${e}`;let n=t.more>0?` (+${t.more})`:"";return`Noting under ${e}: ${function(e){let t=e.trim().replace(/\s+/g," ");if(t.length<=28)return t;let r=t.slice(0,28),n=r.lastIndexOf(" ");return`${(n>14?r.slice(0,n):r).trimEnd()}…`}(t.text)}${n}`}if(e===t.TOOL_NAMES.thread_start){let e="string"==typeof r.bot?r.bot.trim():"";return e?`Handing this to ${e}`:"Handing this over"}if(e===t.TOOL_NAMES.web_search){let e="string"==typeof r.query?r.query.trim():"";return e?`Searching \xb7 ${e}`:null}if(e===t.TOOL_NAMES.routine){if("create"===r.action){let e=["string"==typeof r.bot?r.bot.trim():"",function(e){if("string"==typeof e.at&&e.at.length>=16){let[t,r]=e.at.split(" "),[n,a,l]=t.split("-").map(Number),i=new Date(n,a-1,l);if(i.toDateString()===new Date().toDateString())return`once at ${r}`;let s=i.toLocaleDateString("en-US",{month:"short",day:"numeric"});return`once, ${s} ${r}`}return"string"==typeof e.time&&e.time?`daily at ${e.time}`:"number"==typeof e.everyHours?`every ${e.everyHours} hours`:null}(r)].filter(Boolean).join(", ");return e?`Setting a routine \xb7 ${e}`:"Setting a routine"}return"change"===r.action?"Changing a routine":"delete"===r.action?"Deleting a routine":null}let a="string"==typeof r.thread?r.thread.trim():"";return e===t.TOOL_NAMES.thread_tell?n?`Telling ${n}`:"Passing that on":e===t.TOOL_NAMES.thread_answer?n?`Answering ${n}`:"Answering that":e===t.TOOL_NAMES.thread_cancel?a?`Stopping ${a}`:"Stopping that":e===t.TOOL_NAMES.thread_seen?a?`Marking ${a} as read`:"Marking that as read":e===t.TOOL_NAMES.thread_show?a?`Opening ${a}`:"Opening that":e===t.TOOL_NAMES.thread_status?a&&"all"!==a.toLowerCase()?`Checking on ${a}`:"Checking on the work":null}(e,s,l))??r[e]??((i=e.indexOf("__"))<=0?null:`Reaching ${e.slice(0,i).replace(/[-_]/g," ")}`)}])},319841,e=>{"use strict";var t=e.i(271645);let r=["ctrl","alt","meta"],n=/^(Control|Alt|Shift|Meta|OS)/,a=/^(input|textarea|select)$/i,l=e=>!!e&&!!(a.test(e.tagName)||e.isContentEditable||e.closest?.("[data-hotkey-capture]"));function i(e){let{code:t,ctrlKey:r,altKey:a,shiftKey:l,metaKey:i}=e;if(!t||n.test(t)||!r&&!a&&!i)return null;let s=[];return r&&s.push("ctrl"),a&&s.push("alt"),l&&s.push("shift"),i&&s.push("meta"),[...s,t].join("+")}let s={ctrl:["Ctrl","⌃"],alt:["Alt","⌥"],shift:["Shift","⇧"],meta:["Meta","⌘"]};e.s(["HOTKEY_CAPTURE",0,{"data-hotkey-capture":""},"capturesKeys",0,l,"comboOf",0,i,"isCombo",0,e=>{let t=e.split("+"),a=t.at(-1);return!!(a&&!n.test(a)&&t.slice(0,-1).some(e=>r.includes(e)))},"useHotkey",0,function({enabled:e,combo:r,onPress:n}){let a=(0,t.useRef)(n);a.current=n,(0,t.useEffect)(()=>{if(!e||!r)return;let t=e=>{e.repeat||l(e.target)||i(e)===r&&(e.preventDefault(),a.current())};return window.addEventListener("keydown",t),()=>window.removeEventListener("keydown",t)},[e,r])},"useHotkeyLabel",0,function(e){let[r,n]=(0,t.useState)(!1);return(0,t.useEffect)(()=>n(/mac/i.test(navigator.userAgent)),[]),e?function(e,t=!1){let r=e.split("+"),n=r.at(-1)??"",a=r.slice(0,-1).map(e=>s[e]?.[+!!t]??e),l=n.replace(/^(Key|Digit|Numpad)/,"").replace(/([a-z])([A-Z])/g,"$1 $2")||n;return t?[...a,l].join(""):[...a,l].join(" + ")}(e,r):null}])}]);
package/README.md CHANGED
@@ -14,7 +14,7 @@ You talk. Bots take the slow work to a real browser, a shell and your files, and
14
14
 
15
15
  [English](README.md) · [한국어](README.ko.md)
16
16
 
17
- ![A live call: she answers a weather question herself while a bot's finished page lands in the corner](docs/images/demo.gif)
17
+ ![A live call: asked "Jarvis, how's it going?", she checks on the bot's job and says the GitHub Trending page is done](docs/images/demo.gif)
18
18
 
19
19
  [▶ Watch the 90-second demo, with sound](https://youtu.be/V7fBDY3cYRU)
20
20
 
@@ -2,12 +2,9 @@ import { asSchema } from "ai";
2
2
  import z from "zod";
3
3
  import { loadTools } from "@/features/ai/load-tools";
4
4
  import { modelErrorToString } from "@/features/ai/model";
5
- import { createServerProbe } from "@/lib/probe.server";
6
5
  import { serverRoute } from "@/lib/protocol/server-route";
7
6
  import { publicError } from "@/lib/public-error";
8
7
 
9
- const probe = createServerProbe("server");
10
-
11
8
  /**
12
9
  * Executes a tool call from the voice session. The page forwards what the model
13
10
  * asked for; bots never come through here (they call `execute` directly).
@@ -58,7 +55,6 @@ export const POST = serverRoute(async (request) => {
58
55
  );
59
56
  }
60
57
 
61
- const began = Date.now();
62
58
  try {
63
59
  const output = await tool.execute(parsed?.value ?? input ?? {}, {
64
60
  toolCallId,
@@ -66,18 +62,8 @@ export const POST = serverRoute(async (request) => {
66
62
  context: undefined,
67
63
  abortSignal: request.signal,
68
64
  });
69
- const drained = await drain(output);
70
- probe("tool", {
71
- callId,
72
- name,
73
- input,
74
- ms: Date.now() - began,
75
- // The rows keep a tool's arguments only; what it answered is kept here
76
- output: JSON.stringify(drained)?.slice(0, 3000),
77
- });
78
- return { output: drained };
65
+ return { output: await drain(output) };
79
66
  } catch (cause) {
80
- probe("tool.failed", { callId, name, input, error: String(cause) });
81
67
  // A tool failure is a line the model reads and recovers from, not a masked server error.
82
68
  publicError(`"${name}" failed: ${modelErrorToString(cause)}`);
83
69
  }
Binary file
@@ -23,17 +23,20 @@ delegation is a different integration: its notification contains metadata, not t
23
23
  text, so the application would have to reconstruct the request and operate the backend.
24
24
 
25
25
  The voice and the backend are one assistant. Both prompts open with the same identity
26
- (`thursdayIdentity`) and the same rule for ending the call (`callEnding`), read the same
26
+ (`thursdayIdentity`), each followed by its own rule for ending the call, read the same
27
27
  memory, and neither is told it is part of something else. The voice holds conversation and
28
28
  memory only. Right under the identity, `## Always` groups what holds on every turn: the ending
29
29
  rule (the only line marked `IMPORTANT`), the guide's starter backchannel and interruption
30
- policies, and under the guide's `Delegation policy` label three lines — hand everything but
31
- greetings, small talk and a brief clarification to the backend; hand over whatever the user says
32
- about themselves, their people, their plans or how they want things done as they say it, unless
33
- it is already written in the prompt; answer from what the backend returns without guessing while
34
- waiting. Live decides by itself whether to delegate, so the rule stays even this short. It says
35
- nothing else about how to speak; it sees no tool schema and no tool name but `end_call`, in the
36
- ending rule. The backend prompt holds the work: memory (merging a fact that repeats or changes one
30
+ policies, and the guide's `Delegation policy` under its three labels: `Backend tools` names
31
+ what the backend can do (end the call, background work, routines, memory, this computer and the
32
+ web) and never how; `Delegate to the backend when` is the user wanting the call to end, anything
33
+ on that list or a change to work already asked for, and whatever the user says about themselves,
34
+ their people, their plans or how they want things done, unless it is already written in the
35
+ prompt; `Do not delegate to the backend when` is greetings, small talk, only wanting her to stop
36
+ talking, what the conversation already answers, and a brief clarification. Live decides by
37
+ itself whether to delegate, and it decides from that list: without it (09-17 to 09-19) a
38
+ hang-up, a stop or a routine was answered and never handed over. It says nothing else about how
39
+ to speak; it sees no tool schema and no tool name but `end_call`, in the ending rule. The backend prompt holds the work: memory (merging a fact that repeats or changes one
37
40
  already kept, and tidying with the user past the limits), background work and threads, this
38
41
  computer, what to return, and the earlier calls. A request that carries earlier work further goes to
39
42
  that thread; one that stands on its own opens a new one; it asks the user only when it could be
@@ -212,10 +215,15 @@ for a goodbye, which would leave the ending to the model.
212
215
 
213
216
  The user wanting the call to end, however they say it, sets everything else aside: the
214
217
  voice answers yes and hands it to the backend at once, and the backend runs `end_call`
215
- without deliberating. The ending rule names `end_call` in the voice prompt too, the one tool
216
- name it holds: without it, ending read as something to say rather than do.
218
+ without deliberating. The voice's rule names `end_call` too, the one tool name it holds:
219
+ without it, ending read as something to say rather than do. The two rules say what each
220
+ side can do: while they were one sentence ("forget every other task, answer yes, then use
221
+ the tool"), the voice said yes and went quiet with the line open, four times in five
222
+ (09-20), so its rule says to hand the turn over, and that a yes alone leaves the line open.
217
223
  Whether that turn reaches the backend at all is the voice's own decision, and it often
218
- answers and hands nothing over (measured 09-18: eight calls, none ended by asking). The
224
+ answers and hands nothing over. Ending the call leads the `Backend tools` list for that
225
+ reason: with the list, five calls in seven ended by asking (09-16); without it, one in 21,
226
+ then none in 34 (09-17 to 09-19). The
219
227
  quiet hang-up below is what ends such a call.
220
228
  The page does not close on `end_call` itself: it waits until her voice has been quiet
221
229
  for `CALL_END.quietMs`, or `CALL_END.unsaidMs` when nothing was said, never past
@@ -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",
@@ -1,3 +1,4 @@
1
+ import { TOOL_NAMES } from "@/features/ai/tools/tool-name";
1
2
  import {
2
3
  listAlwaysLoaded,
3
4
  listNoteIndex,
@@ -10,7 +11,6 @@ import {
10
11
  type MemoryNoteView,
11
12
  } from "@/features/memory/memory.schema";
12
13
  import {
13
- callEnding,
14
14
  carriedLines,
15
15
  expandedFacts,
16
16
  logPromptSize,
@@ -21,16 +21,15 @@ import {
21
21
 
22
22
  /**
23
23
  * Everything the Live voice hears: who Thursday is and how a call ends (the words the backend
24
- * opens with too), the guide's starter backchannel and interruption policies, a two-line
25
- * delegation policy, and what she knows about the user. What the backend can do, how work is
26
- * handed over, earlier calls and tidying memory are the backend's (thursday.prompt): the voice
27
- * hands everything but conversation over and answers from what comes back. Assembled on every
28
- * call, never cached.
24
+ * opens with too), the guide's starter backchannel and interruption policies, its delegation
25
+ * policy (what the backend can do, when to hand over and when not), and what she knows about
26
+ * the user. How the work is done, earlier calls and tidying memory are the backend's
27
+ * (thursday.prompt): the voice hands everything but conversation over and answers from what
28
+ * comes back. Assembled on every call, never cached.
29
29
  */
30
30
  export async function loadLivePrompt(options: {
31
31
  /** Settings › Thursday › Voice instructions; added to, never replacing, what is below. */
32
32
  voicePrompt?: string | null;
33
- locale?: string | null;
34
33
  /** The page placed this call because background work waits on the user (call-back). */
35
34
  calledBack?: boolean;
36
35
  /** The last call is in the conversation ahead of the opening (call-last). */
@@ -45,11 +44,6 @@ export async function loadLivePrompt(options: {
45
44
 
46
45
  const first = !open.notes.find((note) => note.path === "profile")?.facts
47
46
  .length;
48
- // Only the first-call greeting reads it: before they have said anything, the
49
- // browser's locale is the one sign of their language
50
- const language = options.locale
51
- ? `the language of \`${options.locale}\`, their browser's setting`
52
- : "the language they use";
53
47
 
54
48
  const text = [
55
49
  thursdayIdentity(),
@@ -69,7 +63,7 @@ export async function loadLivePrompt(options: {
69
63
  opening: options.calledBack
70
64
  ? "You placed this call because background work has something for the user; it comes in next. Speak first: greet them in one line and say that is why you called."
71
65
  : first
72
- ? `Open the call now, in ${language}: say who you are and what you are here to do for them, in a line or two, then ask what to call them. Then stop and listen.`
66
+ ? "Open the call now: say who you are and what you are here to do for them, in a line or two, then ask what to call them. Then stop and listen."
73
67
  : options.remembers
74
68
  ? "The call has just started. Speak first: greet the user naturally, in one line, as someone who remembers the last call."
75
69
  : "The call has just started. Speak first: greet the user naturally, in one line.",
@@ -79,40 +73,71 @@ export async function loadLivePrompt(options: {
79
73
  /**
80
74
  * The rules for every turn, together right under the identity, where the model weighs most.
81
75
  * One heading marks them; `IMPORTANT` stays on the ending rule alone, the one that failed
82
- * without it (09-17), so stamping it on all four would thin it out.
76
+ * without it (09-17), so stamping it on all of them would thin it out.
83
77
  */
84
78
  const always = () => `## Always
85
79
 
86
- ${callEnding()}
80
+ ${ending()}
87
81
 
88
82
  ${speaking()}
89
83
 
90
84
  ${delegation()}`;
91
85
 
86
+ /**
87
+ * How a call ends, as the voice can end it: it holds no tools, so it says yes and hands the turn
88
+ * over, and the backend runs the tool. The rule both prompts shared until 09-20 ("forget every
89
+ * other task, answer yes, then use the tool") left the voice saying yes and going quiet with the
90
+ * line still open, four times in five. The tool is still named, the one name the voice sees, so
91
+ * ending reads as something done rather than said.
92
+ */
93
+ const ending = () =>
94
+ `IMPORTANT — always follow this: when the user wants the call to end, however they say it, answer yes in one word of their language and hand it to the backend at once. Only the backend can end the line, with the ${TOOL_NAMES.end_call} tool; saying yes alone leaves it open.`;
95
+
92
96
  /**
93
97
  * The guide's starter lines on listening and interruptions, labels kept as it says. The
94
98
  * backchannel line is the one it invites changing: a long turn heard in silence reads as
95
- * nobody listening.
99
+ * nobody listening. The language is the one being spoken, never the browser's: a first call
100
+ * opened in the browser's language kept an English speaker in Korean.
96
101
  */
97
102
  function speaking(): string {
98
103
  return `Backchannel policy: Use moderate backchannels. When the user speaks at length, acknowledge now and then with a short listening sound so they know you are following, without competing with the main response.
99
104
 
100
- Interruption policy: Stop speaking when the user interrupts. Listen to what they say.`;
105
+ Interruption policy: Stop speaking when the user interrupts. Listen to what they say.
106
+
107
+ Speak the language the user is speaking, whatever language came before; when they switch, switch with them.`;
101
108
  }
102
109
 
103
110
  /**
104
- * Under the guide's label, and no longer than this: Live decides for itself whether to hand a
105
- * turn over, and with no rule it answered from its own knowledge or only said it would act.
106
- * What the backend can do and how is the backend's to know. What they say about themselves is
107
- * named on its own: nothing is kept that is not handed over, and it is rarely a request. The
108
- * voice sees only profile and preferences whole, so "already written" is a rough filter; the
109
- * backend merges the rest (thursday.prompt memory).
111
+ * The guide's three labels, as it asks: Live decides for itself whether to hand a turn over,
112
+ * and reads that from what the list says the backend can do. Without the list (09-17 to 09-19)
113
+ * it said "yes" to a hang-up, a stop or a routine and handed nothing over: 1 `end_call` in 21
114
+ * calls, then none in 34, where the list had drawn 5 in 7. The list names what can be done,
115
+ * never how: tools, bots and threads stay the backend's. What they say about themselves is
116
+ * its own line: nothing is kept that is not handed over, and it is rarely a request. The voice
117
+ * sees only profile and preferences whole, so "already written" is a rough filter; the backend
118
+ * merges the rest (thursday.prompt memory). Stopping her voice is not stopping a job (the
119
+ * guide's interruptions): the one is hers, the other the backend's.
110
120
  */
111
121
  function delegation(): string {
112
122
  return `Delegation policy:
113
- Delegate to the backend everything the user asks for, tells you or asks about, except greetings, small talk and a brief clarification.
114
- Whatever they tell you about themselves, the people in their life, their plans or how they want things done goes to the backend as they say it, however small — unless it is already written below.
115
- Answer from what the backend returns, and do not guess the result while waiting.`;
123
+ Backend tools:
124
+ - Ending the call: hangs up the line.
125
+ - Background work: hands a job to a bot, passes words on, stops or changes a job, answers a bot's question, says how the work stands.
126
+ - Routines: jobs that start by themselves later.
127
+ - Memory: keeps what the user tells you about themselves, and looks it up.
128
+ - This computer and the web: runs a command, searches.
129
+
130
+ Delegate to the backend when:
131
+ - The user wants the call to end.
132
+ - They ask for anything on that list, or change or stop work already asked for.
133
+ - They tell you about themselves, the people in their life, their plans or how they want things done, however small, unless it is already written below.
134
+
135
+ Do not delegate to the backend when:
136
+ - They greet you, make small talk, or only want you to stop talking.
137
+ - You can answer from the conversation or a result still current.
138
+ - You need a brief clarification to understand the request.
139
+
140
+ Delegate before giving an answer that depends on backend work. Do not guess the result while waiting.`;
116
141
  }
117
142
 
118
143
  /**
@@ -22,7 +22,7 @@ import { clip } from "@/lib/utils";
22
22
  /**
23
23
  * Row-to-line formatters shared by the call prompts (live, thursday) and bot.prompt, plus the tidying check.
24
24
  * Nothing here wraps a sentence; headings and paragraphs live in the prompt that says them. The
25
- * exceptions are `thursdayIdentity` and `callEnding`, the words both call prompts open with.
25
+ * exception is `thursdayIdentity`, the words both call prompts open with.
26
26
  */
27
27
 
28
28
  /**
@@ -85,14 +85,6 @@ export const thursdayIdentity = (now = new Date()) =>
85
85
 
86
86
  What they tell you is kept, so you know them better over time, and whatever they want done can be done for them in the background.`;
87
87
 
88
- /**
89
- * How a call ends, in the same words right after the identity in both call prompts. It names
90
- * the tool in both, the one tool name the voice sees: without it, ending the call read as
91
- * something to say rather than do, and the line stayed open through repeated requests.
92
- */
93
- export const callEnding = () =>
94
- `IMPORTANT — always follow this: when the user wants the call to end, however they say it, forget every other task, answer yes in one word of their language, then immediately, without thinking, use the ${TOOL_NAMES.end_call} tool.`;
95
-
96
88
  /**
97
89
  * When a call happened, the one way every prompt and tool says it: local, the
98
90
  * same shape as `Now` (clockNow), with how long ago. A UTC stamp beside a local
@@ -28,7 +28,6 @@ import {
28
28
  import { openWorkspace } from "@/features/workspace/workspace";
29
29
  import { listConnectedToolNames } from "../tools/connected";
30
30
  import {
31
- callEnding,
32
31
  carriedLines,
33
32
  expandedFacts,
34
33
  logPromptSize,
@@ -88,7 +87,7 @@ export async function loadThursdayPrompt(
88
87
  // Order matters: earlier calls go last so the current call follows them in time order
89
88
  const text = [
90
89
  thursdayIdentity(),
91
- written ? "" : callEnding(),
90
+ written ? "" : ending(),
92
91
  memory(index, carried, open.notes),
93
92
  // A skill is named once, on the side that can read it: this computer's chapter
94
93
  // when the setting hands the call the tool, the bots' reach when it does not
@@ -110,6 +109,13 @@ export async function loadThursdayPrompt(
110
109
  return text;
111
110
  }
112
111
 
112
+ /**
113
+ * How a call ends, right after the identity. Only the backend can end the line, so its rule is
114
+ * to do it at once, with the tool named; the voice's own rule (live.prompt) is to hand it over.
115
+ */
116
+ const ending = () =>
117
+ `IMPORTANT — always follow this: when the user wants the call to end, however they say it, forget every other task, answer yes in one word of their language, then immediately, without thinking, use the ${TOOL_NAMES.end_call} tool.`;
118
+
113
119
  /**
114
120
  * What goes back is said aloud, so it is what a tool or a note confirmed and nothing more — or
115
121
  * the one question the voice puts to the user before work is handed over (backgroundWork).
@@ -30,6 +30,7 @@ import {
30
30
  type JobBot,
31
31
  type TokenUsage,
32
32
  } from "@/features/bot/bot.schema";
33
+ import { renewSignIns } from "@/features/signins/signins.query";
33
34
  import {
34
35
  botBrowserSession,
35
36
  filesOnDisk,
@@ -154,6 +155,9 @@ export async function runBot(
154
155
  : null,
155
156
  openBotFolders(name),
156
157
  ]);
158
+ const session =
159
+ options.session ??
160
+ (options.threadId ? botBrowserSession(options.threadId, name) : null);
157
161
  const [prompt, tools] = await Promise.all([
158
162
  loadBotPrompt(
159
163
  name,
@@ -170,9 +174,7 @@ export async function runBot(
170
174
  target: "bot",
171
175
  bot: name,
172
176
  thread: options.threadId ?? null,
173
- session:
174
- options.session ??
175
- (options.threadId ? botBrowserSession(options.threadId, name) : null),
177
+ session,
176
178
  model,
177
179
  }),
178
180
  ]);
@@ -474,6 +476,10 @@ export async function runBot(
474
476
  quiet.end();
475
477
  acknowledgeStep();
476
478
  await Promise.allSettled([...inFlight]);
479
+ if (session)
480
+ void renewSignIns(session).catch((cause) =>
481
+ logger.warn(`${name}: kept sign-ins were not renewed`, cause),
482
+ );
477
483
  }
478
484
 
479
485
  try {