@withbuddi/buddi 0.1.0-pre.28 → 0.1.0-pre.30

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 (1190) hide show
  1. package/README.md +3 -1
  2. package/extension/manifest.json +2 -2
  3. package/node_modules/@buddi/cli/dist/.tsbuildinfo +1 -1
  4. package/node_modules/@buddi/cli/dist/args.d.ts +19 -3
  5. package/node_modules/@buddi/cli/dist/args.d.ts.map +1 -1
  6. package/node_modules/@buddi/cli/dist/args.js +19 -5
  7. package/node_modules/@buddi/cli/dist/args.js.map +1 -1
  8. package/node_modules/@buddi/cli/dist/commands.d.ts.map +1 -1
  9. package/node_modules/@buddi/cli/dist/commands.js +80 -8
  10. package/node_modules/@buddi/cli/dist/commands.js.map +1 -1
  11. package/node_modules/@buddi/cli/dist/dashboard-cmd.d.ts +3 -0
  12. package/node_modules/@buddi/cli/dist/dashboard-cmd.d.ts.map +1 -1
  13. package/node_modules/@buddi/cli/dist/dashboard-cmd.js +63 -0
  14. package/node_modules/@buddi/cli/dist/dashboard-cmd.js.map +1 -1
  15. package/node_modules/@buddi/cli/dist/doctor-probes.d.ts.map +1 -1
  16. package/node_modules/@buddi/cli/dist/doctor-probes.js +11 -4
  17. package/node_modules/@buddi/cli/dist/doctor-probes.js.map +1 -1
  18. package/node_modules/@buddi/cli/dist/doctor.d.ts +1 -1
  19. package/node_modules/@buddi/cli/dist/doctor.d.ts.map +1 -1
  20. package/node_modules/@buddi/cli/dist/jobs-cmd.d.ts +4 -0
  21. package/node_modules/@buddi/cli/dist/jobs-cmd.d.ts.map +1 -1
  22. package/node_modules/@buddi/cli/dist/jobs-cmd.js +53 -4
  23. package/node_modules/@buddi/cli/dist/jobs-cmd.js.map +1 -1
  24. package/node_modules/@buddi/cli/dist/main.d.ts.map +1 -1
  25. package/node_modules/@buddi/cli/dist/main.js +27 -2
  26. package/node_modules/@buddi/cli/dist/main.js.map +1 -1
  27. package/node_modules/@buddi/cli/dist/mcp/gateway-client.d.ts +19 -17
  28. package/node_modules/@buddi/cli/dist/mcp/gateway-client.d.ts.map +1 -1
  29. package/node_modules/@buddi/cli/dist/mcp/gateway-client.js +128 -29
  30. package/node_modules/@buddi/cli/dist/mcp/gateway-client.js.map +1 -1
  31. package/node_modules/@buddi/cli/dist/mcp/tools.d.ts +6 -0
  32. package/node_modules/@buddi/cli/dist/mcp/tools.d.ts.map +1 -1
  33. package/node_modules/@buddi/cli/dist/mcp/tools.js +20 -1
  34. package/node_modules/@buddi/cli/dist/mcp/tools.js.map +1 -1
  35. package/node_modules/@buddi/cli/dist/telegram-cmd.d.ts.map +1 -1
  36. package/node_modules/@buddi/cli/dist/telegram-cmd.js +5 -4
  37. package/node_modules/@buddi/cli/dist/telegram-cmd.js.map +1 -1
  38. package/node_modules/@buddi/core/dist/.tsbuildinfo +1 -1
  39. package/node_modules/@buddi/core/dist/agents/catalog.d.ts.map +1 -1
  40. package/node_modules/@buddi/core/dist/agents/catalog.js +7 -6
  41. package/node_modules/@buddi/core/dist/agents/catalog.js.map +1 -1
  42. package/node_modules/@buddi/core/dist/agents/frontmatter.d.ts +12 -12
  43. package/node_modules/@buddi/core/dist/agents/skills.d.ts +2 -2
  44. package/node_modules/@buddi/core/dist/clock-widget.d.ts +38 -0
  45. package/node_modules/@buddi/core/dist/clock-widget.d.ts.map +1 -0
  46. package/node_modules/@buddi/core/dist/clock-widget.js +114 -0
  47. package/node_modules/@buddi/core/dist/clock-widget.js.map +1 -0
  48. package/node_modules/@buddi/core/dist/failures/owner-message.d.ts +25 -0
  49. package/node_modules/@buddi/core/dist/failures/owner-message.d.ts.map +1 -1
  50. package/node_modules/@buddi/core/dist/failures/owner-message.js +90 -0
  51. package/node_modules/@buddi/core/dist/failures/owner-message.js.map +1 -1
  52. package/node_modules/@buddi/core/dist/feedback/index.d.ts +23 -2
  53. package/node_modules/@buddi/core/dist/feedback/index.d.ts.map +1 -1
  54. package/node_modules/@buddi/core/dist/feedback/index.js +23 -3
  55. package/node_modules/@buddi/core/dist/feedback/index.js.map +1 -1
  56. package/node_modules/@buddi/core/dist/groups.d.ts +33 -0
  57. package/node_modules/@buddi/core/dist/groups.d.ts.map +1 -1
  58. package/node_modules/@buddi/core/dist/groups.js +76 -4
  59. package/node_modules/@buddi/core/dist/groups.js.map +1 -1
  60. package/node_modules/@buddi/core/dist/home.d.ts +5 -5
  61. package/node_modules/@buddi/core/dist/host/build.d.ts +19 -1
  62. package/node_modules/@buddi/core/dist/host/build.d.ts.map +1 -1
  63. package/node_modules/@buddi/core/dist/host/build.js +122 -2
  64. package/node_modules/@buddi/core/dist/host/build.js.map +1 -1
  65. package/node_modules/@buddi/core/dist/host/types.d.ts +33 -0
  66. package/node_modules/@buddi/core/dist/host/types.d.ts.map +1 -1
  67. package/node_modules/@buddi/core/dist/index.d.ts +8 -0
  68. package/node_modules/@buddi/core/dist/index.d.ts.map +1 -1
  69. package/node_modules/@buddi/core/dist/index.js +8 -0
  70. package/node_modules/@buddi/core/dist/index.js.map +1 -1
  71. package/node_modules/@buddi/core/dist/lock.d.ts +82 -0
  72. package/node_modules/@buddi/core/dist/lock.d.ts.map +1 -0
  73. package/node_modules/@buddi/core/dist/lock.js +182 -0
  74. package/node_modules/@buddi/core/dist/lock.js.map +1 -0
  75. package/node_modules/@buddi/core/dist/metrics.d.ts.map +1 -1
  76. package/node_modules/@buddi/core/dist/metrics.js +4 -2
  77. package/node_modules/@buddi/core/dist/metrics.js.map +1 -1
  78. package/node_modules/@buddi/core/dist/onboarding/store.d.ts +5 -0
  79. package/node_modules/@buddi/core/dist/onboarding/store.d.ts.map +1 -1
  80. package/node_modules/@buddi/core/dist/onboarding/store.js +35 -5
  81. package/node_modules/@buddi/core/dist/onboarding/store.js.map +1 -1
  82. package/node_modules/@buddi/core/dist/onboarding/types.d.ts +10 -0
  83. package/node_modules/@buddi/core/dist/onboarding/types.d.ts.map +1 -1
  84. package/node_modules/@buddi/core/dist/onboarding/types.js +2 -0
  85. package/node_modules/@buddi/core/dist/onboarding/types.js.map +1 -1
  86. package/node_modules/@buddi/core/dist/owner-format.d.ts +14 -0
  87. package/node_modules/@buddi/core/dist/owner-format.d.ts.map +1 -0
  88. package/node_modules/@buddi/core/dist/owner-format.js +47 -0
  89. package/node_modules/@buddi/core/dist/owner-format.js.map +1 -0
  90. package/node_modules/@buddi/core/dist/owner-timezone.d.ts +46 -0
  91. package/node_modules/@buddi/core/dist/owner-timezone.d.ts.map +1 -0
  92. package/node_modules/@buddi/core/dist/owner-timezone.js +43 -0
  93. package/node_modules/@buddi/core/dist/owner-timezone.js.map +1 -0
  94. package/node_modules/@buddi/core/dist/pages.d.ts +13 -39
  95. package/node_modules/@buddi/core/dist/pages.d.ts.map +1 -1
  96. package/node_modules/@buddi/core/dist/pages.js +12 -1
  97. package/node_modules/@buddi/core/dist/pages.js.map +1 -1
  98. package/node_modules/@buddi/core/dist/places.d.ts +110 -0
  99. package/node_modules/@buddi/core/dist/places.d.ts.map +1 -0
  100. package/node_modules/@buddi/core/dist/places.js +239 -0
  101. package/node_modules/@buddi/core/dist/places.js.map +1 -0
  102. package/node_modules/@buddi/core/dist/plugin/index.d.ts +9 -2
  103. package/node_modules/@buddi/core/dist/plugin/index.d.ts.map +1 -1
  104. package/node_modules/@buddi/core/dist/plugin/index.js +3 -0
  105. package/node_modules/@buddi/core/dist/plugin/index.js.map +1 -1
  106. package/node_modules/@buddi/core/dist/plugin/requires.d.ts +75 -0
  107. package/node_modules/@buddi/core/dist/plugin/requires.d.ts.map +1 -0
  108. package/node_modules/@buddi/core/dist/plugin/requires.js +77 -0
  109. package/node_modules/@buddi/core/dist/plugin/requires.js.map +1 -0
  110. package/node_modules/@buddi/core/dist/plugin/uses.d.ts +1 -1
  111. package/node_modules/@buddi/core/dist/plugin/uses.d.ts.map +1 -1
  112. package/node_modules/@buddi/core/dist/plugin/uses.js +2 -0
  113. package/node_modules/@buddi/core/dist/plugin/uses.js.map +1 -1
  114. package/node_modules/@buddi/core/dist/plugin/version.d.ts +1 -1
  115. package/node_modules/@buddi/core/dist/plugin/version.js +1 -1
  116. package/node_modules/@buddi/core/dist/queue/failures.d.ts +84 -0
  117. package/node_modules/@buddi/core/dist/queue/failures.d.ts.map +1 -0
  118. package/node_modules/@buddi/core/dist/queue/failures.js +195 -0
  119. package/node_modules/@buddi/core/dist/queue/failures.js.map +1 -0
  120. package/node_modules/@buddi/core/dist/queue/index.d.ts +1 -0
  121. package/node_modules/@buddi/core/dist/queue/index.d.ts.map +1 -1
  122. package/node_modules/@buddi/core/dist/queue/index.js +1 -0
  123. package/node_modules/@buddi/core/dist/queue/index.js.map +1 -1
  124. package/node_modules/@buddi/core/dist/queue/jobs.d.ts +39 -3
  125. package/node_modules/@buddi/core/dist/queue/jobs.d.ts.map +1 -1
  126. package/node_modules/@buddi/core/dist/queue/jobs.js +54 -4
  127. package/node_modules/@buddi/core/dist/queue/jobs.js.map +1 -1
  128. package/node_modules/@buddi/core/dist/queue/retry-policy.d.ts +5 -0
  129. package/node_modules/@buddi/core/dist/queue/retry-policy.d.ts.map +1 -1
  130. package/node_modules/@buddi/core/dist/queue/retry-policy.js +19 -2
  131. package/node_modules/@buddi/core/dist/queue/retry-policy.js.map +1 -1
  132. package/node_modules/@buddi/core/dist/queue/types.d.ts +20 -0
  133. package/node_modules/@buddi/core/dist/queue/types.d.ts.map +1 -1
  134. package/node_modules/@buddi/core/dist/queue/types.js +17 -0
  135. package/node_modules/@buddi/core/dist/queue/types.js.map +1 -1
  136. package/node_modules/@buddi/core/dist/registry.d.ts +37 -2
  137. package/node_modules/@buddi/core/dist/registry.d.ts.map +1 -1
  138. package/node_modules/@buddi/core/dist/registry.js +137 -3
  139. package/node_modules/@buddi/core/dist/registry.js.map +1 -1
  140. package/node_modules/@buddi/core/dist/scheduler/enqueue.d.ts +71 -0
  141. package/node_modules/@buddi/core/dist/scheduler/enqueue.d.ts.map +1 -0
  142. package/node_modules/@buddi/core/dist/scheduler/enqueue.js +116 -0
  143. package/node_modules/@buddi/core/dist/scheduler/enqueue.js.map +1 -0
  144. package/node_modules/@buddi/core/dist/scheduler/index.d.ts +1 -0
  145. package/node_modules/@buddi/core/dist/scheduler/index.d.ts.map +1 -1
  146. package/node_modules/@buddi/core/dist/scheduler/index.js +1 -0
  147. package/node_modules/@buddi/core/dist/scheduler/index.js.map +1 -1
  148. package/node_modules/@buddi/core/dist/scheduler/missions.d.ts +15 -0
  149. package/node_modules/@buddi/core/dist/scheduler/missions.d.ts.map +1 -1
  150. package/node_modules/@buddi/core/dist/scheduler/missions.js +43 -4
  151. package/node_modules/@buddi/core/dist/scheduler/missions.js.map +1 -1
  152. package/node_modules/@buddi/core/dist/scheduler/types.d.ts +10 -0
  153. package/node_modules/@buddi/core/dist/scheduler/types.d.ts.map +1 -1
  154. package/node_modules/@buddi/core/dist/scheduler/types.js +3 -0
  155. package/node_modules/@buddi/core/dist/scheduler/types.js.map +1 -1
  156. package/node_modules/@buddi/core/dist/secrets/settings.d.ts +6 -6
  157. package/node_modules/@buddi/core/dist/secrets/settings.d.ts.map +1 -1
  158. package/node_modules/@buddi/core/dist/secrets/settings.js +23 -3
  159. package/node_modules/@buddi/core/dist/secrets/settings.js.map +1 -1
  160. package/node_modules/@buddi/core/dist/semver.d.ts +17 -0
  161. package/node_modules/@buddi/core/dist/semver.d.ts.map +1 -1
  162. package/node_modules/@buddi/core/dist/semver.js +130 -0
  163. package/node_modules/@buddi/core/dist/semver.js.map +1 -1
  164. package/node_modules/@buddi/core/dist/sentinels/digest.d.ts +8 -1
  165. package/node_modules/@buddi/core/dist/sentinels/digest.d.ts.map +1 -1
  166. package/node_modules/@buddi/core/dist/sentinels/digest.js +10 -3
  167. package/node_modules/@buddi/core/dist/sentinels/digest.js.map +1 -1
  168. package/node_modules/@buddi/core/dist/sentinels/index.d.ts +1 -0
  169. package/node_modules/@buddi/core/dist/sentinels/index.d.ts.map +1 -1
  170. package/node_modules/@buddi/core/dist/sentinels/index.js +1 -0
  171. package/node_modules/@buddi/core/dist/sentinels/index.js.map +1 -1
  172. package/node_modules/@buddi/core/dist/sentinels/mutes.d.ts +51 -0
  173. package/node_modules/@buddi/core/dist/sentinels/mutes.d.ts.map +1 -0
  174. package/node_modules/@buddi/core/dist/sentinels/mutes.js +86 -0
  175. package/node_modules/@buddi/core/dist/sentinels/mutes.js.map +1 -0
  176. package/node_modules/@buddi/core/dist/sentinels/run.d.ts +20 -5
  177. package/node_modules/@buddi/core/dist/sentinels/run.d.ts.map +1 -1
  178. package/node_modules/@buddi/core/dist/sentinels/run.js +105 -42
  179. package/node_modules/@buddi/core/dist/sentinels/run.js.map +1 -1
  180. package/node_modules/@buddi/core/dist/sentinels/types.d.ts +165 -2
  181. package/node_modules/@buddi/core/dist/sentinels/types.d.ts.map +1 -1
  182. package/node_modules/@buddi/core/dist/sentinels/types.js +126 -2
  183. package/node_modules/@buddi/core/dist/sentinels/types.js.map +1 -1
  184. package/node_modules/@buddi/core/dist/sources/run.d.ts +8 -0
  185. package/node_modules/@buddi/core/dist/sources/run.d.ts.map +1 -1
  186. package/node_modules/@buddi/core/dist/sources/run.js +1 -1
  187. package/node_modules/@buddi/core/dist/sources/run.js.map +1 -1
  188. package/node_modules/@buddi/core/dist/sources/watch.d.ts +3 -0
  189. package/node_modules/@buddi/core/dist/sources/watch.d.ts.map +1 -1
  190. package/node_modules/@buddi/core/dist/sources/watch.js +1 -1
  191. package/node_modules/@buddi/core/dist/sources/watch.js.map +1 -1
  192. package/node_modules/@buddi/core/dist/time.d.ts +17 -3
  193. package/node_modules/@buddi/core/dist/time.d.ts.map +1 -1
  194. package/node_modules/@buddi/core/dist/time.js +27 -3
  195. package/node_modules/@buddi/core/dist/time.js.map +1 -1
  196. package/node_modules/@buddi/core/dist/tools.d.ts +30 -1
  197. package/node_modules/@buddi/core/dist/tools.d.ts.map +1 -1
  198. package/node_modules/@buddi/core/dist/tools.js.map +1 -1
  199. package/node_modules/@buddi/core/dist/views.d.ts +164 -164
  200. package/node_modules/@buddi/core/dist/views.d.ts.map +1 -1
  201. package/node_modules/@buddi/core/dist/views.js +5 -0
  202. package/node_modules/@buddi/core/dist/views.js.map +1 -1
  203. package/node_modules/@buddi/core/dist/widget-settings.d.ts +161 -0
  204. package/node_modules/@buddi/core/dist/widget-settings.d.ts.map +1 -0
  205. package/node_modules/@buddi/core/dist/widget-settings.js +314 -0
  206. package/node_modules/@buddi/core/dist/widget-settings.js.map +1 -0
  207. package/node_modules/@buddi/core/dist/widgets.d.ts +206 -0
  208. package/node_modules/@buddi/core/dist/widgets.d.ts.map +1 -0
  209. package/node_modules/@buddi/core/dist/widgets.js +247 -0
  210. package/node_modules/@buddi/core/dist/widgets.js.map +1 -0
  211. package/node_modules/@buddi/core/migrations/059_dashboard_lock.sql +33 -0
  212. package/node_modules/@buddi/core/migrations/060_owner_places.sql +30 -0
  213. package/node_modules/@buddi/core/migrations/061_owner_formats.sql +10 -0
  214. package/node_modules/@buddi/core/migrations/062_group_deleted.sql +7 -0
  215. package/node_modules/@buddi/core/migrations/063_provider_account_limits.sql +20 -0
  216. package/node_modules/@buddi/core/migrations/064_mission_coalesce.sql +12 -0
  217. package/node_modules/@buddi/core/migrations/065_api_tokens.sql +28 -0
  218. package/node_modules/@buddi/core/migrations/066_alert_decisions.sql +45 -0
  219. package/node_modules/@buddi/core/migrations/067_job_acknowledged.sql +21 -0
  220. package/node_modules/@buddi/gateway/dist/.tsbuildinfo +1 -1
  221. package/node_modules/@buddi/gateway/dist/account-limits.d.ts +45 -0
  222. package/node_modules/@buddi/gateway/dist/account-limits.d.ts.map +1 -0
  223. package/node_modules/@buddi/gateway/dist/account-limits.js +87 -0
  224. package/node_modules/@buddi/gateway/dist/account-limits.js.map +1 -0
  225. package/node_modules/@buddi/gateway/dist/accounts-cli.d.ts +88 -0
  226. package/node_modules/@buddi/gateway/dist/accounts-cli.d.ts.map +1 -0
  227. package/node_modules/@buddi/gateway/dist/accounts-cli.js +216 -0
  228. package/node_modules/@buddi/gateway/dist/accounts-cli.js.map +1 -0
  229. package/node_modules/@buddi/gateway/dist/agents/canvas.d.ts +20 -20
  230. package/node_modules/@buddi/gateway/dist/agents/learning-digest.d.ts +4 -0
  231. package/node_modules/@buddi/gateway/dist/agents/learning-digest.d.ts.map +1 -1
  232. package/node_modules/@buddi/gateway/dist/agents/learning-digest.js +18 -5
  233. package/node_modules/@buddi/gateway/dist/agents/learning-digest.js.map +1 -1
  234. package/node_modules/@buddi/gateway/dist/agents/owner-tools.d.ts.map +1 -1
  235. package/node_modules/@buddi/gateway/dist/agents/owner-tools.js +3 -2
  236. package/node_modules/@buddi/gateway/dist/agents/owner-tools.js.map +1 -1
  237. package/node_modules/@buddi/gateway/dist/agents/platform.d.ts +24 -24
  238. package/node_modules/@buddi/gateway/dist/api-token-cli.d.ts +17 -0
  239. package/node_modules/@buddi/gateway/dist/api-token-cli.d.ts.map +1 -0
  240. package/node_modules/@buddi/gateway/dist/api-token-cli.js +108 -0
  241. package/node_modules/@buddi/gateway/dist/api-token-cli.js.map +1 -0
  242. package/node_modules/@buddi/gateway/dist/bootstrap.d.ts +6 -2
  243. package/node_modules/@buddi/gateway/dist/bootstrap.d.ts.map +1 -1
  244. package/node_modules/@buddi/gateway/dist/bootstrap.js +25 -7
  245. package/node_modules/@buddi/gateway/dist/bootstrap.js.map +1 -1
  246. package/node_modules/@buddi/gateway/dist/chat/conversations.d.ts.map +1 -1
  247. package/node_modules/@buddi/gateway/dist/chat/conversations.js +8 -2
  248. package/node_modules/@buddi/gateway/dist/chat/conversations.js.map +1 -1
  249. package/node_modules/@buddi/gateway/dist/chat/session.d.ts +5 -0
  250. package/node_modules/@buddi/gateway/dist/chat/session.d.ts.map +1 -1
  251. package/node_modules/@buddi/gateway/dist/chat/session.js +11 -1
  252. package/node_modules/@buddi/gateway/dist/chat/session.js.map +1 -1
  253. package/node_modules/@buddi/gateway/dist/cli.d.ts.map +1 -1
  254. package/node_modules/@buddi/gateway/dist/cli.js +14 -3
  255. package/node_modules/@buddi/gateway/dist/cli.js.map +1 -1
  256. package/node_modules/@buddi/gateway/dist/index.d.ts +3 -0
  257. package/node_modules/@buddi/gateway/dist/index.d.ts.map +1 -1
  258. package/node_modules/@buddi/gateway/dist/index.js +3 -0
  259. package/node_modules/@buddi/gateway/dist/index.js.map +1 -1
  260. package/node_modules/@buddi/gateway/dist/missions/dead-letter.d.ts +2 -1
  261. package/node_modules/@buddi/gateway/dist/missions/dead-letter.d.ts.map +1 -1
  262. package/node_modules/@buddi/gateway/dist/missions/dead-letter.js +19 -5
  263. package/node_modules/@buddi/gateway/dist/missions/dead-letter.js.map +1 -1
  264. package/node_modules/@buddi/gateway/dist/missions/defaults.d.ts +6 -0
  265. package/node_modules/@buddi/gateway/dist/missions/defaults.d.ts.map +1 -1
  266. package/node_modules/@buddi/gateway/dist/missions/defaults.js +10 -2
  267. package/node_modules/@buddi/gateway/dist/missions/defaults.js.map +1 -1
  268. package/node_modules/@buddi/gateway/dist/missions/execute.d.ts.map +1 -1
  269. package/node_modules/@buddi/gateway/dist/missions/execute.js +49 -9
  270. package/node_modules/@buddi/gateway/dist/missions/execute.js.map +1 -1
  271. package/node_modules/@buddi/gateway/dist/missions/goals.d.ts +12 -1
  272. package/node_modules/@buddi/gateway/dist/missions/goals.d.ts.map +1 -1
  273. package/node_modules/@buddi/gateway/dist/missions/goals.js +21 -1
  274. package/node_modules/@buddi/gateway/dist/missions/goals.js.map +1 -1
  275. package/node_modules/@buddi/gateway/dist/missions/inline.js +1 -1
  276. package/node_modules/@buddi/gateway/dist/missions/inline.js.map +1 -1
  277. package/node_modules/@buddi/gateway/dist/missions/sentinel-wake.d.ts +14 -0
  278. package/node_modules/@buddi/gateway/dist/missions/sentinel-wake.d.ts.map +1 -1
  279. package/node_modules/@buddi/gateway/dist/missions/sentinel-wake.js +41 -2
  280. package/node_modules/@buddi/gateway/dist/missions/sentinel-wake.js.map +1 -1
  281. package/node_modules/@buddi/gateway/dist/missions-cli.d.ts.map +1 -1
  282. package/node_modules/@buddi/gateway/dist/missions-cli.js +5 -5
  283. package/node_modules/@buddi/gateway/dist/missions-cli.js.map +1 -1
  284. package/node_modules/@buddi/gateway/dist/nudges-cli.js +2 -2
  285. package/node_modules/@buddi/gateway/dist/nudges-cli.js.map +1 -1
  286. package/node_modules/@buddi/gateway/dist/owner-seed.js +2 -2
  287. package/node_modules/@buddi/gateway/dist/owner-seed.js.map +1 -1
  288. package/node_modules/@buddi/gateway/dist/plugins/live.d.ts +8 -1
  289. package/node_modules/@buddi/gateway/dist/plugins/live.d.ts.map +1 -1
  290. package/node_modules/@buddi/gateway/dist/plugins/live.js +25 -7
  291. package/node_modules/@buddi/gateway/dist/plugins/live.js.map +1 -1
  292. package/node_modules/@buddi/gateway/dist/plugins/load.d.ts +55 -0
  293. package/node_modules/@buddi/gateway/dist/plugins/load.d.ts.map +1 -1
  294. package/node_modules/@buddi/gateway/dist/plugins/load.js +100 -4
  295. package/node_modules/@buddi/gateway/dist/plugins/load.js.map +1 -1
  296. package/node_modules/@buddi/gateway/dist/plugins/requires.d.ts +79 -0
  297. package/node_modules/@buddi/gateway/dist/plugins/requires.d.ts.map +1 -0
  298. package/node_modules/@buddi/gateway/dist/plugins/requires.js +178 -0
  299. package/node_modules/@buddi/gateway/dist/plugins/requires.js.map +1 -0
  300. package/node_modules/@buddi/gateway/dist/plugins/stage.d.ts +6 -0
  301. package/node_modules/@buddi/gateway/dist/plugins/stage.d.ts.map +1 -1
  302. package/node_modules/@buddi/gateway/dist/plugins/stage.js +6 -1
  303. package/node_modules/@buddi/gateway/dist/plugins/stage.js.map +1 -1
  304. package/node_modules/@buddi/gateway/dist/plugins/update.d.ts +21 -0
  305. package/node_modules/@buddi/gateway/dist/plugins/update.d.ts.map +1 -1
  306. package/node_modules/@buddi/gateway/dist/plugins/update.js +16 -0
  307. package/node_modules/@buddi/gateway/dist/plugins/update.js.map +1 -1
  308. package/node_modules/@buddi/gateway/dist/plugins-cli.d.ts +1 -1
  309. package/node_modules/@buddi/gateway/dist/plugins-cli.d.ts.map +1 -1
  310. package/node_modules/@buddi/gateway/dist/plugins-cli.js +6 -2
  311. package/node_modules/@buddi/gateway/dist/plugins-cli.js.map +1 -1
  312. package/node_modules/@buddi/gateway/dist/provider-accounts.d.ts +4 -0
  313. package/node_modules/@buddi/gateway/dist/provider-accounts.d.ts.map +1 -1
  314. package/node_modules/@buddi/gateway/dist/provider-accounts.js +68 -10
  315. package/node_modules/@buddi/gateway/dist/provider-accounts.js.map +1 -1
  316. package/node_modules/@buddi/gateway/dist/provider-diagnostics.d.ts.map +1 -1
  317. package/node_modules/@buddi/gateway/dist/provider-diagnostics.js +9 -0
  318. package/node_modules/@buddi/gateway/dist/provider-diagnostics.js.map +1 -1
  319. package/node_modules/@buddi/gateway/dist/reminders-cli.js +2 -2
  320. package/node_modules/@buddi/gateway/dist/reminders-cli.js.map +1 -1
  321. package/node_modules/@buddi/gateway/dist/serve.d.ts +2 -0
  322. package/node_modules/@buddi/gateway/dist/serve.d.ts.map +1 -1
  323. package/node_modules/@buddi/gateway/dist/serve.js +66 -8
  324. package/node_modules/@buddi/gateway/dist/serve.js.map +1 -1
  325. package/node_modules/@buddi/gateway/dist/surfaces/failure.d.ts.map +1 -1
  326. package/node_modules/@buddi/gateway/dist/surfaces/failure.js +9 -1
  327. package/node_modules/@buddi/gateway/dist/surfaces/failure.js.map +1 -1
  328. package/node_modules/@buddi/gateway/dist/surfaces/offered-actions.d.ts +17 -0
  329. package/node_modules/@buddi/gateway/dist/surfaces/offered-actions.d.ts.map +1 -1
  330. package/node_modules/@buddi/gateway/dist/surfaces/offered-actions.js +27 -0
  331. package/node_modules/@buddi/gateway/dist/surfaces/offered-actions.js.map +1 -1
  332. package/node_modules/@buddi/gateway/dist/system-context.d.ts +18 -0
  333. package/node_modules/@buddi/gateway/dist/system-context.d.ts.map +1 -1
  334. package/node_modules/@buddi/gateway/dist/system-context.js +46 -4
  335. package/node_modules/@buddi/gateway/dist/system-context.js.map +1 -1
  336. package/node_modules/@buddi/gateway/dist/telegram/main.js +3 -3
  337. package/node_modules/@buddi/gateway/dist/telegram/main.js.map +1 -1
  338. package/node_modules/@buddi/gateway/dist/telegram/outbound.d.ts +1 -1
  339. package/node_modules/@buddi/gateway/dist/telegram/outbound.d.ts.map +1 -1
  340. package/node_modules/@buddi/gateway/dist/telegram/outbound.js +7 -2
  341. package/node_modules/@buddi/gateway/dist/telegram/outbound.js.map +1 -1
  342. package/node_modules/@buddi/gateway/dist/telegram/reactions.d.ts.map +1 -1
  343. package/node_modules/@buddi/gateway/dist/telegram/reactions.js +12 -2
  344. package/node_modules/@buddi/gateway/dist/telegram/reactions.js.map +1 -1
  345. package/node_modules/@buddi/gateway/dist/telegram/surface.d.ts +4 -1
  346. package/node_modules/@buddi/gateway/dist/telegram/surface.d.ts.map +1 -1
  347. package/node_modules/@buddi/gateway/dist/telegram/surface.js +13 -3
  348. package/node_modules/@buddi/gateway/dist/telegram/surface.js.map +1 -1
  349. package/node_modules/@buddi/gateway/dist/tips/engine.d.ts +2 -0
  350. package/node_modules/@buddi/gateway/dist/tips/engine.d.ts.map +1 -1
  351. package/node_modules/@buddi/gateway/dist/tips/engine.js +8 -5
  352. package/node_modules/@buddi/gateway/dist/tips/engine.js.map +1 -1
  353. package/node_modules/@buddi/gateway/dist/tips/facts.d.ts +23 -0
  354. package/node_modules/@buddi/gateway/dist/tips/facts.d.ts.map +1 -1
  355. package/node_modules/@buddi/gateway/dist/tips/facts.js +19 -0
  356. package/node_modules/@buddi/gateway/dist/tips/facts.js.map +1 -1
  357. package/node_modules/@buddi/gateway/dist/tips/route.js +2 -2
  358. package/node_modules/@buddi/gateway/dist/tips/route.js.map +1 -1
  359. package/node_modules/@buddi/gateway/dist/tips/rules.d.ts +3 -2
  360. package/node_modules/@buddi/gateway/dist/tips/rules.d.ts.map +1 -1
  361. package/node_modules/@buddi/gateway/dist/tips/rules.js +26 -0
  362. package/node_modules/@buddi/gateway/dist/tips/rules.js.map +1 -1
  363. package/node_modules/@buddi/gateway/dist/web/alerts.d.ts +179 -0
  364. package/node_modules/@buddi/gateway/dist/web/alerts.d.ts.map +1 -0
  365. package/node_modules/@buddi/gateway/dist/web/alerts.js +363 -0
  366. package/node_modules/@buddi/gateway/dist/web/alerts.js.map +1 -0
  367. package/node_modules/@buddi/gateway/dist/web/api-routes.d.ts +103 -0
  368. package/node_modules/@buddi/gateway/dist/web/api-routes.d.ts.map +1 -0
  369. package/node_modules/@buddi/gateway/dist/web/api-routes.js +1239 -0
  370. package/node_modules/@buddi/gateway/dist/web/api-routes.js.map +1 -0
  371. package/node_modules/@buddi/gateway/dist/web/api-scan.d.ts +17 -0
  372. package/node_modules/@buddi/gateway/dist/web/api-scan.d.ts.map +1 -0
  373. package/node_modules/@buddi/gateway/dist/web/api-scan.js +206 -0
  374. package/node_modules/@buddi/gateway/dist/web/api-scan.js.map +1 -0
  375. package/node_modules/@buddi/gateway/dist/web/api-tokens.d.ts +58 -0
  376. package/node_modules/@buddi/gateway/dist/web/api-tokens.d.ts.map +1 -0
  377. package/node_modules/@buddi/gateway/dist/web/api-tokens.js +136 -0
  378. package/node_modules/@buddi/gateway/dist/web/api-tokens.js.map +1 -0
  379. package/node_modules/@buddi/gateway/dist/web/backups.js +2 -2
  380. package/node_modules/@buddi/gateway/dist/web/backups.js.map +1 -1
  381. package/node_modules/@buddi/gateway/dist/web/chat.d.ts +1 -0
  382. package/node_modules/@buddi/gateway/dist/web/chat.d.ts.map +1 -1
  383. package/node_modules/@buddi/gateway/dist/web/chat.js +4 -3
  384. package/node_modules/@buddi/gateway/dist/web/chat.js.map +1 -1
  385. package/node_modules/@buddi/gateway/dist/web/group-lifecycle.d.ts +18 -0
  386. package/node_modules/@buddi/gateway/dist/web/group-lifecycle.d.ts.map +1 -0
  387. package/node_modules/@buddi/gateway/dist/web/group-lifecycle.js +46 -0
  388. package/node_modules/@buddi/gateway/dist/web/group-lifecycle.js.map +1 -0
  389. package/node_modules/@buddi/gateway/dist/web/lock-image.d.ts +37 -0
  390. package/node_modules/@buddi/gateway/dist/web/lock-image.d.ts.map +1 -0
  391. package/node_modules/@buddi/gateway/dist/web/lock-image.js +253 -0
  392. package/node_modules/@buddi/gateway/dist/web/lock-image.js.map +1 -0
  393. package/node_modules/@buddi/gateway/dist/web/lock.d.ts +165 -0
  394. package/node_modules/@buddi/gateway/dist/web/lock.d.ts.map +1 -0
  395. package/node_modules/@buddi/gateway/dist/web/lock.js +478 -0
  396. package/node_modules/@buddi/gateway/dist/web/lock.js.map +1 -0
  397. package/node_modules/@buddi/gateway/dist/web/pages.d.ts +1 -0
  398. package/node_modules/@buddi/gateway/dist/web/pages.d.ts.map +1 -1
  399. package/node_modules/@buddi/gateway/dist/web/pages.js +12 -1
  400. package/node_modules/@buddi/gateway/dist/web/pages.js.map +1 -1
  401. package/node_modules/@buddi/gateway/dist/web/places.d.ts +27 -0
  402. package/node_modules/@buddi/gateway/dist/web/places.d.ts.map +1 -0
  403. package/node_modules/@buddi/gateway/dist/web/places.js +90 -0
  404. package/node_modules/@buddi/gateway/dist/web/places.js.map +1 -0
  405. package/node_modules/@buddi/gateway/dist/web/plugins.d.ts +28 -0
  406. package/node_modules/@buddi/gateway/dist/web/plugins.d.ts.map +1 -1
  407. package/node_modules/@buddi/gateway/dist/web/plugins.js +83 -9
  408. package/node_modules/@buddi/gateway/dist/web/plugins.js.map +1 -1
  409. package/node_modules/@buddi/gateway/dist/web/read.d.ts +52 -26
  410. package/node_modules/@buddi/gateway/dist/web/read.d.ts.map +1 -1
  411. package/node_modules/@buddi/gateway/dist/web/read.js +52 -36
  412. package/node_modules/@buddi/gateway/dist/web/read.js.map +1 -1
  413. package/node_modules/@buddi/gateway/dist/web/secrets.d.ts +61 -1
  414. package/node_modules/@buddi/gateway/dist/web/secrets.d.ts.map +1 -1
  415. package/node_modules/@buddi/gateway/dist/web/secrets.js +111 -3
  416. package/node_modules/@buddi/gateway/dist/web/secrets.js.map +1 -1
  417. package/node_modules/@buddi/gateway/dist/web/server.d.ts +9 -0
  418. package/node_modules/@buddi/gateway/dist/web/server.d.ts.map +1 -1
  419. package/node_modules/@buddi/gateway/dist/web/server.js +531 -46
  420. package/node_modules/@buddi/gateway/dist/web/server.js.map +1 -1
  421. package/node_modules/@buddi/gateway/dist/web/sessions.d.ts +43 -2
  422. package/node_modules/@buddi/gateway/dist/web/sessions.d.ts.map +1 -1
  423. package/node_modules/@buddi/gateway/dist/web/sessions.js +67 -3
  424. package/node_modules/@buddi/gateway/dist/web/sessions.js.map +1 -1
  425. package/node_modules/@buddi/gateway/dist/web/signed-out.d.ts +17 -18
  426. package/node_modules/@buddi/gateway/dist/web/signed-out.d.ts.map +1 -1
  427. package/node_modules/@buddi/gateway/dist/web/signed-out.js +135 -33
  428. package/node_modules/@buddi/gateway/dist/web/signed-out.js.map +1 -1
  429. package/node_modules/@buddi/gateway/dist/web/stream.d.ts.map +1 -1
  430. package/node_modules/@buddi/gateway/dist/web/stream.js +14 -0
  431. package/node_modules/@buddi/gateway/dist/web/stream.js.map +1 -1
  432. package/node_modules/@buddi/gateway/dist/web/tailscale.d.ts +33 -4
  433. package/node_modules/@buddi/gateway/dist/web/tailscale.d.ts.map +1 -1
  434. package/node_modules/@buddi/gateway/dist/web/tailscale.js +76 -16
  435. package/node_modules/@buddi/gateway/dist/web/tailscale.js.map +1 -1
  436. package/node_modules/@buddi/gateway/dist/web/widgets.d.ts +131 -0
  437. package/node_modules/@buddi/gateway/dist/web/widgets.d.ts.map +1 -0
  438. package/node_modules/@buddi/gateway/dist/web/widgets.js +478 -0
  439. package/node_modules/@buddi/gateway/dist/web/widgets.js.map +1 -0
  440. package/node_modules/@buddi/gateway/dist/web/write.d.ts +23 -0
  441. package/node_modules/@buddi/gateway/dist/web/write.d.ts.map +1 -1
  442. package/node_modules/@buddi/gateway/dist/web/write.js +46 -1
  443. package/node_modules/@buddi/gateway/dist/web/write.js.map +1 -1
  444. package/node_modules/@buddi/install/dist/.tsbuildinfo +1 -1
  445. package/node_modules/@buddi/runtime/dist/.tsbuildinfo +1 -1
  446. package/node_modules/@buddi/runtime/dist/anthropic.d.ts +15 -0
  447. package/node_modules/@buddi/runtime/dist/anthropic.d.ts.map +1 -1
  448. package/node_modules/@buddi/runtime/dist/anthropic.js +26 -9
  449. package/node_modules/@buddi/runtime/dist/anthropic.js.map +1 -1
  450. package/node_modules/@buddi/runtime/dist/codex-direct.d.ts +2 -1
  451. package/node_modules/@buddi/runtime/dist/codex-direct.d.ts.map +1 -1
  452. package/node_modules/@buddi/runtime/dist/codex-direct.js +13 -6
  453. package/node_modules/@buddi/runtime/dist/codex-direct.js.map +1 -1
  454. package/node_modules/@buddi/runtime/dist/index.d.ts +1 -0
  455. package/node_modules/@buddi/runtime/dist/index.d.ts.map +1 -1
  456. package/node_modules/@buddi/runtime/dist/index.js +1 -0
  457. package/node_modules/@buddi/runtime/dist/index.js.map +1 -1
  458. package/node_modules/@buddi/runtime/dist/loop.d.ts +2 -0
  459. package/node_modules/@buddi/runtime/dist/loop.d.ts.map +1 -1
  460. package/node_modules/@buddi/runtime/dist/loop.js +22 -0
  461. package/node_modules/@buddi/runtime/dist/loop.js.map +1 -1
  462. package/node_modules/@buddi/runtime/dist/openai.d.ts +34 -1
  463. package/node_modules/@buddi/runtime/dist/openai.d.ts.map +1 -1
  464. package/node_modules/@buddi/runtime/dist/openai.js +85 -19
  465. package/node_modules/@buddi/runtime/dist/openai.js.map +1 -1
  466. package/node_modules/@buddi/runtime/dist/rate-limit.d.ts +91 -0
  467. package/node_modules/@buddi/runtime/dist/rate-limit.d.ts.map +1 -0
  468. package/node_modules/@buddi/runtime/dist/rate-limit.js +291 -0
  469. package/node_modules/@buddi/runtime/dist/rate-limit.js.map +1 -0
  470. package/node_modules/@buddi/runtime/dist/retry.d.ts +40 -0
  471. package/node_modules/@buddi/runtime/dist/retry.d.ts.map +1 -1
  472. package/node_modules/@buddi/runtime/dist/retry.js +42 -8
  473. package/node_modules/@buddi/runtime/dist/retry.js.map +1 -1
  474. package/node_modules/@buddi/tool-artifacts/dist/.tsbuildinfo +1 -1
  475. package/node_modules/@buddi/tool-browser/dist/.tsbuildinfo +1 -1
  476. package/node_modules/@buddi/tool-email/dist/.tsbuildinfo +1 -1
  477. package/node_modules/@buddi/tool-email/dist/agent.js +1 -1
  478. package/node_modules/@buddi/tool-email/dist/folders.d.ts +14 -0
  479. package/node_modules/@buddi/tool-email/dist/folders.d.ts.map +1 -1
  480. package/node_modules/@buddi/tool-email/dist/folders.js +23 -0
  481. package/node_modules/@buddi/tool-email/dist/folders.js.map +1 -1
  482. package/node_modules/@buddi/tool-email/dist/imap/fake.d.ts +55 -0
  483. package/node_modules/@buddi/tool-email/dist/imap/fake.d.ts.map +1 -1
  484. package/node_modules/@buddi/tool-email/dist/imap/fake.js +163 -4
  485. package/node_modules/@buddi/tool-email/dist/imap/fake.js.map +1 -1
  486. package/node_modules/@buddi/tool-email/dist/imap/imapflow-client.d.ts +8 -0
  487. package/node_modules/@buddi/tool-email/dist/imap/imapflow-client.d.ts.map +1 -1
  488. package/node_modules/@buddi/tool-email/dist/imap/imapflow-client.js +124 -4
  489. package/node_modules/@buddi/tool-email/dist/imap/imapflow-client.js.map +1 -1
  490. package/node_modules/@buddi/tool-email/dist/index.d.ts.map +1 -1
  491. package/node_modules/@buddi/tool-email/dist/index.js +3 -0
  492. package/node_modules/@buddi/tool-email/dist/index.js.map +1 -1
  493. package/node_modules/@buddi/tool-email/dist/mail.d.ts +48 -0
  494. package/node_modules/@buddi/tool-email/dist/mail.d.ts.map +1 -1
  495. package/node_modules/@buddi/tool-email/dist/mail.js +119 -0
  496. package/node_modules/@buddi/tool-email/dist/mail.js.map +1 -1
  497. package/node_modules/@buddi/tool-email/dist/mailbox/actions.d.ts +90 -5
  498. package/node_modules/@buddi/tool-email/dist/mailbox/actions.d.ts.map +1 -1
  499. package/node_modules/@buddi/tool-email/dist/mailbox/actions.js +643 -200
  500. package/node_modules/@buddi/tool-email/dist/mailbox/actions.js.map +1 -1
  501. package/node_modules/@buddi/tool-email/dist/mailbox/select.d.ts +6 -0
  502. package/node_modules/@buddi/tool-email/dist/mailbox/select.d.ts.map +1 -1
  503. package/node_modules/@buddi/tool-email/dist/mailbox/select.js +20 -2
  504. package/node_modules/@buddi/tool-email/dist/mailbox/select.js.map +1 -1
  505. package/node_modules/@buddi/tool-email/dist/metrics.d.ts +8 -9
  506. package/node_modules/@buddi/tool-email/dist/metrics.d.ts.map +1 -1
  507. package/node_modules/@buddi/tool-email/dist/metrics.js +8 -9
  508. package/node_modules/@buddi/tool-email/dist/metrics.js.map +1 -1
  509. package/node_modules/@buddi/tool-email/dist/needs-you.d.ts +58 -0
  510. package/node_modules/@buddi/tool-email/dist/needs-you.d.ts.map +1 -0
  511. package/node_modules/@buddi/tool-email/dist/needs-you.js +97 -0
  512. package/node_modules/@buddi/tool-email/dist/needs-you.js.map +1 -0
  513. package/node_modules/@buddi/tool-email/dist/pages/descriptors.d.ts.map +1 -1
  514. package/node_modules/@buddi/tool-email/dist/pages/descriptors.js +126 -80
  515. package/node_modules/@buddi/tool-email/dist/pages/descriptors.js.map +1 -1
  516. package/node_modules/@buddi/tool-email/dist/pages/drafts-tools.d.ts +2 -2
  517. package/node_modules/@buddi/tool-email/dist/pages/queries.d.ts +14 -0
  518. package/node_modules/@buddi/tool-email/dist/pages/queries.d.ts.map +1 -1
  519. package/node_modules/@buddi/tool-email/dist/pages/queries.js +65 -7
  520. package/node_modules/@buddi/tool-email/dist/pages/queries.js.map +1 -1
  521. package/node_modules/@buddi/tool-email/dist/policies/auto.d.ts +9 -9
  522. package/node_modules/@buddi/tool-email/dist/policies/auto.d.ts.map +1 -1
  523. package/node_modules/@buddi/tool-email/dist/policies/auto.js +79 -24
  524. package/node_modules/@buddi/tool-email/dist/policies/auto.js.map +1 -1
  525. package/node_modules/@buddi/tool-email/dist/ports.d.ts +55 -0
  526. package/node_modules/@buddi/tool-email/dist/ports.d.ts.map +1 -1
  527. package/node_modules/@buddi/tool-email/dist/ports.js.map +1 -1
  528. package/node_modules/@buddi/tool-email/dist/sentinels/suspicious-sender.d.ts.map +1 -1
  529. package/node_modules/@buddi/tool-email/dist/sentinels/suspicious-sender.js +4 -1
  530. package/node_modules/@buddi/tool-email/dist/sentinels/suspicious-sender.js.map +1 -1
  531. package/node_modules/@buddi/tool-email/dist/sentinels/waiting-on-me.d.ts +19 -22
  532. package/node_modules/@buddi/tool-email/dist/sentinels/waiting-on-me.d.ts.map +1 -1
  533. package/node_modules/@buddi/tool-email/dist/sentinels/waiting-on-me.js +44 -63
  534. package/node_modules/@buddi/tool-email/dist/sentinels/waiting-on-me.js.map +1 -1
  535. package/node_modules/@buddi/tool-email/dist/sources/idle.d.ts +10 -2
  536. package/node_modules/@buddi/tool-email/dist/sources/idle.d.ts.map +1 -1
  537. package/node_modules/@buddi/tool-email/dist/sources/idle.js +70 -3
  538. package/node_modules/@buddi/tool-email/dist/sources/idle.js.map +1 -1
  539. package/node_modules/@buddi/tool-email/dist/sources/inbox-poll.d.ts +69 -2
  540. package/node_modules/@buddi/tool-email/dist/sources/inbox-poll.d.ts.map +1 -1
  541. package/node_modules/@buddi/tool-email/dist/sources/inbox-poll.js +143 -13
  542. package/node_modules/@buddi/tool-email/dist/sources/inbox-poll.js.map +1 -1
  543. package/node_modules/@buddi/tool-email/dist/sources/presence.d.ts +47 -0
  544. package/node_modules/@buddi/tool-email/dist/sources/presence.d.ts.map +1 -0
  545. package/node_modules/@buddi/tool-email/dist/sources/presence.js +128 -0
  546. package/node_modules/@buddi/tool-email/dist/sources/presence.js.map +1 -0
  547. package/node_modules/@buddi/tool-email/dist/suspicions-store.d.ts +6 -0
  548. package/node_modules/@buddi/tool-email/dist/suspicions-store.d.ts.map +1 -1
  549. package/node_modules/@buddi/tool-email/dist/suspicions-store.js +16 -1
  550. package/node_modules/@buddi/tool-email/dist/suspicions-store.js.map +1 -1
  551. package/node_modules/@buddi/tool-email/dist/threads.d.ts +19 -2
  552. package/node_modules/@buddi/tool-email/dist/threads.d.ts.map +1 -1
  553. package/node_modules/@buddi/tool-email/dist/threads.js +47 -17
  554. package/node_modules/@buddi/tool-email/dist/threads.js.map +1 -1
  555. package/node_modules/@buddi/tool-email/dist/tools/mailbox.d.ts +3 -0
  556. package/node_modules/@buddi/tool-email/dist/tools/mailbox.d.ts.map +1 -1
  557. package/node_modules/@buddi/tool-email/dist/tools/mailbox.js +9 -4
  558. package/node_modules/@buddi/tool-email/dist/tools/mailbox.js.map +1 -1
  559. package/node_modules/@buddi/tool-email/dist/tools/read.d.ts.map +1 -1
  560. package/node_modules/@buddi/tool-email/dist/tools/read.js +29 -2
  561. package/node_modules/@buddi/tool-email/dist/tools/read.js.map +1 -1
  562. package/node_modules/@buddi/tool-email/dist/tools/threads.d.ts +7 -3
  563. package/node_modules/@buddi/tool-email/dist/tools/threads.d.ts.map +1 -1
  564. package/node_modules/@buddi/tool-email/dist/tools/threads.js +18 -5
  565. package/node_modules/@buddi/tool-email/dist/tools/threads.js.map +1 -1
  566. package/node_modules/@buddi/tool-email/dist/watchers.d.ts +91 -7
  567. package/node_modules/@buddi/tool-email/dist/watchers.d.ts.map +1 -1
  568. package/node_modules/@buddi/tool-email/dist/watchers.js +164 -1
  569. package/node_modules/@buddi/tool-email/dist/watchers.js.map +1 -1
  570. package/node_modules/@buddi/tool-email/dist/widgets.d.ts +14 -0
  571. package/node_modules/@buddi/tool-email/dist/widgets.d.ts.map +1 -0
  572. package/node_modules/@buddi/tool-email/dist/widgets.js +51 -0
  573. package/node_modules/@buddi/tool-email/dist/widgets.js.map +1 -0
  574. package/node_modules/@buddi/tool-email/migrations/020_mailbox_presence.sql +44 -0
  575. package/node_modules/@buddi/tool-email/migrations/021_learned_line.sql +9 -0
  576. package/node_modules/@buddi/tool-email/migrations/022_bulk_checked.sql +13 -0
  577. package/node_modules/@buddi/tool-email/migrations/023_attention.sql +100 -0
  578. package/node_modules/@buddi/tool-email/migrations/024_auth_domain.sql +9 -0
  579. package/node_modules/@buddi/tool-email/migrations/025_thread_ignore.sql +77 -0
  580. package/node_modules/@buddi/tool-email/package.json +1 -1
  581. package/node_modules/@buddi/tool-host/dist/.tsbuildinfo +1 -1
  582. package/node_modules/@buddi/tool-mcp/dist/.tsbuildinfo +1 -1
  583. package/node_modules/@buddi/tool-memory/dist/.tsbuildinfo +1 -1
  584. package/node_modules/@buddi/tool-memory/dist/admin.d.ts +9 -0
  585. package/node_modules/@buddi/tool-memory/dist/admin.d.ts.map +1 -1
  586. package/node_modules/@buddi/tool-memory/dist/admin.js +11 -0
  587. package/node_modules/@buddi/tool-memory/dist/admin.js.map +1 -1
  588. package/node_modules/@buddi/tool-web/dist/.tsbuildinfo +1 -1
  589. package/node_modules/ip-address/README.md +34 -34
  590. package/node_modules/ip-address/dist/ipv4.js +7 -0
  591. package/node_modules/ip-address/dist/ipv4.js.map +1 -1
  592. package/node_modules/ip-address/package.json +1 -1
  593. package/package.json +2 -2
  594. package/packages/cli/dist/.tsbuildinfo +1 -1
  595. package/packages/cli/dist/args.d.ts +19 -3
  596. package/packages/cli/dist/args.d.ts.map +1 -1
  597. package/packages/cli/dist/args.js +19 -5
  598. package/packages/cli/dist/args.js.map +1 -1
  599. package/packages/cli/dist/commands.d.ts.map +1 -1
  600. package/packages/cli/dist/commands.js +80 -8
  601. package/packages/cli/dist/commands.js.map +1 -1
  602. package/packages/cli/dist/dashboard-cmd.d.ts +3 -0
  603. package/packages/cli/dist/dashboard-cmd.d.ts.map +1 -1
  604. package/packages/cli/dist/dashboard-cmd.js +63 -0
  605. package/packages/cli/dist/dashboard-cmd.js.map +1 -1
  606. package/packages/cli/dist/doctor-probes.d.ts.map +1 -1
  607. package/packages/cli/dist/doctor-probes.js +11 -4
  608. package/packages/cli/dist/doctor-probes.js.map +1 -1
  609. package/packages/cli/dist/doctor.d.ts +1 -1
  610. package/packages/cli/dist/doctor.d.ts.map +1 -1
  611. package/packages/cli/dist/jobs-cmd.d.ts +4 -0
  612. package/packages/cli/dist/jobs-cmd.d.ts.map +1 -1
  613. package/packages/cli/dist/jobs-cmd.js +53 -4
  614. package/packages/cli/dist/jobs-cmd.js.map +1 -1
  615. package/packages/cli/dist/main.d.ts.map +1 -1
  616. package/packages/cli/dist/main.js +27 -2
  617. package/packages/cli/dist/main.js.map +1 -1
  618. package/packages/cli/dist/mcp/gateway-client.d.ts +19 -17
  619. package/packages/cli/dist/mcp/gateway-client.d.ts.map +1 -1
  620. package/packages/cli/dist/mcp/gateway-client.js +128 -29
  621. package/packages/cli/dist/mcp/gateway-client.js.map +1 -1
  622. package/packages/cli/dist/mcp/tools.d.ts +6 -0
  623. package/packages/cli/dist/mcp/tools.d.ts.map +1 -1
  624. package/packages/cli/dist/mcp/tools.js +20 -1
  625. package/packages/cli/dist/mcp/tools.js.map +1 -1
  626. package/packages/cli/dist/telegram-cmd.d.ts.map +1 -1
  627. package/packages/cli/dist/telegram-cmd.js +5 -4
  628. package/packages/cli/dist/telegram-cmd.js.map +1 -1
  629. package/packages/core/dist/.tsbuildinfo +1 -1
  630. package/packages/core/dist/agents/catalog.d.ts.map +1 -1
  631. package/packages/core/dist/agents/catalog.js +7 -6
  632. package/packages/core/dist/agents/catalog.js.map +1 -1
  633. package/packages/core/dist/agents/frontmatter.d.ts +12 -12
  634. package/packages/core/dist/agents/skills.d.ts +2 -2
  635. package/packages/core/dist/clock-widget.d.ts +38 -0
  636. package/packages/core/dist/clock-widget.d.ts.map +1 -0
  637. package/packages/core/dist/clock-widget.js +114 -0
  638. package/packages/core/dist/clock-widget.js.map +1 -0
  639. package/packages/core/dist/failures/owner-message.d.ts +25 -0
  640. package/packages/core/dist/failures/owner-message.d.ts.map +1 -1
  641. package/packages/core/dist/failures/owner-message.js +90 -0
  642. package/packages/core/dist/failures/owner-message.js.map +1 -1
  643. package/packages/core/dist/feedback/index.d.ts +23 -2
  644. package/packages/core/dist/feedback/index.d.ts.map +1 -1
  645. package/packages/core/dist/feedback/index.js +23 -3
  646. package/packages/core/dist/feedback/index.js.map +1 -1
  647. package/packages/core/dist/groups.d.ts +33 -0
  648. package/packages/core/dist/groups.d.ts.map +1 -1
  649. package/packages/core/dist/groups.js +76 -4
  650. package/packages/core/dist/groups.js.map +1 -1
  651. package/packages/core/dist/home.d.ts +5 -5
  652. package/packages/core/dist/host/build.d.ts +19 -1
  653. package/packages/core/dist/host/build.d.ts.map +1 -1
  654. package/packages/core/dist/host/build.js +122 -2
  655. package/packages/core/dist/host/build.js.map +1 -1
  656. package/packages/core/dist/host/types.d.ts +33 -0
  657. package/packages/core/dist/host/types.d.ts.map +1 -1
  658. package/packages/core/dist/index.d.ts +8 -0
  659. package/packages/core/dist/index.d.ts.map +1 -1
  660. package/packages/core/dist/index.js +8 -0
  661. package/packages/core/dist/index.js.map +1 -1
  662. package/packages/core/dist/lock.d.ts +82 -0
  663. package/packages/core/dist/lock.d.ts.map +1 -0
  664. package/packages/core/dist/lock.js +182 -0
  665. package/packages/core/dist/lock.js.map +1 -0
  666. package/packages/core/dist/metrics.d.ts.map +1 -1
  667. package/packages/core/dist/metrics.js +4 -2
  668. package/packages/core/dist/metrics.js.map +1 -1
  669. package/packages/core/dist/onboarding/store.d.ts +5 -0
  670. package/packages/core/dist/onboarding/store.d.ts.map +1 -1
  671. package/packages/core/dist/onboarding/store.js +35 -5
  672. package/packages/core/dist/onboarding/store.js.map +1 -1
  673. package/packages/core/dist/onboarding/types.d.ts +10 -0
  674. package/packages/core/dist/onboarding/types.d.ts.map +1 -1
  675. package/packages/core/dist/onboarding/types.js +2 -0
  676. package/packages/core/dist/onboarding/types.js.map +1 -1
  677. package/packages/core/dist/owner-format.d.ts +14 -0
  678. package/packages/core/dist/owner-format.d.ts.map +1 -0
  679. package/packages/core/dist/owner-format.js +47 -0
  680. package/packages/core/dist/owner-format.js.map +1 -0
  681. package/packages/core/dist/owner-timezone.d.ts +46 -0
  682. package/packages/core/dist/owner-timezone.d.ts.map +1 -0
  683. package/packages/core/dist/owner-timezone.js +43 -0
  684. package/packages/core/dist/owner-timezone.js.map +1 -0
  685. package/packages/core/dist/pages.d.ts +13 -39
  686. package/packages/core/dist/pages.d.ts.map +1 -1
  687. package/packages/core/dist/pages.js +12 -1
  688. package/packages/core/dist/pages.js.map +1 -1
  689. package/packages/core/dist/places.d.ts +110 -0
  690. package/packages/core/dist/places.d.ts.map +1 -0
  691. package/packages/core/dist/places.js +239 -0
  692. package/packages/core/dist/places.js.map +1 -0
  693. package/packages/core/dist/plugin/index.d.ts +9 -2
  694. package/packages/core/dist/plugin/index.d.ts.map +1 -1
  695. package/packages/core/dist/plugin/index.js +3 -0
  696. package/packages/core/dist/plugin/index.js.map +1 -1
  697. package/packages/core/dist/plugin/requires.d.ts +75 -0
  698. package/packages/core/dist/plugin/requires.d.ts.map +1 -0
  699. package/packages/core/dist/plugin/requires.js +77 -0
  700. package/packages/core/dist/plugin/requires.js.map +1 -0
  701. package/packages/core/dist/plugin/uses.d.ts +1 -1
  702. package/packages/core/dist/plugin/uses.d.ts.map +1 -1
  703. package/packages/core/dist/plugin/uses.js +2 -0
  704. package/packages/core/dist/plugin/uses.js.map +1 -1
  705. package/packages/core/dist/plugin/version.d.ts +1 -1
  706. package/packages/core/dist/plugin/version.js +1 -1
  707. package/packages/core/dist/queue/failures.d.ts +84 -0
  708. package/packages/core/dist/queue/failures.d.ts.map +1 -0
  709. package/packages/core/dist/queue/failures.js +195 -0
  710. package/packages/core/dist/queue/failures.js.map +1 -0
  711. package/packages/core/dist/queue/index.d.ts +1 -0
  712. package/packages/core/dist/queue/index.d.ts.map +1 -1
  713. package/packages/core/dist/queue/index.js +1 -0
  714. package/packages/core/dist/queue/index.js.map +1 -1
  715. package/packages/core/dist/queue/jobs.d.ts +39 -3
  716. package/packages/core/dist/queue/jobs.d.ts.map +1 -1
  717. package/packages/core/dist/queue/jobs.js +54 -4
  718. package/packages/core/dist/queue/jobs.js.map +1 -1
  719. package/packages/core/dist/queue/retry-policy.d.ts +5 -0
  720. package/packages/core/dist/queue/retry-policy.d.ts.map +1 -1
  721. package/packages/core/dist/queue/retry-policy.js +19 -2
  722. package/packages/core/dist/queue/retry-policy.js.map +1 -1
  723. package/packages/core/dist/queue/types.d.ts +20 -0
  724. package/packages/core/dist/queue/types.d.ts.map +1 -1
  725. package/packages/core/dist/queue/types.js +17 -0
  726. package/packages/core/dist/queue/types.js.map +1 -1
  727. package/packages/core/dist/registry.d.ts +37 -2
  728. package/packages/core/dist/registry.d.ts.map +1 -1
  729. package/packages/core/dist/registry.js +137 -3
  730. package/packages/core/dist/registry.js.map +1 -1
  731. package/packages/core/dist/scheduler/enqueue.d.ts +71 -0
  732. package/packages/core/dist/scheduler/enqueue.d.ts.map +1 -0
  733. package/packages/core/dist/scheduler/enqueue.js +116 -0
  734. package/packages/core/dist/scheduler/enqueue.js.map +1 -0
  735. package/packages/core/dist/scheduler/index.d.ts +1 -0
  736. package/packages/core/dist/scheduler/index.d.ts.map +1 -1
  737. package/packages/core/dist/scheduler/index.js +1 -0
  738. package/packages/core/dist/scheduler/index.js.map +1 -1
  739. package/packages/core/dist/scheduler/missions.d.ts +15 -0
  740. package/packages/core/dist/scheduler/missions.d.ts.map +1 -1
  741. package/packages/core/dist/scheduler/missions.js +43 -4
  742. package/packages/core/dist/scheduler/missions.js.map +1 -1
  743. package/packages/core/dist/scheduler/types.d.ts +10 -0
  744. package/packages/core/dist/scheduler/types.d.ts.map +1 -1
  745. package/packages/core/dist/scheduler/types.js +3 -0
  746. package/packages/core/dist/scheduler/types.js.map +1 -1
  747. package/packages/core/dist/secrets/settings.d.ts +6 -6
  748. package/packages/core/dist/secrets/settings.d.ts.map +1 -1
  749. package/packages/core/dist/secrets/settings.js +23 -3
  750. package/packages/core/dist/secrets/settings.js.map +1 -1
  751. package/packages/core/dist/semver.d.ts +17 -0
  752. package/packages/core/dist/semver.d.ts.map +1 -1
  753. package/packages/core/dist/semver.js +130 -0
  754. package/packages/core/dist/semver.js.map +1 -1
  755. package/packages/core/dist/sentinels/digest.d.ts +8 -1
  756. package/packages/core/dist/sentinels/digest.d.ts.map +1 -1
  757. package/packages/core/dist/sentinels/digest.js +10 -3
  758. package/packages/core/dist/sentinels/digest.js.map +1 -1
  759. package/packages/core/dist/sentinels/index.d.ts +1 -0
  760. package/packages/core/dist/sentinels/index.d.ts.map +1 -1
  761. package/packages/core/dist/sentinels/index.js +1 -0
  762. package/packages/core/dist/sentinels/index.js.map +1 -1
  763. package/packages/core/dist/sentinels/mutes.d.ts +51 -0
  764. package/packages/core/dist/sentinels/mutes.d.ts.map +1 -0
  765. package/packages/core/dist/sentinels/mutes.js +86 -0
  766. package/packages/core/dist/sentinels/mutes.js.map +1 -0
  767. package/packages/core/dist/sentinels/run.d.ts +20 -5
  768. package/packages/core/dist/sentinels/run.d.ts.map +1 -1
  769. package/packages/core/dist/sentinels/run.js +105 -42
  770. package/packages/core/dist/sentinels/run.js.map +1 -1
  771. package/packages/core/dist/sentinels/types.d.ts +165 -2
  772. package/packages/core/dist/sentinels/types.d.ts.map +1 -1
  773. package/packages/core/dist/sentinels/types.js +126 -2
  774. package/packages/core/dist/sentinels/types.js.map +1 -1
  775. package/packages/core/dist/sources/run.d.ts +8 -0
  776. package/packages/core/dist/sources/run.d.ts.map +1 -1
  777. package/packages/core/dist/sources/run.js +1 -1
  778. package/packages/core/dist/sources/run.js.map +1 -1
  779. package/packages/core/dist/sources/watch.d.ts +3 -0
  780. package/packages/core/dist/sources/watch.d.ts.map +1 -1
  781. package/packages/core/dist/sources/watch.js +1 -1
  782. package/packages/core/dist/sources/watch.js.map +1 -1
  783. package/packages/core/dist/time.d.ts +17 -3
  784. package/packages/core/dist/time.d.ts.map +1 -1
  785. package/packages/core/dist/time.js +27 -3
  786. package/packages/core/dist/time.js.map +1 -1
  787. package/packages/core/dist/tools.d.ts +30 -1
  788. package/packages/core/dist/tools.d.ts.map +1 -1
  789. package/packages/core/dist/tools.js.map +1 -1
  790. package/packages/core/dist/views.d.ts +164 -164
  791. package/packages/core/dist/views.d.ts.map +1 -1
  792. package/packages/core/dist/views.js +5 -0
  793. package/packages/core/dist/views.js.map +1 -1
  794. package/packages/core/dist/widget-settings.d.ts +161 -0
  795. package/packages/core/dist/widget-settings.d.ts.map +1 -0
  796. package/packages/core/dist/widget-settings.js +314 -0
  797. package/packages/core/dist/widget-settings.js.map +1 -0
  798. package/packages/core/dist/widgets.d.ts +206 -0
  799. package/packages/core/dist/widgets.d.ts.map +1 -0
  800. package/packages/core/dist/widgets.js +247 -0
  801. package/packages/core/dist/widgets.js.map +1 -0
  802. package/packages/core/migrations/059_dashboard_lock.sql +33 -0
  803. package/packages/core/migrations/060_owner_places.sql +30 -0
  804. package/packages/core/migrations/061_owner_formats.sql +10 -0
  805. package/packages/core/migrations/062_group_deleted.sql +7 -0
  806. package/packages/core/migrations/063_provider_account_limits.sql +20 -0
  807. package/packages/core/migrations/064_mission_coalesce.sql +12 -0
  808. package/packages/core/migrations/065_api_tokens.sql +28 -0
  809. package/packages/core/migrations/066_alert_decisions.sql +45 -0
  810. package/packages/core/migrations/067_job_acknowledged.sql +21 -0
  811. package/packages/gateway/dist/.tsbuildinfo +1 -1
  812. package/packages/gateway/dist/account-limits.d.ts +45 -0
  813. package/packages/gateway/dist/account-limits.d.ts.map +1 -0
  814. package/packages/gateway/dist/account-limits.js +87 -0
  815. package/packages/gateway/dist/account-limits.js.map +1 -0
  816. package/packages/gateway/dist/accounts-cli.d.ts +88 -0
  817. package/packages/gateway/dist/accounts-cli.d.ts.map +1 -0
  818. package/packages/gateway/dist/accounts-cli.js +216 -0
  819. package/packages/gateway/dist/accounts-cli.js.map +1 -0
  820. package/packages/gateway/dist/agents/canvas.d.ts +20 -20
  821. package/packages/gateway/dist/agents/learning-digest.d.ts +4 -0
  822. package/packages/gateway/dist/agents/learning-digest.d.ts.map +1 -1
  823. package/packages/gateway/dist/agents/learning-digest.js +18 -5
  824. package/packages/gateway/dist/agents/learning-digest.js.map +1 -1
  825. package/packages/gateway/dist/agents/owner-tools.d.ts.map +1 -1
  826. package/packages/gateway/dist/agents/owner-tools.js +3 -2
  827. package/packages/gateway/dist/agents/owner-tools.js.map +1 -1
  828. package/packages/gateway/dist/agents/platform.d.ts +24 -24
  829. package/packages/gateway/dist/api-token-cli.d.ts +17 -0
  830. package/packages/gateway/dist/api-token-cli.d.ts.map +1 -0
  831. package/packages/gateway/dist/api-token-cli.js +108 -0
  832. package/packages/gateway/dist/api-token-cli.js.map +1 -0
  833. package/packages/gateway/dist/bootstrap.d.ts +6 -2
  834. package/packages/gateway/dist/bootstrap.d.ts.map +1 -1
  835. package/packages/gateway/dist/bootstrap.js +25 -7
  836. package/packages/gateway/dist/bootstrap.js.map +1 -1
  837. package/packages/gateway/dist/chat/conversations.d.ts.map +1 -1
  838. package/packages/gateway/dist/chat/conversations.js +8 -2
  839. package/packages/gateway/dist/chat/conversations.js.map +1 -1
  840. package/packages/gateway/dist/chat/session.d.ts +5 -0
  841. package/packages/gateway/dist/chat/session.d.ts.map +1 -1
  842. package/packages/gateway/dist/chat/session.js +11 -1
  843. package/packages/gateway/dist/chat/session.js.map +1 -1
  844. package/packages/gateway/dist/cli.d.ts.map +1 -1
  845. package/packages/gateway/dist/cli.js +14 -3
  846. package/packages/gateway/dist/cli.js.map +1 -1
  847. package/packages/gateway/dist/index.d.ts +3 -0
  848. package/packages/gateway/dist/index.d.ts.map +1 -1
  849. package/packages/gateway/dist/index.js +3 -0
  850. package/packages/gateway/dist/index.js.map +1 -1
  851. package/packages/gateway/dist/missions/dead-letter.d.ts +2 -1
  852. package/packages/gateway/dist/missions/dead-letter.d.ts.map +1 -1
  853. package/packages/gateway/dist/missions/dead-letter.js +19 -5
  854. package/packages/gateway/dist/missions/dead-letter.js.map +1 -1
  855. package/packages/gateway/dist/missions/defaults.d.ts +6 -0
  856. package/packages/gateway/dist/missions/defaults.d.ts.map +1 -1
  857. package/packages/gateway/dist/missions/defaults.js +10 -2
  858. package/packages/gateway/dist/missions/defaults.js.map +1 -1
  859. package/packages/gateway/dist/missions/execute.d.ts.map +1 -1
  860. package/packages/gateway/dist/missions/execute.js +49 -9
  861. package/packages/gateway/dist/missions/execute.js.map +1 -1
  862. package/packages/gateway/dist/missions/goals.d.ts +12 -1
  863. package/packages/gateway/dist/missions/goals.d.ts.map +1 -1
  864. package/packages/gateway/dist/missions/goals.js +21 -1
  865. package/packages/gateway/dist/missions/goals.js.map +1 -1
  866. package/packages/gateway/dist/missions/inline.js +1 -1
  867. package/packages/gateway/dist/missions/inline.js.map +1 -1
  868. package/packages/gateway/dist/missions/sentinel-wake.d.ts +14 -0
  869. package/packages/gateway/dist/missions/sentinel-wake.d.ts.map +1 -1
  870. package/packages/gateway/dist/missions/sentinel-wake.js +41 -2
  871. package/packages/gateway/dist/missions/sentinel-wake.js.map +1 -1
  872. package/packages/gateway/dist/missions-cli.d.ts.map +1 -1
  873. package/packages/gateway/dist/missions-cli.js +5 -5
  874. package/packages/gateway/dist/missions-cli.js.map +1 -1
  875. package/packages/gateway/dist/nudges-cli.js +2 -2
  876. package/packages/gateway/dist/nudges-cli.js.map +1 -1
  877. package/packages/gateway/dist/owner-seed.js +2 -2
  878. package/packages/gateway/dist/owner-seed.js.map +1 -1
  879. package/packages/gateway/dist/plugins/live.d.ts +8 -1
  880. package/packages/gateway/dist/plugins/live.d.ts.map +1 -1
  881. package/packages/gateway/dist/plugins/live.js +25 -7
  882. package/packages/gateway/dist/plugins/live.js.map +1 -1
  883. package/packages/gateway/dist/plugins/load.d.ts +55 -0
  884. package/packages/gateway/dist/plugins/load.d.ts.map +1 -1
  885. package/packages/gateway/dist/plugins/load.js +100 -4
  886. package/packages/gateway/dist/plugins/load.js.map +1 -1
  887. package/packages/gateway/dist/plugins/requires.d.ts +79 -0
  888. package/packages/gateway/dist/plugins/requires.d.ts.map +1 -0
  889. package/packages/gateway/dist/plugins/requires.js +178 -0
  890. package/packages/gateway/dist/plugins/requires.js.map +1 -0
  891. package/packages/gateway/dist/plugins/stage.d.ts +6 -0
  892. package/packages/gateway/dist/plugins/stage.d.ts.map +1 -1
  893. package/packages/gateway/dist/plugins/stage.js +6 -1
  894. package/packages/gateway/dist/plugins/stage.js.map +1 -1
  895. package/packages/gateway/dist/plugins/update.d.ts +21 -0
  896. package/packages/gateway/dist/plugins/update.d.ts.map +1 -1
  897. package/packages/gateway/dist/plugins/update.js +16 -0
  898. package/packages/gateway/dist/plugins/update.js.map +1 -1
  899. package/packages/gateway/dist/plugins-cli.d.ts +1 -1
  900. package/packages/gateway/dist/plugins-cli.d.ts.map +1 -1
  901. package/packages/gateway/dist/plugins-cli.js +6 -2
  902. package/packages/gateway/dist/plugins-cli.js.map +1 -1
  903. package/packages/gateway/dist/provider-accounts.d.ts +4 -0
  904. package/packages/gateway/dist/provider-accounts.d.ts.map +1 -1
  905. package/packages/gateway/dist/provider-accounts.js +68 -10
  906. package/packages/gateway/dist/provider-accounts.js.map +1 -1
  907. package/packages/gateway/dist/provider-diagnostics.d.ts.map +1 -1
  908. package/packages/gateway/dist/provider-diagnostics.js +9 -0
  909. package/packages/gateway/dist/provider-diagnostics.js.map +1 -1
  910. package/packages/gateway/dist/reminders-cli.js +2 -2
  911. package/packages/gateway/dist/reminders-cli.js.map +1 -1
  912. package/packages/gateway/dist/serve.d.ts +2 -0
  913. package/packages/gateway/dist/serve.d.ts.map +1 -1
  914. package/packages/gateway/dist/serve.js +66 -8
  915. package/packages/gateway/dist/serve.js.map +1 -1
  916. package/packages/gateway/dist/surfaces/failure.d.ts.map +1 -1
  917. package/packages/gateway/dist/surfaces/failure.js +9 -1
  918. package/packages/gateway/dist/surfaces/failure.js.map +1 -1
  919. package/packages/gateway/dist/surfaces/offered-actions.d.ts +17 -0
  920. package/packages/gateway/dist/surfaces/offered-actions.d.ts.map +1 -1
  921. package/packages/gateway/dist/surfaces/offered-actions.js +27 -0
  922. package/packages/gateway/dist/surfaces/offered-actions.js.map +1 -1
  923. package/packages/gateway/dist/system-context.d.ts +18 -0
  924. package/packages/gateway/dist/system-context.d.ts.map +1 -1
  925. package/packages/gateway/dist/system-context.js +46 -4
  926. package/packages/gateway/dist/system-context.js.map +1 -1
  927. package/packages/gateway/dist/telegram/main.js +3 -3
  928. package/packages/gateway/dist/telegram/main.js.map +1 -1
  929. package/packages/gateway/dist/telegram/outbound.d.ts +1 -1
  930. package/packages/gateway/dist/telegram/outbound.d.ts.map +1 -1
  931. package/packages/gateway/dist/telegram/outbound.js +7 -2
  932. package/packages/gateway/dist/telegram/outbound.js.map +1 -1
  933. package/packages/gateway/dist/telegram/reactions.d.ts.map +1 -1
  934. package/packages/gateway/dist/telegram/reactions.js +12 -2
  935. package/packages/gateway/dist/telegram/reactions.js.map +1 -1
  936. package/packages/gateway/dist/telegram/surface.d.ts +4 -1
  937. package/packages/gateway/dist/telegram/surface.d.ts.map +1 -1
  938. package/packages/gateway/dist/telegram/surface.js +13 -3
  939. package/packages/gateway/dist/telegram/surface.js.map +1 -1
  940. package/packages/gateway/dist/tips/engine.d.ts +2 -0
  941. package/packages/gateway/dist/tips/engine.d.ts.map +1 -1
  942. package/packages/gateway/dist/tips/engine.js +8 -5
  943. package/packages/gateway/dist/tips/engine.js.map +1 -1
  944. package/packages/gateway/dist/tips/facts.d.ts +23 -0
  945. package/packages/gateway/dist/tips/facts.d.ts.map +1 -1
  946. package/packages/gateway/dist/tips/facts.js +19 -0
  947. package/packages/gateway/dist/tips/facts.js.map +1 -1
  948. package/packages/gateway/dist/tips/route.js +2 -2
  949. package/packages/gateway/dist/tips/route.js.map +1 -1
  950. package/packages/gateway/dist/tips/rules.d.ts +3 -2
  951. package/packages/gateway/dist/tips/rules.d.ts.map +1 -1
  952. package/packages/gateway/dist/tips/rules.js +26 -0
  953. package/packages/gateway/dist/tips/rules.js.map +1 -1
  954. package/packages/gateway/dist/web/alerts.d.ts +179 -0
  955. package/packages/gateway/dist/web/alerts.d.ts.map +1 -0
  956. package/packages/gateway/dist/web/alerts.js +363 -0
  957. package/packages/gateway/dist/web/alerts.js.map +1 -0
  958. package/packages/gateway/dist/web/api-routes.d.ts +103 -0
  959. package/packages/gateway/dist/web/api-routes.d.ts.map +1 -0
  960. package/packages/gateway/dist/web/api-routes.js +1239 -0
  961. package/packages/gateway/dist/web/api-routes.js.map +1 -0
  962. package/packages/gateway/dist/web/api-scan.d.ts +17 -0
  963. package/packages/gateway/dist/web/api-scan.d.ts.map +1 -0
  964. package/packages/gateway/dist/web/api-scan.js +206 -0
  965. package/packages/gateway/dist/web/api-scan.js.map +1 -0
  966. package/packages/gateway/dist/web/api-tokens.d.ts +58 -0
  967. package/packages/gateway/dist/web/api-tokens.d.ts.map +1 -0
  968. package/packages/gateway/dist/web/api-tokens.js +136 -0
  969. package/packages/gateway/dist/web/api-tokens.js.map +1 -0
  970. package/packages/gateway/dist/web/backups.js +2 -2
  971. package/packages/gateway/dist/web/backups.js.map +1 -1
  972. package/packages/gateway/dist/web/chat.d.ts +1 -0
  973. package/packages/gateway/dist/web/chat.d.ts.map +1 -1
  974. package/packages/gateway/dist/web/chat.js +4 -3
  975. package/packages/gateway/dist/web/chat.js.map +1 -1
  976. package/packages/gateway/dist/web/group-lifecycle.d.ts +18 -0
  977. package/packages/gateway/dist/web/group-lifecycle.d.ts.map +1 -0
  978. package/packages/gateway/dist/web/group-lifecycle.js +46 -0
  979. package/packages/gateway/dist/web/group-lifecycle.js.map +1 -0
  980. package/packages/gateway/dist/web/lock-image.d.ts +37 -0
  981. package/packages/gateway/dist/web/lock-image.d.ts.map +1 -0
  982. package/packages/gateway/dist/web/lock-image.js +253 -0
  983. package/packages/gateway/dist/web/lock-image.js.map +1 -0
  984. package/packages/gateway/dist/web/lock.d.ts +165 -0
  985. package/packages/gateway/dist/web/lock.d.ts.map +1 -0
  986. package/packages/gateway/dist/web/lock.js +478 -0
  987. package/packages/gateway/dist/web/lock.js.map +1 -0
  988. package/packages/gateway/dist/web/pages.d.ts +1 -0
  989. package/packages/gateway/dist/web/pages.d.ts.map +1 -1
  990. package/packages/gateway/dist/web/pages.js +12 -1
  991. package/packages/gateway/dist/web/pages.js.map +1 -1
  992. package/packages/gateway/dist/web/places.d.ts +27 -0
  993. package/packages/gateway/dist/web/places.d.ts.map +1 -0
  994. package/packages/gateway/dist/web/places.js +90 -0
  995. package/packages/gateway/dist/web/places.js.map +1 -0
  996. package/packages/gateway/dist/web/plugins.d.ts +28 -0
  997. package/packages/gateway/dist/web/plugins.d.ts.map +1 -1
  998. package/packages/gateway/dist/web/plugins.js +83 -9
  999. package/packages/gateway/dist/web/plugins.js.map +1 -1
  1000. package/packages/gateway/dist/web/read.d.ts +52 -26
  1001. package/packages/gateway/dist/web/read.d.ts.map +1 -1
  1002. package/packages/gateway/dist/web/read.js +52 -36
  1003. package/packages/gateway/dist/web/read.js.map +1 -1
  1004. package/packages/gateway/dist/web/secrets.d.ts +61 -1
  1005. package/packages/gateway/dist/web/secrets.d.ts.map +1 -1
  1006. package/packages/gateway/dist/web/secrets.js +111 -3
  1007. package/packages/gateway/dist/web/secrets.js.map +1 -1
  1008. package/packages/gateway/dist/web/server.d.ts +9 -0
  1009. package/packages/gateway/dist/web/server.d.ts.map +1 -1
  1010. package/packages/gateway/dist/web/server.js +531 -46
  1011. package/packages/gateway/dist/web/server.js.map +1 -1
  1012. package/packages/gateway/dist/web/sessions.d.ts +43 -2
  1013. package/packages/gateway/dist/web/sessions.d.ts.map +1 -1
  1014. package/packages/gateway/dist/web/sessions.js +67 -3
  1015. package/packages/gateway/dist/web/sessions.js.map +1 -1
  1016. package/packages/gateway/dist/web/signed-out.d.ts +17 -18
  1017. package/packages/gateway/dist/web/signed-out.d.ts.map +1 -1
  1018. package/packages/gateway/dist/web/signed-out.js +135 -33
  1019. package/packages/gateway/dist/web/signed-out.js.map +1 -1
  1020. package/packages/gateway/dist/web/stream.d.ts.map +1 -1
  1021. package/packages/gateway/dist/web/stream.js +14 -0
  1022. package/packages/gateway/dist/web/stream.js.map +1 -1
  1023. package/packages/gateway/dist/web/tailscale.d.ts +33 -4
  1024. package/packages/gateway/dist/web/tailscale.d.ts.map +1 -1
  1025. package/packages/gateway/dist/web/tailscale.js +76 -16
  1026. package/packages/gateway/dist/web/tailscale.js.map +1 -1
  1027. package/packages/gateway/dist/web/widgets.d.ts +131 -0
  1028. package/packages/gateway/dist/web/widgets.d.ts.map +1 -0
  1029. package/packages/gateway/dist/web/widgets.js +478 -0
  1030. package/packages/gateway/dist/web/widgets.js.map +1 -0
  1031. package/packages/gateway/dist/web/write.d.ts +23 -0
  1032. package/packages/gateway/dist/web/write.d.ts.map +1 -1
  1033. package/packages/gateway/dist/web/write.js +46 -1
  1034. package/packages/gateway/dist/web/write.js.map +1 -1
  1035. package/packages/install/dist/.tsbuildinfo +1 -1
  1036. package/packages/runtime/dist/.tsbuildinfo +1 -1
  1037. package/packages/runtime/dist/anthropic.d.ts +15 -0
  1038. package/packages/runtime/dist/anthropic.d.ts.map +1 -1
  1039. package/packages/runtime/dist/anthropic.js +26 -9
  1040. package/packages/runtime/dist/anthropic.js.map +1 -1
  1041. package/packages/runtime/dist/codex-direct.d.ts +2 -1
  1042. package/packages/runtime/dist/codex-direct.d.ts.map +1 -1
  1043. package/packages/runtime/dist/codex-direct.js +13 -6
  1044. package/packages/runtime/dist/codex-direct.js.map +1 -1
  1045. package/packages/runtime/dist/index.d.ts +1 -0
  1046. package/packages/runtime/dist/index.d.ts.map +1 -1
  1047. package/packages/runtime/dist/index.js +1 -0
  1048. package/packages/runtime/dist/index.js.map +1 -1
  1049. package/packages/runtime/dist/loop.d.ts +2 -0
  1050. package/packages/runtime/dist/loop.d.ts.map +1 -1
  1051. package/packages/runtime/dist/loop.js +22 -0
  1052. package/packages/runtime/dist/loop.js.map +1 -1
  1053. package/packages/runtime/dist/openai.d.ts +34 -1
  1054. package/packages/runtime/dist/openai.d.ts.map +1 -1
  1055. package/packages/runtime/dist/openai.js +85 -19
  1056. package/packages/runtime/dist/openai.js.map +1 -1
  1057. package/packages/runtime/dist/rate-limit.d.ts +91 -0
  1058. package/packages/runtime/dist/rate-limit.d.ts.map +1 -0
  1059. package/packages/runtime/dist/rate-limit.js +291 -0
  1060. package/packages/runtime/dist/rate-limit.js.map +1 -0
  1061. package/packages/runtime/dist/retry.d.ts +40 -0
  1062. package/packages/runtime/dist/retry.d.ts.map +1 -1
  1063. package/packages/runtime/dist/retry.js +42 -8
  1064. package/packages/runtime/dist/retry.js.map +1 -1
  1065. package/packages/tools/artifacts/dist/.tsbuildinfo +1 -1
  1066. package/packages/tools/browser/dist/.tsbuildinfo +1 -1
  1067. package/packages/tools/email/dist/.tsbuildinfo +1 -1
  1068. package/packages/tools/email/dist/agent.js +1 -1
  1069. package/packages/tools/email/dist/folders.d.ts +14 -0
  1070. package/packages/tools/email/dist/folders.d.ts.map +1 -1
  1071. package/packages/tools/email/dist/folders.js +23 -0
  1072. package/packages/tools/email/dist/folders.js.map +1 -1
  1073. package/packages/tools/email/dist/imap/fake.d.ts +55 -0
  1074. package/packages/tools/email/dist/imap/fake.d.ts.map +1 -1
  1075. package/packages/tools/email/dist/imap/fake.js +163 -4
  1076. package/packages/tools/email/dist/imap/fake.js.map +1 -1
  1077. package/packages/tools/email/dist/imap/imapflow-client.d.ts +8 -0
  1078. package/packages/tools/email/dist/imap/imapflow-client.d.ts.map +1 -1
  1079. package/packages/tools/email/dist/imap/imapflow-client.js +124 -4
  1080. package/packages/tools/email/dist/imap/imapflow-client.js.map +1 -1
  1081. package/packages/tools/email/dist/index.d.ts.map +1 -1
  1082. package/packages/tools/email/dist/index.js +3 -0
  1083. package/packages/tools/email/dist/index.js.map +1 -1
  1084. package/packages/tools/email/dist/mail.d.ts +48 -0
  1085. package/packages/tools/email/dist/mail.d.ts.map +1 -1
  1086. package/packages/tools/email/dist/mail.js +119 -0
  1087. package/packages/tools/email/dist/mail.js.map +1 -1
  1088. package/packages/tools/email/dist/mailbox/actions.d.ts +90 -5
  1089. package/packages/tools/email/dist/mailbox/actions.d.ts.map +1 -1
  1090. package/packages/tools/email/dist/mailbox/actions.js +643 -200
  1091. package/packages/tools/email/dist/mailbox/actions.js.map +1 -1
  1092. package/packages/tools/email/dist/mailbox/select.d.ts +6 -0
  1093. package/packages/tools/email/dist/mailbox/select.d.ts.map +1 -1
  1094. package/packages/tools/email/dist/mailbox/select.js +20 -2
  1095. package/packages/tools/email/dist/mailbox/select.js.map +1 -1
  1096. package/packages/tools/email/dist/metrics.d.ts +8 -9
  1097. package/packages/tools/email/dist/metrics.d.ts.map +1 -1
  1098. package/packages/tools/email/dist/metrics.js +8 -9
  1099. package/packages/tools/email/dist/metrics.js.map +1 -1
  1100. package/packages/tools/email/dist/needs-you.d.ts +58 -0
  1101. package/packages/tools/email/dist/needs-you.d.ts.map +1 -0
  1102. package/packages/tools/email/dist/needs-you.js +97 -0
  1103. package/packages/tools/email/dist/needs-you.js.map +1 -0
  1104. package/packages/tools/email/dist/pages/descriptors.d.ts.map +1 -1
  1105. package/packages/tools/email/dist/pages/descriptors.js +126 -80
  1106. package/packages/tools/email/dist/pages/descriptors.js.map +1 -1
  1107. package/packages/tools/email/dist/pages/drafts-tools.d.ts +2 -2
  1108. package/packages/tools/email/dist/pages/queries.d.ts +14 -0
  1109. package/packages/tools/email/dist/pages/queries.d.ts.map +1 -1
  1110. package/packages/tools/email/dist/pages/queries.js +65 -7
  1111. package/packages/tools/email/dist/pages/queries.js.map +1 -1
  1112. package/packages/tools/email/dist/policies/auto.d.ts +9 -9
  1113. package/packages/tools/email/dist/policies/auto.d.ts.map +1 -1
  1114. package/packages/tools/email/dist/policies/auto.js +79 -24
  1115. package/packages/tools/email/dist/policies/auto.js.map +1 -1
  1116. package/packages/tools/email/dist/ports.d.ts +55 -0
  1117. package/packages/tools/email/dist/ports.d.ts.map +1 -1
  1118. package/packages/tools/email/dist/ports.js.map +1 -1
  1119. package/packages/tools/email/dist/sentinels/suspicious-sender.d.ts.map +1 -1
  1120. package/packages/tools/email/dist/sentinels/suspicious-sender.js +4 -1
  1121. package/packages/tools/email/dist/sentinels/suspicious-sender.js.map +1 -1
  1122. package/packages/tools/email/dist/sentinels/waiting-on-me.d.ts +19 -22
  1123. package/packages/tools/email/dist/sentinels/waiting-on-me.d.ts.map +1 -1
  1124. package/packages/tools/email/dist/sentinels/waiting-on-me.js +44 -63
  1125. package/packages/tools/email/dist/sentinels/waiting-on-me.js.map +1 -1
  1126. package/packages/tools/email/dist/sources/idle.d.ts +10 -2
  1127. package/packages/tools/email/dist/sources/idle.d.ts.map +1 -1
  1128. package/packages/tools/email/dist/sources/idle.js +70 -3
  1129. package/packages/tools/email/dist/sources/idle.js.map +1 -1
  1130. package/packages/tools/email/dist/sources/inbox-poll.d.ts +69 -2
  1131. package/packages/tools/email/dist/sources/inbox-poll.d.ts.map +1 -1
  1132. package/packages/tools/email/dist/sources/inbox-poll.js +143 -13
  1133. package/packages/tools/email/dist/sources/inbox-poll.js.map +1 -1
  1134. package/packages/tools/email/dist/sources/presence.d.ts +47 -0
  1135. package/packages/tools/email/dist/sources/presence.d.ts.map +1 -0
  1136. package/packages/tools/email/dist/sources/presence.js +128 -0
  1137. package/packages/tools/email/dist/sources/presence.js.map +1 -0
  1138. package/packages/tools/email/dist/suspicions-store.d.ts +6 -0
  1139. package/packages/tools/email/dist/suspicions-store.d.ts.map +1 -1
  1140. package/packages/tools/email/dist/suspicions-store.js +16 -1
  1141. package/packages/tools/email/dist/suspicions-store.js.map +1 -1
  1142. package/packages/tools/email/dist/threads.d.ts +19 -2
  1143. package/packages/tools/email/dist/threads.d.ts.map +1 -1
  1144. package/packages/tools/email/dist/threads.js +47 -17
  1145. package/packages/tools/email/dist/threads.js.map +1 -1
  1146. package/packages/tools/email/dist/tools/mailbox.d.ts +3 -0
  1147. package/packages/tools/email/dist/tools/mailbox.d.ts.map +1 -1
  1148. package/packages/tools/email/dist/tools/mailbox.js +9 -4
  1149. package/packages/tools/email/dist/tools/mailbox.js.map +1 -1
  1150. package/packages/tools/email/dist/tools/read.d.ts.map +1 -1
  1151. package/packages/tools/email/dist/tools/read.js +29 -2
  1152. package/packages/tools/email/dist/tools/read.js.map +1 -1
  1153. package/packages/tools/email/dist/tools/threads.d.ts +7 -3
  1154. package/packages/tools/email/dist/tools/threads.d.ts.map +1 -1
  1155. package/packages/tools/email/dist/tools/threads.js +18 -5
  1156. package/packages/tools/email/dist/tools/threads.js.map +1 -1
  1157. package/packages/tools/email/dist/watchers.d.ts +91 -7
  1158. package/packages/tools/email/dist/watchers.d.ts.map +1 -1
  1159. package/packages/tools/email/dist/watchers.js +164 -1
  1160. package/packages/tools/email/dist/watchers.js.map +1 -1
  1161. package/packages/tools/email/dist/widgets.d.ts +14 -0
  1162. package/packages/tools/email/dist/widgets.d.ts.map +1 -0
  1163. package/packages/tools/email/dist/widgets.js +51 -0
  1164. package/packages/tools/email/dist/widgets.js.map +1 -0
  1165. package/packages/tools/email/migrations/020_mailbox_presence.sql +44 -0
  1166. package/packages/tools/email/migrations/021_learned_line.sql +9 -0
  1167. package/packages/tools/email/migrations/022_bulk_checked.sql +13 -0
  1168. package/packages/tools/email/migrations/023_attention.sql +100 -0
  1169. package/packages/tools/email/migrations/024_auth_domain.sql +9 -0
  1170. package/packages/tools/email/migrations/025_thread_ignore.sql +77 -0
  1171. package/packages/tools/email/package.json +1 -1
  1172. package/packages/tools/host/dist/.tsbuildinfo +1 -1
  1173. package/packages/tools/mcp/dist/.tsbuildinfo +1 -1
  1174. package/packages/tools/memory/dist/.tsbuildinfo +1 -1
  1175. package/packages/tools/memory/dist/admin.d.ts +9 -0
  1176. package/packages/tools/memory/dist/admin.d.ts.map +1 -1
  1177. package/packages/tools/memory/dist/admin.js +11 -0
  1178. package/packages/tools/memory/dist/admin.js.map +1 -1
  1179. package/packages/tools/web/dist/.tsbuildinfo +1 -1
  1180. package/packages/web/dist/assets/earth-2560-Ce3xs8Cb.webp +0 -0
  1181. package/packages/web/dist/assets/earth-phone-BqC7cDhk.webp +0 -0
  1182. package/packages/web/dist/assets/index-WS4UjGsy.js +129 -0
  1183. package/packages/web/dist/assets/index-Zrt_o2UG.css +1 -0
  1184. package/packages/web/dist/assets/{lottie_light-CSeMXM8D.js → lottie_light-Ls7i1ATS.js} +1 -1
  1185. package/packages/web/dist/build.json +1 -1
  1186. package/packages/web/dist/index.html +2 -2
  1187. package/packages/web/dist/precache.json +4 -4
  1188. package/packages/web/dist/sw.js +3 -2
  1189. package/packages/web/dist/assets/index-CKuhKCWw.js +0 -131
  1190. package/packages/web/dist/assets/index-DsK8UWCJ.css +0 -1
