thursday-agent 0.17.0 → 0.17.2

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 (361) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-path-routes-manifest.json +2 -0
  3. package/.next/build-manifest.json +3 -3
  4. package/.next/prerender-manifest.json +3 -3
  5. package/.next/routes-manifest.json +12 -0
  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.html +1 -1
  14. package/.next/server/app/_not-found.rsc +1 -1
  15. package/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  16. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  17. package/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  18. package/.next/server/app/api/artifact/route.js +9 -8
  19. package/.next/server/app/api/artifact/route.js.nft.json +1 -1
  20. package/.next/server/app/api/bot/memory/files/route.js.nft.json +1 -1
  21. package/.next/server/app/api/bot/memory/route.js +8 -7
  22. package/.next/server/app/api/bot/memory/route.js.nft.json +1 -1
  23. package/.next/server/app/api/bot/route.js +8 -7
  24. package/.next/server/app/api/bot/route.js.nft.json +1 -1
  25. package/.next/server/app/api/bot/thread/[id]/route.js +4 -4
  26. package/.next/server/app/api/bot/thread/[id]/route.js.nft.json +1 -1
  27. package/.next/server/app/api/bot/thread/route.js +3 -3
  28. package/.next/server/app/api/bot/thread/route.js.nft.json +1 -1
  29. package/.next/server/app/api/config/route.js.nft.json +1 -1
  30. package/.next/server/app/api/events/route.js.nft.json +1 -1
  31. package/.next/server/app/api/favicon/[host]/route.js +4 -3
  32. package/.next/server/app/api/favicon/[host]/route.js.nft.json +1 -1
  33. package/.next/server/app/api/file/[...path]/route.js.nft.json +1 -1
  34. package/.next/server/app/api/llm-model/automatic/route/app-paths-manifest.json +3 -0
  35. package/.next/server/app/api/llm-model/automatic/route/build-manifest.json +12 -0
  36. package/.next/server/app/api/llm-model/automatic/route/server-reference-manifest.json +4 -0
  37. package/.next/server/app/api/llm-model/automatic/route.js +17 -0
  38. package/.next/server/app/api/llm-model/automatic/route.js.map +5 -0
  39. package/.next/server/app/api/llm-model/automatic/route.js.nft.json +1 -0
  40. package/.next/server/app/api/llm-model/automatic/route_client-reference-manifest.js +3 -0
  41. package/.next/server/app/api/llm-model/catalog/route.js.nft.json +1 -1
  42. package/.next/server/app/api/llm-model/credits/route.js.nft.json +1 -1
  43. package/.next/server/app/api/llm-model/route.js.nft.json +1 -1
  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.nft.json +1 -1
  46. package/.next/server/app/api/mcp/oauth/callback/route.js.nft.json +1 -1
  47. package/.next/server/app/api/mcp/route.js.nft.json +1 -1
  48. package/.next/server/app/api/mcp/tools/route.js.nft.json +1 -1
  49. package/.next/server/app/api/memory/edit/route.js +14 -13
  50. package/.next/server/app/api/memory/edit/route.js.nft.json +1 -1
  51. package/.next/server/app/api/memory/route.js.nft.json +1 -1
  52. package/.next/server/app/api/reach/route.js +17 -16
  53. package/.next/server/app/api/reach/route.js.nft.json +1 -1
  54. package/.next/server/app/api/routine/route.js +10 -10
  55. package/.next/server/app/api/routine/route.js.nft.json +1 -1
  56. package/.next/server/app/api/signins/route.js.nft.json +1 -1
  57. package/.next/server/app/api/skills/[source]/[name]/route.js +9 -8
  58. package/.next/server/app/api/skills/[source]/[name]/route.js.nft.json +1 -1
  59. package/.next/server/app/api/skills/route.js +9 -8
  60. package/.next/server/app/api/skills/route.js.nft.json +1 -1
  61. package/.next/server/app/api/thursday/call/end/route/app-paths-manifest.json +3 -0
  62. package/.next/server/app/api/thursday/call/end/route/build-manifest.json +12 -0
  63. package/.next/server/app/api/thursday/call/end/route/server-reference-manifest.json +4 -0
  64. package/.next/server/app/api/thursday/call/end/route.js +17 -0
  65. package/.next/server/app/api/thursday/call/end/route.js.map +5 -0
  66. package/.next/server/app/api/thursday/call/end/route.js.nft.json +1 -0
  67. package/.next/server/app/api/thursday/call/end/route_client-reference-manifest.js +3 -0
  68. package/.next/server/app/api/thursday/call/route.js +6 -6
  69. package/.next/server/app/api/thursday/call/route.js.nft.json +1 -1
  70. package/.next/server/app/api/thursday/settings/route.js +5 -5
  71. package/.next/server/app/api/thursday/settings/route.js.nft.json +1 -1
  72. package/.next/server/app/api/thursday/text/route.js +16 -15
  73. package/.next/server/app/api/thursday/text/route.js.nft.json +1 -1
  74. package/.next/server/app/api/thursday/tool-call/route.js +13 -12
  75. package/.next/server/app/api/thursday/tool-call/route.js.nft.json +1 -1
  76. package/.next/server/app/api/workspace/files/route.js +5 -5
  77. package/.next/server/app/api/workspace/files/route.js.nft.json +1 -1
  78. package/.next/server/app/api/workspace/route.js +5 -5
  79. package/.next/server/app/api/workspace/route.js.nft.json +1 -1
  80. package/.next/server/app/artifact/[...path]/page/server-reference-manifest.json +3 -3
  81. package/.next/server/app/artifact/[...path]/page.js +2 -2
  82. package/.next/server/app/artifact/[...path]/page.js.nft.json +1 -1
  83. package/.next/server/app/artifact/[...path]/page_client-reference-manifest.js +1 -1
  84. package/.next/server/app/favicon.ico/route.js.nft.json +1 -1
  85. package/.next/server/app/manifest.webmanifest/route.js.nft.json +1 -1
  86. package/.next/server/app/page/server-reference-manifest.json +60 -60
  87. package/.next/server/app/page.js +8 -8
  88. package/.next/server/app/page.js.nft.json +1 -1
  89. package/.next/server/app/page_client-reference-manifest.js +1 -1
  90. package/.next/server/app-paths-manifest.json +2 -0
  91. package/.next/server/chunks/{[externals]__178rv3v._.js → [externals]__12stas-._.js} +1 -1
  92. package/.next/server/chunks/[root-of-the-server]__00qyw01._.js +1 -1
  93. package/.next/server/chunks/{[root-of-the-server]__1ignh6-._.js → [root-of-the-server]__01k3vi3._.js} +1 -1
  94. package/.next/server/chunks/[root-of-the-server]__01ypm_z._.js +1 -1
  95. package/.next/server/chunks/[root-of-the-server]__021dkui._.js +1 -1
  96. package/.next/server/chunks/[root-of-the-server]__03vunn6._.js +1 -1
  97. package/.next/server/chunks/[root-of-the-server]__03xamry._.js +1 -1
  98. package/.next/server/chunks/[root-of-the-server]__05dp5tr._.js +1 -1
  99. package/.next/server/chunks/{[root-of-the-server]__208vmyf._.js → [root-of-the-server]__061o2_x._.js} +1 -1
  100. package/.next/server/chunks/[root-of-the-server]__09gdscj._.js +3 -3
  101. package/.next/server/chunks/[root-of-the-server]__0bqveex._.js +5 -0
  102. package/.next/server/chunks/[root-of-the-server]__0eivkvk._.js +5 -0
  103. package/.next/server/chunks/[root-of-the-server]__0f7m79q._.js +3 -0
  104. package/.next/server/chunks/[root-of-the-server]__0g38-aj._.js +2 -2
  105. package/.next/server/chunks/[root-of-the-server]__0h656y-._.js +2 -2
  106. package/.next/server/chunks/[root-of-the-server]__0hkxwim._.js +3 -0
  107. package/.next/server/chunks/[root-of-the-server]__0hm3tiq._.js +5 -0
  108. package/.next/server/chunks/[root-of-the-server]__0hzdqnv._.js +5 -0
  109. package/.next/server/chunks/[root-of-the-server]__0liwkmx._.js +4 -4
  110. package/.next/server/chunks/[root-of-the-server]__0ljizgj._.js +2 -2
  111. package/.next/server/chunks/[root-of-the-server]__0mgyt8p._.js +5 -0
  112. package/.next/server/chunks/[root-of-the-server]__0mrk2it._.js +1 -1
  113. package/.next/server/chunks/[root-of-the-server]__0nmust6._.js +2 -2
  114. package/.next/server/chunks/[root-of-the-server]__0p80i1n._.js +3 -0
  115. package/.next/server/chunks/[root-of-the-server]__0qzho69._.js +3 -0
  116. package/.next/server/chunks/[root-of-the-server]__0sm5xvm._.js +1 -1
  117. package/.next/server/chunks/[root-of-the-server]__0svzjwa._.js +3 -3
  118. package/.next/server/chunks/{[root-of-the-server]__0b36yfw._.js → [root-of-the-server]__0ts7ai0._.js} +1 -1
  119. package/.next/server/chunks/[root-of-the-server]__1-18_pz._.js +3 -0
  120. package/.next/server/chunks/[root-of-the-server]__1-rmal0._.js +5 -0
  121. package/.next/server/chunks/[root-of-the-server]__13hng6h._.js +1 -1
  122. package/.next/server/chunks/[root-of-the-server]__1_04mcf._.js +2 -2
  123. package/.next/server/chunks/[root-of-the-server]__1_h4hf9._.js +3 -3
  124. package/.next/server/chunks/[root-of-the-server]__1ceammd._.js +1 -1
  125. package/.next/server/chunks/[root-of-the-server]__1ckt1yj._.js +3 -0
  126. package/.next/server/chunks/[root-of-the-server]__1cu5f3z._.js +5 -0
  127. package/.next/server/chunks/[root-of-the-server]__1hviq62._.js +5 -0
  128. package/.next/server/chunks/{[root-of-the-server]__12m24xl._.js → [root-of-the-server]__1k2qs1m._.js} +1 -1
  129. package/.next/server/chunks/[root-of-the-server]__1kmnkbk._.js +3 -0
  130. package/.next/server/chunks/[root-of-the-server]__1ndi14y._.js +1 -1
  131. package/.next/server/chunks/[root-of-the-server]__1p47fbb._.js +2 -2
  132. package/.next/server/chunks/[root-of-the-server]__1pugoq0._.js +3 -0
  133. package/.next/server/chunks/[root-of-the-server]__1t02-1p._.js +1 -1
  134. package/.next/server/chunks/[root-of-the-server]__1t0jj1j._.js +1 -1
  135. package/.next/server/chunks/[root-of-the-server]__1vlxv19._.js +2 -2
  136. package/.next/server/chunks/[root-of-the-server]__1ygplx1._.js +1 -1
  137. package/.next/server/chunks/[root-of-the-server]__1zn039k._.js +1 -1
  138. package/.next/server/chunks/_05gl-xy._.js +5 -5
  139. package/.next/server/chunks/_06hnfi8._.js +8 -0
  140. package/.next/server/chunks/_06u9yo-._.js +1 -1
  141. package/.next/server/chunks/_07nxi75._.js +25 -21
  142. package/.next/server/chunks/_08354bn._.js +25 -21
  143. package/.next/server/chunks/_08btiir._.js +3 -3
  144. package/.next/server/chunks/_0c49lmw._.js +5 -0
  145. package/.next/server/chunks/_0ey0s6v._.js +3 -0
  146. package/.next/server/chunks/_0hgvg55._.js +5 -0
  147. package/.next/server/chunks/_0j0-gq6._.js +2 -2
  148. package/.next/server/chunks/_0nn99o2._.js +1 -1
  149. package/.next/server/chunks/_0p6v1fr._.js +2 -2
  150. package/.next/server/chunks/_0s8ao8z._.js +3 -0
  151. package/.next/server/chunks/_0srlnvd._.js +1 -1
  152. package/.next/server/chunks/_0t_7gji._.js +1 -1
  153. package/.next/server/chunks/_0ucx1jv._.js +3 -0
  154. package/.next/server/chunks/_0uzj57i._.js +1 -1
  155. package/.next/server/chunks/_0xygcxs._.js +25 -21
  156. package/.next/server/chunks/_1-sk_q4._.js +1 -1
  157. package/.next/server/chunks/{_1xcnogc._.js → _108gsm8._.js} +4 -4
  158. package/.next/server/chunks/{_20oecmn._.js → _15negpy._.js} +4 -4
  159. package/.next/server/chunks/_19fh9t2._.js +3 -0
  160. package/.next/server/chunks/_19kea1l._.js +18 -18
  161. package/.next/server/chunks/_1dtm9bs._.js +1 -1
  162. package/.next/server/chunks/_1dxq827._.js +2 -2
  163. package/.next/server/chunks/_1e54wxa._.js +1 -1
  164. package/.next/server/chunks/_1frcwj1._.js +3 -0
  165. package/.next/server/chunks/_1gn2r2q._.js +5 -5
  166. package/.next/server/chunks/_1gxankq._.js +2 -2
  167. package/.next/server/chunks/_1i3uucm._.js +5 -0
  168. package/.next/server/chunks/_1m88lkh._.js +9 -9
  169. package/.next/server/chunks/_1mx9sfo._.js +1 -1
  170. package/.next/server/chunks/_1q6e56i._.js +5 -5
  171. package/.next/server/chunks/_1qxheoa._.js +1 -1
  172. package/.next/server/chunks/_1t5ijzv._.js +3 -0
  173. package/.next/server/chunks/_1wwl_7o._.js +1 -1
  174. package/.next/server/chunks/_1zfxb7j._.js +1 -1
  175. package/.next/server/chunks/_211dn2c._.js +1 -1
  176. package/.next/server/chunks/_next-internal_server_app_api_llm-model_automatic_route_actions_1-eyan7.js +3 -0
  177. package/.next/server/chunks/_next-internal_server_app_api_thursday_call_end_route_actions_0u5xjft.js +3 -0
  178. package/.next/server/chunks/config_ts_1g4sz5o._.js +1 -1
  179. package/.next/server/chunks/{features_0wm-ujw._.js → features_bot_08z387_._.js} +4 -4
  180. package/.next/server/chunks/{ssr/[root-of-the-server]__07660xu._.js → features_bot_0zy_q8y._.js} +8 -9
  181. package/.next/server/chunks/features_bot_1dfrdsb._.js +37 -0
  182. package/.next/server/chunks/features_workspace_workspace_ts_13h82gv._.js +3 -3
  183. package/.next/server/chunks/features_workspace_workspace_ts_1iyjroj._.js +3 -3
  184. package/.next/server/chunks/node_modules_103lpef._.js +3 -0
  185. package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_0_nz09c._.js → node_modules_consola_dist_chunks_prompt_mjs_0-t5tbs._.js} +1 -1
  186. package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_1341cnf._.js → node_modules_consola_dist_chunks_prompt_mjs_039fwo9._.js} +1 -1
  187. package/.next/server/chunks/{node_modules_consola_dist_chunks_prompt_mjs_1x3bsmx._.js → node_modules_consola_dist_chunks_prompt_mjs_0pce1b3._.js} +1 -1
  188. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_0tvy5lq._.js +3 -0
  189. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_0wxw35t._.js +3 -0
  190. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1dlthym._.js +3 -0
  191. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1smfi4-._.js +3 -0
  192. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_1x1omfi._.js +3 -0
  193. package/.next/server/chunks/node_modules_consola_dist_chunks_prompt_mjs_20is7e3._.js +3 -0
  194. package/.next/server/chunks/ssr/{[root-of-the-server]__149x25m._.js → [root-of-the-server]__0-af_o7._.js} +2 -2
  195. package/.next/server/chunks/ssr/[root-of-the-server]__09f39cp._.js +4 -0
  196. package/.next/server/chunks/ssr/[root-of-the-server]__0ouu4qp._.js +3 -0
  197. package/.next/server/chunks/ssr/[root-of-the-server]__0q9g9ea._.js +5 -0
  198. package/.next/server/chunks/ssr/[root-of-the-server]__17h1ggo._.js +11 -9
  199. package/.next/server/chunks/ssr/[root-of-the-server]__1jyeu61._.js +1 -1
  200. package/.next/server/chunks/ssr/{_0aeknva._.js → _01al00i._.js} +2 -2
  201. package/.next/server/chunks/ssr/_088vzgn._.js +1 -1
  202. package/.next/server/chunks/ssr/_0afrpci._.js +1 -1
  203. package/.next/server/chunks/ssr/_0bgse1c._.js +162 -0
  204. package/.next/server/chunks/ssr/_0cd6g3l._.js +15 -15
  205. package/.next/server/chunks/ssr/_0cv9tmv._.js +1 -1
  206. package/.next/server/chunks/ssr/{_0_vnw9v._.js → _0e2fnvg._.js} +2 -2
  207. package/.next/server/chunks/ssr/_0fo4552._.js +25 -21
  208. package/.next/server/chunks/ssr/_0jstvlg._.js +39 -0
  209. package/.next/server/chunks/ssr/{_0r0g9ki._.js → _0l7rjg5._.js} +2 -2
  210. package/.next/server/chunks/ssr/_0qsmpcu._.js +1 -1
  211. package/.next/server/chunks/ssr/_0v9r8g2._.js +1 -1
  212. package/.next/server/chunks/ssr/{_18-e7zi._.js → _0vo_oym._.js} +4 -4
  213. package/.next/server/chunks/ssr/_0x8ophf._.js +1 -1
  214. package/.next/server/chunks/ssr/{_0ztbn5q._.js → _0xfafez._.js} +2 -2
  215. package/.next/server/chunks/ssr/_0z38nha._.js +1 -1
  216. package/.next/server/chunks/ssr/_10-_awu._.js +1 -1
  217. package/.next/server/chunks/ssr/{_1z6pirx._.js → _10_ph1t._.js} +2 -2
  218. package/.next/server/chunks/ssr/_116lfdc._.js +3 -0
  219. package/.next/server/chunks/ssr/_14dfh7a._.js +1 -1
  220. package/.next/server/chunks/ssr/_14oirtb._.js +3 -0
  221. package/.next/server/chunks/ssr/{_1umbr78._.js → _163dr78._.js} +2 -2
  222. package/.next/server/chunks/ssr/{_1c5iqz1._.js → _17a4qyk._.js} +3 -3
  223. package/.next/server/chunks/ssr/{_1sttj8x._.js → _1_5xof_._.js} +2 -2
  224. package/.next/server/chunks/ssr/{_1hbjh6n._.js → _1aqjk-1._.js} +2 -2
  225. package/.next/server/chunks/ssr/{_0n2scfq._.js → _1dfv66y._.js} +2 -2
  226. package/.next/server/chunks/ssr/_1neoj22._.js +1 -1
  227. package/.next/server/chunks/ssr/_1ou5sj0._.js +1 -1
  228. package/.next/server/chunks/ssr/{_15m5ctz._.js → _1tmw842._.js} +2 -2
  229. package/.next/server/chunks/ssr/_1uij_rj._.js +1 -1
  230. package/.next/server/chunks/ssr/_1w9w1ok._.js +1 -1
  231. package/.next/server/chunks/ssr/features_0796o8r._.js +1 -1
  232. package/.next/server/chunks/ssr/features_bot_0ouemw8._.js +3 -0
  233. package/.next/server/chunks/ssr/{features_133mpna._.js → features_bot_0tb4ui-._.js} +2 -2
  234. package/.next/server/chunks/ssr/{features_config_0n0zu89._.js → features_config_09n-q9q._.js} +3 -3
  235. package/.next/server/chunks/ssr/features_connectors_components_mcp-setting_tsx_0jmbgvp._.js +1 -1
  236. package/.next/server/chunks/ssr/features_memory_components_memory-setting_tsx_0oa43sw._.js +1 -1
  237. package/.next/server/chunks/ssr/features_routine_components_routine-setting_tsx_055fknz._.js +1 -1
  238. package/.next/server/chunks/ssr/features_workspace_workspace_ts_1wc7_u_._.js +4 -4
  239. package/.next/server/chunks/ssr/{node_modules_1hefp6h._.js → node_modules_021lid9._.js} +1 -1
  240. package/.next/server/chunks/ssr/{node_modules_0kwie-o._.js → node_modules_04x5wyv._.js} +1 -1
  241. package/.next/server/chunks/ssr/{node_modules_180l3i0._.js → node_modules_096up6a._.js} +1 -1
  242. package/.next/server/chunks/ssr/{node_modules_00h1t1j._.js → node_modules_0__0tvm._.js} +1 -1
  243. package/.next/server/chunks/ssr/{node_modules_03uejh6._.js → node_modules_0cjnmzp._.js} +1 -1
  244. package/.next/server/chunks/ssr/{node_modules_1ubln7w._.js → node_modules_0d6j33x._.js} +1 -1
  245. package/.next/server/chunks/ssr/{node_modules_1_n9o9s._.js → node_modules_0gd9hbz._.js} +1 -1
  246. package/.next/server/chunks/ssr/{node_modules_0zf3wuu._.js → node_modules_0k8-y89._.js} +1 -1
  247. package/.next/server/chunks/ssr/{node_modules_0u_8z64._.js → node_modules_0m73b88._.js} +1 -1
  248. package/.next/server/chunks/ssr/{node_modules_09ikzel._.js → node_modules_0msrhxf._.js} +1 -1
  249. package/.next/server/chunks/ssr/{node_modules_0f5bmkb._.js → node_modules_0nmkv-v._.js} +1 -1
  250. package/.next/server/chunks/ssr/{node_modules_07mo9rn._.js → node_modules_0nw5jz7._.js} +1 -1
  251. package/.next/server/chunks/ssr/{node_modules_09e8kz_._.js → node_modules_0q-klni._.js} +1 -1
  252. package/.next/server/chunks/ssr/{node_modules_02ficyi._.js → node_modules_10_fv2a._.js} +1 -1
  253. package/.next/server/chunks/ssr/{node_modules_142z3o5._.js → node_modules_113l3e5._.js} +1 -1
  254. package/.next/server/chunks/ssr/{node_modules_1wyhtw9._.js → node_modules_13bqv6i._.js} +1 -1
  255. package/.next/server/chunks/ssr/{node_modules_0_d_7gq._.js → node_modules_13g-d25._.js} +1 -1
  256. package/.next/server/chunks/ssr/{node_modules_0r-9e4n._.js → node_modules_156kv_t._.js} +1 -1
  257. package/.next/server/chunks/ssr/{node_modules_06grs09._.js → node_modules_1_8-jcj._.js} +1 -1
  258. package/.next/server/chunks/ssr/{node_modules_1fw32pg._.js → node_modules_1gq3ght._.js} +1 -1
  259. package/.next/server/chunks/ssr/{node_modules_0_p8w7p._.js → node_modules_1k5i-_9._.js} +1 -1
  260. package/.next/server/chunks/ssr/{node_modules_03q71_j._.js → node_modules_1lmyts8._.js} +1 -1
  261. package/.next/server/chunks/ssr/{node_modules_1irot3r._.js → node_modules_1p_6sq7._.js} +1 -1
  262. package/.next/server/chunks/ssr/{node_modules_1om2itc._.js → node_modules_1qstb1x._.js} +1 -1
  263. package/.next/server/chunks/ssr/{node_modules_197vh1s._.js → node_modules_1ri_eip._.js} +1 -1
  264. package/.next/server/chunks/ssr/{node_modules_1-7fc7h._.js → node_modules_1xb-ndg._.js} +1 -1
  265. package/.next/server/chunks/ssr/{node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_0aczkbn._.js → node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_0amkw0b._.js} +1 -1
  266. package/.next/server/chunks/ssr/{node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_0ah684s._.js → node_modules_@mermaid-js_parser_dist_chunks_mermaid-parser_core_0zq3l45._.js} +1 -1
  267. package/.next/server/middleware-build-manifest.js +3 -3
  268. package/.next/server/middleware.js +1 -1
  269. package/.next/server/pages/404.html +1 -1
  270. package/.next/server/pages/500.html +1 -1
  271. package/.next/server/server-reference-manifest.js +1 -1
  272. package/.next/server/server-reference-manifest.json +61 -61
  273. package/.next/static/chunks/{38edd4rpcbvzp.js → 01l7kw74vfp32.js} +1 -1
  274. package/.next/static/chunks/0a5_-jqhaktjj.js +1 -0
  275. package/.next/static/chunks/{0_b_bi2pobasx.js → 0obogzscwwekj.js} +2 -2
  276. package/.next/static/chunks/{1-63yde5eaz7i.js → 0p2f6uv4xytfm.js} +1 -1
  277. package/.next/static/chunks/{2v6e_9p95o2e3.js → 0uxq_vs6uxi-b.js} +1 -1
  278. package/.next/static/chunks/{024plctckvq-1.js → 166smhw8v-s3j.js} +1 -1
  279. package/.next/static/chunks/{1wbqaidq7vc3_.js → 1bnhw-5fj7aiz.js} +1 -1
  280. package/.next/static/chunks/1cglo3a2mbeou.js +1 -0
  281. package/.next/static/chunks/{0sv142q1yrva2.js → 1in6nxpu33iab.js} +1 -1
  282. package/.next/static/chunks/1u7kg91f9qy3g.js +1 -0
  283. package/.next/static/chunks/{0sowxe4nnl5qu.js → 1xv4g10m-cl1s.js} +1 -1
  284. package/.next/static/chunks/{0dfvwgnyrp8qt.js → 2ajs12-fcdwzm.js} +1 -1
  285. package/.next/static/chunks/2i7qtmxc1kuqg.js +1 -0
  286. package/.next/static/chunks/{3-qp777vtfglj.js → 2kz1f6r59nky0.js} +1 -1
  287. package/.next/static/chunks/2qgkbdshzpq1c.js +1 -0
  288. package/.next/static/chunks/{1bgvxd3xny53w.js → 2zbl41hed17g3.js} +2 -2
  289. package/.next/static/chunks/35jj-5u4te56r.js +1 -0
  290. package/.next/static/chunks/37ixzapa06xlo.js +1 -0
  291. package/.next/static/chunks/3b96xy59nl_gd.js +1 -0
  292. package/.next/static/chunks/{0f47nnshdlucs.js → 3gsxnqqqphh-1.js} +1 -1
  293. package/.next/static/chunks/{44vre0f7xqsh-.js → 3jtcieuk1l6tw.js} +1 -1
  294. package/.next/static/chunks/{05scfrgo_a_5_.js → 3k1d8y03t5nax.js} +1 -1
  295. package/.next/static/chunks/3sla-dm1puqd1.js +35 -0
  296. package/.next/static/chunks/3t2c76awm9k_p.js +1 -0
  297. package/.next/static/chunks/3vrmcm31ih7gb.js +1 -0
  298. package/.next/static/chunks/3yiqr95d7ybeq.js +15 -0
  299. package/bin/autostart.mjs +4 -1
  300. package/bin/database.mjs +26 -4
  301. package/bin/lock.mjs +59 -0
  302. package/bin/node-check.mjs +21 -0
  303. package/bin/thursday.mjs +8 -1
  304. package/guide/bots.md +4 -2
  305. package/guide/calls.md +11 -9
  306. package/guide/memory.md +3 -2
  307. package/guide/phone.md +7 -4
  308. package/guide/setup.md +26 -9
  309. package/guide/trouble.md +11 -4
  310. package/package.json +1 -1
  311. package/public/voices/intro/asleepBare-15199d56.ogg +0 -0
  312. package/public/voices/intro/style-88adf274.ogg +0 -0
  313. package/seed-skills/concierge/travel/scripts/itinerary.mjs +6 -4
  314. package/skills/artifact/references/book.md +2 -1
  315. package/skills/artifact/references/sheet.md +12 -7
  316. package/skills/artifact/runtime/sheet/format.mjs +16 -9
  317. package/skills/artifact/scripts/book.mjs +19 -6
  318. package/skills/artifact/scripts/spreadsheet.mjs +194 -97
  319. package/skills/browser/SKILL.md +9 -6
  320. package/.next/server/chunks/[root-of-the-server]__03b09q0._.js +0 -5
  321. package/.next/server/chunks/[root-of-the-server]__05n-hql._.js +0 -5
  322. package/.next/server/chunks/[root-of-the-server]__0j_nz36._.js +0 -3
  323. package/.next/server/chunks/[root-of-the-server]__0jzwdg-._.js +0 -3
  324. package/.next/server/chunks/[root-of-the-server]__0tsded0._.js +0 -5
  325. package/.next/server/chunks/[root-of-the-server]__12tahb4._.js +0 -3
  326. package/.next/server/chunks/[root-of-the-server]__1de1o6m._.js +0 -3
  327. package/.next/server/chunks/[root-of-the-server]__1yl5l25._.js +0 -3
  328. package/.next/server/chunks/_02lipqs._.js +0 -5
  329. package/.next/server/chunks/_05sa7xl._.js +0 -3
  330. package/.next/server/chunks/_074f2ts._.js +0 -3
  331. package/.next/server/chunks/_0caua_s._.js +0 -3
  332. package/.next/server/chunks/_0p-h6xe._.js +0 -5
  333. package/.next/server/chunks/_0up2a9o._.js +0 -3
  334. package/.next/server/chunks/_17i1lt2._.js +0 -3
  335. package/.next/server/chunks/_1hy9x9_._.js +0 -3
  336. package/.next/server/chunks/_1hyvcgk._.js +0 -5
  337. package/.next/server/chunks/_1wl2g8_._.js +0 -6
  338. package/.next/server/chunks/_1y3mnz4._.js +0 -3
  339. package/.next/server/chunks/ssr/[root-of-the-server]__10eb-1x._.js +0 -3
  340. package/.next/server/chunks/ssr/[root-of-the-server]__19s8qyj._.js +0 -3
  341. package/.next/server/chunks/ssr/_0o_o9ji._.js +0 -3
  342. package/.next/server/chunks/ssr/_0qne8xs._.js +0 -3
  343. package/.next/server/chunks/ssr/_0rvbegp._.js +0 -7
  344. package/.next/server/chunks/ssr/_1vtgiou._.js +0 -162
  345. package/.next/server/chunks/ssr/features_bot_1kr0_m-._.js +0 -3
  346. package/.next/static/chunks/04toe_3nqfjqt.js +0 -1
  347. package/.next/static/chunks/0mtfu8adz57qz.js +0 -1
  348. package/.next/static/chunks/0tp868040z9nn.js +0 -35
  349. package/.next/static/chunks/14qitm0kwsb6g.js +0 -15
  350. package/.next/static/chunks/1cyrrz4q871aj.js +0 -1
  351. package/.next/static/chunks/1st3b0c9vhxg3.js +0 -1
  352. package/.next/static/chunks/28sxb_k460e9h.js +0 -1
  353. package/.next/static/chunks/33ekkscpcq-z1.js +0 -1
  354. package/.next/static/chunks/388l-zszwa_jf.js +0 -1
  355. package/.next/static/chunks/3bwrvpjk95_x4.js +0 -1
  356. package/.next/static/chunks/3itdg6t243u6f.js +0 -1
  357. package/.next/static/chunks/3kj0pri2oc1g1.js +0 -1
  358. package/public/voices/intro/style-cb6fa4f7.ogg +0 -0
  359. /package/.next/static/{VtbCMn-0G969p8QJsWdGv → 8I2hKtciyA9LXvd8txuOz}/_buildManifest.js +0 -0
  360. /package/.next/static/{VtbCMn-0G969p8QJsWdGv → 8I2hKtciyA9LXvd8txuOz}/_clientMiddlewareManifest.js +0 -0
  361. /package/.next/static/{VtbCMn-0G969p8QJsWdGv → 8I2hKtciyA9LXvd8txuOz}/_ssgManifest.js +0 -0
