@rubytech/create-maxy-code 0.1.538 → 0.1.540

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 (279) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/lib/agent-slug/dist/index.d.ts +31 -0
  3. package/payload/platform/lib/agent-slug/dist/index.d.ts.map +1 -0
  4. package/payload/platform/lib/agent-slug/dist/index.js +53 -0
  5. package/payload/platform/lib/agent-slug/dist/index.js.map +1 -0
  6. package/payload/platform/lib/agent-slug/src/index.ts +53 -0
  7. package/payload/platform/lib/agent-slug/tsconfig.json +8 -0
  8. package/payload/platform/package.json +2 -2
  9. package/payload/platform/plugins/admin/.claude-plugin/plugin.json +1 -1
  10. package/payload/platform/plugins/admin/PLUGIN.md +33 -1
  11. package/payload/platform/plugins/admin/mcp/dist/index.js +136 -0
  12. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  13. package/payload/platform/plugins/admin/mcp/dist/tools/agent-config-schema.d.ts +9 -0
  14. package/payload/platform/plugins/admin/mcp/dist/tools/agent-config-schema.d.ts.map +1 -0
  15. package/payload/platform/plugins/admin/mcp/dist/tools/agent-config-schema.js +49 -0
  16. package/payload/platform/plugins/admin/mcp/dist/tools/agent-config-schema.js.map +1 -0
  17. package/payload/platform/plugins/admin/mcp/dist/tools/agent-write.d.ts +64 -0
  18. package/payload/platform/plugins/admin/mcp/dist/tools/agent-write.d.ts.map +1 -0
  19. package/payload/platform/plugins/admin/mcp/dist/tools/agent-write.js +151 -0
  20. package/payload/platform/plugins/admin/mcp/dist/tools/agent-write.js.map +1 -0
  21. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +108 -14
  22. package/payload/platform/plugins/admin/skills/public-agent-manager/SKILL.md +36 -20
  23. package/payload/platform/plugins/admin/skills/update-knowledge/SKILL.md +4 -3
  24. package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +14 -0
  25. package/payload/platform/plugins/docs/references/admin-ui.md +73 -0
  26. package/payload/platform/plugins/docs/references/channel-wake-and-prompt.md +32 -11
  27. package/payload/platform/plugins/docs/references/internals.md +2 -2
  28. package/payload/platform/plugins/scheduling/PLUGIN.md +1 -1
  29. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-get-description.test.d.ts +2 -0
  30. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-get-description.test.d.ts.map +1 -0
  31. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-get-description.test.js +59 -0
  32. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-get-description.test.js.map +1 -0
  33. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-get.d.ts.map +1 -1
  34. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-get.js +6 -0
  35. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-get.js.map +1 -1
  36. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.d.ts.map +1 -1
  37. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.js +10 -6
  38. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.js.map +1 -1
  39. package/payload/platform/plugins/whatsapp/PLUGIN.md +2 -2
  40. package/payload/platform/plugins/whatsapp/mcp/dist/index.js +6 -1
  41. package/payload/platform/plugins/whatsapp/mcp/dist/index.js.map +1 -1
  42. package/payload/platform/plugins/whatsapp/skills/manage-whatsapp-config/SKILL.md +14 -8
  43. package/payload/platform/scripts/__tests__/check-plugin-tool-declarations.test.ts +51 -0
  44. package/payload/platform/scripts/check-plugin-tool-declarations.mjs +97 -0
  45. package/payload/platform/scripts/check-risk-class.mjs +5 -0
  46. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
  47. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +8 -0
  48. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
  49. package/payload/platform/services/claude-session-manager/dist/channel-targets.d.ts +3 -0
  50. package/payload/platform/services/claude-session-manager/dist/channel-targets.d.ts.map +1 -1
  51. package/payload/platform/services/claude-session-manager/dist/channel-targets.js.map +1 -1
  52. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  53. package/payload/platform/services/claude-session-manager/dist/http-server.js +20 -1
  54. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  55. package/payload/platform/services/claude-session-manager/dist/index.js +35 -18
  56. package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
  57. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
  58. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +57 -8
  59. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
  60. package/payload/platform/services/claude-session-manager/dist/public-knowledge-audit.d.ts +58 -0
  61. package/payload/platform/services/claude-session-manager/dist/public-knowledge-audit.d.ts.map +1 -0
  62. package/payload/platform/services/claude-session-manager/dist/public-knowledge-audit.js +152 -0
  63. package/payload/platform/services/claude-session-manager/dist/public-knowledge-audit.js.map +1 -0
  64. package/payload/platform/services/claude-session-manager/dist/wa-channel-mcp.d.ts +4 -0
  65. package/payload/platform/services/claude-session-manager/dist/wa-channel-mcp.d.ts.map +1 -1
  66. package/payload/platform/services/claude-session-manager/dist/wa-channel-mcp.js +3 -0
  67. package/payload/platform/services/claude-session-manager/dist/wa-channel-mcp.js.map +1 -1
  68. package/payload/platform/services/webchat-channel/dist/notification.d.ts +31 -0
  69. package/payload/platform/services/webchat-channel/dist/notification.d.ts.map +1 -1
  70. package/payload/platform/services/webchat-channel/dist/notification.js +31 -1
  71. package/payload/platform/services/webchat-channel/dist/notification.js.map +1 -1
  72. package/payload/platform/services/webchat-channel/dist/server.d.ts.map +1 -1
  73. package/payload/platform/services/webchat-channel/dist/server.js +15 -1
  74. package/payload/platform/services/webchat-channel/dist/server.js.map +1 -1
  75. package/payload/platform/services/whatsapp-channel/dist/notification.d.ts +40 -3
  76. package/payload/platform/services/whatsapp-channel/dist/notification.d.ts.map +1 -1
  77. package/payload/platform/services/whatsapp-channel/dist/notification.js +43 -4
  78. package/payload/platform/services/whatsapp-channel/dist/notification.js.map +1 -1
  79. package/payload/platform/services/whatsapp-channel/dist/server.d.ts.map +1 -1
  80. package/payload/platform/services/whatsapp-channel/dist/server.js +41 -25
  81. package/payload/platform/services/whatsapp-channel/dist/server.js.map +1 -1
  82. package/payload/platform/services/whatsapp-channel/dist/targets.d.ts +1 -0
  83. package/payload/platform/services/whatsapp-channel/dist/targets.d.ts.map +1 -1
  84. package/payload/platform/services/whatsapp-channel/dist/targets.js +9 -5
  85. package/payload/platform/services/whatsapp-channel/dist/targets.js.map +1 -1
  86. package/payload/server/{chunk-BP7LH7MC.js → chunk-CKTHAHL4.js} +26 -16
  87. package/payload/server/{chunk-IALJPXIO.js → chunk-ERIM3EFB.js} +1 -1
  88. package/payload/server/{chunk-FQO5RDWZ.js → chunk-TQTZXAK3.js} +124 -17
  89. package/payload/server/{manager-EBZQRV5V.js → manager-F6NXSOJW.js} +2 -2
  90. package/payload/server/maxy-edge.js +2 -2
  91. package/payload/server/public/activity.html +5 -5
  92. package/payload/server/public/agents.html +4 -4
  93. package/payload/server/public/assets/AdminLoginScreens-DuFCjbz2.js +1 -0
  94. package/payload/server/public/assets/AdminLoginScreens-DuFCjbz2.js.br +0 -0
  95. package/payload/server/public/assets/AdminLoginScreens-DuFCjbz2.js.gz +0 -0
  96. package/payload/server/public/assets/AdminShell-DJL5DzRX.js +2 -0
  97. package/payload/server/public/assets/AdminShell-DJL5DzRX.js.br +0 -0
  98. package/payload/server/public/assets/AdminShell-DJL5DzRX.js.gz +0 -0
  99. package/payload/server/public/assets/activity-CpMnNr5c.js +1 -0
  100. package/payload/server/public/assets/activity-CpMnNr5c.js.br +0 -0
  101. package/payload/server/public/assets/activity-CpMnNr5c.js.gz +0 -0
  102. package/payload/server/public/assets/admin-CBwKIfaI.js +1 -0
  103. package/payload/server/public/assets/admin-CBwKIfaI.js.br +0 -0
  104. package/payload/server/public/assets/admin-CBwKIfaI.js.gz +0 -0
  105. package/payload/server/public/assets/agents-C4LmSKjb.js +1 -0
  106. package/payload/server/public/assets/agents-C4LmSKjb.js.br +0 -0
  107. package/payload/server/public/assets/agents-C4LmSKjb.js.gz +0 -0
  108. package/payload/server/public/assets/browser-Bm9xm_yc.js +1 -0
  109. package/payload/server/public/assets/browser-Bm9xm_yc.js.br +0 -0
  110. package/payload/server/public/assets/browser-Bm9xm_yc.js.gz +0 -0
  111. package/payload/server/public/assets/calendar-CNY9FTWe.js +1 -0
  112. package/payload/server/public/assets/calendar-CNY9FTWe.js.br +0 -0
  113. package/payload/server/public/assets/calendar-CNY9FTWe.js.gz +0 -0
  114. package/payload/server/public/assets/chat-3WoUGCTd.js +1 -0
  115. package/payload/server/public/assets/chat-3WoUGCTd.js.br +0 -0
  116. package/payload/server/public/assets/chat-3WoUGCTd.js.gz +0 -0
  117. package/payload/server/public/assets/chevron-left-BE16BJnw.js +1 -0
  118. package/payload/server/public/assets/chevron-left-BE16BJnw.js.br +0 -0
  119. package/payload/server/public/assets/chevron-right-Bu2VKpeU.js +1 -0
  120. package/payload/server/public/assets/chevron-right-Bu2VKpeU.js.br +0 -0
  121. package/payload/server/public/assets/clock-C4Nu2aRV.js +1 -0
  122. package/payload/server/public/assets/clock-C4Nu2aRV.js.br +0 -0
  123. package/payload/server/public/assets/copy-3kj9Oaoc.js +1 -0
  124. package/payload/server/public/assets/copy-3kj9Oaoc.js.br +0 -0
  125. package/payload/server/public/assets/copy-3kj9Oaoc.js.gz +0 -0
  126. package/payload/server/public/assets/data-C-x5EHyi.js +1 -0
  127. package/payload/server/public/assets/data-C-x5EHyi.js.br +1 -0
  128. package/payload/server/public/assets/data-C-x5EHyi.js.gz +0 -0
  129. package/payload/server/public/assets/file-text-CBaewT76.js +1 -0
  130. package/payload/server/public/assets/file-text-CBaewT76.js.br +0 -0
  131. package/payload/server/public/assets/file-text-CBaewT76.js.gz +0 -0
  132. package/payload/server/public/assets/{graph-Bo-WcsKS.js → graph-B8-e2_Z-.js} +3 -3
  133. package/payload/server/public/assets/graph-B8-e2_Z-.js.br +0 -0
  134. package/payload/server/public/assets/graph-B8-e2_Z-.js.gz +0 -0
  135. package/payload/server/public/assets/graph-labels-Bsc23eZU.js +1 -0
  136. package/payload/server/public/assets/graph-labels-Bsc23eZU.js.br +0 -0
  137. package/payload/server/public/assets/graph-labels-Bsc23eZU.js.gz +0 -0
  138. package/payload/server/public/assets/operator-Cve0-qfO.js +1 -0
  139. package/payload/server/public/assets/operator-Cve0-qfO.js.br +0 -0
  140. package/payload/server/public/assets/operator-Cve0-qfO.js.gz +0 -0
  141. package/payload/server/public/assets/page-BgVMs6Vf.js +1 -0
  142. package/payload/server/public/assets/page-BgVMs6Vf.js.br +0 -0
  143. package/payload/server/public/assets/page-BgVMs6Vf.js.gz +0 -0
  144. package/payload/server/public/assets/page-fABub-w8.js +32 -0
  145. package/payload/server/public/assets/page-fABub-w8.js.br +0 -0
  146. package/payload/server/public/assets/page-fABub-w8.js.gz +0 -0
  147. package/payload/server/public/assets/play-B6zXB9K7.js +1 -0
  148. package/payload/server/public/assets/play-B6zXB9K7.js.br +0 -0
  149. package/payload/server/public/assets/play-B6zXB9K7.js.gz +0 -0
  150. package/payload/server/public/assets/public--R2DbdWs.js +1 -0
  151. package/payload/server/public/assets/public--R2DbdWs.js.br +0 -0
  152. package/payload/server/public/assets/public--R2DbdWs.js.gz +0 -0
  153. package/payload/server/public/assets/rotate-ccw-FZW7c8p8.js +1 -0
  154. package/payload/server/public/assets/rotate-ccw-FZW7c8p8.js.br +0 -0
  155. package/payload/server/public/assets/rotate-ccw-FZW7c8p8.js.gz +0 -0
  156. package/payload/server/public/assets/routines-BpZs2SaT.js +2 -0
  157. package/payload/server/public/assets/routines-BpZs2SaT.js.br +0 -0
  158. package/payload/server/public/assets/routines-BpZs2SaT.js.gz +0 -0
  159. package/payload/server/public/assets/skills-DF7uyEEz.js +1 -0
  160. package/payload/server/public/assets/skills-DF7uyEEz.js.br +0 -0
  161. package/payload/server/public/assets/skills-DF7uyEEz.js.gz +0 -0
  162. package/payload/server/public/assets/tasks-BfJJmoWO.js +3 -0
  163. package/payload/server/public/assets/tasks-BfJJmoWO.js.br +0 -0
  164. package/payload/server/public/assets/tasks-BfJJmoWO.js.gz +0 -0
  165. package/payload/server/public/assets/triangle-alert-CR-jRJdI.js +1 -0
  166. package/payload/server/public/assets/triangle-alert-CR-jRJdI.js.br +0 -0
  167. package/payload/server/public/assets/triangle-alert-CR-jRJdI.js.gz +0 -0
  168. package/payload/server/public/assets/useCopyFeedback-IOuPUAHY.js +1 -0
  169. package/payload/server/public/assets/useCopyFeedback-IOuPUAHY.js.br +0 -0
  170. package/payload/server/public/assets/useCopyFeedback-IOuPUAHY.js.gz +0 -0
  171. package/payload/server/public/assets/{useSubAccountSwitcher-CVHqKsqK.js → useMediaQuery-CA6dR5iz.js} +1 -1
  172. package/payload/server/public/assets/useMediaQuery-CA6dR5iz.js.br +0 -0
  173. package/payload/server/public/assets/{useSubAccountSwitcher-CVHqKsqK.js.gz → useMediaQuery-CA6dR5iz.js.gz} +0 -0
  174. package/payload/server/public/assets/{useSubAccountSwitcher-yN4lhH2x.css → useMediaQuery-DpwgV1Da.css} +1 -1
  175. package/payload/server/public/assets/useMediaQuery-DpwgV1Da.css.br +0 -0
  176. package/payload/server/public/assets/{useSubAccountSwitcher-yN4lhH2x.css.gz → useMediaQuery-DpwgV1Da.css.gz} +0 -0
  177. package/payload/server/public/assets/useVoiceRecorder-DGhsN7nV.js +2 -0
  178. package/payload/server/public/assets/useVoiceRecorder-DGhsN7nV.js.br +0 -0
  179. package/payload/server/public/assets/useVoiceRecorder-DGhsN7nV.js.gz +0 -0
  180. package/payload/server/public/assets/wrench-CpCOYUBc.js +1 -0
  181. package/payload/server/public/assets/wrench-CpCOYUBc.js.br +0 -0
  182. package/payload/server/public/assets/wrench-CpCOYUBc.js.gz +0 -0
  183. package/payload/server/public/browser.html +4 -4
  184. package/payload/server/public/calendar.html +8 -7
  185. package/payload/server/public/chat.html +13 -13
  186. package/payload/server/public/data.html +11 -11
  187. package/payload/server/public/graph.html +9 -9
  188. package/payload/server/public/index.html +14 -14
  189. package/payload/server/public/operator.html +14 -14
  190. package/payload/server/public/public.html +13 -13
  191. package/payload/server/public/routines.html +6 -6
  192. package/payload/server/public/skills.html +5 -5
  193. package/payload/server/public/tasks.html +6 -6
  194. package/payload/server/server.js +476 -148
  195. package/payload/server/public/assets/AdminLoginScreens-CfXQwKIY.js +0 -1
  196. package/payload/server/public/assets/AdminLoginScreens-CfXQwKIY.js.br +0 -0
  197. package/payload/server/public/assets/AdminLoginScreens-CfXQwKIY.js.gz +0 -0
  198. package/payload/server/public/assets/AdminShell-y0_mzlDF.js +0 -2
  199. package/payload/server/public/assets/AdminShell-y0_mzlDF.js.br +0 -0
  200. package/payload/server/public/assets/AdminShell-y0_mzlDF.js.gz +0 -0
  201. package/payload/server/public/assets/activity-h8-sjHz9.js +0 -1
  202. package/payload/server/public/assets/activity-h8-sjHz9.js.br +0 -0
  203. package/payload/server/public/assets/activity-h8-sjHz9.js.gz +0 -0
  204. package/payload/server/public/assets/admin-BzhhLC7C.js +0 -1
  205. package/payload/server/public/assets/admin-BzhhLC7C.js.br +0 -0
  206. package/payload/server/public/assets/admin-BzhhLC7C.js.gz +0 -0
  207. package/payload/server/public/assets/agents-DLuhIIgn.js +0 -1
  208. package/payload/server/public/assets/agents-DLuhIIgn.js.br +0 -0
  209. package/payload/server/public/assets/agents-DLuhIIgn.js.gz +0 -0
  210. package/payload/server/public/assets/browser-FAnTY27n.js +0 -1
  211. package/payload/server/public/assets/browser-FAnTY27n.js.br +0 -0
  212. package/payload/server/public/assets/browser-FAnTY27n.js.gz +0 -0
  213. package/payload/server/public/assets/calendar-C_PkqlkQ.js +0 -1
  214. package/payload/server/public/assets/calendar-C_PkqlkQ.js.br +0 -0
  215. package/payload/server/public/assets/calendar-C_PkqlkQ.js.gz +0 -0
  216. package/payload/server/public/assets/chat-DW81Ra89.js +0 -1
  217. package/payload/server/public/assets/chat-DW81Ra89.js.br +0 -0
  218. package/payload/server/public/assets/chat-DW81Ra89.js.gz +0 -0
  219. package/payload/server/public/assets/chevron-left-zV-WRzHb.js +0 -1
  220. package/payload/server/public/assets/chevron-left-zV-WRzHb.js.br +0 -0
  221. package/payload/server/public/assets/chevron-right-fnINU4bx.js +0 -1
  222. package/payload/server/public/assets/chevron-right-fnINU4bx.js.br +0 -0
  223. package/payload/server/public/assets/clock-2fSxBl6d.js +0 -1
  224. package/payload/server/public/assets/clock-2fSxBl6d.js.br +0 -0
  225. package/payload/server/public/assets/copy-Rde_TL9Q.js +0 -1
  226. package/payload/server/public/assets/copy-Rde_TL9Q.js.br +0 -0
  227. package/payload/server/public/assets/copy-Rde_TL9Q.js.gz +0 -0
  228. package/payload/server/public/assets/data-S5g4wIDe.js +0 -1
  229. package/payload/server/public/assets/data-S5g4wIDe.js.br +0 -0
  230. package/payload/server/public/assets/data-S5g4wIDe.js.gz +0 -0
  231. package/payload/server/public/assets/file-text-DMCUVg80.js +0 -1
  232. package/payload/server/public/assets/file-text-DMCUVg80.js.br +0 -0
  233. package/payload/server/public/assets/file-text-DMCUVg80.js.gz +0 -0
  234. package/payload/server/public/assets/graph-Bo-WcsKS.js.br +0 -0
  235. package/payload/server/public/assets/graph-Bo-WcsKS.js.gz +0 -0
  236. package/payload/server/public/assets/graph-labels-g-JodMWQ.js +0 -1
  237. package/payload/server/public/assets/graph-labels-g-JodMWQ.js.br +0 -0
  238. package/payload/server/public/assets/graph-labels-g-JodMWQ.js.gz +0 -0
  239. package/payload/server/public/assets/operator-X_LcOnAI.js +0 -1
  240. package/payload/server/public/assets/operator-X_LcOnAI.js.br +0 -0
  241. package/payload/server/public/assets/operator-X_LcOnAI.js.gz +0 -0
  242. package/payload/server/public/assets/page-Cz0p1mBf.js +0 -1
  243. package/payload/server/public/assets/page-Cz0p1mBf.js.br +0 -0
  244. package/payload/server/public/assets/page-Cz0p1mBf.js.gz +0 -0
  245. package/payload/server/public/assets/page-Dzs3MsFL.js +0 -32
  246. package/payload/server/public/assets/page-Dzs3MsFL.js.br +0 -0
  247. package/payload/server/public/assets/page-Dzs3MsFL.js.gz +0 -0
  248. package/payload/server/public/assets/play-CraN5kUU.js +0 -1
  249. package/payload/server/public/assets/play-CraN5kUU.js.br +0 -0
  250. package/payload/server/public/assets/play-CraN5kUU.js.gz +0 -0
  251. package/payload/server/public/assets/public--NUjaJ-q.js +0 -1
  252. package/payload/server/public/assets/public--NUjaJ-q.js.br +0 -0
  253. package/payload/server/public/assets/public--NUjaJ-q.js.gz +0 -0
  254. package/payload/server/public/assets/rotate-ccw-DshFgg2T.js +0 -1
  255. package/payload/server/public/assets/rotate-ccw-DshFgg2T.js.br +0 -0
  256. package/payload/server/public/assets/rotate-ccw-DshFgg2T.js.gz +0 -0
  257. package/payload/server/public/assets/routines-CfAS4gri.js +0 -2
  258. package/payload/server/public/assets/routines-CfAS4gri.js.br +0 -0
  259. package/payload/server/public/assets/routines-CfAS4gri.js.gz +0 -0
  260. package/payload/server/public/assets/skills-CM6ryWpx.js +0 -1
  261. package/payload/server/public/assets/skills-CM6ryWpx.js.br +0 -0
  262. package/payload/server/public/assets/skills-CM6ryWpx.js.gz +0 -0
  263. package/payload/server/public/assets/tasks-B07m9LIA.js +0 -3
  264. package/payload/server/public/assets/tasks-B07m9LIA.js.br +0 -0
  265. package/payload/server/public/assets/tasks-B07m9LIA.js.gz +0 -0
  266. package/payload/server/public/assets/triangle-alert-CKHyS_gC.js +0 -1
  267. package/payload/server/public/assets/triangle-alert-CKHyS_gC.js.br +0 -0
  268. package/payload/server/public/assets/triangle-alert-CKHyS_gC.js.gz +0 -0
  269. package/payload/server/public/assets/useCopyFeedback-CmawEsVi.js +0 -1
  270. package/payload/server/public/assets/useCopyFeedback-CmawEsVi.js.br +0 -0
  271. package/payload/server/public/assets/useCopyFeedback-CmawEsVi.js.gz +0 -0
  272. package/payload/server/public/assets/useSubAccountSwitcher-CVHqKsqK.js.br +0 -0
  273. package/payload/server/public/assets/useSubAccountSwitcher-yN4lhH2x.css.br +0 -0
  274. package/payload/server/public/assets/useVoiceRecorder-DpQTvvqD.js +0 -2
  275. package/payload/server/public/assets/useVoiceRecorder-DpQTvvqD.js.br +0 -0
  276. package/payload/server/public/assets/useVoiceRecorder-DpQTvvqD.js.gz +0 -0
  277. package/payload/server/public/assets/wrench-BPOEUNJB.js +0 -1
  278. package/payload/server/public/assets/wrench-BPOEUNJB.js.br +0 -0
  279. package/payload/server/public/assets/wrench-BPOEUNJB.js.gz +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rubytech/create-maxy-code",
