@fish-under-sea/opencode-meoo-auth 1.0.1 → 1.1.0

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 +43 -4
  2. package/index.mjs +134 -32
  3. package/package.json +63 -62
package/README.md CHANGED
@@ -2,16 +2,55 @@
2
2
 
3
3
  OpenCode & Magpie provider plugin for **Meoo 秒悟**(`meoo.com`)。npm 包名 `@fish-under-sea/opencode-meoo-auth`。
4
4
 
5
- 在 Magpie 的插件/供应商列表里,外层显示名是 **Meoo**;点进插件详情,看到的是完整包名 `@fish-under-sea/opencode-meoo-auth`——外层短名由插件的 `provider.name` 给出,完整包名由宿主读到的插件 spec 给出,与官方插件(`@magpie-community/opencode-*-auth`)的呈现方式一致。
5
+ 在 Magpie 的插件界面里,名字是两层:**外层短名 `Meoo`**(「已安装」那一行、插件卡片的标题、供应商卡片),**点进插件详情**看到的是 `npm · @fish-under-sea/opencode-meoo-auth`(npm 发布者 + 完整包名)。这与官方插件(卡片上 `magpie 社区 · @magpie-community/…`)同一套呈现:短名由 `package.json` 的 `magpie.name` 给出(社区列表没收录时生效),详情里的包名由宿主读到的插件 spec 给出。
6
+
7
+ ```json
8
+ "magpie": {
9
+ "name": "Meoo",
10
+ "summary": {
11
+ "zh": "用自己的 Meoo 秒悟账号使用 Meoo 网关上的模型——浏览器 PKCE 授权、复用本机登录态或项目服务 AK,模型目录实时同步。",
12
+ "en": "Meoo 秒悟 (meoo.com) in magpie: sign in with your own Meoo account and its gateway's models show up as one provider, with usage-billed tokens."
13
+ }
14
+ }
15
+ ```
16
+
17
+ `magpie.name` 最多 80 字节、必须单行、不能含控制或双向格式字符,否则整条忽略(回落成包名);`summary` 按语言给一句,最多 300 字节。
6
18
 
7
19
  作者:[@Fish-under-sea](https://github.com/Fish-under-sea)、[Chensy(elysia395)](https://github.com/elysia395)。本包由 [FISH-DOCK-Plugins PR #35](https://github.com/Fish-under-sea/FISH-DOCK-Plugins/pull/35) 的 Magpie 供应商插件落成独立 npm 包;代码源头是 [dsh-meoo-connect](https://github.com/2239058652/dsh-meoo-connect)(DeepSeek Harness 的 dsh 插件):同一套 Meoo 官方「AI 服务」链路(OAuth 登录 → 项目服务 AK → OpenAI 兼容网关),换到 Magpie / OpenCode 的 provider 插件平面上。装好并登录后,Meoo 的模型会出现在 Magpie 的模型选择器里,也作为 OpenCode 的一个 provider。
8
20
 
21
+ ## 模型与上下文
22
+
23
+ 网关 `/models` 只回裸 id,不带上下文与输出上限,所以规格由包里那张表给出(数字取自各家官方文档,2026-11 核对):
24
+
25
+ | 模型 | 传参值 | 上下文 | 最大输出 | 图片 |
26
+ | --- | --- | --- | --- | --- |
27
+ | Qwen3.8-Flash | `qwen3.8-flash` | 1M | 131072 | ✓ |
28
+ | Qwen3.8-Max | `qwen3.8-max` | 1M | 131072 | ✓ |
29
+ | Qwen3.7-Max | `qwen3.7-max` | 1M | 131072 | |
30
+ | Qwen3.7-Plus | `qwen3.7-plus` | 1M | 131072 | ✓ |
31
+ | DeepSeek V4.1 Flash | `deepseek-v4.1-flash-1017` | 1M | 384K | ✓ |
32
+ | DeepSeek V4 Pro | `deepseek-v4-pro-0813` | 1M | 384K | |
33
+ | DeepSeek V4 Flash | `deepseek-v4-flash-0731` | 1M | 384K | |
34
+ | GLM-5.2-Fast | `glm-5.2-fast-preview` | 1M | 128K | |
35
+ | GLM-5.2 | `glm-5.2` | 1M | 128K | |
36
+ | Qwen VL(视觉理解) | `qwen3-vl-plus` | 262144 | 32768 | ✓ |
37
+
38
+ 两点和别家插件不一样,值得知道:
39
+
40
+ - **`qwen3-vl-plus` 不在网关 `/models` 里**,但 Meoo 文档给了、网关也接(实测可调)。插件拉目录时会用一次 1-token 的探针试它,接了就补进目录,否则不提——不写死一个调不通的模型。
41
+ - **目录里出现表外的新模型**按保守值给(200K 上下文 / 64K 输出、纯文本),不会把 1M 随手许出去;要正式支持就把它加进 `MODEL_SPECS`。
42
+
43
+ ## 余额
44
+
45
+ 浏览器授权登录后,供应商卡片会带一张积分卡(控制面 `/open/v1/cli-compat/account/points`):
46
+
9
47
  ```
10
- Qwen3.8-Flash · Qwen3.8-Max · Qwen3.7-Max · Qwen3.7-Plus
11
- DeepSeek V4.1 Flash · DeepSeek V4 Pro · DeepSeek V4 Flash
12
- GLM-5.2 · GLM-5.2-Fast
48
+ Fishundersea · 58,847 积分 · 2026-11-10 到期
49
+ 已用 2,153 积分
13
50
  ```
14
51
 
52
+ 按 magpie 的**预付费钱包**窗口给出:窗口只有 `balance` + `unit`、不写 `used`/`limit`,所以卡片显示数字而不是百分比条;`runsOutAt` 是最近一批还没用完的积分的到期日。手填项目服务 AK 的登录读不到积分账户,卡片会说明要用浏览器授权。
53
+
15
54
  ## 思考强度
16
55
 
17
56
  模型默认带三档思考强度,对应会话 UI 里的 **快速 / 适中 / 极致**(`reasoning_effort: low / medium / high`)。网关实测该参数真实生效(low 档思考 tokens 约为 high 档的 60%~70%,`enable_thinking:false` 可完全关闭,但为避免不可控行为未暴露「关闭」档)。不选档位时走上游默认思考。
package/index.mjs CHANGED
@@ -44,22 +44,47 @@ const EARLY_MS = 60 * 1000
44
44
  const LEAD_MS = 5 * 60 * 1000
45
45
  const KEEP_RENEWED_MS = 60 * 1000
46
46
  const CATALOG_TTL_MS = 10 * 60 * 1000
47
+ // 目录里认不出的新模型先按保守值给,等它也进规格表。
47
48
  const CONTEXT_WINDOW = 200_000
48
49
  const DEFAULT_MAX_TOKENS = 64_000
49
50
 
50
- /** 网关目录拿不到时的兜底清单(id → 展示名,取自 meoo 文档与控制台)。 */
51
- const FALLBACK_MODELS = [
52
- { id: "qwen3.8-flash", name: "Qwen3.8-Flash" },
53
- { id: "qwen3.8-max", name: "Qwen3.8-Max" },
54
- { id: "qwen3.7-max", name: "Qwen3.7-Max" },
55
- { id: "qwen3.7-plus", name: "Qwen3.7-Plus" },
56
- { id: "deepseek-v4.1-flash-1017", name: "DeepSeek V4.1 Flash" },
57
- { id: "deepseek-v4-pro-0813", name: "DeepSeek V4 Pro" },
58
- { id: "deepseek-v4-flash-0731", name: "DeepSeek V4 Flash" },
59
- { id: "glm-5.2-fast-preview", name: "GLM-5.2-Fast" },
60
- { id: "glm-5.2", name: "GLM-5.2" },
51
+ /**
52
+ * 模型规格表。网关 /models 只回裸 id,不带上下文/输出上限,所以数字得自己带。
53
+ * 取值来自各家官方文档(2026-11 核对):
54
+ * Qwen 3.8/3.7 全家 1M 上下文 / 131072 输出;
55
+ * DeepSeek V4 全家 1M / 384K;
56
+ * GLM-5.2 与 GLM-5.2-Fast 1M / 128K;
57
+ * Qwen VL 262144 / 32768。
58
+ * image 只给官方写明原生多模态的那几个,其余按纯文本,免得让 UI 递图片。
59
+ */
60
+ const MODEL_SPECS = [
61
+ { id: "qwen3.8-flash", name: "Qwen3.8-Flash", context: 1_000_000, output: 131_072, image: true },
62
+ { id: "qwen3.8-max", name: "Qwen3.8-Max", context: 1_000_000, output: 131_072, image: true },
63
+ { id: "qwen3.7-max", name: "Qwen3.7-Max", context: 1_000_000, output: 131_072 },
64
+ { id: "qwen3.7-plus", name: "Qwen3.7-Plus", context: 1_000_000, output: 131_072, image: true },
65
+ { id: "deepseek-v4.1-flash-1017", name: "DeepSeek V4.1 Flash", context: 1_000_000, output: 384_000, image: true },
66
+ { id: "deepseek-v4-pro-0813", name: "DeepSeek V4 Pro", context: 1_000_000, output: 384_000 },
67
+ { id: "deepseek-v4-flash-0731", name: "DeepSeek V4 Flash", context: 1_000_000, output: 384_000 },
68
+ { id: "glm-5.2-fast-preview", name: "GLM-5.2-Fast", context: 1_000_000, output: 128_000 },
69
+ { id: "glm-5.2", name: "GLM-5.2", context: 1_000_000, output: 128_000 },
70
+ { id: "qwen3-vl-plus", name: "Qwen VL", context: 262_144, output: 32_768, image: true },
61
71
  ]
62
72
 
73
+ /**
74
+ * 文档里写了、网关 /models 却不一定列出来的模型:拉目录时用一次 1-token 的
75
+ * 请求探一下,网关接了才放进目录。
76
+ * qwen3-vl-plus 就是这样:Meoo 文档「视觉理解」一节里的唯一模型,2026-11 实测
77
+ * 网关可调,但 /models 只回 9 个文本 id,不探就永远看不见。
78
+ */
79
+ const SUPPLEMENT_MODELS = ["qwen3-vl-plus"]
80
+
81
+ const MODEL_BY_ID = new Map(MODEL_SPECS.map((m) => [m.id, m]))
82
+
83
+ /** 目录里出现的未知 id 当纯文本、给保守上限,不把 1M 乱许出去。 */
84
+ function specOf(id) {
85
+ return MODEL_BY_ID.get(id) ?? { id, name: id, context: CONTEXT_WINDOW, output: DEFAULT_MAX_TOKENS }
86
+ }
87
+
63
88
  const mainOrigin = () => String(process.env.MEOO_MAIN_SITE_URL || DEFAULT_API_BASE).replace(/\/+$/, "")
64
89
  const gatewayBase = () => String(process.env.MEOO_GATEWAY_BASE_URL || DEFAULT_GATEWAY).replace(/\/+$/, "")
65
90
  // apiBase 跟着账号记录走(登录用的哪个站点,续期/控制面就打哪个),环境变量只是兜底。
@@ -73,13 +98,27 @@ function clientIdFor(apiBaseUrl) {
73
98
  }
74
99
  }
75
100
 
76
- const labelOf = (id) => FALLBACK_MODELS.find((m) => m.id === id)?.name || id
101
+ const labelOf = (id) => specOf(id).name
77
102
  const int = (n, fallback = 0) => {
78
103
  const v = Math.trunc(Number(n))
79
104
  return Number.isFinite(v) && v >= 0 ? v : fallback
80
105
  }
81
106
  const vendorError = (json, text) => json?.detail || json?.message || String(text ?? "").slice(0, 160)
82
107
 
108
+ /** 最近一批还没用完的积分的到期日(YYYY-MM-DD),给余额卡当提示。 */
109
+ function soonestLapse(grants) {
110
+ let best = ""
111
+ for (const g of Array.isArray(grants) ? grants : []) {
112
+ for (const d of g?.grantDetails || []) {
113
+ if (int(d?.remainingAmount) <= 0) continue
114
+ const day = String(d?.expiresDate || "").slice(0, 10)
115
+ if (!day) continue
116
+ if (!best || day < best) best = day
117
+ }
118
+ }
119
+ return best
120
+ }
121
+
83
122
  // ---- OAuth(Authorization Code + PKCE,public client)----------------------
84
123
 
85
124
  async function tokenRequest(apiBaseUrl, params) {
@@ -342,12 +381,36 @@ function parseGatewayModels(payload) {
342
381
  const id = typeof entry === "string" ? entry.trim() : String(entry?.id ?? "").trim()
343
382
  if (!id || seen.has(id)) continue
344
383
  seen.add(id)
345
- const name = typeof entry === "string" ? labelOf(id) : String(entry?.name || labelOf(id))
346
- out.push({ id, name, context: int(entry?.context) || CONTEXT_WINDOW, output: int(entry?.max_output || entry?.max_output_tokens || entry?.max_tokens) || DEFAULT_MAX_TOKENS })
384
+ const spec = specOf(id)
385
+ out.push({
386
+ id,
387
+ name: (typeof entry === "object" && entry?.name) || spec.name,
388
+ context: int(entry?.context) || spec.context,
389
+ output: int(entry?.max_output || entry?.max_output_tokens || entry?.max_tokens) || spec.output,
390
+ image: !!spec.image,
391
+ })
347
392
  }
348
393
  return out
349
394
  }
350
395
 
396
+ /**
397
+ * 探一个目录外的模型:1 token 的对话请求,网关接了才算可用。
398
+ * 只用来补 SUPPLEMENT_MODELS,结果随目录一起缓存,10 分钟最多探一次。
399
+ */
400
+ async function acceptsModel(ak, id) {
401
+ try {
402
+ const res = await fetch(`${gatewayBase()}/chat/completions`, {
403
+ method: "POST",
404
+ headers: { authorization: `Bearer ${ak}`, "content-type": "application/json" },
405
+ body: JSON.stringify({ model: id, messages: [{ role: "user", content: "hi" }], max_tokens: 1, stream: false }),
406
+ signal: AbortSignal.timeout(20_000),
407
+ })
408
+ return res.ok
409
+ } catch {
410
+ return false
411
+ }
412
+ }
413
+
351
414
  async function fetchGatewayModels(ak) {
352
415
  const base = gatewayBase()
353
416
  if (catalogCache.models && catalogCache.origin === base && Date.now() - catalogCache.at < CATALOG_TTL_MS) {
@@ -360,6 +423,13 @@ async function fetchGatewayModels(ak) {
360
423
  if (!res.ok) throw new Error(`模型目录 HTTP ${res.status}`)
361
424
  const models = parseGatewayModels(await res.json())
362
425
  if (!models.length) throw new Error("empty catalog")
426
+ const seen = new Set(models.map((m) => m.id))
427
+ for (const id of SUPPLEMENT_MODELS) {
428
+ if (seen.has(id)) continue
429
+ if (!(await acceptsModel(ak, id))) continue
430
+ const spec = specOf(id)
431
+ models.push({ id, name: spec.name, context: spec.context, output: spec.output, image: !!spec.image })
432
+ }
363
433
  catalogCache = { origin: base, models, at: Date.now() }
364
434
  return models
365
435
  }
@@ -374,40 +444,47 @@ const REASONING_VARIANTS = {
374
444
  high: { reasoningEffort: "high" },
375
445
  }
376
446
 
447
+ function configModel(m) {
448
+ const spec = specOf(m.id)
449
+ const context = m.context ?? spec.context
450
+ const output = m.output ?? spec.output
451
+ const image = m.image ?? spec.image ?? false
452
+ return {
453
+ name: m.name ?? spec.name,
454
+ limit: { context, output },
455
+ tool_call: true,
456
+ reasoning: true,
457
+ attachment: image,
458
+ modalities: { input: image ? ["text", "image"] : ["text"], output: ["text"] },
459
+ variants: REASONING_VARIANTS,
460
+ }
461
+ }
462
+
377
463
  function configModels() {
378
- return Object.fromEntries(
379
- FALLBACK_MODELS.map((m) => [
380
- m.id,
381
- {
382
- name: m.name,
383
- limit: { context: CONTEXT_WINDOW, output: DEFAULT_MAX_TOKENS },
384
- tool_call: true,
385
- reasoning: true,
386
- attachment: false,
387
- modalities: { input: ["text"], output: ["text"] },
388
- variants: REASONING_VARIANTS,
389
- },
390
- ]),
391
- )
464
+ return Object.fromEntries(MODEL_SPECS.map((m) => [m.id, configModel(m)]))
392
465
  }
393
466
 
394
467
  function runtimeModel(provider, m) {
468
+ const spec = specOf(m.id)
469
+ const context = m.context ?? spec.context
470
+ const output = m.output ?? spec.output
471
+ const image = m.image ?? spec.image ?? false
395
472
  return {
396
473
  id: m.id,
397
474
  providerID: provider.id,
398
- name: m.name,
475
+ name: m.name ?? spec.name,
399
476
  api: { id: m.id, url: gatewayBase(), npm: NPM },
400
477
  status: "active",
401
478
  headers: {},
402
479
  options: {},
403
480
  cost: { input: 0, output: 0, cache: { read: 0, write: 0 } },
404
- limit: { context: m.context ?? CONTEXT_WINDOW, output: m.output ?? DEFAULT_MAX_TOKENS },
481
+ limit: { context, output },
405
482
  capabilities: {
406
483
  temperature: true,
407
484
  reasoning: true,
408
- attachment: false,
485
+ attachment: image,
409
486
  toolcall: true,
410
- input: { text: true, image: false, audio: false, video: false, pdf: false },
487
+ input: { text: true, image, audio: false, video: false, pdf: false },
411
488
  output: { text: true, image: false, audio: false, video: false, pdf: false },
412
489
  interleaved: false,
413
490
  },
@@ -740,6 +817,31 @@ export const MeooAuthPlugin = async ({ client }) => {
740
817
  ...(a.serviceAk ? { serviceAk: a.serviceAk, serviceAkProjectId: a.serviceAkProjectId, projectUrlId: a.projectUrlId, apiBase: a.apiBase } : {}),
741
818
  }
742
819
  },
820
+ // 余额:Meoo 的积分账户(控制面 /account/points)。预付费钱包按 magpie 的
821
+ // balance 窗口显示——这种窗口不写 used/limit,卡片显示数字而不是百分比条;
822
+ // 再补一条「已用」和最近一批到期日,免得只看得到余额看不到花在哪。
823
+ async usage(getAuth) {
824
+ const auth = await getAuth()
825
+ if (!auth) throw new Error("还没有连接 Meoo")
826
+ if (auth.type === "api") {
827
+ throw new Error("手填的项目服务 AK 读不到积分账户;要用余额卡,请用浏览器授权登录一次")
828
+ }
829
+ if (auth.type !== "oauth") throw new Error("登录态类型未知,无法读取积分")
830
+ const { a } = await currentAuth(ctx, auth)
831
+ const data = await controlRequest(ctx, a, "GET", "/open/v1/cli-compat/account/points")
832
+ const acc = data?.account || {}
833
+ const left = int(acc.availableBalance)
834
+ const used = int(acc.totalConsumed)
835
+ const frozen = int(acc.frozenBalance)
836
+ const fmt = (n) => new Intl.NumberFormat("en-US").format(n)
837
+ const wallet = { name: "积分", balance: left, unit: "积分" }
838
+ const lapse = soonestLapse(data?.activeGrants)
839
+ if (lapse) wallet.runsOutAt = lapse
840
+ const windows = [wallet]
841
+ if (used > 0) windows.push({ name: "已用", display: `${fmt(used)} 积分`, aside: true })
842
+ if (frozen > 0) windows.push({ name: "冻结", display: `${fmt(frozen)} 积分`, aside: true })
843
+ return { user: a.username || "", balance: `${fmt(left)} 积分`, windows }
844
+ },
743
845
  async loader(getAuth) {
744
846
  const auth = await getAuth()
745
847
  if (auth?.type === "api") return auth.key ? { baseURL: gatewayBase(), apiKey: auth.key } : {}
package/package.json CHANGED
@@ -1,63 +1,64 @@
1
- {
2
- "name": "@fish-under-sea/opencode-meoo-auth",
3
- "version": "1.0.1",
4
- "description": "Meoo 秒悟 (meoo.com) in OpenCode and Magpie: browser PKCE sign-in, reuse of a local dsh-meoo-connect / meoo-proxy sign-in, or a project service AK, with a live model catalog",
5
- "type": "module",
6
- "main": "./opencode.mjs",
7
- "exports": {
8
- ".": "./opencode2.mjs"
9
- },
10
- "files": [
11
- "index.mjs",
12
- "opencode.mjs",
13
- "opencode2.mjs",
14
- "README.md",
15
- "LICENSE",
16
- "THIRD_PARTY_NOTICES.md"
17
- ],
18
- "scripts": {
19
- "test": "node --test test/offline.test.mjs"
20
- },
21
- "engines": {
22
- "node": ">=20"
23
- },
24
- "keywords": [
25
- "opencode",
26
- "opencode-plugin",
27
- "magpie",
28
- "magpie-provider",
29
- "meoo",
30
- "秒悟",
31
- "openai-compatible"
32
- ],
33
- "license": "MIT",
34
- "author": {
35
- "name": "Fish-under-sea",
36
- "url": "https://github.com/Fish-under-sea"
37
- },
38
- "contributors": [
39
- {
40
- "name": "Chensy (elysia395)",
41
- "url": "https://github.com/elysia395"
42
- }
43
- ],
44
- "repository": {
45
- "type": "git",
46
- "url": "git+https://github.com/Fish-under-sea/opencode-meoo-auth.git"
47
- },
48
- "homepage": "https://github.com/Fish-under-sea/opencode-meoo-auth#readme",
49
- "bugs": {
50
- "url": "https://github.com/Fish-under-sea/opencode-meoo-auth/issues"
51
- },
52
- "publishConfig": {
53
- "access": "public"
54
- },
55
- "magpie": {
56
- "name": "Meoo",
57
- "summary": {
58
- "en": "Meoo 秒悟 (meoo.com) in magpie: sign in with your own Meoo account and its gateway's models show up as one provider, with usage-billed tokens.",
59
- "zh": "用自己的 Meoo 秒悟账号使用 Meoo 网关上的模型——浏览器 PKCE 授权、复用本机登录态或项目服务 AK,模型目录实时同步。"
60
- },
61
- "icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAADbElEQVR4nOWZ51IVQRCF52nIlxwlq6CEhxKzYkQQxQBmxYSoiOFdFEQQlYyCCNXW7N4tL1VwxgP3zsLOqepf++v7pqe7plYpMi2HV6X5yB9pPupX0zFdK9J0fEUO6jqh67ccOBmvU8vSqOv0sjS2L0tD+5I0nFmS/brO6vol+87F6/xP2avrgl/1FxelvsOvuku6FqSuc0FqdXXNS42uy35Vd895xfIY09q2Ji1tq6LBdzp89ZU5qbqqa1aqemalsmd260JaD63JboevvDbj1Z7rM5yIqMF7dWP6/yREFb5C102DhKjDV/ROS3nv1MYSXIEv75uSsr4NJLgEX3brhzgNr6v0doIEF+HXC3AQvvTO9/UCXIMvCQS4Cl9yV9c3US7DF9/TAkh4FBvwKCx88f24AObkjQJSfPJQAAnvCWDbHgqw0PYoLHzRg0ktgLvzKDbuPBRAwvsCyIEHBVgYeCYBDHzRw0lR7LQ3CUj1tEdh4Qs9AeSqQ7Gx6owCCPjCR1+1gGjveQRfoAWw8LADOhbh92TseRQWvqA/EECcPIo+eZRk7HkogIQv6J8QxbY9FrBgFrDNPY8FcPD5jydEsXceCug0CEjCnkdh4X0B5MBDqTUISMaehwJI+PwnWgA57aGArnmDgO3veZMABj7v6bgodtWh1JgEJGHPo7DwvoCI73kEn/dsXBQLDzvAwnsedgAJn+sJIE8excZ7HoWFz33+RQvg2t4oIMXveSiAhPcEsHceCrDwnkdh4WMDgQBi4KHYeM9DASR8bGBMFDvtsYDUv+exAA4+9mJMFLvqoAAL73kUFj7HExDxPY/gcwbjAhh4FBvwsANI+OzBz6LYkzcJSPXJo7Dw2S+1ALLtUWy0vVEAAZ/9Ki6AufNGASm+81AACZ+lBbADDwqwMPBQWPis16NaADftUWxMeyiAhPcFkKsOCrCw6kwCGPjMoVFRUd/zCD5zaERU2P/nWXgUFj7zzYiosP/PsycPBZDwGZ6AkP/Ps22PwsJnDMcFhPl/nr3zUAAJnzH8SVTY/+fZgYfCwqe/DQSE+H+enfZQAAnvCdAJ8/88u+qggK3A+wKiu+c3g09/lyjAQfi09x//CXARfp0AT4LL8Douwad92ECAJ8Fl+CBOwwdxGj6I0/CJ2e3wWwbfLDsdnuX5C8g/SO/MmyfJAAAAAElFTkSuQmCC"
62
- }
1
+ {
2
+ "name": "@fish-under-sea/opencode-meoo-auth",
3
+ "version": "1.1.0",
4
+ "description": "Meoo 秒悟 (meoo.com) in OpenCode and Magpie: PKCE sign-in, reuse of a local dsh-meoo-connect state or a project service AK, a live catalog with each model's real context window, and the account's points balance",
5
+ "type": "module",
6
+ "main": "./opencode.mjs",
7
+ "exports": {
8
+ ".": "./opencode2.mjs"
9
+ },
10
+ "files": [
11
+ "index.mjs",
12
+ "opencode.mjs",
13
+ "opencode2.mjs",
14
+ "README.md",
15
+ "LICENSE",
16
+ "THIRD_PARTY_NOTICES.md"
17
+ ],
18
+ "scripts": {
19
+ "test": "node --test test/offline.test.mjs"
20
+ },
21
+ "engines": {
22
+ "node": ">=20"
23
+ },
24
+ "keywords": [
25
+ "opencode",
26
+ "opencode-plugin",
27
+ "magpie",
28
+ "magpie-provider",
29
+ "meoo",
30
+ "秒悟",
31
+ "openai-compatible"
32
+ ],
33
+ "license": "MIT",
34
+ "author": {
35
+ "name": "Fish-under-sea",
36
+ "url": "https://github.com/Fish-under-sea"
37
+ },
38
+ "contributors": [
39
+ {
40
+ "name": "Chensy (elysia395)",
41
+ "url": "https://github.com/elysia395"
42
+ }
43
+ ],
44
+ "repository": {
45
+ "type": "git",
46
+ "url": "git+https://github.com/Fish-under-sea/opencode-meoo-auth.git"
47
+ },
48
+ "homepage": "https://github.com/Fish-under-sea/opencode-meoo-auth#readme",
49
+ "bugs": {
50
+ "url": "https://github.com/Fish-under-sea/opencode-meoo-auth/issues"
51
+ },
52
+ "publishConfig": {
53
+ "access": "public"
54
+ },
55
+ "magpie": {
56
+ "name": "Meoo",
57
+ "summary": {
58
+ "en": "Meoo 秒悟 (meoo.com) in magpie: sign in with your own Meoo account and its gateway's models show up as one provider, with usage-billed tokens.",
59
+ "zh": "用自己的 Meoo 秒悟账号使用 Meoo 网关上的模型——浏览器 PKCE 授权、复用本机登录态或项目服务 AK,模型目录实时同步。"
60
+ },
61
+ "icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAADbElEQVR4nOWZ51IVQRCF52nIlxwlq6CEhxKzYkQQxQBmxYSoiOFdFEQQlYyCCNXW7N4tL1VwxgP3zsLOqepf++v7pqe7plYpMi2HV6X5yB9pPupX0zFdK9J0fEUO6jqh67ccOBmvU8vSqOv0sjS2L0tD+5I0nFmS/brO6vol+87F6/xP2avrgl/1FxelvsOvuku6FqSuc0FqdXXNS42uy35Vd895xfIY09q2Ji1tq6LBdzp89ZU5qbqqa1aqemalsmd260JaD63JboevvDbj1Z7rM5yIqMF7dWP6/yREFb5C102DhKjDV/ROS3nv1MYSXIEv75uSsr4NJLgEX3brhzgNr6v0doIEF+HXC3AQvvTO9/UCXIMvCQS4Cl9yV9c3US7DF9/TAkh4FBvwKCx88f24AObkjQJSfPJQAAnvCWDbHgqw0PYoLHzRg0ktgLvzKDbuPBRAwvsCyIEHBVgYeCYBDHzRw0lR7LQ3CUj1tEdh4Qs9AeSqQ7Gx6owCCPjCR1+1gGjveQRfoAWw8LADOhbh92TseRQWvqA/EECcPIo+eZRk7HkogIQv6J8QxbY9FrBgFrDNPY8FcPD5jydEsXceCug0CEjCnkdh4X0B5MBDqTUISMaehwJI+PwnWgA57aGArnmDgO3veZMABj7v6bgodtWh1JgEJGHPo7DwvoCI73kEn/dsXBQLDzvAwnsedgAJn+sJIE8excZ7HoWFz33+RQvg2t4oIMXveSiAhPcEsHceCrDwnkdh4WMDgQBi4KHYeM9DASR8bGBMFDvtsYDUv+exAA4+9mJMFLvqoAAL73kUFj7HExDxPY/gcwbjAhh4FBvwsANI+OzBz6LYkzcJSPXJo7Dw2S+1ALLtUWy0vVEAAZ/9Ki6AufNGASm+81AACZ+lBbADDwqwMPBQWPis16NaADftUWxMeyiAhPcFkKsOCrCw6kwCGPjMoVFRUd/zCD5zaERU2P/nWXgUFj7zzYiosP/PsycPBZDwGZ6AkP/Ps22PwsJnDMcFhPl/nr3zUAAJnzH8SVTY/+fZgYfCwqe/DQSE+H+enfZQAAnvCdAJ8/88u+qggK3A+wKiu+c3g09/lyjAQfi09x//CXARfp0AT4LL8Douwad92ECAJ8Fl+CBOwwdxGj6I0/CJ2e3wWwbfLDsdnuX5C8g/SO/MmyfJAAAAAElFTkSuQmCC"
62
+ }
63
63
  }
64
+