feat: unify all links on WebSocket+Protobuf (v2), deprecate v1#144
Merged
Conversation
…nned versions - buf.yaml/buf.gen.yaml replace raw protoc; make proto-check adds lint+breaking gates - .golangci.yml baseline; CI gains lint step and wider proto drift gate - stdlib log -> log/slog; internal/observability adds logging setup and v1/v2 protocol usage counters (exposed later via /api/status) - mise.toml (tracked) pins go/buf/protoc/golangci-lint/node/pnpm; CI matches
unchecked defers, unused symbols, ineffectual assignment, staticcheck simplifications; no behavior change
- proto/v2/gateway_ws.proto: hello handshake, browser/agent/terminal frame
shells, gateway-local payloads; v1 messages stay the three-end source of truth
- deprecate service AgentGateway (option deprecated); CancelChatRequest gains run_id
- Rust build.rs compiles both packages as gateway_proto::{v1,v2} with proto alias
- internal/transport/wscore: priority dual-queue write pump, shedding, retries, heartbeat, idle eviction (behavior-identical port, tests moved) - internal/protocol/shared: origin check, terminal gating/finalize, interest tracker - internal/chatcmd: chat command orchestration (normalize/probe/dispatch/watchdog) - session.AwaitUnaryResponse: shared unary request/response primitive - v1 server rewired onto the shared pieces; behavior unchanged
- internal/protocol/pbws: browser link (envelope passthrough with whitelist guard and per-connection request-id namespacing, local chat/status/workspace ops, nine broadcast fanouts, snapshot replay), agent link (replaces gRPC Authenticate+AgentConnect), terminal link (proto frames for both roles) - routes mounted beside v1; /api/status exposes protocol_usage counters - integration suite incl. full binary browser<->gateway<->agent path; encode benchmark: ~47x faster, 52% smaller than v1 JSON shaping
- /ws/v2 with liveagent.v2.pb subprotocol; protoc-gen-es generated codecs (web/src/lib/proto/gen) plus adapters restoring v1-shaped app payloads (single bigint boundary, oneof dispatch) - terminal client moves to /ws/v2/terminal proto frames, replacing the custom binary framing; public client API unchanged - v1 wire internals deleted (embedded WebUI is lockstep with the gateway); tests rewritten for binary frames + new adapter unit tests
…ol badge - ws_transport: URL derivation (UI port box applied), subprotocol handshake, handshake-vs-auth error classification; serve loop keeps dual-lane merge, reconciliation and backoff; liveness watchdog replaces h2 keepalive - fallback to deprecated v1 gRPC only on handshake-level failure; fallback sessions redial v2 after 10min so transient blips never pin v1 - terminal stream rides /ws/v2/terminal; tokio-tungstenite gains rustls TLS - status snapshot carries protocol; settings page shows Connected (v2)/(v1)
…ounters - Go 'Deprecated:' markers on the JSON WebSocket server, route table, all domain handlers, payload shaping, terminal stream, and gRPC service - v1 connections/requests increment protocol_usage counters and log WARN, so operators can watch v1 traffic reach zero before removal - command-queue-timeout flag becomes a documented no-op
SendToAgent, RegisterStream, SendToAgentOrQueue and the offline command queue had no production callers (queue enqueue was unreachable); tests migrate to the context-aware variants
- protocols.md rewritten around the unified WebSocket+Protobuf links, v1 kept as a deprecated appendix; gateway/webui/gui/overview updated - new protocol-v2-migration.md: skew matrix, zero-traffic criteria, step-by-step v1 removal checklist - development.md: gateway layering map, capability-addition walkthrough, deprecation conventions, lint/proto-check commands
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
Unifies every realtime link on a single WebSocket+Protobuf protocol (v2) and deprecates the dual v1 stack (browser JSON WebSocket + desktop gRPC). Business messages in
proto/v1/gateway.protoremain the single source of truthfor all three ends; v2 only adds frame shells around them (
proto/v2/gateway_ws.proto).Problem
types that had already drifted (inconsistent key casing, dual-case compat fields).
log, unpinned codegen toolchain.Protocol v2
/ws/v2(browser),/ws/v2/agent(desktop, replacesAuthenticate+AgentConnect),/ws/v2/terminal(both roles, replaces the custom binary framing andAgentTerminalConnect). Subprotocolliveagent.v2.pb; one proto message per binary WS frame; first frame isClientHello(constant-time token check, close 4401 on reject).GatewayEnvelopepassthrough behind a whitelist guard (pbws/guard.go, inheriting the v1 route table's security role) with per-connection request-id namespacing; nine broadcast fanoutsforward session-layer seam messages with zero shaping.
internal/transport/wscorebyte-identical and shared by v1/v2. Reconnect/replaysemantics (
after_seq/stream_epoch, snapshot replay, command dedupe) are unchanged.Settings page badge shows Connected (v2)/(v1).
Compatibility & removal path
/ws; old desktops keep working on gRPC; new desktop ↔ old gateway falls back automatically. Embedded WebUI is lockstep with the gateway.Deprecated:markers (Go/Rust/TS/proto) and runtime counters:/api/status→protocol_usageplus WARN logs on v1 connections. Removal checklist and zero-traffic criteria:docs/architecture/protocol-v2-migration.md.Toolchain
make proto-check= lint + breaking vs origin/main, CI drift gate widened to all generated dirs); golangci-lint baseline fixed and gated in CI; stdlib log →log/slog; trackedmise.tomlpins go/buf/protoc/golangci-lint/node/pnpm to the exact CI versions.Performance (measured,
websocket_payload_bench_test.go, 50-conversation history.list)Desktop link performance is unchanged by design (it was already protobuf over gRPC); its win is one transport/port and simpler self-hosting.
Test plan
go test ./...all green, incl. new v2 integration suite (hello auth, passthrough roundtrip + guard, chat command orchestration, terminal gating, full binary browser↔gateway↔agent path) and-race -count=3onv2/transport packages
golangci-lint run ./...— 0 issues;buf lint+buf breaking+ generated-code drift check cleancargo check --testsclean; gateway suite 53 passed (incl. 9 ws_transport tests: URL/port derivation, handshake-vs-auth classification, mock-server hello+envelope roundtrip); chat_history 43 passedprotocol_usage: v2_browser active, 1200+ requests), desktop connects via/ws/v2/agent(v2_agent_active=1, v1 counters flat at 0), v1 fallback exercisedagainst the pre-v2 gateway build and auto-upgraded back to v2 after the retry window