Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions cli-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -27812,6 +27812,25 @@
"modulePath": "openreview/venue.js",
"sourceFile": "openreview/venue.js"
},
{
"site": "openrouter",
"name": "credits",
"description": "Read the OpenRouter total available credits balance from the settings/credits page.",
"access": "read",
"domain": "openrouter.ai",
"strategy": "cookie",
"browser": true,
"args": [],
"columns": [
"totalAvailable",
"currency"
],
"type": "js",
"modulePath": "openrouter/credits.js",
"sourceFile": "openrouter/credits.js",
"navigateBefore": true,
"siteSession": "persistent"
},
{
"site": "osv",
"name": "query",
Expand Down
71 changes: 71 additions & 0 deletions clis/openrouter/credits.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// OpenRouter credits balance summary.
// Reads the "Total available credits" balance from the settings/credits page.
// The value is exposed as an aria-label on the balance card, so we extract it
// from the DOM instead of relying on an undocumented internal API.

import { cli, Strategy } from '@jackwener/opencli/registry';
import { CommandExecutionError } from '@jackwener/opencli/errors';

const OR_DOMAIN = 'openrouter.ai';
const CREDITS_URL = 'https://openrouter.ai/settings/credits';

// Runs in the browser via page.evaluate. Backslashes are doubled because this
// string is interpolated into a template literal.
const EVAL_JS = `
var el = document.querySelector('[aria-label^="Total available credits:"]');
var total = null;
var currency = null;

if (el) {
var label = el.getAttribute('aria-label') || '';
var m = label.match(/Total available credits:\\s*\\$?\\s*([\\d,.]+)/);
if (m) {
total = m[1].replace(/,/g, '');
currency = 'USD';
}
}

// Fallback: scan the balance card text for a currency amount
if (total === null && el) {
var text = el.innerText || '';
var tm = text.match(/([\\d,.]+)/);
if (tm) total = tm[1].replace(/,/g, '');
}

return { totalAvailable: total, currency: currency };
`;

cli({
site: 'openrouter',
name: 'credits',
access: 'read',
description: 'Read the OpenRouter total available credits balance from the settings/credits page.',
domain: OR_DOMAIN,
strategy: Strategy.COOKIE,
browser: true,
siteSession: 'persistent',
navigateBefore: true,
args: [],
columns: [
'totalAvailable',
'currency',
],
func: async (page) => {
await page.goto(CREDITS_URL);
await page.wait(3);

const data = await page.evaluate(`(() => {${EVAL_JS}})()`);

if (!data || typeof data !== 'object' || Array.isArray(data)) {
throw new CommandExecutionError('openrouter credits returned malformed payload: expected object');
}
if (!data.totalAvailable) {
throw new CommandExecutionError('openrouter credits returned malformed payload: missing totalAvailable balance');
}

return [{
totalAvailable: String(data.totalAvailable),
currency: String(data.currency || 'USD'),
}];
},
});
Loading