@@ -41,6 +41,7 @@
41
41
  * No `Access-Control-*` header is ever emitted, and `OPTIONS` is refused: a
42
42
  * page on another origin gets no preflight and no permission.
43
43
  */
44
+ import { runningAgentRuns } from '@buddi/runtime';
44
45
  import { agentMuteRoute, focusRoute, listNotificationsRoute, markSeenRoute, notificationSettingsRoute, presenceRoute, testChannelRoute } from './notifications.js';
45
46
  import { catalogSkillLookup, discardProposalFromWeb, keepAllProposalsFromWeb, keepProposalFromWeb, readProposals, registryChangeLookup } from './proposals.js';
46
47
  import { latestDigest, readDigestSchedule, setDigestSchedule } from '../agents/learning-digest.js';
@@ -60,18 +61,20 @@ import { mlxhBaseUrl, probeMlxh } from '../mlxh.js';
60
61
  import { OnboardingRefusal, WEB_ONBOARDING_STEPS, WEB_ONBOARDING_SURFACE, claimOpeningTurn, createFirstAgent, probeOllama, readOnboarding, rebindBrain, updateFirstAgent, withFirstRunFacts, readFirstAgentPersona } from './onboarding.js';
61
62
  import { TakeOnRefusal, readTakeOn, startTakeOn } from './take-on.js';
