Repository navigation
Conversation
Wire V2 session deletion to PTY cleanup and return SDK-typed teardown from PluginV2.setup. Dispose V1 servers on unload; keep PTYs alive across plugin reloads. The V2 cleanup only aborts the event subscription. The server and the PTYs it shows are shared by every location in the process, and the host unloads a location after an hour without session events, so stopping the server there would kill the web UI of the other locations while the PTYs keep running.
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
The plugin misses its cleanup in two places. In V2, deleting a session leaves its PTYs running because nothing listens for
session.deleted. In V1, unloading the plugin leaves the PTY web server running and its origin record on disk because the plugin has nodisposehook.In plain terms: delete a session in OpenCode 2 and the terminals it started keep running. When the host unloads the V1 plugin, its web server and published address stay behind. Now deleting a V2 session cleans up its terminals, and unloading V1 shuts its server down.
Cause
session.deletedin itseventhook (src/plugin.ts:72) and callsadapter.onSessionDeleted, which runsmanager.cleanupBySession. The V2 adapter has the same method and nothing calls it.PTYServeralready implements[Symbol.dispose]: it stops the server, closes the callback manager and removes the origin record. V1 never called it.PluginV2.setupwas typedPromise<void> | void, so it could not return a teardown callback.Changes
plugin.ts(V1):dispose: async () => ptyServer?.[Symbol.dispose](). PTYs are left alone.v2/index.ts: subscribe toctx.eventwith anAbortControllerand calladapter.onSessionDeleted(event.data.sessionID)for eachsession.deleted.setupreturns() => events.abort(). A subscription failure is logged unless the abort caused it.v2/types.ts: addeventtoPluginContextV2and type the return ofsetupafter the SDK'sPlugin.setup.The V2 teardown only aborts the subscription and does not stop the server. The server and the PTYs it lists are shared by every location in the process, and the host unloads a location after an hour without session events. Stopping the server there would take the web UI down for PTYs that are still running.
Behavior changes
Validation
Three new tests in
test/plugin-lifecycle.test.ts: V1disposeremoves the origin record, V2session.deletedcleans the PTYs of that session, and V2 teardown aborts the subscription and leaves the shared server running. All three fail on main.Three mutations each fail one test: removing
dispose, ignoringsession.deletedin V2, and returning a no-op teardown in V2.bun testovertest/*.test.ts, without the npm-pack and live suites, gives 187 passing.bun run typecheck,bun run lintandbunx biome format .are clean. The CI workflow passes on this commit in my fork, including the Playwright e2e. I did not delete a session or unload the plugin in a live host.Diff
Production: +19 lines (+20/-1) in
src/plugin.ts,src/v2/index.tsandsrc/v2/types.ts.Tests: +89 lines, one new file (
test/plugin-lifecycle.test.ts).