mslxdff 0.1.231 → 0.1.233

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 (117) hide show
  1. package/bin/mslxdff.js +3 -3
  2. package/package.json +1 -1
  3. package/src/auto.js +264 -254
  4. package/src/bench/cline-bench.js +42 -42
  5. package/src/bench/probe.js +70 -70
  6. package/src/bench/report.js +162 -162
  7. package/src/bench/runner.js +77 -77
  8. package/src/bench/via-probe.js +124 -124
  9. package/src/bench/via-routes.js +87 -87
  10. package/src/bench/workbuddy-bench.js +54 -54
  11. package/src/chat/engine.js +160 -160
  12. package/src/chat/gateway.js +163 -163
  13. package/src/chat/orchestrator.js +234 -234
  14. package/src/chat/prompt.js +70 -70
  15. package/src/chat/repl.js +88 -88
  16. package/src/chat/terminal.js +135 -135
  17. package/src/chat/tools.js +306 -306
  18. package/src/chat-pipeline/index.js +155 -145
  19. package/src/chat-pipeline/policy.js +84 -84
  20. package/src/cli/commands/group.js +266 -266
  21. package/src/cli/commands/model/picks.js +50 -50
  22. package/src/cli/commands/provider/bench-via.js +247 -247
  23. package/src/cli/commands/provider/bench.js +141 -141
  24. package/src/cli/commands/provider/index.js +139 -139
  25. package/src/cli/commands/provider/models.js +149 -149
  26. package/src/cli/commands/provider/qwenwork-login.js +119 -119
  27. package/src/cli/commands/provider/raccoon-quota.js +156 -156
  28. package/src/cli/commands/sync.js +310 -310
  29. package/src/cli/status.js +279 -279
  30. package/src/daemon.js +246 -246
  31. package/src/model-capabilities/enrich.js +86 -86
  32. package/src/model-capabilities/index.js +183 -183
  33. package/src/model-capabilities/parse.js +70 -70
  34. package/src/model-trace.js +10 -2
  35. package/src/models.js +292 -225
  36. package/src/peers.js +345 -345
  37. package/src/providers/agentrouter.js +238 -238
  38. package/src/providers/base.js +164 -164
  39. package/src/providers/cline/auth.js +228 -228
  40. package/src/providers/cline/chat.js +307 -307
  41. package/src/providers/cline.js +2 -2
  42. package/src/providers/codearts/chat.js +207 -207
  43. package/src/providers/dispatcher.js +147 -147
  44. package/src/providers/globalqwenwork/cosy.js +123 -123
  45. package/src/providers/globalqwenwork/crypto.js +218 -218
  46. package/src/providers/globalqwenwork/http.js +20 -20
  47. package/src/providers/globalqwenwork/rsa.js +54 -54
  48. package/src/providers/globalqwenwork/sse.js +268 -268
  49. package/src/providers/globalqwenwork/stream.js +130 -130
  50. package/src/providers/globalqwenwork/upstream.js +122 -122
  51. package/src/providers/keyring.js +60 -60
  52. package/src/providers/qoder/account-store.js +18 -0
  53. package/src/providers/qoder/chat.js +292 -203
  54. package/src/providers/qoder/checkin.js +25 -12
  55. package/src/providers/qoder/index.js +311 -249
  56. package/src/providers/qoder/models.js +64 -2
  57. package/src/providers/qoder/oauth.js +42 -1
  58. package/src/providers/qoder/payload.js +116 -80
  59. package/src/providers/qoder/request.js +7 -2
  60. package/src/providers/qoder/session.js +26 -10
  61. package/src/providers/qoder/sse.js +233 -145
  62. package/src/providers/qoder/sticky.js +5 -2
  63. package/src/providers/qoder/wire-messages.js +242 -0
  64. package/src/providers/qwenwork/account-store.js +133 -133
  65. package/src/providers/qwenwork/constants.js +67 -67
  66. package/src/providers/qwenwork/cosy.js +120 -120
  67. package/src/providers/qwenwork/crypto.js +218 -218
  68. package/src/providers/qwenwork/http.js +20 -20
  69. package/src/providers/qwenwork/index.js +337 -337
  70. package/src/providers/qwenwork/payload.js +144 -144
  71. package/src/providers/qwenwork/rsa.js +54 -54
  72. package/src/providers/qwenwork/sse.js +268 -268
  73. package/src/providers/qwenwork/stream.js +130 -130
  74. package/src/providers/qwenwork/upstream.js +120 -120
  75. package/src/providers/qwenwork.js +1 -1
  76. package/src/providers/raccoon/chat.js +1 -1
  77. package/src/providers/raccoon/const.js +219 -202
  78. package/src/providers/raccoon/credits.js +285 -285
  79. package/src/providers/raccoon/index.js +15 -2
  80. package/src/providers/raccoon/models.js +68 -17
  81. package/src/providers/registry.js +89 -89
  82. package/src/providers/workbuddy/auth.js +16 -0
  83. package/src/providers/workbuddy/chat.js +298 -264
  84. package/src/providers/workbuddy/client-headers.js +148 -0
  85. package/src/providers/workbuddy/desktop-info.js +17 -1
  86. package/src/providers/workbuddy/models.js +8 -20
  87. package/src/providers/workbuddy/reshape.js +152 -152
  88. package/src/providers/workbuddy.js +2 -2
  89. package/src/reasoning.js +32 -32
  90. package/src/routes/chat/broadband-handler.js +80 -80
  91. package/src/routes/chat/gateway.js +46 -46
  92. package/src/routes/chat/relay-pipeline.js +282 -282
  93. package/src/routes/chat/via-route-handler.js +156 -156
  94. package/src/routes/hedge.js +260 -260
  95. package/src/routes/models-route.js +167 -167
  96. package/src/routes/peers.js +373 -373
  97. package/src/routes/stream.js +364 -347
  98. package/src/runtime/bootstrap.js +75 -75
  99. package/src/runtime/keep-warm.js +135 -135
  100. package/src/runtime/provider-gate.js +75 -75
  101. package/src/runtime/providers-setup.js +187 -187
  102. package/src/runtime/raccoon-checkin.js +175 -175
  103. package/src/server.js +85 -85
  104. package/src/state/schemas/allowlist.js +92 -92
  105. package/src/sync-opencode.js +280 -280
  106. package/src/transport/index.js +244 -244
  107. package/src/transport/pool.js +56 -56
  108. package/src/transport/retry.js +24 -24
  109. package/src/transport/sse.js +93 -93
  110. package/src/upstream-probe/display.js +52 -52
  111. package/src/upstream-probe/probe.js +49 -49
  112. package/src/upstream-probe/rotate.js +110 -110
  113. package/src/upstream-probe/start.js +45 -45
  114. package/src/upstream.js +355 -355
  115. package/docs/cli_help_mini.md +0 -148
  116. package/src/providers/AGENTS.md +0 -49
  117. package/src/routes/AGENTS.md +0 -37
