Skip to content

Commit 92b457b

Browse files
committed
Remove legacy quota tools; skip firmware confirm
Stop requiring explicit confirmation for /firmware_reset_window: the command handler and tool execution no longer block on confirm, though optional JSON args are still parsed for compatibility. The firmware_reset_window tool's confirm schema is now optional and marked deprecated. Removed several legacy quota_* tools (daily, weekly, monthly, all, today, session, between) and updated README docs to reflect the firmware reset behavior and that it consumes 1 of 2 weekly resets.
1 parent a85eaaa commit 92b457b

2 files changed

Lines changed: 6 additions & 181 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ Works automatically if OpenCode has Firmware configured. Alternatively, provide
118118

119119
The `apiKey` field supports `{env:VAR_NAME}` syntax or a direct key.
120120

121-
**Firmware-specific command:** Use `/firmware_reset_window` to manually reset your 5-hour spending window. Run `/firmware_reset_window {"confirm": true}` to confirm.
121+
**Firmware-specific command:** Use `/firmware_reset_window` to reset your 5-hour spending window (consumes 1 of 2 weekly resets).
122122

123123
</details>
124124

src/plugin.ts

Lines changed: 5 additions & 180 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,6 +1043,8 @@ export const QuotaToastPlugin: Plugin = async ({ client }) => {
10431043

10441044
// Handle /firmware_reset_window (reset 5-hour spending window)
10451045
if (cmd === "firmware_reset_window") {
1046+
// Note: Optional JSON args are still parsed for forward compatibility,
1047+
// but confirmation is no longer required.
10461048
const parsed = parseOptionalJsonArgs(input.arguments);
10471049
if (!parsed.ok) {
10481050
await injectRawOutput(
@@ -1052,15 +1054,6 @@ export const QuotaToastPlugin: Plugin = async ({ client }) => {
10521054
throw new Error("__QUOTA_COMMAND_HANDLED__");
10531055
}
10541056

1055-
// Require explicit confirmation to prevent accidental resets
1056-
if (parsed.value["confirm"] !== true) {
1057-
await injectRawOutput(
1058-
sessionID,
1059-
`⚠️ This will consume 1 of your 2 weekly window resets.\n\nTo confirm, run:\n/firmware_reset_window {"confirm": true}`,
1060-
);
1061-
throw new Error("__QUOTA_COMMAND_HANDLED__");
1062-
}
1063-
10641057
const result = await resetFirmwareQuotaWindow();
10651058

10661059
if (!result) {
@@ -1095,76 +1088,6 @@ export const QuotaToastPlugin: Plugin = async ({ client }) => {
10951088
},
10961089

10971090
tool: {
1098-
quota_daily: tool({
1099-
description: "Token + official API cost summary for the last 24 hours (rolling).",
1100-
args: {},
1101-
async execute(_args, context) {
1102-
const untilMs = Date.now();
1103-
const sinceMs = untilMs - 24 * 60 * 60 * 1000;
1104-
const out = await buildQuotaReport({
1105-
title: "Tokens used (Last 24 Hours) (/tokens_daily)",
1106-
sinceMs,
1107-
untilMs,
1108-
sessionID: context.sessionID,
1109-
});
1110-
context.metadata({ title: "Tokens used (Last 24 Hours)" });
1111-
await injectRawOutput(context.sessionID, out);
1112-
return ""; // Empty return - output already injected with noReply
1113-
},
1114-
}),
1115-
1116-
quota_weekly: tool({
1117-
description: "Token + official API cost summary for the last 7 days (rolling).",
1118-
args: {},
1119-
async execute(_args, context) {
1120-
const untilMs = Date.now();
1121-
const sinceMs = untilMs - 7 * 24 * 60 * 60 * 1000;
1122-
const out = await buildQuotaReport({
1123-
title: "Tokens used (Last 7 Days) (/tokens_weekly)",
1124-
sinceMs,
1125-
untilMs,
1126-
sessionID: context.sessionID,
1127-
});
1128-
context.metadata({ title: "Tokens used (Last 7 Days)" });
1129-
await injectRawOutput(context.sessionID, out);
1130-
return ""; // Empty return - output already injected with noReply
1131-
},
1132-
}),
1133-
1134-
quota_monthly: tool({
1135-
description: "Token + official API cost summary for the last 30 days (rolling).",
1136-
args: {},
1137-
async execute(_args, context) {
1138-
const untilMs = Date.now();
1139-
const sinceMs = untilMs - 30 * 24 * 60 * 60 * 1000;
1140-
const out = await buildQuotaReport({
1141-
title: "Tokens used (Last 30 Days) (/tokens_monthly)",
1142-
sinceMs,
1143-
untilMs,
1144-
sessionID: context.sessionID,
1145-
});
1146-
context.metadata({ title: "Tokens used (Last 30 Days)" });
1147-
await injectRawOutput(context.sessionID, out);
1148-
return ""; // Empty return - output already injected with noReply
1149-
},
1150-
}),
1151-
1152-
quota_all: tool({
1153-
description: "Token + official API cost summary for all locally saved OpenCode history.",
1154-
args: {},
1155-
async execute(_args, context) {
1156-
const out = await buildQuotaReport({
1157-
title: "Tokens used (All Time) (/tokens_all)",
1158-
sessionID: context.sessionID,
1159-
topModels: 12,
1160-
topSessions: 12,
1161-
});
1162-
context.metadata({ title: "Tokens used (All Time)" });
1163-
await injectRawOutput(context.sessionID, out);
1164-
return ""; // Empty return - output already injected with noReply
1165-
},
1166-
}),
1167-
11681091
quota_status: tool({
11691092
description:
11701093
"Diagnostics for toast + pricing + local storage (includes unknown pricing report).",
@@ -1196,114 +1119,16 @@ export const QuotaToastPlugin: Plugin = async ({ client }) => {
11961119
},
11971120
}),
11981121

1199-
quota_today: tool({
1200-
description: "Token + official API cost summary for today (calendar day, local timezone).",
1201-
args: {},
1202-
async execute(_args, context) {
1203-
const now = new Date();
1204-
const startOfDay = new Date(now.getFullYear(), now.getMonth(), now.getDate());
1205-
const sinceMs = startOfDay.getTime();
1206-
const untilMs = now.getTime();
1207-
const out = await buildQuotaReport({
1208-
title: "Tokens used (Today) (/tokens_today)",
1209-
sinceMs,
1210-
untilMs,
1211-
sessionID: context.sessionID,
1212-
});
1213-
context.metadata({ title: "Tokens used (Today)" });
1214-
await injectRawOutput(context.sessionID, out);
1215-
return ""; // Empty return - output already injected with noReply
1216-
},
1217-
}),
1218-
1219-
quota_session: tool({
1220-
description: "Token + official API cost summary for current session only.",
1221-
args: {},
1222-
async execute(_args, context) {
1223-
const out = await buildQuotaReport({
1224-
title: "Tokens used (Current Session) (/tokens_session)",
1225-
sessionID: context.sessionID,
1226-
filterSessionID: context.sessionID,
1227-
sessionOnly: true,
1228-
});
1229-
context.metadata({ title: "Tokens used (Current Session)" });
1230-
await injectRawOutput(context.sessionID, out);
1231-
return ""; // Empty return - output already injected with noReply
1232-
},
1233-
}),
1234-
1235-
quota_between: tool({
1236-
description:
1237-
"Token + official API cost summary between two YYYY-MM-DD dates (local timezone, inclusive).",
1238-
args: {
1239-
startingDate: tool.schema
1240-
.string()
1241-
.regex(/^\d{4}-\d{2}-\d{2}$/)
1242-
.describe("Starting date in YYYY-MM-DD format (local timezone)"),
1243-
endingDate: tool.schema
1244-
.string()
1245-
.regex(/^\d{4}-\d{2}-\d{2}$/)
1246-
.describe("Ending date in YYYY-MM-DD format (local timezone, inclusive)"),
1247-
},
1248-
async execute(args, context) {
1249-
const startYmd = parseYyyyMmDd(args.startingDate);
1250-
if (!startYmd) {
1251-
await injectRawOutput(
1252-
context.sessionID,
1253-
`Invalid starting date: "${args.startingDate}". Expected YYYY-MM-DD.`,
1254-
);
1255-
return "";
1256-
}
1257-
const endYmd = parseYyyyMmDd(args.endingDate);
1258-
if (!endYmd) {
1259-
await injectRawOutput(
1260-
context.sessionID,
1261-
`Invalid ending date: "${args.endingDate}". Expected YYYY-MM-DD.`,
1262-
);
1263-
return "";
1264-
}
1265-
const startMs = startOfLocalDayMs(startYmd);
1266-
const endMs = startOfLocalDayMs(endYmd);
1267-
if (endMs < startMs) {
1268-
await injectRawOutput(
1269-
context.sessionID,
1270-
`Ending date (${args.endingDate}) is before starting date (${args.startingDate}).`,
1271-
);
1272-
return "";
1273-
}
1274-
const sinceMs = startMs;
1275-
const untilMs = startOfNextLocalDayMs(endYmd); // Exclusive upper bound for inclusive end date
1276-
const startStr = formatYmd(startYmd);
1277-
const endStr = formatYmd(endYmd);
1278-
const out = await buildQuotaReport({
1279-
title: `Tokens used (${startStr} .. ${endStr}) (/tokens_between)`,
1280-
sinceMs,
1281-
untilMs,
1282-
sessionID: context.sessionID,
1283-
});
1284-
context.metadata({ title: "Tokens used (Date Range)" });
1285-
await injectRawOutput(context.sessionID, out);
1286-
return ""; // Empty return - output already injected with noReply
1287-
},
1288-
}),
1289-
12901122
firmware_reset_window: tool({
12911123
description:
12921124
"Manually reset your Firmware 5-hour spending window. Consumes 1 of 2 weekly resets.",
12931125
args: {
12941126
confirm: tool.schema
12951127
.boolean()
1296-
.describe("Must be true to proceed with the reset"),
1128+
.optional()
1129+
.describe("Deprecated: no longer required"),
12971130
},
1298-
async execute(args, context) {
1299-
if (!args.confirm) {
1300-
await injectRawOutput(
1301-
context.sessionID,
1302-
"⚠️ This will consume 1 of your 2 weekly window resets.\n\nPass confirm: true to proceed.",
1303-
);
1304-
return "";
1305-
}
1306-
1131+
async execute(_args, context) {
13071132
const result = await resetFirmwareQuotaWindow();
13081133

13091134
if (!result) {

0 commit comments

Comments
 (0)