@ar-agents/mercadopago 0.14.0 → 0.15.0

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/dist/index.d.cts CHANGED
@@ -2167,7 +2167,49 @@ interface MercadoPagoToolsOptions {
2167
2167
  * retries (which fire on 5xx and can deliver the same event 5+ times).
2168
2168
  */
2169
2169
  webhookDedup?: WebhookDedup;
2170
+ /**
2171
+ * v0.15 — Programmatic Human-In-The-Loop gate for irreversible /
2172
+ * money-moving operations. When set, every call to one of the gated
2173
+ * tools (cancel_payment, capture_payment, refund_payment,
2174
+ * delete_customer_card, cancel_qr_payment, cancel_order,
2175
+ * cancel_point_payment_intent, delete_webhook) invokes this callback
2176
+ * BEFORE executing. Return `true` to proceed, `false` to reject the
2177
+ * call (the tool returns `{ ok: false, reason: "Confirmation declined" }`).
2178
+ *
2179
+ * The description-based HITL warnings still apply (they nudge the LLM
2180
+ * to confirm in-conversation), but those depend on the LLM's heuristic
2181
+ * and can be bypassed via prompt injection. This callback is the actual
2182
+ * out-of-band enforcement: wire it to your UI / Slack / email / SMS
2183
+ * confirmation flow so a human approves money-movement explicitly.
2184
+ *
2185
+ * @example
2186
+ * ```ts
2187
+ * mercadoPagoTools(client, {
2188
+ * state, backUrl,
2189
+ * requireConfirmation: async (op, args) => {
2190
+ * // Send a Slack DM to the operator with the operation summary
2191
+ * // and wait for their button click. Throw or return false to reject.
2192
+ * return await slack.confirm({
2193
+ * channel: "#mp-approvals",
2194
+ * text: `Refund $${args.amount ?? "FULL"} on payment ${args.payment_id}?`,
2195
+ * timeoutMs: 60_000,
2196
+ * });
2197
+ * },
2198
+ * });
2199
+ * ```
2200
+ *
2201
+ * If omitted (default), the description-based HITL is the only line of
2202
+ * defense — fine for trusted/internal agents, NOT recommended for
2203
+ * untrusted-input agents (anything reading from a public webhook).
2204
+ */
2205
+ requireConfirmation?: (operation: GatedOperation, args: Record<string, unknown>) => Promise<boolean>;
2170
2206
  }
2207
+ /**
2208
+ * Tool names that go through `requireConfirmation` when configured.
2209
+ * Adding a new irreversible operation? Add it here AND in the
2210
+ * `applyConfirmationGate` wrapper at the bottom of this file.
2211
+ */
2212
+ type GatedOperation = "cancel_payment" | "capture_payment" | "refund_payment" | "delete_customer_card" | "cancel_qr_payment" | "cancel_order" | "cancel_point_payment_intent" | "delete_webhook";
2171
2213
  type ToolName = "create_subscription" | "get_subscription_status" | "cancel_subscription" | "pause_subscription" | "resume_subscription" | "create_payment" | "get_payment" | "search_payments" | "cancel_payment" | "capture_payment" | "refund_payment" | "list_refunds" | "create_payment_preference" | "get_payment_preference" | "create_customer" | "find_customer_by_email" | "list_customer_cards" | "delete_customer_card" | "list_payment_methods" | "calculate_installments" | "get_account_info" | "charge_saved_card" | "create_qr_payment" | "cancel_qr_payment" | "create_subscription_plan" | "list_subscription_plans" | "update_subscription_plan" | "subscribe_to_plan" | "list_subscription_payments" | "create_store" | "list_stores" | "create_pos" | "list_pos" | "list_payment_disputes" | "get_dispute" | "list_identification_types" | "list_issuers" | "list_webhooks" | "create_webhook" | "update_webhook" | "delete_webhook" | "handle_webhook" | "oauth_authorize_url" | "oauth_exchange_code" | "oauth_refresh_token" | "create_order" | "get_order" | "update_order" | "capture_order" | "cancel_order" | "get_account_balance" | "list_account_movements" | "list_settlements" | "get_settlement" | "analyze_payment_3ds" | "get_test_cards" | "get_customer" | "update_customer" | "create_customer_card" | "get_customer_card" | "get_subscription_plan" | "update_subscription" | "search_subscriptions" | "get_refund" | "update_payment_preference" | "get_merchant_order" | "search_merchant_orders" | "update_merchant_order" | "get_store" | "update_store" | "delete_store" | "get_pos" | "update_pos" | "delete_pos" | "list_bank_accounts" | "register_bank_account" | "list_point_devices" | "update_point_device_mode" | "create_point_payment_intent" | "get_point_payment_intent" | "cancel_point_payment_intent" | "compute_marketplace_fee" | "explain_payment_status" | "mp_health_check" | "find_applicable_promos" | "confirm_3ds_challenge" | "search_payments_all" | "list_settlements_all" | "validate_tax_id";
2172
2214
  /**
2173
2215
  * Build a tool set for the Vercel AI SDK that exposes Mercado Pago to an
package/dist/index.d.ts CHANGED
@@ -2167,7 +2167,49 @@ interface MercadoPagoToolsOptions {
2167
2167
  * retries (which fire on 5xx and can deliver the same event 5+ times).
2168
2168
  */
2169
2169
  webhookDedup?: WebhookDedup;
2170
+ /**
2171
+ * v0.15 — Programmatic Human-In-The-Loop gate for irreversible /
2172
+ * money-moving operations. When set, every call to one of the gated
2173
+ * tools (cancel_payment, capture_payment, refund_payment,
2174
+ * delete_customer_card, cancel_qr_payment, cancel_order,
2175
+ * cancel_point_payment_intent, delete_webhook) invokes this callback
2176
+ * BEFORE executing. Return `true` to proceed, `false` to reject the
2177
+ * call (the tool returns `{ ok: false, reason: "Confirmation declined" }`).
2178
+ *
2179
+ * The description-based HITL warnings still apply (they nudge the LLM
2180
+ * to confirm in-conversation), but those depend on the LLM's heuristic
2181
+ * and can be bypassed via prompt injection. This callback is the actual
2182
+ * out-of-band enforcement: wire it to your UI / Slack / email / SMS
2183
+ * confirmation flow so a human approves money-movement explicitly.
2184
+ *
2185
+ * @example
2186
+ * ```ts
2187
+ * mercadoPagoTools(client, {
2188
+ * state, backUrl,
2189
+ * requireConfirmation: async (op, args) => {
2190
+ * // Send a Slack DM to the operator with the operation summary
2191
+ * // and wait for their button click. Throw or return false to reject.
2192
+ * return await slack.confirm({
2193
+ * channel: "#mp-approvals",
2194
+ * text: `Refund $${args.amount ?? "FULL"} on payment ${args.payment_id}?`,
2195
+ * timeoutMs: 60_000,
2196
+ * });
2197
+ * },
2198
+ * });
2199
+ * ```
2200
+ *
2201
+ * If omitted (default), the description-based HITL is the only line of
2202
+ * defense — fine for trusted/internal agents, NOT recommended for
2203
+ * untrusted-input agents (anything reading from a public webhook).
2204
+ */
2205
+ requireConfirmation?: (operation: GatedOperation, args: Record<string, unknown>) => Promise<boolean>;
2170
2206
  }
2207
+ /**
2208
+ * Tool names that go through `requireConfirmation` when configured.
2209
+ * Adding a new irreversible operation? Add it here AND in the
2210
+ * `applyConfirmationGate` wrapper at the bottom of this file.
2211
+ */
2212
+ type GatedOperation = "cancel_payment" | "capture_payment" | "refund_payment" | "delete_customer_card" | "cancel_qr_payment" | "cancel_order" | "cancel_point_payment_intent" | "delete_webhook";
2171
2213
  type ToolName = "create_subscription" | "get_subscription_status" | "cancel_subscription" | "pause_subscription" | "resume_subscription" | "create_payment" | "get_payment" | "search_payments" | "cancel_payment" | "capture_payment" | "refund_payment" | "list_refunds" | "create_payment_preference" | "get_payment_preference" | "create_customer" | "find_customer_by_email" | "list_customer_cards" | "delete_customer_card" | "list_payment_methods" | "calculate_installments" | "get_account_info" | "charge_saved_card" | "create_qr_payment" | "cancel_qr_payment" | "create_subscription_plan" | "list_subscription_plans" | "update_subscription_plan" | "subscribe_to_plan" | "list_subscription_payments" | "create_store" | "list_stores" | "create_pos" | "list_pos" | "list_payment_disputes" | "get_dispute" | "list_identification_types" | "list_issuers" | "list_webhooks" | "create_webhook" | "update_webhook" | "delete_webhook" | "handle_webhook" | "oauth_authorize_url" | "oauth_exchange_code" | "oauth_refresh_token" | "create_order" | "get_order" | "update_order" | "capture_order" | "cancel_order" | "get_account_balance" | "list_account_movements" | "list_settlements" | "get_settlement" | "analyze_payment_3ds" | "get_test_cards" | "get_customer" | "update_customer" | "create_customer_card" | "get_customer_card" | "get_subscription_plan" | "update_subscription" | "search_subscriptions" | "get_refund" | "update_payment_preference" | "get_merchant_order" | "search_merchant_orders" | "update_merchant_order" | "get_store" | "update_store" | "delete_store" | "get_pos" | "update_pos" | "delete_pos" | "list_bank_accounts" | "register_bank_account" | "list_point_devices" | "update_point_device_mode" | "create_point_payment_intent" | "get_point_payment_intent" | "cancel_point_payment_intent" | "compute_marketplace_fee" | "explain_payment_status" | "mp_health_check" | "find_applicable_promos" | "confirm_3ds_challenge" | "search_payments_all" | "list_settlements_all" | "validate_tax_id";
2172
2214
  /**
2173
2215
  * Build a tool set for the Vercel AI SDK that exposes Mercado Pago to an
package/dist/index.js CHANGED
@@ -3028,7 +3028,8 @@ async function verifyWebhookSignature(params) {
3028
3028
 
3029
3029
  // src/tools.ts
3030
3030
  async function deterministicIdempotencyKey(...parts) {
3031
- const payload = parts.filter((p) => p !== void 0 && p !== null).map(String).join("|");
3031
+ const filtered = parts.filter((p) => p !== void 0 && p !== null).map(String);
3032
+ const payload = filtered.map((p) => `${p.length}:${p}`).join("|");
3032
3033
  return (await sha256Hex(payload)).slice(0, 32);
3033
3034
  }
3034
3035
  var DEFAULT_DESCRIPTIONS = {
@@ -3156,6 +3157,10 @@ var DEFAULT_DESCRIPTIONS = {
3156
3157
  };
3157
3158
  function mercadoPagoTools(client, options) {
3158
3159
  const desc = (name) => options.descriptions?.[name] ?? DEFAULT_DESCRIPTIONS[name];
3160
+ const built = buildAllTools(client, options, desc);
3161
+ return options.requireConfirmation ? applyConfirmationGate(built, options.requireConfirmation) : built;
3162
+ }
3163
+ function buildAllTools(client, options, desc) {
3159
3164
  return {
3160
3165
  // ─────────────────────────────────────────────────────────────────────────
3161
3166
  // Subscriptions (v0.1 — kept identical for backward compatibility)
@@ -4269,6 +4274,22 @@ function mercadoPagoTools(client, options) {
4269
4274
  resource: null
4270
4275
  };
4271
4276
  }
4277
+ if (options.webhookDedup && request_id_header) {
4278
+ const { shouldProcess } = await options.webhookDedup.check({
4279
+ topic: event.topic,
4280
+ dataId: event.dataId,
4281
+ requestId: request_id_header
4282
+ });
4283
+ if (!shouldProcess) {
4284
+ return {
4285
+ verified: true,
4286
+ deduplicated: true,
4287
+ event,
4288
+ resource: null,
4289
+ resource_error: "Webhook is a duplicate (same topic+dataId+requestId seen recently). Side effects skipped."
4290
+ };
4291
+ }
4292
+ }
4272
4293
  let resource = null;
4273
4294
  let resourceError = null;
4274
4295
  if (auto_fetch) {
@@ -5161,6 +5182,43 @@ function mercadoPagoTools(client, options) {
5161
5182
  })
5162
5183
  };
5163
5184
  }
5185
+ var GATED_TOOL_NAMES = [
5186
+ "cancel_payment",
5187
+ "capture_payment",
5188
+ "refund_payment",
5189
+ "delete_customer_card",
5190
+ "cancel_qr_payment",
5191
+ "cancel_order",
5192
+ "cancel_point_payment_intent",
5193
+ "delete_webhook"
5194
+ ];
5195
+ function applyConfirmationGate(tools, requireConfirmation) {
5196
+ const wrapped = { ...tools };
5197
+ for (const name of GATED_TOOL_NAMES) {
5198
+ const original = tools[name];
5199
+ if (!original) continue;
5200
+ wrapped[name] = {
5201
+ ...original,
5202
+ execute: async (input, ctx) => {
5203
+ const args = input ?? {};
5204
+ const approved = await requireConfirmation(name, args);
5205
+ if (!approved) {
5206
+ return {
5207
+ ok: false,
5208
+ reason: "Confirmation declined by requireConfirmation gate.",
5209
+ operation: name,
5210
+ args
5211
+ };
5212
+ }
5213
+ return await original.execute(
5214
+ input,
5215
+ ctx
5216
+ );
5217
+ }
5218
+ };
5219
+ }
5220
+ return wrapped;
5221
+ }
5164
5222
 
5165
5223
  // src/state.ts
5166
5224
  var InMemoryStateAdapter = class {