From fd26d92335a77d8b2810cfda0922b82ec16d49fd Mon Sep 17 00:00:00 2001 From: RTCartist Date: Fri, 5 Jun 2026 09:43:11 +0800 Subject: [PATCH 1/3] fix(doctor): use consistent path separators in formatted output on Windows `config.toml`'s path is resolved via `pathe` (forward slashes everywhere) while `tui.toml`'s path is resolved via `node:path` (native separators). On Windows this surfaced a mixed-separator output in `kimi doctor`: SKIP config.toml C:/Users/me/.kimi-code/config.toml SKIP tui.toml C:\Users\me\.kimi-code\tui.toml Normalize each path with `node:path` `normalize()` in `formatResults` so both lines render with the platform-native separator, matching what the user sees elsewhere in the TUI (working-directory badge, etc.). --- apps/kimi-code/src/cli/sub/doctor.ts | 9 ++++++-- apps/kimi-code/test/cli/doctor.test.ts | 29 ++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/apps/kimi-code/src/cli/sub/doctor.ts b/apps/kimi-code/src/cli/sub/doctor.ts index 0ccc38d2..8431c5a1 100644 --- a/apps/kimi-code/src/cli/sub/doctor.ts +++ b/apps/kimi-code/src/cli/sub/doctor.ts @@ -1,6 +1,6 @@ import { existsSync } from 'node:fs'; import { readFile } from 'node:fs/promises'; -import { isAbsolute, resolve } from 'node:path'; +import { isAbsolute, normalize, resolve } from 'node:path'; import { createKimiConfigRpc, @@ -259,7 +259,12 @@ function formatFailure(results: readonly CheckResult[], issueCount: number): str function formatResults(results: readonly CheckResult[]): string[] { const lines: string[] = []; for (const result of results) { - lines.push(`${result.status} ${result.label.padEnd(12)} ${result.path}`); + // Normalize the path to the platform's native separators so config.toml + // (resolved via `pathe`, always `/`) and tui.toml (resolved via + // `node:path`, native separator) render consistently. Without this, + // Windows users see both `C:/Users/me/.kimi-code/config.toml` and + // `C:\Users\me\.kimi-code\tui.toml` in the same output. + lines.push(`${result.status} ${result.label.padEnd(12)} ${normalize(result.path)}`); if (result.message !== undefined) { for (const line of result.message.split('\n')) { lines.push(` ${line}`); diff --git a/apps/kimi-code/test/cli/doctor.test.ts b/apps/kimi-code/test/cli/doctor.test.ts index b6404c97..1acc96aa 100644 --- a/apps/kimi-code/test/cli/doctor.test.ts +++ b/apps/kimi-code/test/cli/doctor.test.ts @@ -267,4 +267,33 @@ max_context_size = "large" expect(err).toContain('Validation issues:'); expect(err).toContain('models.kimi.max_context_size:'); }); + + it('normalizes path separators in formatted output', async () => { + // Regression: config.toml is resolved via `pathe` (always `/`) while + // tui.toml is resolved via `node:path` (native separators on Windows). + // The formatted output must use one consistent separator — otherwise + // Windows users see a mix of `C:/Users/me/...` and `C:\Users\me\...` + // in the same `kimi doctor` block. + const { deps, stdout } = makeDeps(); + const code = await handleDoctor( + { + ...deps, + // Force a `/`-only path here to simulate what `pathe` would yield. + defaultConfigPath: () => 'C:/fixture/.kimi-code/config.toml', + defaultTuiConfigPath: () => 'C:\\fixture\\.kimi-code\\tui.toml', + fileExists: () => false, + }, + {}, + ); + + expect(code).toBe(0); + const out = stdout.join(''); + // On Windows, both lines should use backslashes; on POSIX, both forward + // slashes. Path.sep is what `normalize` aligns to. + const sep = process.platform === 'win32' ? '\\' : '/'; + const expectedConfig = `C:${sep}fixture${sep}.kimi-code${sep}config.toml`; + const expectedTui = `C:${sep}fixture${sep}.kimi-code${sep}tui.toml`; + expect(out).toContain(expectedConfig); + expect(out).toContain(expectedTui); + }); }); From 0302e2282b377eabcddafe9a1b05881271520743 Mon Sep 17 00:00:00 2001 From: RTCartist Date: Fri, 5 Jun 2026 09:43:26 +0800 Subject: [PATCH 2/3] chore: add changeset for Windows path separator fix in doctor --- .changeset/doctor-windows-path-separators.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/doctor-windows-path-separators.md diff --git a/.changeset/doctor-windows-path-separators.md b/.changeset/doctor-windows-path-separators.md new file mode 100644 index 00000000..df001362 --- /dev/null +++ b/.changeset/doctor-windows-path-separators.md @@ -0,0 +1,5 @@ +--- +"@moonshot-ai/kimi-code": patch +--- + +Fix mixed path separators in `kimi doctor` output on Windows (config.toml showed `C:/...` while tui.toml showed `C:\...`) From f6c7286e329f571b2f63ee64916d33fc54f1e2c6 Mon Sep 17 00:00:00 2001 From: RTCartist Date: Fri, 5 Jun 2026 09:50:04 +0800 Subject: [PATCH 3/3] fix: normalize "See log:" path separators on Windows The SDK resolves the global log path via `pathe` (forward slashes everywhere), so startup-error fallbacks were showing "See log: C:/Users/me/.kimi-code/logs/kimi-code.log" on Windows. Normalize via `node:path` `normalize()` before display so the path matches what users see in File Explorer / their shell. --- apps/kimi-code/src/main.ts | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/apps/kimi-code/src/main.ts b/apps/kimi-code/src/main.ts index 8a7d9fa7..608cbdda 100644 --- a/apps/kimi-code/src/main.ts +++ b/apps/kimi-code/src/main.ts @@ -5,6 +5,8 @@ * outer update preflight, then delegates to the requested UI runner. */ +import { normalize } from 'node:path'; + import { createKimiHarness, flushDiagnosticLogs, @@ -21,6 +23,16 @@ import { withTelemetryContext, } from '@moonshot-ai/kimi-telemetry'; +/** + * The SDK resolves the log path via `pathe` (forward slashes everywhere) + * which produces `C:/Users/.../kimi-code.log` on Windows. Normalize to the + * platform-native separator before showing the path to the user so it + * matches what they'd see in File Explorer / their shell. + */ +function formatLogPathForUser(homeDir: string): string { + return normalize(resolveGlobalLogPath(homeDir)); +} + import { createProgram } from './cli/commands'; import type { CLIOptions } from './cli/options'; import { OptionConflictError, validateOptions } from './cli/options'; @@ -142,7 +154,7 @@ export function main(): void { operation, }), ); - process.stderr.write(`See log: ${resolveGlobalLogPath(resolveKimiHome())}\n`); + process.stderr.write(`See log: ${formatLogPathForUser(resolveKimiHome())}\n`); process.exit(1); }); }, @@ -150,7 +162,7 @@ export function main(): void { void handleMigrateCommand(version).catch(async (error: unknown) => { await logStartupFailure('run migration', error); process.stderr.write(formatStartupError(error, { operation: 'run migration' })); - process.stderr.write(`See log: ${resolveGlobalLogPath(resolveKimiHome())}\n`); + process.stderr.write(`See log: ${formatLogPathForUser(resolveKimiHome())}\n`); process.exit(1); }); }, @@ -165,7 +177,7 @@ export function main(): void { void handleUpgradeCommand(version).catch(async (error: unknown) => { await logStartupFailure('upgrade', error); process.stderr.write(formatStartupError(error, { operation: 'upgrade' })); - process.stderr.write(`See log: ${resolveGlobalLogPath(resolveKimiHome())}\n`); + process.stderr.write(`See log: ${formatLogPathForUser(resolveKimiHome())}\n`); process.exit(1); }); },