@ar-agents/mercadopago 0.10.0 → 0.12.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/CHANGELOG.md +55 -0
- package/MIGRATION.md +176 -0
- package/cookbook/09-otel-wired.ts +155 -0
- package/cookbook/README.md +1 -0
- package/dist/audit-B9Nhj3PH.d.cts +294 -0
- package/dist/audit-B9Nhj3PH.d.ts +294 -0
- package/dist/index.cjs +588 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +270 -194
- package/dist/index.d.ts +270 -194
- package/dist/index.js +581 -5
- package/dist/index.js.map +1 -1
- package/dist/vercel-kv.cjs +81 -0
- package/dist/vercel-kv.cjs.map +1 -1
- package/dist/vercel-kv.d.cts +38 -2
- package/dist/vercel-kv.d.ts +38 -2
- package/dist/vercel-kv.js +81 -1
- package/dist/vercel-kv.js.map +1 -1
- package/package.json +4 -3
- package/tools.manifest.json +1 -1
- package/dist/state-C6Wzb_XX.d.cts +0 -106
- package/dist/state-C6Wzb_XX.d.ts +0 -106
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,60 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.12.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes — Idempotency-by-default for state-mutating writes
|
|
6
|
+
|
|
7
|
+
`MercadoPagoClient` now auto-generates a UUID v4 X-Idempotency-Key header on
|
|
8
|
+
every state-mutating POST request when the caller doesn't provide one
|
|
9
|
+
explicitly. Naive callers (and the LLM tools layer) often forget to pass an
|
|
10
|
+
idempotency key, leaving them exposed to double-charge bugs on network
|
|
11
|
+
partitions. This makes the safe default: safe.
|
|
12
|
+
|
|
13
|
+
- **Auto-generated keys are unique per call** (Web Crypto's `randomUUID()` —
|
|
14
|
+
Edge Runtime + Node 19+ + Cloudflare Workers + browsers).
|
|
15
|
+
- **Caller-supplied keys still win** — pass `idempotencyKey: "..."` for
|
|
16
|
+
deterministic retries from a job queue (e.g., same key across retry
|
|
17
|
+
attempts).
|
|
18
|
+
- **Only POST requests are auto-keyed.** GET / DELETE are HTTP-idempotent
|
|
19
|
+
by spec. PUT skips auto-gen because MP's PUT endpoints encode the dedup
|
|
20
|
+
key in the resource path (`/v1/payments/:id` → cancel; `/preapproval/:id` →
|
|
21
|
+
pause/resume — already deduped by id).
|
|
22
|
+
|
|
23
|
+
6 new tests in `idempotency-default.test.ts` verify:
|
|
24
|
+
- UUID v4 format on auto-gen
|
|
25
|
+
- Different keys per call
|
|
26
|
+
- Caller-supplied keys honored over auto-gen
|
|
27
|
+
- GET requests NOT keyed
|
|
28
|
+
- Works for `createPayment`, `createPreference`, `createPreapproval`
|
|
29
|
+
|
|
30
|
+
### New cookbook recipe
|
|
31
|
+
|
|
32
|
+
- `cookbook/09-otel-wired.ts` — full OpenTelemetry wiring example. Shows
|
|
33
|
+
how to wire `traceContext` for distributed-trace correlation, instrument
|
|
34
|
+
the client + tools, and what the resulting trace + metric shape looks
|
|
35
|
+
like in your APM. Closes the half-finished OTel story (lib + subpath
|
|
36
|
+
existed since v0.10 but no recipe wired it end-to-end).
|
|
37
|
+
|
|
38
|
+
## 0.11.0
|
|
39
|
+
|
|
40
|
+
### Minor Changes — Composability + cross-LATAM + fraud scoring
|
|
41
|
+
|
|
42
|
+
**Tool middleware pattern (NEW)**: composable wrappers around any AI SDK tool. Ships `withAuditLog`, `withRateLimit`, `withMetrics`, `withRetry` + `compose()` + `applyToAllTools()`. Add audit + rate-limit + metrics to every tool with a single config block instead of wiring each concern into the tool implementation.
|
|
43
|
+
|
|
44
|
+
**TaxID validation cross-LATAM (NEW)**: `validateTaxId(input, type)` for AR (DNI/CUIT/CUIL with modulo-11), BR (CPF/CNPJ two-step weighted), MX (RFC structure), CL (RUT with K), CO (NIT modulo-11), UY (RUT 12-digit), PE (RUC 11-digit + prefix). `detectAndValidate(input, country)` auto-detects type from length. New `validate_tax_id` agent tool. Pure, no network.
|
|
45
|
+
|
|
46
|
+
**`additional_info` on `create_payment` (fraud scoring enrichment)**: `payer` profile (registration_date, authentication_type, is_first_purchase, is_prime_user, last_purchase), `shipments` (receiver_address, express_shipment, local_pickup), `ip_address`, `referral_url`. Per MP RG 5286/2023, payments without enrichment have 3-5x higher rejection rate — this is a real conversion uplift. Documented in tool description so the agent surfaces it proactively.
|
|
47
|
+
|
|
48
|
+
**VercelKVAuditLog (NEW)**: production audit-log adapter in `@ar-agents/mercadopago/vercel-kv` subpath. Storage layout: per-entry key + ZSET indexes by day/actor/tenant for O(log N) time-range queries. Backed by Vercel KV (Upstash Redis).
|
|
49
|
+
|
|
50
|
+
**Migration guide vs `mercadopago` (official SDK)** — `MIGRATION.md` shipped in tarball with side-by-side mappings, conceptual table, "when to use both" section.
|
|
51
|
+
|
|
52
|
+
**CI fixes**: build packages BEFORE typecheck (was failing for facturacion → identity workspace dep with subpath exports). Release workflow now `workflow_dispatch` only (was spamming failure emails on every push because changesets/action couldn't create PRs without explicit repo permission).
|
|
53
|
+
|
|
54
|
+
**New tools**: `validate_tax_id`. Tool count: **87** (was 86).
|
|
55
|
+
|
|
56
|
+
**Quality**: 284 tests pass (was 245; +39 v0.11 tests covering middleware, taxId, and more). publint clean, attw 🟢 across 3 subpaths. Bundle: main 42.9 KB brotli'd (size budget bumped 40→50 KB).
|
|
57
|
+
|
|
3
58
|
## 0.10.0
|
|
4
59
|
|
|
5
60
|
### Minor Changes — Compliance + DX + observability deepening
|
package/MIGRATION.md
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# Migration guide — `mercadopago` (official SDK) → `@ar-agents/mercadopago`
|
|
2
|
+
|
|
3
|
+
If you're already using MP's official Node SDK and want to switch to (or
|
|
4
|
+
add on top of) the agent toolkit, this guide shows the side-by-side mapping.
|
|
5
|
+
|
|
6
|
+
The agent toolkit is **not** a drop-in replacement — it's a layer ABOVE
|
|
7
|
+
the underlying API designed for AI agents. You can use both packages in
|
|
8
|
+
the same project: keep `mercadopago` for traditional server flows, add
|
|
9
|
+
`@ar-agents/mercadopago` for the agent layer.
|
|
10
|
+
|
|
11
|
+
## Conceptual mapping
|
|
12
|
+
|
|
13
|
+
| `mercadopago` (official) | `@ar-agents/mercadopago` |
|
|
14
|
+
|---|---|
|
|
15
|
+
| `MercadoPagoConfig({ accessToken })` | `new MercadoPagoClient({ accessToken })` |
|
|
16
|
+
| `new Payment(config)` | Same `MercadoPagoClient` (single object, no per-resource client) |
|
|
17
|
+
| `payment.create({ body })` | `client.createPayment(params)` (camelCase params) |
|
|
18
|
+
| `payment.get({ id })` | `client.getPayment(id)` |
|
|
19
|
+
| `payment.search({ options })` | `client.searchPayments(filter)` |
|
|
20
|
+
| `preApproval.create({ body })` | `client.createPreapproval(params)` |
|
|
21
|
+
| `customer.search({ options: { criteria: 'desc', email } })` | `client.searchCustomers({ email })` |
|
|
22
|
+
| Manual webhook signature check | `verifyWebhookSignature({ ... })` (HMAC + replay protection) |
|
|
23
|
+
| Manual idempotency key generation | Auto-generated by tool layer (deterministic SHA-256) |
|
|
24
|
+
| Manual retry logic | Built-in retry budget + circuit breaker |
|
|
25
|
+
| Manual installments display | `findApplicablePromos({ issuer, ... })` |
|
|
26
|
+
|
|
27
|
+
## Side-by-side: create a payment
|
|
28
|
+
|
|
29
|
+
**Before (`mercadopago`):**
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
import { MercadoPagoConfig, Payment } from "mercadopago";
|
|
33
|
+
|
|
34
|
+
const config = new MercadoPagoConfig({ accessToken: process.env.MP_ACCESS_TOKEN! });
|
|
35
|
+
const payment = new Payment(config);
|
|
36
|
+
|
|
37
|
+
const created = await payment.create({
|
|
38
|
+
body: {
|
|
39
|
+
transaction_amount: 100,
|
|
40
|
+
payment_method_id: "visa",
|
|
41
|
+
payer: { email: "buyer@test.com" },
|
|
42
|
+
token: cardToken,
|
|
43
|
+
description: "Test",
|
|
44
|
+
external_reference: "order-123",
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
console.log(created.id, created.status);
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**After (`@ar-agents/mercadopago` — direct client):**
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
import { MercadoPagoClient } from "@ar-agents/mercadopago";
|
|
54
|
+
|
|
55
|
+
const client = new MercadoPagoClient({ accessToken: process.env.MP_ACCESS_TOKEN! });
|
|
56
|
+
|
|
57
|
+
const created = await client.createPayment({
|
|
58
|
+
transactionAmount: 100, // camelCase
|
|
59
|
+
paymentMethodId: "visa",
|
|
60
|
+
payerEmail: "buyer@test.com", // flat (not nested under `payer`)
|
|
61
|
+
token: cardToken,
|
|
62
|
+
description: "Test",
|
|
63
|
+
externalReference: "order-123",
|
|
64
|
+
});
|
|
65
|
+
console.log(created.id, created.status);
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**After (`@ar-agents/mercadopago` — agent tool):**
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
import { MercadoPagoClient, mercadoPagoTools, InMemoryStateAdapter } from "@ar-agents/mercadopago";
|
|
72
|
+
|
|
73
|
+
const client = new MercadoPagoClient({ accessToken: process.env.MP_ACCESS_TOKEN! });
|
|
74
|
+
const tools = mercadoPagoTools(client, {
|
|
75
|
+
state: new InMemoryStateAdapter(),
|
|
76
|
+
backUrl: "https://yourapp.com/done",
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Tool runs from inside an Agent.generate() call:
|
|
80
|
+
// "Cobrale 100 pesos a buyer@test.com"
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Side-by-side: webhook signature verification
|
|
84
|
+
|
|
85
|
+
**Before (`mercadopago`)**: not provided — you implement HMAC-SHA256 yourself
|
|
86
|
+
from the docs.
|
|
87
|
+
|
|
88
|
+
**After (`@ar-agents/mercadopago`):**
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
import { verifyWebhookSignature, parseWebhookEvent } from "@ar-agents/mercadopago";
|
|
92
|
+
|
|
93
|
+
export async function POST(req: Request) {
|
|
94
|
+
const rawBody = await req.text();
|
|
95
|
+
const event = parseWebhookEvent(JSON.parse(rawBody));
|
|
96
|
+
const verified = await verifyWebhookSignature({
|
|
97
|
+
requestId: req.headers.get("x-request-id"),
|
|
98
|
+
dataId: event!.dataId,
|
|
99
|
+
signatureHeader: req.headers.get("x-signature"),
|
|
100
|
+
secret: process.env.MP_WEBHOOK_SECRET!,
|
|
101
|
+
// 5-min replay protection by default
|
|
102
|
+
});
|
|
103
|
+
if (!verified) return new Response("unauthorized", { status: 401 });
|
|
104
|
+
// ...
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Side-by-side: idempotency
|
|
109
|
+
|
|
110
|
+
**Before (`mercadopago`)**: pass `requestOptions: { idempotencyKey: "..." }`
|
|
111
|
+
manually on each call. You compute the key yourself.
|
|
112
|
+
|
|
113
|
+
**After (`@ar-agents/mercadopago`)**: tools auto-derive a deterministic
|
|
114
|
+
idempotency key from the meaningful inputs (SHA-256 of `external_reference`,
|
|
115
|
+
amount, payment_method, etc.). Same input → same key → MP dedupes safely
|
|
116
|
+
across retries. No manual work.
|
|
117
|
+
|
|
118
|
+
## Side-by-side: retries + timeouts
|
|
119
|
+
|
|
120
|
+
**Before**: implement your own retry loop + AbortController.
|
|
121
|
+
|
|
122
|
+
**After**: built into `MercadoPagoClient`:
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
new MercadoPagoClient({
|
|
126
|
+
accessToken: "...",
|
|
127
|
+
requestTimeoutMs: 30_000, // default 30s
|
|
128
|
+
maxRetries: 1, // default 1, retries 5xx + 429
|
|
129
|
+
circuitBreaker: new CircuitBreaker({ failureThreshold: 5 }),
|
|
130
|
+
// Honors Retry-After on 429 automatically
|
|
131
|
+
});
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## What this toolkit adds that the official SDK doesn't have
|
|
135
|
+
|
|
136
|
+
- **Agent tool layer** for Vercel AI SDK 6+ (`mercadoPagoTools()`)
|
|
137
|
+
- **Webhook HMAC + replay protection** (`verifyWebhookSignature` async)
|
|
138
|
+
- **Circuit breaker** with state machine
|
|
139
|
+
- **Deadline propagation** via parent `AbortSignal`
|
|
140
|
+
- **W3C Trace Context** propagation (OpenTelemetry compat sin peer dep)
|
|
141
|
+
- **Audit logging** with pluggable adapter (`AuditLogger` + `InMemoryAuditLog`)
|
|
142
|
+
- **Webhook idempotency dedup** (`WebhookDedup` — short-circuits MP retries)
|
|
143
|
+
- **Pagination helpers** (`paginate()` AsyncIterable for 7 endpoints)
|
|
144
|
+
- **Token bucket rate limiter** with adaptive learning from MP headers
|
|
145
|
+
- **AR issuer cuotas catalog** (`AR_ISSUER_PROMOS`, `findApplicablePromos`)
|
|
146
|
+
- **OpenTelemetry instrumentation subpath** (`@ar-agents/mercadopago/otel`)
|
|
147
|
+
- **Tool middleware pattern** (`withAuditLog`, `withRateLimit`, `withMetrics`, `withRetry`)
|
|
148
|
+
- **3DS challenge resolution** (`confirmChallengeAndPoll`)
|
|
149
|
+
- **TaxID validation cross-LATAM** (DNI/CUIT/CPF/CNPJ/RFC/RUT/NIT/RUC)
|
|
150
|
+
- **Status detail explainer** (`explainPaymentStatus` — Spanish actionable guidance)
|
|
151
|
+
- **Marketplace fee calculator** (`computeMarketplaceFee`)
|
|
152
|
+
- **Vercel KV state adapters** (subscription state + OAuth tokens + idempotency cache + audit log)
|
|
153
|
+
- **Cookbook** with 8 production-grade recipes
|
|
154
|
+
- **Edge Runtime support** (Web Crypto, no `node:crypto`)
|
|
155
|
+
- **Property-based testing** with fast-check (~1500 random scenarios)
|
|
156
|
+
- **Failure injection tests** + integration tests vs MP sandbox
|
|
157
|
+
- **Benchmarks** (`pnpm bench`)
|
|
158
|
+
|
|
159
|
+
## When to keep using `mercadopago` (official) instead
|
|
160
|
+
|
|
161
|
+
- Your codebase is already deeply integrated with the official SDK
|
|
162
|
+
- You don't need the agent layer (no Vercel AI SDK)
|
|
163
|
+
- You operate primarily server-side with cron jobs and don't care about
|
|
164
|
+
agent ergonomics, audit logs, circuit breakers, or status explainers
|
|
165
|
+
|
|
166
|
+
## When to add `@ar-agents/mercadopago`
|
|
167
|
+
|
|
168
|
+
- You're building anything with an AI agent (Claude, GPT, Gemini)
|
|
169
|
+
- You're deploying to Vercel and want first-class KV adapters
|
|
170
|
+
- You need **production-grade webhook handling** (HMAC + dedup + replay protection)
|
|
171
|
+
- You operate a **marketplace** with per-seller OAuth flows
|
|
172
|
+
- You need **compliance-grade audit logging** for refunds/payments
|
|
173
|
+
- You want **AR-specific knowledge** (cuotas catalog, status_detail explainer in Spanish, AR landmines documented)
|
|
174
|
+
- You want **OpenTelemetry-native** observability without writing instrumentation glue
|
|
175
|
+
|
|
176
|
+
You can use BOTH packages in the same project — they don't conflict.
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recipe 09 — OpenTelemetry wired end-to-end.
|
|
3
|
+
*
|
|
4
|
+
* # Pattern
|
|
5
|
+
*
|
|
6
|
+
* 1. Wire an OTel SDK at app boot (NodeSDK or Edge equivalent)
|
|
7
|
+
* 2. Build the MP client with `traceContext` so each MP request injects a
|
|
8
|
+
* W3C `traceparent` header (correlates with your distributed traces)
|
|
9
|
+
* 3. Wrap the client / tools with the OTel instrumentation from
|
|
10
|
+
* `@ar-agents/mercadopago/otel` to get spans + metrics for every call:
|
|
11
|
+
* - `mp.request` span per MP API call (with attrs for endpoint, method,
|
|
12
|
+
* status, duration, retry count)
|
|
13
|
+
* - `mp.tool` span per agent-invoked tool (with input + output attrs)
|
|
14
|
+
* - Metrics: latency p50/p95/p99, error rate, rate-limit-remaining
|
|
15
|
+
* 4. Ship traces + metrics to your OTel collector (Honeycomb, Datadog,
|
|
16
|
+
* New Relic, Grafana Tempo, ...)
|
|
17
|
+
*
|
|
18
|
+
* # Why this matters
|
|
19
|
+
*
|
|
20
|
+
* MP's API is the slow path of any agent that uses it (200-600ms per call).
|
|
21
|
+
* Without observability you can't tell:
|
|
22
|
+
* - Which tool calls are slow (`create_payment` vs `create_subscription` vs `get_payment`)
|
|
23
|
+
* - When MP is degraded (rate-limit-remaining trending down before failures)
|
|
24
|
+
* - Where retries kick in (so you can size your timeout budget correctly)
|
|
25
|
+
*
|
|
26
|
+
* # Setup (one-time at app boot)
|
|
27
|
+
*
|
|
28
|
+
* ```ts
|
|
29
|
+
* // instrumentation.ts (Vercel auto-loads this if present)
|
|
30
|
+
* import { NodeSDK } from "@opentelemetry/sdk-node";
|
|
31
|
+
* import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
|
|
32
|
+
* import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http";
|
|
33
|
+
* import { PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics";
|
|
34
|
+
*
|
|
35
|
+
* const sdk = new NodeSDK({
|
|
36
|
+
* serviceName: "my-ar-agent",
|
|
37
|
+
* traceExporter: new OTLPTraceExporter({ url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT! }),
|
|
38
|
+
* metricReader: new PeriodicExportingMetricReader({
|
|
39
|
+
* exporter: new OTLPMetricExporter({ url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT! }),
|
|
40
|
+
* exportIntervalMillis: 30_000,
|
|
41
|
+
* }),
|
|
42
|
+
* });
|
|
43
|
+
* sdk.start();
|
|
44
|
+
* ```
|
|
45
|
+
*
|
|
46
|
+
* # Edge Runtime
|
|
47
|
+
*
|
|
48
|
+
* Edge-compatible. Use `@vercel/otel` instead of `@opentelemetry/sdk-node`.
|
|
49
|
+
* The instrumentation in `@ar-agents/mercadopago/otel` is runtime-agnostic
|
|
50
|
+
* (uses the `@opentelemetry/api` interface, no Node-only deps).
|
|
51
|
+
*/
|
|
52
|
+
|
|
53
|
+
import { trace, context as otelContext } from "@opentelemetry/api";
|
|
54
|
+
import { Experimental_Agent as Agent, stepCountIs } from "ai";
|
|
55
|
+
import {
|
|
56
|
+
MercadoPagoClient,
|
|
57
|
+
mercadoPagoTools,
|
|
58
|
+
InMemoryStateAdapter,
|
|
59
|
+
CircuitBreaker,
|
|
60
|
+
} from "@ar-agents/mercadopago";
|
|
61
|
+
import {
|
|
62
|
+
instrumentMercadoPagoClient,
|
|
63
|
+
instrumentMercadoPagoTools,
|
|
64
|
+
} from "@ar-agents/mercadopago/otel";
|
|
65
|
+
|
|
66
|
+
const tracer = trace.getTracer("my-ar-agent");
|
|
67
|
+
const meter = trace.getTracer("my-ar-agent"); // simplified — use `metrics.getMeter` in real code
|
|
68
|
+
|
|
69
|
+
// 1. Build the client with traceContext so each MP request injects traceparent.
|
|
70
|
+
// The function returns whatever active OTel context exists at call time.
|
|
71
|
+
const mp = new MercadoPagoClient({
|
|
72
|
+
accessToken: process.env.MP_ACCESS_TOKEN!,
|
|
73
|
+
// Wire OTel context propagation. MP logs will be correlated with your trace
|
|
74
|
+
// graph, and downstream tooling (Datadog APM, Honeycomb) can join the dots.
|
|
75
|
+
traceContext: () => {
|
|
76
|
+
const span = trace.getActiveSpan();
|
|
77
|
+
if (!span) return undefined;
|
|
78
|
+
const ctx = span.spanContext();
|
|
79
|
+
return {
|
|
80
|
+
traceId: ctx.traceId,
|
|
81
|
+
spanId: ctx.spanId,
|
|
82
|
+
traceFlags: ctx.traceFlags,
|
|
83
|
+
};
|
|
84
|
+
},
|
|
85
|
+
// Production hardening — circuit breaker observed by OTel as well.
|
|
86
|
+
circuitBreaker: new CircuitBreaker({
|
|
87
|
+
failureThreshold: 5,
|
|
88
|
+
rollingWindowMs: 60_000,
|
|
89
|
+
cooldownMs: 30_000,
|
|
90
|
+
}),
|
|
91
|
+
maxRetries: 2,
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// 2. Instrument the client. Wraps every public method with a span + metric.
|
|
95
|
+
const instrumentedMp = instrumentMercadoPagoClient(mp, { tracer, meter });
|
|
96
|
+
|
|
97
|
+
// 3. Build tools as usual, then wrap with OTel tool instrumentation.
|
|
98
|
+
const baseTools = mercadoPagoTools(instrumentedMp, {
|
|
99
|
+
state: new InMemoryStateAdapter(),
|
|
100
|
+
backUrl: "https://example.com/done",
|
|
101
|
+
});
|
|
102
|
+
const tools = instrumentMercadoPagoTools(baseTools, { tracer });
|
|
103
|
+
|
|
104
|
+
// 4. Use the agent. Every tool call becomes a span; every MP request is a
|
|
105
|
+
// nested span with full request context. Open Honeycomb / Tempo and you
|
|
106
|
+
// see the full picture.
|
|
107
|
+
export const agent = new Agent({
|
|
108
|
+
model: "anthropic/claude-sonnet-4-6",
|
|
109
|
+
instructions: "You are a billing assistant for a SaaS in Argentina.",
|
|
110
|
+
tools,
|
|
111
|
+
stopWhen: stepCountIs(8),
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Trace shape (in your APM):
|
|
116
|
+
*
|
|
117
|
+
* tool: agent.generate (root span)
|
|
118
|
+
* ├── tool: create_payment_preference (mp.tool)
|
|
119
|
+
* │ └── http: POST /checkout/preferences (mp.request)
|
|
120
|
+
* │ attrs:
|
|
121
|
+
* │ mp.method = POST
|
|
122
|
+
* │ mp.path = /checkout/preferences
|
|
123
|
+
* │ mp.status = 201
|
|
124
|
+
* │ mp.duration_ms = 287
|
|
125
|
+
* │ mp.retried = false
|
|
126
|
+
* │ mp.idempotency_key = <uuid>
|
|
127
|
+
* │
|
|
128
|
+
* └── tool: get_payment (mp.tool)
|
|
129
|
+
* └── http: GET /v1/payments/9999 (mp.request)
|
|
130
|
+
* attrs:
|
|
131
|
+
* mp.method = GET
|
|
132
|
+
* mp.duration_ms = 142
|
|
133
|
+
*
|
|
134
|
+
* Metrics emitted (with attributes [endpoint, method, status_class]):
|
|
135
|
+
*
|
|
136
|
+
* mp_request_duration_ms (histogram)
|
|
137
|
+
* mp_request_total (counter)
|
|
138
|
+
* mp_request_error_total (counter, by status_class=4xx|5xx|network)
|
|
139
|
+
* mp_circuit_breaker_state (gauge: closed=0, open=1, half_open=0.5)
|
|
140
|
+
* mp_rate_limit_remaining (gauge, from x-ratelimit-remaining response header)
|
|
141
|
+
*/
|
|
142
|
+
|
|
143
|
+
// Example: wrap a request handler with a parent span so MP calls join the trace.
|
|
144
|
+
export async function handleAgentRequest(userMessage: string) {
|
|
145
|
+
return tracer.startActiveSpan("agent.request", async (span) => {
|
|
146
|
+
try {
|
|
147
|
+
const result = await agent.generate({ prompt: userMessage });
|
|
148
|
+
span.setAttribute("agent.steps", result.steps.length);
|
|
149
|
+
span.setAttribute("agent.finish_reason", result.finishReason);
|
|
150
|
+
return result;
|
|
151
|
+
} finally {
|
|
152
|
+
span.end();
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
}
|
package/cookbook/README.md
CHANGED
|
@@ -16,6 +16,7 @@ deploy on Vercel as-is.
|
|
|
16
16
|
| 06 | `06-3ds-challenge.ts` | Detect challenge → redirect buyer → recover via webhook |
|
|
17
17
|
| 07 | `07-auth-only-order.ts` | `Order` with manual capture → capture later when service completes |
|
|
18
18
|
| 08 | `08-recovery-patterns.ts` | Retry expired subscriptions, recover stuck-pending payments, etc. |
|
|
19
|
+
| 09 | `09-otel-wired.ts` | Full OpenTelemetry wiring — spans + metrics for every MP call + tool |
|
|
19
20
|
|
|
20
21
|
## Conventions
|
|
21
22
|
|