@narumitw/pi-usage 0.60.1 → 0.60.3
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/dist/index.ts +77 -24
- package/dist/index.ts.map +2 -2
- package/package.json +2 -2
- package/src/format.ts +34 -23
- package/src/providers/minimax.ts +21 -0
- package/src/usage-settings-ui.ts +36 -1
- package/src/usage.ts +11 -11
package/dist/index.ts
CHANGED
|
@@ -1254,6 +1254,26 @@ function normalizeWindow(row, fields) {
|
|
|
1254
1254
|
}
|
|
1255
1255
|
const total = nonnegativeInteger(row[fields.totalField], fields.totalField);
|
|
1256
1256
|
const count = nonnegativeInteger(row[fields.countField], fields.countField);
|
|
1257
|
+
if (total === 0) {
|
|
1258
|
+
if (count !== 0) {
|
|
1259
|
+
throw new Error(`MiniMax Token Plan ${fields.label} counts were inconsistent.`);
|
|
1260
|
+
}
|
|
1261
|
+
if (percent === void 0) {
|
|
1262
|
+
throw new Error(`MiniMax Token Plan ${fields.label} returned no quota and no percent.`);
|
|
1263
|
+
}
|
|
1264
|
+
return {
|
|
1265
|
+
id: fields.id,
|
|
1266
|
+
label: fields.label,
|
|
1267
|
+
groupId: fields.groupId,
|
|
1268
|
+
groupLabel: fields.groupLabel,
|
|
1269
|
+
remaining: percent,
|
|
1270
|
+
used: 100 - percent,
|
|
1271
|
+
limit: 0,
|
|
1272
|
+
unit: "percent",
|
|
1273
|
+
windowMinutes,
|
|
1274
|
+
resetsAt
|
|
1275
|
+
};
|
|
1276
|
+
}
|
|
1257
1277
|
const resolved = resolveQuotaCounts(count, total, percent);
|
|
1258
1278
|
if (!resolved) throw new Error(`MiniMax Token Plan ${fields.label} counts were inconsistent.`);
|
|
1259
1279
|
return {
|
|
@@ -3418,7 +3438,7 @@ function formatMiniMaxReport(lines, report2) {
|
|
|
3418
3438
|
if (bucket.groupId !== previousGroup) lines.push(`${bucket.groupLabel ?? "Token Plan"}:`);
|
|
3419
3439
|
previousGroup = bucket.groupId;
|
|
3420
3440
|
const reset = bucket.resetsAt ? ` (resets ${formatReset(bucket.resetsAt)})` : "";
|
|
3421
|
-
const value = bucket.period === "unlimited" ? "unlimited" : bucket.limit && bucket.remaining !== void 0 ? `${bucket.remaining} of ${bucket.limit} left \xB7 ${percentRemaining(bucket)}%${reset}` : "unavailable";
|
|
3441
|
+
const value = bucket.period === "unlimited" ? "unlimited" : bucket.unit === "percent" && bucket.remaining !== void 0 ? `${bucket.remaining}% remaining${reset}` : bucket.limit !== void 0 && bucket.remaining !== void 0 ? `${bucket.remaining} of ${bucket.limit} left \xB7 ${percentRemaining(bucket)}%${reset}` : "unavailable";
|
|
3422
3442
|
lines.push(`${`${bucket.label}:`.padEnd(VALUE_COLUMN)}${value}`);
|
|
3423
3443
|
}
|
|
3424
3444
|
}
|
|
@@ -3439,7 +3459,11 @@ function formatMiniMaxStatusline(report2, model) {
|
|
|
3439
3459
|
parts.push(`unlimited ${window}`);
|
|
3440
3460
|
continue;
|
|
3441
3461
|
}
|
|
3442
|
-
if (
|
|
3462
|
+
if (bucket.unit === "percent" && bucket.remaining !== void 0) {
|
|
3463
|
+
parts.push(`${bucket.remaining}% ${window}`);
|
|
3464
|
+
continue;
|
|
3465
|
+
}
|
|
3466
|
+
if (bucket.limit === void 0 || bucket.remaining === void 0) continue;
|
|
3443
3467
|
parts.push(`${percentRemaining(bucket)}% ${window}`);
|
|
3444
3468
|
}
|
|
3445
3469
|
return parts.length > 1 ? parts.join(" ") : void 0;
|
|
@@ -3451,22 +3475,26 @@ function selectMiniMaxGroup(report2, model) {
|
|
|
3451
3475
|
)
|
|
3452
3476
|
];
|
|
3453
3477
|
if (groups.length <= 1) return groups[0];
|
|
3454
|
-
if (model
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
const
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
(
|
|
3468
|
-
|
|
3469
|
-
|
|
3478
|
+
if (model && model.provider !== report2.providerId) return void 0;
|
|
3479
|
+
if (model) {
|
|
3480
|
+
const modelKeys = [model.id, model.name].map(normalizeMiniMaxModelKey).filter((key) => key !== void 0);
|
|
3481
|
+
const candidates = groups.map((group) => {
|
|
3482
|
+
const bucket = report2.buckets.find((candidate) => candidate.groupId === group);
|
|
3483
|
+
const patterns = [bucket?.groupLabel, ...bucket?.modelKeys ?? [], group].map(normalizeMiniMaxModelKey).filter((key) => key !== void 0);
|
|
3484
|
+
return { group, patterns };
|
|
3485
|
+
});
|
|
3486
|
+
const exact = candidates.find(
|
|
3487
|
+
({ patterns }) => patterns.some((pattern) => !pattern.includes("*") && modelKeys.includes(pattern))
|
|
3488
|
+
);
|
|
3489
|
+
if (exact) return exact.group;
|
|
3490
|
+
const wildcard = candidates.find(
|
|
3491
|
+
({ patterns }) => patterns.some(
|
|
3492
|
+
(pattern) => pattern.includes("*") && modelKeys.some((key) => wildcardKeyMatches(pattern, key))
|
|
3493
|
+
)
|
|
3494
|
+
);
|
|
3495
|
+
if (wildcard) return wildcard.group;
|
|
3496
|
+
}
|
|
3497
|
+
return groups.find((group) => group === "general");
|
|
3470
3498
|
}
|
|
3471
3499
|
function normalizeMiniMaxModelKey(value) {
|
|
3472
3500
|
const key = value?.toLowerCase().replace(/[^a-z0-9*]+/gu, "");
|
|
@@ -4177,6 +4205,7 @@ function isTimeoutError(error) {
|
|
|
4177
4205
|
}
|
|
4178
4206
|
|
|
4179
4207
|
// src/usage-settings-ui.ts
|
|
4208
|
+
import { stripVTControlCharacters } from "node:util";
|
|
4180
4209
|
import {
|
|
4181
4210
|
getSettingsListTheme
|
|
4182
4211
|
} from "@earendil-works/pi-coding-agent";
|
|
@@ -4189,11 +4218,25 @@ import {
|
|
|
4189
4218
|
} from "@earendil-works/pi-tui";
|
|
4190
4219
|
var OFF = "Off";
|
|
4191
4220
|
var ON = "On";
|
|
4221
|
+
function fitSettingsRows(lines, maxRows) {
|
|
4222
|
+
if (lines.length <= maxRows) return lines;
|
|
4223
|
+
const content = lines.filter((line) => stripVTControlCharacters(line).trim().length > 0);
|
|
4224
|
+
if (content.length <= maxRows) return content;
|
|
4225
|
+
const selectedIndex = content.findIndex(
|
|
4226
|
+
(line) => /^[→›]\s/u.test(stripVTControlCharacters(line))
|
|
4227
|
+
);
|
|
4228
|
+
if (selectedIndex < 0) return content.slice(0, maxRows);
|
|
4229
|
+
return content.map((line, index) => ({ index, line })).sort(
|
|
4230
|
+
(left, right) => Math.abs(left.index - selectedIndex) - Math.abs(right.index - selectedIndex) || left.index - right.index
|
|
4231
|
+
).slice(0, maxRows).sort((left, right) => left.index - right.index).map(({ line }) => line);
|
|
4232
|
+
}
|
|
4192
4233
|
async function showUsageSettings(ctx, settingsRuntime, parentSignal, isCurrent, onApplied) {
|
|
4193
4234
|
if (ctx.mode !== "tui") {
|
|
4194
4235
|
if (ctx.hasUI) ctx.ui.notify(`Edit settings manually: ${settingsRuntime.get().path}`, "info");
|
|
4195
4236
|
return false;
|
|
4196
4237
|
}
|
|
4238
|
+
const { HorizontalRule } = await import("@narumitw/pi-tui-kit");
|
|
4239
|
+
if (parentSignal.aborted || !isCurrent()) return false;
|
|
4197
4240
|
return await ctx.ui.custom((tui, theme, _keybindings, done) => {
|
|
4198
4241
|
const localController = new AbortController();
|
|
4199
4242
|
const signal = AbortSignal.any([parentSignal, localController.signal]);
|
|
@@ -4218,6 +4261,7 @@ async function showUsageSettings(ctx, settingsRuntime, parentSignal, isCurrent,
|
|
|
4218
4261
|
}
|
|
4219
4262
|
];
|
|
4220
4263
|
const container = new Container();
|
|
4264
|
+
const rule = new HorizontalRule({ ruleStyle: (text) => theme.fg("border", text) });
|
|
4221
4265
|
container.addChild(new Text(theme.fg("accent", theme.bold("pi-usage Settings")), 1, 1));
|
|
4222
4266
|
let settingsList;
|
|
4223
4267
|
const cancel = () => {
|
|
@@ -4268,7 +4312,16 @@ async function showUsageSettings(ctx, settingsRuntime, parentSignal, isCurrent,
|
|
|
4268
4312
|
container.addChild(settingsList);
|
|
4269
4313
|
parentSignal.addEventListener("abort", cancel, { once: true });
|
|
4270
4314
|
return {
|
|
4271
|
-
render
|
|
4315
|
+
render(width) {
|
|
4316
|
+
const content = container.render(width);
|
|
4317
|
+
const terminalRows = Number.isFinite(tui.terminal?.rows) ? Math.floor(tui.terminal.rows) : 24;
|
|
4318
|
+
const availableRows = Math.max(1, terminalRows - 3);
|
|
4319
|
+
if (content.length + 2 > availableRows) {
|
|
4320
|
+
return fitSettingsRows(content, availableRows);
|
|
4321
|
+
}
|
|
4322
|
+
const [ruleLine = ""] = rule.render(width);
|
|
4323
|
+
return [ruleLine, ...content, ruleLine];
|
|
4324
|
+
},
|
|
4272
4325
|
invalidate: () => container.invalidate(),
|
|
4273
4326
|
handleInput(data) {
|
|
4274
4327
|
if (closing) return;
|
|
@@ -4370,10 +4423,8 @@ function usageExtension(pi, dependencies = {}) {
|
|
|
4370
4423
|
return;
|
|
4371
4424
|
}
|
|
4372
4425
|
if (outcome.state.status !== "ready") {
|
|
4373
|
-
|
|
4374
|
-
|
|
4375
|
-
outcome.state.status === "auth-unavailable" ? "auth unavailable" : outcome.state.status === "selection-required" ? "selection required" : "usage error"
|
|
4376
|
-
)) {
|
|
4426
|
+
const chip = outcome.state.status === "auth-unavailable" ? "auth unavailable" : outcome.state.status === "selection-required" ? "selection required" : `usage err: ${outcome.state.message.slice(0, 50)}`;
|
|
4427
|
+
if (safeSetStatus(ctx, chip)) {
|
|
4377
4428
|
if (shouldSchedule && sessionActive) scheduleStatusRefresh(ctx, model);
|
|
4378
4429
|
}
|
|
4379
4430
|
return;
|
|
@@ -4737,7 +4788,9 @@ function usageExtension(pi, dependencies = {}) {
|
|
|
4737
4788
|
const startStatusRefresh = (ctx, model, force) => {
|
|
4738
4789
|
void refreshCurrentStatus(ctx, model, force).catch((error) => {
|
|
4739
4790
|
if (isStaleExtensionContextError(error) || isAbortError3(error)) return;
|
|
4740
|
-
|
|
4791
|
+
const message = errorMessage(error);
|
|
4792
|
+
console.error("[pi-usage] refresh failed:", message);
|
|
4793
|
+
safeSetStatus(ctx, `usage err: ${message.slice(0, 50)}`);
|
|
4741
4794
|
});
|
|
4742
4795
|
};
|
|
4743
4796
|
const runMenuOperation = async (ctx, label, parentSignal, operation, cancellable = true) => {
|