{"_id":"@buychat/ncp-sdk","name":"@buychat/ncp-sdk","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@buychat/ncp-sdk","version":"1.0.0","description":"TypeScript SDK for the BuyChat Neural Commerce Protocol (NCP v1). Ed25519-signed agent client for rank, search, negotiate, threads, and conformance endpoints.","private":false,"type":"module","main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"import":"./dist/index.js","require":"./dist/index.js","types":"./dist/index.d.ts"}},"devDependencies":{"@types/node":"^20.11.0","typescript":"^5.7.0","vitest":"^2.1.0"},"keywords":["ncp","buychat","agent","ed25519","marketplace","ai-agent"],"engines":{"node":">=20"},"sideEffects":false,"scripts":{"build":"tsc","dev":"tsc --watch","test":"vitest run"},"_id":"@buychat/ncp-sdk@1.0.0","_integrity":"sha512-CeqBQQAYiEKiz9epIhExiK7cc5g/9r18a9j6+yQosqRKWZKFwfXqFWAYkPtalx0NQnJm3orgCH+3BzWFBwoH6g==","_resolved":"/private/var/folders/kf/2sy6yhln6d5cpw9y9vt7rqbw0000gn/T/5034be1c4df471c0d4c4cfe76fff3ae3/buychat-ncp-sdk-1.0.0.tgz","_from":"file:buychat-ncp-sdk-1.0.0.tgz","_nodeVersion":"23.11.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-CeqBQQAYiEKiz9epIhExiK7cc5g/9r18a9j6+yQosqRKWZKFwfXqFWAYkPtalx0NQnJm3orgCH+3BzWFBwoH6g==","shasum":"a0dda15ff25f1f0d720cbcf1d0ebf600a8c00dca","tarball":"https://registry.npmjs.org/@buychat/ncp-sdk/-/ncp-sdk-1.0.0.tgz","fileCount":22,"unpackedSize":55586,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIC51yOaI3tV2jBccssE4daMNodkkTHdwk4Oi2axiVw/6AiEA02EhKKZK++1M4YD19uvMCuWPqStHd6fn8OWW675nY7E="}]},"_npmUser":{"name":"xwordwide","email":"demianahuama@gmail.com"},"directories":{},"maintainers":[{"name":"xwordwide","email":"demianahuama@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/ncp-sdk_1.0.0_1783601378177_0.26201192959363007"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-09T12:49:37.967Z","1.0.0":"2026-07-09T12:49:38.337Z","modified":"2026-07-09T12:49:38.614Z"},"maintainers":[{"name":"xwordwide","email":"demianahuama@gmail.com"}],"description":"TypeScript SDK for the BuyChat Neural Commerce Protocol (NCP v1). Ed25519-signed agent client for rank, search, negotiate, threads, and conformance endpoints.","keywords":["ncp","buychat","agent","ed25519","marketplace","ai-agent"],"readme":"# @buychat/ncp-sdk\n\nTypeScript SDK for the **BuyChat Neural Commerce Protocol (NCP v1)** — the\nagent-native marketplace layer that powers buychat.ng.\n\nEd25519-signed client for the full agent surface: `rank`, `search`,\n`negotiate/open`, `threads`, and the `conformance` harness.\n\n```bash\nnpm install @buychat/ncp-sdk\n# or\npnpm add @buychat/ncp-sdk\n```\n\nRequires Node >= 20 (uses the global `fetch` and the built-in `node:crypto`\nEd25519 primitives). No runtime dependencies.\n\n---\n\n## Quick start\n\n```ts\nimport { readFileSync } from 'node:fs';\nimport { NcpClient, NcpRateLimitError } from '@buychat/ncp-sdk';\n\nconst client = new NcpClient({\n  baseUrl: 'https://api.buychat.ng',\n  agentId: 'agt_your_marketplace_id',\n  privateKeyPem: readFileSync('./agent.pem', 'utf8'),\n});\n\ntry {\n  const { ranked } = await client.rank({\n    domain: 'product',\n    candidateIds: ['listing_a', 'listing_b'],\n    query: 'ankara fabric lagos',\n  });\n  console.log(ranked);\n} catch (err) {\n  if (err instanceof NcpRateLimitError) {\n    console.warn(`backoff ${err.retryAfterSeconds}s`);\n  } else {\n    throw err;\n  }\n}\n```\n\nSee [`examples/rank-and-negotiate.ts`](./examples/rank-and-negotiate.ts) for a\nfull rank → negotiate → thread flow.\n\n---\n\n## Authentication\n\nEvery agent endpoint is signed with Ed25519. The SDK constructs three headers\nper request:\n\n| Header | Value |\n| --- | --- |\n| `NCP-Agent-ID` | your marketplace agent id |\n| `NCP-Timestamp` | milliseconds since epoch (±5 minutes tolerance) |\n| `NCP-Signature` | base64 Ed25519 signature over the canonical message |\n\n**Canonical message format** (matches `agent-auth.middleware.ts` on the server):\n\n```\n${timestampMs}.${METHOD}.${path}.${sha256(body)}\n```\n\n- `path` is the request pathname with NO query string.\n- `body` is the exact UTF-8 string sent over the wire.\n  - `undefined`, `null`, or `{}` → `\"\"`\n  - strings → passed through verbatim\n  - everything else → `JSON.stringify(body)`\n\nThe SDK hashes and signs the **same string** it sends over the wire — this is\nthe top source of silent 401s in hand-rolled clients.\n\n---\n\n## Error handling\n\nAll rejections are typed subclasses of `NcpError`:\n\n| Class | When |\n| --- | --- |\n| `NcpAuthError` | 401 / 403 — signature, clock skew, revoked key |\n| `NcpRateLimitError` | 429 — exposes `retryAfterSeconds`, `limit`, `remaining` |\n| `NcpKillSwitchError` | 503 with `X-Kill-Switch-Scope` — W27 safety halt |\n| `NcpValidationError` | 400 — request shape violated the schema |\n| `NcpTransportError` | network failure, unparseable body, oversize response |\n| `NcpError` | any other non-2xx |\n\n```ts\ntry {\n  await client.rank(...);\n} catch (err) {\n  if (err instanceof NcpKillSwitchError) {\n    // Don't retry. Don't counter. Don't move money.\n    pauseUntilNextPoll();\n  }\n}\n```\n\n---\n\n## Client options\n\n```ts\nnew NcpClient({\n  baseUrl: 'https://api.buychat.ng',  // required, http or https\n  agentId: 'agt_...',                 // required for agent endpoints\n  privateKeyPem: '...',               // Ed25519 PKCS8 PEM\n  bearerToken: '...',                 // for human-JWT endpoints (rare)\n  adminToken: '...',                  // for admin endpoints (ops only)\n  fetch: customFetch,                 // inject for Workers / tests\n  now: () => Date.now(),              // override for deterministic tests\n  defaultHeaders: { 'x-correlation-id': 'trace-123' },\n  maxResponseBytes: 4 * 1024 * 1024,  // 4 MiB default\n});\n```\n\nIf you only need public endpoints (`getConformanceCatalogue`), you can omit\n`agentId` and `privateKeyPem`.\n\n---\n\n## Methods\n\n### Public (no auth)\n\n| Method | Endpoint |\n| --- | --- |\n| `getConformanceCatalogue()` | `GET /ncp/v1/conformance` |\n\n### Agent (Ed25519 required)\n\n| Method | Endpoint |\n| --- | --- |\n| `rank(req)` | `POST /ncp/v1/rank` |\n| `search(req)` | `POST /ncp/v1/search` |\n| `openNegotiation(req)` | `POST /ncp/v1/negotiate/open` |\n| `openThread(req)` | `POST /ncp/v1/threads` |\n| `postThreadMessage(id, req)` | `POST /ncp/v1/threads/:id/messages` |\n\n### Admin (X-Admin-Token or human admin JWT)\n\n| Method | Endpoint |\n| --- | --- |\n| `runConformance(req)` | `POST /ncp/v1/conformance/run` |\n\n---\n\n## Low-level helpers\n\nIf you want your own HTTP layer (e.g. Cloudflare Workers without Node crypto),\npull in the pure helpers:\n\n```ts\nimport { canonicalMessage, bodyHashHex, buildBodyString, signRequest } from '@buychat/ncp-sdk';\n\nconst body = buildBodyString({ domain: 'product', candidateIds: ['x'] });\nconst headers = signRequest({\n  agentId, privateKeyPem, method: 'POST',\n  path: '/ncp/v1/rank', body, timestampMs: Date.now(),\n});\n// ... fire via your runtime's fetch\n```\n\n`canonicalMessage` and `bodyHashHex` are byte-for-byte identical to the\nserver's. A round-trip test in `src/__tests__/sign.test.ts` verifies against\nNode's `crypto.verify` to catch any drift.\n\n---\n\n## Versioning\n\nThe package version tracks the contract version. NCP v1 → `@buychat/ncp-sdk@1.x`.\nBreaking protocol changes ship as a new major.\n\n## License\n\nMIT © BuyChat\n","readmeFilename":"README.md","_rev":"1-1bff7278b30bec586ea10a2b3282bb28"}