From 78a058acd2fc91de5cca0c1d66d415ee35884889 Mon Sep 17 00:00:00 2001 From: Kai Date: Thu, 2 Jul 2026 19:50:51 +0800 Subject: [PATCH] chore(agent-core): remove experimental micro compaction (#1317) * chore(agent-core): remove experimental micro compaction * fix(docs): drop micro compaction row from env-vars table --- .changeset/remove-micro-compaction.md | 5 + apps/kimi-code/src/tui/commands/config.ts | 3 +- docs/en/configuration/config-files.md | 6 +- docs/en/configuration/env-vars.md | 1 - docs/zh/configuration/config-files.md | 6 +- docs/zh/configuration/env-vars.md | 1 - .../agent-core/src/agent/compaction/micro.ts | 159 ++++++++++-------- packages/agent-core/src/flags/registry.ts | 19 ++- packages/agent-core/src/flags/types.ts | 5 +- packages/agent-core/test/agent/basic.test.ts | 4 +- .../compaction/compaction-scenarios.test.ts | 4 +- .../test/agent/compaction/full.test.ts | 12 +- .../test/agent/compaction/micro.test.ts | 19 ++- .../agent-core/test/harness/runtime.test.ts | 42 +++-- packages/migration-legacy/src/steps/config.ts | 2 +- .../test/steps/config.test.ts | 7 +- packages/node-sdk/test/config.test.ts | 25 +-- 17 files changed, 170 insertions(+), 150 deletions(-) create mode 100644 .changeset/remove-micro-compaction.md diff --git a/.changeset/remove-micro-compaction.md b/.changeset/remove-micro-compaction.md new file mode 100644 index 000000000..2f3d7f6b8 --- /dev/null +++ b/.changeset/remove-micro-compaction.md @@ -0,0 +1,5 @@ +--- +"@moonshot-ai/kimi-code": patch +--- + +Remove the experimental micro compaction feature and its toggle from the experiments panel. diff --git a/apps/kimi-code/src/tui/commands/config.ts b/apps/kimi-code/src/tui/commands/config.ts index 8c02afb98..efa859181 100644 --- a/apps/kimi-code/src/tui/commands/config.ts +++ b/apps/kimi-code/src/tui/commands/config.ts @@ -1,7 +1,6 @@ import { effectiveModelAlias, type ExperimentalFeatureState, - type FlagId, type ModelAlias, type PermissionMode, type Session, @@ -590,7 +589,7 @@ export async function applyExperimentalFeatureChanges( return; } - const experimental: Partial> = {}; + const experimental: Record = {}; for (const change of changes) { experimental[change.id] = change.enabled; } diff --git a/docs/en/configuration/config-files.md b/docs/en/configuration/config-files.md index 4bfbe6432..a33826230 100644 --- a/docs/en/configuration/config-files.md +++ b/docs/en/configuration/config-files.md @@ -51,8 +51,8 @@ reserved_context_size = 50000 max_running_tasks = 4 keep_alive_on_exit = false -[experimental] -micro_compaction = false +# [experimental] +# micro_compaction = false # disabled: micro compaction has been removed [[permission.rules]] decision = "allow" @@ -200,6 +200,7 @@ You can also switch models temporarily without touching the config file — by s `keep_alive_on_exit` can be overridden by the `KIMI_CODE_BACKGROUND_KEEP_ALIVE_ON_EXIT` environment variable, which takes higher priority than `config.toml`. + ## `services` diff --git a/docs/en/configuration/env-vars.md b/docs/en/configuration/env-vars.md index e084c326e..809bda3c2 100644 --- a/docs/en/configuration/env-vars.md +++ b/docs/en/configuration/env-vars.md @@ -125,7 +125,6 @@ Switches that control the behavior of subsystems such as telemetry, background t | `KIMI_CODE_PLUGIN_MARKETPLACE_URL` | Override the plugin marketplace JSON loaded by `/plugins`; useful for dev loopback servers, staging CDN files, or alternate marketplace directories | `https://code.kimi.com/kimi-code/plugins/marketplace.json`; also accepts `http://`, `file://` URLs, and local paths | | `KIMI_CODE_AGENT_SWARM_MAX_CONCURRENCY` | Cap how many AgentSwarm subagents run concurrently during the initial ramp; leave unset for no cap | Positive integer; invalid values fail fast | | `KIMI_CODE_EXPERIMENTAL_FLAG` | Enable all registered experimental features for this process | `1`, `true`, `yes`, `on` | -| `KIMI_CODE_EXPERIMENTAL_MICRO_COMPACTION` | Override [`[experimental].micro_compaction`](./config-files.md#experimental) for this process | Truthy or falsy | | `KIMI_SHELL_PATH` | Override the Git Bash path on Windows (used when auto-detection fails) | Absolute path | | `KIMI_MODEL_MAX_COMPLETION_TOKENS` | Hard cap on `max_completion_tokens` per LLM step; applies to the `kimi` provider only | Positive integer; `0` or negative disables clamping | | `KIMI_MODEL_TEMPERATURE` | Sampling temperature for every request; applies to the `kimi` provider only (global — independent of `KIMI_MODEL_NAME`) | Number, e.g. `0.3` | diff --git a/docs/zh/configuration/config-files.md b/docs/zh/configuration/config-files.md index 3eefe21b0..8310b2ca8 100644 --- a/docs/zh/configuration/config-files.md +++ b/docs/zh/configuration/config-files.md @@ -51,8 +51,8 @@ reserved_context_size = 50000 max_running_tasks = 4 keep_alive_on_exit = false -[experimental] -micro_compaction = false +# [experimental] +# micro_compaction = false # disabled: micro compaction has been removed [[permission.rules]] decision = "allow" @@ -200,6 +200,7 @@ default_effort = "high" `keep_alive_on_exit` 可被环境变量 `KIMI_CODE_BACKGROUND_KEEP_ALIVE_ON_EXIT` 覆盖,优先级高于配置文件。 + ## `services` diff --git a/docs/zh/configuration/env-vars.md b/docs/zh/configuration/env-vars.md index 19bce1e73..6adc95d38 100644 --- a/docs/zh/configuration/env-vars.md +++ b/docs/zh/configuration/env-vars.md @@ -125,7 +125,6 @@ kimi | `KIMI_CODE_PLUGIN_MARKETPLACE_URL` | 覆盖 `/plugins` 加载的 plugin marketplace JSON,适合 dev loopback server、测试 CDN 文件或替换 marketplace 目录 | `https://code.kimi.com/kimi-code/plugins/marketplace.json`;也接受 `http://`、`file://` URL 和本地路径 | | `KIMI_CODE_AGENT_SWARM_MAX_CONCURRENCY` | 限制 AgentSwarm 初始提升并发阶段可同时运行的子 Agent 数量;不设置表示不限制 | 正整数;非法值会立即失败 | | `KIMI_CODE_EXPERIMENTAL_FLAG` | 在当前进程启用所有已注册的实验功能 | `1`、`true`、`yes`、`on` | -| `KIMI_CODE_EXPERIMENTAL_MICRO_COMPACTION` | 覆盖当前进程的 [`[experimental].micro_compaction`](./config-files.md#experimental) | 真值或假值 | | `KIMI_SHELL_PATH` | Windows 上覆盖 Git Bash 路径(自动探测失败时使用) | 绝对路径 | | `KIMI_MODEL_MAX_COMPLETION_TOKENS` | 单步 LLM 请求的 `max_completion_tokens` 硬上限,仅对 `kimi` 供应商生效 | 正整数;`0` 或负数禁用 clamp | | `KIMI_MODEL_TEMPERATURE` | 每次请求的采样温度,仅对 `kimi` 供应商生效(全局生效,不依赖 `KIMI_MODEL_NAME`) | 数字,如 `0.3` | diff --git a/packages/agent-core/src/agent/compaction/micro.ts b/packages/agent-core/src/agent/compaction/micro.ts index 903709600..223e3b6ac 100644 --- a/packages/agent-core/src/agent/compaction/micro.ts +++ b/packages/agent-core/src/agent/compaction/micro.ts @@ -1,10 +1,11 @@ -import type { ContentPart } from '@moonshot-ai/kosong'; +// Micro compaction is disabled; ContentPart is no longer referenced here. +// import type { ContentPart } from '@moonshot-ai/kosong'; import type { Agent } from '..'; import type { ContextMessage } from '../context'; import { estimateTokensForContentParts, - estimateTokensForMessages, + // estimateTokensForMessages, // disabled with micro compaction } from '../../utils/tokens'; export interface MicroCompactionConfig { @@ -47,83 +48,93 @@ export class MicroCompaction { } detect(): void { - if (!this.agent.experimentalFlags.enabled('micro_compaction')) return; + // Micro compaction is disabled: the `micro_compaction` experimental flag has + // been removed from the registry, so detection is intentionally a no-op. + return; - const config = this.config; - const { history, lastAssistantAt } = this.agent.context; - const cacheAgeMs = lastAssistantAt === null ? null : Date.now() - lastAssistantAt; - const cacheMissed = cacheAgeMs !== null && cacheAgeMs >= config.cacheMissedThresholdMs; - if (!cacheMissed) return; - - const maxContextTokens = this.agent.config.modelCapabilities.max_context_tokens; - const contextTokens = this.agent.context.tokenCountWithPending; - const contextUsageRatio = - maxContextTokens !== undefined && maxContextTokens > 0 - ? contextTokens / maxContextTokens - : 1; - if (contextUsageRatio < config.minContextUsageRatio) return; - - const previousCutoff = this.cutoff; - const nextCutoff = Math.max(0, history.length - config.keepRecentMessages); - this.apply(nextCutoff); - if (previousCutoff !== nextCutoff) { - const effect = this.measureEffect(history, nextCutoff); - const previousEffect = this.measureEffect(history, previousCutoff); - const rawContextTokens = estimateTokensForMessages(history); - // Whole-context length before/after this cutoff change, mirroring the - // `tokens_before`/`tokens_after` fields on `compaction_finished` so the - // two compaction paths can be compared on the same axis. - const tokensBefore = - rawContextTokens - - previousEffect.truncatedToolResultTokensBefore + - previousEffect.truncatedToolResultTokensAfter; - const tokensAfter = - rawContextTokens - - effect.truncatedToolResultTokensBefore + - effect.truncatedToolResultTokensAfter; - this.agent.telemetry.track('micro_compaction_finished', { - keep_recent_messages: config.keepRecentMessages, - min_content_tokens: config.minContentTokens, - cache_missed_threshold_ms: config.cacheMissedThresholdMs, - truncated_marker: config.truncatedMarker, - min_context_usage_ratio: config.minContextUsageRatio, - truncated_tool_result_count: effect.truncatedToolResultCount, - truncated_tool_result_tokens_before: effect.truncatedToolResultTokensBefore, - truncated_tool_result_tokens_after: effect.truncatedToolResultTokensAfter, - tokens_before: tokensBefore, - tokens_after: tokensAfter, - previous_cutoff: previousCutoff, - cutoff: nextCutoff, - message_count: history.length, - cache_age_ms: cacheAgeMs, - thinking_effort: this.agent.config.thinkingEffort, - }); - } + // Original implementation (disabled): + // if (!this.agent.experimentalFlags.enabled('micro_compaction')) return; + // + // const config = this.config; + // const { history, lastAssistantAt } = this.agent.context; + // const cacheAgeMs = lastAssistantAt === null ? null : Date.now() - lastAssistantAt; + // const cacheMissed = cacheAgeMs !== null && cacheAgeMs >= config.cacheMissedThresholdMs; + // if (!cacheMissed) return; + // + // const maxContextTokens = this.agent.config.modelCapabilities.max_context_tokens; + // const contextTokens = this.agent.context.tokenCountWithPending; + // const contextUsageRatio = + // maxContextTokens !== undefined && maxContextTokens > 0 + // ? contextTokens / maxContextTokens + // : 1; + // if (contextUsageRatio < config.minContextUsageRatio) return; + // + // const previousCutoff = this.cutoff; + // const nextCutoff = Math.max(0, history.length - config.keepRecentMessages); + // this.apply(nextCutoff); + // if (previousCutoff !== nextCutoff) { + // const effect = this.measureEffect(history, nextCutoff); + // const previousEffect = this.measureEffect(history, previousCutoff); + // const rawContextTokens = estimateTokensForMessages(history); + // // Whole-context length before/after this cutoff change, mirroring the + // // `tokens_before`/`tokens_after` fields on `compaction_finished` so the + // // two compaction paths can be compared on the same axis. + // const tokensBefore = + // rawContextTokens - + // previousEffect.truncatedToolResultTokensBefore + + // previousEffect.truncatedToolResultTokensAfter; + // const tokensAfter = + // rawContextTokens - + // effect.truncatedToolResultTokensBefore + + // effect.truncatedToolResultTokensAfter; + // this.agent.telemetry.track('micro_compaction_finished', { + // keep_recent_messages: config.keepRecentMessages, + // min_content_tokens: config.minContentTokens, + // cache_missed_threshold_ms: config.cacheMissedThresholdMs, + // truncated_marker: config.truncatedMarker, + // min_context_usage_ratio: config.minContextUsageRatio, + // truncated_tool_result_count: effect.truncatedToolResultCount, + // truncated_tool_result_tokens_before: effect.truncatedToolResultTokensBefore, + // truncated_tool_result_tokens_after: effect.truncatedToolResultTokensAfter, + // tokens_before: tokensBefore, + // tokens_after: tokensAfter, + // previous_cutoff: previousCutoff, + // cutoff: nextCutoff, + // message_count: history.length, + // cache_age_ms: cacheAgeMs, + // thinking_effort: this.agent.config.thinkingEffort, + // }); + // } } compact(messages: readonly ContextMessage[]): readonly ContextMessage[] { - if (!this.agent.experimentalFlags.enabled('micro_compaction')) return messages; + // Micro compaction is disabled: the `micro_compaction` experimental flag has + // been removed from the registry, so messages are always returned unchanged. + return messages; - const config = this.config; - const result: ContextMessage[] = []; - let i = 0; - for (const msg of messages) { - if ( - i < this.cutoff && - msg.role === 'tool' && - msg.toolCallId !== undefined && - estimateTokensForContentParts(msg.content) >= config.minContentTokens - ) { - result.push({ - ...msg, - content: [{ type: 'text', text: config.truncatedMarker } satisfies ContentPart], - }); - } else { - result.push(msg); - } - i++; - } - return result; + // Original implementation (disabled): + // if (!this.agent.experimentalFlags.enabled('micro_compaction')) return messages; + // + // const config = this.config; + // const result: ContextMessage[] = []; + // let i = 0; + // for (const msg of messages) { + // if ( + // i < this.cutoff && + // msg.role === 'tool' && + // msg.toolCallId !== undefined && + // estimateTokensForContentParts(msg.content) >= config.minContentTokens + // ) { + // result.push({ + // ...msg, + // content: [{ type: 'text', text: config.truncatedMarker } satisfies ContentPart], + // }); + // } else { + // result.push(msg); + // } + // i++; + // } + // return result; } private measureEffect( diff --git a/packages/agent-core/src/flags/registry.ts b/packages/agent-core/src/flags/registry.ts index fcce75ece..a8e815e91 100644 --- a/packages/agent-core/src/flags/registry.ts +++ b/packages/agent-core/src/flags/registry.ts @@ -12,14 +12,17 @@ import type { FlagDefinitionInput } from './types'; * not equal the master switch 'KIMI_CODE_EXPERIMENTAL_FLAG'; `id` must not be 'flag'. */ export const FLAG_DEFINITIONS = [ - { - id: 'micro_compaction', - title: 'Micro compaction', - description: 'Trim older large tool results from context while keeping recent conversation intact.', - env: 'KIMI_CODE_EXPERIMENTAL_MICRO_COMPACTION', - default: false, - surface: 'core', - }, + // Micro compaction has been disabled and removed: the capability cannot be + // enabled via env, config, or the master experimental switch. The entry is + // kept here commented out so it can be restored if the feature is revived. + // { + // id: 'micro_compaction', + // title: 'Micro compaction', + // description: 'Trim older large tool results from context while keeping recent conversation intact.', + // env: 'KIMI_CODE_EXPERIMENTAL_MICRO_COMPACTION', + // default: false, + // surface: 'core', + // }, ] as const satisfies readonly FlagDefinitionInput[]; /** Literal union of registered flag ids. */ diff --git a/packages/agent-core/src/flags/types.ts b/packages/agent-core/src/flags/types.ts index 061029369..d93a2523f 100644 --- a/packages/agent-core/src/flags/types.ts +++ b/packages/agent-core/src/flags/types.ts @@ -26,7 +26,10 @@ export type ExperimentalFlagConfig = Partial>; export type ExperimentalFlagSource = 'master-env' | 'env' | 'config' | 'default'; export interface ExperimentalFeatureState { - readonly id: FlagId; + /** Feature id. Typed as `string` because this is a runtime snapshot that + * crosses the SDK/RPC boundary and must remain usable even when no flags are + * registered (in which case the internal `FlagId` union collapses to `never`). */ + readonly id: string; readonly title: string; readonly description: string; readonly surface: FlagSurface; diff --git a/packages/agent-core/test/agent/basic.test.ts b/packages/agent-core/test/agent/basic.test.ts index 2ecaf615e..f034effd5 100644 --- a/packages/agent-core/test/agent/basic.test.ts +++ b/packages/agent-core/test/agent/basic.test.ts @@ -9,7 +9,9 @@ it('creates an independent agent with a scoped experimental flag resolver', () = experimentalFlags: new FlagResolver({}, FLAG_DEFINITIONS), }); - expect(ctx.agent.experimentalFlags.enabled('micro_compaction')).toBe(false); + // No experimental flags are currently registered, so the scoped resolver + // reports none enabled. + expect(ctx.agent.experimentalFlags.enabledIds()).toEqual([]); }); it('runs a text-only agent turn from prompt to completion', async () => { diff --git a/packages/agent-core/test/agent/compaction/compaction-scenarios.test.ts b/packages/agent-core/test/agent/compaction/compaction-scenarios.test.ts index 8494881e8..3392820b6 100644 --- a/packages/agent-core/test/agent/compaction/compaction-scenarios.test.ts +++ b/packages/agent-core/test/agent/compaction/compaction-scenarios.test.ts @@ -354,7 +354,9 @@ describe('compaction — probe tests (high-risk scenarios)', () => { // to a recent suffix but still projected through MicroCompaction.compact() // with the cutoff computed for the FULL history. The absolute cutoff applied // to the shifted suffix can clear recent tool results the summary needs. - it.fails('does not clear recent tool results when projecting a shrunk suffix under an active micro-compaction cutoff', () => { + // SKIPPED: micro-compaction has been disabled and its flag removed, so this + // defect no longer exists. + it.skip('does not clear recent tool results when projecting a shrunk suffix under an active micro-compaction cutoff', () => { // This defect only exists when micro-compaction is active, so enable the // flag explicitly rather than inheriting the ambient KIMI_CODE_EXPERIMENTAL // master switch — otherwise the probe's pass/fail flips with the runner's diff --git a/packages/agent-core/test/agent/compaction/full.test.ts b/packages/agent-core/test/agent/compaction/full.test.ts index 5e3805447..a31a24767 100644 --- a/packages/agent-core/test/agent/compaction/full.test.ts +++ b/packages/agent-core/test/agent/compaction/full.test.ts @@ -324,7 +324,9 @@ describe('FullCompaction', () => { ).toBe(false); }); - it('micro-compacts old tool results before sending the summary request', async () => { + // Micro compaction is disabled; this scenario is skipped because the feature + // can no longer be enabled. + it.skip('micro-compacts old tool results before sending the summary request', async () => { vi.useFakeTimers(); enableMicroCompactionFlag(); const ctx = testAgent({ @@ -2227,11 +2229,9 @@ function enableMicroCompactionFlag(): void { } function getMicroCompactionFlagEnv(): string { - const flag = FLAG_DEFINITIONS.find((definition) => definition.id === 'micro_compaction'); - if (flag === undefined) { - throw new Error('Missing micro_compaction flag definition.'); - } - return flag.env; + // Micro compaction is disabled and its flag has been removed from the registry; + // the env var name is kept so the (skipped) test still type-checks. + return 'KIMI_CODE_EXPERIMENTAL_MICRO_COMPACTION'; } function deferred() { diff --git a/packages/agent-core/test/agent/compaction/micro.test.ts b/packages/agent-core/test/agent/compaction/micro.test.ts index 6043c7519..2193bb79e 100644 --- a/packages/agent-core/test/agent/compaction/micro.test.ts +++ b/packages/agent-core/test/agent/compaction/micro.test.ts @@ -29,15 +29,18 @@ const MINUTE = 60 * 1000; const DEFAULT_MARKER = '[Old tool result content cleared]'; const MICRO_COMPACTION_FLAG_ENV = getMicroCompactionFlagEnv(); -describe('MicroCompaction', () => { +// Micro compaction is disabled and its flag has been removed; the suite is +// skipped because the feature can no longer be enabled. +describe.skip('MicroCompaction', () => { beforeEach(() => { vi.stubEnv(MASTER_ENV, '0'); vi.stubEnv(MICRO_COMPACTION_FLAG_ENV, '1'); }); - it('defaults the micro_compaction flag off', () => { - expect(new FlagResolver({}, FLAG_DEFINITIONS).enabled('micro_compaction')).toBe(false); - }); + // The micro_compaction flag no longer exists, so there is no default to assert. + // it('defaults the micro_compaction flag off', () => { + // expect(new FlagResolver({}, FLAG_DEFINITIONS).enabled('micro_compaction')).toBe(false); + // }); it('truncates old tool results after cache miss', () => { vi.useFakeTimers(); @@ -966,11 +969,9 @@ function hasMarker(messages: readonly Message[]): boolean { } function getMicroCompactionFlagEnv(): string { - const flag = FLAG_DEFINITIONS.find((definition) => definition.id === 'micro_compaction'); - if (flag === undefined) { - throw new Error('Missing micro_compaction flag definition.'); - } - return flag.env; + // Micro compaction is disabled and its flag has been removed from the registry; + // the env var name is kept so the (skipped) suite still type-checks. + return 'KIMI_CODE_EXPERIMENTAL_MICRO_COMPACTION'; } function singleTelemetryEvent( diff --git a/packages/agent-core/test/harness/runtime.test.ts b/packages/agent-core/test/harness/runtime.test.ts index 7d5821181..569c7d5fa 100644 --- a/packages/agent-core/test/harness/runtime.test.ts +++ b/packages/agent-core/test/harness/runtime.test.ts @@ -26,16 +26,15 @@ import type { OAuthTokenProviderResolver } from '../../src/session/provider-mana import { testKaos } from '../fixtures/test-kaos'; function requiredFlagEnv(id: string): string { - const def = FLAG_DEFINITIONS.find((item) => item.id === id); - if (def === undefined) throw new Error(`Missing flag definition: ${id}`); - return def.env; + // Micro compaction was the only registered flag and has been removed, so the + // env var name is derived directly; the (skipped) tests still type-check. + return `KIMI_CODE_EXPERIMENTAL_${id.toUpperCase()}`; } function clearExperimentalEnv(): void { vi.stubEnv(MASTER_ENV, '0'); - for (const def of FLAG_DEFINITIONS) { - vi.stubEnv(def.env, ''); - } + // No experimental flags are currently registered, so there are no per-flag + // env vars to clear. } function experimentalFeatureEnabled(core: KimiCore, id: string): boolean | undefined { @@ -94,16 +93,19 @@ describe('KimiCore runtime config', () => { vi.unstubAllGlobals(); }); - it('logs all enabled experimental flags once on core startup', async () => { + // Micro compaction was the only experimental flag and has been removed; this + // test is skipped because there is no flag to enable. + it.skip('logs all enabled experimental flags once on core startup', async () => { tmp = await mkdtemp(join(tmpdir(), 'kimi-core-runtime-')); const homeDir = join(tmp, 'home'); await mkdir(homeDir, { recursive: true }); await getRootLogger().configure(resolveLoggingConfig({ homeDir })); vi.stubEnv(MASTER_ENV, '0'); - for (const def of FLAG_DEFINITIONS) { - vi.stubEnv(def.env, '0'); - } + // No experimental flags are currently registered, so there is nothing to clear. + // for (const def of FLAG_DEFINITIONS) { + // vi.stubEnv(def.env, '0'); + // } vi.stubEnv(requiredFlagEnv('micro_compaction'), '1'); void new KimiCore(async () => ({}) as never, { homeDir }); @@ -115,7 +117,9 @@ describe('KimiCore runtime config', () => { expect(text.match(/experimental flags enabled/g)).toHaveLength(1); }); - it('resolves experimental flags from each core config independently', async () => { + // Micro compaction was the only experimental flag and has been removed; this + // test is skipped because there is no flag to resolve. + it.skip('resolves experimental flags from each core config independently', async () => { tmp = await mkdtemp(join(tmpdir(), 'kimi-core-runtime-')); const firstHome = join(tmp, 'first-home'); const secondHome = join(tmp, 'second-home'); @@ -144,7 +148,9 @@ micro_compaction = false expect(experimentalFeatureEnabled(second, 'micro_compaction')).toBe(false); }); - it('updates the scoped experimental resolver after setKimiConfig', async () => { + // Micro compaction was the only experimental flag and has been removed; this + // test is skipped because there is no flag to update. + it.skip('updates the scoped experimental resolver after setKimiConfig', async () => { tmp = await mkdtemp(join(tmpdir(), 'kimi-core-runtime-')); const homeDir = join(tmp, 'home'); await mkdir(homeDir, { recursive: true }); @@ -169,7 +175,9 @@ micro_compaction = false expect(experimentalFeatureEnabled(core, 'micro_compaction')).toBe(true); }); - it('updates the shared experimental resolver while goal tools stay available', async () => { + // Micro compaction was the only experimental flag and has been removed; this + // test is skipped because there is no flag to update. + it.skip('updates the shared experimental resolver while goal tools stay available', async () => { tmp = await mkdtemp(join(tmpdir(), 'kimi-core-runtime-')); const homeDir = join(tmp, 'home'); const workDir = join(tmp, 'work'); @@ -201,8 +209,8 @@ micro_compaction = false const session = core.sessions.get(created.id); const mainAgent = session?.getReadyAgent('main'); - expect(session?.experimentalFlags.enabled('micro_compaction')).toBe(false); - expect(mainAgent?.experimentalFlags.enabled('micro_compaction')).toBe(false); + // expect(session?.experimentalFlags.enabled('micro_compaction')).toBe(false); + // expect(mainAgent?.experimentalFlags.enabled('micro_compaction')).toBe(false); expect(mainAgent?.tools.data().some((tool) => tool.name === 'CreateGoal')).toBe(true); await core.setKimiConfig({ @@ -211,8 +219,8 @@ micro_compaction = false }, }); - expect(session?.experimentalFlags.enabled('micro_compaction')).toBe(true); - expect(mainAgent?.experimentalFlags.enabled('micro_compaction')).toBe(true); + // expect(session?.experimentalFlags.enabled('micro_compaction')).toBe(true); + // expect(mainAgent?.experimentalFlags.enabled('micro_compaction')).toBe(true); expect(mainAgent?.tools.data().some((tool) => tool.name === 'CreateGoal')).toBe(true); await rpc.reloadSession({ sessionId: created.id }); diff --git a/packages/migration-legacy/src/steps/config.ts b/packages/migration-legacy/src/steps/config.ts index a685025d7..2cc83ac66 100644 --- a/packages/migration-legacy/src/steps/config.ts +++ b/packages/migration-legacy/src/steps/config.ts @@ -30,7 +30,7 @@ const BACKGROUND_FIELDS_TO_KEEP = new Set([ 'keep_alive_on_exit', ]); const REGISTERED_EXPERIMENTAL_FLAGS: ReadonlySet = new Set( - FLAG_DEFINITIONS.map((definition) => definition.id), + (FLAG_DEFINITIONS as ReadonlyArray<{ readonly id: string }>).map((definition) => definition.id), ); // kimi-code's tui.toml `theme` enum (mirrors apps/kimi-code TuiThemeSchema). diff --git a/packages/migration-legacy/test/steps/config.test.ts b/packages/migration-legacy/test/steps/config.test.ts index 58a1088c8..8cd62d025 100644 --- a/packages/migration-legacy/test/steps/config.test.ts +++ b/packages/migration-legacy/test/steps/config.test.ts @@ -458,8 +458,11 @@ base_url = "https://target.example/v1" expect(r.migrated).toBe(true); const cfg = await readFile(join(tgt, 'config.toml'), 'utf-8'); - expect(cfg).toContain('[experimental]'); - expect(cfg).toContain('micro_compaction = false'); + // No experimental flags are currently registered, so the whole + // `[experimental]` section (including the former `micro_compaction`) is + // dropped along with unknown flags during migration. + expect(cfg).not.toContain('[experimental]'); + expect(cfg).not.toContain('micro_compaction'); expect(cfg).not.toContain('unknown_flag'); expect(cfg).toContain('[loop_control]'); expect(cfg).toContain('max_retries_per_step = 2'); diff --git a/packages/node-sdk/test/config.test.ts b/packages/node-sdk/test/config.test.ts index 91bff92d7..5c51d7e10 100644 --- a/packages/node-sdk/test/config.test.ts +++ b/packages/node-sdk/test/config.test.ts @@ -329,32 +329,13 @@ describe('KimiHarness config API', () => { it('returns experimental feature metadata through the harness', async () => { vi.stubEnv('KIMI_CODE_EXPERIMENTAL_FLAG', '0'); - vi.stubEnv('KIMI_CODE_EXPERIMENTAL_MICRO_COMPACTION', ''); const homeDir = await makeTempDir(); - await writeFile( - join(homeDir, 'config.toml'), - ` -[experimental] -micro_compaction = false -`, - 'utf-8', - ); const harness = createKimiHarness({ homeDir, identity: TEST_IDENTITY }); + // No experimental features are currently registered, so the harness exposes + // an empty list. const features = await harness.getExperimentalFeatures(); - const microCompaction = features.find((feature) => feature.id === 'micro_compaction'); - - expect(microCompaction).toMatchObject({ - id: 'micro_compaction', - title: 'Micro compaction', - enabled: false, - source: 'config', - configValue: false, - env: 'KIMI_CODE_EXPERIMENTAL_MICRO_COMPACTION', - }); - expect(features).toEqual([ - expect.objectContaining({ id: 'micro_compaction', enabled: false }), - ]); + expect(features).toEqual([]); }); it('can create the default config scaffold without selecting a model', async () => {