The TypeScript SDK
A promise-based, fully typed client for CAVS Hub. Streamed hashing, presigned transfers, dedup-aware uploads and a typed error hierarchy with automatic retries — all behind CAVS.fromEnv().
Requires Node 18 or newer. Ships ESM + CJS with bundled type declarations. Defaults X-CAVS-Integration to javascript-sdk and sends its version in User-Agent.
From install to CI.
Five steps take you from an empty environment to an artifact uploaded and restored inside a pipeline.
1 Install the package
Add @cavsnode/cavs-sdk to your project and commit the lockfile for reproducible builds.
$ npm install @cavsnode/cavs-sdk
2 Create a service account & export a token
Create a service account in the CAVS dashboard scoped to artifacts:read and artifacts:write, then export its cavs_sk_ key. Never commit tokens; the SDK redacts them from logs and errors.
$ export CAVS_TOKEN=cavs_sk_... $ export CAVS_API=https://cavsnode.com # or your self-hosted Hub
3 Your first upload
upload() streams a sha256 per file, opens a session, skips objects the Hub already stores, PUTs the rest to presigned URLs, then finalizes a version and resolves with dedup stats.
const client = CAVS.fromEnv(); const artifact = await client.artifacts.upload({ path: "./model", project: "vision-models", name: "resnet50", kind: "model", version: "1.4.0", }); console.log(artifact.reference, artifact.deduplicationRatio);
4 Your first download
download() authorizes object ids, streams each to a temp file while hashing, verifies the sha256 against the oid (throwing ChecksumError on mismatch), then atomically renames into place.
await client.artifacts.download({ reference: "cavs://acme-ai/vision-models/model/resnet50:1.4.0", dest: "./restored", });
5 Use it in CI
Store the token as a secret and run a small publish script from any job.
# .github/workflows/publish.yml (job step) - run: npm ci && node publish.mjs env: CAVS_TOKEN: ${{ secrets.CAVS_TOKEN }} CAVS_API: https://cavsnode.com
Typed failures, safe retries.
Every rejection is a subclass of CAVSError. Transient failures (429, 5xx, transport) retry automatically — up to 4 attempts with exponential backoff and jitter, honouring Retry-After (capped ~30s).
- AuthenticationError — 401 · AuthorizationError — 403
- NotFoundError — 404 · ConflictError — 409
- QuotaExceededError — 413 / 402
- RateLimitError — 429 (respects Retry-After)
- ChecksumError — download hash mismatch
- UploadError / DownloadError — transport
import { CAVS, QuotaExceededError, AuthenticationError } from "@cavsnode/cavs-sdk"; const client = CAVS.fromEnv(); try { await client.artifacts.upload({ path: "./model", project: "p", name: "m", kind: "model", version: "1.0.0" }); } catch (err) { if (err instanceof QuotaExceededError) alert("quota hit"); else if (err instanceof AuthenticationError) alert("bad token"); else throw err; }
toString(), thrown errors, or logs — it is shown as cavs_sk_…abcd.