@withbuddi/buddi 0.1.0-pre.22 → 0.1.0-pre.24

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 (486) hide show
  1. package/README.md +10 -7
  2. package/node_modules/@buddi/cli/dist/.tsbuildinfo +1 -1
  3. package/node_modules/@buddi/cli/dist/commands.d.ts.map +1 -1
  4. package/node_modules/@buddi/cli/dist/commands.js +30 -1
  5. package/node_modules/@buddi/cli/dist/commands.js.map +1 -1
  6. package/node_modules/@buddi/cli/dist/doctor-probes.d.ts.map +1 -1
  7. package/node_modules/@buddi/cli/dist/doctor-probes.js +1 -0
  8. package/node_modules/@buddi/cli/dist/doctor-probes.js.map +1 -1
  9. package/node_modules/@buddi/cli/dist/doctor.d.ts +2 -0
  10. package/node_modules/@buddi/cli/dist/doctor.d.ts.map +1 -1
  11. package/node_modules/@buddi/cli/dist/doctor.js +7 -0
  12. package/node_modules/@buddi/cli/dist/doctor.js.map +1 -1
  13. package/node_modules/@buddi/cli/dist/main.d.ts.map +1 -1
  14. package/node_modules/@buddi/cli/dist/main.js +2 -1
  15. package/node_modules/@buddi/cli/dist/main.js.map +1 -1
  16. package/node_modules/@buddi/cli/dist/plugins-toggle.d.ts +9 -0
  17. package/node_modules/@buddi/cli/dist/plugins-toggle.d.ts.map +1 -0
  18. package/node_modules/@buddi/cli/dist/plugins-toggle.js +20 -0
  19. package/node_modules/@buddi/cli/dist/plugins-toggle.js.map +1 -0
  20. package/node_modules/@buddi/core/dist/.tsbuildinfo +1 -1
  21. package/node_modules/@buddi/core/dist/agents/catalog.d.ts +37 -2
  22. package/node_modules/@buddi/core/dist/agents/catalog.d.ts.map +1 -1
  23. package/node_modules/@buddi/core/dist/agents/catalog.js +49 -11
  24. package/node_modules/@buddi/core/dist/agents/catalog.js.map +1 -1
  25. package/node_modules/@buddi/core/dist/home.d.ts +30 -1
  26. package/node_modules/@buddi/core/dist/home.d.ts.map +1 -1
  27. package/node_modules/@buddi/core/dist/home.js +1 -1
  28. package/node_modules/@buddi/core/dist/home.js.map +1 -1
  29. package/node_modules/@buddi/core/dist/host/build.d.ts +7 -0
  30. package/node_modules/@buddi/core/dist/host/build.d.ts.map +1 -1
  31. package/node_modules/@buddi/core/dist/host/build.js +51 -4
  32. package/node_modules/@buddi/core/dist/host/build.js.map +1 -1
  33. package/node_modules/@buddi/core/dist/host/http.d.ts +32 -0
  34. package/node_modules/@buddi/core/dist/host/http.d.ts.map +1 -1
  35. package/node_modules/@buddi/core/dist/host/http.js +102 -2
  36. package/node_modules/@buddi/core/dist/host/http.js.map +1 -1
  37. package/node_modules/@buddi/core/dist/host/types.d.ts +8 -0
  38. package/node_modules/@buddi/core/dist/host/types.d.ts.map +1 -1
  39. package/node_modules/@buddi/core/dist/index.d.ts +1 -0
  40. package/node_modules/@buddi/core/dist/index.d.ts.map +1 -1
  41. package/node_modules/@buddi/core/dist/index.js +1 -0
  42. package/node_modules/@buddi/core/dist/index.js.map +1 -1
  43. package/node_modules/@buddi/core/dist/learning/announce.d.ts +1 -1
  44. package/node_modules/@buddi/core/dist/notifications/focus.d.ts +42 -0
  45. package/node_modules/@buddi/core/dist/notifications/focus.d.ts.map +1 -0
  46. package/node_modules/@buddi/core/dist/notifications/focus.js +150 -0
  47. package/node_modules/@buddi/core/dist/notifications/focus.js.map +1 -0
  48. package/node_modules/@buddi/core/dist/notifications/index.d.ts +1 -0
  49. package/node_modules/@buddi/core/dist/notifications/index.d.ts.map +1 -1
  50. package/node_modules/@buddi/core/dist/notifications/index.js +1 -0
  51. package/node_modules/@buddi/core/dist/notifications/index.js.map +1 -1
  52. package/node_modules/@buddi/core/dist/notifications/notify.d.ts +66 -7
  53. package/node_modules/@buddi/core/dist/notifications/notify.d.ts.map +1 -1
  54. package/node_modules/@buddi/core/dist/notifications/notify.js +123 -38
  55. package/node_modules/@buddi/core/dist/notifications/notify.js.map +1 -1
  56. package/node_modules/@buddi/core/dist/notifications/store.d.ts +6 -4
  57. package/node_modules/@buddi/core/dist/notifications/store.d.ts.map +1 -1
  58. package/node_modules/@buddi/core/dist/notifications/store.js +24 -23
  59. package/node_modules/@buddi/core/dist/notifications/store.js.map +1 -1
  60. package/node_modules/@buddi/core/dist/notifications/types.d.ts +46 -3
  61. package/node_modules/@buddi/core/dist/notifications/types.d.ts.map +1 -1
  62. package/node_modules/@buddi/core/dist/notifications/types.js +12 -0
  63. package/node_modules/@buddi/core/dist/notifications/types.js.map +1 -1
  64. package/node_modules/@buddi/core/dist/pages.d.ts +186 -6
  65. package/node_modules/@buddi/core/dist/pages.d.ts.map +1 -1
  66. package/node_modules/@buddi/core/dist/pages.js +232 -13
  67. package/node_modules/@buddi/core/dist/pages.js.map +1 -1
  68. package/node_modules/@buddi/core/dist/plugin/author.d.ts +42 -0
  69. package/node_modules/@buddi/core/dist/plugin/author.d.ts.map +1 -0
  70. package/node_modules/@buddi/core/dist/plugin/author.js +77 -0
  71. package/node_modules/@buddi/core/dist/plugin/author.js.map +1 -0
  72. package/node_modules/@buddi/core/dist/plugin/index.d.ts +7 -3
  73. package/node_modules/@buddi/core/dist/plugin/index.d.ts.map +1 -1
  74. package/node_modules/@buddi/core/dist/plugin/index.js +3 -0
  75. package/node_modules/@buddi/core/dist/plugin/index.js.map +1 -1
  76. package/node_modules/@buddi/core/dist/plugin/version.d.ts +1 -1
  77. package/node_modules/@buddi/core/dist/plugin/version.d.ts.map +1 -1
  78. package/node_modules/@buddi/core/dist/plugin/version.js +1 -1
  79. package/node_modules/@buddi/core/dist/plugin/version.js.map +1 -1
  80. package/node_modules/@buddi/core/dist/plugins/record.d.ts +8 -0
  81. package/node_modules/@buddi/core/dist/plugins/record.d.ts.map +1 -1
  82. package/node_modules/@buddi/core/dist/plugins/record.js +17 -0
  83. package/node_modules/@buddi/core/dist/plugins/record.js.map +1 -1
  84. package/node_modules/@buddi/core/dist/plugins/types.d.ts +7 -0
  85. package/node_modules/@buddi/core/dist/plugins/types.d.ts.map +1 -1
  86. package/node_modules/@buddi/core/dist/plugins/types.js.map +1 -1
  87. package/node_modules/@buddi/core/dist/registry.d.ts +11 -0
  88. package/node_modules/@buddi/core/dist/registry.d.ts.map +1 -1
  89. package/node_modules/@buddi/core/dist/registry.js +47 -6
  90. package/node_modules/@buddi/core/dist/registry.js.map +1 -1
  91. package/node_modules/@buddi/core/dist/scheduler/materialize.js +1 -1
  92. package/node_modules/@buddi/core/dist/scheduler/missions.d.ts +10 -0
  93. package/node_modules/@buddi/core/dist/scheduler/missions.d.ts.map +1 -1
  94. package/node_modules/@buddi/core/dist/scheduler/missions.js +29 -1
  95. package/node_modules/@buddi/core/dist/scheduler/missions.js.map +1 -1
  96. package/node_modules/@buddi/core/dist/scheduler/types.d.ts +7 -0
  97. package/node_modules/@buddi/core/dist/scheduler/types.d.ts.map +1 -1
  98. package/node_modules/@buddi/core/dist/scheduler/types.js +1 -0
  99. package/node_modules/@buddi/core/dist/scheduler/types.js.map +1 -1
  100. package/node_modules/@buddi/core/dist/secrets/destinations.d.ts +2 -0
  101. package/node_modules/@buddi/core/dist/secrets/destinations.d.ts.map +1 -1
  102. package/node_modules/@buddi/core/dist/secrets/destinations.js +6 -0
  103. package/node_modules/@buddi/core/dist/secrets/destinations.js.map +1 -1
  104. package/node_modules/@buddi/core/dist/tools.d.ts +8 -0
  105. package/node_modules/@buddi/core/dist/tools.d.ts.map +1 -1
  106. package/node_modules/@buddi/core/dist/tools.js.map +1 -1
  107. package/node_modules/@buddi/core/dist/views.d.ts +178 -3
  108. package/node_modules/@buddi/core/dist/views.d.ts.map +1 -1
  109. package/node_modules/@buddi/core/dist/views.js +56 -1
  110. package/node_modules/@buddi/core/dist/views.js.map +1 -1
  111. package/node_modules/@buddi/core/migrations/051_notification_focus.sql +20 -0
  112. package/node_modules/@buddi/core/migrations/052_mission_paused_reason.sql +6 -0
  113. package/node_modules/@buddi/gateway/dist/.tsbuildinfo +1 -1
  114. package/node_modules/@buddi/gateway/dist/agents/catalog.d.ts +7 -0
  115. package/node_modules/@buddi/gateway/dist/agents/catalog.d.ts.map +1 -1
  116. package/node_modules/@buddi/gateway/dist/agents/catalog.js +18 -1
  117. package/node_modules/@buddi/gateway/dist/agents/catalog.js.map +1 -1
  118. package/node_modules/@buddi/gateway/dist/agents/starter-team.d.ts +2 -0
  119. package/node_modules/@buddi/gateway/dist/agents/starter-team.d.ts.map +1 -1
  120. package/node_modules/@buddi/gateway/dist/agents/starter-team.js +8 -3
  121. package/node_modules/@buddi/gateway/dist/agents/starter-team.js.map +1 -1
  122. package/node_modules/@buddi/gateway/dist/index.d.ts +1 -1
  123. package/node_modules/@buddi/gateway/dist/index.d.ts.map +1 -1
  124. package/node_modules/@buddi/gateway/dist/index.js.map +1 -1
  125. package/node_modules/@buddi/gateway/dist/missions-cli.d.ts.map +1 -1
  126. package/node_modules/@buddi/gateway/dist/missions-cli.js +6 -3
  127. package/node_modules/@buddi/gateway/dist/missions-cli.js.map +1 -1
  128. package/node_modules/@buddi/gateway/dist/plugins/approve.d.ts.map +1 -1
  129. package/node_modules/@buddi/gateway/dist/plugins/approve.js +9 -2
  130. package/node_modules/@buddi/gateway/dist/plugins/approve.js.map +1 -1
  131. package/node_modules/@buddi/gateway/dist/plugins/index.d.ts +1 -0
  132. package/node_modules/@buddi/gateway/dist/plugins/index.d.ts.map +1 -1
  133. package/node_modules/@buddi/gateway/dist/plugins/index.js +1 -0
  134. package/node_modules/@buddi/gateway/dist/plugins/index.js.map +1 -1
  135. package/node_modules/@buddi/gateway/dist/plugins/live.d.ts +42 -0
  136. package/node_modules/@buddi/gateway/dist/plugins/live.d.ts.map +1 -0
  137. package/node_modules/@buddi/gateway/dist/plugins/live.js +81 -0
  138. package/node_modules/@buddi/gateway/dist/plugins/live.js.map +1 -0
  139. package/node_modules/@buddi/gateway/dist/plugins/load.d.ts +5 -0
  140. package/node_modules/@buddi/gateway/dist/plugins/load.d.ts.map +1 -1
  141. package/node_modules/@buddi/gateway/dist/plugins/load.js +10 -1
  142. package/node_modules/@buddi/gateway/dist/plugins/load.js.map +1 -1
  143. package/node_modules/@buddi/gateway/dist/plugins/provenance.d.ts.map +1 -1
  144. package/node_modules/@buddi/gateway/dist/plugins/provenance.js +10 -3
  145. package/node_modules/@buddi/gateway/dist/plugins/provenance.js.map +1 -1
  146. package/node_modules/@buddi/gateway/dist/plugins/scaffold.d.ts +8 -0
  147. package/node_modules/@buddi/gateway/dist/plugins/scaffold.d.ts.map +1 -1
  148. package/node_modules/@buddi/gateway/dist/plugins/scaffold.js +46 -7
  149. package/node_modules/@buddi/gateway/dist/plugins/scaffold.js.map +1 -1
  150. package/node_modules/@buddi/gateway/dist/plugins/stage.d.ts +6 -1
  151. package/node_modules/@buddi/gateway/dist/plugins/stage.d.ts.map +1 -1
  152. package/node_modules/@buddi/gateway/dist/plugins/stage.js +3 -1
  153. package/node_modules/@buddi/gateway/dist/plugins/stage.js.map +1 -1
  154. package/node_modules/@buddi/gateway/dist/plugins/toggle.d.ts +37 -0
  155. package/node_modules/@buddi/gateway/dist/plugins/toggle.d.ts.map +1 -0
  156. package/node_modules/@buddi/gateway/dist/plugins/toggle.js +110 -0
  157. package/node_modules/@buddi/gateway/dist/plugins/toggle.js.map +1 -0
  158. package/node_modules/@buddi/gateway/dist/plugins-cli.d.ts +61 -6
  159. package/node_modules/@buddi/gateway/dist/plugins-cli.d.ts.map +1 -1
  160. package/node_modules/@buddi/gateway/dist/plugins-cli.js +247 -20
  161. package/node_modules/@buddi/gateway/dist/plugins-cli.js.map +1 -1
  162. package/node_modules/@buddi/gateway/dist/serve.js +3 -3
  163. package/node_modules/@buddi/gateway/dist/serve.js.map +1 -1
  164. package/node_modules/@buddi/gateway/dist/speech-cli.d.ts +13 -0
  165. package/node_modules/@buddi/gateway/dist/speech-cli.d.ts.map +1 -1
  166. package/node_modules/@buddi/gateway/dist/speech-cli.js +40 -1
  167. package/node_modules/@buddi/gateway/dist/speech-cli.js.map +1 -1
  168. package/node_modules/@buddi/gateway/dist/telegram/focus.d.ts +27 -0
  169. package/node_modules/@buddi/gateway/dist/telegram/focus.d.ts.map +1 -0
  170. package/node_modules/@buddi/gateway/dist/telegram/focus.js +72 -0
  171. package/node_modules/@buddi/gateway/dist/telegram/focus.js.map +1 -0
  172. package/node_modules/@buddi/gateway/dist/telegram/main.d.ts.map +1 -1
  173. package/node_modules/@buddi/gateway/dist/telegram/main.js +1 -0
  174. package/node_modules/@buddi/gateway/dist/telegram/main.js.map +1 -1
  175. package/node_modules/@buddi/gateway/dist/telegram/surface.d.ts +2 -0
  176. package/node_modules/@buddi/gateway/dist/telegram/surface.d.ts.map +1 -1
  177. package/node_modules/@buddi/gateway/dist/telegram/surface.js +24 -1
  178. package/node_modules/@buddi/gateway/dist/telegram/surface.js.map +1 -1
  179. package/node_modules/@buddi/gateway/dist/tips/rules.d.ts +2 -0
  180. package/node_modules/@buddi/gateway/dist/tips/rules.d.ts.map +1 -1
  181. package/node_modules/@buddi/gateway/dist/tips/rules.js +10 -0
  182. package/node_modules/@buddi/gateway/dist/tips/rules.js.map +1 -1
  183. package/node_modules/@buddi/gateway/dist/web/agent-offers.js +1 -1
  184. package/node_modules/@buddi/gateway/dist/web/agent-offers.js.map +1 -1
  185. package/node_modules/@buddi/gateway/dist/web/folders.d.ts +23 -0
  186. package/node_modules/@buddi/gateway/dist/web/folders.d.ts.map +1 -0
  187. package/node_modules/@buddi/gateway/dist/web/folders.js +100 -0
  188. package/node_modules/@buddi/gateway/dist/web/folders.js.map +1 -0
  189. package/node_modules/@buddi/gateway/dist/web/market.d.ts +111 -0
  190. package/node_modules/@buddi/gateway/dist/web/market.d.ts.map +1 -0
  191. package/node_modules/@buddi/gateway/dist/web/market.js +347 -0
  192. package/node_modules/@buddi/gateway/dist/web/market.js.map +1 -0
  193. package/node_modules/@buddi/gateway/dist/web/notifications.d.ts +8 -1
  194. package/node_modules/@buddi/gateway/dist/web/notifications.d.ts.map +1 -1
  195. package/node_modules/@buddi/gateway/dist/web/notifications.js +23 -1
  196. package/node_modules/@buddi/gateway/dist/web/notifications.js.map +1 -1
  197. package/node_modules/@buddi/gateway/dist/web/plugins.d.ts +38 -3
  198. package/node_modules/@buddi/gateway/dist/web/plugins.d.ts.map +1 -1
  199. package/node_modules/@buddi/gateway/dist/web/plugins.js +73 -5
  200. package/node_modules/@buddi/gateway/dist/web/plugins.js.map +1 -1
  201. package/node_modules/@buddi/gateway/dist/web/profile.d.ts +2 -0
  202. package/node_modules/@buddi/gateway/dist/web/profile.d.ts.map +1 -1
  203. package/node_modules/@buddi/gateway/dist/web/profile.js +2 -1
  204. package/node_modules/@buddi/gateway/dist/web/profile.js.map +1 -1
  205. package/node_modules/@buddi/gateway/dist/web/rail.d.ts +33 -0
  206. package/node_modules/@buddi/gateway/dist/web/rail.d.ts.map +1 -0
  207. package/node_modules/@buddi/gateway/dist/web/rail.js +45 -0
  208. package/node_modules/@buddi/gateway/dist/web/rail.js.map +1 -0
  209. package/node_modules/@buddi/gateway/dist/web/read.d.ts +46 -0
  210. package/node_modules/@buddi/gateway/dist/web/read.d.ts.map +1 -1
  211. package/node_modules/@buddi/gateway/dist/web/read.js +78 -2
  212. package/node_modules/@buddi/gateway/dist/web/read.js.map +1 -1
  213. package/node_modules/@buddi/gateway/dist/web/server.d.ts.map +1 -1
  214. package/node_modules/@buddi/gateway/dist/web/server.js +68 -6
  215. package/node_modules/@buddi/gateway/dist/web/server.js.map +1 -1
  216. package/node_modules/@buddi/gateway/dist/web/svg.d.ts +23 -0
  217. package/node_modules/@buddi/gateway/dist/web/svg.d.ts.map +1 -0
  218. package/node_modules/@buddi/gateway/dist/web/svg.js +125 -0
  219. package/node_modules/@buddi/gateway/dist/web/svg.js.map +1 -0
  220. package/node_modules/@buddi/gateway/src/agents/starter/planner/agent.md +2 -2
  221. package/node_modules/@buddi/gateway/src/agents/starter/planner/skills/writing-the-morning-brief.md +18 -11
  222. package/node_modules/@buddi/install/dist/.tsbuildinfo +1 -1
  223. package/node_modules/@buddi/runtime/dist/.tsbuildinfo +1 -1
  224. package/node_modules/@buddi/tool-artifacts/dist/.tsbuildinfo +1 -1
  225. package/node_modules/@buddi/tool-browser/dist/.tsbuildinfo +1 -1
  226. package/node_modules/@buddi/tool-email/dist/.tsbuildinfo +1 -1
  227. package/node_modules/@buddi/tool-host/dist/.tsbuildinfo +1 -1
  228. package/node_modules/@buddi/tool-mcp/dist/.tsbuildinfo +1 -1
  229. package/node_modules/@buddi/tool-memory/dist/.tsbuildinfo +1 -1
  230. package/node_modules/@buddi/tool-web/dist/.tsbuildinfo +1 -1
  231. package/node_modules/@hono/node-server/README.md +21 -10
  232. package/node_modules/@hono/node-server/dist/early-hints.cjs +1 -1
  233. package/node_modules/@hono/node-server/dist/early-hints.mjs +1 -1
  234. package/node_modules/@hono/node-server/dist/index.cjs +41 -19
  235. package/node_modules/@hono/node-server/dist/index.mjs +42 -20
  236. package/node_modules/@hono/node-server/dist/serve-static.cjs +1 -0
  237. package/node_modules/@hono/node-server/dist/serve-static.d.cts +2 -1
  238. package/node_modules/@hono/node-server/dist/serve-static.d.mts +2 -1
  239. package/node_modules/@hono/node-server/dist/serve-static.mjs +1 -0
  240. package/node_modules/@hono/node-server/package.json +3 -2
  241. package/node_modules/hono/dist/cjs/adapter/bun/websocket.js +1 -1
  242. package/node_modules/hono/dist/cjs/middleware/language/language.js +1 -1
  243. package/node_modules/hono/dist/cjs/middleware/serve-static/index.js +1 -0
  244. package/node_modules/hono/dist/middleware/language/language.js +1 -1
  245. package/node_modules/hono/dist/middleware/serve-static/index.js +1 -0
  246. package/node_modules/hono/dist/types/middleware/serve-static/index.d.ts +2 -0
  247. package/node_modules/hono/package.json +1 -1
  248. package/package.json +2 -2
  249. package/packages/cli/dist/.tsbuildinfo +1 -1
  250. package/packages/cli/dist/commands.d.ts.map +1 -1
  251. package/packages/cli/dist/commands.js +30 -1
  252. package/packages/cli/dist/commands.js.map +1 -1
  253. package/packages/cli/dist/doctor-probes.d.ts.map +1 -1
  254. package/packages/cli/dist/doctor-probes.js +1 -0
  255. package/packages/cli/dist/doctor-probes.js.map +1 -1
  256. package/packages/cli/dist/doctor.d.ts +2 -0
  257. package/packages/cli/dist/doctor.d.ts.map +1 -1
  258. package/packages/cli/dist/doctor.js +7 -0
  259. package/packages/cli/dist/doctor.js.map +1 -1
  260. package/packages/cli/dist/main.d.ts.map +1 -1
  261. package/packages/cli/dist/main.js +2 -1
  262. package/packages/cli/dist/main.js.map +1 -1
  263. package/packages/cli/dist/plugins-toggle.d.ts +9 -0
  264. package/packages/cli/dist/plugins-toggle.d.ts.map +1 -0
  265. package/packages/cli/dist/plugins-toggle.js +20 -0
  266. package/packages/cli/dist/plugins-toggle.js.map +1 -0
  267. package/packages/core/dist/.tsbuildinfo +1 -1
  268. package/packages/core/dist/agents/catalog.d.ts +37 -2
  269. package/packages/core/dist/agents/catalog.d.ts.map +1 -1
  270. package/packages/core/dist/agents/catalog.js +49 -11
  271. package/packages/core/dist/agents/catalog.js.map +1 -1
  272. package/packages/core/dist/home.d.ts +30 -1
  273. package/packages/core/dist/home.d.ts.map +1 -1
  274. package/packages/core/dist/home.js +1 -1
  275. package/packages/core/dist/home.js.map +1 -1
  276. package/packages/core/dist/host/build.d.ts +7 -0
  277. package/packages/core/dist/host/build.d.ts.map +1 -1
  278. package/packages/core/dist/host/build.js +51 -4
  279. package/packages/core/dist/host/build.js.map +1 -1
  280. package/packages/core/dist/host/http.d.ts +32 -0
  281. package/packages/core/dist/host/http.d.ts.map +1 -1
  282. package/packages/core/dist/host/http.js +102 -2
  283. package/packages/core/dist/host/http.js.map +1 -1
  284. package/packages/core/dist/host/types.d.ts +8 -0
  285. package/packages/core/dist/host/types.d.ts.map +1 -1
  286. package/packages/core/dist/index.d.ts +1 -0
  287. package/packages/core/dist/index.d.ts.map +1 -1
  288. package/packages/core/dist/index.js +1 -0
  289. package/packages/core/dist/index.js.map +1 -1
  290. package/packages/core/dist/learning/announce.d.ts +1 -1
  291. package/packages/core/dist/notifications/focus.d.ts +42 -0
  292. package/packages/core/dist/notifications/focus.d.ts.map +1 -0
  293. package/packages/core/dist/notifications/focus.js +150 -0
  294. package/packages/core/dist/notifications/focus.js.map +1 -0
  295. package/packages/core/dist/notifications/index.d.ts +1 -0
  296. package/packages/core/dist/notifications/index.d.ts.map +1 -1
  297. package/packages/core/dist/notifications/index.js +1 -0
  298. package/packages/core/dist/notifications/index.js.map +1 -1
  299. package/packages/core/dist/notifications/notify.d.ts +66 -7
  300. package/packages/core/dist/notifications/notify.d.ts.map +1 -1
  301. package/packages/core/dist/notifications/notify.js +123 -38
  302. package/packages/core/dist/notifications/notify.js.map +1 -1
  303. package/packages/core/dist/notifications/store.d.ts +6 -4
  304. package/packages/core/dist/notifications/store.d.ts.map +1 -1
  305. package/packages/core/dist/notifications/store.js +24 -23
  306. package/packages/core/dist/notifications/store.js.map +1 -1
  307. package/packages/core/dist/notifications/types.d.ts +46 -3
  308. package/packages/core/dist/notifications/types.d.ts.map +1 -1
  309. package/packages/core/dist/notifications/types.js +12 -0
  310. package/packages/core/dist/notifications/types.js.map +1 -1
  311. package/packages/core/dist/pages.d.ts +186 -6
  312. package/packages/core/dist/pages.d.ts.map +1 -1
  313. package/packages/core/dist/pages.js +232 -13
  314. package/packages/core/dist/pages.js.map +1 -1
  315. package/packages/core/dist/plugin/author.d.ts +42 -0
  316. package/packages/core/dist/plugin/author.d.ts.map +1 -0
  317. package/packages/core/dist/plugin/author.js +77 -0
  318. package/packages/core/dist/plugin/author.js.map +1 -0
  319. package/packages/core/dist/plugin/index.d.ts +7 -3
  320. package/packages/core/dist/plugin/index.d.ts.map +1 -1
  321. package/packages/core/dist/plugin/index.js +3 -0
  322. package/packages/core/dist/plugin/index.js.map +1 -1
  323. package/packages/core/dist/plugin/version.d.ts +1 -1
  324. package/packages/core/dist/plugin/version.d.ts.map +1 -1
  325. package/packages/core/dist/plugin/version.js +1 -1
  326. package/packages/core/dist/plugin/version.js.map +1 -1
  327. package/packages/core/dist/plugins/record.d.ts +8 -0
  328. package/packages/core/dist/plugins/record.d.ts.map +1 -1
  329. package/packages/core/dist/plugins/record.js +17 -0
  330. package/packages/core/dist/plugins/record.js.map +1 -1
  331. package/packages/core/dist/plugins/types.d.ts +7 -0
  332. package/packages/core/dist/plugins/types.d.ts.map +1 -1
  333. package/packages/core/dist/plugins/types.js.map +1 -1
  334. package/packages/core/dist/registry.d.ts +11 -0
  335. package/packages/core/dist/registry.d.ts.map +1 -1
  336. package/packages/core/dist/registry.js +47 -6
  337. package/packages/core/dist/registry.js.map +1 -1
  338. package/packages/core/dist/scheduler/materialize.js +1 -1
  339. package/packages/core/dist/scheduler/missions.d.ts +10 -0
  340. package/packages/core/dist/scheduler/missions.d.ts.map +1 -1
  341. package/packages/core/dist/scheduler/missions.js +29 -1
  342. package/packages/core/dist/scheduler/missions.js.map +1 -1
  343. package/packages/core/dist/scheduler/types.d.ts +7 -0
  344. package/packages/core/dist/scheduler/types.d.ts.map +1 -1
  345. package/packages/core/dist/scheduler/types.js +1 -0
  346. package/packages/core/dist/scheduler/types.js.map +1 -1
  347. package/packages/core/dist/secrets/destinations.d.ts +2 -0
  348. package/packages/core/dist/secrets/destinations.d.ts.map +1 -1
  349. package/packages/core/dist/secrets/destinations.js +6 -0
  350. package/packages/core/dist/secrets/destinations.js.map +1 -1
  351. package/packages/core/dist/tools.d.ts +8 -0
  352. package/packages/core/dist/tools.d.ts.map +1 -1
  353. package/packages/core/dist/tools.js.map +1 -1
  354. package/packages/core/dist/views.d.ts +178 -3
  355. package/packages/core/dist/views.d.ts.map +1 -1
  356. package/packages/core/dist/views.js +56 -1
  357. package/packages/core/dist/views.js.map +1 -1
  358. package/packages/core/migrations/051_notification_focus.sql +20 -0
  359. package/packages/core/migrations/052_mission_paused_reason.sql +6 -0
  360. package/packages/gateway/dist/.tsbuildinfo +1 -1
  361. package/packages/gateway/dist/agents/catalog.d.ts +7 -0
  362. package/packages/gateway/dist/agents/catalog.d.ts.map +1 -1
  363. package/packages/gateway/dist/agents/catalog.js +18 -1
  364. package/packages/gateway/dist/agents/catalog.js.map +1 -1
  365. package/packages/gateway/dist/agents/starter-team.d.ts +2 -0
  366. package/packages/gateway/dist/agents/starter-team.d.ts.map +1 -1
  367. package/packages/gateway/dist/agents/starter-team.js +8 -3
  368. package/packages/gateway/dist/agents/starter-team.js.map +1 -1
  369. package/packages/gateway/dist/index.d.ts +1 -1
  370. package/packages/gateway/dist/index.d.ts.map +1 -1
  371. package/packages/gateway/dist/index.js.map +1 -1
  372. package/packages/gateway/dist/missions-cli.d.ts.map +1 -1
  373. package/packages/gateway/dist/missions-cli.js +6 -3
  374. package/packages/gateway/dist/missions-cli.js.map +1 -1
  375. package/packages/gateway/dist/plugins/approve.d.ts.map +1 -1
  376. package/packages/gateway/dist/plugins/approve.js +9 -2
  377. package/packages/gateway/dist/plugins/approve.js.map +1 -1
  378. package/packages/gateway/dist/plugins/index.d.ts +1 -0
  379. package/packages/gateway/dist/plugins/index.d.ts.map +1 -1
  380. package/packages/gateway/dist/plugins/index.js +1 -0
  381. package/packages/gateway/dist/plugins/index.js.map +1 -1
  382. package/packages/gateway/dist/plugins/live.d.ts +42 -0
  383. package/packages/gateway/dist/plugins/live.d.ts.map +1 -0
  384. package/packages/gateway/dist/plugins/live.js +81 -0
  385. package/packages/gateway/dist/plugins/live.js.map +1 -0
  386. package/packages/gateway/dist/plugins/load.d.ts +5 -0
  387. package/packages/gateway/dist/plugins/load.d.ts.map +1 -1
  388. package/packages/gateway/dist/plugins/load.js +10 -1
  389. package/packages/gateway/dist/plugins/load.js.map +1 -1
  390. package/packages/gateway/dist/plugins/provenance.d.ts.map +1 -1
  391. package/packages/gateway/dist/plugins/provenance.js +10 -3
  392. package/packages/gateway/dist/plugins/provenance.js.map +1 -1
  393. package/packages/gateway/dist/plugins/scaffold.d.ts +8 -0
  394. package/packages/gateway/dist/plugins/scaffold.d.ts.map +1 -1
  395. package/packages/gateway/dist/plugins/scaffold.js +46 -7
  396. package/packages/gateway/dist/plugins/scaffold.js.map +1 -1
  397. package/packages/gateway/dist/plugins/stage.d.ts +6 -1
  398. package/packages/gateway/dist/plugins/stage.d.ts.map +1 -1
  399. package/packages/gateway/dist/plugins/stage.js +3 -1
  400. package/packages/gateway/dist/plugins/stage.js.map +1 -1
  401. package/packages/gateway/dist/plugins/toggle.d.ts +37 -0
  402. package/packages/gateway/dist/plugins/toggle.d.ts.map +1 -0
  403. package/packages/gateway/dist/plugins/toggle.js +110 -0
  404. package/packages/gateway/dist/plugins/toggle.js.map +1 -0
  405. package/packages/gateway/dist/plugins-cli.d.ts +61 -6
  406. package/packages/gateway/dist/plugins-cli.d.ts.map +1 -1
  407. package/packages/gateway/dist/plugins-cli.js +247 -20
  408. package/packages/gateway/dist/plugins-cli.js.map +1 -1
  409. package/packages/gateway/dist/serve.js +3 -3
  410. package/packages/gateway/dist/serve.js.map +1 -1
  411. package/packages/gateway/dist/speech-cli.d.ts +13 -0
  412. package/packages/gateway/dist/speech-cli.d.ts.map +1 -1
  413. package/packages/gateway/dist/speech-cli.js +40 -1
  414. package/packages/gateway/dist/speech-cli.js.map +1 -1
  415. package/packages/gateway/dist/telegram/focus.d.ts +27 -0
  416. package/packages/gateway/dist/telegram/focus.d.ts.map +1 -0
  417. package/packages/gateway/dist/telegram/focus.js +72 -0
  418. package/packages/gateway/dist/telegram/focus.js.map +1 -0
  419. package/packages/gateway/dist/telegram/main.d.ts.map +1 -1
  420. package/packages/gateway/dist/telegram/main.js +1 -0
  421. package/packages/gateway/dist/telegram/main.js.map +1 -1
  422. package/packages/gateway/dist/telegram/surface.d.ts +2 -0
  423. package/packages/gateway/dist/telegram/surface.d.ts.map +1 -1
  424. package/packages/gateway/dist/telegram/surface.js +24 -1
  425. package/packages/gateway/dist/telegram/surface.js.map +1 -1
  426. package/packages/gateway/dist/tips/rules.d.ts +2 -0
  427. package/packages/gateway/dist/tips/rules.d.ts.map +1 -1
  428. package/packages/gateway/dist/tips/rules.js +10 -0
  429. package/packages/gateway/dist/tips/rules.js.map +1 -1
  430. package/packages/gateway/dist/web/agent-offers.js +1 -1
  431. package/packages/gateway/dist/web/agent-offers.js.map +1 -1
  432. package/packages/gateway/dist/web/folders.d.ts +23 -0
  433. package/packages/gateway/dist/web/folders.d.ts.map +1 -0
  434. package/packages/gateway/dist/web/folders.js +100 -0
  435. package/packages/gateway/dist/web/folders.js.map +1 -0
  436. package/packages/gateway/dist/web/market.d.ts +111 -0
  437. package/packages/gateway/dist/web/market.d.ts.map +1 -0
  438. package/packages/gateway/dist/web/market.js +347 -0
  439. package/packages/gateway/dist/web/market.js.map +1 -0
  440. package/packages/gateway/dist/web/notifications.d.ts +8 -1
  441. package/packages/gateway/dist/web/notifications.d.ts.map +1 -1
  442. package/packages/gateway/dist/web/notifications.js +23 -1
  443. package/packages/gateway/dist/web/notifications.js.map +1 -1
  444. package/packages/gateway/dist/web/plugins.d.ts +38 -3
  445. package/packages/gateway/dist/web/plugins.d.ts.map +1 -1
  446. package/packages/gateway/dist/web/plugins.js +73 -5
  447. package/packages/gateway/dist/web/plugins.js.map +1 -1
  448. package/packages/gateway/dist/web/profile.d.ts +2 -0
  449. package/packages/gateway/dist/web/profile.d.ts.map +1 -1
  450. package/packages/gateway/dist/web/profile.js +2 -1
  451. package/packages/gateway/dist/web/profile.js.map +1 -1
  452. package/packages/gateway/dist/web/rail.d.ts +33 -0
  453. package/packages/gateway/dist/web/rail.d.ts.map +1 -0
  454. package/packages/gateway/dist/web/rail.js +45 -0
  455. package/packages/gateway/dist/web/rail.js.map +1 -0
  456. package/packages/gateway/dist/web/read.d.ts +46 -0
  457. package/packages/gateway/dist/web/read.d.ts.map +1 -1
  458. package/packages/gateway/dist/web/read.js +78 -2
  459. package/packages/gateway/dist/web/read.js.map +1 -1
  460. package/packages/gateway/dist/web/server.d.ts.map +1 -1
  461. package/packages/gateway/dist/web/server.js +68 -6
  462. package/packages/gateway/dist/web/server.js.map +1 -1
  463. package/packages/gateway/dist/web/svg.d.ts +23 -0
  464. package/packages/gateway/dist/web/svg.d.ts.map +1 -0
  465. package/packages/gateway/dist/web/svg.js +125 -0
  466. package/packages/gateway/dist/web/svg.js.map +1 -0
  467. package/packages/gateway/src/agents/starter/planner/agent.md +2 -2
  468. package/packages/gateway/src/agents/starter/planner/skills/writing-the-morning-brief.md +18 -11
  469. package/packages/install/dist/.tsbuildinfo +1 -1
  470. package/packages/runtime/dist/.tsbuildinfo +1 -1
  471. package/packages/tools/artifacts/dist/.tsbuildinfo +1 -1
  472. package/packages/tools/browser/dist/.tsbuildinfo +1 -1
  473. package/packages/tools/email/dist/.tsbuildinfo +1 -1
  474. package/packages/tools/host/dist/.tsbuildinfo +1 -1
  475. package/packages/tools/mcp/dist/.tsbuildinfo +1 -1
  476. package/packages/tools/memory/dist/.tsbuildinfo +1 -1
  477. package/packages/tools/web/dist/.tsbuildinfo +1 -1
  478. package/packages/web/dist/assets/index-C-NAQ_MT.css +1 -0
  479. package/packages/web/dist/assets/index-DzFS39N3.js +125 -0
  480. package/packages/web/dist/assets/{lottie_light-BCNsQpt8.js → lottie_light-D7STH9tF.js} +1 -1
  481. package/packages/web/dist/build.json +1 -1
  482. package/packages/web/dist/index.html +2 -2
  483. package/packages/web/dist/precache.json +4 -4
  484. package/packages/web/dist/sw.js +8 -1
  485. package/packages/web/dist/assets/index-CBEdA2dN.js +0 -125
  486. package/packages/web/dist/assets/index-Ddp9egOQ.css +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"folders.d.ts","sourceRoot":"","sources":["../../src/web/folders.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,iEAAiE;AACjE,eAAO,MAAM,WAAW,MAAM,CAAC;AAE/B,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,qDAAqD;IACrD,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,mDAAmD;IACnD,SAAS,CAAC,EAAE,IAAI,CAAC;CAClB;AAED,oFAAoF;AACpF,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAOrD;AAeD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,EAAE,GAAG,EAAE,GAAG,GAAG,UAAU,CAkD/E"}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * `GET /api/plugins/folders?path=<absolute path>` — the folders on the
