feat: generalized channel config + openclaw passthrough#38
Merged
Conversation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Introduce data-driven channel definitions modeled after CapabilityDef. Each ChannelDef declares essential fields (credential + key settings) that drive validation, wizard rendering, bootstrap, and sanitization. - ChannelDef type + registry with Telegram, Discord, Slack, WhatsApp - channels and openclaw keys on InstanceConfig - Zod schemas for new config sections - Backward compat: top-level telegram key kept (deprecated) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- buildChannelsSchema() derives Zod schemas from ChannelDef fields with passthrough for extra fields - loadConfig() migrates deprecated top-level telegram to channels.telegram - validateConfig() applies channel schemas like capability schemas - sanitizeConfig() generically strips channel secrets via ChannelDef Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace hardcoded Telegram bootstrap with a generic channel command generator that works for any channel. Each channel's config is walked and applied via openclaw config set commands. ChannelDef postCommands handle channel-specific ordering (e.g., Telegram dmPolicy after allowFrom). Add openclaw passthrough: arbitrary dotpath-to-value mappings applied during bootstrap for config not covered by ChannelDefs. Generalize infra-secrets patching to handle any channel's secret refs, not just Telegram. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove all backward-compatibility code for the deprecated top-level `telegram` config key. Channels now live exclusively under `channels.*`. Introduce DynamicSection abstraction that unifies capabilities and channels in the wizard. Both are driven by configDef and rendered by the same CapabilitySection component. All focus-list, sidebar, and select-field logic operates on DynamicSection uniformly — no more scattered string prefix parsing. - Delete telegramSchema (orphaned) - Remove telegram migration in loadConfig - Remove hardcoded telegram wizard section and state - Single dynamicValues state for both capabilities and channels - Update tests and examples to use channels.telegram - Update config-review for dynamic channel rows Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…rough Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Non-interactive visual separators that group related sections: - Infrastructure: Resources, Provider, Network, capabilities - Channels: Telegram, Discord, Slack, WhatsApp - Identity: Agent Identity / bootstrap Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add "toggle" to ConfigFieldType — renders as [x]/[ ] checkbox in the
wizard, toggles on Enter, derives z.boolean() in Zod schemas.
Every channel now has an explicit "enabled" toggle as its first field:
- JSON: { "whatsapp": { "enabled": true } } instead of empty object
- Wizard: expand channel, first item is [x] Enabled toggle
- Bootstrap: skips channels with enabled: false
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Prevents emitting channels with enabled: false or channels where the user expanded the section but never toggled enabled. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace hardcoded allowFrom/groups check in bootstrap with a handledKeys array on the ChannelDef postCommands object. The generic loop reads handled keys from the definition rather than maintaining channel-specific knowledge in bootstrap code. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
channelsconfig key: Replaces the old top-leveltelegramkey. Each channel has an explicitenabledtoggle and channel-specific fields.openclawpassthrough: Arbitrary dotpath-to-value config applied viaopenclaw config setduring bootstrap — users can configure anything OpenClaw supports without waiting for a ChannelDef.DynamicSectionabstraction: Unifies capabilities and channels in the wizard. One registry, typed lookups, no scattered string prefix parsing.togglefield type: New configDef field type rendering as[x]/[ ]checkbox, used for channelenabledtoggles.Adding a new channel
Add a ~15-line
ChannelDefentry inpackages/types/src/channels.ts. Everything else (wizard, validation, bootstrap, sanitization) is automatic.Config shape
{ "channels": { "telegram": { "enabled": true, "botToken": "123:ABC-..." }, "discord": { "enabled": true, "token": "MTIz..." }, "whatsapp": { "enabled": true } }, "openclaw": { "channels.discord.streaming": "partial", "session.dmScope": "per-channel-peer" } }Test plan
bun test— 260 pass, 0 failclawctl-dev create— interactive wizard renders channel sections with group headers and toggle fieldsclawctl-dev create --config examples/config.full.json— headless mode with channel configenabled: false) is skipped during bootstrap🤖 Generated with Claude Code