fix(controller): preserve channel configs and agent model fallbacks on redeploy#1337
fix(controller): preserve channel configs and agent model fallbacks on redeploy#1337kilo-code-bot[bot] wants to merge 1 commit intomainfrom
Conversation
…n redeploy Channel configs (Telegram, Discord, Slack) and agent model defaults were being overwritten with fresh object literals on every restart/redeploy, destroying user customizations. Switch to null-coalescing init + field-level set pattern (consistent with the rest of generateBaseConfig) so existing config keys are preserved and only env-derived fields are updated.
| config.channels.telegram.botToken = env.TELEGRAM_BOT_TOKEN; | ||
| config.channels.telegram.enabled = true; | ||
| config.channels.telegram.dmPolicy = dmPolicy; | ||
| if (env.TELEGRAM_DM_ALLOW_FROM) { |
There was a problem hiding this comment.
WARNING: Stale Telegram allowlist survives env changes
allowFrom is still env-derived here, but this branch only ever sets it and never removes it. If a redeploy stops sending TELEGRAM_DM_ALLOW_FROM or changes TELEGRAM_DM_POLICY away from open, the previous allowlist or ['*'] value remains in the config and keeps the old DM access policy in effect.
| config.channels.discord.enabled = true; | ||
| config.channels.discord.dm = config.channels.discord.dm ?? {}; | ||
| config.channels.discord.dm.policy = dmPolicy; | ||
| if (dmPolicy === 'open') { |
There was a problem hiding this comment.
WARNING: Stale Discord DM allowlist survives policy changes
This now preserves dm.allowFrom indefinitely, but that field is derived from the current env policy rather than user customization. A machine that was previously deployed with DISCORD_DM_POLICY=open will keep allowFrom: ['*'] even after a later redeploy tightens the policy, so the written config no longer matches the requested env state.
Code Review SummaryStatus: 2 Issues Found | Recommendation: Address before merge Overview
Fix these issues in Kilo Cloud Issue Details (click to expand)CRITICAL
WARNING
SUGGESTION
Other Observations (not in diff)Issues found in unchanged code that cannot receive inline comments: N/A Files Reviewed (2 files)
Reviewed by gpt-5.4-20260305 · 259,363 tokens |
Summary
The controller's
generateBaseConfig()was overwriting channel configs (channels.telegram,channels.discord,channels.slack) and the agent model default (agents.defaults.model) with fresh object literals on every restart/redeploy. This destroyed user customizations such as Discord guild configs, Slack slash commands, Telegram group policies, DM allowlists, and model fallback settings.Fix: Switch from full object assignment to the null-coalescing init + field-level set pattern (already used elsewhere in
generateBaseConfigforgateway,tools,browser,plugins.entries, etc.). On redeploy, existing config objects are preserved viaconfig.channels.X = config.channels.X ?? {}and only env-derived fields (botToken,enabled,dmPolicy, etc.) are updated. User-added keys are left untouched. Initial bootstrap still sets all defaults because the config starts empty.Changes in
config-writer.ts:config.channels.telegram = { ... }with field-level setsconfig.channels.discord = { ... }with field-level sets; also preservesdmsub-objectconfig.channels.slack = { ... }with field-level setsconfig.agents.defaults.model = { primary: ... }withconfig.agents.defaults.model.primary = ..., preservingfallbackand other user-set keysVerification
pnpm typecheck— passed (0 errors)pnpm test -- controller/src/config-writer.test.ts— 47 tests passedpnpm test(full suite) — 948 tests passed across 42 filespnpm lint(kiloclaw) — 0 warnings, 0 errorsVisual Changes
N/A
Reviewer Notes
config.gateway,config.tools,config.browser, andconfig.plugins.entriesin the same function — no new patterns introduced.writeBaseConfig(fresh install / config restore) path is unaffected because config starts empty, so the?? {}initializers create fresh objects and all fields are set — identical behavior to before.Built for Florian by Kilo for Slack