quotacap 0.0.11 → 0.0.13
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/format/table.js
CHANGED
|
@@ -18,14 +18,15 @@ export function renderQuotasTable(quotas, advisories = []) {
|
|
|
18
18
|
const daysLeft = a?.daysLeft != null ? a.daysLeft.toFixed(1) : "—";
|
|
19
19
|
const ideal = a?.idealRate != null ? `${Math.round(a.idealRate)}%/day` : "—";
|
|
20
20
|
const burn = a?.burnMeasured ? `${a.burnRate.toFixed(1)}%/day` : "—";
|
|
21
|
-
//
|
|
22
|
-
//
|
|
23
|
-
|
|
21
|
+
// Astral-plane emoji (U+1F000+): naive wcwidth counts them as 2 cells and
|
|
22
|
+
// they paint 2, so count equals paint in every renderer — colored AND
|
|
23
|
+
// aligned, unlike BMP emoji (✅/⚠️) whose +1 gap shifts the pipes.
|
|
24
|
+
const icon = a?.status === "at risk" ? "🔴" : a != null ? "🟢" : "—";
|
|
24
25
|
const waste = a?.wastePct != null ? `${Math.round(a.wastePct)}%` : "—";
|
|
25
|
-
return `| ${q.provider} | ${used}% | ${100 - used}% | ${resets} | ${daysLeft} | ${ideal} | ${burn} | ${
|
|
26
|
+
return `| ${q.provider} | ${used}% | ${100 - used}% | ${resets} | ${daysLeft} | ${ideal} | ${burn} | ${waste} | ${icon} |`;
|
|
26
27
|
});
|
|
27
28
|
return [
|
|
28
|
-
"| Provider | Used | Remaining | Resets | Days left | Ideal daily burn | Burn rate |
|
|
29
|
+
"| Provider | Used | Remaining | Resets | Days left | Ideal daily burn | Burn rate | Waste if unused | Status |",
|
|
29
30
|
"|---|---|---|---|---|---|---|---|---|",
|
|
30
31
|
...rows,
|
|
31
32
|
].join("\n");
|
package/dist/src/format/table.js
CHANGED
|
@@ -18,14 +18,15 @@ export function renderQuotasTable(quotas, advisories = []) {
|
|
|
18
18
|
const daysLeft = a?.daysLeft != null ? a.daysLeft.toFixed(1) : "—";
|
|
19
19
|
const ideal = a?.idealRate != null ? `${Math.round(a.idealRate)}%/day` : "—";
|
|
20
20
|
const burn = a?.burnMeasured ? `${a.burnRate.toFixed(1)}%/day` : "—";
|
|
21
|
-
//
|
|
22
|
-
//
|
|
23
|
-
|
|
21
|
+
// Astral-plane emoji (U+1F000+): naive wcwidth counts them as 2 cells and
|
|
22
|
+
// they paint 2, so count equals paint in every renderer — colored AND
|
|
23
|
+
// aligned, unlike BMP emoji (✅/⚠️) whose +1 gap shifts the pipes.
|
|
24
|
+
const icon = a?.status === "at risk" ? "🔴" : a != null ? "🟢" : "—";
|
|
24
25
|
const waste = a?.wastePct != null ? `${Math.round(a.wastePct)}%` : "—";
|
|
25
|
-
return `| ${q.provider} | ${used}% | ${100 - used}% | ${resets} | ${daysLeft} | ${ideal} | ${burn} | ${
|
|
26
|
+
return `| ${q.provider} | ${used}% | ${100 - used}% | ${resets} | ${daysLeft} | ${ideal} | ${burn} | ${waste} | ${icon} |`;
|
|
26
27
|
});
|
|
27
28
|
return [
|
|
28
|
-
"| Provider | Used | Remaining | Resets | Days left | Ideal daily burn | Burn rate |
|
|
29
|
+
"| Provider | Used | Remaining | Resets | Days left | Ideal daily burn | Burn rate | Waste if unused | Status |",
|
|
29
30
|
"|---|---|---|---|---|---|---|---|---|",
|
|
30
31
|
...rows,
|
|
31
32
|
].join("\n");
|
package/dist/src/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// generated by scripts/build-embed.mjs — do not edit
|
|
2
|
-
export const VERSION = "0.0.
|
|
2
|
+
export const VERSION = "0.0.13";
|
|
@@ -11,9 +11,9 @@ describe("format table", () => {
|
|
|
11
11
|
{ provider: "claude", wastePct: 52.9, daysLeft: 5.5, idealRate: 11.6, burnRate: 2, burnMeasured: false, status: "on track" },
|
|
12
12
|
];
|
|
13
13
|
const table = renderQuotasTable(quotas, advisories);
|
|
14
|
-
expect(table).toMatch(/\| Provider \| Used \| Remaining \| Resets \| Days left \| Ideal daily burn \| Burn rate \|
|
|
15
|
-
expect(table).toMatch(/\| kimi \| 16% \| 84% \|.*\| 3.0 \| 28%\/day \| 40.0%\/day \|
|
|
16
|
-
expect(table).toMatch(/\| claude \| 37% \| 63% \|.*\| 5.5 \| 12%\/day \| — \|
|
|
14
|
+
expect(table).toMatch(/\| Provider \| Used \| Remaining \| Resets \| Days left \| Ideal daily burn \| Burn rate \| Waste if unused \| Status \|/);
|
|
15
|
+
expect(table).toMatch(/\| kimi \| 16% \| 84% \|.*\| 3.0 \| 28%\/day \| 40.0%\/day \| 78% \| 🔴 \|/);
|
|
16
|
+
expect(table).toMatch(/\| claude \| 37% \| 63% \|.*\| 5.5 \| 12%\/day \| — \| 53% \| 🟢 \|/);
|
|
17
17
|
});
|
|
18
18
|
it("renders quota-only rows with placeholders when no advisories exist", () => {
|
|
19
19
|
const quotas = [{ provider: "kimi", usedPct: 16, resetsAt: "2026-09-01T09:02:00+10:00" }];
|
|
@@ -27,4 +27,31 @@ describe("format table", () => {
|
|
|
27
27
|
expect(table).toMatch(/Sept?[^|]*2026/);
|
|
28
28
|
expect(table).not.toMatch(/9\/1\/2026/);
|
|
29
29
|
});
|
|
30
|
+
it("keeps every pipe aligned under both naive and emoji-aware width models", () => {
|
|
31
|
+
const quotas = [
|
|
32
|
+
{ provider: "kimi", usedPct: 16, resetsAt: "2026-09-01T09:02:00+10:00" },
|
|
33
|
+
{ provider: "claude", usedPct: 37, resetsAt: "2026-09-03T21:00:00+10:00" },
|
|
34
|
+
];
|
|
35
|
+
const advisories = [
|
|
36
|
+
{ provider: "kimi", wastePct: 78.0, daysLeft: 3.0, idealRate: 28.0, burnRate: 40, burnMeasured: true, status: "at risk" },
|
|
37
|
+
{ provider: "claude", wastePct: 52.9, daysLeft: 5.5, idealRate: 11.6, burnRate: 2, burnMeasured: false, status: "on track" },
|
|
38
|
+
];
|
|
39
|
+
const table = renderQuotasTable(quotas, advisories);
|
|
40
|
+
const lines = table.split("\n");
|
|
41
|
+
// Paint is terminal reality; the naive width model is the strictest
|
|
42
|
+
// count. Any cell where paint > naive-count shifts that row's pipes.
|
|
43
|
+
const paintWidth = (ch) => {
|
|
44
|
+
const c = ch.codePointAt(0);
|
|
45
|
+
return c >= 0x10000 || (c >= 0x2600 && c <= 0x27BF) ? 2 : 1;
|
|
46
|
+
};
|
|
47
|
+
const naiveWidth = (ch) => (ch.codePointAt(0) >= 0x10000 ? 2 : 1);
|
|
48
|
+
for (const line of lines) {
|
|
49
|
+
const cells = line.split("|").slice(1, -1);
|
|
50
|
+
for (const cell of cells) {
|
|
51
|
+
const painted = [...cell].reduce((w, ch) => w + paintWidth(ch), 0);
|
|
52
|
+
const counted = [...cell].reduce((w, ch) => w + naiveWidth(ch), 0);
|
|
53
|
+
expect(painted).toBe(counted);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
});
|
|
30
57
|
});
|
package/dist/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// generated by scripts/build-embed.mjs — do not edit
|
|
2
|
-
export const VERSION = "0.0.
|
|
2
|
+
export const VERSION = "0.0.13";
|