@shuyhere/takotako 0.0.1
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/CONTRIBUTING.md +84 -0
- package/LICENSE +21 -0
- package/README.md +171 -0
- package/dist/agents/communication.d.ts +48 -0
- package/dist/agents/communication.d.ts.map +1 -0
- package/dist/agents/communication.js +123 -0
- package/dist/agents/communication.js.map +1 -0
- package/dist/agents/config.d.ts +52 -0
- package/dist/agents/config.d.ts.map +1 -0
- package/dist/agents/config.js +65 -0
- package/dist/agents/config.js.map +1 -0
- package/dist/agents/model-catalog.d.ts +49 -0
- package/dist/agents/model-catalog.d.ts.map +1 -0
- package/dist/agents/model-catalog.js +79 -0
- package/dist/agents/model-catalog.js.map +1 -0
- package/dist/agents/registry.d.ts +71 -0
- package/dist/agents/registry.d.ts.map +1 -0
- package/dist/agents/registry.js +297 -0
- package/dist/agents/registry.js.map +1 -0
- package/dist/agents/roles.d.ts +79 -0
- package/dist/agents/roles.d.ts.map +1 -0
- package/dist/agents/roles.js +174 -0
- package/dist/agents/roles.js.map +1 -0
- package/dist/agents/subagent.d.ts +124 -0
- package/dist/agents/subagent.d.ts.map +1 -0
- package/dist/agents/subagent.js +352 -0
- package/dist/agents/subagent.js.map +1 -0
- package/dist/agents/templates.d.ts +18 -0
- package/dist/agents/templates.d.ts.map +1 -0
- package/dist/agents/templates.js +341 -0
- package/dist/agents/templates.js.map +1 -0
- package/dist/agents/thread-binding.d.ts +77 -0
- package/dist/agents/thread-binding.d.ts.map +1 -0
- package/dist/agents/thread-binding.js +167 -0
- package/dist/agents/thread-binding.js.map +1 -0
- package/dist/auth/agent-profiles.d.ts +46 -0
- package/dist/auth/agent-profiles.d.ts.map +1 -0
- package/dist/auth/agent-profiles.js +97 -0
- package/dist/auth/agent-profiles.js.map +1 -0
- package/dist/auth/allow-from.d.ts +27 -0
- package/dist/auth/allow-from.d.ts.map +1 -0
- package/dist/auth/allow-from.js +118 -0
- package/dist/auth/allow-from.js.map +1 -0
- package/dist/auth/oauth.d.ts +66 -0
- package/dist/auth/oauth.d.ts.map +1 -0
- package/dist/auth/oauth.js +253 -0
- package/dist/auth/oauth.js.map +1 -0
- package/dist/auth/storage.d.ts +69 -0
- package/dist/auth/storage.d.ts.map +1 -0
- package/dist/auth/storage.js +157 -0
- package/dist/auth/storage.js.map +1 -0
- package/dist/cache/file-cache.d.ts +68 -0
- package/dist/cache/file-cache.d.ts.map +1 -0
- package/dist/cache/file-cache.js +176 -0
- package/dist/cache/file-cache.js.map +1 -0
- package/dist/cache/manager.d.ts +69 -0
- package/dist/cache/manager.d.ts.map +1 -0
- package/dist/cache/manager.js +117 -0
- package/dist/cache/manager.js.map +1 -0
- package/dist/cache/symbol-index.d.ts +75 -0
- package/dist/cache/symbol-index.d.ts.map +1 -0
- package/dist/cache/symbol-index.js +267 -0
- package/dist/cache/symbol-index.js.map +1 -0
- package/dist/cache/tool-cache.d.ts +75 -0
- package/dist/cache/tool-cache.d.ts.map +1 -0
- package/dist/cache/tool-cache.js +173 -0
- package/dist/cache/tool-cache.js.map +1 -0
- package/dist/channels/channel.d.ts +156 -0
- package/dist/channels/channel.d.ts.map +1 -0
- package/dist/channels/channel.js +25 -0
- package/dist/channels/channel.js.map +1 -0
- package/dist/channels/cli.d.ts +35 -0
- package/dist/channels/cli.d.ts.map +1 -0
- package/dist/channels/cli.js +94 -0
- package/dist/channels/cli.js.map +1 -0
- package/dist/channels/delivery-queue.d.ts +31 -0
- package/dist/channels/delivery-queue.d.ts.map +1 -0
- package/dist/channels/delivery-queue.js +127 -0
- package/dist/channels/delivery-queue.js.map +1 -0
- package/dist/channels/discord.d.ts +124 -0
- package/dist/channels/discord.d.ts.map +1 -0
- package/dist/channels/discord.js +664 -0
- package/dist/channels/discord.js.map +1 -0
- package/dist/channels/retry.d.ts +31 -0
- package/dist/channels/retry.d.ts.map +1 -0
- package/dist/channels/retry.js +94 -0
- package/dist/channels/retry.js.map +1 -0
- package/dist/channels/telegram.d.ts +69 -0
- package/dist/channels/telegram.d.ts.map +1 -0
- package/dist/channels/telegram.js +499 -0
- package/dist/channels/telegram.js.map +1 -0
- package/dist/channels/tui.d.ts +42 -0
- package/dist/channels/tui.d.ts.map +1 -0
- package/dist/channels/tui.js +126 -0
- package/dist/channels/tui.js.map +1 -0
- package/dist/cli/acp.d.ts +10 -0
- package/dist/cli/acp.d.ts.map +1 -0
- package/dist/cli/acp.js +69 -0
- package/dist/cli/acp.js.map +1 -0
- package/dist/cli/audit.d.ts +11 -0
- package/dist/cli/audit.d.ts.map +1 -0
- package/dist/cli/audit.js +55 -0
- package/dist/cli/audit.js.map +1 -0
- package/dist/cli/cache.d.ts +10 -0
- package/dist/cli/cache.d.ts.map +1 -0
- package/dist/cli/cache.js +77 -0
- package/dist/cli/cache.js.map +1 -0
- package/dist/cli/config.d.ts +5 -0
- package/dist/cli/config.d.ts.map +1 -0
- package/dist/cli/config.js +168 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/cron.d.ts +5 -0
- package/dist/cli/cron.d.ts.map +1 -0
- package/dist/cli/cron.js +192 -0
- package/dist/cli/cron.js.map +1 -0
- package/dist/cli/extensions.d.ts +5 -0
- package/dist/cli/extensions.d.ts.map +1 -0
- package/dist/cli/extensions.js +53 -0
- package/dist/cli/extensions.js.map +1 -0
- package/dist/cli/logs.d.ts +5 -0
- package/dist/cli/logs.d.ts.map +1 -0
- package/dist/cli/logs.js +49 -0
- package/dist/cli/logs.js.map +1 -0
- package/dist/cli/memory.d.ts +5 -0
- package/dist/cli/memory.d.ts.map +1 -0
- package/dist/cli/memory.js +78 -0
- package/dist/cli/memory.js.map +1 -0
- package/dist/cli/message.d.ts +5 -0
- package/dist/cli/message.d.ts.map +1 -0
- package/dist/cli/message.js +69 -0
- package/dist/cli/message.js.map +1 -0
- package/dist/cli/service.d.ts +14 -0
- package/dist/cli/service.d.ts.map +1 -0
- package/dist/cli/service.js +181 -0
- package/dist/cli/service.js.map +1 -0
- package/dist/cli/symphony.d.ts +5 -0
- package/dist/cli/symphony.d.ts.map +1 -0
- package/dist/cli/symphony.js +114 -0
- package/dist/cli/symphony.js.map +1 -0
- package/dist/cli/update.d.ts +5 -0
- package/dist/cli/update.d.ts.map +1 -0
- package/dist/cli/update.js +48 -0
- package/dist/cli/update.js.map +1 -0
- package/dist/commands/channel-setup.d.ts +31 -0
- package/dist/commands/channel-setup.d.ts.map +1 -0
- package/dist/commands/channel-setup.js +138 -0
- package/dist/commands/channel-setup.js.map +1 -0
- package/dist/commands/dispatch.d.ts +48 -0
- package/dist/commands/dispatch.d.ts.map +1 -0
- package/dist/commands/dispatch.js +68 -0
- package/dist/commands/dispatch.js.map +1 -0
- package/dist/commands/model-picker.d.ts +16 -0
- package/dist/commands/model-picker.d.ts.map +1 -0
- package/dist/commands/model-picker.js +120 -0
- package/dist/commands/model-picker.js.map +1 -0
- package/dist/commands/parser.d.ts +32 -0
- package/dist/commands/parser.d.ts.map +1 -0
- package/dist/commands/parser.js +39 -0
- package/dist/commands/parser.js.map +1 -0
- package/dist/commands/registry.d.ts +76 -0
- package/dist/commands/registry.d.ts.map +1 -0
- package/dist/commands/registry.js +351 -0
- package/dist/commands/registry.js.map +1 -0
- package/dist/commands/skill-commands.d.ts +35 -0
- package/dist/commands/skill-commands.d.ts.map +1 -0
- package/dist/commands/skill-commands.js +61 -0
- package/dist/commands/skill-commands.js.map +1 -0
- package/dist/config/resolve.d.ts +25 -0
- package/dist/config/resolve.d.ts.map +1 -0
- package/dist/config/resolve.js +289 -0
- package/dist/config/resolve.js.map +1 -0
- package/dist/config/schema.d.ts +520 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +123 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/core/agent-loop.d.ts +137 -0
- package/dist/core/agent-loop.d.ts.map +1 -0
- package/dist/core/agent-loop.js +700 -0
- package/dist/core/agent-loop.js.map +1 -0
- package/dist/core/audit.d.ts +87 -0
- package/dist/core/audit.d.ts.map +1 -0
- package/dist/core/audit.js +224 -0
- package/dist/core/audit.js.map +1 -0
- package/dist/core/bootstrap.d.ts +23 -0
- package/dist/core/bootstrap.d.ts.map +1 -0
- package/dist/core/bootstrap.js +162 -0
- package/dist/core/bootstrap.js.map +1 -0
- package/dist/core/context.d.ts +44 -0
- package/dist/core/context.d.ts.map +1 -0
- package/dist/core/context.js +65 -0
- package/dist/core/context.js.map +1 -0
- package/dist/core/cron.d.ts +111 -0
- package/dist/core/cron.d.ts.map +1 -0
- package/dist/core/cron.js +284 -0
- package/dist/core/cron.js.map +1 -0
- package/dist/core/exec-approvals.d.ts +50 -0
- package/dist/core/exec-approvals.d.ts.map +1 -0
- package/dist/core/exec-approvals.js +187 -0
- package/dist/core/exec-approvals.js.map +1 -0
- package/dist/core/heartbeat.d.ts +71 -0
- package/dist/core/heartbeat.d.ts.map +1 -0
- package/dist/core/heartbeat.js +214 -0
- package/dist/core/heartbeat.js.map +1 -0
- package/dist/core/message-queue.d.ts +60 -0
- package/dist/core/message-queue.d.ts.map +1 -0
- package/dist/core/message-queue.js +182 -0
- package/dist/core/message-queue.js.map +1 -0
- package/dist/core/network-policy.d.ts +39 -0
- package/dist/core/network-policy.d.ts.map +1 -0
- package/dist/core/network-policy.js +121 -0
- package/dist/core/network-policy.js.map +1 -0
- package/dist/core/progress.d.ts +48 -0
- package/dist/core/progress.d.ts.map +1 -0
- package/dist/core/progress.js +81 -0
- package/dist/core/progress.js.map +1 -0
- package/dist/core/prompt.d.ts +105 -0
- package/dist/core/prompt.d.ts.map +1 -0
- package/dist/core/prompt.js +411 -0
- package/dist/core/prompt.js.map +1 -0
- package/dist/core/pruning.d.ts +40 -0
- package/dist/core/pruning.d.ts.map +1 -0
- package/dist/core/pruning.js +165 -0
- package/dist/core/pruning.js.map +1 -0
- package/dist/core/rate-limiter.d.ts +64 -0
- package/dist/core/rate-limiter.d.ts.map +1 -0
- package/dist/core/rate-limiter.js +142 -0
- package/dist/core/rate-limiter.js.map +1 -0
- package/dist/core/reactions.d.ts +31 -0
- package/dist/core/reactions.d.ts.map +1 -0
- package/dist/core/reactions.js +67 -0
- package/dist/core/reactions.js.map +1 -0
- package/dist/core/retry-queue.d.ts +56 -0
- package/dist/core/retry-queue.d.ts.map +1 -0
- package/dist/core/retry-queue.js +106 -0
- package/dist/core/retry-queue.js.map +1 -0
- package/dist/core/sanitizer.d.ts +38 -0
- package/dist/core/sanitizer.d.ts.map +1 -0
- package/dist/core/sanitizer.js +181 -0
- package/dist/core/sanitizer.js.map +1 -0
- package/dist/core/secret-scanner.d.ts +39 -0
- package/dist/core/secret-scanner.d.ts.map +1 -0
- package/dist/core/secret-scanner.js +96 -0
- package/dist/core/secret-scanner.js.map +1 -0
- package/dist/core/secrets.d.ts +38 -0
- package/dist/core/secrets.d.ts.map +1 -0
- package/dist/core/secrets.js +137 -0
- package/dist/core/secrets.js.map +1 -0
- package/dist/core/security.d.ts +58 -0
- package/dist/core/security.d.ts.map +1 -0
- package/dist/core/security.js +120 -0
- package/dist/core/security.js.map +1 -0
- package/dist/core/self-awareness.d.ts +19 -0
- package/dist/core/self-awareness.d.ts.map +1 -0
- package/dist/core/self-awareness.js +124 -0
- package/dist/core/self-awareness.js.map +1 -0
- package/dist/core/session-init.d.ts +34 -0
- package/dist/core/session-init.d.ts.map +1 -0
- package/dist/core/session-init.js +68 -0
- package/dist/core/session-init.js.map +1 -0
- package/dist/core/streaming.d.ts +82 -0
- package/dist/core/streaming.d.ts.map +1 -0
- package/dist/core/streaming.js +264 -0
- package/dist/core/streaming.js.map +1 -0
- package/dist/core/symphony/orchestrator.d.ts +61 -0
- package/dist/core/symphony/orchestrator.d.ts.map +1 -0
- package/dist/core/symphony/orchestrator.js +476 -0
- package/dist/core/symphony/orchestrator.js.map +1 -0
- package/dist/core/symphony/status.d.ts +11 -0
- package/dist/core/symphony/status.d.ts.map +1 -0
- package/dist/core/symphony/status.js +133 -0
- package/dist/core/symphony/status.js.map +1 -0
- package/dist/core/symphony/types.d.ts +84 -0
- package/dist/core/symphony/types.d.ts.map +1 -0
- package/dist/core/symphony/types.js +5 -0
- package/dist/core/symphony/types.js.map +1 -0
- package/dist/core/symphony/workflow.d.ts +18 -0
- package/dist/core/symphony/workflow.d.ts.map +1 -0
- package/dist/core/symphony/workflow.js +149 -0
- package/dist/core/symphony/workflow.js.map +1 -0
- package/dist/core/symphony/workspace.d.ts +24 -0
- package/dist/core/symphony/workspace.d.ts.map +1 -0
- package/dist/core/symphony/workspace.js +94 -0
- package/dist/core/symphony/workspace.js.map +1 -0
- package/dist/core/thinking.d.ts +27 -0
- package/dist/core/thinking.d.ts.map +1 -0
- package/dist/core/thinking.js +83 -0
- package/dist/core/thinking.js.map +1 -0
- package/dist/core/thread-bindings.d.ts +47 -0
- package/dist/core/thread-bindings.d.ts.map +1 -0
- package/dist/core/thread-bindings.js +94 -0
- package/dist/core/thread-bindings.js.map +1 -0
- package/dist/core/timezone.d.ts +28 -0
- package/dist/core/timezone.d.ts.map +1 -0
- package/dist/core/timezone.js +72 -0
- package/dist/core/timezone.js.map +1 -0
- package/dist/core/tool-loop-detector.d.ts +41 -0
- package/dist/core/tool-loop-detector.d.ts.map +1 -0
- package/dist/core/tool-loop-detector.js +83 -0
- package/dist/core/tool-loop-detector.js.map +1 -0
- package/dist/core/tool-validator.d.ts +44 -0
- package/dist/core/tool-validator.d.ts.map +1 -0
- package/dist/core/tool-validator.js +175 -0
- package/dist/core/tool-validator.js.map +1 -0
- package/dist/core/typing.d.ts +25 -0
- package/dist/core/typing.d.ts.map +1 -0
- package/dist/core/typing.js +48 -0
- package/dist/core/typing.js.map +1 -0
- package/dist/core/usage-tracker.d.ts +66 -0
- package/dist/core/usage-tracker.d.ts.map +1 -0
- package/dist/core/usage-tracker.js +163 -0
- package/dist/core/usage-tracker.js.map +1 -0
- package/dist/daemon/commands.d.ts +16 -0
- package/dist/daemon/commands.d.ts.map +1 -0
- package/dist/daemon/commands.js +445 -0
- package/dist/daemon/commands.js.map +1 -0
- package/dist/daemon/pid.d.ts +30 -0
- package/dist/daemon/pid.d.ts.map +1 -0
- package/dist/daemon/pid.js +62 -0
- package/dist/daemon/pid.js.map +1 -0
- package/dist/doctor/checks/browser.d.ts +9 -0
- package/dist/doctor/checks/browser.d.ts.map +1 -0
- package/dist/doctor/checks/browser.js +54 -0
- package/dist/doctor/checks/browser.js.map +1 -0
- package/dist/doctor/checks/channels.d.ts +9 -0
- package/dist/doctor/checks/channels.d.ts.map +1 -0
- package/dist/doctor/checks/channels.js +90 -0
- package/dist/doctor/checks/channels.js.map +1 -0
- package/dist/doctor/checks/config.d.ts +10 -0
- package/dist/doctor/checks/config.d.ts.map +1 -0
- package/dist/doctor/checks/config.js +89 -0
- package/dist/doctor/checks/config.js.map +1 -0
- package/dist/doctor/checks/memory.d.ts +10 -0
- package/dist/doctor/checks/memory.d.ts.map +1 -0
- package/dist/doctor/checks/memory.js +82 -0
- package/dist/doctor/checks/memory.js.map +1 -0
- package/dist/doctor/checks/permissions.d.ts +9 -0
- package/dist/doctor/checks/permissions.d.ts.map +1 -0
- package/dist/doctor/checks/permissions.js +53 -0
- package/dist/doctor/checks/permissions.js.map +1 -0
- package/dist/doctor/checks/providers.d.ts +10 -0
- package/dist/doctor/checks/providers.d.ts.map +1 -0
- package/dist/doctor/checks/providers.js +93 -0
- package/dist/doctor/checks/providers.js.map +1 -0
- package/dist/doctor/checks/sessions.d.ts +10 -0
- package/dist/doctor/checks/sessions.d.ts.map +1 -0
- package/dist/doctor/checks/sessions.js +86 -0
- package/dist/doctor/checks/sessions.js.map +1 -0
- package/dist/doctor/doctor.d.ts +35 -0
- package/dist/doctor/doctor.d.ts.map +1 -0
- package/dist/doctor/doctor.js +51 -0
- package/dist/doctor/doctor.js.map +1 -0
- package/dist/doctor/repairs.d.ts +14 -0
- package/dist/doctor/repairs.d.ts.map +1 -0
- package/dist/doctor/repairs.js +34 -0
- package/dist/doctor/repairs.js.map +1 -0
- package/dist/gateway/compaction.d.ts +63 -0
- package/dist/gateway/compaction.d.ts.map +1 -0
- package/dist/gateway/compaction.js +235 -0
- package/dist/gateway/compaction.js.map +1 -0
- package/dist/gateway/gateway.d.ts +94 -0
- package/dist/gateway/gateway.d.ts.map +1 -0
- package/dist/gateway/gateway.js +466 -0
- package/dist/gateway/gateway.js.map +1 -0
- package/dist/gateway/lock.d.ts +24 -0
- package/dist/gateway/lock.d.ts.map +1 -0
- package/dist/gateway/lock.js +88 -0
- package/dist/gateway/lock.js.map +1 -0
- package/dist/gateway/protocol.d.ts +117 -0
- package/dist/gateway/protocol.d.ts.map +1 -0
- package/dist/gateway/protocol.js +5 -0
- package/dist/gateway/protocol.js.map +1 -0
- package/dist/gateway/session.d.ts +123 -0
- package/dist/gateway/session.d.ts.map +1 -0
- package/dist/gateway/session.js +573 -0
- package/dist/gateway/session.js.map +1 -0
- package/dist/hooks/hooks.d.ts +18 -0
- package/dist/hooks/hooks.d.ts.map +1 -0
- package/dist/hooks/hooks.js +45 -0
- package/dist/hooks/hooks.js.map +1 -0
- package/dist/hooks/types.d.ts +112 -0
- package/dist/hooks/types.d.ts.map +1 -0
- package/dist/hooks/types.js +23 -0
- package/dist/hooks/types.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2900 -0
- package/dist/index.js.map +1 -0
- package/dist/media/storage.d.ts +25 -0
- package/dist/media/storage.d.ts.map +1 -0
- package/dist/media/storage.js +97 -0
- package/dist/media/storage.js.map +1 -0
- package/dist/memory/embeddings.d.ts +46 -0
- package/dist/memory/embeddings.d.ts.map +1 -0
- package/dist/memory/embeddings.js +118 -0
- package/dist/memory/embeddings.js.map +1 -0
- package/dist/memory/hybrid.d.ts +35 -0
- package/dist/memory/hybrid.d.ts.map +1 -0
- package/dist/memory/hybrid.js +156 -0
- package/dist/memory/hybrid.js.map +1 -0
- package/dist/memory/markdown.d.ts +48 -0
- package/dist/memory/markdown.d.ts.map +1 -0
- package/dist/memory/markdown.js +228 -0
- package/dist/memory/markdown.js.map +1 -0
- package/dist/memory/store.d.ts +88 -0
- package/dist/memory/store.d.ts.map +1 -0
- package/dist/memory/store.js +21 -0
- package/dist/memory/store.js.map +1 -0
- package/dist/memory/vector.d.ts +24 -0
- package/dist/memory/vector.d.ts.map +1 -0
- package/dist/memory/vector.js +63 -0
- package/dist/memory/vector.js.map +1 -0
- package/dist/mods/mod.d.ts +100 -0
- package/dist/mods/mod.d.ts.map +1 -0
- package/dist/mods/mod.js +242 -0
- package/dist/mods/mod.js.map +1 -0
- package/dist/onboard/channels.d.ts +12 -0
- package/dist/onboard/channels.d.ts.map +1 -0
- package/dist/onboard/channels.js +283 -0
- package/dist/onboard/channels.js.map +1 -0
- package/dist/onboard/models.d.ts +13 -0
- package/dist/onboard/models.d.ts.map +1 -0
- package/dist/onboard/models.js +491 -0
- package/dist/onboard/models.js.map +1 -0
- package/dist/onboard/onboard.d.ts +12 -0
- package/dist/onboard/onboard.d.ts.map +1 -0
- package/dist/onboard/onboard.js +1137 -0
- package/dist/onboard/onboard.js.map +1 -0
- package/dist/providers/anthropic.d.ts +83 -0
- package/dist/providers/anthropic.d.ts.map +1 -0
- package/dist/providers/anthropic.js +583 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/failover.d.ts +46 -0
- package/dist/providers/failover.d.ts.map +1 -0
- package/dist/providers/failover.js +149 -0
- package/dist/providers/failover.js.map +1 -0
- package/dist/providers/litellm.d.ts +38 -0
- package/dist/providers/litellm.d.ts.map +1 -0
- package/dist/providers/litellm.js +349 -0
- package/dist/providers/litellm.js.map +1 -0
- package/dist/providers/openai.d.ts +28 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +321 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/providers/prompt-cache.d.ts +50 -0
- package/dist/providers/prompt-cache.d.ts.map +1 -0
- package/dist/providers/prompt-cache.js +96 -0
- package/dist/providers/prompt-cache.js.map +1 -0
- package/dist/providers/provider.d.ts +173 -0
- package/dist/providers/provider.d.ts.map +1 -0
- package/dist/providers/provider.js +22 -0
- package/dist/providers/provider.js.map +1 -0
- package/dist/sandbox/config.d.ts +42 -0
- package/dist/sandbox/config.d.ts.map +1 -0
- package/dist/sandbox/config.js +20 -0
- package/dist/sandbox/config.js.map +1 -0
- package/dist/sandbox/container.d.ts +71 -0
- package/dist/sandbox/container.d.ts.map +1 -0
- package/dist/sandbox/container.js +193 -0
- package/dist/sandbox/container.js.map +1 -0
- package/dist/sandbox/sandbox.d.ts +82 -0
- package/dist/sandbox/sandbox.d.ts.map +1 -0
- package/dist/sandbox/sandbox.js +176 -0
- package/dist/sandbox/sandbox.js.map +1 -0
- package/dist/skills/channel-loader.d.ts +18 -0
- package/dist/skills/channel-loader.d.ts.map +1 -0
- package/dist/skills/channel-loader.js +35 -0
- package/dist/skills/channel-loader.js.map +1 -0
- package/dist/skills/extension-loader.d.ts +15 -0
- package/dist/skills/extension-loader.d.ts.map +1 -0
- package/dist/skills/extension-loader.js +63 -0
- package/dist/skills/extension-loader.js.map +1 -0
- package/dist/skills/extension-registry.d.ts +32 -0
- package/dist/skills/extension-registry.d.ts.map +1 -0
- package/dist/skills/extension-registry.js +57 -0
- package/dist/skills/extension-registry.js.map +1 -0
- package/dist/skills/extensions.d.ts +91 -0
- package/dist/skills/extensions.d.ts.map +1 -0
- package/dist/skills/extensions.js +14 -0
- package/dist/skills/extensions.js.map +1 -0
- package/dist/skills/loader.d.ts +64 -0
- package/dist/skills/loader.d.ts.map +1 -0
- package/dist/skills/loader.js +382 -0
- package/dist/skills/loader.js.map +1 -0
- package/dist/skills/marketplace.d.ts +56 -0
- package/dist/skills/marketplace.d.ts.map +1 -0
- package/dist/skills/marketplace.js +183 -0
- package/dist/skills/marketplace.js.map +1 -0
- package/dist/skills/types.d.ts +94 -0
- package/dist/skills/types.d.ts.map +1 -0
- package/dist/skills/types.js +9 -0
- package/dist/skills/types.js.map +1 -0
- package/dist/tools/acp-sessions.d.ts +89 -0
- package/dist/tools/acp-sessions.d.ts.map +1 -0
- package/dist/tools/acp-sessions.js +391 -0
- package/dist/tools/acp-sessions.js.map +1 -0
- package/dist/tools/acp.d.ts +18 -0
- package/dist/tools/acp.d.ts.map +1 -0
- package/dist/tools/acp.js +102 -0
- package/dist/tools/acp.js.map +1 -0
- package/dist/tools/agent-tools.d.ts +24 -0
- package/dist/tools/agent-tools.d.ts.map +1 -0
- package/dist/tools/agent-tools.js +611 -0
- package/dist/tools/agent-tools.js.map +1 -0
- package/dist/tools/browser.d.ts +26 -0
- package/dist/tools/browser.d.ts.map +1 -0
- package/dist/tools/browser.js +242 -0
- package/dist/tools/browser.js.map +1 -0
- package/dist/tools/comms.d.ts +8 -0
- package/dist/tools/comms.d.ts.map +1 -0
- package/dist/tools/comms.js +39 -0
- package/dist/tools/comms.js.map +1 -0
- package/dist/tools/cron-tools.d.ts +9 -0
- package/dist/tools/cron-tools.d.ts.map +1 -0
- package/dist/tools/cron-tools.js +117 -0
- package/dist/tools/cron-tools.js.map +1 -0
- package/dist/tools/exec-safety.d.ts +71 -0
- package/dist/tools/exec-safety.d.ts.map +1 -0
- package/dist/tools/exec-safety.js +141 -0
- package/dist/tools/exec-safety.js.map +1 -0
- package/dist/tools/exec.d.ts +24 -0
- package/dist/tools/exec.d.ts.map +1 -0
- package/dist/tools/exec.js +191 -0
- package/dist/tools/exec.js.map +1 -0
- package/dist/tools/fs.d.ts +15 -0
- package/dist/tools/fs.d.ts.map +1 -0
- package/dist/tools/fs.js +249 -0
- package/dist/tools/fs.js.map +1 -0
- package/dist/tools/git.d.ts +9 -0
- package/dist/tools/git.d.ts.map +1 -0
- package/dist/tools/git.js +56 -0
- package/dist/tools/git.js.map +1 -0
- package/dist/tools/image.d.ts +15 -0
- package/dist/tools/image.d.ts.map +1 -0
- package/dist/tools/image.js +106 -0
- package/dist/tools/image.js.map +1 -0
- package/dist/tools/introspect.d.ts +22 -0
- package/dist/tools/introspect.d.ts.map +1 -0
- package/dist/tools/introspect.js +223 -0
- package/dist/tools/introspect.js.map +1 -0
- package/dist/tools/memory.d.ts +11 -0
- package/dist/tools/memory.d.ts.map +1 -0
- package/dist/tools/memory.js +101 -0
- package/dist/tools/memory.js.map +1 -0
- package/dist/tools/message.d.ts +24 -0
- package/dist/tools/message.d.ts.map +1 -0
- package/dist/tools/message.js +205 -0
- package/dist/tools/message.js.map +1 -0
- package/dist/tools/model.d.ts +14 -0
- package/dist/tools/model.d.ts.map +1 -0
- package/dist/tools/model.js +62 -0
- package/dist/tools/model.js.map +1 -0
- package/dist/tools/policy.d.ts +101 -0
- package/dist/tools/policy.d.ts.map +1 -0
- package/dist/tools/policy.js +168 -0
- package/dist/tools/policy.js.map +1 -0
- package/dist/tools/registry.d.ts +52 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +154 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/search.d.ts +10 -0
- package/dist/tools/search.d.ts.map +1 -0
- package/dist/tools/search.js +78 -0
- package/dist/tools/search.js.map +1 -0
- package/dist/tools/session.d.ts +13 -0
- package/dist/tools/session.d.ts.map +1 -0
- package/dist/tools/session.js +142 -0
- package/dist/tools/session.js.map +1 -0
- package/dist/tools/spawn.d.ts +10 -0
- package/dist/tools/spawn.d.ts.map +1 -0
- package/dist/tools/spawn.js +72 -0
- package/dist/tools/spawn.js.map +1 -0
- package/dist/tools/symphony.d.ts +12 -0
- package/dist/tools/symphony.d.ts.map +1 -0
- package/dist/tools/symphony.js +142 -0
- package/dist/tools/symphony.js.map +1 -0
- package/dist/tools/system-tools.d.ts +11 -0
- package/dist/tools/system-tools.d.ts.map +1 -0
- package/dist/tools/system-tools.js +39 -0
- package/dist/tools/system-tools.js.map +1 -0
- package/dist/tools/tool.d.ts +119 -0
- package/dist/tools/tool.d.ts.map +1 -0
- package/dist/tools/tool.js +29 -0
- package/dist/tools/tool.js.map +1 -0
- package/dist/tools/web.d.ts +10 -0
- package/dist/tools/web.d.ts.map +1 -0
- package/dist/tools/web.js +105 -0
- package/dist/tools/web.js.map +1 -0
- package/dist/tui/App.d.ts +43 -0
- package/dist/tui/App.d.ts.map +1 -0
- package/dist/tui/App.js +265 -0
- package/dist/tui/App.js.map +1 -0
- package/dist/tui/bridge.d.ts +40 -0
- package/dist/tui/bridge.d.ts.map +1 -0
- package/dist/tui/bridge.js +29 -0
- package/dist/tui/bridge.js.map +1 -0
- package/dist/tui/components/Header.d.ts +14 -0
- package/dist/tui/components/Header.d.ts.map +1 -0
- package/dist/tui/components/Header.js +7 -0
- package/dist/tui/components/Header.js.map +1 -0
- package/dist/tui/components/InputBar.d.ts +10 -0
- package/dist/tui/components/InputBar.d.ts.map +1 -0
- package/dist/tui/components/InputBar.js +121 -0
- package/dist/tui/components/InputBar.js.map +1 -0
- package/dist/tui/components/MessageList.d.ts +18 -0
- package/dist/tui/components/MessageList.d.ts.map +1 -0
- package/dist/tui/components/MessageList.js +34 -0
- package/dist/tui/components/MessageList.js.map +1 -0
- package/dist/tui/components/Spinner.d.ts +9 -0
- package/dist/tui/components/Spinner.d.ts.map +1 -0
- package/dist/tui/components/Spinner.js +18 -0
- package/dist/tui/components/Spinner.js.map +1 -0
- package/dist/tui/components/StatusBar.d.ts +16 -0
- package/dist/tui/components/StatusBar.d.ts.map +1 -0
- package/dist/tui/components/StatusBar.js +15 -0
- package/dist/tui/components/StatusBar.js.map +1 -0
- package/dist/tui/components/ToolCallBox.d.ts +12 -0
- package/dist/tui/components/ToolCallBox.d.ts.map +1 -0
- package/dist/tui/components/ToolCallBox.js +12 -0
- package/dist/tui/components/ToolCallBox.js.map +1 -0
- package/dist/tui/theme.d.ts +58 -0
- package/dist/tui/theme.d.ts.map +1 -0
- package/dist/tui/theme.js +80 -0
- package/dist/tui/theme.js.map +1 -0
- package/dist/utils/logger.d.ts +16 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +70 -0
- package/dist/utils/logger.js.map +1 -0
- package/docs/DEVELOPMENT.md +74 -0
- package/docs/INSTALL.md +161 -0
- package/docs/USAGE.md +94 -0
- package/docs/architecture.md +128 -0
- package/docs/channels.md +140 -0
- package/docs/configuration.md +209 -0
- package/docs/io-system.md +430 -0
- package/docs/providers.md +99 -0
- package/docs/skill-channels.md +113 -0
- package/docs/skills.md +246 -0
- package/package.json +89 -0
- package/skills/acp-router/SKILL.md +41 -0
- package/skills/acp-router/tools/acp-router.mjs +239 -0
- package/skills/find-skills/SKILL.md +133 -0
- package/skills/security-audit/SKILL.md +181 -0
- package/skills/security-audit/audit.sh +67 -0
- package/skills/skill-creator/SKILL.md +479 -0
- package/skills/skill-security-audit/.clawhub/origin.json +7 -0
- package/skills/skill-security-audit/SKILL.md +196 -0
- package/skills/skill-security-audit/_meta.json +6 -0
- package/skills/skill-security-audit/references/prompt-injection-patterns.md +276 -0
- package/skills/skill-security-audit/references/vulnerability-patterns.md +348 -0
- package/skills/symphony/README.md +53 -0
- package/skills/symphony/SKILL.md +75 -0
- package/skills/symphony/tools/symphony-orchestrator.ts +8 -0
- package/tako.example.json +33 -0
|
@@ -0,0 +1,664 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Discord channel adapter.
|
|
3
|
+
*
|
|
4
|
+
* Connects to Discord via bot token using discord.js.
|
|
5
|
+
* Listens for messages, converts them to InboundMessage,
|
|
6
|
+
* and sends responses back to the appropriate channel.
|
|
7
|
+
*/
|
|
8
|
+
import { Client, GatewayIntentBits, Events, ChannelType, Partials, REST, Routes, } from 'discord.js';
|
|
9
|
+
import { withRetry, DISCORD_RETRY } from './retry.js';
|
|
10
|
+
import { scanSecrets } from '../core/security.js';
|
|
11
|
+
const MAX_DISCORD_MESSAGE_LENGTH = 2000;
|
|
12
|
+
/** Mask a name for privacy: keep first 2 and last 3 chars, replace middle with ***. */
|
|
13
|
+
function maskName(name) {
|
|
14
|
+
if (name.length <= 5)
|
|
15
|
+
return name[0] + '***' + name[name.length - 1];
|
|
16
|
+
return name.slice(0, 2) + '***' + name.slice(-3);
|
|
17
|
+
}
|
|
18
|
+
export class DiscordChannel {
|
|
19
|
+
id = 'discord';
|
|
20
|
+
agentId;
|
|
21
|
+
token;
|
|
22
|
+
guilds;
|
|
23
|
+
client = null;
|
|
24
|
+
handlers = [];
|
|
25
|
+
slashCommandHandler = null;
|
|
26
|
+
interactiveHandlers = new Map();
|
|
27
|
+
modalHandlers = [];
|
|
28
|
+
selectMenuHandlers = [];
|
|
29
|
+
buttonHandlers = [];
|
|
30
|
+
nativeCommands = [];
|
|
31
|
+
previousSkillNames;
|
|
32
|
+
reconnectAttempts = 0;
|
|
33
|
+
maxReconnectAttempts = 5;
|
|
34
|
+
reconnectDelay = 5000;
|
|
35
|
+
constructor(opts) {
|
|
36
|
+
this.token = opts.token;
|
|
37
|
+
this.guilds = opts.guilds ? new Set(opts.guilds) : undefined;
|
|
38
|
+
}
|
|
39
|
+
async connect() {
|
|
40
|
+
this.client = new Client({
|
|
41
|
+
intents: [
|
|
42
|
+
GatewayIntentBits.Guilds,
|
|
43
|
+
GatewayIntentBits.GuildMessages,
|
|
44
|
+
GatewayIntentBits.DirectMessages,
|
|
45
|
+
GatewayIntentBits.MessageContent,
|
|
46
|
+
],
|
|
47
|
+
// Partials required for DM support — discord.js won't emit
|
|
48
|
+
// MessageCreate for DMs without Channel + Message partials
|
|
49
|
+
partials: [Partials.Channel, Partials.Message],
|
|
50
|
+
});
|
|
51
|
+
this.client.on(Events.MessageCreate, async (message) => {
|
|
52
|
+
if (message.author.bot)
|
|
53
|
+
return;
|
|
54
|
+
if (this.guilds && message.guild && !this.guilds.has(message.guild.id))
|
|
55
|
+
return;
|
|
56
|
+
// ─── Mention-based routing ─────────────────────────────────────
|
|
57
|
+
// ALL bots (main and agent) require @mention in guild channels.
|
|
58
|
+
// DMs always go through. This prevents agent bots from responding
|
|
59
|
+
// to messages not addressed to them in shared servers.
|
|
60
|
+
const myBotId = this.client?.user?.id;
|
|
61
|
+
if (myBotId && message.guild) {
|
|
62
|
+
if (!message.mentions.has(myBotId)) {
|
|
63
|
+
return; // Not mentioned — ignore
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const inbound = this.convertInbound(message);
|
|
67
|
+
for (const handler of this.handlers) {
|
|
68
|
+
try {
|
|
69
|
+
await handler(inbound);
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
console.error('[discord] Handler error:', err instanceof Error ? err.message : err);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
// Handle native slash command interactions
|
|
77
|
+
this.client.on(Events.InteractionCreate, async (interaction) => {
|
|
78
|
+
if (!interaction.isChatInputCommand())
|
|
79
|
+
return;
|
|
80
|
+
const cmdInteraction = interaction;
|
|
81
|
+
// Check interactive handlers first (model picker, etc.)
|
|
82
|
+
const interactiveHandler = this.interactiveHandlers.get(cmdInteraction.commandName);
|
|
83
|
+
if (interactiveHandler) {
|
|
84
|
+
try {
|
|
85
|
+
const handled = await interactiveHandler(cmdInteraction);
|
|
86
|
+
if (handled)
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
console.error('[discord] Interactive handler error:', err instanceof Error ? err.message : err);
|
|
91
|
+
if (!cmdInteraction.replied && !cmdInteraction.deferred) {
|
|
92
|
+
await cmdInteraction.reply({ content: 'Something went wrong.', ephemeral: true });
|
|
93
|
+
}
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// Fall through to text-based slash command handler
|
|
98
|
+
if (!this.slashCommandHandler) {
|
|
99
|
+
await cmdInteraction.reply({ content: 'Commands not ready yet.', ephemeral: true });
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
// Defer reply in case handler takes a moment
|
|
103
|
+
await cmdInteraction.deferReply();
|
|
104
|
+
const author = {
|
|
105
|
+
id: cmdInteraction.user.id,
|
|
106
|
+
name: cmdInteraction.user.displayName || cmdInteraction.user.username,
|
|
107
|
+
meta: {
|
|
108
|
+
discriminator: cmdInteraction.user.discriminator,
|
|
109
|
+
guildId: cmdInteraction.guild?.id,
|
|
110
|
+
guildName: cmdInteraction.guild?.name,
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
const channelId = cmdInteraction.channelId;
|
|
114
|
+
const result = await this.slashCommandHandler(cmdInteraction.commandName, channelId, author, cmdInteraction.guild?.id);
|
|
115
|
+
await cmdInteraction.editReply({ content: result || 'Done.' });
|
|
116
|
+
});
|
|
117
|
+
// Handle modal submit interactions
|
|
118
|
+
this.client.on(Events.InteractionCreate, async (interaction) => {
|
|
119
|
+
if (!interaction.isModalSubmit())
|
|
120
|
+
return;
|
|
121
|
+
for (const handler of this.modalHandlers) {
|
|
122
|
+
try {
|
|
123
|
+
const handled = await handler(interaction);
|
|
124
|
+
if (handled)
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
catch (err) {
|
|
128
|
+
console.error('[discord] Modal handler error:', err instanceof Error ? err.message : err);
|
|
129
|
+
if (!interaction.replied && !interaction.deferred) {
|
|
130
|
+
await interaction.reply({ content: 'Something went wrong.', flags: 64 }).catch(() => { });
|
|
131
|
+
}
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
// Handle string select menu interactions
|
|
137
|
+
this.client.on(Events.InteractionCreate, async (interaction) => {
|
|
138
|
+
if (!interaction.isStringSelectMenu())
|
|
139
|
+
return;
|
|
140
|
+
for (const handler of this.selectMenuHandlers) {
|
|
141
|
+
try {
|
|
142
|
+
const handled = await handler(interaction);
|
|
143
|
+
if (handled)
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
catch (err) {
|
|
147
|
+
console.error('[discord] Select menu handler error:', err instanceof Error ? err.message : err);
|
|
148
|
+
if (!interaction.replied && !interaction.deferred) {
|
|
149
|
+
await interaction.reply({ content: 'Something went wrong.', flags: 64 }).catch(() => { });
|
|
150
|
+
}
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
// Handle button interactions
|
|
156
|
+
this.client.on(Events.InteractionCreate, async (interaction) => {
|
|
157
|
+
if (!interaction.isButton())
|
|
158
|
+
return;
|
|
159
|
+
for (const handler of this.buttonHandlers) {
|
|
160
|
+
try {
|
|
161
|
+
const handled = await handler(interaction);
|
|
162
|
+
if (handled)
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
catch (err) {
|
|
166
|
+
console.error('[discord] Button handler error:', err instanceof Error ? err.message : err);
|
|
167
|
+
if (!interaction.replied && !interaction.deferred) {
|
|
168
|
+
await interaction.reply({ content: 'Something went wrong.', flags: 64 }).catch(() => { });
|
|
169
|
+
}
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
this.client.on(Events.ClientReady, async (c) => {
|
|
175
|
+
this.reconnectAttempts = 0;
|
|
176
|
+
console.log(`[discord] ✦ Connected as ${maskName(c.user.tag)}`);
|
|
177
|
+
// Register native slash commands per guild (instant, no 1-hour delay)
|
|
178
|
+
if (this.nativeCommands.length > 0) {
|
|
179
|
+
await this.registerSlashCommands(c.user.id);
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
// When bot joins a new guild, introduce itself
|
|
183
|
+
this.client.on(Events.GuildCreate, async (guild) => {
|
|
184
|
+
console.log(`[discord] Joined guild: ${guild.name} (${guild.id})`);
|
|
185
|
+
const agentName = this.agentId ?? 'Tako';
|
|
186
|
+
const intro = [
|
|
187
|
+
`👋 **${agentName}** just joined **${guild.name}**!`,
|
|
188
|
+
'',
|
|
189
|
+
`I'm an AI assistant powered by Tako 🐙. Here's how to talk to me:`,
|
|
190
|
+
`• **Mention me** — \`@${this.client?.user?.displayName ?? agentName}\` followed by your message`,
|
|
191
|
+
`• **DM me** — send a direct message for private conversations`,
|
|
192
|
+
'',
|
|
193
|
+
`**Commands:**`,
|
|
194
|
+
`• \`/help\` — see available commands`,
|
|
195
|
+
`• \`/status\` — check my current status`,
|
|
196
|
+
`• \`/model\` — view or switch the AI model`,
|
|
197
|
+
`• \`/new\` — start a fresh conversation`,
|
|
198
|
+
'',
|
|
199
|
+
`Ready to help! 🐙`,
|
|
200
|
+
].join('\n');
|
|
201
|
+
// Send to system channel or first text channel
|
|
202
|
+
const target = guild.systemChannel
|
|
203
|
+
?? guild.channels.cache.find((ch) => ch.type === ChannelType.GuildText &&
|
|
204
|
+
ch.permissionsFor(guild.members.me)?.has('SendMessages') === true);
|
|
205
|
+
if (target && 'send' in target) {
|
|
206
|
+
try {
|
|
207
|
+
await target.send(intro);
|
|
208
|
+
}
|
|
209
|
+
catch (err) {
|
|
210
|
+
console.error(`[discord] Failed to send intro to ${guild.name}:`, err.message);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
this.client.on(Events.Error, (err) => {
|
|
215
|
+
console.error('[discord] Client error:', err.message);
|
|
216
|
+
});
|
|
217
|
+
this.client.on(Events.ShardDisconnect, () => {
|
|
218
|
+
console.warn('[discord] Disconnected, will attempt reconnect...');
|
|
219
|
+
this.attemptReconnect();
|
|
220
|
+
});
|
|
221
|
+
await this.client.login(this.token);
|
|
222
|
+
}
|
|
223
|
+
async disconnect() {
|
|
224
|
+
if (this.client) {
|
|
225
|
+
this.client.removeAllListeners();
|
|
226
|
+
await this.client.destroy();
|
|
227
|
+
this.client = null;
|
|
228
|
+
console.log('[discord] Disconnected');
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
async send(msg) {
|
|
232
|
+
if (!this.client)
|
|
233
|
+
throw new Error('[discord] Not connected');
|
|
234
|
+
const channel = await this.client.channels.fetch(msg.target);
|
|
235
|
+
if (!channel || !channel.isTextBased()) {
|
|
236
|
+
throw new Error(`[discord] Cannot send to channel ${msg.target}`);
|
|
237
|
+
}
|
|
238
|
+
// Scan for secrets before sending
|
|
239
|
+
const safeContent = scanSecrets(msg.content);
|
|
240
|
+
const sendable = channel;
|
|
241
|
+
await this.sendChunks(sendable, safeContent, msg.replyTo);
|
|
242
|
+
}
|
|
243
|
+
/** Send message chunks to a text-based channel with retry. */
|
|
244
|
+
async sendChunks(channel, content, replyTo) {
|
|
245
|
+
const chunks = this.splitMessage(content);
|
|
246
|
+
for (let i = 0; i < chunks.length; i++) {
|
|
247
|
+
const opts = {
|
|
248
|
+
content: chunks[i],
|
|
249
|
+
...(i === 0 && replyTo ? { reply: { messageReference: replyTo } } : {}),
|
|
250
|
+
};
|
|
251
|
+
await withRetry(() => channel.send(opts), DISCORD_RETRY, `send chunk ${i + 1}/${chunks.length}`);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
async sendAndGetId(msg) {
|
|
255
|
+
if (!this.client)
|
|
256
|
+
throw new Error('[discord] Not connected');
|
|
257
|
+
const channel = await this.client.channels.fetch(msg.target);
|
|
258
|
+
if (!channel || !channel.isTextBased()) {
|
|
259
|
+
throw new Error(`[discord] Cannot send to channel ${msg.target}`);
|
|
260
|
+
}
|
|
261
|
+
const sendable = channel;
|
|
262
|
+
const sent = await withRetry(() => sendable.send({
|
|
263
|
+
content: msg.content,
|
|
264
|
+
...(msg.replyTo ? { reply: { messageReference: msg.replyTo } } : {}),
|
|
265
|
+
}), DISCORD_RETRY, 'sendAndGetId');
|
|
266
|
+
return sent.id;
|
|
267
|
+
}
|
|
268
|
+
async editMessage(chatId, messageId, content) {
|
|
269
|
+
if (!this.client)
|
|
270
|
+
throw new Error('[discord] Not connected');
|
|
271
|
+
const channel = await this.client.channels.fetch(chatId);
|
|
272
|
+
if (!channel || !channel.isTextBased()) {
|
|
273
|
+
throw new Error(`[discord] Cannot edit in channel ${chatId}`);
|
|
274
|
+
}
|
|
275
|
+
const textChannel = channel;
|
|
276
|
+
const message = await textChannel.messages.fetch(messageId);
|
|
277
|
+
await withRetry(() => message.edit({ content }), DISCORD_RETRY, 'editMessage');
|
|
278
|
+
}
|
|
279
|
+
onMessage(handler) {
|
|
280
|
+
this.handlers.push(handler);
|
|
281
|
+
}
|
|
282
|
+
convertInbound(message) {
|
|
283
|
+
return {
|
|
284
|
+
id: message.id,
|
|
285
|
+
channelId: `discord:${message.channelId}`,
|
|
286
|
+
author: {
|
|
287
|
+
id: message.author.id,
|
|
288
|
+
name: message.author.displayName || message.author.username,
|
|
289
|
+
meta: {
|
|
290
|
+
discriminator: message.author.discriminator,
|
|
291
|
+
guildId: message.guild?.id,
|
|
292
|
+
guildName: message.guild?.name,
|
|
293
|
+
},
|
|
294
|
+
},
|
|
295
|
+
content: message.content,
|
|
296
|
+
attachments: message.attachments.map((a) => ({
|
|
297
|
+
type: (a.contentType?.startsWith('image/') ? 'image'
|
|
298
|
+
: a.contentType?.startsWith('audio/') ? 'audio'
|
|
299
|
+
: a.contentType?.startsWith('video/') ? 'video'
|
|
300
|
+
: 'file'),
|
|
301
|
+
url: a.url,
|
|
302
|
+
filename: a.name ?? undefined,
|
|
303
|
+
mimeType: a.contentType ?? undefined,
|
|
304
|
+
})),
|
|
305
|
+
timestamp: message.createdAt.toISOString(),
|
|
306
|
+
raw: message,
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
splitMessage(content) {
|
|
310
|
+
if (content.length <= MAX_DISCORD_MESSAGE_LENGTH)
|
|
311
|
+
return [content];
|
|
312
|
+
const chunks = [];
|
|
313
|
+
let remaining = content;
|
|
314
|
+
while (remaining.length > 0) {
|
|
315
|
+
if (remaining.length <= MAX_DISCORD_MESSAGE_LENGTH) {
|
|
316
|
+
chunks.push(remaining);
|
|
317
|
+
break;
|
|
318
|
+
}
|
|
319
|
+
let splitAt = remaining.lastIndexOf('\n', MAX_DISCORD_MESSAGE_LENGTH);
|
|
320
|
+
if (splitAt === -1 || splitAt < MAX_DISCORD_MESSAGE_LENGTH / 2) {
|
|
321
|
+
splitAt = remaining.lastIndexOf(' ', MAX_DISCORD_MESSAGE_LENGTH);
|
|
322
|
+
}
|
|
323
|
+
if (splitAt === -1 || splitAt < MAX_DISCORD_MESSAGE_LENGTH / 2) {
|
|
324
|
+
splitAt = MAX_DISCORD_MESSAGE_LENGTH;
|
|
325
|
+
}
|
|
326
|
+
chunks.push(remaining.slice(0, splitAt));
|
|
327
|
+
remaining = remaining.slice(splitAt).trimStart();
|
|
328
|
+
}
|
|
329
|
+
return chunks;
|
|
330
|
+
}
|
|
331
|
+
/** Get the underlying discord.js Client (for advanced operations). */
|
|
332
|
+
getClient() {
|
|
333
|
+
return this.client;
|
|
334
|
+
}
|
|
335
|
+
/** Create a text channel in a guild. */
|
|
336
|
+
async createChannel(guildId, name, opts) {
|
|
337
|
+
if (!this.client)
|
|
338
|
+
throw new Error('[discord] Not connected');
|
|
339
|
+
const guild = await this.client.guilds.fetch(guildId);
|
|
340
|
+
const createOpts = {
|
|
341
|
+
name,
|
|
342
|
+
type: ChannelType.GuildText,
|
|
343
|
+
...(opts?.topic ? { topic: opts.topic } : {}),
|
|
344
|
+
...(opts?.parentId ? { parent: opts.parentId } : {}),
|
|
345
|
+
};
|
|
346
|
+
const channel = await guild.channels.create(createOpts);
|
|
347
|
+
return { id: channel.id, name: channel.name };
|
|
348
|
+
}
|
|
349
|
+
/** Broadcast a system message to all guild system/general channels. */
|
|
350
|
+
async broadcast(text) {
|
|
351
|
+
if (!this.client)
|
|
352
|
+
return;
|
|
353
|
+
try {
|
|
354
|
+
const guilds = this.guilds
|
|
355
|
+
? [...this.guilds].map(id => this.client.guilds.cache.get(id)).filter(Boolean)
|
|
356
|
+
: [...this.client.guilds.cache.values()];
|
|
357
|
+
for (const guild of guilds) {
|
|
358
|
+
if (!guild)
|
|
359
|
+
continue;
|
|
360
|
+
// Find the first text channel the bot can send to
|
|
361
|
+
const target = guild.systemChannel
|
|
362
|
+
?? guild.channels.cache.find((ch) => ch.type === ChannelType.GuildText &&
|
|
363
|
+
ch.permissionsFor(guild.members.me)?.has('SendMessages') === true);
|
|
364
|
+
if (target && 'send' in target) {
|
|
365
|
+
await target.send(text);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
catch (err) {
|
|
370
|
+
console.error('[discord] Broadcast failed:', err.message);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
/** Delete a channel by ID. */
|
|
374
|
+
async deleteChannel(channelId) {
|
|
375
|
+
if (!this.client)
|
|
376
|
+
throw new Error('[discord] Not connected');
|
|
377
|
+
const channel = await this.client.channels.fetch(channelId);
|
|
378
|
+
if (!channel)
|
|
379
|
+
throw new Error(`[discord] Channel not found: ${channelId}`);
|
|
380
|
+
if ('delete' in channel && typeof channel.delete === 'function') {
|
|
381
|
+
await channel.delete();
|
|
382
|
+
}
|
|
383
|
+
else {
|
|
384
|
+
throw new Error(`[discord] Cannot delete channel ${channelId}`);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
/** Edit a channel (name, topic). */
|
|
388
|
+
async editChannel(channelId, opts) {
|
|
389
|
+
if (!this.client)
|
|
390
|
+
throw new Error('[discord] Not connected');
|
|
391
|
+
const channel = await this.client.channels.fetch(channelId);
|
|
392
|
+
if (!channel)
|
|
393
|
+
throw new Error(`[discord] Channel not found: ${channelId}`);
|
|
394
|
+
if ('edit' in channel && typeof channel.edit === 'function') {
|
|
395
|
+
await channel.edit(opts);
|
|
396
|
+
}
|
|
397
|
+
else {
|
|
398
|
+
throw new Error(`[discord] Cannot edit channel ${channelId}`);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
/** Send a message to a specific channel by ID. */
|
|
402
|
+
async sendToChannel(channelId, content) {
|
|
403
|
+
if (!this.client)
|
|
404
|
+
throw new Error('[discord] Not connected');
|
|
405
|
+
const channel = await this.client.channels.fetch(channelId);
|
|
406
|
+
if (!channel || !channel.isTextBased()) {
|
|
407
|
+
throw new Error(`[discord] Cannot send to channel ${channelId}`);
|
|
408
|
+
}
|
|
409
|
+
const sendable = channel;
|
|
410
|
+
const chunks = this.splitMessage(content);
|
|
411
|
+
let lastMessageId = '';
|
|
412
|
+
for (const chunk of chunks) {
|
|
413
|
+
const msg = await sendable.send({ content: chunk });
|
|
414
|
+
lastMessageId = msg.id;
|
|
415
|
+
}
|
|
416
|
+
return lastMessageId;
|
|
417
|
+
}
|
|
418
|
+
/** Create a thread in a channel. */
|
|
419
|
+
async createThread(channelId, name, opts) {
|
|
420
|
+
if (!this.client)
|
|
421
|
+
throw new Error('[discord] Not connected');
|
|
422
|
+
const channel = await this.client.channels.fetch(channelId);
|
|
423
|
+
if (!channel || !channel.isTextBased()) {
|
|
424
|
+
throw new Error(`[discord] Cannot create thread in ${channelId}`);
|
|
425
|
+
}
|
|
426
|
+
const textChannel = channel;
|
|
427
|
+
if (opts?.messageId) {
|
|
428
|
+
const message = await textChannel.messages.fetch(opts.messageId);
|
|
429
|
+
const thread = await message.startThread({ name });
|
|
430
|
+
return { id: thread.id, name: thread.name };
|
|
431
|
+
}
|
|
432
|
+
else {
|
|
433
|
+
const thread = await textChannel.threads.create({ name });
|
|
434
|
+
return { id: thread.id, name: thread.name };
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
/** React to a message with an emoji. */
|
|
438
|
+
async react(channelId, messageId, emoji) {
|
|
439
|
+
if (!this.client)
|
|
440
|
+
throw new Error('[discord] Not connected');
|
|
441
|
+
const channel = await this.client.channels.fetch(channelId);
|
|
442
|
+
if (!channel || !channel.isTextBased()) {
|
|
443
|
+
throw new Error(`[discord] Cannot react in channel ${channelId}`);
|
|
444
|
+
}
|
|
445
|
+
const textChannel = channel;
|
|
446
|
+
const message = await textChannel.messages.fetch(messageId);
|
|
447
|
+
await message.react(emoji);
|
|
448
|
+
}
|
|
449
|
+
async sendTyping(channelId) {
|
|
450
|
+
if (!this.client)
|
|
451
|
+
return;
|
|
452
|
+
try {
|
|
453
|
+
const channel = await this.client.channels.fetch(channelId);
|
|
454
|
+
if (channel && channel.isTextBased() && 'sendTyping' in channel) {
|
|
455
|
+
await channel.sendTyping();
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
catch (err) {
|
|
459
|
+
console.error('[discord] sendTyping error:', err instanceof Error ? err.message : err);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
async addReaction(channelId, messageId, emoji) {
|
|
463
|
+
if (!this.client)
|
|
464
|
+
return;
|
|
465
|
+
try {
|
|
466
|
+
const channel = await this.client.channels.fetch(channelId);
|
|
467
|
+
if (channel && channel.isTextBased()) {
|
|
468
|
+
const message = await channel.messages.fetch(messageId);
|
|
469
|
+
await message.react(emoji);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
catch (err) {
|
|
473
|
+
console.error('[discord] addReaction error:', err instanceof Error ? err.message : err);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
async removeReaction(channelId, messageId, emoji) {
|
|
477
|
+
if (!this.client)
|
|
478
|
+
return;
|
|
479
|
+
try {
|
|
480
|
+
const channel = await this.client.channels.fetch(channelId);
|
|
481
|
+
if (channel && channel.isTextBased()) {
|
|
482
|
+
const message = await channel.messages.fetch(messageId);
|
|
483
|
+
const botUser = this.client.user;
|
|
484
|
+
if (botUser) {
|
|
485
|
+
await message.reactions.resolve(emoji)?.users.remove(botUser.id);
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
catch (err) {
|
|
490
|
+
console.error('[discord] removeReaction error:', err instanceof Error ? err.message : err);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
/** Set native slash commands and their handler. Call before connect(). */
|
|
494
|
+
setSlashCommands(commands, handler) {
|
|
495
|
+
this.nativeCommands = commands;
|
|
496
|
+
this.slashCommandHandler = handler;
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* Register an interactive handler for a specific slash command.
|
|
500
|
+
* Interactive handlers receive the raw ChatInputCommandInteraction and can
|
|
501
|
+
* reply with embeds, components, and collectors. They run before the
|
|
502
|
+
* text-based handler; if they return true the interaction is consumed.
|
|
503
|
+
*/
|
|
504
|
+
setInteractiveHandler(commandName, handler) {
|
|
505
|
+
this.interactiveHandlers.set(commandName, handler);
|
|
506
|
+
}
|
|
507
|
+
/**
|
|
508
|
+
* Register skill commands as Discord slash commands.
|
|
509
|
+
* Merges skill specs with existing native commands, re-registers with Discord API.
|
|
510
|
+
* Call after connect() when skills are loaded.
|
|
511
|
+
*/
|
|
512
|
+
async registerSkillCommands(specs, handler) {
|
|
513
|
+
// Rebuild command list: keep non-skill native commands, then add all skill specs
|
|
514
|
+
// This ensures no duplicates accumulate across hot-reloads
|
|
515
|
+
const skillNames = new Set(specs.map((s) => s.name));
|
|
516
|
+
const coreCommands = this.nativeCommands.filter((c) => !skillNames.has(c.name) && !this.previousSkillNames?.has(c.name));
|
|
517
|
+
const skillCommands = specs.map((s) => ({ name: s.name, description: s.description }));
|
|
518
|
+
// Deduplicate: if a core command has the same name as a skill, skill wins
|
|
519
|
+
const coreFiltered = coreCommands.filter((c) => !skillNames.has(c.name));
|
|
520
|
+
this.nativeCommands = [...coreFiltered, ...skillCommands];
|
|
521
|
+
this.previousSkillNames = skillNames;
|
|
522
|
+
this.slashCommandHandler = handler;
|
|
523
|
+
// Re-register with Discord API if already connected
|
|
524
|
+
const clientId = this.client?.user?.id;
|
|
525
|
+
if (clientId) {
|
|
526
|
+
await this.registerSlashCommands(clientId);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
/** Register a handler for modal submit interactions. */
|
|
530
|
+
onModalSubmit(handler) {
|
|
531
|
+
this.modalHandlers.push(handler);
|
|
532
|
+
}
|
|
533
|
+
/** Register a handler for string select menu interactions. */
|
|
534
|
+
onSelectMenu(handler) {
|
|
535
|
+
this.selectMenuHandlers.push(handler);
|
|
536
|
+
}
|
|
537
|
+
/** Register a handler for button interactions. */
|
|
538
|
+
onButton(handler) {
|
|
539
|
+
this.buttonHandlers.push(handler);
|
|
540
|
+
}
|
|
541
|
+
/** Register slash commands with Discord API per guild (instant update). */
|
|
542
|
+
async registerSlashCommands(clientId) {
|
|
543
|
+
const rest = new REST({ version: '10' }).setToken(this.token);
|
|
544
|
+
// Deduplicate by command name (last wins) to avoid accidental duplicates
|
|
545
|
+
const deduped = new Map();
|
|
546
|
+
for (const cmd of this.nativeCommands) {
|
|
547
|
+
deduped.set(cmd.name, { name: cmd.name, description: cmd.description });
|
|
548
|
+
}
|
|
549
|
+
const body = Array.from(deduped.values());
|
|
550
|
+
const MAX_SLASH_COMMANDS = 25;
|
|
551
|
+
const registerBody = body.length > MAX_SLASH_COMMANDS
|
|
552
|
+
? body.slice(0, MAX_SLASH_COMMANDS)
|
|
553
|
+
: body;
|
|
554
|
+
if (body.length > MAX_SLASH_COMMANDS) {
|
|
555
|
+
console.warn(`[discord] Slash command limit is ${MAX_SLASH_COMMANDS}; truncating ${body.length} -> ${registerBody.length}`);
|
|
556
|
+
}
|
|
557
|
+
if (this.guilds && this.guilds.size > 0) {
|
|
558
|
+
// Register per-guild for instant updates
|
|
559
|
+
for (const guildId of this.guilds) {
|
|
560
|
+
try {
|
|
561
|
+
await rest.put(Routes.applicationGuildCommands(clientId, guildId), { body: registerBody });
|
|
562
|
+
console.log(`[discord] ✦ Registered ${registerBody.length} slash commands for guild ${guildId}`);
|
|
563
|
+
}
|
|
564
|
+
catch (err) {
|
|
565
|
+
console.error(`[discord] Failed to register commands for guild ${guildId}:`, err instanceof Error ? err.message : err);
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
// Keep global commands in sync so DMs also get slash commands
|
|
569
|
+
// (global propagation can take longer than guild commands)
|
|
570
|
+
try {
|
|
571
|
+
await rest.put(Routes.applicationCommands(clientId), { body: registerBody });
|
|
572
|
+
console.log(`[discord] ✦ Synced ${registerBody.length} global slash commands for DM support`);
|
|
573
|
+
}
|
|
574
|
+
catch (err) {
|
|
575
|
+
console.warn('[discord] Could not sync global slash commands:', err instanceof Error ? err.message : err);
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
else {
|
|
579
|
+
// No guild whitelist — discover guilds from cache and register per-guild
|
|
580
|
+
const client = this.client;
|
|
581
|
+
if (client) {
|
|
582
|
+
const guilds = client.guilds.cache;
|
|
583
|
+
if (guilds.size > 0) {
|
|
584
|
+
for (const [guildId] of guilds) {
|
|
585
|
+
try {
|
|
586
|
+
await rest.put(Routes.applicationGuildCommands(clientId, guildId), { body: registerBody });
|
|
587
|
+
console.log(`[discord] ✦ Registered ${registerBody.length} slash commands for guild ${guildId}`);
|
|
588
|
+
}
|
|
589
|
+
catch (err) {
|
|
590
|
+
console.error(`[discord] Failed to register commands for guild ${guildId}:`, err instanceof Error ? err.message : err);
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
// Keep global commands in sync so DMs also get slash commands
|
|
594
|
+
// (global propagation can take longer than guild commands)
|
|
595
|
+
try {
|
|
596
|
+
await rest.put(Routes.applicationCommands(clientId), { body: registerBody });
|
|
597
|
+
console.log(`[discord] ✦ Synced ${registerBody.length} global slash commands for DM support`);
|
|
598
|
+
}
|
|
599
|
+
catch (err) {
|
|
600
|
+
console.warn('[discord] Could not sync global slash commands:', err instanceof Error ? err.message : err);
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
else {
|
|
604
|
+
// Fallback: register globally (takes up to 1 hour to propagate)
|
|
605
|
+
try {
|
|
606
|
+
await rest.put(Routes.applicationCommands(clientId), { body: registerBody });
|
|
607
|
+
console.log(`[discord] ✦ Registered ${registerBody.length} slash commands globally`);
|
|
608
|
+
}
|
|
609
|
+
catch (err) {
|
|
610
|
+
console.error('[discord] Failed to register global commands:', err instanceof Error ? err.message : err);
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
/** Archive a Discord thread by ID. */
|
|
617
|
+
async archiveThread(threadId) {
|
|
618
|
+
if (!this.client)
|
|
619
|
+
return;
|
|
620
|
+
try {
|
|
621
|
+
const channel = await this.client.channels.fetch(threadId);
|
|
622
|
+
if (channel?.isThread()) {
|
|
623
|
+
await channel.setArchived(true);
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
catch (err) {
|
|
627
|
+
console.error('[discord] archiveThread error:', err instanceof Error ? err.message : err);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
attemptReconnect() {
|
|
631
|
+
if (this.reconnectAttempts >= this.maxReconnectAttempts) {
|
|
632
|
+
console.error('[discord] Max reconnection attempts reached — scheduling final retry in 5 minutes');
|
|
633
|
+
setTimeout(async () => {
|
|
634
|
+
try {
|
|
635
|
+
if (this.client) {
|
|
636
|
+
this.reconnectAttempts = 0;
|
|
637
|
+
await this.client.login(this.token);
|
|
638
|
+
console.log('[discord] Final retry succeeded');
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
catch (err) {
|
|
642
|
+
console.error('[discord] Final reconnection failed:', err instanceof Error ? err.message : err);
|
|
643
|
+
console.error('[discord] CRITICAL: Discord channel is offline. Process will continue for other channels.');
|
|
644
|
+
}
|
|
645
|
+
}, 5 * 60 * 1000);
|
|
646
|
+
return;
|
|
647
|
+
}
|
|
648
|
+
this.reconnectAttempts++;
|
|
649
|
+
const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1);
|
|
650
|
+
console.log(`[discord] Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts})`);
|
|
651
|
+
setTimeout(async () => {
|
|
652
|
+
try {
|
|
653
|
+
if (this.client) {
|
|
654
|
+
await this.client.login(this.token);
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
catch (err) {
|
|
658
|
+
console.error('[discord] Reconnection failed:', err instanceof Error ? err.message : err);
|
|
659
|
+
this.attemptReconnect();
|
|
660
|
+
}
|
|
661
|
+
}, delay);
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
//# sourceMappingURL=discord.js.map
|