{"_id":"@agentoffernetwork/sdk","_rev":"6-8c9dc6406f35e866f3daebd0736f9442","name":"@agentoffernetwork/sdk","dist-tags":{"beta":"0.0.2-beta.2","latest":"0.1.1"},"versions":{"0.0.1":{"name":"@agentoffernetwork/sdk","version":"0.0.1","keywords":["agent","offer","network","llm","ai","sdk","advertising","recommendation","chatgpt","claude","mcp"],"author":{"name":"Agent Offer Network","email":"dev@agentoffernetwork.com"},"license":"MIT","_id":"@agentoffernetwork/sdk@0.0.1","maintainers":[{"name":"jolibox-developer","email":"developer@jolibox.com"}],"homepage":"https://agentoffernetwork.com","bugs":{"url":"https://gitlab.com/jolibox-dev-team/aon/aon-main/-/issues"},"dist":{"shasum":"28757c5df0488ea447dea73002d20a389095c087","tarball":"https://registry.npmjs.org/@agentoffernetwork/sdk/-/sdk-0.0.1.tgz","fileCount":39,"integrity":"sha512-wDgP3d8JmdQaBfUTEk/8lRQAlDXMF2AECsm90kRdyAT2OQsZojGWr+yUz0GWPGwdXWceBAhNCwELR6/IXaVnsA==","signatures":[{"sig":"MEQCID59zZ18cbGy0w3vh07aHSsd+VXY8J5ZB9o8Ctv7t/sqAiBzyMNQrzJlNg+1DaHQAtPQf//WnzASE58Jwe2Ozozw2A==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":100367},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"}},"gitHead":"0ec48b9a988b35374e75bb027a59709d909eb41a","scripts":{"test":"vitest run","build":"vite build"},"_npmUser":{"name":"jolibox-developer","email":"developer@jolibox.com"},"repository":{"url":"git+https://gitlab.com/jolibox-dev-team/aon/aon-main.git","type":"git","directory":"sdk/typescript"},"_npmVersion":"10.8.2","description":"TypeScript SDK for Agent Offer Network — intent-driven offer matching, click/conversion tracking, and recommendation formatting for LLM agents.","directories":{},"_nodeVersion":"20.20.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/sdk_0.0.1_1775558617521_0.8382195721331043","host":"s3://npm-registry-packages-npm-production"}},"0.0.2-beta.1":{"name":"@agentoffernetwork/sdk","version":"0.0.2-beta.1","keywords":["agent","offer","network","llm","ai","sdk","advertising","recommendation","chatgpt","claude","mcp"],"author":{"name":"Agent Offer Network","email":"dev@agentoffernetwork.com"},"license":"MIT","_id":"@agentoffernetwork/sdk@0.0.2-beta.1","maintainers":[{"name":"jolibox-developer","email":"developer@jolibox.com"}],"homepage":"https://agentoffernetwork.com","bugs":{"url":"https://gitlab.com/jolibox-dev-team/aon/aon-main/-/issues"},"dist":{"shasum":"aa7c7a1c6ce12f1bb10fc48086b4b8e52db24ae0","tarball":"https://registry.npmjs.org/@agentoffernetwork/sdk/-/sdk-0.0.2-beta.1.tgz","fileCount":39,"integrity":"sha512-/kAv0MVfJC7U1hS/zPzW7MMudZbd513XPcqIiN80qFDP2MGzHaue7ZtqrtlIwV4rWnCyLtU5L2sgvx6ms7kVWw==","signatures":[{"sig":"MEYCIQD5O6zn9W/YiW/CHJZ9YFqQtDS1ukDgaFoF+XuGY3CdpAIhAIogRRMTTY+ya1oJ72P5VikFC54I07MkahHXqh/8URe5","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":100374},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"}},"gitHead":"4baa97dc457a2c05ea00c2a4eb19beb2ab8475c6","scripts":{"test":"vitest run","build":"vite build"},"_npmUser":{"name":"jolibox-developer","email":"developer@jolibox.com"},"repository":{"url":"git+https://gitlab.com/jolibox-dev-team/aon/aon-main.git","type":"git","directory":"sdk/typescript"},"_npmVersion":"10.8.2","description":"TypeScript SDK for Agent Offer Network — intent-driven offer matching, click/conversion tracking, and recommendation formatting for LLM agents.","directories":{},"_nodeVersion":"20.20.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"readmeFilename":"README.md","_npmOperationalInternal":{"tmp":"tmp/sdk_0.0.2-beta.1_1775562168463_0.4514939874539545","host":"s3://npm-registry-packages-npm-production"}},"0.0.2-beta.2":{"name":"@agentoffernetwork/sdk","version":"0.0.2-beta.2","keywords":["agent","offer","network","llm","ai","sdk","advertising","recommendation","chatgpt","claude","mcp"],"author":{"name":"Agent Offer Network","email":"dev@agentoffernetwork.com"},"license":"MIT","_id":"@agentoffernetwork/sdk@0.0.2-beta.2","maintainers":[{"name":"jolibox-developer","email":"developer@jolibox.com"}],"homepage":"https://agentoffernetwork.com","bugs":{"url":"https://gitlab.com/jolibox-dev-team/aon/aon-main/-/issues"},"dist":{"shasum":"e4d9de03e7c3d4dbb81c0cda3aeb5fe09116ff06","tarball":"https://registry.npmjs.org/@agentoffernetwork/sdk/-/sdk-0.0.2-beta.2.tgz","fileCount":39,"integrity":"sha512-OaxPfPEBz65zmmsqRulqqIG1cPYL/M0SUdJVb+e95/0LugOqUmyZIB/fI78Kf2AGpOyqmD+IJOdrnhjCzjGu1Q==","signatures":[{"sig":"MEYCIQDEwnf1OrfoZLOB8t83Nl1bzoy6MOycBqd0dt/B1uWAJQIhAMM0Uhj0CkKwv8wR8OCeOgYcJ9z9x/jzsjWxuyV+9Mba","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":100374},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"}},"gitHead":"7c4b590259549131178f30d1b91ae8134fcda2ba","scripts":{"test":"vitest run","build":"vite build"},"_npmUser":{"name":"jolibox-developer","email":"developer@jolibox.com"},"repository":{"url":"git+https://gitlab.com/jolibox-dev-team/aon/aon-main.git","type":"git","directory":"sdk/typescript"},"_npmVersion":"10.8.2","description":"TypeScript SDK for Agent Offer Network — intent-driven offer matching, click/conversion tracking, and recommendation formatting for LLM agents.","directories":{},"_nodeVersion":"20.20.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"readmeFilename":"README.md","_npmOperationalInternal":{"tmp":"tmp/sdk_0.0.2-beta.2_1775562538865_0.19361956397039193","host":"s3://npm-registry-packages-npm-production"}},"0.0.2":{"name":"@agentoffernetwork/sdk","version":"0.0.2","keywords":["agent","offer","network","llm","ai","sdk","advertising","recommendation","chatgpt","claude","mcp"],"author":{"name":"Agent Offer Network","email":"dev@agentoffernetwork.com"},"license":"MIT","_id":"@agentoffernetwork/sdk@0.0.2","maintainers":[{"name":"jolibox-developer","email":"developer@jolibox.com"}],"homepage":"https://agentoffernetwork.com","bugs":{"url":"https://gitlab.com/jolibox-dev-team/aon/aon-main/-/issues"},"dist":{"shasum":"666f2c927f15e58bc2f6621d46cbb11127e0632a","tarball":"https://registry.npmjs.org/@agentoffernetwork/sdk/-/sdk-0.0.2.tgz","fileCount":39,"integrity":"sha512-Qr2XRVj+WIas9w/ksRwQZCyZoBaB3OWZGPljsqVizSD3IBPex/SfJ/WVWjH8eX54yt+FGXJXfzJSPcLCXzIIlw==","signatures":[{"sig":"MEQCIE3levedMQruYAU7wu//9lCLB34aBC8iCk7HHMkZCWpUAiAx1Zh+8PUtSI8liinAV0yZthtpyMrReK1mSKKKSoomig==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":100367},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"}},"gitHead":"7c4b590259549131178f30d1b91ae8134fcda2ba","scripts":{"test":"vitest run","build":"vite build"},"_npmUser":{"name":"jolibox-developer","email":"developer@jolibox.com"},"repository":{"url":"git+https://gitlab.com/jolibox-dev-team/aon/aon-main.git","type":"git","directory":"sdk/typescript"},"_npmVersion":"10.8.2","description":"TypeScript SDK for Agent Offer Network — intent-driven offer matching, click/conversion tracking, and recommendation formatting for LLM agents.","directories":{},"_nodeVersion":"20.20.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/sdk_0.0.2_1775563219196_0.4850528235721656","host":"s3://npm-registry-packages-npm-production"}},"0.1.0":{"name":"@agentoffernetwork/sdk","version":"0.1.0","keywords":["agent","offer","network","llm","ai","sdk","advertising","recommendation","chatgpt","claude","mcp"],"author":{"name":"Agent Offer Network","email":"dev@agentoffernetwork.com"},"license":"MIT","_id":"@agentoffernetwork/sdk@0.1.0","maintainers":[{"name":"jolibox-developer","email":"developer@jolibox.com"}],"homepage":"https://agentoffernetwork.com","bugs":{"url":"https://gitlab.com/jolibox-dev-team/aon/aon-main/-/issues"},"dist":{"shasum":"e9197984d4dfdf6e59f57b87ca8900a427e16ef9","tarball":"https://registry.npmjs.org/@agentoffernetwork/sdk/-/sdk-0.1.0.tgz","fileCount":47,"integrity":"sha512-V9nG6DB4r+u1lVTuZl3xVeukq622opDXdTGWESO+5Ry+AmcAsH4dJhn33nnXdRJ48ZYog5pmwXzCDiavk87ypA==","signatures":[{"sig":"MEUCIH1HV3vUyRhaxH1ZSp3ZhlUWW/zly49MGYW11Kw3uhcEAiEAzmtfpUSkg33DTCfPOd8xaIywH1JfLFO46nJ+rnzDXb8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":223179},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"}},"gitHead":"c2ab519827a651e0086dd5e3e4e7059d73011ca0","scripts":{"test":"vitest run","build":"vite build"},"_npmUser":{"name":"jolibox-developer","email":"developer@jolibox.com"},"repository":{"url":"git+https://gitlab.com/jolibox-dev-team/aon/aon-main.git","type":"git","directory":"sdk/typescript"},"_npmVersion":"10.8.2","description":"TypeScript SDK for Agent Offer Network — intent-driven offer matching, click/conversion tracking, and recommendation formatting for LLM agents.","directories":{},"_nodeVersion":"20.20.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.0_1776356144177_0.056569655096292415","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@agentoffernetwork/sdk","version":"0.1.1","description":"TypeScript SDK for Agent Offer Network — intent-driven offer matching, click/conversion tracking, and recommendation formatting for LLM agents.","type":"module","license":"MIT","author":{"name":"Agent Offer Network","email":"dev@agentoffernetwork.com"},"homepage":"https://agentoffernetwork.com","repository":{"type":"git","url":"git+https://gitlab.com/jolibox-dev-team/aon/aon-main.git","directory":"sdk/typescript"},"bugs":{"url":"https://gitlab.com/jolibox-dev-team/aon/aon-main/-/issues"},"keywords":["agent","offer","network","llm","ai","sdk","advertising","recommendation","chatgpt","claude","mcp"],"main":"./dist/index.cjs","module":"./dist/index.mjs","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"}},"publishConfig":{"access":"public"},"engines":{"node":">=20"},"scripts":{"build":"vite build","test":"vitest run"},"_id":"@agentoffernetwork/sdk@0.1.1","gitHead":"f99bd1c2df4c347f7ae3121c27ec430189003dd1","_nodeVersion":"20.20.2","_npmVersion":"10.8.2","dist":{"integrity":"sha512-+hoXpqB6CFgfawclJnjVfAOpp4VD+RNJmrrhMfy62JHJTbQP3o8I81u98gs3Us2PW4laUUoIu50GYE+WBDfD2A==","shasum":"60da8cbea5e3ccc86a2432b3bff61dee1da93813","tarball":"https://registry.npmjs.org/@agentoffernetwork/sdk/-/sdk-0.1.1.tgz","fileCount":47,"unpackedSize":223392,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDCaEcz6eL87DS1110KWMiCtdbDxbuVVnF1/6Js35BJVwIhAJ5m9lE7ppqjEaGKpQLor1gZyB/YsQna/jz3TftuBTML"}]},"_npmUser":{"name":"jolibox-developer","email":"developer@jolibox.com"},"directories":{},"maintainers":[{"name":"jolibox-developer","email":"developer@jolibox.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/sdk_0.1.1_1776391793559_0.8288370229169306"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-07T10:43:37.425Z","modified":"2026-04-17T02:09:53.838Z","0.0.1":"2026-04-07T10:43:37.663Z","0.0.2-beta.1":"2026-04-07T11:42:48.618Z","0.0.2-beta.2":"2026-04-07T11:48:59.017Z","0.0.2":"2026-04-07T12:00:19.367Z","0.1.0":"2026-04-16T16:15:44.327Z","0.1.1":"2026-04-17T02:09:53.708Z"},"bugs":{"url":"https://gitlab.com/jolibox-dev-team/aon/aon-main/-/issues"},"author":{"name":"Agent Offer Network","email":"dev@agentoffernetwork.com"},"license":"MIT","homepage":"https://agentoffernetwork.com","keywords":["agent","offer","network","llm","ai","sdk","advertising","recommendation","chatgpt","claude","mcp"],"repository":{"type":"git","url":"git+https://gitlab.com/jolibox-dev-team/aon/aon-main.git","directory":"sdk/typescript"},"description":"TypeScript SDK for Agent Offer Network — intent-driven offer matching, click/conversion tracking, and recommendation formatting for LLM agents.","maintainers":[{"name":"jolibox-developer","email":"developer@jolibox.com"}],"readme":"# @agentoffernetwork/sdk\n\nTypeScript SDK for [Agent Offer Network](https://agentoffernetwork.com) — connect your LLM agent to a marketplace of product and service offers.\n\n> ⚠️ **v0.1.1 Breaking**：完全对齐 Protocol Offer Schema v0.1。从内部预览版 0.0.1 升级需改代码，见 [Migration Guide](#migration-guide-001--010)。\n>\n> 🛑 **`0.1.0` 已废，请勿安装** — 发包时 CI 缓存命中旧 dist 导致 runtime import 失败。详见 [CHANGELOG](./CHANGELOG.md#011--2026-04-17)。安装请用 `@agentoffernetwork/sdk@^0.1.1`。\n\n## Features\n\n- **Intent-driven search** — describe what the user wants in natural language, get matched offers\n- **Multimodal intent** — text + image support (OpenAI-compatible content parts format)\n- **Click & conversion tracking** — full attribution pipeline for monetization\n- **Recommendation formatting** — ready-to-display output with disclosure labels\n- **Strong typing** — `Category.attributes` is a discriminated union (33 sub_type interfaces); **zero `cast` needed** thanks to TypeScript native narrowing\n- **Zero dependencies** — uses native `fetch` (Node 20+)\n- **Dual mode** — `mock` for development, `live` for production\n\n## Install\n\n```bash\nnpm install @agentoffernetwork/sdk\n```\n\nRequires Node **20+**.\n\n## Fastest Start\n\nStart in `mock` mode first. It returns built-in sample offers locally, so you\ncan verify your integration before requesting a live API key.\n\n```typescript\nimport { initialize } from '@agentoffernetwork/sdk';\n\nconst client = await initialize({\n  apiKey: 'test-key',\n  mode: 'mock',\n});\n\nconst result = await client.queryOffers({\n  intent: {\n    content: [{ type: 'input_text', text: 'noise-cancelling headphones under $300' }],\n  },\n  context: {\n    userProfile: {},\n  },\n});\n\nconst top = result.offers[0];\nif (top) {\n  console.log(top.offerInfo.title);\n}\n```\n\nTo switch to production later, keep the same code and only change:\n\n```typescript\nconst client = await initialize({\n  apiKey: process.env.AGENTOFFERNETWORK_API_KEY!,\n  mode: 'live',\n  appId: process.env.AON_APP_ID,   // optional — identifies your app for attribution\n});\n```\n\n## Quick Start\n\n```typescript\nimport { initialize, formatPrice } from '@agentoffernetwork/sdk';\n\nconst client = await initialize({\n  apiKey: 'test-key',\n  mode: 'mock',\n});\n\n// Search offers by intent\nconst result = await client.queryOffers({\n  intent: {\n    content: [{ type: 'input_text', text: 'noise-cancelling headphones under $300' }],\n  },\n  context: {\n    userProfile: {},\n  },\n  pagination: { limit: 5 },\n});\n\n// Access nested fields per Protocol v0.1\nfor (const offer of result.offers) {\n  const info = offer.offerInfo;\n  const price = info.commercial?.price;\n  console.log(`${info.title} — ${formatPrice(price) ?? 'N/A'}`);\n  console.log(client.formatRecommendation(offer, { style: 'markdown' }));\n}\n```\n\n## API\n\n### `initialize(config): Promise<AgentOfferClient>`\n\nCreate an SDK client instance.\n\n```typescript\nconst client = await initialize({\n  apiKey: 'your-api-key',        // Required\n  mode: 'mock',                  // 'mock' | 'live'\n  baseUrl: 'https://api.agentoffernetwork.com', // Optional, default shown\n  timeout: 5000,                 // Optional, ms\n  appId: 'my-app-id',            // Optional — sent as `x-aon-app-id` header\n});\n```\n\n### `client.queryOffers(params): Promise<QueryOffersResponse>`\n\nSearch offers by user intent.\n\n```typescript\nconst result = await client.queryOffers({\n  intent: {\n    content: [\n      { type: 'input_text', text: 'project management tool for small teams' },\n    ],\n  },\n  context: {\n    platform: {\n      name: 'chatgpt',\n      channel: 'action',\n    },\n    userProfile: {\n      language: 'en',\n    },\n  },\n  pagination: {\n    limit: 10,\n    offset: 0,\n  },\n});\n\n// result.offers    — Offer[] (each has .uuid, .offerInfo, .entity, .action, .bid, ...)\n// result.total     — number\n// result.hasMore   — boolean\n// result.queryId   — string\n```\n\n### `client.reportClick(event): Promise<ClickResult>`\n\nTrack when a user clicks an offer. Note: `trackingUrl` is the AON tracking\nendpoint (from your integration layer), NOT the advertiser destination.\nThe advertiser destination is `offer.action.payload.target`.\n\n```typescript\nconst click = await client.reportClick({\n  offerId: offer.uuid,\n  trackingUrl: aonTrackingEndpoint,        // AON tracking endpoint\n  timestamp: new Date().toISOString(),\n});\n\n// click.trackingId — use for conversion attribution\n// click.timestamp\n```\n\n### `client.reportConversion(event): Promise<void>`\n\nTrack when a user completes a purchase.\n\n```typescript\nawait client.reportConversion({\n  offerId: offer.uuid,\n  trackingId: click.trackingId,\n  conversionType: 'sale',\n  amount: '29.99',\n  currency: 'USD',\n  timestamp: new Date().toISOString(),\n});\n```\n\n### `client.formatRecommendation(offer, options?): string`\n\nFormat an offer as display text. Uses `offer.action.payload.target` for the link.\n\n```typescript\n// Styles: 'brief' | 'detailed' | 'markdown'\nconst text = client.formatRecommendation(offer, {\n  style: 'markdown',\n  includeDisclosure: true,       // Default true\n  disclosureText: 'Sponsored',   // Default 'Sponsored'\n  includePrice: true,            // Default true\n});\n```\n\n### `formatPrice(price): string | undefined`\n\nStandalone helper that returns a human-friendly price string (e.g. `\"349.99 USD\"`)\nor `undefined` if no price.\n\n```typescript\nimport { formatPrice } from '@agentoffernetwork/sdk';\n\nconst text = formatPrice(offer.offerInfo.commercial?.price);\n// \"349.99 USD\" or undefined\n```\n\n### `validateCategory(category)` — runtime schema check\n\n```typescript\nimport { validateCategory, AonValidationError } from '@agentoffernetwork/sdk';\n\ntry {\n  validateCategory(offer.offerInfo.category);\n} catch (e) {\n  if (e instanceof AonValidationError) {\n    console.error(e.message, e.details?.jsonPath);\n    // e.g. \"offer.offerInfo.category.attributes.sub_type\"\n  }\n}\n```\n\n## Context\n\nThe optional `QueryContext` helps the backend improve matching. Fill in what's available:\n\n| Field | Type | Example | Purpose |\n|-------|------|---------|---------|\n| `platform.name` | string | `'sdk'`, `'mcp-skill'`, `'chatgpt'`, `'coze'`, `'dify'` | Platform identification |\n| `platform.channel` | string | `'action'`, `'mcp'` | Integration channel |\n| `userProfile.language` | string | `'en'`, `'zh-CN'` | Language matching |\n| `userProfile.interests` | string[] | `['travel']` | Matching hints |\n| `sessionId` | string | UUID | Dedup within session |\n| `userProfile.userPseudoId` | string | — | Pseudonymous user key |\n\n### `createContextForPlatform(target, options?): QueryContext`\n\nUse the explicit platform adapter when you already know the host platform.\n\n```typescript\nimport { createContextForPlatform } from '@agentoffernetwork/sdk';\n\nconst mcpContext = createContextForPlatform('mcp-skill', {\n  interests: ['Apple ecosystem user'],\n});\n\nconst cozeContext = createContextForPlatform('coze', {\n  nativeUserId: 'user-123',\n  nativeSessionId: 'conv-1',\n});\n```\n\nNotes:\n\n- `detectContext()` remains available for legacy auto-detection.\n- Browser-like runtimes may still return `web` / `action` through `detectContext()` for backward compatibility.\n- ChatGPT Action integrations should continue omitting `platform` and `userPseudoId` in the request body; the F011 server path injects them automatically.\n\n## Error Handling\n\n```typescript\nimport {\n  AonAuthError,\n  AonRateLimitError,\n  AonNetworkError,\n  AonValidationError,\n  AonApiError,\n  AonProtocolWarning,\n  protocolWarnings,\n} from '@agentoffernetwork/sdk';\n\ntry {\n  const result = await client.queryOffers({ /* ... */ });\n} catch (err) {\n  if (err instanceof AonAuthError) {\n    // Invalid API key (401)\n  } else if (err instanceof AonRateLimitError) {\n    // Too many requests (429)\n  } else if (err instanceof AonNetworkError) {\n    // Network/timeout error\n  } else if (err instanceof AonValidationError) {\n    // Invalid parameters (has .details?.jsonPath for precise location)\n  } else if (err instanceof AonApiError) {\n    // Business logic error (err.code, err.message)\n  }\n}\n\n// Subscribe to upstream protocol deviations (e.g. envelope-level warnings)\nconst unsubscribe = protocolWarnings.on((warning: AonProtocolWarning) => {\n  console.warn('[AON protocol deviation]', warning.message, warning.details);\n});\n```\n\n## Modes\n\n| Mode | Use case | Backend |\n|------|----------|---------|\n| `mock` | Development & testing | Built-in mock data (12 offers, nested shape) |\n| `live` | Production | `https://api.agentoffernetwork.com` |\n\nMock mode defaults to filtering offers with `auditStatus === \"reject\"` (matches production behavior; no opt-out).\n\n## Platform Integrations\n\nThis SDK is the foundation for agent platform integrations:\n\n| Platform | Integration | Package |\n|----------|-------------|---------|\n| Claude (MCP) | MCP tool server | `@agentoffernetwork/skill` |\n| ChatGPT | OpenAPI Action | Direct API (see `sdk/openapi.json`) |\n| Coze / Dify | HTTP Plugin | Direct API (see `sdk/openapi.json`) |\n| Custom Agent | Code integration | This SDK |\n\n---\n\n## Migration Guide (0.0.1 → 0.1.0)\n\nv0.1.0 is the first public release and is fully aligned with Protocol Offer Schema v0.1.\nThe internal preview 0.0.1 used a flat structure that does **not** decode real API payloads.\nIf you wrote code against 0.0.1, update per this guide before upgrading.\n\n### Field Mapping\n\n| Old SDK (0.0.1) | New SDK (0.1.0) | Type change |\n|---|---|---|\n| `offer.id` | `offer.uuid` | string → string |\n| `offer.title` | `offer.offerInfo.title` | string |\n| `offer.description` | `offer.offerInfo.description` | string |\n| `offer.offerType` | `offer.offerInfo.offerType` | string (Literal) |\n| `offer.category` | `offer.offerInfo.category` | interface restructured (see §Category) |\n| `offer.status` | `offer.offerInfo.status` | string |\n| `offer.expireAt` | `offer.offerInfo.expireAt` | string |\n| `offer.price.amount` | `offer.offerInfo.commercial?.price.amount` | **number → string (decimal)** |\n| `offer.price.currency` | `offer.offerInfo.commercial?.price.currency` | string |\n| `offer.price.display` | (removed — use `formatPrice(price)`) | — |\n| `offer.trackingUrl` | `offer.action.payload.target` | string (⚠️ semantics differ — see below) |\n| `offer.tags` | (removed — no replacement) | — |\n| `offer.conversionRule` | (removed — moved to Postback protocol) | — |\n| `Category.subType` | (removed — moved to `category.attributes.subType`) | — |\n| `Money` interface | (removed — use `Price`) | — |\n| `ConversionRule` interface | (removed) | — |\n\n### Type Imports\n\n```diff\n- import type { Offer, Money, ConversionRule } from '@agentoffernetwork/sdk';\n+ import type { Offer, OfferInfo, CommercialInfo, Price, AuditStatus } from '@agentoffernetwork/sdk';\n```\n\n### Before / After — `queryOffers` + `formatRecommendation`\n\n```typescript\n// ───── 0.0.1 (old flat structure) ──────────────────────────────────\nconst response = await client.queryOffers(params);\nfor (const offer of response.offers) {\n  console.log(offer.title, offer.price?.display ?? 'N/A');\n  console.log(`Click → ${offer.trackingUrl}`);\n  console.log(client.formatRecommendation(offer));\n}\n\nconst click = await client.reportClick({\n  offerId: offer.id,\n  trackingUrl: offer.trackingUrl,\n  timestamp: new Date().toISOString(),\n});\n\n// ───── 0.1.0 (nested aligned with Protocol v0.1) ──────────────────\nimport { formatPrice } from '@agentoffernetwork/sdk';\n\nconst response = await client.queryOffers(params);\nfor (const offer of response.offers) {\n  const info = offer.offerInfo;\n  const price = info.commercial?.price;\n  console.log(info.title, formatPrice(price) ?? 'N/A');\n  // `action.payload.target` is the advertiser destination (e.g. https://notion.so/plus)\n  // — NOT the AON tracking endpoint.\n  console.log(`Destination → ${offer.action.payload.target}`);\n  console.log(client.formatRecommendation(offer));\n}\n\n// The click event still carries `trackingUrl` (the AON tracking endpoint),\n// but you now get it from your own integration (backend / wrapper), not from the Offer.\nconst click = await client.reportClick({\n  offerId: offer.uuid,                       // was offer.id\n  trackingUrl: aonTrackingEndpoint,          // provided by your integration\n  timestamp: new Date().toISOString(),\n});\n```\n\n### TypeScript Narrowing Advantage\n\n`Category.attributes` is a native TypeScript discriminated union keyed on\n`subType`. **Zero `cast` calls are needed** — the compiler narrows attributes\nautomatically once you check `category.type` and `attributes.subType`.\n\n```typescript\nimport type { Category } from '@agentoffernetwork/sdk';\n\nfunction render(cat: Category) {\n  if (cat.type === 'electronics') {\n    const attrs = cat.attributes;\n    if (attrs.subType === 'audio') {\n      // attrs is now AudioAttributes — `audioType` is typed\n      const kind: 'earbuds' | 'headphones' | 'speaker' | 'soundbar' = attrs.audioType;\n      console.log(kind);\n    }\n  }\n}\n```\n\nThis is a direct improvement over the Python SDK (which requires `cast(AudioAttributes, attrs)`).\n\n### tracking_url Semantics\n\n0.0.1 had `Offer.trackingUrl` pointing to an AON redirect URL (conflating two concerns).\nIn 0.1.0 there are **two separate URLs**:\n\n| URL | Location | What it is |\n|---|---|---|\n| Advertiser destination | `offer.action.payload.target` | Where the user actually goes (e.g. `https://notion.so/plus`) |\n| AON tracking endpoint | `ClickEvent.trackingUrl` (user-supplied) | URL for reporting click attribution; obtained from your backend / integration layer |\n\nSDK no longer holds the AON tracking endpoint on `Offer`. When the user clicks a\nrecommendation, your app/agent code:\n1. Redirects the user to `offer.action.payload.target`\n2. Calls `client.reportClick({ offerId: offer.uuid, trackingUrl: <AON endpoint>, ... })`\n\nThe `formatRecommendation(offer)` helper uses `offer.action.payload.target` for the displayed link.\n\n### Price Type Change\n\n`Money { amount: number, currency, display }` → `Price { amount: string (decimal), currency }`.\n\n- `amount` is now a **decimal string** (e.g. `\"349.99\"`), not a number — matches protocol and avoids floating-point rounding.\n- `display` is removed. Build a display string via `formatPrice(price)` or inline:\n  ```typescript\n  `${price.amount} ${price.currency}`  // e.g. \"349.99 USD\"\n  ```\n\n### Material.url\n\n`Material.url` is now `string | undefined` (protocol allows omission in examples).\nAlways guard before use:\n\n```typescript\nfor (const m of offer.material ?? []) {\n  if (m.url) {\n    renderImage(m.url);\n  }\n}\n```\n\n### Removed Fields with No Replacement\n\n- `offer.tags` — no replacement. If you used tags for filtering, use `offer.offerInfo.category` + `attributes.subType` instead.\n- `offer.conversionRule` — moved out of `Offer` into the server-side Postback protocol. SDK consumers no longer need to handle it.\n- `offer.ext` — no replacement. Extension points live on the protocol envelope, not per-offer.\n- `Category.subType` (top-level on `Category`) — now lives inside `Category.attributes.subType`.\n\n### Node Version\n\nMinimum Node is **20** (was 18 in 0.0.1). If you're on 18, bump your runtime before upgrading.\n\n### SDKConfig.appId (new)\n\nPass your app identifier so AON can attribute queries correctly:\n\n```typescript\nconst client = await initialize({\n  apiKey: process.env.AGENTOFFERNETWORK_API_KEY!,\n  mode: 'live',\n  appId: process.env.AON_APP_ID,\n});\n```\n\nInternally this sends `x-aon-app-id: <appId>` on protected endpoints. Skip it in\nmock mode.\n\n### ESM / CJS Dual-Bundle Note\n\nSDK is packaged as ESM (`.mjs`) + CJS (`.cjs`) dual format. The\n`protocolWarnings` pub-sub uses a `globalThis`-keyed singleton, so\nsubscribers keep working even if consumers mix `import` and `require`.\nRecommended: use the ESM entry (`import`) consistently.\n\n## License\n\n[MIT](./LICENSE)\n","readmeFilename":"README.md"}