Skip to content

Add Claude/Codex agents support with WebSocket transport#13

Merged
axeldelafosse merged 4 commits intomainfrom
feat/claude-agent-websocket-transport
Feb 23, 2026
Merged

Add Claude/Codex agents support with WebSocket transport#13
axeldelafosse merged 4 commits intomainfrom
feat/claude-agent-websocket-transport

Conversation

@axeldelafosse
Copy link
Copy Markdown
Owner

Summary

  • Claude as a first-class agent: New claude-sdk-server.ts communicates with Claude via the SDK stream-json protocol over WebSocket. Includes a Bun-based relay server that frontend observers can connect to via /ws for real-time session monitoring.
  • WebSocket transport for codex app-server: Replaces stdin/stdout pipe communication with WebSocket transport using dynamic port allocation (--listen flag). Adds a minimal raw TCP WebSocket client (ws-client.ts) to work around Bun's built-in WS client incompatibility with codex app-server.
  • Strict review signal parsing: Complete rewrite of review output evaluation. Signals must appear on the final non-empty line (with optional quoting). Mixed pass/fail, malformed, missing, and trailing-content signals are all detected and produce deterministic error messages.
  • Simplified main loop: Non-zero exit codes always throw (even when the done signal is present). Cleaner follow-up formatting with failureCount on ReviewResult. Proper readline cleanup via finally block.
  • Port utilities: findFreePort and isPortTaken helpers in ports.ts used by both codex and claude server clients.
  • Model passthrough: The configured model is now forwarded to codex thread creation instead of null.

Test plan

  • All 203 existing tests pass
  • bun run check passes (lint, types, formatting)
  • Manual smoke test: run loop with --agent codex to verify WebSocket transport
  • Manual smoke test: run loop with --agent claude to verify SDK integration

…ignal parsing

- Add Claude as a first-class agent via claude-sdk-server using the SDK stream-json protocol over WebSocket, with a relay server for frontend observers
- Switch codex app-server from stdin/stdout pipes to WebSocket transport with dynamic port allocation via --listen flag
- Add minimal raw TCP WebSocket client (ws-client) to work around Bun's built-in WS client incompatibility with codex app-server
- Add port utility (ports.ts) with isPortTaken/findFreePort helpers
- Rewrite review signal parsing to require signals on the final non-empty line, detect mixed/malformed/trailing signals, and produce deterministic error messages
- Simplify main loop: always error on non-zero exit codes, cleaner follow-up formatting, proper readline cleanup
- Pass model through to codex thread creation
- Add failureCount to ReviewResult for better follow-up formatting
@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello @axeldelafosse, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the agent interaction framework by integrating Claude as a new agent type and migrating the Codex app-server to a more robust WebSocket-based communication. These changes improve real-time feedback, streamline agent-to-system communication, and introduce stricter parsing rules for review outcomes, leading to a more reliable and extensible system for automated development workflows.

Highlights

  • Claude Agent Support: Introduced a new claude-sdk-server.ts to enable Claude as a first-class agent, communicating via its SDK's stream-json protocol over WebSocket. This includes a Bun-based relay server for real-time session monitoring by frontend observers.
  • WebSocket Transport for Codex App-Server: Replaced the existing stdin/stdout pipe communication with WebSocket transport for the codex app-server, utilizing dynamic port allocation. A minimal raw TCP WebSocket client (ws-client.ts) was added to address Bun's built-in WS client incompatibilities.
  • Strict Review Signal Parsing: Implemented a complete rewrite of the review output evaluation, requiring review signals to appear on the final non-empty line (with optional quoting). This change ensures deterministic error messages for mixed pass/fail, malformed, missing, or trailing-content signals.
  • Simplified Main Loop Logic: Refactored the main loop to ensure non-zero exit codes always throw errors, even when a done signal is present. Improved follow-up formatting with failureCount on ReviewResult and added proper readline cleanup.
  • Port Utility Functions: Added new utility functions (findFreePort and isPortTaken) in ports.ts to facilitate dynamic port allocation for both Codex and Claude server clients.
  • Model Passthrough: Ensured that the configured model is now correctly forwarded to Codex thread creation instead of being passed as null.
