A tiny Hono HTTP server that accepts OpenAI Responses API requests (e.g. from @ai-sdk/openai's openai.responses(modelId)) and forwards them to any provider supported by @mariozechner/pi-ai. Defaults to OpenAI Codex (ChatGPT Plus/Pro OAuth).
The Responses API has native event types for reasoning summaries, structured output items, and function-call argument streaming — pi-ai's unified events map to it directly with no <think> tag smuggling and no AI-SDK middleware.
- Reasoning is native. pi-ai's
thinking_*events becomeresponse.reasoning_summary_text.deltachunks; AI SDK surfaces them as properreasoning-*parts. - Auth is provider-agnostic. Swapping
PI_PROVIDERswitches between Anthropic Pro/Max OAuth, GitHub Copilot, Gemini CLI, Antigravity, OpenAI Codex, or any API-key provider — pi-ai handles refresh. - Reasoning effort per request. Send
x-pi-reasoning: minimal|low|medium|high|xhighto override the default; the request body'sreasoning.effortis also honored.
Using a ChatGPT Plus/Pro subscription (or Anthropic Pro/Max, etc.) for programmatic traffic likely violates the provider's terms. Realistic failure modes: rate-limiting, account suspension, silent capability downgrades, endpoint shape changing without notice. Personal/dev use only — do not ship this to other users.
-
Install pi-ai's CLI and log in once on the host:
cd aisdk-pi-proxy npm install npx @mariozechner/pi-ai login openai-codexThis writes
auth.jsonin the current directory. The proxy reads from the same path on startup; refreshes are written back. -
Other providers (any of
anthropic,github-copilot,google-gemini-cli,google-antigravity) work the same way —npx @mariozechner/pi-ai login <provider>, then setPI_PROVIDERaccordingly.
npm install
npm run dev # watch mode, or:
npm startSmoke-test:
RELAY_URL=http://127.0.0.1:8788 npm run test:liveSends a streaming request and prints content + reasoning bytes + tool-call deltas + usage.
GET /health— liveness + reports the active provider/model/reasoningPOST /v1/responses— Responses API in, Responses API SSE out
x-pi-reasoning: minimal | low | medium | high | xhigh— overridesPI_DEFAULT_REASONING(also overridden by the request body'sreasoning.effort)x-pi-model: <model-id>— overrides the request body'smodelfieldx-pi-session-id: <id>— passed to pi-ai assessionIdfor prompt caching (pi-ai applies this for providers that support it, e.g. OpenAI Codex)
There is no auth on /v1/*. The proxy relies on the network it's deployed on — locally that's loopback; in production that's a Cloudflare VPC subnet reachable only via a Workers VPC connector. Do not expose this on a public interface.
- Reasoning flows as
response.output_item.added(type: reasoning) →response.reasoning_summary_text.delta→response.output_item.done. AI SDK surfaces this asreasoning-start/reasoning-delta/reasoning-endparts. - Text flows as
response.output_item.added(type: message) →response.output_text.delta→response.output_item.done. - Tool calls flow as
response.output_item.added(type: function_call) →response.function_call_arguments.delta→response.output_item.donecarrying the final argument string. - Usage is reported on
response.completedasinput_tokens/output_tokens(withinput_tokens_details.cached_tokenswhen pi-ai surfaces a cache-read count). - Errors during streaming are emitted as a
response.failedframe followed bydata: [DONE]so the client doesn't hang.
aisdk-pi-proxy/
├── package.json
├── tsconfig.json
├── README.md
├── auth.json # created by `pi-ai login`, gitignored
└── src/
├── auth.ts # reads/refreshes auth.json via pi-ai/oauth
├── translate-request.ts # Responses API → pi-ai Context + Tool[]
├── translate-response.ts # pi-ai event stream → Responses API SSE
└── index.ts # Hono server
Self-contained — safe to git mv out to its own repo later.
Run on a host inside a Cloudflare VPC subnet. Bind to the private interface only — no public ingress. The Worker reaches it via a Workers VPC connector binding; the connector is the only network path, so no auth lives on the proxy itself. Same operational model as aisdk-codex-proxy.
Once this proxy is verified end-to-end against ChatGPT Plus OAuth, it can fully replace ../aisdk-codex-proxy/. The Codex auth file layouts differ — this proxy uses pi-ai's auth.json (run pi-ai login openai-codex), not Codex CLI's ~/.codex/auth.json. Until the swap is confirmed, both can coexist on different ports (8787 codex, 8788 pi).
