Skip to content

feat(extension): Trinity Agent Bridge — Chrome Extension for direct human↔agent communication #56

@gHashTag

Description

@gHashTag

🌐 Trinity Agent Bridge — Chrome Extension

🎯 Goal

Build a Chrome Extension that creates direct real-time communication channel between the user and AI agents running in browser tabs (Claude.ai, Cursor, GitHub).

Stack: Chrome Extension (TypeScript) + trios MCP WebSocket server + content scripts.

NO .sh files. Rust + TypeScript only.


🏗 Architecture

┌─────────────────────────────────────────────────────┐
│                    USER BROWSER                     │
│                                                     │
│  ┌──────────────┐     ┌─────────────────────────┐  │
│  │   Extension  │     │   Content Scripts        │  │
│  │   Popup UI   │────▶│   claude.ai injector     │  │
│  │  (React/TS)  │     │   github.com injector    │  │
│  └──────┬───────┘     │   cursor.sh injector     │  │
│         │             └──────────┬──────────────┘  │
└─────────┼────────────────────────┼─────────────────┘
          │ WebSocket              │ DOM events
          ▼                        ▼
┌─────────────────────────────────────────────────────┐
│          trios MCP WebSocket Server                 │
│          (new crate: crates/trios-bridge)           │
│                                                     │
│  ┌──────────────┐   ┌──────────────┐               │
│  │ Agent Router │   │ GitHub API   │               │
│  │ (pub/sub)    │   │ (issues sync)│               │
│  └──────┬───────┘   └──────────────┘               │
└─────────┼───────────────────────────────────────────┘
          │
    ┌─────┴──────┐
    ▼            ▼
 Agent 1      Agent 2
(claude.ai)  (cursor.sh)

📦 Repository structure

crates/
└── trios-bridge/           ← NEW Rust crate (WebSocket server)
    ├── Cargo.toml
    └── src/
        ├── lib.rs
        ├── server.rs       ← tokio + tokio-tungstenite WebSocket
        ├── router.rs       ← agent pub/sub routing
        ├── github.rs       ← GitHub issues sync
        └── protocol.rs     ← message types (serde JSON)

extension/                  ← NEW Chrome Extension
├── manifest.json           ← Manifest V3
├── package.json
├── tsconfig.json
├── src/
│   ├── background/
│   │   ├── service-worker.ts   ← persistent WebSocket to trios-bridge
│   │   └── message-bus.ts      ← Chrome message routing
│   ├── popup/
│   │   ├── App.tsx             ← React popup UI
│   │   ├── AgentBoard.tsx      ← live status of all agents
│   │   ├── CommandInput.tsx    ← send command to agent(s)
│   │   └── IssueTracker.tsx    ← #30 board live view
│   ├── content/
│   │   ├── claude-injector.ts  ← injects commands into claude.ai textarea
│   │   ├── github-injector.ts  ← reads/writes issue #30 comments
│   │   └── cursor-injector.ts  ← injects into cursor.sh chat
│   └── shared/
│       ├── types.ts            ← AgentMessage, AgentStatus, Command
│       └── protocol.ts         ← WebSocket message format (mirrors Rust)
docs/
└── extension/
    └── README.md

📡 WebSocket Protocol

All messages are JSON. Define in both protocol.rs (Rust) and shared/types.ts (TypeScript).

// shared/types.ts

type AgentId = string; // e.g. "agent-1", "agent-claude-main"

type AgentStatus = 'idle' | 'claiming' | 'working' | 'blocked' | 'done';

interface AgentState {
  id: AgentId;
  name: string;
  issue: number | null;     // GitHub issue number currently claimed
  status: AgentStatus;
  branch: string | null;
  last_update: string;      // ISO timestamp
  message: string;          // last status message
}

// Messages: Client → Server
interface SendCommandMsg {
  type: 'send_command';
  target: AgentId | 'broadcast'; // specific agent or all
  command: string;               // text to inject
  issue_comment: boolean;        // also post to GitHub issue #30?
}

