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

@mnemoscale/sdk

v0.1.1

Published

TypeScript SDK for the Mnemos memory API: zero-dependency fetch client with typed errors, retry/backoff, and session/polling helpers mirroring the Python SDK.

Readme

Mnemos TypeScript SDK (@mnemoscale/sdk)

Typed client for the Mnemos memory API, mirroring the Python SDK (libs/sdk/mnemos_sdk) 1:1: API-key auth, retry/backoff on 429/5xx, typed errors, job polling, a session helper, and webhook signature verification.

  • Zero runtime dependencies — uses the global fetch: Node >= 20, browsers, and edge runtimes all work.
  • ESM + CJS + .d.ts — plain tsc dual build, no bundler.
  • Generated-spec honesty — the wire types are hand-written for readability but verified 1:1 against the committed OpenAPI snapshot (openapi.json) in CI (see below).

Quickstart (first query in under 5 minutes)

Bring up Mnemos as in the repo-root quickstart.py (compose deps + API + outbox relay + extraction worker, then mnemos-admin tenant create ... for an API key, agent id, and namespace id). Then:

npm install @mnemoscale/sdk        # in this repo: cd sdk-ts && npm ci && npm run build
import { MnemosClient } from "@mnemoscale/sdk";

const client = new MnemosClient("http://localhost:8001", process.env.MNEMOS_API_KEY!);

await client.withSession(
  { agentId: process.env.MNEMOS_AGENT_ID!, namespaceId: process.env.MNEMOS_NAMESPACE_ID! },
  async (s) => {
    // Blocks until the extraction job completes (extractAsync to fire-and-poll later).
    await s.extract([{ content: "the customer asked about delivery delays", role: "user" }]);

    const result = await s.query("delivery delays", { topK: 5, rerank: true });
    for (const r of result.results) {
      if (r.from_working_memory) continue; // session turns merged per PRD §7.1
      console.log(r.hybrid_score, r.content);
    }
  },
);

The session is created before the callback and ended afterwards (even on error) — the analogue of the Python SDK's with client.session(...) as s:. On runtimes with explicit resource management you can also write:

await using s = await client.openSession({ agentId, namespaceId });
const accepted = await s.extractAsync([{ content: "..." }]); // fire...
const job = await client.waitForJob(accepted.job_id, { agentId }); // ...and poll later

Responses are returned exactly as they appear on the wire (snake_case keys, UUIDs/datetimes as strings), fully typed; method parameters are camelCase and mapped to the wire shape by the client.

Surface

Everything the Python SDK exposes: createNamespace, listNamespaces, createAgent, createSession / getSession / endSession, extract / getJob / waitForJob, query (routing, topK, metadataFilter, rerank, scoring, efSearch, maxContextTokens, minRerankLogit), feedback, getUsage, getProfile, warmUp, webhooks (createWebhook / listWebhooks / deleteWebhook / testWebhook), sources (getSource / deleteSource / eraseSources / exportSources), plus the session helper (openSession / withSession) and verifyWebhookSignature.

Every method accepts request options: agentId (X-Agent-Id header), correlationId (X-Correlation-Id, echoed by the API and attached to typed errors), timeoutMs, and signal (AbortSignal). Client options: timeoutMs, maxRetries, retryBackoffBaseMs, retryAfterCapMs, pollScheduleMs, maxPolls, defaultHeaders, and injectable fetch/sleep for tests.

Errors and retries (Python SDK parity)

HTTP failures throw subclasses of MnemosError; every HTTP error is a MnemosApiError carrying status, code, message, correlationId, and retryable:

| Status | Error | Retried? | | --- | --- | --- | | 401 | AuthenticationError | no | | 402 | PaymentRequiredError (code, manageUrl) | never — billing suspended | | 403 | PermissionError | no | | 404 | NotFoundError | no | | 409 | ConflictError | no | | 422 | ValidationError | no | | 429 | RateLimitError (code) | yes, unless X-Mnemos-Retryable: false | | 500/502/503/504 | ServerError | yes |

Retry policy (identical to the Python SDK): up to maxRetries (default 3) extra attempts with exponential backoff retryBackoffBaseMs * 2^(attempt-1) (default 100 ms → 100/200/400), no jitter. A server-sent Retry-After (seconds or HTTP-date) overrides the computed backoff for that attempt, capped at retryAfterCapMs (default 30 s).

