troxy-cli 1.4.16 → 1.4.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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "troxy-cli",
3
- "version": "1.4.16",
3
+ "version": "1.4.18",
4
4
  "description": "AI payment control — protect your agent's payments with policies",
5
5
  "type": "module",
6
6
  "bin": {
package/src/api.js CHANGED
@@ -55,7 +55,7 @@ export const api = {
55
55
  // Evaluate + confirm (agent API key)
56
56
  evaluate: (body, apiKey) => request('POST', '/evaluate', { apiKey, body }),
57
57
  confirmPayment: (auditId, body, apiKey) => request('POST', `/payments/${auditId}/confirm`, { apiKey, body }),
58
- checkApprovalStatus: (token) => request('GET', `/approvals/${encodeURIComponent(token)}`),
58
+ waitApprovalStatus: (token) => request('GET', `/approvals/${encodeURIComponent(token)}/wait`),
59
59
 
60
60
  // MCP heartbeat (agent API key)
61
61
  mcpHeartbeat: (apiKey, agentName) => request('POST', '/mcp/heartbeat', { apiKey, body: agentName ? { agent_name: agentName } : undefined }),
package/src/mcp-server.js CHANGED
@@ -104,7 +104,7 @@ export async function runMcp() {
104
104
  'based on your Troxy policies. Call this before initiating any payment.',
105
105
  inputSchema: {
106
106
  type: 'object',
107
- required: ['merchant_name', 'amount'],
107
+ required: ['merchant_name', 'amount', 'currency'],
108
108
  properties: {
109
109
  merchant_name: {
110
110
  type: 'string',
@@ -124,7 +124,7 @@ export async function runMcp() {
124
124
  },
125
125
  currency: {
126
126
  type: 'string',
127
- description: 'Currency code, defaults to USD (optional)',
127
+ description: 'ISO 4217 currency code always include this. Examples: "ILS" for Israeli Shekel (NIS), "USD" for US Dollar, "EUR" for Euro.',
128
128
  },
129
129
  approval_token: {
130
130
  type: 'string',
@@ -142,48 +142,46 @@ export async function runMcp() {
142
142
 
143
143
  if (toolName === 'wait_for_payment_approval') {
144
144
  const { approval_token } = args;
145
- const POLL_MS = 10_000; // check every 10 seconds
146
- const MAX_MS = 10 * 60_000; // give up after 10 minutes
147
- const deadline = Date.now() + MAX_MS;
145
+ const MAX_MS = 60 * 60_000; // overall cap: 1 hour
146
+ const deadline = Date.now() + MAX_MS;
148
147
 
148
+ // Long-poll: each request blocks on the server for ~20s, returning the
149
+ // moment the approval is resolved. No sleep needed — instant detection.
149
150
  while (Date.now() < deadline) {
150
151
  let status;
151
152
  try {
152
- status = await api.checkApprovalStatus(approval_token);
153
+ status = await api.waitApprovalStatus(approval_token);
153
154
  } catch (err) {
154
155
  return {
155
- content: [{ type: 'text', text: `Troxy error checking approval: ${err.message}` }],
156
+ content: [{ type: 'text', text: `Troxy error waiting for approval: ${err.message}` }],
156
157
  isError: true,
157
158
  };
158
159
  }
159
160
 
160
- if (status.resolution === 'APPROVED') {
161
+ if (status.status === 'APPROVED') {
161
162
  return {
162
163
  content: [{ type: 'text', text: `✅ Payment approved! Call evaluate_payment again with the same payment details and approval_token: "${approval_token}" to proceed.` }],
163
164
  isError: false,
164
165
  };
165
166
  }
166
- if (status.resolution === 'DECLINED') {
167
+ if (status.status === 'DECLINED') {
167
168
  return {
168
169
  content: [{ type: 'text', text: `❌ Payment declined by the account owner. Do not proceed with this payment.` }],
169
170
  isError: true,
170
171
  };
171
172
  }
172
-
173
- // Check for expiry
174
- if (status.expires_at && new Date(status.expires_at) < new Date()) {
173
+ if (status.status === 'EXPIRED') {
175
174
  return {
176
175
  content: [{ type: 'text', text: `⏱ Approval request has expired. The payment cannot be approved.` }],
177
176
  isError: true,
178
177
  };
179
178
  }
180
-
181
- await new Promise(resolve => setTimeout(resolve, POLL_MS));
179
+ // status === 'pending': server timed out its 20s window, loop immediately
182
180
  }
183
181
 
184
182
  return {
185
- content: [{ type: 'text', text: `⏳ Still waiting for approval after 10 minutes. Call wait_for_payment_approval again to keep checking, or let the user know it is still pending.` }],
186
- isError: false,
183
+ content: [{ type: 'text', text: `⏳ Still waiting for approval after 1 hour. The request has likely expired.` }],
184
+ isError: true,
187
185
  };
188
186
  }
189
187