3
- "version": "0.1.538",
3
+ "version": "0.1.540",
4
4
  "description": "Install Maxy — AI for Productive People",
5
5
  "bin": {
6
6
  "create-maxy-code": "./dist/index.js"
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Static routes registered BEFORE the `/:slug` catch-all in
3
+ * `platform/ui/server/index.ts`. An agent slug equal to one of these is
4
+ * shadowed by the static route and 404s at `/{slug}` (only the bare root can
5
+ * reach such an agent, and only when it is the defaultAgent). This is the
6
+ * single source of truth for the shadowed set: the boot canary in
7
+ * `server/index.ts` reconciles it against the live `app.routes` registry
8
+ * (drift → `[route-shadow] drift` log), and the claude-session-manager
9
+ * reachability audit asserts its own copy equals this list via a cross-package
10
+ * test (the manager cannot import ui modules at build time). Edit this list
11
+ * only in lockstep with the static route registrations.
12
+ */
13
+ export declare const SYSTEM_PATH_SLUGS: readonly ["public", "public-chat", "chat", "graph", "data", "browser"];
14
+ /** Slugs the platform owns at the account root, independent of route order. */
15
+ export declare const RESERVED_AGENT_SLUGS: readonly string[];
16
+ /** Lowercase, starts with a letter, 3 to 50 characters, hyphens allowed. */
17
+ export declare const AGENT_SLUG_PATTERN: RegExp;
18
+ export type AgentSlugRefusal = "shape" | "reserved" | "shadowed";
19
+ export type AgentSlugVerdict = {
20
+ ok: true;
21
+ } | {
22
+ ok: false;
23
+ reason: AgentSlugRefusal;
24
+ };
25
+ /**
26
+ * Which of the three rules a slug breaks, so a caller can report the cause
27
+ * rather than a bare "invalid". The serve path collapses this to a boolean;
28
+ * the write tools surface the reason to the operator.
29
+ */
30
+ export declare function checkAgentSlug(slug: string): AgentSlugVerdict;
31
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAUA;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,iBAAiB,wEAAyE,CAAC;AAExG,+EAA+E;AAC/E,eAAO,MAAM,oBAAoB,EAAE,SAAS,MAAM,EAQjD,CAAC;AAEF,4EAA4E;AAC5E,eAAO,MAAM,kBAAkB,QAA2B,CAAC;AAE3D,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,UAAU,GAAG,UAAU,CAAC;AAEjE,MAAM,MAAM,gBAAgB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAA;CAAE,CAAC;AAEtF;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAK7D"}
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ // The one rule that decides whether a string may be a public-agent slug.
3
+ //
4
+ // It has two consumers that must never disagree: the serve path
5
+ // (`platform/ui/app/lib/claude-agent/account.ts`, which decides whether a
6
+ // request for `/{slug}` can reach an agent) and the write path (the admin MCP
7
+ // agent-create / agent-update tools, which decide whether an agent may be
8
+ // created under that slug). Before Task 2286 only the serve path applied it, so
9
+ // an agent could be created under a slug its own router would refuse — written
10
+ // to disk successfully, then 404ing at its own URL.
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.AGENT_SLUG_PATTERN = exports.RESERVED_AGENT_SLUGS = exports.SYSTEM_PATH_SLUGS = void 0;
13
+ exports.checkAgentSlug = checkAgentSlug;
14
+ /**
15
+ * Static routes registered BEFORE the `/:slug` catch-all in
16
+ * `platform/ui/server/index.ts`. An agent slug equal to one of these is
17
+ * shadowed by the static route and 404s at `/{slug}` (only the bare root can
18
+ * reach such an agent, and only when it is the defaultAgent). This is the
19
+ * single source of truth for the shadowed set: the boot canary in
20
+ * `server/index.ts` reconciles it against the live `app.routes` registry
21
+ * (drift → `[route-shadow] drift` log), and the claude-session-manager
22
+ * reachability audit asserts its own copy equals this list via a cross-package
23
+ * test (the manager cannot import ui modules at build time). Edit this list
24
+ * only in lockstep with the static route registrations.
25
+ */
26
+ exports.SYSTEM_PATH_SLUGS = ["public", "public-chat", "chat", "graph", "data", "browser"];
27
+ /** Slugs the platform owns at the account root, independent of route order. */
28
+ exports.RESERVED_AGENT_SLUGS = [
29
+ "admin",
30
+ "api",
31
+ "assets",
32
+ "agent-assets",
33
+ "brand",
34
+ "bot",
35
+ "privacy",
36
+ ];
37
+ /** Lowercase, starts with a letter, 3 to 50 characters, hyphens allowed. */
38
+ exports.AGENT_SLUG_PATTERN = /^[a-z][a-z0-9-]{2,49}$/;
39
+ /**
40
+ * Which of the three rules a slug breaks, so a caller can report the cause
41
+ * rather than a bare "invalid". The serve path collapses this to a boolean;
42
+ * the write tools surface the reason to the operator.
43
+ */
44
+ function checkAgentSlug(slug) {
45
+ if (!exports.AGENT_SLUG_PATTERN.test(slug))
46
+ return { ok: false, reason: "shape" };
47
+ if (exports.RESERVED_AGENT_SLUGS.includes(slug))
48
+ return { ok: false, reason: "reserved" };
49
+ if (exports.SYSTEM_PATH_SLUGS.includes(slug))
50
+ return { ok: false, reason: "shadowed" };
51
+ return { ok: true };
52
+ }
53
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,yEAAyE;AACzE,EAAE;AACF,gEAAgE;AAChE,0EAA0E;AAC1E,8EAA8E;AAC9E,0EAA0E;AAC1E,gFAAgF;AAChF,+EAA+E;AAC/E,oDAAoD;;;AAuCpD,wCAKC;AA1CD;;;;;;;;;;;GAWG;AACU,QAAA,iBAAiB,GAAG,CAAC,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,CAAU,CAAC;AAExG,+EAA+E;AAClE,QAAA,oBAAoB,GAAsB;IACrD,OAAO;IACP,KAAK;IACL,QAAQ;IACR,cAAc;IACd,OAAO;IACP,KAAK;IACL,SAAS;CACV,CAAC;AAEF,4EAA4E;AAC/D,QAAA,kBAAkB,GAAG,wBAAwB,CAAC;AAM3D;;;;GAIG;AACH,SAAgB,cAAc,CAAC,IAAY;IACzC,IAAI,CAAC,0BAAkB,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;IAC1E,IAAI,4BAAoB,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IAClF,IAAK,yBAAuC,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IACtG,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;AACtB,CAAC"}
@@ -0,0 +1,53 @@
1
+ // The one rule that decides whether a string may be a public-agent slug.
2
+ //
3
+ // It has two consumers that must never disagree: the serve path
4
+ // (`platform/ui/app/lib/claude-agent/account.ts`, which decides whether a
5
+ // request for `/{slug}` can reach an agent) and the write path (the admin MCP
6
+ // agent-create / agent-update tools, which decide whether an agent may be
7
+ // created under that slug). Before Task 2286 only the serve path applied it, so
8
+ // an agent could be created under a slug its own router would refuse — written
9
+ // to disk successfully, then 404ing at its own URL.
10
+
11
+ /**
12
+ * Static routes registered BEFORE the `/:slug` catch-all in
13
+ * `platform/ui/server/index.ts`. An agent slug equal to one of these is
14
+ * shadowed by the static route and 404s at `/{slug}` (only the bare root can
15
+ * reach such an agent, and only when it is the defaultAgent). This is the
16
+ * single source of truth for the shadowed set: the boot canary in
17
+ * `server/index.ts` reconciles it against the live `app.routes` registry
18
+ * (drift → `[route-shadow] drift` log), and the claude-session-manager
19
+ * reachability audit asserts its own copy equals this list via a cross-package
20
+ * test (the manager cannot import ui modules at build time). Edit this list
21
+ * only in lockstep with the static route registrations.
22
+ */
23
+ export const SYSTEM_PATH_SLUGS = ["public", "public-chat", "chat", "graph", "data", "browser"] as const;
24
+
25
+ /** Slugs the platform owns at the account root, independent of route order. */
26
+ export const RESERVED_AGENT_SLUGS: readonly string[] = [
27
+ "admin",
28
+ "api",
29
+ "assets",
30
+ "agent-assets",
31
+ "brand",
32
+ "bot",
33
+ "privacy",
34
+ ];
35
+
36
+ /** Lowercase, starts with a letter, 3 to 50 characters, hyphens allowed. */
37
+ export const AGENT_SLUG_PATTERN = /^[a-z][a-z0-9-]{2,49}$/;
38
+
39
+ export type AgentSlugRefusal = "shape" | "reserved" | "shadowed";
40
+
41
+ export type AgentSlugVerdict = { ok: true } | { ok: false; reason: AgentSlugRefusal };
42
+
43
+ /**
44
+ * Which of the three rules a slug breaks, so a caller can report the cause
45
+ * rather than a bare "invalid". The serve path collapses this to a boolean;
46
+ * the write tools surface the reason to the operator.
47
+ */
48
+ export function checkAgentSlug(slug: string): AgentSlugVerdict {
49
+ if (!AGENT_SLUG_PATTERN.test(slug)) return { ok: false, reason: "shape" };
50
+ if (RESERVED_AGENT_SLUGS.includes(slug)) return { ok: false, reason: "reserved" };
51
+ if ((SYSTEM_PATH_SLUGS as readonly string[]).includes(slug)) return { ok: false, reason: "shadowed" };
52
+ return { ok: true };
53
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "outDir": "dist",
5
+ "rootDir": "src"
6
+ },
7
+ "include": ["src"]
8
+ }
@@ -10,8 +10,8 @@
10
10
  "pdf-lib": "^1.17.1"
11
11
  },
12
12
  "scripts": {
13
- "build": "tsc -p lib/account-schema-regions/tsconfig.json && tsc -p lib/account-ingest-token/tsconfig.json && tsc -p lib/models/tsconfig.json && tsc -p lib/mcp-spawn-tee/tsconfig.json && tsc -p lib/mcp-lifeline/tsconfig.json && tsc -p lib/mcp-eager/tsconfig.json && tsc -p lib/account-enumeration/tsconfig.json && tsc -p lib/account-scope/tsconfig.json && tsc -p lib/graph-write/tsconfig.json && tsc -p lib/ledger-core/tsconfig.json && tsc -p lib/embed-client/tsconfig.json && tsc -p lib/graph-mcp/tsconfig.json && tsc -p lib/graph-trash/tsconfig.json && tsc -p lib/active-rules/tsconfig.json && tsc -p lib/admin-conversation-purge/tsconfig.json && tsc -p lib/graph-search/tsconfig.json && tsc -p lib/graph-style/tsconfig.json && tsc -p lib/device-url/tsconfig.json && tsc -p lib/brand-templating/tsconfig.json && tsc -p lib/entitlement/tsconfig.json && tsc -p lib/task-secrets/tsconfig.json && tsc -p lib/admins-write/tsconfig.json && tsc -p lib/admin-access-password/tsconfig.json && tsc -p lib/persistent-components/tsconfig.json && tsc -p lib/require-port-env/tsconfig.json && tsc -p lib/aeo-llms-txt-writer/tsconfig.json && tsc -p lib/obsidian-parser/tsconfig.json && tsc -p lib/storage-broker/tsconfig.json && tsc -p lib/routine-templates/tsconfig.json && tsc -p lib/agent-dispatch-rule/tsconfig.json && tsc -p lib/learning-constants/tsconfig.json && tsc -p services/claude-session-manager/tsconfig.json && tsc -p services/whatsapp-channel/tsconfig.json && tsc -p services/webchat-channel/tsconfig.json && tsc -p services/telegram-channel/tsconfig.json && NODE_OPTIONS='--max-old-space-size=8192' tsc -b plugins/*/mcp/tsconfig.json",
14
- "build:lib": "tsc -p lib/account-schema-regions/tsconfig.json && tsc -p lib/account-ingest-token/tsconfig.json && tsc -p lib/models/tsconfig.json && tsc -p lib/mcp-spawn-tee/tsconfig.json && tsc -p lib/mcp-lifeline/tsconfig.json && tsc -p lib/mcp-eager/tsconfig.json && tsc -p lib/account-enumeration/tsconfig.json && tsc -p lib/account-scope/tsconfig.json && tsc -p lib/graph-write/tsconfig.json && tsc -p lib/ledger-core/tsconfig.json && tsc -p lib/embed-client/tsconfig.json && tsc -p lib/graph-mcp/tsconfig.json && tsc -p lib/graph-trash/tsconfig.json && tsc -p lib/active-rules/tsconfig.json && tsc -p lib/admin-conversation-purge/tsconfig.json && tsc -p lib/graph-search/tsconfig.json && tsc -p lib/graph-style/tsconfig.json && tsc -p lib/device-url/tsconfig.json && tsc -p lib/brand-templating/tsconfig.json && tsc -p lib/entitlement/tsconfig.json && tsc -p lib/task-secrets/tsconfig.json && tsc -p lib/admins-write/tsconfig.json && tsc -p lib/admin-access-password/tsconfig.json && tsc -p lib/persistent-components/tsconfig.json && tsc -p lib/require-port-env/tsconfig.json && tsc -p lib/aeo-llms-txt-writer/tsconfig.json && tsc -p lib/obsidian-parser/tsconfig.json && tsc -p lib/storage-broker/tsconfig.json && tsc -p lib/routine-templates/tsconfig.json && tsc -p lib/agent-dispatch-rule/tsconfig.json",
13
+ "build": "tsc -p lib/account-schema-regions/tsconfig.json && tsc -p lib/account-ingest-token/tsconfig.json && tsc -p lib/models/tsconfig.json && tsc -p lib/agent-slug/tsconfig.json && tsc -p lib/mcp-spawn-tee/tsconfig.json && tsc -p lib/mcp-lifeline/tsconfig.json && tsc -p lib/mcp-eager/tsconfig.json && tsc -p lib/account-enumeration/tsconfig.json && tsc -p lib/account-scope/tsconfig.json && tsc -p lib/graph-write/tsconfig.json && tsc -p lib/ledger-core/tsconfig.json && tsc -p lib/embed-client/tsconfig.json && tsc -p lib/graph-mcp/tsconfig.json && tsc -p lib/graph-trash/tsconfig.json && tsc -p lib/active-rules/tsconfig.json && tsc -p lib/admin-conversation-purge/tsconfig.json && tsc -p lib/graph-search/tsconfig.json && tsc -p lib/graph-style/tsconfig.json && tsc -p lib/device-url/tsconfig.json && tsc -p lib/brand-templating/tsconfig.json && tsc -p lib/entitlement/tsconfig.json && tsc -p lib/task-secrets/tsconfig.json && tsc -p lib/admins-write/tsconfig.json && tsc -p lib/admin-access-password/tsconfig.json && tsc -p lib/persistent-components/tsconfig.json && tsc -p lib/require-port-env/tsconfig.json && tsc -p lib/aeo-llms-txt-writer/tsconfig.json && tsc -p lib/obsidian-parser/tsconfig.json && tsc -p lib/storage-broker/tsconfig.json && tsc -p lib/routine-templates/tsconfig.json && tsc -p lib/agent-dispatch-rule/tsconfig.json && tsc -p lib/learning-constants/tsconfig.json && tsc -p services/claude-session-manager/tsconfig.json && tsc -p services/whatsapp-channel/tsconfig.json && tsc -p services/webchat-channel/tsconfig.json && tsc -p services/telegram-channel/tsconfig.json && NODE_OPTIONS='--max-old-space-size=8192' tsc -b plugins/*/mcp/tsconfig.json",
14
+ "build:lib": "tsc -p lib/account-schema-regions/tsconfig.json && tsc -p lib/account-ingest-token/tsconfig.json && tsc -p lib/models/tsconfig.json && tsc -p lib/agent-slug/tsconfig.json && tsc -p lib/mcp-spawn-tee/tsconfig.json && tsc -p lib/mcp-lifeline/tsconfig.json && tsc -p lib/mcp-eager/tsconfig.json && tsc -p lib/account-enumeration/tsconfig.json && tsc -p lib/account-scope/tsconfig.json && tsc -p lib/graph-write/tsconfig.json && tsc -p lib/ledger-core/tsconfig.json && tsc -p lib/embed-client/tsconfig.json && tsc -p lib/graph-mcp/tsconfig.json && tsc -p lib/graph-trash/tsconfig.json && tsc -p lib/active-rules/tsconfig.json && tsc -p lib/admin-conversation-purge/tsconfig.json && tsc -p lib/graph-search/tsconfig.json && tsc -p lib/graph-style/tsconfig.json && tsc -p lib/device-url/tsconfig.json && tsc -p lib/brand-templating/tsconfig.json && tsc -p lib/entitlement/tsconfig.json && tsc -p lib/task-secrets/tsconfig.json && tsc -p lib/admins-write/tsconfig.json && tsc -p lib/admin-access-password/tsconfig.json && tsc -p lib/persistent-components/tsconfig.json && tsc -p lib/require-port-env/tsconfig.json && tsc -p lib/aeo-llms-txt-writer/tsconfig.json && tsc -p lib/obsidian-parser/tsconfig.json && tsc -p lib/storage-broker/tsconfig.json && tsc -p lib/routine-templates/tsconfig.json && tsc -p lib/agent-dispatch-rule/tsconfig.json",
15
15
  "gen:canonical-tools": "node scripts/generate-canonical-tool-names.mjs",
16
16
  "build:memory": "tsc -p plugins/memory/mcp/tsconfig.json",
17
17
  "build:contacts": "tsc -p plugins/contacts/mcp/tsconfig.json",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "admin",
3
- "description": "Platform administration plugin. Provides system-status, public-hostname (deterministic Cloudflare public-URL resolver, single call returning the operator's canonical hostname so agents never guess property names on :CloudflareHostname nodes), admin-hostname (the admin-host twin of public-hostname — resolves the host that serves /calendar and the rest of the admin shell behind sign-in from the same ingress + alias + operator files, so agents point the operator at the admin /calendar URL instead of the public host that 404s it), publish-site (move an extracted static-site tree under <accountDir>/sites/<slug>/, emit one canonical path slug, and refresh llms.txt at the site root — typed refusal taxonomy replaces the prior skill-prose contract), brand-settings, account-manage, capabilities-here (deterministic install-introspection — returns enabledPlugins, tier, models, installed platform + premium specialists, registered Claude Code agent types, and the brand block as a single JSON object; the canonical tool for grounding any claim about what is enabled on the current account), linkedin-ingest-token (returns the account's durable LinkedIn ingest token — the one credential the Maxy LinkedIn Ingest Chrome extension needs in its options page; minted on first call then stable across restarts and new chat sessions, and never a conversation session key nor the admin browser's session_key, which the ingest route rejects; action='rotate' replaces it and invalidates every existing extension install), account-update, the multi-account managed-service lifecycle tools (account_list, account_create, account_delete, account_purge, account_channel_routing, account_channel_routing_set — one Rubytech operator hosting N client accounts on one house install; create/delete/purge are operator-only and purge is two-step with a typed confirmation; account_create requires the client business owner's real name (ownerName), refusing a blank or the placeholder \"Owner\" and seeding it onto the sub-account's owner AdminUser and owner Person, and requires the owner's IANA timezone (timezone) — refusing a blank or a non-IANA value — seeding it onto the owner UserProfile marked owner-set so scheduling reads the owner's real zone from the start rather than the box's server default, while a managing house admin (its userId) is optional — when supplied it is validated as a live house admin and recorded as the sub-account's managingAdminUserId, and when omitted the sub-account is unmanaged and its passive-intake tasks route to the install's primary admin; account_reassign_admin repoints a client sub-account's managing admin to another live house admin (the repair path for a dangling managingAdminUserId, or to record one on an unmanaged account); account_roster is the canonical per-account identity view — one row per sub-account giving business name, role, the managing house admin resolved to a name with status (assigned/absent/dangling), the business owner from the graph with status (named/nameless), and the WhatsApp account-manager binding if any, each field carrying what it means and does not (managing admin is the responsible house team member not the owner; account manager is WhatsApp routing only with no admin rights), so the agent never stitches admin-list + account.json + whatsapp-config; account_set_owner_name names (or corrects) a client sub-account's business owner by writing the owned Person — the canonical name source — refusing a blank or the placeholder \"Owner\", the guarded repair for a nameless owner (the standing identity-audit op=nameless-owned-person detector); account_channel_routing_set repoints the house-paired WhatsApp/Telegram inbound stream to a different sub-account, and does not affect a sub-account's own separately paired WhatsApp number), admin-add (refuses on a client sub-account, where admin access is already install-wide so a per-operator seat grants nothing — the sub-account's one identity, its business owner, is set at account creation; the house account, where operators hold PIN logins and admins[] rows, is unchanged), admin-remove (refuses to remove a house admin who still manages one or more client sub-accounts, naming them so the operator reassigns each with account_reassign_admin first — never silently orphans them), admin-list, admin-update-pin, agent-list, agent-config-read, logs-read, cpu-triage-start and cpu-triage-read (the two-call device CPU diagnostic — start spawns a detached sampling run across at least one full 120s reconcile cycle and returns a run handle immediately, read returns running/complete/failed with the per-core distribution; no admin tool blocks through a sampling window, and no spot reading is obtainable), plugin-read, skill-load (one-call resolve+read for SKILL.md by skill name, the canonical primitive for loading a named skill; plugin-read remains the reader for references/* and PLUGIN.md), skill-search (free-text intent → skill resolver: ranks every plugin skill's SKILL.md name+description against a query and returns the top owners with their canonical skills/<slug>/ path, so intent→skill mapping survives the available-skills menu leaving context after a compaction), store-skill (deterministic write counterpart to plugin-read; persists operator-authored skills as plugin files under the active account), session-reset, session-resume, wifi, and action-approval tools (action-pending, action-approve, action-reject, action-edit) for managing the Maxy platform.",
3
+ "description": "Platform administration plugin. Provides system-status, public-hostname (deterministic Cloudflare public-URL resolver, single call returning the operator's canonical hostname so agents never guess property names on :CloudflareHostname nodes), admin-hostname (the admin-host twin of public-hostname — resolves the host that serves /calendar and the rest of the admin shell behind sign-in from the same ingress + alias + operator files, so agents point the operator at the admin /calendar URL instead of the public host that 404s it), publish-site (move an extracted static-site tree under <accountDir>/sites/<slug>/, emit one canonical path slug, and refresh llms.txt at the site root — typed refusal taxonomy replaces the prior skill-prose contract), brand-settings, account-manage, capabilities-here (deterministic install-introspection — returns enabledPlugins, tier, models, installed platform + premium specialists, registered Claude Code agent types, and the brand block as a single JSON object; the canonical tool for grounding any claim about what is enabled on the current account), linkedin-ingest-token (returns the account's durable LinkedIn ingest token — the one credential the Maxy LinkedIn Ingest Chrome extension needs in its options page; minted on first call then stable across restarts and new chat sessions, and never a conversation session key nor the admin browser's session_key, which the ingest route rejects; action='rotate' replaces it and invalidates every existing extension install), account-update, the multi-account managed-service lifecycle tools (account_list, account_create, account_delete, account_purge, account_channel_routing, account_channel_routing_set — one Rubytech operator hosting N client accounts on one house install; create/delete/purge are operator-only and purge is two-step with a typed confirmation; account_create requires the client business owner's real name (ownerName), refusing a blank or the placeholder \"Owner\" and seeding it onto the sub-account's owner AdminUser and owner Person, and requires the owner's IANA timezone (timezone) — refusing a blank or a non-IANA value — seeding it onto the owner UserProfile marked owner-set so scheduling reads the owner's real zone from the start rather than the box's server default, while a managing house admin (its userId) is optional — when supplied it is validated as a live house admin and recorded as the sub-account's managingAdminUserId, and when omitted the sub-account is unmanaged and its passive-intake tasks route to the install's primary admin; account_reassign_admin repoints a client sub-account's managing admin to another live house admin (the repair path for a dangling managingAdminUserId, or to record one on an unmanaged account); account_roster is the canonical per-account identity view — one row per sub-account giving business name, role, the managing house admin resolved to a name with status (assigned/absent/dangling), the business owner from the graph with status (named/nameless), and the WhatsApp account-manager binding if any, each field carrying what it means and does not (managing admin is the responsible house team member not the owner; account manager is WhatsApp routing only with no admin rights), so the agent never stitches admin-list + account.json + whatsapp-config; account_set_owner_name names (or corrects) a client sub-account's business owner by writing the owned Person — the canonical name source — refusing a blank or the placeholder \"Owner\", the guarded repair for a nameless owner (the standing identity-audit op=nameless-owned-person detector); account_channel_routing_set repoints the house-paired WhatsApp/Telegram inbound stream to a different sub-account, and does not affect a sub-account's own separately paired WhatsApp number), admin-add (refuses on a client sub-account, where admin access is already install-wide so a per-operator seat grants nothing — the sub-account's one identity, its business owner, is set at account creation; the house account, where operators hold PIN logins and admins[] rows, is unchanged), admin-remove (refuses to remove a house admin who still manages one or more client sub-accounts, naming them so the operator reassigns each with account_reassign_admin first — never silently orphans them), admin-list, admin-update-pin, agent-list, agent-config-read, the public-agent write tools (agent-create is the only supported way to create a public agent: it validates the slug against the same rule the router serves by, validates config.json against the servable schema, refuses an empty KNOWLEDGE, writes the four files with IDENTITY.md copied verbatim from the platform template, and projects the agent into the graph in the same call, reporting the verified projected count rather than assuming it; agent-update applies the same validation to a merged config, writes only the fields supplied, and re-projects, so the graph cannot fall behind the files; agent-delete removes the :Agent node and its owned knowledge projections before the directory and refuses the admin agent — writing these files by hand reaches none of those checks, which is what left an agent on disk and absent from the graph for a day), agent-image, plugin-toggle-enabled, premium-list, premium-deliver, skill-find, logs-read, cpu-triage-start and cpu-triage-read (the two-call device CPU diagnostic — start spawns a detached sampling run across at least one full 120s reconcile cycle and returns a run handle immediately, read returns running/complete/failed with the per-core distribution; no admin tool blocks through a sampling window, and no spot reading is obtainable), plugin-read, skill-load (one-call resolve+read for SKILL.md by skill name, the canonical primitive for loading a named skill; plugin-read remains the reader for references/* and PLUGIN.md), skill-search (free-text intent → skill resolver: ranks every plugin skill's SKILL.md name+description against a query and returns the top owners with their canonical skills/<slug>/ path, so intent→skill mapping survives the available-skills menu leaving context after a compaction), store-skill (deterministic write counterpart to plugin-read; persists operator-authored skills as plugin files under the active account), session-reset, session-resume, wifi, and action-approval tools (action-pending, action-approve, action-reject, action-edit) for managing the Maxy platform.",
4
4
  "version": "0.1.0",
5
5
  "author": {
6
6
  "name": "Rubytech LLC"
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: admin
3
3
  surface: platform
4
- description: "Platform administration plugin. Provides system-status, public-hostname (deterministic Cloudflare public-URL resolver, single call returning the operator's canonical hostname so agents never guess property names on :CloudflareHostname nodes), admin-hostname (the admin-host twin of public-hostname — resolves the host that serves /calendar and the rest of the admin shell behind sign-in from the same ingress + alias + operator files, so agents point the operator at the admin /calendar URL instead of the public host that 404s it), publish-site (move an extracted static-site tree under <accountDir>/sites/<slug>/, emit one canonical path slug, and refresh llms.txt at the site root — typed refusal taxonomy replaces the prior skill-prose contract), brand-settings, account-manage, capabilities-here (deterministic install-introspection — returns enabledPlugins, tier, models, installed platform + premium specialists, registered Claude Code agent types, and the brand block as a single JSON object; the canonical tool for grounding any claim about what is enabled on the current account), linkedin-ingest-token (returns the account's durable LinkedIn ingest token — the one credential the Maxy LinkedIn Ingest Chrome extension needs in its options page; minted on first call then stable across restarts and new chat sessions, and never a conversation session key nor the admin browser's session_key, which the ingest route rejects; action='rotate' replaces it and invalidates every existing extension install), account-update, the multi-account managed-service lifecycle tools (account_list, account_create, account_delete, account_purge, account_channel_routing, account_channel_routing_set — one Rubytech operator hosting N client accounts on one house install; create/delete/purge are operator-only and purge is two-step with a typed confirmation; account_create requires the client business owner's real name (ownerName), refusing a blank or the placeholder "Owner" and seeding it onto the sub-account's owner AdminUser and owner Person, and requires the owner's IANA timezone (timezone) — refusing a blank or a non-IANA value — seeding it onto the owner UserProfile marked owner-set so scheduling reads the owner's real zone from the start rather than the box's server default, while a managing house admin (its userId) is optional — when supplied it is validated as a live house admin and recorded as the sub-account's managingAdminUserId, and when omitted the sub-account is unmanaged and its passive-intake tasks route to the install's primary admin; account_reassign_admin repoints a client sub-account's managing admin to another live house admin (the repair path for a dangling managingAdminUserId, or to record one on an unmanaged account); account_roster is the canonical per-account identity view — one row per sub-account giving business name, role, the managing house admin resolved to a name with status (assigned/absent/dangling), the business owner from the graph with status (named/nameless), and the WhatsApp account-manager binding if any, each field carrying what it means and does not (managing admin is the responsible house team member not the owner; account manager is WhatsApp routing only with no admin rights), so the agent never stitches admin-list + account.json + whatsapp-config; account_set_owner_name names (or corrects) a client sub-account's business owner by writing the owned Person — the canonical name source — refusing a blank or the placeholder "Owner", the guarded repair for a nameless owner (the standing identity-audit op=nameless-owned-person detector); account_channel_routing_set repoints the house-paired WhatsApp/Telegram inbound stream to a different sub-account, and does not affect a sub-account's own separately paired WhatsApp number), admin-add (refuses on a client sub-account, where admin access is already install-wide so a per-operator seat grants nothing — the sub-account's one identity, its business owner, is set at account creation; the house account, where operators hold PIN logins and admins[] rows, is unchanged), admin-remove (refuses to remove a house admin who still manages one or more client sub-accounts, naming them so the operator reassigns each with account_reassign_admin first — never silently orphans them), admin-list, admin-update-pin, agent-list, agent-config-read, logs-read, cpu-triage-start and cpu-triage-read (the two-call device CPU diagnostic — start spawns a detached sampling run across at least one full 120s reconcile cycle and returns a run handle immediately, read returns running/complete/failed with the per-core distribution; no admin tool blocks through a sampling window, and no spot reading is obtainable), plugin-read, skill-load (one-call resolve+read for SKILL.md by skill name, the canonical primitive for loading a named skill; plugin-read remains the reader for references/* and PLUGIN.md), skill-search (free-text intent → skill resolver: ranks every plugin skill's SKILL.md name+description against a query and returns the top owners with their canonical skills/<slug>/ path, so intent→skill mapping survives the available-skills menu leaving context after a compaction), store-skill (deterministic write counterpart to plugin-read; persists operator-authored skills as plugin files under the active account), session-reset, session-resume, wifi, and action-approval tools (action-pending, action-approve, action-reject, action-edit) for managing the Maxy platform."
4
+ description: "Platform administration plugin. Provides system-status, public-hostname (deterministic Cloudflare public-URL resolver, single call returning the operator's canonical hostname so agents never guess property names on :CloudflareHostname nodes), admin-hostname (the admin-host twin of public-hostname — resolves the host that serves /calendar and the rest of the admin shell behind sign-in from the same ingress + alias + operator files, so agents point the operator at the admin /calendar URL instead of the public host that 404s it), publish-site (move an extracted static-site tree under <accountDir>/sites/<slug>/, emit one canonical path slug, and refresh llms.txt at the site root — typed refusal taxonomy replaces the prior skill-prose contract), brand-settings, account-manage, capabilities-here (deterministic install-introspection — returns enabledPlugins, tier, models, installed platform + premium specialists, registered Claude Code agent types, and the brand block as a single JSON object; the canonical tool for grounding any claim about what is enabled on the current account), linkedin-ingest-token (returns the account's durable LinkedIn ingest token — the one credential the Maxy LinkedIn Ingest Chrome extension needs in its options page; minted on first call then stable across restarts and new chat sessions, and never a conversation session key nor the admin browser's session_key, which the ingest route rejects; action='rotate' replaces it and invalidates every existing extension install), account-update, the multi-account managed-service lifecycle tools (account_list, account_create, account_delete, account_purge, account_channel_routing, account_channel_routing_set — one Rubytech operator hosting N client accounts on one house install; create/delete/purge are operator-only and purge is two-step with a typed confirmation; account_create requires the client business owner's real name (ownerName), refusing a blank or the placeholder "Owner" and seeding it onto the sub-account's owner AdminUser and owner Person, and requires the owner's IANA timezone (timezone) — refusing a blank or a non-IANA value — seeding it onto the owner UserProfile marked owner-set so scheduling reads the owner's real zone from the start rather than the box's server default, while a managing house admin (its userId) is optional — when supplied it is validated as a live house admin and recorded as the sub-account's managingAdminUserId, and when omitted the sub-account is unmanaged and its passive-intake tasks route to the install's primary admin; account_reassign_admin repoints a client sub-account's managing admin to another live house admin (the repair path for a dangling managingAdminUserId, or to record one on an unmanaged account); account_roster is the canonical per-account identity view — one row per sub-account giving business name, role, the managing house admin resolved to a name with status (assigned/absent/dangling), the business owner from the graph with status (named/nameless), and the WhatsApp account-manager binding if any, each field carrying what it means and does not (managing admin is the responsible house team member not the owner; account manager is WhatsApp routing only with no admin rights), so the agent never stitches admin-list + account.json + whatsapp-config; account_set_owner_name names (or corrects) a client sub-account's business owner by writing the owned Person — the canonical name source — refusing a blank or the placeholder "Owner", the guarded repair for a nameless owner (the standing identity-audit op=nameless-owned-person detector); account_channel_routing_set repoints the house-paired WhatsApp/Telegram inbound stream to a different sub-account, and does not affect a sub-account's own separately paired WhatsApp number), admin-add (refuses on a client sub-account, where admin access is already install-wide so a per-operator seat grants nothing — the sub-account's one identity, its business owner, is set at account creation; the house account, where operators hold PIN logins and admins[] rows, is unchanged), admin-remove (refuses to remove a house admin who still manages one or more client sub-accounts, naming them so the operator reassigns each with account_reassign_admin first — never silently orphans them), admin-list, admin-update-pin, agent-list, agent-config-read, the public-agent write tools (agent-create is the only supported way to create a public agent: it validates the slug against the same rule the router serves by, validates config.json against the servable schema, refuses an empty KNOWLEDGE, writes the four files with IDENTITY.md copied verbatim from the platform template, and projects the agent into the graph in the same call, reporting the verified projected count rather than assuming it; agent-update applies the same validation to a merged config, writes only the fields supplied, and re-projects, so the graph cannot fall behind the files; agent-delete removes the :Agent node and its owned knowledge projections before the directory and refuses the admin agent — writing these files by hand reaches none of those checks, which is what left an agent on disk and absent from the graph for a day), agent-image, plugin-toggle-enabled, premium-list, premium-deliver, skill-find, logs-read, cpu-triage-start and cpu-triage-read (the two-call device CPU diagnostic — start spawns a detached sampling run across at least one full 120s reconcile cycle and returns a run handle immediately, read returns running/complete/failed with the per-core distribution; no admin tool blocks through a sampling window, and no spot reading is obtainable), plugin-read, skill-load (one-call resolve+read for SKILL.md by skill name, the canonical primitive for loading a named skill; plugin-read remains the reader for references/* and PLUGIN.md), skill-search (free-text intent → skill resolver: ranks every plugin skill's SKILL.md name+description against a query and returns the top owners with their canonical skills/<slug>/ path, so intent→skill mapping survives the available-skills menu leaving context after a compaction), store-skill (deterministic write counterpart to plugin-read; persists operator-authored skills as plugin files under the active account), session-reset, session-resume, wifi, and action-approval tools (action-pending, action-approve, action-reject, action-edit) for managing the Maxy platform."
5
5
  account-owned-files: [{"file": "webchat-channel-bindings.json", "description": "Routes this account's inbound admin webchat messages. Written by the session manager's webchat-channel-store."}, {"file": "wa-channel-bindings.json", "description": "Routes this account's inbound WhatsApp messages. Written by the session manager's wa-channel-store, which runs on every brand whether or not the whatsapp plugin ships."}, {"file": "telegram-channel-bindings.json", "description": "Routes this account's inbound Telegram messages. Written by the session manager's telegram-channel-store, which runs on every brand whether or not the telegram plugin ships."}, {"file": "canonical-webchat-session.json", "description": "Pins the account's canonical webchat session. Written by the admin UI server."}, {"file": "session-titles.json", "description": "Operator renames of sessions. Written by the session manager's title stores."}, {"file": "agents-disabled.json", "description": "Names the agents the operator switched off. Written by the admin agents route; provision reads it to re-apply the disables and never creates it."}]
6
6
  tools:
7
7
  - name: system-status
@@ -100,6 +100,38 @@ tools:
100
100
  publicAllowlist: false
101
101
  adminAllowlist: true
102
102
  riskClass: read
103
+ - name: agent-create
104
+ publicAllowlist: false
105
+ adminAllowlist: true
106
+ riskClass: write_local
107
+ - name: agent-update
108
+ publicAllowlist: false
109
+ adminAllowlist: true
110
+ riskClass: write_local
111
+ - name: agent-delete
112
+ publicAllowlist: false
113
+ adminAllowlist: true
114
+ riskClass: write_local
115
+ - name: agent-image
116
+ publicAllowlist: false
117
+ adminAllowlist: true
118
+ riskClass: write_local
119
+ - name: plugin-toggle-enabled
120
+ publicAllowlist: false
121
+ adminAllowlist: true
122
+ riskClass: write_local
123
+ - name: premium-list
124
+ publicAllowlist: false
125
+ adminAllowlist: true
126
+ riskClass: read
127
+ - name: premium-deliver
128
+ publicAllowlist: false
129
+ adminAllowlist: true
130
+ riskClass: write_local
131
+ - name: skill-find
132
+ publicAllowlist: false
133
+ adminAllowlist: true
134
+ riskClass: read
103
135
  - name: logs-read
104
136
  publicAllowlist: false
105
137
  adminAllowlist: false
@@ -25,6 +25,7 @@ import { classifySpecialists } from "./specialist-registry.js";
25
25
  import { resolvePublicHostname } from "./lib/public-hostname.js";
26
26
  import { resolveAdminHostname } from "./lib/admin-hostname.js";
27
27
  import { publishSite } from "./tools/publish-site.js";
28
+ import { createAgent, updateAgent, projectAgentViaPlatform } from "./tools/agent-write.js";
28
29
  import { resolveCapabilitiesHere } from "./tools/capabilities-here.js";
29
30
  import { resolveIngestToken } from "./tools/linkedin-ingest-token.js";
30
31
  import { startCpuTriage, readCpuTriage } from "./tools/cpu-triage.js";
@@ -1541,6 +1542,141 @@ lifelineTool(server, "agent-list", "List all public (non-admin) agents with thei
1541
1542
  };
1542
1543
  }
1543
1544
  });
1545
+ // Task 2286 — public-agent CRUD. Before these tools existed there was no write
1546
+ // path at any layer, so an agent creating an agent wrote the four files by hand
1547
+ // and hand-rolled the projection POST. That reached no slug rule, no config
1548
+ // schema and no non-empty-knowledge check, and it is what left the `beagle`
1549
+ // agent on disk and absent from the graph for a day.
1550
+ const AGENT_WRITE_TAG = "[admin/agents]";
1551
+ /** One line per write. `projected` is the verified post-condition read from the
1552
+ * projection response, not the intention.
1553
+ *
1554
+ * `projected` is meaningful for create and update only. A successful delete
1555
+ * logs `projected=0` because it removed the projection, so the
1556
+ * disk-without-graph failure signature is `action=create|update outcome=ok
1557
+ * projected=0` — grepping `outcome=ok projected=0` alone matches every
1558
+ * successful delete. */
1559
+ function logAgentWrite(action, slug, outcome, reason, detail, projected) {
1560
+ console.error(`${AGENT_WRITE_TAG} op=agent-write action=${action} slug=${slug} accountId=${(ACCOUNT_ID ?? "").slice(0, 8)} ` +
1561
+ `outcome=${outcome} reason=${reason} detail=${detail} projected=${projected}`);
1562
+ }
1563
+ lifelineTool(server, "agent-create", "Create a public agent: writes IDENTITY.md (copied verbatim from the platform template), SOUL.md, KNOWLEDGE.md and config.json, then projects the agent into the graph in the same call. Refuses a slug the router would not serve, a config that would not spawn, and an empty KNOWLEDGE, before writing anything. This is the only supported way to create a public agent — writing the files directly reaches none of these checks.", {
1564
+ agentSlug: z.string().describe("Agent slug: lowercase, starts with a letter, 3-50 chars, hyphens allowed"),
1565
+ displayName: z.string().describe("Name shown in the chat header"),
1566
+ model: z.string().describe("Model id: claude-haiku-4-5, claude-sonnet-5, or claude-opus-5[1m]"),
1567
+ soul: z.string().describe("SOUL.md body: personality and the operator-defined role"),
1568
+ knowledge: z.string().describe("KNOWLEDGE.md body: the agent's only knowledge source. Must be non-empty"),
1569
+ knowledgeKeywords: z.array(z.string()).optional().describe("Up to 5 keyword subscriptions"),
1570
+ status: z.enum(["active", "inactive"]).optional().describe("Defaults to active"),
1571
+ showAgentName: z.union([z.boolean(), z.literal("none")]).optional().describe("Chat header title: false for the business name, true for the agent display name, 'none' for logo only"),
1572
+ accessMode: z.enum(["open", "gated", "paid"]).optional().describe("Defaults to open"),
1573
+ }, async ({ agentSlug, ...rest }) => {
1574
+ if (!ACCOUNT_ID)
1575
+ return refuseNoAccount("agent-create");
1576
+ // getAccountDir throws on an unresolvable account dir and createAgent
1577
+ // rethrows an I/O error after cleaning up. wrapWithLifeline re-throws, so
1578
+ // without this catch the failure leaves NO op=agent-write line — the
1579
+ // unobservable-failure class this tool exists to close.
1580
+ try {
1581
+ const res = createAgent({ ...rest, slug: agentSlug, accountDir: getAccountDir(), platformRoot: PLATFORM_ROOT });
1582
+ if (!res.ok) {
1583
+ logAgentWrite("create", agentSlug, "refused", res.reason, res.detail, 0);
1584
+ return { content: [{ type: "text", text: `Refused: ${res.reason} — ${res.detail}` }], isError: true };
1585
+ }
1586
+ const proj = await projectAgentViaPlatform({
1587
+ platformPort: PLATFORM_PORT,
1588
+ accountId: ACCOUNT_ID,
1589
+ slug: agentSlug,
1590
+ houseAdminScope: process.env.HOUSE_ADMIN_SCOPE,
1591
+ });
1592
+ logAgentWrite("create", agentSlug, "ok", proj.projected ? "none" : "projection-failed", proj.error ?? "-", proj.projected);
1593
+ if (!proj.projected) {
1594
+ return {
1595
+ content: [{ type: "text", text: `Agent '${agentSlug}' was written to disk but NOT projected into the graph: ${proj.error}. It will not appear in /graph. Re-run agent-update to retry the projection.` }],
1596
+ isError: true,
1597
+ };
1598
+ }
1599
+ return { content: [{ type: "text", text: `Agent '${agentSlug}' created and projected. Reachable at /${agentSlug}.` }] };
1600
+ }
1601
+ catch (err) {
1602
+ const msg = err instanceof Error ? err.message : String(err);
1603
+ logAgentWrite("create", agentSlug, "refused", "write-failed", msg, 0);
1604
+ return { content: [{ type: "text", text: `agent-create failed: ${msg}` }], isError: true };
1605
+ }
1606
+ });
1607
+ lifelineTool(server, "agent-update", "Update a public agent's SOUL.md, KNOWLEDGE.md or config fields, then re-project it into the graph in the same call. Only the fields supplied are written; config fields merge into the existing file. A refusal leaves the agent directory byte-identical. Use this instead of editing the files directly, or the graph falls behind the files.", {
1608
+ agentSlug: z.string().describe("Agent slug"),
1609
+ displayName: z.string().optional(),
1610
+ model: z.string().optional().describe("claude-haiku-4-5, claude-sonnet-5, or claude-opus-5[1m]"),
1611
+ soul: z.string().optional().describe("Replacement SOUL.md body"),
1612
+ knowledge: z.string().optional().describe("Replacement KNOWLEDGE.md body. Must be non-empty when supplied"),
1613
+ knowledgeKeywords: z.array(z.string()).optional().describe("Up to 5 keyword subscriptions"),
1614
+ status: z.enum(["active", "inactive"]).optional(),
1615
+ showAgentName: z.union([z.boolean(), z.literal("none")]).optional(),
1616
+ accessMode: z.enum(["open", "gated", "paid"]).optional(),
1617
+ }, async ({ agentSlug, ...rest }) => {
1618
+ if (!ACCOUNT_ID)
1619
+ return refuseNoAccount("agent-update");
1620
+ // Same rethrow contract as agent-create: without this catch an
1621
+ // unresolvable account dir or a write error leaves no op=agent-write line.
1622
+ try {
1623
+ const res = updateAgent({ ...rest, slug: agentSlug, accountDir: getAccountDir() });
1624
+ if (!res.ok) {
1625
+ logAgentWrite("update", agentSlug, "refused", res.reason, res.detail, 0);
1626
+ return { content: [{ type: "text", text: `Refused: ${res.reason} — ${res.detail}` }], isError: true };
1627
+ }
1628
+ const proj = await projectAgentViaPlatform({
1629
+ platformPort: PLATFORM_PORT,
1630
+ accountId: ACCOUNT_ID,
1631
+ slug: agentSlug,
1632
+ houseAdminScope: process.env.HOUSE_ADMIN_SCOPE,
1633
+ });
1634
+ logAgentWrite("update", agentSlug, "ok", proj.projected ? "none" : "projection-failed", proj.error ?? "-", proj.projected);
1635
+ if (!proj.projected) {
1636
+ return {
1637
+ content: [{ type: "text", text: `Agent '${agentSlug}' was updated on disk but NOT re-projected: ${proj.error}. /graph now shows stale state for this agent.` }],
1638
+ isError: true,
1639
+ };
1640
+ }
1641
+ return { content: [{ type: "text", text: `Agent '${agentSlug}' updated (${res.filesWritten.join(", ")}) and re-projected.` }] };
1642
+ }
1643
+ catch (err) {
1644
+ const msg = err instanceof Error ? err.message : String(err);
1645
+ logAgentWrite("update", agentSlug, "refused", "write-failed", msg, 0);
1646
+ return { content: [{ type: "text", text: `agent-update failed: ${msg}` }], isError: true };
1647
+ }
1648
+ });
1649
+ lifelineTool(server, "agent-delete", "Delete a public agent: removes its :Agent node and owned knowledge projections from the graph first, then its directory. Refuses the admin agent. Calls the platform route that owns the ordering, so a graph failure preserves the files and the delete can be safely re-run.", {
1650
+ agentSlug: z.string().describe("Agent slug"),
1651
+ }, async ({ agentSlug }) => {
1652
+ if (!ACCOUNT_ID)
1653
+ return refuseNoAccount("agent-delete");
1654
+ // Refused here as well as at the route so the refusal is attributable from
1655
+ // the MCP log alone, without correlating against the platform log.
1656
+ if (agentSlug === "admin") {
1657
+ logAgentWrite("delete", agentSlug, "refused", "slug-unsafe", "reserved", 0);
1658
+ return { content: [{ type: "text", text: "Refused: the admin agent cannot be deleted." }], isError: true };
1659
+ }
1660
+ const headers = { "x-maxy-caller-account": ACCOUNT_ID };
1661
+ if (process.env.HOUSE_ADMIN_SCOPE)
1662
+ headers["x-maxy-house-admin-scope"] = process.env.HOUSE_ADMIN_SCOPE;
1663
+ try {
1664
+ const res = await fetch(`http://127.0.0.1:${PLATFORM_PORT}/api/admin/agents/${agentSlug}?accountId=${ACCOUNT_ID}`, { method: "DELETE", headers, signal: AbortSignal.timeout(5000) });
1665
+ if (!res.ok) {
1666
+ const body = await res.text().catch(() => "");
1667
+ const reason = res.status === 404 ? "not-found" : "delete-failed";
1668
+ logAgentWrite("delete", agentSlug, "refused", reason, String(res.status), 0);
1669
+ return { content: [{ type: "text", text: `Refused: ${reason} — ${res.status} ${body}`.trim() }], isError: true };
1670
+ }
1671
+ logAgentWrite("delete", agentSlug, "ok", "none", "-", 0);
1672
+ return { content: [{ type: "text", text: `Agent '${agentSlug}' deleted from the graph and from disk.` }] };
1673
+ }
1674
+ catch (err) {
1675
+ const msg = err instanceof Error ? err.message : String(err);
1676
+ logAgentWrite("delete", agentSlug, "refused", "delete-failed", msg, 0);
1677
+ return { content: [{ type: "text", text: `Delete failed: ${msg}` }], isError: true };
1678
+ }
1679
+ });
1544
1680
  eagerTool(server, "logs-read", "Read recent logs. Stream logs (type=agent-stream/error/session/public) are per-session — pass `sessionKey` (preferred) or the legacy `sessionId` alias to retrieve a single session's log from first [spawn] to final [process-exit]. type=agent-stream: per-session tool-use/tool-result archive (every `[tool-use]` and `[tool-result]` pair with full input + output JSON, plus raw Claude stream-json, agent events, and MCP server stderr via tee). USE THIS when investigating what an agent ACTUALLY did with its tools — server.log only carries `[persist] tool-call persisted` markers, not bodies. (`type=system` is a backwards-compatible alias for the same archive.) type=session: SSE events sent to client. type=error: Claude subprocess stderr (raw — NODE_DEBUG HTTP/NET/UNDICI traces land in agent-stream via the stream tee, not here). type=heartbeat: platform event dispatcher (check-due-events cron). type=public: public agent diagnostic log. type=server: platform server log. type=mcp: MCP server stderr (per-plugin raw), resolved under ~/.<brand>/logs — the platform config dir, not the account log dir. With a sessionKey, every mcp-*.log whose FILENAME carries that key is tailed, up to 20 files, and a truncated reply names the total that matched; an 8-character key prefix matches. The key is never matched against file contents, because MCP log lines carry no session key. type=vnc: VNC browser viewer lifecycle.", {
1545
1681
  type: z.enum(["agent-stream", "system", "session", "error", "heartbeat", "public", "server", "mcp", "vnc"]).optional(),
1546
1682
  lines: z.number().optional(),