Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/stray-files-session-index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@moonshot-ai/kimi-code": patch
---

Fix sessions not loading in the resume picker when stray files sit inside the sessions directory.
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ const WATCH_DEBOUNCE_MS = 150;
const TORN_READ_RETRIES = 3;
const TORN_READ_RETRY_DELAY_MS = 15;

function isEnoent(error: unknown): boolean {
return (error as NodeJS.ErrnoException).code === 'ENOENT';
function isMissingEntry(error: unknown): boolean {
const code = (error as NodeJS.ErrnoException).code;
return code === 'ENOENT' || code === 'ENOTDIR';
}

export class FileStorageService implements IFileSystemStorageService {
Expand All @@ -42,7 +43,7 @@ export class FileStorageService implements IFileSystemStorageService {
try {
bytes = await readFile(filePath);
} catch (error) {
if (isEnoent(error)) return undefined;
if (isMissingEntry(error)) return undefined;
throw toStorageIoError(error, { path: filePath, op: 'read' });
}
if (attempt >= TORN_READ_RETRIES) return bytes;
Expand Down Expand Up @@ -72,7 +73,7 @@ export class FileStorageService implements IFileSystemStorageService {
yield chunk as Uint8Array;
}
} catch (error) {
if (isEnoent(error)) return;
if (isMissingEntry(error)) return;
throw toStorageIoError(error, { path: filePath, op: 'read' });
}
}
Expand Down Expand Up @@ -144,7 +145,7 @@ export class FileStorageService implements IFileSystemStorageService {
try {
entries = await readdir(this.scopePath(scope));
} catch (error) {
if (isEnoent(error)) return [];
if (isMissingEntry(error)) return [];
throw toStorageIoError(error, { path: this.scopePath(scope), op: 'list' });
}
return prefix === undefined ? entries : entries.filter((entry) => entry.startsWith(prefix));
Expand All @@ -155,7 +156,7 @@ export class FileStorageService implements IFileSystemStorageService {
try {
await unlink(filePath);
} catch (error) {
if (isEnoent(error)) return;
if (isMissingEntry(error)) return;
throw toStorageIoError(error, { path: filePath, op: 'delete' });
}
}
Expand All @@ -165,7 +166,7 @@ export class FileStorageService implements IFileSystemStorageService {
try {
return (await stat(filePath)).size;
} catch (error) {
if (isEnoent(error)) return undefined;
if (isMissingEntry(error)) return undefined;
throw toStorageIoError(error, { path: filePath, op: 'stat' });
}
}
Expand All @@ -175,7 +176,7 @@ export class FileStorageService implements IFileSystemStorageService {
try {
return (await stat(filePath)).mtimeMs;
} catch (error) {
if (isEnoent(error)) return undefined;
if (isMissingEntry(error)) return undefined;
throw toStorageIoError(error, { path: filePath, op: 'stat' });
}
}
Expand Down Expand Up @@ -263,7 +264,7 @@ export class FileStorageService implements IFileSystemStorageService {
await syncDir(dir);
this.syncedDirs.add(dir);
} catch (error) {
if (!isEnoent(error)) throw error;
if (!isMissingEntry(error)) throw error;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,16 @@ describe('FileStorageService — error translation', () => {
await expect(svc.delete('scope', 'missing.json')).resolves.toBeUndefined();
});

it('treats a regular file in place of a scope directory as missing', async () => {
const svc = new FileStorageService(dir);
await writeFile(join(dir, 'junk'), 'x');
expect(await svc.read('junk', 'state.json')).toBeUndefined();
expect(await svc.size('junk', 'state.json')).toBeUndefined();
expect(await svc.mtime('junk', 'state.json')).toBeUndefined();
expect(await svc.list('junk')).toEqual([]);
await expect(svc.delete('junk', 'state.json')).resolves.toBeUndefined();
});

it.skipIf(isWin)('translates non-ENOENT failures into StorageError(io_failed)', async () => {
const svc = new FileStorageService(dir);
await mkdir(join(dir, 'scope', 'adir'), { recursive: true });
Expand Down