interface ClaimIssueMsg {
  type: 'claim_issue';
  agent_id: AgentId;
  issue_number: number;
  branch: string;
}

interface UpdateStatusMsg {
  type: 'update_status';
  agent_id: AgentId;
  status: AgentStatus;
  message: string;
}

// Messages: Server → Client
interface BoardStateMsg {
  type: 'board_state';
  agents: AgentState[];      // full state of all agents
  issues: IssueStatus[];     // #30 child issues status
}

interface AgentEventMsg {
  type: 'agent_event';
  agent_id: AgentId;
  event: 'claimed' | 'done' | 'blocked';
  issue_number: number;
  message: string;
}

interface CommandDeliveredMsg {
  type: 'command_delivered';
  target: AgentId;
  success: boolean;
}

🦀 Rust: crates/trios-bridge

Cargo.toml

[package]
name = "trios-bridge"
version = "0.1.0"
edition = "2021"

[dependencies]
tokio = { version = "1", features = ["full"] }
tokio-tungstenite = "0.21"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
futures-util = "0.3"
octocrab = "0.38"      # GitHub API
tracing = "0.1"
tracing-subscriber = "0.3"
uuid = { version = "1", features = ["v4"] }

server.rs — core requirements

github.rs — required functions

pub async fn post_claiming_comment(issue_number: u64, agent_id: &str, branch: &str) -> Result<()>
pub async fn post_done_comment(issue_number: u64, agent_id: &str, pr_number: u64) -> Result<()>
pub async fn post_blocked_comment(issue_number: u64, agent_id: &str, reason: &str) -> Result<()>
pub async fn list_child_issues(parent: u64) -> Result<Vec<Issue>>
pub async fn get_issue_status(issue_number: u64) -> Result<IssueStatus>

Auth: reads GITHUB_TOKEN from env (same as existing trios pattern).

CLI integration

Add to tri CLI:

tri bridge start              # start WebSocket server on :7474
tri bridge status             # show all connected agents
tri bridge send <agent> <msg> # send command to specific agent
tri bridge broadcast <msg>    # send to all agents

🧩 Chrome Extension: manifest.json

{
  "manifest_version": 3,
  "name": "Trinity Agent Bridge",
  "version": "0.1.0",
  "description": "Direct human↔agent communication via trios MCP",
  "permissions": [
    "tabs",
    "activeTab",
    "storage",
    "scripting"
  ],
  "host_permissions": [
    "https://claude.ai/*",
    "https://github.com/*",
    "https://cursor.sh/*",
    "http://localhost:7474/*"
  ],
  "background": {
    "service_worker": "dist/background/service-worker.js",
    "type": "module"
  },
  "action": {
    "default_popup": "dist/popup/index.html",
    "default_icon": {
      "32": "icons/trinity-32.png",
      "128": "icons/trinity-128.png"
    }
  },
  "content_scripts": [
    {
      "matches": ["https://claude.ai/*"],
      "js": ["dist/content/claude-injector.js"],
      "run_at": "document_idle"
    },
    {
      "matches": ["https://github.com/gHashTag/trios/*"],
      "js": ["dist/content/github-injector.js"],
      "run_at": "document_idle"
    }
  ]
}

🖥 Popup UI — AgentBoard.tsx

Required features:

  1. Live agent board — shows all connected agents with status badges

    🟢 Agent-1  [Lane A - Scaffold]    IN PROGRESS  feat/phd-scaffold
    🟡 Agent-2  [Lane B - Proofs]      IDLE
    🔴 Agent-3  [Lane C - Physics]     BLOCKED      "waiting for #41"
    ✅ Agent-4  [Lane D - Sacred]      DONE         PR #52
    🟢 Agent-5  [Lane E - GF16]        IN PROGRESS  feat/phd-gf16-igla
    
  2. Command input — text field + send button

  3. Issue epic(phd): Trinity Framework — Flos Aureus PhD Dissertation v6.0 #30 mini-board — live view of all 8 child issues

    #41 Lane A Scaffold      🟢 IN PROGRESS
    #43 Lane B Proofs        🔴 TODO
    #44 Lane C Physics       🔴 TODO
    #46 Lane D Sacred        🔴 TODO
    #47 Lane E GF16          🔴 TODO
    #48 Bibliography         🔴 TODO
    #49 Lexicon+Genealogy    🔴 TODO
    #50 TikZ Figures         🔴 TODO
    #51 Final Integration    ⚫ BLOCKED (waiting all)
    
  4. Quick action buttons

    • 🚀 Broadcast: Start your claimed issue NOW
    • 🔄 Sync board from GitHub
    • ⚡ Broadcast: STOP asking questions, just push

