@rubytech/create-sitedesk-code 0.1.514 → 0.1.516

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 (220) hide show
  1. package/dist/__tests__/launchd-bootstrap.test.js +164 -18
  2. package/dist/index.js +15 -14
  3. package/dist/launchd-bootstrap.js +86 -17
  4. package/package.json +1 -1
  5. package/payload/platform/docs/superpowers/plans/2026-07-27-task-2016-disabled-agent-routing.md +624 -0
  6. package/payload/platform/docs/superpowers/specs/2026-07-27-task-2016-disabled-agent-routing-design.md +139 -0
  7. package/payload/platform/plugins/admin/mcp/dist/index.js +14 -16
  8. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  9. package/payload/platform/plugins/admin/mcp/dist/specialist-registry.d.ts +14 -0
  10. package/payload/platform/plugins/admin/mcp/dist/specialist-registry.d.ts.map +1 -0
  11. package/payload/platform/plugins/admin/mcp/dist/specialist-registry.js +57 -0
  12. package/payload/platform/plugins/admin/mcp/dist/specialist-registry.js.map +1 -0
  13. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +66 -5
  14. package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +12 -0
  15. package/payload/platform/plugins/docs/references/admin-ui.md +38 -3
  16. package/payload/platform/plugins/docs/references/deployment.md +4 -0
  17. package/payload/platform/plugins/email/PLUGIN.md +1 -1
  18. package/payload/platform/plugins/email/mcp/dist/__tests__/attachment-metadata-calendar.test.d.ts +2 -0
  19. package/payload/platform/plugins/email/mcp/dist/__tests__/attachment-metadata-calendar.test.d.ts.map +1 -0
  20. package/payload/platform/plugins/email/mcp/dist/__tests__/attachment-metadata-calendar.test.js +94 -0
  21. package/payload/platform/plugins/email/mcp/dist/__tests__/attachment-metadata-calendar.test.js.map +1 -0
  22. package/payload/platform/plugins/email/mcp/dist/index.js +1 -1
  23. package/payload/platform/plugins/email/mcp/dist/index.js.map +1 -1
  24. package/payload/platform/plugins/email/mcp/dist/lib/imap.d.ts +21 -1
  25. package/payload/platform/plugins/email/mcp/dist/lib/imap.d.ts.map +1 -1
  26. package/payload/platform/plugins/email/mcp/dist/lib/imap.js +49 -8
  27. package/payload/platform/plugins/email/mcp/dist/lib/imap.js.map +1 -1
  28. package/payload/platform/plugins/email/references/email-reference.md +4 -0
  29. package/payload/platform/plugins/outlook/mcp/dist/__tests__/graph-client-retry.test.js +143 -2
  30. package/payload/platform/plugins/outlook/mcp/dist/__tests__/graph-client-retry.test.js.map +1 -1
  31. package/payload/platform/plugins/outlook/mcp/dist/__tests__/graph-client.test.js +33 -3
  32. package/payload/platform/plugins/outlook/mcp/dist/__tests__/graph-client.test.js.map +1 -1
  33. package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-search-paging.test.js +142 -0
  34. package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-search-paging.test.js.map +1 -1
  35. package/payload/platform/plugins/outlook/mcp/dist/lib/graph-client.d.ts +8 -0
  36. package/payload/platform/plugins/outlook/mcp/dist/lib/graph-client.d.ts.map +1 -1
  37. package/payload/platform/plugins/outlook/mcp/dist/lib/graph-client.js +40 -0
  38. package/payload/platform/plugins/outlook/mcp/dist/lib/graph-client.js.map +1 -1
  39. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-search.d.ts.map +1 -1
  40. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-search.js +54 -3
  41. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-search.js.map +1 -1
  42. package/payload/platform/plugins/outlook/references/graph-surfaces.md +9 -3
  43. package/payload/platform/plugins/whatsapp/references/channels-whatsapp.md +2 -2
  44. package/payload/platform/scripts/__tests__/agents-md-bootstrap.test.sh +47 -0
  45. package/payload/platform/scripts/lib/agents-md-bootstrap.sh +58 -1
  46. package/payload/platform/services/claude-session-manager/dist/config.d.ts +48 -12
  47. package/payload/platform/services/claude-session-manager/dist/config.d.ts.map +1 -1
  48. package/payload/platform/services/claude-session-manager/dist/config.js +65 -15
  49. package/payload/platform/services/claude-session-manager/dist/config.js.map +1 -1
  50. package/payload/platform/services/claude-session-manager/dist/index.js +7 -4
  51. package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
  52. package/payload/platform/services/claude-session-manager/dist/rootless-client-audit.d.ts.map +1 -1
  53. package/payload/platform/services/claude-session-manager/dist/rootless-client-audit.js +17 -2
  54. package/payload/platform/services/claude-session-manager/dist/rootless-client-audit.js.map +1 -1
  55. package/payload/server/public/activity.html +5 -5
  56. package/payload/server/public/agents.html +4 -4
  57. package/payload/server/public/assets/{AdminLoginScreens-Cs1jSnOF.js → AdminLoginScreens-B5qKb3YK.js} +1 -1
  58. package/payload/server/public/assets/AdminLoginScreens-B5qKb3YK.js.br +0 -0
  59. package/payload/server/public/assets/AdminLoginScreens-B5qKb3YK.js.gz +0 -0
  60. package/payload/server/public/assets/{AdminShell-DkrURZnF.js → AdminShell-BgJEq2zJ.js} +1 -1
  61. package/payload/server/public/assets/AdminShell-BgJEq2zJ.js.br +0 -0
  62. package/payload/server/public/assets/AdminShell-BgJEq2zJ.js.gz +0 -0
  63. package/payload/server/public/assets/{activity-BgZISMuE.js → activity-DmnVUDYO.js} +1 -1
  64. package/payload/server/public/assets/activity-DmnVUDYO.js.br +0 -0
  65. package/payload/server/public/assets/activity-DmnVUDYO.js.gz +0 -0
  66. package/payload/server/public/assets/{admin-DjFysc3-.js → admin-Dpge4OG9.js} +1 -1
  67. package/payload/server/public/assets/admin-Dpge4OG9.js.br +0 -0
  68. package/payload/server/public/assets/admin-Dpge4OG9.js.gz +0 -0
  69. package/payload/server/public/assets/{agents-Bx-MSZW6.js → agents-Bmq9X7P3.js} +1 -1
  70. package/payload/server/public/assets/agents-Bmq9X7P3.js.br +0 -0
  71. package/payload/server/public/assets/agents-Bmq9X7P3.js.gz +0 -0
  72. package/payload/server/public/assets/{browser-1I7syhHu.js → browser-B1G-W80B.js} +1 -1
  73. package/payload/server/public/assets/browser-B1G-W80B.js.br +0 -0
  74. package/payload/server/public/assets/browser-B1G-W80B.js.gz +0 -0
  75. package/payload/server/public/assets/{calendar-D_04JIo1.js → calendar-CHgrOFIN.js} +1 -1
  76. package/payload/server/public/assets/calendar-CHgrOFIN.js.br +0 -0
  77. package/payload/server/public/assets/calendar-CHgrOFIN.js.gz +0 -0
  78. package/payload/server/public/assets/chat-CIwmmtwP.js +1 -0
  79. package/payload/server/public/assets/chat-CIwmmtwP.js.br +0 -0
  80. package/payload/server/public/assets/chat-CIwmmtwP.js.gz +0 -0
  81. package/payload/server/public/assets/chevron-left-EQjfaQ-n.js +1 -0
  82. package/payload/server/public/assets/chevron-left-EQjfaQ-n.js.br +0 -0
  83. package/payload/server/public/assets/chevron-right-Ct8jZUGP.js +1 -0
  84. package/payload/server/public/assets/chevron-right-Ct8jZUGP.js.br +0 -0
  85. package/payload/server/public/assets/clock-Cxz5ybck.js +1 -0
  86. package/payload/server/public/assets/clock-Cxz5ybck.js.br +0 -0
  87. package/payload/server/public/assets/clock-Cxz5ybck.js.gz +0 -0
  88. package/payload/server/public/assets/data-BQVXKVsJ.js +1 -0
  89. package/payload/server/public/assets/data-BQVXKVsJ.js.br +1 -0
  90. package/payload/server/public/assets/data-BQVXKVsJ.js.gz +0 -0
  91. package/payload/server/public/assets/{file-text-DkvKqHMx.js → file-text-BVqqaDun.js} +1 -1
  92. package/payload/server/public/assets/file-text-BVqqaDun.js.br +0 -0
  93. package/payload/server/public/assets/file-text-BVqqaDun.js.gz +0 -0
  94. package/payload/server/public/assets/{graph-CCZhrwZX.js → graph-CEcME0lp.js} +1 -1
  95. package/payload/server/public/assets/graph-CEcME0lp.js.br +0 -0
  96. package/payload/server/public/assets/graph-CEcME0lp.js.gz +0 -0
  97. package/payload/server/public/assets/{graph-labels-BJ7puQkX.js → graph-labels-Zl32_AOH.js} +1 -1
  98. package/payload/server/public/assets/graph-labels-Zl32_AOH.js.br +0 -0
  99. package/payload/server/public/assets/graph-labels-Zl32_AOH.js.gz +0 -0
  100. package/payload/server/public/assets/{maximize-2-Xdj804U1.js → maximize-2-rkkMyAhf.js} +1 -1
  101. package/payload/server/public/assets/maximize-2-rkkMyAhf.js.br +0 -0
  102. package/payload/server/public/assets/maximize-2-rkkMyAhf.js.gz +0 -0
  103. package/payload/server/public/assets/{operator-BkfNpBs7.js → operator-DlL023ch.js} +1 -1
  104. package/payload/server/public/assets/operator-DlL023ch.js.br +0 -0
  105. package/payload/server/public/assets/operator-DlL023ch.js.gz +0 -0
  106. package/payload/server/public/assets/{page-D5n8ShE7.js → page-BAmYYqxp.js} +1 -1
  107. package/payload/server/public/assets/page-BAmYYqxp.js.br +0 -0
  108. package/payload/server/public/assets/page-BAmYYqxp.js.gz +0 -0
  109. package/payload/server/public/assets/{page-BoYc9c4a.js → page-k0BhBkA2.js} +1 -1
  110. package/payload/server/public/assets/page-k0BhBkA2.js.br +0 -0
  111. package/payload/server/public/assets/page-k0BhBkA2.js.gz +0 -0
  112. package/payload/server/public/assets/{public-CX5XSrxD.js → public-Cqgfmo1D.js} +1 -1
  113. package/payload/server/public/assets/public-Cqgfmo1D.js.br +0 -0
  114. package/payload/server/public/assets/public-Cqgfmo1D.js.gz +0 -0
  115. package/payload/server/public/assets/{rotate-ccw-dh_OhL23.js → rotate-ccw-O3RmqoTy.js} +1 -1
  116. package/payload/server/public/assets/rotate-ccw-O3RmqoTy.js.br +0 -0
  117. package/payload/server/public/assets/rotate-ccw-O3RmqoTy.js.gz +0 -0
  118. package/payload/server/public/assets/{routines-bb7dxcrr.js → routines-DMYObMUy.js} +1 -1
  119. package/payload/server/public/assets/routines-DMYObMUy.js.br +0 -0
  120. package/payload/server/public/assets/routines-DMYObMUy.js.gz +0 -0
  121. package/payload/server/public/assets/{skills-TeMwxXmJ.js → skills-DON1BKu5.js} +1 -1
  122. package/payload/server/public/assets/skills-DON1BKu5.js.br +0 -0
  123. package/payload/server/public/assets/skills-DON1BKu5.js.gz +0 -0
  124. package/payload/server/public/assets/{tasks-BqBBJlkg.js → tasks-C2PhUSrf.js} +1 -1
  125. package/payload/server/public/assets/tasks-C2PhUSrf.js.br +0 -0
  126. package/payload/server/public/assets/tasks-C2PhUSrf.js.gz +0 -0
  127. package/payload/server/public/assets/{time-entry-format-Cy_T-wiD.js → time-entry-format-4zgmuQI0.js} +1 -1
  128. package/payload/server/public/assets/time-entry-format-4zgmuQI0.js.br +0 -0
  129. package/payload/server/public/assets/time-entry-format-4zgmuQI0.js.gz +0 -0
  130. package/payload/server/public/assets/{triangle-alert-D-bSbPnX.js → triangle-alert-By5D7wuI.js} +1 -1
  131. package/payload/server/public/assets/triangle-alert-By5D7wuI.js.br +0 -0
  132. package/payload/server/public/assets/triangle-alert-By5D7wuI.js.gz +0 -0
  133. package/payload/server/public/assets/{useCopyFeedback-L7L55nFl.js → useCopyFeedback-Dx0vtm9s.js} +1 -1
  134. package/payload/server/public/assets/useCopyFeedback-Dx0vtm9s.js.br +0 -0
  135. package/payload/server/public/assets/useCopyFeedback-Dx0vtm9s.js.gz +0 -0
  136. package/payload/server/public/assets/{useSubAccountSwitcher-BYl2c7xA.css → useSubAccountSwitcher-UQQDcj0B.css} +1 -1
  137. package/payload/server/public/assets/useSubAccountSwitcher-UQQDcj0B.css.br +0 -0
  138. package/payload/server/public/assets/useSubAccountSwitcher-UQQDcj0B.css.gz +0 -0
  139. package/payload/server/public/assets/{useVoiceRecorder-MuZ7lpet.js → useVoiceRecorder-BgwOCCwj.js} +1 -1
  140. package/payload/server/public/assets/useVoiceRecorder-BgwOCCwj.js.br +0 -0
  141. package/payload/server/public/assets/useVoiceRecorder-BgwOCCwj.js.gz +0 -0
  142. package/payload/server/public/assets/{wrench-DUG1SZQB.js → wrench-CHfMwLza.js} +1 -1
  143. package/payload/server/public/assets/wrench-CHfMwLza.js.br +0 -0
  144. package/payload/server/public/assets/wrench-CHfMwLza.js.gz +0 -0
  145. package/payload/server/public/browser.html +4 -4
  146. package/payload/server/public/calendar.html +7 -7
  147. package/payload/server/public/chat.html +13 -13
  148. package/payload/server/public/data.html +11 -11
  149. package/payload/server/public/graph.html +9 -9
  150. package/payload/server/public/index.html +14 -14
  151. package/payload/server/public/operator.html +14 -14
  152. package/payload/server/public/public.html +13 -13
  153. package/payload/server/public/routines.html +6 -6
  154. package/payload/server/public/skills.html +5 -5
  155. package/payload/server/public/tasks.html +6 -6
  156. package/payload/server/server.js +139 -17
  157. package/payload/server/public/assets/AdminLoginScreens-Cs1jSnOF.js.br +0 -0
  158. package/payload/server/public/assets/AdminLoginScreens-Cs1jSnOF.js.gz +0 -0
  159. package/payload/server/public/assets/AdminShell-DkrURZnF.js.br +0 -0
  160. package/payload/server/public/assets/AdminShell-DkrURZnF.js.gz +0 -0
  161. package/payload/server/public/assets/activity-BgZISMuE.js.br +0 -0
  162. package/payload/server/public/assets/activity-BgZISMuE.js.gz +0 -0
  163. package/payload/server/public/assets/admin-DjFysc3-.js.br +0 -0
  164. package/payload/server/public/assets/admin-DjFysc3-.js.gz +0 -0
  165. package/payload/server/public/assets/agents-Bx-MSZW6.js.br +0 -0
  166. package/payload/server/public/assets/agents-Bx-MSZW6.js.gz +0 -0
  167. package/payload/server/public/assets/browser-1I7syhHu.js.br +0 -0
  168. package/payload/server/public/assets/browser-1I7syhHu.js.gz +0 -0
  169. package/payload/server/public/assets/calendar-D_04JIo1.js.br +0 -0
  170. package/payload/server/public/assets/calendar-D_04JIo1.js.gz +0 -0
  171. package/payload/server/public/assets/chat-BFH3FM5a.js +0 -1
  172. package/payload/server/public/assets/chat-BFH3FM5a.js.br +0 -0
  173. package/payload/server/public/assets/chat-BFH3FM5a.js.gz +0 -0
  174. package/payload/server/public/assets/chevron-left-Ux9-qLkk.js +0 -1
  175. package/payload/server/public/assets/chevron-right-BwIuCfyG.js +0 -1
  176. package/payload/server/public/assets/chevron-right-BwIuCfyG.js.br +0 -0
  177. package/payload/server/public/assets/clock-DhJdZRhC.js +0 -1
  178. package/payload/server/public/assets/clock-DhJdZRhC.js.br +0 -0
  179. package/payload/server/public/assets/data-ChY_uSIk.js +0 -1
  180. package/payload/server/public/assets/data-ChY_uSIk.js.br +0 -0
  181. package/payload/server/public/assets/data-ChY_uSIk.js.gz +0 -0
  182. package/payload/server/public/assets/file-text-DkvKqHMx.js.br +0 -0
  183. package/payload/server/public/assets/file-text-DkvKqHMx.js.gz +0 -0
  184. package/payload/server/public/assets/graph-CCZhrwZX.js.br +0 -0
  185. package/payload/server/public/assets/graph-CCZhrwZX.js.gz +0 -0
  186. package/payload/server/public/assets/graph-labels-BJ7puQkX.js.br +0 -0
  187. package/payload/server/public/assets/graph-labels-BJ7puQkX.js.gz +0 -0
  188. package/payload/server/public/assets/maximize-2-Xdj804U1.js.br +0 -0
  189. package/payload/server/public/assets/maximize-2-Xdj804U1.js.gz +0 -0
  190. package/payload/server/public/assets/operator-BkfNpBs7.js.br +0 -0
  191. package/payload/server/public/assets/operator-BkfNpBs7.js.gz +0 -0
  192. package/payload/server/public/assets/page-BoYc9c4a.js.br +0 -0
  193. package/payload/server/public/assets/page-BoYc9c4a.js.gz +0 -0
  194. package/payload/server/public/assets/page-D5n8ShE7.js.br +0 -0
  195. package/payload/server/public/assets/page-D5n8ShE7.js.gz +0 -0
  196. package/payload/server/public/assets/public-CX5XSrxD.js.br +0 -0
  197. package/payload/server/public/assets/public-CX5XSrxD.js.gz +0 -0
  198. package/payload/server/public/assets/rotate-ccw-dh_OhL23.js.br +0 -0
  199. package/payload/server/public/assets/rotate-ccw-dh_OhL23.js.gz +0 -0
  200. package/payload/server/public/assets/routines-bb7dxcrr.js.br +0 -0
  201. package/payload/server/public/assets/routines-bb7dxcrr.js.gz +0 -0
  202. package/payload/server/public/assets/skills-TeMwxXmJ.js.br +0 -0
  203. package/payload/server/public/assets/skills-TeMwxXmJ.js.gz +0 -0
  204. package/payload/server/public/assets/tasks-BqBBJlkg.js.br +0 -0
  205. package/payload/server/public/assets/tasks-BqBBJlkg.js.gz +0 -0
  206. package/payload/server/public/assets/time-entry-format-Cy_T-wiD.js.br +0 -3
  207. package/payload/server/public/assets/time-entry-format-Cy_T-wiD.js.gz +0 -0
  208. package/payload/server/public/assets/triangle-alert-D-bSbPnX.js.br +0 -1
  209. package/payload/server/public/assets/triangle-alert-D-bSbPnX.js.gz +0 -0
  210. package/payload/server/public/assets/useCopyFeedback-L7L55nFl.js.br +0 -0
  211. package/payload/server/public/assets/useCopyFeedback-L7L55nFl.js.gz +0 -0
  212. package/payload/server/public/assets/useSubAccountSwitcher-BYl2c7xA.css.br +0 -0
  213. package/payload/server/public/assets/useSubAccountSwitcher-BYl2c7xA.css.gz +0 -0
  214. package/payload/server/public/assets/useVoiceRecorder-MuZ7lpet.js.br +0 -0
  215. package/payload/server/public/assets/useVoiceRecorder-MuZ7lpet.js.gz +0 -0
  216. package/payload/server/public/assets/wrench-DUG1SZQB.js.br +0 -0
  217. package/payload/server/public/assets/wrench-DUG1SZQB.js.gz +0 -0
  218. /package/payload/server/public/assets/{useSubAccountSwitcher-DH0P6QMV.js → useSubAccountSwitcher-CRWoQXuU.js} +0 -0
  219. /package/payload/server/public/assets/{useSubAccountSwitcher-DH0P6QMV.js.br → useSubAccountSwitcher-CRWoQXuU.js.br} +0 -0
  220. /package/payload/server/public/assets/{useSubAccountSwitcher-DH0P6QMV.js.gz → useSubAccountSwitcher-CRWoQXuU.js.gz} +0 -0
