Skip to content

Commit eaeda36

Browse files
authored
Merge pull request #656 from rajbos/rajbos/extract-copilot-chat-adapter
Extract CopilotChat and CopilotCli adapters (#654)
2 parents f310c7a + 7c39207 commit eaeda36

11 files changed

Lines changed: 1055 additions & 426 deletions

.github/instructions/cli.instructions.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ Or from the repo root:
3131

3232
When adding support for a new editor or data source, wire it into **both** `vscode-extension/src/` (see `.github/instructions/vscode-extension.instructions.md`) **and** this CLI.
3333

34+
> **Adapter architecture (issue #654)**: The CLI shares the adapter classes from `vscode-extension/src/adapters/` and registers them in `_ecosystems` inside `cli/src/helpers.ts`. Currently 9 adapters are registered: OpenCode, Crush, Continue, ClaudeCode, ClaudeDesktop, VisualStudio, MistralVibe, **CopilotChat**, **CopilotCli**. The Copilot adapters own discovery but their `handles()` returns `false`, so `processSessionFile()` falls through to the existing per-format helpers (JSONL/JSON parsing) for those files. Order matters — register Copilot adapters **last**.
35+
3436
### CLI Files to Update
3537

3638
| File | What to add |

.github/instructions/vscode-extension.instructions.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,3 +151,17 @@ To maintain a consistent, VS Code-native look across all webview panels (Details
151151
## Adding a New Editor / Data Source
152152

153153
When adding support for a new editor or data source, you must wire it into **both** this extension (`vscode-extension/src/`) **and** the CLI (`cli/src/`). See `.github/instructions/cli.instructions.md` for the CLI integration checklist.
154+
155+
### Adapter architecture (issue #654)
156+
157+
All editor integrations live as adapters under `vscode-extension/src/adapters/` implementing `IEcosystemAdapter` (and `IDiscoverableEcosystem` when discovery is needed). `sessionDiscovery.ts` is intentionally a thin generic loop: it iterates the adapters registered in `extension.ts` (`this.ecosystems`) and dedupes the resulting paths. There are **no hardcoded editor paths in `sessionDiscovery.ts`**.
158+
159+
Current adapter set (9):
160+
- `OpenCodeAdapter`, `CrushAdapter`, `ContinueAdapter`, `ClaudeCodeAdapter`, `ClaudeDesktopAdapter`, `VisualStudioAdapter`, `MistralVibeAdapter`
161+
- `CopilotChatAdapter` — VS Code Copilot Chat (workspaceStorage chatSessions in 3 layouts, globalStorage emptyWindowChatSessions, globalStorage `{GitHub,github}.copilot-chat` recursive scan, WSL Windows-side paths)
162+
- `CopilotCliAdapter``~/.copilot/session-state/` flat `.json`/`.jsonl` plus UUID subdirs with `events.jsonl`
163+
164+
**Adapter ordering matters**: register more-specific adapters first. `CopilotChatAdapter` and `CopilotCliAdapter` are registered **last** in `this.ecosystems`.
165+
166+
**`handles()` for CopilotChat/Cli currently returns `false`**: discovery is owned by the adapters, but per-session parsing is still routed through the existing fallback path in `extension.ts` (`countInteractionsInSession`, `estimateTokensFromSession`, `getSessionFileDataCached`). A future PR can flip `handles()` to use the exported `isCopilotChatSessionPath` / `isCopilotCliSessionPath` predicates once the JSON parser helpers are extracted from `extension.ts`. When you flip `handles()`, also fix `_detectEditorSource(filePath, (p) => !!this.findEcosystem(p))` at extension.ts:~3224 — the predicate must check `?.id === 'opencode'` (or use `getEditorTypeFromPath` convention) so that VS Code paths are still labeled "VS Code", not "OpenCode".
167+

cli/src/helpers.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { ClaudeCodeDataAccess } from '../../vscode-extension/src/claudecode';
1515
import { ClaudeDesktopCoworkDataAccess } from '../../vscode-extension/src/claudedesktop';
1616
import { MistralVibeDataAccess } from '../../vscode-extension/src/mistralvibe';
1717
import type { IEcosystemAdapter } from '../../vscode-extension/src/ecosystemAdapter';
18-
import { OpenCodeAdapter, CrushAdapter, ContinueAdapter, ClaudeDesktopAdapter, ClaudeCodeAdapter, VisualStudioAdapter, MistralVibeAdapter } from '../../vscode-extension/src/adapters';
18+
import { OpenCodeAdapter, CrushAdapter, ContinueAdapter, ClaudeDesktopAdapter, ClaudeCodeAdapter, VisualStudioAdapter, MistralVibeAdapter, CopilotChatAdapter, CopilotCliAdapter } from '../../vscode-extension/src/adapters';
1919
import { parseSessionFileContent } from '../../vscode-extension/src/sessionParser';
2020
import { estimateTokensFromText, getModelFromRequest, isJsonlContent, estimateTokensFromJsonlSession, calculateEstimatedCost, getModelTier } from '../../vscode-extension/src/tokenEstimation';
2121
import type { DetailedStats, PeriodStats, ModelUsage, EditorUsage, SessionFileCache, UsageAnalysisStats, UsageAnalysisPeriod } from '../../vscode-extension/src/types';
@@ -98,6 +98,11 @@ const _ecosystems: IEcosystemAdapter[] = [
9898
new ClaudeDesktopAdapter(_claudeDesktopCoworkInstance),
9999
new ClaudeCodeAdapter(_claudeCodeInstance),
100100
new MistralVibeAdapter(_mistralVibeInstance),
101+
// Copilot Chat / CLI adapters: discovery-only. Their handles() returns
102+
// false so processSessionFile() falls through to the shared parser path
103+
// for VS Code Copilot Chat and CLI files. See issue #654.
104+
new CopilotChatAdapter(),
105+
new CopilotCliAdapter(),
101106
];
102107

103108
/** Create session discovery instance for CLI */

0 commit comments

Comments
 (0)