@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.
- package/README.md +1 -1
- package/dist/lib/chutes.d.ts.map +1 -1
- package/dist/lib/chutes.js +1 -5
- package/dist/lib/chutes.js.map +1 -1
- package/dist/lib/command-handled.d.ts +13 -0
- package/dist/lib/command-handled.d.ts.map +1 -0
- package/dist/lib/command-handled.js +15 -0
- package/dist/lib/command-handled.js.map +1 -0
- package/dist/lib/command-parsing.d.ts +53 -0
- package/dist/lib/command-parsing.d.ts.map +1 -0
- package/dist/lib/command-parsing.js +121 -0
- package/dist/lib/command-parsing.js.map +1 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +26 -30
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/firmware.d.ts.map +1 -1
- package/dist/lib/firmware.js +1 -5
- package/dist/lib/firmware.js.map +1 -1
- package/dist/lib/format-utils.d.ts +5 -0
- package/dist/lib/format-utils.d.ts.map +1 -1
- package/dist/lib/format-utils.js +9 -0
- package/dist/lib/format-utils.js.map +1 -1
- package/dist/lib/format.d.ts.map +1 -1
- package/dist/lib/format.js +5 -10
- package/dist/lib/format.js.map +1 -1
- package/dist/lib/openai.d.ts.map +1 -1
- package/dist/lib/openai.js +1 -5
- package/dist/lib/openai.js.map +1 -1
- package/dist/lib/quota-command-format.d.ts.map +1 -1
- package/dist/lib/quota-command-format.js +5 -9
- package/dist/lib/quota-command-format.js.map +1 -1
- package/dist/lib/session-tokens-format.d.ts +15 -0
- package/dist/lib/session-tokens-format.d.ts.map +1 -0
- package/dist/lib/session-tokens-format.js +27 -0
- package/dist/lib/session-tokens-format.js.map +1 -0
- package/dist/lib/session-tokens.d.ts +25 -0
- package/dist/lib/session-tokens.d.ts.map +1 -0
- package/dist/lib/session-tokens.js +51 -0
- package/dist/lib/session-tokens.js.map +1 -0
- package/dist/lib/toast-format-grouped.d.ts.map +1 -1
- package/dist/lib/toast-format-grouped.js +5 -10
- package/dist/lib/toast-format-grouped.js.map +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +30 -188
- package/dist/plugin.js.map +1 -1
- 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,
|
|
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
|
-
|
|
103
|
+
const tokenLines = renderSessionTokensLines(params.sessionTokens);
|
|
104
|
+
if (tokenLines.length > 0) {
|
|
103
105
|
lines.push("");
|
|
104
|
-
lines.push(
|
|
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,
|
|
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;
|
|
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,
|
|
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
|
-
|
|
91
|
+
const tokenLines = renderSessionTokensLines(params.sessionTokens);
|
|
92
|
+
if (tokenLines.length > 0) {
|
|
91
93
|
if (lines.length > 0)
|
|
92
94
|
lines.push("");
|
|
93
|
-
lines.push(
|
|
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":"AAAA;;;;;GAKG;AAGH,OAAO,
|
|
1
|
+
{"version":3,"file":"toast-format-grouped.js","sourceRoot":"","sources":["../../src/lib/toast-format-grouped.ts"],"names":[],"mappings":"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"}
|
package/dist/plugin.d.ts.map
CHANGED
|
@@ -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;
|
|
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
|
|
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
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
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
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
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
|
-
|
|
679
|
+
handled();
|
|
838
680
|
}
|
|
839
681
|
await injectRawOutput(sessionID, msg);
|
|
840
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
788
|
+
handled();
|
|
947
789
|
}
|
|
948
790
|
if (!result.success) {
|
|
949
791
|
await injectRawOutput(sessionID, `Failed to reset Firmware window:\n${result.error}`);
|
|
950
|
-
|
|
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
|
-
|
|
803
|
+
handled();
|
|
962
804
|
}
|
|
963
805
|
},
|
|
964
806
|
tool: {
|