Skip to content

TypeScript SDK

Terminal window
npm i @cavsnode/cavs-sdk

Node 18+ (uses global fetch). Ships ESM, CJS and type declarations.

Terminal window
export CAVS_TOKEN=cavs_ci_...
export CAVS_API=https://cavsnode.com
export CAVS_ORG=acme-ai # optional default organization
import { CAVS } from '@cavsnode/cavs-sdk';
const client = CAVS.fromEnv();
// or explicitly
const client = new CAVS({
token: process.env.CAVS_TOKEN,
api: 'https://cavsnode.com',
org: 'acme-ai',
});
const result = await client.artifacts.upload({
path: './dist/bundle.tar', // a file or a directory
project: process.env.CAVS_REPO_ID!, // the repository UUID — see the note below
name: 'game-client',
kind: 'archive',
version: process.env.GITHUB_SHA!,
metadata: { branch: process.env.GITHUB_REF_NAME, ci: 'github-actions' },
});
console.log(result.reference, result.version);
const controller = new AbortController();
setTimeout(() => controller.abort(), 60_000);
await client.artifacts.upload({
path: './dist',
project: repoId,
name: 'client', kind: 'archive', version: 'nightly',
onProgress: (done, total) => process.stdout.write(`\r${done}/${total}`),
signal: controller.signal,
idempotencyKey: `nightly-${new Date().toISOString().slice(0, 10)}`,
});
Call Status
client.me()
client.search(q)
client.listRepositories(org)
client.artifacts.upload(...) ✓ (UUID project; dedup stats absent)
client.artifacts.download(...) ✗ needs /resolve
client.artifacts.list(...)
client.artifacts.get(id) / .versions(id) ✗ needs /artifacts/{id}
client.usage.get()
client.snapshots.list() / .create()
client.releases.list() / .get(tag)
client.lineage.graph() / .addEdge()
client.resolve(ref) ✗ not deployed
client.runs.* ✗ not deployed
client.serviceAccounts.* ✗ not deployed
// Registry
const artifacts = await client.artifacts.list({ type: 'archive', limit: 20 });
// Usage
const usage = await client.usage.get();
// Releases
const releases = await client.releases.list(repoId);
const release = await client.releases.get(repoId, 'v1.4.0');
// Snapshots
await client.snapshots.create(repoId, { idempotencyKey: 'monthly-2026-07' });
// Lineage
await client.lineage.addEdge(repoId, {
fromType: 'artifact', fromKey: buildOid,
toType: 'artifact', toKey: sourceOid,
relation: 'derived-from',
});
const graph = await client.lineage.graph(repoId);

Hashing and URI helpers:

import { sha256File, uri, VERSION } from '@cavsnode/cavs-sdk';
const oid = await sha256File('./dist/bundle.tar');
const parsed = uri.parse('cavs://acme-ai/game-builds/archive/client:1.2.0');
import {
CAVSError, AuthenticationError, AuthorizationError, NotFoundError,
ConflictError, RateLimitError, QuotaExceededError, ChecksumError,
UploadError, DownloadError, TemporaryServiceError,
} from '@cavsnode/cavs-sdk';
try {
await client.artifacts.upload({ /* … */ });
} catch (err) {
if (err instanceof QuotaExceededError) console.error('plan limit hit');
else if (err instanceof RateLimitError) console.error('throttled');
else if (err instanceof CAVSError) console.error('CAVS error:', err.message);
else throw err;
}

Same taxonomy and mapping as the Python SDK, and the same retry policy: 4 attempts on 429/5xx/network, exponential backoff with jitter, honouring Retry-After.

Inject a fetch implementation:

import { CAVS } from '@cavsnode/cavs-sdk';
const client = new CAVS({
token: 'cavs_pat_test',
api: 'https://test',
fetch: async (input, init) => {
const url = String(input);
if (url.endsWith('/api/v1/users/me')) {
return new Response(JSON.stringify({ user: { id: 'u1', email: '[email protected]' } }), {
status: 200,
headers: { 'content-type': 'application/json' },
});
}
return new Response(
JSON.stringify({ error: { code: 'not_found', message: 'nope' } }),
{ status: 404, headers: { 'content-type': 'application/json' } },
);
},
});
import { CAVS, sha256File } from '@cavsnode/cavs-sdk';
import { writeFile } from 'node:fs/promises';
const client = CAVS.fromEnv();
const repoId = process.env.CAVS_REPO_ID!;
const version = process.env.GITHUB_SHA!;
const result = await client.artifacts.upload({
path: './dist/bundle.tar',
project: repoId,
name: 'game-client',
kind: 'archive',
version,
metadata: { runner: process.env.RUNNER_OS, ref: process.env.GITHUB_REF },
idempotencyKey: `release:${version}`,
});
// Pin the exact bytes for downstream consumers.
const oid = await sha256File('./dist/bundle.tar');
await writeFile('release.json', JSON.stringify({ version, oid, reference: result.reference }, null, 2));
console.log(`published ${result.reference} (oid ${oid})`);