mirror of
https://github.com/ruvnet/RuVector.git
synced 2026-05-25 23:24:03 +00:00
SSE Proxy Decoupling (ADR-130): - Fix ruvbrain-sse proxy: proper MCP handshake, session creation, drain polling - Fix internal queue endpoints: session_create keeps receiver, drain returns buffered messages - Add response_queues to AppState for SSE proxy communication - Skip sparsifier for >5M edge graphs (was crashing on 16M edges) - Add SSE_DISABLED/MAX_SSE env vars for configurable connection limits - Route SSE to dedicated mcp.pi.ruv.io subdomain (Cloudflare CNAME) - Serve SSE at root / path on proxy (no /sse needed) - Update all references from pi.ruv.io/sse to mcp.pi.ruv.io - Fix Dockerfile consciousness crate build (feature/version mismatches) Claude Code CLI Source Research (ADR-133): - 19 research documents analyzing Claude Code internals (3000+ lines) - Decompiler script + RVF corpus builder for all major versions - Binary RVF containers for v0.2, v1.0, v2.0, v2.1 (300-2068 vectors each) - Call graphs, class hierarchies, state machines from minified source Integration Strategy (ADR-134): - 6-tier integration plan: WASM MCP, agents, hooks, cache, SDK, plugin - Integration guide with architecture diagrams and performance targets Co-Authored-By: claude-flow <ruv@ruv.net>
8.3 KiB
8.3 KiB
16 - Call Graphs
Call graphs traced from actual minified source patterns in cli.js (v2.0.62).
Function names shown as minified -> reconstructedName.
1. Main Boot Sequence
graph TD
A["cli.js entry (#!/usr/bin/env node)"] --> B["Parse CLI arguments (process.argv)"]
B --> C{"Mode?"}
C -->|"Interactive REPL"| D["Initialize Ink React app"]
C -->|"--print / -p"| E["SDK non-interactive mode"]
C -->|"MCP server"| F["Start MCP stdio/SSE server"]
C -->|"Sub-command"| G["Route to command handler"]
D --> H["Ll() - createInitialAppState"]
H --> I["gG() - AppStateProvider"]
I --> J["Load settings: qq()"]
J --> K["Load permissions: xC()"]
K --> L["Initialize MCP clients"]
L --> M["Load plugins"]
M --> N["LoA() - resolveThinkingEnabled"]
N --> O["Render main React component"]
O --> P["Wait for user input"]
E --> Q["Build SDK context"]
Q --> R["JP() - prepareQuery"]
R --> S["s$() - agentLoop"]
S --> T["Yield results to SDK caller"]
2. Agent Loop (s$ function)
graph TD
A["s$() entry"] --> B["yield stream_request_start"]
B --> C["Build API params"]
C --> D["qh2() - countTokens"]
D --> E{"Exceeds compact threshold?"}
E -->|Yes| F["Run compaction"]
F --> G["yield system:compact_boundary"]
G --> C
E -->|No| H["d39() - telemetry: tengu_api_query"]
H --> I["Call Anthropic Messages API (streaming)"]
I --> J["Process SSE stream"]
J --> K{"Event type?"}
K -->|"content_block_delta"| L["Accumulate text/tool_use/thinking"]
K -->|"message_stop"| M["yield assistant message"]
M --> N{"Has tool_use blocks?"}
N -->|No| O["yield stop"]
N -->|Yes| P["Process each tool_use"]
P --> Q["Permission check: canUseTool()"]
Q --> R{"Allowed?"}
R -->|Denied| S["yield hookPermissionResult"]
R -->|Ask user| T["Prompt for approval"]
R -->|Allowed| U["tool.validateInput()"]
U --> V{"Valid?"}
V -->|No| W["Return error result"]
V -->|Yes| X["tool.call()"]
X --> Y["yield result"]
Y --> Z["Assemble tool_result messages"]
Z --> AA["yield user (tool results)"]
AA --> AB["yield* s$() RECURSIVE CALL"]
AB --> AC["Continue processing"]
3. Tool Dispatch Flow
graph TD
A["Tool use from API response"] --> B{"Tool name prefix?"}
B -->|"mcp__*"| C["Parse: mcp__server__tool"]
B -->|Built-in| D["Lookup in tools array"]
C --> E["Find MCP client by server name"]
E --> F["MCP callTool(name, args)"]
F --> G["Return MCP result"]
D --> H{"Tool type?"}
H -->|"BashTool"| I["BashTool.call()"]
H -->|"FileReadTool"| J["FileReadTool.call()"]
H -->|"FileEditTool"| K["FileEditTool.call()"]
H -->|"FileWriteTool"| L["FileWriteTool.call()"]
H -->|"Agent"| M["Spawn sub-agent"]
H -->|Other| N["Generic tool.call()"]
I --> I1["Check sandbox config"]
I1 --> I2{"Sandbox enabled?"}
I2 -->|macOS| I3["sandbox-exec -p profile cmd"]
I2 -->|Linux| I4["SOCKS bridge execution"]
I2 -->|Disabled| I5["Direct child_process.exec"]
J --> J1["Validate path permissions"]
J1 --> J2["fs.readFile with offset/limit"]
J2 --> J3["Return content with line numbers"]
M --> M1["Create agent context"]
M1 --> M2["Fork messages if needed: bV0()"]
M2 --> M3["Resolve agent model: JsA()"]
M3 --> M4["yield* mVA() - agent generator"]
M4 --> M5["Runs own s$() loop"]
4. Permission Check Flow
graph TD
A["canUseTool(toolName, input)"] --> B["Get permission context"]
B --> C{"Permission mode?"}
C -->|"bypassPermissions"| D["ALLOW immediately"]
C -->|"dontAsk"| E["ALLOW (agent mode)"]
C -->|"plan"| F["DENY (read-only)"]
C -->|"default"| G["Check rules"]
C -->|"acceptEdits"| H["Allow edits, ask for others"]
G --> I{"Match always-allow rules?"}
I -->|Yes| J["ALLOW"]
I -->|No| K{"Match deny rules?"}
K -->|Yes| L["DENY"]
K -->|No| M{"Is file operation?"}
M -->|Yes| N["tD() - check path permission"]
N --> O{"Path allowed?"}
O -->|"allow"| P["ALLOW"]
O -->|"deny"| Q["DENY"]
O -->|"ask"| R["Prompt user"]
M -->|No| R
R --> S{"User response?"}
S -->|Allow once| T["ALLOW"]
S -->|Allow always| U["Add to always-allow rules"]
S -->|Deny| V["DENY"]
5. MCP Server Lifecycle
graph TD
A["Load MCP config"] --> B{"Config source?"}
B -->|".mcp.json"| C["Read project .mcp.json"]
B -->|"Settings"| D["Read from localSettings"]
B -->|"MCPB"| E["Download + extract MCPB bundle"]
C --> F["Normalize server names: UG()"]
D --> F
E --> F
F --> G{"Transport type?"}
G -->|"stdio"| H["Spawn child process"]
G -->|"sse"| I["HTTP SSE connection"]
G -->|"websocket"| J["WebSocket connection"]
H --> K["Send: initialize"]
I --> K
J --> K
K --> L["Receive: capabilities"]
L --> M["Send: tools/list"]
M --> N["Register tools as mcp__server__tool"]
N --> O["Tool invocation"]
O --> P["Send: tools/call"]
P --> Q["Receive: tool result"]
Q --> R["Return to agent loop"]
K --> S["Send: resources/list"]
S --> T["Register resources"]
R --> U{"Server error?"}
U -->|"Connection lost"| V["Restart MCP server process"]
U -->|"Timeout"| W["k91() - get MCP_TIMEOUT"]
6. Compaction Flow
graph TD
A["Token count check"] --> B{"input_tokens > threshold?"}
B -->|No| C["Continue normally"]
B -->|Yes| D["Start compaction"]
D --> E["Set spinner: compacting"]
E --> F["Call API: querySource='compact'"]
F --> G["Stream summary response"]
G --> H{"Summary valid?"}
H -->|"Empty"| I["tengu_compact_failed: no_summary"]
H -->|"API error prefix"| J["tengu_compact_failed: api_error"]
H -->|"Prompt too long"| K["tengu_compact_failed: prompt_too_long"]
H -->|"Valid"| L["Build new message history"]
L --> M["c12() - refresh readFileState"]
M --> N["Re-read tracked files"]
N --> O["z$('compact') - run SessionStart hooks"]
O --> P["Assemble: summary + boundary + attachments + hooks"]
P --> Q["Track: tengu_compact telemetry"]
Q --> R["Return compacted messages"]
R --> S["Micro-compaction check"]
S --> T{"Stale tool uses?"}
T -->|Yes| U["Remove old tool_use blocks"]
T -->|No| V["Done"]
U --> V
7. Sub-Agent Spawn Flow
graph TD
A["Agent tool invoked"] --> B["mVA() - agent generator"]
B --> C["Resolve model: JsA()"]
C --> D["Create agent ID: vQA()"]
D --> E["Fork context: bV0()"]
E --> F["Build agent system prompt"]
F --> G["Create tool use context: x_A()"]
G --> H{"Agent permission mode?"}
H -->|"Defined on agent"| I["Use agent's permissionMode"]
H -->|"Async agent"| J["Override permission context"]
H -->|"Inherit"| K["Use parent's context"]
I --> L["s$() - run agent's own loop"]
J --> L
K --> L
L --> M["Yield events back to parent"]
M --> N{"Event type?"}
N -->|"assistant"| O["Collect response"]
N -->|"progress"| P["Forward to parent"]
N -->|"user"| Q["Internal to agent"]
8. Slash Command Dispatch
User types /<command>
├── Parse command name and args
├── Look up in commands array
│ ├── /clear → Clear conversation history
│ ├── /compact → Trigger manual compaction
│ ├── /config → Open config panel (React component)
│ ├── /context → Show context usage grid
│ ├── /cost → Show session cost/duration
│ ├── /doctor → Run diagnostics
│ ├── /help → Show help
│ ├── /memory → Edit CLAUDE.md files
│ ├── /mcp → Manage MCP servers
│ ├── /model → Switch model (YI1 component)
│ ├── /plan → View/open session plan
│ ├── /resume → Resume conversation
│ ├── /review → Review pull request
│ ├── /status → Show version, model, account info
│ ├── /vim → Toggle vim mode
│ └── 30+ more commands
├── Execute command handler
│ ├── Some return React components (config, context)
│ ├── Some modify app state (model, vim)
│ └── Some yield messages (compact, review)
└── Return: {newMessages, contextModifier, allowedTools, model}