more oc fixes
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/md5"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
@@ -87,6 +88,8 @@ var llmTransport = &http.Transport{
|
||||
|
||||
var defCfg = Cfg{"https://api.kilo.ai/api/openrouter", "openrouter/free", "-", 0.7, 300, 120, 1000, true, "auto", 262144, 15000, map[string]string{"reasoning_effort": "high"}}
|
||||
const opencodeAgentVersion = "opencode/1.18.31"
|
||||
const opencodeProviderUA = "ai-sdk/provider-utils/4.0.23 runtime/bun/1.3.14"
|
||||
const opencodeIDAlphabet = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"
|
||||
|
||||
func atoiD(s string, d int) int {
|
||||
if v, e := strconv.Atoi(strings.TrimSpace(s)); e == nil {
|
||||
@@ -105,12 +108,7 @@ func queryModelsContextWindow(cfg *Cfg) int {
|
||||
}
|
||||
req, err := http.NewRequest("GET", strings.TrimRight(cfg.Endpoint, "/")+"/models", nil)
|
||||
if err != nil { return 0 }
|
||||
req.Header.Set("User-Agent", opencodeAgentVersion)
|
||||
req.Header.Set("X-Session-Id", projectID())
|
||||
req.Header.Set("x-opencode-project", projectID())
|
||||
req.Header.Set("x-opencode-client", "cli")
|
||||
req.Header.Set("x-opencode-session", opencodeSessionID())
|
||||
if cfg.APIKey != "" && cfg.APIKey != "-" { req.Header.Set("Authorization", "Bearer "+cfg.APIKey) }
|
||||
applyLLMHeaders(req, cfg, ocRequestID())
|
||||
resp, err := client.Do(req)
|
||||
if err != nil || resp.StatusCode >= 400 { return 0 }
|
||||
defer resp.Body.Close()
|
||||
@@ -181,12 +179,7 @@ func listModels(cfg *Cfg) (string, error) {
|
||||
}
|
||||
req, err := http.NewRequest("GET", strings.TrimRight(cfg.Endpoint, "/")+"/models", nil)
|
||||
if err != nil { return "", err }
|
||||
req.Header.Set("User-Agent", opencodeAgentVersion)
|
||||
req.Header.Set("X-Session-Id", projectID())
|
||||
req.Header.Set("x-opencode-project", projectID())
|
||||
req.Header.Set("x-opencode-client", "cli")
|
||||
req.Header.Set("x-opencode-session", opencodeSessionID())
|
||||
if cfg.APIKey != "" && cfg.APIKey != "-" { req.Header.Set("Authorization", "Bearer "+cfg.APIKey) }
|
||||
applyLLMHeaders(req, cfg, ocRequestID())
|
||||
resp, err := client.Do(req)
|
||||
if err != nil { return "", err }
|
||||
defer resp.Body.Close()
|
||||
@@ -1052,6 +1045,7 @@ func llm(ctx context.Context, cfg *Cfg, msgs []Message, tools []map[string]any)
|
||||
pend := c("...requesting...", 1, 2)
|
||||
var resp *http.Response
|
||||
var err error
|
||||
reqID := ocRequestID()
|
||||
for i := 0; i <= len(fib); i++ {
|
||||
if err := ctx.Err(); err != nil {
|
||||
if COL { fmt.Print("\r\033[K") }
|
||||
@@ -1060,12 +1054,7 @@ func llm(ctx context.Context, cfg *Cfg, msgs []Message, tools []map[string]any)
|
||||
if COL { fmt.Print("\r" + pend) } else { fmt.Println(pend) }
|
||||
req, _ := http.NewRequestWithContext(ctx, "POST", strings.TrimRight(cfg.Endpoint, "/")+"/chat/completions", bytes.NewReader(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("User-Agent", opencodeAgentVersion)
|
||||
req.Header.Set("X-Session-Id", projectID())
|
||||
req.Header.Set("x-opencode-project", projectID())
|
||||
req.Header.Set("x-opencode-client", "cli")
|
||||
req.Header.Set("x-opencode-session", opencodeSessionID())
|
||||
if cfg.APIKey != "" && cfg.APIKey != "-" { req.Header.Set("Authorization", "Bearer "+cfg.APIKey) }
|
||||
applyLLMHeaders(req, cfg, reqID)
|
||||
resp, err = client.Do(req)
|
||||
var is4xxClientErr bool
|
||||
if err == nil && resp.StatusCode >= 400 {
|
||||
@@ -1694,6 +1683,57 @@ func opencodeSessionID() string {
|
||||
return "ses_" + pid
|
||||
}
|
||||
|
||||
// isOpencodeEndpoint reports whether the endpoint belongs to OpenCode Zen and
|
||||
// therefore expects the x-opencode-* request headers.
|
||||
func isOpencodeEndpoint(endpoint string) bool {
|
||||
u, err := url.Parse(strings.TrimSpace(endpoint))
|
||||
if err != nil || u.Hostname() == "" {
|
||||
return strings.Contains(strings.ToLower(endpoint), "opencode.ai")
|
||||
}
|
||||
h := strings.ToLower(u.Hostname())
|
||||
return h == "opencode.ai" || strings.HasSuffix(h, ".opencode.ai")
|
||||
}
|
||||
|
||||
// ocRequestID returns a fresh OpenCode-style message id (msg_ followed by 26
|
||||
// base32 characters) matching the ids sent in the x-opencode-request header.
|
||||
func ocRequestID() string {
|
||||
buf := make([]byte, 26)
|
||||
if _, err := rand.Read(buf); err != nil {
|
||||
h := md5.Sum([]byte(fmt.Sprintf("%d-%d", time.Now().UnixNano(), os.Getpid())))
|
||||
for i := range buf {
|
||||
buf[i] = h[i%len(h)]
|
||||
}
|
||||
}
|
||||
var b strings.Builder
|
||||
b.WriteString("msg_")
|
||||
for _, x := range buf {
|
||||
b.WriteByte(opencodeIDAlphabet[int(x)&31])
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
|
||||
// applyLLMHeaders sets the request headers appropriate for the configured
|
||||
// endpoint. OpenCode (Zen) endpoints receive the x-opencode-* family plus the
|
||||
// full provider User-Agent; all other endpoints keep the legacy
|
||||
// session-affinity headers. msgID is used for the x-opencode-request header.
|
||||
func applyLLMHeaders(req *http.Request, cfg *Cfg, msgID string) {
|
||||
sid := opencodeSessionID()
|
||||
if isOpencodeEndpoint(cfg.Endpoint) {
|
||||
req.Header.Set("User-Agent", opencodeAgentVersion+" "+opencodeProviderUA)
|
||||
req.Header.Set("x-opencode-client", "cli")
|
||||
req.Header.Set("x-opencode-project", projectID())
|
||||
req.Header.Set("x-opencode-session", sid)
|
||||
req.Header.Set("x-opencode-request", msgID)
|
||||
} else {
|
||||
req.Header.Set("User-Agent", opencodeAgentVersion)
|
||||
req.Header.Set("x-session-affinity", sid)
|
||||
req.Header.Set("X-Session-Id", sid)
|
||||
}
|
||||
if cfg.APIKey != "" && cfg.APIKey != "-" {
|
||||
req.Header.Set("Authorization", "Bearer "+cfg.APIKey)
|
||||
}
|
||||
}
|
||||
|
||||
func saveSession(msgs []Message, sid string) (string, string) {
|
||||
sid = strings.TrimSpace(sid)
|
||||
if sid == "" {
|
||||
|
||||
Reference in New Issue
Block a user