{"_id":"@apostl-dev/pulse-sdk","_rev":"5-d8839f75862083e87dd8d424bacf5e3b","name":"@apostl-dev/pulse-sdk","dist-tags":{"latest":"0.4.1"},"versions":{"0.1.0":{"name":"@apostl-dev/pulse-sdk","version":"0.1.0","keywords":["ai-agents","analytics","server","privacy","observability"],"author":{"name":"Apostl","email":"hello@apostl.dev"},"license":"MIT","_id":"@apostl-dev/pulse-sdk@0.1.0","maintainers":[{"name":"krutovoy","email":"krutovoyroman@gmail.com"}],"homepage":"https://platform.apostl.dev","bugs":{"url":"https://github.com/apostl-dev/pulse-sdk/issues"},"dist":{"shasum":"d00276cda1ea63b3448c94b1425aeb40d549eab4","tarball":"https://registry.npmjs.org/@apostl-dev/pulse-sdk/-/pulse-sdk-0.1.0.tgz","fileCount":15,"integrity":"sha512-vlVFBK3x1kRPil9l1HkN/Hu6vzHPhX6EFFUm8NW9wJbrMaiimKy4DpJ9K+8bVKFfS+h4mLLW853pl7JLSHOlnQ==","signatures":[{"sig":"MEUCIBnk5cjWEzmzqm6oMTDhl+TKuI+ljvJeE1bH93y9aAV7AiEAk+ary2qIKhnwL9thWt3fVUXc884cDSB5y6ayt+d0+E4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@apostl-dev%2fpulse-sdk@0.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":36936},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./next":{"types":"./dist/next.d.ts","import":"./dist/next.js","require":"./dist/next.cjs"},"./express":{"types":"./dist/express.d.ts","import":"./dist/express.js","require":"./dist/express.cjs"}},"gitHead":"97665210c29c687e19d920e866e2578c1fd54e5a","scripts":{"test":"node --import tsx --test test/*.test.ts","build":"tsup src/index.ts src/express.ts src/next.ts --format esm,cjs --dts --clean --target node20","prepack":"npm run build && npm run typecheck && npm test","test:load":"node --import tsx --test test/load.test.ts","typecheck":"tsc --noEmit"},"_npmUser":{"name":"krutovoy","email":"krutovoyroman@gmail.com"},"repository":{"url":"git+https://github.com/apostl-dev/pulse-sdk.git","type":"git"},"_npmVersion":"11.17.0","description":"Privacy-safe server-side analytics for AI agent traffic","directories":{},"_nodeVersion":"24.19.0","publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.20.0","tsup":"^8.5.0","typescript":"^5.8.3","@types/node":"^22.15.0"},"_npmOperationalInternal":{"tmp":"tmp/pulse-sdk_0.1.0_1787640019578_0.8307325272205146","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@apostl-dev/pulse-sdk","version":"0.2.0","keywords":["ai-agents","analytics","server","privacy","observability"],"author":{"name":"Apostl","email":"hello@apostl.dev"},"license":"MIT","_id":"@apostl-dev/pulse-sdk@0.2.0","maintainers":[{"name":"krutovoy","email":"krutovoyroman@gmail.com"}],"homepage":"https://platform.apostl.dev","bugs":{"url":"https://github.com/apostl-dev/pulse-sdk/issues"},"dist":{"shasum":"e8e52e0987f67a0d9bcf404d2b5c212aaf9cd4fe","tarball":"https://registry.npmjs.org/@apostl-dev/pulse-sdk/-/pulse-sdk-0.2.0.tgz","fileCount":15,"integrity":"sha512-Hn8IeQCwIr2quqAtoRCRRMb2XqAJ6A2iAjqUUcsAPwMOfhCcL6qOPtwIIM4HZCdzdhV3x//ltcIeIi+5wZGWrQ==","signatures":[{"sig":"MEUCIQD4KqPcT6Q0SuV09H1isCaAEjEswgXfIvF3OtIJjhkJJAIgOdUIpo1OAMTNpddOuNDmFSgGe9zD/pfbTE3Em95VVBk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":37281},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./next":{"types":"./dist/next.d.ts","import":"./dist/next.js","require":"./dist/next.cjs"},"./express":{"types":"./dist/express.d.ts","import":"./dist/express.js","require":"./dist/express.cjs"}},"gitHead":"87d601b671c87c638dcf3d7c4002bcf653167f33","scripts":{"test":"node --import tsx --test test/*.test.ts","build":"tsup src/index.ts src/express.ts src/next.ts --format esm,cjs --dts --clean --target node20","prepack":"npm run build && npm run typecheck && npm test","test:load":"node --import tsx --test test/load.test.ts","typecheck":"tsc --noEmit"},"_npmUser":{"name":"krutovoy","email":"krutovoyroman@gmail.com"},"repository":{"url":"git+https://github.com/apostl-dev/pulse-sdk.git","type":"git"},"_npmVersion":"10.9.8","description":"Privacy-safe server-side analytics for AI agent traffic","directories":{},"_nodeVersion":"22.23.1","publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.20.0","tsup":"^8.5.0","typescript":"^5.8.3","@types/node":"^22.15.0"},"_npmOperationalInternal":{"tmp":"tmp/pulse-sdk_0.2.0_1787651226185_0.7732532454876362","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@apostl-dev/pulse-sdk","version":"0.3.0","keywords":["ai-agents","analytics","server","observability"],"author":{"name":"Apostl","email":"hello@apostl.dev"},"license":"MIT","_id":"@apostl-dev/pulse-sdk@0.3.0","maintainers":[{"name":"krutovoy","email":"krutovoyroman@gmail.com"}],"homepage":"https://platform.apostl.dev","bugs":{"url":"https://github.com/apostl-dev/pulse-sdk/issues"},"dist":{"shasum":"6985ade6dc30b959d0d5a2a4629c2e42328a9998","tarball":"https://registry.npmjs.org/@apostl-dev/pulse-sdk/-/pulse-sdk-0.3.0.tgz","fileCount":16,"integrity":"sha512-QyiZ3RtrcDKt19I+eif3DmvRQhPQv36Dmme/XKf3wTCEceZ22iW29reuxnutn8IG1o6L6zzp39H/MZTWL6GMbw==","signatures":[{"sig":"MEUCID3Ic7552p9fH2jmK+lOeJk7/pIxeL77MRUQoCKU7en9AiEA0Vt2Q2Hf5bbR6jDmTDsfmHJnr8CiahfCphS+3UInSU0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":49605},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./next":{"types":"./dist/next.d.ts","import":"./dist/next.js","require":"./dist/next.cjs"},"./express":{"types":"./dist/express.d.ts","import":"./dist/express.js","require":"./dist/express.cjs"}},"gitHead":"9bc6bf260de6ef4da20acd2b8a4736208aa86028","scripts":{"test":"node --import tsx --test test/*.test.ts","build":"tsup src/index.ts src/express.ts src/next.ts --format esm,cjs --dts --clean --target node20","prepack":"npm run build && npm run typecheck && npm test","test:load":"node --import tsx --test test/load.test.ts","typecheck":"tsc --noEmit"},"_npmUser":{"name":"krutovoy","email":"krutovoyroman@gmail.com"},"repository":{"url":"git+https://github.com/apostl-dev/pulse-sdk.git","type":"git"},"_npmVersion":"10.9.8","description":"Server-side analytics for AI agent traffic","directories":{},"_nodeVersion":"22.23.1","publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.20.0","tsup":"^8.5.0","typescript":"^5.8.3","@types/node":"^22.15.0"},"_npmOperationalInternal":{"tmp":"tmp/pulse-sdk_0.3.0_1787663995107_0.8516170173445021","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@apostl-dev/pulse-sdk","version":"0.4.0","keywords":["ai-agents","analytics","server","observability"],"author":{"name":"Apostl","email":"hello@apostl.dev"},"license":"MIT","_id":"@apostl-dev/pulse-sdk@0.4.0","maintainers":[{"name":"krutovoy","email":"krutovoyroman@gmail.com"}],"homepage":"https://platform.apostl.dev","bugs":{"url":"https://github.com/apostl-dev/pulse-sdk/issues"},"dist":{"shasum":"7362e37a483d420830187851040b622df62bea4b","tarball":"https://registry.npmjs.org/@apostl-dev/pulse-sdk/-/pulse-sdk-0.4.0.tgz","fileCount":16,"integrity":"sha512-1rLJGJrsX7m5lRE/Cy7F/1NhCMDwDjpUXyqhvouVM9eU0KS4jLITQ6NMfD5YdS8yQReuPkcXbCoJTsdIvufWsQ==","signatures":[{"sig":"MEUCIQCGfQ2L0bF8kpa5WOsWE+FOveUMN+Z1FAorFx/FAIWo5AIgUTveCixC5Tt0ZFpnBN0sqrsup9pmnywOZ/J5RgLx8xU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":55439},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./next":{"types":"./dist/next.d.ts","import":"./dist/next.js","require":"./dist/next.cjs"},"./express":{"types":"./dist/express.d.ts","import":"./dist/express.js","require":"./dist/express.cjs"}},"scripts":{"test":"node --import tsx --test test/*.test.ts","build":"tsup src/index.ts src/express.ts src/next.ts --format esm,cjs --dts --clean --target node20","prepack":"npm run build && npm run typecheck && npm test","test:load":"node --import tsx --test test/load.test.ts","typecheck":"tsc --noEmit"},"_npmUser":{"name":"krutovoy","email":"krutovoyroman@gmail.com"},"repository":{"url":"git+https://github.com/apostl-dev/pulse-sdk.git","type":"git"},"_npmVersion":"10.9.8","description":"Server-side analytics for AI agent traffic","directories":{},"_nodeVersion":"22.23.1","publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.20.0","tsup":"^8.5.0","typescript":"^5.8.3","@types/node":"^22.15.0"},"_npmOperationalInternal":{"tmp":"tmp/pulse-sdk_0.4.0_1787748915492_0.4520444822337155","host":"s3://npm-registry-packages-npm-production"}},"0.4.1":{"name":"@apostl-dev/pulse-sdk","version":"0.4.1","description":"Server-side analytics for AI agent traffic","license":"MIT","author":{"name":"Apostl","email":"hello@apostl.dev"},"repository":{"type":"git","url":"git+https://github.com/apostl-dev/pulse-sdk.git"},"homepage":"https://platform.apostl.dev","bugs":{"url":"https://github.com/apostl-dev/pulse-sdk/issues"},"keywords":["ai-agents","analytics","server","observability"],"type":"module","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./express":{"types":"./dist/express.d.ts","import":"./dist/express.js","require":"./dist/express.cjs"},"./next":{"types":"./dist/next.d.ts","import":"./dist/next.js","require":"./dist/next.cjs"}},"engines":{"node":">=20"},"scripts":{"build":"tsup src/index.ts src/express.ts src/next.ts --format esm,cjs --dts --clean --target node20","typecheck":"tsc --noEmit","test":"node --import tsx --test test/*.test.ts","test:load":"node --import tsx --test test/load.test.ts","prepack":"npm run build && npm run typecheck && npm test"},"publishConfig":{"access":"public","provenance":true},"devDependencies":{"@types/node":"^22.15.0","tsup":"^8.5.0","tsx":"^4.20.0","typescript":"^5.8.3"},"_id":"@apostl-dev/pulse-sdk@0.4.1","_nodeVersion":"22.23.1","_npmVersion":"10.9.8","dist":{"integrity":"sha512-SkXchHDvIE87/tvg1BmsNpZzEaGVeIaTKaQSLeT72cGLOAlx86U8bUip2bH2P0Z2U5LAJn6Y1ef2u5MUPwUkHA==","shasum":"1164e1bf5fc32a2345ca27746f48e3d76259e5fb","tarball":"https://registry.npmjs.org/@apostl-dev/pulse-sdk/-/pulse-sdk-0.4.1.tgz","fileCount":16,"unpackedSize":57829,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDPenU0zaMNxF1UcV/m26h8Rn6bL8LTvUxhpA9uSwKMmQIgQFnLBR5f2sgvp1M3QmJZVnB7ERCoaJVsPOBlMiIdYxU="}]},"_npmUser":{"name":"krutovoy","email":"krutovoyroman@gmail.com"},"directories":{},"maintainers":[{"name":"krutovoy","email":"krutovoyroman@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/pulse-sdk_0.4.1_1787751398809_0.8395933392683832"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-25T06:40:19.422Z","modified":"2026-08-26T13:36:39.149Z","0.1.0":"2026-08-25T06:40:19.727Z","0.2.0":"2026-08-25T09:47:06.315Z","0.3.0":"2026-08-25T13:19:55.276Z","0.4.0":"2026-08-26T12:55:15.668Z","0.4.1":"2026-08-26T13:36:38.951Z"},"bugs":{"url":"https://github.com/apostl-dev/pulse-sdk/issues"},"author":{"name":"Apostl","email":"hello@apostl.dev"},"license":"MIT","homepage":"https://platform.apostl.dev","keywords":["ai-agents","analytics","server","observability"],"repository":{"type":"git","url":"git+https://github.com/apostl-dev/pulse-sdk.git"},"description":"Server-side analytics for AI agent traffic","maintainers":[{"name":"krutovoy","email":"krutovoyroman@gmail.com"}],"readme":"<p align=\"center\">\n  <img src=\"https://raw.githubusercontent.com/apostl-dev/pulse-sdk/main/docs/pulse-readme.svg\" alt=\"Apostl Pulse — live AI agent traffic signal\" width=\"100%\" />\n</p>\n\n# Apostl Pulse SDK\n\nEstimate AI agent visits and see which public website, docs, or API pages they use.\n\nPulse works as a middleware to track any agent-first endpoint:\n- Markdown-supported pages\n- llms.txt and llms-full.txt\n- API endpoints for agents\n- app routes for agents\n\nPulse groups requests with the same project, trusted IP, and full User-Agent into one journey until a 30-minute inactivity window expires. Installations and origins connected to the same project stay in that journey.\n\nAn exact `llms.txt` visit is immediate evidence. A generic non-browser client such as `curl` is also counted when it visits two distinct machine-readable surfaces within ten minutes—for example `openapi.json` and a Markdown page. This catches real tool-driven research even when the client does not announce an agent name.\n\n## One-line Install\n\n```sh\nnpm install @apostl-dev/pulse-sdk\n```\n\nMIT-licensed [source code is on GitHub](https://github.com/apostl-dev/pulse-sdk).\n\n### Node\n\n```ts\nimport { createPulse } from '@apostl-dev/pulse-sdk';\n\nconst pulse = createPulse({\n  endpoint: 'https://ingest.apostl.dev',\n  apiKey: process.env.APOSTL_PULSE_API_KEY,\n  environment: 'production',\n  // Unknown /api routes fail closed. Add only routes that are intentionally public.\n  publicApiPrefixes: ['/api/public'],\n});\n\npulse.observeRequest({\n  method: request.method,\n  statusCode: response.statusCode,\n  headers: request.headers,\n  ip: clientIp, // resolve this from your trusted server or proxy\n  url: request.url,\n});\n```\n\n* Pulse SDK sends the trusted client IP and User-Agent data to [Apostl website](https://apostl.dev).\n* It records the canonical origin and path only. Query parameters, fragments, request bodies, cookies, and authorization headers are not sent.\n* Public health and API GET/HEAD requests are included; auth/account routes, assets, mutations, and 5xx responses are excluded.\n* `/api/mcp` and `/api/turnstile-config` are safe defaults. Other `/api/*` routes are ignored unless their public prefix is listed in `publicApiPrefixes`.\n* Use `cf-connecting-ip` when your deployment trusts Cloudflare.\n* Keep `APOSTL_PULSE_API_KEY` in the server runtime; never expose it through browser bundles or public environment variables.\n\n### Express\n\n```ts\nimport { pulseExpressMiddleware } from '@apostl-dev/pulse-sdk/express';\n\napp.use(pulseExpressMiddleware(pulse));\n```\n\n### Next.js\n\n```ts\nimport { withPulse } from '@apostl-dev/pulse-sdk/next';\n\nexport const GET = withPulse(pulse, async () => new Response(renderDocs(), {\n  headers: { 'content-type': 'text/html' },\n}));\n```\n\n## Setup for AI agents\n\nInstall the public setup skill:\n\n```sh\nnpx skills add apostl-dev/apostl-skills --skill agent-traffic-analytics -g -y\n```\n\nThen ask your agent to connect the exact public HTTPS origin where it is authorized to deploy the server middleware. The skill stores the one-time API key and setup token in an owner-only file instead of printing them.\n\n`example.com` and similar names are reserved documentation domains, not end-to-end demo targets. Pulse rejects them before issuing credentials. Use a real origin you can deploy, or stop and obtain one from the owner.\n\nExample task:\n\n```text\nUse $agent-traffic-analytics to connect my authorized public docs origin and verify a real visit to /llms.txt.\n```\n\nThe unclaimed setup lasts seven days. A claim URL appears only after the signed public response and the matching genuine event both pass. The owner then signs in with Google, GitHub, or an email magic link; the ingest API key remains active after claim.\n\nRead the [full agent setup guide](https://apostl.dev/pulse.md) or the exact [OpenAPI contract](https://apostl.dev/openapi.json).\n\n## Troubleshooting\n\n| Symptom | Check |\n| --- | --- |\n| No events | Confirm the server has the API key and ingest endpoint, and that requests include a trusted client IP and full User-Agent. |\n| Verification is waiting | Deploy the adapter on the public HTTPS origin and keep the selected verification path reachable, then retry the same `verify_url`. |\n| IP addresses are the same | Check your trusted proxy setup (Cloudflare, nginx, etc) |\n| Final events are missing | Call `await pulse.flush()` during graceful shutdown. |\n| Need local state | `diagnostics()` returns bounded counters without credentials or captured request data. |\n\n## Support\n\nFor setup help, message [@SwiftAdviser](https://t.me/SwiftAdviser) on Telegram.\n","readmeFilename":"README.md"}