@slkiser/opencode-quota 1.4.2 → 1.4.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.
Files changed (46) hide show
  1. package/README.md +1 -1
  2. package/dist/lib/chutes.d.ts.map +1 -1
  3. package/dist/lib/chutes.js +1 -5
  4. package/dist/lib/chutes.js.map +1 -1
  5. package/dist/lib/command-handled.d.ts +13 -0
  6. package/dist/lib/command-handled.d.ts.map +1 -0
  7. package/dist/lib/command-handled.js +15 -0
  8. package/dist/lib/command-handled.js.map +1 -0
  9. package/dist/lib/command-parsing.d.ts +53 -0
  10. package/dist/lib/command-parsing.d.ts.map +1 -0
  11. package/dist/lib/command-parsing.js +121 -0
  12. package/dist/lib/command-parsing.js.map +1 -0
  13. package/dist/lib/config.d.ts.map +1 -1
  14. package/dist/lib/config.js +26 -30
  15. package/dist/lib/config.js.map +1 -1
  16. package/dist/lib/firmware.d.ts.map +1 -1
  17. package/dist/lib/firmware.js +1 -5
  18. package/dist/lib/firmware.js.map +1 -1
  19. package/dist/lib/format-utils.d.ts +5 -0
  20. package/dist/lib/format-utils.d.ts.map +1 -1
  21. package/dist/lib/format-utils.js +9 -0
  22. package/dist/lib/format-utils.js.map +1 -1
  23. package/dist/lib/format.d.ts.map +1 -1
  24. package/dist/lib/format.js +5 -10
  25. package/dist/lib/format.js.map +1 -1
  26. package/dist/lib/openai.d.ts.map +1 -1
  27. package/dist/lib/openai.js +1 -5
  28. package/dist/lib/openai.js.map +1 -1
  29. package/dist/lib/quota-command-format.d.ts.map +1 -1
  30. package/dist/lib/quota-command-format.js +5 -9
  31. package/dist/lib/quota-command-format.js.map +1 -1
  32. package/dist/lib/session-tokens-format.d.ts +15 -0
  33. package/dist/lib/session-tokens-format.d.ts.map +1 -0
  34. package/dist/lib/session-tokens-format.js +27 -0
  35. package/dist/lib/session-tokens-format.js.map +1 -0
  36. package/dist/lib/session-tokens.d.ts +25 -0
  37. package/dist/lib/session-tokens.d.ts.map +1 -0
  38. package/dist/lib/session-tokens.js +51 -0
  39. package/dist/lib/session-tokens.js.map +1 -0
  40. package/dist/lib/toast-format-grouped.d.ts.map +1 -1
  41. package/dist/lib/toast-format-grouped.js +5 -10
  42. package/dist/lib/toast-format-grouped.js.map +1 -1
  43. package/dist/plugin.d.ts.map +1 -1
  44. package/dist/plugin.js +30 -188
  45. package/dist/plugin.js.map +1 -1
  46. package/package.json +1 -1
@@ -6,7 +6,8 @@
6
6
  * - Uses one line per limit, grouped under provider headers
7
7
  * - Includes session token summary (input/output per model)
8
8
  */
