Skip to content

Latest commit

 

History

History
233 lines (204 loc) · 14.3 KB

README.md

File metadata and controls

233 lines (204 loc) · 14.3 KB

Experimental providers using your signed-in browser

Grok, Mistral, Kimi, GLM, ChatGPT, Qwen and Gemini use the normal site's send handler in an existing signed-in tab. They do not copy cookies, passwords or Google OAuth tokens into the bridge. Each provider has a separate queue and scoped conversation ids. All integrations are opt-in and use the selected web model. Browser adapters for Qwen, Kimi, GLM, Mistral, Grok, ChatGPT, Claude and Gemini have been live-checked; DeepSeek stays HTTP-only. Website frontends and account limits can still break a session at any time. For Qwen set QWEN_ENABLED=1 and QWEN_TRANSPORT=browser (the default http transport still uses python -m qwen.auth plus the direct API client). For Gemini set GEMINI_ENABLED=1 and GEMINI_TRANSPORT=browser (the default cli transport still uses the Antigravity CLI and GEMINI_MODELS). Kimi's JSON Connect parser binds root answer blocks to the matching user and successfully completed assistant message; thinking blocks are excluded. Only this verified wire text can be parsed as requested OpenCode tool calls; unsupported snapshots and ambiguous message identities fail the request.

Safari

The two scripts work with Userscripts for Safari, distributed through the developer's App Store link. The observer runs in the page context without privileged APIs. The controller runs in the isolated content context and keeps its local pairing key out of page JavaScript.

  1. Run python -m providers.tab_bridge in this repository. It writes personalized scripts to session/browser-bridge/userscripts/ with private permissions. Never upload, commit or share that directory: the controller contains your local pairing key. The generic files in browser/ contain no key.
  2. Install Userscripts and add the two exported .user.js files to its scripts directory. Grant access only to chat.z.ai, grok.com, chat.mistral.ai, www.kimi.com (or www.kimi.ai), chat.qwen.ai, chatgpt.com (and chat.openai.com if still used), claude.ai, chat.chatgbot.ai, gemini.google.com, and www.google.com; the bridge does not need access to Google Account settings pages beyond the chat UI. After adding or replacing files, open the Userscripts toolbar popup and wait until both script names appear. The extension must rescan externally edited files before the next page load, as described in its linked README. After upgrading the bridge, export and replace the scripts again. The current controller is 0.3.35 and observer is 0.3.18 (ChatGBot Claude /en/chat). On a failed job the badge shows ERROR: … with the reason (hover for full text). Older loaded scripts do not include all lease checks.
  3. Keep the API bound to 127.0.0.1:8000. Set BROWSER_BRIDGE_ENABLED=1 and enable the provider you want, e.g. GROK_ENABLED=1, MISTRAL_ENABLED=1, GLM_ENABLED=1, CHATGPT_ENABLED=1, or CLAUDE_ENABLED=1 (browser-only — no transport flag). For Qwen use QWEN_TRANSPORT=browser; for Gemini GEMINI_TRANSPORT=browser. Then restart the API.
  4. Open the provider in your normal signed-in browser and reload once to load both scripts. Click Подключить вкладку к OpenCode. Keep that tab open. Userscripts may separately ask for 127.0.0.1 access for local job exchange; grant only that address, without choosing all websites. The controller checks that its observer is ready before sending a prompt. Do not use it for manual chat while a bridge request is running.
  5. Point an OpenAI-compatible client at the same /v1 URL. Model ids are grok-web, mistral-web, kimi-web, glm-web, chatgpt-web, claude-web, qwen-web, and gemini-web. They deliberately do not claim a specific model version; select the desired model in the site's UI. Stateless clients (OpenCode) that resend full messages[] resume the same browser chat via the local conversation cache; only the new user/tool turn is typed into the tab after the first reply. An uncertain send/capture outcome retains a durable pause and pending attempt. Inspect the site before explicitly resolving it; visibility in a browser is not proof that a generation never started.

