opencode-ccgo-provider/scripts/quota.mjs

92 lines
3.0 KiB
JavaScript

// Print the live CommandCode quota (5-hour, weekly, monthly) from the alpha billing
// endpoints. The same data drives the TUI sidebar and /cc-usage command; this script is
// the headless check and does not need opencode running.
//
// Run: node scripts/quota.mjs [--config <path>] [--base-url <url>] [--json] (build first: npm run build)
import { readFileSync } from "node:fs";
import { homedir } from "node:os";
import { join } from "node:path";
import { fetchQuota, formatQuota } from "../dist/quota.js";
function parseArgs(argv) {
const opts = {
config: join(homedir(), ".config", "opencode", "opencode.json"),
baseURL: undefined,
json: false,
};
for (let i = 0; i < argv.length; i++) {
const arg = argv[i];
const value = () => {
const next = argv[++i];
if (next === undefined) throw new Error(`Missing value for ${arg}`);
return next;
};
switch (arg) {
case "--config":
opts.config = value();
break;
case "--base-url":
opts.baseURL = value();
break;
case "--json":
opts.json = true;
break;
case "-h":
case "--help":
console.log(
[
"Print CommandCode quota from the alpha billing endpoints.",
"",
"Usage: node scripts/quota.mjs [options]",
" --config <path> opencode config to read (default ~/.config/opencode/opencode.json)",
" --base-url <url> upstream origin (default from config or api.commandcode.ai)",
" --json print the raw quota object instead of formatted text",
].join("\n"),
);
process.exit(0);
break;
default:
throw new Error(`Unknown argument: ${arg}`);
}
}
return opts;
}
function readConfig(path) {
try {
return JSON.parse(readFileSync(path, "utf8"));
} catch {
return {};
}
}
function resolveKey(config, env) {
const fromEnv = env.COMMANDCODE_API_KEY;
if (fromEnv && fromEnv.trim()) return fromEnv.trim();
const options = config?.provider?.commandcode?.options ?? {};
const fromConfig = options.apiKey;
if (typeof fromConfig === "string" && fromConfig.trim()) return fromConfig.trim();
const auth = options.headers?.Authorization ?? options.headers?.authorization;
if (typeof auth === "string" && auth.trim()) return auth.replace(/^Bearer\s+/i, "").trim();
return undefined;
}
const opts = parseArgs(process.argv.slice(2));
const config = readConfig(opts.config);
const apiKey = resolveKey(config, process.env);
if (!apiKey) {
console.error(
`No CommandCode API key found. Set COMMANDCODE_API_KEY or provider.commandcode.options.apiKey in ${opts.config}.`,
);
process.exit(1);
}
const baseURL = opts.baseURL ?? config?.provider?.commandcode?.options?.baseURL;
const result = await fetchQuota({ apiKey, baseURL: typeof baseURL === "string" ? baseURL : undefined });
if (!result.ok) {
console.error(result.error.message);
process.exit(1);
}
console.log(opts.json ? JSON.stringify(result.quota, null, 2) : formatQuota(result.quota));