@narumitw/pi-usage 0.60.1 → 0.60.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@narumitw/pi-usage",
3
- "version": "0.60.1",
3
+ "version": "0.60.2",
4
4
  "description": "Pi extension that shows current-account usage and DeepSeek API balance for supported providers.",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/format.ts CHANGED
@@ -367,9 +367,11 @@ function formatMiniMaxReport(lines: string[], report: UsageReport): void {
367
367
  const value =
368
368
  bucket.period === "unlimited"
369
369
  ? "unlimited"
370
- : bucket.limit && bucket.remaining !== undefined
371
- ? `${bucket.remaining} of ${bucket.limit} left · ${percentRemaining(bucket)}%${reset}`
372
- : "unavailable";
370
+ : bucket.unit === "percent" && bucket.remaining !== undefined
371
+ ? `${bucket.remaining}% remaining${reset}`
372
+ : bucket.limit !== undefined && bucket.remaining !== undefined
373
+ ? `${bucket.remaining} of ${bucket.limit} left · ${percentRemaining(bucket)}%${reset}`
374
+ : "unavailable";
373
375
  lines.push(`${`${bucket.label}:`.padEnd(VALUE_COLUMN)}${value}`);
374
376
  }
375
377
  }
@@ -391,7 +393,11 @@ function formatMiniMaxStatusline(report: UsageReport, model?: UsageModel): strin
391
393
  parts.push(`unlimited ${window}`);
392
394
  continue;
393
395
  }
394
- if (!bucket.limit || bucket.remaining === undefined) continue;
396
+ if (bucket.unit === "percent" && bucket.remaining !== undefined) {
397
+ parts.push(`${bucket.remaining}% ${window}`);
398
+ continue;
399
+ }
400
+ if (bucket.limit === undefined || bucket.remaining === undefined) continue;
395
401
  parts.push(`${percentRemaining(bucket)}% ${window}`);
396
402
  }
397
403
  return parts.length > 1 ? parts.join(" ") : undefined;
@@ -406,27 +412,32 @@ function selectMiniMaxGroup(report: UsageReport, model?: UsageModel): string | u
406
412
  ),
407
413
  ];
408
414
  if (groups.length <= 1) return groups[0];
409
- if (model?.provider !== report.providerId) return undefined;
410
- const modelKeys = [model.id, model.name]
411
- .map(normalizeMiniMaxModelKey)
412
- .filter((key): key is string => key !== undefined);
413
- const candidates = groups.map((group) => {
414
- const bucket = report.buckets.find((candidate) => candidate.groupId === group);
415
- const patterns = [bucket?.groupLabel, ...(bucket?.modelKeys ?? []), group]
415
+ if (model && model.provider !== report.providerId) return undefined;
416
+ if (model) {
417
+ const modelKeys = [model.id, model.name]
416
418
  .map(normalizeMiniMaxModelKey)
417
419
  .filter((key): key is string => key !== undefined);
418
- return { group, patterns };
419
- });
420
- const exact = candidates.find(({ patterns }) =>
421
- patterns.some((pattern) => !pattern.includes("*") && modelKeys.includes(pattern)),
422
- );
423
- if (exact) return exact.group;
424
- return candidates.find(({ patterns }) =>
425
- patterns.some(
426
- (pattern) =>
427
- pattern.includes("*") && modelKeys.some((key) => wildcardKeyMatches(pattern, key)),
428
- ),
429
- )?.group;
420
+ const candidates = groups.map((group) => {
421
+ const bucket = report.buckets.find((candidate) => candidate.groupId === group);
422
+ const patterns = [bucket?.groupLabel, ...(bucket?.modelKeys ?? []), group]
423
+ .map(normalizeMiniMaxModelKey)
424
+ .filter((key): key is string => key !== undefined);
425
+ return { group, patterns };
426
+ });
427
+ const exact = candidates.find(({ patterns }) =>
428
+ patterns.some((pattern) => !pattern.includes("*") && modelKeys.includes(pattern)),
429
+ );
430
+ if (exact) return exact.group;
431
+ const wildcard = candidates.find(({ patterns }) =>
432
+ patterns.some(
433
+ (pattern) =>
434
+ pattern.includes("*") && modelKeys.some((key) => wildcardKeyMatches(pattern, key)),
435
+ ),
436
+ );
437
+ if (wildcard) return wildcard.group;
438
+ }
439
+ // Prefer the Coding Plan catch-all over hiding the chip.
440
+ return groups.find((group) => group === "general");
430
441
  }
431
442
 
432
443
  function normalizeMiniMaxModelKey(value: string | undefined): string | undefined {
@@ -152,6 +152,27 @@ function normalizeWindow(row: Record<string, unknown>, fields: WindowFields): Us
152
152
  }
153
153
  const total = nonnegativeInteger(row[fields.totalField], fields.totalField);
154
154
  const count = nonnegativeInteger(row[fields.countField], fields.countField);
155
+ if (total === 0) {
156
+ if (count !== 0) {
157
+ throw new Error(`MiniMax Token Plan ${fields.label} counts were inconsistent.`);
158
+ }
159
+ if (percent === undefined) {
160
+ throw new Error(`MiniMax Token Plan ${fields.label} returned no quota and no percent.`);
161
+ }
162
+ // Token Plan reports remaining_percent as the quota when both counts are 0.
163
+ return {
164
+ id: fields.id,
165
+ label: fields.label,
166
+ groupId: fields.groupId,
167
+ groupLabel: fields.groupLabel,
168
+ remaining: percent,
169
+ used: 100 - percent,
170
+ limit: 0,
171
+ unit: "percent",
172
+ windowMinutes,
173
+ resetsAt,
174
+ };
175
+ }
155
176
  const resolved = resolveQuotaCounts(count, total, percent);
156
177
  if (!resolved) throw new Error(`MiniMax Token Plan ${fields.label} counts were inconsistent.`);
157
178
  return {
package/src/usage.ts CHANGED
@@ -185,16 +185,14 @@ export default function usageExtension(
185
185
  return;
186
186
  }
187
187
  if (outcome.state.status !== "ready") {
188
- if (
189
- safeSetStatus(
190
- ctx,
191
- outcome.state.status === "auth-unavailable"
192
- ? "auth unavailable"
193
- : outcome.state.status === "selection-required"
194
- ? "selection required"
195
- : "usage error",
196
- )
197
- ) {
188
+ const chip =
189
+ outcome.state.status === "auth-unavailable"
190
+ ? "auth unavailable"
191
+ : outcome.state.status === "selection-required"
192
+ ? "selection required"
193
+ : `usage err: ${outcome.state.message.slice(0, 50)}`;
194
+
195
+ if (safeSetStatus(ctx, chip)) {
198
196
  if (shouldSchedule && sessionActive) scheduleStatusRefresh(ctx, model);
199
197
  }
200
198
  return;
@@ -624,7 +622,9 @@ export default function usageExtension(
624
622
  ) => {
625
623
  void refreshCurrentStatus(ctx, model, force).catch((error) => {
626
624
  if (isStaleExtensionContextError(error) || isAbortError(error)) return;
627
- safeSetStatus(ctx, "usage error");
625
+ const message = errorMessage(error);
626
+ console.error("[pi-usage] refresh failed:", message);
627
+ safeSetStatus(ctx, `usage err: ${message.slice(0, 50)}`);
628
628
  });
629
629
  };
630
630