mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-11-14 10:39:32 +01:00
fix(story-mode): the rest of the PR review: lookups, polling, frame budget, linear links
From review round 7 (PR review): - With no hook path (normal after a server restart), the transcript was looked up by conversation id only; it now also tries the Codeman id and a recovered session's `restored-<fragment>` transcript, as last-response does, and keeps what it found briefly (a lookup reads every project folder; a miss is kept only 4 s). - A session Story Mode cannot draw is not polled, and a page with nothing drawn yet is polled like a finished one (every 15 s), not every 4 s. - Helper steps: one request per helper is drawn, the newest; a failed refetch never writes over steps already shown. - The Director's cut toggle, a skin change and the fonts arriving redraw within the frame budget, not every panel in one task. - A bare name under an `ls` header finds its folder in one pass over the lines; a search per link over the text before it was quadratic (about 1.5 s for 700 links on agent output). - A page of many questions still keeps to 12 panels: questions fold last. - Opening Story Mode while it is open never starts a second runtime; the status announcer carries data-i18n-skip; the turn key in the ETag is clipped. - The crafted-input timing test runs at sizes where the old code took 6 to 29 s and the new one under 10 ms, with a 1.5 s bound. - Docs: `older`, `origin` (`scheduled`), which route answers a 500; mobile.css's stale comment; an orphaned doc comment. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
e7ce3b8e56
commit
42d1c75a19
10 files changed
+191
-41
No files matched your search
@@ -47,6 +47,44 @@ export function claudeProjectsDir(configDir?: string): string {
|
||||
return join(configDir || fromEnv || join(homedir(), '.claude'), 'projects');
|
||||
}
|
||||
|
||||
/**
|
||||
* The one top-level transcript a recovered session (`restored-<first 8+ hex of its uuid>`, how
|
||||
* reconcileSessions() names a session whose mux record was lost) belongs to, or null when none or
|
||||
* more than one matches. The same recovery `last-response` makes (session-routes.ts).
|
||||
*/
|
||||
export async function findRestoredClaudeTranscriptPath(
|
||||
codemanSessionId: string,
|
||||
configDir?: string
|
||||
): Promise<string | null> {
|
||||
const restored = /^restored-([a-f0-9]{8,})$/i.exec(codemanSessionId);
|
||||
if (!restored) return null;
|
||||
const fragment = restored[1].toLowerCase();
|
||||
const uuid = /^[a-f0-9]{8}-[a-f0-9]{4}-[1-5][a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$/i;
|
||||
const projectsDir = claudeProjectsDir(configDir);
|
||||
let projectDirs: string[];
|
||||
try {
|
||||
projectDirs = await readdir(projectsDir);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
const found = new Map<string, string>();
|
||||
for (const projectDir of projectDirs) {
|
||||
let files: string[];
|
||||
try {
|
||||
files = await readdir(join(projectsDir, projectDir));
|
||||
} catch {
|
||||
continue;
|
||||
}
|
||||
for (const file of files) {
|
||||
const id = file.endsWith('.jsonl') ? file.slice(0, -'.jsonl'.length) : '';
|
||||
if (!id.toLowerCase().startsWith(fragment) || !uuid.test(id)) continue;
|
||||
const path = join(projectsDir, projectDir, file);
|
||||
if ((await stat(path).catch(() => null))?.isFile()) found.set(id, path);
|
||||
}
|
||||
}
|
||||
return found.size === 1 ? [...found.values()][0] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Path of the transcript for `conversationId` under any project directory, or null. Unlike
|
||||
* {@link claudeTranscriptExists} it answers with the file (Story Mode reads it), so the id is
|
||||
|
||||
Reference in new issue
Block a user