From 977f433bb2d35ae9a8a21bba2cdb6bac17b857f2 Mon Sep 17 00:00:00 2001 From: KimiSwitch Dev Date: Sun, 4 Oct 2026 00:26:05 +0800 Subject: [PATCH] =?UTF-8?q?fix(settings):=20=E9=80=82=E9=85=8D=20kimi-code?= =?UTF-8?q?=20=E8=BF=91=E6=9C=9F=E5=8F=98=E6=9B=B4=20=E2=80=94=20[watch]?= =?UTF-8?q?=20=E9=BB=98=E8=AE=A4=E5=80=BC=E4=BF=AE=E6=AD=A3=E4=B8=BA?= =?UTF-8?q?=E5=BC=80=E5=90=AF=EF=BC=88=E4=B8=8A=E6=B8=B8=20#4015=20?= =?UTF-8?q?=E7=BF=BB=E5=9B=9E=E9=BB=98=E8=AE=A4=E5=BC=80=EF=BC=89=EF=BC=9B?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E9=A1=B6=E5=B1=82=E5=BC=80=E5=85=B3=20auto?= =?UTF-8?q?=5Fsession=5Ftitle=EF=BC=88#3962=EF=BC=89=E4=B8=8E=20repeat=5Fb?= =?UTF-8?q?reaker=EF=BC=88#3995=EF=BC=8C=E9=BB=98=E8=AE=A4=E5=BC=80?= =?UTF-8?q?=E3=80=81false=20=E6=98=BE=E5=BC=8F=E5=86=99=E5=85=A5/true=20?= =?UTF-8?q?=E5=88=A0=E9=94=AE=EF=BC=89=EF=BC=9B=E6=9C=80=E5=A4=A7=E8=BE=93?= =?UTF-8?q?=E5=87=BA=20Token=20=E6=96=87=E6=A1=88=E4=BF=AE=E6=AD=A3?= =?UTF-8?q?=E4=B8=BA=E3=80=8C=E7=95=99=E7=A9=BA=E5=88=99=E4=B8=8D=E5=8F=91?= =?UTF-8?q?=E9=80=81=E8=BE=93=E5=87=BA=E4=B8=8A=E9=99=90=E3=80=8D=EF=BC=88?= =?UTF-8?q?=E4=B8=8A=E6=B8=B8=20#4091=20=E6=9C=AA=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E5=8D=B3=E7=9C=81=E7=95=A5=20max=5Ftokens=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/AgentSettingsPanel.tsx | 30 ++++++++++++--- src/i18n/en.ts | 11 +++++- src/i18n/zh.ts | 11 +++++- src/lib/agent-settings.test.ts | 53 ++++++++++++++++++++++++--- src/lib/agent-settings.ts | 30 +++++++++++++-- src/types/index.ts | 7 ++++ 6 files changed, 124 insertions(+), 18 deletions(-) diff --git a/src/components/AgentSettingsPanel.tsx b/src/components/AgentSettingsPanel.tsx index c4fb147..f2b4787 100644 --- a/src/components/AgentSettingsPanel.tsx +++ b/src/components/AgentSettingsPanel.tsx @@ -236,19 +236,37 @@ export function AgentSettingsPanel({ rawOther, onChange, models, defaultModel }: - {/* Top-level `[watch] enabled` (kimi-code 2.0.1+; off by default since - 2.0.2). KIMI_CODE_WATCH outranks this config at runtime — the env - var is probed by get_experimental_env_status as a non-flag entry - but deliberately locks nothing here, the toggle just documents the - config value that applies when the env var is unset. */} + {/* Top-level `[watch] enabled` (kimi-code 2.0.1+; 2.0.2 flipped the + default off, #4015 flipped it back on). KIMI_CODE_WATCH outranks + this config at runtime — the env var is probed by + get_experimental_env_status as a non-flag entry but deliberately + locks nothing here, the toggle just documents the config value + that applies when the env var is unset. */} updateWatch({ enabled: checked })} />

{t("watchEnabledDesc")}

+ + {/* Top-level booleans, both default true upstream: false is written + explicitly, true removes the key (see setAgentSettings). */} + update({ auto_session_title: checked })} + /> +

{t("autoSessionTitleDesc")}

+ update({ repeat_breaker: checked })} + /> +

{t("repeatBreakerDesc")}

