Problem
API keys (ZAI_API_KEY, etc.) are currently stored/configured inside BrowserOS agent server. This is architecturally wrong.
BrowserOS is a dumb transport — it proxies browser tools (click, navigate, screenshot) over MCP. It has no business knowing about AI provider credentials.
Multiple clients connect to BrowserOS (Cursor, Claude Code, Roo Code, trios-ext) — none of them should own the keys either.
Correct Architecture
Cursor / Claude Code / Roo Code
│
│ MCP (HTTP :9002)
▼
BrowserOS ←── browser tools ONLY, zero API keys
│
▼
Chrome Extension (trios-ext)
│ keys live HERE — chrome.storage.local
▼
api.z.ai / ZAI_API_KEY (direct fetch from background SW)
Tasks
1 — Settings UI in extension popup
- Add
extension/popup.html settings panel (or a tab in existing panel)
- Input fields:
ZAI_API_KEY, optionally ZAI_BASE_URL
- Save/load via
chrome.storage.local
- Show masked value + "Saved ✓" confirmation
2 — settings.rs module in crates/trios-ext/src/
// chrome.storage.local wrapper
pub fn save_api_key(key: &str) -> Result<(), JsValue>;
pub fn get_api_key() -> Option<String>; // async, returns Promise
3 — mcp.rs reads key from storage
- Remove any hardcoded/env key references
- On each outbound request: resolve key from
chrome.storage.local
- Fetch directly to
api.z.ai from background service worker (bypasses CORS)
4 — Remove key logic from BrowserOS
- Delete
ZAI_API_KEY / provider config from BrowserOS/packages/browseros-agent
- BrowserOS config should have zero provider/apiKey fields
Invariants
- I4: 0 WebSocket — keys flow through
chrome.storage, not WS
- I5: single extension tree at
crates/trios-ext/extension/
- Keys NEVER leave the Chrome Extension process boundary
- BrowserOS remains a stateless MCP transport
Acceptance Criteria
Problem
API keys (ZAI_API_KEY, etc.) are currently stored/configured inside BrowserOS agent server. This is architecturally wrong.
BrowserOS is a dumb transport — it proxies browser tools (click, navigate, screenshot) over MCP. It has no business knowing about AI provider credentials.
Multiple clients connect to BrowserOS (Cursor, Claude Code, Roo Code, trios-ext) — none of them should own the keys either.
Correct Architecture
Tasks
1 — Settings UI in extension popup
extension/popup.htmlsettings panel (or a tab in existing panel)ZAI_API_KEY, optionallyZAI_BASE_URLchrome.storage.local2 —
settings.rsmodule incrates/trios-ext/src/3 —
mcp.rsreads key from storagechrome.storage.localapi.z.aifrom background service worker (bypasses CORS)4 — Remove key logic from BrowserOS
ZAI_API_KEY/ provider config fromBrowserOS/packages/browseros-agentInvariants
chrome.storage, not WScrates/trios-ext/extension/Acceptance Criteria
chrome.storage.localstores and retrievesZAI_API_KEYmcp.rsresolves key dynamically, no hardcoded valuescargo clippy -p trios-ext= 0 warnings