Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
b90190d
fix(usage): propagate claude usage.speed into response service tier
luispater Oct 22, 2026
a014ba0
test(pluginhost,handlers): fix flaky races in plugin load and stream …
luispater Oct 22, 2026
13874f1
fix(pluginhost): pass decoded request body to frontend auth plugins
luispater Oct 22, 2026
4550161
fix(gemini): enable server-side tool invocations when mixing built-in…
luispater Oct 22, 2026
d946c4f
feat(codex): ignore use_siwc and enforce non-SIWC credentials for Cod…
luispater Oct 23, 2026
e45f942
feat(home): add cluster latency telemetry and probing
hkfires Oct 23, 2026
41a4b9f
Merge pull request #6903 from router-for-me/home
hkfires Oct 23, 2026
376015c
fix(codex): map commentary phase messages to thinking blocks in Claud…
luispater Oct 23, 2026
e1fb252
fix(claude): preserve tool arguments for implicitly open empty object…
luispater Oct 23, 2026
e5434f6
fix(signature): sign the first Gemini function call after a text part
luispater Oct 23, 2026
83cb1b9
fix(gemini): populate token limits in Gemini model catalog responses
luispater Oct 23, 2026
3f5d3a1
fix(gemini/vertex): preserve non-content finish reasons and surface p…
luispater Oct 23, 2026
29150a2
fix(schema): preserve Gemini $ref sibling constraints
luispater Oct 23, 2026
888f238
fix(api): add RESP protocol bounds validation and connection panic re…
luispater Oct 23, 2026
8289ec4
fix(usage): preserve interactions token semantics when merging stream…
luispater Oct 23, 2026
0d3ca1d
fix(store,home): handle repository index and packfile corruption and …
luispater Oct 24, 2026
ab139b4
fix(kimi): share thinking replay across K3.1 Pro variants
sususu98 Oct 24, 2026
da21f1e
fix(antigravity): restore non-stream tool signatures and preserve str…
luispater Oct 24, 2026
9d08f0d
fix(pluginhost): strip credential headers across cross-origin redirects
luispater Oct 24, 2026
44d1ddf
fix(pluginhost): translate plugin count_tokens replies as token counts
luispater Oct 24, 2026
35e834d
feat(pluginabi): carry retry-after metadata from plugin executor errors
luispater Oct 24, 2026
50147ae
fix(home): close underlying transport synchronously when canceling re…
luispater Oct 24, 2026
e42eee6
fix(pluginhost): apply user payload rules to plugin executor requests
luispater Oct 24, 2026
c9af529
fix(pluginhost): run canonical thinking pipeline before plugin execution
luispater Oct 24, 2026
179d43d
fix(logging): prevent path traversal vulnerabilities in request log f…
luispater Oct 24, 2026
bc06434
docs: remove outdated third-party extensions and apps from readmes
luispater Oct 24, 2026
2bb6ac6
fix(lint): resolve go vet lostcancel and static analysis warnings fro…
luispater Oct 24, 2026
6340fe4
fix(codex): bind duplex websocket turns to requested client model aft…
luispater Oct 24, 2026
3e7a21e
fix(openai): isolate duplex turn reauthorization from gin context and…
luispater Oct 24, 2026
32dd2c8
fix(watcher): preserve file snapshot binding on persisted auth updates
luispater Oct 24, 2026
2155350
fix(auth): restore re-logged credentials to rotation after refresh fa…
luispater Oct 24, 2026
b2fda98
fix(util): defer Gemini array placeholder items until after ref and a…
luispater Oct 24, 2026
6b56ce6
perf(thinking): skip document copies when deleting absent fields
JohnsonRan Oct 24, 2026
e48d780
fix(plugin): preserve caller scope for replayed Claude OAuth MCP tool…
luispater Oct 25, 2026
0c61b12
fix(xai): deduplicate tools when promoting historical additional_tools
luispater Oct 25, 2026
ce433b3
fix(cliproxy): back off home subscriber retries
hkfires Oct 25, 2026
cf4fc4e
Merge pull request #6969 from router-for-me/home
sususu98 Oct 25, 2026
ba06ec5
fix(vertex): default credential location to global
LTbinglingfeng Oct 25, 2026
bdde391
fix(translator): preserve finishReason in Codex and OpenAI to Gemini …
luispater Oct 25, 2026
3dae075
feat(devin): aggregate swe-2 lightning UIDs into swe-2-lightning model
luispater Oct 25, 2026
27f3abf
feat(management): support session-scoped OAuth proxy with per-account…
luispater Oct 25, 2026
0fe4cc2
fix(openai): report buffered stream error when responses websocket da…
luispater Oct 25, 2026
90fe5b2
fix(handlers): report stream cancellation when channel closes with ca…
luispater Oct 25, 2026
84e8344
test(executor): fix race conditions in flaky websocket executor tests
luispater Oct 25, 2026
3078035
fix(aistudio): translate every SSE frame of a relay stream chunk
luispater Oct 25, 2026
712e497
fix(handlers): report cancellation when stream closes before first chunk
luispater Oct 25, 2026
e5321f5
fix(auth,pluginapi,usage): share per-selection ID between Scheduler.P…
luispater Oct 25, 2026
064e008
feat(codex): add full-chain compression for Codex upstream and downst…
luispater Oct 26, 2026
43f5386
fix(translator): map Claude thinking_tokens to reasoning_tokens in Op…
luispater Oct 26, 2026
531721b
fix(codex): restore Codex commentary history via internal thinking si…
luispater Oct 26, 2026
058b803
fix(api): explicitly allow Authorization in CORS preflight responses
luispater Oct 26, 2026
6fe654b
perf(pluginhost): gate request interceptor body delivery behind schem…
luispater Oct 26, 2026
ede07ca
fix(interactions): emit [DONE] sentinel after terminal usage frame in…
luispater Oct 26, 2026
8a982a5
feat(discovery): align TXT schema with draft-su-ai-gateway-discovery-00
sususu98 Oct 26, 2026
b214385
chore(config): deprecate discovery advertise-management
sususu98 Oct 26, 2026
1d45a5f
fix(claude): handle forced tool restrictions in claude 5.5
luispater Oct 26, 2026
37bd18b
fix(antigravity): accept bare content-block lists in interactions input
luispater Oct 26, 2026
11e5f67
fix(discovery): resolve split mDNS responses with scoped bounded caches
sususu98 Oct 26, 2026
999526c
docs(discovery): describe LAN resolution limits and trust boundaries
sususu98 Oct 26, 2026
aa4130e
fix(gemini): keep truncated HTTP 200 streams out of credential cooldo…
luispater Oct 26, 2026
ec81e70
Merge pull request #7010 from sususu98/feat/discovery-ietf-draft
sususu98 Oct 26, 2026
58a4d04
fix(signature): recognize Vertex bare-Tink Gemini thought signatures
sususu98 Oct 26, 2026
1398f27
fix(signature): scope Vertex bare-Tink replay to Vertex targets
sususu98 Oct 26, 2026
1f917e7
docs(readme): remove APIMart sponsor sections and assets
luispater Oct 26, 2026
c376712
Merge pull request #6959 from JohnsonRan/patch/thinking-delete-missin…
luispater Oct 26, 2026
9a35fa1
fix(codex): treat turn_rate_limit_exceeded as transient capacity with…
luispater Oct 26, 2026
1939853
feat(codex): add workspace and cloud agent orchestrator restrictions …
luispater Oct 26, 2026
a8582fb
fix(signature): pin Vertex bare-Tink recognition to observed key ids
sususu98 Oct 27, 2026
023dd2a
Merge pull request #7016 from sususu98/fix/vertex-gemini-thought-sign…
sususu98 Oct 27, 2026
be929f0
fix(interactions): normalize gemini stream sse lines
luispater Oct 27, 2026
7517549
fix(signature): do not reject Antigravity CAQS signatures by channel ID
sususu98 Oct 27, 2026
437386d
Merge pull request #7042 from sususu98/fix/antigravity-caqs-channel-id
sususu98 Oct 27, 2026
908e95d
fix(models): preserve channel prefix in Gemini model names during pre…
luispater Oct 27, 2026
10417e5
feat(registry,management): support on-demand v8 management refresh fo…
luispater Oct 27, 2026
f73e66a
fix(responses-ws): keep downstream websocket open on upstream Codex d…
luispater Oct 27, 2026
b4f59d7
fix(devin): log apply_patch rejection diagnostics and recover complet…
luispater Oct 27, 2026
826bb16
fix(images): apply payload default rules to xAI image endpoints
luispater Oct 27, 2026
6431612
feat(translator): support Vertex streaming functionCall partialArgs c…
luispater Oct 27, 2026
86a1aab
fix(codex): retry another credential on early websocket 429 without c…
luispater Oct 27, 2026
b744221
fix(auth,usage): snapshot request state to avoid reading reused gin.C…
luispater Oct 27, 2026
477605d
fix(api): prevent incomplete unauthenticated request bodies from exha…
luispater Oct 27, 2026
ad8bdd3
fix(middleware): bound zstd decompression output and window in reques…
luispater Oct 27, 2026
fa920e1
chore: merge upstream/main through ad8bdd3f
jiroamato Oct 27, 2026
d3868c8
test(api): keep auth assertion in transcription trace by disabling re…
jiroamato Oct 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
12 changes: 0 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,6 @@ PackyCode provides special discounts for our software users: register using <a h
<td>Bestproxy provides high-purity residential IPs with dedicated one-IP-per-account support. 🟡Residential Proxy - &#36;0.5/GB;🟡Static Residential Proxy - Starting at &#36;3/IP;🟡Unlimited Residential Proxy - Starting at &#36;67/Day. ✅<a href="https://bestproxy.com/?keyword=ayh7otlb">Get Free Trial.</a></td>
</tr>
<tr>
<td width="180"><a href="https://go.apimart.ai/gh-cliproxyapi"><img src="./assets/apimart-en.png" alt="APIMart" width="150"></a></td>
<td>Thanks to APIMart for sponsoring this project! APIMart is a low-cost API platform for AI image &amp; video generation — GPT-Image-2 from &#36;0.006/image, 160+ images per dollar. One async API covers both image and video: submit a task, get an ID, fetch results via polling or callback. Batch tens of thousands of images without timeouts, switch models without changing code. Pay-as-you-go with no monthly fee — <a href="https://go.apimart.ai/gh-cliproxyapi">sign up here</a> to get started.</td>
</tr>
<tr>
<td width="180"><a href="https://www.swiftproxy.net/?code=PR67S9A95"><img src="./assets/swiftproxy.png" alt="Swiftproxy" width="150"></a></td>
<td>Swiftproxy provides 90M+ clean residential IPs across 220+ locations, supporting HTTP(S)/SOCKS5, IP rotation, Sticky Sessions, and precise location targeting. It helps AI API tools and automation workflows access online services reliably from different locations, making it ideal for API requests, web access, data collection, and location-based testing. Residential proxies from &#36;0.7/GB. Free testing is available, with 10% off using code PROXY90. <a href="https://www.swiftproxy.net/?code=PR67S9A95">Try Swiftproxy Now</a></td>
</tr>
Expand Down Expand Up @@ -305,14 +301,6 @@ Native macOS menu bar app that unifies Claude, Gemini, OpenAI, and Antigravity s

