diff --git a/Makefile b/Makefile index fd27039..21354cd 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ -all: q38max +all: qorona -q38max: +qorona: mkdir -p bin - go build -trimpath -ldflags="-s -w" -o bin/q38max main.go + go build -trimpath -ldflags="-s -w" -o bin/qorona main.go test: go test -v ./... @@ -10,4 +10,4 @@ test: clean: rm -rf bin -.PHONY: all q38max test clean +.PHONY: all qorona test clean diff --git a/README.md b/README.md index 9d8d1e9..f4a31e1 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,16 @@ -# q38max +# qorona Standalone, zero-dependency OpenAI-compatible proxy gateway in Go for the **Qwen 3.8 Max** model (`Qwen/Qwen3.8-Max`) hosted on Hugging Face Spaces (`harpreetsahota-qwen38-max-openlogo-demo.hf.space`). ## Overview -`q38max` reverse-engineers the FiftyOne plugin backend operator interface of the Hugging Face space and transforms it into a standard, production-ready OpenAI API endpoint (`/v1/chat/completions` and `/v1/models`). +`qorona` reverse-engineers the FiftyOne plugin backend operator interface of the Hugging Face space and transforms it into a standard, production-ready OpenAI API endpoint (`/v1/chat/completions` and `/v1/models`). ### Features - **OpenAI Standard Compatibility**: Full drop-in replacement for OpenAI API clients (Curl, Python `openai`, LangChain, LiteLLM, Open-WebUI). - **Zero External Dependencies**: Pure standard library Go implementation (`net/http`, `encoding/json`, `crypto/rand`, `time`). +- **Fully Headless & Browserless**: No Chromium, Playwright, or X11 required. Runs directly on bare servers, containers, or embedded systems. - **Live Streaming SSE & Reasoning**: Streams real-time tokens with separation of reasoning content (`delta.reasoning_content`) and message content (`delta.content`). - **Function / Tool Calling Interception**: Supports OpenAI `tools` specification, system prompt tool schema injection, and stateful streaming interception of tool calls (`delta.tool_calls` and `finish_reason: "tool_calls"`). - **Session Lifecycle Management**: Thread-safe automatic session creation (`/__session/start`), periodic background heartbeats (`/__session/heartbeat`), and auto-reconnect recovery. @@ -21,7 +22,7 @@ Standalone, zero-dependency OpenAI-compatible proxy gateway in Go for the **Qwen ``` +---------------------------+ OpenAI HTTP / SSE +------------------------+ -| Client (Python / Curl / | ===========================> | q38max Gateway | +| Client (Python / Curl / | ===========================> | qorona Gateway | | OpenAI SDK / Open-WebUI) | | (localhost:8080) | +---------------------------+ +------------------------+ | @@ -48,14 +49,14 @@ Standalone, zero-dependency OpenAI-compatible proxy gateway in Go for the **Qwen ### Build ```bash -make q38max +make qorona ``` -Binary is output to `bin/q38max`. +Binary is output to `bin/qorona`. ### Run ```bash -./bin/q38max -port 8080 +./bin/qorona -port 8080 ``` ### CLI Flags @@ -84,7 +85,7 @@ curl http://localhost:8080/v1/models curl -X POST http://localhost:8080/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ - "model": "qwen-3.8-max", + "model": "qorona", "messages": [ {"role": "user", "content": "What is the capital of Germany? Answer in 1 word."} ], @@ -98,7 +99,7 @@ curl -X POST http://localhost:8080/v1/chat/completions \ curl -N -X POST http://localhost:8080/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ - "model": "qwen-3.8-max", + "model": "qorona", "messages": [ {"role": "user", "content": "Calculate 25 * 25 and explain in one sentence."} ], @@ -113,7 +114,7 @@ curl -N -X POST http://localhost:8080/v1/chat/completions \ curl -X POST http://localhost:8080/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ - "model": "qwen-3.8-max", + "model": "qorona", "messages": [ {"role": "user", "content": "What is the weather in Berlin?"} ], @@ -147,7 +148,7 @@ client = OpenAI( ) response = client.chat.completions.create( - model="qwen-3.8-max", + model="qorona", messages=[ {"role": "user", "content": "Write a short haiku about computers."} ], diff --git a/go.mod b/go.mod index 00f0b9a..5b32a53 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,3 @@ -module q38max +module qorona go 1.22 diff --git a/main.go b/main.go index 7898705..ea091d8 100644 --- a/main.go +++ b/main.go @@ -1,4 +1,4 @@ -// q38max: Standalone OpenAI-compatible gateway for Qwen 3.8 Max HuggingFace Spaces +// qorona: Standalone OpenAI-compatible gateway for Qwen 3.8 Max HuggingFace Spaces // Created by Luxferre in 2026, released into the public domain package main @@ -1086,7 +1086,7 @@ func PrepareConversation(req ChatCompletionRequest) (history []map[string]interf // Main Gateway Service // --------------------------------------------------------------------------- -type Q38Gateway struct { +type QoronaGateway struct { spaceURL string samplePath string modelID string @@ -1094,7 +1094,7 @@ type Q38Gateway struct { sessionMgr *FiftyOneSessionManager } -func NewQ38Gateway(spaceURL string, samplePath string, modelID string, timeout time.Duration) *Q38Gateway { +func NewQoronaGateway(spaceURL string, samplePath string, modelID string, timeout time.Duration) *QoronaGateway { tr := &http.Transport{ MaxIdleConns: 100, MaxIdleConnsPerHost: 20, @@ -1104,7 +1104,7 @@ func NewQ38Gateway(spaceURL string, samplePath string, modelID string, timeout t Transport: tr, Timeout: timeout, } - return &Q38Gateway{ + return &QoronaGateway{ spaceURL: strings.TrimRight(spaceURL, "/"), samplePath: samplePath, modelID: modelID, @@ -1113,7 +1113,7 @@ func NewQ38Gateway(spaceURL string, samplePath string, modelID string, timeout t } } -func (gw *Q38Gateway) HandleModels(w http.ResponseWriter, r *http.Request) { +func (gw *QoronaGateway) HandleModels(w http.ResponseWriter, r *http.Request) { EnableCORS(w) if r.Method == http.MethodOptions { w.WriteHeader(http.StatusNoContent) @@ -1130,6 +1130,18 @@ func (gw *Q38Gateway) HandleModels(w http.ResponseWriter, r *http.Request) { Created: now, OwnedBy: "qwen", }, + { + ID: "qorona", + Object: "model", + Created: now, + OwnedBy: "qwen", + }, + { + ID: "qwen-3.8-max", + Object: "model", + Created: now, + OwnedBy: "qwen", + }, { ID: "qwen3.8-max", Object: "model", @@ -1155,7 +1167,7 @@ func (gw *Q38Gateway) HandleModels(w http.ResponseWriter, r *http.Request) { json.NewEncoder(w).Encode(resp) } -func (gw *Q38Gateway) HandleChatCompletions(w http.ResponseWriter, r *http.Request) { +func (gw *QoronaGateway) HandleChatCompletions(w http.ResponseWriter, r *http.Request) { EnableCORS(w) if r.Method == http.MethodOptions { w.WriteHeader(http.StatusNoContent) @@ -1599,7 +1611,7 @@ func main() { ConfiguredToken = *hfToken } - gw := NewQ38Gateway(*spaceURL, *samplePath, *modelID, time.Duration(*timeoutSec)*time.Second) + gw := NewQoronaGateway(*spaceURL, *samplePath, *modelID, time.Duration(*timeoutSec)*time.Second) mux := http.NewServeMux() @@ -1613,28 +1625,28 @@ func main() { mux.HandleFunc("/__health", func(w http.ResponseWriter, r *http.Request) { EnableCORS(w) w.Header().Set("Content-Type", "application/json") - w.Write([]byte(`{"status":"ok","gateway":"q38max"}`)) + w.Write([]byte(`{"status":"ok","gateway":"qorona"}`)) }) mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) { EnableCORS(w) w.Header().Set("Content-Type", "application/json") - w.Write([]byte(`{"status":"ok","gateway":"q38max"}`)) + w.Write([]byte(`{"status":"ok","gateway":"qorona"}`)) }) mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { EnableCORS(w) if r.URL.Path == "/" { w.Header().Set("Content-Type", "application/json") - w.Write([]byte(`{"service":"q38max","description":"OpenAI-compatible gateway for Qwen 3.8 Max","models_endpoint":"/v1/models","completions_endpoint":"/v1/chat/completions"}`)) + w.Write([]byte(`{"service":"qorona","description":"OpenAI-compatible gateway for Qwen 3.8 Max","models_endpoint":"/v1/models","completions_endpoint":"/v1/chat/completions"}`)) return } http.NotFound(w, r) }) addr := fmt.Sprintf(":%d", *port) - log.Printf("[q38max] Listening on http://localhost%s (Upstream: %s)", addr, *spaceURL) - log.Printf("[q38max] OpenAI compatible endpoints: http://localhost%s/v1/chat/completions", addr) + log.Printf("[qorona] Listening on http://localhost%s (Upstream: %s)", addr, *spaceURL) + log.Printf("[qorona] OpenAI compatible endpoints: http://localhost%s/v1/chat/completions", addr) if err := http.ListenAndServe(addr, mux); err != nil { - log.Fatalf("[q38max] Server failed: %v", err) + log.Fatalf("[qorona] Server failed: %v", err) } } diff --git a/q38max_test.go b/qorona_test.go similarity index 93% rename from q38max_test.go rename to qorona_test.go index 4969640..2f838e6 100644 --- a/q38max_test.go +++ b/qorona_test.go @@ -1,4 +1,4 @@ -// Unit and integration tests for q38max +// Unit and integration tests for qorona // Created by Luxferre in 2026, released into the public domain package main @@ -86,7 +86,7 @@ func TestPrepareConversation(t *testing.T) { } func TestModelsHandler(t *testing.T) { - gw := NewQ38Gateway("https://mock.hf.space", "/dummy/path.jpg", "qwen-3.8-max", 5*time.Second) + gw := NewQoronaGateway("https://mock.hf.space", "/dummy/path.jpg", "qwen-3.8-max", 5*time.Second) req := httptest.NewRequest("GET", "/v1/models", nil) w := httptest.NewRecorder() @@ -108,12 +108,12 @@ func TestModelsHandler(t *testing.T) { found := false for _, m := range res.Data { - if m.ID == "qwen-3.8-max" { + if m.ID == "qorona" || m.ID == "qwen-3.8-max" { found = true break } } if !found { - t.Fatalf("qwen-3.8-max not found in models list") + t.Fatalf("model not found in models list") } } diff --git a/xtest.sh b/xtest.sh index e720358..dc02a52 100755 --- a/xtest.sh +++ b/xtest.sh @@ -12,7 +12,7 @@ echo "=== 2. Testing Non-Streaming Chat Completion ===" curl -s -X POST "${BASE_URL}/v1/chat/completions" \ -H "Content-Type: application/json" \ -d '{ - "model": "qwen-3.8-max", + "model": "qorona", "messages": [ {"role": "user", "content": "What is the capital of Italy? Answer in 1 word."} ], @@ -25,7 +25,7 @@ echo "=== 3. Testing Streaming SSE Completion (with reasoning) ===" curl -N -s -X POST "${BASE_URL}/v1/chat/completions" \ -H "Content-Type: application/json" \ -d '{ - "model": "qwen-3.8-max", + "model": "qorona", "messages": [ {"role": "user", "content": "Calculate 25 * 25 and explain briefly in one sentence."} ], @@ -39,7 +39,7 @@ echo "=== 4. Testing Function/Tool Calling ===" curl -s -X POST "${BASE_URL}/v1/chat/completions" \ -H "Content-Type: application/json" \ -d '{ - "model": "qwen-3.8-max", + "model": "qorona", "messages": [ {"role": "user", "content": "What is the weather in Berlin?"} ], @@ -64,4 +64,4 @@ curl -s -X POST "${BASE_URL}/v1/chat/completions" \ }' | jq . echo "" -echo "=== All integration tests finished successfully! ===" +echo "=== All qorona integration tests finished successfully! ==="