@rubytech/create-maxy-code 0.1.582 → 0.1.584
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 +86 -0
- package/payload/platform/lib/telegram-reach/dist/index.d.ts.map +1 -0
- package/payload/platform/lib/telegram-reach/dist/index.js +246 -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 +268 -0
- package/payload/platform/lib/telegram-reach/src/index.ts +296 -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 +146 -8
- package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +16 -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 +17 -3
- package/payload/platform/plugins/docs/references/channel-wake-and-prompt.md +15 -0
- package/payload/platform/plugins/docs/references/telegram-guide.md +113 -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/scheduling/PLUGIN.md +8 -2
- 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/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 +30 -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 +112 -39
- 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/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__/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-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-update.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.js +29 -1
- 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/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/telegram/PLUGIN.md +46 -9
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/api-census.test.js +25 -11
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/api-census.test.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/api-guard.test.js +67 -5
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/api-guard.test.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/api-methods.test.js +9 -3
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/api-methods.test.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/ask-tool.test.js +87 -3
- 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 +184 -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 +106 -0
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/reach-tool.test.js.map +1 -0
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/schemas.test.js +2 -31
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/schemas.test.js.map +1 -1
- 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 +178 -2
- package/payload/platform/plugins/telegram/mcp/dist/__tests__/webhook-register.test.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/index.js +22 -8
- 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 +21 -19
- 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 +44 -36
- 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 +11 -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 +24 -4
- 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 +11 -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 +54 -2
- package/payload/platform/plugins/telegram/mcp/dist/lib/api-guard.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/lib/api-methods.d.ts +0 -3
- package/payload/platform/plugins/telegram/mcp/dist/lib/api-methods.d.ts.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/lib/api-methods.js +0 -1
- package/payload/platform/plugins/telegram/mcp/dist/lib/api-methods.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/lib/business-window-store.d.ts +58 -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 +125 -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 +55 -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 +91 -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 -53
- 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 -94
- 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 +27 -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 +31 -1
- 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 +72 -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 +17 -68
- package/payload/platform/plugins/telegram/mcp/dist/tools/schemas.d.ts.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/tools/schemas.js +30 -90
- 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 +59 -4
- package/payload/platform/plugins/telegram/mcp/dist/tools/webhook-register.js.map +1 -1
- package/payload/platform/plugins/telegram/skills/build/SKILL.md +155 -40
- package/payload/platform/plugins/telegram/skills/build/references/methods.md +3 -13
- 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 -1
- 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 +13 -0
- package/payload/platform/services/telegram-channel/dist/notification.d.ts.map +1 -1
- package/payload/platform/services/telegram-channel/dist/notification.js +13 -2
- 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-AnJZfgFz.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-CEVqyQqg.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-czUaUl8I.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-B0iRcfuk.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-BocONCeQ.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-Cy-rJm3t.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-DUTKxWtd.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-DE9qmAs5.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-DE2tEfTo.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-BHfL2gqo.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-08S_BofN.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-C640Er5R.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-FxjwOUbA.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-FxjwOUbA.css.gz → jsx-runtime-rMaiYjNu.css.gz} +0 -0
- package/payload/server/public/assets/{operator-DH5Kw3fL.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-BDpa4HWT.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-yn7ivq8O.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-D_qjqet7.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-Ixkq1iUA.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-Cxjlmcp7.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-DEo9hSVX.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-BxApOIXI.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-BYzMcXv8.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-Bk2HVcjy.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-DEti-vAx.js → useMediaQuery-B469O83-.js} +1 -1
- package/payload/server/public/assets/useMediaQuery-B469O83-.js.br +0 -0
- package/payload/server/public/assets/{useMediaQuery-DEti-vAx.js.gz → useMediaQuery-B469O83-.js.gz} +0 -0
- package/payload/server/public/assets/{useVoiceRecorder-kQ92rL-f.js → useVoiceRecorder-Bb-51cJv.js} +1 -1
- 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-BhLkHffv.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 +15 -15
- 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 +3114 -1371
- package/payload/server/public/assets/AdminLoginScreens-AnJZfgFz.js.br +0 -0
- package/payload/server/public/assets/AdminLoginScreens-AnJZfgFz.js.gz +0 -0
- package/payload/server/public/assets/AdminShell-CEVqyQqg.js.br +0 -0
- package/payload/server/public/assets/AdminShell-CEVqyQqg.js.gz +0 -0
- package/payload/server/public/assets/activity-czUaUl8I.js.br +0 -0
- package/payload/server/public/assets/activity-czUaUl8I.js.gz +0 -0
- package/payload/server/public/assets/admin-B0iRcfuk.js.br +0 -0
- package/payload/server/public/assets/admin-B0iRcfuk.js.gz +0 -0
- package/payload/server/public/assets/agents-BocONCeQ.js.br +0 -0
- package/payload/server/public/assets/agents-BocONCeQ.js.gz +0 -0
- package/payload/server/public/assets/browser-Cy-rJm3t.js.br +0 -0
- package/payload/server/public/assets/browser-Cy-rJm3t.js.gz +0 -0
- package/payload/server/public/assets/calendar-DUTKxWtd.js.br +0 -0
- package/payload/server/public/assets/calendar-DUTKxWtd.js.gz +0 -0
- package/payload/server/public/assets/chat-Cis7sHsZ.js +0 -1
- package/payload/server/public/assets/chat-Cis7sHsZ.js.br +0 -0
- package/payload/server/public/assets/chat-Cis7sHsZ.js.gz +0 -0
- package/payload/server/public/assets/chevron-left-Bhhx8j2r.js +0 -1
- package/payload/server/public/assets/chevron-left-Bhhx8j2r.js.br +0 -0
- package/payload/server/public/assets/clock-Ca3nx7Cc.js +0 -1
- package/payload/server/public/assets/clock-Ca3nx7Cc.js.br +0 -0
- package/payload/server/public/assets/clock-Ca3nx7Cc.js.gz +0 -0
- package/payload/server/public/assets/copy-DE9qmAs5.js.br +0 -0
- package/payload/server/public/assets/copy-DE9qmAs5.js.gz +0 -0
- package/payload/server/public/assets/data-CkaAEeP1.js +0 -1
- package/payload/server/public/assets/data-CkaAEeP1.js.br +0 -0
- package/payload/server/public/assets/data-CkaAEeP1.js.gz +0 -0
- package/payload/server/public/assets/field-DE2tEfTo.js.br +0 -0
- package/payload/server/public/assets/field-DE2tEfTo.js.gz +0 -0
- package/payload/server/public/assets/file-text-BHfL2gqo.js.br +0 -0
- package/payload/server/public/assets/file-text-BHfL2gqo.js.gz +0 -0
- package/payload/server/public/assets/graph-08S_BofN.js.br +0 -0
- package/payload/server/public/assets/graph-08S_BofN.js.gz +0 -0
- package/payload/server/public/assets/graph-labels-C640Er5R.js.br +0 -0
- package/payload/server/public/assets/graph-labels-C640Er5R.js.gz +0 -0
- package/payload/server/public/assets/jsx-runtime-FxjwOUbA.css.br +0 -0
- package/payload/server/public/assets/operator-DH5Kw3fL.js.br +0 -0
- package/payload/server/public/assets/operator-DH5Kw3fL.js.gz +0 -0
- package/payload/server/public/assets/page-BDpa4HWT.js.br +0 -0
- package/payload/server/public/assets/page-BDpa4HWT.js.gz +0 -0
- package/payload/server/public/assets/page-yn7ivq8O.js.br +0 -0
- package/payload/server/public/assets/page-yn7ivq8O.js.gz +0 -0
- package/payload/server/public/assets/play-CMN7ht-S.js +0 -1
- package/payload/server/public/assets/play-CMN7ht-S.js.br +0 -0
- package/payload/server/public/assets/play-CMN7ht-S.js.gz +0 -0
- package/payload/server/public/assets/public-D_qjqet7.js.br +0 -0
- package/payload/server/public/assets/public-D_qjqet7.js.gz +0 -0
- package/payload/server/public/assets/rotate-ccw-Ixkq1iUA.js.br +0 -0
- package/payload/server/public/assets/rotate-ccw-Ixkq1iUA.js.gz +0 -0
- package/payload/server/public/assets/routines-Cxjlmcp7.js.br +0 -0
- package/payload/server/public/assets/routines-Cxjlmcp7.js.gz +0 -0
- package/payload/server/public/assets/skills-DEo9hSVX.js.br +0 -0
- package/payload/server/public/assets/skills-DEo9hSVX.js.gz +0 -0
- package/payload/server/public/assets/tasks-BxApOIXI.js.br +0 -0
- package/payload/server/public/assets/tasks-BxApOIXI.js.gz +0 -0
- package/payload/server/public/assets/triangle-alert-BYzMcXv8.js.br +0 -0
- package/payload/server/public/assets/triangle-alert-BYzMcXv8.js.gz +0 -0
- package/payload/server/public/assets/useCopyFeedback-Bk2HVcjy.js.br +0 -0
- package/payload/server/public/assets/useCopyFeedback-Bk2HVcjy.js.gz +0 -0
- package/payload/server/public/assets/useMediaQuery-DEti-vAx.js.br +0 -0
- package/payload/server/public/assets/useVoiceRecorder-kQ92rL-f.js.br +0 -0
- package/payload/server/public/assets/useVoiceRecorder-kQ92rL-f.js.gz +0 -0
- package/payload/server/public/assets/wrench-BhLkHffv.js.br +0 -0
- package/payload/server/public/assets/wrench-BhLkHffv.js.gz +0 -0
- /package/payload/server/public/assets/{jsx-runtime-BL3pljPe.js → jsx-runtime-BmNepPEn.js} +0 -0
- /package/payload/server/public/assets/{jsx-runtime-BL3pljPe.js.br → jsx-runtime-BmNepPEn.js.br} +0 -0
- /package/payload/server/public/assets/{jsx-runtime-BL3pljPe.js.gz → jsx-runtime-BmNepPEn.js.gz} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhook-register.d.ts","sourceRoot":"","sources":["../../src/tools/webhook-register.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"webhook-register.d.ts","sourceRoot":"","sources":["../../src/tools/webhook-register.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,YAAY,CAAC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;8DAC0D;IAC1D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,UAAU,CAAC;IAC7C,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC;IACtB,+EAA+E;IAC/E,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;CAC3C;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;CAClB;AAID;;;;;;;uBAOuB;AACvB,wBAAsB,eAAe,CACnC,MAAM,EAAE,qBAAqB,EAC7B,IAAI,EAAE,mBAAmB,GACxB,OAAO,CAAC,qBAAqB,CAAC,CAmPhC"}
|
|
@@ -3,7 +3,7 @@ import { dirname } from "node:path";
|
|
|
3
3
|
import { admitsWebhookPath, botIdFromToken, persistTelegramBot, CANONICAL_TELEGRAM_PREFIX, } from "../lib/account-write.js";
|
|
4
4
|
import { setWebhook, getWebhookInfo, webhookVerdict, TELEGRAM_ALLOWED_UPDATES } from "../lib/telegram.js";
|
|
5
5
|
import { configDirName, resolveSecretFilePath } from "../lib/secret-path.js";
|
|
6
|
-
import { accountDirFor, isActiveAgentSlug } from "../lib/agent-active.js";
|
|
6
|
+
import { accountDirFor, isActiveAgentSlug, listSpecialistCardNames } from "../lib/agent-active.js";
|
|
7
7
|
import { buildWebhookUrl } from "../lib/webhook-url.js";
|
|
8
8
|
const TAG = "[telegram-setup]";
|
|
9
9
|
const fail = (text) => ({ text, isError: true });
|
|
@@ -16,7 +16,7 @@ const fail = (text) => ({ text, isError: true });
|
|
|
16
16
|
* The persist runs LAST: a registration that cannot be proved reachable leaves
|
|
17
17
|
* nothing on disk. */
|
|
18
18
|
export async function webhookRegister(params, deps) {
|
|
19
|
-
const { botToken, webhookUrl, role, agent, adminUsers, dmPolicy, allowFrom } = params;
|
|
19
|
+
const { botToken, webhookUrl, role, agent, specialist, adminUsers, dmPolicy, allowFrom } = params;
|
|
20
20
|
const { platformRoot, accountId, log } = deps;
|
|
21
21
|
const fetchImpl = deps.fetchImpl ?? fetch;
|
|
22
22
|
const nowSec = deps.nowSec ?? (() => Math.floor(Date.now() / 1000));
|
|
@@ -50,6 +50,26 @@ export async function webhookRegister(params, deps) {
|
|
|
50
50
|
return fail(`Agent "${agent}" is not an active agent on this account, so a bot cannot answer as it.`);
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
|
+
// Task 2619 — a specialist bot names the card it runs as and the ids allowed
|
|
54
|
+
// to message it. Both are required. There is no `open` policy for this role,
|
|
55
|
+
// so an empty allowlist would register a bot nobody can reach; and an
|
|
56
|
+
// unresolvable card would register a bot that refuses every message it ever
|
|
57
|
+
// receives, silently, because nothing announces a card being renamed.
|
|
58
|
+
if (role === "specialist") {
|
|
59
|
+
if (!specialist || specialist.length === 0) {
|
|
60
|
+
log(`${TAG} op=token-write-rejected reason=no-specialist botId=${botId}`);
|
|
61
|
+
return fail(`A specialist bot must name the specialist it runs as. Pass \`specialist\` with one of this account's specialist card names.`);
|
|
62
|
+
}
|
|
63
|
+
const cards = listSpecialistCardNames(accountDirFor(platformRoot, accountId));
|
|
64
|
+
if (!cards.includes(specialist)) {
|
|
65
|
+
log(`${TAG} op=token-write-rejected reason=specialist-unknown botId=${botId} specialist=${specialist}`);
|
|
66
|
+
return fail(`"${specialist}" is not a specialist on this account, so a bot cannot run as it. This account has: ${cards.join(", ") || "none"}.`);
|
|
67
|
+
}
|
|
68
|
+
if (!allowFrom || allowFrom.length === 0) {
|
|
69
|
+
log(`${TAG} op=token-write-rejected reason=no-allowlist botId=${botId}`);
|
|
70
|
+
return fail(`A specialist bot needs a list of who may message it. Pass \`allowFrom\` with the numeric Telegram user IDs allowed to reach it; there is no open policy for this role.`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
53
73
|
// Task 2560 — exactly one path reaches the handler. Asserted before Telegram
|
|
54
74
|
// is touched, so a refused path leaves no registration behind.
|
|
55
75
|
const webhookPath = (() => {
|
|
@@ -80,6 +100,36 @@ export async function webhookRegister(params, deps) {
|
|
|
80
100
|
return fail(`Invalid bot token: ${meData.description ?? "getMe failed"}`);
|
|
81
101
|
}
|
|
82
102
|
const botUsername = meData.result?.username ?? "unknown";
|
|
103
|
+
// Task 2616 — the group pre-flight, BEFORE the freshness stamp, so a refused
|
|
104
|
+
// bot leaves no registration behind and nothing on disk. That order is Task
|
|
105
|
+
// 2560's.
|
|
106
|
+
//
|
|
107
|
+
// Privacy mode is what keeps a bot in a room to commands, @mentions and
|
|
108
|
+
// replies. With it off the bot receives every message anyone types in every
|
|
109
|
+
// group it is in, and nothing else on this install would say so: no update
|
|
110
|
+
// names the setting and the flood reads as ordinary traffic.
|
|
111
|
+
//
|
|
112
|
+
// A flag Telegram did not send refuses nothing and prints `absent`, never
|
|
113
|
+
// `false`: `false` would claim Telegram had told us privacy was on when it
|
|
114
|
+
// had told us nothing, and this line is the only standing record of what it
|
|
115
|
+
// said at registration time.
|
|
116
|
+
const rawReadAll = meData.result?.can_read_all_group_messages;
|
|
117
|
+
const rawJoin = meData.result?.can_join_groups;
|
|
118
|
+
const say = (v) => (v === undefined ? "absent" : String(v));
|
|
119
|
+
const privacyOff = rawReadAll === true;
|
|
120
|
+
const cannotJoin = rawJoin === false;
|
|
121
|
+
const groupVerdict = privacyOff || cannotJoin ? "refused" : "ok";
|
|
122
|
+
log(`[telegram-webhook] op=group-preflight botId=${botId} canJoinGroups=${say(rawJoin)} ` +
|
|
123
|
+
`canReadAllGroupMessages=${say(rawReadAll)} verdict=${groupVerdict}`);
|
|
124
|
+
if (privacyOff) {
|
|
125
|
+
return fail(`@${botUsername} has group privacy mode OFF, so in any group it joins it would receive every ` +
|
|
126
|
+
`message anyone types. In BotFather: /mybots, pick this bot, Bot Settings, Group Privacy, ` +
|
|
127
|
+
`Turn on. Then register again. Nothing was registered or written.`);
|
|
128
|
+
}
|
|
129
|
+
if (cannotJoin) {
|
|
130
|
+
return fail(`@${botUsername} cannot be added to groups. In BotFather: /mybots, pick this bot, Bot Settings, ` +
|
|
131
|
+
`Allow Groups?, Turn on. Then register again. Nothing was registered or written.`);
|
|
132
|
+
}
|
|
83
133
|
// Stamped immediately before registering: the probe below only treats an
|
|
84
134
|
// error Telegram saw AT OR AFTER this moment as this registration's.
|
|
85
135
|
const registeredAtSec = nowSec();
|
|
@@ -130,7 +180,9 @@ export async function webhookRegister(params, deps) {
|
|
|
130
180
|
// failure here means nothing was persisted.
|
|
131
181
|
const entry = role === "admin"
|
|
132
182
|
? { id: botId, token: botToken, role: "admin", ...(adminUsers ? { adminUsers } : {}) }
|
|
133
|
-
:
|
|
183
|
+
: role === "specialist"
|
|
184
|
+
? { id: botId, token: botToken, role: "specialist", specialist: specialist, allowFrom: allowFrom }
|
|
185
|
+
: { id: botId, token: botToken, role: "public", agent: agent, ...(dmPolicy ? { dmPolicy } : {}), ...(allowFrom ? { allowFrom } : {}) };
|
|
134
186
|
const persisted = persistTelegramBot(platformRoot, accountId, entry);
|
|
135
187
|
if (!persisted.ok) {
|
|
136
188
|
log(`${TAG} op=token-write-rejected reason=${persisted.error}${persisted.dir ? ` dir=${persisted.dir}` : ""}`);
|
|
@@ -144,7 +196,10 @@ export async function webhookRegister(params, deps) {
|
|
|
144
196
|
// shape. This tool no longer deletes anything of its own.
|
|
145
197
|
return {
|
|
146
198
|
isError: false,
|
|
147
|
-
text: `Webhook registered for @${botUsername} (bot ${botId}, role ${role}
|
|
199
|
+
text: `Webhook registered for @${botUsername} (bot ${botId}, role ${role}` +
|
|
200
|
+
(role === "public" ? `, answering as ${agent}` : "") +
|
|
201
|
+
(role === "specialist" ? `, running ${specialist} for ${allowFrom.length} allowed user(s)` : "") +
|
|
202
|
+
`)` +
|
|
148
203
|
`\nURL: ${registeredUrl}` +
|
|
149
204
|
`\nSecret: generated and saved to ${secretFilePath}` +
|
|
150
205
|
verifyInfo,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhook-register.js","sourceRoot":"","sources":["../../src/tools/webhook-register.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,kBAAkB,EAClB,yBAAyB,GAE1B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAC1G,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC7E,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"webhook-register.js","sourceRoot":"","sources":["../../src/tools/webhook-register.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: build
|
|
3
|
-
description: Build your own Telegram functionality on this install — cards with buttons, editing a card in place, answering a button press, opening a Mini App inside the chat, sending and fetching files, polls and locations,
|
|
3
|
+
description: Build your own Telegram functionality on this install — cards with buttons, editing a card in place, answering a button press, opening a Mini App inside the chat, sending and fetching files, polls and locations, threading a chat per job, and reaching any of the 185 Bot API methods through telegram-api. Use when the operator wants Telegram to do something the named tools do not already do.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Build a Telegram surface
|
|
@@ -17,15 +17,15 @@ 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 |
|
|
27
28
|
| `mcp__telegram__telegram-media-fetch` | Fetching a file by `file_id` |
|
|
28
|
-
| `mcp__telegram__telegram-invoice` | Invoices, invoice links, checkout answers, Telegram Stars |
|
|
29
29
|
| `mcp__telegram__telegram-thread` | Forum topics, one thread per job |
|
|
30
30
|
| `mcp__telegram__message-history` | Reading what arrived |
|
|
31
31
|
| `mcp__telegram__telegram-webhook-register` | Registering a bot's webhook. The only sanctioned path |
|
|
@@ -36,7 +36,20 @@ Ten named tools for the common paths, and one passthrough for everything else.
|
|
|
36
36
|
`telegram-api` takes `botId` (never a token), `method`, `params`, and optionally `files` and
|
|
37
37
|
`timeoutMs`. Field names inside `params` are Telegram's own snake_case.
|
|
38
38
|
|
|
39
|
-
##
|
|
39
|
+
## Who you can send to
|
|
40
|
+
|
|
41
|
+
Telegram does not let a bot open a conversation. Somebody who has messaged one of this account's
|
|
42
|
+
bots can be messaged back at any time with `telegram-card` and their chat id; somebody who never has
|
|
43
|
+
must write to the bot first, and no tool here can shortcut that.
|
|
44
|
+
|
|
45
|
+
`telegram-reach` is what tells the two apart. It takes no parameters and lists, per registered bot,
|
|
46
|
+
every private chat that has messaged it — chat id, name, and when they last wrote — plus any admin
|
|
47
|
+
user allowlisted on that bot who has never messaged. Being on the allowlist is not the same fact as
|
|
48
|
+
having opened the chat, and only the second one makes a send possible.
|
|
49
|
+
|
|
50
|
+
Read it before telling anybody a Telegram send is impossible.
|
|
51
|
+
|
|
52
|
+
## The seven methods it will not call
|
|
40
53
|
|
|
41
54
|
Each refusal names the tool that owns the capability instead.
|
|
42
55
|
|
|
@@ -45,6 +58,41 @@ Each refusal names the tool that owns the capability instead.
|
|
|
45
58
|
| `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
59
|
| `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
60
|
| `logOut`, `close` | Both move the bot off the cloud Bot API server | Nothing. Do not do this |
|
|
61
|
+
| `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 |
|
|
62
|
+
|
|
63
|
+
`getManagedBotAccessSettings` and `setManagedBotAccessSettings` are NOT refused: they return no
|
|
64
|
+
credential, so refusing them would remove a capability while protecting nothing. Prefer
|
|
65
|
+
`telegram-bot-provision action=access` anyway, which logs the change.
|
|
66
|
+
|
|
67
|
+
## Creating a bot without BotFather
|
|
68
|
+
|
|
69
|
+
`telegram-bot-provision` has four actions.
|
|
70
|
+
|
|
71
|
+
| Action | What it does |
|
|
72
|
+
|---|---|
|
|
73
|
+
| `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 |
|
|
74
|
+
| `rotate` | Revokes a managed bot's token, saves the replacement, and re-registers the webhook at the URL it was already on |
|
|
75
|
+
| `access` | Reads the access settings when `isAccessRestricted` is omitted; writes them when it is given. Up to ten `addedUserIds` besides the owner |
|
|
76
|
+
| `list` | This account's bots by id and role. Never a token |
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
telegram-bot-provision botId=<managing-bot> action=offer chatId=<private-chat>
|
|
80
|
+
suggestedName="Front Desk" suggestedUsername="frontdesk_bot"
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Three things to know before using it:
|
|
84
|
+
|
|
85
|
+
- The managing bot must have management of other bots enabled **once**, in the @BotFather Mini App.
|
|
86
|
+
No API call turns it on. `offer` checks `getMe().can_manage_bots` and refuses with the Mini App
|
|
87
|
+
named, so a button that would do nothing is never sent.
|
|
88
|
+
- The button is a REPLY keyboard and Telegram makes it **private chats only**. A group or channel
|
|
89
|
+
id will not work.
|
|
90
|
+
- A provisioned bot lands as `role:'unbound'` and answers nobody until an agent is bound to it. It
|
|
91
|
+
is restricted to its owner on Telegram's side at the same time.
|
|
92
|
+
|
|
93
|
+
Telegram sends no `request_id` back and no event discriminator, so a creation and a token change
|
|
94
|
+
are told apart only by whether the account already holds the bot id, and the log correlates on
|
|
95
|
+
`newBotId` rather than on the request id.
|
|
48
96
|
|
|
49
97
|
## Five things people actually build
|
|
50
98
|
|
|
@@ -166,6 +214,21 @@ form needs forum topic mode enabled on the bot: `sendMessage`'s `message_thread_
|
|
|
166
214
|
working "for forum supergroups and private chats of bots with forum topic mode enabled only", so
|
|
167
215
|
without it the topic exists and nothing can be sent into it.
|
|
168
216
|
|
|
217
|
+
**A message from a topic is answered in that topic, and you do not arrange it.** The route reads the
|
|
218
|
+
topic off the inbound and threads it through the reply, so your turn's final text lands where the
|
|
219
|
+
question was asked. You only pass `messageThreadId` yourself when you are sending into a topic
|
|
220
|
+
nobody just wrote in.
|
|
221
|
+
|
|
222
|
+
**A checklist cannot go into a topic.** `sendChecklist` is the one send method with no
|
|
223
|
+
`message_thread_id` in its table. `telegram-ask` refuses that pair before the network call rather
|
|
224
|
+
than dropping the field and letting the checklist land in the group's General thread, which used to
|
|
225
|
+
read as the call having worked. Send it without `messageThreadId`, or use a poll or a plain message
|
|
226
|
+
for the topic itself.
|
|
227
|
+
|
|
228
|
+
**Only a real topic counts.** Telegram also stamps `message_thread_id` on an ordinary reply in a
|
|
229
|
+
supergroup, so the route keys on `is_topic_message` instead. A plain reply is answered in the
|
|
230
|
+
conversation, not pulled into a thread.
|
|
231
|
+
|
|
169
232
|
### 8. Asking a question, or sending a place
|
|
170
233
|
|
|
171
234
|
`telegram-ask` covers the structured sends. A poll takes its answers as plain strings:
|
|
@@ -200,6 +263,29 @@ connection. Pass one explicitly only to override that. With nothing stored the t
|
|
|
200
263
|
the operator step, which means the answer is to ask the operator to connect the bot, not to hunt for
|
|
201
264
|
a parameter.
|
|
202
265
|
|
|
266
|
+
**A customer messaging the connected business account reaches you in their own conversation, not the
|
|
267
|
+
operator's.** Once the operator connects the bot under Telegram, Settings, Business, Chatbots, every
|
|
268
|
+
message in that account's private chats arrives here as a turn of its own. Four things follow.
|
|
269
|
+
|
|
270
|
+
The turn is a **stranger's**, so it runs as the entry's public agent and carries none of the
|
|
271
|
+
operator's standing rules, whatever role the bot itself holds. The two conversations never share a
|
|
272
|
+
session even when the same person is in both.
|
|
273
|
+
|
|
274
|
+
Every reply **quotes the connection**, and you do not supply it: `telegram-card` and the turn's own
|
|
275
|
+
reply fill it in from the stored connection. Telegram routes the message as the business account
|
|
276
|
+
rather than as the bot, and there is no variant without it.
|
|
277
|
+
|
|
278
|
+
The **24-hour window is a hard limit**. `BusinessBotRights.can_reply` grants the right to answer only
|
|
279
|
+
"in the private chats that had incoming messages in the last 24 hours". A send past that is refused
|
|
280
|
+
here before it is attempted, and the refusal names the window. Nothing is emitted when a window
|
|
281
|
+
closes, so a customer you leave unanswered simply becomes unreachable with no error anywhere. Answer
|
|
282
|
+
while you can.
|
|
283
|
+
|
|
284
|
+
An edit from the customer **changes the message you already have** rather than arriving as a new one.
|
|
285
|
+
It still raises a turn, because a customer who rewrites their question has asked something new; what
|
|
286
|
+
it does not do is leave you two messages to reconcile. A deletion marks the message deleted rather
|
|
287
|
+
than removing it, so what was withdrawn stays readable, and it raises no turn at all.
|
|
288
|
+
|
|
203
289
|
**A business connection and Telegram Premium are two separate gates, and they govern different
|
|
204
290
|
things.** Telegram states them apart, so do not treat one as the other. Bot API 9.1 (3 July 2025)
|
|
205
291
|
added `sendChecklist` and `editMessageChecklist` "allowing bots to send a checklist on behalf of a
|
|
@@ -224,36 +310,13 @@ business account, so send the Mini App button as its own ordinary message. This
|
|
|
224
310
|
|
|
225
311
|
### 9. Charging for something
|
|
226
312
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
so £4.50 is 450 and a 500-star price is 500.
|
|
230
|
-
|
|
231
|
-
```
|
|
232
|
-
telegram-invoice botId=<id> action=send chatId=<chat> title="Emergency callout"
|
|
233
|
-
description="Same-day attendance, first hour" payload="job-4102" currency="XTR"
|
|
234
|
-
prices=[{label:"Callout", amount:500}]
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
`action=link` returns a payable URL instead of posting into a chat, which is what you want for a
|
|
238
|
-
link you paste somewhere else. Don't pass buttons: Telegram requires the first button of an invoice
|
|
239
|
-
keyboard to be a Pay button, and leaving the keyboard off gets that button for free.
|
|
240
|
-
|
|
241
|
-
`payload` is your own reference. It is never shown to the payer and it comes back on the
|
|
242
|
-
successful-payment update, which is how a payment is matched to a job.
|
|
243
|
-
|
|
244
|
-
**You do not answer the pre-checkout query.** Telegram cancels the transaction if no answer lands
|
|
245
|
-
within ten seconds, and a turn cannot start and finish in ten seconds, so the inbound route answers
|
|
246
|
-
it itself: `ok=true` for a sender with access, `ok=false` for one without. You then get a turn saying
|
|
247
|
-
`[pre-checkout approved: …]`, and once the payer confirms, a second one saying
|
|
248
|
-
`[payment received: …]` with your own `payload` on it. `action=answerPreCheckout` stays on the tool
|
|
249
|
-
for a surface that answers out of band; calling it for a query the route has already answered gets a
|
|
250
|
-
Telegram error about a stale id.
|
|
313
|
+
You cannot, inside Telegram. The payment surface was removed: there is no `telegram-invoice`
|
|
314
|
+
tool, and `telegram-api` refuses all eight Bot API payment methods.
|
|
251
315
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
payer
|
|
256
|
-
subscription that is cancelled, re-enabled or fails to charge arrives as its own turn.
|
|
316
|
+
The reason is redemption, not capability. Telegram Stars cannot be withdrawn by a bot — that
|
|
317
|
+
route is a client API method returning a Fragment page that takes a TON wallet address — and the
|
|
318
|
+
fiat path needs a BotFather provider this install does not hold. Charge outside Telegram and send
|
|
319
|
+
the payer a link; `telegram-card` takes a `url` button for exactly that.
|
|
257
320
|
|
|
258
321
|
### Ephemeral messages
|
|
259
322
|
|
|
@@ -266,7 +329,8 @@ sends group messages visible to a single user.
|
|
|
266
329
|
|
|
267
330
|
## What arrives from Telegram
|
|
268
331
|
|
|
269
|
-
Telegram defines twenty-six update classes. This install registers
|
|
332
|
+
Telegram defines twenty-six update classes. This install registers twenty-two and handles seventeen
|
|
333
|
+
of them.
|
|
270
334
|
|
|
271
335
|
| Class | Registered | What happens |
|
|
272
336
|
|---|---|---|
|
|
@@ -275,14 +339,29 @@ Telegram defines twenty-six update classes. This install registers fourteen and
|
|
|
275
339
|
| `poll_answer` | yes | a turn per voter |
|
|
276
340
|
| `poll` | yes | a turn on close only, naming the question and the counts |
|
|
277
341
|
| `message_reaction` | yes | a turn naming the emoji and the message reacted to |
|
|
278
|
-
| `pre_checkout_query` |
|
|
279
|
-
| `shipping_query` |
|
|
342
|
+
| `pre_checkout_query` | no | logged and left to cancel: no answer, no turn |
|
|
343
|
+
| `shipping_query` | no | logged only, no turn |
|
|
280
344
|
| `subscription` | yes | a turn naming the state (`canceled`, `active`, `failed`) |
|
|
281
345
|
| `my_chat_member` | yes | logged only, no turn: in a DM this is a block or an unblock |
|
|
282
346
|
| `business_connection` | yes | recorded so `business_connection_id` can be supplied |
|
|
283
|
-
| `business_message
|
|
347
|
+
| `business_message` | yes | a turn, in the customer's own session |
|
|
348
|
+
| `edited_business_message` | yes | a turn, and it patches the message rather than adding one |
|
|
349
|
+
| `deleted_business_messages` | yes | marks the stored rows deleted, no turn |
|
|
350
|
+
| `chat_member` | yes | logged only, no turn: another member joined, left or was removed |
|
|
351
|
+
| `chat_join_request` | yes | logged only, no turn |
|
|
352
|
+
| `message_reaction_count` | yes | logged against the message, no turn: the anonymous tally, as against `message_reaction` which names the reactor |
|
|
353
|
+
| `chat_boost`, `removed_chat_boost` | yes | logged only, no turn |
|
|
354
|
+
| `channel_post`, `edited_channel_post` | yes | a turn, attributed to the channel, when the channel is allowlisted |
|
|
284
355
|
| everything else | no | does not arrive |
|
|
285
356
|
|
|
357
|
+
None of `chat_member`, `chat_join_request`, `message_reaction_count` or the two boost classes raises
|
|
358
|
+
a turn, and none takes an access decision: they are things that happened, with nobody addressing the
|
|
359
|
+
bot, so there is nobody to admit or refuse.
|
|
360
|
+
|
|
361
|
+
**A channel post has no author.** Telegram documents `Message.from` as "may be empty for messages
|
|
362
|
+
sent to channels", so the turn names the channel by its title and there is no person in it. Do not
|
|
363
|
+
address a channel post as if somebody wrote it.
|
|
364
|
+
|
|
286
365
|
**A reaction may never arrive in a DM.** Telegram documents `message_reaction` as requiring the bot
|
|
287
366
|
to be an administrator in the chat, and a private chat has no administrator. The class is registered
|
|
288
367
|
and the handler exists; if nothing ever arrives from a DM, reactions are group-only here.
|
|
@@ -293,8 +372,13 @@ Naming **any** class in `allowed_updates` replaces Telegram's default set. Teleg
|
|
|
293
372
|
every class except `chat_member`, `message_reaction` and `message_reaction_count` — so a class that
|
|
294
373
|
works today and is missing from the list stops arriving, with no error in any log.
|
|
295
374
|
|
|
375
|
+
Those same three are the ones outside the default, so a bot registered before they were added
|
|
376
|
+
receives none of them until it re-registers. That is not a failure anything reports: the bot simply
|
|
377
|
+
never sees a reaction or a membership change.
|
|
378
|
+
|
|
296
379
|
The list lives in exactly one place, `TELEGRAM_ALLOWED_UPDATES` in
|
|
297
|
-
`
|
|
380
|
+
`platform/lib/telegram-managed-bot/` (re-exported from
|
|
381
|
+
`plugins/telegram/mcp/src/lib/telegram.ts`). Add a class there and nowhere else, and re-register the
|
|
298
382
|
webhook: `allowed_updates` is set at registration, so an existing bot keeps the list it was
|
|
299
383
|
registered with. `telegram-webhook-register` prints
|
|
300
384
|
`op=webhook-allowed … match=yes|no` against what `getWebhookInfo` reports back; `match=no` means
|
|
@@ -303,6 +387,36 @@ Telegram registered something narrower than was asked for.
|
|
|
303
387
|
The registration test asserts the whole array, not that a particular name is in it, because the
|
|
304
388
|
failure it guards against is a name silently dropped.
|
|
305
389
|
|
|
390
|
+
## Sending to a channel or a group
|
|
391
|
+
|
|
392
|
+
Every send whose chat id you choose is checked before it reaches Telegram. A chat id beginning
|
|
393
|
+
`-100` is a channel or a supergroup — Telegram gives the two the same id shape and nothing local can
|
|
394
|
+
tell them apart — and it is refused unless the operator listed it in that bot's `allowChannels` or
|
|
395
|
+
`allowGroups`. The refusal names the id and both fields, and nothing is sent.
|
|
396
|
+
|
|
397
|
+
This is a refusal, not a retry. A channel post reaches every subscriber and cannot be unsent, so the
|
|
398
|
+
check happens before the network call rather than after Telegram's answer. If you are refused, say
|
|
399
|
+
so plainly and name the id; do not try another tool, and do not reach for `telegram-api` to route
|
|
400
|
+
around it, because the same check applies there on `params.chat_id`.
|
|
401
|
+
|
|
402
|
+
Both lists live on public bot entries only. An admin, specialist or unbound bot reaches no channel
|
|
403
|
+
and no group, in either direction.
|
|
404
|
+
|
|
405
|
+
A private chat id (positive) and a basic group id (negative, no `-100`) are unaffected.
|
|
406
|
+
|
|
407
|
+
## Answering a comment on a channel post
|
|
408
|
+
|
|
409
|
+
Telegram builds a comment thread by auto-forwarding each channel post into the channel's linked
|
|
410
|
+
discussion group. That forwarded copy is the thread root, and it is not a message anybody sent you:
|
|
411
|
+
it raises no turn, because the post itself already reached you through the channel.
|
|
412
|
+
|
|
413
|
+
A comment arrives as an ordinary group message whose turn carries the root's message id. Answer by
|
|
414
|
+
replying beneath that root, not at the bottom of the group, or the answer reads to everyone in the
|
|
415
|
+
thread as no answer at all.
|
|
416
|
+
|
|
417
|
+
A commenter who posted anonymously has no personal identity. The turn names the group they commented
|
|
418
|
+
as, which is the only identity Telegram supplies.
|
|
419
|
+
|
|
306
420
|
## Reading the method list
|
|
307
421
|
|
|
308
422
|
`references/methods.md` carries all 185 names grouped as Telegram documents them: Getting updates,
|
|
@@ -315,8 +429,9 @@ works without waiting for a release here. `telegram-api-census` is what reports
|
|
|
315
429
|
|
|
316
430
|
### What stays in the passthrough, and why
|
|
317
431
|
|
|
318
|
-
Named tools own the conversation, structured-input, media-in, media-out
|
|
319
|
-
|
|
432
|
+
Named tools own the conversation, structured-input, media-in, media-out and threading buckets: 31
|
|
433
|
+
methods in all. The payments bucket has no owner: the surface was removed and `telegram-api`
|
|
434
|
+
refuses all eight. These stay on `telegram-api` deliberately, because they are config-time
|
|
320
435
|
rather than per-turn: membership (23 methods), business-account (12), bot-self-config (19, including
|
|
321
436
|
the four managed-bot token methods), org-verification (4) and chat-cosmetic (6).
|
|
322
437
|
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# Bot API 10.2 methods
|
|
2
2
|
|
|
3
3
|
Every method `telegram-api` can call, as documented at `core.telegram.org/bots/api`
|
|
4
|
-
on 14 July 2026.
|
|
5
|
-
the capability instead.
|
|
4
|
+
on 14 July 2026. Seven of them are refused, and each refusal names the tool that owns
|
|
5
|
+
the capability instead. The eight Bot API payment methods are not listed at all: this
|
|
6
|
+
install takes no payment inside Telegram and `telegram-api` refuses them by name. Pass the name to `telegram-api` exactly as written here:
|
|
6
7
|
Telegram's own documentation is case-insensitive but this list is not, because the
|
|
7
8
|
census matches it literally.
|
|
8
9
|
|
|
@@ -197,17 +198,6 @@ census matches it literally.
|
|
|
197
198
|
|
|
198
199
|
- `answerInlineQuery`
|
|
199
200
|
|
|
200
|
-
## Payments
|
|
201
|
-
|
|
202
|
-
- `sendInvoice`
|
|
203
|
-
- `createInvoiceLink`
|
|
204
|
-
- `answerShippingQuery`
|
|
205
|
-
- `answerPreCheckoutQuery`
|
|
206
|
-
- `getMyStarBalance`
|
|
207
|
-
- `getStarTransactions`
|
|
208
|
-
- `refundStarPayment`
|
|
209
|
-
- `editUserStarSubscription`
|
|
210
|
-
|
|
211
201
|
## Telegram Passport
|
|
212
202
|
|
|
213
203
|
- `setPassportDataErrors`
|
|
@@ -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
|
|