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

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 (600) hide show
  1. package/README.md +58 -368
  2. package/examples/agents/concierge/agent.md +10 -2
  3. package/extension/manifest.json +2 -2
  4. package/node_modules/@buddi/cli/dist/.tsbuildinfo +1 -1
  5. package/node_modules/@buddi/cli/dist/agents-catalogue-cmd.d.ts +50 -0
  6. package/node_modules/@buddi/cli/dist/agents-catalogue-cmd.d.ts.map +1 -0
  7. package/node_modules/@buddi/cli/dist/agents-catalogue-cmd.js +328 -0
  8. package/node_modules/@buddi/cli/dist/agents-catalogue-cmd.js.map +1 -0
  9. package/node_modules/@buddi/cli/dist/args.d.ts +5 -0
  10. package/node_modules/@buddi/cli/dist/args.d.ts.map +1 -1
  11. package/node_modules/@buddi/cli/dist/args.js +8 -0
  12. package/node_modules/@buddi/cli/dist/args.js.map +1 -1
  13. package/node_modules/@buddi/cli/dist/commands.d.ts.map +1 -1
  14. package/node_modules/@buddi/cli/dist/commands.js +63 -1
  15. package/node_modules/@buddi/cli/dist/commands.js.map +1 -1
  16. package/node_modules/@buddi/cli/dist/doctor-probes.d.ts.map +1 -1
  17. package/node_modules/@buddi/cli/dist/doctor-probes.js +4 -11
  18. package/node_modules/@buddi/cli/dist/doctor-probes.js.map +1 -1
  19. package/node_modules/@buddi/cli/dist/doctor.d.ts +16 -0
  20. package/node_modules/@buddi/cli/dist/doctor.d.ts.map +1 -1
  21. package/node_modules/@buddi/cli/dist/doctor.js +30 -0
  22. package/node_modules/@buddi/cli/dist/doctor.js.map +1 -1
  23. package/node_modules/@buddi/cli/dist/main.d.ts.map +1 -1
  24. package/node_modules/@buddi/cli/dist/main.js +44 -9
  25. package/node_modules/@buddi/cli/dist/main.js.map +1 -1
  26. package/node_modules/@buddi/cli/dist/mcp/tools.d.ts.map +1 -1
  27. package/node_modules/@buddi/cli/dist/mcp/tools.js +3 -1
  28. package/node_modules/@buddi/cli/dist/mcp/tools.js.map +1 -1
  29. package/node_modules/@buddi/cli/dist/skills-cmd.d.ts +15 -0
  30. package/node_modules/@buddi/cli/dist/skills-cmd.d.ts.map +1 -0
  31. package/node_modules/@buddi/cli/dist/skills-cmd.js +54 -0
  32. package/node_modules/@buddi/cli/dist/skills-cmd.js.map +1 -0
  33. package/node_modules/@buddi/cli/dist/status.d.ts +15 -9
  34. package/node_modules/@buddi/cli/dist/status.d.ts.map +1 -1
  35. package/node_modules/@buddi/cli/dist/status.js +6 -11
  36. package/node_modules/@buddi/cli/dist/status.js.map +1 -1
  37. package/node_modules/@buddi/core/dist/.tsbuildinfo +1 -1
  38. package/node_modules/@buddi/core/dist/actions/store.d.ts +8 -0
  39. package/node_modules/@buddi/core/dist/actions/store.d.ts.map +1 -1
  40. package/node_modules/@buddi/core/dist/actions/store.js +13 -0
  41. package/node_modules/@buddi/core/dist/actions/store.js.map +1 -1
  42. package/node_modules/@buddi/core/dist/agents/catalog.d.ts +11 -3
  43. package/node_modules/@buddi/core/dist/agents/catalog.d.ts.map +1 -1
  44. package/node_modules/@buddi/core/dist/agents/catalog.js +58 -10
  45. package/node_modules/@buddi/core/dist/agents/catalog.js.map +1 -1
  46. package/node_modules/@buddi/core/dist/agents/frontmatter.d.ts +1 -1
  47. package/node_modules/@buddi/core/dist/agents/frontmatter.d.ts.map +1 -1
  48. package/node_modules/@buddi/core/dist/agents/frontmatter.js +1 -1
  49. package/node_modules/@buddi/core/dist/agents/frontmatter.js.map +1 -1
  50. package/node_modules/@buddi/core/dist/agents/skills.d.ts +29 -3
  51. package/node_modules/@buddi/core/dist/agents/skills.d.ts.map +1 -1
  52. package/node_modules/@buddi/core/dist/agents/skills.js +49 -2
  53. package/node_modules/@buddi/core/dist/agents/skills.js.map +1 -1
  54. package/node_modules/@buddi/core/dist/clock-widget.d.ts.map +1 -1
  55. package/node_modules/@buddi/core/dist/clock-widget.js +5 -3
  56. package/node_modules/@buddi/core/dist/clock-widget.js.map +1 -1
  57. package/node_modules/@buddi/core/dist/host/build.d.ts.map +1 -1
  58. package/node_modules/@buddi/core/dist/host/build.js +11 -0
  59. package/node_modules/@buddi/core/dist/host/build.js.map +1 -1
  60. package/node_modules/@buddi/core/dist/host/types.d.ts +7 -0
  61. package/node_modules/@buddi/core/dist/host/types.d.ts.map +1 -1
  62. package/node_modules/@buddi/core/dist/learning/store.d.ts +7 -0
  63. package/node_modules/@buddi/core/dist/learning/store.d.ts.map +1 -1
  64. package/node_modules/@buddi/core/dist/learning/store.js +6 -0
  65. package/node_modules/@buddi/core/dist/learning/store.js.map +1 -1
  66. package/node_modules/@buddi/core/dist/notifications/agent.d.ts +7 -0
  67. package/node_modules/@buddi/core/dist/notifications/agent.d.ts.map +1 -1
  68. package/node_modules/@buddi/core/dist/notifications/agent.js +2 -0
  69. package/node_modules/@buddi/core/dist/notifications/agent.js.map +1 -1
  70. package/node_modules/@buddi/core/dist/notifications/index.d.ts +1 -0
  71. package/node_modules/@buddi/core/dist/notifications/index.d.ts.map +1 -1
  72. package/node_modules/@buddi/core/dist/notifications/index.js +1 -0
  73. package/node_modules/@buddi/core/dist/notifications/index.js.map +1 -1
  74. package/node_modules/@buddi/core/dist/notifications/needs.d.ts +49 -0
  75. package/node_modules/@buddi/core/dist/notifications/needs.d.ts.map +1 -0
  76. package/node_modules/@buddi/core/dist/notifications/needs.js +41 -0
  77. package/node_modules/@buddi/core/dist/notifications/needs.js.map +1 -0
  78. package/node_modules/@buddi/core/dist/notifications/notify.d.ts.map +1 -1
  79. package/node_modules/@buddi/core/dist/notifications/notify.js +16 -7
  80. package/node_modules/@buddi/core/dist/notifications/notify.js.map +1 -1
  81. package/node_modules/@buddi/core/dist/notifications/store.d.ts.map +1 -1
  82. package/node_modules/@buddi/core/dist/notifications/store.js +2 -1
  83. package/node_modules/@buddi/core/dist/notifications/store.js.map +1 -1
  84. package/node_modules/@buddi/core/dist/notifications/types.d.ts +10 -0
  85. package/node_modules/@buddi/core/dist/notifications/types.d.ts.map +1 -1
  86. package/node_modules/@buddi/core/dist/notifications/types.js.map +1 -1
  87. package/node_modules/@buddi/core/dist/offers/store.d.ts.map +1 -1
  88. package/node_modules/@buddi/core/dist/offers/store.js +9 -4
  89. package/node_modules/@buddi/core/dist/offers/store.js.map +1 -1
  90. package/node_modules/@buddi/core/dist/offers/types.d.ts +24 -1
  91. package/node_modules/@buddi/core/dist/offers/types.d.ts.map +1 -1
  92. package/node_modules/@buddi/core/dist/offers/types.js +23 -1
  93. package/node_modules/@buddi/core/dist/offers/types.js.map +1 -1
  94. package/node_modules/@buddi/core/dist/owner-timezone.d.ts +20 -22
  95. package/node_modules/@buddi/core/dist/owner-timezone.d.ts.map +1 -1
  96. package/node_modules/@buddi/core/dist/owner-timezone.js +17 -25
  97. package/node_modules/@buddi/core/dist/owner-timezone.js.map +1 -1
  98. package/node_modules/@buddi/core/dist/plugin/version.d.ts +1 -1
  99. package/node_modules/@buddi/core/dist/plugin/version.js +1 -1
  100. package/node_modules/@buddi/core/dist/scheduler/missions.d.ts +86 -11
  101. package/node_modules/@buddi/core/dist/scheduler/missions.d.ts.map +1 -1
  102. package/node_modules/@buddi/core/dist/scheduler/missions.js +160 -36
  103. package/node_modules/@buddi/core/dist/scheduler/missions.js.map +1 -1
  104. package/node_modules/@buddi/core/dist/scheduler/runner.d.ts.map +1 -1
  105. package/node_modules/@buddi/core/dist/scheduler/runner.js +6 -1
  106. package/node_modules/@buddi/core/dist/scheduler/runner.js.map +1 -1
  107. package/node_modules/@buddi/core/dist/scheduler/types.d.ts +22 -0
  108. package/node_modules/@buddi/core/dist/scheduler/types.d.ts.map +1 -1
  109. package/node_modules/@buddi/core/dist/scheduler/types.js +6 -0
  110. package/node_modules/@buddi/core/dist/scheduler/types.js.map +1 -1
  111. package/node_modules/@buddi/core/dist/web-settings.d.ts +13 -0
  112. package/node_modules/@buddi/core/dist/web-settings.d.ts.map +1 -1
  113. package/node_modules/@buddi/core/dist/web-settings.js +26 -0
  114. package/node_modules/@buddi/core/dist/web-settings.js.map +1 -1
  115. package/node_modules/@buddi/core/dist/widgets.d.ts +13 -5
  116. package/node_modules/@buddi/core/dist/widgets.d.ts.map +1 -1
  117. package/node_modules/@buddi/core/dist/widgets.js +10 -1
  118. package/node_modules/@buddi/core/dist/widgets.js.map +1 -1
  119. package/node_modules/@buddi/core/migrations/068_notification_action.sql +12 -0
  120. package/node_modules/@buddi/core/migrations/069_schedule_zone_explicit.sql +18 -0
  121. package/node_modules/@buddi/core/migrations/070_offer_handoff.sql +15 -0
  122. package/node_modules/@buddi/core/migrations/071_mission_lifespan.sql +19 -0
  123. package/node_modules/@buddi/gateway/dist/.tsbuildinfo +1 -1
  124. package/node_modules/@buddi/gateway/dist/agents/canvas.d.ts +6 -6
  125. package/node_modules/@buddi/gateway/dist/agents/catalogue-package.d.ts +313 -0
  126. package/node_modules/@buddi/gateway/dist/agents/catalogue-package.d.ts.map +1 -0
  127. package/node_modules/@buddi/gateway/dist/agents/catalogue-package.js +356 -0
  128. package/node_modules/@buddi/gateway/dist/agents/catalogue-package.js.map +1 -0
  129. package/node_modules/@buddi/gateway/dist/agents/learning-digest.d.ts +29 -7
  130. package/node_modules/@buddi/gateway/dist/agents/learning-digest.d.ts.map +1 -1
  131. package/node_modules/@buddi/gateway/dist/agents/learning-digest.js +87 -38
  132. package/node_modules/@buddi/gateway/dist/agents/learning-digest.js.map +1 -1
  133. package/node_modules/@buddi/gateway/dist/agents/owner-tools.d.ts.map +1 -1
  134. package/node_modules/@buddi/gateway/dist/agents/owner-tools.js +11 -1
  135. package/node_modules/@buddi/gateway/dist/agents/owner-tools.js.map +1 -1
  136. package/node_modules/@buddi/gateway/dist/agents/platform-catalogue.d.ts +361 -0
  137. package/node_modules/@buddi/gateway/dist/agents/platform-catalogue.d.ts.map +1 -0
  138. package/node_modules/@buddi/gateway/dist/agents/platform-catalogue.js +1021 -0
  139. package/node_modules/@buddi/gateway/dist/agents/platform-catalogue.js.map +1 -0
  140. package/node_modules/@buddi/gateway/dist/agents/platform-names.d.ts.map +1 -1
  141. package/node_modules/@buddi/gateway/dist/agents/platform-names.js +3 -0
  142. package/node_modules/@buddi/gateway/dist/agents/platform-names.js.map +1 -1
  143. package/node_modules/@buddi/gateway/dist/agents/platform.d.ts +62 -25
  144. package/node_modules/@buddi/gateway/dist/agents/platform.d.ts.map +1 -1
  145. package/node_modules/@buddi/gateway/dist/agents/platform.js +123 -29
  146. package/node_modules/@buddi/gateway/dist/agents/platform.js.map +1 -1
  147. package/node_modules/@buddi/gateway/dist/agents-cli.d.ts +1 -1
  148. package/node_modules/@buddi/gateway/dist/agents-cli.d.ts.map +1 -1
  149. package/node_modules/@buddi/gateway/dist/agents-cli.js +6 -0
  150. package/node_modules/@buddi/gateway/dist/agents-cli.js.map +1 -1
  151. package/node_modules/@buddi/gateway/dist/bootstrap.d.ts.map +1 -1
  152. package/node_modules/@buddi/gateway/dist/bootstrap.js +13 -1
  153. package/node_modules/@buddi/gateway/dist/bootstrap.js.map +1 -1
  154. package/node_modules/@buddi/gateway/dist/index.d.ts +1 -0
  155. package/node_modules/@buddi/gateway/dist/index.d.ts.map +1 -1
  156. package/node_modules/@buddi/gateway/dist/index.js +1 -0
  157. package/node_modules/@buddi/gateway/dist/index.js.map +1 -1
  158. package/node_modules/@buddi/gateway/dist/missions/defaults.d.ts +0 -6
  159. package/node_modules/@buddi/gateway/dist/missions/defaults.d.ts.map +1 -1
  160. package/node_modules/@buddi/gateway/dist/missions/defaults.js +4 -8
  161. package/node_modules/@buddi/gateway/dist/missions/defaults.js.map +1 -1
  162. package/node_modules/@buddi/gateway/dist/missions/execute.d.ts +6 -0
  163. package/node_modules/@buddi/gateway/dist/missions/execute.d.ts.map +1 -1
  164. package/node_modules/@buddi/gateway/dist/missions/execute.js +74 -2
  165. package/node_modules/@buddi/gateway/dist/missions/execute.js.map +1 -1
  166. package/node_modules/@buddi/gateway/dist/missions/reminders.d.ts +10 -0
  167. package/node_modules/@buddi/gateway/dist/missions/reminders.d.ts.map +1 -1
  168. package/node_modules/@buddi/gateway/dist/missions/reminders.js +86 -17
  169. package/node_modules/@buddi/gateway/dist/missions/reminders.js.map +1 -1
  170. package/node_modules/@buddi/gateway/dist/missions/zone-provenance.d.ts +13 -0
  171. package/node_modules/@buddi/gateway/dist/missions/zone-provenance.d.ts.map +1 -0
  172. package/node_modules/@buddi/gateway/dist/missions/zone-provenance.js +31 -0
  173. package/node_modules/@buddi/gateway/dist/missions/zone-provenance.js.map +1 -0
  174. package/node_modules/@buddi/gateway/dist/missions-cli.js +2 -2
  175. package/node_modules/@buddi/gateway/dist/missions-cli.js.map +1 -1
  176. package/node_modules/@buddi/gateway/dist/plugins/load.d.ts.map +1 -1
  177. package/node_modules/@buddi/gateway/dist/plugins/load.js +12 -5
  178. package/node_modules/@buddi/gateway/dist/plugins/load.js.map +1 -1
  179. package/node_modules/@buddi/gateway/dist/plugins/provenance.d.ts +35 -1
  180. package/node_modules/@buddi/gateway/dist/plugins/provenance.d.ts.map +1 -1
  181. package/node_modules/@buddi/gateway/dist/plugins/provenance.js +39 -1
  182. package/node_modules/@buddi/gateway/dist/plugins/provenance.js.map +1 -1
  183. package/node_modules/@buddi/gateway/dist/serve.d.ts.map +1 -1
  184. package/node_modules/@buddi/gateway/dist/serve.js +10 -10
  185. package/node_modules/@buddi/gateway/dist/serve.js.map +1 -1
  186. package/node_modules/@buddi/gateway/dist/surfaces/handoff.d.ts +62 -0
  187. package/node_modules/@buddi/gateway/dist/surfaces/handoff.d.ts.map +1 -0
  188. package/node_modules/@buddi/gateway/dist/surfaces/handoff.js +121 -0
  189. package/node_modules/@buddi/gateway/dist/surfaces/handoff.js.map +1 -0
  190. package/node_modules/@buddi/gateway/dist/surfaces/offered-actions.d.ts +2 -0
  191. package/node_modules/@buddi/gateway/dist/surfaces/offered-actions.d.ts.map +1 -1
  192. package/node_modules/@buddi/gateway/dist/surfaces/offered-actions.js +1 -1
  193. package/node_modules/@buddi/gateway/dist/surfaces/offered-actions.js.map +1 -1
  194. package/node_modules/@buddi/gateway/dist/telegram/channel.d.ts +11 -1
  195. package/node_modules/@buddi/gateway/dist/telegram/channel.d.ts.map +1 -1
  196. package/node_modules/@buddi/gateway/dist/telegram/channel.js +13 -2
  197. package/node_modules/@buddi/gateway/dist/telegram/channel.js.map +1 -1
  198. package/node_modules/@buddi/gateway/dist/telegram/main.d.ts.map +1 -1
  199. package/node_modules/@buddi/gateway/dist/telegram/main.js +7 -1
  200. package/node_modules/@buddi/gateway/dist/telegram/main.js.map +1 -1
  201. package/node_modules/@buddi/gateway/dist/telegram/surface.d.ts +9 -1
  202. package/node_modules/@buddi/gateway/dist/telegram/surface.d.ts.map +1 -1
  203. package/node_modules/@buddi/gateway/dist/telegram/surface.js +58 -6
  204. package/node_modules/@buddi/gateway/dist/telegram/surface.js.map +1 -1
  205. package/node_modules/@buddi/gateway/dist/web/agent-offers.d.ts +0 -30
  206. package/node_modules/@buddi/gateway/dist/web/agent-offers.d.ts.map +1 -1
  207. package/node_modules/@buddi/gateway/dist/web/agent-offers.js +1 -64
  208. package/node_modules/@buddi/gateway/dist/web/agent-offers.js.map +1 -1
  209. package/node_modules/@buddi/gateway/dist/web/api-routes.d.ts +1 -0
  210. package/node_modules/@buddi/gateway/dist/web/api-routes.d.ts.map +1 -1
  211. package/node_modules/@buddi/gateway/dist/web/api-routes.js +126 -7
  212. package/node_modules/@buddi/gateway/dist/web/api-routes.js.map +1 -1
  213. package/node_modules/@buddi/gateway/dist/web/catalogue-source.d.ts +33 -0
  214. package/node_modules/@buddi/gateway/dist/web/catalogue-source.d.ts.map +1 -0
  215. package/node_modules/@buddi/gateway/dist/web/catalogue-source.js +124 -0
  216. package/node_modules/@buddi/gateway/dist/web/catalogue-source.js.map +1 -0
  217. package/node_modules/@buddi/gateway/dist/web/catalogue.d.ts +155 -0
  218. package/node_modules/@buddi/gateway/dist/web/catalogue.d.ts.map +1 -0
  219. package/node_modules/@buddi/gateway/dist/web/catalogue.js +734 -0
  220. package/node_modules/@buddi/gateway/dist/web/catalogue.js.map +1 -0
  221. package/node_modules/@buddi/gateway/dist/web/chat.d.ts +3 -1
  222. package/node_modules/@buddi/gateway/dist/web/chat.d.ts.map +1 -1
  223. package/node_modules/@buddi/gateway/dist/web/chat.js +8 -1
  224. package/node_modules/@buddi/gateway/dist/web/chat.js.map +1 -1
  225. package/node_modules/@buddi/gateway/dist/web/client-key.d.ts +24 -0
  226. package/node_modules/@buddi/gateway/dist/web/client-key.d.ts.map +1 -0
  227. package/node_modules/@buddi/gateway/dist/web/client-key.js +17 -0
  228. package/node_modules/@buddi/gateway/dist/web/client-key.js.map +1 -0
  229. package/node_modules/@buddi/gateway/dist/web/lock.d.ts +5 -1
  230. package/node_modules/@buddi/gateway/dist/web/lock.d.ts.map +1 -1
  231. package/node_modules/@buddi/gateway/dist/web/lock.js +4 -15
  232. package/node_modules/@buddi/gateway/dist/web/lock.js.map +1 -1
  233. package/node_modules/@buddi/gateway/dist/web/market.d.ts +1 -0
  234. package/node_modules/@buddi/gateway/dist/web/market.d.ts.map +1 -1
  235. package/node_modules/@buddi/gateway/dist/web/market.js +6 -0
  236. package/node_modules/@buddi/gateway/dist/web/market.js.map +1 -1
  237. package/node_modules/@buddi/gateway/dist/web/needs-you.d.ts +36 -0
  238. package/node_modules/@buddi/gateway/dist/web/needs-you.d.ts.map +1 -0
  239. package/node_modules/@buddi/gateway/dist/web/needs-you.js +65 -0
  240. package/node_modules/@buddi/gateway/dist/web/needs-you.js.map +1 -0
  241. package/node_modules/@buddi/gateway/dist/web/notifications.d.ts +9 -1
  242. package/node_modules/@buddi/gateway/dist/web/notifications.d.ts.map +1 -1
  243. package/node_modules/@buddi/gateway/dist/web/notifications.js +14 -3
  244. package/node_modules/@buddi/gateway/dist/web/notifications.js.map +1 -1
  245. package/node_modules/@buddi/gateway/dist/web/read.d.ts +27 -1
  246. package/node_modules/@buddi/gateway/dist/web/read.d.ts.map +1 -1
  247. package/node_modules/@buddi/gateway/dist/web/read.js +57 -8
  248. package/node_modules/@buddi/gateway/dist/web/read.js.map +1 -1
  249. package/node_modules/@buddi/gateway/dist/web/server.d.ts.map +1 -1
  250. package/node_modules/@buddi/gateway/dist/web/server.js +165 -13
  251. package/node_modules/@buddi/gateway/dist/web/server.js.map +1 -1
  252. package/node_modules/@buddi/gateway/dist/web/skills.d.ts +120 -0
  253. package/node_modules/@buddi/gateway/dist/web/skills.d.ts.map +1 -0
  254. package/node_modules/@buddi/gateway/dist/web/skills.js +672 -0
  255. package/node_modules/@buddi/gateway/dist/web/skills.js.map +1 -0
  256. package/node_modules/@buddi/gateway/dist/web/take-on.d.ts +35 -1
  257. package/node_modules/@buddi/gateway/dist/web/take-on.d.ts.map +1 -1
  258. package/node_modules/@buddi/gateway/dist/web/take-on.js +76 -51
  259. package/node_modules/@buddi/gateway/dist/web/take-on.js.map +1 -1
  260. package/node_modules/@buddi/gateway/dist/web/write.d.ts +9 -1
  261. package/node_modules/@buddi/gateway/dist/web/write.d.ts.map +1 -1
  262. package/node_modules/@buddi/gateway/dist/web/write.js +39 -2
  263. package/node_modules/@buddi/gateway/dist/web/write.js.map +1 -1
  264. package/node_modules/@buddi/gateway/package.json +0 -1
  265. package/node_modules/@buddi/install/dist/.tsbuildinfo +1 -1
  266. package/node_modules/@buddi/install/dist/doctor-timezone.d.ts +17 -0
  267. package/node_modules/@buddi/install/dist/doctor-timezone.d.ts.map +1 -0
  268. package/node_modules/@buddi/install/dist/doctor-timezone.js +34 -0
  269. package/node_modules/@buddi/install/dist/doctor-timezone.js.map +1 -0
  270. package/node_modules/@buddi/install/dist/launcher.d.ts.map +1 -1
  271. package/node_modules/@buddi/install/dist/launcher.js +3 -0
  272. package/node_modules/@buddi/install/dist/launcher.js.map +1 -1
  273. package/node_modules/@buddi/runtime/dist/.tsbuildinfo +1 -1
  274. package/node_modules/@buddi/tool-artifacts/dist/.tsbuildinfo +1 -1
  275. package/node_modules/@buddi/tool-browser/dist/.tsbuildinfo +1 -1
  276. package/node_modules/@buddi/tool-email/dist/.tsbuildinfo +1 -1
  277. package/node_modules/@buddi/tool-email/dist/needs-you.d.ts +4 -1
  278. package/node_modules/@buddi/tool-email/dist/needs-you.d.ts.map +1 -1
  279. package/node_modules/@buddi/tool-email/dist/needs-you.js +2 -0
  280. package/node_modules/@buddi/tool-email/dist/needs-you.js.map +1 -1
  281. package/node_modules/@buddi/tool-email/migrations/026_attention_filed.sql +89 -0
  282. package/node_modules/@buddi/tool-host/dist/.tsbuildinfo +1 -1
  283. package/node_modules/@buddi/tool-mcp/dist/.tsbuildinfo +1 -1
  284. package/node_modules/@buddi/tool-memory/dist/.tsbuildinfo +1 -1
  285. package/node_modules/@buddi/tool-web/dist/.tsbuildinfo +1 -1
  286. package/package.json +2 -2
  287. package/packages/cli/dist/.tsbuildinfo +1 -1
  288. package/packages/cli/dist/agents-catalogue-cmd.d.ts +50 -0
  289. package/packages/cli/dist/agents-catalogue-cmd.d.ts.map +1 -0
  290. package/packages/cli/dist/agents-catalogue-cmd.js +328 -0
  291. package/packages/cli/dist/agents-catalogue-cmd.js.map +1 -0
  292. package/packages/cli/dist/args.d.ts +5 -0
  293. package/packages/cli/dist/args.d.ts.map +1 -1
  294. package/packages/cli/dist/args.js +8 -0
  295. package/packages/cli/dist/args.js.map +1 -1
  296. package/packages/cli/dist/commands.d.ts.map +1 -1
  297. package/packages/cli/dist/commands.js +63 -1
  298. package/packages/cli/dist/commands.js.map +1 -1
  299. package/packages/cli/dist/doctor-probes.d.ts.map +1 -1
  300. package/packages/cli/dist/doctor-probes.js +4 -11
  301. package/packages/cli/dist/doctor-probes.js.map +1 -1
  302. package/packages/cli/dist/doctor.d.ts +16 -0
  303. package/packages/cli/dist/doctor.d.ts.map +1 -1
  304. package/packages/cli/dist/doctor.js +30 -0
  305. package/packages/cli/dist/doctor.js.map +1 -1
  306. package/packages/cli/dist/main.d.ts.map +1 -1
  307. package/packages/cli/dist/main.js +44 -9
  308. package/packages/cli/dist/main.js.map +1 -1
  309. package/packages/cli/dist/mcp/tools.d.ts.map +1 -1
  310. package/packages/cli/dist/mcp/tools.js +3 -1
  311. package/packages/cli/dist/mcp/tools.js.map +1 -1
  312. package/packages/cli/dist/skills-cmd.d.ts +15 -0
  313. package/packages/cli/dist/skills-cmd.d.ts.map +1 -0
  314. package/packages/cli/dist/skills-cmd.js +54 -0
  315. package/packages/cli/dist/skills-cmd.js.map +1 -0
  316. package/packages/cli/dist/status.d.ts +15 -9
  317. package/packages/cli/dist/status.d.ts.map +1 -1
  318. package/packages/cli/dist/status.js +6 -11
  319. package/packages/cli/dist/status.js.map +1 -1
  320. package/packages/core/dist/.tsbuildinfo +1 -1
  321. package/packages/core/dist/actions/store.d.ts +8 -0
  322. package/packages/core/dist/actions/store.d.ts.map +1 -1
  323. package/packages/core/dist/actions/store.js +13 -0
  324. package/packages/core/dist/actions/store.js.map +1 -1
  325. package/packages/core/dist/agents/catalog.d.ts +11 -3
  326. package/packages/core/dist/agents/catalog.d.ts.map +1 -1
  327. package/packages/core/dist/agents/catalog.js +58 -10
  328. package/packages/core/dist/agents/catalog.js.map +1 -1
  329. package/packages/core/dist/agents/frontmatter.d.ts +1 -1
  330. package/packages/core/dist/agents/frontmatter.d.ts.map +1 -1
  331. package/packages/core/dist/agents/frontmatter.js +1 -1
  332. package/packages/core/dist/agents/frontmatter.js.map +1 -1
  333. package/packages/core/dist/agents/skills.d.ts +29 -3
  334. package/packages/core/dist/agents/skills.d.ts.map +1 -1
  335. package/packages/core/dist/agents/skills.js +49 -2
  336. package/packages/core/dist/agents/skills.js.map +1 -1
  337. package/packages/core/dist/clock-widget.d.ts.map +1 -1
  338. package/packages/core/dist/clock-widget.js +5 -3
  339. package/packages/core/dist/clock-widget.js.map +1 -1
  340. package/packages/core/dist/host/build.d.ts.map +1 -1
  341. package/packages/core/dist/host/build.js +11 -0
  342. package/packages/core/dist/host/build.js.map +1 -1
  343. package/packages/core/dist/host/types.d.ts +7 -0
  344. package/packages/core/dist/host/types.d.ts.map +1 -1
  345. package/packages/core/dist/learning/store.d.ts +7 -0
  346. package/packages/core/dist/learning/store.d.ts.map +1 -1
  347. package/packages/core/dist/learning/store.js +6 -0
  348. package/packages/core/dist/learning/store.js.map +1 -1
  349. package/packages/core/dist/notifications/agent.d.ts +7 -0
  350. package/packages/core/dist/notifications/agent.d.ts.map +1 -1
  351. package/packages/core/dist/notifications/agent.js +2 -0
  352. package/packages/core/dist/notifications/agent.js.map +1 -1
  353. package/packages/core/dist/notifications/index.d.ts +1 -0
  354. package/packages/core/dist/notifications/index.d.ts.map +1 -1
  355. package/packages/core/dist/notifications/index.js +1 -0
  356. package/packages/core/dist/notifications/index.js.map +1 -1
  357. package/packages/core/dist/notifications/needs.d.ts +49 -0
  358. package/packages/core/dist/notifications/needs.d.ts.map +1 -0
  359. package/packages/core/dist/notifications/needs.js +41 -0
  360. package/packages/core/dist/notifications/needs.js.map +1 -0
  361. package/packages/core/dist/notifications/notify.d.ts.map +1 -1
  362. package/packages/core/dist/notifications/notify.js +16 -7
  363. package/packages/core/dist/notifications/notify.js.map +1 -1
  364. package/packages/core/dist/notifications/store.d.ts.map +1 -1
  365. package/packages/core/dist/notifications/store.js +2 -1
  366. package/packages/core/dist/notifications/store.js.map +1 -1
  367. package/packages/core/dist/notifications/types.d.ts +10 -0
  368. package/packages/core/dist/notifications/types.d.ts.map +1 -1
  369. package/packages/core/dist/notifications/types.js.map +1 -1
  370. package/packages/core/dist/offers/store.d.ts.map +1 -1
  371. package/packages/core/dist/offers/store.js +9 -4
  372. package/packages/core/dist/offers/store.js.map +1 -1
  373. package/packages/core/dist/offers/types.d.ts +24 -1
  374. package/packages/core/dist/offers/types.d.ts.map +1 -1
  375. package/packages/core/dist/offers/types.js +23 -1
  376. package/packages/core/dist/offers/types.js.map +1 -1
  377. package/packages/core/dist/owner-timezone.d.ts +20 -22
  378. package/packages/core/dist/owner-timezone.d.ts.map +1 -1
  379. package/packages/core/dist/owner-timezone.js +17 -25
  380. package/packages/core/dist/owner-timezone.js.map +1 -1
  381. package/packages/core/dist/plugin/version.d.ts +1 -1
  382. package/packages/core/dist/plugin/version.js +1 -1
  383. package/packages/core/dist/scheduler/missions.d.ts +86 -11
  384. package/packages/core/dist/scheduler/missions.d.ts.map +1 -1
  385. package/packages/core/dist/scheduler/missions.js +160 -36
  386. package/packages/core/dist/scheduler/missions.js.map +1 -1
  387. package/packages/core/dist/scheduler/runner.d.ts.map +1 -1
  388. package/packages/core/dist/scheduler/runner.js +6 -1
  389. package/packages/core/dist/scheduler/runner.js.map +1 -1
  390. package/packages/core/dist/scheduler/types.d.ts +22 -0
  391. package/packages/core/dist/scheduler/types.d.ts.map +1 -1
  392. package/packages/core/dist/scheduler/types.js +6 -0
  393. package/packages/core/dist/scheduler/types.js.map +1 -1
  394. package/packages/core/dist/web-settings.d.ts +13 -0
  395. package/packages/core/dist/web-settings.d.ts.map +1 -1
  396. package/packages/core/dist/web-settings.js +26 -0
  397. package/packages/core/dist/web-settings.js.map +1 -1
  398. package/packages/core/dist/widgets.d.ts +13 -5
  399. package/packages/core/dist/widgets.d.ts.map +1 -1
  400. package/packages/core/dist/widgets.js +10 -1
  401. package/packages/core/dist/widgets.js.map +1 -1
  402. package/packages/core/migrations/068_notification_action.sql +12 -0
  403. package/packages/core/migrations/069_schedule_zone_explicit.sql +18 -0
  404. package/packages/core/migrations/070_offer_handoff.sql +15 -0
  405. package/packages/core/migrations/071_mission_lifespan.sql +19 -0
  406. package/packages/gateway/dist/.tsbuildinfo +1 -1
  407. package/packages/gateway/dist/agents/canvas.d.ts +6 -6
  408. package/packages/gateway/dist/agents/catalogue-package.d.ts +313 -0
  409. package/packages/gateway/dist/agents/catalogue-package.d.ts.map +1 -0
  410. package/packages/gateway/dist/agents/catalogue-package.js +356 -0
  411. package/packages/gateway/dist/agents/catalogue-package.js.map +1 -0
  412. package/packages/gateway/dist/agents/learning-digest.d.ts +29 -7
  413. package/packages/gateway/dist/agents/learning-digest.d.ts.map +1 -1
  414. package/packages/gateway/dist/agents/learning-digest.js +87 -38
  415. package/packages/gateway/dist/agents/learning-digest.js.map +1 -1
  416. package/packages/gateway/dist/agents/owner-tools.d.ts.map +1 -1
  417. package/packages/gateway/dist/agents/owner-tools.js +11 -1
  418. package/packages/gateway/dist/agents/owner-tools.js.map +1 -1
  419. package/packages/gateway/dist/agents/platform-catalogue.d.ts +361 -0
  420. package/packages/gateway/dist/agents/platform-catalogue.d.ts.map +1 -0
  421. package/packages/gateway/dist/agents/platform-catalogue.js +1021 -0
  422. package/packages/gateway/dist/agents/platform-catalogue.js.map +1 -0
  423. package/packages/gateway/dist/agents/platform-names.d.ts.map +1 -1
  424. package/packages/gateway/dist/agents/platform-names.js +3 -0
  425. package/packages/gateway/dist/agents/platform-names.js.map +1 -1
  426. package/packages/gateway/dist/agents/platform.d.ts +62 -25
  427. package/packages/gateway/dist/agents/platform.d.ts.map +1 -1
  428. package/packages/gateway/dist/agents/platform.js +123 -29
  429. package/packages/gateway/dist/agents/platform.js.map +1 -1
  430. package/packages/gateway/dist/agents-cli.d.ts +1 -1
  431. package/packages/gateway/dist/agents-cli.d.ts.map +1 -1
  432. package/packages/gateway/dist/agents-cli.js +6 -0
  433. package/packages/gateway/dist/agents-cli.js.map +1 -1
  434. package/packages/gateway/dist/bootstrap.d.ts.map +1 -1
  435. package/packages/gateway/dist/bootstrap.js +13 -1
  436. package/packages/gateway/dist/bootstrap.js.map +1 -1
  437. package/packages/gateway/dist/index.d.ts +1 -0
  438. package/packages/gateway/dist/index.d.ts.map +1 -1
  439. package/packages/gateway/dist/index.js +1 -0
  440. package/packages/gateway/dist/index.js.map +1 -1
  441. package/packages/gateway/dist/missions/defaults.d.ts +0 -6
  442. package/packages/gateway/dist/missions/defaults.d.ts.map +1 -1
  443. package/packages/gateway/dist/missions/defaults.js +4 -8
  444. package/packages/gateway/dist/missions/defaults.js.map +1 -1
  445. package/packages/gateway/dist/missions/execute.d.ts +6 -0
  446. package/packages/gateway/dist/missions/execute.d.ts.map +1 -1
  447. package/packages/gateway/dist/missions/execute.js +74 -2
  448. package/packages/gateway/dist/missions/execute.js.map +1 -1
  449. package/packages/gateway/dist/missions/reminders.d.ts +10 -0
  450. package/packages/gateway/dist/missions/reminders.d.ts.map +1 -1
  451. package/packages/gateway/dist/missions/reminders.js +86 -17
  452. package/packages/gateway/dist/missions/reminders.js.map +1 -1
  453. package/packages/gateway/dist/missions/zone-provenance.d.ts +13 -0
  454. package/packages/gateway/dist/missions/zone-provenance.d.ts.map +1 -0
  455. package/packages/gateway/dist/missions/zone-provenance.js +31 -0
  456. package/packages/gateway/dist/missions/zone-provenance.js.map +1 -0
  457. package/packages/gateway/dist/missions-cli.js +2 -2
  458. package/packages/gateway/dist/missions-cli.js.map +1 -1
  459. package/packages/gateway/dist/plugins/load.d.ts.map +1 -1
  460. package/packages/gateway/dist/plugins/load.js +12 -5
  461. package/packages/gateway/dist/plugins/load.js.map +1 -1
  462. package/packages/gateway/dist/plugins/provenance.d.ts +35 -1
  463. package/packages/gateway/dist/plugins/provenance.d.ts.map +1 -1
  464. package/packages/gateway/dist/plugins/provenance.js +39 -1
  465. package/packages/gateway/dist/plugins/provenance.js.map +1 -1
  466. package/packages/gateway/dist/serve.d.ts.map +1 -1
  467. package/packages/gateway/dist/serve.js +10 -10
  468. package/packages/gateway/dist/serve.js.map +1 -1
  469. package/packages/gateway/dist/surfaces/handoff.d.ts +62 -0
  470. package/packages/gateway/dist/surfaces/handoff.d.ts.map +1 -0
  471. package/packages/gateway/dist/surfaces/handoff.js +121 -0
  472. package/packages/gateway/dist/surfaces/handoff.js.map +1 -0
  473. package/packages/gateway/dist/surfaces/offered-actions.d.ts +2 -0
  474. package/packages/gateway/dist/surfaces/offered-actions.d.ts.map +1 -1
  475. package/packages/gateway/dist/surfaces/offered-actions.js +1 -1
  476. package/packages/gateway/dist/surfaces/offered-actions.js.map +1 -1
  477. package/packages/gateway/dist/telegram/channel.d.ts +11 -1
  478. package/packages/gateway/dist/telegram/channel.d.ts.map +1 -1
  479. package/packages/gateway/dist/telegram/channel.js +13 -2
  480. package/packages/gateway/dist/telegram/channel.js.map +1 -1
  481. package/packages/gateway/dist/telegram/main.d.ts.map +1 -1
  482. package/packages/gateway/dist/telegram/main.js +7 -1
  483. package/packages/gateway/dist/telegram/main.js.map +1 -1
  484. package/packages/gateway/dist/telegram/surface.d.ts +9 -1
  485. package/packages/gateway/dist/telegram/surface.d.ts.map +1 -1
  486. package/packages/gateway/dist/telegram/surface.js +58 -6
  487. package/packages/gateway/dist/telegram/surface.js.map +1 -1
  488. package/packages/gateway/dist/web/agent-offers.d.ts +0 -30
  489. package/packages/gateway/dist/web/agent-offers.d.ts.map +1 -1
  490. package/packages/gateway/dist/web/agent-offers.js +1 -64
  491. package/packages/gateway/dist/web/agent-offers.js.map +1 -1
  492. package/packages/gateway/dist/web/api-routes.d.ts +1 -0
  493. package/packages/gateway/dist/web/api-routes.d.ts.map +1 -1
  494. package/packages/gateway/dist/web/api-routes.js +126 -7
  495. package/packages/gateway/dist/web/api-routes.js.map +1 -1
  496. package/packages/gateway/dist/web/catalogue-source.d.ts +33 -0
  497. package/packages/gateway/dist/web/catalogue-source.d.ts.map +1 -0
  498. package/packages/gateway/dist/web/catalogue-source.js +124 -0
  499. package/packages/gateway/dist/web/catalogue-source.js.map +1 -0
  500. package/packages/gateway/dist/web/catalogue.d.ts +155 -0
  501. package/packages/gateway/dist/web/catalogue.d.ts.map +1 -0
  502. package/packages/gateway/dist/web/catalogue.js +734 -0
  503. package/packages/gateway/dist/web/catalogue.js.map +1 -0
  504. package/packages/gateway/dist/web/chat.d.ts +3 -1
  505. package/packages/gateway/dist/web/chat.d.ts.map +1 -1
  506. package/packages/gateway/dist/web/chat.js +8 -1
  507. package/packages/gateway/dist/web/chat.js.map +1 -1
  508. package/packages/gateway/dist/web/client-key.d.ts +24 -0
  509. package/packages/gateway/dist/web/client-key.d.ts.map +1 -0
  510. package/packages/gateway/dist/web/client-key.js +17 -0
  511. package/packages/gateway/dist/web/client-key.js.map +1 -0
  512. package/packages/gateway/dist/web/lock.d.ts +5 -1
  513. package/packages/gateway/dist/web/lock.d.ts.map +1 -1
  514. package/packages/gateway/dist/web/lock.js +4 -15
  515. package/packages/gateway/dist/web/lock.js.map +1 -1
  516. package/packages/gateway/dist/web/market.d.ts +1 -0
  517. package/packages/gateway/dist/web/market.d.ts.map +1 -1
  518. package/packages/gateway/dist/web/market.js +6 -0
  519. package/packages/gateway/dist/web/market.js.map +1 -1
  520. package/packages/gateway/dist/web/needs-you.d.ts +36 -0
  521. package/packages/gateway/dist/web/needs-you.d.ts.map +1 -0
  522. package/packages/gateway/dist/web/needs-you.js +65 -0
  523. package/packages/gateway/dist/web/needs-you.js.map +1 -0
  524. package/packages/gateway/dist/web/notifications.d.ts +9 -1
  525. package/packages/gateway/dist/web/notifications.d.ts.map +1 -1
  526. package/packages/gateway/dist/web/notifications.js +14 -3
  527. package/packages/gateway/dist/web/notifications.js.map +1 -1
  528. package/packages/gateway/dist/web/read.d.ts +27 -1
  529. package/packages/gateway/dist/web/read.d.ts.map +1 -1
  530. package/packages/gateway/dist/web/read.js +57 -8
  531. package/packages/gateway/dist/web/read.js.map +1 -1
  532. package/packages/gateway/dist/web/server.d.ts.map +1 -1
  533. package/packages/gateway/dist/web/server.js +165 -13
  534. package/packages/gateway/dist/web/server.js.map +1 -1
  535. package/packages/gateway/dist/web/skills.d.ts +120 -0
  536. package/packages/gateway/dist/web/skills.d.ts.map +1 -0
  537. package/packages/gateway/dist/web/skills.js +672 -0
  538. package/packages/gateway/dist/web/skills.js.map +1 -0
  539. package/packages/gateway/dist/web/take-on.d.ts +35 -1
  540. package/packages/gateway/dist/web/take-on.d.ts.map +1 -1
  541. package/packages/gateway/dist/web/take-on.js +76 -51
  542. package/packages/gateway/dist/web/take-on.js.map +1 -1
  543. package/packages/gateway/dist/web/write.d.ts +9 -1
  544. package/packages/gateway/dist/web/write.d.ts.map +1 -1
  545. package/packages/gateway/dist/web/write.js +39 -2
  546. package/packages/gateway/dist/web/write.js.map +1 -1
  547. package/packages/gateway/package.json +0 -1
  548. package/packages/install/dist/.tsbuildinfo +1 -1
  549. package/packages/install/dist/doctor-timezone.d.ts +17 -0
  550. package/packages/install/dist/doctor-timezone.d.ts.map +1 -0
  551. package/packages/install/dist/doctor-timezone.js +34 -0
  552. package/packages/install/dist/doctor-timezone.js.map +1 -0
  553. package/packages/install/dist/launcher.d.ts.map +1 -1
  554. package/packages/install/dist/launcher.js +3 -0
  555. package/packages/install/dist/launcher.js.map +1 -1
  556. package/packages/runtime/dist/.tsbuildinfo +1 -1
  557. package/packages/tools/artifacts/dist/.tsbuildinfo +1 -1
  558. package/packages/tools/browser/dist/.tsbuildinfo +1 -1
  559. package/packages/tools/email/dist/.tsbuildinfo +1 -1
  560. package/packages/tools/email/dist/needs-you.d.ts +4 -1
  561. package/packages/tools/email/dist/needs-you.d.ts.map +1 -1
  562. package/packages/tools/email/dist/needs-you.js +2 -0
  563. package/packages/tools/email/dist/needs-you.js.map +1 -1
  564. package/packages/tools/email/migrations/026_attention_filed.sql +89 -0
  565. package/packages/tools/host/dist/.tsbuildinfo +1 -1
  566. package/packages/tools/mcp/dist/.tsbuildinfo +1 -1
  567. package/packages/tools/memory/dist/.tsbuildinfo +1 -1
  568. package/packages/tools/web/dist/.tsbuildinfo +1 -1
  569. package/packages/web/dist/assets/index-BldmgplG.css +1 -0
  570. package/packages/web/dist/assets/index-C8GaSH__.js +132 -0
  571. package/packages/web/dist/assets/{lottie_light-Ls7i1ATS.js → lottie_light-DdwKPR04.js} +1 -1
  572. package/packages/web/dist/build.json +1 -1
  573. package/packages/web/dist/index.html +2 -2
  574. package/packages/web/dist/precache.json +4 -4
  575. package/node_modules/@buddi/gateway/dist/agents/starter-team.d.ts +0 -59
  576. package/node_modules/@buddi/gateway/dist/agents/starter-team.d.ts.map +0 -1
  577. package/node_modules/@buddi/gateway/dist/agents/starter-team.js +0 -156
  578. package/node_modules/@buddi/gateway/dist/agents/starter-team.js.map +0 -1
  579. package/node_modules/@buddi/gateway/src/agents/starter/keeper/agent.md +0 -31
  580. package/node_modules/@buddi/gateway/src/agents/starter/keeper/skills/keeping-a-history.md +0 -22
  581. package/node_modules/@buddi/gateway/src/agents/starter/planner/agent.md +0 -30
  582. package/node_modules/@buddi/gateway/src/agents/starter/planner/skills/holding-a-follow-up.md +0 -17
  583. package/node_modules/@buddi/gateway/src/agents/starter/planner/skills/writing-the-morning-brief.md +0 -32
  584. package/node_modules/@buddi/gateway/src/agents/starter/scout/agent.md +0 -33
  585. package/node_modules/@buddi/gateway/src/agents/starter/scout/skills/answering-with-sources.md +0 -23
  586. package/node_modules/@buddi/gateway/src/agents/starter/scout/skills/the-web-is-evidence.md +0 -25
  587. package/packages/gateway/dist/agents/starter-team.d.ts +0 -59
  588. package/packages/gateway/dist/agents/starter-team.d.ts.map +0 -1
  589. package/packages/gateway/dist/agents/starter-team.js +0 -156
  590. package/packages/gateway/dist/agents/starter-team.js.map +0 -1
  591. package/packages/gateway/src/agents/starter/keeper/agent.md +0 -31
  592. package/packages/gateway/src/agents/starter/keeper/skills/keeping-a-history.md +0 -22
  593. package/packages/gateway/src/agents/starter/planner/agent.md +0 -30
  594. package/packages/gateway/src/agents/starter/planner/skills/holding-a-follow-up.md +0 -17
  595. package/packages/gateway/src/agents/starter/planner/skills/writing-the-morning-brief.md +0 -32
  596. package/packages/gateway/src/agents/starter/scout/agent.md +0 -33
  597. package/packages/gateway/src/agents/starter/scout/skills/answering-with-sources.md +0 -23
  598. package/packages/gateway/src/agents/starter/scout/skills/the-web-is-evidence.md +0 -25
  599. package/packages/web/dist/assets/index-WS4UjGsy.js +0 -129
  600. package/packages/web/dist/assets/index-Zrt_o2UG.css +0 -1
