Zookeeper as a full first-party plugin that can be turned off - #13142
Zookeeper as a full first-party plugin that can be turned off#13142pierremtb wants to merge 1 commit into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
pierremtb
left a comment
There was a problem hiding this comment.
Some notes about the current state.
| <CustomIcon | ||
| name={icon} | ||
| className={`w-5 h-5 ${icon === 'loading' ? 'animate-spin' : ''}`} | ||
| aria-hidden | ||
| /> |
| test('closes screenshot annotation when the pane is hidden', () => { | ||
| const conversationProps = { |
There was a problem hiding this comment.
From Codex:
It’s a regression test for a portal-specific edge case.
Because #13142 keeps the Zookeeper React subtree mounted when its pane closes, the normal unmount cleanup no longer runs. If Zoodle screenshot annotation is active, its overlay is portaled into the viewport and would remain visible after closing Zookeeper.
The test verifies that changing isPaneVisible to false explicitly shuts down that overlay via ZookeeperConversation.tsx.
The duplicated prop fixture is ugly and could be cleaned up, but the behavior itself is necessary while we retain the portal approach.
| @@ -167,6 +158,11 @@ function ZookeeperConversationPaneInner(props: AreaTypeComponentProps) { | |||
| zookeeperManagerActor, | |||
There was a problem hiding this comment.
This is where we better not mess up 😬
| // The registry owns the actor and transport. The portal remains a temporary | ||
| // bridge for the React-based file, history, reconnect, queue, and billing hooks. | ||
| export function createZookeeperRuntime( |
There was a problem hiding this comment.
I think this part from Codex is too complex and I'd like to make it easier to follow before marking ready.
00a8997 to
bb7e7a6
Compare
bb7e7a6 to
a5e1ae4
Compare
Stacked on #12885, which provides the project-session signal used as the non-React lifetime boundary.
Closes #12476. Part of #12583.
Why
The Zookeeper actor, WebSocket, prompt queue, reconnect logic, and file-edit bookkeeping used to be owned by the React pane. Closing the pane unmounted those owners, so an active prompt stopped and reopening required a new connection.
This moves session ownership to the Zookeeper registry runtime. There is no hidden React host or portal: pane visibility now controls only the UI, while disabling the plugin tears down the complete Zookeeper subsystem.
What changed
Review guide
The raw diff is larger than the behavioral change because GitHub cannot recognize hooks and callbacks that were split and converted into non-React classes. Most of the old pane/wrapper orchestration is removed and reappears behind focused interfaces.
src/lib/zookeeper/registry/index.ts— start at the plugin boundary. The plugin contributes the pane runtime directly, so registry enablement activates the subsystem and registry disposal is the full off switch.src/lib/zookeeper/registry/runtime.tsx— the central lifetime policy. The runtime deliberately has no layout dependency: a ready authenticated project starts a controller even if the pane has never opened. Pane visibility and same-project readiness gaps retain it; logout, project-session replacement, a real editor replacement, or plugin disposal stop it. The per-project disposal gate prevents a replacement from overlapping an old asynchronous teardown.src/lib/zookeeper/registry/controller.ts— owns session behavior independently of React. The important additions are serialized prompt submission and revalidation of project, file, editor, and code state after asynchronous collection. Clear, resume, reconnect, and disposal invalidate stale work.ZookeeperFileRequestProcessor.tsandZookeeperEditPatchHistory.ts— extracted file-integrity work. Undispatched stale requests are dropped; already-dispatched writes may settle, but cannot refresh or navigate a replacement project/editor. Undo history waits for both the filesystem write and the terminal exchange.ZookeeperConversationPaneWrapper.tsxandZookeeperConversationPane.tsx— read these last. Their large deletion is intentional: mounting and unmounting them now only affects rendering.zookeeperManagerMachine.ts, SystemIO, layout, and the debug contract — small lifecycle seams for explicit socket shutdown, abortable idle waits, stale-navigation prevention, the running indicator, and the close/reopen E2E probe.Non-obvious behavior and review focus
requestedProjectPathguard is the critical last line of defense here and deserves close review.The most useful executable specifications are
runtime.test.tsfor eager activation and ownership boundaries,controller.test.tsfor queue/clear/resume races, the processor/history tests for teardown during writes, and the Playwright case that asserts the actor and WebSocket identities remain unchanged across pane close/reopen. The SystemIOrequestedProjectPathnavigation guard does not yet have a direct regression test, and plugin disable/re-enable is covered at the runtime level rather than by a whole-app flow.