package/bin/lock.mjs ADDED
@@ -0,0 +1,59 @@
1
+ // One server to a data folder. A second one started on the same folder took the next port
2
+ // and, at its boot, parked the first one's running jobs, closed its open calls and joined
3
+ // the phone a second time, so every message was answered twice. The second is refused, and
4
+ // told where the first one is.
5
+
6
+ import { mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
7
+ import { join } from "node:path";
8
+
9
+ /** Beside the database, and named so a checkout never commits it (`*.local.*`). */
10
+ const LOCK_FILE = "server.local.lock";
11
+
12
+ /** The server already serving this data folder: where it is. Null when none is alive. */
13
+ export function runningOn(home) {
14
+ let held;
15
+ try {
16
+ held = JSON.parse(readFileSync(join(home, LOCK_FILE), "utf8"));
17
+ } catch {
18
+ return null;
19
+ }
20
+ if (!Number.isInteger(held?.pid) || held.pid === process.pid) return null;
21
+ try {
22
+ // Signal 0 asks whether the process exists and sends nothing
23
+ process.kill(held.pid, 0);
24
+ } catch (error) {
25
+ // Someone else's process by that id is still a live one
26
+ if (error?.code !== "EPERM") return null;
27
+ }
28
+ return { pid: held.pid, url: String(held.url ?? "") };
29
+ }
30
+
31
+ /** Exits with where the running one is, when this folder already has a server. */
32
+ export function refuseSecond(home) {
33
+ const running = runningOn(home);
34
+ if (!running) return;
35
+ console.error(
36
+ `\n Thursday is already running on this data folder${running.url ? `: ${running.url}` : ""}\n Open that one, or stop it first (Ctrl+C where it runs; one that starts with the\n computer stops with: thursday autostart --off).\n`,
37
+ );
38
+ process.exit(1);
39
+ }
40
+
41
+ /** Marks this folder as served from here until this process ends. */
42
+ export function holdFolder(home, url) {
43
+ const file = join(home, LOCK_FILE);
44
+ try {
45
+ mkdirSync(home, { recursive: true });
46
+ writeFileSync(file, `${JSON.stringify({ pid: process.pid, url })}\n`);
47
+ } catch {
48
+ // A folder that cannot be written is not a reason not to serve
49
+ return;
50
+ }
51
+ process.on("exit", () => {
52
+ try {
53
+ if (JSON.parse(readFileSync(file, "utf8")).pid === process.pid)
54
+ rmSync(file, { force: true });
55
+ } catch {
56
+ // Gone already
57
+ }
58
+ });
59
+ }
@@ -0,0 +1,21 @@
1
+ // The first import of thursday.mjs, so it runs before the rest of bin/ is evaluated: that
2
+ // reads what an older Node does not have (`import.meta.dirname`) while loading, and on
3
+ // Ubuntu's and Debian's own Node 18 it died with a stack trace instead of saying why.
4
+ // Plain JavaScript an old Node runs; the version it asks for is package.json's `engines`.
5
+
6
+ import { readFileSync } from "node:fs";
7
+
8
+ const { engines } = JSON.parse(
9
+ readFileSync(new URL("../package.json", import.meta.url), "utf8"),
10
+ );
11
+ const wanted = /(\d+)\.(\d+)/.exec(engines?.node ?? "");
12
+ if (wanted) {
13
+ const [major, minor] = process.versions.node.split(".").map(Number);
14
+ const [needMajor, needMinor] = [Number(wanted[1]), Number(wanted[2])];
15
+ if (major < needMajor || (major === needMajor && minor < needMinor)) {
16
+ console.error(
17
+ `\n Thursday needs Node ${needMajor}.${needMinor} or newer, and this is ${process.versions.node}.\n Install a newer one from https://nodejs.org, or with your version manager, and run it again.\n`,
18
+ );
19
+ process.exit(1);
20
+ }
21
+ }
package/bin/thursday.mjs CHANGED
@@ -3,6 +3,8 @@
3
3
  // the build and at the user's home (config.ts APP_DIR / DATA_DIR), then boots
4
4
  // the standalone server. Plain JavaScript: this runs before anything is built.
5
5
 
6
+ // First, so an older Node is told what it needs before anything else is evaluated
7
+ import "./node-check.mjs";
6
8
  import { spawn } from "node:child_process";
7
9
  import {
8
10
  existsSync,
@@ -15,6 +17,7 @@ import { readFile } from "node:fs/promises";
15
17
  import { homedir } from "node:os";
16
18
  import { join, resolve } from "node:path";
17
19
  import { askToSetDatabaseAside, MIGRATION_FAILED_EXIT } from "./database.mjs";
20
+ import { holdFolder, refuseSecond } from "./lock.mjs";
18
21
  import { freePort } from "./port.mjs";
19
22
  import { ROOT, toolPath } from "./tools.mjs";
20
23
 
@@ -87,8 +90,11 @@ if (argv[0] === "autostart") {
87
90
  process.exit(0);
88
91
  }
89
92
 
93
+ // Before a port is picked: a second server on this folder would take the next one
94
+ refuseSecond(home);
90
95
  const port = String(await freePort(asked, home));
91
96
  const url = `http://localhost:${port}`;
97
+ holdFolder(home, url);
92
98
  /** Where config.ts DB_PATH puts the database under the home. */
93
99
  const database = join(home, "local.db");
94
100
 
@@ -179,7 +185,8 @@ start();
179
185
  * request to try again.
180
186
  */
181
187
  let stopping = false;
182
- for (const signal of ["SIGINT", "SIGTERM"]) {
188
+ // A terminal closed under it is a stop too (SIGHUP), and the server parks its work for it
189
+ for (const signal of ["SIGINT", "SIGTERM", "SIGHUP"]) {
183
190
  process.on(signal, () => {
184
191
  if (stopping) {
185
192
  child.kill("SIGKILL");
package/guide/bots.md CHANGED
@@ -7,7 +7,8 @@ how a job finds its bot. The roster is **Settings › Bots**. **New bot** makes
7
7
  a description and a model, and a name cannot be changed later — and a bot's page holds what it
8
8
  **Runs on** and its **Effort**, when it **Compacts at**, its **Tools**, its own **Prompt**, its
9
9
  recent threads and its own memory. A bot can be switched off without being deleted. Deleting one keeps what it finished: **Settings ›
10
- Files** still shows it under that bot's name. The first run
10
+ Files** still shows it under that bot's name. What it kept for itself — its memory and the skills it
11
+ installed — is deleted with it, so a bot made later under the same name starts fresh. The first run
11
12
  offers the ready-made ones, all switched on; **Ready-made bots**, beside New bot, adds one later.
12
13
  There can be at most 14 bots, switched-off ones included: at 14 the roster says "14 is the most" in
13
14
  place of New bot, and one has to be deleted before another is made. When fewer places are left than
@@ -326,7 +327,8 @@ time, and at most twelve routines exist:
326
327
  run, and picking a new day and time sets it again. A time already gone is refused.
327
328
  - **On set days**: a time of day on the days picked. Every day, Weekdays and Weekends fill the days
328
329
  in one press.
329
- - **Every few hours**: 1, 2, 3, 6, 12 or 24 in one press, or any number from 1 to 168.
330
+ - **Every few hours**: 1, 2, 3, 6, 12 or 24 in one press. Another number up to 168 is set by asking
331
+ Thursday for it, and then shows beside them.
330
332
 
331
333
  The line under the field says it back in words, with when it first starts. A routine's name and job
332
334
  are saved with **Save**.
package/guide/calls.md CHANGED
@@ -6,8 +6,10 @@ Three ways in, and any of them also answers a call she placed:
6
6
 
7
7
  - Tap her face.
8
8
  - Say the wake phrase, "hey thursday" unless they changed it. It is off to begin with, because it
9
- keeps the microphone open for as long as the tab is. It is heard loosely, in English, so it is
10
- written in English words; a phrase in another language is not saved.
9
+ keeps the microphone open for as long as the tab is, and the listening is the browser's own
10
+ speech recognition: Chrome's sends what the microphone hears to Google, which is not this app's
11
+ to change. It is heard loosely, in English, so it is written in English words; a phrase in
12
+ another language is not saved.
11
13
  - Press the shortcut, Alt + Shift + T (⌥⇧T on a Mac) unless they changed it. It is off to begin
12
14
  with too, and works only while the app's tab has focus and nothing is being typed.
13
15
 
@@ -42,8 +44,8 @@ while it is open, silence included. Work already handed to a bot carries on.
42
44
  ## Writing to her instead
43
45
 
44
46
  The **+** at the left end of the pill in the bottom right corner — or the `/` key — opens a line at
45
- the foot of the screen. It opens on whoever it was last addressed to: her, the first time. What is
46
- sent to her there starts a call in writing: her answers come up beside her face as on a spoken
47
+ the foot of the screen. It opens on her, always. What is sent to her there starts a call in
48
+ writing: her answers come up beside her face as on a spoken
47
49
  call, what she is doing shows with them, and the line stays as the way to write back. She has the
48
50
  same memory, tools and bots as on a spoken call; there is no voice and no microphone, and nothing is
49
51
  billed by the minute.
@@ -53,9 +55,9 @@ billed by the minute.
53
55
  - **Files** go with the words: the paperclip, a paste, or a drop anywhere on the window — at most 8
54
56
  at a time, 25 MB each. A picture handed over in writing is one she can look at herself — a
55
57
  receipt, a screenshot, a chart — so "what does this say?" is answered on the spot.
56
- - **Who it goes to**: the chip at the left of the line, or `@` and a name at the start. During a
57
- written call a bot picked there gets that one message; after it the line is hers again, and
58
- **Esc** with a bot picked goes back to her.
58
+ - **Who it goes to**: the chip at the left of the line, or `@` and a name at the start. A bot
59
+ picked there gets that one message; after it the line is hers again, and **Esc** with a bot
60
+ picked goes back to her.
59
61
  - **What it runs on**: the GPT Subscription when one is signed in, else the OpenAI key. The small
60
62
  **runs on** button under the line says which before anything is sent, and picks another model
61
63
  for writing to her — any provider with a key. The pick is remembered by this browser and is only
@@ -122,7 +124,7 @@ Everything here but her face is in **Settings › Thursday**, and changes apply
122
124
  circling.
123
125
  - **Voice**: the voice runs on GPT-Live 1, with 22 voices to pick from; clicking a name plays it.
124
126
  It is the one setting here a written call or a phone does not use.
125
- - **Style**: who she is to them — ten of them, and the only difference is how she talks. The row
127
+ - **Style**: who she is to them — Bright, Calm, Straight or Rough, and the only difference is how she talks. The row
126
128
  shows the one she is on; opening it lists the rest with a line each. It never changes what she
127
129
  can do. Last in the list, **Your own** opens a box for saying it in their own words on top of
128
130
  the one picked — how she talks, how much she says — which wins wherever the two differ. What to
@@ -176,4 +178,4 @@ sound on a page nobody has clicked yet, so right after a reload it rings on the
176
178
  after another, oldest at the top, each with the jobs it opened and where they stand; a single call
177
179
  can be deleted, or all of them with **Delete all**. A call is kept for three months and then goes
178
180
  by itself. **Reset history** deletes every call, every job and everything she remembers, for good;
179
- keys, bots and connectors stay.
181
+ keys, bots and connectors stay, and so does what each bot keeps for itself.
package/guide/memory.md CHANGED
@@ -32,5 +32,6 @@ of her earlier calls (`calls.md`). Asking her to forget something removes the li
32
32
 
33
33
  Memory holds up to 400 facts, and 50 in one note. When it grows past that she says so once on a
34
34
  call and goes through what looks out of date with the user, the heaviest notes first, deleting
35
- only what they name. **Reset history** in Settings › Thursday deletes all of memory along with
36
- every call and job.
35
+ only what they name. Forgetting a fact takes it out of everything she reads; the earlier wordings it
36
+ replaced stay in the database until its note is deleted. **Reset history** in Settings › Thursday
37
+ deletes all of her memory along with every call and job; what each bot keeps for itself stays.
package/guide/phone.md CHANGED
@@ -126,10 +126,13 @@ starts a new one, and she reads the last one back like any earlier call.
126
126
  in the chat.
127
127
  - **A page** — a report, a deck, a design — arrives as pictures of it, since no chat app opens
128
128
  one: a deck slide by slide, a design board by board, anything else a phone's screen at a time
129
- from the top, nine at most. The page itself comes with them, to open on a computer.
130
- Drawing them takes a few seconds and needs the browser bots use; without it the page comes alone.
131
- - **What she did** — noted something down, started work, looked something up — is one short line
132
- under her answer, in the words the call screen uses.
129
+ from the top, nine at most. The page itself stays on the computer, and the chat says so under
130
+ *Not sent — still on this computer*; sent along, it showed as code in a chat and its own pictures
131
+ never opened on a phone. Drawing them takes a few seconds and needs the browser bots use; without
132
+ it the page comes alone.
133
+ - **What she did** — noted something down, started work, looked something up — is said in one short
134
+ line, in the words the call screen uses, only when she ended a turn without writing anything;
135
+ under an answer she wrote, the line read as part of her reply.
133
136
  - **How her words look**: bold, lists, links and code arrive the way each chat app draws them. A
134
137
  table arrives as rows and a heading as a bold line, since a chat has neither, and a long answer
135
138
  comes as several messages, each cut where a paragraph or a code block ends.
package/guide/setup.md CHANGED
@@ -10,8 +10,10 @@ through six steps on the call screen itself: a voice key, the microphone, which
10
10
  they think with, her style, and the first call. She talks
11
11
  through it in a recorded voice, in English, and says so first; her real voice starts with the first
12
12
  call. The speaker button at the top right mutes the recording, and stays muted the next time, the opening's sounds with it. Every
13
- step can be passed and done later from the screens below. With a key the last button is **Call
14
- her**; without one it is **Look around**. It stops showing once a call has been placed, and adding
13
+ step can be passed and done later from the screens below. The bots picked there are set up when
14
+ it ends, key or no key; they run once there is a model to run on. With a key the last button is
15
+ **Call her**; without one it is **Look around**, and she says whether the bots can already work or
16
+ still need a key or a ChatGPT sign-in. It stops showing once a call has been placed, and adding
15
17
  `?intro` to the address brings it back.
16
18
 
17
19
  ## Around the screen
@@ -19,7 +21,8 @@ her**; without one it is **Look around**. It stops showing once a call has been
19
21
  The buttons at the top right of the call screen open **Thursday**, **Memory** and **Bots** directly,
20
22
  and **Settings** opens everything; each carries a dot when something there wants the user. The
21
23
  Settings list is Thursday, Memory, Bots, Threads, Routines, Files, Skills, Connectors, Sign-ins,
22
- Models, API keys and Phone. ⌘K (Ctrl+K) jumps to its filter, and ⌘ with a number opens that section.
24
+ Models, API keys and Phone. ⌘K (Ctrl+K) jumps to its filter, and ⌘ with a number opens one of the
25
+ first nine.
23
26
  Under Phone, as a group of their own named community, **Ask on Discord** opens the app's community,
24
27
  where people who use and build it answer questions, and **GitHub** opens its code, bug reports and
25
28
  releases. The theme — **System**, **Light** or **Dark** — is picked at the foot of the list.
@@ -35,21 +38,27 @@ The screen puts the two easy ways next: **GPT Subscription**, a sign-in with Cha
35
38
  ChatGPT plan, no key; the row shows how much of the plan is used and when it resets), and the
36
39
  **Vercel AI Gateway**, one key for every model and the one the app recommends (its row shows what is
37
40
  left). Under them every other provider is a mark to tap and paste a key into — Claude, Gemini, xAI
38
- and more behind **More**. The box a key goes in shows how that provider's keys begin where it is
41
+ and the rest; the first run shows four of them and keeps the others behind **More**. The box a key goes in shows how that provider's keys begin where it is
39
42
  known, with a link to the page that makes one; **Remove**, on a key already set, is the red word at
40
43
  the far left.
41
44
 
42
45
  A search key (Exa) is optional. With it, calls and bots both search through Exa, which is cheaper
43
46
  per search and comes with free credits every month. Without it, a call uses OpenAI's own search and
44
- a bot its model's own — which only OpenAI, Claude, Gemini and xAI have, and only on their own keys.
45
- A bot running through the GPT Subscription, the Gateway or any other provider has no search of its
46
- own, so it opens pages in its browser instead.
47
+ a bot its model's own — which the GPT Subscription has, and OpenAI, Claude, Gemini and xAI on their
48
+ own keys. A bot running through the Gateway or any other provider has no search of its own, so it
49
+ opens pages in its browser instead.
47
50
 
48
51
  ## Models
49
52
 
50
53
  **Settings › Models** has two groups. **Bots** holds the **Default model** — the one a bot uses when
51
54
  its own page says nothing; a small one is quick and costs little, and is the place to start — and
52
- its **Default effort**. Left unset it shows *auto* and runs on the first provider with a key. The
55
+ its **Default effort**. Left unset it shows *auto* and names the model bots run on now: the GPT
56
+ Subscription's when you are signed in, since the plan is already paid for, else OpenAI's, else xAI's,
57
+ else the first provider with a key — the **small** model on OpenAI, the one the call's backend starts
58
+ on too, and the **mid** one on the GPT Subscription, which is paid for either way (a Free plan opens
59
+ only the small one and runs that), and elsewhere. A default picked here whose key is
60
+ later removed is not swapped for another provider: bots stop and say so until it is back or another
61
+ is picked. The
53
62
  first run's model step sets this same one, and **App default** at the top of a bot's model list puts
54
63
  that bot back on it. **Studio** holds the **Image model**, **Video model**, **Speech model** and
55
64
  **Transcription model**. A kind with no model picked simply is not there — a bot that needs it says
@@ -157,6 +166,12 @@ settings, because a browser keeps settings per address. Starting it once with `-
157
166
  moves it to that address for good; if that port is taken, it says so and stops. `thursday --help`
158
167
  lists the rest: `--home` for another data folder, `--no-open` to start without opening a browser.
159
168
 
169
+ One data folder is served by one app at a time: started again while it runs — a second `npx`, or
170
+ one beside the one that starts at login — it says the address of the one running and stops, rather
171
+ than serving the same calls, jobs and phone twice. It needs Node 22.18 or newer and says so on an
172
+ older one. Closing the terminal it runs in stops it the way Ctrl+C does: jobs that were running
173
+ are paused, to be picked up again.
174
+
160
175
  ## Where the files are
161
176
 
162
177
  Everything is on this computer, in one folder: `.thursday` in their home folder when the app was
@@ -178,7 +193,9 @@ can be missing the last thing that was said; stopping the app folds that file ba
178
193
  another computer is the same folder put in the same place there. If the app ever cannot open the
179
194
  database, the terminal it was started in asks whether to set it aside and start over; yes moves it
180
195
  next to the new one with `.corrupt-` and a number in its name, and nothing is thrown away. Started by
181
- autostart it cannot ask, so it does not come up until it is started once from a terminal.
196
+ autostart it cannot ask, so it does not come up until it is started once from a terminal. Data a
197
+ newer version of the app has opened is not offered to be set aside: an older one — an autostart left
198
+ behind while `npx` runs the latest — says so and stops, and the newer one opens it as it was.
182
199
 
183
200
  ## What it costs
184
201
 
package/guide/trouble.md CHANGED
@@ -7,15 +7,21 @@ has already said which: a provider's own words are shown as they came, never hid
7
7
 
8
8
  - **"Call failed"** shows the provider's reason. A refused key or no credit left is fixed in
9
9
  **Settings › API keys**; a model the key cannot use is changed in **Settings › Thursday › Models**.
10
+ - **"One call at a time"**: another tab of the app has a spoken call on. Hang up there, or go on
11
+ there; two lines at once were billed twice and said every update twice. A tab closed mid-call
12
+ ends its call as it goes.
10
13
  - **She cannot be heard** on a call that opened by itself (she called back): the browser holds the
11
14
  sound until the page is touched. A tap anywhere lets it through.
12
15
  - **She does not hear them**: the browser asks for the microphone on the first call. If that was
13
16
  refused, it is allowed again from the site's settings in the address bar. The first run's
14
17
  microphone step says which it was: not allowed, no microphone found, one that would not start
15
18
  (another app may be using it), or the browser's own words for anything else.
16
- - **The call ended by itself**: the line under her face says why — *40s of quiet* (nothing was said
17
- for 40 seconds; the last 10 count down on screen), *Thursday hung up*, *Live closed the call*, or
18
- *the connection dropped*. Work already handed to a bot is not affected.
19
+ - **The call ended by itself**: the line under her face says why — *25s of quiet* (nothing was said
20
+ for 25 seconds; the last 10 count down on screen, and an update she is reading is let finish
21
+ first), *Thursday hung up*, *the call ran to Live's time limit*, *Live closed the call*, or *the
22
+ connection dropped*. Only a dropped connection or a close Live gives no reason for shows as a
23
+ failure; when Live's safety filter stops a call, a note says so. Work already handed to a bot is
24
+ not affected.
19
25
 
20
26
  ## "Hey thursday" does nothing
21
27
 
@@ -71,7 +77,8 @@ A job never fails for good; it pauses and waits.
71
77
 
72
78
  Deleting a single call, thread or note is on its own screen. **Settings › Thursday › History ›
73
79
  Reset history** deletes every call, every job and everything she remembers, for good; keys, bots and
74
- connectors stay. Wiping everything, keys included, is removing the data folder (`setup.md` says
80
+ connectors stay, and so does what each bot keeps for itself (its own memory and the skills it
81
+ installed, which go only when that bot is deleted). Wiping everything, keys included, is removing the data folder (`setup.md` says
75
82
  where).
76
83
 
77
84
  ## Still stuck
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thursday-agent",
3
- "version": "0.17.0",
3
+ "version": "0.17.2",
4
4
  "description": "A voice agent that runs on your own machine — talk to her, she hands the slow work to bots with a shell, a browser and skills.",
5
5
  "license": "MIT",
6
6
  "keywords": [
@@ -97,6 +97,12 @@ const out = join(
97
97
 
98
98
  const cur = trip.currency ? String(trip.currency).toUpperCase() : null;
99
99
  const lang = String(trip.lang ?? "en");
100
+ // Built without them, a page in Korean came out with "Day by day" and "Before you go" on it,
101
+ // and the warning printed after the build was passed over
102
+ if (!lang.startsWith("en") && !trip.labels)
103
+ fail(
104
+ `The page is in "${lang}" but its own headings would be English: add "labels" in that language (references/itinerary.md) and build again.`,
105
+ );
100
106
  const place = String(trip.place ?? "");
101
107
  const L = {
102
108
  flights: "Getting there",
@@ -509,7 +515,3 @@ if (missing.length)
509
515
  console.log(
510
516
  `No photo for: ${missing.join("; ")}. Give those a "wiki" title that exists — a place abroad often has one only in its own language's Wikipedia ("pt:Mosteiro dos Jerónimos", "de:Kölner Dom") — or a "photo" page url, or leave them without one.`,
511
517
  );
512
- if (!lang.startsWith("en") && !trip.labels)
513
- console.log(
514
- `The page is in "${lang}" but its own headings are English: add "labels" in that language (references/itinerary.md) and build again.`,
515
- );
@@ -47,7 +47,8 @@ first is the cover, asking the question the book answers.
47
47
  node <skill dir>/scripts/book.mjs put <name> <scratch>/pages.html --lang <the book's language, e.g. ko>
48
48
  ```
49
49
 
50
- It checks each page and puts them all into the book, in place of what it held; a
50
+ A book is named by its folder under your artifacts, or given by its path — the way
51
+ to reach one another job made. It checks each page and puts them all into the book, in place of what it held; a
51
52
  page it cannot take stops it, named, and nothing is written: fix that page in
52
53
  your file and put again. To change the book later, change your file and put it again.
53
54
  4. Look at it once when a page carries a picture you did not draw — a photo you
@@ -84,14 +84,19 @@ Both land in `artifacts/<name>/`: hand back the page and the `.xlsx`.
84
84
  and the file's name. Look at each one: a photo with `look_at`, a PDF's text with
85
85
  `node $THURSDAY_SKILLS/media-digest/scripts/text.mjs <file.pdf> --out <scratch>/<n>.txt`. A
86
86
  figure you cannot read is an empty cell, named in your answer, never a guess. `totals` sums
87
- the amounts; a second sheet by category is `SUMIF` over them, by month `SUMIFS`. Their files
88
- stay where they are, as they are named.
87
+ the amounts; a second sheet by category is `SUMIF` over them, by month `SUMIFS`. Amounts in
88
+ more than one currency get a currency column and are summed a currency at a time (`SUMIFS` by
89
+ currency, no `totals` across them) — won and dollars are never added. Their files stay where
90
+ they are, as they are named.
89
91
  - **A bank's or a card's export** is the CSV they downloaded; never sign in to their bank for it.
90
- `read <file.csv>` prints its lines numbered — when it says the file is not UTF-8, run it again
91
- with the `--encoding` it names. Then `read <file.csv> --header <the line naming the columns>
92
- --json <scratch>/<name>.json` writes the table under that line, dates as dates and amounts as
93
- numbers. Add a column there — a category for each row — and `put <name>` that file; a budget by
94
- month and category is a second sheet of `SUMIFS` over it.
92
+ `read <file.csv>` prints its lines numbered and says which line it takes as the columns. When
93
+ it says the file is not UTF-8, give the likeliest `--encoding` for where the bank is; if its
94
+ words then do not read right, try the next. It also says what it could not take: a total under
95
+ the table (leave it out with `--until <the table's last line>`), or dates written day or month
96
+ first (`--dates dmy` for 03.07.2026, `--dates mdy` for 07/03/2026 — as the bank's country
97
+ writes them). Then add `--json <scratch>/<name>.json`: the table as put takes it, dates as
98
+ dates, amounts as numbers. Add a column there — a category for each row — and `put <name>`
99
+ that file; a budget by month and category is a second sheet of `SUMIFS` over it.
95
100
 
96
101
  ## Their own .xlsx, and changes
97
102
 
@@ -305,16 +305,23 @@ export function formatColor(value, code) {
305
305
  return sectionFor(parts, value).section.color ?? null;
306
306
  }
307
307
 
308
- /** A date written YYYY-MM-DD, with hh:mm or hh:mm:ss after it, as Excel's day number; else null. */
309
- export function serialOf(text) {
310
- const m =
311
- /^(\d{4})[-/.](\d{1,2})[-/.](\d{1,2})(?:[ T](\d{1,2}):(\d{2})(?::(\d{2}))?)?$/.exec(
312
- String(text).trim(),
313
- );
308
+ /**
309
+ * A date as Excel's day number, or null. Written year first (2026-07-03, 2026.07.03,
310
+ * 2026/07/03) unless `order` says the day or the month comes first (`dmy`: 03.07.2026,
311
+ * `mdy`: 07/03/2026) — which of those a file means is for whoever knows the file to say,
312
+ * never guessed here. A time may follow: hh:mm or hh:mm:ss.
313
+ */
314
+ export function serialOf(text, order = "ymd") {
315
+ const time = String.raw`(?:[ T](\d{1,2}):(\d{2})(?::(\d{2}))?)?$`;
316
+ const m = new RegExp(
317
+ order === "ymd"
318
+ ? String.raw`^(\d{4})[-/.](\d{1,2})[-/.](\d{1,2})` + time
319
+ : String.raw`^(\d{1,2})[-/.](\d{1,2})[-/.](\d{4})` + time,
320
+ ).exec(String(text).trim());
314
321
  if (!m) return null;
315
- const [y, mo, d, h = 0, mi = 0, s = 0] = m
316
- .slice(1)
317
- .map((x) => Number(x ?? 0));
322
+ const [a, b, c, h = 0, mi = 0, s = 0] = m.slice(1).map((x) => Number(x ?? 0));
323
+ const [y, mo, d] =
324
+ order === "ymd" ? [a, b, c] : order === "dmy" ? [c, b, a] : [c, a, b];
318
325
  const at = Date.UTC(y, mo - 1, d, h, mi, s);
319
326
  const check = new Date(at);
320
327
  if (check.getUTCMonth() !== mo - 1 || check.getUTCDate() !== d || h > 23)
@@ -2,10 +2,11 @@
2
2
  // A picture book: one HTML file in a folder of its own, printed and read aloud.
3
3
  //
4
4
  // node book.mjs new <name> the book, styled, to write pages into
5
+ // (a book after `new` is its name — its folder under your artifacts — or its path)
5
6
  // node book.mjs put <name> <pages.html> [--lang ko] the pages written in <pages.html> put
6
7
  // into the book, checked first
7
- // node book.mjs shots <name> every page as a picture, and all on one, in scratch/
8
- // node book.mjs pdf <name> the book as a PDF, one page a sheet
8
+ // node book.mjs shots <name | path> every page as a picture, and all on one, in scratch/
9
+ // node book.mjs pdf <name | path> the book as a PDF, one page a sheet
9
10
  // node book.mjs video <name> <audio>... [--size WxH] the book as an mp4, one audio file per page
10
11
  import { spawnSync } from "node:child_process";
11
12
  import {
@@ -15,7 +16,7 @@ import {
15
16
  rmSync,
16
17
  writeFileSync,
17
18
  } from "node:fs";
18
- import { dirname, join, resolve } from "node:path";
19
+ import { basename, dirname, join, resolve } from "node:path";
19
20
  import { fileURLToPath } from "node:url";
20
21
  import { markSvg } from "../runtime/shell/wear.mjs";
21
22
  import {
@@ -44,12 +45,24 @@ function bookFile(name) {
44
45
  return join(ARTIFACTS, name, `${name}.html`);
45
46
  }
46
47
 
48
+ /**
49
+ * A book named, or pointed at by its folder or its file — a book another job made, or one
50
+ * the path names as it was handed back. A path is taken as given; a name is looked for in
51
+ * your own folder.
52
+ */
53
+ function bookAt(arg) {
54
+ if (!arg || !/[/\\]|\.html$/i.test(arg)) return bookFile(arg);
55
+ const path = resolve(arg);
56
+ if (/\.html$/i.test(path)) return path;
57
+ return join(path, `${basename(path)}.html`);
58
+ }
59
+
47
60
  /** An existing book, or how to start one. */
48
61
  function openBook(name) {
49
- const book = bookFile(name);
62
+ const book = bookAt(name);
50
63
  if (!existsSync(book))
51
64
  throw new Stop(
52
- `No book ${shown(book)}. Start it with: node ${SCRIPT} new ${name}`,
65
+ `No book ${shown(book)}. A book is given by its name (its folder under your artifacts) or by its path; to start one: node ${SCRIPT} new <name>`,
53
66
  );
54
67
  return book;
55
68
  }
@@ -212,7 +225,7 @@ function putPages(name, from, args) {
212
225
  */
213
226
  function shotBook(name) {
214
227
  const book = writtenBook(name);
215
- const out = join(WORKSPACE, "scratch", `${name}-shots`);
228
+ const out = join(WORKSPACE, "scratch", `${basename(book, ".html")}-shots`);
216
229
  const sheet = join(out, "book.png");
217
230
  rmSync(out, { recursive: true, force: true });
218
231
  const done = spawnSync(