Transport failures follow the same replay-safety rule as the Python SDK: connection-phase failures (refused, DNS, unreachable — the request provably never reached the server) are retried for any method; ambiguous failures (timeouts, dropped sockets) are only replayed for idempotent requests (GET/DELETE) or POSTs carrying an idempotencyKey. They surface as MnemosConnectionError / MnemosTimeoutError in both SDKs — neither makes you catch the underlying transport library's exception type.

waitForJob polls 250ms → 500ms → 1s → 2s → 5s (then 5 s repeating, max 60 polls) until the job is completed | partial | failed, else throws MnemosTimeoutError — the Python SDK's schedule exactly.

An AbortSignal passed via request options cancels the whole call, including any in-progress backoff/Retry-After or poll sleep: the sleep ends immediately and the call rejects with the abort reason.

Verifying webhooks (PRD §13.2)

import { verifyWebhookSignature, WebhookVerificationError } from "@mnemoscale/sdk";

// In your webhook endpoint, before parsing the body:
try {
  await verifyWebhookSignature(WEBHOOK_SECRET, req.headers["x-mnemos-signature"], rawBody);
} catch (err) {
  if (err instanceof WebhookVerificationError) {
    // err.reason: malformed_header | stale_timestamp | signature_mismatch
    return new Response(null, { status: 400 });
  }
  throw err;
}

Uses WebCrypto (crypto.subtle), hence async — otherwise identical to the Python SDK's verify_webhook_signature (HMAC-SHA-256 over "{t}.{body}", 300 s replay tolerance, constant-time compare).

OpenAPI snapshot

openapi.json is exported from the FastAPI app by scripts/export_openapi.py and committed, so this package's CI needs no network or Python toolchain. Two gates keep it honest: tests/openapi-parity.test.ts verifies every endpoint the client calls and every wire type's property/required sets against the snapshot, and the Python-side contract test tests/contract/test_openapi_snapshot.py (repo root, contract marker) rebuilds the spec from the live app via this script's build_snapshot() and fails CI when the committed snapshot goes stale. When the v1 API changes:

uv sync --all-packages
uv run python sdk-ts/scripts/export_openapi.py > sdk-ts/openapi.json
cd sdk-ts && npm test   # parity test tells you what to update in src/types.ts

Developing

cd sdk-ts
npm ci
npm run typecheck   # tsc strict, src + tests
npm test            # vitest, mocked fetch — no network, no live services
npm run build       # dist/esm + dist/cjs + .d.ts
npm pack            # publish-ready tarball (runs the build via prepack)

The sdk-ts CI job runs exactly these and uploads the npm pack tarball as the mnemos-sdk-npm artifact.

Releasing

Publishing is automated: .github/workflows/release-sdk-ts.yaml publishes to npm with trusted publishing (GitHub OIDC — no NPM_TOKEN to store, and provenance attached automatically) when a sdk-ts-v<version> tag is pushed.

# 1. bump `version` in package.json and land it on main
# 2. rehearse: Actions -> release-sdk-ts -> Run workflow  (stops at --dry-run)
# 3. release (read the version back, so the tag cannot disagree with package.json):
tag="sdk-ts-v$(node -p "require('./package.json').version")"
git tag "$tag" && git push origin "$tag"

The job re-runs typecheck/tests/build against the tagged commit, refuses a tag that disagrees with package.json or a version already on the registry, publishes, and then installs the published package in a scratch directory and imports it through both the ESM and CJS entry points.

The one-time human setup — the @mnemoscale scope and the trusted-publisher entry — is in docs/runbooks/sdk-release.md. The package is licensed Apache-2.0 (LICENSE).

Parity with the Python SDK

sdk-parity.json at the repo root is the shared surface contract between this package and libs/sdk: methods, error taxonomy, constants, retry policy, and request/client options, named in both languages. tests/parity.test.ts and the Python tests/unit/test_sdk_parity.py assert their own side against it, so adding something to one SDK fails the other's suite until it lands there too. The manifest's notes record the differences that are deliberate because the languages differ — milliseconds here versus seconds in Python, one async client here versus a sync and an async one there, AbortSignal versus asyncio cancellation.