@@ -0,0 +1,1021 @@
1
+ /**
2
+ * The agent catalogue on the platform's side (agent-catalogue.md §5, §7, §8):
3
+ * where a listed package stands on this installation, and the gated tool that
4
+ * adds one, or updates one already added.
5
+ *
6
+ * Adding a package is accepting a proposal by another name, so it is built on
7
+ * the very same pieces `platform.accept_plugin_agent` is: `buildCreateEnvelope`
8
+ * (the id and handle checks, `checkTools`, the "would this file load" parse),
9
+ * the account the accepting agent speaks through, the same create preview
10
+ * naming the whole grant. On top: the v1 denylist, the package's integrity
11
+ * (checked when the listing was read), the picks rendered as "## For this
12
+ * owner", the missions created off unless chosen, the picture, and a sidecar
13
+ * recording `source: market`.
14
+ *
15
+ * Updating is the same tool with `agent`: an agent whose file is untouched is
16
+ * written again from the new package with the same picks; one the owner
17
+ * edited is never touched unless they ask to replace their changes, and then
18
+ * their file goes to the trash first. Existing missions are the owner's rows
19
+ * and are never edited; new suggested ones arrive off.
20
+ *
21
+ * Nothing here reaches the network: the listings, the picks' choices and the
22
+ * picture come through a `CatalogueService` the gateway binds
23
+ * (`web/catalogue-source.ts`), so this module never imports a web route and a
24
+ * test hands in a fixture.
25
+ */
26
+ import { existsSync, readdirSync, readFileSync, rmSync, statSync } from 'node:fs';
27
+ import path from 'node:path';
28
+ import { AGENT_FILE, applyFrontmatterPatch, assertApprovedEffect, getMission, HANDLE_MAX, hashEnvelope, parseAgentFile, parseSkillFile, satisfiesRange, setSchedule, SKILLS_DIR, STARTER_MAX, upsertMission, } from '@buddi/core';
29
+ import { z } from 'zod';
30
+ import { composePackagePersona, cronAt, cronClock, deniedTools, fileHash, parseClock, } from './catalogue-package.js';
31
+ import { composeProvenance, fileEdited, packageOwnedText, readProvenance, PROVENANCE_FILE } from '../plugins/provenance.js';
32
+ import { composeAgentFile, composeSkillFile, createAgentDirAtomic, trashStamp, writeFilesAtomic } from './platform-files.js';
33
+ import { diffGrant, grantChangeBlock } from './platform-grant.js';
34
+ import { agentMissionId, describeCadence } from '../missions/reminders.js';
35
+ import { normaliseAvatar } from './avatar-image.js';
36
+ import { readAvatar, writeAvatar } from './avatars.js';
37
+ /** Said when there is neither a fresh list nor a copy. */
38
+ export const CATALOGUE_OFFLINE = "The catalogue needs withbuddi.com; try again when you're online.";
39
+ /**
40
+ * The skills written with this agent that the owner has changed or deleted
41
+ * since, by name. Only the skills the sidecar recorded: one the owner added
42
+ * is theirs and no update touches it.
43
+ */
44
+ export function editedSkills(dir, provenance) {
45
+ const out = [];
46
+ for (const [name, hash] of Object.entries(provenance.skills ?? {})) {
47
+ const file = path.join(dir, SKILLS_DIR, `${name}.md`);
48
+ try {
49
+ if (fileHash(readFileSync(file, 'utf8')) !== hash)
50
+ out.push(name);
51
+ }
52
+ catch {
53
+ out.push(name);
54
+ }
55
+ }
56
+ return out;
57
+ }
58
+ /** Every agent directory with a sidecar, read once. */
59
+ export function addedAgents(agentsDir) {
60
+ if (!existsSync(agentsDir))
61
+ return [];
62
+ const out = [];
63
+ for (const name of readdirSync(agentsDir).sort()) {
64
+ if (name.startsWith('.'))
65
+ continue;
66
+ const dir = path.join(agentsDir, name);
67
+ const file = path.join(dir, AGENT_FILE);
68
+ try {
69
+ if (!statSync(dir).isDirectory() || !existsSync(file))
70
+ continue;
71
+ }
72
+ catch {
73
+ continue;
74
+ }
75
+ const provenance = readProvenance(dir);
76
+ if (!provenance)
77
+ continue;
78
+ let edited = true;
79
+ try {
80
+ // The `skills:` grants are the owner's, not the package's: they never count here.
81
+ edited = fileEdited(provenance.file, readFileSync(file, 'utf8')) || editedSkills(dir, provenance).length > 0;
82
+ }
83
+ catch {
84
+ edited = true;
85
+ }
86
+ out.push({ agentId: name, dir, file, provenance, edited });
87
+ }
88
+ return out;
89
+ }
90
+ /** Is this added agent a copy of the package, directly or by `replaces`? */
91
+ export function matchesPackage(pkg, added) {
92
+ const p = added.provenance;
93
+ if (p.source === 'market' && p.package === pkg.manifest.name)
94
+ return 'package';
95
+ if (pkg.manifest.replaces.includes(`${p.plugin}/${p.agent}`))
96
+ return 'replaces';
97
+ return null;
98
+ }
99
+ export function installedAsFor(pkg, added, handleOf) {
100
+ const direct = added.find((a) => matchesPackage(pkg, a) === 'package');
101
+ const match = direct ?? added.find((a) => matchesPackage(pkg, a) === 'replaces');
102
+ if (!match)
103
+ return undefined;
104
+ const via = direct ? undefined : `${match.provenance.plugin}/${match.provenance.agent}`;
105
+ const moved = via !== undefined || match.provenance.proposal !== pkg.manifest.integrity;
106
+ const drift = match.edited ? (moved && via === undefined ? 'edited-update' : 'edited') : moved ? 'update' : 'current';
107
+ return {
108
+ agentId: match.agentId,
109
+ handle: handleOf(match.agentId),
110
+ version: match.provenance.version,
111
+ drift,
112
+ ...(via === undefined ? {} : { via }),
113
+ };
114
+ }
115
+ /** The plugins a package requires that are not loaded here in range, each with its fix. */
116
+ export function missingPlugins(pkg, ctx) {
117
+ const loaded = new Map(ctx.registry.manifests().map((m) => [m.name, m.version]));
118
+ const out = [];
119
+ for (const [name, range] of Object.entries(pkg.manifest.requires)) {
120
+ const version = loaded.get(name);
121
+ if (version !== undefined) {
122
+ if (satisfiesRange(version, range) === false)
123
+ out.push({ kind: 'plugin', name, range, fix: 'update', installed: version });
124
+ continue;
125
+ }
126
+ const record = ctx.plugins.find((p) => p.name === name);
127
+ if (!record)
128
+ out.push({ kind: 'plugin', name, range, fix: 'install' });
129
+ else if (satisfiesRange(record.version, range) === false)
130
+ out.push({ kind: 'plugin', name, range, fix: 'update', installed: record.version });
131
+ else
132
+ out.push({ kind: 'plugin', name, range, fix: 'enable' });
133
+ }
134
+ return out;
135
+ }
136
+ /** The version a `buddi` range is read against: a checkout's "0.1.0 (v0.1.0-3-g…)" is its first word. */
137
+ export function plainVersion(version) {
138
+ return version.trim().split(/\s+/)[0] ?? version;
139
+ }
140
+ export function packageState(pkg, ctx) {
141
+ const installed = installedAsFor(pkg, ctx.added, ctx.handleOf);
142
+ if (installed)
143
+ return { state: 'installed', installed };
144
+ if (satisfiesRange(plainVersion(ctx.version), pkg.manifest.buddi) === false) {
145
+ return { state: 'unavailable', reason: `Needs buddi ${pkg.manifest.buddi}; this is ${plainVersion(ctx.version)}. Update buddi first.` };
146
+ }
147
+ const missing = [...missingPlugins(pkg, ctx)];
148
+ for (const need of pkg.manifest.needs) {
149
+ // `mailbox?` makes it better and never holds it back.
150
+ if (need === 'mailbox?')
151
+ continue;
152
+ if (!ctx.needs[need])
153
+ missing.push({ kind: 'need', name: need, fix: need === 'mailbox' ? 'mailbox' : 'accounts' });
154
+ }
155
+ return missing.length === 0 ? { state: 'ready' } : { state: 'needs', missing };
156
+ }
157
+ export class CatalogueRefusal extends Error {
158
+ code;
159
+ name = 'PlatformRefusal';
160
+ constructor(code, message) {
161
+ super(message);
162
+ this.code = code;
163
+ }
164
+ }
165
+ function refuse(code, message) {
166
+ throw new CatalogueRefusal(code, message);
167
+ }
168
+ export const installAgentInput = z
169
+ .object({
170
+ name: z.string().min(1).describe('The package, as platform.catalogue lists it: "chef".'),
171
+ version: z
172
+ .string()
173
+ .min(1)
174
+ .optional()
175
+ .describe('The version the owner saw. Refused when the catalogue has moved on, so they approve what they read.'),
176
+ handle: z
177
+ .string()
178
+ .min(1)
179
+ .optional()
180
+ .describe('A handle the owner asked for. Leave it out for the package\'s own, or a free one beside it (chef-2).'),
181
+ fills: z
182
+ .record(z.string(), z.string())
183
+ .optional()
184
+ .describe('The picks platform.catalogue lists for it, by id: a mailbox address, calendar names (comma-separated, empty for ' +
185
+ 'all), a saved place, a mission hour as HH:MM, or one line of text. Leave a pick out for its default.'),
186
+ missionsOn: z
187
+ .array(z.string().min(1))
188
+ .optional()
189
+ .describe('The package missions the owner asked to turn on now, by id. Every other mission arrives off.'),
190
+ account: z
191
+ .string()
192
+ .min(1)
193
+ .optional()
194
+ .describe('A named model account the owner picked. Leave it out and it speaks through the same account you do.'),
195
+ agent: z
196
+ .string()
197
+ .min(1)
198
+ .optional()
199
+ .describe('Update this agent, already added from the package (or an older one it replaces), instead of adding a new one: ' +
200
+ 'by id or handle.'),
201
+ replaceEdits: z
202
+ .literal(true)
203
+ .optional()
204
+ .describe('Only when the owner said to replace their own changes to that agent\'s file. Their file goes to the trash first.'),
205
+ plan: z
206
+ .string()
207
+ .min(1)
208
+ .optional()
209
+ .describe('The plan fingerprint the dashboard or `buddi agents` showed the owner. Refused when anything it covers moved ' +
210
+ '(the package, the grant, the files on disk). Leave it out from chat: your approval card is the preview.'),
211
+ })
212
+ .strict();
213
+ function freeName(base, taken, max) {
214
+ if (!taken(base))
215
+ return base;
216
+ for (let n = 2; n < 100; n += 1) {
217
+ const suffix = `-${n}`;
218
+ const candidate = `${base.slice(0, max - suffix.length).replace(/-+$/, '')}${suffix}`;
219
+ if (!taken(candidate))
220
+ return candidate;
221
+ }
222
+ refuse('no-free-name', `every name from ${base} to ${base}-99 is taken`);
223
+ }
224
+ /** The picks answered, with each default filled in (§7). */
225
+ export function resolvePicks(pkg, given, choices) {
226
+ const answers = given ?? {};
227
+ const known = new Set(pkg.manifest.fills.map((f) => f.id));
228
+ const stray = Object.keys(answers).filter((id) => !known.has(id));
229
+ if (stray.length > 0) {
230
+ refuse('unknown-pick', `${pkg.manifest.title} asks no "${stray.join('", "')}". Its picks: ${pkg.manifest.fills.map((f) => f.id).join(', ') || 'none'}.`);
231
+ }
232
+ return pkg.manifest.fills.map((fill) => {
233
+ const raw = answers[fill.id]?.trim();
234
+ let value;
235
+ switch (fill.kind) {
236
+ case 'mailbox': {
237
+ value = raw ?? choices.mailboxes[0] ?? '';
238
+ if (raw !== undefined && raw !== '' && choices.mailboxes.length > 0 && !choices.mailboxes.some((m) => m.toLowerCase() === raw.toLowerCase())) {
239
+ refuse('bad-pick', `"${raw}" is not one of your mailboxes (${choices.mailboxes.join(', ')}).`);
240
+ }
241
+ break;
242
+ }
243
+ case 'calendar': {
244
+ value = raw ?? '';
245
+ const names = value.split(',').map((s) => s.trim()).filter(Boolean);
246
+ const unknown = choices.calendars.length === 0 ? [] : names.filter((n) => !choices.calendars.includes(n));
247
+ if (raw !== undefined && unknown.length > 0) {
248
+ refuse('bad-pick', `${unknown.join(', ')} ${unknown.length === 1 ? 'is not a linked calendar' : 'are not linked calendars'} (${choices.calendars.join(', ')}).`);
249
+ }
250
+ value = names.join(', ');
251
+ break;
252
+ }
253
+ case 'place': {
254
+ const fallback = choices.places.find((p) => p.id === 'home')?.label ?? choices.places[0]?.label ?? '';
255
+ const wanted = raw;
256
+ if (wanted === undefined || wanted === '') {
257
+ value = raw === '' ? '' : fallback;
258
+ }
259
+ else {
260
+ const match = choices.places.find((p) => p.id === wanted.toLowerCase() || p.label.toLowerCase() === wanted.toLowerCase());
261
+ if (!match && raw !== undefined && choices.places.length > 0) {
262
+ refuse('bad-pick', `"${raw}" is not one of your saved places (${choices.places.map((p) => p.label).join(', ')}).`);
263
+ }
264
+ value = match?.label ?? wanted;
265
+ }
266
+ break;
267
+ }
268
+ case 'time': {
269
+ const mission = pkg.manifest.missions.find((m) => m.id === fill.mission);
270
+ value = raw ?? (mission ? cronClock(mission.cron) : null) ?? '';
271
+ if (value !== '' && parseClock(value) === null)
272
+ refuse('bad-pick', `"${value}" is not a time of day (HH:MM, like 07:30).`);
273
+ if (value !== '') {
274
+ const [h, m] = parseClock(value);
275
+ value = `${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}`;
276
+ }
277
+ break;
278
+ }
279
+ case 'text': {
280
+ value = raw ?? '';
281
+ if (/[\r\n]/.test(value))
282
+ refuse('bad-pick', `"${fill.label}" takes one line.`);
283
+ if (value.length > 200)
284
+ refuse('bad-pick', `"${fill.label}" takes at most 200 characters.`);
285
+ break;
286
+ }
287
+ }
288
+ return { id: fill.id, kind: fill.kind, label: fill.label, value };
289
+ });
290
+ }
291
+ /** Lines that differ, `- ` removed and `+ ` added, from a plain longest-common-subsequence. */
292
+ export function lineDiff(before, after) {
293
+ const a = before.trim().split('\n');
294
+ const b = after.trim().split('\n');
295
+ const n = a.length;
296
+ const m = b.length;
297
+ const table = Array.from({ length: n + 1 }, () => new Array(m + 1).fill(0));
298
+ for (let i = n - 1; i >= 0; i -= 1) {
299
+ for (let j = m - 1; j >= 0; j -= 1) {
300
+ table[i][j] = a[i] === b[j] ? table[i + 1][j + 1] + 1 : Math.max(table[i + 1][j], table[i][j + 1]);
301
+ }
302
+ }
303
+ const out = [];
304
+ let i = 0;
305
+ let j = 0;
306
+ while (i < n && j < m) {
307
+ if (a[i] === b[j]) {
308
+ i += 1;
309
+ j += 1;
310
+ }
311
+ else if (table[i + 1][j] >= table[i][j + 1]) {
312
+ out.push(`- ${a[i]}`);
313
+ i += 1;
314
+ }
315
+ else {
316
+ out.push(`+ ${b[j]}`);
317
+ j += 1;
318
+ }
319
+ }
320
+ while (i < n)
321
+ out.push(`- ${a[i++]}`);
322
+ while (j < m)
323
+ out.push(`+ ${b[j++]}`);
324
+ return out;
325
+ }
326
+ /** The package the input names, read from the catalogue the gateway keeps; a refusal otherwise. */
327
+ export async function findPackage(service, name) {
328
+ if (!service)
329
+ refuse('no-catalogue', 'this process has no catalogue bound, so no package can be added from it');
330
+ const loaded = await service.load();
331
+ if ('unavailable' in loaded)
332
+ refuse('offline', `${CATALOGUE_OFFLINE} (${loaded.unavailable})`);
333
+ const pkg = loaded.packages.find((p) => p.manifest.name === name.trim().toLowerCase());
334
+ if (!pkg) {
335
+ const refused = loaded.problems.find((p) => p.startsWith(`${name.trim().toLowerCase()}:`));
336
+ if (refused)
337
+ refuse('refused-listing', refused);
338
+ refuse('unknown-package', `the catalogue lists no agent "${name}". Listed: ${loaded.packages.map((p) => p.manifest.name).join(', ') || 'nothing'}. ` +
339
+ 'Call platform.catalogue to see them.');
340
+ }
341
+ return pkg;
342
+ }
343
+ /** The example asks the agent file can carry as its starters (each at most STARTER_MAX characters). */
344
+ function starters(pkg) {
345
+ return pkg.manifest.examples.filter((example) => example.trim().length <= STARTER_MAX).map((example) => example.trim());
346
+ }
347
+ function pickRecord(picks) {
348
+ return Object.fromEntries(picks.map((p) => [p.id, p.value]));
349
+ }
350
+ function missionPlans(pkg, agentId, picks, timezone, on) {
351
+ return pkg.manifest.missions.map((m) => {
352
+ const time = pkg.manifest.fills.find((f) => f.kind === 'time' && f.mission === m.id);
353
+ const clock = time ? picks.find((p) => p.id === time.id)?.value : undefined;
354
+ return {
355
+ id: agentMissionId(agentId, m.id),
356
+ slug: m.id,
357
+ name: m.name,
358
+ cron: clock ? cronAt(m.cron, clock) : m.cron,
359
+ timezone,
360
+ prompt: m.prompt,
361
+ enabled: on.has(m.id),
362
+ ...(m.alwaysDeliver === undefined ? {} : { alwaysDeliver: m.alwaysDeliver }),
363
+ ...(m.misfirePolicy === undefined ? {} : { misfirePolicy: m.misfirePolicy }),
364
+ };
365
+ });
366
+ }
367
+ function packageSkills(pkg, agentDir) {
368
+ return pkg.skills.map((skill) => {
369
+ const content = composeSkillFile({
370
+ name: skill.name,
371
+ description: skill.description,
372
+ provenance: 'imported',
373
+ source: `catalogue/${pkg.manifest.name}@${pkg.manifest.version}`,
374
+ body: skill.body,
375
+ });
376
+ try {
377
+ parseSkillFile(content, { fileName: skill.name });
378
+ }
379
+ catch (err) {
380
+ refuse('would-not-load', `${pkg.manifest.title} carries a skill the loader refuses: ${err instanceof Error ? err.message : String(err)}`);
381
+ }
382
+ return { name: skill.name, description: skill.description, file: path.join(agentDir, SKILLS_DIR, `${skill.name}.md`), content };
383
+ });
384
+ }
385
+ function checkDenied(pkg, resolvedTools) {
386
+ const denied = deniedTools(pkg.manifest.tools, resolvedTools);
387
+ if (denied.length > 0) {
388
+ refuse('denied-tool', `${pkg.manifest.title} asks for ${denied.join(', ')}, which no catalogue agent may be given. ` +
389
+ 'You can add any of them by hand after it is added.');
390
+ }
391
+ }
392
+ /**
393
+ * The plan the owner was shown, as one fingerprint: the whole envelope but who
394
+ * proposed it — the package's integrity, the resolved grant, the file's and
395
+ * every affected skill's hash as they are now, the missions. The dashboard and
396
+ * `buddi agents` send it back with the click, so the approval the route
397
+ * records is the plan the owner read, or nothing (agent-catalogue.md §8).
398
+ */
399
+ export function planFingerprint(envelope) {
400
+ const { proposedBy: _proposedBy, created, ...rest } = envelope;
401
+ const bound = created ? { ...rest, created: { ...created, proposedBy: '' } } : rest;
402
+ return hashEnvelope(bound);
403
+ }
404
+ /**
405
+ * Build the envelope for adding (or, with `agent`, updating) a package, and
406
+ * refuse it when the plan the owner was shown (`plan`) is no longer it.
407
+ */
408
+ export async function buildInstallEnvelope(input, deps) {
409
+ const envelope = await composeInstallEnvelope(input, deps);
410
+ if (input.plan !== undefined && planFingerprint(envelope) !== input.plan) {
411
+ refuse('plan-moved', `what ${envelope.mode === 'update' ? `updating @${envelope.handle}` : `adding ${envelope.package.title}`} would do changed since ` +
412
+ 'it was shown (the package, the tools it gets, or a file on disk). Look at it again before you approve it.');
413
+ }
414
+ return envelope;
415
+ }
416
+ /**
417
+ * Compose the envelope. Everything knowable is checked here, before any
418
+ * approval exists.
419
+ */
420
+ async function composeInstallEnvelope(input, deps) {
421
+ const { registry, helpers } = deps;
422
+ const service = helpers.service(registry);
423
+ const pkg = await findPackage(service, input.name);
424
+ const m = pkg.manifest;
425
+ if (input.version !== undefined && input.version.trim() !== m.version) {
426
+ refuse('version-moved', `the catalogue now lists ${m.title} ${m.version}, not ${input.version}. Look at it again before adding it.`);
427
+ }
428
+ const version = await service.version();
429
+ if (satisfiesRange(plainVersion(version), m.buddi) === false) {
430
+ refuse('buddi-too-old', `${m.title} needs buddi ${m.buddi}; this is ${plainVersion(version)}. Update buddi first.`);
431
+ }
432
+ const missing = missingPlugins(pkg, { registry, plugins: service.plugins() });
433
+ if (missing.length > 0) {
434
+ refuse('missing-plugin', `${m.title} needs ${missing.map((p) => `the ${p.name} plugin${p.fix === 'update' ? ` ${p.range} (${p.installed} is installed)` : p.fix === 'enable' ? ' (installed, but off)' : ''}`).join(' and ')}. ` +
435
+ 'Adding it from the catalogue installs a missing by-buddi plugin on the way; from here, install it first.');
436
+ }
437
+ const needs = await service.needs();
438
+ const unmet = m.needs.filter((need) => need !== 'mailbox?' && !needs[need]);
439
+ if (unmet.length > 0 && input.agent === undefined) {
440
+ refuse('missing-need', `${m.title} needs ${unmet.map((n) => (n === 'mailbox' ? 'a mailbox (Settings → Email)' : 'an account that draws (Settings → Model accounts)')).join(' and ')} first.`);
441
+ }
442
+ const binding = helpers.resolved(registry);
443
+ const choices = m.fills.some((f) => f.kind === 'mailbox' || f.kind === 'calendar' || f.kind === 'place')
444
+ ? await service.choices()
445
+ : { mailboxes: [], calendars: [], places: [] };
446
+ const known = new Set(m.missions.map((mission) => mission.id));
447
+ const strayMissions = (input.missionsOn ?? []).filter((id) => !known.has(id));
448
+ if (strayMissions.length > 0) {
449
+ refuse('unknown-mission', `${m.title} has no mission "${strayMissions.join('", "')}". Its missions: ${[...known].join(', ') || 'none'}.`);
450
+ }
451
+ const avatar = pkg.avatar && pkg.avatarSha256 ? { url: pkg.avatar, sha256: pkg.avatarSha256 } : null;
452
+ const packageInfo = { name: m.name, version: m.version, integrity: m.integrity, title: m.title, changes: m.changes };
453
+ if (input.agent !== undefined)
454
+ return buildUpdate(input, deps, pkg, binding, choices, packageInfo, avatar);
455
+ if (input.replaceEdits !== undefined)
456
+ refuse('not-an-update', '`replaceEdits` goes with `agent`, the agent being updated');
457
+ const already = installedAsFor(pkg, addedAgents(binding.agentsDir), (id) => binding.catalog.get(id)?.handle ?? id);
458
+ if (already) {
459
+ refuse('already-added', `${m.title} is already on the team as @${already.handle}${already.via ? ` (from ${already.via})` : ''}. ` +
460
+ (already.drift === 'update' ? `To bring it to ${m.version}, update it (agent: "${already.agentId}").` : 'Nothing to add.'));
461
+ }
462
+ const takenId = (id) => binding.catalog.get(id) !== undefined || existsSync(path.join(binding.agentsDir, id));
463
+ const takenHandle = (handle) => binding.catalog.list().some((a) => a.handle.toLowerCase() === handle.toLowerCase());
464
+ const id = freeName(m.name, takenId, 40);
465
+ const handle = input.handle !== undefined ? input.handle.trim().replace(/^@/, '').toLowerCase() : freeName(m.handle, takenHandle, HANDLE_MAX);
466
+ const picks = resolvePicks(pkg, input.fills, choices);
467
+ const speaks = input.account === undefined ? helpers.speakingAccount(registry, deps.proposedBy) : null;
468
+ const created = helpers.buildCreate({
469
+ id,
470
+ handle,
471
+ name: m.title,
472
+ description: m.description,
473
+ persona: composePackagePersona(pkg.persona, picks),
474
+ tools: [...m.tools],
475
+ ...(m.language === undefined ? {} : { language: m.language }),
476
+ ...(m.idleRollover === undefined ? {} : { idleRollover: m.idleRollover }),
477
+ ...(starters(pkg).length === 0 ? {} : { starters: starters(pkg) }),
478
+ ...(m.roles === undefined || m.roles.length === 0 ? {} : { roles: [...m.roles] }),
479
+ ...(input.account !== undefined ? { account: input.account } : speaks ? { account: speaks.account.label, model: speaks.account.model } : {}),
480
+ }, { registry, proposedBy: deps.proposedBy });
481
+ checkDenied(pkg, created.tools);
482
+ const agentDir = path.dirname(created.file);
483
+ return {
484
+ tool: 'platform.install_agent',
485
+ mode: 'install',
486
+ proposedBy: deps.proposedBy,
487
+ package: packageInfo,
488
+ id: created.id,
489
+ handle: created.handle,
490
+ name: created.name,
491
+ description: created.description,
492
+ file: created.file,
493
+ tools: created.tools,
494
+ declaredTools: created.declaredTools,
495
+ account: created.account,
496
+ inheritedFrom: created.account === null ? null : (speaks?.from ?? null),
497
+ content: created.content,
498
+ skills: packageSkills(pkg, agentDir),
499
+ missions: missionPlans(pkg, created.id, picks, deps.timezone, new Set(input.missionsOn ?? [])),
500
+ picks,
501
+ avatar,
502
+ created,
503
+ };
504
+ }
505
+ async function buildUpdate(input, deps, pkg, binding, choices, packageInfo, avatar) {
506
+ const { registry, helpers } = deps;
507
+ const m = pkg.manifest;
508
+ const wanted = input.agent.trim().replace(/^@/, '');
509
+ const agent = binding.catalog.get(wanted) ?? binding.catalog.byHandle(wanted);
510
+ if (!agent)
511
+ refuse('unknown-agent', `there is no agent "${input.agent}" here`);
512
+ const dir = path.dirname(agent.file);
513
+ const added = addedAgents(path.dirname(dir)).find((a) => a.agentId === path.basename(dir));
514
+ const how = added ? matchesPackage(pkg, added) : null;
515
+ if (!added || how === null) {
516
+ refuse('not-from-package', `@${agent.handle} did not come from ${m.title} in the catalogue, so there is nothing to update; it is yours as it is.`);
517
+ }
518
+ const via = how === 'replaces' ? `${added.provenance.plugin}/${added.provenance.agent}` : null;
519
+ if (how === 'package' && added.provenance.proposal === m.integrity && !added.edited) {
520
+ refuse('up-to-date', `@${agent.handle} is already ${m.title} ${m.version}, unchanged on both sides.`);
521
+ }
522
+ // Every skill file the update touches, as it is now. A file of the same name the
523
+ // earlier version never wrote is the owner's (or a learned one): replacing it is
524
+ // replacing their work. A skill the earlier version wrote and this one dropped
525
+ // goes to the trash, or it would keep running with nobody's provenance on it.
526
+ const skills = packageSkills(pkg, dir);
527
+ const tracked = added.provenance.skills ?? {};
528
+ const readNow = (file) => {
529
+ try {
530
+ return readFileSync(file, 'utf8');
531
+ }
532
+ catch {
533
+ return null;
534
+ }
535
+ };
536
+ const skillsBefore = {};
537
+ const replacesOwn = [];
538
+ for (const skill of skills) {
539
+ const now = readNow(skill.file);
540
+ skillsBefore[skill.name] = now === null ? null : fileHash(now);
541
+ if (now !== null && !(skill.name in tracked) && now !== skill.content)
542
+ replacesOwn.push(skill.name);
543
+ }
544
+ const retires = [];
545
+ for (const name of Object.keys(tracked).sort()) {
546
+ if (skills.some((skill) => skill.name === name))
547
+ continue;
548
+ const now = readNow(path.join(dir, SKILLS_DIR, `${name}.md`));
549
+ skillsBefore[name] = now === null ? null : fileHash(now);
550
+ if (now !== null)
551
+ retires.push(name);
552
+ }
553
+ const edited = added.edited || replacesOwn.length > 0;
554
+ if (edited && input.replaceEdits !== true) {
555
+ refuse('owner-edited', replacesOwn.length > 0 && !added.edited
556
+ ? `@${agent.handle} has ${replacesOwn.length === 1 ? 'a skill' : 'skills'} of your own (${replacesOwn.join(', ')}) that ` +
557
+ `${m.title} ${m.version} would replace with ${replacesOwn.length === 1 ? 'one' : 'ones'} of the same name, so nothing will ` +
558
+ 'touch it. To replace them, the owner has to say so (replaceEdits), and theirs go to the trash first.'
559
+ : `you have changed @${agent.handle}'s file or one of its skills, so nothing will touch it. ${m.title} ${m.version} is out; ` +
560
+ 'to replace your changes with it, the owner has to say so (replaceEdits), and their file goes to the trash first.');
561
+ }
562
+ if (input.handle !== undefined)
563
+ refuse('not-a-field', 'an update keeps the handle; rename it on the Agents page');
564
+ if (input.missionsOn !== undefined && input.missionsOn.length > 0) {
565
+ refuse('not-a-field', 'an update adds new missions off and never turns one on; switch them on under Agents → Missions');
566
+ }
567
+ const current = readFileSync(agent.file, 'utf8');
568
+ const before = parseAgentFile(current, { file: agent.file });
569
+ const remembered = added.provenance.fills ?? {};
570
+ const keep = Object.fromEntries(Object.entries(remembered).filter(([id]) => m.fills.some((f) => f.id === id)));
571
+ const picks = resolvePicks(pkg, { ...keep, ...(input.fills ?? {}) }, choices);
572
+ const persona = composePackagePersona(pkg.persona, picks);
573
+ const declared = [...m.tools];
574
+ const tools = helpers.checkTools(declared, registry, agent.id);
575
+ checkDenied(pkg, tools);
576
+ const composed = composeAgentFile({
577
+ id: agent.id,
578
+ handle: agent.handle,
579
+ name: m.title,
580
+ description: m.description,
581
+ tools: declared,
582
+ ...(m.language === undefined ? {} : { language: m.language }),
583
+ ...(m.idleRollover === undefined ? {} : { idleRollover: m.idleRollover }),
584
+ ...(starters(pkg).length === 0 ? {} : { starters: starters(pkg) }),
585
+ ...(m.roles === undefined || m.roles.length === 0 ? {} : { roles: [...m.roles] }),
586
+ persona,
587
+ });
588
+ // The skills the owner granted it are theirs, not the package's: an update keeps them.
589
+ const granted = before.frontmatter.skills ?? [];
590
+ const content = granted.length === 0 ? composed : applyFrontmatterPatch(composed, { skills: [...granted] }, agent.file);
591
+ try {
592
+ parseAgentFile(content, { dirName: agent.id });
593
+ }
594
+ catch (err) {
595
+ refuse('would-not-load', `this would write a file the loader refuses: ${err instanceof Error ? err.message : String(err)}`);
596
+ }
597
+ const grant = diffGrant(agent.tools, tools);
598
+ const existing = new Set();
599
+ if (deps.db) {
600
+ for (const mission of m.missions) {
601
+ const row = await getMission(deps.db, agentMissionId(agent.id, mission.id)).catch(() => null);
602
+ if (row)
603
+ existing.add(mission.id);
604
+ }
605
+ }
606
+ const missions = missionPlans(pkg, agent.id, picks, deps.timezone, new Set()).filter((plan) => !existing.has(plan.slug));
607
+ return {
608
+ tool: 'platform.install_agent',
609
+ mode: 'update',
610
+ proposedBy: deps.proposedBy,
611
+ package: packageInfo,
612
+ id: agent.id,
613
+ handle: agent.handle,
614
+ name: m.title,
615
+ description: m.description,
616
+ file: agent.file,
617
+ tools,
618
+ declaredTools: declared,
619
+ account: null,
620
+ inheritedFrom: null,
621
+ content,
622
+ skills,
623
+ missions,
624
+ picks,
625
+ avatar,
626
+ update: {
627
+ fromVersion: added.provenance.version,
628
+ via,
629
+ edited,
630
+ previousFile: fileHash(current),
631
+ skillsBefore,
632
+ replacesOwn,
633
+ retires,
634
+ toolsBefore: [...agent.tools],
635
+ added: grant.added,
636
+ removed: grant.removed,
637
+ widened: grant.widened,
638
+ personaDiff: lineDiff(before.body, persona),
639
+ },
640
+ };
641
+ }
642
+ function missionLines(missions) {
643
+ return missions.map((mission) => ` ${mission.name}, ${describeCadence(mission.cron, mission.timezone)} — ` +
644
+ (mission.enabled ? 'ON from the start' : 'off until you turn it on'));
645
+ }
646
+ export function renderInstallPreview(envelope, specs, renderCreate) {
647
+ const picks = envelope.picks.filter((p) => p.kind !== 'time' && p.value !== '');
648
+ if (envelope.mode === 'update' && envelope.update) {
649
+ const u = envelope.update;
650
+ return [
651
+ `Update @${envelope.handle} from the catalogue: ${envelope.package.title} ${envelope.package.version}` +
652
+ ` (you have ${u.via ? `${u.via} ${u.fromVersion}` : u.fromVersion}).`,
653
+ `What changed: ${envelope.package.changes}`,
654
+ '',
655
+ ...(u.edited
656
+ ? [
657
+ u.replacesOwn.length > 0
658
+ ? `YOUR OWN SKILL${u.replacesOwn.length === 1 ? '' : 'S'} ${u.replacesOwn.join(', ')} would be replaced by the ` +
659
+ `catalogue's of the same name. Approving replaces ${u.replacesOwn.length === 1 ? 'it' : 'them'} (and any change you made ` +
660
+ 'to its file); your versions are kept in the trash beside your agents, and moving them back restores them.'
661
+ : `YOU CHANGED THIS FILE. Approving replaces your changes with the catalogue's; your version is kept in ` +
662
+ 'the trash beside your agents, and moving it back restores it.',
663
+ '',
664
+ ]
665
+ : []),
666
+ ...(u.retires.length > 0
667
+ ? [
668
+ `This version no longer carries ${u.retires.length === 1 ? 'the skill' : 'the skills'} ${u.retires.join(', ')}: ` +
669
+ `${u.retires.length === 1 ? 'it goes' : 'they go'} to the trash beside your agents.`,
670
+ '',
671
+ ]
672
+ : []),
673
+ ...grantChangeBlock(envelope.handle, { ...diffGrant(u.toolsBefore, envelope.tools) }, specs),
674
+ '',
675
+ ...(u.personaDiff.length === 0
676
+ ? ['Its persona is unchanged.']
677
+ : ['Its persona changes:', ...u.personaDiff.slice(0, 80).map((line) => ` ${line}`), ...(u.personaDiff.length > 80 ? [` … and ${u.personaDiff.length - 80} more lines`] : [])]),
678
+ ...(envelope.missions.length === 0
679
+ ? []
680
+ : ['', 'New missions it suggests, each off until you turn it on:', ...missionLines(envelope.missions)]),
681
+ '',
682
+ 'Missions it already has are yours and stay exactly as they are. Its handle, its account and its memory do not change.',
683
+ `File: ${envelope.file}`,
684
+ `Proposed by ${envelope.proposedBy}.`,
685
+ ].join('\n');
686
+ }
687
+ return [
688
+ `Add ${envelope.package.title} ${envelope.package.version} from the catalogue (made by buddi).`,
689
+ '',
690
+ renderCreate(envelope.created, specs),
691
+ '',
692
+ ...(envelope.account === null
693
+ ? []
694
+ : [
695
+ `Speaks through ${envelope.account.label} with ${envelope.account.model}` +
696
+ `${envelope.inheritedFrom === null ? '' : ` (from @${envelope.inheritedFrom})`}; change it on the Agents page.`,
697
+ '',
698
+ ]),
699
+ ...(picks.length === 0
700
+ ? []
701
+ : ['For this owner (written after its persona):', ...picks.map((p) => ` ${p.label.replace(/[?:.\s]+$/, '')}: ${p.value}`), '']),
702
+ ...(envelope.skills.length === 0
703
+ ? []
704
+ : [
705
+ `It arrives with ${envelope.skills.length} skill${envelope.skills.length === 1 ? '' : 's'} of its own ` +
706
+ '(a procedure in its prompt; it grants no tool and lowers no tier):',
707
+ ...envelope.skills.map((s) => ` ${s.name} — ${s.description}`),
708
+ '',
709
+ ]),
710
+ ...(envelope.missions.length === 0
711
+ ? []
712
+ : [`Its missions (pause or start any of them under Agents → Missions):`, ...missionLines(envelope.missions), '']),
713
+ `Once you approve, this file is YOURS: an update from the catalogue is always offered, never written`,
714
+ 'without your approval, and a file you change is never touched.',
715
+ ].join('\n');
716
+ }
717
+ export function entryView(pkg, state, timezone, defaults) {
718
+ const m = pkg.manifest;
719
+ return {
720
+ name: m.name,
721
+ version: m.version,
722
+ handle: m.handle,
723
+ title: m.title,
724
+ pitch: m.pitch,
725
+ description: m.description,
726
+ about: m.about,
727
+ category: m.category,
728
+ trust: m.trust,
729
+ author: m.author,
730
+ requires: m.requires,
731
+ optional: m.optional,
732
+ needs: m.needs,
733
+ tools: m.tools,
734
+ missions: m.missions.map((mission) => ({
735
+ id: mission.id,
736
+ name: mission.name,
737
+ cron: mission.cron,
738
+ when: describeCadence(mission.cron, timezone),
739
+ prompt: mission.prompt,
740
+ })),
741
+ fills: m.fills.map((fill) => ({
742
+ id: fill.id,
743
+ kind: fill.kind,
744
+ label: fill.label,
745
+ optional: fill.optional === true,
746
+ default: defaults?.find((d) => d.id === fill.id)?.value ?? '',
747
+ })),
748
+ examples: m.examples,
749
+ skills: pkg.skills.map((s) => s.name),
750
+ changes: m.changes,
751
+ replaces: m.replaces,
752
+ avatar: pkg.avatar,
753
+ page: pkg.page,
754
+ ...(m.claims === undefined ? {} : { claims: m.claims }),
755
+ state: state.state,
756
+ ...(state.state === 'needs' ? { missing: state.missing } : {}),
757
+ ...(state.state === 'installed' ? { installed: state.installed } : {}),
758
+ ...(state.state === 'unavailable' ? { reason: state.reason } : {}),
759
+ };
760
+ }
761
+ /** A context for `packageState`, read once for a whole list. */
762
+ export async function stateContext(registry, service, binding) {
763
+ return {
764
+ registry,
765
+ version: await service.version(),
766
+ needs: await service.needs(),
767
+ plugins: service.plugins(),
768
+ added: addedAgents(binding.agentsDir),
769
+ handleOf: (id) => binding.catalog.get(id)?.handle ?? id,
770
+ };
771
+ }
772
+ export function createCatalogueTools(registry, helpers) {
773
+ const catalogue = {
774
+ name: 'platform.catalogue',
775
+ description: 'The agent catalogue: ready-made teammates buddi publishes on withbuddi.com (a chef, a researcher, a CFO…), ' +
776
+ 'each with what it is for, its category, the picks it asks, its missions (they arrive off) and where it stands ' +
777
+ 'here: ready, needs a plugin or a mailbox, already added (with an update when one is out), or unavailable. ' +
778
+ 'Read this before you offer one, and before you make an agent from scratch: the owner may want one already listed.',
779
+ tier: 'auto',
780
+ input: z.object({}).strict(),
781
+ async execute(_input, ctx) {
782
+ const service = helpers.service(registry);
783
+ if (!service)
784
+ return { unavailable: 'this process has no catalogue bound', agents: [] };
785
+ const loaded = await service.load();
786
+ if ('unavailable' in loaded)
787
+ return { unavailable: CATALOGUE_OFFLINE, agents: [] };
788
+ const binding = helpers.resolved(registry);
789
+ const state = await stateContext(registry, service, binding);
790
+ const choices = loaded.packages.some((p) => p.manifest.fills.length > 0) ? await service.choices() : null;
791
+ return {
792
+ fetchedAt: loaded.fetchedAt,
793
+ ...(loaded.stale ? { stale: true } : {}),
794
+ agents: loaded.packages.map((pkg) => {
795
+ const view = entryView(pkg, packageState(pkg, state), ctx.timezone);
796
+ return {
797
+ name: view.name,
798
+ version: view.version,
799
+ title: view.title,
800
+ handle: view.handle,
801
+ pitch: view.pitch,
802
+ category: view.category,
803
+ about: view.about,
804
+ state: view.state,
805
+ ...(view.missing ? { missing: view.missing } : {}),
806
+ ...(view.installed ? { installed: view.installed } : {}),
807
+ ...(view.reason ? { reason: view.reason } : {}),
808
+ picks: pkg.manifest.fills.map((fill) => ({
809
+ id: fill.id,
810
+ kind: fill.kind,
811
+ question: fill.label,
812
+ optional: fill.optional === true,
813
+ ...(choices && fill.kind === 'mailbox' ? { choices: choices.mailboxes } : {}),
814
+ ...(choices && fill.kind === 'calendar' ? { choices: choices.calendars } : {}),
815
+ ...(choices && fill.kind === 'place' ? { choices: choices.places.map((p) => p.label) } : {}),
816
+ })),
817
+ missions: view.missions.map((mission) => ({ id: mission.id, name: mission.name, when: mission.when })),
818
+ examples: view.examples,
819
+ tools: view.tools,
820
+ };
821
+ }),
822
+ fromPlugins: helpers
823
+ .proposals(registry)
824
+ .filter(({ plugin, agent }) => !loaded.packages.some((p) => p.manifest.replaces.includes(`${plugin}/${agent.id}`)))
825
+ .map(({ plugin, agent }) => ({
826
+ plugin,
827
+ id: agent.id,
828
+ name: agent.name,
829
+ description: agent.description,
830
+ accepted: binding.catalog.get(agent.id) !== undefined,
831
+ })),
832
+ note: 'Add one with platform.install_agent: ask the owner each pick in a sentence first (a missing answer takes its ' +
833
+ 'default), and which missions to turn on now. Agents "from" a plugin are added with platform.accept_plugin_agent.',
834
+ };
835
+ },
836
+ };
837
+ const install = {
838
+ name: 'platform.install_agent',
839
+ description: 'Add an agent from the catalogue (platform.catalogue) to the owner\'s team, or update one already added (`agent`). ' +
840
+ 'Its persona is written verbatim with the owner\'s picks after it; it gets exactly the tools the package asks for, ' +
841
+ 'shown to the owner tool by tool; its missions arrive off unless the owner asked for them. Needs the owner\'s ' +
842
+ 'approval, and the file is theirs once written. A package whose plugin is not installed is refused here: the ' +
843
+ 'dashboard\'s catalogue installs a by-buddi plugin on the way, so send the owner there, or install the plugin first.',
844
+ tier: 'gated',
845
+ input: installAgentInput,
846
+ async describe(input, ctx) {
847
+ const envelope = await buildInstallEnvelope(input, {
848
+ registry,
849
+ helpers,
850
+ proposedBy: ctx.agentId ?? 'unknown',
851
+ timezone: ctx.timezone,
852
+ ...(ctx.db ? { db: ctx.db } : {}),
853
+ });
854
+ return { envelope, preview: renderInstallPreview(envelope, registry.list(), helpers.renderCreatePreview) };
855
+ },
856
+ async execute(input, ctx) {
857
+ const envelope = await buildInstallEnvelope(input, {
858
+ registry,
859
+ helpers,
860
+ proposedBy: ctx.agentId ?? 'unknown',
861
+ timezone: ctx.timezone,
862
+ ...(ctx.db ? { db: ctx.db } : {}),
863
+ });
864
+ assertApprovedEffect(ctx, envelope);
865
+ const binding = helpers.resolved(registry);
866
+ const dir = path.dirname(envelope.file);
867
+ const sidecar = composeProvenance({
868
+ source: 'market',
869
+ plugin: 'market',
870
+ package: envelope.package.name,
871
+ version: envelope.package.version,
872
+ agent: envelope.package.name,
873
+ acceptedAt: ctx.now(),
874
+ proposal: envelope.package.integrity,
875
+ // Hashed without the owner's `skills:` grants, which an update carries over.
876
+ file: packageOwnedText(envelope.content),
877
+ fills: pickRecord(envelope.picks),
878
+ skills: Object.fromEntries(envelope.skills.map((skill) => [skill.name, skill.content])),
879
+ });
880
+ let trashed = null;
881
+ /** Put the tree back as it was, when the catalogue will not load with the change. */
882
+ let undo;
883
+ if (envelope.mode === 'install') {
884
+ createAgentDirAtomic(dir, {
885
+ [AGENT_FILE]: envelope.content,
886
+ [PROVENANCE_FILE]: sidecar,
887
+ ...Object.fromEntries(envelope.skills.map((skill) => [path.join(SKILLS_DIR, `${skill.name}.md`), skill.content])),
888
+ });
889
+ undo = () => rmSync(dir, { recursive: true, force: true });
890
+ }
891
+ else {
892
+ const u = envelope.update;
893
+ const retiredFile = (name) => path.join(dir, SKILLS_DIR, `${name}.md`);
894
+ // Every path this touches, as it is now: what an undo writes back.
895
+ const before = new Map();
896
+ for (const file of [envelope.file, path.join(dir, PROVENANCE_FILE), ...envelope.skills.map((s) => s.file), ...u.retires.map(retiredFile)]) {
897
+ before.set(file, existsSync(file) ? readFileSync(file, 'utf8') : null);
898
+ }
899
+ // What goes to the trash, where a deleted agent goes: moving it back restores it.
900
+ // The owner's file when they changed it; any skill of theirs a package skill
901
+ // replaces; every skill this version retires.
902
+ const aside = path.join(binding.trashRoot, 'agents', `${envelope.id}-${trashStamp(ctx.now())}-replaced`);
903
+ const kept = [];
904
+ if (u.edited) {
905
+ trashed = path.join(aside, AGENT_FILE);
906
+ kept.push({ path: trashed, content: before.get(envelope.file) ?? '' });
907
+ }
908
+ for (const skill of envelope.skills) {
909
+ const now = before.get(skill.file);
910
+ if (now !== null && now !== undefined && now !== skill.content)
911
+ kept.push({ path: path.join(aside, SKILLS_DIR, `${skill.name}.md`), content: now });
912
+ }
913
+ for (const name of u.retires) {
914
+ const now = before.get(retiredFile(name));
915
+ if (now !== null && now !== undefined)
916
+ kept.push({ path: path.join(aside, SKILLS_DIR, `${name}.md`), content: now });
917
+ }
918
+ if (kept.length > 0)
919
+ writeFilesAtomic(kept);
920
+ writeFilesAtomic([
921
+ { path: envelope.file, content: envelope.content },
922
+ { path: path.join(dir, PROVENANCE_FILE), content: sidecar },
923
+ ...envelope.skills.map((skill) => ({ path: skill.file, content: skill.content })),
924
+ ]);
925
+ for (const name of u.retires)
926
+ rmSync(retiredFile(name), { force: true });
927
+ undo = () => {
928
+ writeFilesAtomic([...before].filter((e) => e[1] !== null).map(([file, content]) => ({ path: file, content })));
929
+ for (const [file, content] of before)
930
+ if (content === null)
931
+ rmSync(file, { force: true });
932
+ if (kept.length > 0)
933
+ rmSync(aside, { recursive: true, force: true });
934
+ };
935
+ }
936
+ const reload = helpers.reload(registry);
937
+ if (!reload.reloaded) {
938
+ // A tree the catalogue refuses would not boot either: nothing stays written.
939
+ undo();
940
+ helpers.reload(registry);
941
+ refuse('would-not-load', `${envelope.mode === 'install' ? `${envelope.package.title} was not added` : `@${envelope.handle} was not updated`}, and ` +
942
+ `nothing was changed: the agents would not load with it (${reload.error ?? reload.message}).`);
943
+ }
944
+ const assigned = envelope.mode === 'install' ? await helpers.assignAccount(registry, envelope.id, envelope.account) : '';
945
+ let pictured = false;
946
+ // The package's picture is kept in the database at install, so every page draws it without asking
947
+ // the market again. An update gives one only to an agent that has none (the fetch failed at install,
948
+ // or it came through `replaces`); a face the owner chose is never replaced.
949
+ const wantsPicture = envelope.mode === 'install' || (ctx.db ? (await readAvatar(ctx.db, envelope.id).catch(() => null)) === null : false);
950
+ if (wantsPicture && envelope.avatar && ctx.db) {
951
+ // Best effort: an agent without its face is still the agent the owner approved.
952
+ try {
953
+ const service = helpers.service(registry);
954
+ const pkg = service ? await findPackage(service, envelope.package.name) : null;
955
+ const bytes = pkg ? await service.avatar(pkg) : null;
956
+ if (bytes) {
957
+ await writeAvatar(ctx.db, envelope.id, await normaliseAvatar(bytes));
958
+ pictured = true;
959
+ }
960
+ }
961
+ catch {
962
+ pictured = false;
963
+ }
964
+ }
965
+ const created = [];
966
+ if (ctx.db) {
967
+ for (const mission of envelope.missions) {
968
+ if (envelope.mode === 'update' && (await getMission(ctx.db, mission.id).catch(() => null)))
969
+ continue;
970
+ await upsertMission(ctx.db, {
971
+ id: mission.id,
972
+ name: mission.name,
973
+ agentId: envelope.id,
974
+ prompt: mission.prompt,
975
+ enabled: mission.enabled,
976
+ alwaysDeliver: mission.alwaysDeliver ?? false,
977
+ });
978
+ await setSchedule(ctx.db, mission.id, {
979
+ cron: mission.cron,
980
+ timezone: mission.timezone,
981
+ // The owner's zone of the moment: it follows the owner.
982
+ timezoneExplicit: false,
983
+ misfirePolicy: mission.misfirePolicy ?? 'coalesce',
984
+ });
985
+ created.push(mission.id);
986
+ }
987
+ }
988
+ return {
989
+ ok: true,
990
+ mode: envelope.mode,
991
+ id: envelope.id,
992
+ handle: envelope.handle,
993
+ file: envelope.file,
994
+ package: { name: envelope.package.name, version: envelope.package.version },
995
+ tools: envelope.tools,
996
+ skills: envelope.skills.map((s) => s.name),
997
+ missions: created,
998
+ ...(pictured ? { picture: true } : {}),
999
+ ...(trashed ? { previousFile: trashed } : {}),
1000
+ live: reload.reloaded,
1001
+ message: (envelope.mode === 'install'
1002
+ ? `@${envelope.handle} is on the team, and the file is the owner's now. `
1003
+ : `@${envelope.handle} is ${envelope.package.title} ${envelope.package.version} now${trashed ? `; the owner's previous file is at ${trashed}` : ''}. `) +
1004
+ `${reload.message}${assigned}`,
1005
+ };
1006
+ },
1007
+ };
1008
+ return [catalogue, install];
1009
+ }
1010
+ /** The plan the dashboard's sheet draws: the envelope and its preview, nothing written. */
1011
+ export async function planInstall(registry, helpers, input, ctx) {
1012
+ const envelope = await buildInstallEnvelope(input, {
1013
+ registry,
1014
+ helpers,
1015
+ proposedBy: ctx.agentId ?? 'owner',
1016
+ timezone: ctx.timezone,
1017
+ ...(ctx.db ? { db: ctx.db } : {}),
1018
+ });
1019
+ return { envelope, preview: renderInstallPreview(envelope, registry.list(), helpers.renderCreatePreview), plan: planFingerprint(envelope) };
1020
+ }
1021
+ //# sourceMappingURL=platform-catalogue.js.map