💉 claude-injector.ts — content script

// Listens for commands from service-worker
chrome.runtime.onMessage.addListener((msg) => {
  if (msg.type === 'inject_command') {
    injectIntoClaudeTextarea(msg.command);
  }
});

function injectIntoClaudeTextarea(command: string): void {
  // Find Claude's textarea (ProseMirror div)
  const editor = document.querySelector(
    '[contenteditable="true"][data-testid="chat-input"]'
    ?? 'div.ProseMirror' // fallback
  );
  if (!editor) return;

  // Inject text using React synthetic events (required for ProseMirror)
  const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
    window.HTMLDivElement.prototype, 'innerHTML'
  );
  editor.innerHTML = command;
  editor.dispatchEvent(new Event('input', { bubbles: true }));

  // Auto-submit after 500ms
  setTimeout(() => {
    const sendButton = document.querySelector('[data-testid="send-button"]'
      ?? 'button[aria-label="Send message"]');
    sendButton?.click();
  }, 500);
}

🐙 github-injector.ts — content script

On github.com/gHashTag/trios/issues/30:

  • Parses all comments to extract agent status (CLAIMING / DONE / BLOCKED)
  • Sends parsed AgentState[] to service-worker via chrome.runtime.sendMessage
  • Adds Trinity Agent Bridge sidebar to the page:
    ┌─────────────────────────┐
    │ 🔱 Trinity Agent Bridge │
    │─────────────────────────│
    │ 🟢 Agent-1  WORKING     │
    │ 🔴 Agent-2  IDLE        │
    │─────────────────────────│
    │ [Broadcast Command    ] │
    │ [         Send        ] │
    └─────────────────────────┘
    

🔨 Build system

extension/
├── package.json
│     scripts:
│       build:   "tsc && vite build"
│       watch:   "vite build --watch"
│       package: "zip -r trinity-bridge.zip dist/ manifest.json icons/"

Makefile target in root:

extension-build:
	cd extension && npm run build

extension-package:
	cd extension && npm run package

NO .sh files — all build steps via Makefile + npm scripts.


✅ Acceptance Criteria

Rust bridge

  • tri bridge start launches WebSocket on ws://localhost:7474
  • Multiple simultaneous connections work
  • tri bridge send agent-1 "do X" delivers message
  • tri bridge broadcast "stop asking, just push" reaches all agents
  • GitHub CLAIMING/DONE comments posted automatically
  • cargo test passes for all crates

Chrome Extension

Integration

  • Full flow: user types in popup → WebSocket → service-worker → content script → claude.ai textarea auto-filled + submitted
  • Agent status visible in popup within 5 seconds of GitHub comment
  • NO .sh files anywhere
  • All commits refs #52

🌿 Branch

feat/trinity-agent-bridge

📅 Timeline

Date Milestone
Apr 21 trios-bridge crate: WebSocket server running
Apr 22 tri bridge start/send/broadcast CLI commands
Apr 23 Chrome extension popup + service-worker skeleton
Apr 24 claude-injector.ts working (inject + submit)
Apr 25 github-injector.ts sidebar on issue #30
Apr 26 Full integration test: popup → Claude.ai
Apr 27 Package + docs

📢 Sync

Post in this issue before starting:
🔒 AGENT [name] CLAIMING: Trinity Agent Bridge | Branch: feat/trinity-agent-bridge | Status: IN PROGRESS

refs #30

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions