troxy-cli 1.30.7 → 1.30.9

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 CHANGED
@@ -291,7 +291,7 @@ switch (command) {
291
291
  break;
292
292
  }
293
293
 
294
- // ── Pause / resume payment evaluations ───────────────────────
294
+ // ── Pause / resume policy checkpoints ───────────────────────
295
295
  case 'pause':
296
296
  await runPause();
297
297
  break;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "troxy-cli",
3
- "version": "1.30.7",
3
+ "version": "1.30.9",
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/mcps.js CHANGED
@@ -8,7 +8,7 @@ const HELP = {
8
8
  rename: ` troxy mcps rename --name <new-name> [--mcp <target>]\n\n Renames an MCP. Without --mcp, renames this machine's MCP.\n\n Options:\n --name New name\n --mcp Name/prefix of the MCP to rename (default: this machine)\n\n Example:\n troxy mcps rename --name "My Laptop"\n troxy mcps rename --mcp "old-name" --name "Staging Server"\n`,
9
9
  create: ` troxy mcps create --name <name>\n\n Creates a new API key for another agent/machine. The key is shown once.\n Save it, then run 'troxy init --key <key>' on that machine.\n\n Options:\n --name Label for the new key\n`,
10
10
  revoke: ` troxy mcps revoke --mcp <name>\n\n Permanently revokes an MCP's API key. That machine will stop being able\n to evaluate payments until reconnected with a new key.\n`,
11
- pause: ` troxy pause / troxy mcps pause [--mcp <name>]\n\n Pauses an MCP (blocks all its payment evaluations). Without --mcp, pauses\n this machine's MCP, same as running 'troxy pause'.\n`,
11
+ pause: ` troxy pause / troxy mcps pause [--mcp <name>]\n\n Pauses an MCP (blocks all its policy checkpoints). Without --mcp, pauses\n this machine's MCP, same as running 'troxy pause'.\n`,
12
12
  resume: ` troxy resume / troxy mcps resume [--mcp <name>]\n\n Resumes a paused MCP. Without --mcp, resumes this machine's MCP.\n`,
13
13
  budget: ` troxy mcps budget --mcp <name> [options]\n\n Sets or clears a monthly spend limit for a specific MCP.\n\n Options:\n --mcp <name> MCP to configure (required)\n --currency <cur> USD, ILS, or EUR (default: USD)\n --limit <n> Monthly limit\n --clear Remove the limit for that currency\n --action <action> block, escalate, notify, or allow: what happens once hit\n --reset-usage Reset this cycle's usage back to 0\n\n Example:\n troxy mcps budget --mcp "My Laptop" --currency USD --limit 500\n`,
14
14
  'set-default-action': ` troxy mcps set-default-action --mcp <name> --action <action>\n\n Sets the fallback decision for an MCP when no policy matches.\n\n Options:\n --mcp <name> MCP to configure (required)\n --action <action> ALLOW, BLOCK, ESCALATE, or NOTIFY\n`,
package/src/pause.js CHANGED
@@ -18,7 +18,7 @@ export async function runPause() {
18
18
  const id = await _localTokenId(jwt, config);
19
19
  await api.pauseToken(jwt, id);
20
20
  console.log('✓');
21
- console.log(' ⏸ All payment evaluations are now blocked.');
21
+ console.log(' ⏸ Policy checkpoints are now blocked. This does not turn off model switching (use /troxy off in Claude Code).');
22
22
  console.log(' Run "troxy resume" to resume.\n');
23
23
  }
24
24
 
@@ -29,5 +29,5 @@ export async function runResume() {
29
29
  const id = await _localTokenId(jwt, config);
30
30
  await api.resumeToken(jwt, id);
31
31
  console.log('✓');
32
- console.log(' ▶ Payment evaluations are active again.\n');
32
+ console.log(' ▶ Policy checkpoints are active again.\n');
33
33
  }
@@ -171,6 +171,9 @@ async function readStdin(timeoutMs) {
171
171
  // (`troxy posttooluse-hook`, registered via patchClaudeCodeHooks in
172
172
  // init.js) and, below, by this file's own direct-execution guard.
173
173
  export async function runPostToolUseHook() {
174
+ // Off by default: the 2026-10-22 split A/B showed output compression alone made the model
175
+ // re-run and re-read (about 4.5x the tool calls) and cost more bar. TROXY_COMPRESS=1 re-enables it.
176
+ if (process.env.TROXY_COMPRESS !== '1') process.exit(0);
174
177
  try {
175
178
  const raw = await readStdin(STDIN_TIMEOUT_MS);
176
179
  const input = JSON.parse(raw);
@@ -114,6 +114,7 @@ test('end-to-end: real init -> real hook subprocess -> real recall, and real fai
114
114
  ...process.env,
115
115
  HOME: tmpHome,
116
116
  PATH: '/usr/bin:/bin',
117
+ TROXY_COMPRESS: '1',
117
118
  };
118
119
 
119
120
  let stdout = '';
@@ -255,3 +255,19 @@ test('the hook records the tokens fetched back with troxy_recall, per session, a
255
255
  await buildHookResponse({ tool_name: 'mcp__troxy__troxy_recall', tool_response: [{ type: 'text', text: 'z'.repeat(800) }] }, { storeDir: dir });
256
256
  assert.equal(fs.readdirSync(path.join(dir, 'recalled')).length, 1);
257
257
  });
258
+
259
+ test('posttooluse-hook is a no-op unless TROXY_COMPRESS=1', () => {
260
+ const tmpHome = fs.mkdtempSync(path.join(os.tmpdir(), 'troxy-home-'));
261
+ try {
262
+ const run = (extra) => execFileSync(process.execPath, [troxyBin, 'posttooluse-hook'], {
263
+ input: JSON.stringify({ session_id: 's1', tool_name: 'Bash', tool_response: bashResult('x'.repeat(5000)) }),
264
+ env: { ...process.env, HOME: tmpHome, TROXY_COMPRESS: '', ...extra },
265
+ encoding: 'utf8',
266
+ });
267
+ assert.equal(run({}), '');
268
+ // Enabled: either compressed (treated arm) or left alone (holdout arm), never an error.
269
+ assert.doesNotThrow(() => run({ TROXY_COMPRESS: '1' }));
270
+ } finally {
271
+ fs.rmSync(tmpHome, { recursive: true, force: true });
272
+ }
273
+ });