Docker / publish (push) Canceled after 0s
Release / crates-io (push) Canceled after 0s
Release / release (macos-14, aarch64-apple-darwin) (push) Canceled after 0s
Release / release (ubuntu-latest, x86_64-unknown-linux-gnu) (push) Canceled after 0s
Release / release (windows-latest, x86_64-pc-windows-msvc) (push) Canceled after 0s
/v1/chat/completions answered ordinary client payloads with a bare HTTP 422 (a plain-text body no OpenAI client can parse), so Open WebUI showed neither an answer nor an error — it just hung. Parse the body leniently instead: content as string/null/content-part array, tools: null, stream: null, a string reasoning_effort, max_completion_tokens, messages[].name and tool_call_id, and a missing Content-Type. Unreadable bodies now come back as an OpenAI error envelope with 400. Responses are strict OpenAI JSON: no "tool_calls": null, finish_reason mapped to the spec's closed set (cortiq serve's max_tokens -> length), never an empty id, and `model` echoes the id the client requested — the model that actually answered stays in cortiq.selected_model and X-Cortiq-Selected-Model. Streaming is re-normalised rather than forwarded verbatim: a leading role delta, message-shaped chunks converted to delta, one terminal finish_reason, always a trailing data: [DONE], and an SSE error event when the upstream dies mid-flight. Adds X-Accel-Buffering: no so a fronting proxy cannot buffer the stream into a hang. GET /v1/models now lists managed [[cmf.servers]] models with their live running/healthy state, so clients can pin a local .cmf directly. Also strips client bookkeeping keys (chat_id, session_id, metadata, features, ...) from the upstream call and drops the leftover [to_wire] debug prints.
80 lines
2.2 KiB
TOML
80 lines
2.2 KiB
TOML
[package]
|
|
name = "cortiq-gateway"
|
|
version = "0.2.45"
|
|
edition = "2021"
|
|
rust-version = "1.75"
|
|
license = "Apache-2.0"
|
|
description = "Universal LLM gateway with intelligent routing and an embedded multilingual admin console"
|
|
repository = "https://github.com/infosave2007/cortiq-gateway"
|
|
homepage = "https://api.allaigate.com"
|
|
readme = "README.md"
|
|
keywords = ["llm", "gateway", "proxy", "openai", "routing"]
|
|
categories = ["web-programming::http-server", "command-line-utilities"]
|
|
# Files shipped in the published crate. The embedded admin SPA MUST be included
|
|
# because rust-embed compiles it in; docs/screenshots are excluded to keep the
|
|
# crate lean. The web/ subfolders are listed one by one rather than as web/**/*
|
|
# so stray scratch files dropped next to the SPA never end up published.
|
|
include = [
|
|
"src/**/*",
|
|
"web/index.html",
|
|
"web/favicon.svg",
|
|
"web/css/**/*",
|
|
"web/js/**/*",
|
|
"config/gateway.example.toml",
|
|
"README.md",
|
|
"CHANGELOG.md",
|
|
"LICENSE",
|
|
]
|
|
|
|
[dependencies]
|
|
# async runtime + HTTP server
|
|
tokio = { version = "1", features = ["full"] }
|
|
axum = { version = "0.7", features = ["macros"] }
|
|
tower = "0.5"
|
|
tower-http = { version = "0.6", features = ["limit", "trace", "cors"] }
|
|
|
|
# HTTP client to providers and to cortiq-router (rustls, no OpenSSL)
|
|
reqwest = { version = "0.12", default-features = false, features = ["json", "stream", "rustls-tls"] }
|
|
|
|
# serialization
|
|
serde = { version = "1", features = ["derive"] }
|
|
serde_json = "1"
|
|
toml = "0.8"
|
|
|
|
# hot-reloadable shared state + embedded admin SPA
|
|
arc-swap = "1"
|
|
rust-embed = "8"
|
|
mime_guess = "2"
|
|
|
|
# cross-platform CSPRNG for admin/key token generation (Linux/macOS/Windows)
|
|
getrandom = "0.2"
|
|
|
|
# streaming / async utils
|
|
futures = "0.3"
|
|
async-trait = "0.1"
|
|
async-stream = "0.3"
|
|
bytes = "1"
|
|
tokio-stream = "0.1"
|
|
|
|
# CLI / config
|
|
clap = { version = "4", features = ["derive"] }
|
|
# open browser on first run (optional)
|
|
open = { version = "5", optional = true }
|
|
|
|
# host metrics for the admin dashboard (CPU / RAM / disk)
|
|
sysinfo = "0.39"
|
|
|
|
# errors / logging / metrics
|
|
thiserror = "1"
|
|
anyhow = "1"
|
|
tracing = "0.1"
|
|
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
|
|
|
[features]
|
|
default = ["open-browser"]
|
|
open-browser = ["open"]
|
|
|
|
[profile.release]
|
|
lto = true
|
|
codegen-units = 1
|