provider: a plugin provider's accounts can be dragged into a new order too (#216) — dragging them failed with "accounts changed; reopen the provider and try again": the account a plugin's provider holds names its agent "plugin", which no list goes by, while the page lists and switches its accounts by the provider's id and logins.json keeps them as plugin:<id>. SetAccountOrder now lists and switches a plugin's accounts by the provider's id and writes their ranks on its plugin:<id> rows, so the order dragged is the order shown and tried. TestAccountOrderPluginAccounts fails without the change. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass (TestAccountProxy flaked once under load, passes alone).

This commit is contained in:
yetone committed 2026-10-02 03:32:42 +08:00
1 parent e230b9f31a
commit 187df65b16
2 files changed
+70 -2

No files matched your search

+13 -2
View File
@@ -10,6 +10,11 @@ func SetAccountOrder(id string, order []string) error {
if err != nil {
return err
}
if p.IsPlugin() {
// a plugin's accounts are listed and switched by the provider's id,
// and kept in logins.json as plugin:<its id>
return arrangeLoginsAs(p.ID, pluginAgent(*p.Account.plugin), order)
}
if p.Account != nil {
return arrangeLogins(p.Account.Agent, order)
}
@@ -39,6 +44,12 @@ func SetAccountOrder(id string, order []string) error {
}
func arrangeLogins(agent string, order []string) error {
return arrangeLoginsAs(agent, agent, order)
}
// arrangeLoginsAs arranges the accounts agent lists and switches, saved in
// logins.json under stored.
func arrangeLoginsAs(agent, stored string, order []string) error {
var available []string
var first Login
for _, l := range Logins(agent) {
@@ -64,7 +75,7 @@ func arrangeLogins(agent string, order []string) error {
rank[user] = i + 1
}
for i := range ls {
if ls[i].Agent == agent {
if ls[i].Agent == stored {
before[ls[i].User] = ls[i].Order
ls[i].Order = rank[ls[i].User]
}
@@ -86,7 +97,7 @@ func arrangeLogins(agent string, order []string) error {
loginsMu.Lock()
ls = readLogins()
for i := range ls {
if ls[i].Agent == agent {
if ls[i].Agent == stored {
ls[i].Order = before[ls[i].User]
}
}
@@ -0,0 +1,57 @@
package provider
import (
"context"
"os/exec"
"path/filepath"
"reflect"
"testing"
"time"
"github.com/yetone/magpie/internal/plugin"
)
// A plugin provider's accounts are arranged like a built-in's: the page
// names them by the provider's id, magpie keeps them as plugin:<id>, and
// the gateway tries them in the order dragged.
func TestAccountOrderPluginAccounts(t *testing.T) {
bun, err := exec.LookPath("bun")
if err != nil {
t.Skip("no bun on PATH")
}
claudeHome(t)
t.Setenv("MAGPIE_BUN", bun)
t.Cleanup(plugin.Settle)
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()
abs, _ := filepath.Abs("../plugin/testdata/fake/index.js")
if _, err := plugin.Add(ctx, abs); err != nil {
t.Fatal(err)
}
var rows []savedLogin
users := []string{"a@fake", "b@fake", "c@fake"}
for _, user := range users {
k, err := plugin.Import(ctx, "fakeco", map[string]any{"type": "oauth", "refresh": "r-" + user, "access": "a", "expires": 9e15, "accountId": user})
if err != nil {
t.Fatal(err)
}
rows = append(rows, savedLogin{Agent: "plugin:fakeco", User: user, Home: k, On: true})
}
saveLogins(t, rows...)
if _, err := plugin.Providers(ctx); err != nil {
t.Fatal(err)
}
id := PluginID("fakeco")
order := []string{"c@fake", "a@fake", "b@fake"}
if err := SetAccountOrder(id, order); err != nil {
t.Fatal(err)
}
shown, _ := loginUsers(Logins(id))
p, err := Find(id)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(shown, order) || !reflect.DeepEqual(loginRoutingUsers(p), order) {
t.Fatalf("display=%v routing=%v", shown, loginRoutingUsers(p))
}
}