@@ -3219,7 +3219,7 @@ var WhatsAppConfigSchema = z.object({
3219
3219
  z.string(),
3220
3220
  z.object({ managesAccount: z.string(), mode: z.enum(["active", "passive"]).optional() })
3221
3221
  ])
3222
- ).optional().describe("Account-manager bindings: E.164 phone \u2192 sub-account. The value is a bare sub-account UUID (mode 'active', the default: a full admin session) or { managesAccount, mode } where mode 'passive' selects a constrained requirement-intake spawn (only work-create, no reply). A bare string and an object without mode both resolve to 'active'. Managed via add-account-manager / remove-account-manager. A phone here must not also be in adminPhones."),
3222
+ ).optional().describe("Account-manager bindings: E.164 phone \u2192 sub-account. The value is a bare sub-account UUID (mode 'active', the default: a full admin session) or { managesAccount, mode } where mode 'passive' selects a constrained requirement-intake spawn (only work-create, no reply). A bare string and an object without mode both resolve to 'active'. Managed via add-account-manager / remove-account-manager. A phone here must not also be in adminPhones. Read only from the account whose account.json the manager loads its config from (the house); add-account-manager is refused on any other account, and a map left there is inert and purged at boot."),
3223
3223
  allowFrom: z.array(z.string()).optional().describe("Phone numbers allowed to message the public agent when DM policy is 'allowlist'. Add '*' for open access. Does not affect admin routing \u2014 use adminPhones for that."),
