troxy-cli 1.30.16 → 1.30.18
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/package.json
CHANGED
|
@@ -116,12 +116,10 @@ const RULES = [
|
|
|
116
116
|
const paths = pathArgs(segment, 2).filter((w) => !w.startsWith('-'));
|
|
117
117
|
return { action_verb: 'delete', resource: summarizeResource(paths, 'a branch'), item_count: 1 };
|
|
118
118
|
}
|
|
119
|
-
if (/^git\s+push\b/.test(segment) && (/\s--delete\b/.test(segment) || /\s
|
|
120
|
-
// `git push origin :branch`
|
|
121
|
-
// `git push origin
|
|
122
|
-
|
|
123
|
-
// touched, which is what matters here regardless of which it deletes.
|
|
124
|
-
const target = segment.match(/--delete\s+(\S+)/)?.[1] || segment.match(/\s\S*:(\S+)/)?.[1];
|
|
119
|
+
if (/^git\s+push\b/.test(segment) && (/\s--delete\b/.test(segment) || /\s:\S+/.test(segment))) {
|
|
120
|
+
// Only an empty source (`git push origin :branch`) deletes.
|
|
121
|
+
// `git push origin HEAD:main` is a normal push, not a delete.
|
|
122
|
+
const target = segment.match(/--delete\s+(\S+)/)?.[1] || segment.match(/\s:(\S+)/)?.[1];
|
|
125
123
|
return { action_verb: 'delete', resource: target || 'a remote branch', item_count: 1 };
|
|
126
124
|
}
|
|
127
125
|
return null;
|
package/src/init.js
CHANGED
|
@@ -195,7 +195,7 @@ export async function reprovisionKeyConsumers(key, agentName, proxyOptIn = null,
|
|
|
195
195
|
const installed = await installTroxyGuardMod();
|
|
196
196
|
console.log(installed
|
|
197
197
|
? ` • Troxy model routing (terminal + Desktop) ✓`
|
|
198
|
-
: ` • Troxy model routing
|
|
198
|
+
: ` • Troxy model routing ✗ NOT installed: needs Claude Code 2.1.287+ (run claude --version). Usage and Savings stays empty until it is.`);
|
|
199
199
|
} catch (err) {
|
|
200
200
|
console.log(` • Troxy model routing ✗ (${err.message})`);
|
|
201
201
|
}
|
|
@@ -486,6 +486,11 @@ const MCP_CLIENTS = [
|
|
|
486
486
|
];
|
|
487
487
|
|
|
488
488
|
export async function runInit({ key, name, proxy, concise } = {}) {
|
|
489
|
+
// Under sudo, os.homedir() can be root's, so the mod would land where Claude Code never looks.
|
|
490
|
+
if (process.env.SUDO_USER) {
|
|
491
|
+
console.error('\n Run this without sudo: troxy init --key ...\n (sudo is only for the install command.)\n');
|
|
492
|
+
process.exit(1);
|
|
493
|
+
}
|
|
489
494
|
// undefined (flag never passed) -> null, so reprovisionKeyConsumers can
|
|
490
495
|
// tell "not decided, ask interactively" apart from an explicit --proxy.
|
|
491
496
|
const proxyOptIn = proxy === undefined ? null : Boolean(proxy);
|
|
@@ -86,6 +86,10 @@ describe('actionFor - git force push / branch delete', () => {
|
|
|
86
86
|
assert.equal(bash('git push origin --delete old-feature').action_verb, 'delete');
|
|
87
87
|
assert.equal(bash('git push origin :old-feature').action_verb, 'delete');
|
|
88
88
|
});
|
|
89
|
+
|
|
90
|
+
it('does not treat a normal src:dst push as a delete', () => {
|
|
91
|
+
assert.equal(bash('git push -q origin HEAD:main'), null);
|
|
92
|
+
});
|
|
89
93
|
});
|
|
90
94
|
|
|
91
95
|
describe('actionFor - terraform / kubectl / docker / aws', () => {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
1
3
|
import { test } from 'node:test';
|
|
2
4
|
import assert from 'node:assert/strict';
|
|
3
5
|
import os from 'node:os';
|
|
@@ -94,3 +96,10 @@ test('refreshTroxyGuardMod: re-copies a stale mod, leaves a current or missing o
|
|
|
94
96
|
fs.rmSync(tmpHome, { recursive: true, force: true });
|
|
95
97
|
}
|
|
96
98
|
});
|
|
99
|
+
|
|
100
|
+
test('init refuses to run under sudo, so the mod is not installed in root\'s home', () => {
|
|
101
|
+
const r = spawnSync(process.execPath, [fileURLToPath(new URL('../../bin/troxy.js', import.meta.url)), 'init', '--key', 'x'],
|
|
102
|
+
{ env: { ...process.env, SUDO_USER: 'someone' }, encoding: 'utf8' });
|
|
103
|
+
assert.equal(r.status, 1);
|
|
104
|
+
assert.match(r.stderr, /without sudo/);
|
|
105
|
+
});
|