~cytrogen/gstack

ref: 9c5f479745acc90533a7ff75a00771b9056c43ef gstack/docs/designs/CONDUCTOR_SESSION_API.md -rw-r--r-- 3.9 KiB
9c5f4797 — Cytrogen fork: 频率分级路由 + 触发式描述符重写 2 days ago

#Conductor Session Streaming API Proposal

#Problem

When Claude controls your real browser via CDP (gstack $B connect), you look at two windows: Conductor (to see Claude's thinking) and Chrome (to see Claude's actions).

gstack's Chrome extension Side Panel shows browse activity — every command, result, and error. But for full session mirroring (Claude's thinking, tool calls, code edits), the Side Panel needs Conductor to expose the conversation stream.

#What this enables

A "Session" tab in the gstack Chrome extension Side Panel that shows:

  • Claude's thinking/content (truncated for performance)
  • Tool call names + icons (Edit, Bash, Read, etc.)
  • Turn boundaries with cost estimates
  • Real-time updates as the conversation progresses

The user sees everything in one place — Claude's actions in their browser + Claude's thinking in the Side Panel — without switching windows.

#Proposed API

#GET http://127.0.0.1:{PORT}/workspace/{ID}/session/stream

Server-Sent Events endpoint that re-emits Claude Code's conversation as NDJSON events.

Event types (reuse Claude Code's --output-format stream-json format):

event: assistant
data: {"type":"assistant","content":"Let me check that page...","truncated":true}

event: tool_use
data: {"type":"tool_use","name":"Bash","input":"$B snapshot","truncated_input":true}

event: tool_result
data: {"type":"tool_result","name":"Bash","output":"[snapshot output...]","truncated_output":true}

event: turn_complete
data: {"type":"turn_complete","input_tokens":1234,"output_tokens":567,"cost_usd":0.02}

Content truncation: Tool inputs/outputs capped at 500 chars in the stream. Full data stays in Conductor's UI. The Side Panel is a summary view, not a replacement.

#GET http://127.0.0.1:{PORT}/api/workspaces

Discovery endpoint listing active workspaces.

{
  "workspaces": [
    {
      "id": "abc123",
      "name": "gstack",
      "branch": "garrytan/chrome-extension-ctrl",
      "directory": "/Users/garry/gstack",
      "pid": 12345,
      "active": true
    }
  ]
}

The Chrome extension auto-selects a workspace by matching the browse server's git repo (from /health response) to a workspace's directory or name.

#Security

  • Localhost-only. Same trust model as Claude Code's own debug output.
  • No auth required. If Conductor wants auth, include a Bearer token in the workspace listing that the extension passes on SSE requests.
  • Content truncation is a privacy feature — long code outputs, file contents, and sensitive tool results never leave Conductor's full UI.

#What gstack builds (extension side)

Already scaffolded in the Side Panel "Session" tab (currently shows placeholder).

When Conductor's API is available:

  1. Side Panel discovers Conductor via port probe or manual entry
  2. Fetches /api/workspaces, matches to browse server's repo
  3. Opens EventSource to /workspace/{id}/session/stream
  4. Renders: assistant messages, tool names + icons, turn boundaries, cost
  5. Falls back gracefully: "Connect Conductor for full session view"

Estimated effort: ~200 LOC in sidepanel.js.

#What Conductor builds (server side)

  1. SSE endpoint that re-emits Claude Code's stream-json per workspace
  2. /api/workspaces discovery endpoint with active workspace list
  3. Content truncation (500 char cap on tool inputs/outputs)

Estimated effort: ~100-200 LOC if Conductor already captures the Claude Code stream internally (which it does for its own UI rendering).

#Design decisions

Decision Choice Rationale
Transport SSE (not WebSocket) Unidirectional, auto-reconnect, simpler
Format Claude's stream-json Conductor already parses this; no new schema
Discovery HTTP endpoint (not file) Chrome extensions can't read filesystem
Auth None (localhost) Same as browse server, CDP port, Claude Code
Truncation 500 chars Side Panel is ~300px wide; long content useless