feat(remote): Implement phase 1 for ZooCode remote control#683
feat(remote): Implement phase 1 for ZooCode remote control#683navedmerchant wants to merge 5 commits into
Conversation
…rface (#650) Add packages/remote-bridge, a standalone forked Node process that connects to the Zoo Code extension's IPC server (the API surface) over a Unix socket using the same IpcClient the CLI uses. Phase 1 scope (issue #650): - Bridge class wraps IpcClient: connect(), sendCommand(), onEvent(), request() (send a TaskCommand and await the matching TaskEvent response), plus getModes()/getCommands()/getModels()/sendMessage() helpers. - main.ts is the forked process entry point (CLI) that connects to a socket (defaulting to ROO_CODE_IPC_SOCKET_PATH) and runs a single API call, pretty-printing the response. - Integration test stands up a real IpcServer with a mock command handler (mirroring src/extension/api.ts) and proves the round-trip: connect -> Ack -> GetModes -> ModesResponse, plus event forwarding and request timeout. - scripts/demo.ts forks main.ts as a real child process against a mock server to demonstrate the live API call end-to-end. Verified: check-types, lint, and 3/3 vitest tests pass; live demo prints the modesResponse payload from a forked child process. Later phases will forward this IPC traffic over a WebRTC data channel.
…rom extension (#650) Wire the Phase 1 bridge into the extension so it can be toggled from Zoo Code preferences instead of requiring the ROO_CODE_IPC_SOCKET_PATH env var. Extension changes: - Add zoo-code.remoteControl.enabled and zoo-code.remoteControl.socketPath settings to src/package.json contributes.configuration (+ package.nls.json). - src/extension.ts now starts the IpcServer when the setting is on OR the env var is set, and forks the bridge in --serve mode via RemoteBridgeHost when the setting is on. A config-change listener hot-toggles start/stop without a restart; deactivate() disposes the host. - Add RemoteBridgeHost (src/services/remote-bridge): owns the forked bridge lifecycle with crash-restart backoff, pipes child stdout/stderr to the output channel. Fork impl is injectable for unit tests (7 tests). - Bundle the bridge as a separate esbuild entry to dist/remote-bridge/main.js so the extension can child_process.fork it from the VSIX. Bridge changes: - main.ts gains a long-running --serve mode (the mode the extension forks): connects and streams every TaskEvent to stdout as newline-delimited JSON. One-shot mode is unchanged. - scripts/serve-demo.ts forks the bundled bridge against a mock IPC server and verifies an event streams end-to-end. Verified: src + remote-bridge check-types/lint clean; RemoteBridgeHost 7/7 and bridge 3/3 tests pass; live serve-demo prints the streamed taskStarted ndjson from a forked bundled bridge process.
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Closing as I am going to do it in a different way that scales better |
Related GitHub Issue
Closes: #682
Description
This PR implements Phase 1 of the Remote Control & Approval feature: a forked Node.js bridge process that connects to the Zoo Code extension's IPC API surface over a Unix socket, plus the extension-side wiring to opt into it from the SettingsView.
What Phase 1 delivers:
@zoo-code/remote-bridgeworkspace package containing aBridgeclass that owns anIpcClientand can issue anyTaskCommand(e.g.GetModes,GetCommands,SendMessage) and receive the matchingTaskEventresponses.main.ts) with two modes: a one-shot mode that runs a single API call and prints the response, and a long-running--servemode (the mode the extension forks) that stays connected and streams everyTaskEventto stdout as newline-delimited JSON. Phase 2 will replace this stdout line with a WebRTC data channel write.RemoteBridgeHost, which forks the bundled bridge (dist/remote-bridge/main.js) in--servemode, pipes its output to the Zoo Code output channel, and restarts it with exponential backoff after unexpected crashes (up tomaxRestarts).RemoteControlSettings.tsx) with an enable checkbox and an optional socket path field, persisted through the ContextProxy /GlobalSettingsasremoteControlEnabled/remoteControlSocketPath.webviewMessageHandlerupdateSettingshandler persists the new values and firesClineProvider#onRemoteControlChange, whichsrc/extension.tssubscribes to in order to start/stop/restart the IPC server and forked bridge.dist/remote-bridge/main.jsby a new esbuild context insrc/esbuild.mjs.Key design choices:
remoteControlEnabledis on. The legacyROO_CODE_IPC_SOCKET_PATHenv var still starts the IPC server for headless/CLI use but does not auto-fork the bridge.IpcClientthe CLI uses, so it speaks the exact same API contract — no new protocol surface.RemoteBridgeHost's fork implementation is injectable (ForkFn), enabling unit testing of the lifecycle/restart logic without spawning real processes.@zoo-code/remote-bridgeto reflect that it's a Zoo Code library.What Phase 1 does NOT do (later phases): WebRTC data channel, signaling, remote UI, push notifications.
Test Procedure
Unit tests — RemoteBridgeHost lifecycle (
src):Covers: fork in
--servemode with socket path, no double-fork when already running,stop()kills child + cancels restarts, crash-restart with exponential backoff, giving up aftermaxRestarts,restart()re-forks against the same socket, and stdout/stderr piping to the logger.Integration tests — Bridge IPC round-trip (
packages/remote-bridge):Stands up a real
IpcServeron a temporary socket and verifies theBridgecan: connect and receive itsAck, issueGetModesand receive theModesResponseevent, forward broadcastTaskEvents toonEventsubscribers (and unsubscribe correctly), and rejectrequest()on timeout when no response arrives.Extension host tests (
src):Verifies
getStateToPostToWebviewreturns/defaults theremoteControl*values, and that theupdateSettingshandler persists them and callsnotifyRemoteControlChange(and does not notify for unrelated settings).Webview UI tests (
webview-ui):Verifies the enable checkbox renders, the socket path input only appears when enabled, and
setCachedStateFieldis called on toggle/input change.Live demos (manual smoke test):
Pre-Submission Checklist
Screenshots / Videos
Documentation Updates
packages/remote-bridge/README.mddocuments the bridge architecture, usage (library + CLI), enabling from Zoo Code preferences, scripts, and tests. User-facing docs for the Remote Control settings tab should be added to the docs repository.Additional Notes
dist/remote-bridge/main.js) and runs as its own Node process, not in the extension host —vscodeis marked external for that bundle.knip.jsonwas updated to includeremote-bridgein the workspace package group.remoteControlSocketPathsetting →ROO_CODE_IPC_SOCKET_PATHenv var → per-user default/tmp/zoo-code-<uid>.sock.--servewire format (ndjson on stdout) is intentionally a Phase 1 placeholder; Phase 2 will swap it for a WebRTC data channel forward.Get in Touch