Skip to content

Repository files navigation

fx-bridge

Use Vercel fx with a standard OpenAI-compatible API through a local, loopback-only protocol bridge.

fx-bridge does not patch the fx binary or replace fx authentication. It translates fx's AI SDK Language Model Specification v4 request/response format into OpenAI Chat Completions and keeps provider credentials on your machine.

Important

fx and its local gateway override are experimental. Pin a known-working fx version and run the included smoke test after every fx upgrade.

fx ── FX_GATEWAY_CHAT_URL ──▶ fx-bridge (127.0.0.1) ──▶ OpenAI-compatible API
        LMS-v4 request/SSE       Python stdlib only         Chat Completions/SSE

Features

  • No fx binary patching; fx upgrade remains available.
  • Python standard library only, with no runtime dependencies.
  • Loopback-only listener and HTTPS-only remote upstreams.
  • Streaming text, reasoning, tool calls, tool results, images, and usage.
  • Explicit model mapping and fail-closed routing by default.
  • Configurable endpoint paths, headers, request fields, and model metadata.
  • Deterministic mock mode plus unit, HTTP integration, and real-fx smoke tests.

Requirements

  • Python 3.9 or newer (including the macOS system Python used by launchd).
  • A working fx installation. fx may still require fx login or fx setup; the credential fx sends to the loopback bridge is ignored.
  • An API exposing the OpenAI Chat Completions streaming format. Provider-specific protocols such as Anthropic Messages are not supported directly.

Quick start

git clone https://github.com/elijah7x/fx-bridge.git
cd fx-bridge

mkdir -p ~/.config/fx-bridge
cp config.example.json ~/.config/fx-bridge/config.json
chmod 600 ~/.config/fx-bridge/config.json

# Prefer an environment variable over a literal key in JSON.
read -rs FX_BRIDGE_API_KEY && export FX_BRIDGE_API_KEY && echo

python3 fx-bridge.py

Start fx with both local overrides:

alias fxb='FX_GATEWAY_BASE_URL=http://127.0.0.1:8790 FX_GATEWAY_CHAT_URL=http://127.0.0.1:8790/v3/ai/language-model fx'

FX_MODEL=your-model-id fxb ask "hello"

FX_GATEWAY_CHAT_URL controls chat requests. FX_GATEWAY_BASE_URL makes fx models and the interactive model selector use the upstream model catalog exposed by the bridge.

Configuration

The default configuration path is ~/.config/fx-bridge/config.json. Use --config PATH to override it.

Field Default Description
port 8790 Loopback listening port.
upstream_base_url required HTTPS API base URL, or loopback HTTP for local inference. Query parameters are preserved.
upstream_api_key_env FX_BRIDGE_API_KEY Environment variable containing the upstream key.
upstream_api_key empty Legacy literal key. If used, fx-bridge warns when the config permissions are broader than 0600.
upstream_headers {} Additional or replacement upstream headers, including custom authorization schemes.
chat_path chat/completions Path appended to the base URL unless already present.
models_path models Model catalog path appended to the base URL.
model_map {} Exact fx model ID to upstream model ID mappings.
unknown_model_policy error error, fallback, or passthrough. fallback requires default_model.
default_model empty Model used when the request has no model, or when fallback is explicitly enabled.
strip_provider_prefix false If enabled, route vendor/model as model only when the stripped ID is present in the upstream catalog.
send_reasoning_effort false Forward fx's low/medium/high effort as reasoning_effort.
extra_body {} Extra Chat Completions fields. Protocol-owned fields cannot be overridden.
catalog_defaults see example Metadata fx requires when displaying upstream models. These are display assumptions, not provider discovery.
connect_timeout 30 Connection timeout in seconds.
read_timeout 600 Streaming read timeout in seconds.
max_request_bytes 8388608 Maximum request body accepted from fx.
require_upstream_done true Reject a stream that ends before the OpenAI [DONE] sentinel.

Provider variations

The bridge supports custom headers and endpoint paths without provider-specific code:

{
  "upstream_base_url": "https://gateway.example.com/openai/v1?api-version=2026-01-01",
  "upstream_api_key_env": "MY_GATEWAY_KEY",
  "upstream_headers": {
    "X-Client": "fx-bridge"
  },
  "chat_path": "chat/completions",
  "models_path": "models",
  "unknown_model_policy": "passthrough"
}

If a provider does not implement /models, use model_map or passthrough. Use fallback only when silently routing unknown fx model IDs to one configured model is intentional.

Verification

Run the dependency-free regression suite:

python3 -m unittest discover -v

Run the HTTP-only mock server:

python3 fx-bridge.py --mock
curl -fsS http://127.0.0.1:8790/healthz

Run the end-to-end smoke test against the installed fx binary:

scripts/smoke-fx.sh

The smoke test starts an isolated mock bridge, asks fx to execute a real read_file tool call, verifies the tool result returns through a second model turn, and removes its temporary files.

Failure behavior

fx-bridge fails closed for conditions that could otherwise execute the wrong tool or accept an incomplete model response:

  • malformed fx request bodies;
  • unknown models under the default routing policy;
  • malformed streamed JSON or upstream error events;
  • invalid or incomplete tool-call arguments;
  • upstream EOF before [DONE];
  • remote plaintext HTTP endpoints.

Upstream failures are returned to fx as LMS error events. They are not converted into successful stop completions.

Diagnostics and privacy

Set FXB_DUMP=/path/request.json to capture the raw fx request for protocol debugging. Dumps can contain prompts, source code, tool output, and secrets. fx-bridge creates the file with mode 0600; review and delete it after use.

The bridge logs model routing and request counts, but never logs API keys, request bodies, the config path, or the upstream URL.

Architecture

fx_bridge/
  config.py                 validation, secrets, endpoint construction
  routing.py                explicit model routing policy
  protocols/openai_chat.py  fx request → Chat Completions
  protocols/fx_lms.py       Chat Completions stream → fx LMS-v4 SSE
  transport.py              upstream HTTP, SSE parser, model cache
  server.py                 loopback HTTP boundary
  mock.py                   deterministic two-turn tool harness

The wire contract is derived from the fx source parser and tests. FX_GATEWAY_CHAT_URL is deliberately restricted by fx to a loopback HTTP URL, but it remains an experimental integration surface rather than a public stability guarantee.

Known limitations

  • Gateway-native provider tools such as hosted web search are not forwarded. Local fx function tools continue to work.
  • Only OpenAI Chat Completions-compatible request and streaming response shapes are supported.
  • Model context windows and output limits cannot be discovered reliably from the OpenAI /models shape; configure catalog_defaults conservatively.
  • The bridge listens only on 127.0.0.1 and is not intended to be a shared network proxy.

Security

See SECURITY.md. Do not publish credentials, raw request dumps, logs, or private provider URLs in bug reports.

License and affiliation

Licensed under Apache-2.0. See LICENSE.

fx-bridge is an independent community project. It is not affiliated with, endorsed by, or sponsored by Vercel. “Vercel” and “fx” are used only to identify compatibility with the upstream product.

About

Use Vercel fx with an OpenAI-compatible API through a local protocol bridge.

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages