fix(disposal): Complete Instance disposal chain for plugins and caches
Summary
Complete the Instance disposal chain to ensure plugins and cached resources are properly cleaned up when instances are disposed.
Fixes #9157 Depends on #9141 (LRU cache utility)
Note: This PR builds on the LRU cache utility from #9141. Please merge that PR first.
Problem
When Instance.dispose() is called:
- Plugins not disposed - Plugins may hold resources (connections, file handles) that need cleanup
- Cached instances not disposed - The instance cache doesn't call disposal hooks when evicting entries
- No disposal hook in Hooks interface - Plugins have no way to register cleanup logic
Solution
1. Plugin Dispose Hook
Add dispose() method to plugin Hooks interface.
2. LRU Cache onEvict Callback
Use the LRU cache's onEvict callback to dispose instances when evicted.
3. Bootstrap Cleanup
Add cleanup in bootstrap to dispose plugins before process exit.
Changes
-
packages/plugin/src/index.ts- Adddispose()to Hooks interface -
packages/opencode/src/plugin/index.ts- Call plugin dispose() on instance disposal -
packages/opencode/src/project/instance.ts- Add onEvict callback for cache eviction -
packages/opencode/src/project/bootstrap.ts- Add cleanup for plugins on exit -
packages/opencode/src/provider/provider.ts- Use LRU cache for SDK instances -
packages/opencode/src/util/cache.ts- Add iterator support (from #9141)
Testing
- [x] TypeScript compilation passes (
bun turbo typecheck) - [x] Unit tests pass (725 tests, 0 failures)
- [x] Instance/project tests pass
Note: Manual plugin disposal testing was not performed. This requires creating a test plugin with cleanup logic and verifying it's called.
Stacking
This PR includes commits from #9141 (LRU cache utility). After #9141 is merged, this PR can be rebased to only include the disposal-specific changes.