Skip to content

fix(controller): preserve channel configs and agent model fallbacks on redeploy#1337

Open
kilo-code-bot[bot] wants to merge 1 commit intomainfrom
fix/preserve-channel-and-model-configs-on-redeploy
Open

fix(controller): preserve channel configs and agent model fallbacks on redeploy#1337
kilo-code-bot[bot] wants to merge 1 commit intomainfrom
fix/preserve-channel-and-model-configs-on-redeploy

Conversation

@kilo-code-bot
Copy link
Contributor

@kilo-code-bot kilo-code-bot bot commented Mar 20, 2026

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 generateBaseConfig for gateway, tools, browser, plugins.entries, etc.). On redeploy, existing config objects are preserved via config.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:

  • Telegram (lines 224-236): replaced config.channels.telegram = { ... } with field-level sets
  • Discord (lines 243-254): replaced config.channels.discord = { ... } with field-level sets; also preserves dm sub-object
  • Slack (lines 260-266): replaced config.channels.slack = { ... } with field-level sets
  • Agent model (lines 184-189): replaced config.agents.defaults.model = { primary: ... } with config.agents.defaults.model.primary = ..., preserving fallback and other user-set keys

Verification

  • pnpm typecheck — passed (0 errors)
  • pnpm test -- controller/src/config-writer.test.ts — 47 tests passed
  • pnpm test (full suite) — 948 tests passed across 42 files
  • pnpm lint (kiloclaw) — 0 warnings, 0 errors

Visual Changes

N/A

Reviewer Notes

  • The fix follows the exact same null-coalescing + field-level set pattern already used for config.gateway, config.tools, config.browser, and config.plugins.entries in the same function — no new patterns introduced.
  • Four new tests verify that user customizations survive a restart for each channel (Telegram, Discord, Slack) and for agent model fallback settings.
  • The 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

…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) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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') {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@kilo-code-bot
Copy link
Contributor Author

kilo-code-bot bot commented Mar 20, 2026

Code Review Summary

Status: 2 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 2
SUGGESTION 0

Fix these issues in Kilo Cloud

Issue Details (click to expand)

CRITICAL

File Line Issue
N/A N/A None

WARNING

File Line Issue
kiloclaw/controller/src/config-writer.ts 231 Telegram allowFrom is never cleared, so removed env allowlists or tighter DM policy settings do not take effect on redeploy.
kiloclaw/controller/src/config-writer.ts 251 Discord dm.allowFrom remains ['*'] after switching away from DISCORD_DM_POLICY=open, leaving stale access state in the generated config.

SUGGESTION

File Line Issue
N/A N/A None
Other Observations (not in diff)

Issues found in unchanged code that cannot receive inline comments:

N/A

Files Reviewed (2 files)
  • kiloclaw/controller/src/config-writer.ts - 2 issues
  • kiloclaw/controller/src/config-writer.test.ts - 0 issues

Reviewed by gpt-5.4-20260305 · 259,363 tokens

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant