agent: WorkBuddy's magpie models pointed at another machine's magpie stay there through a sync (悠悠哥 on Discord: 这个问题workbuddy也会有) — as v0.1.891 did for ZCode: a sync rewrote every magpie entry in ~/.workbuddy/models.json to this machine's gateway and key, so models the user had moved to the magpie on a NAS went back to the local one. A sync now keeps the url and apiKey of a magpie entry on another machine (onAnotherMachine) for all of magpie's entries; one on this machine's loopback follows the gateway as before. TestWorkBuddyKeepsRemoteAddress fails on the old code (url http://127.0.0.1:3425/…, key magpie-workbuddy). go vet, builds (darwin, GOOS=linux nogui, GOOS=windows) and go test -tags nogui -count=1 ./... under a temp HOME pass.
This commit is contained in:
1 parent
fe2603ff4f
commit
5daba301ca
2 files changed
+81
-1
No files matched your search
@@ -94,6 +94,8 @@ type workbuddyEntry struct {
|
||||
ID string `json:"id"`
|
||||
Vendor string `json:"vendor"`
|
||||
Disabled *bool `json:"disabled"`
|
||||
URL string `json:"url"`
|
||||
APIKey string `json:"apiKey"`
|
||||
}
|
||||
|
||||
func workbuddyMine(raw json.RawMessage) (workbuddyEntry, bool) {
|
||||
@@ -109,7 +111,9 @@ func workbuddyWired(path string) bool {
|
||||
|
||||
// workbuddyWrite puts magpie's models into models.json (on) or takes them
|
||||
// out, leaving every other entry and key as WorkBuddy wrote it. A model
|
||||
// turned off in WorkBuddy stays off.
|
||||
// turned off in WorkBuddy stays off, and models the user pointed at a magpie
|
||||
// on another machine (a NAS's) stay there with its key, as ZCode's do
|
||||
// (zcodeAddress): a sync brings the models up to date, not the address.
|
||||
func workbuddyWrite(path string, on bool) error {
|
||||
d, err := workbuddyRead(path)
|
||||
if err != nil {
|
||||
@@ -118,12 +122,16 @@ func workbuddyWrite(path string, on bool) error {
|
||||
var kept []json.RawMessage
|
||||
var ours []string
|
||||
off := map[string]bool{}
|
||||
var remote, remoteKey string
|
||||
at := -1 // where magpie's were, which they keep
|
||||
for _, raw := range d.models {
|
||||
if e, ok := workbuddyMine(raw); ok {
|
||||
if at < 0 {
|
||||
at = len(kept)
|
||||
}
|
||||
if remote == "" && onAnotherMachine(e.URL) {
|
||||
remote, remoteKey = e.URL, e.APIKey
|
||||
}
|
||||
ours = append(ours, e.ID)
|
||||
if e.Disabled != nil && *e.Disabled {
|
||||
off[e.ID] = true
|
||||
@@ -143,6 +151,12 @@ func workbuddyWrite(path string, on bool) error {
|
||||
if off[m.ID] {
|
||||
e["disabled"] = true
|
||||
}
|
||||
if remote != "" {
|
||||
e["url"] = remote
|
||||
if remoteKey != "" {
|
||||
e["apiKey"] = remoteKey
|
||||
}
|
||||
}
|
||||
b, err := json.Marshal(e)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -123,3 +123,69 @@ func TestWorkBuddyEfforts(t *testing.T) {
|
||||
t.Fatalf("%v", e)
|
||||
}
|
||||
}
|
||||
|
||||
// WorkBuddy pointed at a magpie on another machine stays there through a
|
||||
// sync, with that magpie's key (悠悠哥 on Discord: models moved to the
|
||||
// magpie on a NAS were put back on this machine's), while one on this
|
||||
// machine's loopback follows the gateway.
|
||||
func TestWorkBuddyKeepsRemoteAddress(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"))
|
||||
t.Setenv("WORKBUDDY_CONFIG_DIR", "")
|
||||
if err := provider.Save(provider.Provider{ID: "deepseek", Name: "DeepSeek", Chat: "https://api.deepseek.com/v1", Key: "k", Models: []string{"pro", "flash"}}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
path := filepath.Join(home, ".workbuddy", "models.json")
|
||||
os.MkdirAll(filepath.Dir(path), 0o755)
|
||||
a := workbuddy(home)
|
||||
if err := a.Field("provider").Set(magpieID); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
read := func() []map[string]any {
|
||||
t.Helper()
|
||||
var ms []map[string]any
|
||||
b, _ := os.ReadFile(path)
|
||||
if err := json.Unmarshal(b, &ms); err != nil {
|
||||
t.Fatalf("%v\n%s", err, b)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
point := func(url, key string) {
|
||||
t.Helper()
|
||||
ms := read()
|
||||
for _, m := range ms {
|
||||
m["url"], m["apiKey"] = url, key
|
||||
}
|
||||
b, _ := json.Marshal(ms)
|
||||
os.WriteFile(path, b, 0o600)
|
||||
}
|
||||
|
||||
const nas = "http://192.168.1.20:3425/v1/chat/completions"
|
||||
point(nas, "nas-key")
|
||||
if err := a.Sync(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ms := read()
|
||||
if len(ms) != 2 {
|
||||
t.Fatalf("models: %v", ms)
|
||||
}
|
||||
for _, m := range ms {
|
||||
if m["url"] != nas || m["apiKey"] != "nas-key" {
|
||||
t.Fatalf("NAS address not kept: %v", m)
|
||||
}
|
||||
}
|
||||
|
||||
// an address on this machine is magpie's own and follows the gateway
|
||||
point("http://localhost:9999/v1/chat/completions", "old")
|
||||
if err := a.Sync(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, m := range read() {
|
||||
if m["url"] != gatewayV1()+"/chat/completions" || m["apiKey"] != "magpie-workbuddy" {
|
||||
t.Fatalf("local address not followed: %v", m)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user