Windows-native CLIProxyAPI fork with TUI, system tray, and multi-provider OAuth for AI coding tools - no API keys needed.

### [Claude Proxy VSCode](https://github.com/uzhao/claude-proxy-vscode)

VSCode extension for quick switching between Claude Code models, featuring integrated CLIProxyAPI as its backend with automatic background lifecycle management.

### [ZeroLimit](https://github.com/0xtbug/zero-limit)

Windows desktop app built with Tauri + React for monitoring AI coding assistant quotas via CLIProxyAPI. Track usage across Gemini, Claude, OpenAI Codex, and Antigravity accounts with real-time dashboard, system tray integration, and one-click proxy control - no API keys needed.

### [CPA-XXX Panel](https://github.com/ferretgeek/CPA-X)

A lightweight web admin panel for CLIProxyAPI with health checks, resource monitoring, real-time logs, auto-update, request statistics and pricing display. Supports one-click installation and systemd service.
Expand Down
12 changes: 0 additions & 12 deletions README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,6 @@ PackyCode 为本软件用户提供了特别优惠:使用<a href="https://www.p
<td>感谢 Cubence 对本项目的赞助!Cubence 是一家可靠高效的 API 中转服务商,提供 Claude Code、Codex、Gemini 等多种服务的中转。Cubence 为本软件用户提供了特别优惠:使用<a href="https://cubence.com/signup?code=CLIPROXYAPI&source=cpa">此链接</a>注册,并在充值时输入 "CLIPROXYAPI" 优惠码即可享受九折优惠。</td>
</tr>
<tr>
<td width="180"><a href="https://go.apimart.ai/gh-cliproxyapi"><img src="./assets/apimart-zh.png" alt="APIMart" width="150"></a></td>
<td>感谢 APIMart 赞助了本项目!APIMart 是专注 AI 图片/视频生成的低价 API 平台,GPT-Image-2 低至 &#36;0.006/张,1 美元可出图 160+ 张。图片、视频一套异步 API 通吃,提交任务拿 ID、回调取结果,跑批万张不超时、换模型不改代码。按量付费、无月费,通过<a href="https://go.apimart.ai/gh-cliproxyapi">此注册链接</a>注册即可开用。</td>
</tr>
<tr>
<td width="180"><a href="https://www.swiftproxy.net/?code=PR67S9A95"><img src="./assets/swiftproxy.png" alt="Swiftproxy" width="150"></a></td>
<td>Swiftproxy 提供 9000万+ 纯净住宅 IP,覆盖全球 220+ 个国家和地区,支持 HTTP(S)/SOCKS5、IP 轮换、Sticky Session 及精准地域定位。帮助 AI API 工具和自动化工作流从不同地区稳定访问在线服务,适用于 API 请求、网页访问、数据采集及地域测试等场景。住宅代理低至 &#36;0.7/GB,支持免费测试,使用优惠码 PROXY90 可享 9 折优惠。<a href="https://www.swiftproxy.net/?code=PR67S9A95">立即体验 Swiftproxy</a>。</td>
</tr>
Expand Down Expand Up @@ -204,14 +200,6 @@ CLI 封装器,用于通过 CLIProxyAPI OAuth 即时切换多个 Claude 账户

原生 Windows CLIProxyAPI 分支,集成 TUI、系统托盘及多服务商 OAuth 认证,专为 AI 编程工具打造,无需 API 密钥。

### [Claude Proxy VSCode](https://github.com/uzhao/claude-proxy-vscode)

一款 VSCode 扩展,提供了在 VSCode 中快速切换 Claude Code 模型的功能,内置 CLIProxyAPI 作为其后端,支持后台自动启动和关闭。

### [ZeroLimit](https://github.com/0xtbug/zero-limit)

Windows 桌面应用,基于 Tauri + React 构建,用于通过 CLIProxyAPI 监控 AI 编程助手配额。支持跨 Gemini、Claude、OpenAI Codex 和 Antigravity 账户的使用量追踪,提供实时仪表盘、系统托盘集成和一键代理控制,无需 API 密钥。

### [CPA-XXX Panel](https://github.com/ferretgeek/CPA-X)

面向 CLIProxyAPI 的 Web 管理面板,提供健康检查、资源监控、日志查看、自动更新、请求统计与定价展示,支持一键安装与 systemd 服务。
Expand Down
12 changes: 0 additions & 12 deletions README_JA.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,6 @@ PackyCodeは当ソフトウェアのユーザーに特別割引を提供して
<td>Cubenceのスポンサーシップに感謝します!Cubenceは信頼性が高く効率的なAPIリレーサービスプロバイダーで、Claude Code、Codex、Geminiなどのリレーサービスを提供しています。Cubenceは当ソフトウェアのユーザーに特別割引を提供しています:<a href="https://cubence.com/signup?code=CLIPROXYAPI&source=cpa">こちらのリンク</a>から登録し、チャージ時にプロモーションコード「CLIPROXYAPI」を入力すると10%割引になります。</td>
</tr>
<tr>
<td width="180"><a href="https://go.apimart.ai/gh-cliproxyapi"><img src="./assets/apimart-en.png" alt="APIMart" width="150"></a></td>
<td>APIMartによる本プロジェクトへのご支援に感謝します!APIMartは、AI画像・動画生成に特化した低価格APIプラットフォームです。GPT-Image-2は1枚あたりわずか&#36;0.006で、1ドルで160枚以上の画像を生成できます。画像と動画の両方を1つの非同期APIで扱えます。タスクを送信してIDを取得し、ポーリングまたはコールバックで結果を受け取れます。数万枚規模の画像をタイムアウトなしでバッチ生成でき、コードを変更せずにモデルを切り替えられます。従量課金制で月額料金は不要です。<a href="https://go.apimart.ai/gh-cliproxyapi">こちらの登録リンク</a>からすぐに始められます。</td>
</tr>
<tr>
<td width="180"><a href="https://www.swiftproxy.net/?code=PR67S9A95"><img src="./assets/swiftproxy.png" alt="Swiftproxy" width="150"></a></td>
<td>Swiftproxyは、世界220以上の国と地域をカバーする9,000万以上のクリーンな住宅IPを提供し、HTTP(S)/SOCKS5、IPローテーション、Sticky Session、詳細な地域指定に対応しています。AI APIツールや自動化ワークフローが異なる地域からオンラインサービスへ安定してアクセスできるよう支援し、APIリクエスト、Webアクセス、データ収集、地域別テストなどに最適です。住宅プロキシは&#36;0.7/GBから利用でき、無料テストにも対応しています。割引コードPROXY90の使用で10%割引になります。<a href="https://www.swiftproxy.net/?code=PR67S9A95">今すぐSwiftproxyを試す</a></td>
</tr>
Expand Down Expand Up @@ -203,14 +199,6 @@ Claude、Gemini、OpenAI、Antigravityのサブスクリプションを統合し

TUI、システムトレイ、マルチプロバイダーOAuthを備えたWindows向けCLIProxyAPIフォーク - AIコーディングツール用、APIキー不要

### [Claude Proxy VSCode](https://github.com/uzhao/claude-proxy-vscode)

Claude Codeモデルを素早く切り替えるVSCode拡張機能。バックエンドとしてCLIProxyAPIを統合し、バックグラウンドでの自動ライフサイクル管理を搭載

### [ZeroLimit](https://github.com/0xtbug/zero-limit)

CLIProxyAPIを使用してAIコーディングアシスタントのクォータを監視するTauri + React製のWindowsデスクトップアプリ。Gemini、Claude、OpenAI Codex、Antigravityアカウントの使用量をリアルタイムダッシュボード、システムトレイ統合、ワンクリックプロキシコントロールで追跡 - APIキー不要

### [CPA-XXX Panel](https://github.com/ferretgeek/CPA-X)

CLIProxyAPI向けの軽量Web管理パネル。ヘルスチェック、リソース監視、リアルタイムログ、自動更新、リクエスト統計、料金表示機能を搭載。ワンクリックインストールとsystemdサービスに対応
Expand Down
Binary file removed assets/apimart-en.png
Binary file not shown.
Binary file removed assets/apimart-zh.png
Binary file not shown.
20 changes: 18 additions & 2 deletions cmd/fetch_devin_models/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,15 @@ var devinCompoundSuffixes = []struct {
{suffix: "-thinking", effort: ""},
{suffix: "-max-1m", effort: "max", readd: "-1m"},
{suffix: "-none-1m", effort: "none", readd: "-1m"},
// Lightning tier keeps the effort before the -lightning suffix upstream
// (e.g. swe-2-high-lightning), so it aggregates as <base>-lightning.
{suffix: "-minimal-lightning", effort: "minimal", readd: "-lightning"},
{suffix: "-low-lightning", effort: "low", readd: "-lightning"},
{suffix: "-medium-lightning", effort: "medium", readd: "-lightning"},
{suffix: "-high-lightning", effort: "high", readd: "-lightning"},
{suffix: "-xhigh-lightning", effort: "xhigh", readd: "-lightning"},
{suffix: "-max-lightning", effort: "max", readd: "-lightning"},
{suffix: "-none-lightning", effort: "none", readd: "-lightning"},
}

