Spaces:
Paused
Paused
| title: p5jsAi API | |
| emoji: ๐ | |
| colorFrom: blue | |
| colorTo: purple | |
| sdk: docker | |
| pinned: false | |
| # p5js.ai 2 API | |
| [English](#english) | [ไธญๆ](#ไธญๆ) | |
| --- | |
| <a id="ไธญๆ"></a> | |
| ## p5js.ai 2 API โ ๅฐ p5js.ai ๅ ่ดนๆฅๅฃๅ ่ฃ ไธบ Anthropic / OpenAI ๅ ผๅฎน API | |
| `p5js.ai 2 API` ๆฏไธไธช่ฝป้็บง็ๅๅไปฃ็้้ ๅจ๏ผๅฐ `https://p5js.ai/api/ai-chat` ๅ ่ดน่ๅคฉๆฅๅฃๅๆถๅ ่ฃ ๆ **Anthropic Messages API** ๅ **OpenAI Chat Completions API** ๅ ผๅฎนๆฅๅฃใ | |
| ่ฟๆๅณ็ไปปไฝๆฏๆ Anthropic ๆ OpenAI ๅ่ฎฎ็ๅทฅๅ ทโโClaude CodeใChatboxใNextChatใLobeChatใone-apiใCherry Studio ็ญโโ้ฝๅฏไปฅ็ดๆฅๆฅๅ ฅ๏ผๅฐฑๅ่ฟๆฅไธไธช็ๆญฃ็ Anthropic ๆ OpenAI ็ซฏ็นไธๆ ทใ | |
| ### ๆ ธๅฟ็นๆง | |
| - **ๅๅ่ฎฎๅ ผๅฎน** โ ๅๆถๆไพ `/v1/messages`๏ผAnthropic๏ผๅ `/v1/chat/completions`๏ผOpenAI๏ผ็ซฏ็น | |
| - **Tool Use ไปฟ็** โ ไธๆธธไธๆฏๆๅ็ tool_use๏ผๆฌๆๅก้่ฟ XML ๆ ผๅผ็ `<function_calls>` ๆ็คบ่ฏๆณจๅ ฅๅฎ็ฐไผชๅทฅๅ ท่ฐ็จ๏ผๅนถ่ชๅจๅฐๅๅบไธญ็ XML ่งฃๆๅๆ ๅ `tool_use` / `tool_calls` ๆ ผๅผ | |
| - **p5.js ๅชๅฃฐ่ฟๆปค** โ ่ชๅจๆฃๆตๅนถๅฅ็ฆปไธๆธธๆณจๅ ฅ็ p5.js ๅฉๆ้ฎๅ่ฏญใๅ็ผๅๅฐพ็ผ | |
| - **SSE ไฟฎๅค** โ ไธๆธธไผ่พๅบ็ธๅฝข็ `ddata:` / `ata:` ๅ็ผ๏ผๆฌๆๅก่ชๅจไฟฎๆญฃไธบๆ ๅ SSE ๆ ผๅผ | |
| - **ๅๅฑ็ผๅญ** โ ๅ ๅญ็ผๅญ + ๅฏ้ Redis ไบ็บง็ผๅญ๏ผ็ธๅ่ฏทๆฑ่ชๅจๅฝไธญ๏ผๆตๅผ/้ๆตๅผๅ ฑ็จๅไธไปฝๅฎๆ็ปๆ | |
| - **In-flight ๅๅนถ** โ ๅนถๅ็ธๅ่ฏทๆฑไธไผ้ๅคๆไธๆธธ๏ผfollower ็ญๅพ leader ็ปๆ | |
| - **่ฟๆฅๆฑ ๅค็จ** โ ๅ ฑไบซ httpx ๅผๆญฅ่ฟๆฅๆฑ ๏ผ้ๅ้ซๅนถๅๅบๆฏ | |
| - **ไปฃ็ๆฏๆ** โ ๆฏๆ `UPSTREAM_PROXY_URL` ๆๆ ๅ `HTTP_PROXY` / `HTTPS_PROXY` ็ฏๅขๅ้ | |
| ### ้กน็ฎ็ปๆ | |
| ``` | |
| p5js/ | |
| โโโ main.py # FastAPI ๅบ็จๅ ฅๅฃใ่ทฏ็ฑๅฎไน | |
| โโโ config.py # ๅธธ้ใ็ฏๅขๅ้ใๆจกๅๅ่กจใๆญฃๅๆจกๅผ | |
| โโโ filters.py # p5.js ๅชๅฃฐ่ฟๆปคใๅทฅๅ ทๆ็ฅๆๆฌ็ผๅฒ | |
| โโโ tools.py # Tool XML ๆ็คบ่ฏๆๅปบใ่งฃๆใๆๅ | |
| โโโ translate.py # ๅ่ฎฎ่ฝฌๆข๏ผAnthropic/OpenAI โ ไธๆธธๆถๆฏๆ ผๅผ๏ผ | |
| โโโ upstream.py # ไธๆธธ HTTP ๅฎขๆท็ซฏใSSE ่งฃๆใๅฎๆถๆ่ท | |
| โโโ render.py # Artifact โ Anthropic/OpenAI JSON/SSE ๆธฒๆ | |
| โโโ stream.py # ๅฎๆถๆตๅค็๏ผๅธฆ/ไธๅธฆๅทฅๅ ท๏ผๅธฆ็ผๅญ้ๆ๏ผ | |
| โโโ response_cache.py # ๅๅฑ็ผๅญ็ณป็ป๏ผๅ ๅญ + Redis๏ผ | |
| โโโ tests/ # ๆต่ฏๅฅไปถ | |
| โ โโโ test_response_cache.py | |
| โ โโโ test_filters.py | |
| โโโ Dockerfile | |
| โโโ docker-compose.yml | |
| โโโ requirements.txt | |
| โโโ start.sh | |
| โโโ .env.example # ็ฏๅขๅ้็คบไพ | |
| โโโ README.md | |
| ``` | |
| ### ๅฟซ้ๅผๅง | |
| #### ๆฌๅฐ่ฟ่ก | |
| ```bash | |
| ./start.sh | |
| ``` | |
| ้ฆๆฌก่ฟ่กไผ่ชๅจๅๅปบ `venv` ๅนถๅฎ่ฃ ไพ่ต๏ผ็ถๅๅจ `http://127.0.0.1:18185` ็ๅฌใ | |
| #### Docker ้จ็ฝฒ | |
| ```bash | |
| # ็ดๆฅๆๅปบ | |
| docker build -t p5js2api:latest . | |
| docker run --rm -p 18185:18185 p5js2api:latest | |
| # ๆไฝฟ็จ docker compose๏ผ่ชๅธฆ Redis๏ผ | |
| docker compose up -d --build | |
| ``` | |
| ้ป่ฎค compose ้ ็ฝฎๅๆถๅฏๅจไธไธชๆฌๅฐ Redis ๅฎไพ๏ผ็ซฏๅฃ้่ฟ `P5JS2API_PORT` ็ฏๅขๅ้ๆงๅถ๏ผ้ป่ฎค `18185`๏ผใ | |
| ### ๆฏๆ็ๆจกๅ | |
| | ๆจกๅ | ่ฏดๆ | | |
| |------|------| | |
| | `claude-opus-4-7` | ๆๆฐๆ่ฐ | | |
| | `claude-opus-4-6` | | | |
| | `claude-opus-4-1` / `claude-opus-4-1-20250805` | | | |
| | `claude-opus-4-20250514` | | | |
| | `claude-sonnet-4-6` | | | |
| | `claude-sonnet-4-5` / `claude-sonnet-4-5-20250929` | **้ป่ฎคๆจกๅ** | | |
| | `claude-sonnet-4-20250514` | | | |
| | `claude-haiku-4-5` / `claude-haiku-4-5-20251001` | ่ฝป้ๅฟซ้ | | |
| ### ๆฅๅฃไธ่ง | |
| | ่ทฏๅพ | ๆนๆณ | ่ฏดๆ | | |
| |------|------|------| | |
| | `/health` | GET | ๅฅๅบทๆฃๆฅ๏ผ่ฟๅๆๅก็ถๆใ็ผๅญ็ป่ฎกใไธๆธธ้ ็ฝฎ | | |
| | `/v1/models` | GET | ๆจกๅๅ่กจ๏ผAnthropic ๆ ผๅผ๏ผ | | |
| | `/v1/messages` | POST | **Anthropic Messages API**๏ผๆฏๆ `stream` | | |
| | `/v1/chat/completions` | POST | **OpenAI Chat Completions API**๏ผๆฏๆ `stream` | | |
| > ๆๅกไธๆ ก้ช API Key๏ผไปปๆ้็ฉบๅญ็ฌฆไธฒๅๅฏ้่ฟ่ฎค่ฏใ | |
| ### ไฝฟ็จ็คบไพ | |
| #### Claude Code๏ผAnthropic ๅ่ฎฎ๏ผ | |
| ```bash | |
| export ANTHROPIC_BASE_URL=http://127.0.0.1:18185 | |
| export ANTHROPIC_AUTH_TOKEN=dummy | |
| export ANTHROPIC_MODEL=claude-opus-4-7 | |
| export ANTHROPIC_SMALL_FAST_MODEL=claude-haiku-4-5 | |
| claude | |
| ``` | |
| #### OpenAI Python SDK | |
| ```python | |
| from openai import OpenAI | |
| client = OpenAI( | |
| base_url="http://127.0.0.1:18185/v1", | |
| api_key="sk-dummy", | |
| ) | |
| resp = client.chat.completions.create( | |
| model="claude-sonnet-4-5", | |
| messages=[{"role": "user", "content": "ไฝ ๅฅฝ"}], | |
| stream=True, | |
| ) | |
| for chunk in resp: | |
| print(chunk.choices[0].delta.content or "", end="", flush=True) | |
| ``` | |
| #### ็ฌฌไธๆนๅทฅๅ ท๏ผChatbox / NextChat / LobeChat / one-api / Cherry Studio ็ญ๏ผ | |
| - **Base URL / API ๅฐๅ**: `http://127.0.0.1:18185/v1` | |
| - **API Key**: ไปปๆ้็ฉบๅญ็ฌฆไธฒ๏ผๅฆ `sk-dummy`๏ผ | |
| - **ๆจกๅๅ**: ๅกซๅไธๆนใๆฏๆ็ๆจกๅใไธญ็ไปปไธ้กน | |
| #### curl | |
| ```bash | |
| # Anthropic ๅ่ฎฎ | |
| curl http://127.0.0.1:18185/v1/messages \ | |
| -H 'content-type: application/json' \ | |
| -H 'x-api-key: dummy' \ | |
| -d '{"model":"claude-sonnet-4-5","max_tokens":1024,"messages":[{"role":"user","content":"hi"}]}' | |
| # OpenAI ๅ่ฎฎ | |
| curl http://127.0.0.1:18185/v1/chat/completions \ | |
| -H 'content-type: application/json' \ | |
| -d '{"model":"claude-sonnet-4-5","messages":[{"role":"user","content":"hi"}]}' | |
| ``` | |
| ### ็ผๅญ็ณป็ป | |
| ๆๅก้ป่ฎคๅฏ็จๅฎๆดๅๅบ็ผๅญ๏ผ | |
| - ๅ ่ตฐ่ฟ็จๅ ๅ ๅญ็ผๅญ๏ผLRU๏ผ้ป่ฎค 256 ๆก๏ผ | |
| - ้ ็ฝฎ `RESPONSE_CACHE_REDIS_URL` ๅๅ็บงไธบ **ๅ ๅญ + Redis** ๅๅฑ็ผๅญ | |
| - ็ธๅ่ฏทๆฑๅนถๅๅฝไธญ miss ๆถๅ **in-flight ๅๅนถ**๏ผ้ฟๅ ๅๆถๆ็ไธๆธธ | |
| - `stream=true` ๅ `stream=false` ๅ ฑ็จๅไธไปฝๅฎๆ็ปๆ็ผๅญ | |
| #### ็ฏๅขๅ้ | |
| ๅฎๆด็ฏๅขๅ้ๅ่กจ่ง `.env.example`๏ผๆ ธๅฟ้ ็ฝฎ๏ผ | |
| | ๅ้ | ้ป่ฎคๅผ | ่ฏดๆ | | |
| |------|--------|------| | |
| | `RESPONSE_CACHE_ENABLED` | `true` | ๆฏๅฆๅฏ็จ็ผๅญ | | |
| | `RESPONSE_CACHE_TTL_SECS` | `300` | ๆฎ้่ฏทๆฑ็ผๅญ TTL๏ผ็ง๏ผ | | |
| | `RESPONSE_CACHE_TOOL_TTL_SECS` | `120` | ๅธฆๅทฅๅ ท่ฏทๆฑ็ผๅญ TTL๏ผ็ง๏ผ | | |
| | `RESPONSE_CACHE_MAX_ENTRY_BYTES` | `33554432` | ๅๆก็ผๅญๆๅคงๅญ่ๆฐ๏ผ0 = ไธ้๏ผ | | |
| | `RESPONSE_CACHE_REDIS_URL` | โ | Redis ่ฟๆฅๅฐๅ๏ผ้ ็ฝฎๅๅฏ็จไบ็บง็ผๅญ | | |
| #### ๅๅบๅคด | |
| - `X-Proxy-Cache: HIT | MISS | BYPASS | DISABLED` | |
| - `X-Proxy-Cache-Source: memory | redis | inflight | live` | |
| #### ่ทณ่ฟ็ผๅญ | |
| ไปปไธๆนๅผ๏ผ | |
| - ่ฏทๆฑๅคด `X-Proxy-Cache: bypass` | |
| - ่ฏทๆฑๅคด `Cache-Control: no-cache` | |
| ### ไปฃ็้ ็ฝฎ | |
| ๅฎนๅจๅ ๆฏๆไธค็งไปฃ็ๆนๅผ๏ผ | |
| - ๆพๅผ่ฎพ็ฝฎ `UPSTREAM_PROXY_URL` | |
| - ๆ ๅ็ฏๅขๅ้ `HTTP_PROXY` / `HTTPS_PROXY` / `NO_PROXY` | |
| `/health` ้็ `upstream.proxy_configured` ไผๆพ็คบๅฝๅๆฏๅฆๆฃๆตๅฐไปฃ็้ ็ฝฎใ | |
| ### ๅทฅไฝๅ็ | |
| ``` | |
| โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ | |
| โ Client โโโโโโถโ p5js.ai 2 API โโโโโโถโ p5js.ai โ | |
| โ (Claude/ โโโโโโโ (this project) โโโโโโโ upstream โ | |
| โ OpenAI) โ โ โ โ โ | |
| โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ | |
| โ โโ ๅ่ฎฎ่ฝฌๆข โ | |
| โ โโ Tool XML ๆณจๅ ฅ/่งฃๆ โ | |
| โ โโ p5.js ๅชๅฃฐ่ฟๆปค โ | |
| โ โโ SSE ไฟฎๅค โ | |
| โ โโ ๅๅฑ็ผๅญ โ | |
| ``` | |
| 1. **ๅ่ฎฎ่ฝฌๆข**๏ผๅฐ Anthropic ๆ OpenAI ๆ ผๅผ็่ฏทๆฑ่ฝฌๆขไธบ p5js.ai ไธๆธธๆ ผๅผ๏ผ`messages` + `provider` + `model` + `deviceId` + `sessionId`๏ผ | |
| 2. **Tool Use ไปฟ็**๏ผๅฐๅทฅๅ ทๅฎไนๆณจๅ ฅ็ณป็ปๆ็คบ่ฏไธบ XML ๆ ผๅผ๏ผๅฐไธๆธธๆๆฌๅๅบไธญ็ `<function_calls>` XML ๅ่งฃๆๅๆ ๅ `tool_use` / `tool_calls` | |
| 3. **ๅชๅฃฐ่ฟๆปค**๏ผๆฃๆตๅนถๅฅ็ฆปไธๆธธ่ชๅจๆณจๅ ฅ็ p5.js ๅฉๆ้ฎๅ่ฏญใๆ ้ขใๅฐพ็ผๆจ่ | |
| 4. **SSE ไฟฎๅค**๏ผไธๆธธ่พๅบ็็ธๅฝข `ddata:` / `ata:` ๅ็ผ่ชๅจไฟฎๆญฃไธบๆ ๅ `data:` | |
| 5. **็ผๅญ**๏ผๅฎๆดๅๅบ็ผๅญ๏ผๆตๅผๅ้ๆตๅผๅ ฑ็จ๏ผๆฏๆ in-flight ๅๅนถ | |
| ### ๆณจๆไบ้กน | |
| - ไธๆธธ p5js.ai ไผๅจๆฒกๆ system ๅญๆฎตๆถๆณจๅ ฅ p5.js ๅฉๆๆ็คบ่ฏ๏ผๅฎขๆท็ซฏๆพๅผไผ `system`๏ผAnthropic๏ผๆ `{"role":"system"}` ๆถๆฏ๏ผOpenAI๏ผๅณๅฏ่ฆ็ | |
| - ๆตๅผ็ผๅญๅฝไธญๆถไผ้ๆฐ็ๆๆฐ็ๅๅบ ID / ๆถ้ดๆณ๏ผๅนถๆๆฌๅฐๅ่ฎฎ้ๆฐๆธฒๆ | |
| - ้ป่ฎค็ผๅญไธ้ 32 MiB๏ผ่ถ ่ฟไธไผๆชๆญ่ฟๅ๏ผๅชๆฏ่ทณ่ฟ็ผๅญ๏ผๅจ `/health` ็ `cache.oversize_skips` ๅฏ่ง | |
| - ่ฎพ `RESPONSE_CACHE_MAX_ENTRY_BYTES=0` ๅฏๅๆถไธ้ | |
| - ๆฌๆๅกไพ่ต p5js.ai ๆฅๅฃๅฏ็จๆง๏ผไธๆธธๅๆดๅฏ่ฝๅฝฑๅไฝฟ็จ | |
| ### ่ด่ฐข | |
| - ๆ่ฐข [ๅฐ่พฃๆค็ไธดๆถ้ฎ็ฎฑ](https://vip.215.im) ๆไพๆณจๅๆฏๆ | |
| ### ่ฎธๅฏ่ฏ | |
| MIT License | |
| --- | |
| <a id="english"></a> | |
| ## p5js.ai 2 API โ Wrap p5js.ai Free Chat as Anthropic / OpenAI Compatible API | |
| `p5js.ai 2 API` is a lightweight reverse-proxy adapter that wraps the free chat endpoint at `https://p5js.ai/api/ai-chat` into both an **Anthropic Messages API** and an **OpenAI Chat Completions API** compatible interface. | |
| This means any tool that speaks either protocol โ Claude Code, Chatbox, NextChat, LobeChat, one-api, Cherry Studio, etc. โ can connect to it as if it were a real Anthropic or OpenAI endpoint. | |
| ### Key Features | |
| - **Dual protocol** โ Serves both `/v1/messages` (Anthropic) and `/v1/chat/completions` (OpenAI) | |
| - **Pseudo tool use** โ The upstream doesn't support native tool_use; this service injects an XML-based `<function_calls>` prompt and parses the XML back into proper `tool_use` / `tool_calls` format | |
| - **p5.js noise filter** โ Automatically detects and strips p5.js assistant greetings, headings, and trailing recommendations injected by the upstream | |
| - **SSE fix-up** โ The upstream emits malformed `ddata:` / `ata:` prefixes; this service auto-corrects them to standard SSE | |
| - **Two-tier caching** โ In-memory + optional Redis second-level cache; streaming and non-streaming share the same completion cache | |
| - **In-flight deduplication** โ Concurrent identical requests don't hammer the upstream; followers wait for the leader's result | |
| - **Connection pooling** โ Shared httpx async connection pool for high-concurrency scenarios | |
| - **Proxy support** โ Supports `UPSTREAM_PROXY_URL` or standard `HTTP_PROXY` / `HTTPS_PROXY` env vars | |
| ### Project Structure | |
| ``` | |
| p5js/ | |
| โโโ main.py # FastAPI app entry point, route definitions | |
| โโโ config.py # Constants, env vars, model list, regex patterns | |
| โโโ filters.py # p5.js noise filtering, tool-aware text buffering | |
| โโโ tools.py # Tool XML prompt building, parsing, extraction | |
| โโโ translate.py # Protocol translation (Anthropic/OpenAI โ upstream format) | |
| โโโ upstream.py # Upstream HTTP client, SSE parsing, live capture | |
| โโโ render.py # Artifact โ Anthropic/OpenAI JSON/SSE rendering | |
| โโโ stream.py # Live stream handling (with/without tools, with cache integration) | |
| โโโ response_cache.py # Two-tier cache system (memory + Redis) | |
| โโโ tests/ # Test suite | |
| โ โโโ test_response_cache.py | |
| โ โโโ test_filters.py | |
| โโโ Dockerfile | |
| โโโ docker-compose.yml | |
| โโโ requirements.txt | |
| โโโ start.sh | |
| โโโ .env.example # Environment variable template | |
| โโโ README.md | |
| ``` | |
| ### Quick Start | |
| #### Local | |
| ```bash | |
| ./start.sh | |
| ``` | |
| The first run automatically creates a `venv`, installs dependencies, and listens on `http://127.0.0.1:18185`. | |
| #### Docker | |
| ```bash | |
| # Build and run | |
| docker build -t p5js2api:latest . | |
| docker run --rm -p 18185:18185 p5js2api:latest | |
| # Or with docker compose (includes Redis) | |
| docker compose up -d --build | |
| ``` | |
| The default compose config spins up a local Redis instance. Port is controlled via the `P5JS2API_PORT` env var (default `18185`). | |
| ### Supported Models | |
| | Model | Notes | | |
| |-------|-------| | |
| | `claude-opus-4-7` | Latest flagship | | |
| | `claude-opus-4-6` | | | |
| | `claude-opus-4-1` / `claude-opus-4-1-20250805` | | | |
| | `claude-opus-4-20250514` | | | |
| | `claude-sonnet-4-6` | | | |
| | `claude-sonnet-4-5` / `claude-sonnet-4-5-20250929` | **Default** | | |
| | `claude-sonnet-4-20250514` | | | |
| | `claude-haiku-4-5` / `claude-haiku-4-5-20251001` | Lightweight & fast | | |
| ### API Endpoints | |
| | Path | Method | Description | | |
| |------|--------|-------------| | |
| | `/health` | GET | Health check โ returns service status, cache stats, upstream config | | |
| | `/v1/models` | GET | Model list (Anthropic format) | | |
| | `/v1/messages` | POST | **Anthropic Messages API**, supports `stream` | | |
| | `/v1/chat/completions` | POST | **OpenAI Chat Completions API**, supports `stream` | | |
| > The service does not validate API keys โ any non-empty string is accepted. | |
| ### Usage Examples | |
| #### Claude Code (Anthropic Protocol) | |
| ```bash | |
| export ANTHROPIC_BASE_URL=http://127.0.0.1:18185 | |
| export ANTHROPIC_AUTH_TOKEN=dummy | |
| export ANTHROPIC_MODEL=claude-opus-4-7 | |
| export ANTHROPIC_SMALL_FAST_MODEL=claude-haiku-4-5 | |
| claude | |
| ``` | |
| #### OpenAI Python SDK | |
| ```python | |
| from openai import OpenAI | |
| client = OpenAI( | |
| base_url="http://127.0.0.1:18185/v1", | |
| api_key="sk-dummy", | |
| ) | |
| resp = client.chat.completions.create( | |
| model="claude-sonnet-4-5", | |
| messages=[{"role": "user", "content": "Hello"}], | |
| stream=True, | |
| ) | |
| for chunk in resp: | |
| print(chunk.choices[0].delta.content or "", end="", flush=True) | |
| ``` | |
| #### Third-party Tools (Chatbox / NextChat / LobeChat / one-api / Cherry Studio etc.) | |
| - **Base URL**: `http://127.0.0.1:18185/v1` | |
| - **API Key**: Any non-empty string (e.g. `sk-dummy`) | |
| - **Model**: Pick one from the "Supported Models" table above | |
| #### curl | |
| ```bash | |
| # Anthropic protocol | |
| curl http://127.0.0.1:18185/v1/messages \ | |
| -H 'content-type: application/json' \ | |
| -H 'x-api-key: dummy' \ | |
| -d '{"model":"claude-sonnet-4-5","max_tokens":1024,"messages":[{"role":"user","content":"hi"}]}' | |
| # OpenAI protocol | |
| curl http://127.0.0.1:18185/v1/chat/completions \ | |
| -H 'content-type: application/json' \ | |
| -d '{"model":"claude-sonnet-4-5","messages":[{"role":"user","content":"hi"}]}' | |
| ``` | |
| ### Caching | |
| The service enables full-response caching by default: | |
| - In-process memory cache first (LRU, default 256 entries) | |
| - Configure `RESPONSE_CACHE_REDIS_URL` to upgrade to **memory + Redis** two-tier caching | |
| - Concurrent identical cache misses are **in-flight deduplicated** โ followers wait for the leader | |
| - `stream=true` and `stream=false` share the same completion cache | |
| #### Environment Variables | |
| See `.env.example` for the full list. Key settings: | |
| | Variable | Default | Description | | |
| |----------|---------|-------------| | |
| | `RESPONSE_CACHE_ENABLED` | `true` | Enable/disable caching | | |
| | `RESPONSE_CACHE_TTL_SECS` | `300` | Cache TTL for plain requests (seconds) | | |
| | `RESPONSE_CACHE_TOOL_TTL_SECS` | `120` | Cache TTL for tool-use requests (seconds) | | |
| | `RESPONSE_CACHE_MAX_ENTRY_BYTES` | `33554432` | Max cache entry size in bytes (0 = unlimited) | | |
| | `RESPONSE_CACHE_REDIS_URL` | โ | Redis URL; set to enable second-level cache | | |
| #### Response Headers | |
| - `X-Proxy-Cache: HIT | MISS | BYPASS | DISABLED` | |
| - `X-Proxy-Cache-Source: memory | redis | inflight | live` | |
| #### Bypass Cache | |
| Either of: | |
| - Request header `X-Proxy-Cache: bypass` | |
| - Request header `Cache-Control: no-cache` | |
| ### Proxy Configuration | |
| Two proxy options inside the container: | |
| - Explicit `UPSTREAM_PROXY_URL` | |
| - Standard env vars `HTTP_PROXY` / `HTTPS_PROXY` / `NO_PROXY` | |
| The `/health` endpoint's `upstream.proxy_configured` field shows whether a proxy is detected. | |
| ### How It Works | |
| ``` | |
| โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ | |
| โ Client โโโโโโถโ p5js.ai 2 API โโโโโโถโ p5js.ai โ | |
| โ (Claude/ โโโโโโโ (this project) โโโโโโโ upstream โ | |
| โ OpenAI) โ โ โ โ โ | |
| โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ | |
| โ โโ Protocol translation โ | |
| โ โโ Tool XML inject/parse โ | |
| โ โโ p5.js noise filtering โ | |
| โ โโ SSE fix-up โ | |
| โ โโ Two-tier caching โ | |
| ``` | |
| 1. **Protocol translation**: Converts Anthropic or OpenAI format requests into the p5js.ai upstream format (`messages` + `provider` + `model` + `deviceId` + `sessionId`) | |
| 2. **Tool use emulation**: Injects tool definitions as XML into the system prompt, parses `<function_calls>` XML blocks from upstream text responses back into standard `tool_use` / `tool_calls` | |
| 3. **Noise filtering**: Detects and strips p5.js assistant greetings, headings, and trailing recommendations auto-injected by the upstream | |
| 4. **SSE fix-up**: Auto-corrects malformed `ddata:` / `ata:` prefixes to standard `data:` | |
| 5. **Caching**: Full-response caching shared between streaming and non-streaming, with in-flight deduplication | |
| ### Caveats | |
| - The upstream p5js.ai injects a p5.js assistant prompt when no `system` field is present. Passing `system` (Anthropic) or a `{"role":"system"}` message (OpenAI) overrides it. | |
| - Cache hits re-generate new response IDs/timestamps and re-render per the local protocol. | |
| - Default cache entry limit is 32 MiB. Oversized entries are not truncated โ they're simply not cached. Check `/health` โ `cache.oversize_skips`. | |
| - Set `RESPONSE_CACHE_MAX_ENTRY_BYTES=0` to remove the limit. | |
| - This service depends on p5js.ai availability. Upstream changes may affect functionality. | |
| ### Acknowledgements | |
| - Special thanks to [ๅฐ่พฃๆค็ไธดๆถ้ฎ็ฎฑ (Xiaolajiao Temp Mail)](https://vip.215.im) for registration support | |
| ### License | |
| MIT License | |