troxy-cli 1.29.21 → 1.29.23
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/bin/troxy.js +41 -0
- package/package.json +1 -1
- package/src/api.js +1 -0
- package/src/init.js +12 -2
- package/src/tests/proxy-wiring.test.js +1 -1
package/bin/troxy.js
CHANGED
|
@@ -467,6 +467,46 @@ switch (command) {
|
|
|
467
467
|
break;
|
|
468
468
|
}
|
|
469
469
|
|
|
470
|
+
// ── Usage bar ────────────────────────────────────────────────────
|
|
471
|
+
case 'usage-bar': {
|
|
472
|
+
if (flags.help || flags.h) {
|
|
473
|
+
console.log(`
|
|
474
|
+
troxy usage-bar [options]
|
|
475
|
+
|
|
476
|
+
Shows what Troxy's model routing and context trimming actually did for
|
|
477
|
+
your Claude Code usage bar over a given period. Login required.
|
|
478
|
+
|
|
479
|
+
These are plain counts of things that already happened, not an estimated
|
|
480
|
+
percentage - how much longer your usage bar actually lasts depends on
|
|
481
|
+
your own mix of requests, so we report what Troxy did and let you judge
|
|
482
|
+
the effect on your own bar, rather than quote one shared number back at
|
|
483
|
+
everyone.
|
|
484
|
+
|
|
485
|
+
Options:
|
|
486
|
+
--period <days> Number of days to look back (default: 30)
|
|
487
|
+
|
|
488
|
+
Examples:
|
|
489
|
+
troxy usage-bar
|
|
490
|
+
troxy usage-bar --period 7
|
|
491
|
+
`);
|
|
492
|
+
process.exit(0);
|
|
493
|
+
}
|
|
494
|
+
const jwt = requireJwt();
|
|
495
|
+
const period = Number(flags.period || 30);
|
|
496
|
+
const d = await api.agentUsageBar(jwt, period);
|
|
497
|
+
console.log(`
|
|
498
|
+
Usage bar (last ${d.period_days} days)
|
|
499
|
+
──────────────────────────────────
|
|
500
|
+
Total requests: ${d.total_requests}
|
|
501
|
+
Swapped to cheaper model: ${d.swapped_to_cheaper_model}
|
|
502
|
+
Context trimmed: ${d.context_trimmed}
|
|
503
|
+
`);
|
|
504
|
+
if (d.thread_passthrough > 0) {
|
|
505
|
+
console.log(` Note: ${d.thread_passthrough} request(s) came in through Claude Desktop's thread mode, which Troxy can't currently route or trim - only Claude Code's terminal CLI gets the full benefit today.\n`);
|
|
506
|
+
}
|
|
507
|
+
break;
|
|
508
|
+
}
|
|
509
|
+
|
|
470
510
|
// ── Shorthand: troxy list [resource] ──────────────────────────
|
|
471
511
|
case 'list':
|
|
472
512
|
if (!sub || sub === 'policies') { await runPolicies(['list'], flags); break; }
|
|
@@ -814,6 +854,7 @@ switch (command) {
|
|
|
814
854
|
Activity & insights
|
|
815
855
|
troxy activity [--limit 50] [--mine]
|
|
816
856
|
troxy insights [--period 7]
|
|
857
|
+
troxy usage-bar [--period 7]
|
|
817
858
|
|
|
818
859
|
Simulate (test your policies against every checkpoint, not just payment)
|
|
819
860
|
troxy pay --merchant "Amazon" --amount 50
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "troxy-cli",
|
|
3
|
-
"version": "1.29.
|
|
3
|
+
"version": "1.29.23",
|
|
4
4
|
"description": "A secure control layer for AI agents: policies across payments, messages, logins, destructive actions, model usage, and secrets, all enforceable from the CLI",
|
|
5
5
|
"homepage": "https://troxy.io",
|
|
6
6
|
"bugs": {
|
package/src/api.js
CHANGED
|
@@ -172,6 +172,7 @@ export const api = {
|
|
|
172
172
|
agentMcps: (jwt, tokenPrefix) => request('GET', `/agent/mcps${tokenPrefix ? `?token_prefix=${encodeURIComponent(tokenPrefix)}` : ''}`, { jwt }),
|
|
173
173
|
agentActivity: (jwt, limit, mine, tokenPrefix) => request('GET', `/agent/activity?limit=${limit || 20}${mine ? `&mine=true&token_prefix=${encodeURIComponent(tokenPrefix || '')}` : ''}`, { jwt }),
|
|
174
174
|
agentInsights: (jwt, period) => request('GET', `/agent/insights?period=${period || 30}`, { jwt }),
|
|
175
|
+
agentUsageBar: (jwt, period) => request('GET', `/agent/usage-bar?period=${period || 30}`, { jwt }),
|
|
175
176
|
};
|
|
176
177
|
|
|
177
178
|
// Named export for backwards compat with init.js + mcp-server.js
|
package/src/init.js
CHANGED
|
@@ -951,10 +951,20 @@ async function maybeEnableTroxyInterception(proxyOptIn, hasDesktop, configPath =
|
|
|
951
951
|
|
|
952
952
|
if (interceptionIsConfigured(configPath)) return; // already set up correctly, nothing to ask
|
|
953
953
|
|
|
954
|
+
// No auto-started background service on Windows yet (installService throws
|
|
955
|
+
// there), so pointing Claude Code at 127.0.0.1 would break every call
|
|
956
|
+
// after a reboot. Policies still work; the engine waits for Windows support.
|
|
957
|
+
if (process.platform === 'win32') {
|
|
958
|
+
console.log('\n The Troxy engine (lighter Claude Code requests) is not available on');
|
|
959
|
+
console.log(' Windows yet. Policies work. Mac and Linux get the engine today.');
|
|
960
|
+
return;
|
|
961
|
+
}
|
|
962
|
+
|
|
954
963
|
let enable = proxyOptIn === true;
|
|
955
964
|
if (proxyOptIn === null && process.stdin.isTTY) {
|
|
956
|
-
console.log("\n
|
|
957
|
-
console.log('
|
|
965
|
+
console.log("\n Turn on the Troxy engine? Claude Code's requests go through Troxy and");
|
|
966
|
+
console.log(' are made lighter, so your usage goes further. Your normal Claude login');
|
|
967
|
+
console.log(' (subscription or API key) still');
|
|
958
968
|
console.log(' pays - Troxy never substitutes its own credential. Troxy does see your');
|
|
959
969
|
console.log(' real credential in transit, forwarded upstream to actually make the');
|
|
960
970
|
console.log(' call to Anthropic on your behalf.');
|
|
@@ -69,7 +69,7 @@ describe('reprovisionKeyConsumers: desktop detection gate', () => {
|
|
|
69
69
|
it('maybeEnableTroxyInterception runs migration before the enable/proxyOptIn decision, so it always fires', () => {
|
|
70
70
|
const fnStart = initSrc.indexOf('async function maybeEnableTroxyInterception');
|
|
71
71
|
assert.ok(fnStart !== -1, 'maybeEnableTroxyInterception not found');
|
|
72
|
-
const fnBody = initSrc.slice(fnStart, fnStart +
|
|
72
|
+
const fnBody = initSrc.slice(fnStart, fnStart + 2000);
|
|
73
73
|
const migrateIdx = fnBody.indexOf('migrateBaseUrlProxyToInterception(');
|
|
74
74
|
const optInIdx = fnBody.indexOf('proxyOptIn === true');
|
|
75
75
|
assert.ok(migrateIdx !== -1, 'migrateBaseUrlProxyToInterception call not found in function body');
|