- Add panel-stream-investigation.md documenting dead end - Update KNOWN_ISSUES: move polling and panel stream to resolved - Update GEMINI.md with standalone LS section and new MITM setup - Fix standalone-ls-todo to reflect default mode
3.0 KiB
Panel Stream Investigation — Dead End
Summary
Investigated StreamCascadePanelReactiveUpdates RPC as a potential source for
progressive thinking text. Result: dead end. The panel state only contains
UI metadata (plan_status, user_settings), not thinking content.
What We Tried
1. Subscribe with Cascade ID
Attempted to subscribe to StreamCascadePanelReactiveUpdates using the cascade
ID as the reactive component identifier:
{ "protocolVersion": 1, "id": "<cascade-id>" }
Result: "reactive component <cascade-id> not found"
2. Retry with Delays
Added retry logic (3 attempts, 500ms/1s/1.5s delays) to handle the possibility that the panel state is created asynchronously after cascade start.
Result: Same error on all attempts. The panel state uses a different identifier than the cascade ID.
3. InitializeCascadePanelState Analysis
Examined the RPC that creates panel state:
await this.client.initializeCascadePanelState({ metadata: e, userStatus: t });
Takes workspace metadata + user status, not cascade ID. Panel state is workspace-scoped, not cascade-scoped.
CascadePanelState Proto Definition
exa.cortex_pb.CascadePanelState:
field 1: plan_status (PlanStatus)
field 2: user_settings (UserSettings)
Only 2 fields — neither contains thinking text.
Where Thinking Text Actually Lives
Thinking text flows through StreamCascadeReactiveUpdates (the cascade
reactive diffs that we already subscribe to):
CascadeState (jetski_cortex_pb)
└─ field 2: trajectory (gemini_coder.Trajectory)
└─ field 2: steps[] (gemini_coder.Step)
└─ field 20: planner_response (CortexStepPlannerResponse)
├─ field 1: response (string — streams progressively)
├─ field 3: thinking (string — raw thinking text)
├─ field 8: modified_response (string)
└─ field 11: thinking_duration (Duration)
Observed Behavior (gemini-3-flash)
- Thinking text arrives as a single atomic diff (341 chars, one shot)
- Response text streams progressively across many diffs (26 → 1796 chars)
- Total diffs per request: ~20
Current Proxy Approach
The proxy already captures thinking text correctly through polling
GetCascadeTrajectory + extract_thinking_content(). No reactive diff
parsing needed for current functionality.
Future: Progressive Thinking for Extended-Thinking Models
For Opus models with extended thinking, the thinking text might arrive progressively across multiple reactive diffs. If needed:
- Parse reactive diff JSON for field 3 changes within field 20
- Diff the thinking text between updates for incremental deltas
- Emit
response.reasoning_summary_text.deltaevents as thinking grows
Cleanup
- Removed
stream_cascade_panel_updates()frombackend.rs - Removed panel stream subscription + retry code from
responses.rs StreamCascadeReactiveUpdates(cascade diffs) is still used for real-time notification of state changes (with polling as fallback)