minimax-status 1.1.10 → 1.1.12

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 CHANGED
@@ -5,19 +5,19 @@
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
6
  [![VSCode Extension](https://img.shields.io/badge/VSCode-MiniMax-blue?style=flat-square)](https://marketplace.visualstudio.com/items?itemName=JochenYang.minimax-status-vscode)
7
7
 
8
- MiniMax coding-plan 使用状态监控工具,支持 CLI 命令和 Claude Code 状态栏集成。
8
+ MiniMax Token-Plan 使用状态监控工具,支持 CLI 命令和 Claude Code 状态栏集成。
9
9
 
10
10
  ## 版本
11
11
 
12
12
  | 插件 | 版本 | 安装方式 |
13
13
  |------|------|----------|
14
- | **CLI** | 1.1.9 | `npm install -g minimax-status` |
15
- | **VSCode** | 1.2.6 | [VSCode Marketplace](https://marketplace.visualstudio.com/items?itemName=JochenYang.minimax-status-vscode) 或 [下载 VSIX](https://github.com/JochenYang/minimax-status/releases) |
14
+ | **CLI** | 1.1.11 | `npm install -g minimax-status` |
15
+ | **VSCode** | 1.2.7 | [VSCode Marketplace](https://marketplace.visualstudio.com/items?itemName=JochenYang.minimax-status-vscode) 或 [下载 VSIX](https://github.com/JochenYang/minimax-status/releases) |
16
16
  | **OpenClaw** | - | 参考 `openclaw/minimax-usage/` 目录 |
17
17
 
18
18
  ## 特性
19
19
 
20
- - ✅ **实时状态监控**: 显示 MiniMax coding-plan 使用额度、剩余次数、重置时间
20
+ - ✅ **实时状态监控**: 显示 MiniMax Token-Plan 使用额度、剩余次数、重置时间
21
21
  - ✅ **上下文窗口跟踪**: 智能解析转录文件,准确显示当前会话的上下文使用量
22
22
  - ✅ **多种显示模式**: 详细模式、紧凑模式、持续状态栏
23
23
  - ✅ **Claude Code 集成**: 可在 Claude Code 底部状态栏显示
@@ -413,4 +413,4 @@ MIT License - 详见 [LICENSE](LICENSE) 文件
413
413
 
414
414
  ---
415
415
 
416
- **注意**: 本工具仅用于监控 MiniMax coding-plan 用量使用状态,不存储或传输任何用户数据。
416
+ **注意**: 本工具仅用于监控 MiniMax Token-Plan 用量使用状态,不存储或传输任何用户数据。
package/cli/api.js CHANGED
@@ -173,10 +173,11 @@ class MinimaxAPI {
173
173
 
174
174
  /**
175
175
  * Fetch all billing records with pagination
176
- * @param {number} maxPages - Maximum number of pages to fetch
176
+ * @param {number} maxPages - Maximum number of pages to fetch (default 100)
177
+ * @param {number} minStartTime - Optional: stop fetching when records are older than this time (ms)
177
178
  * @returns {Promise<Array>} All billing records
178
179
  */
179
- async getAllBillingRecords(maxPages = 10) {
180
+ async getAllBillingRecords(maxPages = 100, minStartTime = 0) {
180
181
  const allRecords = [];
181
182
 
182
183
  for (let page = 1; page <= maxPages; page++) {
@@ -190,6 +191,15 @@ class MinimaxAPI {
190
191
 
191
192
  allRecords.push(...records);
192
193
 
194
+ // 如果传入了时间范围,检查是否需要继续获取
195
+ if (minStartTime > 0) {
196
+ const lastRecord = records[records.length - 1];
197
+ const lastRecordTime = (lastRecord.created_at || 0) * 1000;
198
+ if (lastRecordTime < minStartTime) {
199
+ break;
200
+ }
201
+ }
202
+
193
203
  if (records.length < 100) {
194
204
  break;
195
205
  }
@@ -302,7 +312,7 @@ class MinimaxAPI {
302
312
  // Calculate weekly usage data
303
313
  const weeklyUsed = modelData.current_weekly_total_count - modelData.current_weekly_usage_count;
304
314
  const weeklyTotal = modelData.current_weekly_total_count;
305
- const weeklyPercentage = Math.floor((weeklyUsed / weeklyTotal) * 100);
315
+ const weeklyPercentage = weeklyTotal > 0 ? Math.floor((weeklyUsed / weeklyTotal) * 100) : 0;
306
316
  const weeklyRemainingMs = modelData.weekly_remains_time;
307
317
  const weeklyDays = Math.floor(weeklyRemainingMs / (1000 * 60 * 60 * 24));
308
318
  const weeklyHours = Math.floor((weeklyRemainingMs % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
@@ -383,6 +393,7 @@ class MinimaxAPI {
383
393
  percentage: weeklyPercentage,
384
394
  days: weeklyDays,
385
395
  hours: weeklyHours,
396
+ unlimited: weeklyTotal === 0,
386
397
  text: weeklyDays > 0
387
398
  ? `${weeklyDays} 天 ${weeklyHours} 小时后重置`
388
399
  : `${weeklyHours} 小时后重置`,
@@ -391,6 +402,41 @@ class MinimaxAPI {
391
402
  expiry: expiryInfo,
392
403
  };
393
404
  }
405
+
406
+ /**
407
+ * Parse all models from API data
408
+ * @param {Object} apiData - Raw API response
409
+ * @returns {Array} Array of model usage data
410
+ */
411
+ parseAllModels(apiData) {
412
+ if (!apiData.model_remains || apiData.model_remains.length === 0) {
413
+ return [];
414
+ }
415
+
416
+ return apiData.model_remains.map(modelData => {
417
+ const totalCount = modelData.current_interval_total_count;
418
+ const remainingCount = modelData.current_interval_usage_count;
419
+ const usedCount = totalCount - remainingCount;
420
+ const usedPercentage = totalCount > 0 ? Math.round((usedCount / totalCount) * 100) : 0;
421
+
422
+ // Weekly data
423
+ const weeklyTotal = modelData.current_weekly_total_count || 0;
424
+ const weeklyUsed = weeklyTotal > 0 ? (modelData.current_weekly_total_count - modelData.current_weekly_usage_count) : 0;
425
+ const weeklyPercentage = weeklyTotal > 0 ? Math.floor((weeklyUsed / weeklyTotal) * 100) : 0;
426
+
427
+ return {
428
+ name: modelData.model_name,
429
+ used: usedCount,
430
+ remaining: remainingCount,
431
+ total: totalCount,
432
+ percentage: usedPercentage,
433
+ unlimited: weeklyTotal === 0,
434
+ weeklyPercentage,
435
+ weeklyTotal,
436
+ weeklyRemainingCount: modelData.current_weekly_usage_count || 0,
437
+ };
438
+ });
439
+ }
394
440
  }
395
441
 
396
442
  module.exports = MinimaxAPI;
package/cli/index.js CHANGED
@@ -118,24 +118,12 @@ program
118
118
  // 获取账单数据用于消耗统计
119
119
  let usageStats = null;
120
120
  try {
121
- const billingRecords = await api.getAllBillingRecords(10);
121
+ // 按自然月统计当月消耗
122
+ const now = new Date();
123
+ const monthStart = new Date(now.getFullYear(), now.getMonth(), 1, 0, 0, 0, 0).getTime();
124
+ const billingRecords = await api.getAllBillingRecords(100, monthStart);
122
125
  if (billingRecords.length > 0) {
123
- // 计算套餐开始时间:到期时间往前推1个月
124
- let planStartTime = 0;
125
- if (subscriptionData &&
126
- subscriptionData.current_subscribe &&
127
- subscriptionData.current_subscribe.current_subscribe_end_time) {
128
- const expiryDateStr = subscriptionData.current_subscribe.current_subscribe_end_time;
129
- const [month, day, year] = expiryDateStr.split('/').map(Number);
130
- planStartTime = new Date(year, month - 2, day).getTime();
131
- }
132
-
133
- const now = Date.now();
134
- usageStats = api.calculateUsageStats(
135
- billingRecords,
136
- planStartTime > 0 ? planStartTime : 0,
137
- now
138
- );
126
+ usageStats = api.calculateUsageStats(billingRecords, monthStart, now.getTime());
139
127
  }
140
128
  } catch (billingError) {
141
129
  // 账单数据获取失败不影响主要功能
@@ -143,6 +131,7 @@ program
143
131
  }
144
132
 
145
133
  const statusBar = new StatusBar(usageData, usageStats, api);
134
+ const allModels = api.parseAllModels(apiData);
146
135
 
147
136
  spinner.succeed("状态获取成功");
148
137
 
@@ -150,6 +139,7 @@ program
150
139
  console.log(statusBar.renderCompact());
151
140
  } else {
152
141
  console.log("\n" + statusBar.render() + "\n");
142
+ console.log(StatusBar.renderAllModels(allModels) + "\n");
153
143
  }
154
144
 
155
145
  if (options.watch) {
@@ -176,10 +166,12 @@ program
176
166
  api.getSubscriptionDetails(),
177
167
  ]);
178
168
  const usageData = api.parseUsageData(apiData, subscriptionData);
169
+ const allModels = api.parseAllModels(apiData);
179
170
  const statusBar = new StatusBar(usageData);
180
171
 
181
172
  spinner.succeed("状态获取成功");
182
173
  console.log("\n" + statusBar.render() + "\n");
174
+ console.log(StatusBar.renderAllModels(allModels) + "\n");
183
175
  } catch (error) {
184
176
  spinner.fail(chalk.red("获取状态失败"));
185
177
  console.error(chalk.red(`错误: ${error.message}`));
@@ -677,11 +669,15 @@ program
677
669
  // 使用量 - 进度条风格 (显示次数)
678
670
  const usageBar = coloredBar(usage.percentage);
679
671
  const usageColor = usage.percentage >= 85 ? chalk.red : usage.percentage >= 60 ? chalk.yellow : chalk.green;
680
- let usageLine = `${chalk.yellow('Usage')} ${usageBar} ${usageColor(usage.percentage + '%')} (${usage.remaining}/${usage.total})`;
672
+ let usageLine = `${usageBar} ${usageColor(usage.percentage + '%')} (${usage.remaining}/${usage.total})`;
681
673
  // 周用量紧跟在 usage 后面
682
674
  if (weekly) {
683
- const weeklyColor = weekly.percentage >= 85 ? chalk.red : weekly.percentage >= 60 ? chalk.yellow : chalk.green;
684
- usageLine += ` ${chalk.gray('·')} ${chalk.blue('W')} ${weeklyColor(weekly.percentage + '%')}`;
675
+ if (weekly.unlimited) {
676
+ usageLine += ` ${chalk.gray('·')} ${chalk.blue('W')} ♾️`;
677
+ } else {
678
+ const weeklyColor = weekly.percentage >= 85 ? chalk.red : weekly.percentage >= 60 ? chalk.yellow : chalk.green;
679
+ usageLine += ` ${chalk.gray('·')} ${chalk.blue('W')} ${weeklyColor(weekly.percentage + '%')}`;
680
+ }
685
681
  }
686
682
  parts.push(usageLine);
687
683
 
package/cli/renderer.js CHANGED
@@ -123,11 +123,15 @@ class Renderer {
123
123
  const filled = Math.round((usagePercentage / 100) * 10);
124
124
  const empty = 10 - filled;
125
125
  const usageBar = usageColor('█'.repeat(filled) + '\x1b[2m' + '░'.repeat(empty) + '\x1b[0m');
126
- let usageLine = `${chalk.yellow('Usage')} ${usageBar} ${usageColor(usagePercentage + '%')} (${usage.remaining}/${usage.total})`;
126
+ let usageLine = `${usageBar} ${usageColor(usagePercentage + '%')} (${usage.remaining}/${usage.total})`;
127
127
  // 周用量紧跟在 usage 后面
128
128
  if (weekly) {
129
- const weeklyColor = this.getStatusColor(weekly.percentage);
130
- usageLine += ` ${chalk.gray('·')} ${chalk.blue('W')} ${weeklyColor(weekly.percentage + '%')}`;
129
+ if (weekly.unlimited) {
130
+ usageLine += ` ${chalk.gray('·')} ${chalk.blue('W')} ♾️`;
131
+ } else {
132
+ const weeklyColor = this.getStatusColor(weekly.percentage);
133
+ usageLine += ` ${chalk.gray('·')} ${chalk.blue('W')} ${weeklyColor(weekly.percentage + '%')}`;
134
+ }
131
135
  }
132
136
  parts.push(usageLine);
133
137
 
package/cli/status.js CHANGED
@@ -49,7 +49,7 @@ class StatusBar {
49
49
 
50
50
  lines.push(formatLine('昨日消耗: ', this.usageStats.lastDayUsage));
51
51
  lines.push(formatLine('近7天消耗: ', this.usageStats.weeklyUsage));
52
- lines.push(formatLine('套餐总消耗: ', this.usageStats.planTotalUsage));
52
+ lines.push(formatLine('当月消耗: ', this.usageStats.planTotalUsage));
53
53
 
54
54
  return lines.join('\n');
55
55
  }
@@ -113,15 +113,21 @@ class StatusBar {
113
113
  // 周用量(如果有数据)
114
114
  if (weekly) {
115
115
  contentLines.push('');
116
- const weeklyPercent = weekly.percentage;
117
- const weeklyColor = weeklyPercent >= 85 ? chalk.red : weeklyPercent >= 60 ? chalk.yellow : chalk.green;
118
- const weeklyProgress = this.createProgressBar(
119
- Math.floor((weeklyPercent / 100) * 15),
120
- 15 - Math.floor((weeklyPercent / 100) * 15),
121
- weeklyPercent
122
- );
123
- contentLines.push(`${chalk.cyan('周用量:')} ${weeklyColor(weeklyProgress)} ${weeklyColor(weekly.percentage + '%')} (${weekly.used}/${weekly.total})`);
124
- contentLines.push(`${chalk.dim(' 重置:')} ${weekly.text}`);
116
+ if (weekly.unlimited) {
117
+ // 不受限制
118
+ contentLines.push(`${chalk.cyan('周限额:')} ${chalk.green('不受限制')}`);
119
+ } else {
120
+ // 有限制,显示具体数据
121
+ const weeklyPercent = weekly.percentage;
122
+ const weeklyColor = weeklyPercent >= 85 ? chalk.red : weeklyPercent >= 60 ? chalk.yellow : chalk.green;
123
+ const weeklyProgress = this.createProgressBar(
124
+ Math.floor((weeklyPercent / 100) * 15),
125
+ 15 - Math.floor((weeklyPercent / 100) * 15),
126
+ weeklyPercent
127
+ );
128
+ contentLines.push(`${chalk.cyan('周限额:')} ${weeklyColor(weeklyProgress)} ${weeklyColor(weekly.percentage + '%')} (${weekly.used}/${weekly.total})`);
129
+ contentLines.push(`${chalk.dim(' 重置:')} ${weekly.text}`);
130
+ }
125
131
  }
126
132
 
127
133
  // 添加到期行(如果可用)
@@ -216,6 +222,42 @@ class StatusBar {
216
222
 
217
223
  return `${color('●')} ${modelName} ${usage.percentage}% ${chalk.dim(`(${usage.remaining}/${usage.total})`)} ${chalk.gray('•')} ${remaining.text} ${chalk.gray('•')} ${status}${expiryInfo}`;
218
224
  }
225
+
226
+ // 渲染所有模型的额度
227
+ static renderAllModels(models) {
228
+ if (!models || models.length === 0) {
229
+ return '';
230
+ }
231
+
232
+ const lines = [];
233
+ lines.push('');
234
+ lines.push(chalk.bold('📋 所有模型额度'));
235
+
236
+ // 表头
237
+ lines.push(chalk.gray('─'.repeat(55)));
238
+ lines.push(`│ ${chalk.cyan('模型').padEnd(30)} ${chalk.cyan('已用/总额').padEnd(15)} ${chalk.cyan('状态')}`);
239
+ lines.push(chalk.gray('─'.repeat(55)));
240
+
241
+ for (const model of models) {
242
+ // 颜色基于百分比
243
+ let color;
244
+ if (model.percentage >= 85) {
245
+ color = chalk.red;
246
+ } else if (model.percentage >= 60) {
247
+ color = chalk.yellow;
248
+ } else {
249
+ color = chalk.green;
250
+ }
251
+
252
+ const status = model.percentage >= 85 ? '⚠ 即将用完' : model.percentage >= 60 ? '⚡ 注意' : '✓ 正常';
253
+ const name = model.name.length > 28 ? model.name.substring(0, 25) + '...' : model.name;
254
+
255
+ lines.push(`│ ${name.padEnd(30)} ${color(`${model.used}/${model.total} (${model.percentage}%)`).padEnd(15)} ${color(status)}`);
256
+ }
257
+
258
+ lines.push(chalk.gray('─'.repeat(55)));
259
+ return lines.join('\n');
260
+ }
219
261
  }
220
262
 
221
263
  module.exports = StatusBar;
package/cli/statusbar.js CHANGED
@@ -10,7 +10,7 @@ class StatusBar {
10
10
  }
11
11
 
12
12
  render() {
13
- const { usage, remaining, modelName } = this.data;
13
+ const { usage, remaining, modelName, weekly } = this.data;
14
14
  const percentage = usage.percentage;
15
15
 
16
16
  // 基于已使用百分比:使用越多越危险
@@ -26,7 +26,17 @@ class StatusBar {
26
26
  ? `${remaining.hours}h${remaining.minutes}m`
27
27
  : `${remaining.minutes}m`;
28
28
 
29
- return `${color('●')} ${modelName} ${color(percentage + '%')} (${usage.used}/${usage.total}) ${remainingText} ${statusIcon}`;
29
+ let weeklyStr = '';
30
+ if (weekly) {
31
+ if (weekly.unlimited) {
32
+ weeklyStr = ` ${chalk.blue('W')} ♾️`;
33
+ } else {
34
+ const weeklyColor = weekly.percentage >= 85 ? chalk.red : weekly.percentage >= 60 ? chalk.yellow : chalk.green;
35
+ weeklyStr = ` ${chalk.blue('W')} ${weeklyColor(weekly.percentage + '%')}`;
36
+ }
37
+ }
38
+
39
+ return `${color('●')} ${modelName} ${color(percentage + '%')} (${usage.used}/${usage.total}) ${remainingText}${weeklyStr} ${statusIcon}`;
30
40
  }
31
41
  }
32
42
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "minimax-status",
3
- "version": "1.1.10",
3
+ "version": "1.1.12",
4
4
  "description": "MiniMax Claude Code 使用状态监控工具",
5
5
  "bin": {
6
6
  "minimax-status": "cli/index.js",