magpie-plugin-loomy-auth 0.0.0-stage → 0.1.6

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 MYCF711
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/NOTICE.md ADDED
@@ -0,0 +1,35 @@
1
+ # NOTICE
2
+
3
+ 本插件的实现参考了以下来源。按各自的许可要求在此声明。
4
+
5
+ ## magpie 插件契约
6
+
7
+ - **yetone/magpie** — Copyright (c) 2026 yetone, MIT License
8
+ - `src/pure.mjs` 里 `auth.usage` 的 windows 字段形状、`used` 的归一化行为、
9
+ `aside` 的语义、签到 `outcome` 的合法值清单、`client.auth.set` 的整体替换
10
+ (而非合并)语义,均取自 magpie 二进制内嵌的插件契约源码。
11
+ - `free` 字段的判据取自其路由模式说明("Free first"):模型供应商是否
12
+ **不消耗本订阅的额度或积分**。
13
+
14
+ ## Loomy(讯飞)协议实现
15
+
16
+ - **sucooer / anyaer 的 `magpie-plugin-loomy`**(`github.com/sucooer/magpie-plugins`, MIT)
17
+ - `src/crypto.mjs` + `src/pure.mjs` 的 `signedHeaders`:账号接口的 HMAC-SHA1
18
+ 待签串构造(9 段 `\n` 连接)、路径分段转义规则。
19
+ - `src/desktop.mjs`:Loomy 桌面端登录态的 leveldb 读取方式(键名
20
+ `loomy-auth-session`、追加写所以从后往前找)。
21
+
22
+ - **agent2api**(`loomy/sign.rs`, `loomy/images.rs`)
23
+ - deepseek 系模型只认 `<image_base64>` 标记、不认 `image_url` data URI 的结论,
24
+ 以及把标记并入相邻 text 块的做法。
25
+
26
+ ## 与上述实现的差异
27
+
28
+ 本插件的额度上报口径与它们**不同**:市场现有实现不上报 `used`(或在拿不到上限时
29
+ 上报 0),导致 magpie 把被蹬空的账号排在路由队首。本插件上报真实占比、把永久池
30
+ 标为 `aside`、并在两池皆空时合成一条 `used: 100` 的参与路由窗口。
31
+ 详见 README 的「这个插件修的是什么」。
32
+
33
+ ## 本项目自身
34
+
35
+ Copyright (c) 2026 MYCF711, MIT License(见 `LICENSE`)。
package/README.md CHANGED
@@ -1,3 +1,171 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
1
+ # Loomy for magpie
2
+
3
+ > 讯飞 Loomy 的编程订阅接进 magpie。**10 个模型、三种登录、积分按 magpie 的路由语义如实上报。**
4
+ >
5
+ > npm 包名 `magpie-plugin-loomy-auth` · 仓库 `MYCF711/magpie-loomy-auth`
6
+
7
+ ---
8
+
9
+ ## 装它有什么好处
10
+
11
+ **1. 积分算得对。** 别人做的 Loomy 插件不报「已用百分比」,于是 magpie 一律当成 0% ——
12
+ 一个已经用光的号会显示「剩余 100%」,而且被排到路由队首。本机三天日志里,
13
+ 一个余额 0 的号被选中 256 次里占了 255 次,11 次请求被上游拒掉。
14
+ 这个插件报真实数字:**空号会沉底,余额 0 的就是 0**。
15
+
16
+ **2. 多领两笔钱。**
17
+ - **新手任务 10,000 分**:卡片上显示「可领 9500 积分(7 项待完成)」,签到后自动领。
18
+ 别人做的插件没接这个,这笔钱就躺在那里。
19
+ - **邀请码 5,000 分**:新添加账号时,自动用本机老账号的邀请码 —— **双方各得 5000**。
20
+
21
+ **3. 登录态直接复用。** 如果你现在装着别的 Loomy 插件,装这个**不用重新登录**。
22
+
23
+ ---
24
+
25
+ ## 你需要什么
26
+
27
+ - magpie([usemagpie.ai](https://usemagpie.ai))
28
+ - 一个 Loomy 账号(讯飞,[loomy.xunfei.cn](https://loomy.xunfei.cn))
29
+ - 本机装了 Loomy 客户端的话,可以一键导入登录态,不用收短信
30
+
31
+ ---
32
+
33
+ ## 安装
34
+
35
+ ⚠ 先卸掉别的 Loomy 插件。两个插件抢同一个 `loomy` 供应商,会互相打架:
36
+
37
+ ```bash
38
+ magpie plugin rm magpie-plugin-loomy # 或你装的那个
39
+ magpie plugin add magpie-plugin-loomy-auth
40
+ ```
41
+
42
+ 也可以从 GitHub 源码装(拿仓库当前代码,不走 npm):
43
+
44
+ ```bash
45
+ magpie plugin add github:MYCF711/magpie-loomy-auth
46
+ ```
47
+
48
+ 装完 `magpie plugin list` 应该看到:
49
+
50
+ ```
51
+ magpie-plugin-loomy-auth on
52
+ loomy (Loomy, 10 models) signed in as 189****8051
53
+ ```
54
+
55
+ ---
56
+
57
+ ## 登录
58
+
59
+ 三种方式,挑一个:
60
+
61
+ | | 适用 | 要做什么 |
62
+ |---|---|---|
63
+ | **桌面端导入**(推荐) | 本机装了 Loomy 客户端并且登录着 | 点一下就好,不收短信 |
64
+ | **手机号 + 短信** | 没装客户端 | 输 11 位手机号 → 收 6 位验证码 |
65
+ | **粘贴 session** | 想手动导 | 从客户端登录态复制 session 串 |
66
+
67
+ **会话固定 14 天,Loomy 没有续期接口。** 所以到期后必须重新登录一次 ——
68
+ 这个插件不会假装能自动续(那样 magpie 会以为一直可用,你反而收不到「请重新登录」的提示)。
69
+
70
+ ### 加第二个账号
71
+
72
+ Loomy 的邀请机制:**邀请好友双方各得 5000 积分**。
73
+
74
+ 本插件在你添加新账号时,会**自动从本机已有账号里挑一个邀请码**带上去,
75
+ 不用你手动填。挑码规则很简单:用自己没用过的、还有余量的、用得最少的那个;
76
+ 新账号如果已经用过别人的码就跳过(每个号只能兑换一次)。
77
+
78
+ 所以你只要正常「添加账号」,那 5000 分自己就到手了。
79
+
80
+ ---
81
+
82
+ ## 卡片刻度:两个池 + 一笔待领
83
+
84
+ Loomy 的积分分几处,卡片按它们真实的作用分开显示:
85
+
86
+ ```
87
+ 今日积分 ████████░░ 4014 / 5000 积分 ← 有周期、有上限,决定现在能不能用这个号
88
+ 永久积分 5500 积分 (附加) ← 不会过期,不参与路由
89
+ 新手任务 可领 9500 积分(7 项待完成)(附加) ← 一次性,领完就没了
90
+ ```
91
+
92
+ 看懂了就一句话:**只有「今日积分」会决定 magpie 把请求派给谁**,
93
+ 另外两笔只是告诉你「还有多少家底」。
94
+
95
+ 为什么这么分:今日池每天重置,用光了今天就是没了;永久积分不会过期,
96
+ 所以不该因为它多就优先烧它;新手任务是领一次就结束的,更不能拿它当常规额度。
97
+
98
+ ### 签到
99
+
100
+ magpie 按北京时间每天调一次签到,签到同时会:
101
+ - 刷新当天额度(`今日积分` 回到满格)
102
+ - **自动领取新手任务里已经完成的那几项**
103
+
104
+ 签到结果会显示「今日额度已刷新(3479/5000 积分)」这种具体数字,不是含糊的失败/成功。
105
+
106
+ ---
107
+
108
+ ## 模型
109
+
110
+ 10 个对话模型,都是实测的数字(不是抄文档):
111
+
112
+ | 模型 | 上下文 | 最大输出 | 看图 | 倍率 |
113
+ |---|---|---|---|---|
114
+ | `DeepSeek-V4.1-Flash` | 1M | 384K | ✓ | x2.0 |
115
+ | `MiniMax-M3` | 1M | 512K | ✓ | x4.0 |
116
+ | `GLM-5.3-Flash` | 1M | 128K | ✓ | x0.8 |
117
+ | `qwen3.8-flash` | 1M | 128K | ✓ | x0.8 |
118
+ | `mimo-v2.5` | 1M | 128K | ✓ | x3.3 |
119
+ | `qwen-3.8-max` | 1M | 64K | ✗ | x12.0 |
120
+ | `Kimi-k2.6` | 256K | 64K | ✓ | x6.5 |
121
+ | `spark-x2.6` | 1M | 128K | ✗ | **免费** |
122
+ | `spark-x` | 1M | 64K | ✗ | **免费** |
123
+ | `auto` | — | — | ✗ | 自动选 |
124
+
125
+ **两个 `spark` 是限时免费的**(0 倍率,不扣积分)。如果你的路由组用「免费优先」,
126
+ 它们会被排在前面 —— 这个插件把「免费」这个标记也如实报给 magpie 了,
127
+ 别人做的插件漏了这一点,导致免费模型拿不到优先权。
128
+
129
+ **思考档位**:`none / low / medium / high / xhigh`,默认 `low`,在 magpie 里直接选。
130
+
131
+ **图片**:支持视觉的模型可以直接发图。deepseek 系 Loomy 要求特殊格式,
132
+ 插件已自动转换(发标准格式会被上游当成乱码文本读)。
133
+
134
+ ---
135
+
136
+ ## 常见问题
137
+
138
+ **Q:装完没反应 / 还显示旧插件?**
139
+ 两个插件可能同时在。`magpie plugin list` 确认只有一个 `loomy`。
140
+ 改完配置重启一次 magpie 最稳(登录态不会丢)。
141
+
142
+ **Q:显示「登录已失效」?**
143
+ Loomy 会话 14 天到期,没有自动续期。重新登录一次即可。
144
+
145
+ **Q:积分显示 0,但官方 App 里还有?**
146
+ 分两种情况:① 今日额度用光了,等北京时间 0 点后重置;② 那笔是**新手任务**,
147
+ 卡片上单独一行「可领 XXXX 积分」,签到后自动到账。
148
+
149
+ **Q:这个插件会花我的积分吗?**
150
+ 不会。它只读余额、签到、领任务奖励。真正消耗积分的是你通过 magpie 发的对话请求。
151
+
152
+ **Q:它能看到我的什么?**
153
+ 你的 Loomy 登录态(存在 magpie 自己的 `plugin-auth.json` 里),以及积分/模型/任务读数。
154
+ 插件直连 `loomyad.xunfei.cn`(业务)与 `account.xfinfr.com`(登录),不经过任何第三方中转。
155
+ 邀请码功能会读同文件里**其它 Loomy 账号**的邀请码 —— 只读、不发到别处。
156
+
157
+ ---
158
+
159
+ ## 卸载
160
+
161
+ ```bash
162
+ magpie plugin rm magpie-plugin-loomy-auth
163
+ ```
164
+
165
+ 登录态留在 magpie 的凭据里,重装即恢复,不用重新登录。
166
+
167
+ ---
168
+
169
+ ## 许可
170
+
171
+ MIT。协议细节、实现判据、测试与取舍见 [`docs/internals.md`](docs/internals.md)。
@@ -0,0 +1,276 @@
1
+ # 实现细节(给要改这份代码的人)
2
+
3
+ > 这是插件 README 的技术附录。**装机用户看 [README](../README.md) 就够了。**
4
+ >
5
+ > 这里放的是:协议事实、为什么这么上报、怎么验证、哪些地方故意不做。
6
+ > 每条都尽量带「实测判据」—— 不是推测。
7
+
8
+ Loomy(讯飞)做成 magpie 供应商插件:**桌面端登录态导入 / 短信 / 粘贴 session**
9
+ 三种登录、实时模型目录与思考档位、工具调用与图片对话、每日额度刷新,
10
+ 以及**按 magpie 的真实路由语义分池上报的积分**。
11
+
12
+ ```
13
+ magpie-plugin-loomy-auth on
14
+ loomy (Loomy, 10 models) signed in as 189****8051
15
+ ```
16
+
17
+ ---
18
+
19
+ ## 这个插件修的是什么
20
+
21
+ 市场现有的 Loomy 插件把积分卡片报错了。**这不是外观问题** ——
22
+ magpie 按每个非 `aside` 窗口的 `used` 给账号排序:
23
+
24
+ ```js
25
+ // magpie 二进制里的原文
26
+ const group = (w) => w.used >= 98 ? "spent" : w.used >= 90 ? "low" : "fine"
27
+ // spent 的账号 "answers only when nothing else can"(排到最后)
28
+ // usage 归一化时 used: Math.max(0, num(w?.used)) —— 插件不给就是 0
29
+ ```
30
+
31
+ 而现有插件根本不上报 `used`,于是 `used` 全被当成 0,**被蹬空的号以「满额」
32
+ 的姿态排在队首**。实测三天本机路由日志:
33
+
34
+ | 事实 | 数字 |
35
+ |---|---|
36
+ | 所在组被实际选中 | 256 / 2592 = **9.9%** |
37
+ | 其中命中余额为 0 的那个号 | **255 次** |
38
+ | 带失败迹象 | 11 次,含 `Loomy: 积分余额不足,请获取积分后再试` |
39
+
40
+ 本插件的上报口径:
41
+
42
+ | | 上报方式 | 理由 |
43
+ |---|---|---|
44
+ | **今日池** | 参与路由:`used` / `amount` / `limit` / `resetsAt` 齐全 | 它有周期(北京日)、有上限,是唯一该决定「现在能不能用这个号」的窗口 |
45
+ | **永久池** | `aside: true`,只给 `display` | 它无周期、无上限。伪造 `total = 剩余` 就是把占比说谎 |
46
+ | **两池皆空** | 合成一条 `used: 100` 的**参与路由**窗口 | 让这个号沉底。不画窗口 = 它继续以 0% 排在最前面 |
47
+ | **上限未知** | `aside` + `used: 0`,显示「N 积分剩余(今日上限未知)」 | 宁可降级,也不谎报一个占比 |
48
+
49
+ 顺带修掉同源的第二个缺陷:签到返回的 `outcome` 必须是契约六个合法值之一
50
+ (`claimed` / `done` / `ineligible` / `inactive` / `captcha` / `failed`)。
51
+ 现有插件返回 `"success"` —— 不在表里,magpie 一律归 `failed` 却**保留它的
52
+ message**,于是界面出现「签到失败 · 每日赠送积分已刷新」这种自相矛盾的行。
53
+
54
+ ---
55
+
56
+ ## 登录方式
57
+
58
+ | 方式 | 说明 |
59
+ |---|---|
60
+ | **桌面端登录态导入** | 自动读本机 Loomy 客户端的 Local Storage(leveldb 明文,键 `loomy-auth-session`),无需短信 |
61
+ | **手机号 + 短信验证码** | 中国大陆 11 位手机号 → 6 位验证码 |
62
+ | **粘贴 session** | 手动粘贴客户端登录态,可带备注名 |
63
+
64
+ Loomy **没有续期接口**(会话固定 14 天),所以本插件**不伪造 `refresh_token`** ——
65
+ `auth.refresh` 恒返回 `undefined`。伪造的后果比过期更糟:magpie 会以为能自动续,
66
+ 把账号标记成「可恢复」,用户永远等不到「请重新登录」。
67
+
68
+ ---
69
+
70
+ ## 模型
71
+
72
+ 10 个 chat 模型(上游还下发 3 条 `type:"image"`,**按类型过滤掉** —— 它们不是
73
+ 对话模型,列出来就是让用户选中一个必然失败的东西)。
74
+
75
+ | id | context | output | 视觉 | 倍率 |
76
+ |---|---|---|---|---|
77
+ | `DeepSeek-V4.1-Flash` | 1,048,576 | 384,000 | ✓ | x2.0 |
78
+ | `spark-x2.6` | 1,048,576 | 131,072 | ✗ | x0.0 |
79
+ | `spark-x` | 1,048,576 | 65,536 | ✗ | x0.0 |
80
+ | `MiniMax-M3` | 1,048,576 | 512,000 | ✓ | x4.0 |
81
+ | `Kimi-k2.6` | 262,144 | 65,536 | ✓ | x6.5 |
82
+ | `qwen-3.8-max` | 1,000,000 | 65,536 | ✗ | x12.0 |
83
+ | `GLM-5.3-Flash` | 1,048,576 | 131,072 | ✓ | x0.8 |
84
+ | `qwen3.8-flash` | 1,000,000 | 131,072 | ✓ | x0.8 |
85
+ | `mimo-v2.5` | 1,048,576 | 131,072 | ✓ | x3.3 |
86
+ | `auto` | — | — | ✗ | — |
87
+
88
+ 以上全部取自一次实测(`GET /api/v1/models`),**不是文档抄的**。
89
+ `context` 原样上报:magpie 把它转给 agent 决定何时压缩对话,而**路由组按
90
+ 组内最大值算窗口** —— 一个填小的成员会把整组拉低。
91
+
92
+ 思考档位来自上游 `reasoning_efforts`:`none|low|medium|high|xhigh`,默认 `low`。
93
+ `auto` 上游没有 thinking_config,因此不声明 reasoning。
94
+
95
+ ---
96
+
97
+ ## 协议要点(本插件依赖的实测事实)
98
+
99
+ | 事实 | 影响 |
100
+ |---|---|
101
+ | `dailyQuota` / `dailyConsumed` / `dailyCycleDate` **只在** `POST /points/first-login`(写端点,幂等) | 上限只能签到/登录时拿到并记进凭据;**不许硬编码 5000**(活动会变) |
102
+ | `/api/v1/points/balance` 只回 3 个数字(实测 61~233ms) | 热路径用它,是三家现有插件都没用的最小端点 |
103
+ | `/api/v1/points/records` 每条 debit 带 `consumeSource` + `dailyCycleDate` | 上限的**降级推导**:`quota ≈ dailyBalance + Σ(本业务日 daily 扣分)`。两号实测吻合:0/0 → used 100%;有余额 → 3.96% |
104
+ | 业务日按东八区,重置在次日 00:05 | `resetsAt` 用它;跨日旧上限**作废** |
105
+ | 部分错误是 **HTTP 200 + 信封 `{code:"100002"}`** | 「状态码 ok」不等于成功,一律判业务码;失效时打 `X-Magpie-Sign-In: expired` |
106
+ | deepseek 系模型只认 `<image_base64>` 标记 | `image_url` data URI 会被上游当截断的 base64 文本读,所以只对 deepseek 系改写 |
107
+ | `POST /points/first-login` 幂等,判据是 `alreadyProcessed` | 「今天已领」必须是 `done` 而不是 `claimed` |
108
+
109
+ ### 新手任务:一次性可领的 1 万分
110
+
111
+ Loomy 还有第三笔额度 —— **新手任务奖励**,总计 10,000 分,可主动领取:
112
+
113
+ | key | 任务 | 分值 |
114
+ |---|---|---|
115
+ | `first_message` | 发送第一条消息 | 500 |
116
+ | `pick_skill` | 选择一个技能 | 1000 |
117
+ | `generate_ppt` | 生成第一份 PPT | 1500 |
118
+ | `set_schedule` | 设置定时任务 | 1000 |
119
+ | `install_skill` | 安装一个技能 | 1500 |
120
+ | `configure_remote` | 配置远程控制 | 1000 |
121
+ | `create_soul` | 创建第一个搭子 | 1500 |
122
+ | `share_soul` | 分享搭子给朋友 | 2000 |
123
+
124
+ 端点:`GET /api/v1/onboarding/tasks`(只读)+ `POST /api/v1/onboarding/tasks/complete`
125
+ (幂等写,判据 `alreadyCompleted`)。实测两个账号都能读;流水里能看到
126
+ 「新手任务-发送第一条消息 +500」的 credit 记录 —— **领取是真到账的**。
127
+
128
+ 插件怎么用它:
129
+
130
+ - **卡片上是 `aside` 窗口**:「可领 9500 积分(7 项待完成)」。一次性奖励
131
+ **不参与路由打分**(不给 `limit`、`aside: true`)—— 否则一个任务没做完的号
132
+ 会显得额度很足而被优先派活。
133
+ - **签到成功后自动领**:领取是幂等的,放在每天一次的签到里做,既不会漏也不会
134
+ 重复。按分值**从高到低**串行领(中途失败至少领到大的那几项),失败不影响
135
+ 签到结果。
136
+ - **单独缓存 10 分钟**:`onboarding/tasks` 是另一个端点,而 `usage` 会被频繁
137
+ 刷新 —— 不能每次都打。
138
+
139
+ > 实况:`181****0632` 余额 0,但还有 10,000 分新手任务可领。卡片会如实显示,
140
+ > 不会因为「余额 0」就把这个人判死刑。
141
+
142
+ ### 邀请码:新账号自动用老账号的邀请资格
143
+
144
+ Loomy 的「分享有礼」——**邀请好友双方各得 5000 积分**(客户端常量 `nb = 5e3`;
145
+ ⚠ 别和新手任务里 `share_soul` 的 2000 混,那是两笔不同的奖励)。
146
+
147
+ 每个账号有**专属邀请码**(实测:`189****8051` → `E4DPT6`、`181****00632` → `FDW3CU`,
148
+ 上限 1000 次、已用 0),并且**每个账号只能兑换一次**别人的码。
149
+
150
+ | 端点 | 用途 |
151
+ |---|---|
152
+ | `GET /api/v1/invitation-codes` | 查自己的码(只读) |
153
+ | `GET /api/v1/points/activation` | 本账号是否已用过别人的码(只读) |
154
+ | `POST /api/v1/points/activation` | 绑定别人的码(一次性写) |
155
+ | `POST /api/v1/points/first-login` | **也接受 `{inviteCode, deviceId}`** —— 首次初始化时捎上,不用事后再绑 |
156
+
157
+ **这个插件怎么做的**:新账号登录时,自动从**本机其它已登录的 Loomy 账号**里挑一个
158
+ 邀请码带上去。
159
+
160
+ - 挑码规则:排除自己的、用完的(`usedCount >= maxUses`)、非 `active` 的;
161
+ 优先**用得最少**的(把额度摊开);`maxUses <= 0` 视为不限次。
162
+ - 先查 `activation`:**已用过就跳过**,不白发一次写请求(每账号只能用一次)。
163
+ - 走 `first-login {inviteCode}`(首次初始化顺带绑定);那条没成再退回
164
+ `points/activation`。**绑定失败不影响登录** —— 这是加分项。
165
+ - 为什么能拿到别的账号的邀请码:`getAuth()` 只在当前账号作用域里可见
166
+ (magpie 的 `inScope`),所以直接读 `~/.config/magpie/plugin-auth.json`,
167
+ 把 `loomy` / `loomy#xxxxxx` 全捞出来逐个查(只读、不打印 session)。
168
+
169
+ ```
170
+ 新账号登录 → 收集本机其它 Loomy 账号的邀请码 → 挑用得最少的
171
+ → 查 activation(已用过就跳过)→ first-login {inviteCode}
172
+ → 双方各 +5000
173
+ ```
174
+
175
+ ### 一次 `usage()` 的请求数
176
+
177
+ | 情形 | 请求数 |
178
+ |---|---|
179
+ | 凭据里有当天 `dailyQuota`(签到/登录写过) | **1**(只读 balance) |
180
+ | 凭据里没有当天上限 | 2(balance + 流水,翻页上限 6 页) |
181
+ | 之后每一轮 | 回到 **1**(推导出来的上限会写回凭据) |
182
+
183
+ 写回走 `client.auth.set({path:{id}})`;它在账号作用域里把 id 解析成**当前账号**的键,
184
+ 所以多账号互不串(实测两号各自写回自己的 `dailyQuota`)。
185
+
186
+ ---
187
+
188
+ ## 测试
189
+
190
+ ```bash
191
+ npm test # 57 条,全离线、零额度
192
+ node tests/live.mjs # 真实账号 + 真实上游(只读 + 幂等签到,不消费额度)
193
+ ```
194
+
195
+ 单测锁死这几组语义(**都做过反向验证**:改回市场插件的写法,对应用例会变红):
196
+
197
+ 1. 两池皆 0 → 一条 `used:100` 的**参与路由**窗口(不许 aside、不许消失)—— 变异后 4 条红
198
+ 2. 永久池恒 `aside` 且不给 `amount`/`limit`
199
+ 3. 上限未知 → `aside` + `used:0`,绝不谎报成满额
200
+ 4. 上限已知 → 真实占比 + 完整字段;跨日旧上限作废
201
+ 5. 签到 outcome 必须是契约六值之一(`"success"` 会让 magpie 显示「签到失败 · 已刷新」)—— 变异后 2 条红
202
+ 6. `free` 只由厂商声明决定(`rate === 0` 不等于免费)—— 变异后 1 条红
203
+ 7. 新手任务按分值排序、`aside` 不参与路由、全领完不画
204
+ 8. 邀请码:排除自己/用完/非 active,优先用得最少
205
+
206
+ `tests/live.mjs` 在真账号上的当前输出(2026-10-26):
207
+
208
+ ```
209
+ === loomy 18970098051
210
+ balance=8979 积分 used=30.42% limit=5000 永久池 aside
211
+ checkin → {"outcome":"done","message":"今日额度已刷新(3479/5000 积分)"}
212
+ === loomy#0zloqw 18170800632
213
+ balance=0 积分 used=100 ← 参与路由,会让这个号沉底
214
+ checkin → {"outcome":"done",...}
215
+ ✅ 全部通过
216
+ ```
217
+
218
+ ---
219
+
220
+ ## 已知取舍
221
+
222
+ - **不做二维码 / 微信登录**:上游把微信登录放在一个需要本地起页面的流程里,
223
+ 而桌面端导入 + 短信已经覆盖同一批账号;少一条链路少一份维护面。
224
+ - **不做「锁定永久积分」开关**:本插件把永久池恒标 `aside`(不参与路由),
225
+ 于是 magpie 只在其它号都不可用时才用它 —— 这已经是「优先别烧永久积分」的语义,
226
+ 不需要再加一个开关。
227
+ - **不做多账号并发选号**:magpie 自己管这个(`signInKey` → 账号作用域)。
228
+ 插件只负责把一个账号的真实读数报准 —— 报准了,选号自然对。
229
+
230
+ ---
231
+
232
+ ## 从本地 tgz 安装(不走 npm 时)
233
+
234
+ `magpie plugin add <tgz>` **不能用** —— 它把 tgz 当 JS 模块 `import()`,报
235
+ `exports no OpenCode plugin function`。按包名 + 本地 `file:` 依赖装:
236
+
237
+ ```bash
238
+ npm pack --pack-destination ./dist
239
+ cp dist/magpie-plugin-loomy-auth-*.tgz ~/.config/magpie/plugins/dist/
240
+ # plugins.json 追加 { "spec": "magpie-plugin-loomy-auth" }
241
+ # plugins/package.json 追加 "magpie-plugin-loomy-auth": "./dist/magpie-plugin-loomy-auth-*.tgz"
242
+ cd ~/.config/magpie/plugins && ~/.cache/magpie/bun/1.4.4/magpie-bun.exe install
243
+ ```
244
+
245
+ ⚠ **改了代码必须 bump `version` 再打包**:同一个版本号重打,bun 会命中缓存
246
+ (输出 `no changes`),装了个寂寞。
247
+
248
+ ### 装完要不要重启
249
+
250
+ **实测(2026-10-26):不必需。** 本地 tgz 装好、`plugins.json` 登记完成后,
251
+ 运行中的 magpie 在约几分钟内自行用上了新插件 —— 路由日志里同一个空号的 `used`
252
+ 从 `0` 变成 `100`(`2026-10-26T04:19:33`),进程 PID 未变。
253
+
254
+ ⚠ 触发机制**未查明**:二进制里没有 `fsnotify`/`Watcher`/`reloadPlugins` 符号,
255
+ 不是目录监听,疑似按 tick 复查配置。既然机制不明,**改完重启一次最稳**
256
+ (重启不丢登录态)。
257
+
258
+ ### ⚠ npm 包名与仓库名不是同一个
259
+
260
+ | | 值 |
261
+ |---|---|
262
+ | 仓库名 | `magpie-loomy-auth` |
263
+ | npm 包名 | **`magpie-plugin-loomy-auth`** |
264
+
265
+ `magpie-loomy-auth` 这个包名**在 npm 上已被他人占用**(0.3.2,维护者 `an0119`)。
266
+ magpie 的「有新版本」检查按**包名**去 npm 查,与仓库属主无关 —— 撞名会让界面提示
267
+ 一个**别人的**新版,点「更新」就把别人的包装进来顶掉本插件。加 `-plugin-` 段避开。
268
+
269
+ ⚠ **插件内 `REGISTRY_ENTRY.package` 必须与 `package.json` 的 `name` 一字不差**,
270
+ 否则自注册条目对不上市场卡片。
271
+
272
+ ---
273
+
274
+ ## 许可
275
+
276
+ MIT