mirror of
https://github.com/MoonshotAI/kimi-code.git
synced 2026-08-31 10:24:37 +00:00
fix(cli): validate config.toml against the v2 schema in kimi doctor (#3372)
Some checks are pending
CI / test (3) (push) Waiting to run
CI / test (4) (push) Waiting to run
CI / test (5) (push) Waiting to run
CI / test-pi-tui (push) Waiting to run
CI / test-vscode-legacy (push) Waiting to run
CI / test-windows (push) Waiting to run
CI / lint (push) Waiting to run
CI / typecheck (push) Waiting to run
Release / Release (push) Waiting to run
Release / Deploy docs (push) Blocked by required conditions
Release / Native release artifact (push) Blocked by required conditions
Release / Publish native release assets (push) Blocked by required conditions
Publish VS Code extension / Publish VSIX to marketplaces (push) Waiting to run
CI / test (1) (push) Waiting to run
CI / test (2) (push) Waiting to run
CI / build (push) Waiting to run
Nix Build / Check flake.nix workspace sync (push) Waiting to run
Nix Build / nix build .#kimi-code (push) Blocked by required conditions
Some checks are pending
CI / test (3) (push) Waiting to run
CI / test (4) (push) Waiting to run
CI / test (5) (push) Waiting to run
CI / test-pi-tui (push) Waiting to run
CI / test-vscode-legacy (push) Waiting to run
CI / test-windows (push) Waiting to run
CI / lint (push) Waiting to run
CI / typecheck (push) Waiting to run
Release / Release (push) Waiting to run
Release / Deploy docs (push) Blocked by required conditions
Release / Native release artifact (push) Blocked by required conditions
Release / Publish native release assets (push) Blocked by required conditions
Publish VS Code extension / Publish VSIX to marketplaces (push) Waiting to run
CI / test (1) (push) Waiting to run
CI / test (2) (push) Waiting to run
CI / build (push) Waiting to run
Nix Build / Check flake.nix workspace sync (push) Waiting to run
Nix Build / nix build .#kimi-code (push) Blocked by required conditions
This commit is contained in:
parent
961927739e
commit
56b5480ed0
3 changed files with 50 additions and 39 deletions
|
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
* Agent engine routing gates for the CLI surfaces.
|
||||
*
|
||||
* `kimi -p`, the interactive TUI, and `kimi doctor` use the native
|
||||
* `kimi -p` and the interactive TUI use the native
|
||||
* agent-core-v2 path by default. A truthy `KIMI_CODE_LEGACY_FLAG` selects the
|
||||
* legacy agent-core-backed path instead. `KIMI_CODE_EXPERIMENTAL_FLAG` remains
|
||||
* the master switch for experimental features within either engine; it does
|
||||
|
|
|
|||
|
|
@ -2,15 +2,10 @@ import { existsSync } from 'node:fs';
|
|||
import { readFile } from 'node:fs/promises';
|
||||
import { isAbsolute, resolve } from 'node:path';
|
||||
|
||||
import {
|
||||
createKimiConfigRpc,
|
||||
type KimiConfigRpc,
|
||||
type KimiConfigValidationIssue,
|
||||
} from '@moonshot-ai/kimi-code-sdk';
|
||||
import { resolveConfigPath, type KimiConfigValidationIssue } from '@moonshot-ai/kimi-code-sdk';
|
||||
import type { Command } from 'commander';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { isKimiV2Enabled } from '#/cli/experimental-v2';
|
||||
import { getTuiConfigPath, parseTuiConfig } from '#/tui/config';
|
||||
|
||||
interface WritableLike {
|
||||
|
|
@ -26,7 +21,6 @@ export interface DoctorDeps {
|
|||
readonly stdout: WritableLike;
|
||||
readonly stderr: WritableLike;
|
||||
readonly exit: (code: number) => never;
|
||||
readonly configRpc?: KimiConfigRpc;
|
||||
readonly fileExists?: (path: string) => boolean;
|
||||
readonly readTextFile?: (path: string) => Promise<string>;
|
||||
readonly validateConfigToml?: (text: string, path: string) => MaybePromise<string | void>;
|
||||
|
|
@ -115,15 +109,9 @@ async function runDoctorCommand(
|
|||
}
|
||||
|
||||
function resolveDeps(deps: Partial<DoctorDeps> | DoctorDeps | undefined): ResolvedDoctorDeps {
|
||||
let configRpc = deps?.configRpc;
|
||||
const getConfigRpc = (): KimiConfigRpc => {
|
||||
configRpc ??= createKimiConfigRpc();
|
||||
return configRpc;
|
||||
};
|
||||
|
||||
return {
|
||||
cwd: deps?.cwd ?? (() => process.cwd()),
|
||||
defaultConfigPath: deps?.defaultConfigPath ?? (() => getConfigRpc().resolveConfigPath()),
|
||||
defaultConfigPath: deps?.defaultConfigPath ?? (() => resolveConfigPath({})),
|
||||
defaultTuiConfigPath: deps?.defaultTuiConfigPath ?? getTuiConfigPath,
|
||||
stdout: deps?.stdout ?? process.stdout,
|
||||
stderr: deps?.stderr ?? process.stderr,
|
||||
|
|
@ -133,15 +121,8 @@ function resolveDeps(deps: Partial<DoctorDeps> | DoctorDeps | undefined): Resolv
|
|||
validateConfigToml:
|
||||
deps?.validateConfigToml ??
|
||||
(async (text, filePath) => {
|
||||
if (isKimiV2Enabled()) {
|
||||
// Default v2 route (same engine gate as `kimi -p`): validate with
|
||||
// the agent-core-v2 section registry instead of the legacy schema.
|
||||
// Loaded lazily so the v2 module graph stays off the legacy path.
|
||||
const { validateConfigTomlV2 } = await import('../v2/validate-config');
|
||||
return validateConfigTomlV2(text, filePath);
|
||||
}
|
||||
await getConfigRpc().validateConfigToml({ text, filePath });
|
||||
return undefined;
|
||||
const { validateConfigTomlV2 } = await import('../v2/validate-config');
|
||||
return validateConfigTomlV2(text, filePath);
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ import {
|
|||
let dir: string;
|
||||
|
||||
beforeEach(async () => {
|
||||
vi.stubEnv('KIMI_CODE_LEGACY_FLAG', '');
|
||||
dir = join(tmpdir(), `kimi-doctor-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
||||
await mkdir(dir, { recursive: true });
|
||||
});
|
||||
|
|
@ -103,25 +102,56 @@ describe('kimi doctor', () => {
|
|||
expect(out).toContain('built-in defaults will apply');
|
||||
});
|
||||
|
||||
it('uses the legacy validator when legacy wins over the experimental flag', async () => {
|
||||
it('keeps v2 validation when the legacy flag is set', async () => {
|
||||
const configPath = join(dir, 'config.toml');
|
||||
const text = '[providers.kimi]\ntype = "kimi"\n';
|
||||
await writeFile(configPath, text, 'utf-8');
|
||||
vi.stubEnv('KIMI_CODE_LEGACY_FLAG', '1');
|
||||
vi.stubEnv('KIMI_CODE_EXPERIMENTAL_FLAG', '1');
|
||||
const validateConfigToml = vi.fn(async () => undefined);
|
||||
const { deps } = makeDeps();
|
||||
await writeFile(
|
||||
configPath,
|
||||
`
|
||||
default_model = "kimi"
|
||||
|
||||
const code = await handleDoctor(
|
||||
{
|
||||
...deps,
|
||||
configRpc: { validateConfigToml } as unknown as NonNullable<DoctorDeps['configRpc']>,
|
||||
},
|
||||
{ target: 'config' },
|
||||
[providers.kimi]
|
||||
type = "kimi"
|
||||
base_url = "https://api.example.com/v1"
|
||||
api_key = "YOUR_API_KEY"
|
||||
|
||||
[models.kimi]
|
||||
provider = "kimi"
|
||||
model = "kimi"
|
||||
protocol = "openai"
|
||||
max_context_size = 262144
|
||||
`,
|
||||
'utf-8',
|
||||
);
|
||||
vi.stubEnv('KIMI_CODE_LEGACY_FLAG', '1');
|
||||
const { deps, stdout, stderr } = makeDeps();
|
||||
|
||||
const code = await handleDoctor(deps, { target: 'config' });
|
||||
|
||||
expect(code).toBe(0);
|
||||
expect(validateConfigToml).toHaveBeenCalledWith({ text, filePath: configPath });
|
||||
expect(stderr.join('')).toBe('');
|
||||
expect(stdout.join('')).toContain(`OK config.toml ${configPath}`);
|
||||
});
|
||||
|
||||
it('reports schema-invalid sections with the v2 engine when the legacy flag is set', async () => {
|
||||
await writeFile(
|
||||
join(dir, 'config.toml'),
|
||||
`
|
||||
[models.kimi]
|
||||
provider = "kimi"
|
||||
model = "kimi"
|
||||
max_context_size = "large"
|
||||
`,
|
||||
'utf-8',
|
||||
);
|
||||
vi.stubEnv('KIMI_CODE_LEGACY_FLAG', '1');
|
||||
const { deps, stderr } = makeDeps();
|
||||
|
||||
const code = await handleDoctor(deps, { target: 'config' });
|
||||
|
||||
expect(code).toBe(1);
|
||||
const err = stderr.join('');
|
||||
expect(err).toContain('Validation issues:');
|
||||
expect(err).toContain('models.kimi.max_context_size:');
|
||||
});
|
||||
|
||||
it('checks only config.toml when the config target is selected', async () => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue