Skip to content

Commit 5873bab

Browse files
committed
docs: reposition auth split and benchmark clarity
1 parent 21b43c3 commit 5873bab

11 files changed

Lines changed: 130 additions & 25 deletions

File tree

.codex-plugin/plugin.json

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "codex-fast-proxy",
33
"version": "0.1.0",
4-
"description": "Codex App proxy for third-party OpenAI-compatible Responses API providers with Fast/Priority controls.",
4+
"description": "Codex App auth-split proxy for signing in with ChatGPT while using third-party OpenAI-compatible APIs.",
55
"author": {
66
"name": "gaoguobin",
77
"url": "https://github.com/gaoguobin"
@@ -19,13 +19,15 @@
1919
"responses-api",
2020
"fast-mode",
2121
"service-tier",
22-
"openai-compatible-api"
22+
"openai-compatible-api",
23+
"chatgpt-login",
24+
"auth-split"
2325
],
2426
"skills": "./skills/",
2527
"interface": {
2628
"displayName": "Codex Fast Proxy",
27-
"shortDescription": "Third-party API proxy for Codex App with Fast/Priority controls.",
28-
"longDescription": "Manage a local, safety-bounded proxy and Agent Skill so Codex App users on third-party OpenAI-compatible API providers can preserve the App Fast toggle, optionally force global Fast/Priority, split upstream auth for ChatGPT login, verify traffic, benchmark, update, and uninstall.",
29+
"shortDescription": "Use Codex App sign-in with third-party API providers.",
30+
"longDescription": "Manage a local, safety-bounded proxy and Agent Skill so Codex App users can sign in with ChatGPT for UI features while model requests continue through a third-party OpenAI-compatible provider. It supports upstream auth split, App-controlled Fast/Priority behavior, benchmark verification, update, and uninstall workflows.",
2931
"developerName": "gaoguobin",
3032
"category": "Developer Tools",
3133
"capabilities": [
@@ -34,16 +36,17 @@
3436
"Benchmark"
3537
],
3638
"websiteURL": "https://github.com/gaoguobin/codex-fast-proxy",
37-
"privacyPolicyURL": "https://github.com/gaoguobin/codex-fast-proxy#safety-model",
39+
"privacyPolicyURL": "https://github.com/gaoguobin/codex-fast-proxy#safety",
3840
"termsOfServiceURL": "https://github.com/gaoguobin/codex-fast-proxy/blob/main/LICENSE",
3941
"defaultPrompt": [
4042
"Enable Codex Fast proxy.",
43+
"Prepare Codex Fast proxy for ChatGPT account login.",
4144
"Show Codex Fast proxy status.",
4245
"Run Codex Fast proxy benchmark."
4346
],
4447
"brandColor": "#10A37F",
4548
"screenshots": [
46-
"./docs/assets/dashboard.png"
49+
"./docs/assets/hero.png"
4750
]
4851
}
4952
}

README.md

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,60 @@
22

33
[![CI](https://github.com/gaoguobin/codex-fast-proxy/actions/workflows/ci.yml/badge.svg)](https://github.com/gaoguobin/codex-fast-proxy/actions/workflows/ci.yml)
44

5-
Codex App Fast/Priority proxy for third-party OpenAI-compatible APIs.
5+
Codex App auth-split proxy for third-party OpenAI-compatible APIs.
66

7-
This project is for Codex App users who already use a third-party API provider or relay service.
8-
It lets Codex App route model requests through a local proxy, keep streaming intact, preserve the
9-
App's own Fast control when available, and optionally inject `service_tier="priority"` when Codex
10-
does not send a tier.
7+
Use Codex App while you sign in with ChatGPT for the full App UI, but keep model requests on your
8+
third-party OpenAI-compatible API provider. `codex-fast-proxy` routes provider traffic through a
9+
local proxy, applies an optional provider-auth override, preserves streaming, and keeps the App's
10+
own Fast controls intact when they are available.
1111

1212
[Chinese Guide](docs/README.zh-CN.md) · [Quick Start](#quick-start) · [Common Workflows](#common-workflows) · [Dashboard](#dashboard) · [Safety](#safety) · [Advanced Usage](docs/advanced-usage.md) · [Sponsor](#sponsor)
1313

14-
![Codex Fast Proxy dashboard](docs/assets/dashboard.png)
14+
![Codex Fast Proxy overview](docs/assets/hero.png)
15+
16+
[Watch the 10-second overview video](docs/assets/codex-fast-proxy-promo.mp4)
1517

1618
## Why
1719

18-
Codex CLI can already use Fast mode. The main use case here is Codex App + third-party API
19-
providers, where users may still want the richer App experience: plugin marketplace, GitHub/Apps
20-
connectors, manual Fast controls, status hints, voice input, and a local dashboard.
20+
Codex App features such as plugin marketplace, GitHub/Apps connectors, manual Fast controls, status
21+
hints, and voice input are tied to signing in with ChatGPT. Users of third-party API providers still
22+
need model requests to use the provider's endpoint and API key.
23+
24+
This project keeps those two concerns separate: Codex App can stay signed in with ChatGPT for UI and
25+
connector features, while `/v1/responses` model traffic continues through your configured provider.
26+
Fast/Priority routing is then treated as a provider capability that should be measured, not assumed.
2127

2228
## What It Does
2329

30+
- Lets Codex App stay signed in with ChatGPT while provider API requests use your third-party
31+
upstream.
2432
- Routes Codex provider traffic from `http://127.0.0.1:8787/v1` to your saved upstream provider.
33+
- Optionally replaces proxied provider `Authorization` with a key from an environment variable, so
34+
ChatGPT account auth is not forwarded to the third-party provider.
2535
- Only patches `POST /v1/responses`, and only when the configured Fast policy allows it.
2636
- Leaves `model`, `reasoning`, `tools`, `input`, request bodies, and SSE frames unchanged.
27-
- Supports an optional auth split for ChatGPT-login users: provider API requests can use a separate
28-
environment variable while ChatGPT plugin/GitHub/App connector traffic remains untouched.
37+
- Preserves Codex App's manual Fast controls when the App sends its own `service_tier`.
2938
- Installs a Codex `SessionStart` hook so future Codex sessions can start a missing proxy.
3039
- Provides a read-only local dashboard with redacted status, recent traffic, and benchmark summary.
3140

41+
## Fast Effect
42+
43+
Fast/Priority is an important feature, but it is not a local guarantee. This proxy can send the
44+
priority hint, but the real latency effect depends on the upstream OpenAI-compatible provider. Some
45+
providers accept `service_tier="priority"` without making the measured workload faster, and some may
46+
not echo priority metadata in the response.
47+
48+
Use the built-in A/B benchmark as the source of truth for your current provider and model:
49+
50+
```text
51+
Run the Codex Fast proxy A/B benchmark
52+
```
53+
54+
Benchmark results separate three facts: whether priority requests were accepted, whether the
55+
measured workload got faster, and whether provider response metadata explicitly confirmed priority.
56+
The benchmark also records whether the control split was valid, so default samples must omit
57+
`service_tier` while priority samples send the expected value.
58+
3259
## Quick Start
3360

3461
Paste this into Codex:
@@ -84,10 +111,11 @@ In API-key mode, the default `auto` policy can inject global priority when Codex
84111
`service_tier`. In ChatGPT-login or unclear states, the default behavior is conservative and
85112
preserves Codex's own Fast choice.
86113

87-
## ChatGPT Login
114+
## Sign In With ChatGPT
88115

89-
ChatGPT login is optional. Use it only if you want the full Codex App UI, such as plugin
90-
marketplace, GitHub/Apps/connectors, manual Fast controls, status hints, or voice input.
116+
Signing in with ChatGPT is optional. Use it only if you want the full Codex App UI, such as plugin
117+
marketplace, GitHub/Apps/connectors, manual Fast controls, status hints, or voice input. The proxy's
118+
auth split keeps model requests on your third-party provider after that sign-in.
91119

92120
Before switching Codex App to ChatGPT login, ask Codex to prepare provider auth:
93121

docs/README.zh-CN.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# codex-fast-proxy 中文指南
22

3-
`codex-fast-proxy` 面向使用兼容 OpenAI API 的第三方供应商的 Codex App 用户。它把 Codex App 的模型请求转到本地代理,再转发到第三方上游;默认尊重 Codex App 自己的 Fast 选择,也可以在 API-key 模式下补缺失的 `service_tier="priority"`
3+
`codex-fast-proxy` 面向使用兼容 OpenAI API 的第三方供应商的 Codex App 用户。核心用途是让 Codex App 可以保持 ChatGPT 账户登录,继续使用插件市场、GitHub/Apps/connectors、Fast 手动选择、状态提示和语音输入等 UI 能力,同时把模型请求转到第三方上游。
4+
5+
Fast/Priority 是重要能力,但实际是否加速取决于上游 API 提供商是否支持;请以 A/B benchmark 的结果为准。
46

57
[返回英文 README](../README.md)
68

docs/advanced-usage.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,8 @@ python -m codex_fast_proxy benchmark --api-key-env PACKY_API_KEY
174174

175175
Interpretation:
176176

177+
- `service_tier_control.valid=true`: default samples omitted `service_tier` and priority samples sent
178+
the expected value.
177179
- `priority_accepted=true`: at least one priority sample succeeded.
178180
- `observed_priority_effective=true`: the measured workload benefited.
179181
- `provider_confirmed_priority=true`: provider response metadata explicitly confirmed priority when
863 KB
Binary file not shown.

docs/assets/dashboard.png

-771 KB
Binary file not shown.

docs/assets/hero.png

76.5 KB
Loading

pyproject.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
55
[project]
66
name = "codex-fast-proxy"
77
version = "0.1.0"
8-
description = "Codex App proxy for third-party OpenAI-compatible Responses API providers with Fast/Priority controls."
8+
description = "Codex App auth-split proxy for signing in with ChatGPT while using third-party OpenAI-compatible APIs."
99
readme = "README.md"
1010
requires-python = ">=3.11"
1111
dependencies = []
@@ -21,6 +21,8 @@ keywords = [
2121
"fast-mode",
2222
"service-tier",
2323
"openai-compatible-api",
24+
"chatgpt-login",
25+
"auth-split",
2426
]
2527
classifiers = [
2628
"License :: OSI Approved :: MIT License",

skills/codex-fast-proxy/SKILL.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
---
22
name: codex-fast-proxy
3-
description: Codex App Fast proxy for third-party OpenAI-compatible APIs. Preserves UI Fast toggles, benchmarks, changes upstream, supports ChatGPT-login upstream auth split, and optionally injects priority service_tier.
3+
description: Codex App Fast proxy and auth-split for third-party OpenAI-compatible APIs. Supports Sign in with ChatGPT, priority service_tier, Responses API benchmark, enable/check/update/uninstall.
44
---
55

6-
Use this skill when the user wants Codex to manage the local Fast proxy for Codex App.
6+
Use this skill when the user wants Codex to manage the local auth-split and Fast proxy for Codex App.
77

88
## Trigger patterns
99

@@ -207,7 +207,8 @@ For upstream URL changes after enable, prefer `set-upstream --upstream-base <url
207207
- Do not print API keys, `auth.json`, request bodies, prompts, or Codex history.
208208
- For benchmark results, report profile, medians, observed speedup, `priority_accepted`,
209209
`observed_priority_effective`, provider-confirmed priority metadata when present, sample counts,
210-
and errors. Prioritize full-response total latency and first-output latency over first-event/TTFB.
210+
`service_tier_control.valid`, and errors. Prioritize full-response total latency and first-output
211+
latency over first-event/TTFB.
211212
Treat `priority_accepted=true` as proof that the wire parameter is accepted, and
212213
`observed_priority_effective=true` as proof that this measured workload benefited. Report
213214
`benchmark_mode` and do not present Codex CLI/app-server benchmark results as an App-specific

src/codex_fast_proxy/benchmark.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,9 @@ def default_connection_factory(scheme: str, host: str, port: int | None, timeout
340340
"upgrade",
341341
}
342342

343+
ABSENT_SERVICE_TIER = "<absent>"
344+
UNKNOWN_SERVICE_TIER = "<unknown>"
345+
343346

344347
def forward_path(upstream_base: str, incoming_path: str) -> str:
345348
parsed = urlsplit(upstream_base)
@@ -656,6 +659,7 @@ def run_sample(
656659
return {
657660
"tier": label,
658661
"status": response.status,
662+
"request_service_tier": target.service_tier if label == "priority" else None,
659663
"ttfb_ms": first_event_ms,
660664
"first_event_ms": first_event_ms,
661665
"first_output_ms": first_output_ms,
@@ -696,6 +700,7 @@ def summarize_samples(samples: list[dict[str, Any]], label: str) -> dict[str, An
696700
output_char_values = [
697701
float(sample["output_chars"]) for sample in ok_samples if sample.get("output_chars") is not None
698702
]
703+
request_tiers = sorted({request_service_tier_label(sample) for sample in matching})
699704
tiers = sorted({sample["response_service_tier"] for sample in ok_samples if sample.get("response_service_tier")})
700705
return {
701706
"count": len(matching),
@@ -704,10 +709,44 @@ def summarize_samples(samples: list[dict[str, Any]], label: str) -> dict[str, An
704709
"median_ttfb_ms": median(ttfb_values),
705710
"median_first_output_ms": median(first_output_values),
706711
"median_output_chars": median(output_char_values),
712+
"request_service_tiers": request_tiers,
707713
"response_service_tiers": tiers,
708714
}
709715

710716

717+
def request_service_tier_label(sample: dict[str, Any]) -> str:
718+
if "request_service_tier" not in sample:
719+
return UNKNOWN_SERVICE_TIER
720+
value = sample.get("request_service_tier")
721+
if value is None:
722+
return ABSENT_SERVICE_TIER
723+
if isinstance(value, str) and value:
724+
return value
725+
return str(value)
726+
727+
728+
def service_tier_control(
729+
target: BenchmarkTarget,
730+
default_summary: dict[str, Any],
731+
priority_summary: dict[str, Any],
732+
) -> dict[str, Any]:
733+
default_tiers = default_summary.get("request_service_tiers", [])
734+
priority_tiers = priority_summary.get("request_service_tiers", [])
735+
valid = default_tiers == [ABSENT_SERVICE_TIER] and priority_tiers == [target.service_tier]
736+
message = (
737+
"Default samples omitted service_tier and priority samples sent the expected value."
738+
if valid
739+
else "Benchmark request tiers did not match the expected default-vs-priority split."
740+
)
741+
return {
742+
"valid": valid,
743+
"default_request_service_tiers": default_tiers,
744+
"priority_request_service_tiers": priority_tiers,
745+
"expected_priority_service_tier": target.service_tier,
746+
"message": message,
747+
}
748+
749+
711750
def speedup(default_ms: float | None, priority_ms: float | None) -> float | None:
712751
if not default_ms or not priority_ms:
713752
return None
@@ -849,6 +888,7 @@ def summarize_benchmark_result(
849888
profile = profile_for_name(target.profile)
850889
default_summary = summarize_samples(samples, "default")
851890
priority_summary = summarize_samples(samples, "priority")
891+
tier_control = service_tier_control(target, default_summary, priority_summary)
852892
total_speedup = speedup(default_summary["median_total_ms"], priority_summary["median_total_ms"])
853893
ttfb_speedup = speedup(default_summary["median_ttfb_ms"], priority_summary["median_ttfb_ms"])
854894
first_output_speedup = speedup(default_summary["median_first_output_ms"], priority_summary["median_first_output_ms"])
@@ -868,6 +908,7 @@ def summarize_benchmark_result(
868908
"samples": samples,
869909
"default": default_summary,
870910
"priority": priority_summary,
911+
"service_tier_control": tier_control,
871912
"observed_speedup_total": total_speedup,
872913
"observed_speedup_ttfb": ttfb_speedup,
873914
"observed_speedup_first_output": first_output_speedup,

0 commit comments

Comments
 (0)