add vscode copilot and mistral vibe#70
Conversation
| const messagesPath = path.join(dir, 'messages.jsonl'); | ||
| if (!fs.existsSync(messagesPath)) continue; | ||
|
|
||
| const meta = JSON.parse(fs.readFileSync(metaPath, 'utf-8')) as VibeMeta; |
There was a problem hiding this comment.
🔴 mistral-vibe.ts uses fs.readFileSync in parser — blocks event loop
The parseMistralVibeSessions function at line 86 uses fs.readFileSync to read meta.json. REVIEW.md explicitly states: "Flag any use of fs.readFileSync or fs.writeFileSync in parser code — these block the event loop and can stall the CLI when scanning large session directories." AGENTS.md also lists fs.readFileSync/fs.writeFileSync in parsers as an anti-pattern. The kimi parser demonstrates the correct approach at src/parsers/kimi.ts:84 using fs.promises.readFile (async).
| const meta = JSON.parse(fs.readFileSync(metaPath, 'utf-8')) as VibeMeta; | |
| const meta = JSON.parse(await fs.promises.readFile(metaPath, 'utf-8')) as VibeMeta; |
Was this helpful? React with 👍 or 👎 to provide feedback.
| model: extractModelFromTurns(turns), | ||
| }); | ||
| } else { | ||
| const data = JSON.parse(fs.readFileSync(filePath, 'utf-8')) as VscodeChatSessionJson; |
There was a problem hiding this comment.
🔴 vscode-copilot.ts uses fs.readFileSync in parser — blocks event loop during discovery and extraction
Three call sites in the VS Code Copilot parser use synchronous fs.readFileSync:
- Line 149 (
extractCwd): readsworkspace.jsonfor every workspace hash directory during session discovery - Line 229 (
parseVscodeCopilotSessions): reads full JSON session files during discovery - Line 269 (
extractVscodeCopilotContext): reads full JSON session files during context extraction
REVIEW.md explicitly states: "Flag any use of fs.readFileSync or fs.writeFileSync in parser code — these block the event loop and can stall the CLI when scanning large session directories." Line 229 is particularly impactful as it runs for every legacy JSON session file during the discovery phase. The kimi parser at src/parsers/kimi.ts:84 demonstrates the correct pattern using fs.promises.readFile.
Prompt for agents
Three call sites in src/parsers/vscode-copilot.ts use fs.readFileSync and need to be converted to async equivalents:
1. Line 149 in extractCwd: change to use fs.promises.readFile and make extractCwd async. All callers (line 206) need to await it.
2. Line 229 in parseVscodeCopilotSessions: change to fs.promises.readFile for reading JSON session files.
3. Line 269 in extractVscodeCopilotContext: change to fs.promises.readFile for reading JSON session files.
See src/parsers/kimi.ts:84 for the correct async pattern using fs.promises.readFile. The extractCwd function becoming async means its caller at line 206 needs to be updated to await.
Was this helpful? React with 👍 or 👎 to provide feedback.
| const messages = await parseMessages(messagesPath); | ||
| const conversationMessages = extractConversationMessages(messages); | ||
| if (conversationMessages.length === 0) continue; |
There was a problem hiding this comment.
🚩 parseMistralVibeSessions reads full JSONL during discovery phase
The parseMistralVibeSessions function reads the entire messages.jsonl for every session during the discovery phase (src/parsers/mistral-vibe.ts:93). This is done to filter out sessions with zero conversation messages (line 95) and to extract the first user message for the summary (line 97). Most other parsers (e.g., src/parsers/kimi.ts, src/parsers/qwen-code.ts) only read file metadata (size, timestamps) or scan just the first few lines using scanJsonlHead during discovery, deferring full message reading to the extraction phase. For users with many Mistral Vibe sessions, this could noticeably slow down the continues list and continues scan commands. Consider using scanJsonlHead to check for at least one user/assistant message and extracting a summary from the first few lines only.
Was this helpful? React with 👍 or 👎 to provide feedback.
| async function findChatSessionFiles(): Promise<Array<{ filePath: string; hashDir: string }>> { | ||
| if (!fs.existsSync(WORKSPACE_STORAGE_DIR)) return []; | ||
| const results: Array<{ filePath: string; hashDir: string }> = []; | ||
| const files = findFiles(WORKSPACE_STORAGE_DIR, { | ||
| match: (entry) => entry.name.endsWith('.json') || entry.name.endsWith('.jsonl'), | ||
| maxDepth: 2, | ||
| }); | ||
| for (const filePath of files) { | ||
| if (filePath.includes(`${path.sep}chatSessions${path.sep}`)) { | ||
| const hashDir = path.dirname(path.dirname(filePath)); | ||
| results.push({ filePath, hashDir }); | ||
| } | ||
| } | ||
| return results; | ||
| } |
There was a problem hiding this comment.
📝 Info: VS Code Copilot discovery scans broadly with maxDepth: 2
The findChatSessionFiles function at src/parsers/vscode-copilot.ts:184-187 uses findFiles with match: (entry) => entry.name.endsWith('.json') || entry.name.endsWith('.jsonl') and maxDepth: 2. The VS Code workspaceStorage directory can contain hundreds of workspace hash directories, each storing data from many extensions. This broad .json/.jsonl match collects all JSON files at depth ≤ 2 before filtering to only those under chatSessions/ (line 189). While functionally correct, this could collect a large number of irrelevant file paths on machines with many workspaces. A tighter match predicate (e.g., checking if the parent directory is chatSessions) or a more targeted directory walk could reduce unnecessary work.
Was this helpful? React with 👍 or 👎 to provide feedback.
| function extractCwd(workspaceJson: string): string { | ||
| try { | ||
| const data = JSON.parse(fs.readFileSync(workspaceJson, 'utf-8')) as { folder?: string; workspace?: string }; | ||
| const raw = data.folder ?? data.workspace ?? ''; | ||
| return raw.replace(/^file:\/\//, ''); | ||
| } catch { | ||
| return ''; | ||
| } | ||
| } |
There was a problem hiding this comment.
📝 Info: extractCwd strips file:// but may leave leading slash on Windows paths
The extractCwd function at src/parsers/vscode-copilot.ts:151 uses raw.replace(/^file:\/\//, '') to strip the file:// protocol. For Windows paths like file:///C:/Users/project, this produces /C:/Users/project with a leading / that's incorrect on Windows. The copilot.ts parser has a similar pattern at src/parsers/copilot.ts:67. Using Node.js fileURLToPath from node:url would handle platform differences correctly, but since this matches the existing copilot parser pattern and only affects Windows, it's a pre-existing design choice rather than a regression introduced by this PR.
Was this helpful? React with 👍 or 👎 to provide feedback.
| // ── Mistral Vibe ───────────────────────────────────────────────────── | ||
| register({ | ||
| name: 'mistral-vibe', | ||
| label: 'Mistral Vibe', | ||
| color: chalk.hex('#FF7000'), | ||
| storagePath: '~/.vibe/logs/session/', | ||
| envVar: 'VIBE_HOME', | ||
| binaryName: 'vibe', | ||
| parseSessions: parseMistralVibeSessions, | ||
| extractContext: extractMistralVibeContext, | ||
| nativeResumeArgs: () => [], | ||
| crossToolArgs: (prompt) => [prompt], | ||
| resumeCommandDisplay: () => 'vibe', | ||
| }); | ||
|
|
||
| // ── VS Code Copilot Chat ───────────────────────────────────────────── | ||
| register({ | ||
| name: 'vscode-copilot', | ||
| label: 'VS Code Copilot', | ||
| color: chalk.hex('#24A0ED'), | ||
| storagePath: '~/Library/Application Support/Code/User/workspaceStorage/ (Linux: ~/.config/Code/User/workspaceStorage/, Windows: %APPDATA%/Code/User/workspaceStorage/)', | ||
| envVar: 'VSCODE_COPILOT_HOME', | ||
| binaryName: 'code', | ||
| parseSessions: parseVscodeCopilotSessions, | ||
| extractContext: extractVscodeCopilotContext, | ||
| nativeResumeArgs: () => [], | ||
| crossToolArgs: (prompt) => [prompt], | ||
| resumeCommandDisplay: () => 'code', | ||
| }); |
There was a problem hiding this comment.
📝 Info: New parser checklist complete for both tools
Both Mistral Vibe and VS Code Copilot correctly follow all 5 steps of the new-parser checklist from REVIEW.md/AGENTS.md: (1) tool names added to TOOL_NAMES in src/types/tool-names.ts:24-25, (2) parser files created with parse*Sessions and extract*Context exports, (3) registry entries added in src/parsers/registry.ts:944-972, (4) fixture factories added in src/__tests__/fixtures/index.ts:1207-1291, and (5) conversion tests added in src/__tests__/unit-conversions.test.ts:464-984. The registry completeness assertion at src/parsers/registry.ts:977 ensures these tools are wired up correctly.
Was this helpful? React with 👍 or 👎 to provide feedback.
Summary by cubic
Adds support for VS Code Copilot Chat and Mistral Vibe, enabling resume and any-to-any handoffs. Supported tools increase from 16 to 18 with updated docs and tests.
New Features
vscode-copilot(JSON + JSONL) andmistral-vibe(JSONL + JSON) with registry entries.workspaceStorage(override withVSCODE_COPILOT_HOME); Vibe at~/.vibe/logs/session/(override withVIBE_HOME)..jsonand new.jsonl; builds messages from requests; extracts model fromresult.details; uses custom title or first user message.meta.json+messages.jsonl; extracts recent messages, model, cwd; summarizestool_calls(bash, read/write, grep, web_search/fetch, task, fallback MCP) via tool summarizer.TOOL_NAMESincludesmistral-vibeandvscode-copilot(count 18); addedsearch_replaceto edit tools.Refactors
Written for commit e3dcd4d. Summary will update on new commits.