var devinSimpleEffortSuffixes = []struct {
Expand Down Expand Up @@ -571,12 +580,19 @@ func aggregateModels(raw []rawDevinModel) []devinModelJSON {
}
}

// Lightning display names strip both the effort word and "Lightning";
// re-append it so swe-2-lightning shows as "SWE-2 Lightning".
displayName := entry.displayName
if strings.HasSuffix(id, "-lightning") && !strings.HasSuffix(strings.ToLower(displayName), "lightning") {
displayName = strings.TrimSpace(displayName + " Lightning")
}

res = append(res, devinModelJSON{
ID: entry.baseID,
Object: "model",
Type: "devin",
OwnedBy: vendorName(entry.vendorID, entry.baseID),
DisplayName: entry.displayName,
DisplayName: displayName,
ContextLength: entry.contextLength,
MaxCompletionTokens: 64000,
SupportedInputModalities: modalities,
Expand All @@ -595,7 +611,7 @@ var devinDisplayNameSuffixes = []string{
" Low Thinking", " Medium Thinking", " High Thinking", " XHigh Thinking",
" Max Thinking", " No Thinking",
" Low", " Medium", " High", " XHigh", " Max", " None", " Minimal",
" Thinking", " Fast",
" Thinking", " Fast", " Lightning",
}

func cleanDisplayName(label string) string {
Expand Down
3 changes: 3 additions & 0 deletions cmd/fetch_devin_models/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ func TestSplitDevinUID(t *testing.T) {
{"swe-1-6-slow", "swe-1-6-slow", ""},
{"swe-1-6-fast", "swe-1-6", ""},
{"swe-2", "swe-2", ""},
{"swe-2-medium-lightning", "swe-2-lightning", "medium"},
{"swe-2-high-lightning", "swe-2-lightning", "high"},
{"swe-2-max-lightning", "swe-2-lightning", "max"},
}

for _, tt := range tests {
Expand Down
29 changes: 26 additions & 3 deletions config.example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@ server:
# Default is 0 (disabled / no limit).
max-request-body-bytes: 0

# Negotiated compression of downstream HTTP responses (including SSE streams).
# Responses are compressed only when the client advertises zstd or gzip in
# Accept-Encoding; WebSocket upgrades are never wrapped.
response-compression:
# Default: true.
enabled: true
# Non-streaming responses smaller than this many bytes are sent uncompressed.
min-bytes: 1024

# Global token for GitHub requests (for example, release and asset downloads).
# A non-empty config token takes precedence over the GITHUB_TOKEN environment variable.
# Leave empty to use GITHUB_TOKEN, or unauthenticated requests if neither is set.
Expand All @@ -58,6 +67,9 @@ server:

# Enable local network mDNS / DNS-SD service discovery (RFC 6762 / RFC 6763).
# When enabled, broadcasts _ai-gateway._tcp with API protocol subtypes on the local network.
# TXT records follow draft-su-ai-gateway-discovery-00:
# txtvers, path, tls, auth, protocols, auth_type, product, id, role
# The TXT protocols list mirrors the advertised subtypes. Management endpoints are never advertised.
# NOTE for Docker users: Link-local multicast (224.0.0.251) cannot cross default NAT bridge networks.
# To broadcast across the physical LAN, run the container with host networking (--net=host / network_mode: host).
discovery:
Expand All @@ -70,12 +82,12 @@ server:
# - "_messages"
# - "_generate-content"
# - "_interactions"
# # Optional extended subtypes: _completions, _responses-ws, _realtime, _images,
# # _videos, _audio, _count-tokens, _search
# interfaces:
# include: [] # White-listed interfaces (empty: auto-detect physical interfaces)
# exclude: [] # Additional interface patterns to exclude
# auth-required: true # Advertise that credentials are required

# advertise-management: false # Advertise management availability
# auth-required: true # Advertise auth=1 (credentials required)

# Management API settings
management:
Expand Down Expand Up @@ -342,6 +354,17 @@ upstream:
# Experimental full-duplex Codex Responses WebSocket steering (default: false).
# Keeps one upstream account/model per socket; accepted input is never replayed.
response-steering: false
# Compress request bodies sent to the ChatGPT Codex backend with zstd,
# mirroring the official Codex client. Applies only to OAuth credentials
# targeting https://chatgpt.com/backend-api/codex (API-key credentials,
# custom base URLs, and SIWC requests are never compressed). A 400/415
# rejection is retried once with an uncompressed body. Default: false.
upstream-request-compression: false
# Request bodies smaller than this many bytes are sent uncompressed.
upstream-request-compression-min-bytes: 1024
# Enable permessage-deflate compression on Codex WebSocket connections
# (upstream and downstream) after negotiation. Default: true.
websocket-compression: true
# Disable forcing the official Codex User-Agent and Originator headers on HTTP/SSE and WebSocket requests.
disable-codex-cloaking: false
# Hold back the frames that carry nothing the client has seen - the handshake (response.created,
Expand Down
86 changes: 86 additions & 0 deletions docs/lan-discovery.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# LAN AI gateway discovery

CPA advertises `_ai-gateway._tcp` using the profile in
[draft-su-ai-gateway-discovery-00](https://datatracker.ietf.org/doc/draft-su-ai-gateway-discovery/).
Discovery is opt-in. Management routes are never advertised; the deprecated
`advertise-management` configuration field is accepted but ignored.

## TXT records

Advertisements place `txtvers`, `path`, `tls`, and `auth` first. Optional keys
are `protocols`, `auth_type`, `product`, `id`, and `role`, in that order.
Each character-string is at most 255 bytes and the complete TXT payload,
including length prefixes, is at most 400 bytes. Optional values are omitted
whole when they do not fit. The capability list is derived from advertised
subtypes. Version 1 booleans use `0` and `1`.

Browsers compare ASCII keys case-insensitively without trimming whitespace.
The first occurrence wins, including bare keys. Unsupported `txtvers` or invalid
required attributes cannot fall back to the old CPA schema. Known draft values
must satisfy the profile's printable ASCII and token syntax. Unknown protocol
and authentication tokens remain in `raw_txt` but are not exposed as recognized
capabilities or assigned operation URLs.

Legacy CPA advertisements using `version=1`, `api_*`, and `auth_required` are
accepted separately. If their optional `protocols` list was omitted, only the
advertised API base paths are exposed; no operation support is inferred.

## Resolution and interface scope

The browser uses a bounded, per-interface DNS record cache rather than the
zeroconf dependency's single-packet browse implementation. PTR, SRV, TXT, A,
and AAAA may arrive in separate packets in any order. Missing records are
queried with exponential backoff, while known PTR lifetimes independently
trigger refreshes before expiry. Repeated queries include fresh known answers;
long lists use bounded, TC-marked continuation packets. TTL expiration,
cache-flush, and goodbye one-second grace periods apply. At cache capacity,
flush replacements take precedence over the old records being retired. Expired records do not remain in returned
results. Full subtype queries such as `_responses._sub._ai-gateway._tcp` resolve
the PTR target's main service records.

Only responses from UDP port 5353 on selected interfaces are accepted. Receive
interface and destination control messages are required; platforms unable to
provide them fail closed. Multicast responses must target the standard mDNS
group; unicast responses must target a local interface address and originate
on-link (RFC 6762 Section 11). Joining a multicast group alone is not treated
as receive isolation. Default interface selection follows CPA's physical LAN
filter and never falls back to all interfaces.

Loopback, unspecified, multicast, and limited-broadcast addresses are filtered.
IPv6 link-local results retain their receiving interface in `ipv6_zones`, keyed
by address string. `interface_index` distinguishes same-name instances on
different links. Consumers must use the zone when connecting to a link-local
address. CLI WebSocket URLs use `ws`/`wss`; scoped URI hosts escape the zone
separator as `%25`. Unscoped link-local addresses are not offered as usable
connection targets.

The cache admits at most 256 service instances, 17,408 resource records, and
4 MiB of accounted record storage. Address RRsets are capped at 64 combined
IPv4/IPv6 addresses per host/interface; TXT records have at most 64 strings.
Legacy TXT input is capped at 16 KiB; draft input remains capped at 400 bytes.
These bounds constrain retained data, not transient allocations made by the
DNS packet decoder or exact process heap usage.

`Browse` honors its caller's context without imposing an internal deadline.
Cancellation closes sockets, joins reader goroutines, and returns the currently
valid partial results. Reaching 256 resolved services may end the scan early.

## Trust boundary

mDNS is unauthenticated. Source/interface validation reduces accidental and
off-link candidate pollution; it does not authenticate an on-link advertiser.
Neither `product`, `id`, instance names, nor advertised hostnames establish trust.
The discover CLI displays candidates and never connects to them or sends keys.
Clients must obtain user approval or match preconfigured trust rules before
connecting, validate TLS identity independently when applicable, and never
forward credentials to a different origin automatically. Querying model
catalogs is optional; `auth=1` catalogs require credentials.

## Verification

Deterministic tests exercise all 120 orderings of the five resolution records,
TTL/cache-flush/goodbye behavior, per-interface separation, source acceptance,
subtype resolution, size boundaries, legacy compatibility, and scoped URLs.
The existing live multicast integration test additionally checks discovery of
CPA's advertiser on the local machine. This is not a complete RFC conformance
or cross-platform network test suite.
Loading
Loading