npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

cortex-sdk

v0.3.0

Published

Typed TypeScript client for Cortex — agent memory that catches contradictions at write time and returns what is still true.

Readme

cortex-sdk

Typed TypeScript client for Cortex — agent memory that catches contradictions at write time and returns what is still true.

When your agent learns something that conflicts with what it already knew, Cortex notices at the moment of writing, records why, and ranks the current fact above the stale one. Nothing is deleted; superseded facts stay queryable and demoted, so you can always show your work.

  • Zero dependencies. ESM + CommonJS. Node 18+.
  • Every response fully typed against the live API.
  • Typed errors, automatic retry with backoff, configurable timeouts, polling helper.

Preview software. Cortex is a preview-stage service run by one developer. See the Terms and Security pages before pointing production at it.


Install

npm install cortex-sdk

Want to pin an exact commit instead of a published version? See Install from GitHub.

Quickstart

import { Cortex } from "cortex-sdk";

const cortex = new Cortex({ apiKey: process.env.CORTEX_API_KEY! });

await cortex.store({ agentId: "support", content: "Jordan is now CTO at BetaWorks." });
const hits = await cortex.retrieve({ agentId: "support", query: "Where does Jordan work?" });

console.log(hits.results[0].fact);

Getting a key

curl -X POST https://your-cortex-host/signup \
  -H 'content-type: application/json' \
  -d '{"email":"[email protected]","accept_terms":true}'

Open the returned onboard_url, paste your own Anthropic or OpenAI key, and you get a crtx_live_… key — shown once. Cortex is bring-your-own-key: fact extraction and contradiction judging are billed to your provider account. Retrieval is local and costs nothing.

Configuration

const cortex = new Cortex({
  apiKey: process.env.CORTEX_API_KEY!,
  baseUrl: "https://your-cortex-host",  // or set CORTEX_BASE_URL; defaults to localhost:4000
  timeoutMs: 30_000,                    // per request
  retry: { maxRetries: 2, baseDelayMs: 250, maxDelayMs: 8_000 },
  headers: { "x-trace-id": "…" },       // merged into every request
  onRetry: (i) => console.warn(`retry ${i.attempt}/${i.maxRetries} on ${i.endpoint}`),
});

baseUrl resolves in order: the explicit option → CORTEX_BASE_URL → http://localhost:4000.


Methods

Every method takes an optional last argument { signal?, timeoutMs? } to cancel that call or give it its own timeout.

store(input)

const { id, status, contradictions } = await cortex.store({
  agentId: "support",
  content: "Jordan left Sable Freight — he is now CTO at BetaWorks.",
  type: "semantic",   // optional; auto-detected
  sync: false,        // optional; see below
});

Returns { id, status, memory, contradictions, … }. id and status are lifted to the top level for the common path.

Async by default. The memory is persisted and searchable immediately with status: "pending", while extraction and contradiction detection run on the write queue. Use waitFor(id) to await the result.

Pass sync: true to block until extraction and judging finish, so contradictions is populated in the same response — good for demos, slower under load.

store() is never retried automatically. Replaying a store the server already accepted would duplicate the memory, and duplicate memories are the thing this product exists to prevent.

get(id)

const memory = await cortex.get("mem_abc123");
console.log(memory.status, memory.fact, memory.confidence);

Throws CortexNotFoundError if the id doesn't exist under your key.

waitFor(id, options?)

Polls until extraction finishes (pending → active).

const memory = await cortex.waitFor(id, {
  timeoutMs: 60_000,
  intervalMs: 1_000,
  onPoll: (m, elapsedMs) => console.log(m.status, elapsedMs),
});

Throws CortexTimeoutError if the timeout elapses first. In practice that means the backend's LLM credential is missing, unfunded, or rate-limited — a pending memory is retried until it succeeds. The memory is never lost; it stays stored and searchable with its raw text as the fact.

retrieve(input)

const res = await cortex.retrieve({
  agentId: "support",       // optional; omit to search every agent
  query: "Where does Jordan work now?",
  limit: 5,                 // server default 5, max 50
});

Returns:

| Field | Meaning | |---|---| | results | Ranked hits, each with score, relevance_pct, confidence_pct, lifecycle_state, stale, contested, via | | excluded | Candidates that matched but fell below threshold, each with an excluded_reason | | reasoning | Plain-language account of how the ranking was produced | | latency_ms | Server-side time, excluding network | | output_id | Provenance handle — GET /outputs/{output_id}/trace shows exactly what informed this answer |

Ranking is semantic + keyword relevance, then weighted by live confidence and lifecycle state. A superseded fact can score higher on raw relevance and still rank below the current one — that is the point:

1. 0.273  [active]      Jordan left Sable Freight — he is now CTO at BetaWorks.
          relevance 30% · confidence 90%
2. 0.041  [superseded]  Jordan works at Sable Freight as a backend engineer.
          relevance 38% · confidence 90%

listContradictions(input?)

const page = await cortex.listContradictions({ status: "open", limit: 20 });

for (const c of page.contradictions) {
  console.log(c.memory_a?.fact, "vs", c.memory_b?.fact);
  console.log(c.suggested_resolution?.reasoning);
}

Newest first. With limit you get one page plus a nextCursor; without it you get everything and a null cursor. Paging is keyset-based, so a contradiction detected while you are iterating never causes a row to be skipped or repeated.

Iterating every page:

let cursor: string | undefined;
do {
  const page = await cortex.listContradictions({ status: "open", limit: 50, cursor });
  for (const c of page.contradictions) handle(c);
  cursor = page.nextCursor ?? undefined;
} while (cursor);

resolve(contradictionId, options?)

await cortex.resolve("ctr_abc123");                          // accept the suggestion
await cortex.resolve("ctr_abc123", { choice: "supersede" }); // retire the loser
await cortex.resolve("ctr_abc123", { choice: "keep_both" }); // both stay active
await cortex.resolve("ctr_abc123", { choice: "supersede", supersedeId: "mem_x" });

With no choice, the backend applies its own suggestion — usually superseding the older memory. Superseding never deletes: the losing memory stays queryable, marked superseded, and demoted in ranking. Returns the recomputed trust_score and stats.

Throws CortexConflictError (409) if it was already resolved.

entities.list() and entities.graph(id, options?)

const entities = await cortex.entities.list();

const graph = await cortex.entities.graph(entities[0].id, { hops: 2 });
// graph.entity           — the seed
// graph.facts            — facts mentioning it
// graph.linked_entities  — entities within `hops`, each tagged with its hop distance
// graph.edges            — entity→fact MENTIONS, plus fact→fact SUPERSEDES / EVOLUTION_OF / CONTRADICTS

hops is clamped to 1–4 server-side; the default is 2. Entities are extracted by the same LLM step as facts, so they appear once a memory reaches active.

usage()

const usage = await cortex.usage();
console.log(usage.totals.cost_usd, usage.by_type.store?.count);

This calendar month's metered operations, token counts and estimated cost. comparison estimates what an equivalent managed vector stack would have cost — an illustration with its assumptions shown, not a charge.

stats()

const stats = await cortex.stats();
console.log(stats.trust_score, stats.open_contradictions, stats.by_state);

Error handling

Every failure is a subclass of CortexError, so one instanceof catches everything the SDK throws.

import {
  CortexError,
  CortexAuthError,
  CortexRateLimitError,
  CortexValidationError,
  CortexConnectionError,
} from "cortex-sdk";

try {
  await cortex.store({ agentId: "support", content: text });
} catch (err) {
  if (err instanceof CortexAuthError) {
    // 401 — key missing, unknown, or revoked. Retrying will not help.
  } else if (err instanceof CortexRateLimitError) {
    console.log(err.retryAfterSeconds, err.resetAt, err.limit, err.isQuota);
    // isQuota distinguishes the monthly store quota from a per-minute rate limit.
  } else if (err instanceof CortexValidationError) {
    console.log(err.field, err.fields);  // e.g. "content"
  } else if (err instanceof CortexConnectionError) {
    console.log(err.timedOut);           // true when our timeout fired, not the network
  } else if (err instanceof CortexError) {
    console.log(err.status, err.endpoint, err.requestId);
  }
}

| Class | Status | Carries | |---|---|---| | CortexAuthError | 401 | — | | CortexForbiddenError | 403 | — | | CortexNotFoundError | 404 | — | | CortexConflictError | 409 | — | | CortexValidationError | 400 / 413 / 422 | field, fields | | CortexRateLimitError | 429 | retryAfterSeconds, resetAt, limit, isQuota | | CortexServerError | 5xx | — | | CortexConnectionError | 0 | timedOut | | CortexTimeoutError | 0 | memoryId, waitedMs (from waitFor) |

All of them also carry status, body, endpoint and requestId — quote requestId when reporting a bug and the server-side log line is one grep away.

Retries

Retried automatically, with exponential backoff and full jitter:

  • 429 — the server's Retry-After always wins over the computed delay.
  • 5xx and network failures/timeouts.

Not retried:

  • 4xx other than 429. A bad key or malformed body fails identically the second time.
  • store() — see above. Every other method is safe to replay and is retried.
  • Caller aborts. signal is an instruction, not a failure.

Disable entirely with retry: { maxRetries: 0 }.


Example

examples/quickstart.ts stores two facts that cannot both be true and walks the whole flow: store → wait → detect → resolve → trust-weighted retrieve → graph → usage.

export CORTEX_API_KEY=crtx_live_...
export CORTEX_BASE_URL=https://your-cortex-host
npx tsx examples/quickstart.ts

If the backend has no working LLM credential, the example says so explicitly and continues with the steps that don't need one — rather than printing an empty result and looking broken.


Install from GitHub

For pinning an exact commit rather than a published version. The package builds itself on install (prepare runs tsc), so a git install needs no extra step. But npm installs the repository root, and this SDK lives in cortex-sdk/ — so install it by path or tarball:

# clone and install by path
git clone https://github.com/AAGAM17/prism.git ~/prism
npm install ~/prism/cortex-sdk

# or pack a tarball
cd ~/prism/cortex-sdk && npm pack     # → cortex-sdk-0.3.0.tgz
npm install /path/to/cortex-sdk-0.3.0.tgz

Both give you the same import { Cortex } from "cortex-sdk". For a reproducible install, clone at a specific commit (git checkout <sha>) rather than tracking a branch.


Development

npm run typecheck       # src + examples, no emit
npm run build           # ESM + CJS + .d.ts into dist/
npm run smoke           # offline transport tests (errors, retries, timeouts, paging)
npm run verify:example  # boots cortex-core + a stub LLM, runs the example, asserts its output
npm test                # typecheck + build + smoke

npm run verify:example needs the monorepo checkout (it uses ../cortex-core); the others are self-contained.

Links

MIT © Aagam Shah