3
+ * gateway's machine, for "A directory I built".
4
+ *
5
+ * The page cannot browse the machine buddi runs on (a browser's own folder
6
+ * picker gives no path, and the browser may be on a phone), so this lists one
7
+ * folder's subfolders by name and says which of them hold a package.json. It
8
+ * starts at the owner's home directory and refuses anything outside it, the
9
+ * way the folder the owner builds a plugin in always is. Hidden folders are
10
+ * left out of the list; a path that names one explicitly is still answered,
11
+ * because the owner typed it.
12
+ *
13
+ * Names and one existence check each: nothing is read, nothing is written,
14
+ * and nothing leaves the machine.
15
+ */
16
+ import { existsSync, readdirSync, realpathSync, statSync } from 'node:fs';
17
+ import { homedir } from 'node:os';
18
+ import path from 'node:path';
19
+ /** More than this in one folder and the list says it stopped. */
20
+ export const MAX_FOLDERS = 500;
21
+ /** The owner's home directory: `HOME` as the gateway was started, else the OS's. */
22
+ export function homeOf(env) {
23
+ const home = env.HOME?.trim() || homedir();
24
+ try {
25
+ return realpathSync(home);
26
+ }
27
+ catch {
28
+ return path.resolve(home);
29
+ }
30
+ }
31
+ function inside(root, candidate) {
32
+ const rel = path.relative(root, candidate);
33
+ return rel === '' || (!rel.startsWith('..') && !path.isAbsolute(rel));
34
+ }
35
+ function isDirectory(full) {
36
+ try {
37
+ return statSync(full).isDirectory();
38
+ }
39
+ catch {
40
+ return false;
41
+ }
42
+ }
43
+ export function pluginFoldersRoute(env, url) {
44
+ const home = homeOf(env);
45
+ const asked = url.searchParams.get('path')?.trim() || home;
46
+ if (!path.isAbsolute(asked)) {
47
+ return { status: 400, body: { error: 'Give the whole path, starting at /.' } };
48
+ }
49
+ let real;
50
+ try {
51
+ real = realpathSync(path.resolve(asked));
52
+ }
53
+ catch {
54
+ return { status: 404, body: { error: `There is no folder at ${asked}.` } };
55
+ }
56
+ // Checked after links are followed: a link out of the home directory is outside it.
57
+ if (!inside(home, real)) {
58
+ return { status: 403, body: { error: 'Only folders inside your home directory are listed here.' } };
59
+ }
60
+ if (!isDirectory(real)) {
61
+ return { status: 400, body: { error: `${asked} is a file, not a folder.` } };
62
+ }
63
+ let names;
64
+ try {
65
+ names = readdirSync(real);
66
+ }
67
+ catch (err) {
68
+ const code = err.code;
69
+ return {
70
+ status: 403,
71
+ body: { error: code === 'EACCES' || code === 'EPERM' ? `buddi may not read ${real}.` : `${real} could not be read.` },
72
+ };
73
+ }
74
+ const folders = [];
75
+ for (const name of names.sort((a, b) => a.localeCompare(b, undefined, { sensitivity: 'base' }))) {
76
+ if (name.startsWith('.'))
77
+ continue;
78
+ const full = path.join(real, name);
79
+ if (!isDirectory(full))
80
+ continue;
81
+ // A link that leads out of the home directory is not offered as a way in.
82
+ try {
83
+ if (!inside(home, realpathSync(full)))
84
+ continue;
85
+ }
86
+ catch {
87
+ continue;
88
+ }
89
+ folders.push({ name, path: full, plugin: existsSync(path.join(full, 'package.json')) });
90
+ }
91
+ const view = {
92
+ path: real,
93
+ parent: real === home ? null : path.dirname(real),
94
+ home,
95
+ folders: folders.slice(0, MAX_FOLDERS),
96
+ ...(folders.length > MAX_FOLDERS ? { truncated: true } : {}),
97
+ };
98
+ return { status: 200, body: view };
99
+ }
100
+ //# sourceMappingURL=folders.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"folders.js","sourceRoot":"","sources":["../../src/web/folders.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC1E,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,iEAAiE;AACjE,MAAM,CAAC,MAAM,WAAW,GAAG,GAAG,CAAC;AAoB/B,oFAAoF;AACpF,MAAM,UAAU,MAAM,CAAC,GAAsB;IAC3C,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,OAAO,EAAE,CAAC;IAC3C,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;AACH,CAAC;AAED,SAAS,MAAM,CAAC,IAAY,EAAE,SAAiB;IAC7C,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAC3C,OAAO,GAAG,KAAK,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;AACxE,CAAC;AAED,SAAS,WAAW,CAAC,IAAY;IAC/B,IAAI,CAAC;QACH,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,GAAsB,EAAE,GAAQ;IACjE,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IACzB,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC;IAC3D,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,qCAAqC,EAAE,EAAE,CAAC;IACjF,CAAC;IACD,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACH,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,yBAAyB,KAAK,GAAG,EAAE,EAAE,CAAC;IAC7E,CAAC;IACD,oFAAoF;IACpF,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;QACxB,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,0DAA0D,EAAE,EAAE,CAAC;IACtG,CAAC;IACD,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;QACvB,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,GAAG,KAAK,2BAA2B,EAAE,EAAE,CAAC;IAC/E,CAAC;IACD,IAAI,KAAe,CAAC;IACpB,IAAI,CAAC;QACH,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,GAAI,GAA6B,CAAC,IAAI,CAAC;QACjD,OAAO;YACL,MAAM,EAAE,GAAG;YACX,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,sBAAsB,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,qBAAqB,EAAE;SACtH,CAAC;IACJ,CAAC;IACD,MAAM,OAAO,GAAkB,EAAE,CAAC;IAClC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC;QAChG,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QACnC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACnC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;YAAE,SAAS;QACjC,0EAA0E;QAC1E,IAAI,CAAC;YACH,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC;gBAAE,SAAS;QAClD,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC;IAC1F,CAAC;IACD,MAAM,IAAI,GAAgB;QACxB,IAAI,EAAE,IAAI;QACV,MAAM,EAAE,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;QACjD,IAAI;QACJ,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC;QACtC,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACtE,CAAC;IACF,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACrC,CAAC"}
@@ -0,0 +1,111 @@
1
+ import { z } from 'zod';
2
+ import { type InstalledPlugin } from '@buddi/core';
3
+ import { type RouteReply } from './plugins.js';
4
+ export declare const MARKET_ORIGIN = "https://withbuddi.com";
5
+ /** How long a fetched list is trusted before Browse asks again. The pictures keep a day. */
6
+ export declare const MARKET_TTL_MS: number;
7
+ export declare const MARKET_ASSET_TTL_MS: number;
8
+ export declare const MARKET_TIMEOUT_MS = 10000;
9
+ export declare const MARKET_CATEGORIES: readonly ["days", "money", "home", "voice", "work", "other"];
10
+ /**
11
+ * One listing. Only what Browse relies on is checked; every other field the
12
+ * site writes is kept as it came, so a newer index still reaches the page.
13
+ */
14
+ declare const entrySchema: z.ZodObject<{
15
+ name: z.ZodString;
16
+ npm: z.ZodString;
17
+ version: z.ZodString;
18
+ title: z.ZodString;
19
+ summary: z.ZodString;
20
+ category: z.ZodCatch<z.ZodEnum<["days", "money", "home", "voice", "work", "other"]>>;
21
+ trust: z.ZodEnum<["by-buddi", "reviewed"]>;
22
+ pricing: z.ZodCatch<z.ZodObject<{
23
+ kind: z.ZodEnum<["free", "paid", "subscription"]>;
24
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
25
+ kind: z.ZodEnum<["free", "paid", "subscription"]>;
26
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
27
+ kind: z.ZodEnum<["free", "paid", "subscription"]>;
28
+ }, z.ZodTypeAny, "passthrough">>>;
29
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
30
+ name: z.ZodString;
31
+ npm: z.ZodString;
32
+ version: z.ZodString;
33
+ title: z.ZodString;
34
+ summary: z.ZodString;
35
+ category: z.ZodCatch<z.ZodEnum<["days", "money", "home", "voice", "work", "other"]>>;
36
+ trust: z.ZodEnum<["by-buddi", "reviewed"]>;
37
+ pricing: z.ZodCatch<z.ZodObject<{
38
+ kind: z.ZodEnum<["free", "paid", "subscription"]>;
39
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
40
+ kind: z.ZodEnum<["free", "paid", "subscription"]>;
41
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
42
+ kind: z.ZodEnum<["free", "paid", "subscription"]>;
43
+ }, z.ZodTypeAny, "passthrough">>>;
44
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
45
+ name: z.ZodString;
46
+ npm: z.ZodString;
47
+ version: z.ZodString;
48
+ title: z.ZodString;
49
+ summary: z.ZodString;
50
+ category: z.ZodCatch<z.ZodEnum<["days", "money", "home", "voice", "work", "other"]>>;
51
+ trust: z.ZodEnum<["by-buddi", "reviewed"]>;
52
+ pricing: z.ZodCatch<z.ZodObject<{
53
+ kind: z.ZodEnum<["free", "paid", "subscription"]>;
54
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
55
+ kind: z.ZodEnum<["free", "paid", "subscription"]>;
56
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
57
+ kind: z.ZodEnum<["free", "paid", "subscription"]>;
58
+ }, z.ZodTypeAny, "passthrough">>>;
59
+ }, z.ZodTypeAny, "passthrough">>;
60
+ export type MarketEntry = z.infer<typeof entrySchema>;
61
+ export interface MarketIndex {
62
+ generatedAt?: string;
63
+ plugins: MarketEntry[];
64
+ }
65
+ export interface MarketDeps {
66
+ env: NodeJS.ProcessEnv;
67
+ log: (line: string) => void;
68
+ /** Injected by tests that want no socket at all; the gateway uses the global. */
69
+ fetch?: typeof fetch;
70
+ now?: () => Date;
71
+ }
72
+ /** For tests: forget the in-memory copies. */
73
+ export declare function resetMarketCache(): void;
74
+ export declare function marketFile(env: NodeJS.ProcessEnv): string;
75
+ export declare function marketUrl(env: NodeJS.ProcessEnv): string;
76
+ /** The index as buddi keeps it: shape checked, bad entries left out and said so. */
77
+ export declare function parseMarketIndex(value: unknown, log?: (line: string) => void): MarketIndex;
78
+ export declare function annotateMarket(plugins: readonly MarketEntry[], record: readonly InstalledPlugin[]): Array<Record<string, unknown>>;
79
+ /** Where every listing's files live; nothing outside it is fetched for the page. */
80
+ export declare const MARKET_ASSET_PREFIX = "https://withbuddi.com/plugins/";
81
+ /** A screenshot is a few hundred kilobytes; this is room and no more. */
82
+ export declare const MAX_ASSET_BYTES: number;
83
+ /** The URL, when it is a listing's file; `undefined` for anything else. */
84
+ export declare function marketAssetUrl(env: NodeJS.ProcessEnv, raw: string | null | undefined): URL | undefined;
85
+ interface Asset {
86
+ bytes: Buffer;
87
+ type: string;
88
+ fetchedAt: string;
89
+ }
90
+ /**
91
+ * One listing's file: from the copy beside the index while it is under a day
92
+ * old, else fetched and kept. A fetch that fails with a copy on hand answers
93
+ * the copy; with none, it throws.
94
+ */
95
+ export declare function marketAsset(deps: MarketDeps, url: URL): Promise<Asset>;
96
+ /** A reply that is a file rather than JSON. */
97
+ export interface AssetReply {
98
+ status: number;
99
+ body?: unknown;
100
+ bytes?: Buffer;
101
+ type?: string;
102
+ }
103
+ /**
104
+ * `GET /api/market/asset?url=<a listing's file>` — a screenshot for the
105
+ * detail sheet. An SVG goes out only as the sanitiser re-wrote it.
106
+ */
107
+ export declare function marketAssetRoute(deps: MarketDeps, url: URL): Promise<AssetReply>;
108
+ /** `GET /api/market[?refresh=1]`. */
109
+ export declare function marketRoute(deps: MarketDeps, url: URL): Promise<RouteReply>;
110
+ export {};
111
+ //# sourceMappingURL=market.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"market.d.ts","sourceRoot":"","sources":["../../src/web/market.ts"],"names":[],"mappings":"AAgCA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAmC,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AACpF,OAAO,EAA8B,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAG3E,eAAO,MAAM,aAAa,0BAA0B,CAAC;AACrD,4FAA4F;AAC5F,eAAO,MAAM,aAAa,QAAiB,CAAC;AAC5C,eAAO,MAAM,mBAAmB,QAAsB,CAAC;AACvD,eAAO,MAAM,iBAAiB,QAAS,CAAC;AAExC,eAAO,MAAM,iBAAiB,8DAA+D,CAAC;AAE9F;;;GAGG;AACH,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCAcD,CAAC;AASjB,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEtD,MAAM,WAAW,WAAW;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB;AAOD,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,iFAAiF;IACjF,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;CAClB;AAKD,8CAA8C;AAC9C,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAEzD;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAGxD;AAED,oFAAoF;AACpF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAe,GAAG,WAAW,CAYpG;AA2DD,wBAAgB,cAAc,CAC5B,OAAO,EAAE,SAAS,WAAW,EAAE,EAC/B,MAAM,EAAE,SAAS,eAAe,EAAE,GACjC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAWhC;AAMD,oFAAoF;AACpF,eAAO,MAAM,mBAAmB,mCAA8B,CAAC;AAC/D,yEAAyE;AACzE,eAAO,MAAM,eAAe,QAAkB,CAAC;AAgB/C,2EAA2E;AAC3E,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,GAAG,GAAG,SAAS,CAatG;AAED,UAAU,KAAK;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AA6CD;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,CAY5E;AAED,+CAA+C;AAC/C,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,UAAU,CAAC,CAgBtF;AAgBD,qCAAqC;AACrC,wBAAsB,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,UAAU,CAAC,CAwCjF"}
@@ -0,0 +1,347 @@
1
+ /**
2
+ * `GET /api/market` — the plugin list from withbuddi.com, for Browse.
3
+ *
4
+ * The page never reaches the internet itself: it asks this route, and this
5
+ * route fetches `<origin>/plugins/index.json` only when it is asked — which is
6
+ * when the owner opens the Browse tab. Nothing fetches it at start or on a
7
+ * timer. It is one of the few things that leave the machine, and the docs list
8
+ * it as that: "the plugin list from withbuddi.com, when you open Browse".
9
+ *
10
+ * The answer is kept a day, in memory and on disk under the data directory, so
11
+ * opening Browse twice does not ask twice. A fetch that fails with a copy on
12
+ * hand answers the copy, marked `stale`; one that fails with nothing answers
13
+ * an empty list and the sentence, still with a 200, because "withbuddi.com did
14
+ * not answer" is something the page shows, not an error in the gateway.
15
+ *
16
+ * Each entry is annotated against the installed record: `installed` when a
17
+ * plugin of that npm name (or buddi name) is here, `update` when the listed
18
+ * version is newer, and `usesWords` in the same words the staged card uses.
19
+ * Nothing about installing changes: Install on the page stages the spec, and
20
+ * the staged card and its approvals are the ones every install goes through.
21
+ *
22
+ * The listings' pictures come through here too: `GET /api/market/asset?url=`
23
+ * fetches a file under `https://withbuddi.com/plugins/` (a screenshot) and
24
+ * keeps it beside the index, so the page never reaches the internet itself.
25
+ * Each listing's icon is read the same way while the list is answered and
26
+ * passed on as `iconSvg`, sanitised to plain shapes (`svg.ts`), so the page can
27
+ * draw it inline in the colour of its tile. Both happen only on the way to
28
+ * Browse, which is already the one time the market is asked anything.
29
+ */
30
+ import { createHash } from 'node:crypto';
31
+ import { mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
32
+ import path from 'node:path';
33
+ import { z } from 'zod';
34
+ import { compareVersions, resolveDataDir } from '@buddi/core';
35
+ import { installedRecord, usesWords } from './plugins.js';
36
+ import { sanitizeIconSvg } from './svg.js';
37
+ export const MARKET_ORIGIN = 'https://withbuddi.com';
38
+ /** How long a fetched list is trusted before Browse asks again. The pictures keep a day. */
39
+ export const MARKET_TTL_MS = 60 * 60 * 1000;
40
+ export const MARKET_ASSET_TTL_MS = 24 * 60 * 60 * 1000;
41
+ export const MARKET_TIMEOUT_MS = 10_000;
42
+ export const MARKET_CATEGORIES = ['days', 'money', 'home', 'voice', 'work', 'other'];
43
+ /**
44
+ * One listing. Only what Browse relies on is checked; every other field the
45
+ * site writes is kept as it came, so a newer index still reaches the page.
46
+ */
47
+ const entrySchema = z
48
+ .object({
49
+ name: z.string().min(1),
50
+ npm: z.string().min(1),
51
+ version: z.string().min(1),
52
+ title: z.string().min(1),
53
+ summary: z.string(),
54
+ category: z.enum(MARKET_CATEGORIES).catch('other'),
55
+ trust: z.enum(['by-buddi', 'reviewed']),
56
+ pricing: z
57
+ .object({ kind: z.enum(['free', 'paid', 'subscription']) })
58
+ .passthrough()
59
+ .catch({ kind: 'free' }),
60
+ })
61
+ .passthrough();
62
+ const indexSchema = z
63
+ .object({
64
+ generatedAt: z.string().optional(),
65
+ plugins: z.array(z.unknown()),
66
+ })
67
+ .passthrough();
68
+ /** Keyed by the file on disk, so two data directories never share a copy. */
69
+ const memory = new Map();
70
+ /** For tests: forget the in-memory copies. */
71
+ export function resetMarketCache() {
72
+ memory.clear();
73
+ }
74
+ export function marketFile(env) {
75
+ return path.join(resolveDataDir(env), 'market', 'index.json');
76
+ }
77
+ export function marketUrl(env) {
78
+ const origin = env.BUDDI_MARKET_URL?.trim() || MARKET_ORIGIN;
79
+ return `${origin.replace(/\/+$/, '')}/plugins/index.json`;
80
+ }
81
+ /** The index as buddi keeps it: shape checked, bad entries left out and said so. */
82
+ export function parseMarketIndex(value, log = () => { }) {
83
+ const index = indexSchema.parse(value);
84
+ const plugins = [];
85
+ for (const raw of index.plugins) {
86
+ const parsed = entrySchema.safeParse(raw);
87
+ if (parsed.success)
88
+ plugins.push(parsed.data);
89
+ else {
90
+ const name = typeof raw?.name === 'string' ? raw.name : '?';
91
+ log(`market: left out the listing "${name}": ${parsed.error.issues[0]?.message ?? 'not a listing'}`);
92
+ }
93
+ }
94
+ return { ...index, plugins };
95
+ }
96
+ function readDisk(file) {
97
+ try {
98
+ const parsed = JSON.parse(readFileSync(file, 'utf8'));
99
+ if (typeof parsed.fetchedAt !== 'string')
100
+ return undefined;
101
+ return { fetchedAt: parsed.fetchedAt, index: parseMarketIndex(parsed.index) };
102
+ }
103
+ catch {
104
+ return undefined;
105
+ }
106
+ }
107
+ function writeDisk(file, cached, log) {
108
+ try {
109
+ mkdirSync(path.dirname(file), { recursive: true });
110
+ const tmp = `${file}.${process.pid}.tmp`;
111
+ writeFileSync(tmp, `${JSON.stringify(cached, null, 2)}\n`);
112
+ renameSync(tmp, file);
113
+ }
114
+ catch (err) {
115
+ // The copy in memory still answers; a day's cache on disk is a convenience.
116
+ log(`market: could not keep the list on disk: ${err instanceof Error ? err.message : String(err)}`);
117
+ }
118
+ }
119
+ async function fetchIndex(deps) {
120
+ const doFetch = deps.fetch ?? fetch;
121
+ const url = marketUrl(deps.env);
122
+ const response = await doFetch(url, {
123
+ signal: AbortSignal.timeout(MARKET_TIMEOUT_MS),
124
+ headers: { accept: 'application/json' },
125
+ });
126
+ if (!response.ok)
127
+ throw new Error(`${url} answered ${response.status}`);
128
+ return parseMarketIndex(await response.json(), deps.log);
129
+ }
130
+ function reason(err) {
131
+ if (err instanceof Error && (err.name === 'TimeoutError' || err.name === 'AbortError')) {
132
+ return `it did not answer within ${MARKET_TIMEOUT_MS / 1000} seconds`;
133
+ }
134
+ if (err instanceof z.ZodError)
135
+ return 'what it answered is not a plugin list';
136
+ const cause = err instanceof Error && err.cause instanceof Error ? `: ${err.cause.message}` : '';
137
+ return `${err instanceof Error ? err.message : String(err)}${cause}`;
138
+ }
139
+ /** Which installed record, if any, is this listing. */
140
+ function installedAs(entry, record) {
141
+ return record.find((plugin) => plugin.name === entry.name || (plugin.source.kind === 'registry' && plugin.source.name === entry.npm));
142
+ }
143
+ /** The areas a listing reaches, from its claims, in the staged card's words. */
144
+ function listedUses(entry) {
145
+ const claims = entry.claims;
146
+ const uses = claims?.package?.uses ?? claims?.manifest?.uses;
147
+ return Array.isArray(uses) ? uses : [];
148
+ }
149
+ export function annotateMarket(plugins, record) {
150
+ return plugins.map((entry) => {
151
+ const here = installedAs(entry, record);
152
+ const newer = here !== undefined && (compareVersions(entry.version, here.version) ?? 0) > 0;
153
+ return {
154
+ ...entry,
155
+ usesWords: usesWords(listedUses(entry)),
156
+ ...(here === undefined ? {} : { installed: { version: here.version, name: here.name } }),
157
+ ...(newer ? { update: entry.version } : {}),
158
+ };
159
+ });
160
+ }
161
+ /* ------------------------------------------------------------------ *
162
+ * The listings' files: icons and screenshots
163
+ * ------------------------------------------------------------------ */
164
+ /** Where every listing's files live; nothing outside it is fetched for the page. */
165
+ export const MARKET_ASSET_PREFIX = `${MARKET_ORIGIN}/plugins/`;
166
+ /** A screenshot is a few hundred kilobytes; this is room and no more. */
167
+ export const MAX_ASSET_BYTES = 5 * 1024 * 1024;
168
+ /** What a listing's file may be. Anything else is not passed on. */
169
+ const ASSET_TYPES = new Set(['image/webp', 'image/png', 'image/jpeg', 'image/gif', 'image/svg+xml']);
170
+ /**
171
+ * The prefixes a file may be fetched from: withbuddi.com's, and the origin
172
+ * `BUDDI_MARKET_URL` names when set (a staging copy of the site), whose own
173
+ * files sit at the same place under it.
174
+ */
175
+ function assetPrefixes(env) {
176
+ const configured = env.BUDDI_MARKET_URL?.trim();
177
+ const prefixes = [MARKET_ASSET_PREFIX];
178
+ if (configured)
179
+ prefixes.push(`${configured.replace(/\/+$/, '')}/plugins/`);
180
+ return [...new Set(prefixes)];
181
+ }
182
+ /** The URL, when it is a listing's file; `undefined` for anything else. */
183
+ export function marketAssetUrl(env, raw) {
184
+ if (!raw)
185
+ return undefined;
186
+ let url;
187
+ try {
188
+ url = new URL(raw);
189
+ }
190
+ catch {
191
+ return undefined;
192
+ }
193
+ // Parsed, so `..` and encoded dots are resolved before the prefix is checked.
194
+ if (url.username || url.password || url.search || url.hash)
195
+ return undefined;
196
+ return assetPrefixes(env).some((prefix) => url.href.startsWith(prefix)) && url.href.length > url.origin.length + '/plugins/'.length
197
+ ? url
198
+ : undefined;
199
+ }
200
+ function assetPaths(env, url) {
201
+ const key = createHash('sha256').update(url.href).digest('hex');
202
+ const dir = path.join(path.dirname(marketFile(env)), 'assets');
203
+ return { bytes: path.join(dir, key), meta: path.join(dir, `${key}.json`) };
204
+ }
205
+ function readAsset(env, url) {
206
+ try {
207
+ const files = assetPaths(env, url);
208
+ const meta = JSON.parse(readFileSync(files.meta, 'utf8'));
209
+ if (meta.url !== url.href || typeof meta.type !== 'string' || typeof meta.fetchedAt !== 'string')
210
+ return undefined;
211
+ return { bytes: readFileSync(files.bytes), type: meta.type, fetchedAt: meta.fetchedAt };
212
+ }
213
+ catch {
214
+ return undefined;
215
+ }
216
+ }
217
+ function writeAsset(env, url, asset, log) {
218
+ try {
219
+ const files = assetPaths(env, url);
220
+ mkdirSync(path.dirname(files.bytes), { recursive: true });
221
+ const tmp = `${files.bytes}.${process.pid}.tmp`;
222
+ writeFileSync(tmp, asset.bytes);
223
+ renameSync(tmp, files.bytes);
224
+ writeFileSync(files.meta, `${JSON.stringify({ url: url.href, type: asset.type, fetchedAt: asset.fetchedAt })}\n`);
225
+ }
226
+ catch (err) {
227
+ log(`market: could not keep ${url.href} on disk: ${err instanceof Error ? err.message : String(err)}`);
228
+ }
229
+ }
230
+ async function fetchAsset(deps, url) {
231
+ const doFetch = deps.fetch ?? fetch;
232
+ const response = await doFetch(url.href, { signal: AbortSignal.timeout(MARKET_TIMEOUT_MS), redirect: 'error' });
233
+ if (!response.ok)
234
+ throw new Error(`${url.href} answered ${response.status}`);
235
+ const type = (response.headers.get('content-type') ?? '').split(';')[0]?.trim().toLowerCase() ?? '';
236
+ if (!ASSET_TYPES.has(type))
237
+ throw new Error(`${url.href} is not a picture (${type || 'no type'})`);
238
+ const declared = Number(response.headers.get('content-length') ?? '0');
239
+ if (declared > MAX_ASSET_BYTES)
240
+ throw new Error(`${url.href} is larger than a listing's picture should be`);
241
+ const bytes = Buffer.from(await response.arrayBuffer());
242
+ if (bytes.length > MAX_ASSET_BYTES)
243
+ throw new Error(`${url.href} is larger than a listing's picture should be`);
244
+ return { bytes, type };
245
+ }
246
+ /**
247
+ * One listing's file: from the copy beside the index while it is under a day
248
+ * old, else fetched and kept. A fetch that fails with a copy on hand answers
249
+ * the copy; with none, it throws.
250
+ */
251
+ export async function marketAsset(deps, url) {
252
+ const now = deps.now ?? (() => new Date());
253
+ const kept = readAsset(deps.env, url);
254
+ if (kept && now().getTime() - Date.parse(kept.fetchedAt) < MARKET_ASSET_TTL_MS)
255
+ return kept;
256
+ try {
257
+ const asset = { ...(await fetchAsset(deps, url)), fetchedAt: now().toISOString() };
258
+ writeAsset(deps.env, url, asset, deps.log);
259
+ return asset;
260
+ }
261
+ catch (err) {
262
+ if (kept)
263
+ return kept;
264
+ throw err;
265
+ }
266
+ }
267
+ /**
268
+ * `GET /api/market/asset?url=<a listing's file>` — a screenshot for the
269
+ * detail sheet. An SVG goes out only as the sanitiser re-wrote it.
270
+ */
271
+ export async function marketAssetRoute(deps, url) {
272
+ const target = marketAssetUrl(deps.env, url.searchParams.get('url'));
273
+ if (!target)
274
+ return { status: 400, body: { error: `Only a listing's own files, under ${MARKET_ASSET_PREFIX}, come through here.` } };
275
+ let asset;
276
+ try {
277
+ asset = await marketAsset(deps, target);
278
+ }
279
+ catch (err) {
280
+ deps.log(`market: fetching ${target.href} failed: ${reason(err)}`);
281
+ return { status: 502, body: { error: `buddi could not fetch that picture from withbuddi.com: ${reason(err)}` } };
282
+ }
283
+ if (asset.type === 'image/svg+xml') {
284
+ const svg = sanitizeIconSvg(asset.bytes.toString('utf8'));
285
+ if (svg === undefined)
286
+ return { status: 415, body: { error: 'That picture is not one buddi will draw.' } };
287
+ return { status: 200, bytes: Buffer.from(svg), type: asset.type };
288
+ }
289
+ return { status: 200, bytes: asset.bytes, type: asset.type };
290
+ }
291
+ /** A listing's icon, as markup the page may draw inline; `undefined` when there is none it will draw. */
292
+ async function iconSvgOf(deps, entry) {
293
+ const icon = entry.icon;
294
+ const url = typeof icon === 'string' ? marketAssetUrl(deps.env, icon) : undefined;
295
+ if (!url)
296
+ return undefined;
297
+ try {
298
+ const asset = await marketAsset(deps, url);
299
+ return asset.type === 'image/svg+xml' ? sanitizeIconSvg(asset.bytes.toString('utf8')) : undefined;
300
+ }
301
+ catch (err) {
302
+ deps.log(`market: the icon of "${entry.name}" was left out: ${reason(err)}`);
303
+ return undefined;
304
+ }
305
+ }
306
+ /** `GET /api/market[?refresh=1]`. */
307
+ export async function marketRoute(deps, url) {
308
+ const now = deps.now ?? (() => new Date());
309
+ const file = marketFile(deps.env);
310
+ const refresh = url.searchParams.get('refresh') === '1';
311
+ let cached = memory.get(file) ?? readDisk(file);
312
+ if (cached !== undefined)
313
+ memory.set(file, cached);
314
+ const fresh = cached !== undefined && now().getTime() - Date.parse(cached.fetchedAt) < MARKET_TTL_MS;
315
+ let stale = false;
316
+ if (refresh || !fresh) {
317
+ try {
318
+ const index = await fetchIndex(deps);
319
+ cached = { fetchedAt: now().toISOString(), index };
320
+ memory.set(file, cached);
321
+ writeDisk(file, cached, deps.log);
322
+ }
323
+ catch (err) {
324
+ const why = reason(err);
325
+ deps.log(`market: fetching the plugin list failed: ${why}`);
326
+ if (cached === undefined) {
327
+ return {
328
+ status: 200,
329
+ body: { plugins: [], unavailable: `buddi could not reach withbuddi.com: ${why}` },
330
+ };
331
+ }
332
+ stale = true;
333
+ }
334
+ }
335
+ const { plugins: record } = installedRecord(deps.env);
336
+ const listed = cached.index.plugins;
337
+ const icons = await Promise.all(listed.map((entry) => iconSvgOf(deps, entry)));
338
+ return {
339
+ status: 200,
340
+ body: {
341
+ fetchedAt: cached.fetchedAt,
342
+ ...(stale ? { stale: true } : {}),
343
+ plugins: annotateMarket(listed, record).map((entry, i) => icons[i] === undefined ? entry : { ...entry, iconSvg: icons[i] }),
344
+ },
345
+ };
346
+ }
347
+ //# sourceMappingURL=market.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"market.js","sourceRoot":"","sources":["../../src/web/market.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,8 @@
7
7
  * GET /api/notifications/settings the settings, and the channels there are
8
8
  * PUT /api/notifications/settings the whole settings value, replaced
9
9
  * POST /api/notifications/test { channel } one line through that channel, now
10
+ * GET /api/notifications/focus the focus in force now, or null
11
+ * PUT /api/notifications/focus { mode, duration } switch it; mode `normal` turns it off
10
12
  * POST /api/presence { state } `active` every 30 s while the page is
11
13
  * visible and focused; `away` on blur or hide
12
14
  *
@@ -14,7 +16,7 @@
14
16
  * stream is per conversation and opened only while a chat is on screen, and
15
17
  * the owner is present on Home and Settings too.
16
18
  */
17
- import { type Queryable } from '@buddi/core';
19
+ import { type NotifyDeps, type Queryable } from '@buddi/core';
18
20
  export interface NotificationsRouteReply {
19
21
  status: number;
20
22
  body: unknown;
@@ -33,4 +35,9 @@ export declare const TEST_MESSAGE_TITLE = "A test from buddi. This is where your
33
35
  * never shows in the last twenty or waits for the morning.
34
36
  */
35
37
  export declare function testChannelRoute(body: Record<string, unknown>, now: Date): Promise<NotificationsRouteReply>;
38
+ /**
39
+ * The owner menu's Focus: what is on now, or a switch to a mode for a
40
+ * duration (`1h`, `3h`, `tomorrow`, `indefinite`); `normal` turns it off.
41
+ */
42
+ export declare function focusRoute(pool: Queryable, deps: NotifyDeps, method: 'GET' | 'PUT', body?: unknown): Promise<NotificationsRouteReply>;
36
43
  //# sourceMappingURL=notifications.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../../src/web/notifications.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EASL,KAAK,SAAS,EACf,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;CACf;AAED,+DAA+D;AAC/D,eAAO,MAAM,oBAAoB,QAAQ,CAAC;AAE1C,wBAAsB,sBAAsB,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAGpH;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAI5G;AAED,wBAAsB,yBAAyB,CAC7C,IAAI,EAAE,SAAS,EACf,MAAM,EAAE,KAAK,GAAG,KAAK,EACrB,IAAI,CAAC,EAAE,OAAO,GACb,OAAO,CAAC,uBAAuB,CAAC,CAOlC;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,IAAI,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAK/H;AAED,6DAA6D;AAC7D,eAAO,MAAM,kBAAkB,gEAAgE,CAAC;AAEhG;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,IAAI,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAQjH"}
1
+ {"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../../src/web/notifications.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAWL,KAAK,UAAU,EACf,KAAK,SAAS,EACf,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;CACf;AAED,+DAA+D;AAC/D,eAAO,MAAM,oBAAoB,QAAQ,CAAC;AAE1C,wBAAsB,sBAAsB,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAGpH;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAI5G;AAED,wBAAsB,yBAAyB,CAC7C,IAAI,EAAE,SAAS,EACf,MAAM,EAAE,KAAK,GAAG,KAAK,EACrB,IAAI,CAAC,EAAE,OAAO,GACb,OAAO,CAAC,uBAAuB,CAAC,CAOlC;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,IAAI,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAK/H;AAED,6DAA6D;AAC7D,eAAO,MAAM,kBAAkB,gEAAgE,CAAC;AAEhG;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,IAAI,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAQjH;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,IAAI,EAAE,SAAS,EACf,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,KAAK,GAAG,KAAK,EACrB,IAAI,CAAC,EAAE,OAAO,GACb,OAAO,CAAC,uBAAuB,CAAC,CAalC"}