opencode-lobster-auth 0.1.2 → 0.2.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.
package/lib/usage.mjs CHANGED
@@ -1,41 +1,83 @@
1
- // magpie 的 auth.usage 返回形状。数据来自两个端点:
2
- // GET /api/user/quota 免费额度与订阅状态
3
- // GET /api/user/profile-summary 昵称、剩余积分明细
4
-
5
- const round = (n, d = 2) => {
6
- const p = 10 ** d
7
- return Math.round(Number(n) * p) / p
8
- }
9
-
10
- export function usageFrom(quota, profile, signIn) {
11
- const q = quota ?? {}
12
- const p = profile ?? {}
13
- const out = { windows: [] }
14
-
15
- if (q.planName) out.plan = String(q.planName)
16
- if (p.nickname) out.user = String(p.nickname)
17
-
18
- const left = Number(p.totalCreditsRemaining)
19
- out.balance = Number.isFinite(left) && left > 0 ? `${round(left)} 点数` : ""
20
-
21
- const total = Number(q.freeCreditsTotal)
22
- const used = Number(q.freeCreditsUsed)
23
- if (Number.isFinite(total) && total > 0) {
24
- const u = Number.isFinite(used) ? used : 0
25
- out.windows.push({
26
- name: "免费额度",
27
- used: round((u / total) * 100),
28
- display: `${round(u, 1)} / ${round(total, 1)} 免费积分`,
29
- aside: !!q.freeCreditsExpired,
30
- })
31
- }
32
-
33
- const dates = (Array.isArray(p.creditItems) ? p.creditItems : [])
34
- .map((c) => c?.expiresAt)
35
- .filter((d) => typeof d === "string" && d !== "")
36
- .sort()
37
- if (dates.length > 0) out.until = dates[0]
38
-
39
- if (signIn) out.signIn = signIn
40
- return out
41
- }
1
+ // magpie 的 auth.usage 返回形状。数据来自两个端点:
2
+ // GET /api/user/quota 免费额度与订阅状态
3
+ // GET /api/user/profile-summary 昵称、剩余积分明细
4
+
5
+ const round = (n, d = 2) => {
6
+ const p = 10 ** d
7
+ return Math.round(Number(n) * p) / p
8
+ }
9
+
10
+ // 上游的时间不带时区(如 2026-11-11T09:11:24)。magpie 用 new Date(...) 读它,
11
+ // 裸时间会被当成本机本地时间 —— magpie 跑在 UTC 的容器 / NAS 上就差 8 小时。
12
+ // 上游是北京时间(签到 context 的 state.timezone 是 Asia/Shanghai),补上 +08:00。
13
+ //
14
+ // 形态不止一种(带秒/不带秒/带毫秒/空格分隔),漏掉哪一种就等于那个 bug 换了
15
+ // 形状还在。所以:先把空格分隔规整成 T,再判断「有没有已经写明的偏移量」;
16
+ // 只有日期(2026-11-01)保持原样,那是整天语义、没有时刻可言。
17
+ // 认不出的原样透传,绝不编一个时间出来。
18
+ const rfc3339 = (s) => {
19
+ let v = String(s ?? "").trim()
20
+ if (!v) return v
21
+ // 2026-11-11 09:11:24 → 2026-11-11T09:11:24
22
+ if (/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}/.test(v)) v = v.replace(" ", "T")
23
+ // 只有日期:整天语义
24
+ if (/^\d{4}-\d{2}-\d{2}$/.test(v)) return v
25
+ // 有时刻但没写偏移量(Z 或 ±hh:mm 都算写了)
26
+ if (/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}/.test(v) && !/(?:Z|[+-]\d{2}:?\d{2})$/.test(v)) {
27
+ // 补足秒位,magpie 的 Date 解析对 `T09:11` 的支持不统一
28
+ const withSeconds = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}$/.test(v) ? `${v}:00` : v
29
+ return `${withSeconds}+08:00`
30
+ }
31
+ return v
32
+ }
33
+
34
+ export function usageFrom(quota, profile, signIn) {
35
+ const q = quota ?? {}
36
+ const p = profile ?? {}
37
+ const out = { windows: [] }
38
+
39
+ if (q.planName) out.plan = String(q.planName)
40
+ if (p.nickname) out.user = String(p.nickname)
41
+
42
+ // 钱包窗口。积分是一批批的余额,不是「用了几成」的额度:magpie 的匹配规则里
43
+ // 窗口带 balance 才被当钱包(不当 Text/Aside),路由才会按余额排序、先花快
44
+ // 到期的。原来把它塞进顶层 balance 字符串,magpie 只能当文字显示,路由读不到。
45
+ const left = Number(p.totalCreditsRemaining)
46
+ if (Number.isFinite(left)) {
47
+ // 名字只当标签用。magpie 把它渲染成「<窗口名> <余额> <单位> left」,
48
+ // 叫「点数」会读成「点数 2,487.54 点数 left」,所以用「余额」。
49
+ const w = { name: "余额", balance: round(left), unit: "点数" }
50
+ // 每天领的 100 点各是一批、逐日到期,先到期先扣;不报出来就白作废。
51
+ // 只剩 0 的批次不算「将要到期」,否则永远指向一批已经用完的。
52
+ const soonest = (Array.isArray(p.creditItems) ? p.creditItems : [])
53
+ .filter((c) => Number(c?.creditsRemaining) > 0 && typeof c?.expiresAt === "string" && c.expiresAt !== "")
54
+ .sort((a, b) => String(a.expiresAt).localeCompare(String(b.expiresAt)))[0]
55
+ if (soonest) {
56
+ w.runsOutAt = rfc3339(soonest.expiresAt)
57
+ w.runsOut = round(soonest.creditsRemaining)
58
+ }
59
+ out.windows.push(w)
60
+ }
61
+
62
+ // 免费额度只在还没过期时才算一笔有效额度。免费期 2026-08 就结束了,
63
+ // 过了还按「6% used」显示,看起来像还有一笔可用额度。
64
+ const total = Number(q.freeCreditsTotal)
65
+ const used = Number(q.freeCreditsUsed)
66
+ if (Number.isFinite(total) && total > 0 && !q.freeCreditsExpired) {
67
+ const u = Number.isFinite(used) ? used : 0
68
+ out.windows.push({
69
+ name: "免费额度",
70
+ used: round((u / total) * 100),
71
+ display: `${round(u, 1)} / ${round(total, 1)} 免费积分`,
72
+ })
73
+ }
74
+
75
+ const dates = (Array.isArray(p.creditItems) ? p.creditItems : [])
76
+ .map((c) => c?.expiresAt)
77
+ .filter((d) => typeof d === "string" && d !== "")
78
+ .sort()
79
+ if (dates.length > 0) out.until = rfc3339(dates[0])
80
+
81
+ if (signIn) out.signIn = signIn
82
+ return out
83
+ }
package/package.json CHANGED
@@ -1,38 +1,39 @@
1
- {
2
- "name": "opencode-lobster-auth",
3
- "version": "0.1.2",
4
- "description": "OpenCode provider plugin: NetEase Youdao LobsterAI (有道龙虾)",
5
- "type": "module",
6
- "main": "./index.mjs",
7
- "exports": "./index.mjs",
8
- "files": [
9
- "index.mjs",
10
- "lib",
11
- "README.md",
12
- "README.zh-CN.md",
13
- "LICENSE"
14
- ],
15
- "keywords": [
16
- "opencode",
17
- "opencode-plugin",
18
- "magpie",
19
- "lobster",
20
- "lobsterai",
21
- "youdao"
22
- ],
23
- "license": "MIT",
24
- "author": "Jasery <jaserydev@163.com>",
25
- "repository": {
26
- "type": "git",
27
- "url": "git+https://github.com/Jasery/opencode-lobster-auth.git"
28
- },
29
- "homepage": "https://github.com/Jasery/opencode-lobster-auth#readme",
30
- "bugs": "https://github.com/Jasery/opencode-lobster-auth/issues",
31
- "scripts": {
32
- "test": "bun test"
33
- },
34
- "magpie": {
35
- "maxConcurrency": 8,
36
- "icon": "https://lobsterai.youdao.com/portal/lobsterai-logo.png"
37
- }
1
+ {
2
+ "name": "opencode-lobster-auth",
3
+ "version": "0.2.0",
4
+ "description": "OpenCode provider plugin: NetEase Youdao LobsterAI (有道龙虾)",
5
+ "type": "module",
6
+ "main": "./index.mjs",
7
+ "exports": "./index.mjs",
8
+ "files": [
9
+ "index.mjs",
10
+ "lib",
11
+ "README.md",
12
+ "README.zh-CN.md",
13
+ "LICENSE"
14
+ ],
15
+ "keywords": [
16
+ "opencode",
17
+ "opencode-plugin",
18
+ "magpie",
19
+ "lobster",
20
+ "lobsterai",
21
+ "youdao"
22
+ ],
23
+ "license": "MIT",
24
+ "author": "Jasery <jaserydev@163.com>",
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "git+https://github.com/Jasery/opencode-lobster-auth.git"
28
+ },
29
+ "homepage": "https://github.com/Jasery/opencode-lobster-auth#readme",
30
+ "bugs": "https://github.com/Jasery/opencode-lobster-auth/issues",
31
+ "scripts": {
32
+ "test": "bun test"
33
+ },
34
+ "magpie": {
35
+ "maxConcurrency": 8,
36
+ "icon": "https://lobsterai.youdao.com/portal/lobsterai-logo.png"
37
+ }
38
38
  }
39
+