@@ -1,156 +1,156 @@
1
- // mslxdff -provider raccoon quota — 逐号查积分余额(五分项)
2
- // mslxdff -provider raccoon checkin — 结算每日积分(每天)+ 补领一次性登录奖励
3
- // ⚠ 纠偏(2026-10-21 账单实测,推翻 2026-10-10 旧结论):每日积分是**惰性结算**——
4
- // 服务端按天挂账,当天第一次访问 `/office/v3/setting_info` 才真正入账(入账即有效期到 T+6,
5
- // 即官方文案「当天登录后延长至 7 天」)。不访问则当天 `daily_points` 恒 0、账单里没有 `daily_grant`。
6
- // 当前档位是 500 分(不是旧注释的 300),且**每天都要触发一次**,不是一次性。
7
- // 「桌面端登录奖励 3000」才是每号一次性的,登录时已自动领,checkin 只是兜底补领。
8
- // 判据一律走账单:上游对重复领取照样回 code:0,只信回执就会谎报到账。
9
- import { normalizeProviderId } from "../../../providers/model-id.js";
10
- import { compatFetch } from "../../../compat.js";
11
- import { listRaccoonAccountDocs, raccoonCredentialFromDoc } from "../../../providers/raccoon/account-store.js";
12
- import {
13
- claimRaccoonDailyPoints,
14
- claimRaccoonLoginReward,
15
- fetchRaccoonBalance,
16
- raccoonClaimStatus,
17
- raccoonDailyStatus,
18
- } from "../../../providers/raccoon/credits.js";
19
- import { raccoonTokenFingerprint } from "../../../providers/raccoon/auth.js";
20
-
21
- const SUBS = new Set(["quota", "credits", "balance", "checkin", "signin"]);
22
-
23
- /** 逐号列出(旧实现只取 docs[0],多号时会漏看余额、漏领一次性礼包)。 */
24
- function targets(deps) {
25
- if (deps.credential) return [{ name: "", credential: deps.credential }];
26
- return listRaccoonAccountDocs(deps.dir ? { dirs: [deps.dir] } : {})
27
- .filter((d) => d.accessToken)
28
- .map((d) => ({ name: d.name || "", credential: raccoonCredentialFromDoc(d) }));
29
- }
30
-
31
- const STATUS_LINE = {
32
- claimed: (r) => `🎁 已领取 +${r.points} 分 —— 账单已确认入账(每号仅此一次)`,
33
- already: () => `已领过 —— 每号只有一次,没有"明天再来"这回事`,
34
- phantom: () => `⚠ 上游回执「成功」但账单里查不到这笔 → 判定未到账,别当领过`,
35
- unverified: () => `已提交,但账单暂时查不到 → 未确认,稍后用 quota 核对`,
36
- error: (r) => `❌ 领取失败:${r.msg || "未知原因"}`,
37
- };
38
-
39
- const DAILY_LINE = {
40
- claimed: (r) => `✅ 每日积分 +${r.dailyPoints} 分 已入账${r.dailyExpireAt ? `(可用至 ${r.dailyExpireAt})` : ""}`,
41
- already: (r) => `每日积分今天已结算过${r.dailyPoints ? `(${r.dailyPoints} 分在账)` : ""}`,
42
- unverified: () => `⚠ 已触发结算,但账单里没看到今天这笔 → 未确认,稍后用 quota 核对`,
43
- error: () => `❌ 每日积分结算失败`,
44
- };
45
-
46
- // row.account 在构造时已换成 token 指纹(凭据纪律:CLI 只打指纹,绝不打完整 token)
47
- const label = (row) => `[${row.account}${row.uid ? " · " + row.uid : ""}]`;
48
-
49
- function expiredHint(error) {
50
- return error?.authExpired || error?.status === 401 || error?.code === 200001 || error?.code === 200003
51
- ? "登录态已失效(access_token 只有约 3 小时寿命),重新扫码: mslxdff -provider raccoon login"
52
- : "";
53
- }
54
-
55
- export async function handleRaccoonQuota(id, sub, rest = [], deps = {}) {
56
- const pid = normalizeProviderId(id) || String(id || "").toLowerCase();
57
- if (pid !== "raccoon") return false;
58
- if (!SUBS.has(sub)) return false;
59
-
60
- const fetchImpl = deps.fetchImpl || compatFetch;
61
- const log = deps.log || ((m) => console.log(m));
62
- const exit = deps.exit || ((code) => process.exit(code));
63
- const json = rest.includes("--json");
64
- const isCheckin = sub === "checkin" || sub === "signin";
65
- const list = targets(deps);
66
-
67
- if (!list.length) {
68
- if (json) log(JSON.stringify({ error: "not_logged_in", hint: "mslxdff -provider raccoon login" }));
69
- else {
70
- log("未登录:还没有可用的 raccoon 账号");
71
- log(" 先运行: mslxdff -provider raccoon login(登录时会自动领一次性登录奖励)");
72
- }
73
- exit(1);
74
- return true;
75
- }
76
-
77
- const rows = [];
78
- for (const t of list) {
79
- const base = { account: raccoonTokenFingerprint(t.credential.access_token), uid: t.credential.uid, name: t.name };
80
- try {
81
- if (isCheckin) {
82
- // 每日积分结算在前(每天必做),一次性登录奖励补领在后(正常态是「已领过」)。
83
- // 两件事互不影响:每日结算失败不该导致补领不跑。
84
- let daily = "error";
85
- let dailyPoints = 0;
86
- let dailyExpireAt;
87
- try {
88
- const d = await claimRaccoonDailyPoints({ credential: t.credential, fetchImpl, env: deps.env });
89
- daily = raccoonDailyStatus(d);
90
- dailyPoints = d.points || 0;
91
- if (d.expireAt !== undefined) dailyExpireAt = new Date(d.expireAt).toLocaleString("zh-CN", { hour12: false });
92
- } catch {
93
- daily = "error";
94
- }
95
- const r = await claimRaccoonLoginReward({ credential: t.credential, fetchImpl, env: deps.env });
96
- const status = raccoonClaimStatus(r);
97
- rows.push({
98
- ...base,
99
- ok: daily === "claimed" || daily === "already",
100
- daily,
101
- dailyPoints,
102
- ...(dailyExpireAt === undefined ? {} : { dailyExpireAt }),
103
- status,
104
- points: r.points,
105
- });
106
- } else {
107
- const b = await fetchRaccoonBalance({ credential: t.credential, fetchImpl, env: deps.env });
108
- rows.push({ ...base, ok: true, total: b.total, items: b.items });
109
- }
110
- } catch (e) {
111
- rows.push({ ...base, ok: false, status: "error", msg: String(e?.message ?? e).slice(0, 160), relogin: expiredHint(e) });
112
- }
113
- }
114
- const failed = rows.filter((r) => !r.ok).length;
115
-
116
- if (json) {
117
- log(JSON.stringify({ accounts: rows, ok: rows.length - failed, total: rows.length }));
118
- exit(failed === rows.length ? 1 : 0);
119
- return true;
120
- }
121
-
122
- if (isCheckin) {
123
- log(`raccoon 每日积分(每天结算 · 当前档位 500 分)· 共 ${rows.length} 个号`);
124
- for (const r of rows) {
125
- if (!r.ok) {
126
- log(` ${label(r)} ❌ ${r.msg || "登录态异常"}`);
127
- if (r.relogin) log(` → ${r.relogin}`);
128
- continue;
129
- }
130
- log(` ${label(r)} ${DAILY_LINE[r.daily]?.(r) || r.daily}`);
131
- // 一次性登录奖励:只有「真领到」才值得单独提一行;已领过是绝大多数情况,不再刷屏
132
- if (r.status === "claimed") log(` ${STATUS_LINE.claimed(r)}`);
133
- else if (r.status === "phantom" || r.status === "unverified") log(` ${STATUS_LINE[r.status](r)}`);
134
- }
135
- if (rows.some((r) => r.daily === "claimed")) log(` 查看余额: mslxdff -provider raccoon quota`);
136
- exit(failed === rows.length ? 1 : 0);
137
- return true;
138
- }
139
-
140
- log(`raccoon 积分 · 共 ${rows.length} 个号`);
141
- for (const r of rows) {
142
- if (!r.ok) {
143
- log(` ${label(r)} ❌ ${r.msg}`);
144
- if (r.relogin) log(` → ${r.relogin}`);
145
- continue;
146
- }
147
- const detail = r.items.length ? r.items.map((i) => `${i.label} ${i.value}`).join(" · ") : "(上游未返回分项明细)";
148
- log(` ${label(r)} 可用 ${r.total} ${detail}`);
149
- }
150
- log("");
151
- log(" ⚠ 「每日积分」每天 00:00 挂账、当天首次访问才入账(登录即入账),入账后有效期 7 天。不登录不结算就拿不到。");
152
- log(" ⚠ 倍率 0 的模型不扣积分(`mslxdff -provider raccoon models` 看倍率列),想省积分优先用它们。");
153
- log(" 登录奖励每号只有一次,登录时已自动领;本命令的 checkin 是「每日结算 + 补领兜底」。");
154
- exit(failed === rows.length ? 1 : 0);
155
- return true;
156
- }
1
+ // mslxdff -provider raccoon quota — 逐号查积分余额(五分项)
2
+ // mslxdff -provider raccoon checkin — 结算每日积分(每天)+ 补领一次性登录奖励
3
+ // ⚠ 纠偏(2026-10-21 账单实测,推翻 2026-10-10 旧结论):每日积分是**惰性结算**——
4
+ // 服务端按天挂账,当天第一次访问 `/office/v3/setting_info` 才真正入账(入账即有效期到 T+6,
5
+ // 即官方文案「当天登录后延长至 7 天」)。不访问则当天 `daily_points` 恒 0、账单里没有 `daily_grant`。
6
+ // 当前档位是 500 分(不是旧注释的 300),且**每天都要触发一次**,不是一次性。
7
+ // 「桌面端登录奖励 3000」才是每号一次性的,登录时已自动领,checkin 只是兜底补领。
8
+ // 判据一律走账单:上游对重复领取照样回 code:0,只信回执就会谎报到账。
9
+ import { normalizeProviderId } from "../../../providers/model-id.js";
10
+ import { compatFetch } from "../../../compat.js";
11
+ import { listRaccoonAccountDocs, raccoonCredentialFromDoc } from "../../../providers/raccoon/account-store.js";
12
+ import {
13
+ claimRaccoonDailyPoints,
14
+ claimRaccoonLoginReward,
15
+ fetchRaccoonBalance,
16
+ raccoonClaimStatus,
17
+ raccoonDailyStatus,
18
+ } from "../../../providers/raccoon/credits.js";
19
+ import { raccoonTokenFingerprint } from "../../../providers/raccoon/auth.js";
20
+
21
+ const SUBS = new Set(["quota", "credits", "balance", "checkin", "signin"]);
22
+
23
+ /** 逐号列出(旧实现只取 docs[0],多号时会漏看余额、漏领一次性礼包)。 */
24
+ function targets(deps) {
25
+ if (deps.credential) return [{ name: "", credential: deps.credential }];
26
+ return listRaccoonAccountDocs(deps.dir ? { dirs: [deps.dir] } : {})
27
+ .filter((d) => d.accessToken)
28
+ .map((d) => ({ name: d.name || "", credential: raccoonCredentialFromDoc(d) }));
29
+ }
30
+
31
+ const STATUS_LINE = {
32
+ claimed: (r) => `🎁 已领取 +${r.points} 分 —— 账单已确认入账(每号仅此一次)`,
33
+ already: () => `已领过 —— 每号只有一次,没有"明天再来"这回事`,
34
+ phantom: () => `⚠ 上游回执「成功」但账单里查不到这笔 → 判定未到账,别当领过`,
35
+ unverified: () => `已提交,但账单暂时查不到 → 未确认,稍后用 quota 核对`,
36
+ error: (r) => `❌ 领取失败:${r.msg || "未知原因"}`,
37
+ };
38
+
39
+ const DAILY_LINE = {
40
+ claimed: (r) => `✅ 每日积分 +${r.dailyPoints} 分 已入账${r.dailyExpireAt ? `(可用至 ${r.dailyExpireAt})` : ""}`,
41
+ already: (r) => `每日积分今天已结算过${r.dailyPoints ? `(${r.dailyPoints} 分在账)` : ""}`,
42
+ unverified: () => `⚠ 已触发结算,但账单里没看到今天这笔 → 未确认,稍后用 quota 核对`,
43
+ error: () => `❌ 每日积分结算失败`,
44
+ };
45
+
46
+ // row.account 在构造时已换成 token 指纹(凭据纪律:CLI 只打指纹,绝不打完整 token)
47
+ const label = (row) => `[${row.account}${row.uid ? " · " + row.uid : ""}]`;
48
+
49
+ function expiredHint(error) {
50
+ return error?.authExpired || error?.status === 401 || error?.code === 200001 || error?.code === 200003
51
+ ? "登录态已失效(access_token 只有约 3 小时寿命),重新扫码: mslxdff -provider raccoon login"
52
+ : "";
53
+ }
54
+
55
+ export async function handleRaccoonQuota(id, sub, rest = [], deps = {}) {
56
+ const pid = normalizeProviderId(id) || String(id || "").toLowerCase();
57
+ if (pid !== "raccoon") return false;
58
+ if (!SUBS.has(sub)) return false;
59
+
60
+ const fetchImpl = deps.fetchImpl || compatFetch;
61
+ const log = deps.log || ((m) => console.log(m));
62
+ const exit = deps.exit || ((code) => process.exit(code));
63
+ const json = rest.includes("--json");
64
+ const isCheckin = sub === "checkin" || sub === "signin";
65
+ const list = targets(deps);
66
+
67
+ if (!list.length) {
68
+ if (json) log(JSON.stringify({ error: "not_logged_in", hint: "mslxdff -provider raccoon login" }));
69
+ else {
70
+ log("未登录:还没有可用的 raccoon 账号");
71
+ log(" 先运行: mslxdff -provider raccoon login(登录时会自动领一次性登录奖励)");
72
+ }
73
+ exit(1);
74
+ return true;
75
+ }
76
+
77
+ const rows = [];
78
+ for (const t of list) {
79
+ const base = { account: raccoonTokenFingerprint(t.credential.access_token), uid: t.credential.uid, name: t.name };
80
+ try {
81
+ if (isCheckin) {
82
+ // 每日积分结算在前(每天必做),一次性登录奖励补领在后(正常态是「已领过」)。
83
+ // 两件事互不影响:每日结算失败不该导致补领不跑。
84
+ let daily = "error";
85
+ let dailyPoints = 0;
86
+ let dailyExpireAt;
87
+ try {
88
+ const d = await claimRaccoonDailyPoints({ credential: t.credential, fetchImpl, env: deps.env });
89
+ daily = raccoonDailyStatus(d);
90
+ dailyPoints = d.points || 0;
91
+ if (d.expireAt !== undefined) dailyExpireAt = new Date(d.expireAt).toLocaleString("zh-CN", { hour12: false });
92
+ } catch {
93
+ daily = "error";
94
+ }
95
+ const r = await claimRaccoonLoginReward({ credential: t.credential, fetchImpl, env: deps.env });
96
+ const status = raccoonClaimStatus(r);
97
+ rows.push({
98
+ ...base,
99
+ ok: daily === "claimed" || daily === "already",
100
+ daily,
101
+ dailyPoints,
102
+ ...(dailyExpireAt === undefined ? {} : { dailyExpireAt }),
103
+ status,
104
+ points: r.points,
105
+ });
106
+ } else {
107
+ const b = await fetchRaccoonBalance({ credential: t.credential, fetchImpl, env: deps.env });
108
+ rows.push({ ...base, ok: true, total: b.total, items: b.items });
109
+ }
110
+ } catch (e) {
111
+ rows.push({ ...base, ok: false, status: "error", msg: String(e?.message ?? e).slice(0, 160), relogin: expiredHint(e) });
112
+ }
113
+ }
114
+ const failed = rows.filter((r) => !r.ok).length;
115
+
116
+ if (json) {
117
+ log(JSON.stringify({ accounts: rows, ok: rows.length - failed, total: rows.length }));
118
+ exit(failed === rows.length ? 1 : 0);
119
+ return true;
120
+ }
121
+
122
+ if (isCheckin) {
123
+ log(`raccoon 每日积分(每天结算 · 当前档位 500 分)· 共 ${rows.length} 个号`);
124
+ for (const r of rows) {
125
+ if (!r.ok) {
126
+ log(` ${label(r)} ❌ ${r.msg || "登录态异常"}`);
127
+ if (r.relogin) log(` → ${r.relogin}`);
128
+ continue;
129
+ }
130
+ log(` ${label(r)} ${DAILY_LINE[r.daily]?.(r) || r.daily}`);
131
+ // 一次性登录奖励:只有「真领到」才值得单独提一行;已领过是绝大多数情况,不再刷屏
132
+ if (r.status === "claimed") log(` ${STATUS_LINE.claimed(r)}`);
133
+ else if (r.status === "phantom" || r.status === "unverified") log(` ${STATUS_LINE[r.status](r)}`);
134
+ }
135
+ if (rows.some((r) => r.daily === "claimed")) log(` 查看余额: mslxdff -provider raccoon quota`);
136
+ exit(failed === rows.length ? 1 : 0);
137
+ return true;
138
+ }
139
+
140
+ log(`raccoon 积分 · 共 ${rows.length} 个号`);
141
+ for (const r of rows) {
142
+ if (!r.ok) {
143
+ log(` ${label(r)} ❌ ${r.msg}`);
144
+ if (r.relogin) log(` → ${r.relogin}`);
145
+ continue;
146
+ }
147
+ const detail = r.items.length ? r.items.map((i) => `${i.label} ${i.value}`).join(" · ") : "(上游未返回分项明细)";
148
+ log(` ${label(r)} 可用 ${r.total} ${detail}`);
149
+ }
150
+ log("");
151
+ log(" ⚠ 「每日积分」每天 00:00 挂账、当天首次访问才入账(登录即入账),入账后有效期 7 天。不登录不结算就拿不到。");
152
+ log(" ⚠ 倍率 0 的模型不扣积分(`mslxdff -provider raccoon models` 看倍率列),想省积分优先用它们。");
153
+ log(" 登录奖励每号只有一次,登录时已自动领;本命令的 checkin 是「每日结算 + 补领兜底」。");
154
+ exit(failed === rows.length ? 1 : 0);
155
+ return true;
156
+ }