@rubytech/create-maxy-code 0.1.581 → 0.1.583
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/package.json +1 -1
- package/payload/platform/lib/routine-templates/dist/index.d.ts +1 -1
- package/payload/platform/lib/routine-templates/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/routine-templates/dist/index.js +5 -1
- package/payload/platform/lib/routine-templates/dist/index.js.map +1 -1
- package/payload/platform/lib/routine-templates/src/index.ts +4 -0
- package/payload/platform/lib/telegram-managed-bot/dist/index.d.ts +269 -0
- package/payload/platform/lib/telegram-managed-bot/dist/index.d.ts.map +1 -0
- package/payload/platform/lib/telegram-managed-bot/dist/index.js +351 -0
- package/payload/platform/lib/telegram-managed-bot/dist/index.js.map +1 -0
- package/payload/platform/lib/telegram-managed-bot/src/__tests__/managed-bot.test.ts +251 -0
- package/payload/platform/lib/telegram-managed-bot/src/index.ts +529 -0
- package/payload/platform/lib/telegram-managed-bot/tsconfig.json +9 -0
- package/payload/platform/lib/telegram-managed-bot/vitest.config.ts +9 -0
- package/payload/platform/lib/telegram-reach/dist/index.d.ts +80 -0
- package/payload/platform/lib/telegram-reach/dist/index.d.ts.map +1 -0
- package/payload/platform/lib/telegram-reach/dist/index.js +211 -0
- package/payload/platform/lib/telegram-reach/dist/index.js.map +1 -0
- package/payload/platform/lib/telegram-reach/src/__tests__/telegram-reach.test.ts +216 -0
- package/payload/platform/lib/telegram-reach/src/index.ts +262 -0
- package/payload/platform/lib/telegram-reach/tsconfig.json +9 -0
- package/payload/platform/lib/telegram-reach/vitest.config.ts +9 -0
- package/payload/platform/package.json +2 -2
- package/payload/platform/plugins/admin/PLUGIN.md +1 -1
- package/payload/platform/plugins/admin/hooks/__tests__/fs-schema-guard.test.sh +9 -0
- package/payload/platform/plugins/admin/hooks/__tests__/preference-consult-directive.test.sh +26 -0
- package/payload/platform/plugins/admin/hooks/fs-schema-guard.sh +20 -3
- package/payload/platform/plugins/admin/hooks/preference-consult-directive.sh +50 -5
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +181 -9
- package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +17 -0
- package/payload/platform/plugins/contacts/mcp/dist/__tests__/telegram-user-id.test.d.ts +2 -0
- package/payload/platform/plugins/contacts/mcp/dist/__tests__/telegram-user-id.test.d.ts.map +1 -0
- package/payload/platform/plugins/contacts/mcp/dist/__tests__/telegram-user-id.test.js +100 -0
- package/payload/platform/plugins/contacts/mcp/dist/__tests__/telegram-user-id.test.js.map +1 -0
- package/payload/platform/plugins/contacts/mcp/dist/index.js +11 -5
- package/payload/platform/plugins/contacts/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.d.ts +5 -0
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.d.ts.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.js +21 -4
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.js.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.d.ts +5 -0
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.d.ts.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.js +29 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.js.map +1 -1
- package/payload/platform/plugins/contacts/mcp/vitest.config.ts +14 -0
- package/payload/platform/plugins/docs/references/admin-ui.md +20 -4
- package/payload/platform/plugins/docs/references/calendar-booking.md +2 -0
- package/payload/platform/plugins/docs/references/channel-wake-and-prompt.md +15 -0
- package/payload/platform/plugins/docs/references/telegram-guide.md +143 -4
- package/payload/platform/plugins/filesystem/PLUGIN.md +2 -2
- package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/account-schema.test.d.ts +2 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/account-schema.test.d.ts.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/account-schema.test.js +108 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/account-schema.test.js.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/account-schema.d.ts +17 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/account-schema.d.ts.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/account-schema.js +162 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/account-schema.js.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/__tests__/schema-fence.test.d.ts +2 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/__tests__/schema-fence.test.d.ts.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/__tests__/schema-fence.test.js +116 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/__tests__/schema-fence.test.js.map +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 +9 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-edit.js.map +1 -1
- 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 +10 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-write.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/label-origin-gate.test.js +64 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/label-origin-gate.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/label-origin-gate.d.ts +5 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/label-origin-gate.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/label-origin-gate.js +28 -6
- package/payload/platform/plugins/memory/mcp/dist/lib/label-origin-gate.js.map +1 -1
- package/payload/platform/plugins/memory/references/schema-knowledge-work.md +1 -1
- package/payload/platform/plugins/scheduling/PLUGIN.md +19 -3
- package/payload/platform/plugins/scheduling/mcp/dist/index.js +7 -2
- package/payload/platform/plugins/scheduling/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate-audits.test.js +53 -6
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate-audits.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate.test.js +38 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/meeting-uid-stamp.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/meeting-uid-stamp.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/meeting-uid-stamp.test.js +102 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/meeting-uid-stamp.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/schedule-audit.test.js +43 -9
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/schedule-audit.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/booking-reconcile.d.ts +50 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/booking-reconcile.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/booking-reconcile.js +47 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/booking-reconcile.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/gate.d.ts +5 -3
- package/payload/platform/plugins/scheduling/mcp/dist/lib/gate.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/gate.js +18 -3
- package/payload/platform/plugins/scheduling/mcp/dist/lib/gate.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/schedule-audit.d.ts +40 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/schedule-audit.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/schedule-audit.js +132 -41
- package/payload/platform/plugins/scheduling/mcp/dist/lib/schedule-audit.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js +14 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js +61 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-gate-write.test.js +258 -8
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-gate-write.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-trash-filter.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-trash-filter.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-trash-filter.test.js +67 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-trash-filter.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/scheduling-gate.test.js +206 -3
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/scheduling-gate.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-cancel.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-cancel.js +8 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-cancel.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.d.ts +29 -21
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js +94 -14
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-get.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-get.js +6 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-get.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-list.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-list.js +7 -2
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-list.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.js +46 -3
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/scheduling-gate.d.ts +30 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/scheduling-gate.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/scheduling-gate.js +69 -6
- package/payload/platform/plugins/scheduling/mcp/dist/tools/scheduling-gate.js.map +1 -1
- package/payload/platform/plugins/telegram/PLUGIN.md +49 -1
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/api-census.test.js +3 -3
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/api-guard.test.js +28 -2
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/api-guard.test.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/ask-business-connection.test.d.ts +2 -0
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/ask-business-connection.test.d.ts.map +1 -0
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/ask-business-connection.test.js +140 -0
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/ask-business-connection.test.js.map +1 -0
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/ask-tool.test.js +93 -5
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/ask-tool.test.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/bot-provision-tool.test.d.ts +2 -0
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/bot-provision-tool.test.d.ts.map +1 -0
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/bot-provision-tool.test.js +326 -0
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/bot-provision-tool.test.js.map +1 -0
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/card-business.test.d.ts +2 -0
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/card-business.test.d.ts.map +1 -0
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/card-business.test.js +173 -0
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/card-business.test.js.map +1 -0
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/card-tool.test.js +79 -0
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/card-tool.test.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/chat-send-policy.test.d.ts +2 -0
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/chat-send-policy.test.d.ts.map +1 -0
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/chat-send-policy.test.js +34 -0
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/chat-send-policy.test.js.map +1 -0
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/reach-tool.test.d.ts +2 -0
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/reach-tool.test.d.ts.map +1 -0
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/reach-tool.test.js +93 -0
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/reach-tool.test.js.map +1 -0
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/thread-tool.test.js +15 -1
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/thread-tool.test.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/webhook-register.test.js +245 -0
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/webhook-register.test.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/webhook-verdict.test.js +10 -1
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/webhook-verdict.test.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/index.js +26 -4
- package/payload/platform/plugins/telegram/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/lib/account-token.d.ts +19 -0
- package/payload/platform/plugins/telegram/mcp/dist/lib/account-token.d.ts.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/lib/account-token.js +41 -1
- package/payload/platform/plugins/telegram/mcp/dist/lib/account-token.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/lib/account-write.d.ts +15 -20
- package/payload/platform/plugins/telegram/mcp/dist/lib/account-write.d.ts.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/lib/account-write.js +27 -32
- package/payload/platform/plugins/telegram/mcp/dist/lib/account-write.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/lib/agent-active.d.ts +13 -0
- package/payload/platform/plugins/telegram/mcp/dist/lib/agent-active.d.ts.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/lib/agent-active.js +22 -1
- package/payload/platform/plugins/telegram/mcp/dist/lib/agent-active.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/lib/api-census.d.ts.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/lib/api-census.js +6 -0
- package/payload/platform/plugins/telegram/mcp/dist/lib/api-census.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/lib/api-guard.d.ts +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/lib/api-guard.d.ts.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/lib/api-guard.js +22 -2
- package/payload/platform/plugins/telegram/mcp/dist/lib/api-guard.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/lib/business-connection-store.d.ts +38 -0
- package/payload/platform/plugins/telegram/mcp/dist/lib/business-connection-store.d.ts.map +1 -0
- package/payload/platform/plugins/telegram/mcp/dist/lib/business-connection-store.js +56 -0
- package/payload/platform/plugins/telegram/mcp/dist/lib/business-connection-store.js.map +1 -0
- package/payload/platform/plugins/telegram/mcp/dist/lib/business-window-store.d.ts +55 -0
- package/payload/platform/plugins/telegram/mcp/dist/lib/business-window-store.d.ts.map +1 -0
- package/payload/platform/plugins/telegram/mcp/dist/lib/business-window-store.js +116 -0
- package/payload/platform/plugins/telegram/mcp/dist/lib/business-window-store.js.map +1 -0
- package/payload/platform/plugins/telegram/mcp/dist/lib/chat-send-policy.d.ts +54 -0
- package/payload/platform/plugins/telegram/mcp/dist/lib/chat-send-policy.d.ts.map +1 -0
- package/payload/platform/plugins/telegram/mcp/dist/lib/chat-send-policy.js +90 -0
- package/payload/platform/plugins/telegram/mcp/dist/lib/chat-send-policy.js.map +1 -0
- package/payload/platform/plugins/telegram/mcp/dist/lib/telegram.d.ts +2 -28
- package/payload/platform/plugins/telegram/mcp/dist/lib/telegram.d.ts.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/lib/telegram.js +8 -53
- package/payload/platform/plugins/telegram/mcp/dist/lib/telegram.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/tools/api.d.ts.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/tools/api.js +19 -0
- package/payload/platform/plugins/telegram/mcp/dist/tools/api.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/tools/ask.d.ts.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/tools/ask.js +79 -10
- package/payload/platform/plugins/telegram/mcp/dist/tools/ask.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/tools/bot-provision.d.ts +64 -0
- package/payload/platform/plugins/telegram/mcp/dist/tools/bot-provision.d.ts.map +1 -0
- package/payload/platform/plugins/telegram/mcp/dist/tools/bot-provision.js +217 -0
- package/payload/platform/plugins/telegram/mcp/dist/tools/bot-provision.js.map +1 -0
- package/payload/platform/plugins/telegram/mcp/dist/tools/card.d.ts +7 -0
- package/payload/platform/plugins/telegram/mcp/dist/tools/card.d.ts.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/tools/card.js +56 -0
- package/payload/platform/plugins/telegram/mcp/dist/tools/card.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/tools/invoice.d.ts.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/tools/invoice.js +15 -0
- package/payload/platform/plugins/telegram/mcp/dist/tools/invoice.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/tools/media-send.d.ts.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/tools/media-send.js +12 -0
- package/payload/platform/plugins/telegram/mcp/dist/tools/media-send.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/tools/reach.d.ts +22 -0
- package/payload/platform/plugins/telegram/mcp/dist/tools/reach.d.ts.map +1 -0
- package/payload/platform/plugins/telegram/mcp/dist/tools/reach.js +67 -0
- package/payload/platform/plugins/telegram/mcp/dist/tools/reach.js.map +1 -0
- package/payload/platform/plugins/telegram/mcp/dist/tools/schemas.d.ts +21 -2
- package/payload/platform/plugins/telegram/mcp/dist/tools/schemas.d.ts.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/tools/schemas.js +47 -2
- package/payload/platform/plugins/telegram/mcp/dist/tools/schemas.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/tools/thread.d.ts.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/tools/thread.js +12 -0
- package/payload/platform/plugins/telegram/mcp/dist/tools/thread.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/tools/webhook-register.d.ts +4 -1
- package/payload/platform/plugins/telegram/mcp/dist/tools/webhook-register.d.ts.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/tools/webhook-register.js +73 -6
- package/payload/platform/plugins/telegram/mcp/dist/tools/webhook-register.js.map +1 -1
- package/payload/platform/plugins/telegram/skills/build/SKILL.md +217 -11
- package/payload/platform/plugins/telegram/skills/configure/SKILL.md +87 -6
- package/payload/platform/plugins/whatsapp/references/channels-whatsapp.md +12 -0
- package/payload/platform/services/claude-session-manager/dist/account-dir-schema-reconcile.d.ts +36 -5
- package/payload/platform/services/claude-session-manager/dist/account-dir-schema-reconcile.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/account-dir-schema-reconcile.js +103 -10
- package/payload/platform/services/claude-session-manager/dist/account-dir-schema-reconcile.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +2 -0
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
- 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 +42 -4
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- 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 +19 -5
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts +9 -0
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +5 -1
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
- package/payload/platform/services/telegram-channel/dist/instructions.d.ts.map +1 -1
- package/payload/platform/services/telegram-channel/dist/instructions.js +13 -0
- package/payload/platform/services/telegram-channel/dist/instructions.js.map +1 -1
- package/payload/platform/services/telegram-channel/dist/notification.d.ts +40 -0
- package/payload/platform/services/telegram-channel/dist/notification.d.ts.map +1 -1
- package/payload/platform/services/telegram-channel/dist/notification.js +41 -4
- package/payload/platform/services/telegram-channel/dist/notification.js.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/notification.d.ts +52 -0
- package/payload/platform/services/whatsapp-channel/dist/notification.d.ts.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/notification.js +64 -1
- package/payload/platform/services/whatsapp-channel/dist/notification.js.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/server.d.ts.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/server.js +14 -2
- package/payload/platform/services/whatsapp-channel/dist/server.js.map +1 -1
- package/payload/platform/templates/account-schema/SCHEMA.md +17 -10
- package/payload/platform/templates/agents/admin/IDENTITY.md +5 -0
- package/payload/platform/templates/specialists/agents/data-manager.md +2 -2
- package/payload/platform/templates/specialists/agents/personal-assistant.md +1 -1
- package/payload/server/{chunk-BFRB2U75.js → chunk-CV6AEMKH.js} +1 -0
- package/payload/server/{manager-CTVTF4YB.js → manager-FQSQSSJ3.js} +1 -1
- package/payload/server/public/activity.html +6 -6
- package/payload/server/public/agents.html +5 -5
- package/payload/server/public/assets/{AdminLoginScreens-B1lu4-_F.js → AdminLoginScreens-BLsDYWVi.js} +1 -1
- package/payload/server/public/assets/AdminLoginScreens-BLsDYWVi.js.br +0 -0
- package/payload/server/public/assets/AdminLoginScreens-BLsDYWVi.js.gz +0 -0
- package/payload/server/public/assets/{AdminShell-BMslfZxN.js → AdminShell-BZS8jzFA.js} +1 -1
- package/payload/server/public/assets/AdminShell-BZS8jzFA.js.br +0 -0
- package/payload/server/public/assets/AdminShell-BZS8jzFA.js.gz +0 -0
- package/payload/server/public/assets/{activity-kQ3w70LJ.js → activity-DOjvoLdd.js} +1 -1
- package/payload/server/public/assets/activity-DOjvoLdd.js.br +0 -0
- package/payload/server/public/assets/activity-DOjvoLdd.js.gz +0 -0
- package/payload/server/public/assets/{admin-CkASgYA7.js → admin-JrSNg29g.js} +1 -1
- package/payload/server/public/assets/admin-JrSNg29g.js.br +0 -0
- package/payload/server/public/assets/admin-JrSNg29g.js.gz +0 -0
- package/payload/server/public/assets/{agents-Cn_bZgnD.js → agents--9WMJVLC.js} +1 -1
- package/payload/server/public/assets/agents--9WMJVLC.js.br +0 -0
- package/payload/server/public/assets/agents--9WMJVLC.js.gz +0 -0
- package/payload/server/public/assets/{browser-BE-GDk5-.js → browser-DiiMmTrM.js} +1 -1
- package/payload/server/public/assets/browser-DiiMmTrM.js.br +0 -0
- package/payload/server/public/assets/browser-DiiMmTrM.js.gz +0 -0
- package/payload/server/public/assets/{calendar-Di7BEHHN.js → calendar-CazmCzgO.js} +1 -1
- package/payload/server/public/assets/calendar-CazmCzgO.js.br +0 -0
- package/payload/server/public/assets/calendar-CazmCzgO.js.gz +0 -0
- package/payload/server/public/assets/chat-CB0TcyXX.js +1 -0
- package/payload/server/public/assets/chat-CB0TcyXX.js.br +0 -0
- package/payload/server/public/assets/chat-CB0TcyXX.js.gz +0 -0
- package/payload/server/public/assets/chevron-left-0tVo23Dh.js +1 -0
- package/payload/server/public/assets/chevron-left-0tVo23Dh.js.br +0 -0
- package/payload/server/public/assets/clock-D2cZ0sge.js +1 -0
- package/payload/server/public/assets/clock-D2cZ0sge.js.br +0 -0
- package/payload/server/public/assets/clock-D2cZ0sge.js.gz +0 -0
- package/payload/server/public/assets/{copy-nkxspu2J.js → copy-C87QIN_o.js} +1 -1
- package/payload/server/public/assets/copy-C87QIN_o.js.br +0 -0
- package/payload/server/public/assets/copy-C87QIN_o.js.gz +0 -0
- package/payload/server/public/assets/data-CK7AMxPt.js +1 -0
- package/payload/server/public/assets/data-CK7AMxPt.js.br +0 -0
- package/payload/server/public/assets/data-CK7AMxPt.js.gz +0 -0
- package/payload/server/public/assets/{field-2rIXxGMt.js → field-C3kQgGWE.js} +1 -1
- package/payload/server/public/assets/field-C3kQgGWE.js.br +0 -0
- package/payload/server/public/assets/field-C3kQgGWE.js.gz +0 -0
- package/payload/server/public/assets/{file-text-CdSqrscg.js → file-text-rWowl9RN.js} +1 -1
- package/payload/server/public/assets/file-text-rWowl9RN.js.br +0 -0
- package/payload/server/public/assets/file-text-rWowl9RN.js.gz +0 -0
- package/payload/server/public/assets/{graph-BfBHHXaC.js → graph-CVJKz1Uo.js} +1 -1
- package/payload/server/public/assets/graph-CVJKz1Uo.js.br +0 -0
- package/payload/server/public/assets/graph-CVJKz1Uo.js.gz +0 -0
- package/payload/server/public/assets/{graph-labels-CHW2aBke.js → graph-labels-kneGnsHB.js} +1 -1
- package/payload/server/public/assets/graph-labels-kneGnsHB.js.br +0 -0
- package/payload/server/public/assets/graph-labels-kneGnsHB.js.gz +0 -0
- package/payload/server/public/assets/{jsx-runtime-D43jgaWP.css → jsx-runtime-rMaiYjNu.css} +1 -1
- package/payload/server/public/assets/jsx-runtime-rMaiYjNu.css.br +0 -0
- package/payload/server/public/assets/{jsx-runtime-D43jgaWP.css.gz → jsx-runtime-rMaiYjNu.css.gz} +0 -0
- package/payload/server/public/assets/{operator-DRn9LITC.js → operator-BGvB4hu4.js} +1 -1
- package/payload/server/public/assets/operator-BGvB4hu4.js.br +0 -0
- package/payload/server/public/assets/operator-BGvB4hu4.js.gz +0 -0
- package/payload/server/public/assets/{page-D_9mPS6W.js → page-DBQLOasI.js} +1 -1
- package/payload/server/public/assets/page-DBQLOasI.js.br +0 -0
- package/payload/server/public/assets/page-DBQLOasI.js.gz +0 -0
- package/payload/server/public/assets/{page-BwqQsoU8.js → page-DyVAu7tm.js} +1 -1
- package/payload/server/public/assets/page-DyVAu7tm.js.br +0 -0
- package/payload/server/public/assets/page-DyVAu7tm.js.gz +0 -0
- package/payload/server/public/assets/play-DgP7vl0r.js +1 -0
- package/payload/server/public/assets/play-DgP7vl0r.js.br +0 -0
- package/payload/server/public/assets/play-DgP7vl0r.js.gz +0 -0
- package/payload/server/public/assets/{public-CrjZYpdW.js → public-BvUQR3hd.js} +1 -1
- package/payload/server/public/assets/public-BvUQR3hd.js.br +0 -0
- package/payload/server/public/assets/public-BvUQR3hd.js.gz +0 -0
- package/payload/server/public/assets/{rotate-ccw-J9f-GWjm.js → rotate-ccw-Dnn7gbPh.js} +1 -1
- package/payload/server/public/assets/rotate-ccw-Dnn7gbPh.js.br +0 -0
- package/payload/server/public/assets/rotate-ccw-Dnn7gbPh.js.gz +0 -0
- package/payload/server/public/assets/{routines-C1AB-3FR.js → routines-N8NmxPOZ.js} +1 -1
- package/payload/server/public/assets/routines-N8NmxPOZ.js.br +0 -0
- package/payload/server/public/assets/routines-N8NmxPOZ.js.gz +0 -0
- package/payload/server/public/assets/{skills-C4EfNKEx.js → skills-B2CRgO-U.js} +1 -1
- package/payload/server/public/assets/skills-B2CRgO-U.js.br +0 -0
- package/payload/server/public/assets/skills-B2CRgO-U.js.gz +0 -0
- package/payload/server/public/assets/{tasks-DszD3aZl.js → tasks-8QLGtlSj.js} +1 -1
- package/payload/server/public/assets/tasks-8QLGtlSj.js.br +0 -0
- package/payload/server/public/assets/tasks-8QLGtlSj.js.gz +0 -0
- package/payload/server/public/assets/{triangle-alert-B5WAyAkC.js → triangle-alert-el772yUQ.js} +1 -1
- package/payload/server/public/assets/triangle-alert-el772yUQ.js.br +0 -0
- package/payload/server/public/assets/triangle-alert-el772yUQ.js.gz +0 -0
- package/payload/server/public/assets/{useCopyFeedback-B2nuNNJw.js → useCopyFeedback-DfNAu8hQ.js} +1 -1
- package/payload/server/public/assets/useCopyFeedback-DfNAu8hQ.js.br +0 -0
- package/payload/server/public/assets/useCopyFeedback-DfNAu8hQ.js.gz +0 -0
- package/payload/server/public/assets/{useMediaQuery-DUPJPHQt.js → useMediaQuery-B469O83-.js} +1 -1
- package/payload/server/public/assets/useMediaQuery-B469O83-.js.br +0 -0
- package/payload/server/public/assets/useMediaQuery-B469O83-.js.gz +0 -0
- package/payload/server/public/assets/useVoiceRecorder-Bb-51cJv.js +2 -0
- package/payload/server/public/assets/useVoiceRecorder-Bb-51cJv.js.br +0 -0
- package/payload/server/public/assets/useVoiceRecorder-Bb-51cJv.js.gz +0 -0
- package/payload/server/public/assets/{wrench-DZJZm17j.js → wrench-Ck4phkdB.js} +1 -1
- package/payload/server/public/assets/wrench-Ck4phkdB.js.br +0 -0
- package/payload/server/public/assets/wrench-Ck4phkdB.js.gz +0 -0
- package/payload/server/public/browser.html +5 -5
- package/payload/server/public/calendar.html +8 -8
- package/payload/server/public/chat.html +14 -14
- package/payload/server/public/data.html +12 -12
- package/payload/server/public/field.html +3 -3
- package/payload/server/public/graph.html +10 -10
- package/payload/server/public/index.html +14 -14
- package/payload/server/public/operator.html +16 -16
- package/payload/server/public/public.html +14 -14
- package/payload/server/public/routines.html +8 -8
- package/payload/server/public/skills.html +6 -6
- package/payload/server/public/tasks.html +7 -7
- package/payload/server/server.js +3777 -1258
- package/payload/server/public/assets/AdminLoginScreens-B1lu4-_F.js.br +0 -0
- package/payload/server/public/assets/AdminLoginScreens-B1lu4-_F.js.gz +0 -0
- package/payload/server/public/assets/AdminShell-BMslfZxN.js.br +0 -0
- package/payload/server/public/assets/AdminShell-BMslfZxN.js.gz +0 -0
- package/payload/server/public/assets/activity-kQ3w70LJ.js.br +0 -0
- package/payload/server/public/assets/activity-kQ3w70LJ.js.gz +0 -0
- package/payload/server/public/assets/admin-CkASgYA7.js.br +0 -0
- package/payload/server/public/assets/admin-CkASgYA7.js.gz +0 -0
- package/payload/server/public/assets/agents-Cn_bZgnD.js.br +0 -0
- package/payload/server/public/assets/agents-Cn_bZgnD.js.gz +0 -0
- package/payload/server/public/assets/browser-BE-GDk5-.js.br +0 -0
- package/payload/server/public/assets/browser-BE-GDk5-.js.gz +0 -0
- package/payload/server/public/assets/calendar-Di7BEHHN.js.br +0 -0
- package/payload/server/public/assets/calendar-Di7BEHHN.js.gz +0 -0
- package/payload/server/public/assets/chat-CKyMT5Ai.js +0 -1
- package/payload/server/public/assets/chat-CKyMT5Ai.js.br +0 -1
- package/payload/server/public/assets/chat-CKyMT5Ai.js.gz +0 -0
- package/payload/server/public/assets/chevron-left-Id9VAZAz.js +0 -1
- package/payload/server/public/assets/chevron-left-Id9VAZAz.js.br +0 -0
- package/payload/server/public/assets/clock-DKpWWJbJ.js +0 -1
- package/payload/server/public/assets/clock-DKpWWJbJ.js.br +0 -0
- package/payload/server/public/assets/copy-nkxspu2J.js.br +0 -0
- package/payload/server/public/assets/copy-nkxspu2J.js.gz +0 -0
- package/payload/server/public/assets/data-1c33cAHp.js +0 -1
- package/payload/server/public/assets/data-1c33cAHp.js.br +0 -2
- package/payload/server/public/assets/data-1c33cAHp.js.gz +0 -0
- package/payload/server/public/assets/field-2rIXxGMt.js.br +0 -0
- package/payload/server/public/assets/field-2rIXxGMt.js.gz +0 -0
- package/payload/server/public/assets/file-text-CdSqrscg.js.br +0 -0
- package/payload/server/public/assets/file-text-CdSqrscg.js.gz +0 -0
- package/payload/server/public/assets/graph-BfBHHXaC.js.br +0 -0
- package/payload/server/public/assets/graph-BfBHHXaC.js.gz +0 -0
- package/payload/server/public/assets/graph-labels-CHW2aBke.js.br +0 -0
- package/payload/server/public/assets/graph-labels-CHW2aBke.js.gz +0 -0
- package/payload/server/public/assets/jsx-runtime-D43jgaWP.css.br +0 -0
- package/payload/server/public/assets/operator-DRn9LITC.js.br +0 -0
- package/payload/server/public/assets/operator-DRn9LITC.js.gz +0 -0
- package/payload/server/public/assets/page-BwqQsoU8.js.br +0 -0
- package/payload/server/public/assets/page-BwqQsoU8.js.gz +0 -0
- package/payload/server/public/assets/page-D_9mPS6W.js.br +0 -0
- package/payload/server/public/assets/page-D_9mPS6W.js.gz +0 -0
- package/payload/server/public/assets/play-7LTxCuLX.js +0 -1
- package/payload/server/public/assets/play-7LTxCuLX.js.br +0 -0
- package/payload/server/public/assets/play-7LTxCuLX.js.gz +0 -0
- package/payload/server/public/assets/public-CrjZYpdW.js.br +0 -0
- package/payload/server/public/assets/public-CrjZYpdW.js.gz +0 -0
- package/payload/server/public/assets/rotate-ccw-J9f-GWjm.js.br +0 -0
- package/payload/server/public/assets/rotate-ccw-J9f-GWjm.js.gz +0 -0
- package/payload/server/public/assets/routines-C1AB-3FR.js.br +0 -0
- package/payload/server/public/assets/routines-C1AB-3FR.js.gz +0 -0
- package/payload/server/public/assets/skills-C4EfNKEx.js.br +0 -0
- package/payload/server/public/assets/skills-C4EfNKEx.js.gz +0 -0
- package/payload/server/public/assets/tasks-DszD3aZl.js.br +0 -0
- package/payload/server/public/assets/tasks-DszD3aZl.js.gz +0 -0
- package/payload/server/public/assets/triangle-alert-B5WAyAkC.js.br +0 -4
- package/payload/server/public/assets/triangle-alert-B5WAyAkC.js.gz +0 -0
- package/payload/server/public/assets/useCopyFeedback-B2nuNNJw.js.br +0 -0
- package/payload/server/public/assets/useCopyFeedback-B2nuNNJw.js.gz +0 -0
- package/payload/server/public/assets/useMediaQuery-DUPJPHQt.js.br +0 -0
- package/payload/server/public/assets/useMediaQuery-DUPJPHQt.js.gz +0 -0
- package/payload/server/public/assets/useVoiceRecorder-CCK60d2i.js +0 -2
- package/payload/server/public/assets/useVoiceRecorder-CCK60d2i.js.br +0 -0
- package/payload/server/public/assets/useVoiceRecorder-CCK60d2i.js.gz +0 -0
- package/payload/server/public/assets/wrench-DZJZm17j.js.br +0 -0
- package/payload/server/public/assets/wrench-DZJZm17j.js.gz +0 -0
- /package/payload/server/public/assets/{jsx-runtime-Cjug_Cyb.js → jsx-runtime-BmNepPEn.js} +0 -0
- /package/payload/server/public/assets/{jsx-runtime-Cjug_Cyb.js.br → jsx-runtime-BmNepPEn.js.br} +0 -0
- /package/payload/server/public/assets/{jsx-runtime-Cjug_Cyb.js.gz → jsx-runtime-BmNepPEn.js.gz} +0 -0
|
@@ -17,10 +17,11 @@ and this skill says how to call it.
|
|
|
17
17
|
|
|
18
18
|
## What you have
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
Eleven named tools for the common paths, and one passthrough for everything else.
|
|
21
21
|
|
|
22
22
|
| Tool | Use it for |
|
|
23
23
|
|---|---|
|
|
24
|
+
| `mcp__telegram__telegram-reach` | Which chats each registered bot can message now, and which allowlisted admins have never messaged it |
|
|
24
25
|
| `mcp__telegram__telegram-card` | Posting a card, or editing the one your key already names |
|
|
25
26
|
| `mcp__telegram__telegram-ask` | Polls, checklists, locations, venues, contacts, dice |
|
|
26
27
|
| `mcp__telegram__telegram-media-send` | Sending a photo, file, video, audio or album, and editing media or captions |
|
|
@@ -36,7 +37,20 @@ Ten named tools for the common paths, and one passthrough for everything else.
|
|
|
36
37
|
`telegram-api` takes `botId` (never a token), `method`, `params`, and optionally `files` and
|
|
37
38
|
`timeoutMs`. Field names inside `params` are Telegram's own snake_case.
|
|
38
39
|
|
|
39
|
-
##
|
|
40
|
+
## Who you can send to
|
|
41
|
+
|
|
42
|
+
Telegram does not let a bot open a conversation. Somebody who has messaged one of this account's
|
|
43
|
+
bots can be messaged back at any time with `telegram-card` and their chat id; somebody who never has
|
|
44
|
+
must write to the bot first, and no tool here can shortcut that.
|
|
45
|
+
|
|
46
|
+
`telegram-reach` is what tells the two apart. It takes no parameters and lists, per registered bot,
|
|
47
|
+
every private chat that has messaged it — chat id, name, and when they last wrote — plus any admin
|
|
48
|
+
user allowlisted on that bot who has never messaged. Being on the allowlist is not the same fact as
|
|
49
|
+
having opened the chat, and only the second one makes a send possible.
|
|
50
|
+
|
|
51
|
+
Read it before telling anybody a Telegram send is impossible.
|
|
52
|
+
|
|
53
|
+
## The seven methods it will not call
|
|
40
54
|
|
|
41
55
|
Each refusal names the tool that owns the capability instead.
|
|
42
56
|
|
|
@@ -45,6 +59,41 @@ Each refusal names the tool that owns the capability instead.
|
|
|
45
59
|
| `setWebhook`, `deleteWebhook` | Webhook state is registered on the one path the maxy edge admits, stamped with the bot id. A raw call silently repoints or stops every inbound message | `telegram-webhook-register` |
|
|
46
60
|
| `getUpdates` | Telegram's two ways of receiving updates are mutually exclusive, and this one does not work while a webhook is set | The webhook already delivers inbound |
|
|
47
61
|
| `logOut`, `close` | Both move the bot off the cloud Bot API server | Nothing. Do not do this |
|
|
62
|
+
| `getManagedBotToken`, `replaceManagedBotToken` | The result IS a live bot token. Relaying it puts a credential in a tool result, and therefore in the transcript | `telegram-bot-provision`, which persists tokens and returns only bot ids |
|
|
63
|
+
|
|
64
|
+
`getManagedBotAccessSettings` and `setManagedBotAccessSettings` are NOT refused: they return no
|
|
65
|
+
credential, so refusing them would remove a capability while protecting nothing. Prefer
|
|
66
|
+
`telegram-bot-provision action=access` anyway, which logs the change.
|
|
67
|
+
|
|
68
|
+
## Creating a bot without BotFather
|
|
69
|
+
|
|
70
|
+
`telegram-bot-provision` has four actions.
|
|
71
|
+
|
|
72
|
+
| Action | What it does |
|
|
73
|
+
|---|---|
|
|
74
|
+
| `offer` | Sends a one-tap button into a private chat. The person taps it, names the bot, and this install receives it, stores its token, restricts it to its owner and registers its webhook |
|
|
75
|
+
| `rotate` | Revokes a managed bot's token, saves the replacement, and re-registers the webhook at the URL it was already on |
|
|
76
|
+
| `access` | Reads the access settings when `isAccessRestricted` is omitted; writes them when it is given. Up to ten `addedUserIds` besides the owner |
|
|
77
|
+
| `list` | This account's bots by id and role. Never a token |
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
telegram-bot-provision botId=<managing-bot> action=offer chatId=<private-chat>
|
|
81
|
+
suggestedName="Front Desk" suggestedUsername="frontdesk_bot"
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Three things to know before using it:
|
|
85
|
+
|
|
86
|
+
- The managing bot must have management of other bots enabled **once**, in the @BotFather Mini App.
|
|
87
|
+
No API call turns it on. `offer` checks `getMe().can_manage_bots` and refuses with the Mini App
|
|
88
|
+
named, so a button that would do nothing is never sent.
|
|
89
|
+
- The button is a REPLY keyboard and Telegram makes it **private chats only**. A group or channel
|
|
90
|
+
id will not work.
|
|
91
|
+
- A provisioned bot lands as `role:'unbound'` and answers nobody until an agent is bound to it. It
|
|
92
|
+
is restricted to its owner on Telegram's side at the same time.
|
|
93
|
+
|
|
94
|
+
Telegram sends no `request_id` back and no event discriminator, so a creation and a token change
|
|
95
|
+
are told apart only by whether the account already holds the bot id, and the log correlates on
|
|
96
|
+
`newBotId` rather than on the request id.
|
|
48
97
|
|
|
49
98
|
## Five things people actually build
|
|
50
99
|
|
|
@@ -166,6 +215,21 @@ form needs forum topic mode enabled on the bot: `sendMessage`'s `message_thread_
|
|
|
166
215
|
working "for forum supergroups and private chats of bots with forum topic mode enabled only", so
|
|
167
216
|
without it the topic exists and nothing can be sent into it.
|
|
168
217
|
|
|
218
|
+
**A message from a topic is answered in that topic, and you do not arrange it.** The route reads the
|
|
219
|
+
topic off the inbound and threads it through the reply, so your turn's final text lands where the
|
|
220
|
+
question was asked. You only pass `messageThreadId` yourself when you are sending into a topic
|
|
221
|
+
nobody just wrote in.
|
|
222
|
+
|
|
223
|
+
**A checklist cannot go into a topic.** `sendChecklist` is the one send method with no
|
|
224
|
+
`message_thread_id` in its table. `telegram-ask` refuses that pair before the network call rather
|
|
225
|
+
than dropping the field and letting the checklist land in the group's General thread, which used to
|
|
226
|
+
read as the call having worked. Send it without `messageThreadId`, or use a poll or a plain message
|
|
227
|
+
for the topic itself.
|
|
228
|
+
|
|
229
|
+
**Only a real topic counts.** Telegram also stamps `message_thread_id` on an ordinary reply in a
|
|
230
|
+
supergroup, so the route keys on `is_topic_message` instead. A plain reply is answered in the
|
|
231
|
+
conversation, not pulled into a thread.
|
|
232
|
+
|
|
169
233
|
### 8. Asking a question, or sending a place
|
|
170
234
|
|
|
171
235
|
`telegram-ask` covers the structured sends. A poll takes its answers as plain strings:
|
|
@@ -188,9 +252,40 @@ telegram-ask botId=<id> chatId=<chat> kind=editLiveLocation messageId=<id> latit
|
|
|
188
252
|
longitude=-0.13
|
|
189
253
|
```
|
|
190
254
|
|
|
191
|
-
`venue`, `contact` and `dice` are one call each.
|
|
192
|
-
|
|
193
|
-
and
|
|
255
|
+
`venue`, `contact` and `dice` are one call each.
|
|
256
|
+
|
|
257
|
+
**The two checklist kinds need a connected business account, and you do not have to find its
|
|
258
|
+
identifier yourself.** `business_connection_id` is required on `sendChecklist` and
|
|
259
|
+
`editMessageChecklist` and there is no variant without it, so a bot can never send a checklist as
|
|
260
|
+
itself. Telegram announces the identifier once, on a `business_connection` update, when the operator
|
|
261
|
+
connects the bot under Telegram, Settings, Business, Chatbots. This install captures it and stores it
|
|
262
|
+
per bot, so `telegram-ask kind=checklist` with no `businessConnectionId` sends on the stored
|
|
263
|
+
connection. Pass one explicitly only to override that. With nothing stored the tool refuses and names
|
|
264
|
+
the operator step, which means the answer is to ask the operator to connect the bot, not to hunt for
|
|
265
|
+
a parameter.
|
|
266
|
+
|
|
267
|
+
**A customer messaging the connected business account reaches you in their own conversation, not the
|
|
268
|
+
operator's.** Once the operator connects the bot under Telegram, Settings, Business, Chatbots, every
|
|
269
|
+
message in that account's private chats arrives here as a turn of its own. Four things follow.
|
|
270
|
+
|
|
271
|
+
The turn is a **stranger's**, so it runs as the entry's public agent and carries none of the
|
|
272
|
+
operator's standing rules, whatever role the bot itself holds. The two conversations never share a
|
|
273
|
+
session even when the same person is in both.
|
|
274
|
+
|
|
275
|
+
Every reply **quotes the connection**, and you do not supply it: `telegram-card` and the turn's own
|
|
276
|
+
reply fill it in from the stored connection. Telegram routes the message as the business account
|
|
277
|
+
rather than as the bot, and there is no variant without it.
|
|
278
|
+
|
|
279
|
+
The **24-hour window is a hard limit**. `BusinessBotRights.can_reply` grants the right to answer only
|
|
280
|
+
"in the private chats that had incoming messages in the last 24 hours". A send past that is refused
|
|
281
|
+
here before it is attempted, and the refusal names the window. Nothing is emitted when a window
|
|
282
|
+
closes, so a customer you leave unanswered simply becomes unreachable with no error anywhere. Answer
|
|
283
|
+
while you can.
|
|
284
|
+
|
|
285
|
+
An edit from the customer **changes the message you already have** rather than arriving as a new one.
|
|
286
|
+
It still raises a turn, because a customer who rewrites their question has asked something new; what
|
|
287
|
+
it does not do is leave you two messages to reconcile. A deletion marks the message deleted rather
|
|
288
|
+
than removing it, so what was withdrawn stays readable, and it raises no turn at all.
|
|
194
289
|
|
|
195
290
|
**A business connection and Telegram Premium are two separate gates, and they govern different
|
|
196
291
|
things.** Telegram states them apart, so do not treat one as the other. Bot API 9.1 (3 July 2025)
|
|
@@ -199,8 +294,20 @@ business account" — that gate is the business connection, and it is the one `b
|
|
|
199
294
|
carries. Bot API 9.4 (9 February 2026) allowed "custom emoji in messages directly sent by the bot to
|
|
200
295
|
private, group and supergroup chats if the owner of the bot has a Telegram Premium subscription" —
|
|
201
296
|
that gate is Premium, it is on the bot's OWNER rather than on a connection, and it governs custom
|
|
202
|
-
emoji, not checklists.
|
|
203
|
-
|
|
297
|
+
emoji, not checklists.
|
|
298
|
+
|
|
299
|
+
On Premium and Business, `core.telegram.org/api/business` says two things and you need both. "All
|
|
300
|
+
Telegram Business features are available for free to Premium subscribers." And: "Additionally,
|
|
301
|
+
connected bots are also available to non-Premium users." A checklist rides on a connected bot, so do
|
|
302
|
+
not tell an operator that a checklist requires Premium. If Telegram nevertheless answers
|
|
303
|
+
`PREMIUM_ACCOUNT_REQUIRED` on a `sendChecklist` that carried a valid `business_connection_id`, that is
|
|
304
|
+
a finding worth reporting rather than a settled fact.
|
|
305
|
+
|
|
306
|
+
**A Mini App button and a checklist cannot share one message.** Telegram's `InlineKeyboardButton`
|
|
307
|
+
table says a `web_app` button is "Available only in private chats between a user and the bot. Not
|
|
308
|
+
supported for messages sent on behalf of a business account." A checklist is sent on behalf of a
|
|
309
|
+
business account, so send the Mini App button as its own ordinary message. This install's Mini App is
|
|
310
|
+
`/field?bot=<botId>` on the install's own origin, not the public site.
|
|
204
311
|
|
|
205
312
|
### 9. Charging for something
|
|
206
313
|
|
|
@@ -221,10 +328,19 @@ keyboard to be a Pay button, and leaving the keyboard off gets that button for f
|
|
|
221
328
|
`payload` is your own reference. It is never shown to the payer and it comes back on the
|
|
222
329
|
successful-payment update, which is how a payment is matched to a job.
|
|
223
330
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
`
|
|
227
|
-
|
|
331
|
+
**You do not answer the pre-checkout query.** Telegram cancels the transaction if no answer lands
|
|
332
|
+
within ten seconds, and a turn cannot start and finish in ten seconds, so the inbound route answers
|
|
333
|
+
it itself: `ok=true` for a sender with access, `ok=false` for one without. You then get a turn saying
|
|
334
|
+
`[pre-checkout approved: …]`, and once the payer confirms, a second one saying
|
|
335
|
+
`[payment received: …]` with your own `payload` on it. `action=answerPreCheckout` stays on the tool
|
|
336
|
+
for a surface that answers out of band; calling it for a query the route has already answered gets a
|
|
337
|
+
Telegram error about a stale id.
|
|
338
|
+
|
|
339
|
+
Set `isFlexible` and Telegram sends a shipping query mid-checkout. That one **is** yours: the route
|
|
340
|
+
raises a turn saying `[shipping query: …]` with the `queryId`, because only you know the options.
|
|
341
|
+
Answer it with `action=answerShipping`. `ok=false` needs `errorMessage`, which Telegram shows the
|
|
342
|
+
payer verbatim. `balance`, `transactions`, `refund` and `editSubscription` are the Stars controls; a
|
|
343
|
+
subscription that is cancelled, re-enabled or fails to charge arrives as its own turn.
|
|
228
344
|
|
|
229
345
|
### Ephemeral messages
|
|
230
346
|
|
|
@@ -235,6 +351,96 @@ other send methods. The resulting message has `message_id: 0` and carries its id
|
|
|
235
351
|
address. Send one through `telegram-api`; no named tool covers it, because nothing on this install
|
|
236
352
|
sends group messages visible to a single user.
|
|
237
353
|
|
|
354
|
+
## What arrives from Telegram
|
|
355
|
+
|
|
356
|
+
Telegram defines twenty-six update classes. This install registers twenty-two and handles seventeen
|
|
357
|
+
of them.
|
|
358
|
+
|
|
359
|
+
| Class | Registered | What happens |
|
|
360
|
+
|---|---|---|
|
|
361
|
+
| `message`, `edited_message` | yes | a turn, with media, transcription, location and the quoted original when the sender replied |
|
|
362
|
+
| `callback_query` | yes | answered, stored, and a turn unless it is a dispatch button |
|
|
363
|
+
| `poll_answer` | yes | a turn per voter |
|
|
364
|
+
| `poll` | yes | a turn on close only, naming the question and the counts |
|
|
365
|
+
| `message_reaction` | yes | a turn naming the emoji and the message reacted to |
|
|
366
|
+
| `pre_checkout_query` | yes | answered by the route inside ten seconds, then a turn |
|
|
367
|
+
| `shipping_query` | yes | a turn; you answer it with `telegram-invoice action=answerShipping` |
|
|
368
|
+
| `subscription` | yes | a turn naming the state (`canceled`, `active`, `failed`) |
|
|
369
|
+
| `my_chat_member` | yes | logged only, no turn: in a DM this is a block or an unblock |
|
|
370
|
+
| `business_connection` | yes | recorded so `business_connection_id` can be supplied |
|
|
371
|
+
| `business_message` | yes | a turn, in the customer's own session |
|
|
372
|
+
| `edited_business_message` | yes | a turn, and it patches the message rather than adding one |
|
|
373
|
+
| `deleted_business_messages` | yes | marks the stored rows deleted, no turn |
|
|
374
|
+
| `chat_member` | yes | logged only, no turn: another member joined, left or was removed |
|
|
375
|
+
| `chat_join_request` | yes | logged only, no turn |
|
|
376
|
+
| `message_reaction_count` | yes | logged against the message, no turn: the anonymous tally, as against `message_reaction` which names the reactor |
|
|
377
|
+
| `chat_boost`, `removed_chat_boost` | yes | logged only, no turn |
|
|
378
|
+
| `channel_post`, `edited_channel_post` | yes | a turn, attributed to the channel, when the channel is allowlisted |
|
|
379
|
+
| everything else | no | does not arrive |
|
|
380
|
+
|
|
381
|
+
None of `chat_member`, `chat_join_request`, `message_reaction_count` or the two boost classes raises
|
|
382
|
+
a turn, and none takes an access decision: they are things that happened, with nobody addressing the
|
|
383
|
+
bot, so there is nobody to admit or refuse.
|
|
384
|
+
|
|
385
|
+
**A channel post has no author.** Telegram documents `Message.from` as "may be empty for messages
|
|
386
|
+
sent to channels", so the turn names the channel by its title and there is no person in it. Do not
|
|
387
|
+
address a channel post as if somebody wrote it.
|
|
388
|
+
|
|
389
|
+
**A reaction may never arrive in a DM.** Telegram documents `message_reaction` as requiring the bot
|
|
390
|
+
to be an administrator in the chat, and a private chat has no administrator. The class is registered
|
|
391
|
+
and the handler exists; if nothing ever arrives from a DM, reactions are group-only here.
|
|
392
|
+
|
|
393
|
+
### The `allowed_updates` trap
|
|
394
|
+
|
|
395
|
+
Naming **any** class in `allowed_updates` replaces Telegram's default set. Telegram's default is
|
|
396
|
+
every class except `chat_member`, `message_reaction` and `message_reaction_count` — so a class that
|
|
397
|
+
works today and is missing from the list stops arriving, with no error in any log.
|
|
398
|
+
|
|
399
|
+
Those same three are the ones outside the default, so a bot registered before they were added
|
|
400
|
+
receives none of them until it re-registers. That is not a failure anything reports: the bot simply
|
|
401
|
+
never sees a reaction or a membership change.
|
|
402
|
+
|
|
403
|
+
The list lives in exactly one place, `TELEGRAM_ALLOWED_UPDATES` in
|
|
404
|
+
`platform/lib/telegram-managed-bot/` (re-exported from
|
|
405
|
+
`plugins/telegram/mcp/src/lib/telegram.ts`). Add a class there and nowhere else, and re-register the
|
|
406
|
+
webhook: `allowed_updates` is set at registration, so an existing bot keeps the list it was
|
|
407
|
+
registered with. `telegram-webhook-register` prints
|
|
408
|
+
`op=webhook-allowed … match=yes|no` against what `getWebhookInfo` reports back; `match=no` means
|
|
409
|
+
Telegram registered something narrower than was asked for.
|
|
410
|
+
|
|
411
|
+
The registration test asserts the whole array, not that a particular name is in it, because the
|
|
412
|
+
failure it guards against is a name silently dropped.
|
|
413
|
+
|
|
414
|
+
## Sending to a channel or a group
|
|
415
|
+
|
|
416
|
+
Every send whose chat id you choose is checked before it reaches Telegram. A chat id beginning
|
|
417
|
+
`-100` is a channel or a supergroup — Telegram gives the two the same id shape and nothing local can
|
|
418
|
+
tell them apart — and it is refused unless the operator listed it in that bot's `allowChannels` or
|
|
419
|
+
`allowGroups`. The refusal names the id and both fields, and nothing is sent.
|
|
420
|
+
|
|
421
|
+
This is a refusal, not a retry. A channel post reaches every subscriber and cannot be unsent, so the
|
|
422
|
+
check happens before the network call rather than after Telegram's answer. If you are refused, say
|
|
423
|
+
so plainly and name the id; do not try another tool, and do not reach for `telegram-api` to route
|
|
424
|
+
around it, because the same check applies there on `params.chat_id`.
|
|
425
|
+
|
|
426
|
+
Both lists live on public bot entries only. An admin, specialist or unbound bot reaches no channel
|
|
427
|
+
and no group, in either direction.
|
|
428
|
+
|
|
429
|
+
A private chat id (positive) and a basic group id (negative, no `-100`) are unaffected.
|
|
430
|
+
|
|
431
|
+
## Answering a comment on a channel post
|
|
432
|
+
|
|
433
|
+
Telegram builds a comment thread by auto-forwarding each channel post into the channel's linked
|
|
434
|
+
discussion group. That forwarded copy is the thread root, and it is not a message anybody sent you:
|
|
435
|
+
it raises no turn, because the post itself already reached you through the channel.
|
|
436
|
+
|
|
437
|
+
A comment arrives as an ordinary group message whose turn carries the root's message id. Answer by
|
|
438
|
+
replying beneath that root, not at the bottom of the group, or the answer reads to everyone in the
|
|
439
|
+
thread as no answer at all.
|
|
440
|
+
|
|
441
|
+
A commenter who posted anonymously has no personal identity. The turn names the group they commented
|
|
442
|
+
as, which is the only identity Telegram supplies.
|
|
443
|
+
|
|
238
444
|
## Reading the method list
|
|
239
445
|
|
|
240
446
|
`references/methods.md` carries all 185 names grouped as Telegram documents them: Getting updates,
|
|
@@ -18,12 +18,30 @@ A finished Telegram setup has all of these, and the skill is not done until each
|
|
|
18
18
|
- The bot is stored as one entry in `account.json`'s `telegram.bots` array (under the brand install, never `~/.claude/`). The `telegram-webhook-register` tool writes it there and logs `[telegram-setup] op=token-write dir=… brand=…`.
|
|
19
19
|
- The webhook is registered against a URL whose path is `/api/telegram/` (the only path the maxy edge admits). The register tool refuses any other path and logs `op=webhook-register path=… botId=… account=… admitted=false` when it does.
|
|
20
20
|
- The registered URL carries `bot=<botId>`, the bot's own Telegram id. The register tool derives it from the token and appends it, so you never type it. The receiver requires it and rejects `reason=unknown-bot`; the bot id is what determines the account, so no `account=` is carried.
|
|
21
|
-
- The bot's `role` is stated, not inferred: `admin` or `
|
|
22
|
-
- Access policy is set **on that entry**: an admin bot carries the operator's numeric Telegram user IDs (`adminUsers`); a public bot carries a DM policy (and an allowlist when the policy is `allowlist`). Nothing is shared with the account's other bots.
|
|
23
|
-
- A public bot names the `agent` it answers as, and that agent is active. An admin bot names
|
|
21
|
+
- The bot's `role` is stated, not inferred: `admin`, `public` or `specialist`. It selects the spawn path, so it is a privilege decision. (A bot that arrived through the one-tap path lands as `unbound`, which answers nobody; giving it a role is what finishes it.)
|
|
22
|
+
- Access policy is set **on that entry**: an admin bot carries the operator's numeric Telegram user IDs (`adminUsers`); a public bot carries a DM policy (and an allowlist when the policy is `allowlist`); a specialist bot carries `allowFrom` and nothing else, because there is no open policy for that role. Nothing is shared with the account's other bots.
|
|
23
|
+
- A public bot names the `agent` it answers as, and that agent is active. A specialist bot names the `specialist` card it runs as, and the account has that card. An admin bot names neither: it reads `agents/admin` by construction.
|
|
24
|
+
- If the bot is to work in a **group**, it is a public bot (never an admin or specialist bot), its group privacy mode is on in BotFather before registration, and every group it answers in is listed by chat id on that entry (`groupPolicy: 'allowlist'`, `allowGroups`). An admin bot cannot be used in a group at all.
|
|
25
|
+
- If the bot is to work in a **channel**, it is a public bot for the same reason, it is a channel administrator with post rights, and every channel it reads or posts to is listed by chat id on that entry (`channelPolicy: 'allowlist'`, `allowChannels`). The list gates both directions: a channel not on it is neither read nor posted to. An admin bot cannot be used in a channel at all, and it can no longer post to any group or channel either, in either direction.
|
|
24
26
|
|
|
25
27
|
An account may hold any number of bots. Registering, re-pointing or removing one never disturbs another, in any account.
|
|
26
28
|
|
|
29
|
+
## Two ways in, and the first one is preferred
|
|
30
|
+
|
|
31
|
+
**The one-tap path.** If this account already has a working admin bot, a new bot needs no BotFather
|
|
32
|
+
visit and no token typed anywhere. Call `telegram-bot-provision action=offer` with that admin bot's
|
|
33
|
+
id and the operator's private chat id. They tap the button, name the bot, and this install receives
|
|
34
|
+
it, stores its token, restricts it to its owner and registers its webhook by itself. What arrives is
|
|
35
|
+
a `role:'unbound'` entry that answers nobody; binding it to an agent is the only step left.
|
|
36
|
+
|
|
37
|
+
That path needs the managing bot to have management of other bots enabled **once**, in the
|
|
38
|
+
@BotFather Mini App. No API call turns it on. `offer` checks first and refuses with the Mini App
|
|
39
|
+
named rather than sending a button that would do nothing.
|
|
40
|
+
|
|
41
|
+
**The BotFather path**, below, is still the way in for the first bot on an install, and for a bot
|
|
42
|
+
the operator already owns. Everything after Step 1 applies to it alone: a provisioned bot has
|
|
43
|
+
already had Steps 1, 3, 4 and 5 done for it.
|
|
44
|
+
|
|
27
45
|
## Flow
|
|
28
46
|
|
|
29
47
|
Read `references/setup-guide.md` (cited throughout this flow) with the `plugin-read` tool (`file="references/setup-guide.md"`), which resolves it at the plugin root. A plain `Read` against this skill's base directory misses, because the file lives one level up at the plugin root, not under the skill.
|
|
@@ -32,12 +50,17 @@ Read `references/setup-guide.md` (cited throughout this flow) with the `plugin-r
|
|
|
32
50
|
|
|
33
51
|
Follow `references/setup-guide.md` "Creating a Bot": the operator creates the bot via @BotFather and gives you the token (e.g. `123456:ABC-DEF…`). Confirm you have it before continuing.
|
|
34
52
|
|
|
53
|
+
Skip this step entirely when the account already has a working admin bot: use `telegram-bot-provision action=offer` instead, and no token is ever handled by anyone.
|
|
54
|
+
|
|
35
55
|
### Step 2 — Decide the role, and for a public bot its agent
|
|
36
56
|
|
|
37
57
|
Ask which role this bot serves (see `references/setup-guide.md` "Admin Bot vs Public Bot"). The role is stated by the operator, never worked out from anything else: it decides which spawn path the bot's messages take.
|
|
38
58
|
|
|
39
59
|
- **Admin bot** — only the numeric Telegram user IDs the operator names for THIS bot may message it; everything else is denied. Collect those IDs (`references/setup-guide.md` "Finding Your Telegram User ID"). It answers as the admin agent.
|
|
40
60
|
- **Public bot** — customer-facing; choose a DM policy (`open`, `allowlist`, or `disabled`), for `allowlist` the allowed numeric IDs, and **which of this account's agents answers on it**. Call `account-manage` to list the account's agents and let the operator pick one. The agent must be active; the register tool refuses an inactive or unknown slug.
|
|
61
|
+
- **Specialist bot** — a bot bound to one of the account's own specialist cards, so messaging it runs that specialist with its own prompt and its own tools instead of the admin seat. Collect two things: **which card** (the file name under the account's `specialists/agents/`, without `.md` — that is the name the spawn resolves, not the card's title) and **who may message it** (numeric IDs). Both are required: there is no open policy for this role, because the session carries the card's own tool surface rather than the public zero-tool ringfence.
|
|
62
|
+
|
|
63
|
+
If the operator wants this bot in a **group**, say plainly that groups are a public-bot feature. An admin bot added to a group answers nobody: it would otherwise put the operator's own agent, with the operator's own standing rules and tools, into a room other people read, and every member's messages into its context. There is no setting that changes this.
|
|
41
64
|
|
|
42
65
|
The account may already hold other bots. This one is added alongside them and shares nothing with them.
|
|
43
66
|
|
|
@@ -54,15 +77,62 @@ The register tool aborts on any other path, so do not invent `/channels/telegram
|
|
|
54
77
|
Call `telegram-webhook-register` with:
|
|
55
78
|
- `botToken` — the BotFather token
|
|
56
79
|
- `webhookUrl` — the URL from Step 3
|
|
57
|
-
- `role` — `admin` or `
|
|
80
|
+
- `role` — `admin`, `public` or `specialist`
|
|
58
81
|
- admin bot: `adminUsers` — the numeric IDs from Step 2
|
|
59
82
|
- public bot: `agent` — the slug from Step 2, plus `dmPolicy` and, for `allowlist`, `allowFrom`
|
|
83
|
+
- specialist bot: `specialist` — the card file name from Step 2, plus `allowFrom` (both required)
|
|
84
|
+
|
|
85
|
+
On success the tool has, in this order: verified the token, derived the bot id, set the webhook with a generated secret (written to `~/.<brand>/telegram-secrets/<botId>`), probed Telegram and confirmed no delivery error since the registration, and only then persisted the entry into `account.json`'s `telegram.bots` array. It logs `op=webhook-register admitted=true` + `op=webhook-verify reachable=true` + `op=token-write`. It replaces only the entry with this bot's id, so the account's other bots are untouched. If it returns an error, read it back to the operator verbatim — the common ones are a wrong path (`admitted=false`), a webhook Telegram cannot reach (`op=webhook-verify reachable=false`), a public bot with no or an inactive `agent` (`op=token-write-rejected reason=no-agent|agent-inactive`), a specialist bot with no card, an unknown card or an empty allowlist (`op=token-write-rejected reason=no-specialist|specialist-unknown|no-allowlist`), or a token write blocked outside the brand install.
|
|
86
|
+
|
|
87
|
+
### Step 4a — Groups, when the bot is to work in one
|
|
88
|
+
|
|
89
|
+
Only for a public bot, and only if the operator asked for it. Skip this step entirely otherwise.
|
|
90
|
+
|
|
91
|
+
The outcome is that an allowlisted group can address the bot and gets an answer in that group, and that the bot reads nothing else said in the room.
|
|
92
|
+
|
|
93
|
+
Three things have to be true, and the register tool has already checked the first:
|
|
94
|
+
|
|
95
|
+
- **Group privacy mode is ON in BotFather.** With it off the bot receives every message anyone types in every group it joins. `telegram-webhook-register` refuses such a bot outright and logs `[telegram-webhook] op=group-preflight … canReadAllGroupMessages=true verdict=refused`, naming the BotFather step. With it on, Telegram delivers only commands, @mentions and replies to the bot's own messages, which is why no further "was I being addressed" rule exists anywhere in the code.
|
|
96
|
+
- **The bot is in the group.** A group admin adds it. The install cannot do this and does not try.
|
|
97
|
+
- **The group's chat id is on the entry.** Set `groupPolicy: 'allowlist'` and put the numeric chat id in `allowGroups`. A supergroup id is negative and long, e.g. `-1001234567890`. Until the id is listed, the bot answers nobody in that room and logs `op=group-refused … reason=not-in-allowGroups`.
|
|
98
|
+
|
|
99
|
+
The chat is what is admitted, not its members: once a group is allowlisted, anyone in it can address the bot, including people on no `allowFrom` list. Say that to the operator in those words before they allowlist a room. `dmPolicy` and `allowFrom` govern one-to-one chats only and are never consulted for a group.
|
|
100
|
+
|
|
101
|
+
A group is one conversation, not one per member: everyone in the room shares a single thread and a single session, and each turn names who spoke.
|
|
102
|
+
|
|
103
|
+
## Setting a bot up in a channel
|
|
104
|
+
|
|
105
|
+
The outcome is that a post in an allowlisted channel reaches the agent, that the agent can post to
|
|
106
|
+
that channel and no other, and that comments on a post can be attributed and answered.
|
|
107
|
+
|
|
108
|
+
Three things have to be true:
|
|
109
|
+
|
|
110
|
+
- **The bot is a channel administrator, with post rights.** A channel admin adds it and grants
|
|
111
|
+
"Post Messages". The install cannot do this and does not try. Without the post right the bot still
|
|
112
|
+
reads posts but every send fails, which from the agent's side is indistinguishable from a channel
|
|
113
|
+
nobody reads.
|
|
114
|
+
- **The channel's chat id is on the entry.** Set `channelPolicy: 'allowlist'` and put the numeric
|
|
115
|
+
chat id in `allowChannels`. A channel id is negative and long, e.g. `-1001234567890`. Until the id
|
|
116
|
+
is listed, no post from that channel reaches the agent (`op=channel-refused …
|
|
117
|
+
reason=not-in-allowChannels`) and no send to it leaves the install.
|
|
118
|
+
- **For comments, the channel has a linked discussion group,** and that group is allowlisted too
|
|
119
|
+
(`groupPolicy`, `allowGroups`). Telegram builds comment threads by auto-forwarding each post into
|
|
120
|
+
the linked group; without the link there is nothing to comment on and nothing to answer in.
|
|
121
|
+
|
|
122
|
+
The list gates **both directions**. That is the difference from a group, and it is deliberate: a
|
|
123
|
+
channel post reaches every subscriber and cannot be unsent, so a send to a channel outside
|
|
124
|
+
`allowChannels` is refused before it reaches Telegram, and the refusal names both list fields.
|
|
125
|
+
|
|
126
|
+
Say this to the operator in these words before they allowlist a channel: the agent will be able to
|
|
127
|
+
post to it, and a post cannot be taken back.
|
|
60
128
|
|
|
61
|
-
|
|
129
|
+
A channel post has no author. Telegram sends no sender for it, so the turn names the channel by its
|
|
130
|
+
title. A comment does have an author, unless the person commented anonymously, in which case the
|
|
131
|
+
turn names the group they commented as.
|
|
62
132
|
|
|
63
133
|
### Step 5 — Confirm
|
|
64
134
|
|
|
65
|
-
Tell the operator the bot is connected, which role it has, and that messaging the bot now reaches the agent and a reply returns. For a public bot, name the agent that will respond. If the account holds other bots, say that this one is separate from them: its own people, its own agent, its own conversations.
|
|
135
|
+
Tell the operator the bot is connected, which role it has, and that messaging the bot now reaches the agent and a reply returns. For a public bot, name the agent that will respond; for a specialist bot, name the card and say the conversation stays the same one across days. If the account holds other bots, say that this one is separate from them: its own people, its own agent, its own conversations.
|
|
66
136
|
|
|
67
137
|
## Failure modes (state these loudly, do not paper over)
|
|
68
138
|
|
|
@@ -76,6 +146,17 @@ Tell the operator the bot is connected, which role it has, and that messaging th
|
|
|
76
146
|
- **One bot id claimed by two accounts** — inbound is refused `[telegram-inbound] op=reject reason=duplicate-bot-id`, and the standing `[telegram-audit] op=duplicate-bot-id` names it every tick. Two accounts hold the same token. Remove it from the one that should not have it; nothing picks between them.
|
|
77
147
|
- **Chat id claimed by two bots** — a scheduled dispatch logs `[schedule-inject] op=telegram-destination-ambiguous … dispatched=no`. Two bots, in one account or two, list the same numeric ID in their `adminUsers`. Remove it from the one that should not have it; the dispatch refuses rather than guessing which bot the person should hear from.
|
|
78
148
|
- **A secret file with no bot, or a bot with no secret file** — `[telegram-audit] op=secret-orphan botId=… side=file|entry`. Neither shows up any other way. `side=entry` means that bot cannot receive anything until it re-registers; `side=file` is left-over state from a bot that has been removed.
|
|
149
|
+
- **Group privacy mode off at registration** — register returns an error naming BotFather's Group Privacy setting and logs `op=group-preflight … verdict=refused`. Nothing was registered and nothing written. Turn privacy on, then register again.
|
|
150
|
+
- **The bot cannot be added to groups** — the same refusal, naming BotFather's "Allow Groups?" setting instead.
|
|
151
|
+
- **Admin bot in a group** — `[telegram-inbound] op=group-refused … reason=admin-entry-no-groups`, and no turn runs. This is not a misconfiguration to fix; the admin persona never enters a group. Use a public bot for the room.
|
|
152
|
+
- **Group not allowlisted** — `op=group-refused … reason=not-in-allowGroups` (the id is missing from `allowGroups`) or `reason=group-policy-disabled` (the entry has no `groupPolicy: 'allowlist'` at all). Both are silent to everyone in the room, so check the log rather than assuming the bot is broken.
|
|
153
|
+
- **Privacy mode turned off AFTER registration** — nothing fails and no update says so; the bot simply starts reading every message in the room. The hourly `[telegram-audit] op=group-census … privacyOff=<n>` is the only thing that reports it. `privacyOff>0` needs the BotFather setting turned back on.
|
|
154
|
+
- **Bot removed from a group** — every later send fails and no inbound arrives again. `op=chat-member-group … status=kicked` catches it live; if the install was down when it happened, the hourly `op=group-census … absent=<n>` is what surfaces it. Read `bots=` and `groups=` on that line before trusting `absent=0`: zero absent out of zero groups is an install with no groups, not a healthy one.
|
|
155
|
+
- **Admin or specialist bot in a channel** — `[telegram-inbound] op=channel-refused … reason=admin-entry-no-channels` (or `specialist-entry-no-channels`, or `unbound-entry-no-channels`), and no turn runs. Not a misconfiguration to fix; those personas never enter a channel. Use a public bot.
|
|
156
|
+
- **Channel not allowlisted** — `op=channel-refused … reason=not-in-allowChannels` (the id is missing from `allowChannels`) or `reason=channel-policy-disabled` (the entry has no `channelPolicy: 'allowlist'` at all). Both are silent to every subscriber, so read the log rather than assuming the bot is broken. The same two states also refuse every send, logged as `[telegram-outbound] op=channel-send … allowed=no reason=not-in-allowChannels`.
|
|
157
|
+
- **Agent says it cannot post to a channel or group** — the id is on neither `allowChannels` nor `allowGroups`. Both lists exist on public entries only, so an admin, specialist or unbound bot can never post to any channel or group. The refusal names the id and both fields.
|
|
158
|
+
- **Bot loses its post rights, or is demoted in a channel** — every later send fails one at a time and nothing announces it. The hourly `[telegram-audit] op=channel-census … admin=<n> notAdmin=<n> noPostRight=<n>` is the only thing that reports it. `noPostRight>0` means the bot is still an administrator but cannot post; `notAdmin>0` means it is no longer an administrator at all. Read `bots=` and `channels=` before trusting either zero: zero out of zero channels is an install with no channels, not a healthy one.
|
|
159
|
+
- **Comments arrive but answers land in the wrong place** — the reply must sit beneath the auto-forwarded root post, whose id the turn carries. `op=channel-comment-root … rootMessageId=<id>` is the record of that id; a thread with no root line is a thread whose comments point nowhere, which means the discussion group is not linked or not allowlisted.
|
|
79
160
|
|
|
80
161
|
## Language
|
|
81
162
|
|
|
@@ -12,6 +12,18 @@ The agent has **no tool to initiate a WhatsApp message to an arbitrary number.**
|
|
|
12
12
|
|
|
13
13
|
What the agent **can** still do: reply within an existing chat. **The `reply` and `reply-document` tools are retired**; the agent no longer chooses to deliver. Its answer is the text its turn ends with, read from the session record and sent by the gateway, split into separate messages on any line that is exactly `[[next]]`. A scheduled turn delivers the same way, so a scheduled turn with nothing to report must end with no text at all. Files go through `SendUserFile`, caught by a read-only JSONL follower on the session and funnelled through `sendWhatsAppDocument`, the one send core that owns path validation, the 100 MB ceiling, the canonical log, and per-file reconciliation. Delivery stays reply-only by construction: the follower runs only for an admin session and its recipient is fixed when the session spawns, so there is no recipient the agent can name. (The removed `whatsapp-send-document` route tool and the bridge path `SendUserFile` → `file-delivery-bridge.ts` → `POST /api/whatsapp/send-document` are the legacy webchat/email bridge surface, not the native WhatsApp channel.) Replying within your chats is what WhatsApp permits; starting new chats from a linked device is what it penalises.
|
|
14
14
|
|
|
15
|
+
The operator-facing half of this rule now also lives in the admin identity, under its `## Channel reality` section. This page loads only with the WhatsApp skill, and on 2026-08-09 an admin turn that had not loaded it filled the gap from model priors and offered a cold send three times. The identity states which channels can start a conversation and with whom; this page stays the authority on why WhatsApp cannot. A change to either belongs in both.
|
|
16
|
+
|
|
17
|
+
## The channel-suggestion clause
|
|
18
|
+
|
|
19
|
+
The platform arm of this door's turn wrapper — `REFRAME_INSTRUCTION` in `platform/services/whatsapp-channel/src/notification.ts`, the body of a turn the operator authored from their own handset or the scheduler — ends with a clause telling the agent that when the turn wanted something this door cannot do (a button, an in-place card, a poll or checklist, a map pin, a photo or album, an invoice, a reply in a group, an edit to a message already sent, or a message to someone not already registered) it names the missing thing, says Telegram has it, and offers to set it up. It is conditioned on the turn: when this door served the request, the agent never raises another door, which is what stops it becoming a nag without needing a per-sender counter.
|
|
20
|
+
|
|
21
|
+
It exists because Telegram's own wrapper gained a paragraph naming its surfaces and no counterpart was possible here, so on the weaker door the agent answered in prose and never said a better door existed.
|
|
22
|
+
|
|
23
|
+
**WhatsApp-only, and it offers no counterweight.** A public visitor's turn takes the account arm and never reads this constant. The two twins' tests assert the clause's absence, so copying it across fails there. Three counterweights were drafted and each was struck on evidence: there is no outbound reach on this door at all and the paired number is a dedicated line no contact already holds; Telegram runs the same whisper wrapper, so the voice-note transcript is not this door's alone; and both doors gate inbound on the same `dmPolicy`. A clause that invents an advantage here is the defect it exists to close, and its test asserts all three are absent.
|
|
24
|
+
|
|
25
|
+
**How to see it.** The `[reframe] op=applied` line carries `arm=<platform|account|webchat>` and `suggestClause=<bool>`, both read back off the composed body rather than off the branch the composer meant to take. `arm=platform suggestClause=false` means the constant shipped without the clause; `arm=account suggestClause=true`, or any `suggestClause=true` on a webchat line, is a leak. Whether it ever converts anyone has no event of its own, so the hourly `[channel-suggest-census]` counts the state instead: `accountsWaOnly` flat over weeks while `waOperatorTurns` climbs is the signal. It is a proxy and never proof of causation — an operator who reads the clause and decides against Telegram is a correct outcome that moves the number not at all.
|
|
26
|
+
|
|
15
27
|
## Per-account observe socket (account manager)
|
|
16
28
|
|
|
17
29
|
Each sub-account can pair its own WhatsApp number as a linked device, separate from the house socket. This is intended for an account manager's phone: the agent reads that WhatsApp, but the phone's inbound is never treated as instructions to the agent.
|
package/payload/platform/services/claude-session-manager/dist/account-dir-schema-reconcile.d.ts
CHANGED
|
@@ -43,15 +43,46 @@ export interface ReconcileDeps {
|
|
|
43
43
|
* account has settings reports hooks-missing=0 and reads as fenced.
|
|
44
44
|
*
|
|
45
45
|
* The matcher is compared for equality, which is the shape
|
|
46
|
-
* provision-account-dir.sh writes for
|
|
47
|
-
* same effect another way — a matcher-less catch-all entry, or a
|
|
48
|
-
* alternation — reads as missing here. That is intended: what this audits
|
|
49
|
-
* whether the account carries the provisioned fence, and drift from the
|
|
50
|
-
* is worth a line even when it happens to be equivalent.
|
|
46
|
+
* provision-account-dir.sh writes for the five tool rows. A settings file that
|
|
47
|
+
* reaches the same effect another way — a matcher-less catch-all entry, or a
|
|
48
|
+
* regex alternation — reads as missing here. That is intended: what this audits
|
|
49
|
+
* is whether the account carries the provisioned fence, and drift from the
|
|
50
|
+
* template is worth a line even when it happens to be equivalent.
|
|
51
|
+
*
|
|
52
|
+
* A row with a null matcher inverts that test to "no matcher key at all", which
|
|
53
|
+
* is the shape account-settings.json writes for every UserPromptSubmit hook. The
|
|
54
|
+
* rule is the same in both directions: match the template exactly.
|
|
51
55
|
*/
|
|
52
56
|
export declare function hookRegistration(accountDir: string): {
|
|
53
57
|
missing: string[];
|
|
54
58
|
} | null;
|
|
59
|
+
/**
|
|
60
|
+
* Per-account count of the entity folders and their child folders.
|
|
61
|
+
*
|
|
62
|
+
* The archive exception widened the guard's depth rule, and a rule that is too
|
|
63
|
+
* wide produces NO event: a successful write emits nothing, so an entity folder
|
|
64
|
+
* quietly growing a second subtree on some route is invisible. `stray` above zero
|
|
65
|
+
* is that signature.
|
|
66
|
+
*
|
|
67
|
+
* `entities` rides the same line because `stray=0` alone cannot tell a clean
|
|
68
|
+
* account from a walker that read nothing: `entities=0` on an account that holds
|
|
69
|
+
* entity folders is the not-measuring reading, and the two are indistinguishable
|
|
70
|
+
* without the denominator.
|
|
71
|
+
*
|
|
72
|
+
* Directories only; files are not counted. Dot-prefixed entries are skipped at
|
|
73
|
+
* both levels, because SCHEMA.md's name rule exempts them at every level and the
|
|
74
|
+
* write guard skips them too: counting one as a stray would raise a standing
|
|
75
|
+
* alarm about an entry the rules permit.
|
|
76
|
+
*
|
|
77
|
+
* A bucket that does not exist, or a child that cannot be stat'd, contributes
|
|
78
|
+
* nothing rather than throwing: the caller already swallows per-account errors,
|
|
79
|
+
* and a partial count is worth more than a dropped line.
|
|
80
|
+
*/
|
|
81
|
+
export declare function entitySubdirs(accountDir: string): {
|
|
82
|
+
entities: number;
|
|
83
|
+
archive: number;
|
|
84
|
+
stray: number;
|
|
85
|
+
};
|
|
55
86
|
/** One reconcile pass over every account under the accounts root: one op=strays
|
|
56
87
|
* line naming the unaccounted-for entries of each account that has any, then the
|
|
57
88
|
* single summary line. An account is any child dir with an account.json (the
|
package/payload/platform/services/claude-session-manager/dist/account-dir-schema-reconcile.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account-dir-schema-reconcile.d.ts","sourceRoot":"","sources":["../src/account-dir-schema-reconcile.ts"],"names":[],"mappings":"AA8EA,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,MAAM,CAAA;IACrB,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD;;;;;0CAKsC;IACtC,UAAU,EAAE,MAAM,EAAE,CAAA;CACrB;AAED;;+DAE+D;AAC/D,wBAAgB,mBAAmB,CACjC,CAAC,EAAE,eAAe,EAClB,WAAW,SAAI,EACf,aAAa,SAAI,EACjB,UAAU,SAAI,EACd,YAAY,SAAI,EAChB,cAAc,SAAI,GACjB,MAAM,CAIR;AAED;;8EAE8E;AAC9E,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAcpE;AA+ED;;;8EAG8E;AAC9E,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,CAoCpE;AAED,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAA;IACpB,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CAC/B;
|
|
1
|
+
{"version":3,"file":"account-dir-schema-reconcile.d.ts","sourceRoot":"","sources":["../src/account-dir-schema-reconcile.ts"],"names":[],"mappings":"AA8EA,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,MAAM,CAAA;IACrB,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD;;;;;0CAKsC;IACtC,UAAU,EAAE,MAAM,EAAE,CAAA;CACrB;AAED;;+DAE+D;AAC/D,wBAAgB,mBAAmB,CACjC,CAAC,EAAE,eAAe,EAClB,WAAW,SAAI,EACf,aAAa,SAAI,EACjB,UAAU,SAAI,EACd,YAAY,SAAI,EAChB,cAAc,SAAI,GACjB,MAAM,CAIR;AAED;;8EAE8E;AAC9E,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAcpE;AA+ED;;;8EAG8E;AAC9E,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,CAoCpE;AAED,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAA;IACpB,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CAC/B;AA8ED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,IAAI,CAgCjF;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAuCtG;AAED;;;;;;;;;;;;;iCAaiC;AACjC,wBAAgB,YAAY,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,CAsFtD;AAED,MAAM,WAAW,yBAAyB;IACxC,KAAK,IAAI,IAAI,CAAA;IACb,IAAI,IAAI,IAAI,CAAA;CACb;AAED;oDACoD;AACpD,wBAAgB,+BAA+B,CAC7C,IAAI,EAAE,aAAa,GAAG;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,GAC3C,yBAAyB,CAiB3B"}
|