agent: every agent in a WSL distro under NAT is given the LAN sharing key, not "magpie" (whqtian on Discord) — v0.1.972 gave it to omp only, and OpenCode in WSL was still written "apiKey": "magpie" with Windows' address, which the gateway takes from loopback only. keyAt(gw) is the key for a gateway URL: the LAN sharing key when the URL isn't this machine's and sharing is on, else gateway.Token; OpenCode (and MiMo Code), Crush, Pi/omo, Codex, Claude Code, Kimi Code, Hermes, Grok, MiniMax Code, Droid, Morph, dsh, Qoder/Qoder CN and omp write it, their Checks compare against it (an old "magpie" there shows as drift), and ourKey still sees a LAN-keyed config as magpie's. TestGatewayKeyBeyondLoopback fails without the change. go vet ./..., go test -tags nogui ./internal/agent ./internal/gui ./internal/gateway ./internal/access ./internal/provider under a temp HOME, GOOS=linux/windows go build pass.
This commit is contained in:
1 parent
2c801b6f9a
commit
e77a373792
14 files changed
+161
-46
No files matched your search
@@ -337,7 +337,7 @@ func magpieProviderJSONAt(shape, catalog, gw string) any {
|
||||
ms[m.ID] = e
|
||||
}
|
||||
return map[string]any{"npm": "@ai-sdk/openai-compatible", "name": "magpie",
|
||||
"options": map[string]any{"baseURL": gw + "/v1", "apiKey": gateway.Token}, "models": ms}
|
||||
"options": map[string]any{"baseURL": gw + "/v1", "apiKey": keyAt(gw)}, "models": ms}
|
||||
case "crush":
|
||||
var ms []map[string]any
|
||||
for _, m := range models {
|
||||
@@ -359,7 +359,7 @@ func magpieProviderJSONAt(shape, catalog, gw string) any {
|
||||
if ms == nil {
|
||||
ms = []map[string]any{}
|
||||
}
|
||||
return map[string]any{"type": "openai", "name": "magpie", "base_url": gw + "/v1", "api_key": gateway.Token, "models": ms}
|
||||
return map[string]any{"type": "openai", "name": "magpie", "base_url": gw + "/v1", "api_key": keyAt(gw), "models": ms}
|
||||
case "pi":
|
||||
var ms []map[string]any
|
||||
for _, m := range models {
|
||||
@@ -368,7 +368,7 @@ func magpieProviderJSONAt(shape, catalog, gw string) any {
|
||||
if ms == nil {
|
||||
ms = []map[string]any{}
|
||||
}
|
||||
return map[string]any{"name": "magpie", "baseUrl": gw + "/v1", "api": "openai-completions", "apiKey": gateway.Token, "models": ms}
|
||||
return map[string]any{"name": "magpie", "baseUrl": gw + "/v1", "api": "openai-completions", "apiKey": keyAt(gw), "models": ms}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -613,7 +613,7 @@ func openCodeLike(at place, id, name, icon, bin, dir, auth string, ua []string,
|
||||
return ""
|
||||
}
|
||||
return wiringOff(name, path, func(k string) (string, bool) { return edit.GetJSON(path, "provider."+magpieID+".options."+k) },
|
||||
"baseURL", at.v1(), "apiKey", gateway.Token)
|
||||
"baseURL", at.v1(), "apiKey", at.gwKey())
|
||||
},
|
||||
Sync: func() error {
|
||||
// a model of magpie's chosen, but its provider gone from the
|
||||
@@ -802,7 +802,7 @@ func piLike(at place, id, name, dir string) *Agent {
|
||||
return ""
|
||||
}
|
||||
return wiringOff(name, modelsPath, func(k string) (string, bool) { return edit.GetJSON(modelsPath, "providers."+magpieID+"."+k) },
|
||||
"baseUrl", at.v1(), "apiKey", gateway.Token)
|
||||
"baseUrl", at.v1(), "apiKey", at.gwKey())
|
||||
},
|
||||
Sync: func() error {
|
||||
return syncJSON(modelsPath, "providers."+magpieID, func() any { return magpieProviderJSONAt("pi", id, at.gw()) })
|
||||
@@ -1158,7 +1158,7 @@ func crushAt(at place, path, data string) *Agent {
|
||||
return ""
|
||||
}
|
||||
return wiringOff("Crush", path, func(k string) (string, bool) { return get("providers." + magpieID + "." + k) },
|
||||
"base_url", at.v1(), "api_key", gateway.Token)
|
||||
"base_url", at.v1(), "api_key", at.gwKey())
|
||||
},
|
||||
Sync: func() error {
|
||||
return syncJSON(path, "providers."+magpieID, provider)
|
||||
|
||||
@@ -572,7 +572,7 @@ func claudeIn(at place) *Agent {
|
||||
return err
|
||||
}
|
||||
keys := []string{"model"}
|
||||
if env("ANTHROPIC_AUTH_TOKEN") == gateway.Token {
|
||||
if ourKey(env("ANTHROPIC_AUTH_TOKEN")) {
|
||||
// magpie's, left at a gateway address since changed
|
||||
for _, k := range claudeEnv {
|
||||
keys = append(keys, "env."+k)
|
||||
@@ -651,7 +651,7 @@ func claudeIn(at place) *Agent {
|
||||
}
|
||||
kvs := []edit.KV{
|
||||
{Path: "env.ANTHROPIC_BASE_URL", Value: at.gw()},
|
||||
{Path: "env.ANTHROPIC_AUTH_TOKEN", Value: gateway.Token},
|
||||
{Path: "env.ANTHROPIC_AUTH_TOKEN", Value: at.gwKey()},
|
||||
{Path: "env.ANTHROPIC_SMALL_FAST_MODEL", Value: tiers["haiku"]},
|
||||
{Path: "model", Value: main},
|
||||
}
|
||||
@@ -1042,7 +1042,7 @@ func claudeIn(at place) *Agent {
|
||||
return "Claude Code's managed settings (" + at.native(managed) + ") set ANTHROPIC_BASE_URL to " + u + ", which wins over magpie's"
|
||||
}
|
||||
return wiringOff("Claude Code", path, func(k string) (string, bool) { return edit.GetJSON(path, "env."+k) },
|
||||
"ANTHROPIC_BASE_URL", at.gw(), "ANTHROPIC_AUTH_TOKEN", gateway.Token)
|
||||
"ANTHROPIC_BASE_URL", at.gw(), "ANTHROPIC_AUTH_TOKEN", at.gwKey())
|
||||
},
|
||||
// every prompt typed into Claude Code goes into history.jsonl
|
||||
LastUsed: func() time.Time {
|
||||
|
||||
@@ -148,7 +148,7 @@ func codexIn(at place) *Agent {
|
||||
edit.KV{Path: "name", Value: "magpie"},
|
||||
edit.KV{Path: "base_url", Value: at.v1()},
|
||||
edit.KV{Path: "wire_api", Value: "responses"},
|
||||
edit.KV{Path: "experimental_bearer_token", Value: gateway.Token},
|
||||
edit.KV{Path: "experimental_bearer_token", Value: at.gwKey()},
|
||||
)
|
||||
}
|
||||
hasProvider := func() bool {
|
||||
@@ -739,7 +739,7 @@ func codexIn(at place) *Agent {
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
if t["base_url"] != at.v1() || t["experimental_bearer_token"] != gateway.Token || t["wire_api"] != "responses" {
|
||||
if t["base_url"] != at.v1() || t["experimental_bearer_token"] != at.gwKey() || t["wire_api"] != "responses" {
|
||||
return "Codex's [model_providers.magpie] no longer points at magpie's gateway (" + at.v1() + ")"
|
||||
}
|
||||
if c := get("model_catalog_json"); !ownCatalog(c) {
|
||||
@@ -1057,7 +1057,7 @@ func codexKeptGateway(path string) string {
|
||||
}
|
||||
base, _ := edit.GetTOMLTop(path, "openai_base_url")
|
||||
var table string
|
||||
if t, _ := edit.GetTOMLTable(path, "model_providers."+magpieID); t["experimental_bearer_token"] == gateway.Token {
|
||||
if t, _ := edit.GetTOMLTable(path, "model_providers."+magpieID); ourKey(t["experimental_bearer_token"]) {
|
||||
table = kept(t["base_url"], "/v1")
|
||||
}
|
||||
// the one Codex is on first: magpie's table when it is the provider
|
||||
|
||||
@@ -65,7 +65,7 @@ func droidEntries() []droidEntry { return droidEntriesAt(gateway.URL()) }
|
||||
func droidEntriesAt(gw string) []droidEntry {
|
||||
var out []droidEntry
|
||||
for _, m := range magpieModels("droid") {
|
||||
e := droidEntry{Model: m.ID, ID: droidID + m.ID, BaseURL: gw + "/v1", APIKey: gateway.Token,
|
||||
e := droidEntry{Model: m.ID, ID: droidID + m.ID, BaseURL: gw + "/v1", APIKey: keyAt(gw),
|
||||
Provider: "generic-chat-completion-api", MaxContextLimit: m.Context, MaxOutputTokens: maxTokens(m), NoImageSupport: !m.Images}
|
||||
switch {
|
||||
case slices.Contains(m.APIs, string(provider.Responses)):
|
||||
@@ -238,7 +238,7 @@ func droidIn(at place) *Agent {
|
||||
base = at.gw()
|
||||
}
|
||||
return wiringOff("Droid", path, func(k string) (string, bool) { g := r.Get(k); return g.String(), g.Exists() },
|
||||
"baseUrl", base, "apiKey", gateway.Token)
|
||||
"baseUrl", base, "apiKey", at.gwKey())
|
||||
},
|
||||
Fields: []Field{{
|
||||
Key: "model", Label: "model",
|
||||
|
||||
+10
-10
@@ -141,7 +141,7 @@ func dshAt(at place) *Agent {
|
||||
if err := dshMirrorHome(dir, nil, gw(), true); err != nil {
|
||||
return err
|
||||
}
|
||||
return dshEnv(dir, false)
|
||||
return dshEnv(dir, gw(), false)
|
||||
},
|
||||
Fields: []Field{{
|
||||
Key: "model", Label: "model",
|
||||
@@ -697,11 +697,11 @@ func dshCheck(dir, gw string) string {
|
||||
}
|
||||
env := filepath.Join(dir, ".env")
|
||||
if off := wiringOff("DeepSeek Harness", env, func(k string) (string, bool) { return edit.GetEnvFile(env, k) },
|
||||
dshKeyRef, gateway.Token); off != "" {
|
||||
dshKeyRef, keyAt(gw)); off != "" {
|
||||
return off
|
||||
}
|
||||
creds := filepath.Join(dir, ".credentials.yaml")
|
||||
if v, ok := edit.GetYAML(creds, "refs."+dshKeyRef); ok && v != gateway.Token {
|
||||
if v, ok := edit.GetYAML(creds, "refs."+dshKeyRef); ok && v != keyAt(gw) {
|
||||
return "DeepSeek Harness's own key store (" + creds + ") holds another " + dshKeyRef + ", which it uses over magpie's; remove it there (dsh's Models page, Magpie's key) to go through magpie"
|
||||
}
|
||||
return ""
|
||||
@@ -759,7 +759,7 @@ func dshSet(dir, v, gw string) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := dshEnv(dir, viaGateway); err != nil {
|
||||
if err := dshEnv(dir, gw, viaGateway); err != nil {
|
||||
return err
|
||||
}
|
||||
// a model picked in dsh 0.1.x is saved in its settings and goes over
|
||||
@@ -773,18 +773,18 @@ func dshSet(dir, v, gw string) error {
|
||||
|
||||
// dshEnv puts the key for the gateway in $DSH_HOME/.env, or with on false
|
||||
// takes it out; the name magpie's llm-deepseek entry used goes either way.
|
||||
func dshEnv(dir string, on bool) error {
|
||||
func dshEnv(dir, gw string, on bool) error {
|
||||
env := filepath.Join(dir, ".env")
|
||||
if on {
|
||||
if v, ok := edit.GetEnvFile(env, dshKeyRef); !ok || v != gateway.Token {
|
||||
if err := edit.SetEnvFile(env, edit.KV{Path: dshKeyRef, Value: gateway.Token}); err != nil {
|
||||
if v, ok := edit.GetEnvFile(env, dshKeyRef); !ok || v != keyAt(gw) {
|
||||
if err := edit.SetEnvFile(env, edit.KV{Path: dshKeyRef, Value: keyAt(gw)}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, k := range []string{dshKeyRef, dshOldKeyRef} {
|
||||
// the old name only as magpie left it
|
||||
if v, ok := edit.GetEnvFile(env, k); ok && !(k == dshKeyRef && on) && (k == dshKeyRef || v == gateway.Token) {
|
||||
if v, ok := edit.GetEnvFile(env, k); ok && !(k == dshKeyRef && on) && (k == dshKeyRef || ourKey(v)) {
|
||||
if err := edit.DelEnvFile(env, k); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1108,7 +1108,7 @@ func dshProviderLines(effort string, models []catalog.Model, gw string) []string
|
||||
lines := []string{
|
||||
"- id: llm-deepseek " + dshMark,
|
||||
" config:",
|
||||
" apiKey: " + yamlQuote(gateway.Token),
|
||||
" apiKey: " + yamlQuote(keyAt(gw)),
|
||||
" baseURL: " + yamlQuote(gw+"/v1"),
|
||||
" thinking: enabled",
|
||||
" reasoningEffort: " + effort,
|
||||
@@ -1190,7 +1190,7 @@ func dshSync(dir, gw string) error {
|
||||
defer func() {
|
||||
// the key under the name the route gives it, moved from the old one
|
||||
if _, items, err := dshRead(files[0]); err == nil && dshWired(items) {
|
||||
dshEnv(dir, true)
|
||||
dshEnv(dir, gw, true)
|
||||
}
|
||||
}()
|
||||
for _, f := range files {
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"github.com/yetone/magpie/internal/access"
|
||||
"github.com/yetone/magpie/internal/gateway"
|
||||
)
|
||||
|
||||
// keyAt is the key an agent that reaches the gateway at gw sends it. On
|
||||
// this machine's loopback that is gateway.Token, which the gateway takes
|
||||
// from this computer only; from another machine — a WSL distro under NAT,
|
||||
// which asks Windows' address — the gateway turns a request without a
|
||||
// named key away, so it is the LAN sharing key, while sharing is on
|
||||
// (whqtian on Discord: omp, then OpenCode, in WSL were refused).
|
||||
func keyAt(gw string) string {
|
||||
if onAnotherMachine(gw) {
|
||||
if k := access.LANSecret(); k != "" {
|
||||
return k
|
||||
}
|
||||
}
|
||||
return gateway.Token
|
||||
}
|
||||
|
||||
// gwKey is keyAt for the agent at p.
|
||||
func (p place) gwKey() string { return keyAt(p.gw()) }
|
||||
|
||||
// agentKeyAt is keyAt for an agent whose key on this machine names it
|
||||
// (gateway.TokenFor), for requests that carry nothing else of it.
|
||||
func agentKeyAt(agent, gw string) string {
|
||||
if k := keyAt(gw); k != gateway.Token {
|
||||
return k
|
||||
}
|
||||
return gateway.TokenFor(agent)
|
||||
}
|
||||
|
||||
// ourKey says k is a key magpie gives an agent: gateway.Token, or the LAN
|
||||
// sharing key one that reaches the gateway from elsewhere is given.
|
||||
func ourKey(k string) bool {
|
||||
if k == gateway.Token {
|
||||
return true
|
||||
}
|
||||
return k != "" && k == access.LANSecret()
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/yetone/magpie/internal/access"
|
||||
"github.com/yetone/magpie/internal/gateway"
|
||||
)
|
||||
|
||||
// An agent in a WSL distro under NAT reaches the gateway at Windows'
|
||||
// address, where gateway.Token is turned away (whqtian on Discord: OpenCode
|
||||
// in WSL was written "apiKey": "magpie" and refused). Every agent's config
|
||||
// carries the LAN sharing key there while sharing is on, and gateway.Token on
|
||||
// loopback, or while nothing is shared.
|
||||
func TestGatewayKeyBeyondLoopback(t *testing.T) {
|
||||
home := t.TempDir()
|
||||
t.Setenv("HOME", home)
|
||||
t.Setenv("USERPROFILE", home)
|
||||
t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config"))
|
||||
t.Setenv("XDG_CACHE_HOME", filepath.Join(home, ".cache"))
|
||||
wsl := "http://172.23.80.1:3425"
|
||||
local := "http://127.0.0.1:3425"
|
||||
|
||||
keys := func(gw string) map[string]string {
|
||||
oc := magpieProviderJSONAt("opencode", "opencode", gw).(map[string]any)["options"].(map[string]any)
|
||||
cr := magpieProviderJSONAt("crush", "crush", gw).(map[string]any)
|
||||
pi := magpieProviderJSONAt("pi", "pi", gw).(map[string]any)
|
||||
out := map[string]string{
|
||||
"opencode": oc["apiKey"].(string),
|
||||
"crush": cr["api_key"].(string),
|
||||
"pi": pi["apiKey"].(string),
|
||||
"hermes": hermesProviderAt(gw).APIKey,
|
||||
}
|
||||
for _, e := range droidEntriesAt(gw) {
|
||||
out["droid"] = e.APIKey
|
||||
}
|
||||
return out
|
||||
}
|
||||
want := func(gw, key string) {
|
||||
t.Helper()
|
||||
for agent, k := range keys(gw) {
|
||||
if k != key {
|
||||
t.Errorf("%s at %s: key %q, want %q", agent, gw, k, key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
want(wsl, gateway.Token) // nothing shared: nothing else to give
|
||||
if err := access.ConfigureLAN(true, false); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
lan := access.LANSecret()
|
||||
if !strings.HasPrefix(lan, access.Prefix) {
|
||||
t.Fatalf("LAN key %q", lan)
|
||||
}
|
||||
want(wsl, lan)
|
||||
want(local, gateway.Token)
|
||||
want("http://localhost:3425", gateway.Token)
|
||||
if k := qoderProviderAt("qoder", "", wsl+"/v1")["apiKey"]; k != lan {
|
||||
t.Errorf("Qoder in WSL: key %q, want the LAN key", k)
|
||||
}
|
||||
if k := qoderProviderAt("qoder", "", local+"/v1")["apiKey"]; k != gateway.TokenFor("qoder") {
|
||||
t.Errorf("Qoder on loopback: key %q", k)
|
||||
}
|
||||
if !ourKey(lan) || !ourKey(gateway.Token) || ourKey("sk-someone-else") || ourKey("") {
|
||||
t.Error("ourKey tells magpie's keys from others wrongly")
|
||||
}
|
||||
if !qoderKeyed(lan, "qoder") {
|
||||
t.Error("a Qoder given the LAN key isn't seen as on magpie")
|
||||
}
|
||||
|
||||
if err := access.ConfigureLAN(false, false); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
want(wsl, gateway.Token)
|
||||
}
|
||||
@@ -25,7 +25,6 @@ import (
|
||||
|
||||
"github.com/yetone/magpie/internal/catalog"
|
||||
"github.com/yetone/magpie/internal/edit"
|
||||
"github.com/yetone/magpie/internal/gateway"
|
||||
)
|
||||
|
||||
// grokEfforts are the reasoning efforts Grok knows.
|
||||
@@ -43,7 +42,7 @@ func grokModelTables(v1 string) []edit.Table {
|
||||
{Path: "model", Value: m.ID},
|
||||
{Path: "name", Value: m.Name},
|
||||
{Path: "base_url", Value: v1},
|
||||
{Path: "api_key", Value: gateway.Token},
|
||||
{Path: "api_key", Value: keyAt(v1)},
|
||||
{Path: "api_backend", Value: "chat_completions"},
|
||||
}
|
||||
if m.Context > 0 {
|
||||
@@ -153,7 +152,7 @@ func grokIn(at place) *Agent {
|
||||
return "Grok Build's [model." + strconv.Quote(v) + "] (config.toml) is gone, so it no longer reaches magpie"
|
||||
}
|
||||
return wiringOff("Grok Build", path, func(k string) (string, bool) { v, ok := t[k]; return v, ok },
|
||||
"base_url", at.v1(), "api_key", gateway.Token)
|
||||
"base_url", at.v1(), "api_key", at.gwKey())
|
||||
},
|
||||
Fields: []Field{
|
||||
{
|
||||
|
||||
@@ -69,7 +69,7 @@ func hermesIn(at place) *Agent {
|
||||
return ""
|
||||
}
|
||||
return wiringOff("Hermes", path, func(k string) (string, bool) { return edit.GetYAML(path, "providers."+magpieID+"."+k) },
|
||||
"base_url", at.v1(), "api_key", gateway.Token)
|
||||
"base_url", at.v1(), "api_key", at.gwKey())
|
||||
},
|
||||
Fields: []Field{{
|
||||
Key: "model", Label: "model",
|
||||
@@ -152,7 +152,7 @@ func hermesProviderAt(gw string) hermesProviderEntry {
|
||||
ms = append(ms, m.ID)
|
||||
}
|
||||
return hermesProviderEntry{
|
||||
Name: magpieID, BaseURL: gw + "/v1", APIKey: gateway.Token, APIMode: "chat_completions",
|
||||
Name: magpieID, BaseURL: gw + "/v1", APIKey: keyAt(gw), APIMode: "chat_completions",
|
||||
Headers: map[string]string{"User-Agent": "hermes-agent"}, Models: ms,
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,6 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/yetone/magpie/internal/edit"
|
||||
"github.com/yetone/magpie/internal/gateway"
|
||||
)
|
||||
|
||||
// kimiModelTable is the header prefix of every model table magpie writes.
|
||||
@@ -130,7 +129,7 @@ func kimiIn(at place) *Agent {
|
||||
if err := edit.SetTOMLTable(path, providerTable,
|
||||
edit.KV{Path: "type", Value: "kimi"},
|
||||
edit.KV{Path: "base_url", Value: at.v1()},
|
||||
edit.KV{Path: "api_key", Value: gateway.Token},
|
||||
edit.KV{Path: "api_key", Value: at.gwKey()},
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -191,7 +190,7 @@ func kimiIn(at place) *Agent {
|
||||
return "Kimi Code's [" + providerTable + "] (config.toml) is gone, so it no longer reaches magpie"
|
||||
}
|
||||
return wiringOff("Kimi Code", path, func(k string) (string, bool) { v, ok := t[k]; return v, ok },
|
||||
"base_url", at.v1(), "api_key", gateway.Token)
|
||||
"base_url", at.v1(), "api_key", at.gwKey())
|
||||
},
|
||||
Fields: []Field{{
|
||||
Key: "model", Label: "model",
|
||||
|
||||
@@ -102,7 +102,7 @@ func miniMaxAt(at place, dir string) *Agent {
|
||||
return "MiniMax Code's " + mcodeEntry + " (config.yaml) is turned off, so it no longer reaches magpie"
|
||||
}
|
||||
return wiringOff("MiniMax Code", path, func(k string) (string, bool) { return edit.GetYAML(path, mcodeEntry+".options."+k) },
|
||||
"baseURL", at.gw(), "apiKey", gateway.Token)
|
||||
"baseURL", at.gw(), "apiKey", at.gwKey())
|
||||
},
|
||||
Fields: []Field{{
|
||||
Key: "model", Label: "model",
|
||||
@@ -183,7 +183,7 @@ func writeMiniMaxEntryAt(path, gw string) error {
|
||||
// sends them; MiniMax Code's own API is that too
|
||||
yamlSet(entry, "api", "anthropic-messages")
|
||||
opts := yamlMap(entry, "options")
|
||||
yamlSet(opts, "apiKey", gateway.Token)
|
||||
yamlSet(opts, "apiKey", keyAt(gw))
|
||||
yamlSet(opts, "baseURL", gw)
|
||||
yamlSet(opts, "authMode", "api-key")
|
||||
yamlSet(yamlMap(opts, "headers"), "User-Agent", mcodeUA)
|
||||
|
||||
@@ -21,7 +21,6 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/yetone/magpie/internal/edit"
|
||||
"github.com/yetone/magpie/internal/gateway"
|
||||
)
|
||||
|
||||
// morphUA is the User-Agent magpie has morph send, in llm.headers: its
|
||||
@@ -46,7 +45,7 @@ func morphIn(at place) *Agent {
|
||||
getKey := func(k string) string { v, _ := edit.GetYAML(path, "llm."+k); return v }
|
||||
// the token is magpie's alone, where the endpoint moves with the
|
||||
// gateway's port
|
||||
onMagpie := func() bool { return getKey("api_key") == gateway.Token }
|
||||
onMagpie := func() bool { return ourKey(getKey("api_key")) }
|
||||
// restore puts back what the user had under llm before magpie
|
||||
restore := func() error {
|
||||
var del []string
|
||||
@@ -135,7 +134,7 @@ func morphIn(at place) *Agent {
|
||||
kvs := []edit.KV{
|
||||
{Path: "llm.inference_provider", Value: "openai_response_compatible"},
|
||||
{Path: "llm.endpoint", Value: at.v1()},
|
||||
{Path: "llm.api_key", Value: gateway.Token},
|
||||
{Path: "llm.api_key", Value: at.gwKey()},
|
||||
{Path: "llm.model", Value: ref},
|
||||
{Path: "llm.headers.User-Agent", Value: morphUA},
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/yetone/magpie/internal/access"
|
||||
"github.com/yetone/magpie/internal/appdir"
|
||||
"github.com/yetone/magpie/internal/catalog"
|
||||
"github.com/yetone/magpie/internal/edit"
|
||||
@@ -480,10 +479,8 @@ func ompProviderAt(gw, version string) ompProviderEntry {
|
||||
Headers: map[string]string{"User-Agent": "omp"}, Models: ms}
|
||||
// whqtian on Discord: a WSL omp under NAT asks Windows' address, where
|
||||
// the gateway turns a request without a named key away
|
||||
if onAnotherMachine(gw) {
|
||||
if key := access.LANSecret(); key != "" {
|
||||
e.Auth, e.APIKey = "", key
|
||||
}
|
||||
if key := keyAt(gw); key != gateway.Token {
|
||||
e.Auth, e.APIKey = "", key
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
@@ -288,13 +288,14 @@ func qoderProviderAt(agent, model, v1 string) map[string]any {
|
||||
ms = append(ms, e)
|
||||
}
|
||||
return map[string]any{"displayName": "magpie", "protocol": "openai", "baseUrl": v1,
|
||||
"apiKey": gateway.TokenFor(agent), "model": model, "models": ms}
|
||||
"apiKey": agentKeyAt(agent, v1), "model": model, "models": ms}
|
||||
}
|
||||
|
||||
// qoderKeyed: key is one magpie gives Qoder's provider — its own,
|
||||
// gateway.TokenFor, since Qoder's requests carry Bun's User-Agent and
|
||||
// nothing of Qoder's, or gateway.Token, which it was given before; a sync
|
||||
// gives it the new one.
|
||||
// nothing of Qoder's, gateway.Token, which it was given before, or the LAN
|
||||
// sharing key one in a WSL distro is given (agentKeyAt); a sync gives it
|
||||
// the new one.
|
||||
func qoderKeyed(key, agent string) bool {
|
||||
return key == gateway.TokenFor(agent) || key == gateway.Token
|
||||
return key == gateway.TokenFor(agent) || ourKey(key)
|
||||
}
|
||||
Reference in new issue
Block a user