Rio

Overview & Vision

Status: Draft v1.0, Work in progress Last Updated: November 2025

Github: https://github.com/bhi5hmaraj/rio/tree/main

Executive Summary

Rio is an open-source Chrome Extension that acts as a "Radar Intercept Officer" (RIO/RSO) for AI conversations. While the user (the Pilot) flies the conversation in ChatGPT or other AI interfaces, Rio sits in the back seat (the Chrome Side Panel), actively scanning the chat for hallucinations, bias, and missed nuances.

Rio is a Chrome extension that analyzes web pages and chat conversations in real-time, extracting concepts to build a Concept DAG (Directed Acyclic Graph) rendered in a persistent side-panel HUD. The HUD hosts a React app with CopilotKit (for agent actions) and React Flow (for graph visualization).

Unlike passive tools, Rio is agentic:

Rio operates on a "Bring Your Own Key" (BYOK) model for the core extension, ensuring user privacy and zero infrastructure costs. An optional backend server (open source, self-hostable) provides advanced features like long-term storage, RAG on conversation history, and proactive analysis across all websites.

Problem Statement

Large Language Models (LLMs) like ChatGPT are powerful but prone to:

  1. Hallucinations: Stating falsehoods confidently
  2. Sycophancy: Agreeing with the user even when the user is wrong
  3. Bias: Non-neutral perspectives that go unnoticed
  4. Complexity: Long conversations become difficult to track mentally
  5. Lost Context: Important concepts and relationships get buried in conversation flow

Existing solutions are either:

Core Value Propositions

1. Real-Time AI Critique

2. Concept Visualization

3. Privacy-First Architecture

4. Robust & Non-Invasive

Goals & Non-Goals

Goals

Non-Goals

Target Users

Primary

Secondary

Success Metrics

Adoption

Utility

Quality

Architecture

Status: Draft v1.0 Last Updated: November 2025

System Overview

Rio is built as a Manifest V3 Chrome Extension to bypass CSP limitations and enable a rich UI via the Side Panel API. The architecture follows a "Hybrid" component model with three distinct contexts communicating via the Chrome Runtime API.

The "Hybrid" Component Model

Components & Responsibilities

