diff --git a/.agents/skills/agent-core-dev/config.md b/.agents/skills/agent-core-dev/config.md index d7d6b12fc..c84111259 100644 --- a/.agents/skills/agent-core-dev/config.md +++ b/.agents/skills/agent-core-dev/config.md @@ -101,7 +101,7 @@ pass `ConfigTarget.Memory` for a per-run override that is never written to disk. - `src/kosong/model/thinking.ts` (owner domain, not `config`) — the `resolveThinkingEffort` helper and the authoritative `ThinkingConfig` type (the `thinking` section itself registers from `src/app/kosongConfig/configSection.ts`). - `src/app/config/configPure.ts` — `isPlainObject`, `deepMerge`, `omitUndefined`, `describeUnknownError`. -A domain that owns a section keeps the schema in its own `configSection.ts` (e.g. `src/app/flag/flag.ts` for `experimental`, `src/agent/loop/configSection.ts` for `loopControl`). Exception: kosong-owned sections (`providers`, `models`, `thinking`) — kosong is a pure, persistence-free abstraction layer that defines only the types (`src/kosong/{provider,model}`); the section constants, the zod schemas (re-derived from those types and compile-time pinned via `AssertExact, Type>>`, see `_base/utils/typeEquality.ts`), the registrations, env bindings, and TOML transforms all live in the persistence wrapper `src/app/kosongConfig/configSection.ts`. (`modelCatalog` has no kosong-side type at all — its section is fully self-contained in `app/kosongConfig`, types derived from the schema.) A cross-section env overlay (e.g. the `KIMI_MODEL_*` synthesis in `src/app/kosongConfig/envOverlay.ts`) lives in the wrapper too and is registered via module-level `registerConfigOverlay`. The session subagent domain owns two sections in `src/session/subagent/configSection.ts`: `[subagent]` (`timeout_ms` on disk) and `[secondary_model]` (`default_model` plus the `[secondary_model.models]` pool, with a lone legacy v1 `model` key honored as a fallback default below `default_model`), with the legacy `[subagent]` pool keys declared as deprecations; neither carries a cross-section overlay. Cross-field pool validation (default present / in-pool / every key resolvable) runs at session creation in `subagentModelsValidationService.ts`, not in the schema. The two-way sync between config sections and kosong's in-memory registries is owned by `IKosongConfigService` (`src/app/kosongConfig/kosongConfigService.ts`). +A domain that owns a section keeps the schema in its own `configSection.ts` (e.g. `src/app/flag/flag.ts` for `experimental`, `src/agent/loop/configSection.ts` for `loopControl`). Exception: kosong-owned sections (`providers`, `models`, `thinking`) — kosong is a pure, persistence-free abstraction layer that defines only the types (`src/kosong/{provider,model}`); the section constants, the zod schemas (re-derived from those types and compile-time pinned via `AssertExact, Type>>`, see `_base/utils/typeEquality.ts`), the registrations, env bindings, and TOML transforms all live in the persistence wrapper `src/app/kosongConfig/configSection.ts`. (`modelCatalog` has no kosong-side type at all — its section is fully self-contained in `app/kosongConfig`, types derived from the schema.) A cross-section env overlay (e.g. the `KIMI_MODEL_*` synthesis in `src/app/kosongConfig/envOverlay.ts`) lives in the wrapper too and is registered via module-level `registerConfigOverlay`. The session subagent domain owns two sections in `src/session/subagent/configSection.ts`: `[subagent]` (`timeout_ms` on disk) and `[secondary_model]` (`default_model` plus the `[secondary_model.models]` pool, with a lone legacy v1 `model` key honored as a fallback default below `default_model`); neither carries a cross-section overlay. Cross-field pool validation (default present / in-pool / every key resolvable) runs at session creation in `subagentModelsValidationService.ts`, not in the schema. The two-way sync between config sections and kosong's in-memory registries is owned by `IKosongConfigService` (`src/app/kosongConfig/kosongConfigService.ts`). ## Scope diff --git a/docs/en/configuration/config-files.md b/docs/en/configuration/config-files.md index cf62875b1..af7834b6a 100644 --- a/docs/en/configuration/config-files.md +++ b/docs/en/configuration/config-files.md @@ -264,8 +264,6 @@ Note that `default_effort` stays a model-level default: once a global `[thinking Configuration errors fail loudly instead of falling back silently: session creation, resume, and fork all fail at startup when `default_model` is missing, is not a pool key, or a pool key does not resolve to a configured `[models]` entry — and likewise when `force` is set without `default_model` or combined with a `[secondary_model.models]` table. The alias `primary` is reserved — it always binds the caller's own model — and is rejected as a pool key. A spawn whose `model` is neither a pool alias nor `"primary"` fails with an error listing the available choices. -The pool keys used to live under `[subagent]`; a leftover `[subagent] default_model` or `[subagent.models]` table no longer applies and is reported as a deprecation warning — move them into `[secondary_model]` as shown above. - When only the recipe `model` key is set — no `default_model`, no `[secondary_model.models]` table — the v2 engine reads it compatibly as the pool default: an implicit single-entry pool ranked below `default_model`, so a recipe setup keeps working unchanged. The compatibility only takes the model alias, though: the recipe patch fields (`default_effort`, `max_output_size`, …) do not carry over — write those settings onto the `[models]` entry the alias points to, for example via [`[models."".overrides]`](#model-overrides). Once a `[secondary_model.models]` table is configured, `default_model` stays required and `model` does not substitute for it. To migrate explicitly, point the pool default at the same alias: @@ -383,8 +381,6 @@ In print mode (`kimi -p ""`), Kimi Code stays alive after the main agent `timeout_ms` can be overridden by the `KIMI_SUBAGENT_TIMEOUT_MS` environment variable, which takes higher priority than `config.toml`. -The model pool that used to be configured here (`default_model`, `[subagent.models]`) moved to the [subagent model pool](#subagent-model-pool) under `[secondary_model]`; the old keys no longer apply and are reported as deprecation warnings. - ## `mcp` | Field | Type | Default | Description | diff --git a/docs/zh/configuration/config-files.md b/docs/zh/configuration/config-files.md index cad685969..c51a56d7e 100644 --- a/docs/zh/configuration/config-files.md +++ b/docs/zh/configuration/config-files.md @@ -263,8 +263,6 @@ kimi-for-coding-highspeed-deep = "同一模型的高 Thinking 档位。适合较 配置错误一律直接报错,不做静默回退:`default_model` 缺失、不是池中 key,或池中 key 无法解析到已配置的 `[models]` 条目时,会话的创建、恢复(resume)与 fork 都会在启动时直接失败;`force` 未搭配 `default_model` 或与 `[secondary_model.models]` 表同用时亦然。别名 `primary` 是保留字——它始终绑定调用方自己的模型——不能作为池中 key。工具调用传入的 `model` 既不是池中别名也不是 `"primary"` 时,本次派生报错并列出可选值。 -模型池键之前位于 `[subagent]` 下;遗留的 `[subagent] default_model` 或 `[subagent.models]` 表不再生效,并会以弃用警告的形式报告——按上文示例移入 `[secondary_model]` 即可。 - 只写了配方键 `model`(没有 `default_model`,也没有 `[secondary_model.models]` 表)时,v2 引擎会兼容读取它,把该别名当作池的默认模型——等价于只含它一个条目的隐式模型池,优先级低于 `default_model`,所以从配方迁移过来不改配置也能工作。注意兼容只取模型别名:补丁字段(`default_effort`、`max_output_size` 等)不会随之生效——请把这些设置写到别名指向的 `[models]` 条目上,例如通过 [`[models."".overrides]`](#模型覆盖项)。一旦配置了 `[secondary_model.models]` 表,`default_model` 依旧必填,`model` 不能顶替。 要显式迁移,把模型别名改为池的默认模型即可: @@ -382,8 +380,6 @@ max_output_size = 8192 `timeout_ms` 可被环境变量 `KIMI_SUBAGENT_TIMEOUT_MS` 覆盖,优先级高于配置文件。 -之前在此配置的模型池(`default_model`、`[subagent.models]`)已移至 `[secondary_model]` 下的[子 Agent 模型池](#子-agent-模型池);旧键不再生效,并会以弃用警告的形式报告。 - ## `mcp` | 字段 | 类型 | 默认值 | 说明 | diff --git a/packages/agent-core-v2/docs/config-manifest.toml b/packages/agent-core-v2/docs/config-manifest.toml index 463356d40..99b6a14c4 100644 --- a/packages/agent-core-v2/docs/config-manifest.toml +++ b/packages/agent-core-v2/docs/config-manifest.toml @@ -374,9 +374,6 @@ merge_all_available_skills = true # owner: src/session/subagent/configSection.ts # scope: core # hooks: stripEnv -# deprecations (old key is ignored + warns; rename manually): -# default_model -> secondary_model.default_model -# models -> secondary_model.models # env: # timeout_ms <- KIMI_SUBAGENT_TIMEOUT_MS (custom parse) # ########################################################################## diff --git a/packages/agent-core-v2/src/session/subagent/configSection.ts b/packages/agent-core-v2/src/session/subagent/configSection.ts index 5140f6793..c84b012b3 100644 --- a/packages/agent-core-v2/src/session/subagent/configSection.ts +++ b/packages/agent-core-v2/src/session/subagent/configSection.ts @@ -9,9 +9,7 @@ * var is set, `stripEnvBoundFields` restores the env-free raw value before * persistence, so the override never leaks into `config.toml`. Per-run * timeouts resolve through `resolveSubagentTimeoutMs`, and the timeout - * message renders with `formatSubagentTimeoutDescription`. The pool keys - * `default_model` / `models` are declared as deprecations on this section: - * they moved to `[secondary_model]` and their values here no longer apply. + * message renders with `formatSubagentTimeoutDescription`. * * - `[secondary_model]` — the subagent model pool: `default_model` names the * fallback model and the `[secondary_model.models]` table maps alias → @@ -165,10 +163,6 @@ registerConfigSection(SUBAGENT_SECTION, SubagentConfigSchema, { defaultValue: { timeoutMs: DEFAULT_SUBAGENT_TIMEOUT_MS }, env: subagentEnvBindings, stripEnv: stripSubagentEnv, - deprecations: [ - { key: 'default_model', replacement: 'secondary_model.default_model' }, - { key: 'models', replacement: 'secondary_model.models' }, - ], }); registerConfigSection(SECONDARY_MODEL_SECTION, SecondaryModelConfigSchema); diff --git a/packages/agent-core-v2/test/app/config/config.test.ts b/packages/agent-core-v2/test/app/config/config.test.ts index aa00d63d9..521da8377 100644 --- a/packages/agent-core-v2/test/app/config/config.test.ts +++ b/packages/agent-core-v2/test/app/config/config.test.ts @@ -1208,31 +1208,6 @@ describe('config deprecations', () => { disposables.dispose(); }); - it('warns and ignores the legacy [subagent] pool keys, which moved to [secondary_model]', async () => { - const { config, disposables } = await createConfig( - {}, - '[subagent]\ndefault_model = "provider/fast"\n\n[subagent.models]\n"provider/fast" = "fast and cheap"\n', - ); - - // The old values no longer apply — the pool only resolves from - // [secondary_model] now. - expect(resolveSubagentModelPool(config)).toBeUndefined(); - expect(config.diagnostics()).toContainEqual({ - domain: SUBAGENT_SECTION, - severity: 'warning', - message: - "[subagent] 'default_model' is deprecated and no longer used; rename it to 'secondary_model.default_model'. Run /update-config to fix it.", - }); - expect(config.diagnostics()).toContainEqual({ - domain: SUBAGENT_SECTION, - severity: 'warning', - message: - "[subagent] 'models' is deprecated and no longer used; rename it to 'secondary_model.models'. Run /update-config to fix it.", - }); - - disposables.dispose(); - }); - it('lets the replacement key win when both are present, still warning', async () => { const { config, disposables } = await createConfig( {},