refactor: replace ecosystem if-chains with IEcosystemAdapter registry#641
Merged
refactor: replace ecosystem if-chains with IEcosystemAdapter registry#641
Conversation
- Add IEcosystemAdapter interface (ecosystemAdapter.ts) - Add 7 adapter implementations in src/adapters/ (OpenCode, Crush, Continue, ClaudeDesktop, ClaudeCode, VisualStudio, MistralVibe) - Replace 8 if-chain methods in extension.ts with findEcosystem() dispatch - Replace getModelUsageFromSession() if-chain in usageAnalysis.ts with adapter dispatch + legacy fallback - Replace statSessionFile() + processSessionFile() if-chains in cli/src/helpers.ts - Wire ecosystems registry into calculateUsageAnalysisStats() in CLI - Remove now-unused isCrushSessionFile() + isOpenCodeDbSession() helpers from CLI - Fix duplicate VS check bugs in statSessionFile() and estimateTokensFromSession() - Fix missing MistralVibe in isSpecialSession check and getSessionFileDetails() - Fix missing ClaudeCode in getSessionFileDetails() Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… pattern - Replace 6-ecosystem buildTurns if-chain in getSessionLogData() with adapter delegation (~450 lines -> ~20 lines) - Fix ClaudeDesktopAdapter constructor call with required callbacks - Replace openRawFile VS-specific handler with adapter getRawFileContent() - Fix detectEditorSource to use findEcosystem() instead of isOpenCodeSessionFile() Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ters Add IDiscoverableEcosystem interface with discover() and getCandidatePaths() methods. All 7 adapters implement both methods, moving ~200 lines of ecosystem-specific discovery blocks from SessionDiscovery into the adapters. - ecosystemAdapter.ts: add CandidatePath, DiscoveryResult, IDiscoverableEcosystem - All 7 adapters: implement discover() + getCandidatePaths() - sessionDiscovery.ts: replace 7 discovery blocks + 7 diagnostic blocks with adapter loops (~200 lines removed) - extension.ts + cli/helpers.ts: wire ecosystems into SessionDiscovery deps Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… DA calls Phase 4: Drop 7 individual DataAccess fields from SessionDiscoveryDeps. SessionDiscovery now only needs ecosystems + log/warn/error + optional override. Updated constructor calls in extension.ts and cli/src/helpers.ts. Phase 5 (partial): Fix last 3 direct this.openCode.* calls in extension.ts. - getEditorTypeFromPath(): use findEcosystem(p)?.id === 'opencode' instead of this.openCode.isOpenCodeSessionFile() - Folder counting loop: use adapter.getEditorRoot() for all adapter-owned sessions (was only handling OpenCode; now handles Crush and other virtual-path sessions too) Phase 3 tests: Add 24 unit tests covering adapter discovery: - isDiscoverable() type guard (all 7 adapters + negative case) - handles() path recognition for OpenCode/Continue/ClaudeCode/MistralVibe - getCandidatePaths() structure validation for all adapters - getEditorRoot() returns non-empty string for all adapters - discover() returns valid DiscoveryResult shape (graceful empty dirs) - getCandidatePaths/discover consistency invariant Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove 7 individual DataAccess fields from UsageAnalysisDeps. All usage analysis routing now goes through the IAnalyzableEcosystem interface implemented by all 7 ecosystem adapters. Changes: - ecosystemAdapter.ts: add UsageAnalysisAdapterContext, IAnalyzableEcosystem interface and isAnalyzable() type guard - usageAnalysis.ts: slim UsageAnalysisDeps from 13 to 5 fields, replace 7 DA if-blocks in analyzeSessionUsage() with adapter dispatch, remove legacy DA fallback from getModelUsageFromSession(), export readClaudeCodeEventsForAnalysis, applyModelTierClassification, and createEmptySessionUsageAnalysis() factory - All 7 adapters: implement IAnalyzableEcosystem with analyzeUsage() - openCodeAdapter.ts + crushAdapter.ts: add getSyncData() for backend sync - extension.ts: slim usageAnalysisDeps getter to 5 fields - cli/src/helpers.ts: slim calculateUsageAnalysisStats deps to 5 fields - usageAnalysis.test.ts: update makeMockDeps to adapter-based mock Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
ClaudeDesktopCoworkDataAccess.getCoworkBaseDir() intentionally returns '' on non-Windows platforms (the feature is Windows-only). The test 'getEditorRoot: all adapters return non-empty string' was failing on Linux CI because it called getEditorRoot() on every adapter without regard for platform availability. Skip the claudedesktop adapter check when not on win32. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Replaces the repeated ecosystem
if-statement chains inextension.ts,usageAnalysis.ts, andcli/src/helpers.tswith a unifiedIEcosystemAdapterregistry pattern.Problem
Every method that touched session files had a chain like:
This existed in 8+ methods across 3 files. Adding a new ecosystem required updating all of them.
Solution
Adapter pattern — a common
IEcosystemAdapterinterface with 7 thin implementations:All 8 if-chain methods are replaced with:
Files Changed
New:
vscode-extension/src/ecosystemAdapter.ts—IEcosystemAdapterinterfacevscode-extension/src/adapters/— 7 adapter implementations (OpenCode, Crush, Continue, ClaudeDesktop, ClaudeCode, VisualStudio, MistralVibe)Modified:
vscode-extension/src/extension.ts— 8 if-chain methods replaced;findEcosystem()addedvscode-extension/src/usageAnalysis.ts— adapter dispatch ingetModelUsageFromSession()with legacy fallbackcli/src/helpers.ts— adapter registry wired intostatSessionFile(),processSessionFile(), andcalculateUsageAnalysisStats()Bugs Fixed Along the Way
statSessionFile()andestimateTokensFromSession()(unreachable dead code)isSpecialSessioncheck andgetSessionFileDetails()getSessionFileDetails()What's NOT Changed
CopilotChatAdaptercan wrap it)analyzeSessionUsage()inusageAnalysis.ts(too complex, deferred to follow-up)Adding a New Ecosystem (Going Forward)
src/adapters/newEditorAdapter.tsimplementingIEcosystemAdapterextension.tsconstructor andcli/src/helpers.ts