Changelog
  • biome.jsonc
    • Updated Biome configuration to disable noBitwiseOperators and noExcessiveCognitiveComplexity rules for src/loop/ws-client.ts.
  • src/loop.ts
    • Imported closeClaudeSdk for proper cleanup.
    • Modified the finally block in runCli to close both closeAppServer and closeClaudeSdk concurrently.
  • src/loop/claude-sdk-server.ts
    • Added new file to implement Claude SDK server, managing WebSocket communication with the Claude SDK.
    • Included logic for starting, running turns, interrupting, and closing the Claude SDK process.
    • Implemented message handling for various Claude SDK stream events and control requests.
    • Provided utilities for broadcasting messages to frontend observers.
  • src/loop/codex-app-server.ts
    • Imported findFreePort for dynamic port allocation.
    • Added constants for WebSocket connection attempts and delays.
    • Introduced ConnectWsFn type and connectWsFn variable for WebSocket client injection.
    • Modified AppServerClient to use a WebSocket client (ws) instead of direct stdin/stdout for communication.
    • Updated start method to find a free port, launch the app server with a listen URL, and connect via WebSocket.
    • Implemented findPort and connectWebSocket methods for port discovery and WebSocket connection management.
    • Modified close method to properly close the WebSocket connection.
    • Updated ensureThread method to pass the configured model to the METHOD_THREAD_START request.
    • Changed sendRequest and sendResponse to use sendFrame for WebSocket communication.
    • Added sendFrame method to abstract sending data over WebSocket or stdin.
    • Updated handleUnexpectedExit to close the WebSocket connection.
  • src/loop/main.ts
    • Refactored doneSignalText, doneSignalMissingText, doneSignalPassedText, and doneSignalExitText into doneText and formatFollowUp.
    • Modified runIterations to strictly throw an error if an agent exits with a non-zero code, even if a done signal is present.
    • Updated review follow-up logic to use formatFollowUp for clearer messaging based on failureCount and consensusFail.
    • Removed hasExistingPr parameter from runIterations and runDraftPrStep.
    • Refactored the main runLoop to use a try...finally block for readline cleanup and simplified interactive follow-up prompting.
  • src/loop/ports.ts
    • Added new file containing isPortTaken and findFreePort utility functions for managing network ports.
  • src/loop/prompts.ts
    • Updated buildReviewPrompt to include stricter instructions for review signals, emphasizing exact signal text, final non-empty line placement, and content restrictions.
  • src/loop/review.ts
    • Imported NEWLINE_RE for consistent line splitting.
    • Added new constants for various review signal parsing error messages.
    • Introduced ReviewSignal, ReviewCheck, and ReviewSignalSummary types for structured review output evaluation.
    • Implemented cleanOutput, parseSignal, splitOutputLines, getFinalNonEmptyLine, collectSignalPresence, and lineContainsReviewSignalToken for robust signal parsing.
    • Added parseSignalSummary to consolidate signal extraction logic.
    • Implemented reasonFromFailureOutput, formatFailure, and formatUnknownError for consistent error reporting.
    • Rewrote runReviewWith to use the new strict signal parsing logic, handling cases like mixed signals, missing signals, malformed signals, and trailing content.
    • Added failureCount to the ReviewResult interface.
  • src/loop/runner.ts
    • Imported Claude SDK related functions (hasClaudeSdkProcess, interruptClaudeSdk, runClaudeTurn, startClaudeSdk).
    • Added activeClaudeSdkRuns counter for tracking active Claude SDK processes.
    • Updated onSigint and onSigterm to interrupt interruptClaudeSdk.
    • Modified syncSignalHandlers to include activeClaudeSdkRuns and hasClaudeSdkProcess in determining if signal handlers are needed.
    • Added runClaudeAgent function to handle execution of the Claude agent, including starting the SDK, running turns, and managing output streams.
    • Extended runAgent to dispatch to runClaudeAgent when the agent is 'claude'.
  • src/loop/types.ts
    • Added failureCount: number; to the ReviewResult interface to track the number of failed reviews.
  • src/loop/utils.ts
    • Added ReviewDecisionLike type for flexible review decision parsing.
    • Introduced APPROVED_STATUSES and REQUEST_CHANGES_STATUSES sets for normalizing review status strings.
    • Implemented isObject, parseStatusValue, and parseStatusFromRecord for robust parsing of review status from various data structures.
    • Defined ReviewDecision interface and normalizeReviewDecision function for consistent review decision handling.
  • src/loop/ws-client.ts
    • Added new file implementing a minimal WebSocket client over raw TCP using Bun.connect, designed to work around Bun's built-in WebSocket client incompatibilities.
    • Included functions for encoding WebSocket frames (text, close, pong) and managing the WebSocket handshake and data processing.
  • tests/loop/codex-app-server.test.ts
    • Added installConnectWs function to mock WebSocket connection for codex-app-server tests.
    • Updated getModule to call installConnectWs.
    • Modified resetState to restore the default connectWsFn.
  • tests/loop/main.test.ts
    • Updated noopReview to include failureCount: 0.
    • Modified test case for agent non-zero exit code to expect an error throw instead of stopping silently.
    • Updated test cases for runDraftPrStep to reflect the removal of the hasExistingPr parameter.
    • Added new test cases for interactive mode, including prompting for follow-up on max iterations and immediate exit on done signal.
    • Adjusted test cases for review notes forwarding to reflect the new failureCount and formatFollowUp logic.
  • tests/loop/prompts.test.ts
    • Updated test for buildReviewPrompt to verify the new strict review signal instructions.
  • tests/loop/review-run.test.ts
    • Updated runReview test expectations to include failureCount.
    • Added comprehensive test cases for strict review signal parsing, including mixed PASS/FAIL, missing signals, malformed signals, trailing content, quoted signals, and fallback messages.
    • Added tests for runReview to accept pass/fail signals from combined output with body.
    • Added tests for handling reviewer rejections and ensuring deterministic note ordering regardless of completion order.
  • tests/loop/review.test.ts
    • Added makeRunResult and makeOptions helper functions for review tests.
    • Added extensive test cases for createRunReview to cover various scenarios of strict review signal parsing, including valid pass/fail signals, quoted signals, whitespace handling, missing signals, malformed signals, mixed signals, trailing content, and error extraction from failure bodies.
    • Added tests for deterministic note ordering and handling non-zero exit codes or runtime failures from reviewers.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@axeldelafosse axeldelafosse changed the title Add Claude agent support with WebSocket transport Add Claude/Codex agents support with WebSocket transport Feb 23, 2026
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This is a substantial pull request that introduces significant architectural improvements, most notably adding Claude agent support with a WebSocket transport and migrating the existing codex agent to use WebSockets as well. The strict new parsing for review signals is a fantastic change that will improve robustness. The simplification of the main loop and addition of port utilities are also great quality-of-life improvements. My review focuses on a few areas in the new code, including potential race conditions, dead code, and opportunities to improve the robustness of the new networking clients.

Comment thread src/loop/codex-app-server.ts
Comment thread src/loop/claude-sdk-server.ts
Comment thread src/loop/claude-sdk-server.ts
Comment thread src/loop/utils.ts Outdated
Comment thread src/loop/ws-client.ts
… code

- codex-app-server: replace stdout processing in consumeFrames with a
  simple drain, since all JSON-RPC communication now goes through WebSocket
- utils: remove unused normalizeReviewDecision and all related helpers
  (ReviewDecisionLike, APPROVED_STATUSES, REQUEST_CHANGES_STATUSES,
  parseStatusValue, parseStatusFromRecord, isObject, ReviewDecision)
@axeldelafosse axeldelafosse merged commit 93417a1 into main Feb 23, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant