troxy-cli 1.4.4 → 1.4.6
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 +58 -0
- package/package.json +1 -1
- package/src/activity.js +18 -0
- package/src/mcps.js +10 -0
- package/src/policies.js +38 -2
package/bin/troxy.js
CHANGED
|
@@ -87,6 +87,26 @@ switch (command) {
|
|
|
87
87
|
break;
|
|
88
88
|
|
|
89
89
|
case 'rotate-key': {
|
|
90
|
+
if (flags.help || flags.h) {
|
|
91
|
+
console.log(`
|
|
92
|
+
troxy rotate-key [options]
|
|
93
|
+
|
|
94
|
+
Creates a new MCP API key, saves it to ~/.troxy/config.json, and optionally
|
|
95
|
+
revokes the old key. Login required.
|
|
96
|
+
|
|
97
|
+
Options:
|
|
98
|
+
--name <name> Name for the new key (default: "Rotated key")
|
|
99
|
+
--revoke-old Revoke the old key immediately after creating the new one
|
|
100
|
+
|
|
101
|
+
Examples:
|
|
102
|
+
troxy rotate-key
|
|
103
|
+
troxy rotate-key --revoke-old
|
|
104
|
+
troxy rotate-key --name "My Agent Key" --revoke-old
|
|
105
|
+
|
|
106
|
+
After rotating: update TROXY_API_KEY in your MCP config and restart the MCP server.
|
|
107
|
+
`);
|
|
108
|
+
process.exit(0);
|
|
109
|
+
}
|
|
90
110
|
const jwt = requireJwt();
|
|
91
111
|
const { loadConfig, saveConfig } = await import('../src/config.js');
|
|
92
112
|
const oldKey = loadConfig()?.apiKey;
|
|
@@ -143,6 +163,28 @@ switch (command) {
|
|
|
143
163
|
|
|
144
164
|
// ── Simulate a payment evaluation ────────────────────────────
|
|
145
165
|
case 'pay': {
|
|
166
|
+
if (flags.help || flags.h) {
|
|
167
|
+
console.log(`
|
|
168
|
+
troxy pay --merchant <name> --amount <n> [options]
|
|
169
|
+
|
|
170
|
+
Simulates a payment evaluation request — identical to what your AI agent sends.
|
|
171
|
+
Use this to test your policies. Login required.
|
|
172
|
+
|
|
173
|
+
Required:
|
|
174
|
+
--merchant <name> Merchant name (e.g. "Amazon")
|
|
175
|
+
--amount <n> Payment amount in USD
|
|
176
|
+
|
|
177
|
+
Optional:
|
|
178
|
+
--card <alias> Card alias (default: "Work")
|
|
179
|
+
--category <cat> Merchant category (e.g. travel, software, food)
|
|
180
|
+
|
|
181
|
+
Examples:
|
|
182
|
+
troxy pay --merchant "Amazon" --amount 50
|
|
183
|
+
troxy pay --merchant "Amazon" --amount 350 --card "Work"
|
|
184
|
+
troxy pay --merchant "Delta" --amount 250 --card "Work" --category travel
|
|
185
|
+
`);
|
|
186
|
+
process.exit(0);
|
|
187
|
+
}
|
|
146
188
|
requireJwt();
|
|
147
189
|
const apiKey = loadConfig()?.apiKey || process.env.TROXY_API_KEY;
|
|
148
190
|
if (!apiKey) { console.error(' No API key. Run: troxy init --key txy-...\n'); process.exit(1); }
|
|
@@ -179,6 +221,21 @@ switch (command) {
|
|
|
179
221
|
break;
|
|
180
222
|
|
|
181
223
|
case 'insights': {
|
|
224
|
+
if (flags.help || flags.h) {
|
|
225
|
+
console.log(`
|
|
226
|
+
troxy insights [options]
|
|
227
|
+
|
|
228
|
+
Shows a spending and decision summary for a given period. Login required.
|
|
229
|
+
|
|
230
|
+
Options:
|
|
231
|
+
--period <days> Number of days to look back (default: 30)
|
|
232
|
+
|
|
233
|
+
Examples:
|
|
234
|
+
troxy insights
|
|
235
|
+
troxy insights --period 7
|
|
236
|
+
`);
|
|
237
|
+
process.exit(0);
|
|
238
|
+
}
|
|
182
239
|
const jwt = requireJwt();
|
|
183
240
|
const period = Number(flags.period || 30);
|
|
184
241
|
const data = await api.agentInsights(jwt, period);
|
|
@@ -309,6 +366,7 @@ switch (command) {
|
|
|
309
366
|
troxy policies list
|
|
310
367
|
troxy policies describe --name "Block Amazon"
|
|
311
368
|
troxy policies create --name "X" --action BLOCK --field amount --operator gte --value 500
|
|
369
|
+
troxy policies create --name "X" --action BLOCK --mcp "My Laptop" (scoped to one MCP)
|
|
312
370
|
troxy policies enable --name "X"
|
|
313
371
|
troxy policies disable --name "X"
|
|
314
372
|
troxy policies delete --name "X"
|
package/package.json
CHANGED
package/src/activity.js
CHANGED
|
@@ -5,6 +5,24 @@ import { table } from './print.js';
|
|
|
5
5
|
const ICON = { ALLOW: '✓', BLOCK: '✗', ESCALATE: '⏳', NOTIFY: '~' };
|
|
6
6
|
|
|
7
7
|
export async function runActivity(flags) {
|
|
8
|
+
if (flags.help || flags.h) {
|
|
9
|
+
console.log(`
|
|
10
|
+
troxy activity [options]
|
|
11
|
+
|
|
12
|
+
Shows recent payment decisions across all your MCPs. Login required.
|
|
13
|
+
|
|
14
|
+
Options:
|
|
15
|
+
--limit <n> Number of rows to show (default: 20, max: 200)
|
|
16
|
+
--mine Show only decisions from this machine's MCP
|
|
17
|
+
|
|
18
|
+
Examples:
|
|
19
|
+
troxy activity
|
|
20
|
+
troxy activity --limit 50
|
|
21
|
+
troxy activity --mine
|
|
22
|
+
`);
|
|
23
|
+
process.exit(0);
|
|
24
|
+
}
|
|
25
|
+
|
|
8
26
|
const jwt = requireJwt();
|
|
9
27
|
const limit = Number(flags.limit || 20);
|
|
10
28
|
const mine = !!flags.mine;
|
package/src/mcps.js
CHANGED
|
@@ -3,7 +3,17 @@ import { loadConfig, saveConfig } from './config.js';
|
|
|
3
3
|
import { requireJwt } from './auth.js';
|
|
4
4
|
import { table } from './print.js';
|
|
5
5
|
|
|
6
|
+
const HELP = {
|
|
7
|
+
list: ` troxy mcps list\n\n Lists all MCP connections on your account — name, prefix, status, last seen,\n policies assigned, default action, and which one is this machine.\n`,
|
|
8
|
+
rename: ` troxy mcps rename --name <new-name>\n\n Renames this machine's MCP. The new name appears in the dashboard immediately.\n\n Options:\n --name New name for this machine's MCP\n\n Example:\n troxy mcps rename --name "My Laptop"\n`,
|
|
9
|
+
};
|
|
10
|
+
|
|
6
11
|
export async function runMcps([sub], flags) {
|
|
12
|
+
if (flags.help || flags.h) {
|
|
13
|
+
console.log('\n' + (HELP[sub] || ` troxy mcps <subcommand> [options]\n\n Subcommands:\n list List all MCP connections\n rename Rename this machine's MCP\n\n Run 'troxy mcps <subcommand> --help' for subcommand help.\n`));
|
|
14
|
+
process.exit(0);
|
|
15
|
+
}
|
|
16
|
+
|
|
7
17
|
switch (sub || 'list') {
|
|
8
18
|
case 'list': {
|
|
9
19
|
const jwt = requireJwt();
|
package/src/policies.js
CHANGED
|
@@ -10,7 +10,21 @@ function _scope(p) {
|
|
|
10
10
|
return 'no MCPs applied';
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
const HELP = {
|
|
14
|
+
list: ` troxy policies list\n\n Lists all policies in your account with their action, scope, status, and conditions.\n`,
|
|
15
|
+
describe: ` troxy policies describe --name <policy-name>\n\n Shows full details for a single policy.\n\n Options:\n --name Name of the policy (use single quotes for names with special chars)\n`,
|
|
16
|
+
create: ` troxy policies create --name <name> --action <action> [options]\n\n Creates a new policy. Login required.\n\n Required:\n --name Policy name\n --action ALLOW, BLOCK, NOTIFY, or ESCALATE\n\n Optional conditions:\n --field Field to match: amount, merchant_name, merchant_category,\n merchant_country, currency, agent_name, hour, day_of_week\n --operator eq, neq, gt, gte, lt, lte, contains, between\n --value Comparison value (e.g. 500, amazon, Monday)\n --value2 Upper bound for 'between' operator\n\n Scope:\n --mcp <name> Scope policy to a specific MCP only (default: all MCPs)\n Run 'troxy mcps list' to see MCP names.\n\n Examples:\n troxy policies create --name "Block large" --action BLOCK --field amount --operator gte --value 500\n troxy policies create --name "Block Amazon" --action BLOCK --field merchant_name --operator contains --value amazon\n troxy policies create --name "Cap spend" --action BLOCK --mcp "My Laptop" --field amount --operator gte --value 200\n`,
|
|
17
|
+
enable: ` troxy policies enable --name <policy-name>\n\n Enables a disabled policy.\n\n Options:\n --name Name of the policy to enable\n`,
|
|
18
|
+
disable: ` troxy policies disable --name <policy-name>\n\n Disables a policy without deleting it.\n\n Options:\n --name Name of the policy to disable\n`,
|
|
19
|
+
delete: ` troxy policies delete --name <policy-name>\n\n Permanently deletes a policy.\n\n Options:\n --name Name of the policy to delete\n`,
|
|
20
|
+
};
|
|
21
|
+
|
|
13
22
|
export async function runPolicies([sub, ...args], flags) {
|
|
23
|
+
if (flags.help || flags.h) {
|
|
24
|
+
console.log('\n' + (HELP[sub] || ` troxy policies <subcommand> [options]\n\n Subcommands:\n list List all policies\n describe Show details for a policy\n create Create a new policy\n enable Enable a policy\n disable Disable a policy\n delete Delete a policy\n\n Run 'troxy policies <subcommand> --help' for subcommand help.\n`));
|
|
25
|
+
process.exit(0);
|
|
26
|
+
}
|
|
27
|
+
|
|
14
28
|
// Read-only subcommands work with a login session
|
|
15
29
|
const readOnly = !sub || sub === 'list' || sub === 'describe';
|
|
16
30
|
|
|
@@ -82,8 +96,30 @@ export async function runPolicies([sub, ...args], flags) {
|
|
|
82
96
|
if (flags.value2) cond.value2 = flags.value2;
|
|
83
97
|
conditions.push(cond);
|
|
84
98
|
}
|
|
85
|
-
|
|
86
|
-
|
|
99
|
+
|
|
100
|
+
// --mcp <name>: scope policy to a specific MCP instead of all
|
|
101
|
+
let isGlobal = true;
|
|
102
|
+
let mcpIds = [];
|
|
103
|
+
if (flags.mcp) {
|
|
104
|
+
const { tokens = [] } = await api.listTokens(jwt);
|
|
105
|
+
const needle = flags.mcp.toLowerCase();
|
|
106
|
+
const match = tokens.find(t =>
|
|
107
|
+
(t.name && t.name.toLowerCase() === needle) ||
|
|
108
|
+
(t.agent_name && t.agent_name.toLowerCase() === needle) ||
|
|
109
|
+
(t.prefix && t.prefix.toLowerCase().startsWith(needle))
|
|
110
|
+
);
|
|
111
|
+
if (!match) {
|
|
112
|
+
console.error(`\n MCP "${flags.mcp}" not found. Run: troxy mcps list\n`);
|
|
113
|
+
process.exit(1);
|
|
114
|
+
}
|
|
115
|
+
isGlobal = false;
|
|
116
|
+
mcpIds = [match.id];
|
|
117
|
+
console.log(`\n Scoping to MCP: ${match.name || match.agent_name || match.prefix}`);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const policy = await api.createPolicy(jwt, { name, action, conditions, enabled: true, global: isGlobal, mcp_ids: mcpIds });
|
|
121
|
+
const scope = isGlobal ? 'all MCPs' : (policy.mcps?.[0]?.name || flags.mcp);
|
|
122
|
+
console.log(`\n Policy "${policy.name}" created ✓ (priority: ${policy.priority}, scope: ${scope})\n`);
|
|
87
123
|
break;
|
|
88
124
|
}
|
|
89
125
|
|