Component Role Runtime Context Tech Stack Key Responsibilities
Content Script "The Hands" Injected into web page Vanilla TS + @hypothesis/text-quote-selector • Scrape chat text
• Tag DOM elements with stable IDs
• Paint colored highlights on page
• Render tooltips on hover
Side Panel "The Face" Extension page (chrome-extension://) React + CopilotKit + React Flow • Main UI/HUD
• Display Concept DAG
• "Run Critique" triggers
• Manage user settings (API Key)
Background Service Worker "The Brain" Extension background Service Worker (TS) • Orchestrate API calls to Gemini
• Handle chrome.storage encryption/decryption
• Manage global events
• Cross-origin fetch (via host_permissions)
Backend Server (Optional) "The Memory" Self-hosted server FastAPI + PostgreSQL + Vector DB • Long-term annotation storage
• RAG on conversation history
• Proactive analysis queue
• Graph clustering & ML features

Why This Architecture?

  1. Side Panel Isolation

    • Runs in extension context, immune to page CSP/Trusted-Types
    • Allows React, external scripts, and iframes
    • Persistent UI that doesn't interfere with page layout
    • See: Chrome Side Panel API
  2. Content Script Limitations

    • Can read/modify DOM but inherits page CSP
    • Cannot use innerHTML on Gemini (TrustedHTML enforcement)
    • Cannot load external scripts on ChatGPT (CSP blocks)
    • Should be kept minimal and focused on DOM operations only
  3. Background Worker Power

    • Can make cross-origin fetches (via host_permissions)
    • Persistent storage access
    • Can coordinate between multiple tabs/panels
    • Service Worker lifecycle (event-driven, not always running)
  4. Optional Backend Server

    • Extension works fully standalone (local-first)
    • Backend adds: unlimited storage, RAG, proactive analysis
    • Open source, self-hostable (no vendor lock-in)
    • See: Backend Server Design

Data Flow

The "Critique Loop" (Primary Workflow)

┌─────────────┐
│  User       │
│  (clicks    │
│  "Critique")│
└──────┬──────┘
       │
       ▼
┌─────────────────────┐
│  Side Panel (React) │
│  - CopilotKit UI    │
└──────┬──────────────┘
       │ chrome.runtime.sendMessage({action: "critique"})
       ▼
┌──────────────────────┐
│  Background Worker   │
│  - Routes request    │
└──────┬───────────────┘
       │ chrome.tabs.sendMessage({action: "scrape"})
       ▼
┌──────────────────────┐
│  Content Script      │
│  - Scrape chat DOM   │
│  - Extract messages  │
└──────┬───────────────┘
       │ returns {messages: [...]}
       ▼
┌──────────────────────┐
│  Background Worker   │
│  - Call Gemini API   │
│  - With Google Search│
└──────┬───────────────┘
       │ Gemini response: {annotations: [...]}
       ▼
┌──────────────────────┴──────────────┐
│  Background broadcasts to:          │
│  1. Side Panel (for DAG)            │
│  2. Content Script (for highlights) │
└─────────────────────────────────────┘

Message Schemas

See Data Models for detailed schemas.

Content → Background (Scrape Result)

{
  action: "scrapeComplete",
  data: {
    pageId: string,
    url: string,
    messages: Array<{
      id: string,
      role: "user" | "assistant",
      text: string,
      html: string,
      timestamp: number
    }>
  }
}

Background → Side Panel (Analysis Result)

{
  action: "analysisComplete",
  data: {
    dag: {
      nodes: Node[],
      edges: Edge[]
    },
    annotations: Annotation[],
    status: "success" | "error",
    error?: string
  }
}

Background → Content Script (Highlight Command)

{
  action: "applyHighlights",
  annotations: Array<{
    id: string,
    target: {
      messageId: string,
      selector: TextQuoteSelector | TextPositionSelector
    },
    color: "blue" | "green" | "orange" | "red",
    category: "critique" | "factuality" | "sycophancy" | "bias",
    note: string
  }>
}

Manifest V3 Configuration

Required Permissions (Minimal Scope)

{
  "permissions": [
    "sidePanel",      // For the UI
    "storage",        // For API keys and settings
    "activeTab",      // Minimize warnings; only active when clicked
    "scripting"       // To inject content script
  ],
  "host_permissions": [
    "https://generativelanguage.googleapis.com/*",  // Gemini API
    "https://chat.openai.com/*",                    // ChatGPT scraping
    "https://gemini.google.com/*"                   // Gemini scraping
  ],
  "optional_permissions": [
    "http://localhost:*/*"  // For local development/testing
  ]
}

Content Security Policy

The Side Panel (as an extension page) has relaxed CSP and can:

The Content Script inherits the page's CSP and cannot:

Key Modules (Swappable Components)

1. Scraper (Content Script)

Interface:

interface Scraper {
  scrape(): Promise<ScrapedData>;
  detectSite(): "chatgpt" | "gemini" | "claude" | "generic";
}

Implementations:

Output: Linearized text + DOM map (offsets ↔ nodes)

2. AnchorEngine (Content Script)

Built on Hypothesis standards + libraries.

Interface:

interface AnchorEngine {
  createSelector(range: Range): TextQuoteSelector & TextPositionSelector;
  resolveSelector(selector: Selector): Range | null;
}

Libraries:

Features:

See Text Anchoring for details.

3. AnalyzerAdapter (Background Worker)

Interface:

interface AnalyzerAdapter {
  analyze(text: string, options: AnalysisOptions): Promise<AnalysisResult>;
}

Implementations:

Output: Normalized {nodes, edges, annotations}

4. DAGRenderer (Side Panel)

Interface:

interface DAGRenderer {
  render(dag: Graph): void;
  export(format: "svg" | "png" | "json"): Blob;
}

Implementations:

5. CopilotLayer (Side Panel)

Integration: CopilotKit hooks

Actions:

See UI/UX Design for details.

Security Boundaries

What Content Script CAN Do

✅ Read page DOM (text, structure) ✅ Create temporary overlays (highlights, tooltips) ✅ Tag elements with data-* attributes ✅ Communicate with Background via messages

What Content Script CANNOT Do

❌ Inject complex HTML (CSP/Trusted Types blocks it) ❌ Load external libraries (CSP blocks <script src>) ❌ Make cross-origin fetches directly ❌ Access chrome.storage directly (must go through Background)

What Side Panel CAN Do

✅ Full React app with external dependencies ✅ Direct access to chrome.storage ✅ iframe embedding (if needed) ✅ WebGL/Canvas rendering (React Flow)

What Background Worker CAN Do

✅ Cross-origin fetches (via host_permissions) ✅ Long-lived operations (within service worker limits) ✅ Global state management ✅ Tab coordination

Performance Considerations

Content Script

Side Panel

Background Worker

Testing Strategy

Unit Tests

Integration Tests

E2E Tests (Playwright)


Revision #2
Created 20 March 2026 15:49:56 by bhishma
Updated 20 March 2026 15:54:27 by bhishma