9
- import { bar, clampInt, formatTokenCount, padLeft, padRight, shortenModelName, } from "./format-utils.js";
9
+ import { bar, clampInt, padRight } from "./format-utils.js";
10
+ import { renderSessionTokensLines } from "./session-tokens-format.js";
10
11
  /**
11
12
  * Format reset time in compact form (different from toast countdown).
12
13
  * Uses seconds/minutes/hours/days format for /quota command.
@@ -99,15 +100,10 @@ export function formatQuotaCommand(params) {
99
100
  }
100
101
  }
101
102
  // Add session token summary (if data available and non-empty)
102
- if (params.sessionTokens && params.sessionTokens.models.length > 0) {
103
+ const tokenLines = renderSessionTokensLines(params.sessionTokens);
104
+ if (tokenLines.length > 0) {
103
105
  lines.push("");
104
- lines.push("Session Tokens");
105
- for (const model of params.sessionTokens.models) {
106
- const shortName = shortenModelName(model.modelID, 20);
107
- const inStr = formatTokenCount(model.input);
108
- const outStr = formatTokenCount(model.output);
109
- lines.push(` ${padRight(shortName, 20)} ${padLeft(inStr, 6)} in ${padLeft(outStr, 6)} out`);
110
- }
106
+ lines.push(...tokenLines);
111
107
  }
112
108
  if (params.errors.length > 0) {
113
109
  lines.push("");
@@ -1 +1 @@
1
- {"version":3,"file":"quota-command-format.js","sourceRoot":"","sources":["../../src/lib/quota-command-format.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EACL,GAAG,EACH,QAAQ,EACR,gBAAgB,EAChB,OAAO,EACP,QAAQ,EACR,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAG3B;;;GAGG;AACH,SAAS,sBAAsB,CAAC,WAAmB;IACjD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,WAAW,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACpE,IAAI,WAAW,GAAG,EAAE;QAAE,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC;IAC1D,IAAI,WAAW,GAAG,IAAI;QAAE,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC,GAAG,CAAC;IACjE,IAAI,WAAW,GAAG,KAAK;QAAE,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC;IACrE,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,KAAK,CAAC,GAAG,CAAC;AAC/C,CAAC;AAED,SAAS,cAAc,CAAC,GAAY;IAClC,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,CAAC;IACpB,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;IAClC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IACnC,MAAM,WAAW,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC;IAC5C,OAAO,eAAe,sBAAsB,CAAC,WAAW,CAAC,GAAG,CAAC;AAC/D,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAa;IACzC,0EAA0E;IAC1E,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;IACnD,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,EAAE,CAAC;IAClD,OAAO,IAAI,KAAK,CAAC,IAAI,EAAE,GAAG,CAAC;AAC7B,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAa;IACzC,MAAM,CAAC,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IAC9B,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,OAAO,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,SAAS,CAAC;AAC/E,CAAC;AAED,SAAS,aAAa,CAAC,OAA0B;IAC/C,MAAM,GAAG,GAAsB,EAAE,CAAC;IAClC,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;YACZ,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACZ,SAAS;QACX,CAAC;QAED,2EAA2E;QAC3E,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;QAChD,IAAI,CAAC,IAAI,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;YAC5C,GAAG,CAAC,IAAI,CAAC;gBACP,GAAG,CAAC;gBACJ,KAAK,EAAE,uBAAuB,CAAC,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,GAAG;gBAC7C,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,GAAG;aAC1B,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QAED,oDAAoD;QACpD,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;IACtD,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,MAIlC;IACC,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAE9C,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,MAAM,MAAM,GAAG,IAAI,GAAG,EAA6B,CAAC;IACpD,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACjC,IAAI,CAAC,CAAC;YAAE,SAAS;QACjB,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC3B,IAAI,IAAI;YAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;aAClB,CAAC;YACJ,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACnB,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IAED,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAE/B,MAAM,QAAQ,GAAG,EAAE,CAAC;IACpB,MAAM,OAAO,GAAG,EAAE,CAAC;IAEnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3C,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,CAAE,CAAC;QACzB,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAEjC,IAAI,CAAC,GAAG,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAE1B,KAAK,CAAC,IAAI,CAAC,KAAK,oBAAoB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAE3C,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;YAC7C,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;YAC1C,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC;YACnD,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YAChD,KAAK,CAAC,IAAI,CAAC,KAAK,QAAQ,IAAI,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,KAAK,GAAG,SAAS,MAAM,EAAE,CAAC,CAAC;QAC3E,CAAC;IACH,CAAC;IAED,8DAA8D;IAC9D,IAAI,MAAM,CAAC,aAAa,IAAI,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAE7B,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC;YAChD,MAAM,SAAS,GAAG,gBAAgB,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YACtD,MAAM,KAAK,GAAG,gBAAgB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC5C,MAAM,MAAM,GAAG,gBAAgB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAC9C,KAAK,CAAC,IAAI,CACR,KAAK,QAAQ,CAAC,SAAS,EAAE,EAAE,CAAC,KAAK,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,QAAQ,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CACnF,CAAC;QACJ,CAAC;IACH,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YAChC,KAAK,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,KAAK,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
1
+ {"version":3,"file":"quota-command-format.js","sourceRoot":"","sources":["../../src/lib/quota-command-format.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Shared "Session Tokens" rendering block.
3
+ *
4
+ * Extracted from format.ts, toast-format-grouped.ts, and
5
+ * quota-command-format.ts to eliminate verbatim duplication.
6
+ */
7
+ import type { SessionTokensData } from "./entries.js";
8
+ /**
9
+ * Render the "Session Tokens" section lines.
10
+ *
11
+ * Returns an empty array when there is no data to display.
12
+ * Callers are responsible for inserting a leading blank line if needed.
13
+ */
14
+ export declare function renderSessionTokensLines(sessionTokens?: SessionTokensData): string[];
15
+ //# sourceMappingURL=session-tokens-format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-tokens-format.d.ts","sourceRoot":"","sources":["../../src/lib/session-tokens-format.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAGtD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,aAAa,CAAC,EAAE,iBAAiB,GAAG,MAAM,EAAE,CAcpF"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Shared "Session Tokens" rendering block.
3
+ *
4
+ * Extracted from format.ts, toast-format-grouped.ts, and
5
+ * quota-command-format.ts to eliminate verbatim duplication.
6
+ */
7
+ import { formatTokenCount, padLeft, padRight, shortenModelName } from "./format-utils.js";
8
+ /**
9
+ * Render the "Session Tokens" section lines.
10
+ *
11
+ * Returns an empty array when there is no data to display.
12
+ * Callers are responsible for inserting a leading blank line if needed.
13
+ */
14
+ export function renderSessionTokensLines(sessionTokens) {
15
+ if (!sessionTokens || sessionTokens.models.length === 0)
16
+ return [];
17
+ const lines = [];
18
+ lines.push("Session Tokens");
19
+ for (const model of sessionTokens.models) {
20
+ const shortName = shortenModelName(model.modelID, 20);
21
+ const inStr = formatTokenCount(model.input);
22
+ const outStr = formatTokenCount(model.output);
23
+ lines.push(` ${padRight(shortName, 20)} ${padLeft(inStr, 6)} in ${padLeft(outStr, 6)} out`);
24
+ }
25
+ return lines;
26
+ }
27
+ //# sourceMappingURL=session-tokens-format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-tokens-format.js","sourceRoot":"","sources":["../../src/lib/session-tokens-format.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE1F;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB,CAAC,aAAiC;IACxE,IAAI,CAAC,aAAa,IAAI,aAAa,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEnE,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAE7B,KAAK,MAAM,KAAK,IAAI,aAAa,CAAC,MAAM,EAAE,CAAC;QACzC,MAAM,SAAS,GAAG,gBAAgB,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QACtD,MAAM,KAAK,GAAG,gBAAgB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC5C,MAAM,MAAM,GAAG,gBAAgB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC9C,KAAK,CAAC,IAAI,CAAC,KAAK,QAAQ,CAAC,SAAS,EAAE,EAAE,CAAC,KAAK,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,QAAQ,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IACjG,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Shared session-token fetching helper.
3
+ *
4
+ * Consolidates the duplicated try/catch + error-capture logic that was
5
+ * previously inlined in both `fetchQuotaMessage()` and
6
+ * `fetchQuotaCommandMessage()` in plugin.ts.
7
+ */
8
+ import type { SessionTokensData } from "./entries.js";
9
+ import type { SessionTokenError } from "./quota-status.js";
10
+ export interface SessionTokenFetchResult {
11
+ sessionTokens?: SessionTokensData;
12
+ error?: SessionTokenError;
13
+ }
14
+ /**
15
+ * Fetch session token summary for display.
16
+ *
17
+ * @returns `sessionTokens` on success (undefined if no data),
18
+ * `error` on failure (for diagnostics).
19
+ * When both are undefined the feature was disabled or sessionID missing.
20
+ */
21
+ export declare function fetchSessionTokensForDisplay(params: {
22
+ enabled: boolean;
23
+ sessionID?: string;
24
+ }): Promise<SessionTokenFetchResult>;
25
+ //# sourceMappingURL=session-tokens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-tokens.d.ts","sourceRoot":"","sources":["../../src/lib/session-tokens.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEtD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,MAAM,WAAW,uBAAuB;IACtC,aAAa,CAAC,EAAE,iBAAiB,CAAC;IAClC,KAAK,CAAC,EAAE,iBAAiB,CAAC;CAC3B;AAED;;;;;;GAMG;AACH,wBAAsB,4BAA4B,CAAC,MAAM,EAAE;IACzD,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAiCnC"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Shared session-token fetching helper.
3
+ *
4
+ * Consolidates the duplicated try/catch + error-capture logic that was
5
+ * previously inlined in both `fetchQuotaMessage()` and
6
+ * `fetchQuotaCommandMessage()` in plugin.ts.
7
+ */
8
+ import { getSessionTokenSummary, SessionNotFoundError } from "./quota-stats.js";
9
+ /**
10
+ * Fetch session token summary for display.
11
+ *
12
+ * @returns `sessionTokens` on success (undefined if no data),
13
+ * `error` on failure (for diagnostics).
14
+ * When both are undefined the feature was disabled or sessionID missing.
15
+ */
16
+ export async function fetchSessionTokensForDisplay(params) {
17
+ if (!params.enabled || !params.sessionID)
18
+ return {};
19
+ try {
20
+ const summary = await getSessionTokenSummary(params.sessionID);
21
+ if (summary && summary.models.length > 0) {
22
+ return {
23
+ sessionTokens: {
24
+ models: summary.models,
25
+ totalInput: summary.totalInput,
26
+ totalOutput: summary.totalOutput,
27
+ },
28
+ };
29
+ }
30
+ // Success but no data — clear any previous error
31
+ return {};
32
+ }
33
+ catch (err) {
34
+ if (err instanceof SessionNotFoundError) {
35
+ return {
36
+ error: {
37
+ sessionID: err.sessionID,
38
+ error: err.message,
39
+ checkedPath: err.checkedPath,
40
+ },
41
+ };
42
+ }
43
+ return {
44
+ error: {
45
+ sessionID: params.sessionID,
46
+ error: err instanceof Error ? err.message : String(err),
47
+ },
48
+ };
49
+ }
50
+ }
51
+ //# sourceMappingURL=session-tokens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-tokens.js","sourceRoot":"","sources":["../../src/lib/session-tokens.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAQhF;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAAC,MAGlD;IACC,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,SAAS;QAAE,OAAO,EAAE,CAAC;IAEpD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,sBAAsB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC/D,IAAI,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzC,OAAO;gBACL,aAAa,EAAE;oBACb,MAAM,EAAE,OAAO,CAAC,MAAM;oBACtB,UAAU,EAAE,OAAO,CAAC,UAAU;oBAC9B,WAAW,EAAE,OAAO,CAAC,WAAW;iBACjC;aACF,CAAC;QACJ,CAAC;QACD,iDAAiD;QACjD,OAAO,EAAE,CAAC;IACZ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,oBAAoB,EAAE,CAAC;YACxC,OAAO;gBACL,KAAK,EAAE;oBACL,SAAS,EAAE,GAAG,CAAC,SAAS;oBACxB,KAAK,EAAE,GAAG,CAAC,OAAO;oBAClB,WAAW,EAAE,GAAG,CAAC,WAAW;iBAC7B;aACF,CAAC;QACJ,CAAC;QACD,OAAO;YACL,KAAK,EAAE;gBACL,SAAS,EAAE,MAAM,CAAC,SAAS;gBAC3B,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;aACxD;SACF,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"toast-format-grouped.d.ts","sourceRoot":"","sources":["../../src/lib/toast-format-grouped.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAWxF,MAAM,MAAM,eAAe,GAAG,eAAe,GAAG;IAC9C,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAQF,wBAAgB,sBAAsB,CAAC,MAAM,EAAE;IAC7C,MAAM,CAAC,EAAE;QACP,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,OAAO,CAAC,EAAE,eAAe,EAAE,CAAC;IAC5B,MAAM,CAAC,EAAE,eAAe,EAAE,CAAC;IAC3B,aAAa,CAAC,EAAE,iBAAiB,CAAC;CACnC,GAAG,MAAM,CAsGT"}
1
+ {"version":3,"file":"toast-format-grouped.d.ts","sourceRoot":"","sources":["../../src/lib/toast-format-grouped.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAIxF,MAAM,MAAM,eAAe,GAAG,eAAe,GAAG;IAC9C,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAQF,wBAAgB,sBAAsB,CAAC,MAAM,EAAE;IAC7C,MAAM,CAAC,EAAE;QACP,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,OAAO,CAAC,EAAE,eAAe,EAAE,CAAC;IAC5B,MAAM,CAAC,EAAE,eAAe,EAAE,CAAC;IAC3B,aAAa,CAAC,EAAE,iBAAiB,CAAC;CACnC,GAAG,MAAM,CA6FT"}
@@ -4,7 +4,8 @@
4
4
  * Renders quota entries grouped by provider/account with compact bars.
5
5
  * Designed to feel like a status dashboard while still respecting OpenCode toast width.
6
6
  */
7
- import { bar, clampInt, formatResetCountdown, formatTokenCount, padLeft, padRight, shortenModelName, } from "./format-utils.js";
7
+ import { bar, clampInt, formatResetCountdown, padLeft, padRight } from "./format-utils.js";
8
+ import { renderSessionTokensLines } from "./session-tokens-format.js";
8
9
  function splitGroupName(name) {
9
10
  // Heuristic: "Label (group)" -> group is label, label is empty.
10
11
  // Prefer explicit group/label metadata when available.
@@ -87,17 +88,11 @@ export function formatQuotaRowsGrouped(params) {
87
88
  lines.push(`${err.label}: ${err.message}`);
88
89
  }
89
90
  // Add session token summary (if data available and non-empty)
90
- if (params.sessionTokens && params.sessionTokens.models.length > 0) {
91
+ const tokenLines = renderSessionTokensLines(params.sessionTokens);
92
+ if (tokenLines.length > 0) {
91
93
  if (lines.length > 0)
92
94
  lines.push("");
93
- lines.push("Session Tokens");
94
- for (const model of params.sessionTokens.models) {
95
- // Shorten model name for compact display
96
- const shortName = shortenModelName(model.modelID, 20);
97
- const inStr = formatTokenCount(model.input);
98
- const outStr = formatTokenCount(model.output);
99
- lines.push(` ${padRight(shortName, 20)} ${padLeft(inStr, 6)} in ${padLeft(outStr, 6)} out`);
100
- }
95
+ lines.push(...tokenLines);
101
96
  }
102
97
  return lines.join("\n");
103
98
  }
@@ -1 +1 @@
1
- {"version":3,"file":"toast-format-grouped.js","sourceRoot":"","sources":["../../src/lib/toast-format-grouped.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"toast-format-grouped.js","sourceRoot":"","sources":["../../src/lib/toast-format-grouped.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAwOlD;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAslC9B,CAAC"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAyOlD;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,MA+6B9B,CAAC"}
package/dist/plugin.js CHANGED
@@ -12,11 +12,14 @@ import { formatQuotaRows } from "./lib/format.js";
12
12
  import { formatQuotaCommand } from "./lib/quota-command-format.js";
13
13
  import { getProviders } from "./providers/registry.js";
14
14
  import { tool } from "@opencode-ai/plugin";
15
- import { aggregateUsage, getSessionTokenSummary, SessionNotFoundError } from "./lib/quota-stats.js";
15
+ import { aggregateUsage } from "./lib/quota-stats.js";
16
+ import { fetchSessionTokensForDisplay } from "./lib/session-tokens.js";
16
17
  import { formatQuotaStatsReport } from "./lib/quota-stats-format.js";
17
18
  import { buildQuotaStatusReport } from "./lib/quota-status.js";
18
19
  import { refreshGoogleTokensForAllAccounts } from "./lib/google.js";
19
20
  import { resetFirmwareQuotaWindow } from "./lib/firmware.js";
21
+ import { parseOptionalJsonArgs, parseQuotaBetweenArgs, startOfLocalDayMs, startOfNextLocalDayMs, formatYmd, } from "./lib/command-parsing.js";
22
+ import { handled } from "./lib/command-handled.js";
20
23
  /** All token report command specifications */
21
24
  const TOKEN_REPORT_COMMANDS = [
22
25
  {
@@ -77,12 +80,6 @@ const TOKEN_REPORT_COMMANDS = [
77
80
  template: "/tokens_between",
78
81
  description: "Token + cost report between two YYYY-MM-DD dates (local timezone, inclusive).",
79
82
  titleForRange: (startYmd, endYmd) => {
80
- const formatYmd = (ymd) => {
81
- const y = String(ymd.y).padStart(4, "0");
82
- const m = String(ymd.m).padStart(2, "0");
83
- const d = String(ymd.d).padStart(2, "0");
84
- return `${y}-${m}-${d}`;
85
- };
86
83
  return `Tokens used (${formatYmd(startYmd)} .. ${formatYmd(endYmd)}) (/tokens_between)`;
87
84
  },
88
85
  metadataTitle: "Tokens used (Date Range)",
@@ -180,117 +177,6 @@ export const QuotaToastPlugin = async ({ client }) => {
180
177
  })();
181
178
  return configInFlight;
182
179
  }
183
- function parseOptionalJsonArgs(input) {
184
- const raw = input?.trim() || "";
185
- if (!raw)
186
- return { ok: true, value: {} };
187
- try {
188
- const parsed = JSON.parse(raw);
189
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
190
- return { ok: false, error: 'Arguments must be a JSON object (e.g. {"force":true}).' };
191
- }
192
- return { ok: true, value: parsed };
193
- }
194
- catch {
195
- return { ok: false, error: "Failed to parse JSON arguments." };
196
- }
197
- }
198
- /**
199
- * Parse a YYYY-MM-DD string. Returns null if invalid format or invalid date.
200
- */
201
- function parseYyyyMmDd(input) {
202
- const pattern = /^\d{4}-\d{2}-\d{2}$/;
203
- if (!pattern.test(input))
204
- return null;
205
- const [yStr, mStr, dStr] = input.split("-");
206
- const y = parseInt(yStr, 10);
207
- const m = parseInt(mStr, 10);
208
- const d = parseInt(dStr, 10);
209
- // Validate by round-trip: construct a Date and check components match
210
- const date = new Date(y, m - 1, d);
211
- if (date.getFullYear() !== y || date.getMonth() !== m - 1 || date.getDate() !== d) {
212
- return null; // Invalid date (e.g., 2026-02-31)
213
- }
214
- return { y, m, d };
215
- }
216
- /**
217
- * Get the start of a local day (midnight) in milliseconds.
218
- */
219
- function startOfLocalDayMs(ymd) {
220
- return new Date(ymd.y, ymd.m - 1, ymd.d).getTime();
221
- }
222
- /**
223
- * Get the start of the next local day (midnight of the following day) in milliseconds.
224
- * Used for inclusive end date: untilMs = startOfNextLocalDayMs(end) (exclusive upper bound).
225
- */
226
- function startOfNextLocalDayMs(ymd) {
227
- return new Date(ymd.y, ymd.m - 1, ymd.d + 1).getTime();
228
- }
229
- /**
230
- * Parse /tokens_between arguments. Supports:
231
- * - Positional: "2026-01-01 2026-01-15"
232
- * - JSON: {"starting_date":"2026-01-01","ending_date":"2026-01-15"}
233
- */
234
- function parseQuotaBetweenArgs(input) {
235
- const raw = input?.trim() || "";
236
- if (!raw) {
237
- return {
238
- ok: false,
239
- error: "Missing arguments. Expected two dates in YYYY-MM-DD format.",
240
- };
241
- }
242
- let startStr;
243
- let endStr;
244
- if (raw.startsWith("{")) {
245
- // JSON format
246
- try {
247
- const parsed = JSON.parse(raw);
248
- startStr = String(parsed["starting_date"] ?? parsed["startingDate"] ?? "");
249
- endStr = String(parsed["ending_date"] ?? parsed["endingDate"] ?? "");
250
- }
251
- catch {
252
- return { ok: false, error: "Failed to parse JSON arguments." };
253
- }
254
- }
255
- else {
256
- // Positional format: split on whitespace
257
- const parts = raw.split(/\s+/);
258
- if (parts.length !== 2) {
259
- return {
260
- ok: false,
261
- error: "Expected exactly two dates in YYYY-MM-DD format.",
262
- };
263
- }
264
- [startStr, endStr] = parts;
265
- }
266
- const startYmd = parseYyyyMmDd(startStr);
267
- if (!startYmd) {
268
- return { ok: false, error: `Invalid starting date: "${startStr}". Expected YYYY-MM-DD.` };
269
- }
270
- const endYmd = parseYyyyMmDd(endStr);
271
- if (!endYmd) {
272
- return { ok: false, error: `Invalid ending date: "${endStr}". Expected YYYY-MM-DD.` };
273
- }
274
- // Check end >= start
275
- const startMs = startOfLocalDayMs(startYmd);
276
- const endMs = startOfLocalDayMs(endYmd);
277
- if (endMs < startMs) {
278
- return {
279
- ok: false,
280
- error: `Ending date (${endStr}) is before starting date (${startStr}).`,
281
- };
282
- }
283
- return { ok: true, startYmd, endYmd };
284
- }
285
- /**
286
- * Format a Ymd as YYYY-MM-DD string.
287
- */
288
- function formatYmd(ymd) {
289
- const y = String(ymd.y).padStart(4, "0");
290
- const m = String(ymd.m).padStart(2, "0");
291
- const d = String(ymd.d).padStart(2, "0");
292
- return `${y}-${m}-${d}`;
293
- }
294
180
  // Best-effort async init (do not await)
295
181
  void (async () => {
296
182
  await refreshConfig();
@@ -490,35 +376,13 @@ export const QuotaToastPlugin = async ({ client }) => {
490
376
  // Fetch session tokens if enabled and sessionID is available
491
377
  let sessionTokens;
492
378
  if (config.showSessionTokens && sessionID) {
493
- try {
494
- const summary = await getSessionTokenSummary(sessionID);
495
- if (summary && summary.models.length > 0) {
496
- sessionTokens = {
497
- models: summary.models,
498
- totalInput: summary.totalInput,
499
- totalOutput: summary.totalOutput,
500
- };
501
- }
502
- // Clear any previous error on success
503
- lastSessionTokenError = undefined;
504
- }
505
- catch (err) {
506
- // Capture error for /quota_status diagnostics
507
- if (err instanceof SessionNotFoundError) {
508
- lastSessionTokenError = {
509
- sessionID: err.sessionID,
510
- error: err.message,
511
- checkedPath: err.checkedPath,
512
- };
513
- }
514
- else {
515
- lastSessionTokenError = {
516
- sessionID,
517
- error: err instanceof Error ? err.message : String(err),
518
- };
519
- }
520
- // Toast still displays without session tokens
521
- }
379
+ const stResult = await fetchSessionTokensForDisplay({
380
+ enabled: config.showSessionTokens,
381
+ sessionID,
382
+ });
383
+ sessionTokens = stResult.sessionTokens;
384
+ // Update diagnostics state: clear on success (no error returned), set on failure
385
+ lastSessionTokenError = stResult.error;
522
386
  }
523
387
  if (entries.length > 0) {
524
388
  const formatted = formatQuotaRows({
@@ -647,35 +511,13 @@ export const QuotaToastPlugin = async ({ client }) => {
647
511
  // Fetch session tokens if enabled and sessionID is available
648
512
  let sessionTokens;
649
513
  if (config.showSessionTokens && sessionID) {
650
- try {
651
- const summary = await getSessionTokenSummary(sessionID);
652
- if (summary && summary.models.length > 0) {
653
- sessionTokens = {
654
- models: summary.models,
655
- totalInput: summary.totalInput,
656
- totalOutput: summary.totalOutput,
657
- };
658
- }
659
- // Clear any previous error on success
660
- lastSessionTokenError = undefined;
661
- }
662
- catch (err) {
663
- // Capture error for /quota_status diagnostics
664
- if (err instanceof SessionNotFoundError) {
665
- lastSessionTokenError = {
666
- sessionID: err.sessionID,
667
- error: err.message,
668
- checkedPath: err.checkedPath,
669
- };
670
- }
671
- else {
672
- lastSessionTokenError = {
673
- sessionID,
674
- error: err instanceof Error ? err.message : String(err),
675
- };
676
- }
677
- // Command still returns without session tokens
678
- }
514
+ const stResult = await fetchSessionTokensForDisplay({
515
+ enabled: config.showSessionTokens,
516
+ sessionID,
517
+ });
518
+ sessionTokens = stResult.sessionTokens;
519
+ // Update diagnostics state: clear on success (no error returned), set on failure
520
+ lastSessionTokenError = stResult.error;
679
521
  }
680
522
  return formatQuotaCommand({ entries, errors, sessionTokens });
681
523
  }
@@ -834,10 +676,10 @@ export const QuotaToastPlugin = async ({ client }) => {
834
676
  await injectRawOutput(sessionID, `Quota unavailable\n\nProviders detected (${availableIds.join(", ")}) but returned no data. This may be a temporary API error.\n\nRun /quota_status for diagnostics.`);
835
677
  }
836
678
  }
837
- throw new Error("__QUOTA_COMMAND_HANDLED__");
679
+ handled();
838
680
  }
839
681
  await injectRawOutput(sessionID, msg);
840
- throw new Error("__QUOTA_COMMAND_HANDLED__");
682
+ handled();
841
683
  }
842
684
  const untilMs = Date.now();
843
685
  // Handle token report commands (/tokens_*)
@@ -848,7 +690,7 @@ export const QuotaToastPlugin = async ({ client }) => {
848
690
  const parsed = parseQuotaBetweenArgs(input.arguments);
849
691
  if (!parsed.ok) {
850
692
  await injectRawOutput(sessionID, `Invalid arguments for /${spec.id}\n\n${parsed.error}\n\nExpected: /${spec.id} YYYY-MM-DD YYYY-MM-DD\nExample: /${spec.id} 2026-01-01 2026-01-15`);
851
- throw new Error("__QUOTA_COMMAND_HANDLED__");
693
+ handled();
852
694
  }
853
695
  const sinceMs = startOfLocalDayMs(parsed.startYmd);
854
696
  const rangeUntilMs = startOfNextLocalDayMs(parsed.endYmd); // Exclusive upper bound for inclusive end date
@@ -859,7 +701,7 @@ export const QuotaToastPlugin = async ({ client }) => {
859
701
  sessionID,
860
702
  });
861
703
  await injectRawOutput(sessionID, out);
862
- throw new Error("__QUOTA_COMMAND_HANDLED__");
704
+ handled();
863
705
  }
864
706
  // Non-between token report commands
865
707
  let sinceMs;
@@ -897,14 +739,14 @@ export const QuotaToastPlugin = async ({ client }) => {
897
739
  topSessions,
898
740
  });
899
741
  await injectRawOutput(sessionID, out);
900
- throw new Error("__QUOTA_COMMAND_HANDLED__");
742
+ handled();
901
743
  }
902
744
  // Handle /quota_status (diagnostics - not a token report)
903
745
  if (cmd === "quota_status") {
904
746
  const parsed = parseOptionalJsonArgs(input.arguments);
905
747
  if (!parsed.ok) {
906
748
  await injectRawOutput(sessionID, `Invalid arguments for /quota_status\n\n${parsed.error}\n\nExample:\n/quota_status {"refreshGoogleTokens": true}`);
907
- throw new Error("__QUOTA_COMMAND_HANDLED__");
749
+ handled();
908
750
  }
909
751
  const out = await buildStatusReport({
910
752
  refreshGoogleTokens: parsed.value["refreshGoogleTokens"] === true,
@@ -915,7 +757,7 @@ export const QuotaToastPlugin = async ({ client }) => {
915
757
  sessionID,
916
758
  });
917
759
  await injectRawOutput(sessionID, out);
918
- throw new Error("__QUOTA_COMMAND_HANDLED__");
760
+ handled();
919
761
  }
920
762
  // Handle /firmware_reset_window (reset 5-hour spending window)
921
763
  if (cmd === "firmware_reset_window") {
@@ -932,22 +774,22 @@ export const QuotaToastPlugin = async ({ client }) => {
932
774
  }
933
775
  catch {
934
776
  await injectRawOutput(sessionID, `Invalid JSON arguments for /firmware_reset_window\n\nTo proceed, run:\n/firmware_reset_window confirm`);
935
- throw new Error("__QUOTA_COMMAND_HANDLED__");
777
+ handled();
936
778
  }
937
779
  }
938
780
  // Require explicit confirmation (destructive action with limited weekly resets)
939
781
  if (!confirmed) {
940
782
  await injectRawOutput(sessionID, `⚠️ This will reset your Firmware 5-hour spending window.\nYou have a maximum of 2 resets per week.\n\nTo proceed, run:\n/firmware_reset_window confirm`);
941
- throw new Error("__QUOTA_COMMAND_HANDLED__");
783
+ handled();
942
784
  }
943
785
  const result = await resetFirmwareQuotaWindow();
944
786
  if (!result) {
945
787
  await injectRawOutput(sessionID, "Firmware API key not configured. Cannot reset window.");
946
- throw new Error("__QUOTA_COMMAND_HANDLED__");
788
+ handled();
947
789
  }
948
790
  if (!result.success) {
949
791
  await injectRawOutput(sessionID, `Failed to reset Firmware window:\n${result.error}`);
950
- throw new Error("__QUOTA_COMMAND_HANDLED__");
792
+ handled();
951
793
  }
952
794
  // Build success message
953
795
  const resetsLeft = result.windowResetsRemaining;
@@ -958,7 +800,7 @@ export const QuotaToastPlugin = async ({ client }) => {
958
800
  const quotaMsg = await fetchQuotaCommandMessage("command:/firmware_reset_window", sessionID);
959
801
  const successOutput = `✓ Firmware 5-hour window reset successful${resetsMsg}${quotaMsg ? `\n\n${quotaMsg}` : ""}`;
960
802
  await injectRawOutput(sessionID, successOutput);
961
- throw new Error("__QUOTA_COMMAND_HANDLED__");
803
+ handled();
962
804
  }
963
805
  },
964
806
  tool: {