3224
3224
  sendReadReceipts: z.boolean().optional().default(true).describe("Whether to send read receipts (blue ticks) when messages are received. Disabling may feel less responsive but preserves privacy."),
3225
3225
  mediaMaxMb: z.number().int().positive().optional().default(50).describe("Maximum file size in MB for media the agent will download and process."),
@@ -8123,7 +8123,7 @@ function createScheduleInjectRoutes(deps) {
8123
8123
  const houseAccountId = account.accountId;
8124
8124
  console.error(`${TAG21} op=received eventId=${eventId} channel=${channel} destination=${destination} account=${houseAccountId}`);
8125
8125
  if (channel === "whatsapp") {
8126
- const effectiveAccount2 = deps.effectiveAccountFor(houseAccountId, account.accountDir, destination);
8126
+ const effectiveAccount2 = deps.effectiveAccountFor(account.accountDir, destination);
8127
8127
  if (effectiveAccount2 === null) {
8128
8128
  console.error(`${TAG21} op=schedule-account-manager-reject eventId=${eventId} destination=${destination} reason=unresolved-effective-account`);
8129
8129
  return c.json({ ok: false, error: "account-manager-unresolved" }, 403);
@@ -8441,6 +8441,54 @@ function purgeNonSocketAdminPhonesAtBoot() {
8441
8441
  purgeNonSocketAdminPhones(acct.accountDir, socketOwner);
8442
8442
  }
8443
8443
  }
8444
+ function purgeNonSocketAccountManagers(accountDir, socketOwnerId) {
8445
+ try {
8446
+ const config = readConfig(accountDir);
8447
+ const wa = config.whatsapp;
8448
+ if (!wa || typeof wa !== "object") return { removed: [] };
8449
+ const targetId = typeof config.accountId === "string" && config.accountId ? config.accountId : basename2(resolve9(accountDir));
8450
+ if (targetId === socketOwnerId) return { removed: [] };
8451
+ const map = wa.accountManagers;
8452
+ if (!map || typeof map !== "object" || Array.isArray(map)) return { removed: [] };
8453
+ const removed = Object.entries(map).map(([phone, entry]) => ({
8454
+ phone,
8455
+ managesAccount: typeof entry === "string" ? entry : entry && typeof entry === "object" && typeof entry.managesAccount === "string" ? entry.managesAccount : ""
8456
+ }));
8457
+ if (removed.length === 0) return { removed: [] };
8458
+ delete wa.accountManagers;
8459
+ writeConfig(accountDir, config);
8460
+ for (const { phone, managesAccount } of removed) {
8461
+ console.error(`[admin-identity] op=purge-nonsocket-accountmanager accountId=${targetId} phone=${phone} managesAccount=${managesAccount} removed=true`);
8462
+ }
8463
+ return { removed };
8464
+ } catch (err) {
8465
+ console.error(`[admin-identity] purge-nonsocket-accountmanager failed dir=${accountDir}: ${String(err)}`);
8466
+ return { removed: [] };
8467
+ }
8468
+ }
8469
+ function purgeNonSocketAccountManagersAtBoot() {
8470
+ let socketOwner;
8471
+ try {
8472
+ socketOwner = resolveHouseOrSoleAccountId(ACCOUNTS_DIR);
8473
+ } catch (err) {
8474
+ console.error(`[admin-identity] purge-nonsocket-accountmanager skipped \u2014 cannot resolve socket owner: ${String(err)}`);
8475
+ return;
8476
+ }
8477
+ const configOwner = resolveAccount()?.accountId ?? null;
8478
+ if (configOwner !== socketOwner) {
8479
+ console.error(`[admin-identity] purge-nonsocket-accountmanager skipped \u2014 resolver disagreement house=${socketOwner} configLoadedFrom=${configOwner ?? "unresolved"}`);
8480
+ return;
8481
+ }
8482
+ let accounts;
8483
+ try {
8484
+ accounts = listValidAccounts();
8485
+ } catch {
8486
+ return;
8487
+ }
8488
+ for (const acct of accounts) {
8489
+ purgeNonSocketAccountManagers(acct.accountDir, socketOwner);
8490
+ }
8491
+ }
8444
8492
  function setAccountManager(accountDir, phone, subAccountId, mode = "active") {
8445
8493
  const normalized = phone.trim();
8446
8494
  if (!E164_PATTERN.test(normalized)) {
@@ -8475,6 +8523,15 @@ function setAccountManager(accountDir, phone, subAccountId, mode = "active") {
8475
8523
  }
8476
8524
  try {
8477
8525
  const config = readConfig(accountDir);
8526
+ const targetId = typeof config.accountId === "string" && config.accountId ? config.accountId : basename2(resolve9(accountDir));
8527
+ if (targetId !== houseId) {
8528
+ console.error(`${TAG22} set-account-manager rejected phone=${normalized} reason=not-socket-account`);
8529
+ return {
8530
+ ok: false,
8531
+ reason: "not-socket-account",
8532
+ error: `The account-manager routing table is read from ${houseId}'s account.json only, so a binding stored on ${targetId} is never consulted. Bind ${normalized} on ${houseId} instead.`
8533
+ };
8534
+ }
8478
8535
  if (!config.whatsapp || typeof config.whatsapp !== "object") {
8479
8536
  config.whatsapp = {};
8480
8537
  }
@@ -17062,6 +17119,7 @@ var session_upload_default = app17;
17062
17119
  // server/routes/admin/agents.ts
17063
17120
  import { resolve as resolve23 } from "path";
17064
17121
  import { readdirSync as readdirSync22, readFileSync as readFileSync33, existsSync as existsSync31, rmSync as rmSync2, renameSync as renameSync9, mkdirSync as mkdirSync7, writeFileSync as writeFileSync13 } from "fs";
17122
+ import { execFileSync as execFileSync6 } from "child_process";
17065
17123
 
17066
17124
  // ../services/claude-session-manager/src/tool-surface.ts
17067
17125
  import { readFileSync as readFileSync32, readdirSync as readdirSync21, statSync as statSync15, existsSync as existsSync30 } from "fs";
@@ -17490,6 +17548,20 @@ function readDisabledStore(accountDir) {
17490
17548
  return /* @__PURE__ */ new Set();
17491
17549
  }
17492
17550
  }
17551
+ function authoredAgentFilenames(accountDir) {
17552
+ const pluginsDir = resolve23(accountDir, "plugins");
17553
+ const names = /* @__PURE__ */ new Set();
17554
+ for (const plugin of subdirs(pluginsDir)) {
17555
+ const dir = resolve23(pluginsDir, plugin, "agents");
17556
+ if (!existsSync31(dir)) continue;
17557
+ try {
17558
+ for (const entry of readdirSync22(dir)) if (entry.endsWith(".md")) names.add(entry);
17559
+ } catch (err) {
17560
+ console.error(`[admin/agents] op=authored-scan read-failed plugin=${plugin} error="${err}"`);
17561
+ }
17562
+ }
17563
+ return names;
17564
+ }
17493
17565
  function shippedSourceDirs(accountDir) {
17494
17566
  return [
17495
17567
  resolve23(accountDir, ...SPECIALISTS_DIR),
@@ -17505,7 +17577,7 @@ function writeDisabledStore(accountDir, disabled) {
17505
17577
  { mode: 384 }
17506
17578
  );
17507
17579
  }
17508
- function listShipped(accountDir, riskByTool, disabled, riskSurfaceFailed) {
17580
+ function listShipped(accountDir, riskByTool, disabled, riskSurfaceFailed, authoredFilenames) {
17509
17581
  const dirs = shippedSourceDirs(accountDir);
17510
17582
  const names = /* @__PURE__ */ new Set();
17511
17583
  for (const dir of dirs) {
@@ -17518,9 +17590,15 @@ function listShipped(accountDir, riskByTool, disabled, riskSurfaceFailed) {
17518
17590
  }
17519
17591
  const shipped = [];
17520
17592
  let shippedSkipped = 0;
17593
+ let deduped = 0;
17521
17594
  for (const filename of [...names].sort()) {
17522
17595
  const source = dirs.find((d) => existsSync31(resolve23(d, filename)));
17523
17596
  if (!source) continue;
17597
+ if (source === dirs[0] && authoredFilenames.has(filename)) {
17598
+ deduped++;
17599
+ console.log(`[admin/agents] op=list-shipped-dedup file=${filename}`);
17600
+ continue;
17601
+ }
17524
17602
  try {
17525
17603
  const { fm } = splitFrontmatter(readFileSync33(resolve23(source, filename), "utf-8"));
17526
17604
  if (!fm.name) {
@@ -17553,7 +17631,7 @@ function listShipped(accountDir, riskByTool, disabled, riskSurfaceFailed) {
17553
17631
  console.error(`[admin/agents] op=list-shipped-skip file=${filename} error="${err}"`);
17554
17632
  }
17555
17633
  }
17556
- return { shipped, shippedSkipped };
17634
+ return { shipped, shippedSkipped, deduped };
17557
17635
  }
17558
17636
  function parseToolsLine(raw) {
17559
17637
  return raw ? raw.split(",").map((t) => t.trim()).filter(Boolean) : [];
@@ -17661,7 +17739,13 @@ app18.get("/", requireAdminSession, (c) => {
17661
17739
  }
17662
17740
  }
17663
17741
  const { specialists, specialistsSkipped } = listSpecialists(account.accountDir, riskByTool, riskSurfaceFailed !== null);
17664
- const { shipped, shippedSkipped } = listShipped(account.accountDir, riskByTool, disabled, riskSurfaceFailed !== null);
17742
+ const { shipped, shippedSkipped, deduped } = listShipped(
17743
+ account.accountDir,
17744
+ riskByTool,
17745
+ disabled,
17746
+ riskSurfaceFailed !== null,
17747
+ authoredAgentFilenames(account.accountDir)
17748
+ );
17665
17749
  const rows = [...agents, ...specialists, ...shipped];
17666
17750
  const acct = account.accountId.slice(0, 8);
17667
17751
  for (const row of rows) {
@@ -17670,13 +17754,17 @@ app18.get("/", requireAdminSession, (c) => {
17670
17754
  `[admin/agents] op=classify account=${acct} agent=${row.slug} origin=${row.origin} risk=${row.risk} riskiestTool=${row.riskiestTool ?? "none"} tools=${row.toolCount} unresolved=${row.unresolved.length > 0 ? row.unresolved.join(",") : "none"} disabled=${row.disabled}`
17671
17755
  );
17672
17756
  }
17673
- console.log(`[admin/agents] op=list accountId=${acct} agents=${agents.length} specialists=${specialists.length} shipped=${shipped.length} skipped=${skipped} specialistsSkipped=${specialistsSkipped} shippedSkipped=${shippedSkipped}`);
17757
+ console.log(`[admin/agents] op=list accountId=${acct} agents=${agents.length} specialists=${specialists.length} shipped=${shipped.length} skipped=${skipped} specialistsSkipped=${specialistsSkipped} shippedSkipped=${shippedSkipped} deduped=${deduped}`);
17674
17758
  return c.json({
17675
17759
  agents: rows,
17676
17760
  accountId: account.accountId,
17677
17761
  skipped,
17678
17762
  specialistsSkipped,
17679
17763
  shippedSkipped,
17764
+ // How many live-directory candidates were dropped as authored duplicates.
17765
+ // `shipped + shippedSkipped + deduped` equals the number of distinct `.md`
17766
+ // names across the three source directories.
17767
+ deduped,
17680
17768
  riskSurfaceFailed: riskSurfaceFailed !== null
17681
17769
  });
17682
17770
  });
@@ -17811,6 +17899,17 @@ async function resolveWritableAccount(c, op, slug) {
17811
17899
  }
17812
17900
  return account;
17813
17901
  }
17902
+ function reconcileRoutingProse(accountDir, accountId, op, slug) {
17903
+ const script = resolve23(PLATFORM_ROOT, "scripts", "lib", "agents-md-bootstrap.sh");
17904
+ try {
17905
+ execFileSync6("bash", [script, accountDir], { encoding: "utf-8", timeout: 1e4 });
17906
+ return true;
17907
+ } catch (err) {
17908
+ const msg = err instanceof Error ? err.message : String(err);
17909
+ console.error(`[admin/agents] op=agents-md-reconcile source=${op} accountId=${accountId.slice(0, 8)} slug=${slug} outcome=failed reason="${msg}"`);
17910
+ return false;
17911
+ }
17912
+ }
17814
17913
  app18.post("/:slug/disable", async (c) => {
17815
17914
  const slug = c.req.param("slug");
17816
17915
  if (SLUG_UNSAFE(slug)) return c.json({ error: "Invalid agent slug" }, 400);
@@ -17819,6 +17918,10 @@ app18.post("/:slug/disable", async (c) => {
17819
17918
  const filename = `${slug}.md`;
17820
17919
  const live = resolve23(resolved.accountDir, ...SPECIALISTS_DIR, filename);
17821
17920
  const quarantined = resolve23(resolved.accountDir, ...QUARANTINE_DIR, filename);
17921
+ if (authoredAgentFilenames(resolved.accountDir).has(filename)) {
17922
+ console.error(`[admin/agents] op=disable accountId=${resolved.accountId.slice(0, 8)} slug=${slug} outcome=failed reason=user-created-specialist`);
17923
+ return c.json({ error: "Only a shipped agent can be disabled" }, 404);
17924
+ }
17822
17925
  if (!shippedSourceDirs(resolved.accountDir).some((d) => existsSync31(resolve23(d, filename)))) {
17823
17926
  console.error(`[admin/agents] op=disable accountId=${resolved.accountId.slice(0, 8)} slug=${slug} outcome=failed reason=not-a-shipped-agent`);
17824
17927
  return c.json({ error: "Only a shipped agent can be disabled" }, 404);
@@ -17838,8 +17941,9 @@ app18.post("/:slug/disable", async (c) => {
17838
17941
  console.error(`[admin/agents] op=disable accountId=${resolved.accountId.slice(0, 8)} slug=${slug} outcome=failed reason="${msg}"`);
17839
17942
  return c.json({ error: `Disable failed, disabled store unreadable or unwritable: ${msg}` }, 500);
17840
17943
  }
17841
- console.log(`[admin/agents] op=disable accountId=${resolved.accountId.slice(0, 8)} slug=${slug} outcome=ok moved=${moved}`);
17842
- return c.json({ ok: true, moved });
17944
+ const routingReconciled = reconcileRoutingProse(resolved.accountDir, resolved.accountId, "disable", slug);
17945
+ console.log(`[admin/agents] op=disable accountId=${resolved.accountId.slice(0, 8)} slug=${slug} outcome=ok moved=${moved} routingReconciled=${routingReconciled}`);
17946
+ return c.json({ ok: true, moved, routingReconciled });
17843
17947
  });
17844
17948
  app18.post("/:slug/enable", async (c) => {
17845
17949
  const slug = c.req.param("slug");
@@ -17868,8 +17972,9 @@ app18.post("/:slug/enable", async (c) => {
17868
17972
  console.error(`[admin/agents] op=enable accountId=${resolved.accountId.slice(0, 8)} slug=${slug} outcome=failed reason="${msg}"`);
17869
17973
  return c.json({ error: `Enable failed: ${msg}` }, 500);
17870
17974
  }
17871
- console.log(`[admin/agents] op=enable accountId=${resolved.accountId.slice(0, 8)} slug=${slug} outcome=ok restored=${restored}`);
17872
- return c.json({ ok: true, restored });
17975
+ const routingReconciled = reconcileRoutingProse(resolved.accountDir, resolved.accountId, "enable", slug);
17976
+ console.log(`[admin/agents] op=enable accountId=${resolved.accountId.slice(0, 8)} slug=${slug} outcome=ok restored=${restored} routingReconciled=${routingReconciled}`);
17977
+ return c.json({ ok: true, restored, routingReconciled });
17873
17978
  });
17874
17979
  app18.delete("/:slug", async (c) => {
17875
17980
  const slug = c.req.param("slug");
@@ -31780,6 +31885,22 @@ function warnOnChannelAdminBindingDrift() {
31780
31885
  }
31781
31886
  }
31782
31887
 
31888
+ // server/routes/channel/effective-account.ts
31889
+ function resolveScheduledEffectiveAccount(deps, accountDir, destination) {
31890
+ const managed = managedAccountFor(deps.readAccountManagers(accountDir), destination);
31891
+ if (managed === null) return deps.resolvePlatformAccountId();
31892
+ if (managed.mode === "passive") return null;
31893
+ if (!deps.isValidAccountId(managed.account)) return null;
31894
+ return managed.account;
31895
+ }
31896
+ function resolveScheduledEffectiveAccountForInstall(accountDir, destination) {
31897
+ return resolveScheduledEffectiveAccount(
31898
+ { readAccountManagers, resolvePlatformAccountId, isValidAccountId },
31899
+ accountDir,
31900
+ destination
31901
+ );
31902
+ }
31903
+
31783
31904
  // server/lib/booking-site-accounts.ts
31784
31905
  import { existsSync as existsSync46, readFileSync as readFileSync46 } from "fs";
31785
31906
  import { resolve as resolve43 } from "path";
@@ -32512,13 +32633,13 @@ var scheduleInjectRoutes = createScheduleInjectRoutes({
32512
32633
  const sent = await sendTelegramText(botToken, chatId, text);
32513
32634
  if (!sent.ok) throw new Error(sent.error ?? "telegram send failed");
32514
32635
  },
32515
- effectiveAccountFor: (accountId, accountDir, destination) => {
32516
- const managed = managedAccountFor(readAccountManagers(accountDir), destination);
32517
- if (managed === null) return accountId;
32518
- if (managed.mode === "passive") return null;
32519
- if (!isValidAccountId(managed.account)) return null;
32520
- return managed.account;
32521
- }
32636
+ // Task 2051 the four branches moved into their own module so they have a
32637
+ // test, and so the non-manager branch resolves the channel account through
32638
+ // `resolvePlatformAccountId` (the function the live inbound path uses) rather
32639
+ // than returning the house id this closure used to be handed. See
32640
+ // effective-account.ts for why `resolveAccount()` was the wrong side to move,
32641
+ // and why the real dependencies are bound there rather than assembled here.
32642
+ effectiveAccountFor: resolveScheduledEffectiveAccountForInstall
32522
32643
  });
32523
32644
  app69.route("/api/channel/schedule-inject", scheduleInjectRoutes);
32524
32645
  app69.use("*", clientIpMiddleware);
@@ -33820,6 +33941,7 @@ for (const acct of listValidAccounts()) {
33820
33941
  cleanupLeakedPremiumSubs(acct.accountDir, acct.config, acct.accountId);
33821
33942
  }
33822
33943
  purgeNonSocketAdminPhonesAtBoot();
33944
+ purgeNonSocketAccountManagersAtBoot();
33823
33945
  void preloadEmbedModel();
33824
33946
  warnOnChannelAdminBindingDrift();
33825
33947
  var bootEnabled = Array.isArray(bootAccountConfig?.enabledPlugins) ? bootAccountConfig.enabledPlugins : [];
@@ -1 +0,0 @@
1
- import{B as e,W as t}from"./useSubAccountSwitcher-DH0P6QMV.js";import"./useVoiceRecorder-MuZ7lpet.js";import"./AdminShell-DkrURZnF.js";import{n}from"./page-BoYc9c4a.js";import"./useCopyFeedback-L7L55nFl.js";var r=t(),i=e();(0,r.createRoot)(document.getElementById(`root`)).render((0,i.jsx)(n,{}));
@@ -1 +0,0 @@
1
- import{P as e}from"./useSubAccountSwitcher-DH0P6QMV.js";var t=e(`chevron-left`,[[`path`,{d:`m15 18-6-6 6-6`,key:`1wnfg3`}]]);export{t};
@@ -1 +0,0 @@
1
- import{P as e}from"./useSubAccountSwitcher-DH0P6QMV.js";var t=e(`chevron-right`,[[`path`,{d:`m9 18 6-6-6-6`,key:`mthhwq`}]]);export{t};
@@ -1 +0,0 @@
1
- import{P as e}from"./useSubAccountSwitcher-DH0P6QMV.js";var t=e(`clock`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M12 6v6l4 2`,key:`mmk7yg`}]]);export{t};
@@ -1 +0,0 @@
1
- import{B as e,W as t}from"./useSubAccountSwitcher-DH0P6QMV.js";import"./useVoiceRecorder-MuZ7lpet.js";import{t as n}from"./page-D5n8ShE7.js";import"./graph-labels-BJ7puQkX.js";var r=t(),i=e();(0,r.createRoot)(document.getElementById(`root`)).render((0,i.jsx)(n,{}));
@@ -1,3 +0,0 @@
1
- �����B�����"@GzN�n?�V��VF�Ybf�|c�9����Ja���'�T�
2
- ��s��'X`�cQ�Al�A�_� ڢ4��o ���6N|�Ϋ7A���8�$OI%��o��7D��dG��ݮ��m5��9�u��
3
- �^ʠ"I��22k'�l�ûV�Li����>� ۟`;;��z�����s�~�ι�n~��>��P�_��@&��%~ p3$)H_ ���f��R*�]��������)v�P�g?�,+���95䅷6��mxJ�w1