+
+ {/* kimi-code `[permission] dangerous_command_guard`. The env var KIMI_CODE_DANGEROUS_COMMAND_GUARD (literal "true"/"false") diff --git a/src/i18n/en.ts b/src/i18n/en.ts index 2807385..2fc8db5 100644 --- a/src/i18n/en.ts +++ b/src/i18n/en.ts @@ -112,7 +112,7 @@ export const enTranslations: Record = { envPairs: "Env pairs", addEnv: "+ Add", modelMappingDesc: "Display name only affects the /model menu.", - maxOutputSizeDesc: "Max output tokens writes max_output_size — leave blank to use the upstream default.", + maxOutputSizeDesc: "Max output tokens writes max_output_size — leave blank to send no output cap upstream.", oneClickSetup: "One-click setup", fetchModels: "Fetch models", fetchingModels: "Fetching...", @@ -188,7 +188,14 @@ export const enTranslations: Record = { watchSettings: "File Watching", watchEnabled: "Enable file watching", watchEnabledDesc: - "Watch config files and the workspace for changes (configurable since kimi-code 2.0.1, off by default since 2.0.2). The KIMI_CODE_WATCH environment variable overrides this setting.", + "Watch config files and the workspace for changes (configurable since kimi-code 2.0.1, on by default). The KIMI_CODE_WATCH environment variable overrides this setting.", + behaviorSettings: "Behavior", + autoSessionTitle: "Auto session title", + autoSessionTitleDesc: + "Let clients auto-generate session titles (on by default; turning it off writes false).", + repeatBreaker: "Repeat breaker", + repeatBreakerDesc: + "Remind and force-stop on consecutively repeated identical tool calls (on by default). The KIMI_CODE_REPEAT_BREAKER environment variable overrides this setting.", permissionRules: "Permission Rules", permissionDecision: "Decision", permissionPattern: "Pattern", diff --git a/src/i18n/zh.ts b/src/i18n/zh.ts index a33674b..b1016bb 100644 --- a/src/i18n/zh.ts +++ b/src/i18n/zh.ts @@ -109,7 +109,7 @@ export const zhTranslations = { envPairs: "Env 键值对", addEnv: "+ 添加", modelMappingDesc: "显示名称只影响 /model 菜单。", - maxOutputSizeDesc: "「最大输出 Token」写入 max_output_size,留空则用上游默认值。", + maxOutputSizeDesc: "「最大输出 Token」写入 max_output_size,留空则不发送输出上限。", oneClickSetup: "一键设置", fetchModels: "获取模型列表", fetchingModels: "获取中...", @@ -181,7 +181,14 @@ export const zhTranslations = { watchSettings: "文件监听", watchEnabled: "启用文件监听", watchEnabledDesc: - "监听配置文件与工作目录变化(kimi-code 2.0.1 起可配置,2.0.2 起默认关闭)。环境变量 KIMI_CODE_WATCH 会覆盖本配置。", + "监听配置文件与工作目录变化(kimi-code 2.0.1 起可配置,默认开启)。环境变量 KIMI_CODE_WATCH 会覆盖本配置。", + behaviorSettings: "行为开关", + autoSessionTitle: "自动生成会话标题", + autoSessionTitleDesc: + "允许客户端自动生成会话标题(默认开启;关闭后写入 false)。", + repeatBreaker: "重复调用拦截", + repeatBreakerDesc: + "连续重复相同工具调用时提醒并强制停止(默认开启)。环境变量 KIMI_CODE_REPEAT_BREAKER 会覆盖本配置。", permissionRules: "权限规则", permissionDecision: "处置", permissionPattern: "模式", diff --git a/src/lib/agent-settings.test.ts b/src/lib/agent-settings.test.ts index 0063325..7caca11 100644 --- a/src/lib/agent-settings.test.ts +++ b/src/lib/agent-settings.test.ts @@ -201,8 +201,8 @@ describe("loop_control.compaction_max_attempts", () => { }); // --------------------------------------------------------------------------- -// [watch] enabled (kimi-code 2.0.1+) — top-level section, off by default since -// 2.0.2; mirrors the [background] handling +// [watch] enabled (kimi-code 2.0.1+) — top-level section; 2.0.2 flipped the +// default off, #4015 flipped it back on. Mirrors the [background] handling. // --------------------------------------------------------------------------- function watchOf(raw: unknown): Record { @@ -213,9 +213,9 @@ function watchOf(raw: unknown): Record { } describe("[watch] enabled", () => { - it("reads as false when the section or key is absent (2.0.2 default)", () => { - expect(getAgentSettings({}).watch?.enabled).toBe(false); - expect(getAgentSettings({ watch: {} }).watch?.enabled).toBe(false); + it("reads as true when the section or key is absent (#4015 default)", () => { + expect(getAgentSettings({}).watch?.enabled).toBe(true); + expect(getAgentSettings({ watch: {} }).watch?.enabled).toBe(true); }); it("reads an explicit value", () => { @@ -248,6 +248,49 @@ describe("[watch] enabled", () => { }); }); +// --------------------------------------------------------------------------- +// Top-level booleans (auto_session_title #3962 / repeat_breaker #3995): +// upstream default true — false is written explicitly, true removes the key. +// --------------------------------------------------------------------------- + +describe("top-level boolean switches", () => { + it("reads as undefined when the key is absent (default true)", () => { + const s = getAgentSettings({}); + expect(s.auto_session_title).toBeUndefined(); + expect(s.repeat_breaker).toBeUndefined(); + }); + + it("reads explicit false values", () => { + const s = getAgentSettings({ + auto_session_title: false, + repeat_breaker: false, + }); + expect(s.auto_session_title).toBe(false); + expect(s.repeat_breaker).toBe(false); + }); + + it("writes false explicitly and removes the key on true", () => { + const off = setAgentSettings({}, { repeat_breaker: false }) as Record< + string, + unknown + >; + expect(off.repeat_breaker).toBe(false); + const on = setAgentSettings( + { repeat_breaker: false }, + { repeat_breaker: true } + ) as Record; + expect("repeat_breaker" in on).toBe(false); + }); + + it("keeps an explicit false on saves that do not touch it", () => { + const next = setAgentSettings( + { auto_session_title: false }, + { thinking: { effort: "high" } } + ) as Record; + expect(next.auto_session_title).toBe(false); + }); +}); + describe("permission.dangerous_command_guard", () => { it("reads as undefined when the key is absent (default on)", () => { diff --git a/src/lib/agent-settings.ts b/src/lib/agent-settings.ts index 158c046..2dabb74 100644 --- a/src/lib/agent-settings.ts +++ b/src/lib/agent-settings.ts @@ -13,10 +13,11 @@ const DEFAULT_SETTINGS: AgentSettings = { background: { keep_alive_on_exit: false, }, - // `[watch] enabled` — kimi-code 2.0.1 added the key, 2.0.2 flipped the - // default to off, so an absent key reads as "off". + // `[watch] enabled` — kimi-code 2.0.1 added the key; 2.0.2 flipped the + // default to off, then #4015 flipped it back on, so an absent key reads + // as "on". watch: { - enabled: false, + enabled: true, }, permission: { rules: [] }, hooks: [], @@ -37,6 +38,7 @@ function getSection(rawOther: unknown, key: string): T | undefined { } export function getAgentSettings(rawOther: unknown): AgentSettings { + const root = asRecord(rawOther); const sectionLoop = getSection( rawOther, "loop_control" @@ -92,6 +94,16 @@ export function getAgentSettings(rawOther: unknown): AgentSettings { : {}), }, hooks: getSection(rawOther, "hooks") ?? [], + // Top-level booleans (upstream default true): keep only explicit values, + // an absent key means "on" — the UI shows `?? true`. + auto_session_title: + typeof root.auto_session_title === "boolean" + ? root.auto_session_title + : undefined, + repeat_breaker: + typeof root.repeat_breaker === "boolean" + ? root.repeat_breaker + : undefined, }; } @@ -166,5 +178,17 @@ export function setAgentSettings( delete root.hooks; } + // Top-level booleans with an upstream default of true: an explicit false + // is written; true/undefined removes the key so the config tracks the + // upstream default instead of pinning it. + for (const key of ["auto_session_title", "repeat_breaker"] as const) { + const value = patch[key] ?? current[key]; + if (value === false) { + root[key] = false; + } else { + delete root[key]; + } + } + return root; } diff --git a/src/types/index.ts b/src/types/index.ts index d0e3c4a..d101321 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -172,6 +172,13 @@ export interface AgentSettings { background?: BackgroundConfig; /** Top-level `[watch]` section (kimi-code 2.0.1+). */ watch?: WatchConfig; + /** Top-level config.toml key (kimi-code #3962): let clients auto-generate + * session titles. Default true; only an explicit false disables. */ + auto_session_title?: boolean; + /** Top-level config.toml key (kimi-code #3995): repeat-breaker for + * consecutively repeated identical tool calls. Default true; env + * KIMI_CODE_REPEAT_BREAKER outranks this config. */ + repeat_breaker?: boolean; permission?: { rules?: PermissionRule[]; /** kimi-code `[permission]` key. Default true when the key is