Requests to the local job endpoints require the private pairing key and a loopback client address. There is no CORS grant. A claimed job is tied to one tab, provider, document instance, random id and lease. Sending requires a one-time server authorization; only explicit navigation can hand an unsubmitted job to a new document. Cancelled, late and replayed results fail, and the controller checks lease liveness while waiting for a response. Unsent drafts cause a failure rather than being overwritten. A reload during generation fails the job instead of automatically repeating its prompt.

Completed text is buffered and validated before any tool calls are returned. SSE keepalives protect client timeouts. Quota, security and region rejections are terminal; the bridge does not rotate accounts, solve captchas, change fingerprints, or retry through another endpoint.

Provider pauses

All adapters are opt-in. The API attempts a prompt once; quota, security, regional or uncertain upstream failures persist a provider pause across restarts. Later requests return HTTP 403 before any browser job or CLI process is created. A failure after SSE starts is a terminal error event. This does not undo account restrictions or guarantee that website automation is permitted.

Inspect python -m providers.access status. Only after manually checking normal website access, use python -m providers.access resume PROVIDER. A new sign-in or a different model cannot silently clear the pause. The default 10-second interval between attempts and continuations is pacing, not a website allowance. Use one server process; multiple workers do not share an in-flight queue.

Usage limits

Free access is subject to the website's account, model and feature allowances. The bridge does not provide an unlimited API or a separate quota. An OpenCode task can consume several website messages because tool results require another model turn. A resumed conversation consumes allowance too.

  • Mistral/Vibe: the official Free plan limits messages and web searches. During the 2026-10-02 live test a new completion succeeded, then the resumed request returned HTTP 429; the user also observed the free allowance warning. Further requests stopped. No fixed message count or reset time was established. Website plan allowances are distinct from Studio/developer API rate limits.
  • Kimi: the official chat FAQ documents a conversation frequency limit and peak-load throttling. Selected membership features/models also consume a shared credit pool. Kimi Code limits apply to Kimi Code and must not be presented as this browser chat adapter's quota. Large composer pastes (~4KB+, typical OpenCode system+tools) are turned into a TXT attachment by the site instead of chat text — keep bridge prompts shorter, or use the HTTP transport after session capture.
  • DeepSeek: our account received a temporary restriction (biz_code=5, user is muted) on 2026-10-02. The exact trigger is unknown; no live retest was attempted after the safety changes. Automated website access can restrict an account even without an observed quota warning.
  • Qwen and GLM: no exhausted web-chat quota was observed in our controlled qualification tests. This is not proof of unlimited usage. We have not established a fixed current web-chat allowance; API/CLI quota tables must not be substituted for website limits.

On 429 or a website quota notice, stop the task and inspect the normal account UI for the relevant allowance and reset time. The bridge does not automatically switch accounts or models, create another conversation to evade the quota, purchase credits or retry the rejected turn. Limits can change; check the provider's current plan before relying on it for sustained agent work.

ChatGPT

ChatGPT is browser-only (CHATGPT_ENABLED=1, no transport flag). Pair a signed-in tab on https://chatgpt.com/ (or https://chat.openai.com/), use model id chatgpt-web, and select the model in the site UI. The observer captures /backend-api/conversation and /backend-api/f/conversation SSE only for the active bridge job. Conversation tokens use /c/<id>. Captchas, Sentinel challenges and plan limits must be resolved in the normal tab; the bridge does not automate them. Live browser-adapter checks for this provider have passed; account quotas, captchas and Sentinel challenges still apply per session.

Claude

Claude is browser-only (CLAUDE_ENABLED=1, no transport flag). Pair a signed-in tab on ChatGBot (preferred) or https://claude.ai/, use model id claude-web, and select the model in the site UI. The controller fills the ProseMirror composer ([data-testid="chat-input"]) and clicks Send. On ChatGBot the empty chat is /en/chat and threads are /en/chat/<id>; bridge tokens stay /chat/<id>. The observer captures only /api/organizations/.../chat_conversations/<id>/completion SSE for the active job (line-oriented content_block_delta / message_stop; thinking frames with "stop_reason": null are not treated as done). An incomplete wire body is rejected; visible DOM text cannot substitute for a terminal network response. Do not point OpenCode small_model / session-title at claude-web while a long turn is running — use another provider or disable title LLM (Harness already disables session-title-llm). Captchas and plan limits must be resolved in the normal tab. Live browser-adapter checks for this provider have passed; account quotas and challenges still apply per session.

Gemini

Browser tab (GEMINI_TRANSPORT=browser)

Set GEMINI_ENABLED=1, GEMINI_TRANSPORT=browser, and BROWSER_BRIDGE_ENABLED=1. Export and install the userscripts, open a signed-in Gemini tab — either https://www.google.com/search?udm=50 (AI Mode empty chat) or https://gemini.google.com/app — connect it, and use model id gemini-web. The site UI selects the model. Conversation tokens use /app/<id> when the SPA exposes one (not Antigravity UUIDs).

Answer capture. The controller forwards only request-bound network captures. It never substitutes visible DOM text or synthesizes completion markers. Google AI Mode HTML prompt echoes are removed only at an exact normalized prefix; ambiguous embedded echoes are rejected. A stalled capture stops the turn and retains the safety pause. These changes were verified offline, not against live Gemini accounts.

Antigravity CLI (GEMINI_TRANSPORT=cli, default)

Install the official Antigravity CLI and complete its Google account sign-in yourself. Individual free access to the old Gemini CLI was retired; do not reuse its OAuth credentials in this bridge.

Run agy models and put the account's real slugs into GEMINI_MODELS, for example a JSON object mapping your chosen gemini-... public name to the exact CLI slug. Set GEMINI_ENABLED=1. No Gemini models are advertised when the map is empty. The adapter runs the official CLI in an empty temporary workspace, with a custom text agent containing tools: [], no slash commands and no permission bypass. OpenCode remains responsible for tool execution. The CLI's streaming initialization must confirm the selected model, custom agent, empty tool list and normal permission mode before the prompt is sent. Only one successful terminal result is accepted; tool/subagent events fail. An available model list does not prove account eligibility: the CLI checks regional access again when starting a completion. The adapter currently requires POSIX process groups and terminates the entire owned group before deleting its temporary workspace, including descendants whose parent has already exited.

If the official CLI's token exchange fails specifically on an IPv6 socket, python -m providers.antigravity_ipv4 runs the same official CLI through a loopback CONNECT tunnel using IPv4 on your existing network route. Google TLS is not decrypted; OAuth traffic is not logged. This optional workaround refuses to override an existing proxy. It is not a region-access workaround: stop if Google rejects your account or region. No system, browser, DNS or VPN settings are modified.

Verification

python -m unittest discover -s tests -q checks routing, authentication, queue ownership, cancellation, protocol completion and CLI isolation. To also run the owned browser fixtures, install Playwright Chromium and use RUN_BROWSER_FIXTURES=1 python -m unittest tests.test_userscripts -q. Those fixtures intercept all requests; they do not authenticate or contact providers. Passing fixtures are not proof of a successful live Safari/provider integration.

On 2026-10-02, a signed-in Safari account using GLM-5.3-Flash passed a controlled new completion, resumed SSE with the same conversation id, and an OpenCode plan request with a completed native read followed by the exact fixture contents. This used both 0.1.4 scripts and the matching server protocol. It qualifies that account/session and test, not all GLM models or arbitrary tasks.

With both 0.2.4 scripts on 2026-10-02, Kimi passed an exact new completion and resumed SSE with the same conversation id, stop and [DONE], followed by an OpenCode plan request with a completed native read and the exact owned fixture contents. This qualifies that account/session and controlled test. Large Kimi composer pastes (~4KB+, typical OpenCode system+tools) are still turned into a TXT attachment by the site — confirmed on later live checks; keep bridge prompts shorter or use HTTP after session capture. As of 2026-10-11, live browser-adapter checks also passed for Mistral (mistral-web), Grok (grok-web), ChatGPT (chatgpt-web), Claude (claude-web), Qwen (qwen-web) and Gemini (gemini-web). Earlier partial failures (Mistral 429 on continuation, Grok capture gaps) do not overturn those later adapter checks; quotas and UI challenges still apply per account. Official Antigravity CLI login and model listing succeeded, but completion was rejected by Google's regional eligibility check; further CLI attempts stopped. Prefer GEMINI_TRANSPORT=browser / gemini-web when the tab path works.