feat(cli): provide manual session UUID via command line arg (#26060)

This commit is contained in:
Coco Sheng
2026-04-27 17:05:27 -04:00
committed by GitHub
parent 820a4e3c92
commit 6cc0b1b136
6 changed files with 238 additions and 52 deletions
@@ -47,6 +47,47 @@ describe('SessionSelector', () => {
}
});
describe('sessionExists', () => {
it('should return true if a session file with the exact UUID exists', async () => {
const sessionId = randomUUID();
const chatsDir = path.join(tmpDir, 'chats');
await fs.mkdir(chatsDir, { recursive: true });
await fs.writeFile(
path.join(
chatsDir,
`session-20240101T000000-${sessionId.slice(0, 8)}.jsonl`,
),
JSON.stringify({ sessionId }),
);
const selector = new SessionSelector(storage);
const exists = await selector.sessionExists(sessionId);
expect(exists).toBe(true);
});
it('should return false if no session file matches the UUID', async () => {
const sessionId = randomUUID();
const chatsDir = path.join(tmpDir, 'chats');
await fs.mkdir(chatsDir, { recursive: true });
await fs.writeFile(
path.join(chatsDir, `session-different-uuid-20240101.jsonl`),
'{}',
);
const selector = new SessionSelector(storage);
const exists = await selector.sessionExists(sessionId);
expect(exists).toBe(false);
});
it('should return false if the chats directory does not exist', async () => {
const sessionId = randomUUID();
// Notice we do NOT create chatsDir here.
const selector = new SessionSelector(storage);
const exists = await selector.sessionExists(sessionId);
expect(exists).toBe(false);
});
});
it('should resolve session by UUID', async () => {
const sessionId1 = randomUUID();
const sessionId2 = randomUUID();
+30
View File
@@ -408,6 +408,36 @@ export const getSessionFiles = async (
export class SessionSelector {
constructor(private storage: Storage) {}
/**
* Checks if a session with the given ID already exists on disk.
*/
async sessionExists(id: string): Promise<boolean> {
const chatsDir = path.join(this.storage.getProjectTempDir(), 'chats');
const files = await fs.readdir(chatsDir).catch(() => []);
// The filename format is `session-<TIMESTAMP>-<ID_SLICE(0,8)>.jsonl`
const shortId = id.slice(0, 8);
const candidateFiles = files.filter(
(f) =>
f.startsWith(SESSION_FILE_PREFIX) &&
(f.endsWith(`-${shortId}.json`) || f.endsWith(`-${shortId}.jsonl`)),
);
for (const fileName of candidateFiles) {
try {
const sessionPath = path.join(chatsDir, fileName);
const sessionData = await loadConversationRecord(sessionPath);
if (sessionData && sessionData.sessionId === id) {
return true;
}
} catch {
// Ignore unparseable files
}
}
return false;
}
/**
* Lists all available sessions for the current project.
*/