# hygate-c A small, dependency-light C port of the Hygate gateway that exposes a **Gradio-hosted Hunyuan model (`hy3`)** behind an **OpenAI-compatible** REST API. It translates OpenAI `chat/completions` requests into Gradio's queue API (`POST /gradio_api/call/chat` → `GET /gradio_api/call/chat/{event_id}` SSE stream) and translates the Gradio stream back into OpenAI streaming and non-streaming responses, including tool calls and reasoning content. ## Build Requires `libcurl` and `json-c` (auto-detected via `pkg-config`); falls back to `-lcurl -ljson-c` if `pkg-config` is unavailable. ```sh make # dynamic binary -> bin/hygate make static # static binary -> bin/hygate.static make clean ``` Build is POSIX-portable (Linux, FreeBSD, macOS) and compiles clean with `-Wall -Wextra`. ## Run ```sh ./bin/hygate [options] ``` ### Options | Flag | Default | Description | |------|---------|-------------| | `-port ` | `8080` | Listen port (binds `0.0.0.0`). | | `-endpoint ` | `https://tencent-hy3.hf.space` | Upstream Gradio Space base URL (trailing slash trimmed). | | `-model ` | `hy3` | Model name reported in `/v1/models` and responses. | | `-user-agent ` / `-ua ` | built-in Firefox UA | Outgoing `User-Agent`. Empty string => default. | | `-max-body ` | `5242880` (5 MiB) | Maximum request body size. Oversized requests are rejected with `413`. | | `-max-conn ` | `16` | Maximum concurrent connections (worker threads). Excess connections queue in the kernel listen backlog. | Flag forms: `-key value` or `-key=value`. Example — listen on `9090`, allow 8 MiB bodies, cap at 32 concurrent connections: ```sh ./bin/hygate -port 9090 -max-body 8388608 -max-conn 32 ``` ## Endpoints | Method | Path | Notes | |--------|------|-------| | `GET` | `/v1/models`, `/models` | Returns the configured model (served locally, no upstream call). | | `POST` | `/v1/chat/completions`, `/chat/completions` | OpenAI-style chat completion. Supports `stream`, `tools`/`tool_calls`, and `reasoning_content`. | | `OPTIONS` | any of the above | CORS preflight. | CORS is enabled for all origins (`Access-Control-Allow-Origin: *`). ## Request / response notes - OpenAI `messages` are mapped into Gradio's `[message, system, history, "high", temperature, max_tokens, top_p, null, functions_json]` payload. - `max_tokens` / `max_completion_tokens` are honored; defaults to `131072` when omitted. - Upstream calls use Fibonacci-backoff retries (up to `MAX_RETRIES = 5`, 300 s timeout). ## Token usage counting Responses include an OpenAI-style `usage` object with `prompt_tokens`, `completion_tokens`, and `total_tokens`. These are computed locally by an **embedded cl100k_base BPE tokenizer** (vocabulary data in `tokenizer_data.c`, logic in `tokenizer.c`) — no upstream token counts are available from the Gradio backend. - `prompt_tokens` sums each message's `content` (or multi-part content parts), `reasoning_content`, and any `tool_calls` function `name` / `arguments`. - `completion_tokens` sums the assistant `content`, `reasoning_content`, and any emitted `tool_calls`. - `total_tokens = prompt_tokens + completion_tokens`. cl100k_base is OpenAI's canonical multilingual tokenizer and is used as the best available approximation for Hunyuan; the resulting counts are deterministic subword counts and may differ slightly from the exact Hunyuan vocabulary. No per-message formatting overhead (the `+3`/priming tokens OpenAI applies) is added. ## Security considerations - The server binds all interfaces (`0.0.0.0`) and currently enforces **no authentication** — it is an open relay to the configured upstream. Do not expose it to untrusted networks without a fronting proxy or auth layer. - `-max-body` and `-max-conn` exist to bound resource usage (memory and thread count) against abusive clients. ## Source layout | File | Role | |------|------| | `main.c` | Entry point, flag parsing, TCP listen, thread-per-connection with concurrency cap. | | `server.c` | HTTP parsing, routing, SSE emitters, libcurl upstream calls, streaming state machine. | | `jsonapi.c` | OpenAI <-> Gradio payload translation and stream parsing. | | `util.c` | Growable string buffer (`strbuf`), UUID, backoff, helpers. | | `hygate.h` | Shared types and declarations. | ## Credits Created by Luxferre in 2026, released into the public domain with no warranties.