@magpie-community/opencode-trae-auth 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +7 -5
  2. package/index.mjs +30 -4
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -32,9 +32,10 @@ agent's `POST https://trae-api-cn.mchost.guru/api/agent/v3/llm_utils_chat`:
32
32
  - **Request:**
33
33
  - The messages go as `{role, content: [{type: "text", text}]}`.
34
34
  - The model goes as `config_name` and `model`.
35
- - The function is `chat_v3`, the classic IDE's. If Trae answers 4001, 4023
36
- or 1005, the plugin tries `solo_work_lite` (SOLO's) once and remembers
37
- which one worked.
35
+ - The function is the one whose model list has the model (`chat_v3`, the
36
+ classic IDE's, first; else `solo_work_lite`, SOLO's). If Trae answers
37
+ 4001, 4023 or 1005, the plugin tries the other once and remembers which
38
+ one worked.
38
39
  - **Headers:** the IDE's: `Authorization: Cloud-IDE-JWT …`,
39
40
  `X-Cloudide-Token`, `x-app-id`, `x-ide-version`, the device headers and
40
41
  `x-uid`.
@@ -54,8 +55,9 @@ agent's `POST https://trae-api-cn.mchost.guru/api/agent/v3/llm_utils_chat`:
54
55
  - Earlier calls and their results go back in as text.
55
56
  - Images aren't sent.
56
57
 
57
- The model list is the account's own, from `/api/ide/v1/get_detail_param`.
58
- When that can't be read, the plugin uses the models Trae CN's `chat_v3` is
58
+ The model list is the account's own, from `/api/ide/v1/get_detail_param`,
59
+ asked for both functions and put together: SOLO lists models `chat_v3`
60
+ doesn't (DeepSeek-V4.1-Flash). When neither can be read, the plugin uses the models Trae CN's `chat_v3` is
59
61
  known to serve: GLM-5.2, GLM-5, Kimi K2.6, Qwen 3.7 Plus, DeepSeek V4 Pro
60
62
  and DeepSeek V4 Flash.
61
63
 
package/index.mjs CHANGED
@@ -727,6 +727,8 @@ export const TraeCNAuthPlugin = async ({ client }) => {
727
727
  const renewed = new Map()
728
728
  // the chat function that served each account last
729
729
  const fnOf = new Map()
730
+ // the first chat function whose model list has each model
731
+ const listedBy = new Map()
730
732
 
731
733
  const save = async (auth) => {
732
734
  try {
@@ -814,10 +816,10 @@ export const TraeCNAuthPlugin = async ({ client }) => {
814
816
  return out
815
817
  }
816
818
 
817
- // liveModels is the account's model list, as the IDE asks for it
818
- const liveModels = async (a) => {
819
+ // listOf is one function's model list, as the IDE asks for it
820
+ const listOf = async (a, fn) => {
819
821
  const r = await post(a, apiOf(a) + "/api/ide/v1/get_detail_param", {
820
- function: FUNCTIONS[0], config_names: null, need_prompt: false, current_config_info: null, poly_prompt: true, mode_type: null, agent_type: null,
822
+ function: fn, config_names: null, need_prompt: false, current_config_info: null, poly_prompt: true, mode_type: null, agent_type: null,
821
823
  })
822
824
  if (r.status === 401 || lapsedCode(errorOf(r.v).code)) throw new Expired("Trae CN's sign-in has expired; sign in again")
823
825
  if (r.status !== 200) throw new Error(`Trae CN models: ${statusLine(r.status)}`)
@@ -825,6 +827,28 @@ export const TraeCNAuthPlugin = async ({ client }) => {
825
827
  return list.filter((m) => m?.config_name)
826
828
  }
827
829
 
830
+ // liveModels is the account's model list: every chat function's, since
831
+ // SOLO lists models the classic IDE's chat_v3 doesn't (DeepSeek-V4.1-Flash
832
+ // came to SOLO first, yetone/magpie#681); a model listed by one function
833
+ // only is asked through that one. One function's list failing leaves the
834
+ // others'; all failing is the error.
835
+ const liveModels = async (a) => {
836
+ const got = await Promise.allSettled(FUNCTIONS.map((fn) => listOf(a, fn)))
837
+ const expired = got.find((g) => g.status === "rejected" && g.reason instanceof Expired)
838
+ if (expired) throw expired.reason
839
+ if (got.every((g) => g.status === "rejected")) throw got[0].reason
840
+ const out = new Map()
841
+ got.forEach((g, i) => {
842
+ if (g.status !== "fulfilled") return
843
+ for (const m of g.value) {
844
+ const id = String(m.config_name)
845
+ if (!out.has(id)) out.set(id, { m, fn: FUNCTIONS[i] })
846
+ }
847
+ })
848
+ for (const [id, { fn }] of out) listedBy.set(id, fn)
849
+ return [...out.values()].map((x) => x.m)
850
+ }
851
+
828
852
  const modelOf = (provider, m) => {
829
853
  const id = String(m.config_name)
830
854
  const was = provider.models?.[id] ?? {}
@@ -889,7 +913,9 @@ export const TraeCNAuthPlugin = async ({ client }) => {
889
913
  }
890
914
  const signIn = a.renewed ? "renewed" : "kept"
891
915
  const who = a.uid || a.name
892
- const fns = fnOf.has(who) ? [fnOf.get(who), ...FUNCTIONS.filter((f) => f !== fnOf.get(who))] : FUNCTIONS
916
+ // the function that lists the model first, then the one that
917
+ // served this account last, then the rest
918
+ const fns = [...new Set([listedBy.get(String(req.model)), fnOf.get(who), ...FUNCTIONS].filter(Boolean))]
893
919
  let last
894
920
  for (const fn of fns) {
895
921
  const res = await fetch(apiOf(a) + "/api/agent/v3/llm_utils_chat", {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@magpie-community/opencode-trae-auth",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "OpenCode provider plugin for Trae CN (trae.cn): your Trae CN account's models, free tier included, with Trae's own browser sign-in",
5
5
  "type": "module",
6
6
  "main": "./index.mjs",