62
63
  import { TelegramWebError, saveTelegramToken, telegramBot, telegramDevices, telegramPairing, telegramStatus, unpairTelegramDevice, } from './telegram.js';
63
- import { PAGE_ROUTE, sendPageFile, actOnPage, listPageDescriptors, runPageQuery, } from './pages.js';
64
+ import { PAGE_ROUTE, sendPageFile, actOnPage, actRateLimited, listPageDescriptors, runPageQuery, } from './pages.js';
64
65
  import { listSecrets, secretUses, secretsAct } from './secrets.js';
65
66
  import { sayRoute, transcribeRoute } from './speech.js';
66
67
  import { createServer } from 'node:http';
67
- import { getAction, idleRolloverMs, inRecovery, listPendingActions, isJobState, parseAgentFile, setSentinelEnabled, snoozeFinding } from '@buddi/core';
68
+ import { getAction, idleRolloverMs, inRecovery, listMissions, listPendingActions, isJobState, parseAgentFile, setSentinelEnabled, snoozeFinding, snoozeFindings, unmuteFindings } from '@buddi/core';
69
+ import { actOnAlerts, askPrompt, findingsForAsk, muteAlert } from './alerts.js';
68
70
  import { connectionsOf } from '@buddi/tool-mcp';
69
71
  import { CONNECTIONS_CALLBACK_PATH, connectionsRoute } from './connections.js';
70
72
  import { browserHost } from '../browser-host.js';
71
73
  import { hostService } from '@buddi/tool-host';
72
- import { listToolPermissions, revokeToolPermission, getArtifact, readArtifactBytes, artifactBytesExist, discardUnreferencedUpload, listLibrary, getLibraryEntry, decodeCursor, filterKey, textPreviewable, readArtifactPrefix, FILE_FAMILIES, LIBRARY_PAGE_MAX, getOwnerProfile, setOwnerProfile, isKnownTimezone, listGroups, getGroup, createGroup, updateGroup, archiveGroup, GroupRefusal, createGroupConversation, listGroupConversations, latestGroupConversation, openGroupRequest, conversationGroup } from '@buddi/core';
74
+ import { listToolPermissions, revokeToolPermission, getArtifact, readArtifactBytes, artifactBytesExist, discardUnreferencedUpload, listLibrary, getLibraryEntry, decodeCursor, filterKey, textPreviewable, readArtifactPrefix, FILE_FAMILIES, LIBRARY_PAGE_MAX, getOwnerProfile, saveOwnerProfile, isKnownTimezone, listGroups, getGroup, createGroup, updateGroup, archiveGroup, deleteGroup, restoreGroup, clearGroupHistory, groupHistorySize, GROUP_UNDO_MS, GroupRefusal, createGroupConversation, listGroupConversations, latestGroupConversation, openGroupRequest, conversationGroup } from '@buddi/core';
73
75
  import { beginOnboarding, completeOnboarding, markStepDone, setOnboardingDetails, skipOnboarding, readWebSetting, writeWebSetting } from '@buddi/core';
