@rubytech/create-maxy-code 0.1.542 → 0.1.544
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.
- package/dist/__tests__/public-instruction-seed.test.js +102 -0
- package/dist/index.js +47 -0
- package/dist/public-instruction-seed.js +70 -0
- package/package.json +1 -1
- package/payload/platform/lib/shared-folder/dist/index.d.ts +47 -0
- package/payload/platform/lib/shared-folder/dist/index.d.ts.map +1 -0
- package/payload/platform/lib/shared-folder/dist/index.js +93 -0
- package/payload/platform/lib/shared-folder/dist/index.js.map +1 -0
- package/payload/platform/lib/shared-folder/src/index.ts +92 -0
- package/payload/platform/lib/shared-folder/tsconfig.json +5 -0
- package/payload/platform/package.json +2 -2
- package/payload/platform/plugins/admin/PLUGIN.md +2 -0
- package/payload/platform/plugins/admin/hooks/__tests__/public-tool-surface.test.sh +173 -0
- package/payload/platform/plugins/admin/hooks/public-tool-surface.sh +123 -0
- package/payload/platform/plugins/admin/mcp/dist/tools/agent-write.d.ts.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/tools/agent-write.js +13 -1
- package/payload/platform/plugins/admin/mcp/dist/tools/agent-write.js.map +1 -1
- package/payload/platform/plugins/admin/skills/channel-instruction/SKILL.md +46 -0
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +18 -1
- package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +15 -0
- package/payload/platform/plugins/docs/references/access-control.md +14 -0
- package/payload/platform/plugins/docs/references/internals.md +2 -0
- package/payload/platform/plugins/docs/references/platform.md +1 -0
- package/payload/platform/plugins/filesystem/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/filesystem/PLUGIN.md +11 -1
- package/payload/platform/plugins/filesystem/mcp/dist/index.js +23 -7
- package/payload/platform/plugins/filesystem/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/scope.test.js +104 -4
- package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/scope.test.js.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/shared-folder.test.d.ts +2 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/shared-folder.test.d.ts.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/shared-folder.test.js +67 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/shared-folder.test.js.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/scope.d.ts +16 -2
- package/payload/platform/plugins/filesystem/mcp/dist/lib/scope.d.ts.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/lib/scope.js +54 -1
- package/payload/platform/plugins/filesystem/mcp/dist/lib/scope.js.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/__tests__/handlers.test.js +76 -2
- package/payload/platform/plugins/filesystem/mcp/dist/tools/__tests__/handlers.test.js.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-edit.d.ts +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-edit.d.ts.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-edit.js +3 -3
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-edit.js.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-glob.d.ts +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-glob.d.ts.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-glob.js +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-glob.js.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-grep.d.ts +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-grep.d.ts.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-grep.js +3 -3
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-grep.js.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-list.d.ts +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-list.d.ts.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-list.js +3 -3
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-list.js.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-read.d.ts +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-read.d.ts.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-read.js +3 -3
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-read.js.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-write.d.ts +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-write.d.ts.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-write.js +3 -3
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-write.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/agent-turn-dispatch.test.js +81 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/agent-turn-dispatch.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts +22 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js +80 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js +13 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js.map +1 -1
- package/payload/platform/plugins/whatsapp/PLUGIN.md +2 -2
- package/payload/platform/plugins/whatsapp/mcp/dist/index.js +1 -1
- package/payload/platform/plugins/whatsapp/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/whatsapp/references/channels-whatsapp.md +1 -1
- package/payload/platform/scripts/__tests__/public-surface-registered.test.sh +102 -0
- package/payload/platform/scripts/check-no-esm-require.mjs +5 -0
- package/payload/platform/scripts/lib/__tests__/account-settings-public-surface.test.sh +109 -0
- package/payload/platform/scripts/lib/account-settings-public-surface.sh +109 -0
- package/payload/platform/scripts/lib/provision-account-dir.sh +6 -3
- package/payload/platform/scripts/setup-account.sh +14 -0
- package/payload/platform/services/claude-session-manager/dist/agent-identity-locator.d.ts +8 -4
- package/payload/platform/services/claude-session-manager/dist/agent-identity-locator.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/agent-identity-locator.js +27 -7
- package/payload/platform/services/claude-session-manager/dist/agent-identity-locator.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/config.d.ts +11 -6
- package/payload/platform/services/claude-session-manager/dist/config.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/config.js +8 -4
- package/payload/platform/services/claude-session-manager/dist/config.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/fs-watcher.d.ts +24 -2
- package/payload/platform/services/claude-session-manager/dist/fs-watcher.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/fs-watcher.js +23 -1
- package/payload/platform/services/claude-session-manager/dist/fs-watcher.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts +35 -0
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.js +286 -25
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/index.js +169 -51
- package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +24 -12
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +194 -28
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/public-agent-reachability.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/public-agent-reachability.js +4 -0
- package/payload/platform/services/claude-session-manager/dist/public-agent-reachability.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/public-surface-audit.d.ts +24 -3
- package/payload/platform/services/claude-session-manager/dist/public-surface-audit.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/public-surface-audit.js +29 -3
- package/payload/platform/services/claude-session-manager/dist/public-surface-audit.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/rc-public-lockdown.d.ts +27 -0
- package/payload/platform/services/claude-session-manager/dist/rc-public-lockdown.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/rc-public-lockdown.js +32 -0
- package/payload/platform/services/claude-session-manager/dist/rc-public-lockdown.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/role-census.d.ts +24 -0
- package/payload/platform/services/claude-session-manager/dist/role-census.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/role-census.js +50 -0
- package/payload/platform/services/claude-session-manager/dist/role-census.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/session-sidecar.d.ts +24 -2
- package/payload/platform/services/claude-session-manager/dist/session-sidecar.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/session-sidecar.js +21 -0
- package/payload/platform/services/claude-session-manager/dist/session-sidecar.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/stuck-turn-recover.d.ts +76 -0
- package/payload/platform/services/claude-session-manager/dist/stuck-turn-recover.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/stuck-turn-recover.js +110 -19
- package/payload/platform/services/claude-session-manager/dist/stuck-turn-recover.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/stuck-turn-respawn.d.ts +60 -0
- package/payload/platform/services/claude-session-manager/dist/stuck-turn-respawn.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/stuck-turn-respawn.js +93 -0
- package/payload/platform/services/claude-session-manager/dist/stuck-turn-respawn.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/stuck-turn.d.ts +31 -1
- package/payload/platform/services/claude-session-manager/dist/stuck-turn.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/stuck-turn.js +72 -9
- package/payload/platform/services/claude-session-manager/dist/stuck-turn.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts +1 -1
- package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/system-prompt.js +9 -1
- package/payload/platform/services/claude-session-manager/dist/system-prompt.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/types.d.ts +9 -3
- package/payload/platform/services/claude-session-manager/dist/types.d.ts.map +1 -1
- package/payload/platform/services/telegram-channel/dist/instructions.d.ts +0 -1
- package/payload/platform/services/telegram-channel/dist/instructions.d.ts.map +1 -1
- package/payload/platform/services/telegram-channel/dist/instructions.js +0 -46
- package/payload/platform/services/telegram-channel/dist/instructions.js.map +1 -1
- package/payload/platform/services/telegram-channel/dist/notification.d.ts +16 -4
- package/payload/platform/services/telegram-channel/dist/notification.d.ts.map +1 -1
- package/payload/platform/services/telegram-channel/dist/notification.js +27 -14
- package/payload/platform/services/telegram-channel/dist/notification.js.map +1 -1
- package/payload/platform/services/telegram-channel/dist/server.d.ts.map +1 -1
- package/payload/platform/services/telegram-channel/dist/server.js +10 -0
- package/payload/platform/services/telegram-channel/dist/server.js.map +1 -1
- package/payload/platform/services/webchat-channel/dist/instructions.d.ts +0 -1
- package/payload/platform/services/webchat-channel/dist/instructions.d.ts.map +1 -1
- package/payload/platform/services/webchat-channel/dist/instructions.js +0 -60
- package/payload/platform/services/webchat-channel/dist/instructions.js.map +1 -1
- package/payload/platform/services/webchat-channel/dist/notification.d.ts +14 -2
- package/payload/platform/services/webchat-channel/dist/notification.d.ts.map +1 -1
- package/payload/platform/services/webchat-channel/dist/notification.js +28 -12
- package/payload/platform/services/webchat-channel/dist/notification.js.map +1 -1
- package/payload/platform/services/webchat-channel/dist/server.d.ts.map +1 -1
- package/payload/platform/services/webchat-channel/dist/server.js +10 -0
- package/payload/platform/services/webchat-channel/dist/server.js.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/notification.d.ts +97 -33
- package/payload/platform/services/whatsapp-channel/dist/notification.d.ts.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/notification.js +98 -76
- package/payload/platform/services/whatsapp-channel/dist/notification.js.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/server.d.ts +18 -0
- package/payload/platform/services/whatsapp-channel/dist/server.d.ts.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/server.js +87 -5
- package/payload/platform/services/whatsapp-channel/dist/server.js.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/targets.d.ts +41 -9
- package/payload/platform/services/whatsapp-channel/dist/targets.d.ts.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/targets.js +42 -7
- package/payload/platform/services/whatsapp-channel/dist/targets.js.map +1 -1
- package/payload/platform/templates/agents/admin/INSTRUCTION.md +0 -0
- package/payload/server/{adminuser-self-heal-LC7HZAC6.js → adminuser-self-heal-ZHFNDKJK.js} +1 -1
- package/payload/server/{chunk-HZP7BKBF.js → chunk-CVUSUNXM.js} +128 -4
- package/payload/server/{chunk-CKTHAHL4.js → chunk-DU7GPDJJ.js} +4 -2
- package/payload/server/{chunk-PFF6I7KP.js → chunk-HYQNUVGO.js} +8 -1
- package/payload/server/{chunk-ERIM3EFB.js → chunk-X2RRMHVV.js} +1 -1
- package/payload/server/{manager-CM55K4J2.js → manager-TI2YJQVZ.js} +3 -3
- package/payload/server/maxy-edge.js +3 -3
- package/payload/server/public/activity.html +5 -5
- package/payload/server/public/agents.html +4 -4
- package/payload/server/public/assets/AdminLoginScreens-BGKtDqAk.js +1 -0
- package/payload/server/public/assets/AdminLoginScreens-BGKtDqAk.js.br +0 -0
- package/payload/server/public/assets/AdminLoginScreens-BGKtDqAk.js.gz +0 -0
- package/payload/server/public/assets/AdminShell-DnfgsAQl.js +2 -0
- package/payload/server/public/assets/AdminShell-DnfgsAQl.js.br +0 -0
- package/payload/server/public/assets/AdminShell-DnfgsAQl.js.gz +0 -0
- package/payload/server/public/assets/activity-ByJSut0Q.js +1 -0
- package/payload/server/public/assets/activity-ByJSut0Q.js.br +0 -0
- package/payload/server/public/assets/activity-ByJSut0Q.js.gz +0 -0
- package/payload/server/public/assets/admin-CkeJO6kA.js +1 -0
- package/payload/server/public/assets/admin-CkeJO6kA.js.br +0 -0
- package/payload/server/public/assets/admin-CkeJO6kA.js.gz +0 -0
- package/payload/server/public/assets/agents-D8phtRX5.js +1 -0
- package/payload/server/public/assets/agents-D8phtRX5.js.br +0 -0
- package/payload/server/public/assets/agents-D8phtRX5.js.gz +0 -0
- package/payload/server/public/assets/browser-DQSTjdom.js +1 -0
- package/payload/server/public/assets/browser-DQSTjdom.js.br +0 -0
- package/payload/server/public/assets/browser-DQSTjdom.js.gz +0 -0
- package/payload/server/public/assets/calendar-DFJu1XjP.js +1 -0
- package/payload/server/public/assets/calendar-DFJu1XjP.js.br +0 -0
- package/payload/server/public/assets/calendar-DFJu1XjP.js.gz +0 -0
- package/payload/server/public/assets/chat-DUqtIsOt.js +1 -0
- package/payload/server/public/assets/chat-DUqtIsOt.js.br +0 -0
- package/payload/server/public/assets/chat-DUqtIsOt.js.gz +0 -0
- package/payload/server/public/assets/chevron-left-DFK18xVX.js +1 -0
- package/payload/server/public/assets/chevron-left-DFK18xVX.js.br +0 -0
- package/payload/server/public/assets/chevron-right-DJ4oaHoN.js +1 -0
- package/payload/server/public/assets/chevron-right-DJ4oaHoN.js.br +0 -0
- package/payload/server/public/assets/clock-wHIan2DW.js +1 -0
- package/payload/server/public/assets/clock-wHIan2DW.js.br +0 -0
- package/payload/server/public/assets/{copy-3kj9Oaoc.js → copy-lFFhXRGk.js} +1 -1
- package/payload/server/public/assets/copy-lFFhXRGk.js.br +0 -0
- package/payload/server/public/assets/copy-lFFhXRGk.js.gz +0 -0
- package/payload/server/public/assets/data-Cxv97ARy.js +1 -0
- package/payload/server/public/assets/data-Cxv97ARy.js.br +0 -0
- package/payload/server/public/assets/data-Cxv97ARy.js.gz +0 -0
- package/payload/server/public/assets/{file-text-CBaewT76.js → file-text-D2Y-bkNy.js} +1 -1
- package/payload/server/public/assets/file-text-D2Y-bkNy.js.br +0 -0
- package/payload/server/public/assets/file-text-D2Y-bkNy.js.gz +0 -0
- package/payload/server/public/assets/{graph-B8-e2_Z-.js → graph-C-3yN6JD.js} +3 -3
- package/payload/server/public/assets/graph-C-3yN6JD.js.br +0 -0
- package/payload/server/public/assets/graph-C-3yN6JD.js.gz +0 -0
- package/payload/server/public/assets/{graph-labels-Bsc23eZU.js → graph-labels-DiaPLP27.js} +1 -1
- package/payload/server/public/assets/graph-labels-DiaPLP27.js.br +0 -0
- package/payload/server/public/assets/graph-labels-DiaPLP27.js.gz +0 -0
- package/payload/server/public/assets/operator-KuGPvSa9.js +1 -0
- package/payload/server/public/assets/operator-KuGPvSa9.js.br +0 -0
- package/payload/server/public/assets/operator-KuGPvSa9.js.gz +0 -0
- package/payload/server/public/assets/page-BhGeFXWA.js +1 -0
- package/payload/server/public/assets/page-BhGeFXWA.js.br +0 -0
- package/payload/server/public/assets/page-BhGeFXWA.js.gz +0 -0
- package/payload/server/public/assets/page-EnbVC-yM.js +32 -0
- package/payload/server/public/assets/page-EnbVC-yM.js.br +0 -0
- package/payload/server/public/assets/page-EnbVC-yM.js.gz +0 -0
- package/payload/server/public/assets/play-jZFZAG-t.js +1 -0
- package/payload/server/public/assets/play-jZFZAG-t.js.br +0 -0
- package/payload/server/public/assets/play-jZFZAG-t.js.gz +0 -0
- package/payload/server/public/assets/public-CdSgMNC7.js +1 -0
- package/payload/server/public/assets/public-CdSgMNC7.js.br +0 -0
- package/payload/server/public/assets/public-CdSgMNC7.js.gz +0 -0
- package/payload/server/public/assets/{rotate-ccw-FZW7c8p8.js → rotate-ccw-rTRuTqei.js} +1 -1
- package/payload/server/public/assets/rotate-ccw-rTRuTqei.js.br +0 -0
- package/payload/server/public/assets/rotate-ccw-rTRuTqei.js.gz +0 -0
- package/payload/server/public/assets/routines-DNRxNRSQ.js +2 -0
- package/payload/server/public/assets/routines-DNRxNRSQ.js.br +0 -0
- package/payload/server/public/assets/routines-DNRxNRSQ.js.gz +0 -0
- package/payload/server/public/assets/skills-DFWtZNkW.js +1 -0
- package/payload/server/public/assets/skills-DFWtZNkW.js.br +0 -0
- package/payload/server/public/assets/skills-DFWtZNkW.js.gz +0 -0
- package/payload/server/public/assets/tasks-B94AuKSy.js +3 -0
- package/payload/server/public/assets/tasks-B94AuKSy.js.br +0 -0
- package/payload/server/public/assets/tasks-B94AuKSy.js.gz +0 -0
- package/payload/server/public/assets/{triangle-alert-CR-jRJdI.js → triangle-alert-DtWUg6jR.js} +1 -1
- package/payload/server/public/assets/triangle-alert-DtWUg6jR.js.br +0 -0
- package/payload/server/public/assets/triangle-alert-DtWUg6jR.js.gz +0 -0
- package/payload/server/public/assets/useCopyFeedback-CjKYO-Qf.js +1 -0
- package/payload/server/public/assets/useCopyFeedback-CjKYO-Qf.js.br +0 -0
- package/payload/server/public/assets/useCopyFeedback-CjKYO-Qf.js.gz +0 -0
- package/payload/server/public/assets/useMediaQuery-BYIHo-xL.js +14 -0
- package/payload/server/public/assets/useMediaQuery-BYIHo-xL.js.br +0 -0
- package/payload/server/public/assets/useMediaQuery-BYIHo-xL.js.gz +0 -0
- package/payload/server/public/assets/useMediaQuery-DlOWP56H.css +1 -0
- package/payload/server/public/assets/useMediaQuery-DlOWP56H.css.br +0 -0
- package/payload/server/public/assets/useMediaQuery-DlOWP56H.css.gz +0 -0
- package/payload/server/public/assets/useVoiceRecorder-BKFAYuzz.js +2 -0
- package/payload/server/public/assets/useVoiceRecorder-BKFAYuzz.js.br +0 -0
- package/payload/server/public/assets/useVoiceRecorder-BKFAYuzz.js.gz +0 -0
- package/payload/server/public/assets/{wrench-CpCOYUBc.js → wrench-Ct4kf-uv.js} +1 -1
- package/payload/server/public/assets/wrench-Ct4kf-uv.js.br +0 -0
- package/payload/server/public/assets/wrench-Ct4kf-uv.js.gz +0 -0
- package/payload/server/public/browser.html +4 -4
- package/payload/server/public/calendar.html +8 -8
- package/payload/server/public/chat.html +13 -13
- package/payload/server/public/data.html +11 -11
- package/payload/server/public/graph.html +9 -9
- package/payload/server/public/index.html +14 -14
- package/payload/server/public/operator.html +14 -14
- package/payload/server/public/public.html +13 -13
- package/payload/server/public/routines.html +6 -6
- package/payload/server/public/skills.html +5 -5
- package/payload/server/public/tasks.html +6 -6
- package/payload/server/server.js +537 -263
- package/payload/server/{src-JN6PIAJN.js → src-MM64CYYZ.js} +1 -1
- package/payload/server/{userprofile-reconcile-QHVLY2AH.js → userprofile-reconcile-TL4JKBPG.js} +1 -1
- package/payload/server/public/assets/AdminLoginScreens-DuFCjbz2.js +0 -1
- package/payload/server/public/assets/AdminLoginScreens-DuFCjbz2.js.br +0 -0
- package/payload/server/public/assets/AdminLoginScreens-DuFCjbz2.js.gz +0 -0
- package/payload/server/public/assets/AdminShell-DJL5DzRX.js +0 -2
- package/payload/server/public/assets/AdminShell-DJL5DzRX.js.br +0 -0
- package/payload/server/public/assets/AdminShell-DJL5DzRX.js.gz +0 -0
- package/payload/server/public/assets/activity-CpMnNr5c.js +0 -1
- package/payload/server/public/assets/activity-CpMnNr5c.js.br +0 -0
- package/payload/server/public/assets/activity-CpMnNr5c.js.gz +0 -0
- package/payload/server/public/assets/admin-CBwKIfaI.js +0 -1
- package/payload/server/public/assets/admin-CBwKIfaI.js.br +0 -0
- package/payload/server/public/assets/admin-CBwKIfaI.js.gz +0 -0
- package/payload/server/public/assets/agents-C4LmSKjb.js +0 -1
- package/payload/server/public/assets/agents-C4LmSKjb.js.br +0 -0
- package/payload/server/public/assets/agents-C4LmSKjb.js.gz +0 -0
- package/payload/server/public/assets/browser-Bm9xm_yc.js +0 -1
- package/payload/server/public/assets/browser-Bm9xm_yc.js.br +0 -0
- package/payload/server/public/assets/browser-Bm9xm_yc.js.gz +0 -0
- package/payload/server/public/assets/calendar-CNY9FTWe.js +0 -1
- package/payload/server/public/assets/calendar-CNY9FTWe.js.br +0 -0
- package/payload/server/public/assets/calendar-CNY9FTWe.js.gz +0 -0
- package/payload/server/public/assets/chat-3WoUGCTd.js +0 -1
- package/payload/server/public/assets/chat-3WoUGCTd.js.br +0 -0
- package/payload/server/public/assets/chat-3WoUGCTd.js.gz +0 -0
- package/payload/server/public/assets/chevron-left-BE16BJnw.js +0 -1
- package/payload/server/public/assets/chevron-left-BE16BJnw.js.br +0 -0
- package/payload/server/public/assets/chevron-right-Bu2VKpeU.js +0 -1
- package/payload/server/public/assets/chevron-right-Bu2VKpeU.js.br +0 -0
- package/payload/server/public/assets/clock-C4Nu2aRV.js +0 -1
- package/payload/server/public/assets/clock-C4Nu2aRV.js.br +0 -0
- package/payload/server/public/assets/copy-3kj9Oaoc.js.br +0 -0
- package/payload/server/public/assets/copy-3kj9Oaoc.js.gz +0 -0
- package/payload/server/public/assets/data-C-x5EHyi.js +0 -1
- package/payload/server/public/assets/data-C-x5EHyi.js.br +0 -1
- package/payload/server/public/assets/data-C-x5EHyi.js.gz +0 -0
- package/payload/server/public/assets/file-text-CBaewT76.js.br +0 -0
- package/payload/server/public/assets/file-text-CBaewT76.js.gz +0 -0
- package/payload/server/public/assets/graph-B8-e2_Z-.js.br +0 -0
- package/payload/server/public/assets/graph-B8-e2_Z-.js.gz +0 -0
- package/payload/server/public/assets/graph-labels-Bsc23eZU.js.br +0 -0
- package/payload/server/public/assets/graph-labels-Bsc23eZU.js.gz +0 -0
- package/payload/server/public/assets/operator-Cve0-qfO.js +0 -1
- package/payload/server/public/assets/operator-Cve0-qfO.js.br +0 -0
- package/payload/server/public/assets/operator-Cve0-qfO.js.gz +0 -0
- package/payload/server/public/assets/page-BgVMs6Vf.js +0 -1
- package/payload/server/public/assets/page-BgVMs6Vf.js.br +0 -0
- package/payload/server/public/assets/page-BgVMs6Vf.js.gz +0 -0
- package/payload/server/public/assets/page-fABub-w8.js +0 -32
- package/payload/server/public/assets/page-fABub-w8.js.br +0 -0
- package/payload/server/public/assets/page-fABub-w8.js.gz +0 -0
- package/payload/server/public/assets/play-B6zXB9K7.js +0 -1
- package/payload/server/public/assets/play-B6zXB9K7.js.br +0 -0
- package/payload/server/public/assets/play-B6zXB9K7.js.gz +0 -0
- package/payload/server/public/assets/public--R2DbdWs.js +0 -1
- package/payload/server/public/assets/public--R2DbdWs.js.br +0 -0
- package/payload/server/public/assets/public--R2DbdWs.js.gz +0 -0
- package/payload/server/public/assets/rotate-ccw-FZW7c8p8.js.br +0 -0
- package/payload/server/public/assets/rotate-ccw-FZW7c8p8.js.gz +0 -0
- package/payload/server/public/assets/routines-BpZs2SaT.js +0 -2
- package/payload/server/public/assets/routines-BpZs2SaT.js.br +0 -0
- package/payload/server/public/assets/routines-BpZs2SaT.js.gz +0 -0
- package/payload/server/public/assets/skills-DF7uyEEz.js +0 -1
- package/payload/server/public/assets/skills-DF7uyEEz.js.br +0 -0
- package/payload/server/public/assets/skills-DF7uyEEz.js.gz +0 -0
- package/payload/server/public/assets/tasks-BfJJmoWO.js +0 -3
- package/payload/server/public/assets/tasks-BfJJmoWO.js.br +0 -0
- package/payload/server/public/assets/tasks-BfJJmoWO.js.gz +0 -0
- package/payload/server/public/assets/triangle-alert-CR-jRJdI.js.br +0 -0
- package/payload/server/public/assets/triangle-alert-CR-jRJdI.js.gz +0 -0
- package/payload/server/public/assets/useCopyFeedback-IOuPUAHY.js +0 -1
- package/payload/server/public/assets/useCopyFeedback-IOuPUAHY.js.br +0 -0
- package/payload/server/public/assets/useCopyFeedback-IOuPUAHY.js.gz +0 -0
- package/payload/server/public/assets/useMediaQuery-CA6dR5iz.js +0 -14
- package/payload/server/public/assets/useMediaQuery-CA6dR5iz.js.br +0 -0
- package/payload/server/public/assets/useMediaQuery-CA6dR5iz.js.gz +0 -0
- package/payload/server/public/assets/useMediaQuery-DpwgV1Da.css +0 -1
- package/payload/server/public/assets/useMediaQuery-DpwgV1Da.css.br +0 -0
- package/payload/server/public/assets/useMediaQuery-DpwgV1Da.css.gz +0 -0
- package/payload/server/public/assets/useVoiceRecorder-DGhsN7nV.js +0 -2
- package/payload/server/public/assets/useVoiceRecorder-DGhsN7nV.js.br +0 -0
- package/payload/server/public/assets/useVoiceRecorder-DGhsN7nV.js.gz +0 -0
- package/payload/server/public/assets/wrench-CpCOYUBc.js.br +0 -0
- package/payload/server/public/assets/wrench-CpCOYUBc.js.gz +0 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// Task 2342 — a public agent owns the `## Instruction` block of the turns it
|
|
2
|
+
// answers. install-defaults runs on upgrade, so this pass is what gives every
|
|
3
|
+
// agent created before the file existed a file of its own. Filesystem fixtures
|
|
4
|
+
// under a tmp dir; no installer side effects. Runs under `node --test dist/__tests__/*`.
|
|
5
|
+
import test from "node:test";
|
|
6
|
+
import assert from "node:assert/strict";
|
|
7
|
+
import { mkdtempSync, mkdirSync, writeFileSync, readFileSync, existsSync, rmSync, statSync, chmodSync } from "node:fs";
|
|
8
|
+
import { tmpdir } from "node:os";
|
|
9
|
+
import { join } from "node:path";
|
|
10
|
+
import { seedPublicInstructionFiles } from "../public-instruction-seed.js";
|
|
11
|
+
function makeAccount() {
|
|
12
|
+
const dir = mkdtempSync(join(tmpdir(), "pub-instr-2342-"));
|
|
13
|
+
mkdirSync(join(dir, "agents"), { recursive: true });
|
|
14
|
+
return dir;
|
|
15
|
+
}
|
|
16
|
+
function agent(accountDir, slug, files) {
|
|
17
|
+
const d = join(accountDir, "agents", slug);
|
|
18
|
+
mkdirSync(d, { recursive: true });
|
|
19
|
+
for (const [name, body] of Object.entries(files))
|
|
20
|
+
writeFileSync(join(d, name), body);
|
|
21
|
+
}
|
|
22
|
+
test("creates a zero-byte INSTRUCTION.md for an agent that has none", () => {
|
|
23
|
+
const acct = makeAccount();
|
|
24
|
+
try {
|
|
25
|
+
agent(acct, "beagle", { "config.json": "{}", "SOUL.md": "s" });
|
|
26
|
+
const out = seedPublicInstructionFiles(acct);
|
|
27
|
+
assert.deepEqual(out.map((r) => [r.slug, r.action, r.bytes]), [["beagle", "created", 0]]);
|
|
28
|
+
const p = join(acct, "agents", "beagle", "INSTRUCTION.md");
|
|
29
|
+
assert.equal(existsSync(p), true);
|
|
30
|
+
assert.equal(statSync(p).size, 0);
|
|
31
|
+
}
|
|
32
|
+
finally {
|
|
33
|
+
rmSync(acct, { recursive: true, force: true });
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
test("never overwrites an operator's file, and reports its size", () => {
|
|
37
|
+
const acct = makeAccount();
|
|
38
|
+
try {
|
|
39
|
+
agent(acct, "beagle", { "config.json": "{}", "INSTRUCTION.md": "Ask for the trip.\n" });
|
|
40
|
+
const out = seedPublicInstructionFiles(acct);
|
|
41
|
+
assert.deepEqual(out.map((r) => [r.slug, r.action]), [["beagle", "preserved"]]);
|
|
42
|
+
assert.equal(readFileSync(join(acct, "agents", "beagle", "INSTRUCTION.md"), "utf-8"), "Ask for the trip.\n");
|
|
43
|
+
assert.equal(out[0].bytes, 18);
|
|
44
|
+
}
|
|
45
|
+
finally {
|
|
46
|
+
rmSync(acct, { recursive: true, force: true });
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
// installDefaults seeds agents/admin/INSTRUCTION.md from its own template
|
|
50
|
+
// immediately before this pass runs; reaching it here would report a file this
|
|
51
|
+
// pass did not handle.
|
|
52
|
+
test("skips admin, and skips a directory with no config.json", () => {
|
|
53
|
+
const acct = makeAccount();
|
|
54
|
+
try {
|
|
55
|
+
agent(acct, "admin", { "config.json": "{}", "IDENTITY.md": "i" });
|
|
56
|
+
agent(acct, "public", { "IDENTITY.md": "i" });
|
|
57
|
+
const out = seedPublicInstructionFiles(acct);
|
|
58
|
+
assert.deepEqual(out, []);
|
|
59
|
+
assert.equal(existsSync(join(acct, "agents", "admin", "INSTRUCTION.md")), false);
|
|
60
|
+
assert.equal(existsSync(join(acct, "agents", "public", "INSTRUCTION.md")), false);
|
|
61
|
+
}
|
|
62
|
+
finally {
|
|
63
|
+
rmSync(acct, { recursive: true, force: true });
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
// writeInstallDefaults runs on every upgrade. One unwritable agent directory
|
|
67
|
+
// must not abort the install, and must not pass as done either.
|
|
68
|
+
test("reports write-failed instead of throwing when the agent dir is read-only", () => {
|
|
69
|
+
const acct = makeAccount();
|
|
70
|
+
try {
|
|
71
|
+
agent(acct, "beagle", { "config.json": "{}" });
|
|
72
|
+
agent(acct, "clerk", { "config.json": "{}" });
|
|
73
|
+
chmodSync(join(acct, "agents", "beagle"), 0o500);
|
|
74
|
+
const out = seedPublicInstructionFiles(acct).sort((a, b) => a.slug.localeCompare(b.slug));
|
|
75
|
+
assert.deepEqual(out.map((r) => [r.slug, r.action]), [["beagle", "write-failed"], ["clerk", "created"]]);
|
|
76
|
+
// The pass continued past the failure: the later agent still got its file.
|
|
77
|
+
assert.equal(existsSync(join(acct, "agents", "clerk", "INSTRUCTION.md")), true);
|
|
78
|
+
}
|
|
79
|
+
finally {
|
|
80
|
+
chmodSync(join(acct, "agents", "beagle"), 0o700);
|
|
81
|
+
rmSync(acct, { recursive: true, force: true });
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
test("handles several agents in one pass and returns [] for an account with no agents dir", () => {
|
|
85
|
+
const acct = makeAccount();
|
|
86
|
+
try {
|
|
87
|
+
agent(acct, "beagle", { "config.json": "{}" });
|
|
88
|
+
agent(acct, "clerk", { "config.json": "{}", "INSTRUCTION.md": "x" });
|
|
89
|
+
const out = seedPublicInstructionFiles(acct).sort((a, b) => a.slug.localeCompare(b.slug));
|
|
90
|
+
assert.deepEqual(out.map((r) => [r.slug, r.action]), [["beagle", "created"], ["clerk", "preserved"]]);
|
|
91
|
+
}
|
|
92
|
+
finally {
|
|
93
|
+
rmSync(acct, { recursive: true, force: true });
|
|
94
|
+
}
|
|
95
|
+
const bare = mkdtempSync(join(tmpdir(), "pub-instr-bare-"));
|
|
96
|
+
try {
|
|
97
|
+
assert.deepEqual(seedPublicInstructionFiles(bare), []);
|
|
98
|
+
}
|
|
99
|
+
finally {
|
|
100
|
+
rmSync(bare, { recursive: true, force: true });
|
|
101
|
+
}
|
|
102
|
+
});
|
package/dist/index.js
CHANGED
|
@@ -11,6 +11,7 @@ import { validateTierFlag, validateEntitlementBase64, applyTierToAccountConfig,
|
|
|
11
11
|
import { parseOsRelease, isUbuntuLike as isUbuntuLikePure, parseAptCacheCandidate, decideAptResolution, } from "./apt-resolve.js";
|
|
12
12
|
import { findPeerBrandOnDefaultNeo4jPort } from "./peer-brand-detect.js";
|
|
13
13
|
import { removeClientAdminsKey } from "./converge-client-admins.js";
|
|
14
|
+
import { seedPublicInstructionFiles } from "./public-instruction-seed.js";
|
|
14
15
|
import { backupHouseCloudflare, restoreHouseCloudflare, migrateHouseCredentialFromAccount, } from "./preserve-house-cloudflare.js";
|
|
15
16
|
import { resolveNeo4jPidfileScrub } from "./neo4j-pidfile-scrub.js";
|
|
16
17
|
import { runInitLogging } from "./init-logging.js";
|
|
@@ -2577,6 +2578,12 @@ function deployPayload() {
|
|
|
2577
2578
|
// User data lives at {installDir}/data/ — outside the platform/ wipe zone.
|
|
2578
2579
|
// Install path creates this fresh; runtime writers populate it on demand.
|
|
2579
2580
|
mkdirSync(join(INSTALL_DIR, "data"), { recursive: true });
|
|
2581
|
+
// Task 2323 — the install-wide shared folder: written by the house account,
|
|
2582
|
+
// read by every account. Created here rather than lazily by a writer so the
|
|
2583
|
+
// standing census reports exists=true from first boot, and so the pty-spawner's
|
|
2584
|
+
// existsSync-guarded --add-dir and write-deny are live on the first spawn.
|
|
2585
|
+
// Idempotent: an upgrade over an existing install leaves its contents alone.
|
|
2586
|
+
mkdirSync(join(INSTALL_DIR, "data", "shared"), { recursive: true });
|
|
2580
2587
|
// Task 848 — on upgrade the prior server/, platform/, premium-plugins/ trees are
|
|
2581
2588
|
// immutable (chattr +i). Clear all three BEFORE the wipe loop, or the rmSync of
|
|
2582
2589
|
// those dirs below fails with EPERM. Gate on INSTALL_DIR existence (any prior
|
|
@@ -3480,6 +3487,37 @@ function writeInstallDefaults(accountId) {
|
|
|
3480
3487
|
console.log(` [install-defaults] soul-md created path=${soulPath} bytes=${soulContent.length}`);
|
|
3481
3488
|
logFile(` [install-defaults] soul-md created path=${soulPath} bytes=${soulContent.length}`);
|
|
3482
3489
|
}
|
|
3490
|
+
// Admin INSTRUCTION.md is operator-controlled: it is the `## Instruction` body
|
|
3491
|
+
// every WhatsApp channel turn carries, so the operator owns what their agent
|
|
3492
|
+
// does with an inbound and can change it on disk without a publish. Create it
|
|
3493
|
+
// from the bundled template on a fresh install and never overwrite it, exactly
|
|
3494
|
+
// as SOUL.md above. install-defaults runs on upgrades too, which is what
|
|
3495
|
+
// backfills accounts provisioned before this file existed. There is no
|
|
3496
|
+
// code-level default downstream: an account with no such file has its channel
|
|
3497
|
+
// turns refused, so this seeding is what keeps an upgraded install working.
|
|
3498
|
+
//
|
|
3499
|
+
// Unlike the SOUL.md branch above, a missing template here logs and continues
|
|
3500
|
+
// rather than returning: returning would skip the public-agent seeding below.
|
|
3501
|
+
const instructionPath = join(accountDir, "agents/admin/INSTRUCTION.md");
|
|
3502
|
+
mkdirSync(dirname(instructionPath), { recursive: true });
|
|
3503
|
+
if (existsSync(instructionPath)) {
|
|
3504
|
+
const preservedBytes = statSync(instructionPath).size;
|
|
3505
|
+
console.log(` [install-defaults] instruction-md preserved path=${instructionPath} bytes=${preservedBytes}`);
|
|
3506
|
+
logFile(` [install-defaults] instruction-md preserved path=${instructionPath} bytes=${preservedBytes}`);
|
|
3507
|
+
}
|
|
3508
|
+
else {
|
|
3509
|
+
const instructionTemplate = join(INSTALL_DIR, "platform/templates/agents/admin/INSTRUCTION.md");
|
|
3510
|
+
try {
|
|
3511
|
+
const content = readFileSync(instructionTemplate, "utf-8").replace(/\$\{PRODUCT_NAME\}/g, BRAND.productName);
|
|
3512
|
+
writeFileSync(instructionPath, content);
|
|
3513
|
+
console.log(` [install-defaults] instruction-md created path=${instructionPath} bytes=${content.length}`);
|
|
3514
|
+
logFile(` [install-defaults] instruction-md created path=${instructionPath} bytes=${content.length}`);
|
|
3515
|
+
}
|
|
3516
|
+
catch (err) {
|
|
3517
|
+
console.error(` [install-defaults] admin-instruction template missing at ${instructionTemplate}: ${err.message}`);
|
|
3518
|
+
logFile(` [install-defaults] admin-instruction template missing: ${err.message}`);
|
|
3519
|
+
}
|
|
3520
|
+
}
|
|
3483
3521
|
// Public agent IDENTITY.md — the only template-seeded public file, always
|
|
3484
3522
|
// overwritten (Rubytech-controlled toolless directive). Per Task 618/623,
|
|
3485
3523
|
// each public agent's SOUL.md, KNOWLEDGE.md, and config.json are authored
|
|
@@ -3517,6 +3555,15 @@ function writeInstallDefaults(accountId) {
|
|
|
3517
3555
|
}
|
|
3518
3556
|
console.log(` [install-defaults] public-identity path=${publicIdentityDst}`);
|
|
3519
3557
|
logFile(` [install-defaults] public-identity path=${publicIdentityDst}`);
|
|
3558
|
+
// Task 2342 — each public agent's own INSTRUCTION.md, created empty and never
|
|
3559
|
+
// overwritten. install-defaults runs on upgrade, which is what backfills the
|
|
3560
|
+
// agents created before this file existed. Placed after the public-identity
|
|
3561
|
+
// block so the log reads in the same order the files are made.
|
|
3562
|
+
for (const seeded of seedPublicInstructionFiles(accountDir)) {
|
|
3563
|
+
const line = ` [install-defaults] public-instruction-md ${seeded.action} path=${seeded.path} bytes=${seeded.bytes}`;
|
|
3564
|
+
console.log(line);
|
|
3565
|
+
logFile(line);
|
|
3566
|
+
}
|
|
3520
3567
|
}
|
|
3521
3568
|
/**
|
|
3522
3569
|
* Commercial-mode entitlement delivery (Task 240). Writes the decoded payload
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// Task 2342 — every public agent owns the `## Instruction` block of the channel
|
|
2
|
+
// turns it answers, at agents/<slug>/INSTRUCTION.md. Before 2342 that block was
|
|
3
|
+
// read from agents/admin/INSTRUCTION.md whoever the turn woke, so a visitor's
|
|
4
|
+
// turn carried the operator's own operating doctrine.
|
|
5
|
+
//
|
|
6
|
+
// The file is created EMPTY. An empty file resolves 'absent' at the resolver and
|
|
7
|
+
// refuses the turn, which is the intended closed state for an agent whose
|
|
8
|
+
// per-turn behaviour nobody has written; seeding any text would make that text
|
|
9
|
+
// the instruction on every account that never edits it, which is the
|
|
10
|
+
// arrangement 2342 removes. It is never overwritten, so an operator's own file
|
|
11
|
+
// survives every upgrade.
|
|
12
|
+
//
|
|
13
|
+
// A public agent is a directory holding a config.json. `agents/public/` is the
|
|
14
|
+
// template holder installDefaults writes IDENTITY.md into and has no
|
|
15
|
+
// config.json, so it is skipped without needing to be named. `admin` is named
|
|
16
|
+
// because it does carry one on some installs, and installDefaults seeds its
|
|
17
|
+
// file from a template directly before calling this.
|
|
18
|
+
import { existsSync, readdirSync, statSync, writeFileSync } from "node:fs";
|
|
19
|
+
import { join } from "node:path";
|
|
20
|
+
export function seedPublicInstructionFiles(accountDir) {
|
|
21
|
+
const out = [];
|
|
22
|
+
const agentsDir = join(accountDir, "agents");
|
|
23
|
+
let entries = [];
|
|
24
|
+
try {
|
|
25
|
+
entries = readdirSync(agentsDir);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return out;
|
|
29
|
+
}
|
|
30
|
+
for (const slug of entries) {
|
|
31
|
+
if (slug.startsWith(".") || slug === "admin")
|
|
32
|
+
continue;
|
|
33
|
+
const dir = join(agentsDir, slug);
|
|
34
|
+
try {
|
|
35
|
+
if (!statSync(dir).isDirectory())
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
if (!existsSync(join(dir, "config.json")))
|
|
42
|
+
continue;
|
|
43
|
+
const path = join(dir, "INSTRUCTION.md");
|
|
44
|
+
if (existsSync(path)) {
|
|
45
|
+
let bytes = 0;
|
|
46
|
+
try {
|
|
47
|
+
bytes = statSync(path).size;
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
bytes = 0;
|
|
51
|
+
}
|
|
52
|
+
out.push({ slug, action: "preserved", path, bytes });
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
// Guarded like the two reads above, and for the same reason: this runs
|
|
56
|
+
// inside writeInstallDefaults on every upgrade, and one agent directory the
|
|
57
|
+
// installer cannot write must not abort the install part-way. The sibling
|
|
58
|
+
// admin-instruction block does the same. The failure is reported rather
|
|
59
|
+
// than skipped, so it reaches the install log instead of passing as done.
|
|
60
|
+
try {
|
|
61
|
+
writeFileSync(path, "");
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
out.push({ slug, action: "write-failed", path, bytes: 0 });
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
out.push({ slug, action: "created", path, bytes: 0 });
|
|
68
|
+
}
|
|
69
|
+
return out;
|
|
70
|
+
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/** The one literal. The shared root is `<dataRoot>/shared`, a sibling of
|
|
2
|
+
* `<dataRoot>/accounts`, so it is inside DATA_ROOT (which is what lets the
|
|
3
|
+
* /data browser reach it at all) but outside every account partition. */
|
|
4
|
+
export declare const SHARED_DIR_NAME = "shared";
|
|
5
|
+
/** Absolute path of the shared root. `dataRoot` is `<install>/data`. */
|
|
6
|
+
export declare function sharedRoot(dataRoot: string): string;
|
|
7
|
+
/**
|
|
8
|
+
* True when a DATA_ROOT-relative path is inside the shared root.
|
|
9
|
+
*
|
|
10
|
+
* FIRST SEGMENT ONLY. `accounts/<id>/shared` is an account's own directory that
|
|
11
|
+
* happens to be called `shared` and must keep account semantics; a deeper
|
|
12
|
+
* `shared` segment is likewise ordinary content. Callers pass the `relative`
|
|
13
|
+
* that `resolveDataPath` already produces, which is DATA_ROOT-relative.
|
|
14
|
+
*
|
|
15
|
+
* The filesystem plugin does NOT call this: its tool paths are account-relative,
|
|
16
|
+
* so it selects the shared root with an explicit `shared` flag instead.
|
|
17
|
+
*/
|
|
18
|
+
export declare function isSharedPath(relPath: string): boolean;
|
|
19
|
+
export type SharedWriteDecision = {
|
|
20
|
+
allow: true;
|
|
21
|
+
} | {
|
|
22
|
+
reject: "shared-folder-read-only";
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* The write decision. `isHouse` is INJECTED rather than resolved here so the
|
|
26
|
+
* decision stays pure and unit-testable without a filesystem — the same reason
|
|
27
|
+
* `resolveEffectiveAccountCore` takes an injected `isValidAccountId`.
|
|
28
|
+
*/
|
|
29
|
+
export declare function decideSharedWrite(isHouse: boolean): SharedWriteDecision;
|
|
30
|
+
/**
|
|
31
|
+
* Disk-backed house check for the two surfaces that have none: the `filesystem`
|
|
32
|
+
* plugin and the `/data` browser. Drift-safe, matching
|
|
33
|
+
* claude-session-manager/src/config.ts:464 — false when the census shows zero
|
|
34
|
+
* or more than one `role:"house"` account, because under drift there is no
|
|
35
|
+
* single house to grant write to.
|
|
36
|
+
*
|
|
37
|
+
* `platform/plugins/admin/mcp/src/tools/account-lifecycle.ts:85` is a SECOND,
|
|
38
|
+
* different definition (true for any role-house account). It is deliberately
|
|
39
|
+
* not consolidated here: it guards account deletion, where `true` means refuse,
|
|
40
|
+
* so giving it these drift semantics would make a drifted install start
|
|
41
|
+
* ALLOWING deletion of a house account. Consolidation is its own task.
|
|
42
|
+
*
|
|
43
|
+
* Never throws: an unreadable accounts dir or an unparseable account.json reads
|
|
44
|
+
* as "not house", which is the fail-closed answer for a write gate.
|
|
45
|
+
*/
|
|
46
|
+
export declare function isHouseAccountDir(accountsDir: string, accountId: string): boolean;
|
|
47
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA;;0EAE0E;AAC1E,eAAO,MAAM,eAAe,WAAW,CAAC;AAExC,wEAAwE;AACxE,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAGrD;AAED,MAAM,MAAM,mBAAmB,GAC3B;IAAE,KAAK,EAAE,IAAI,CAAA;CAAE,GACf;IAAE,MAAM,EAAE,yBAAyB,CAAA;CAAE,CAAC;AAE1C;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,mBAAmB,CAEvE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAuBjF"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SHARED_DIR_NAME = void 0;
|
|
4
|
+
exports.sharedRoot = sharedRoot;
|
|
5
|
+
exports.isSharedPath = isSharedPath;
|
|
6
|
+
exports.decideSharedWrite = decideSharedWrite;
|
|
7
|
+
exports.isHouseAccountDir = isHouseAccountDir;
|
|
8
|
+
// shared-folder — the single definition of the install-wide shared directory.
|
|
9
|
+
//
|
|
10
|
+
// Task 2323. Three surfaces gate on this module: the `filesystem` plugin, the
|
|
11
|
+
// `/data` admin browser, and the pty-spawner's native --add-dir + deny push.
|
|
12
|
+
// One definition, no drift — the same discipline as platform/lib/account-scope.
|
|
13
|
+
//
|
|
14
|
+
// The pure predicates never touch the filesystem, so this module is safe to
|
|
15
|
+
// import into an MCP server that boots with empty env during plugin-system
|
|
16
|
+
// `tools/list` enumeration. `isHouseAccountDir` DOES read disk, but only when
|
|
17
|
+
// called — nothing runs at module load.
|
|
18
|
+
const node_fs_1 = require("node:fs");
|
|
19
|
+
const node_path_1 = require("node:path");
|
|
20
|
+
/** The one literal. The shared root is `<dataRoot>/shared`, a sibling of
|
|
21
|
+
* `<dataRoot>/accounts`, so it is inside DATA_ROOT (which is what lets the
|
|
22
|
+
* /data browser reach it at all) but outside every account partition. */
|
|
23
|
+
exports.SHARED_DIR_NAME = "shared";
|
|
24
|
+
/** Absolute path of the shared root. `dataRoot` is `<install>/data`. */
|
|
25
|
+
function sharedRoot(dataRoot) {
|
|
26
|
+
return (0, node_path_1.resolve)(dataRoot, exports.SHARED_DIR_NAME);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* True when a DATA_ROOT-relative path is inside the shared root.
|
|
30
|
+
*
|
|
31
|
+
* FIRST SEGMENT ONLY. `accounts/<id>/shared` is an account's own directory that
|
|
32
|
+
* happens to be called `shared` and must keep account semantics; a deeper
|
|
33
|
+
* `shared` segment is likewise ordinary content. Callers pass the `relative`
|
|
34
|
+
* that `resolveDataPath` already produces, which is DATA_ROOT-relative.
|
|
35
|
+
*
|
|
36
|
+
* The filesystem plugin does NOT call this: its tool paths are account-relative,
|
|
37
|
+
* so it selects the shared root with an explicit `shared` flag instead.
|
|
38
|
+
*/
|
|
39
|
+
function isSharedPath(relPath) {
|
|
40
|
+
const segs = relPath.split("/").filter(Boolean);
|
|
41
|
+
return segs.length >= 1 && segs[0] === exports.SHARED_DIR_NAME;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The write decision. `isHouse` is INJECTED rather than resolved here so the
|
|
45
|
+
* decision stays pure and unit-testable without a filesystem — the same reason
|
|
46
|
+
* `resolveEffectiveAccountCore` takes an injected `isValidAccountId`.
|
|
47
|
+
*/
|
|
48
|
+
function decideSharedWrite(isHouse) {
|
|
49
|
+
return isHouse ? { allow: true } : { reject: "shared-folder-read-only" };
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Disk-backed house check for the two surfaces that have none: the `filesystem`
|
|
53
|
+
* plugin and the `/data` browser. Drift-safe, matching
|
|
54
|
+
* claude-session-manager/src/config.ts:464 — false when the census shows zero
|
|
55
|
+
* or more than one `role:"house"` account, because under drift there is no
|
|
56
|
+
* single house to grant write to.
|
|
57
|
+
*
|
|
58
|
+
* `platform/plugins/admin/mcp/src/tools/account-lifecycle.ts:85` is a SECOND,
|
|
59
|
+
* different definition (true for any role-house account). It is deliberately
|
|
60
|
+
* not consolidated here: it guards account deletion, where `true` means refuse,
|
|
61
|
+
* so giving it these drift semantics would make a drifted install start
|
|
62
|
+
* ALLOWING deletion of a house account. Consolidation is its own task.
|
|
63
|
+
*
|
|
64
|
+
* Never throws: an unreadable accounts dir or an unparseable account.json reads
|
|
65
|
+
* as "not house", which is the fail-closed answer for a write gate.
|
|
66
|
+
*/
|
|
67
|
+
function isHouseAccountDir(accountsDir, accountId) {
|
|
68
|
+
let entries;
|
|
69
|
+
try {
|
|
70
|
+
entries = (0, node_fs_1.readdirSync)(accountsDir, { withFileTypes: true })
|
|
71
|
+
.filter((d) => d.isDirectory())
|
|
72
|
+
.map((d) => d.name);
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
const houses = [];
|
|
78
|
+
for (const name of entries) {
|
|
79
|
+
let cfg;
|
|
80
|
+
try {
|
|
81
|
+
cfg = JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.join)(accountsDir, name, "account.json"), "utf-8"));
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
if (cfg.role === "house")
|
|
87
|
+
houses.push(name);
|
|
88
|
+
}
|
|
89
|
+
if (houses.length !== 1)
|
|
90
|
+
return false;
|
|
91
|
+
return houses[0] === accountId;
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAmBA,gCAEC;AAaD,oCAGC;AAWD,8CAEC;AAkBD,8CAuBC;AA3FD,8EAA8E;AAC9E,EAAE;AACF,8EAA8E;AAC9E,6EAA6E;AAC7E,gFAAgF;AAChF,EAAE;AACF,4EAA4E;AAC5E,2EAA2E;AAC3E,8EAA8E;AAC9E,wCAAwC;AACxC,qCAAoD;AACpD,yCAA0C;AAE1C;;0EAE0E;AAC7D,QAAA,eAAe,GAAG,QAAQ,CAAC;AAExC,wEAAwE;AACxE,SAAgB,UAAU,CAAC,QAAgB;IACzC,OAAO,IAAA,mBAAO,EAAC,QAAQ,EAAE,uBAAe,CAAC,CAAC;AAC5C,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAgB,YAAY,CAAC,OAAe;IAC1C,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAChD,OAAO,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,uBAAe,CAAC;AACzD,CAAC;AAMD;;;;GAIG;AACH,SAAgB,iBAAiB,CAAC,OAAgB;IAChD,OAAO,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,yBAAyB,EAAE,CAAC;AAC3E,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,SAAgB,iBAAiB,CAAC,WAAmB,EAAE,SAAiB;IACtE,IAAI,OAAiB,CAAC;IACtB,IAAI,CAAC;QACH,OAAO,GAAG,IAAA,qBAAW,EAAC,WAAW,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;aACxD,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;aAC9B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC3B,IAAI,GAAuB,CAAC;QAC5B,IAAI,CAAC;YACH,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAA,sBAAY,EAAC,IAAA,gBAAI,EAAC,WAAW,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CAE9E,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO;YAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9C,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACtC,OAAO,MAAM,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC;AACjC,CAAC"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// shared-folder — the single definition of the install-wide shared directory.
|
|
2
|
+
//
|
|
3
|
+
// Task 2323. Three surfaces gate on this module: the `filesystem` plugin, the
|
|
4
|
+
// `/data` admin browser, and the pty-spawner's native --add-dir + deny push.
|
|
5
|
+
// One definition, no drift — the same discipline as platform/lib/account-scope.
|
|
6
|
+
//
|
|
7
|
+
// The pure predicates never touch the filesystem, so this module is safe to
|
|
8
|
+
// import into an MCP server that boots with empty env during plugin-system
|
|
9
|
+
// `tools/list` enumeration. `isHouseAccountDir` DOES read disk, but only when
|
|
10
|
+
// called — nothing runs at module load.
|
|
11
|
+
import { readFileSync, readdirSync } from "node:fs";
|
|
12
|
+
import { join, resolve } from "node:path";
|
|
13
|
+
|
|
14
|
+
/** The one literal. The shared root is `<dataRoot>/shared`, a sibling of
|
|
15
|
+
* `<dataRoot>/accounts`, so it is inside DATA_ROOT (which is what lets the
|
|
16
|
+
* /data browser reach it at all) but outside every account partition. */
|
|
17
|
+
export const SHARED_DIR_NAME = "shared";
|
|
18
|
+
|
|
19
|
+
/** Absolute path of the shared root. `dataRoot` is `<install>/data`. */
|
|
20
|
+
export function sharedRoot(dataRoot: string): string {
|
|
21
|
+
return resolve(dataRoot, SHARED_DIR_NAME);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* True when a DATA_ROOT-relative path is inside the shared root.
|
|
26
|
+
*
|
|
27
|
+
* FIRST SEGMENT ONLY. `accounts/<id>/shared` is an account's own directory that
|
|
28
|
+
* happens to be called `shared` and must keep account semantics; a deeper
|
|
29
|
+
* `shared` segment is likewise ordinary content. Callers pass the `relative`
|
|
30
|
+
* that `resolveDataPath` already produces, which is DATA_ROOT-relative.
|
|
31
|
+
*
|
|
32
|
+
* The filesystem plugin does NOT call this: its tool paths are account-relative,
|
|
33
|
+
* so it selects the shared root with an explicit `shared` flag instead.
|
|
34
|
+
*/
|
|
35
|
+
export function isSharedPath(relPath: string): boolean {
|
|
36
|
+
const segs = relPath.split("/").filter(Boolean);
|
|
37
|
+
return segs.length >= 1 && segs[0] === SHARED_DIR_NAME;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export type SharedWriteDecision =
|
|
41
|
+
| { allow: true }
|
|
42
|
+
| { reject: "shared-folder-read-only" };
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* The write decision. `isHouse` is INJECTED rather than resolved here so the
|
|
46
|
+
* decision stays pure and unit-testable without a filesystem — the same reason
|
|
47
|
+
* `resolveEffectiveAccountCore` takes an injected `isValidAccountId`.
|
|
48
|
+
*/
|
|
49
|
+
export function decideSharedWrite(isHouse: boolean): SharedWriteDecision {
|
|
50
|
+
return isHouse ? { allow: true } : { reject: "shared-folder-read-only" };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Disk-backed house check for the two surfaces that have none: the `filesystem`
|
|
55
|
+
* plugin and the `/data` browser. Drift-safe, matching
|
|
56
|
+
* claude-session-manager/src/config.ts:464 — false when the census shows zero
|
|
57
|
+
* or more than one `role:"house"` account, because under drift there is no
|
|
58
|
+
* single house to grant write to.
|
|
59
|
+
*
|
|
60
|
+
* `platform/plugins/admin/mcp/src/tools/account-lifecycle.ts:85` is a SECOND,
|
|
61
|
+
* different definition (true for any role-house account). It is deliberately
|
|
62
|
+
* not consolidated here: it guards account deletion, where `true` means refuse,
|
|
63
|
+
* so giving it these drift semantics would make a drifted install start
|
|
64
|
+
* ALLOWING deletion of a house account. Consolidation is its own task.
|
|
65
|
+
*
|
|
66
|
+
* Never throws: an unreadable accounts dir or an unparseable account.json reads
|
|
67
|
+
* as "not house", which is the fail-closed answer for a write gate.
|
|
68
|
+
*/
|
|
69
|
+
export function isHouseAccountDir(accountsDir: string, accountId: string): boolean {
|
|
70
|
+
let entries: string[];
|
|
71
|
+
try {
|
|
72
|
+
entries = readdirSync(accountsDir, { withFileTypes: true })
|
|
73
|
+
.filter((d) => d.isDirectory())
|
|
74
|
+
.map((d) => d.name);
|
|
75
|
+
} catch {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
const houses: string[] = [];
|
|
79
|
+
for (const name of entries) {
|
|
80
|
+
let cfg: { role?: unknown };
|
|
81
|
+
try {
|
|
82
|
+
cfg = JSON.parse(readFileSync(join(accountsDir, name, "account.json"), "utf-8")) as {
|
|
83
|
+
role?: unknown;
|
|
84
|
+
};
|
|
85
|
+
} catch {
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (cfg.role === "house") houses.push(name);
|
|
89
|
+
}
|
|
90
|
+
if (houses.length !== 1) return false;
|
|
91
|
+
return houses[0] === accountId;
|
|
92
|
+
}
|
|
@@ -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/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",
|
|
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/shared-folder/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/shared-folder/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/shared-folder/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",
|
|
@@ -256,6 +256,7 @@ Tools are available via the `admin` MCP server.
|
|
|
256
256
|
| Compose a business document | User asks to write or draft a proposal, report (market / analysis / strategic), brief, memo, white paper, plan (non-fundraise), or case study | `skills/professional-document/SKILL.md` |
|
|
257
257
|
| Manage admin users | User asks to add, remove, or list admins on this account, or change an admin PIN | `skills/admin-user-management/SKILL.md` |
|
|
258
258
|
| Session reset / continue / resume | User asks to clear the session, start fresh, continue the last session, or pick up where they left off | `skills/session-management/SKILL.md` |
|
|
259
|
+
| Set up channel message handling | Owner asks to set up or change what the agent does with incoming channel messages, asks why an incoming message got no answer, or reports the agent replying to someone it should not have | `skills/channel-instruction/SKILL.md` |
|
|
259
260
|
| Show or download a file | User asks to view, attach, or download a file or document, or the current turn produces a document the owner needs to review | `skills/file-presentation/SKILL.md` |
|
|
260
261
|
| Upgrade Maxy | User asks to upgrade, update, install the latest version, or accepts an upgrade offer | `skills/upgrade/SKILL.md` |
|
|
261
262
|
| Run a structured sprint without `gstack` | User asks to run a sprint, execute a `.tasks/NNN-*.md`, or invokes "superpowers sprint" / "sprint without gstack" | `skills/superpowers-sprint/SKILL.md` |
|
|
@@ -273,6 +274,7 @@ Tools are available via the `admin` MCP server.
|
|
|
273
274
|
- `hooks/webfetch-preflight.mjs` — short-circuits WebFetch on JS-SPA shells with a structured `WEBFETCH_CANNOT_READ_JS_SPA` error so the agent surfaces a loud failure to the owner instead of paying the 60s extraction timeout. Fail-open on any internal error.
|
|
274
275
|
- `hooks/askuserquestion-investigate-gate.sh` — PreToolUse matcher=`AskUserQuestion`. Blocks the question (exit 2) when no read-only investigation tool has fired since the latest real user turn in the session JSONL. The structural fix for the failure class where the agent fabricates a menu before evidence-gathering (session `c085ec2c-46fb-4b73-8865-68cf85866ea8` 2026-05-22 — "change remote access password" → invented options "Admin PIN / Cloudflare tunnel / WiFi password" with zero prior tool_use; post-correction the agent immediately fired `remote-auth-status` → `ToolSearch` → `remote-auth-set-password`, proving it knew the moves). **Allowlist** (exact, with trailing `__<tool>` suffix-match for namespaced `mcp__plugin_<plugin>_<server>__<tool>` aliases): `ToolSearch`, `Grep`, `Glob`, `Read`, `LS`, `NotebookRead`, `Bash`, `WebFetch`, `WebSearch`, plus the read-only admin / memory MCP tools (`*-status`, `*-list`, `*-read`, `skill-find`, `memory-find-candidates`, `profile-read`, `conversation-list`, `memory-list-attachments`, `memory-read-attachment`). **Block message:** `Blocked: AskUserQuestion requires at least one investigation tool (ToolSearch, Grep, Read, *-list, *-status, *-read, skill-find, ...) earlier in this turn. Search the operator's literal phrase first.` **Log line** (stderr, one per call): `[ask-gate] decision=<allow|block> sessionId=<id8> seen=<csv|-> reason=<allowlist-hit|no-investigation|fail-open-no-transcript|fail-open-parse-error>`. **Fail-open** on missing transcript or parse error — nudges, never bricks the UI.
|
|
275
276
|
- `hooks/askuserquestion-channel-carrier-gate.sh` — PreToolUse matcher=`AskUserQuestion`, registered as a **second command on the same matcher** as the investigate-gate (either exit 2 blocks; the two guard different conditions). Blocks the question (exit 2) when the session has a native channel attached, because the Claude Code channel protocol carries only the two permission methods — there is no carrier for the `AskUserQuestion` elicitation, so on an rc-spawn channel (webchat/WhatsApp/Telegram) session the harness would block the turn awaiting a selection that can never arrive and the reader renders only delivered replies, wedging the turn (live SiteDesk incident session `1a085718` 2026-07-11: `/chat` stalled on the delivered "On it…" ack with no card). **Signal:** the rc-spawn writes the channel MCP registration as a config file in `os.tmpdir()` keyed by session id (`maxy-channel-<sid>.json` / `maxy-webchat-channel-<sid>.json` / `maxy-wa-channel-<sid>.json` / `maxy-telegram-channel-<sid>.json`, `sid` sanitized `[^A-Za-z0-9_-]→_` exactly as the writers do); its presence at tool-call time is the authoritative "channel attached to this session" marker. The hook resolves the tmpdir the way Node's `os.tmpdir()` does (`${TMPDIR:-/tmp}`, trailing slash stripped). Correct in both readings of the claude.ai/code scoping question: a Pi channel process sees the tmpfile (block); a claude.ai/code process on another host never sees the Pi tmpfile (fail-open → allow, that surface can answer the card). **Block message:** `Blocked: this is a native-channel session and AskUserQuestion cannot be delivered over a channel (the channel protocol carries no elicitation card, so the turn would wedge). Ask the same question as prose in your channel reply tool and wait for the operator's next message.` **Log line** (stderr, one per decisive call): `[ask-channel] decision=<allow|block> sessionId=<id8> channel=<attached|none> reason=<channel-attached|no-channel|fail-open-no-envelope|fail-open-no-session>`. **Fail-open** on no envelope, blank session id, or absent channel file — nudges, never bricks the UI. The complementary standing check (`interactive-wedge` in the session manager) catches any un-carried interactive tool_use that slips past this hook; it scans every account's project-slug (not just the boot slug), so a client sub-account channel wedge is covered too. **Reach on upgrade:** `provision-account-dir.sh` writes this matcher only at account-provision time, and the upgrade path re-provisions only the house account — so an account provisioned before this gate landed keeps a stale matcher and re-wedges (live SiteDesk recurrence session `d39a22b0`, account `2078cb54`, 2026-07-15). `setup-account.sh` runs `reconcile_all_accounts_askgate` (`platform/scripts/lib/account-settings-askgate.sh`) on every install to retrofit the carrier gate onto every existing account's `settings.json` — idempotent surgical jq patch of the `AskUserQuestion` matcher, one `[backfill-1683] file=<f> status=<absent|no-hooks|already-set|updated|rewrite-failed>` line per account, contents never echoed.
|
|
277
|
+
- `hooks/public-tool-surface.sh` — **PreToolUse matcher-less (every tool) + UserPromptSubmit + Stop.** Records the tool surface a `role='public'` spawn REALISES, which nothing recorded before: `tool-allowlist` records the surface a spawn was given, and `[public-surface] op=audit` reconciles MCP server names from spawn-tee filenames, so it is blind to `Read`, `Bash`, `Skill` and `ToolSearch` (no MCP child, no tee file). On 2026-08-01 five such tools ran in a session spawned with `--allowed-tools mcp__whatsapp-channel__reply --strict-mcp-config --permission-mode dontAsk` and produced no line. **Input:** `MAXY_PUBLIC_ALLOWED_TOOLS`, stamped by both spawn paths (`http-server.ts` rc-spawn, `pty-spawner.ts`) for `role='public'` only, carrying that spawn's final `--allowed-tools` argv set comma-joined. Absent means not a public spawn: the hook exits 0 in silence. **Log lines** (server.log only — a visitor's PTY gains no output): `[public-surface] op=tool-realised sessionId=<id8> tool=<name> allowed=<y|n>` per call, `allowed` being exact membership of the stamped set; `[public-surface] op=realised-census sessionId=<id8> calls=<n> disallowed=<n>` at Stop, emitted including zero so a session with no disallowed call is distinguishable from one the hook never saw. Per-call tallies are appends to `<logdir>/public-surface/<sanitised-session-id>`, removed by the census, so no counter mutex is needed. The `UserPromptSubmit` registration is the turn-start reset and emits nothing: the stuck-turn recycler kills a wedged PTY and resumes the SAME session id, so that turn's `Stop` never fires and its tally would otherwise be counted into the next turn's census (measured: three calls in a killed turn plus one call in the next reported `calls=4 disallowed=3`). **Never blocks:** exit 0 on every path, including unparseable stdin, absent `session_id`, missing `python3` and an unwritable log. **Reach on upgrade:** `provision-account-dir.sh` writes both entries only at account-provision time, so `setup-account.sh` runs `reconcile_all_accounts_public_surface` (`platform/scripts/lib/account-settings-public-surface.sh`) on every install to retrofit them onto every existing account, one `[backfill-2339] file=<f> status=<absent|no-hooks|already-set|updated|rewrite-failed>` line per account, contents never echoed.
|
|
276
278
|
- `hooks/mcp-tool-missing.sh` — **PostToolUse hook on `mcp__.*` (directive 3).** Defence-in-depth for the `No such tool available: mcp__…` failure class that the name-binding is built to eliminate. Fires on any MCP tool call; no-op unless the `tool_response` carries `No such tool available` AND the qualified name resolves to a maxy plugin (read from the generated `hooks/lib/maxy-mcp-plugins.txt`). On a maxy match it logs one deterministic `[mcp-tool-missing] server=<server> tool=<tool>` line and exits 2 with a fixed envelope on stderr, so the agent relays a named server-unavailable failure instead of narrating "warming up" or blind-retrying. A missing non-maxy bridge tool (Playwright etc., upstream-owned) passes through (exit 0). The maxy-plugin list is regenerated and gate-diffed by `platform/scripts/check-canonical-tool-names.mjs`.
|
|
277
279
|
- `hooks/post-tool-use-agent.sh` — **PostToolUse hook on `Agent`.** Drains any subagent hook-decision buffers under `~/.maxy-code/logs/hook-decisions/` modified since this parent's previous PostToolUse-Agent fire (cursor file keyed by parent session id), prints one `[hook-propagate]` line per record to stdout — Claude Code attaches the stdout as a `hook_success` attachment on the parent JSONL, making the records grep-queryable from the parent session alone. Rotates consumed buffers to `consumed/`. Emits one `[hook-propagate-census] parentSession=<…> subagentHooksObserved=<N> attachmentsEmitted=<M>` line per fire to stdout and server.log; `N != M` is the propagation regression signal. The companion emitter library `hooks/lib/hook-emit.sh` is sourced by `post-tool-use-agent.sh` and any other hook that records a block decision (4 KB stderr truncation, `truncated=true` set on the record).
|
|
278
280
|
- `hooks/admin-authoring-observer.sh` — **PostToolUse hook on Write and Edit.** Observation only — never blocks; exits 0 on every path. Fires when the admin agent (not a specialist subagent — gated by `MAXY_SPECIALIST` env) writes or edits a file under `<accountDir>/output/`. Walks the session transcript from the latest real-user turn forward to detect any prior `Task` `tool_use` whose `subagent_type` starts with `specialists:`. Emits one stderr line `[admin-authoring] inline-write path=<rel> priorSpecialistSpawnInTurn=<true|false|unknown>`. A `false` value on a long-form prose file is the regression signal this hook was designed to make visible — the BioSymm proposal session (admin authored a customer-facing proposal inline despite content-producer being installed) is the failure mode this surfaces mechanically. Mechanical enforcement (refuse the write, force a re-spawn) is deferred per the task spec.
|