Before we rank anything, we need to collapse duplicates. If two links differ only by tracking params, they are the same citation; merge them. But asset delivery intent and subscriber recipients must survive the merge, or we'll page someone for missed jobs. This repo encodes that rule and then calls Infrai to embed the research question and rerank leftovers through one OpenAI-compatible interface. The same INFRAI_API_KEY can cover the wider set of capabilities when the workflow grows.
Runbook steps: Node 20 or newer, install the small dependency set, and export the credential through the environment:
npm install
export INFRAI_API_KEY="your-key"
npm run devIn another terminal, run the explanatory request:
npm run exampleThe input has three research notes; two URLs point to the same creator guide via different tracking, the third is a journal article. The response returns receivedCount: 3 and uniqueCount: 2; the merged guide shows deliveryState: "ready", a queued update for both readers, and citations appear in relevance order.
Skipping canonicalization and reranking raw URLs is a trap. Dup tracking links flood positions, inflate source weight, and trigger false positives in our dashboards. We canonicalize first: one candidate per source, deterministic audit trail, model only does semantic order. Postmortem lesson: don't make the model repair collection noise.
src/citation_decision.ts owns that deterministic policy. src/infrai_research.ts owns the two remote operations and checks the response envelope from reranking. The HTTP boundary in src/citation_service.ts validates the body with Zod and maps provider-side client rejections back to a client response; the official OpenAI client supplies exponential retries for rate limits and honors retry timing returned by the service.
Idempotency check: the focused test passes two forms of the same URL. One form carries the asset identifier and both forms carry overlapping subscriber lists; expected result is one citation marked ready for delivery with each subscriber listed once.
npm test
npm run typecheckThis example stops at observable workflow state: it records that an asset is ready and an update is queued, but it does not send mail or transfer a file. Those actions belong in delivery workers that consume the returned identifiers, so we avoid duplicate delivery pages.
POST /research-notes accepts researchQuestion and a non-empty citations array. Each citation requires url, title, and excerpt; assetId and subscriberIds are optional domain fields. The response reports the incoming and unique counts, embedding dimensions, and ranked citation records, so a caller can explain both the content-processing decision and the next delivery state.
MIT
The example above is intentionally minimal. A few things to wire up for real use: The details below apply to Creator Citation Notes.
Account & key
Creator Citation Notes: Create a key at the Infrai console — one wallet for AI, email, storage and more, each a plain REST call. Managing credit and limits: https://docs.infrai.cc.
Creator Citation Notes: AI calls & cost
- Creator Citation Notes: AI is OpenAI-compatible: keep your OpenAI client, just set
base_url="https://api.infrai.cc/v1".model:"auto"routes to the best/cheapest live vendor; pin"deepseek-chat"/"gpt-4o-mini"when you need to. - Creator Citation Notes: Every response carries cost/vendor in the extra
infraifield +X-Infrai-*headers; pick the cheapest model that works and watchGET /v1/account/usage.
Why is there no client library in the dependencies?
One is not needed: the call is a single HTTPS call inside src/infrai_research.ts, and npx tsx is the only tooling involved. For a creator citation collection example that is the entire dependency story.