Overview
Implement the HTTP REST client and WebSocket manager for communicating with ppg serve.
REST Client (client.rs)
Uses reqwest with Bearer token auth. All 13 endpoints consumed by the macOS app:
| Method |
Path |
Returns |
| GET |
/api/status |
Full manifest JSON |
| GET |
/api/worktrees/:id |
Single worktree |
| GET |
/api/worktrees/:id/diff |
Git diff stats |
| GET |
/api/agents/:id/logs?lines=N |
Raw tmux capture |
| GET |
/api/config |
Session config |
| GET |
/api/templates |
Template file names |
| GET |
/api/prompts |
Prompt file names |
| GET |
/api/swarms |
Swarm names |
| POST |
/api/spawn |
Spawn worktree + agents |
| POST |
/api/agents/:id/send |
Send keys to agent |
| POST |
/api/agents/:id/kill |
Kill agent |
| POST |
/api/agents/:id/restart |
Restart agent |
| POST |
/api/worktrees/:id/merge |
Merge worktree |
| POST |
/api/worktrees/:id/kill |
Kill all agents |
| POST |
/api/worktrees/:id/pr |
Create GitHub PR |
WebSocket Client (websocket.rs)
Uses tokio-tungstenite. Connects to /ws?token=<token>.
Server Events to Handle
manifest_updated → full manifest snapshot
agent_status_changed → { agentId, status }
worktree_status_changed → { worktreeId, status }
terminal:output → { agentId, data } (terminal streaming)
pong → heartbeat response
error → { code, message }
Client Commands to Send
{ type: "ping" } — keepalive (every 30s)
{ type: "subscribe", channel: "terminal:<agentId>" }
{ type: "unsubscribe", channel: "terminal:<agentId>" }
{ type: "terminal_input", agentId, data } — keyboard input relay
Reconnection
Exponential backoff: base 1s, max 30s. Track connection state (Disconnected/Connecting/Connected/Reconnecting(attempt)).
GTK Thread Integration
WebSocket runs on tokio runtime. Events dispatched to GTK main thread via glib::MainContext::channel:
let (tx, rx) = glib::MainContext::channel(glib::Priority::DEFAULT);
tokio::spawn(ws_loop(url, token, tx));
rx.attach(None, move |event| {
// Update AppState on GTK main thread
glib::ControlFlow::Continue
});
References
- Server implementation:
src/server/index.ts, src/server/routes/, src/server/ws/
- iOS WebSocket:
ios/PPGMobile/PPGMobile/Networking/WebSocketManager.swift
- macOS WebSocket:
PPG CLI/PPG CLI/WebSocketManager.swift
Acceptance Criteria
Overview
Implement the HTTP REST client and WebSocket manager for communicating with
ppg serve.REST Client (client.rs)
Uses
reqwestwith Bearer token auth. All 13 endpoints consumed by the macOS app:/api/status/api/worktrees/:id/api/worktrees/:id/diff/api/agents/:id/logs?lines=N/api/config/api/templates/api/prompts/api/swarms/api/spawn/api/agents/:id/send/api/agents/:id/kill/api/agents/:id/restart/api/worktrees/:id/merge/api/worktrees/:id/kill/api/worktrees/:id/prWebSocket Client (websocket.rs)
Uses
tokio-tungstenite. Connects to/ws?token=<token>.Server Events to Handle
manifest_updated→ full manifest snapshotagent_status_changed→{ agentId, status }worktree_status_changed→{ worktreeId, status }terminal:output→{ agentId, data }(terminal streaming)pong→ heartbeat responseerror→{ code, message }Client Commands to Send
{ type: "ping" }— keepalive (every 30s){ type: "subscribe", channel: "terminal:<agentId>" }{ type: "unsubscribe", channel: "terminal:<agentId>" }{ type: "terminal_input", agentId, data }— keyboard input relayReconnection
Exponential backoff: base 1s, max 30s. Track connection state (Disconnected/Connecting/Connected/Reconnecting(attempt)).
GTK Thread Integration
WebSocket runs on tokio runtime. Events dispatched to GTK main thread via
glib::MainContext::channel:References
src/server/index.ts,src/server/routes/,src/server/ws/ios/PPGMobile/PPGMobile/Networking/WebSocketManager.swiftPPG CLI/PPG CLI/WebSocketManager.swiftAcceptance Criteria