Skip to content

Instantly share code, notes, and snippets.

@benedictjohannes
Last active August 4, 2026 01:46
Show Gist options
  • Select an option

  • Save benedictjohannes/dab3d7a0ecca27530f305aebf97104f2 to your computer and use it in GitHub Desktop.

Select an option

Save benedictjohannes/dab3d7a0ecca27530f305aebf97104f2 to your computer and use it in GitHub Desktop.
proxy to agentrouter.org - fixing bugs and fixing headers to opencode
https://agentrouter.org/register?aff=U6vc
Click: Sign In,
then,
Continue with GitHub
// the agentrouter.org proxy has some problematic SSE response that needs to be filtered out.
// This go program filters SSE events that makes OpenCode error out.
package main
import (
"bufio"
"bytes"
"io"
"log/slog"
"net/http"
"os"
"strings"
)
const targetBaseURL = "https://agentrouter.org"
func handleProxy(w http.ResponseWriter, r *http.Request) {
// Log incoming request details and headers
var headers []any
for key, values := range r.Header {
if strings.ToLower(key) == "authorization" {
headers = append(headers, slog.String(key, "[MASKED]"))
} else {
headers = append(headers, slog.String(key, strings.Join(values, ", ")))
}
}
slog.Info("Incoming Request",
slog.String("method", r.Method),
slog.String("url", r.URL.String()),
slog.Group("headers", headers...),
)
// Construct the upstream URL
upstreamURL := targetBaseURL + r.URL.Path
if r.URL.RawQuery != "" {
upstreamURL += "?" + r.URL.RawQuery
}
// Read body for forwarding
bodyBytes, _ := io.ReadAll(r.Body)
req, err := http.NewRequest(r.Method, upstreamURL, bytes.NewBuffer(bodyBytes))
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// Copy incoming headers EXCEPT transport-level headers, user-agent, and encoding configurations
ignoredHeaders := map[string]bool{
"accept-encoding": true,
"content-length": true,
"connection": true,
"keep-alive": true,
"proxy-connection": true,
"transfer-encoding": true,
"upgrade": true,
"user-agent": true,
}
for key, values := range r.Header {
if ignoredHeaders[strings.ToLower(key)] {
continue
}
for _, val := range values {
req.Header.Add(key, val)
}
}
// Spoof User-Agent to match OpenCode client
req.Header.Set("User-Agent", "opencode/1.18.3 ai-sdk/provider-utils/4.0.23 runtime/bun/1.3.14")
// Execute request to AgentRouter
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
http.Error(w, err.Error(), http.StatusBadGateway)
return
}
defer resp.Body.Close()
// Log upstream response status and headers
var respHeaders []any
for key, values := range resp.Header {
respHeaders = append(respHeaders, slog.String(key, strings.Join(values, ", ")))
}
slog.Info("Upstream Response",
slog.Int("status_code", resp.StatusCode),
slog.Group("headers", respHeaders...),
)
// Read and log response body if it's an error status
if resp.StatusCode >= 400 {
bodyBytes, _ := io.ReadAll(resp.Body)
slog.Warn("Upstream Response Error Body",
slog.Int("status_code", resp.StatusCode),
slog.String("body", string(bodyBytes)),
)
resp.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))
}
// Copy response headers back EXCEPT encoding variations
for key, values := range resp.Header {
if strings.ToLower(key) == "content-encoding" || strings.ToLower(key) == "content-length" {
continue // Let the local response figure out its own length/encoding
}
for _, val := range values {
w.Header().Add(key, val)
}
}
w.WriteHeader(resp.StatusCode)
// Check if this is an Event-Stream (SSE)
if strings.Contains(resp.Header.Get("Content-Type"), "text/event-stream") {
reader := bufio.NewReader(resp.Body)
for {
line, err := reader.ReadString('\n')
if err != nil {
if err != io.EOF {
slog.Error("Stream read error", slog.Any("error", err))
}
break
}
trimmedLine := strings.TrimSpace(line)
// Fix 1: Skip the old malformed null chunk
if trimmedLine == "data: null" {
continue
}
// Fix 2: Skip the custom metadata billing summary block injected by the proxy
if strings.Contains(trimmedLine, `"object":"billing.summary"`) {
continue
}
// Forward valid lines down the pipe
w.Write([]byte(line))
if flusher, ok := w.(http.Flusher); ok {
flusher.Flush()
}
}
return
}
// Standard non-streaming fallback
io.Copy(w, resp.Body)
}
func main() {
slog.SetDefault(slog.New(slog.NewJSONHandler(os.Stdout, nil)))
http.HandleFunc("/", handleProxy)
slog.Info("Filtering proxy active on :8080...")
if err := http.ListenAndServe(":8080", nil); err != nil {
slog.Error("Server failed to start", slog.Any("error", err))
os.Exit(1)
}
}
# ~/.config/systemd/user/opencode-web.service
# you can then run systemctl --user start opencode-web.service
[Unit]
Description=OpenCode Web
After=network.target
StartLimitIntervalSec=0
[Service]
Type=simple
Restart=always
RestartSec=10
ExecStart=%h/.bun/bin/opencode serve --hostname 10.10.20.20 --port 8724 --cors opencode.bench01.t.haiyaa.my.id
[Install]
WantedBy=default.target
// ~/.config/opencode/opencode.jsonc
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"agentrouter": {
"npm": "@ai-sdk/openai-compatible",
"name": "AgentRouter (OpenAI Compatible)",
"options": {
"baseURL": "https://agentrouter.localhost/v1"
},
"models": {
"claude-opus-5": {
"name": "claude-opus-5"
},
"claude-opus-4-8": {
"name": "claude-opus-4-8"
},
"gpt-5.6-sol": {
"name": "gpt-5.6-sol"
}
}
},
},
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment