zcode-acp-server 0.1.0 → 0.2.0
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 +98 -1
- package/README.zh-CN.md +81 -1
- package/dist/backend/client.d.ts +12 -4
- package/dist/backend/client.d.ts.map +1 -1
- package/dist/backend/client.js +72 -7
- package/dist/backend/client.js.map +1 -1
- package/dist/backend/credentials.d.ts.map +1 -1
- package/dist/backend/credentials.js +2 -1
- package/dist/backend/credentials.js.map +1 -1
- package/dist/backend/listener.d.ts +12 -4
- package/dist/backend/listener.d.ts.map +1 -1
- package/dist/backend/listener.js +68 -12
- package/dist/backend/listener.js.map +1 -1
- package/dist/backend/types.d.ts +1 -1
- package/dist/backend/types.d.ts.map +1 -1
- package/dist/bin/quota.d.ts +54 -0
- package/dist/bin/quota.d.ts.map +1 -0
- package/dist/bin/quota.js +333 -0
- package/dist/bin/quota.js.map +1 -0
- package/dist/config/auto-compact.d.ts +23 -0
- package/dist/config/auto-compact.d.ts.map +1 -0
- package/dist/config/auto-compact.js +67 -0
- package/dist/config/auto-compact.js.map +1 -0
- package/dist/config/mcp-discovery.d.ts +34 -0
- package/dist/config/mcp-discovery.d.ts.map +1 -0
- package/dist/config/mcp-discovery.js +153 -0
- package/dist/config/mcp-discovery.js.map +1 -0
- package/dist/config/model-cache.d.ts +12 -1
- package/dist/config/model-cache.d.ts.map +1 -1
- package/dist/config/model-cache.js +30 -8
- package/dist/config/model-cache.js.map +1 -1
- package/dist/config/options.d.ts +87 -9
- package/dist/config/options.d.ts.map +1 -1
- package/dist/config/options.js +248 -45
- package/dist/config/options.js.map +1 -1
- package/dist/config/plugin-commands.d.ts +24 -0
- package/dist/config/plugin-commands.d.ts.map +1 -0
- package/dist/config/plugin-commands.js +107 -0
- package/dist/config/plugin-commands.js.map +1 -0
- package/dist/config/provider-registry.d.ts +60 -0
- package/dist/config/provider-registry.d.ts.map +1 -0
- package/dist/config/provider-registry.js +128 -0
- package/dist/config/provider-registry.js.map +1 -0
- package/dist/config/runtime-model.d.ts +54 -18
- package/dist/config/runtime-model.d.ts.map +1 -1
- package/dist/config/runtime-model.js +105 -61
- package/dist/config/runtime-model.js.map +1 -1
- package/dist/config/skill-discovery.d.ts +35 -0
- package/dist/config/skill-discovery.d.ts.map +1 -0
- package/dist/config/skill-discovery.js +188 -0
- package/dist/config/skill-discovery.js.map +1 -0
- package/dist/handlers/background-tasks.d.ts +72 -0
- package/dist/handlers/background-tasks.d.ts.map +1 -0
- package/dist/handlers/background-tasks.js +330 -0
- package/dist/handlers/background-tasks.js.map +1 -0
- package/dist/handlers/dispatch.d.ts.map +1 -1
- package/dist/handlers/dispatch.js +134 -22
- package/dist/handlers/dispatch.js.map +1 -1
- package/dist/handlers/extensions.d.ts +15 -0
- package/dist/handlers/extensions.d.ts.map +1 -1
- package/dist/handlers/extensions.js +43 -27
- package/dist/handlers/extensions.js.map +1 -1
- package/dist/handlers/io.d.ts +11 -2
- package/dist/handlers/io.d.ts.map +1 -1
- package/dist/handlers/io.js +51 -7
- package/dist/handlers/io.js.map +1 -1
- package/dist/handlers/server-requests.d.ts +20 -4
- package/dist/handlers/server-requests.d.ts.map +1 -1
- package/dist/handlers/server-requests.js +293 -63
- package/dist/handlers/server-requests.js.map +1 -1
- package/dist/handlers/session.d.ts +113 -10
- package/dist/handlers/session.d.ts.map +1 -1
- package/dist/handlers/session.js +876 -220
- package/dist/handlers/session.js.map +1 -1
- package/dist/handlers/slash.d.ts +14 -0
- package/dist/handlers/slash.d.ts.map +1 -1
- package/dist/handlers/slash.js +80 -6
- package/dist/handlers/slash.js.map +1 -1
- package/dist/index.js +38 -4
- package/dist/index.js.map +1 -1
- package/dist/interaction/adapter.d.ts +19 -33
- package/dist/interaction/adapter.d.ts.map +1 -1
- package/dist/interaction/adapter.js +80 -79
- package/dist/interaction/adapter.js.map +1 -1
- package/dist/lazy-sessions.d.ts +35 -0
- package/dist/lazy-sessions.d.ts.map +1 -0
- package/dist/lazy-sessions.js +98 -0
- package/dist/lazy-sessions.js.map +1 -0
- package/dist/quota/cache.d.ts +18 -0
- package/dist/quota/cache.d.ts.map +1 -0
- package/dist/quota/cache.js +32 -0
- package/dist/quota/cache.js.map +1 -0
- package/dist/quota/client.d.ts +30 -0
- package/dist/quota/client.d.ts.map +1 -0
- package/dist/quota/client.js +57 -0
- package/dist/quota/client.js.map +1 -0
- package/dist/quota/color.d.ts +58 -0
- package/dist/quota/color.d.ts.map +1 -0
- package/dist/quota/color.js +95 -0
- package/dist/quota/color.js.map +1 -0
- package/dist/quota/combined.d.ts +66 -0
- package/dist/quota/combined.d.ts.map +1 -0
- package/dist/quota/combined.js +179 -0
- package/dist/quota/combined.js.map +1 -0
- package/dist/quota/format.d.ts +105 -0
- package/dist/quota/format.d.ts.map +1 -0
- package/dist/quota/format.js +219 -0
- package/dist/quota/format.js.map +1 -0
- package/dist/quota/index.d.ts +23 -0
- package/dist/quota/index.d.ts.map +1 -0
- package/dist/quota/index.js +42 -0
- package/dist/quota/index.js.map +1 -0
- package/dist/quota/opencode-go/cache.d.ts +17 -0
- package/dist/quota/opencode-go/cache.d.ts.map +1 -0
- package/dist/quota/opencode-go/cache.js +31 -0
- package/dist/quota/opencode-go/cache.js.map +1 -0
- package/dist/quota/opencode-go/client.d.ts +28 -0
- package/dist/quota/opencode-go/client.d.ts.map +1 -0
- package/dist/quota/opencode-go/client.js +48 -0
- package/dist/quota/opencode-go/client.js.map +1 -0
- package/dist/quota/opencode-go/config.d.ts +37 -0
- package/dist/quota/opencode-go/config.d.ts.map +1 -0
- package/dist/quota/opencode-go/config.js +58 -0
- package/dist/quota/opencode-go/config.js.map +1 -0
- package/dist/quota/opencode-go/format.d.ts +36 -0
- package/dist/quota/opencode-go/format.d.ts.map +1 -0
- package/dist/quota/opencode-go/format.js +87 -0
- package/dist/quota/opencode-go/format.js.map +1 -0
- package/dist/quota/opencode-go/index.d.ts +30 -0
- package/dist/quota/opencode-go/index.d.ts.map +1 -0
- package/dist/quota/opencode-go/index.js +108 -0
- package/dist/quota/opencode-go/index.js.map +1 -0
- package/dist/quota/opencode-go/parse.d.ts +41 -0
- package/dist/quota/opencode-go/parse.d.ts.map +1 -0
- package/dist/quota/opencode-go/parse.js +75 -0
- package/dist/quota/opencode-go/parse.js.map +1 -0
- package/dist/quota/opencode-go/types.d.ts +48 -0
- package/dist/quota/opencode-go/types.d.ts.map +1 -0
- package/dist/quota/opencode-go/types.js +11 -0
- package/dist/quota/opencode-go/types.js.map +1 -0
- package/dist/quota/parse.d.ts +33 -0
- package/dist/quota/parse.d.ts.map +1 -0
- package/dist/quota/parse.js +200 -0
- package/dist/quota/parse.js.map +1 -0
- package/dist/quota/types.d.ts +72 -0
- package/dist/quota/types.d.ts.map +1 -0
- package/dist/quota/types.js +10 -0
- package/dist/quota/types.js.map +1 -0
- package/dist/server.d.ts +104 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +119 -2
- package/dist/server.js.map +1 -1
- package/dist/tasks-index.d.ts +14 -4
- package/dist/tasks-index.d.ts.map +1 -1
- package/dist/tasks-index.js +145 -46
- package/dist/tasks-index.js.map +1 -1
- package/dist/translators/event-translator.d.ts +33 -0
- package/dist/translators/event-translator.d.ts.map +1 -1
- package/dist/translators/event-translator.js +101 -0
- package/dist/translators/event-translator.js.map +1 -1
- package/dist/translators/index.d.ts +1 -1
- package/dist/translators/index.d.ts.map +1 -1
- package/dist/translators/index.js +1 -1
- package/dist/translators/index.js.map +1 -1
- package/dist/translators/projection-differ.d.ts +8 -0
- package/dist/translators/projection-differ.d.ts.map +1 -1
- package/dist/translators/projection-differ.js +19 -9
- package/dist/translators/projection-differ.js.map +1 -1
- package/dist/translators/tool-helpers.d.ts +28 -0
- package/dist/translators/tool-helpers.d.ts.map +1 -1
- package/dist/translators/tool-helpers.js +104 -0
- package/dist/translators/tool-helpers.js.map +1 -1
- package/dist/translators/types.d.ts +38 -1
- package/dist/translators/types.d.ts.map +1 -1
- package/dist/translators/types.js.map +1 -1
- package/dist/utils.d.ts +35 -6
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +52 -4
- package/dist/utils.js.map +1 -1
- package/docs/ARCHITECTURE.md +96 -38
- package/docs/BACKLOG.md +57 -0
- package/docs/DEVELOPMENT.md +5 -0
- package/docs/PROTOCOL.md +270 -5
- package/docs/TROUBLESHOOTING.md +98 -14
- package/docs/agents/domain.md +51 -0
- package/docs/agents/issue-tracker.md +22 -0
- package/docs/agents/triage-labels.md +15 -0
- package/package.json +6 -5
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"color.d.ts","sourceRoot":"","sources":["../../src/quota/color.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,0CAA0C;AAC1C,eAAO,MAAM,KAAK,cAAY,CAAC;AAE/B,yBAAyB;AACzB,KAAK,GAAG,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAwB7C;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAQ1C;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GAAG,MAAM,CAUT;AAED,0CAA0C;AAC1C,MAAM,WAAW,eAAe;IAC9B,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,eAAe,GAAG,MAAM,CAmBlF"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Color progress-bar rendering for the `zcode-quota` CLI.
|
|
3
|
+
*
|
|
4
|
+
* The default CLI view overlays the usage numbers directly onto a heat-colored
|
|
5
|
+
* (green→yellow→red) bar using 24-bit ANSI background colors, so the percentage
|
|
6
|
+
* or used/total counter reads from inside the bar and the right margin stays
|
|
7
|
+
* short (just the reset time). `--plain` and the `/quota` slash command bypass
|
|
8
|
+
* this module entirely and keep the classic monochrome `█`/`░` layout from
|
|
9
|
+
* {@link renderBar}.
|
|
10
|
+
*
|
|
11
|
+
* Only real terminals render 24-bit color; the CLI caller gates this on
|
|
12
|
+
* `process.stdout.isTTY` so piping to a file or another command never emits
|
|
13
|
+
* raw escape codes.
|
|
14
|
+
*/
|
|
15
|
+
/** ANSI reset (cancel all attributes). */
|
|
16
|
+
export const RESET = "\x1b[0m";
|
|
17
|
+
/** ANSI 24-bit background-color escape. */
|
|
18
|
+
function bg(r, g, b) {
|
|
19
|
+
return `\x1b[48;2;${r};${g};${b}m`;
|
|
20
|
+
}
|
|
21
|
+
/** ANSI 24-bit foreground (text) color escape. */
|
|
22
|
+
function fg(r, g, b) {
|
|
23
|
+
return `\x1b[38;2;${r};${g};${b}m`;
|
|
24
|
+
}
|
|
25
|
+
/** Linear interpolation between two numbers, rounded to an 8-bit channel. */
|
|
26
|
+
function lerp(a, b, t) {
|
|
27
|
+
return Math.round(a + (b - a) * t);
|
|
28
|
+
}
|
|
29
|
+
/** Empty-cell background (constant dark gray, independent of usage). */
|
|
30
|
+
const EMPTY_BG = [40, 40, 48];
|
|
31
|
+
/** Empty-cell foreground (muted gray text). */
|
|
32
|
+
const EMPTY_FG = [120, 120, 130];
|
|
33
|
+
/** Fill-cell foreground (white text — high contrast on saturated fill). */
|
|
34
|
+
const FILL_FG = [255, 255, 255];
|
|
35
|
+
/**
|
|
36
|
+
* Green→yellow→red heat color for a usage percent.
|
|
37
|
+
*
|
|
38
|
+
* 0% → green `(34,197,94)`, 50% → yellow `(234,179,8)`, 100% → red
|
|
39
|
+
* `(239,68,68)`, piecewise-linearly interpolated. Input is clamped to [0, 100].
|
|
40
|
+
*/
|
|
41
|
+
export function heatColor(pct) {
|
|
42
|
+
const p = Math.max(0, Math.min(100, pct));
|
|
43
|
+
if (p < 50) {
|
|
44
|
+
const t = p / 50;
|
|
45
|
+
return [lerp(34, 234, t), lerp(197, 179, t), lerp(94, 8, t)];
|
|
46
|
+
}
|
|
47
|
+
const t = (p - 50) / 50;
|
|
48
|
+
return [lerp(234, 239, t), lerp(179, 68, t), lerp(8, 68, t)];
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Pick the overlay text drawn inside the bar.
|
|
52
|
+
*
|
|
53
|
+
* Returns `"used/total"` when the item carries both absolute counters (e.g. the
|
|
54
|
+
* MCP limit), otherwise `"NN%"` (the rounded used percent). This lets
|
|
55
|
+
* counter-bearing limits show their exact counts in-bar while counter-less
|
|
56
|
+
* limits (5h, Opencode Go windows) show the percent.
|
|
57
|
+
*/
|
|
58
|
+
export function pickOverlay(item) {
|
|
59
|
+
if (typeof item.usedCount === "number" &&
|
|
60
|
+
typeof item.totalCount === "number" &&
|
|
61
|
+
Number.isFinite(item.usedCount) &&
|
|
62
|
+
Number.isFinite(item.totalCount)) {
|
|
63
|
+
return `${item.usedCount}/${item.totalCount}`;
|
|
64
|
+
}
|
|
65
|
+
return `${Math.round(Math.max(0, Math.min(100, item.usedPercent)))}%`;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Render a heat-colored progress bar with optional centered overlay text.
|
|
69
|
+
*
|
|
70
|
+
* Each cell is one background color: the fill cells use {@link heatColor} (so
|
|
71
|
+
* low usage reads green, high usage red), the empty cells use a constant dark
|
|
72
|
+
* gray. When an overlay string is supplied its characters are written over the
|
|
73
|
+
* bar with a contrasting foreground (white on fill, gray on empty), centered
|
|
74
|
+
* across the `width` cells. The result always ends with {@link RESET} so the
|
|
75
|
+
* color never leaks into the text that follows.
|
|
76
|
+
*/
|
|
77
|
+
export function renderColorBar(usedPercent, opts) {
|
|
78
|
+
const width = opts?.width ?? 20;
|
|
79
|
+
const pct = Math.max(0, Math.min(100, usedPercent));
|
|
80
|
+
const filled = Math.round((pct / 100) * width);
|
|
81
|
+
const [fr, fgg, fb] = heatColor(pct);
|
|
82
|
+
const overlay = opts?.overlay ?? "";
|
|
83
|
+
const overlayStart = Math.floor((width - overlay.length) / 2);
|
|
84
|
+
let out = "";
|
|
85
|
+
for (let i = 0; i < width; i++) {
|
|
86
|
+
const isFill = i < filled;
|
|
87
|
+
const [br, bgg, bb] = isFill ? [fr, fgg, fb] : EMPTY_BG;
|
|
88
|
+
const idx = i - overlayStart;
|
|
89
|
+
const ch = idx >= 0 && idx < overlay.length ? overlay[idx] : " ";
|
|
90
|
+
const [tr, tg, tb] = isFill ? FILL_FG : EMPTY_FG;
|
|
91
|
+
out += `${bg(br, bgg, bb)}${fg(tr, tg, tb)}${ch}`;
|
|
92
|
+
}
|
|
93
|
+
return out + RESET;
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=color.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"color.js","sourceRoot":"","sources":["../../src/quota/color.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,0CAA0C;AAC1C,MAAM,CAAC,MAAM,KAAK,GAAG,SAAS,CAAC;AAK/B,2CAA2C;AAC3C,SAAS,EAAE,CAAC,CAAS,EAAE,CAAS,EAAE,CAAS;IACzC,OAAO,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;AACrC,CAAC;AAED,kDAAkD;AAClD,SAAS,EAAE,CAAC,CAAS,EAAE,CAAS,EAAE,CAAS;IACzC,OAAO,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;AACrC,CAAC;AAED,6EAA6E;AAC7E,SAAS,IAAI,CAAC,CAAS,EAAE,CAAS,EAAE,CAAS;IAC3C,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AACrC,CAAC;AAED,wEAAwE;AACxE,MAAM,QAAQ,GAAQ,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;AACnC,+CAA+C;AAC/C,MAAM,QAAQ,GAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AACtC,2EAA2E;AAC3E,MAAM,OAAO,GAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAErC;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,GAAW;IACnC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;IAC1C,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;QACX,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;QACjB,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC/D,CAAC;IACD,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC;IACxB,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAC,IAI3B;IACC,IACE,OAAO,IAAI,CAAC,SAAS,KAAK,QAAQ;QAClC,OAAO,IAAI,CAAC,UAAU,KAAK,QAAQ;QACnC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC;QAC/B,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,EAChC,CAAC;QACD,OAAO,GAAG,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;IAChD,CAAC;IACD,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC;AACxE,CAAC;AAUD;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAAC,WAAmB,EAAE,IAAsB;IACxE,MAAM,KAAK,GAAG,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;IAChC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC;IACpD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;IAC/C,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;IAErC,MAAM,OAAO,GAAG,IAAI,EAAE,OAAO,IAAI,EAAE,CAAC;IACpC,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAE9D,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,CAAC,GAAG,MAAM,CAAC;QAC1B,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;QACxD,MAAM,GAAG,GAAG,CAAC,GAAG,YAAY,CAAC;QAC7B,MAAM,EAAE,GAAG,GAAG,IAAI,CAAC,IAAI,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAE,CAAC,CAAC,CAAC,GAAG,CAAC;QAClE,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC;QACjD,GAAG,IAAI,GAAG,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC;IACpD,CAAC;IACD,OAAO,GAAG,GAAG,KAAK,CAAC;AACrB,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Combined multi-provider quota — the orchestration layer used by the
|
|
3
|
+
* `zcode-quota` CLI when no provider subcommand is given (default mode).
|
|
4
|
+
*
|
|
5
|
+
* Queries GLM Coding Plan and Opencode Go in parallel and renders a single
|
|
6
|
+
* merged card with one section per provider. The `/quota` slash command does
|
|
7
|
+
* NOT use this — it stays on the single-provider GLM {@link formatQuota}.
|
|
8
|
+
*
|
|
9
|
+
* Design notes:
|
|
10
|
+
* - `Promise.all` so a slow Opencode Go scrape doesn't delay the GLM card.
|
|
11
|
+
* - A `not_configured` Opencode Go result is silently dropped (no header,
|
|
12
|
+
* no error line) in `all` mode, so GLM-only users see no noise. In `go`
|
|
13
|
+
* mode it surfaces as a help line because the user explicitly asked.
|
|
14
|
+
* - The divider width is computed from the widest body line so the frame
|
|
15
|
+
* stays balanced regardless of which windows/counts are present.
|
|
16
|
+
*/
|
|
17
|
+
import type { FormatOptions } from "./format.js";
|
|
18
|
+
import type { GoQueryResult, GoWindowKey } from "./opencode-go/types.js";
|
|
19
|
+
import type { QuotaResult } from "./types.js";
|
|
20
|
+
/** Which provider(s) to query. */
|
|
21
|
+
export type Provider = "all" | "glm" | "go";
|
|
22
|
+
/** The combined result of both providers. */
|
|
23
|
+
export interface CombinedResult {
|
|
24
|
+
glm: QuotaResult;
|
|
25
|
+
go: GoQueryResult;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Which Opencode Go windows to render. All three (rolling + weekly + monthly)
|
|
29
|
+
* are shown in every mode that renders Go at all — the compact color layout
|
|
30
|
+
* leaves room for the monthly bar.
|
|
31
|
+
*/
|
|
32
|
+
export declare function defaultGoWindows(provider: Provider): GoWindowKey[];
|
|
33
|
+
/**
|
|
34
|
+
* Query both providers in parallel.
|
|
35
|
+
*
|
|
36
|
+
* Each provider degrades internally (GLM → `unavailable`, Go →
|
|
37
|
+
* `not_configured`/`unavailable`); neither ever throws, so `Promise.all`
|
|
38
|
+
* always resolves.
|
|
39
|
+
*/
|
|
40
|
+
export declare function queryCombined(provider: Provider): Promise<CombinedResult>;
|
|
41
|
+
/**
|
|
42
|
+
* Render the combined result as a single fenced ```text card.
|
|
43
|
+
*
|
|
44
|
+
* Sections are separated by a blank line; each section has a ` Header` line
|
|
45
|
+
* (indented one space so it reads as a sub-heading) followed by its body.
|
|
46
|
+
* The divider spans the widest line in the card.
|
|
47
|
+
*/
|
|
48
|
+
export declare function formatCombinedCard(combined: CombinedResult, opts?: {
|
|
49
|
+
provider: Provider;
|
|
50
|
+
glm?: FormatOptions;
|
|
51
|
+
goWindows?: GoWindowKey[];
|
|
52
|
+
/** Render heat-colored 24-bit ANSI bars with overlaid numbers. */
|
|
53
|
+
color?: boolean;
|
|
54
|
+
/** Optional trailing annotation appended to the first section header
|
|
55
|
+
* (e.g. ` · refresh in 29s`). Watch mode uses it to show the countdown. */
|
|
56
|
+
refreshSuffix?: string;
|
|
57
|
+
}): string;
|
|
58
|
+
/** {@link formatCombinedCard} without the fence — for raw terminal output. */
|
|
59
|
+
export declare function formatCombinedCardPlain(combined: CombinedResult, opts?: {
|
|
60
|
+
provider: Provider;
|
|
61
|
+
glm?: FormatOptions;
|
|
62
|
+
goWindows?: GoWindowKey[];
|
|
63
|
+
color?: boolean;
|
|
64
|
+
refreshSuffix?: string;
|
|
65
|
+
}): string;
|
|
66
|
+
//# sourceMappingURL=combined.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"combined.d.ts","sourceRoot":"","sources":["../../src/quota/combined.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAIjD,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,kCAAkC;AAClC,MAAM,MAAM,QAAQ,GAAG,KAAK,GAAG,KAAK,GAAG,IAAI,CAAC;AAE5C,6CAA6C;AAC7C,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,WAAW,CAAC;IACjB,EAAE,EAAE,aAAa,CAAC;CACnB;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,GAAG,WAAW,EAAE,CAOlE;AAED;;;;;;GAMG;AACH,wBAAsB,aAAa,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,cAAc,CAAC,CAa/E;AAeD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,cAAc,EACxB,IAAI,GAAE;IACJ,QAAQ,EAAE,QAAQ,CAAC;IACnB,GAAG,CAAC,EAAE,aAAa,CAAC;IACpB,SAAS,CAAC,EAAE,WAAW,EAAE,CAAC;IAC1B,kEAAkE;IAClE,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;gFAC4E;IAC5E,aAAa,CAAC,EAAE,MAAM,CAAC;CACF,GACtB,MAAM,CAWR;AAED,8EAA8E;AAC9E,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,cAAc,EACxB,IAAI,GAAE;IACJ,QAAQ,EAAE,QAAQ,CAAC;IACnB,GAAG,CAAC,EAAE,aAAa,CAAC;IACpB,SAAS,CAAC,EAAE,WAAW,EAAE,CAAC;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;CACF,GACtB,MAAM,CASR"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Combined multi-provider quota — the orchestration layer used by the
|
|
3
|
+
* `zcode-quota` CLI when no provider subcommand is given (default mode).
|
|
4
|
+
*
|
|
5
|
+
* Queries GLM Coding Plan and Opencode Go in parallel and renders a single
|
|
6
|
+
* merged card with one section per provider. The `/quota` slash command does
|
|
7
|
+
* NOT use this — it stays on the single-provider GLM {@link formatQuota}.
|
|
8
|
+
*
|
|
9
|
+
* Design notes:
|
|
10
|
+
* - `Promise.all` so a slow Opencode Go scrape doesn't delay the GLM card.
|
|
11
|
+
* - A `not_configured` Opencode Go result is silently dropped (no header,
|
|
12
|
+
* no error line) in `all` mode, so GLM-only users see no noise. In `go`
|
|
13
|
+
* mode it surfaces as a help line because the user explicitly asked.
|
|
14
|
+
* - The divider width is computed from the widest body line so the frame
|
|
15
|
+
* stays balanced regardless of which windows/counts are present.
|
|
16
|
+
*/
|
|
17
|
+
import { renderGlmSection } from "./format.js";
|
|
18
|
+
import { queryQuota } from "./index.js";
|
|
19
|
+
import { formatGoSection, queryGoUsage } from "./opencode-go/index.js";
|
|
20
|
+
/**
|
|
21
|
+
* Which Opencode Go windows to render. All three (rolling + weekly + monthly)
|
|
22
|
+
* are shown in every mode that renders Go at all — the compact color layout
|
|
23
|
+
* leaves room for the monthly bar.
|
|
24
|
+
*/
|
|
25
|
+
export function defaultGoWindows(provider) {
|
|
26
|
+
// All three windows everywhere now — the compact color layout leaves room
|
|
27
|
+
// for the monthly bar. `provider` is accepted to keep the call sites
|
|
28
|
+
// self-documenting (and to allow per-provider trimming again later) even
|
|
29
|
+
// though every branch currently returns the same set.
|
|
30
|
+
void provider;
|
|
31
|
+
return ["rolling", "weekly", "monthly"];
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Query both providers in parallel.
|
|
35
|
+
*
|
|
36
|
+
* Each provider degrades internally (GLM → `unavailable`, Go →
|
|
37
|
+
* `not_configured`/`unavailable`); neither ever throws, so `Promise.all`
|
|
38
|
+
* always resolves.
|
|
39
|
+
*/
|
|
40
|
+
export async function queryCombined(provider) {
|
|
41
|
+
// For `glm`-only we skip the Go fetch entirely; for `go`-only we skip GLM.
|
|
42
|
+
// Skipping is cheaper and avoids touching Go credentials the user may not
|
|
43
|
+
// have set. We still return both fields so the formatter's shape is uniform.
|
|
44
|
+
const tasks = provider === "glm"
|
|
45
|
+
? [queryQuota(), Promise.resolve({ kind: "not_configured" })]
|
|
46
|
+
: provider === "go"
|
|
47
|
+
? [Promise.resolve({ kind: "unavailable" }), queryGoUsage()]
|
|
48
|
+
: [queryQuota(), queryGoUsage()];
|
|
49
|
+
const [glm, go] = await Promise.all(tasks);
|
|
50
|
+
return { glm, go };
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Decide whether the Go section should appear at all in `all` mode.
|
|
54
|
+
*
|
|
55
|
+
* `not_configured` is silently dropped (the user hasn't set credentials and
|
|
56
|
+
* didn't explicitly ask for Go). All other kinds — including `unavailable`
|
|
57
|
+
* and `auth_error` — render so the user sees that something is wrong.
|
|
58
|
+
*/
|
|
59
|
+
function shouldShowGo(provider, go) {
|
|
60
|
+
if (provider === "glm")
|
|
61
|
+
return false;
|
|
62
|
+
if (go.kind === "not_configured" && provider === "all")
|
|
63
|
+
return false;
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Render the combined result as a single fenced ```text card.
|
|
68
|
+
*
|
|
69
|
+
* Sections are separated by a blank line; each section has a ` Header` line
|
|
70
|
+
* (indented one space so it reads as a sub-heading) followed by its body.
|
|
71
|
+
* The divider spans the widest line in the card.
|
|
72
|
+
*/
|
|
73
|
+
export function formatCombinedCard(combined, opts = { provider: "all" }) {
|
|
74
|
+
const provider = opts.provider;
|
|
75
|
+
const lines = renderCombinedLines(combined, provider, opts.glm, opts.goWindows, opts.color, opts.refreshSuffix);
|
|
76
|
+
return ["```text", ...lines, "```"].join("\n");
|
|
77
|
+
}
|
|
78
|
+
/** {@link formatCombinedCard} without the fence — for raw terminal output. */
|
|
79
|
+
export function formatCombinedCardPlain(combined, opts = { provider: "all" }) {
|
|
80
|
+
return renderCombinedLines(combined, opts.provider, opts.glm, opts.goWindows, opts.color, opts.refreshSuffix).join("\n");
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Render the card body lines (no fence). Shared by fenced/plain variants.
|
|
84
|
+
*
|
|
85
|
+
* Single-provider modes render just that provider's section header + body
|
|
86
|
+
* (no `Quota Overview` banner, no divider). `all` mode renders the banner,
|
|
87
|
+
* divider, and both sections.
|
|
88
|
+
*/
|
|
89
|
+
/**
|
|
90
|
+
* Width the refresh line is right-aligned to. Matches the classic GLM divider
|
|
91
|
+
* width so the countdown lines up with the card's visual frame.
|
|
92
|
+
*/
|
|
93
|
+
const REFRESH_LINE_WIDTH = 34;
|
|
94
|
+
/**
|
|
95
|
+
* Build the separator line that follows the first rendered section.
|
|
96
|
+
*
|
|
97
|
+
* In watch mode this carries the refresh countdown, right-aligned to
|
|
98
|
+
* {@link REFRESH_LINE_WIDTH} so its position is stable regardless of how many
|
|
99
|
+
* sections follow (or whether Go is configured). When no refresh suffix is
|
|
100
|
+
* supplied the line is blank — it still occupies the row so the layout below
|
|
101
|
+
* it never shifts.
|
|
102
|
+
*/
|
|
103
|
+
function separatorLine(refreshSuffix) {
|
|
104
|
+
if (!refreshSuffix)
|
|
105
|
+
return "";
|
|
106
|
+
return refreshSuffix.padStart(REFRESH_LINE_WIDTH);
|
|
107
|
+
}
|
|
108
|
+
function renderCombinedLines(combined, provider, glmOpts, goWindows, color = false,
|
|
109
|
+
/** Optional refresh countdown rendered on the separator line after the
|
|
110
|
+
* first section (e.g. `refresh in 29s`). */
|
|
111
|
+
refreshSuffix) {
|
|
112
|
+
const { glm, go } = combined;
|
|
113
|
+
const sep = separatorLine(refreshSuffix);
|
|
114
|
+
// Fold the color flag into the GLM FormatOptions so it reaches renderGlmSection
|
|
115
|
+
// alongside detail/compact without each caller having to set it.
|
|
116
|
+
const glmOptsColor = { ...glmOpts, color };
|
|
117
|
+
// Single-provider GLM: behave like the original card (header + divider +
|
|
118
|
+
// body) minus the fence, so `zcode-quota glm` looks identical to today's
|
|
119
|
+
// `zcode-quota`.
|
|
120
|
+
if (provider === "glm") {
|
|
121
|
+
const lines = renderSingleGlm(glm, glmOptsColor);
|
|
122
|
+
// The separator rides after the (only) section, then nothing follows.
|
|
123
|
+
return sep ? [...lines, sep] : lines;
|
|
124
|
+
}
|
|
125
|
+
// Single-provider Go: header + body, no banner/divider.
|
|
126
|
+
if (provider === "go") {
|
|
127
|
+
const section = formatGoSection(go, goWindows ?? defaultGoWindows("go"), Date.now(), color);
|
|
128
|
+
const lines = [section.header, ...section.body];
|
|
129
|
+
return sep ? [...lines, sep] : lines;
|
|
130
|
+
}
|
|
131
|
+
// Combined `all` mode. GLM renders full (MCP on its own line) — the layout
|
|
132
|
+
// is short enough now that compact mode isn't worth the lost detail.
|
|
133
|
+
const glmSection = renderGlmSection(glm, glmOptsColor);
|
|
134
|
+
const showGo = shouldShowGo("all", go);
|
|
135
|
+
const goSection = showGo
|
|
136
|
+
? formatGoSection(go, goWindows ?? defaultGoWindows("all"), Date.now(), color)
|
|
137
|
+
: null;
|
|
138
|
+
const hasGlm = glmSection.body.length > 0;
|
|
139
|
+
const hasGo = !!goSection && goSection.body.length > 0;
|
|
140
|
+
// The separator line always follows the FIRST rendered section, so its row
|
|
141
|
+
// is fixed whether or not a second section appears.
|
|
142
|
+
const sections = [];
|
|
143
|
+
if (hasGlm)
|
|
144
|
+
sections.push([` ${glmSection.header}`, ...glmSection.body]);
|
|
145
|
+
if (hasGo)
|
|
146
|
+
sections.push([` ${goSection.header}`, ...goSection.body]);
|
|
147
|
+
if (sections.length === 0) {
|
|
148
|
+
return [" ⚠ no usage data available"];
|
|
149
|
+
}
|
|
150
|
+
// No banner or top divider — the section headers themselves identify each
|
|
151
|
+
// provider, and an extra banner line adds noise without information. The
|
|
152
|
+
// refresh countdown sits on the separator row between sections (or after
|
|
153
|
+
// the only section), right-aligned.
|
|
154
|
+
const body = [];
|
|
155
|
+
sections.forEach((sec, i) => {
|
|
156
|
+
if (i > 0)
|
|
157
|
+
body.push(sep);
|
|
158
|
+
body.push(...sec);
|
|
159
|
+
});
|
|
160
|
+
// If there's only one section, the separator still trails it so the refresh
|
|
161
|
+
// line keeps its fixed position.
|
|
162
|
+
if (sections.length === 1 && sep)
|
|
163
|
+
body.push(sep);
|
|
164
|
+
return body;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Render a single GLM provider as header + divider + body (the classic card,
|
|
168
|
+
* minus the fence). Used for `zcode-quota glm`.
|
|
169
|
+
*/
|
|
170
|
+
function renderSingleGlm(result, opts) {
|
|
171
|
+
const section = renderGlmSection(result, opts);
|
|
172
|
+
if (result.kind !== "success") {
|
|
173
|
+
// Non-success → just the prose line, no header/divider (matches formatQuota).
|
|
174
|
+
return section.body;
|
|
175
|
+
}
|
|
176
|
+
const divider = "─".repeat(34);
|
|
177
|
+
return [section.header, divider, ...section.body];
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=combined.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"combined.js","sourceRoot":"","sources":["../../src/quota/combined.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Quota result formatting — renders a {@link QuotaResult} as a multi-line
|
|
3
|
+
* plain-text card inside a ```text fenced block.
|
|
4
|
+
*
|
|
5
|
+
* The whole card is wrapped in a fenced code block so the editor renders it in
|
|
6
|
+
* a monospace, bordered, copy-able frame. Monospace also normalises the block
|
|
7
|
+
* element widths (▓/░ are NOT marked East-Asian-Wide, but some proportional
|
|
8
|
+
* chat fonts stretch them; a code frame guarantees 1-cell-per-bar).
|
|
9
|
+
*
|
|
10
|
+
* The progress bar uses two block characters at {@link BAR_WIDTH}-cell width
|
|
11
|
+
* for a clean, precise fill (each cell = 5%):
|
|
12
|
+
* █ (U+2588, full block) — used portion
|
|
13
|
+
* ░ (U+2591, light shade) — remaining portion
|
|
14
|
+
* Inside a monospace code block the full-block reads as a solid, high-impact
|
|
15
|
+
* fill for used quota, with the light shade marking the remainder.
|
|
16
|
+
*/
|
|
17
|
+
import type { QuotaResult } from "./types.js";
|
|
18
|
+
/**
|
|
19
|
+
* Render a {@link BAR_WIDTH}-cell progress bar for a used-percent in [0, 100].
|
|
20
|
+
*
|
|
21
|
+
* 0% → all empty; 100% → all full; otherwise the used portion is `█` and the
|
|
22
|
+
* rest is `░`, rounded to the nearest cell (each cell = 10%).
|
|
23
|
+
*/
|
|
24
|
+
export declare function renderBar(usedPercent: number): string;
|
|
25
|
+
/**
|
|
26
|
+
* Format a reset timestamp (ms) as a local `MM-DD HH:MM` string, or `null`.
|
|
27
|
+
*
|
|
28
|
+
* Exported so the Opencode Go formatter can reuse the same layout (Go windows
|
|
29
|
+
* carry only a relative `resetInSec`; the caller converts that to an absolute
|
|
30
|
+
* ms timestamp against the fetch snapshot first).
|
|
31
|
+
*/
|
|
32
|
+
export declare function formatResetTime(nextResetTime?: number): string | null;
|
|
33
|
+
/**
|
|
34
|
+
* Options controlling which sections of the card are rendered.
|
|
35
|
+
*
|
|
36
|
+
* - `detail` (default `true`): show per-model usage breakdown sub-lines
|
|
37
|
+
* (`├ search-prime …`). Set to `false` for compact terminal output where the
|
|
38
|
+
* aggregate bar is enough.
|
|
39
|
+
* - `compact` (default `false`): collapse the MCP item into a trailing
|
|
40
|
+
* annotation on the 5h line (`· MCP (used/total)`) and drop its standalone
|
|
41
|
+
* bar line + detail sub-lines. Used only by the combined dual-provider CLI
|
|
42
|
+
* view to keep the merged card short; the standalone `glm` subcommand and
|
|
43
|
+
* the `/quota` slash command keep the full layout.
|
|
44
|
+
* - `color` (default `false`): render the bar as a heat-colored (green→red)
|
|
45
|
+
* 24-bit ANSI bar with the usage numbers overlaid inside (see
|
|
46
|
+
* {@link pickOverlay}), leaving only the reset time on the right margin.
|
|
47
|
+
* Only the `zcode-quota` CLI sets this (gated on `stdout.isTTY`); the
|
|
48
|
+
* `/quota` slash command never does, so its fenced ```text card stays plain
|
|
49
|
+
* and copy-paste-safe.
|
|
50
|
+
*/
|
|
51
|
+
export interface FormatOptions {
|
|
52
|
+
detail?: boolean;
|
|
53
|
+
compact?: boolean;
|
|
54
|
+
color?: boolean;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* A rendered GLM section — a header (plan name) and the bar lines.
|
|
58
|
+
*
|
|
59
|
+
* Exported so the combined CLI view can compose the GLM section alongside the
|
|
60
|
+
* Opencode Go section inside one card, without duplicating the per-item
|
|
61
|
+
* formatting logic.
|
|
62
|
+
*/
|
|
63
|
+
export interface RenderedGlmSection {
|
|
64
|
+
header: string;
|
|
65
|
+
body: string[];
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Render the GLM section (header + one bar line per item) without the fence
|
|
69
|
+
* or divider.
|
|
70
|
+
*
|
|
71
|
+
* Non-success kinds return a header of `"GLM Coding Plan"` and a single
|
|
72
|
+
* explanatory body line, mirroring {@link formatQuota}'s non-success prose
|
|
73
|
+
* (just split into header/body for composability).
|
|
74
|
+
*
|
|
75
|
+
* In `compact` mode the MCP item is collapsed into a trailing annotation on
|
|
76
|
+
* the 5h line (`· MCP (used/total)`) and its own bar line + detail sub-lines
|
|
77
|
+
* are dropped — used by the combined dual-provider CLI view to keep the merged
|
|
78
|
+
* card short. The standalone `glm` subcommand and `/quota` slash command use
|
|
79
|
+
* the full layout.
|
|
80
|
+
*/
|
|
81
|
+
export declare function renderGlmSection(result: QuotaResult, opts?: FormatOptions): RenderedGlmSection;
|
|
82
|
+
/**
|
|
83
|
+
* Render a {@link QuotaResult} as a multi-line plain-text card wrapped in a
|
|
84
|
+
* ```text fenced block.
|
|
85
|
+
*
|
|
86
|
+
* The fence makes the editor render the card in a monospace, bordered, copy-
|
|
87
|
+
* able frame — without it the proportional chat font mangles block-element
|
|
88
|
+
* widths (▓/░ render at different glyph advances and can look stretched), and
|
|
89
|
+
* the divider/bars lose their alignment.
|
|
90
|
+
*
|
|
91
|
+
* Success → header line + divider + one progress-bar line per item (plus
|
|
92
|
+
* indented per-model detail where present). Non-success kinds → a single
|
|
93
|
+
* explanatory line, unfenced (they are short prose, not a card).
|
|
94
|
+
*/
|
|
95
|
+
export declare function formatQuota(result: QuotaResult, opts?: FormatOptions): string;
|
|
96
|
+
/**
|
|
97
|
+
* {@link formatQuota} without the ```text fence — for raw terminal output.
|
|
98
|
+
*
|
|
99
|
+
* The fence is only useful inside an editor chat frame (where it triggers a
|
|
100
|
+
* bordered, copy-able code block). A real terminal renders the fence as
|
|
101
|
+
* literal ```` ``` ```` characters, so the standalone CLI strips it.
|
|
102
|
+
* Non-success kinds are already unfenced short prose, returned unchanged.
|
|
103
|
+
*/
|
|
104
|
+
export declare function formatQuotaPlain(result: QuotaResult, opts?: FormatOptions): string;
|
|
105
|
+
//# sourceMappingURL=format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/quota/format.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,KAAK,EAAa,WAAW,EAAE,MAAM,YAAY,CAAC;AAiBzD;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAKrD;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CASrE;AAyCD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAgDD;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,kBAAkB,CA+B9F;AAeD;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,MAAM,CAU7E;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,MAAM,CAGlF"}
|