74
76
  import { listMemory, setPreference, forgetPreference, updateNote, forgetNote } from '@buddi/tool-memory';
77
+ import { purgeGroups, stopGroupWork } from './group-lifecycle.js';
75
78
  import { engineChangeFromBody, readAgentEngines, readDefaultAgent, readEngineOptions, setAgentEngineFromWeb, setDefaultAgentFromWeb, } from './agents.js';
76
79
  import { writeDefaultAgentRecord } from '../agents/default-agent.js';
77
80
  import { ownerEditableInput, updateAgentFromOwner, PlatformRefusal } from '../agents/platform.js';
@@ -86,12 +89,12 @@ import { ATTACHMENTS_UNAVAILABLE, CHAT_CONVERSATIONS_LIMIT, CHAT_UNAVAILABLE, WE
86
89
  import { readAgentAttention, streamAttention } from './attention.js';
87
90
  import { PreviewApp, PreviewTickets, parsePreviewApiPath } from './preview.js';
88
91
  import { allowedOrigins, isLoopback, webAssetsDir, webUrl } from './config.js';
89
- import { TAILSCALE_SETTING_KEY, daemonWhois, isLoginRefusal, plausibleLogin, proxiedThroughTailscale, sameLogin, tailscaleIdentity, tailscaleRefusalReason, tailscaleSelf, toTailscaleSetting, } from './tailscale.js';
92
+ import { TAILSCALE_SETTING_KEY, daemonWhois, isLoginRefusal, isUnansweredRefusal, plausibleLogin, proxiedThroughTailscale, sameLogin, tailscaleIdentity, tailscaleRefusalReason, tailscaleSelf, toTailscaleSetting, } from './tailscale.js';
90
93
  import { retryHref, sendSignedOut, wantsSignedOutPage } from './signed-out.js';
91
94
  import { extensionEndpoint } from './extension.js';
92
95
  import { REMOTE_HAND_SOCKET_PATH, RemoteHandEndpoint } from './remote-hand.js';
93
96
  import { csrfCookieName, CSRF_HEADER, sessionCookieName, requestPort, BodyTooLargeError, first, cookieHeader, parseCookies, parseUrl, readJsonBody, remoteKey, requestOrigin, requestScope, sendEmpty, sendJson, sendText, } from './http.js';
94
- import { boundedLimit, readAgents, readApprovals, readConversation, readConversations, readEventKinds, readEvents, readJobs, readMissions, readOverview, setGlanceHidden, readOffers, readReminders, readSentinels, toApprovalView, } from './read.js';
97
+ import { boundedLimit, readAgents, readApprovals, readConversation, readConversations, readEventKinds, readEvents, readJobs, readJobFailures, readMissions, readOverview, setGlanceHidden, readOffers, readReminders, readSentinels, toApprovalView, } from './read.js';
95
98
  import { RateLimiter, SessionStore, } from './sessions.js';
96
99
  import { supervisorCall } from './service.js';
97
100
  import { backupJobRoute, createBackupRoute, discardUpload, listBackups, passphraseRoute, receiveUpload, restoreRoute, scheduleRoute, verifyBackupRoute, } from './backups.js';
@@ -99,16 +102,24 @@ import { acceptAgentRoute, approveRoute, listPlugins, pluginJobRoute, receivePlu
99
102
  import { marketAssetRoute, marketRoute } from './market.js';
100
103
  import { pluginFoldersRoute } from './folders.js';
101
104
  import { tipsRoute } from '../tips/route.js';
105
+ import { createWidgets, widgetsRoute } from './widgets.js';
106
+ import { createRequirements } from '../plugins/requires.js';
107
+ import { placesList, placesRoute } from './places.js';
108
+ import { OWNER_DATE_FORMATS, OWNER_TIME_FORMATS } from '@buddi/core';
102
109
  import { readFacts, webSettingsStore } from '../tips/facts.js';
103
110
  import { dismissAgentOffer, isPendingAccept, raiseAgentOffers, readAgentOffers, readTeammates } from './agent-offers.js';
104
111
  import { currentVersion, upgradeJobRoute, upgradeRoute, versionCheckRoute, versionRoute, } from './version.js';
105
112
  import { leaveRecoveryMode, readRecoveryView } from './recovery.js';
106
113
  import { readRail, setRailPageHidden } from './rail.js';
107
114
  import { BUILD_MISSING, serveAsset, serveShellAtRoot } from './static.js';
108
- import { StreamBudget, resumeCursor, streamConversation } from './stream.js';
115
+ import { StreamBudget, frame, resumeCursor, streamConversation } from './stream.js';
109
116
  import { ensureWebToken, verifyTicket } from './token.js';
110
117
  import { MAX_UPLOAD_BYTES, readUpload } from './upload.js';
111
- import { cancelJobFromWeb, cancelReminderFromWeb, decideApprovalFromWeb, retryJobFromWeb, setMissionEnabledFromWeb, setPausedFromWeb, setScheduleFromWeb, dismissOfferFromWeb, dismissOffersFromWeb, takeOfferFromWeb, } from './write.js';
118
+ import { LOCKED_BODY, LockUnavailable, allowedWhileLocked, clientOf, createLock } from './lock.js';
119
+ import { matchApiRoute, TOKEN_REFUSALS } from './api-routes.js';
120
+ import { apiTokensRoute, bearerOf, verifyApiToken } from './api-tokens.js';
121
+ import { LockImageRefusal, MAX_LOCK_IMAGE_BYTES, normaliseLockImage } from './lock-image.js';
122
+ import { cancelJobFromWeb, cancelReminderFromWeb, decideApprovalFromWeb, retryJobFromWeb, retryJobsFromWeb, dismissJobsFromWeb, undismissJobsFromWeb, setMissionEnabledFromWeb, setPausedFromWeb, setScheduleFromWeb, dismissOfferFromWeb, dismissOffersFromWeb, takeOfferFromWeb, } from './write.js';
112
123
  /** How often approvals past their expiry are swept, and waiting delegations told. */
113
124
  export const EXPIRY_SWEEP_MS = 60_000;
114
125
  /**
@@ -127,6 +138,16 @@ const WEB_CHATS = new WeakMap();
127
138
  * it down, and a caller that built a bare `createWebApp` is unaffected.
128
139
  */
129
140
  const PREVIEW_APPS = new WeakMap();
141
+ /**
142
+ * What a dashboard says to its open pages just before it closes: one
143
+ * `closing` frame on every live stream, naming the restart or stop the page
144
+ * itself asked for when it was one (`for`), so a page another device or the
145
+ * CLI restarted under draws "Restarting buddi" rather than errors, and
146
+ * reloads once the next process answers `/_buddi/ready` with a new `boot`.
147
+ */
148
+ const CLOSING_SAYS = new WeakMap();
149
+ /** How long a closing frame may take to reach the pages before the sockets go. */
150
+ const CLOSING_FLUSH_MS = 250;
130
151
  /** The chat surface this server is running, if any. */
131
152
  /** The most of a text file a preview shows; the download has the whole. */
132
153
  const PREVIEW_TEXT_BYTES = 100_000;
@@ -232,9 +253,16 @@ export function createWebApp(deps) {
232
253
  const session = await sessions.resolve(parseCookies(req.headers.cookie)[sessionCookieName(cookiePort(req))], scope, now);
233
254
  if (!session)
234
255
  return null;
256
+ // A locked dashboard drives nothing (docs/dashboard.md, "Lock screen").
257
+ if (await lock.locked(session))
258
+ return null;
235
259
  if (session.via === 'tailscale') {
236
- const confirmed = await identityOf(req, now);
260
+ let refusal;
261
+ const confirmed = await identityOf(req, now, (reason) => { refusal = reason; });
237
262
  if (!confirmed || !sameLogin(confirmed.login, session.tailscaleLogin)) {
263
+ // "Could not ask" is not an answer: no socket now, but the session stays.
264
+ if (!confirmed && isUnansweredRefusal(refusal))
265
+ return null;
238
266
  await sessions.destroy(session.id).catch(() => { });
239
267
  return null;
240
268
  }
@@ -273,6 +301,72 @@ export function createWebApp(deps) {
273
301
  return [own, preview].filter((port) => typeof port === 'number');
274
302
  },
275
303
  });
304
+ // Plugin readiness and requirements: serve's, or this server's own.
305
+ const requirements = deps.requirements ??
306
+ createRequirements({ registry: deps.registry, ctx: deps.ctx, env: deps.env ?? process.env, pool: deps.pool, now: deps.now, log });
307
+ // Home's widgets: one cache per server (web/widgets.ts).
308
+ const widgets = createWidgets({ pool: deps.pool, registry: deps.registry, ctx: deps.ctx, now: deps.now });
309
+ /*
310
+ * The lock screen (web/lock.ts): which sessions are locked, the PIN, the
311
+ * gate below. A session that locks has its streams closed and its remote
312
+ * hand let go on the spot, and every half minute the sessions holding a
313
+ * stream are asked again, so one left idle past the delay is locked and cut
314
+ * off even if its page never says a word.
315
+ */
316
+ const lock = createLock({ pool: deps.pool, sessions, now: deps.now, get timezone() { return deps.timezone; }, widgets, log });
317
+ const openStreams = new Map();
318
+ /*
319
+ * This process's boot: answered by `/_buddi/ready`, so a page that watches a
320
+ * restart can tell the process that went from the one that came back.
321
+ * Random, and nothing else: it says which run this is, not when or where.
322
+ */
323
+ const boot = randomUUID();
324
+ /** Set when a page asked the supervisor to restart or stop this process: what the closing frame says. */
325
+ let goingAway;
326
+ /*
327
+ * The session a live API token acts through: minted on its first request,
328
+ * kept in memory only, one per token (and scope), so a stream budget or a
329
+ * sign-in in progress keyed by session id holds across its requests.
330
+ */
331
+ const tokenSessions = new Map();
332
+ const tokenSession = (holder, scope, now) => {
333
+ const key = `${holder.id}:${scope}`;
334
+ const held = tokenSessions.get(key);
335
+ if (held && held.expiresAt.getTime() > now.getTime()) {
336
+ held.expiresAt = new Date(now.getTime() + held.ttlMs);
337
+ return held;
338
+ }
339
+ for (const [k, s] of tokenSessions)
340
+ if (s.expiresAt.getTime() <= now.getTime())
341
+ tokenSessions.delete(k);
342
+ const session = sessions.create(scope, now, { via: 'token', client: 'api' }, { persist: false });
343
+ tokenSessions.set(key, session);
344
+ return session;
345
+ };
346
+ const holdStream = (session, res) => {
347
+ let entry = openStreams.get(session.id);
348
+ if (!entry)
349
+ openStreams.set(session.id, (entry = { session, responses: new Set() }));
350
+ entry.responses.add(res);
351
+ return () => {
352
+ const held = openStreams.get(session.id);
353
+ if (!held)
354
+ return;
355
+ held.responses.delete(res);
356
+ if (held.responses.size === 0)
357
+ openStreams.delete(session.id);
358
+ };
359
+ };
360
+ lock.onLocked((session) => {
361
+ hand.revoke((lease) => lease === session.id);
362
+ for (const res of openStreams.get(session.id)?.responses ?? [])
363
+ res.end();
364
+ });
365
+ const idleSweep = setInterval(() => {
366
+ for (const { session } of openStreams.values())
367
+ void lock.locked(session).catch(() => { });
368
+ }, 30_000);
369
+ idleSweep.unref();
276
370
  const writeDeps = {
277
371
  pool: deps.pool,
278
372
  registry: deps.registry,
@@ -297,7 +391,7 @@ export function createWebApp(deps) {
297
391
  registry: deps.registry,
298
392
  ctx: deps.ctx,
299
393
  now: deps.now,
300
- timezone: deps.timezone,
394
+ get timezone() { return deps.timezone; },
301
395
  log,
302
396
  ...deps.chat,
303
397
  })
@@ -389,7 +483,6 @@ export function createWebApp(deps) {
389
483
  const identityOf = (req, now, onRefusal) => tailscaleIdentity(req, {
390
484
  setting: readTailscaleSetting,
391
485
  whois,
392
- mayAskDaemon: () => !limiter.blocked(remoteKey(req), now),
393
486
  log,
394
487
  now: () => now,
395
488
  onRefusal,
@@ -406,6 +499,51 @@ export function createWebApp(deps) {
406
499
  cookieHeader(csrfCookieName(cookiePort(req)), session.csrf, { httpOnly: false, maxAgeSeconds, secure: session.scope === 'remote' && !!deps.config.publicOrigin }),
407
500
  ];
408
501
  };
502
+ /**
503
+ * The same pair, expired: what a response carries when the browser presented
504
+ * a session that is gone, so it stops presenting it. A forgotten tab or a
505
+ * polling page then sends no credential at all, which counts as nothing.
506
+ */
507
+ const expiredCookies = (req) => {
508
+ const secure = requestScope(req) === 'remote' && !!deps.config.publicOrigin;
509
+ return [
510
+ cookieHeader(sessionCookieName(cookiePort(req)), '', { httpOnly: true, maxAgeSeconds: 0, secure }),
511
+ cookieHeader(csrfCookieName(cookiePort(req)), '', { httpOnly: false, maxAgeSeconds: 0, secure }),
512
+ ];
513
+ };
514
+ /**
515
+ * What the signed-out page should offer this request: how it arrived,
516
+ * whether Tailscale can sign it in, and whether a lockout is running.
517
+ */
518
+ const signedOutFor = async (req, pathname, search, now, refusal) => {
519
+ const proxied = proxiedThroughTailscale(req);
520
+ let publicHost;
521
+ try {
522
+ publicHost = deps.config.publicOrigin ? new URL(deps.config.publicOrigin).hostname : undefined;
523
+ }
524
+ catch {
525
+ publicHost = undefined;
526
+ }
527
+ let host;
528
+ try {
529
+ host = req.headers.host ? new URL(`http://${req.headers.host}`).hostname : undefined;
530
+ }
531
+ catch {
532
+ host = undefined;
533
+ }
534
+ const scope = requestScope(req);
535
+ const arrived = proxied || (publicHost !== undefined && host === publicHost) ? 'tailnet' : scope === 'local' ? 'local' : 'remote';
536
+ const setting = arrived === 'tailnet' ? await readTailscaleSetting() : null;
537
+ const lockedForMs = limiter.retryAfterMs(remoteKey(req), now);
538
+ return {
539
+ retry: retryHref(pathname, search),
540
+ arrived,
541
+ tailscaleSignIn: !!setting?.enabled && !isLoginRefusal(refusal),
542
+ ...(isLoginRefusal(refusal) ? { tailscaleRefusal: tailscaleRefusalReason(refusal) } : {}),
543
+ ...(isUnansweredRefusal(refusal) ? { tailscaleUnanswered: true } : {}),
544
+ ...(lockedForMs > 0 ? { lockedForMs } : {}),
545
+ };
546
+ };
409
547
  /**
410
548
  * The port this request's cookies are named after (http.ts says why they
411
549
  * carry one): the port the browser sees, from the request's Host, so the
@@ -434,6 +572,13 @@ export function createWebApp(deps) {
434
572
  // have to unpack.
435
573
  const server = createServer((req, res) => {
436
574
  handle(req, res).catch((err) => {
575
+ // The lock could not say whether this request may pass: refused, never let in (web/lock.ts).
576
+ if (err instanceof LockUnavailable) {
577
+ log('web: the lock screen\'s state could not be read; refusing until it can');
578
+ if (!res.headersSent)
579
+ return sendEmpty(res, 503, { 'Retry-After': '5' });
580
+ return res.end();
581
+ }
437
582
  // A defect is a 500 with nothing in it. The sentence goes to the log,
438
583
  // where only the owner can read it.
439
584
  log(`web: ${req.method} ${req.url} failed: ${err instanceof Error ? err.stack : String(err)}`);
@@ -446,11 +591,36 @@ export function createWebApp(deps) {
446
591
  if (chat)
447
592
  WEB_CHATS.set(server, chat);
448
593
  PREVIEW_APPS.set(server, previews);
594
+ CLOSING_SAYS.set(server, async () => {
595
+ const said = frame('closing', goingAway === undefined ? {} : { for: goingAway });
596
+ const flushed = [];
597
+ for (const { responses } of openStreams.values()) {
598
+ for (const res of responses) {
599
+ if (res.writableEnded || res.destroyed)
600
+ continue;
601
+ // Ended, not just written: an ended response is flushed before its
602
+ // socket goes, where a frame still queued would be dropped with it.
603
+ flushed.push(new Promise((resolve) => {
604
+ try {
605
+ res.end(said, () => resolve());
606
+ }
607
+ catch {
608
+ resolve();
609
+ }
610
+ }));
611
+ }
612
+ }
613
+ if (flushed.length === 0)
614
+ return;
615
+ let timer;
616
+ await Promise.race([Promise.all(flushed), new Promise((resolve) => { timer = setTimeout(resolve, CLOSING_FLUSH_MS); })]);
617
+ clearTimeout(timer);
618
+ });
449
619
  // "Your browser": the only path this server ever upgrades. Attached here
450
620
  // rather than in `startWebServer` so every caller, tests included, has it.
451
621
  extension.attach(server);
452
622
  extension.attachPath(REMOTE_HAND_SOCKET_PATH, (req, socket, head) => hand.upgrade(req, socket, head));
453
- server.once('close', () => { extension.shutdown(); hand.shutdown(); });
623
+ server.once('close', () => { extension.shutdown(); hand.shutdown(); clearInterval(idleSweep); });
454
624
  return server;
455
625
  async function handle(req, res) {
456
626
  const now = deps.now();
@@ -462,11 +632,13 @@ export function createWebApp(deps) {
462
632
  return sendEmpty(res, 405);
463
633
  // A port answering 401 is not evidence that this installation is ready.
464
634
  // Domain-separated challenge proof never sends the install secret to that port.
465
- if (method === 'GET' && url.pathname === '/_buddi/ready' && deps.env?.BUDDI_WEB_REQUIRE_AUTH === '1') {
635
+ // Answered on every binding: `buddi mcp` asks it before it presents a
636
+ // ticket, so a port held by some other buddi never sees one.
637
+ if (method === 'GET' && url.pathname === '/_buddi/ready') {
466
638
  const challenge = url.searchParams.get('challenge') ?? '';
467
639
  if (!/^[a-f0-9]{64}$/.test(challenge))
468
640
  return sendEmpty(res, 400);
469
- return sendJson(res, 200, { proof: createHmac('sha256', deps.token).update(`buddi-ready-v1:${challenge}`).digest('hex') });
641
+ return sendJson(res, 200, { proof: createHmac('sha256', deps.token).update(`buddi-ready-v1:${challenge}`).digest('hex'), boot }, { 'Cache-Control': 'no-store' });
470
642
  }
471
643
  // A remote socket or proxy metadata can only earn remote access. It
472
644
  // decides how long a session minted now lives, and it must keep matching
@@ -505,7 +677,9 @@ export function createWebApp(deps) {
505
677
  return sendText(res, 401, 'This sign-in link is no longer valid: a link lasts five minutes.\nRun `buddi` again for a fresh one.\n');
506
678
  }
507
679
  limiter.reset(key);
508
- const session = sessions.create(scope, now);
680
+ // A ticket takes the installation's token, so it is the one way in that
681
+ // opens a session unlocked: what `buddi dashboard --unlock` hands out.
682
+ const session = sessions.create(scope, now, { via: scope === 'local' ? 'local' : 'ticket', client: clientOf(req.headers['x-buddi-client']) });
509
683
  const clean = new URL(url.toString());
510
684
  clean.searchParams.delete(TICKET_PARAM);
511
685
  return sendEmpty(res, 302, {
@@ -513,6 +687,43 @@ export function createWebApp(deps) {
513
687
  'Set-Cookie': sessionCookies(req, session),
514
688
  });
515
689
  }
690
+ /*
691
+ * An owner API token (docs/api.md, "Authentication"): `Authorization:
692
+ * Bearer buddi_…` on an /api request, from a script or another program.
693
+ *
694
+ * It is a credential presented, so a wrong or revoked one counts as a
695
+ * failed sign-in for this address exactly as a stale cookie does. A live
696
+ * one is the owner with no cookie and therefore no CSRF to check, and is
697
+ * answered only on a route the table lets a token call: never one that
698
+ * decides an approval, changes a grant, installs code, opens access or
699
+ * touches a secret. The lock screen does not cover it.
700
+ */
701
+ const bearer = url.pathname === '/api' || url.pathname.startsWith('/api/') ? bearerOf(req.headers.authorization) : undefined;
702
+ if (bearer !== undefined) {
703
+ if (limiter.blocked(key, now)) {
704
+ return sendEmpty(res, 429, { 'Retry-After': String(Math.max(1, Math.ceil(limiter.retryAfterMs(key, now) / 1000))) });
705
+ }
706
+ let holder;
707
+ try {
708
+ holder = await verifyApiToken(deps.pool, bearer, now);
709
+ }
710
+ catch (err) {
711
+ log(`web: checking an API token failed: ${err instanceof Error ? err.message : String(err)}`);
712
+ return sendEmpty(res, 503, { 'Retry-After': '5' });
713
+ }
714
+ if (!holder) {
715
+ limiter.failCredential(key, bearer, now);
716
+ return sendEmpty(res, 401, { 'WWW-Authenticate': 'Bearer realm="buddi"' });
717
+ }
718
+ const path = url.pathname.replace(/\/+$/, '') || '/api';
719
+ const route = matchApiRoute(method, path);
720
+ if (!route)
721
+ return method === 'GET' || method === 'HEAD' ? sendJson(res, 404, { error: 'no such endpoint' }) : sendEmpty(res, 405);
722
+ if (route.token) {
723
+ return sendJson(res, 403, { error: `An API token cannot call ${route.method} ${route.path}. ${TOKEN_REFUSALS[route.token]} Do it on the dashboard.` });
724
+ }
725
+ return api(req, res, url, method, now, tokenSession(holder, scope, now));
726
+ }
516
727
  const cookies = parseCookies(req.headers.cookie);
517
728
  const presentedSession = cookies[sessionCookieName(cookiePort(req))];
518
729
  let session = await sessions.resolve(presentedSession, scope, now);
@@ -523,18 +734,29 @@ export function createWebApp(deps) {
523
734
  */
524
735
  let refusal;
525
736
  const noteRefusal = (reason) => { refusal = reason; };
737
+ /*
738
+ * Set when the browser presented a session that is gone: the refusal then
739
+ * expires its cookies, so it stops presenting them (and stops counting).
740
+ */
741
+ let forgetCookies = false;
526
742
  /*
527
743
  * The answer to a refused request: the signed-out page for a person
528
- * opening a page, the empty 401 for everything else (docs/web.md).
744
+ * opening a page, the empty status for everything else (docs/web.md).
745
+ * 401 is "signed out", 429 "too many tries from here", 503 "Tailscale
746
+ * could not be asked; the session is still good, try again".
529
747
  */
530
- const refuse = () => {
748
+ const refuse = async (status = 401) => {
749
+ const headers = forgetCookies ? { 'Set-Cookie': expiredCookies(req) } : {};
750
+ if (status === 429)
751
+ headers['Retry-After'] = String(Math.max(1, Math.ceil(limiter.retryAfterMs(key, now) / 1000)));
752
+ if (status === 503)
753
+ headers['Retry-After'] = '5';
531
754
  if (!wantsSignedOutPage(req, method, url.pathname))
532
- return sendEmpty(res, 401);
533
- return sendSignedOut(res, {
534
- retry: retryHref(url.pathname, url.search),
535
- ...(isLoginRefusal(refusal) ? { tailscaleRefusal: tailscaleRefusalReason(refusal) } : {}),
536
- });
755
+ return sendEmpty(res, status, headers);
756
+ return sendSignedOut(res, await signedOutFor(req, url.pathname, url.search, now, refusal), headers, status);
537
757
  };
758
+ /* A Tailscale session this request ended: not a guess, so never a failed sign-in. */
759
+ let revoked = false;
538
760
  /*
539
761
  * A Tailscale session is re-confirmed on every single request.
540
762
  *
@@ -550,14 +772,23 @@ export function createWebApp(deps) {
550
772
  if (session?.via === 'tailscale') {
551
773
  const confirmed = await identityOf(req, now, noteRefusal);
552
774
  if (!confirmed || !sameLogin(confirmed.login, session.tailscaleLogin)) {
553
- const revoked = session.id;
775
+ /*
776
+ * The daemon could not be asked (busy, starting, timed out). That is
777
+ * not an answer about anyone, so the session is not ended for it —
778
+ * a restart's first burst of requests used to end every tailnet
779
+ * session this way — and nothing is counted. This request waits.
780
+ */
781
+ if (!confirmed && isUnansweredRefusal(refusal))
782
+ return refuse(503);
783
+ const ended = session.id;
554
784
  // A hand this session was holding does not outlive the session.
555
- hand.revoke((lease) => lease === revoked);
556
- await sessions.destroy(revoked);
557
- if (limiter.blocked(key, now))
558
- return sendEmpty(res, 429);
559
- limiter.failCredential(key, presentedSession ?? '', now);
560
- return refuse();
785
+ hand.revoke((lease) => lease === ended);
786
+ await sessions.destroy(ended);
787
+ session = undefined;
788
+ revoked = true;
789
+ forgetCookies = true;
790
+ // The identity on this very request may still earn a new session below.
791
+ refusal = undefined;
561
792
  }
562
793
  }
563
794
  /*
@@ -571,7 +802,14 @@ export function createWebApp(deps) {
571
802
  if (!session && openAccess && scope === 'local') {
572
803
  // Not stored: the next request mints another for free, so there is
573
804
  // nothing to keep across a restart and no row per cookie-less poll.
574
- session = sessions.create(scope, now, undefined, { persist: false });
805
+ // While a PIN is set a browser's new session starts locked: clearing the
806
+ // cookie or opening a private window is not a way past the lock screen.
807
+ //
808
+ // Always a browser's session: `x-buddi-client` is a header anybody can
809
+ // send, so here it earns nothing. Only a ticket from the installation
810
+ // token (the exchange above) names a client the lock does not cover.
811
+ const locked = await lock.startLocked('browser');
812
+ session = sessions.create(scope, now, { via: 'local', client: 'browser' }, { persist: false, ...(locked ? { locked } : {}) });
575
813
  res.setHeader('Set-Cookie', sessionCookies(req, session));
576
814
  }
577
815
  /*
@@ -589,12 +827,13 @@ export function createWebApp(deps) {
589
827
  const identity = await identityOf(req, now, noteRefusal);
590
828
  if (identity) {
591
829
  limiter.reset(key);
830
+ const locked = await lock.startLocked('browser');
592
831
  session = sessions.create('remote', now, {
593
832
  via: 'tailscale',
594
833
  tailscaleLogin: identity.login,
595
834
  tailscaleAddress: identity.address,
596
835
  tailscaleName: identity.name,
597
- });
836
+ }, locked ? { locked } : {});
598
837
  res.setHeader('Set-Cookie', sessionCookies(req, session));
599
838
  }
600
839
  }
@@ -610,8 +849,11 @@ export function createWebApp(deps) {
610
849
  // able to lock the owner out of every way in.
611
850
  if (!presentedSession)
612
851
  return refuse();
852
+ forgetCookies = true;
853
+ if (revoked)
854
+ return refuse();
613
855
  if (limiter.blocked(key, now))
614
- return sendEmpty(res, 429);
856
+ return refuse(429);
615
857
  limiter.failCredential(key, presentedSession, now);
616
858
  return refuse();
617
859
  }
@@ -641,6 +883,14 @@ export function createWebApp(deps) {
641
883
  return sendEmpty(res, 403);
642
884
  }
643
885
  if (url.pathname === '/api' || url.pathname.startsWith('/api/')) {
886
+ /*
887
+ * The lock screen's gate, after the session and its CSRF: a locked
888
+ * session gets 423 for everything but what the lock screen itself
889
+ * draws and the two ways off it (web/lock.ts).
890
+ */
891
+ const path = url.pathname.replace(/\/+$/, '') || '/api';
892
+ if (!allowedWhileLocked(method, path) && (await lock.locked(session)))
893
+ return sendJson(res, 423, LOCKED_BODY);
644
894
  return api(req, res, url, method, now, session);
645
895
  }
646
896
  if (mutating)
@@ -690,6 +940,7 @@ export function createWebApp(deps) {
690
940
  log,
691
941
  pool: deps.pool,
692
942
  registry: deps.registry,
943
+ requirements,
693
944
  ...(deps.plugins ? { engine: deps.plugins } : {}),
694
945
  });
695
946
  /** Is a mailbox connected? The email plugin's own read, the one Home's offer asks. */
@@ -764,6 +1015,24 @@ export function createWebApp(deps) {
764
1015
  now: deps.now,
765
1016
  agents: () => deps.catalog.list(),
766
1017
  plugins: () => deps.registry.manifests().map((m) => m.name),
1018
+ needsSetup: async () => {
1019
+ const out = [];
1020
+ for (const manifest of deps.registry.manifests()) {
1021
+ if (manifest.setup === undefined)
1022
+ continue;
1023
+ const ready = await requirements.readiness.of(manifest.name);
1024
+ if (!ready || ready.ready)
1025
+ continue;
1026
+ const page = ready.page === undefined ? undefined : deps.registry.pages().find((p) => p.plugin === manifest.name && p.id === ready.page);
1027
+ const route = page === undefined
1028
+ ? undefined
1029
+ : page.place === 'settings'
1030
+ ? `#/settings/p.${manifest.name}${page.id === manifest.name ? '' : `.${page.id}`}`
1031
+ : `#/p/${encodeURIComponent(manifest.name)}/${encodeURIComponent(page.id)}`;
1032
+ out.push({ plugin: manifest.name, ...(ready.note ? { note: ready.note } : {}), ...(route ? { route } : {}) });
1033
+ }
1034
+ return out;
1035
+ },
767
1036
  mailboxSet: async () => {
768
1037
  const answer = await runPageQuery(pagesDeps(), 'email', 'triage_offer', new URLSearchParams()).catch(() => null);
769
1038
  return answer?.status === 200 && answer.body?.data?.wanted === true;
@@ -772,6 +1041,74 @@ export function createWebApp(deps) {
772
1041
  }, { method, path, body, preview: url.searchParams.get('preview') });
773
1042
  return sendJson(res, answer.status, answer.body);
774
1043
  }
1044
+ // The lock screen: its state and data, Lock now, Unlock, the PIN, its settings and picture (web/lock.ts).
1045
+ if (path === '/api/lock' || path.startsWith('/api/lock/')) {
1046
+ let body = {};
1047
+ const upload = method === 'POST' && path === '/api/lock/background';
1048
+ if ((method === 'POST' || method === 'PUT') && !upload) {
1049
+ try {
1050
+ body = await readJsonBody(req);
1051
+ }
1052
+ catch {
1053
+ return sendJson(res, 400, { error: 'request body must be JSON' });
1054
+ }
1055
+ }
1056
+ const answer = await lock.route({
1057
+ method,
1058
+ path,
1059
+ body,
1060
+ session,
1061
+ query: url.searchParams,
1062
+ ...(upload ? {
1063
+ upload: async () => {
1064
+ const file = await readUpload(req, MAX_LOCK_IMAGE_BYTES);
1065
+ if (!file.ok)
1066
+ return { ok: false, status: file.status, error: file.status === 413 ? 'A picture can be at most 10 MB.' : file.error };
1067
+ try {
1068
+ return { ok: true, image: normaliseLockImage(file.file.bytes, file.file.mime) };
1069
+ }
1070
+ catch (err) {
1071
+ if (err instanceof LockImageRefusal)
1072
+ return { ok: false, status: err.status, error: err.message };
1073
+ throw err;
1074
+ }
1075
+ },
1076
+ } : {}),
1077
+ });
1078
+ if (answer === null)
1079
+ return sendJson(res, 404, { error: 'no such endpoint' });
1080
+ if ('image' in answer) {
1081
+ const etag = `"${answer.image.sha256}"`;
1082
+ res.setHeader('ETag', etag);
1083
+ res.setHeader('Cache-Control', 'private, max-age=31536000, immutable');
1084
+ res.setHeader('X-Content-Type-Options', 'nosniff');
1085
+ res.setHeader('Cross-Origin-Resource-Policy', 'same-origin');
1086
+ if (req.headers['if-none-match'] === etag)
1087
+ return sendEmpty(res, 304);
1088
+ res.setHeader('Content-Type', 'image/jpeg');
1089
+ res.setHeader('Content-Length', String(answer.image.jpeg.length));
1090
+ res.statusCode = 200;
1091
+ res.end(method === 'HEAD' ? undefined : answer.image.jpeg);
1092
+ return;
1093
+ }
1094
+ if (answer.status === 204)
1095
+ return sendEmpty(res, 204);
1096
+ return sendJson(res, answer.status, answer.body);
1097
+ }
1098
+ // Home's widgets: the gallery, the owner's layout, each placed one's body (web/widgets.ts).
1099
+ if (path === '/api/widgets' || path.startsWith('/api/widgets/')) {
1100
+ let body = {};
1101
+ if (method === 'PUT' || (method === 'POST' && path === '/api/widgets/preview')) {
1102
+ try {
1103
+ body = await readJsonBody(req);
1104
+ }
1105
+ catch {
1106
+ return sendJson(res, 400, { error: 'request body must be JSON' });
1107
+ }
1108
+ }
1109
+ const answer = await widgetsRoute(widgets, { method, path, body, query: url.searchParams });
1110
+ return sendJson(res, answer.status, answer.body);
1111
+ }
775
1112
  // Settings → Connections: every method, one module (web/connections.ts).
776
1113
  if (path === '/api/connections' || path.startsWith('/api/connections/')) {
777
1114
  let body = {};
@@ -952,10 +1289,14 @@ export function createWebApp(deps) {
952
1289
  res.end(method === 'HEAD' ? undefined : bytes);
953
1290
  return;
954
1291
  }
955
- case '/api/session':
1292
+ case '/api/session': {
1293
+ // How the owner reads times and dates: every page formats with it.
1294
+ const formats = await getOwnerProfile(deps.pool).catch(() => null);
956
1295
  return sendJson(res, 200, {
957
1296
  csrf: session.csrf,
958
1297
  timezone: deps.timezone,
1298
+ timeFormat: formats?.timeFormat ?? null,
1299
+ dateFormat: formats?.dateFormat ?? null,
959
1300
  host: deps.config.host,
960
1301
  port: deps.config.port,
961
1302
  // Where buddi runs: a page opened from another machine is still
@@ -979,6 +1320,7 @@ export function createWebApp(deps) {
979
1320
  // the old one" without a second route.
980
1321
  version: await currentVersion(deps.env ?? process.env),
981
1322
  });
1323
+ }
982
1324
  /*
983
1325
  * The Tailscale panel's whole payload: what is stored, whether a
984
1326
  * daemon is here to ask, who this machine is signed in as (so the
@@ -1010,7 +1352,9 @@ export function createWebApp(deps) {
1010
1352
  timezone: deps.timezone,
1011
1353
  now,
1012
1354
  })),
1013
- running: chat?.runningCount ?? 0,
1355
+ // Every surface's runs (Telegram, the queue, the terminal), not only
1356
+ // this dashboard's; a chat send still being set up counts too.
1357
+ running: Math.max(runningAgentRuns(), chat?.runningCount ?? 0),
1014
1358
  });
1015
1359
  case '/api/events':
1016
1360
  return sendJson(res, 200, await readEvents(deps.pool, {
@@ -1035,8 +1379,16 @@ export function createWebApp(deps) {
1035
1379
  kind: q.get('kind') ?? undefined,
1036
1380
  limit: boundedLimit(q.get('limit')),
1037
1381
  offset: Math.max(0, Math.min(Number(q.get('offset') ?? 0) || 0, 100_000)),
1382
+ failed: q.get('failed') === 'open' || q.get('failed') === 'dismissed' ? q.get('failed') : undefined,
1383
+ hideDismissed: q.get('dismissed') === '0',
1038
1384
  }));
1039
1385
  }
1386
+ // Failed jobs grouped by what broke them: the ones still asking, and
1387
+ // the dismissed ones (by the owner, or quiet after 14 days) apart.
1388
+ case '/api/jobs/failures': {
1389
+ const names = new Map(deps.catalog.list().map((a) => [a.id, a.name]));
1390
+ return sendJson(res, 200, await readJobFailures(deps.pool, now, (id) => names.get(id) ?? null));
1391
+ }
1040
1392
  case '/api/approvals': {
1041
1393
  const approvals = await readApprovals(deps.pool, now, boundedLimit(q.get('limit'), 50));
1042
1394
  return sendJson(res, 200, { pending: approvals.pending.map(a => ({ ...a, ...permissionScopes(a.tool) })),
@@ -1068,7 +1420,7 @@ export function createWebApp(deps) {
1068
1420
  reminders: await readReminders(deps.pool, boundedLimit(q.get('limit'))),
1069
1421
  });
1070
1422
  case '/api/sentinels':
1071
- return sendJson(res, 200, await readSentinels(deps.pool, deps.registry, boundedLimit(q.get('limit'), 50)));
1423
+ return sendJson(res, 200, await readSentinels(deps.pool, deps.registry, deps.now()));
1072
1424
  case '/api/chat/agents':
1073
1425
  return sendJson(res, 200, readChatAgents(deps.catalog, await avatarVersions(deps.pool)));
1074
1426
  // Which agents are waiting on the owner. One small query, and the only
@@ -1113,6 +1465,8 @@ export function createWebApp(deps) {
1113
1465
  default: readDefaultAgent(deps.catalog),
1114
1466
  });
1115
1467
  case '/api/groups':
1468
+ // The list is read every few seconds, so it is also where a delete whose minute has passed is made final.
1469
+ await purgeGroups(deps.pool, deps.now(), log);
1116
1470
  return sendJson(res, 200, { groups: (await listGroups(deps.pool)).map(groupView) });
1117
1471
  /*
1118
1472
  * The supervisor, when there is one. A developer checkout has no
@@ -1237,7 +1591,7 @@ export function createWebApp(deps) {
1237
1591
  return sendJson(res, 200, await telegramDevices(telegramDeps()));
1238
1592
  case '/api/owner': {
1239
1593
  const profile = await getOwnerProfile(deps.pool);
1240
- return sendJson(res, 200, { ...profile, detectedTimezone: Intl.DateTimeFormat().resolvedOptions().timeZone, zones: knownTimezones() });
1594
+ return sendJson(res, 200, { ...profile, places: await placesList(deps.pool), detectedTimezone: Intl.DateTimeFormat().resolvedOptions().timeZone, zones: knownTimezones() });
1241
1595
  }
1242
1596
  case '/api/memory': {
1243
1597
  try {
@@ -1249,6 +1603,9 @@ export function createWebApp(deps) {
1249
1603
  return sendJson(res, 503, { error: `Memory is unavailable: ${err instanceof Error ? err.message : String(err)}` });
1250
1604
  }
1251
1605
  }
1606
+ // Settings → API tokens. A token is refused these by the table: it cannot list or make its kind.
1607
+ case '/api/api-tokens':
1608
+ return reply(res, await apiTokensRoute(deps.pool, { method, path, body: null, now }));
1252
1609
  case '/api/provider-accounts':
1253
1610
  if (!deps.providerAccounts)
1254
1611
  return sendJson(res, 503, { error: 'Provider accounts are unavailable in this process.' });
@@ -1420,7 +1777,13 @@ export function createWebApp(deps) {
1420
1777
  return sendJson(res, 404, { error: 'no such group' });
1421
1778
  const latest = await latestGroupConversation(deps.pool, group.id);
1422
1779
  const open = latest ? await openGroupRequest(deps.pool, latest) : null;
1423
- return sendJson(res, 200, { ...groupView(group), latestConversationId: latest, openRequest: open ? { id: open.id, state: open.state, awaitingAgentId: open.awaitingAgentId, budgetReserved: open.budgetReserved, budgetTotal: open.budgetTotal } : null });
1780
+ return sendJson(res, 200, {
1781
+ ...groupView(group),
1782
+ latestConversationId: latest,
1783
+ openRequest: open ? { id: open.id, state: open.state, awaitingAgentId: open.awaitingAgentId, budgetReserved: open.budgetReserved, budgetTotal: open.budgetTotal } : null,
1784
+ // What Clear history and Delete would take, for the sentence that asks first.
1785
+ history: await groupHistorySize(deps.pool, group.id),
1786
+ });
1424
1787
  }
1425
1788
  const chatConversations = /^\/api\/chat\/([^/]+)\/conversations$/.exec(path);
1426
1789
  if (chatConversations) {
@@ -1449,6 +1812,7 @@ export function createWebApp(deps) {
1449
1812
  const release = streams.take(session.id);
1450
1813
  if (release === null)
1451
1814
  return sendEmpty(res, 429);
1815
+ const let_go = holdStream(session, res);
1452
1816
  try {
1453
1817
  await streamAttention(req, res, {
1454
1818
  pool: deps.pool,
@@ -1457,6 +1821,7 @@ export function createWebApp(deps) {
1457
1821
  });
1458
1822
  }
1459
1823
  finally {
1824
+ let_go();
1460
1825
  release();
1461
1826
  }
1462
1827
  return;
@@ -1472,6 +1837,7 @@ export function createWebApp(deps) {
1472
1837
  const release = streams.take(session.id);
1473
1838
  if (release === null)
1474
1839
  return sendEmpty(res, 429);
1840
+ const let_go = holdStream(session, res);
1475
1841
  try {
1476
1842
  await streamConversation(req, res, {
1477
1843
  pool: deps.pool,
@@ -1482,6 +1848,7 @@ export function createWebApp(deps) {
1482
1848
  });
1483
1849
  }
1484
1850
  finally {
1851
+ let_go();
1485
1852
  release();
1486
1853
  }
1487
1854
  return;
@@ -1545,6 +1912,12 @@ export function createWebApp(deps) {
1545
1912
  const forgotten = await extension.unpair();
1546
1913
  return sendJson(res, forgotten.status, forgotten.body);
1547
1914
  }
1915
+ // Revoke an API token: the next request carrying it is a 401.
1916
+ const tokenGone = /^\/api\/api-tokens\/([0-9a-f-]{36})$/i.exec(path);
1917
+ if (tokenGone) {
1918
+ const revoked = await apiTokensRoute(deps.pool, { method, path, body: null, now });
1919
+ return revoked.status === 204 ? sendEmpty(res, 204) : sendJson(res, revoked.status, revoked.body);
1920
+ }
1548
1921
  // A phone the owner no longer wants talking to their agents. Same as
1549
1922
  // `buddi telegram unpair <id>`, and as immediate.
1550
1923
  const phoneGone = /^\/api\/telegram\/devices\/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/i.exec(path);
@@ -1560,14 +1933,21 @@ export function createWebApp(deps) {
1560
1933
  }
1561
1934
  }
1562
1935
  /*
1563
- * A group the owner is done with leaves the rail and takes no new
1564
- * requests — and keeps everything that was said in it. Archived, never
1565
- * deleted: the transcript is the record of work that was done, and no
1566
- * amount of tidying the roster is worth destroying it.
1936
+ * Delete a group: it leaves every list now, with whatever it was doing
1937
+ * stopped, and is removed for good — its history and what the room
1938
+ * remembered, never its agents — once GROUP_UNDO_MS has passed without
1939
+ * a restore. The answer says until when Undo works.
1567
1940
  */
1568
1941
  const groupGone = /^\/api\/groups\/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/i.exec(path);
1569
1942
  if (groupGone) {
1570
- return (await archiveGroup(deps.pool, groupGone[1], deps.now())) ? sendEmpty(res, 204) : sendEmpty(res, 404);
1943
+ const at = deps.now();
1944
+ if (!(await getGroup(deps.pool, groupGone[1])))
1945
+ return sendJson(res, 404, { error: 'no such group' });
1946
+ await stopGroupWork(deps.pool, chat, groupGone[1], at, deps.ctx.ownerId);
1947
+ if (!(await deleteGroup(deps.pool, groupGone[1], at)))
1948
+ return sendJson(res, 404, { error: 'no such group' });
1949
+ await purgeGroups(deps.pool, at, log);
1950
+ return sendJson(res, 200, { undoUntil: new Date(at.getTime() + GROUP_UNDO_MS).toISOString() });
1571
1951
  }
1572
1952
  /*
1573
1953
  * The owner read the note a rollover carried into this conversation and
@@ -1900,6 +2280,8 @@ export function createWebApp(deps) {
1900
2280
  }
1901
2281
  if (path === '/api/presence')
1902
2282
  return reply(res, await presenceRoute(deps.pool, body, deps.now()));
2283
+ if (path === '/api/api-tokens')
2284
+ return reply(res, await apiTokensRoute(deps.pool, { method, path, body, now }));
1903
2285
  if (path === '/api/notifications/test')
1904
2286
  return reply(res, await testChannelRoute(body, deps.now()));
1905
2287
  if (path === '/api/notifications/agent-mute')
@@ -1937,14 +2319,64 @@ export function createWebApp(deps) {
1937
2319
  return sendJson(res, 400, { error: 'Expected agentId and conversationId.' });
1938
2320
  return sendJson(res, 200, { stopped: host.stop(deps.ctx.ownerId, body.agentId, body.conversationId) });
1939
2321
  }
2322
+ /*
2323
+ * Alerts (alerts.ts): the owner's verbs on what the watchers found. Snooze
2324
+ * one ("Not now" for a week with `days`, "Not needed" without), several at
2325
+ * once (Clear all, and its Undo), silence a subject or a kind, run what a
2326
+ * finding declared, or ask the agent that answers for it.
2327
+ */
1940
2328
  const alert = /^\/api\/alerts\/([^/]+)\/snooze$/.exec(path);
1941
2329
  if (alert) {
1942
2330
  if (typeof body.snoozed !== 'boolean')
1943
2331
  return sendJson(res, 400, { error: '`snoozed` must be true or false' });
1944
- const finding = await snoozeFinding(deps.pool, decodeURIComponent(alert[1]), body.snoozed, deps.now());
2332
+ const days = typeof body.days === 'number' && Number.isFinite(body.days) && body.days > 0 && body.days <= 90 ? body.days : null;
2333
+ const until = body.snoozed && days !== null ? new Date(deps.now().getTime() + days * 86_400_000) : null;
2334
+ const finding = await snoozeFinding(deps.pool, decodeURIComponent(alert[1]), body.snoozed, deps.now(), until);
1945
2335
  if (!finding)
1946
2336
  return sendJson(res, 404, { error: 'No open alert has that key.' });
1947
- return sendJson(res, 200, { key: finding.key, snoozedAt: finding.snoozedAt ? finding.snoozedAt.toISOString() : null });
2337
+ return sendJson(res, 200, {
2338
+ key: finding.key,
2339
+ snoozedAt: finding.snoozedAt ? finding.snoozedAt.toISOString() : null,
2340
+ snoozedUntil: finding.snoozedUntil ? finding.snoozedUntil.toISOString() : null,
2341
+ });
2342
+ }
2343
+ if (path === '/api/alerts/snooze') {
2344
+ const keys = Array.isArray(body.keys) ? body.keys.filter((k) => typeof k === 'string').slice(0, 500) : null;
2345
+ if (keys === null || typeof body.snoozed !== 'boolean')
2346
+ return sendJson(res, 400, { error: 'Send `{ keys: string[], snoozed: boolean, days? }`.' });
2347
+ const days = typeof body.days === 'number' && Number.isFinite(body.days) && body.days > 0 && body.days <= 90 ? body.days : null;
2348
+ const until = body.snoozed && days !== null ? new Date(deps.now().getTime() + days * 86_400_000) : null;
2349
+ return sendJson(res, 200, { keys: await snoozeFindings(deps.pool, keys, body.snoozed, deps.now(), until) });
2350
+ }
2351
+ if (path === '/api/alerts/mute')
2352
+ return reply(res, await muteAlert(deps.pool, body, deps.now()));
2353
+ const unmute = /^\/api\/alerts\/mutes\/([^/]+)\/remove$/.exec(path);
2354
+ if (unmute) {
2355
+ const removed = await unmuteFindings(deps.pool, decodeURIComponent(unmute[1]));
2356
+ return removed ? sendJson(res, 200, { removed: true }) : sendJson(res, 404, { error: 'Nothing is silenced under that id.' });
2357
+ }
2358
+ if (path === '/api/alerts/act') {
2359
+ if (actRateLimited(session.id, deps.now().getTime()))
2360
+ return sendJson(res, 429, { error: 'Too many writes from this page. Wait a moment and try again.' });
2361
+ return reply(res, await actOnAlerts({ pool: deps.pool, registry: deps.registry, ctx: deps.ctx, now: deps.now }, body, session));
2362
+ }
2363
+ if (path === '/api/alerts/ask') {
2364
+ const keys = Array.isArray(body.keys) ? body.keys.filter((k) => typeof k === 'string') : [];
2365
+ const findings = await findingsForAsk(deps.pool, keys);
2366
+ if (findings.length === 0)
2367
+ return sendJson(res, 404, { error: 'No alert has those keys.' });
2368
+ if (!chat)
2369
+ return sendJson(res, 503, { error: 'Chat is not running in this process.' });
2370
+ // The agent that answers for them, else whoever runs the wake mission.
2371
+ const wake = (await listMissions(deps.pool)).find((m) => m.id === 'sentinel-wake');
2372
+ const agentId = findings.find((f) => f.agentId !== null && deps.catalog.get(f.agentId) !== undefined)?.agentId ?? wake?.agentId ?? null;
2373
+ if (agentId === null)
2374
+ return sendJson(res, 409, { error: 'No agent answers for this alert yet.' });
2375
+ const { label, prompt } = askPrompt(findings);
2376
+ const sent = await chat.send({ agentId, text: prompt, offer: { id: `alert:${findings[0].key}`.slice(0, 200), label, brief: true } });
2377
+ if (!sent.ok)
2378
+ return sendJson(res, sent.status, { error: sent.error });
2379
+ return sendJson(res, 200, { agentId, conversationId: sent.conversationId, runId: sent.runId });
1948
2380
  }
1949
2381
  /*
1950
2382
  * A watcher, switched off or back on. Off means it does not run: it raises
@@ -2200,8 +2632,10 @@ export function createWebApp(deps) {
2200
2632
  }
2201
2633
  const outcome = await leaveRecoveryMode({ pool: deps.pool, env: deps.env ?? process.env, log }, deps.ctx.ownerId, { dropPending: body.dropPending !== false, keepGrants: keep }, now);
2202
2634
  if (socket) {
2635
+ goingAway = 'restart';
2203
2636
  res.once('finish', () => {
2204
2637
  void supervisorCall(socket, '/restart', 'POST').catch((err) => {
2638
+ goingAway = undefined;
2205
2639
  log(`web: supervisor restart after leaving recovery failed: ${err instanceof Error ? err.message : String(err)}`);
2206
2640
  });
2207
2641
  });
@@ -2241,8 +2675,10 @@ export function createWebApp(deps) {
2241
2675
  return sendJson(res, 503, { error: 'The supervisor is not answering on its control socket. Run buddi in a terminal.' });
2242
2676
  }
2243
2677
  }
2678
+ goingAway = action === 'stop' ? 'stop' : 'restart';
2244
2679
  res.once('finish', () => {
2245
2680
  void supervisorCall(socket, `/${action}`, 'POST').catch((err) => {
2681
+ goingAway = undefined;
2246
2682
  log(`web: supervisor ${action} failed: ${err instanceof Error ? err.message : String(err)}`);
2247
2683
  });
2248
2684
  });
@@ -2301,6 +2737,21 @@ export function createWebApp(deps) {
2301
2737
  if (groupArchive) {
2302
2738
  return (await archiveGroup(deps.pool, groupArchive[1], deps.now())) ? sendEmpty(res, 204) : sendEmpty(res, 404);
2303
2739
  }
2740
+ // Undo a delete, while the minute lasts. Too late: 410, and the page says so.
2741
+ const groupRestore = /^\/api\/groups\/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\/restore$/i.exec(path);
2742
+ if (groupRestore) {
2743
+ const back = await restoreGroup(deps.pool, groupRestore[1], deps.now());
2744
+ return back ? sendJson(res, 200, groupView(back)) : sendJson(res, 410, { error: 'Too late to undo: that group is gone for good.' });
2745
+ }
2746
+ // Clear the history, keep the group: its conversations go, its members and memory stay.
2747
+ const groupClear = /^\/api\/groups\/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\/clear$/i.exec(path);
2748
+ if (groupClear) {
2749
+ const group = await getGroup(deps.pool, groupClear[1]);
2750
+ if (!group)
2751
+ return sendJson(res, 404, { error: 'no such group' });
2752
+ await stopGroupWork(deps.pool, chat, group.id, deps.now(), deps.ctx.ownerId);
2753
+ return sendJson(res, 200, { conversations: await clearGroupHistory(deps.pool, group.id) });
2754
+ }
2304
2755
  /*
2305
2756
  * First run, from the dashboard.
2306
2757
  *
@@ -2532,14 +2983,37 @@ export function createWebApp(deps) {
2532
2983
  return sendJson(res, 400, { error: `\`${key}\` must be a string or null` });
2533
2984
  patch[key] = given;
2534
2985
  }
2986
+ // How times and dates read: a known word, or null for Auto.
2987
+ if (body.timeFormat !== undefined) {
2988
+ if (body.timeFormat !== null && !OWNER_TIME_FORMATS.includes(body.timeFormat))
2989
+ return sendJson(res, 400, { error: '`timeFormat` is 12h, 24h or null (Auto).' });
2990
+ patch.timeFormat = body.timeFormat;
2991
+ }
2992
+ if (body.dateFormat !== undefined) {
2993
+ if (body.dateFormat !== null && !OWNER_DATE_FORMATS.includes(body.dateFormat))
2994
+ return sendJson(res, 400, { error: '`dateFormat` is short, long, iso or null (Auto).' });
2995
+ patch.dateFormat = body.dateFormat;
2996
+ }
2535
2997
  if (patch.timezone && !isKnownTimezone(patch.timezone))
2536
2998
  return sendJson(res, 400, { error: `"${patch.timezone}" is not a timezone this host knows.` });
2537
2999
  if (patch.preferredName && patch.preferredName.length > 80)
2538
3000
  return sendJson(res, 400, { error: 'The name is too long (80 characters at most).' });
2539
3001
  if (patch.about && patch.about.length > 1000)
2540
3002
  return sendJson(res, 400, { error: 'Keep the line about you under 1,000 characters.' });
2541
- const profile = await setOwnerProfile(deps.pool, patch);
2542
- return sendJson(res, 200, { ...profile, detectedTimezone: Intl.DateTimeFormat().resolvedOptions().timeZone, zones: knownTimezones() });
3003
+ // The zone applies at once; schedules kept in the old one move with it.
3004
+ const { profile, zoneChange } = await saveOwnerProfile(deps.pool, patch, deps.env ?? process.env);
3005
+ if (zoneChange)
3006
+ log(`owner: timezone ${zoneChange.from} → ${zoneChange.to}${zoneChange.missions.length > 0 ? `; moved ${zoneChange.missions.join(', ')}` : ''}`);
3007
+ return sendJson(res, 200, { ...profile, places: await placesList(deps.pool), detectedTimezone: Intl.DateTimeFormat().resolvedOptions().timeZone, zones: knownTimezones() });
3008
+ }
3009
+ /* The owner's places beside the timezone: find one, save one, remove one (web/places.ts). */
3010
+ if (path.startsWith('/api/owner/places')) {
3011
+ const answered = await placesRoute({ pool: deps.pool, log, ...(deps.placesHttp ? { http: deps.placesHttp } : {}) }, path, body);
3012
+ if (answered) {
3013
+ // Plugins that read the places answer their setup again now.
3014
+ requirements.readiness.forget();
3015
+ return sendJson(res, answered.status, answered.body);
3016
+ }
2543
3017
  }
2544
3018
  /* Memory, the owner's side: correct a preference, retire one, edit or forget a note. */
2545
3019
  if (path === '/api/memory/preferences') {
@@ -2645,6 +3119,14 @@ export function createWebApp(deps) {
2645
3119
  return sendJson(res, 400, { error: change });
2646
3120
  return finish(res, setAgentEngineFromWeb({ catalog: deps.catalog, env: deps.env ?? process.env }, decodeURIComponent(engine[1]), change));
2647
3121
  }
3122
+ // Failed jobs in bulk — by ids, by cause group, or every one still asking.
3123
+ // Dismiss keeps them on record and out of the footer's count.
3124
+ if (path === '/api/jobs/dismiss')
3125
+ return finish(res, await dismissJobsFromWeb(writeDeps, body));
3126
+ if (path === '/api/jobs/undismiss')
3127
+ return finish(res, await undismissJobsFromWeb(writeDeps, body));
3128
+ if (path === '/api/jobs/retry')
3129
+ return finish(res, await retryJobsFromWeb(writeDeps, body));
2648
3130
  const job = /^\/api\/jobs\/([^/]+)\/(retry|cancel)$/.exec(path);
2649
3131
  if (job) {
2650
3132
  const jobId = decodeURIComponent(job[1]);
@@ -2863,7 +3345,8 @@ export function createWebApp(deps) {
2863
3345
  */
2864
3346
  export async function startWebServer(deps) {
2865
3347
  const token = deps.token ?? (await ensureWebToken()).token;
2866
- const server = createWebApp({ ...deps, token });
3348
+ // The zone stays a getter through the spread: Settings → Profile can change it.
3349
+ const server = createWebApp({ ...deps, token, get timezone() { return deps.timezone; } });
2867
3350
  await new Promise((resolve, reject) => {
2868
3351
  server.once('error', reject);
2869
3352
  server.listen(deps.config.port, deps.config.host, () => {
@@ -2907,6 +3390,8 @@ export async function startWebServer(deps) {
2907
3390
  close: async () => {
2908
3391
  if (expirySweep)
2909
3392
  clearInterval(expirySweep);
3393
+ // Said before anything closes, while the streams can still carry it.
3394
+ await CLOSING_SAYS.get(server)?.();
2910
3395
  // Both listeners, both awaited. A preview socket still open is a port
2911
3396
  // still held, and the next thing to want it — the next test, the
2912
3397
  // gateway coming back up — finds it taken.