diff --git a/AGENTS.md b/AGENTS.md index 42d2ec96..8b6b2e1b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -16,7 +16,7 @@ that does the same job: | Grok | `grok` | `@magpie-community/opencode-grok-auth` | `internal/provider/migrate_side.go` | | Kiro | `kiro` | `@magpie-community/opencode-kiro-auth` | `internal/provider/migrate_kiro.go` | | Xiaomi MiMo | `mimo-app` | `@magpie-community/opencode-mimo-auth` | `internal/provider/migrate_mimo.go` | -| Qoder (qoder.com only; Qoder CN isn't moved) | `qoder` | `@magpie-community/opencode-qoder-auth` | `internal/provider/migrate_qoder.go` | +| Qoder, Qoder CN | `qoder`, `qoder-cn` | `@magpie-community/opencode-qoder-auth` | `internal/provider/migrate_qoder.go` | | WorkBuddy, WorkBuddy AI | `workbuddy`, `workbuddy-ai` | `@magpie-community/opencode-workbuddy-auth` | `internal/provider/migrate_workbuddy.go` | | ZCode | `zcode` | `@magpie-community/opencode-zcode-auth` | `internal/provider/migrate_zcode.go` | | Zed | `zed` | `@magpie-community/opencode-zed-auth` | `internal/provider/migrate_zed.go` | diff --git a/internal/gateway/qoder.go b/internal/gateway/qoder.go index 18f4184c..a0190d48 100644 --- a/internal/gateway/qoder.go +++ b/internal/gateway/qoder.go @@ -1,14 +1,13 @@ package gateway -// PLUGIN-SERVED (see AGENTS.md): Qoder ("qoder") is a deprecated built-in -// subscription served by its plugin, @magpie-community/opencode-qoder-auth, -// once moved onto it (provider.Moved; the default for a new sign-in). A -// moved one's sign-ins, models, requests and usage are all the plugin's, -// never this code's (only the move, in migrate*.go, still reads its -// accounts). A fix here alone doesn't reach those users; fix the plugin +// PLUGIN-SERVED (see AGENTS.md): Qoder ("qoder") and Qoder CN ("qoder-cn") +// are deprecated built-in subscriptions served by their plugin, +// @magpie-community/opencode-qoder-auth, each once moved onto it +// (provider.Moved; the default for a new sign-in). A moved one's +// sign-ins, models, requests and usage are all the plugin's, never this +// code's (only the move, in migrate*.go, still reads its accounts). A fix here alone doesn't reach those users; fix the plugin // (github.com/magpie-community/plugins, packages/qoder) and raise the -// mover's min in internal/provider/migrate_qoder.go. Qoder CN ("qoder-cn") -// isn't moved and still runs here. +// movers' min in internal/provider/migrate_qoder.go. import ( "bufio" diff --git a/internal/provider/migrate_movers_test.go b/internal/provider/migrate_movers_test.go index 9e2562d3..6615ef34 100644 --- a/internal/provider/migrate_movers_test.go +++ b/internal/provider/migrate_movers_test.go @@ -97,6 +97,23 @@ func TestQoderMover(t *testing.T) { }) } +// A Qoder CN account keeps its site, and one that chats on its device +// token keeps doing so. +func TestQoderCNMover(t *testing.T) { + c1 := qoder.Credential{Site: QoderCNID, UID: "u1", Email: "a@q.cn", Token: "d1", RefreshToken: "dr1", DeviceToken: "d1", DeviceRefresh: "dr1", DeviceChat: true, ExpiresAt: 1_900_000_000_123, MachineID: "m1"} + c2 := qoder.Credential{Site: QoderCNID, UID: "u2", Token: "t2", RefreshToken: "r2", DeviceToken: "d2", ExpiresAt: 1_900_000_000_456, MachineID: "m2"} + roundTrip(t, QoderCNID, []savedLogin{ + {Agent: QoderCNID, User: "a@q.cn", First: true, On: true, Auth: authOf(t, c1)}, + {Agent: QoderCNID, User: "u2", Auth: authOf(t, c2)}, + }, func(t *testing.T, a, b savedLogin) { + ca, _ := qoderSaved(a) + cb, _ := qoderSaved(b) + if !reflect.DeepEqual(ca, cb) { + t.Fatalf("qoder-cn %s: %+v, want %+v", a.User, cb, ca) + } + }) +} + func TestFactoryMover(t *testing.T) { c1 := factoryCreds{Access: "a1", Refresh: "r1", ExpiresAt: 1_900_000_000_000, Org: "org_1", Active: "fo1", Email: "a@f.com", UserID: "user_1", Region: "eu", Prem: "llm.example.com"} c2 := factoryCreds{Access: "a2", Refresh: "r2", ExpiresAt: 1_900_000_000_001, UserID: "user_2"} diff --git a/internal/provider/migrate_qoder.go b/internal/provider/migrate_qoder.go index 6b28a210..74431c58 100644 --- a/internal/provider/migrate_qoder.go +++ b/internal/provider/migrate_qoder.go @@ -4,20 +4,31 @@ import ( "encoding/json" "errors" "time" + + "github.com/yetone/magpie/internal/qoder" ) -// Qoder's accounts on @magpie-community/opencode-qoder-auth, as its device +// Qoder's and Qoder CN's accounts on @magpie-community/opencode-qoder-auth, +// which serves both sites as providers "qoder" and "qoder-cn", as its device // sign-in keeps one: the job token pair as access and refresh (the refresh // token is spent on use, so it moves rather than being copied), the device -// token pair and machine id beside them. +// token pair and machine id beside them. A Qoder CN account that chats on +// its device token (DeviceChat) says so, its device pair as access and +// refresh. func init() { - movers["qoder"] = &mover{ + for _, id := range []string{"qoder", QoderCNID} { + movers[id] = qoderMover(id) + } +} + +func qoderMover(id string) *mover { + return &mover{ pkg: "@magpie-community/opencode-qoder-auth", - min: "0.1.4", // a failure's status and its sign-in mark as the built-in's; a refused refresh marks the sign-in - agents: []string{"qoder"}, + min: "0.2.0", // Qoder CN as "qoder-cn", its device-token chat as the built-in's + agents: []string{id}, out: func() ([]Moving, error) { // no refresh of the built-in's runs while the pairs are read - ls := qoderLogins() + ls := qoderLoginsOf(id) qoderMu.Lock() defer qoderMu.Unlock() var out []Moving @@ -39,18 +50,21 @@ func init() { "deviceToken": c.DeviceToken, "deviceRefresh": c.DeviceRefresh, }}) + if c.DeviceChat { + out[len(out)-1].Auth["deviceChat"] = true + } } return out, nil }, back: func(ls []savedLogin, user string, auth map[string]any) ([]savedLogin, string, error) { access, uid := str(auth["access"]), str(auth["uid"]) if access == "" || uid == "" { - return ls, "", errors.New("Qoder: an unreadable plugin sign-in") + return ls, "", errors.New(qoder.SiteOf(id).Name + ": an unreadable plugin sign-in") } if user == "" { user = firstNonEmpty(str(auth["accountId"]), str(auth["email"]), uid) } - i := backInto(&ls, "qoder", user) + i := backInto(&ls, id, user) c, _ := qoderSaved(ls[i]) c.UID, c.Token, c.RefreshToken, c.ExpiresAt = uid, access, str(auth["refresh"]), num(auth["expires"]) c.Email = firstNonEmpty(str(auth["email"]), c.Email) @@ -58,6 +72,7 @@ func init() { c.MachineID = firstNonEmpty(str(auth["machineId"]), c.MachineID) c.DeviceToken = firstNonEmpty(str(auth["deviceToken"]), c.DeviceToken) c.DeviceRefresh = firstNonEmpty(str(auth["deviceRefresh"]), c.DeviceRefresh) + c.DeviceChat = auth["deviceChat"] == true b, err := json.Marshal(c) if err != nil { return ls, "", err diff --git a/internal/provider/qoder.go b/internal/provider/qoder.go index 97e98584..42c5c068 100644 --- a/internal/provider/qoder.go +++ b/internal/provider/qoder.go @@ -1,14 +1,13 @@ package provider -// PLUGIN-SERVED (see AGENTS.md): Qoder ("qoder") is a deprecated built-in -// subscription served by its plugin, @magpie-community/opencode-qoder-auth, -// once moved onto it (provider.Moved; the default for a new sign-in). A -// moved one's sign-ins, models, requests and usage are all the plugin's, -// never this code's (only the move, in migrate*.go, still reads its -// accounts). A fix here alone doesn't reach those users; fix the plugin +// PLUGIN-SERVED (see AGENTS.md): Qoder ("qoder") and Qoder CN ("qoder-cn") +// are deprecated built-in subscriptions served by their plugin, +// @magpie-community/opencode-qoder-auth, each once moved onto it +// (provider.Moved; the default for a new sign-in). A moved one's +// sign-ins, models, requests and usage are all the plugin's, never this +// code's (only the move, in migrate*.go, still reads its accounts). A fix here alone doesn't reach those users; fix the plugin // (github.com/magpie-community/plugins, packages/qoder) and raise the -// mover's min in internal/provider/migrate_qoder.go. Qoder CN ("qoder-cn") -// isn't moved and still runs here. +// movers' min in internal/provider/migrate_qoder.go. import ( "context" diff --git a/internal/provider/qoder_usage.go b/internal/provider/qoder_usage.go index 104b5b71..bc19e438 100644 --- a/internal/provider/qoder_usage.go +++ b/internal/provider/qoder_usage.go @@ -1,14 +1,13 @@ package provider -// PLUGIN-SERVED (see AGENTS.md): Qoder ("qoder") is a deprecated built-in -// subscription served by its plugin, @magpie-community/opencode-qoder-auth, -// once moved onto it (provider.Moved; the default for a new sign-in). A -// moved one's sign-ins, models, requests and usage are all the plugin's, -// never this code's (only the move, in migrate*.go, still reads its -// accounts). A fix here alone doesn't reach those users; fix the plugin +// PLUGIN-SERVED (see AGENTS.md): Qoder ("qoder") and Qoder CN ("qoder-cn") +// are deprecated built-in subscriptions served by their plugin, +// @magpie-community/opencode-qoder-auth, each once moved onto it +// (provider.Moved; the default for a new sign-in). A moved one's +// sign-ins, models, requests and usage are all the plugin's, never this +// code's (only the move, in migrate*.go, still reads its accounts). A fix here alone doesn't reach those users; fix the plugin // (github.com/magpie-community/plugins, packages/qoder) and raise the -// mover's min in internal/provider/migrate_qoder.go. Qoder CN ("qoder-cn") -// isn't moved and still runs here. +// movers' min in internal/provider/migrate_qoder.go. import ( "context" diff --git a/internal/qoder/codec.go b/internal/qoder/codec.go index c7675837..e6d75021 100644 --- a/internal/qoder/codec.go +++ b/internal/qoder/codec.go @@ -1,14 +1,13 @@ package qoder -// PLUGIN-SERVED (see AGENTS.md): Qoder ("qoder") is a deprecated built-in -// subscription served by its plugin, @magpie-community/opencode-qoder-auth, -// once moved onto it (provider.Moved; the default for a new sign-in). A -// moved one's sign-ins, models, requests and usage are all the plugin's, -// never this code's (only the move, in migrate*.go, still reads its -// accounts). A fix here alone doesn't reach those users; fix the plugin +// PLUGIN-SERVED (see AGENTS.md): Qoder ("qoder") and Qoder CN ("qoder-cn") +// are deprecated built-in subscriptions served by their plugin, +// @magpie-community/opencode-qoder-auth, each once moved onto it +// (provider.Moved; the default for a new sign-in). A moved one's +// sign-ins, models, requests and usage are all the plugin's, never this +// code's (only the move, in migrate*.go, still reads its accounts). A fix here alone doesn't reach those users; fix the plugin // (github.com/magpie-community/plugins, packages/qoder) and raise the -// mover's min in internal/provider/migrate_qoder.go. Qoder CN ("qoder-cn") -// isn't moved and still runs here. +// movers' min in internal/provider/migrate_qoder.go. import "strings" diff --git a/internal/qoder/cosy.go b/internal/qoder/cosy.go index a0757f0d..c5fbba01 100644 --- a/internal/qoder/cosy.go +++ b/internal/qoder/cosy.go @@ -1,14 +1,13 @@ package qoder -// PLUGIN-SERVED (see AGENTS.md): Qoder ("qoder") is a deprecated built-in -// subscription served by its plugin, @magpie-community/opencode-qoder-auth, -// once moved onto it (provider.Moved; the default for a new sign-in). A -// moved one's sign-ins, models, requests and usage are all the plugin's, -// never this code's (only the move, in migrate*.go, still reads its -// accounts). A fix here alone doesn't reach those users; fix the plugin +// PLUGIN-SERVED (see AGENTS.md): Qoder ("qoder") and Qoder CN ("qoder-cn") +// are deprecated built-in subscriptions served by their plugin, +// @magpie-community/opencode-qoder-auth, each once moved onto it +// (provider.Moved; the default for a new sign-in). A moved one's +// sign-ins, models, requests and usage are all the plugin's, never this +// code's (only the move, in migrate*.go, still reads its accounts). A fix here alone doesn't reach those users; fix the plugin // (github.com/magpie-community/plugins, packages/qoder) and raise the -// mover's min in internal/provider/migrate_qoder.go. Qoder CN ("qoder-cn") -// isn't moved and still runs here. +// movers' min in internal/provider/migrate_qoder.go. import ( "crypto/aes" diff --git a/internal/qoder/endpoints.go b/internal/qoder/endpoints.go index c2c83758..3d230c3d 100644 --- a/internal/qoder/endpoints.go +++ b/internal/qoder/endpoints.go @@ -13,15 +13,14 @@ // phone number and exist only there. A Site holds each one's hosts. package qoder -// PLUGIN-SERVED (see AGENTS.md): Qoder ("qoder") is a deprecated built-in -// subscription served by its plugin, @magpie-community/opencode-qoder-auth, -// once moved onto it (provider.Moved; the default for a new sign-in). A -// moved one's sign-ins, models, requests and usage are all the plugin's, -// never this code's (only the move, in migrate*.go, still reads its -// accounts). A fix here alone doesn't reach those users; fix the plugin +// PLUGIN-SERVED (see AGENTS.md): Qoder ("qoder") and Qoder CN ("qoder-cn") +// are deprecated built-in subscriptions served by their plugin, +// @magpie-community/opencode-qoder-auth, each once moved onto it +// (provider.Moved; the default for a new sign-in). A moved one's +// sign-ins, models, requests and usage are all the plugin's, never this +// code's (only the move, in migrate*.go, still reads its accounts). A fix here alone doesn't reach those users; fix the plugin // (github.com/magpie-community/plugins, packages/qoder) and raise the -// mover's min in internal/provider/migrate_qoder.go. Qoder CN ("qoder-cn") -// isn't moved and still runs here. +// movers' min in internal/provider/migrate_qoder.go. // OAuth device-flow configuration (verified against live captures). const ( diff --git a/internal/qoder/ids.go b/internal/qoder/ids.go index 09f86e86..ee1cd798 100644 --- a/internal/qoder/ids.go +++ b/internal/qoder/ids.go @@ -1,14 +1,13 @@ package qoder -// PLUGIN-SERVED (see AGENTS.md): Qoder ("qoder") is a deprecated built-in -// subscription served by its plugin, @magpie-community/opencode-qoder-auth, -// once moved onto it (provider.Moved; the default for a new sign-in). A -// moved one's sign-ins, models, requests and usage are all the plugin's, -// never this code's (only the move, in migrate*.go, still reads its -// accounts). A fix here alone doesn't reach those users; fix the plugin +// PLUGIN-SERVED (see AGENTS.md): Qoder ("qoder") and Qoder CN ("qoder-cn") +// are deprecated built-in subscriptions served by their plugin, +// @magpie-community/opencode-qoder-auth, each once moved onto it +// (provider.Moved; the default for a new sign-in). A moved one's +// sign-ins, models, requests and usage are all the plugin's, never this +// code's (only the move, in migrate*.go, still reads its accounts). A fix here alone doesn't reach those users; fix the plugin // (github.com/magpie-community/plugins, packages/qoder) and raise the -// mover's min in internal/provider/migrate_qoder.go. Qoder CN ("qoder-cn") -// isn't moved and still runs here. +// movers' min in internal/provider/migrate_qoder.go. import ( "crypto/rand" diff --git a/internal/qoder/models.go b/internal/qoder/models.go index 3dd6fba8..ada585cd 100644 --- a/internal/qoder/models.go +++ b/internal/qoder/models.go @@ -1,14 +1,13 @@ package qoder -// PLUGIN-SERVED (see AGENTS.md): Qoder ("qoder") is a deprecated built-in -// subscription served by its plugin, @magpie-community/opencode-qoder-auth, -// once moved onto it (provider.Moved; the default for a new sign-in). A -// moved one's sign-ins, models, requests and usage are all the plugin's, -// never this code's (only the move, in migrate*.go, still reads its -// accounts). A fix here alone doesn't reach those users; fix the plugin +// PLUGIN-SERVED (see AGENTS.md): Qoder ("qoder") and Qoder CN ("qoder-cn") +// are deprecated built-in subscriptions served by their plugin, +// @magpie-community/opencode-qoder-auth, each once moved onto it +// (provider.Moved; the default for a new sign-in). A moved one's +// sign-ins, models, requests and usage are all the plugin's, never this +// code's (only the move, in migrate*.go, still reads its accounts). A fix here alone doesn't reach those users; fix the plugin // (github.com/magpie-community/plugins, packages/qoder) and raise the -// mover's min in internal/provider/migrate_qoder.go. Qoder CN ("qoder-cn") -// isn't moved and still runs here. +// movers' min in internal/provider/migrate_qoder.go. import ( "context" diff --git a/internal/qoder/oauth.go b/internal/qoder/oauth.go index 7919edf4..92b7de88 100644 --- a/internal/qoder/oauth.go +++ b/internal/qoder/oauth.go @@ -1,14 +1,13 @@ package qoder -// PLUGIN-SERVED (see AGENTS.md): Qoder ("qoder") is a deprecated built-in -// subscription served by its plugin, @magpie-community/opencode-qoder-auth, -// once moved onto it (provider.Moved; the default for a new sign-in). A -// moved one's sign-ins, models, requests and usage are all the plugin's, -// never this code's (only the move, in migrate*.go, still reads its -// accounts). A fix here alone doesn't reach those users; fix the plugin +// PLUGIN-SERVED (see AGENTS.md): Qoder ("qoder") and Qoder CN ("qoder-cn") +// are deprecated built-in subscriptions served by their plugin, +// @magpie-community/opencode-qoder-auth, each once moved onto it +// (provider.Moved; the default for a new sign-in). A moved one's +// sign-ins, models, requests and usage are all the plugin's, never this +// code's (only the move, in migrate*.go, still reads its accounts). A fix here alone doesn't reach those users; fix the plugin // (github.com/magpie-community/plugins, packages/qoder) and raise the -// mover's min in internal/provider/migrate_qoder.go. Qoder CN ("qoder-cn") -// isn't moved and still runs here. +// movers' min in internal/provider/migrate_qoder.go. import ( "bytes" diff --git a/internal/qoder/store.go b/internal/qoder/store.go index b9700e38..85c07626 100644 --- a/internal/qoder/store.go +++ b/internal/qoder/store.go @@ -1,14 +1,13 @@ package qoder -// PLUGIN-SERVED (see AGENTS.md): Qoder ("qoder") is a deprecated built-in -// subscription served by its plugin, @magpie-community/opencode-qoder-auth, -// once moved onto it (provider.Moved; the default for a new sign-in). A -// moved one's sign-ins, models, requests and usage are all the plugin's, -// never this code's (only the move, in migrate*.go, still reads its -// accounts). A fix here alone doesn't reach those users; fix the plugin +// PLUGIN-SERVED (see AGENTS.md): Qoder ("qoder") and Qoder CN ("qoder-cn") +// are deprecated built-in subscriptions served by their plugin, +// @magpie-community/opencode-qoder-auth, each once moved onto it +// (provider.Moved; the default for a new sign-in). A moved one's +// sign-ins, models, requests and usage are all the plugin's, never this +// code's (only the move, in migrate*.go, still reads its accounts). A fix here alone doesn't reach those users; fix the plugin // (github.com/magpie-community/plugins, packages/qoder) and raise the -// mover's min in internal/provider/migrate_qoder.go. Qoder CN ("qoder-cn") -// isn't moved and still runs here. +// movers' min in internal/provider/migrate_qoder.go. import ( "context" diff --git a/internal/qoder/usage.go b/internal/qoder/usage.go index e4d0fd56..1ce864e7 100644 --- a/internal/qoder/usage.go +++ b/internal/qoder/usage.go @@ -1,14 +1,13 @@ package qoder -// PLUGIN-SERVED (see AGENTS.md): Qoder ("qoder") is a deprecated built-in -// subscription served by its plugin, @magpie-community/opencode-qoder-auth, -// once moved onto it (provider.Moved; the default for a new sign-in). A -// moved one's sign-ins, models, requests and usage are all the plugin's, -// never this code's (only the move, in migrate*.go, still reads its -// accounts). A fix here alone doesn't reach those users; fix the plugin +// PLUGIN-SERVED (see AGENTS.md): Qoder ("qoder") and Qoder CN ("qoder-cn") +// are deprecated built-in subscriptions served by their plugin, +// @magpie-community/opencode-qoder-auth, each once moved onto it +// (provider.Moved; the default for a new sign-in). A moved one's +// sign-ins, models, requests and usage are all the plugin's, never this +// code's (only the move, in migrate*.go, still reads its accounts). A fix here alone doesn't reach those users; fix the plugin // (github.com/magpie-community/plugins, packages/qoder) and raise the -// mover's min in internal/provider/migrate_qoder.go. Qoder CN ("qoder-cn") -// isn't moved and still runs here. +// movers' min in internal/provider/migrate_qoder.go. import ( "context" diff --git a/internal/qoder/userinfo.go b/internal/qoder/userinfo.go index 43f17296..75ba9ecb 100644 --- a/internal/qoder/userinfo.go +++ b/internal/qoder/userinfo.go @@ -1,14 +1,13 @@ package qoder -// PLUGIN-SERVED (see AGENTS.md): Qoder ("qoder") is a deprecated built-in -// subscription served by its plugin, @magpie-community/opencode-qoder-auth, -// once moved onto it (provider.Moved; the default for a new sign-in). A -// moved one's sign-ins, models, requests and usage are all the plugin's, -// never this code's (only the move, in migrate*.go, still reads its -// accounts). A fix here alone doesn't reach those users; fix the plugin +// PLUGIN-SERVED (see AGENTS.md): Qoder ("qoder") and Qoder CN ("qoder-cn") +// are deprecated built-in subscriptions served by their plugin, +// @magpie-community/opencode-qoder-auth, each once moved onto it +// (provider.Moved; the default for a new sign-in). A moved one's +// sign-ins, models, requests and usage are all the plugin's, never this +// code's (only the move, in migrate*.go, still reads its accounts). A fix here alone doesn't reach those users; fix the plugin // (github.com/magpie-community/plugins, packages/qoder) and raise the -// mover's min in internal/provider/migrate_qoder.go. Qoder CN ("qoder-cn") -// isn't moved and still runs here. +// movers' min in internal/provider/migrate_qoder.go. import ( "context"