chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 13:39:12 +08:00
commit d8dcd5f6d1
8604 changed files with 2479390 additions and 0 deletions
+182
View File
@@ -0,0 +1,182 @@
---
title: "AgentRouter Setup Guide"
version: 3.8.40
lastUpdated: 2026-06-28
---
# AgentRouter Setup Guide
[AgentRouter](https://agentrouter.org) is an Anthropic-compatible relay that resells
Claude and other models, often at lower prices than the direct Anthropic API. It is
designed as a drop-in `ANTHROPIC_BASE_URL` replacement for the official Claude Code
client, so it only accepts traffic that matches the Claude Code wire image (specific
User-Agent, `anthropic-beta` flags, Stainless SDK headers, etc.).
## Quick start — use the native `agentrouter` provider (recommended)
For most users, **no special setup is required**. OmniRoute ships a built-in
`agentrouter` provider with the full Claude Code wire image already baked in (see
`open-sse/config/providerRegistry.ts``agentrouter`). To use it:
1. Open **Dashboard → Providers → Add Provider**.
2. Select **AgentRouter** from the list.
3. Paste your `sk-...` API key and save.
That's it — no environment variables, no custom provider type. Built-in models
include `claude-opus-4-6`, `claude-haiku-4-5-20251001`, `glm-5.1`, and
`deepseek-v3.2`.
The rest of this guide covers the **advanced path**: using the
`anthropic-compatible-cc-*` provider type. Use that when you need more control
over the wire image — for example, when connecting to other AgentRouter-style
relays that are not yet in the native provider registry, or when overriding the
base URL, chat path, or header set.
---
## Advanced: connecting via the Claude Code compatible provider type
OmniRoute also supports AgentRouter (and similar relays) through the **Claude Code
compatible** provider type (`anthropic-compatible-cc-*`), which speaks the
Anthropic Messages API with the correct wire image. A generic
`openai-compatible-chat` provider pointing at `https://agentrouter.org` will
**not** work — the upstream WAF rejects requests that do not look like Claude
Code.
---
## Prerequisites
- An AgentRouter account and API key. New signups get free credits via the affiliate
link in the project [README](../README.md).
- OmniRoute running with the `ENABLE_CC_COMPATIBLE_PROVIDER` feature flag enabled
(see below).
## 1. Enable the CC-compatible provider type
The Claude Code compatible provider type is gated behind a feature flag because it
sends traffic that closely mirrors the official Claude Code client. Enable it by
setting an environment variable before starting OmniRoute:
```bash
ENABLE_CC_COMPATIBLE_PROVIDER=true
```
Docker example:
```bash
docker run -d --name omniroute \
--restart unless-stopped \
-p 20128:20128 \
-v omniroute-data:/app/data \
-e ENABLE_CC_COMPATIBLE_PROVIDER=true \
diegosouzapw/omniroute:latest
```
After restarting, the dashboard exposes an **Add Claude Code Compatible** option in
addition to the existing OpenAI-compatible and Anthropic-compatible flows.
## 2. Create the provider in the dashboard
1. Open **Dashboard → Providers → Add Provider**.
2. Choose **Add Claude Code Compatible** (only visible when the flag above is set).
3. Fill in the fields:
| Field | Value |
| --------- | -------------------------------------------------------------- |
| Name | `AgentRouter` (or any label) |
| Prefix | `agentrouter` (friendly alias shown in logs and the dashboard) |
| Base URL | `https://agentrouter.org` |
| Chat path | `/v1/messages?beta=true` (default — leave as-is) |
> The canonical model identifier still uses the full provider node ID
> (`anthropic-compatible-cc-{uuid}/{model}`). The **Prefix** is just a display
> alias resolved by `src/lib/usage/callLogs.ts` for friendlier log output.
4. (Optional) Paste your API key in the **Validate** field and click **Check** to
confirm connectivity before saving.
5. Click **Add**.
Once created, open the provider and add a **Connection** with your AgentRouter API
key (`sk-...`). The connection's `test_status` should turn `active`.
## 3. Use it through a combo or directly
Reference the model using your provider's prefix as the namespace:
```bash
curl -X POST http://localhost:20128/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "agentrouter/claude-opus-4-6",
"messages": [{"role": "user", "content": "hello"}],
"max_tokens": 100
}'
```
The canonical model ID `anthropic-compatible-cc-{uuid}/claude-opus-4-6` also works
and is what shows up in the database and combo configuration.
Or add it to a combo for routing, fallback, and quota management like any other
provider.
---
## Wire image details
For reference, the cc-compatible bridge sends the following on each upstream
request (see `open-sse/services/claudeCodeCompatible.ts`):
| Header | Value |
| ------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| `Authorization` | `Bearer <api-key>` |
| `User-Agent` | `claude-cli/2.1.195 (external, sdk-cli)` |
| `anthropic-version` | `2023-06-01` |
| `anthropic-beta` | `claude-code-20250219,interleaved-thinking-2025-05-14,effort-2025-11-24` |
| Per-connection redact-thinking beta toggle | Adds `redact-thinking-2026-02-12` for upstreams that specifically require redacted thinking streams |
| Per-connection summarized thinking toggle | Adds `display: "summarized"` to CC Compatible thinking requests that did not already set a display mode |
| `anthropic-dangerous-direct-browser-access` | `true` |
| `x-app` | `cli` |
| `X-Stainless-*` | Various Stainless SDK headers (lang, package version, OS, arch, etc.) |
This is what allows requests to pass the upstream WAF / client whitelist.
---
## Troubleshooting
**`{"error":{"message":"unauthorized client detected, ..."}}`** — Your request did
not match the Claude Code wire image. This happens when the provider is configured
as `openai-compatible-chat` instead of `anthropic-compatible-cc`, or when the
`ENABLE_CC_COMPATIBLE_PROVIDER=true` flag was not set at startup.
**`{"error":{"message":"无效的令牌","type":"new_api_error"}}` (HTTP 401)** —
"Invalid token". The wire image is correct but the API key is rejected. Generate a
new key in the AgentRouter dashboard and update the connection.
**`{"error":{"code":"content-blocked","type":"agent_router_api_error"}}`
(HTTP 400)** — AgentRouter's moderation hook rejected the request content, or the
key's plan does not permit the requested model. Try a different prompt or model;
contact AgentRouter support if a benign prompt is consistently blocked.
**`[400]: content-blocked` only on specific models** — Most AgentRouter plans only
allow a subset of models (e.g. `claude-opus-4-6`). Other model IDs return
`unauthorized_client_error` even though the key is valid. Check which models your
plan covers in the AgentRouter dashboard.
**`Invalid JSON response from provider (reset after Ns)` from the omniroute logs** —
The upstream returned a non-JSON body (typically an HTML error page from the WAF).
This usually means the request never reached the AgentRouter backend — recheck that
the provider ID starts with `anthropic-compatible-cc-` (note the trailing dash —
see `CLAUDE_CODE_COMPATIBLE_PREFIX` in `open-sse/services/claudeCodeCompatible.ts`)
and the feature flag is enabled.
---
## See also
- [`docs/providers/CLAUDE_WEB.md`](./CLAUDE_WEB.md) — Claude Web provider integration notes
- [`docs/reference/FREE_TIERS.md`](../reference/FREE_TIERS.md) — Free-tier provider
catalog
- [`open-sse/services/claudeCodeCompatible.ts`](../../open-sse/services/claudeCodeCompatible.ts)
— Wire image implementation
+112
View File
@@ -0,0 +1,112 @@
---
title: "Providers — Claude Web"
version: 3.8.40
lastUpdated: 2026-06-28
---
# Providers — Claude Web
## claude-web
Web-cookie-based provider for **Claude AI** (`claude.ai`) using session cookie authentication.
### How It Works
1. User pastes their `claude.ai` session cookies into the OmniRoute dashboard
2. `ClaudeWebExecutor` transforms OpenAI-format requests to Claude Web API format
3. Requests are sent via **`tls-client-node`** with **Chrome 124 TLS fingerprint** to bypass Cloudflare Turnstile
4. Responses are streamed back via SSE (`text/event-stream`)
### Required Cookies
| Cookie | Purpose | Source |
| -------------- | ------------------------------ | -------------------------------------- |
| `sessionKey` | Main authentication | `claude.ai` browser session |
| `routingHint` | Anthropic routing | `claude.ai` browser session |
| `cf_clearance` | Cloudflare Turnstile clearance | Auto-set by Cloudflare after challenge |
| `__cf_bm` | Cloudflare bot management | Auto-set by Cloudflare |
| `_cfuvid` | Cloudflare visitor ID | Auto-set by Cloudflare |
> **Note**: `cf_clearance` is bound to the TLS fingerprint of the browser that solved Cloudflare's Turnstile challenge. The `tls-client-node` library (via `claudeTlsClient.ts`) spoofs a Chrome 124 TLS handshake so the clearance token works from the OmniRoute server.
### API Reference
**Endpoint**: `POST /api/organizations/{orgId}/chat_conversations/{convId}/completion`
**Required Headers**:
```
accept: text/event-stream
anthropic-client-platform: web_claude_ai
anthropic-device-id: <uuid>
content-type: application/json
Referer: https://claude.ai/chat/{convId}
```
**Request Body**:
```json
{
"prompt": "user message",
"model": "claude-sonnet-4-6",
"timezone": "Asia/Jakarta",
"locale": "en-US",
"personalized_styles": [...],
"tools": [...],
"rendering_mode": "messages",
"create_conversation_params": {
"name": "",
"model": "claude-sonnet-4-6",
"is_temporary": false
}
}
```
### Architecture
```
User Cookies (claude.ai)
OmniRoute Dashboard
ClaudeWebExecutor (open-sse/executors/claude-web.ts)
↓ Request transformation (OpenAI → Claude Web format)
tlsFetchClaude() (open-sse/services/claudeTlsClient.ts)
↓ Chrome 124 TLS fingerprint spoofing
tls-client-node (Go native binding, koffi)
claude.ai API
↓ SSE stream
```
### Files
| File | Purpose |
| ----------------------------------------------------- | ---------------------------------------------------- |
| `src/shared/constants/providers.ts` | Provider registration (WEB_COOKIE_PROVIDERS) |
| `src/lib/providers/webCookieAuth.ts` | Cookie utilities (normalize/extract session cookies) |
| `open-sse/executors/claude-web.ts` | Executor implementation |
| `open-sse/executors/index.ts` | Executor registration |
| `open-sse/services/claudeTlsClient.ts` | TLS fingerprint spoofing via tls-client-node |
| `open-sse/services/__tests__/claudeTlsClient.test.ts` | TLS client tests |
| `tests/unit/claude-web.test.ts` | Executor tests |
### Testing
```bash
# Unit tests
node --import tsx/esm --test tests/unit/claude-web.test.ts
# TLS client tests
npx vitest run open-sse/services/__tests__/claudeTlsClient.test.ts
```
### Setup
1. Start OmniRoute: `omniroute`
2. Go to Dashboard → Providers → Add Provider
3. Select "Web Cookie" category
4. Choose "Claude Web"
5. Paste your full cookie header from `claude.ai` browser DevTools (Network tab → Copy as fetch → Cookie header)
+128
View File
@@ -0,0 +1,128 @@
---
title: "Zed IDE Integration in Docker Environments"
version: 3.8.40
lastUpdated: 2026-06-28
---
# Zed IDE Integration in Docker Environments
When OmniRoute runs inside Docker, the standard "Import from Zed Keychain" flow fails
because the container cannot reach the host OS keychain daemon (libsecret on Linux,
Keychain on macOS, Credential Manager on Windows) and the Zed config directories on the
host filesystem are not visible inside the container by default.
## Why Keychain Import Fails in Docker
Two blocking issues occur inside a container:
1. **Filesystem isolation**`isZedInstalled()` looks for `~/.config/zed` (Linux),
`~/Library/Application Support/Zed` (macOS), or the Windows equivalent. These paths
live on the host and are not available unless explicitly volume-mounted.
2. **IPC isolation** — Even when the config directory is mounted, the `keytar` native
module communicates with the OS keychain service over a Unix socket or D-Bus session.
Neither is bridged into the container by default, so credential reads always fail.
OmniRoute detects the Docker environment via two heuristics:
- Presence of `/.dockerenv` (written by the Docker daemon at container start).
- The string `docker` appearing in `/proc/1/cgroup` (Linux cgroup v1).
When either heuristic triggers, the import route returns HTTP 422 with
`zedDockerEnvironment: true` and a message directing you to the Manual Token Import tab.
## Using the Manual Token Import Tab
1. Open **Dashboard → Providers → Zed**.
2. The **Manual Token Import** panel appears below the keychain import card. When
OmniRoute detects Docker, this panel expands automatically after the first failed
keychain import attempt.
3. Select the provider from the dropdown (OpenAI, Anthropic, Google, Mistral, xAI,
OpenRouter, or DeepSeek).
4. Paste the API key in the password field.
5. Click **Import**.
The key is saved as a new provider connection with the name
`Zed Manual Import (<provider>)`.
## Where Zed Stores API Keys on the Host
Zed stores AI provider keys in the OS keychain under service names such as
`zed-openai`, `ai.zed.openai`, `zed-anthropic`, etc. To retrieve them for manual
import, look in:
**Linux**
```
~/.config/zed/settings.json
```
The `language_models` section contains provider configurations. Keys saved to the
keychain via the Zed UI are not in plain text in `settings.json`; retrieve them through
a keychain viewer such as GNOME Keyring / Seahorse, or by running:
```bash
secret-tool lookup service zed-openai account api-key
```
**macOS**
```
~/Library/Application Support/Zed/settings.json
```
Keychain entries can be found in **Keychain Access.app** by searching for `zed`.
## Volume-Mount Option (Advanced)
You can optionally mount the Zed config directory read-only into the container.
This does not fix the keychain issue but may be useful for future features that read
non-secret Zed config values (e.g., model preferences).
```yaml
# docker-compose.yml snippet
services:
omniroute:
image: omniroute:latest
volumes:
# Linux host
- "${HOME}/.config/zed:/host-zed-config:ro"
# macOS host (uncomment instead)
# - "${HOME}/Library/Application Support/Zed:/host-zed-config:ro"
environment:
# Future: ZED_CONFIG_PATH=/host-zed-config
PORT: "20128"
```
Note: a `ZED_CONFIG_PATH` environment variable override is not yet implemented. This
snippet is provided as a reference for when that feature is added.
## Manual Import API
The manual import endpoint can also be called directly:
```
POST /api/providers/zed/manual-import
Content-Type: application/json
Authorization: Bearer <management-token>
{
"provider": "openai",
"token": "sk-...",
"label": "My Zed OpenAI key" // optional
}
```
On success it returns:
```json
{ "success": true, "connectionId": "...", "provider": "openai" }
```
## Troubleshooting
| Symptom | Cause | Fix |
| ------------------------------------ | ---------------------------- | -------------------------------- |
| 422 + `zedDockerEnvironment: true` | Running inside Docker | Use Manual Token Import tab |
| 404 + `zedInstalled: false` | Zed not installed on host | Install Zed or use manual import |
| 403 + keychain access denied | OS denied keychain access | Grant permission in OS prompt |
| 404 + keychain service not available | `libsecret` missing on Linux | Install `libsecret-1-dev` |
+5
View File
@@ -0,0 +1,5 @@
{
"title": "Providers",
"description": "Provider-specific integration guides",
"pages": ["CLAUDE_WEB", "AGENTROUTER", "ZED-DOCKER"]
}