minimax-status 1.2.0 → 1.2.2
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/README.md +36 -29
- package/cli/api.js +42 -21
- package/cli/index.js +33 -32
- package/cli/model-context-sizes.js +52 -0
- package/cli/renderer.js +7 -3
- package/cli/status.js +19 -21
- package/cli/statusbar.js +12 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -11,9 +11,8 @@ MiniMax Token-Plan 使用状态监控工具,支持 CLI 命令和 Claude Code
|
|
|
11
11
|
|
|
12
12
|
| 插件 | 版本 | 安装方式 |
|
|
13
13
|
|------|------|----------|
|
|
14
|
-
| **CLI** | 1.
|
|
15
|
-
| **VSCode** | 1.2
|
|
16
|
-
| **OpenClaw** | - | 参考 `openclaw/minimax-usage/` 目录 |
|
|
14
|
+
| **CLI** | 1.2.0 | `npm install -g minimax-status` |
|
|
15
|
+
| **VSCode** | 1.3.2 | [VSCode Marketplace](https://marketplace.visualstudio.com/items?itemName=JochenYang.minimax-status-vscode) 或 [下载 VSIX](https://github.com/JochenYang/minimax-status/releases) |
|
|
17
16
|
|
|
18
17
|
## 特性
|
|
19
18
|
|
|
@@ -134,14 +133,14 @@ npm run package
|
|
|
134
133
|
集成成功后,底部状态栏将显示:
|
|
135
134
|
|
|
136
135
|
```
|
|
137
|
-
|
|
136
|
+
cli ❯ main * ❯ MiniMax-M* ❯ 205K ❯ 0% (4500/4500) · W ∞ ❯ 4h59m ❯ 剩336天
|
|
138
137
|
```
|
|
139
138
|
|
|
140
|
-
显示格式:`目录 ❯ 分支 ❯ 模型 ❯ 百分比(
|
|
139
|
+
显示格式:`目录 ❯ 分支 ❯ 模型 ❯ 上下文 ❯ 百分比(已用/总量) · 周限额 ❯ 倒计时 ❯ 到期天数`
|
|
141
140
|
|
|
142
141
|
**颜色说明**:
|
|
143
142
|
|
|
144
|
-
-
|
|
143
|
+
- **使用量**: ≥85%红色 | 60-85%黄色 | <60%绿色
|
|
145
144
|
- **到期时间**: ≤3天红色 | ≤7天黄色 | >7天绿色
|
|
146
145
|
|
|
147
146
|
### Git 分支显示说明
|
|
@@ -219,10 +218,10 @@ my-app │ main * │ ...
|
|
|
219
218
|
集成成功后,底部状态栏将显示:
|
|
220
219
|
|
|
221
220
|
```
|
|
222
|
-
|
|
221
|
+
cli ❯ main * ❯ MiniMax-M* ❯ 205K ❯ 0% (4500/4500) · W ∞ ❯ 4h59m ❯ 剩336天
|
|
223
222
|
```
|
|
224
223
|
|
|
225
|
-
显示格式:`目录 ❯ 分支 ❯ 百分比(
|
|
224
|
+
显示格式:`目录 ❯ 分支 ❯ 模型 ❯ 上下文 ❯ 百分比(已用/总量) · 周限额 ❯ 倒计时 ❯ 到期天数`
|
|
226
225
|
|
|
227
226
|
**颜色说明**:
|
|
228
227
|
|
|
@@ -234,30 +233,38 @@ minimax-status ❯ main * ❯ 10% (4047/4500) ❯ 12m ❯ 剩21天
|
|
|
234
233
|
### 详细模式
|
|
235
234
|
|
|
236
235
|
```
|
|
237
|
-
|
|
236
|
+
┌──────────────────────────────────────────────────────┐
|
|
238
237
|
│ MiniMax Claude Code 使用状态 │
|
|
239
|
-
│
|
|
240
|
-
│ 当前模型: MiniMax-
|
|
241
|
-
│ 时间窗口:
|
|
242
|
-
│ 剩余时间:
|
|
243
|
-
│
|
|
244
|
-
│ 已用额度:
|
|
245
|
-
│ 剩余:
|
|
246
|
-
│
|
|
247
|
-
│
|
|
248
|
-
│
|
|
249
|
-
│
|
|
250
|
-
│
|
|
251
|
-
│
|
|
252
|
-
│
|
|
238
|
+
│ │
|
|
239
|
+
│ 当前模型: MiniMax-M* │
|
|
240
|
+
│ 时间窗口: 05:00-10:00(UTC+8) │
|
|
241
|
+
│ 剩余时间: 6 分钟后重置 │
|
|
242
|
+
│ │
|
|
243
|
+
│ 已用额度: █░░░░░░░░░░░░░░░░░░░░░░░░░░ 7% │
|
|
244
|
+
│ 剩余: 4172/4500 次调用 │
|
|
245
|
+
│ │
|
|
246
|
+
│ 周限额: 不受限制 │
|
|
247
|
+
│ 套餐到期: 03/19/2027 (还剩 336 天) │
|
|
248
|
+
│ │
|
|
249
|
+
│ 📊 Token 消耗统计 │
|
|
250
|
+
│ 昨日消耗: 5380.6万 │
|
|
251
|
+
│ 近7天消耗: 4.8亿 │
|
|
252
|
+
│ 当月消耗: 15亿 │
|
|
253
|
+
│ │
|
|
254
|
+
│ 📋 所有模型额度 │
|
|
255
|
+
│ MiniMax-M* 7% 328/4500 ✓ │
|
|
256
|
+
│ speech-hd 0% 0/19000 ✓ │
|
|
257
|
+
│ Hailuo 0% 0/3 ✓ │
|
|
258
|
+
│ ... │
|
|
259
|
+
│ │
|
|
253
260
|
│ 状态: ✓ 正常使用 │
|
|
254
|
-
|
|
261
|
+
└──────────────────────────────────────────────────────┘
|
|
255
262
|
```
|
|
256
263
|
|
|
257
264
|
### 紧凑模式
|
|
258
265
|
|
|
259
266
|
```
|
|
260
|
-
● MiniMax-
|
|
267
|
+
● MiniMax-M* 0% (4498/4500) • 4 小时 59 分钟后重置 • ✓ 正常使用 • 剩余: 336天
|
|
261
268
|
```
|
|
262
269
|
|
|
263
270
|
### 持续状态栏模式
|
|
@@ -296,10 +303,11 @@ minimax-status ❯ main * ❯ 10% (4047/4500) ❯ 12m ❯ 剩21天
|
|
|
296
303
|
| 元素 | 说明 |
|
|
297
304
|
| ------ | ---------------------------------- |
|
|
298
305
|
| 目录 | 当前工作目录 |
|
|
299
|
-
| 分支 | Git
|
|
306
|
+
| 分支 | Git 分支名称(含未提交状态) |
|
|
300
307
|
| 模型 | MiniMax 模型名称 |
|
|
301
|
-
| 上下文 |
|
|
302
|
-
| Usage | 使用量百分比(
|
|
308
|
+
| 上下文 | 上下文窗口使用 tokens |
|
|
309
|
+
| Usage | 使用量百分比(已用/总量) |
|
|
310
|
+
| 周限额 | 周配额使用情况,∞ 表示无限制 |
|
|
303
311
|
| ⏱ | 额度重置倒计时 |
|
|
304
312
|
| 到期 | 订阅到期时间(颜色动态变化) |
|
|
305
313
|
|
|
@@ -407,7 +415,6 @@ MIT License - 详见 [LICENSE](LICENSE) 文件
|
|
|
407
415
|
|--------|------|------|
|
|
408
416
|
| **CLI** | [`cli/`](cli/) | 命令行工具,npm 全局包 |
|
|
409
417
|
| **VSCode** | [`vscode-extension/`](vscode-extension/) | VSCode 状态栏集成 |
|
|
410
|
-
| **OpenClaw** | [`openclaw/`](openclaw/) | OpenClaw 集成 |
|
|
411
418
|
|
|
412
419
|
---
|
|
413
420
|
|
package/cli/api.js
CHANGED
|
@@ -3,6 +3,7 @@ const https = require("https");
|
|
|
3
3
|
const fs = require("fs");
|
|
4
4
|
const path = require("path");
|
|
5
5
|
const chalk = require("chalk").default;
|
|
6
|
+
const { getContextWindowSize, getDefaultContextWindowSize } = require('./model-context-sizes');
|
|
6
7
|
|
|
7
8
|
// 创建 HTTPS Agent 配置
|
|
8
9
|
const httpsAgent = new https.Agent({
|
|
@@ -80,10 +81,11 @@ class MinimaxAPI {
|
|
|
80
81
|
|
|
81
82
|
try {
|
|
82
83
|
const response = await axios.get(
|
|
83
|
-
`https://www.minimaxi.com/v1/
|
|
84
|
+
`https://www.minimaxi.com/v1/api/openplatform/coding_plan/remains`,
|
|
84
85
|
{
|
|
85
86
|
headers: {
|
|
86
87
|
Authorization: `Bearer ${this.token}`,
|
|
88
|
+
referer: "https://platform.minimaxi.com/",
|
|
87
89
|
Accept: "application/json",
|
|
88
90
|
},
|
|
89
91
|
timeout: 10000, // 10秒超时
|
|
@@ -295,24 +297,33 @@ class MinimaxAPI {
|
|
|
295
297
|
const endTime = new Date(modelData.end_time);
|
|
296
298
|
|
|
297
299
|
// Calculate counts
|
|
298
|
-
// 新接口 usage_count
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
const usedPercentage =
|
|
304
|
-
(
|
|
305
|
-
|
|
300
|
+
// ⚠ 新接口 usage_count 在 video 上语义不一致(usage=3/total=3 但 remaining_percent=100
|
|
301
|
+
// 表示 0% 已用),用 usedPercentage 反算 used(用户视角 = 基于官网显示的已用%)。
|
|
302
|
+
// 这让 video: total=3, usedPercentage=0 → used=0, remaining=3("3/3 剩余"),跟官网一致。
|
|
303
|
+
const totalCount = modelData.current_interval_total_count;
|
|
304
|
+
const remainingPct = modelData.current_interval_remaining_percent;
|
|
305
|
+
const usedPercentage = remainingPct !== undefined && remainingPct !== null
|
|
306
|
+
? Math.round(100 - remainingPct)
|
|
307
|
+
: (totalCount > 0 ? Math.round((modelData.current_interval_usage_count / totalCount) * 100) : 0);
|
|
308
|
+
const usedCount = totalCount > 0 ? Math.round((totalCount * usedPercentage) / 100) : 0;
|
|
309
|
+
const remainingCount = totalCount - usedCount;
|
|
306
310
|
|
|
307
311
|
// Calculate remaining time in human-readable format
|
|
308
312
|
const remainingMs = modelData.remains_time;
|
|
309
313
|
const hours = Math.floor(remainingMs / (1000 * 60 * 60));
|
|
310
314
|
const minutes = Math.floor((remainingMs % (1000 * 60 * 60)) / (1000 * 60));
|
|
311
315
|
|
|
312
|
-
// Calculate weekly usage data
|
|
316
|
+
// Calculate weekly usage data — 同样基于 remaining_percent 反转
|
|
313
317
|
const weeklyUsed = modelData.current_weekly_usage_count;
|
|
314
318
|
const weeklyTotal = modelData.current_weekly_total_count;
|
|
315
|
-
const
|
|
319
|
+
const weeklyRemainingPct = modelData.current_weekly_remaining_percent;
|
|
320
|
+
const weeklyPercentage = weeklyRemainingPct !== undefined && weeklyRemainingPct !== null
|
|
321
|
+
? Math.round(100 - weeklyRemainingPct)
|
|
322
|
+
: (weeklyTotal > 0 ? Math.floor((weeklyUsed / weeklyTotal) * 100) : 0);
|
|
323
|
+
// ⚠ Bug fix: 旧逻辑 weeklyTotal === 0 判 unlimited,但主人账号的 `general`
|
|
324
|
+
// 模型 weekly_total=0、weekly_remaining_percent=97(3% 已用,有数据)。
|
|
325
|
+
// 真正的"无限"应当是 total=0 **且** remaining_percent 也没返回。
|
|
326
|
+
const weeklyUnlimited = weeklyTotal === 0 && (modelData.current_weekly_remaining_percent == null);
|
|
316
327
|
const weeklyRemainingMs = modelData.weekly_remains_time;
|
|
317
328
|
const weeklyDays = Math.floor(weeklyRemainingMs / (1000 * 60 * 60 * 24));
|
|
318
329
|
const weeklyHours = Math.floor((weeklyRemainingMs % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
|
|
@@ -346,10 +357,11 @@ class MinimaxAPI {
|
|
|
346
357
|
}
|
|
347
358
|
|
|
348
359
|
// 上下文窗口信息
|
|
349
|
-
//
|
|
350
|
-
const
|
|
360
|
+
// 根据模型名称获取上下文窗口大小,回退到默认值
|
|
361
|
+
const contextWindowSize =
|
|
362
|
+
getContextWindowSize(modelData.model_name) || getDefaultContextWindowSize();
|
|
351
363
|
const contextWindow = {
|
|
352
|
-
total:
|
|
364
|
+
total: contextWindowSize,
|
|
353
365
|
used: 0,
|
|
354
366
|
percentage: 0,
|
|
355
367
|
totalFormatted: "200K",
|
|
@@ -393,7 +405,7 @@ class MinimaxAPI {
|
|
|
393
405
|
percentage: weeklyPercentage,
|
|
394
406
|
days: weeklyDays,
|
|
395
407
|
hours: weeklyHours,
|
|
396
|
-
unlimited:
|
|
408
|
+
unlimited: weeklyUnlimited,
|
|
397
409
|
text: weeklyDays > 0
|
|
398
410
|
? `${weeklyDays} 天 ${weeklyHours} 小时后重置`
|
|
399
411
|
: `${weeklyHours} 小时后重置`,
|
|
@@ -415,16 +427,25 @@ class MinimaxAPI {
|
|
|
415
427
|
|
|
416
428
|
return apiData.model_remains.map(modelData => {
|
|
417
429
|
const totalCount = modelData.current_interval_total_count;
|
|
418
|
-
// 新接口 usage_count
|
|
419
|
-
|
|
430
|
+
// ⚠ 新接口 usage_count 在 video 上语义不一致;用 usedPercentage 反算 used
|
|
431
|
+
// 跟官网一致:video total=3, used%=0 → used=0, remaining=3("3/3 剩余")
|
|
432
|
+
const remainingPct = modelData.current_interval_remaining_percent;
|
|
433
|
+
const usedPercentage = remainingPct !== undefined && remainingPct !== null
|
|
434
|
+
? Math.round(100 - remainingPct)
|
|
435
|
+
: (totalCount > 0 ? Math.round((modelData.current_interval_usage_count / totalCount) * 100) : 0);
|
|
436
|
+
const usedCount = totalCount > 0 ? Math.round((totalCount * usedPercentage) / 100) : 0;
|
|
420
437
|
const remainingCount = totalCount - usedCount;
|
|
421
|
-
const usedPercentage = totalCount > 0 ? Math.round((usedCount / totalCount) * 100) : 0;
|
|
422
438
|
|
|
423
|
-
// Weekly data
|
|
439
|
+
// Weekly data — 同样基于 remaining_percent 反转
|
|
424
440
|
const weeklyTotal = modelData.current_weekly_total_count || 0;
|
|
425
441
|
const weeklyUsed = modelData.current_weekly_usage_count || 0;
|
|
426
442
|
const weeklyRemainingCount = weeklyTotal - weeklyUsed;
|
|
427
|
-
const
|
|
443
|
+
const weeklyRemainingPct = modelData.current_weekly_remaining_percent;
|
|
444
|
+
const weeklyPercentage = weeklyRemainingPct !== undefined && weeklyRemainingPct !== null
|
|
445
|
+
? Math.round(100 - weeklyRemainingPct)
|
|
446
|
+
: (weeklyTotal > 0 ? Math.floor((weeklyUsed / weeklyTotal) * 100) : 0);
|
|
447
|
+
// Bug fix: 同 parseUsageData — 真正"无限"是 total=0 且 remaining_percent 也没
|
|
448
|
+
const weeklyUnlimited = weeklyTotal === 0 && (modelData.current_weekly_remaining_percent == null);
|
|
428
449
|
|
|
429
450
|
return {
|
|
430
451
|
name: modelData.model_name,
|
|
@@ -432,7 +453,7 @@ class MinimaxAPI {
|
|
|
432
453
|
remaining: remainingCount,
|
|
433
454
|
total: totalCount,
|
|
434
455
|
percentage: usedPercentage,
|
|
435
|
-
unlimited:
|
|
456
|
+
unlimited: weeklyUnlimited,
|
|
436
457
|
weeklyPercentage,
|
|
437
458
|
weeklyTotal,
|
|
438
459
|
weeklyRemainingCount,
|
package/cli/index.js
CHANGED
|
@@ -12,6 +12,7 @@ const TranscriptParser = require("./transcript-parser");
|
|
|
12
12
|
const ConfigCounter = require("./config-counter");
|
|
13
13
|
const Renderer = require("./renderer");
|
|
14
14
|
const packageJson = require("../package.json");
|
|
15
|
+
const { getContextWindowSize, getDefaultContextWindowSize } = require('./model-context-sizes');
|
|
15
16
|
|
|
16
17
|
const program = new Command();
|
|
17
18
|
const api = new MinimaxAPI();
|
|
@@ -238,7 +239,7 @@ program
|
|
|
238
239
|
let displayModel = modelName;
|
|
239
240
|
let currentDir = null;
|
|
240
241
|
let modelId = null;
|
|
241
|
-
let contextSize =
|
|
242
|
+
let contextSize = getContextWindowSize(modelName) || getDefaultContextWindowSize();
|
|
242
243
|
|
|
243
244
|
if (stdinData) {
|
|
244
245
|
if (stdinData.model && stdinData.model.display_name) {
|
|
@@ -257,8 +258,8 @@ program
|
|
|
257
258
|
}
|
|
258
259
|
|
|
259
260
|
if (modelId) {
|
|
260
|
-
// MiniMax
|
|
261
|
-
contextSize =
|
|
261
|
+
// MiniMax 模型使用映射表获取 context window
|
|
262
|
+
contextSize = getContextWindowSize(modelId) || getContextWindowSize(modelName) || getDefaultContextWindowSize();
|
|
262
263
|
}
|
|
263
264
|
|
|
264
265
|
let contextUsageTokens = null;
|
|
@@ -601,7 +602,7 @@ program
|
|
|
601
602
|
// 计算上下文使用量(从 session 实时 token)
|
|
602
603
|
// 使用实时 contextTokens 计算百分比
|
|
603
604
|
const contextUsageValue = contextTokens;
|
|
604
|
-
const contextSizeValue =
|
|
605
|
+
const contextSizeValue = getContextWindowSize(modelName) || getDefaultContextWindowSize();
|
|
605
606
|
|
|
606
607
|
// 获取 Droid 全局配置统计(不是当前工作目录)
|
|
607
608
|
const droidConfigDir = path.join(process.env.HOME || process.env.USERPROFILE, ".factory");
|
|
@@ -688,34 +689,34 @@ program
|
|
|
688
689
|
blocks.push({ text: ` 剩${expiry.daysRemaining}天 `, bg: bg });
|
|
689
690
|
}
|
|
690
691
|
|
|
691
|
-
let out = '';
|
|
692
|
-
const leftArrow = useNerdFonts ? '\uE0B0' : '>';
|
|
693
|
-
|
|
694
|
-
for (let i = 0; i < blocks.length; i++) {
|
|
695
|
-
const b = blocks[i];
|
|
696
|
-
|
|
697
|
-
// 磁贴开启:顺行式起点,利用黑色箭头实现内凹镂空感
|
|
698
|
-
if (i === 0) {
|
|
699
|
-
out += '\u001b[0m' + chalk.bgHex(b.bg).black(leftArrow);
|
|
700
|
-
}
|
|
701
|
-
|
|
702
|
-
// 磁贴文字内容
|
|
703
|
-
out += '\u001b[0m' + chalk.bgHex(b.bg).bold.whiteBright(b.text);
|
|
704
|
-
|
|
705
|
-
if (i < blocks.length - 1) {
|
|
706
|
-
const nextB = blocks[i + 1];
|
|
707
|
-
if (useNerdFonts) {
|
|
708
|
-
// 衔接尖部
|
|
709
|
-
out += '\u001b[0m' + chalk.bgHex(nextB.bg).hex(b.bg)(arrow);
|
|
710
|
-
} else {
|
|
711
|
-
out += '\u001b[0m' + chalk.bgHex(b.bg).bold.whiteBright(arrow);
|
|
712
|
-
}
|
|
713
|
-
} else {
|
|
714
|
-
// 最后一块磁贴:顺行式终点
|
|
715
|
-
out += '\u001b[0m' + chalk.hex(b.bg)(arrow);
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
|
|
692
|
+
let out = '';
|
|
693
|
+
const leftArrow = useNerdFonts ? '\uE0B0' : '>';
|
|
694
|
+
|
|
695
|
+
for (let i = 0; i < blocks.length; i++) {
|
|
696
|
+
const b = blocks[i];
|
|
697
|
+
|
|
698
|
+
// 磁贴开启:顺行式起点,利用黑色箭头实现内凹镂空感
|
|
699
|
+
if (i === 0) {
|
|
700
|
+
out += '\u001b[0m' + chalk.bgHex(b.bg).black(leftArrow);
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
// 磁贴文字内容
|
|
704
|
+
out += '\u001b[0m' + chalk.bgHex(b.bg).bold.whiteBright(b.text);
|
|
705
|
+
|
|
706
|
+
if (i < blocks.length - 1) {
|
|
707
|
+
const nextB = blocks[i + 1];
|
|
708
|
+
if (useNerdFonts) {
|
|
709
|
+
// 衔接尖部
|
|
710
|
+
out += '\u001b[0m' + chalk.bgHex(nextB.bg).hex(b.bg)(arrow);
|
|
711
|
+
} else {
|
|
712
|
+
out += '\u001b[0m' + chalk.bgHex(b.bg).bold.whiteBright(arrow);
|
|
713
|
+
}
|
|
714
|
+
} else {
|
|
715
|
+
// 最后一块磁贴:顺行式终点
|
|
716
|
+
out += '\u001b[0m' + chalk.hex(b.bg)(arrow);
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
|
|
719
720
|
console.log(out);
|
|
720
721
|
});
|
|
721
722
|
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MiniMax 模型 context window 大小映射表
|
|
3
|
+
* 单位: tokens
|
|
4
|
+
*
|
|
5
|
+
* 来源: https://platform.minimax.io/docs/api-reference/text-openai-api
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const MODEL_CONTEXT_SIZES = {
|
|
9
|
+
// MiniMax M 系列 - 统一 200K context window
|
|
10
|
+
'MiniMax-M2': 204800,
|
|
11
|
+
'MiniMax-M2.1': 204800,
|
|
12
|
+
'MiniMax-M2.1-highspeed': 204800,
|
|
13
|
+
'MiniMax-M2.5': 204800,
|
|
14
|
+
'MiniMax-M2.5-highspeed': 204800,
|
|
15
|
+
'MiniMax-M2.7': 204800,
|
|
16
|
+
'MiniMax-M2.7-highspeed': 204800,
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* 根据模型名称获取 context window 大小
|
|
21
|
+
* @param {string} modelName - 模型名称
|
|
22
|
+
* @returns {number|null} context window 大小,如果未找到返回 null
|
|
23
|
+
*/
|
|
24
|
+
function getContextWindowSize(modelName) {
|
|
25
|
+
if (!modelName) return null;
|
|
26
|
+
|
|
27
|
+
// 精确匹配
|
|
28
|
+
if (MODEL_CONTEXT_SIZES[modelName] !== undefined) {
|
|
29
|
+
return MODEL_CONTEXT_SIZES[modelName];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// MiniMax M 系列模糊匹配(兼容未知的 MiniMax-M 系列新型号)
|
|
33
|
+
if (modelName.includes('MiniMax-M')) {
|
|
34
|
+
return 204800;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* 获取默认 context window 大小
|
|
42
|
+
* @returns {number} 默认值 200000
|
|
43
|
+
*/
|
|
44
|
+
function getDefaultContextWindowSize() {
|
|
45
|
+
return 200000;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
module.exports = {
|
|
49
|
+
MODEL_CONTEXT_SIZES,
|
|
50
|
+
getContextWindowSize,
|
|
51
|
+
getDefaultContextWindowSize,
|
|
52
|
+
};
|
package/cli/renderer.js
CHANGED
|
@@ -100,13 +100,17 @@ class Renderer {
|
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
|
|
103
|
+
// 5h 限额 block — 总是显示(即使 total=0 也要显示百分比 + 5h 前缀)
|
|
104
|
+
// ⚠ 不再用 usage.total > 0 过滤(5h 限额数据对 general 模型 total=0 也要显示)
|
|
105
|
+
if (usage && usage.percentage !== undefined && usage.percentage !== null) {
|
|
104
106
|
let bg = '#065F46'; // safe (Emerald 800 - dark enough for white text)
|
|
105
107
|
if (usagePercentage >= 95) bg = '#991B1B'; // danger (Red 800)
|
|
106
108
|
else if (usagePercentage >= 75) bg = '#9A3412'; // warn (Orange 800)
|
|
107
109
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
+
// total=0 时不显示 (X/Y) 段
|
|
111
|
+
const usedTotalSuffix = usage.total > 0 ? ` (${usage.remaining}/${usage.total})` : '';
|
|
112
|
+
let usageText = ` 5h ${usagePercentage}%${usedTotalSuffix} `;
|
|
113
|
+
|
|
110
114
|
if (weekly) {
|
|
111
115
|
if (weekly.unlimited) {
|
|
112
116
|
usageText += `· W ∞ `;
|
package/cli/status.js
CHANGED
|
@@ -35,7 +35,7 @@ class StatusBar {
|
|
|
35
35
|
|
|
36
36
|
const lines = [];
|
|
37
37
|
lines.push('');
|
|
38
|
-
lines.push(chalk.bold('
|
|
38
|
+
lines.push(chalk.bold('Token 消耗统计'));
|
|
39
39
|
|
|
40
40
|
// 计算表格宽度
|
|
41
41
|
const leftWidth = 12; // "昨日消耗: "
|
|
@@ -63,7 +63,7 @@ class StatusBar {
|
|
|
63
63
|
|
|
64
64
|
const lines = [];
|
|
65
65
|
lines.push('');
|
|
66
|
-
lines.push(chalk.bold('
|
|
66
|
+
lines.push(chalk.bold('所有模型额度'));
|
|
67
67
|
|
|
68
68
|
// 简化模型名称映射
|
|
69
69
|
const shortName = (name) => {
|
|
@@ -86,9 +86,9 @@ class StatusBar {
|
|
|
86
86
|
|
|
87
87
|
// 显示状态
|
|
88
88
|
const getStatusText = (percentage) => {
|
|
89
|
-
if (percentage >= 85) return '
|
|
90
|
-
if (percentage >= 60) return '
|
|
91
|
-
return '
|
|
89
|
+
if (percentage >= 85) return 'X';
|
|
90
|
+
if (percentage >= 60) return '!';
|
|
91
|
+
return 'OK';
|
|
92
92
|
};
|
|
93
93
|
|
|
94
94
|
// 每行显示一个模型
|
|
@@ -97,7 +97,8 @@ class StatusBar {
|
|
|
97
97
|
const color = getStatusColor(model.percentage);
|
|
98
98
|
const status = getStatusText(model.percentage);
|
|
99
99
|
const pct = `${model.percentage}%`;
|
|
100
|
-
|
|
100
|
+
// total=0 时不显示 X/Y(避免 0/0 这种无数据展示)
|
|
101
|
+
const usedTotal = model.total > 0 ? `${model.used}/${model.total}` : '—';
|
|
101
102
|
|
|
102
103
|
lines.push(` ${color(short.padEnd(15))} ${color(pct.padEnd(5))} ${color(usedTotal.padEnd(12))} ${color(status)}`);
|
|
103
104
|
}
|
|
@@ -143,13 +144,6 @@ class StatusBar {
|
|
|
143
144
|
|
|
144
145
|
contentLines.push('');
|
|
145
146
|
|
|
146
|
-
// 模型名称
|
|
147
|
-
contentLines.push(`${chalk.cyan('当前模型:')} ${modelName}`);
|
|
148
|
-
|
|
149
|
-
// 时间窗口
|
|
150
|
-
const timeWindowText = `${timeWindow.start}-${timeWindow.end}(${timeWindow.timezone})`;
|
|
151
|
-
contentLines.push(`${chalk.cyan('时间窗口:')} ${timeWindowText}`);
|
|
152
|
-
|
|
153
147
|
// 剩余时间
|
|
154
148
|
contentLines.push(`${chalk.cyan('剩余时间:')} ${remaining.text}`);
|
|
155
149
|
|
|
@@ -158,8 +152,10 @@ class StatusBar {
|
|
|
158
152
|
// 使用百分比与进度条
|
|
159
153
|
contentLines.push(`${chalk.cyan('已用额度:')} ${progressBar} ${usage.percentage}%`);
|
|
160
154
|
|
|
161
|
-
//
|
|
162
|
-
|
|
155
|
+
// 剩余次数(total=0 时不显示)
|
|
156
|
+
if (usage.total > 0) {
|
|
157
|
+
contentLines.push(`${chalk.dim(' 剩余:')} ${usage.remaining}/${usage.total} 次调用`);
|
|
158
|
+
}
|
|
163
159
|
|
|
164
160
|
// 周用量(如果有数据)
|
|
165
161
|
if (weekly) {
|
|
@@ -176,7 +172,9 @@ class StatusBar {
|
|
|
176
172
|
15 - Math.floor((weeklyPercent / 100) * 15),
|
|
177
173
|
weeklyPercent
|
|
178
174
|
);
|
|
179
|
-
|
|
175
|
+
// total=0 时不显示 (X/Y)
|
|
176
|
+
const weeklyUsedTotal = weekly.total > 0 ? ` (${weekly.used}/${weekly.total})` : '';
|
|
177
|
+
contentLines.push(`${chalk.cyan('周限额:')} ${weeklyColor(weeklyProgress)} ${weeklyColor(weekly.percentage + '%')}${weeklyUsedTotal}`);
|
|
180
178
|
contentLines.push(`${chalk.dim(' 重置:')} ${weekly.text}`);
|
|
181
179
|
}
|
|
182
180
|
}
|
|
@@ -249,13 +247,13 @@ class StatusBar {
|
|
|
249
247
|
}
|
|
250
248
|
|
|
251
249
|
getStatus(percentage) {
|
|
252
|
-
//
|
|
250
|
+
// 基于已使用百分比(去 emoji 跟 vscode 1.0.7 风格一致)
|
|
253
251
|
if (percentage >= 85) {
|
|
254
|
-
return '
|
|
252
|
+
return '即将用完';
|
|
255
253
|
} else if (percentage >= 60) {
|
|
256
|
-
return '
|
|
254
|
+
return '注意使用';
|
|
257
255
|
} else {
|
|
258
|
-
return '
|
|
256
|
+
return '正常使用';
|
|
259
257
|
}
|
|
260
258
|
}
|
|
261
259
|
|
|
@@ -287,7 +285,7 @@ class StatusBar {
|
|
|
287
285
|
|
|
288
286
|
const lines = [];
|
|
289
287
|
lines.push('');
|
|
290
|
-
lines.push(chalk.bold('
|
|
288
|
+
lines.push(chalk.bold('所有模型额度'));
|
|
291
289
|
|
|
292
290
|
// 表头
|
|
293
291
|
lines.push(chalk.gray('─'.repeat(55)));
|
package/cli/statusbar.js
CHANGED
|
@@ -10,7 +10,7 @@ class StatusBar {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
render() {
|
|
13
|
-
const { usage, remaining,
|
|
13
|
+
const { usage, remaining, weekly, expiry } = this.data;
|
|
14
14
|
const percentage = usage.percentage;
|
|
15
15
|
|
|
16
16
|
// 基于已使用百分比:使用越多越危险
|
|
@@ -21,22 +21,29 @@ class StatusBar {
|
|
|
21
21
|
color = chalk.yellow;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
const statusIcon = percentage >= 85 ? '⚠' : percentage >= 60 ? '⚡' : '✓';
|
|
25
24
|
const remainingText = remaining.hours > 0
|
|
26
25
|
? `${remaining.hours}h${remaining.minutes}m`
|
|
27
26
|
: `${remaining.minutes}m`;
|
|
28
27
|
|
|
28
|
+
// total=0 时不显示 X/Y(避免 0/0 这种无数据展示,保留百分比)
|
|
29
|
+
const usedTotalSuffix = usage.total > 0 ? ` (${usage.used}/${usage.total})` : '';
|
|
30
|
+
|
|
29
31
|
let weeklyStr = '';
|
|
30
32
|
if (weekly) {
|
|
31
33
|
if (weekly.unlimited) {
|
|
32
|
-
weeklyStr = ` ${chalk.blue('W')}
|
|
34
|
+
weeklyStr = ` ${chalk.blue('W')} ∞`;
|
|
33
35
|
} else {
|
|
34
36
|
const weeklyColor = weekly.percentage >= 85 ? chalk.red : weekly.percentage >= 60 ? chalk.yellow : chalk.green;
|
|
35
|
-
|
|
37
|
+
// total=0 时不显示 (X/Y)
|
|
38
|
+
const weeklySuffix = weekly.total > 0 ? ` (${weekly.used}/${weekly.total})` : '';
|
|
39
|
+
weeklyStr = ` ${chalk.blue('W')} ${weeklyColor(weekly.percentage + '%')}${weeklySuffix}`;
|
|
36
40
|
}
|
|
37
41
|
}
|
|
38
42
|
|
|
39
|
-
|
|
43
|
+
// 到期信息(剩 N 天)— 与 claude-code statusline 对齐
|
|
44
|
+
const expiryStr = expiry ? ` 剩${expiry.daysRemaining}天` : '';
|
|
45
|
+
|
|
46
|
+
return `${color(percentage + '%')}${usedTotalSuffix} ${remainingText}${weeklyStr}${expiryStr}`;
|
|
40
47
|
}
|
|
41
48
|
}
|
|
42
49
|
|