From 0fe13173f411a766e2e858be7452fbcb74ecb44c Mon Sep 17 00:00:00 2001 From: Qkunio <132257510+qkunio@users.noreply.github.com> Date: Mon, 8 Jun 2026 15:10:30 +0800 Subject: [PATCH] fix: handle windows session workdir separators (#486) * fix: handle windows session workdir separators * test: cover Windows session workdir normalization --------- Co-authored-by: qkunio Co-authored-by: liruifengv --- apps/kimi-code/package.json | 1 + apps/kimi-code/src/cli/run-prompt.ts | 3 ++- apps/kimi-code/src/tui/kimi-tui.ts | 3 ++- apps/kimi-code/test/cli/run-prompt.test.ts | 22 ++++++++++++++++ .../test/tui/kimi-tui-startup.test.ts | 25 +++++++++++++++++++ pnpm-lock.yaml | 3 +++ 6 files changed, 55 insertions(+), 2 deletions(-) diff --git a/apps/kimi-code/package.json b/apps/kimi-code/package.json index eca7f97eb..4609c742c 100644 --- a/apps/kimi-code/package.json +++ b/apps/kimi-code/package.json @@ -71,6 +71,7 @@ "chalk": "^5.4.1", "cli-highlight": "^2.1.11", "commander": "^13.1.0", + "pathe": "^2.0.3", "semver": "^7.7.4", "smol-toml": "^1.6.1", "zod": "^4.3.6" diff --git a/apps/kimi-code/src/cli/run-prompt.ts b/apps/kimi-code/src/cli/run-prompt.ts index 190781dbc..32348cf6c 100644 --- a/apps/kimi-code/src/cli/run-prompt.ts +++ b/apps/kimi-code/src/cli/run-prompt.ts @@ -17,6 +17,7 @@ import { type SessionStatus, type TelemetryClient, } from '@moonshot-ai/kimi-code-sdk'; +import { resolve } from 'pathe'; import { CLI_SHUTDOWN_TIMEOUT_MS } from '#/constant/app'; import { experimentalFeatureMap } from '#/utils/experimental-features'; @@ -229,7 +230,7 @@ async function resolvePromptSession( if (target === undefined) { throw new Error(`Session "${opts.session}" not found.`); } - if (target.workDir !== workDir) { + if (resolve(target.workDir) !== resolve(workDir)) { stderr.write( `${chalk.hex('#E8A838')( `Session "${opts.session}" was created under a different directory.\n` + diff --git a/apps/kimi-code/src/tui/kimi-tui.ts b/apps/kimi-code/src/tui/kimi-tui.ts index 991b09a49..7e59fa4e5 100644 --- a/apps/kimi-code/src/tui/kimi-tui.ts +++ b/apps/kimi-code/src/tui/kimi-tui.ts @@ -22,6 +22,7 @@ import type { Session, } from '@moonshot-ai/kimi-code-sdk'; import chalk from 'chalk'; +import { resolve } from 'pathe'; import type { CLIOptions } from '#/cli/options'; import { MigrationScreenComponent, type MigrationScreenResult } from '#/migration/index'; @@ -512,7 +513,7 @@ export class KimiTUI { if (target === undefined) { throw new Error(`Session "${startup.sessionFlag}" not found.`); } - if (target.workDir !== workDir) { + if (resolve(target.workDir) !== resolve(workDir)) { this.state.ui.stop(); process.stderr.write( `${chalk.hex(this.state.theme.colors.warning)( diff --git a/apps/kimi-code/test/cli/run-prompt.test.ts b/apps/kimi-code/test/cli/run-prompt.test.ts index 28ba20df1..e4a2d2149 100644 --- a/apps/kimi-code/test/cli/run-prompt.test.ts +++ b/apps/kimi-code/test/cli/run-prompt.test.ts @@ -440,6 +440,28 @@ describe('runPrompt', () => { expect(mocks.session.setPermission).toHaveBeenNthCalledWith(2, 'manual'); }); + it('allows resuming a concrete session when Windows workdir uses backslashes', async () => { + const cwd = vi.spyOn(process, 'cwd').mockReturnValue(String.raw`C:\Users\kimi\project`); + mocks.harnessListSessions.mockResolvedValueOnce([ + { id: 'ses_existing', workDir: 'C:/Users/kimi/project' }, + ]); + + try { + await runPrompt(opts({ session: 'ses_existing' }), '1.2.3-test', { + stdout: { write: vi.fn(() => true) }, + stderr: { write: vi.fn(() => true) }, + }); + } finally { + cwd.mockRestore(); + } + + expect(mocks.harnessListSessions).toHaveBeenCalledWith({ + sessionId: 'ses_existing', + workDir: String.raw`C:\Users\kimi\project`, + }); + expect(mocks.harnessResumeSession).toHaveBeenCalledWith({ id: 'ses_existing' }); + }); + it('applies the CLI model override to resumed prompt sessions', async () => { await runPrompt(opts({ session: 'ses_existing', model: 'kimi-code/k2.5' }), '1.2.3-test', { stdout: { write: vi.fn(() => true) }, diff --git a/apps/kimi-code/test/tui/kimi-tui-startup.test.ts b/apps/kimi-code/test/tui/kimi-tui-startup.test.ts index 3b5a0c14a..58a4ec762 100644 --- a/apps/kimi-code/test/tui/kimi-tui-startup.test.ts +++ b/apps/kimi-code/test/tui/kimi-tui-startup.test.ts @@ -897,6 +897,31 @@ describe("KimiTUI startup", () => { expect(uiContainsFooter(driver)).toBe(true); }); + + it("resumes a startup session when Windows workdir uses backslashes", async () => { + const session = makeSession({ id: "ses-target" }); + const harness = makeHarness(session, { + listSessions: vi.fn(async () => [ + { id: "ses-target", workDir: "C:/Users/kimi/project" }, + ]), + }); + const driver = makeDriver( + harness, + { + ...makeStartupInput({ session: "ses-target" }), + workDir: String.raw`C:\Users\kimi\project`, + }, + ); + + await expect(driver.init()).resolves.toBe(true); + + expect(harness.listSessions).toHaveBeenCalledWith({ + sessionId: "ses-target", + workDir: String.raw`C:\Users\kimi\project`, + }); + expect(harness.resumeSession).toHaveBeenCalledWith({ id: "ses-target" }); + expect(driver.state.appState.sessionId).toBe("ses-target"); + }); }); function uiContainsFooter(driver: StartupDriver): boolean { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2351ffb92..5c4047ff2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -87,6 +87,9 @@ importers: commander: specifier: ^13.1.0 version: 13.1.0 + pathe: + specifier: ^2.0.3 + version: 2.0.3 semver: specifier: ^7.7.4 version: 7.7.4