@cavsnode/cavs-sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,735 @@
1
+ /**
2
+ * Telemetry headers sent on every request (CONTRACT.md §7).
3
+ *
4
+ * User-Agent: cavs-node/<version>
5
+ * X-CAVS-Client: javascript-sdk
6
+ * X-CAVS-Integration: <javascript-sdk by default; integrations override>
7
+ * X-CAVS-Integration-Version: <version>
8
+ * X-CAVS-Run-ID: <optional correlation id>
9
+ */
10
+ /** The SDK version, embedded in the User-Agent and integration-version headers. */
11
+ declare const VERSION = "0.1.0";
12
+ interface TelemetryOptions {
13
+ /** Integration id; defaults to {@link CLIENT_ID}. Integrations built on top override it. */
14
+ integration?: string;
15
+ /** Version of the integration; defaults to the SDK {@link VERSION}. */
16
+ integrationVersion?: string;
17
+ /** Optional run / correlation id, surfaced as `X-CAVS-Run-ID`. */
18
+ runId?: string;
19
+ }
20
+
21
+ /**
22
+ * HTTP transport built on the global `fetch` (CONTRACT.md §7, §8).
23
+ *
24
+ * Responsibilities:
25
+ * - Attach auth + telemetry headers and an optional Idempotency-Key.
26
+ * - Retry <= `maxRetries` times on 429 / 5xx / network errors with exponential
27
+ * backoff + jitter, honouring `Retry-After` (capped ~30s).
28
+ * - Enforce a request timeout via AbortController and propagate external
29
+ * cancellation.
30
+ * - Bound redirects (<= 5).
31
+ * - Map the server error envelope to a typed {@link CAVSError}.
32
+ * - Never log tokens or presigned URLs.
33
+ */
34
+
35
+ /** Injectable fetch implementation (defaults to the global `fetch`). */
36
+ type FetchLike = typeof fetch;
37
+ /** The request-body type accepted by `fetch` (derived to avoid needing the DOM lib). */
38
+ type BodyInit = NonNullable<RequestInit["body"]>;
39
+ /** A no-arg factory that produces a fresh request body — required so streamed
40
+ * bodies can be rewound and resent on retry. */
41
+ type BodyFactory = () => BodyInit;
42
+ interface HttpClientOptions {
43
+ baseUrl: string;
44
+ token: string;
45
+ fetch?: FetchLike;
46
+ telemetry?: TelemetryOptions;
47
+ /** Max retries on 429/5xx/network (default 4). Total attempts = maxRetries + 1. */
48
+ maxRetries?: number;
49
+ /** Max redirects to follow (default 5). */
50
+ maxRedirects?: number;
51
+ /** Per-attempt timeout in ms (default 30000). */
52
+ timeoutMs?: number;
53
+ /** Base backoff in ms (default 200). Set to 0 in tests to disable delays. */
54
+ retryBaseMs?: number;
55
+ /** Cap on any single backoff/Retry-After wait in ms (default 30000). */
56
+ maxBackoffMs?: number;
57
+ /** Called (never throws) when the server sends `X-CAVS-Deprecation`. */
58
+ onDeprecation?: (message: string) => void;
59
+ /** Injectable sleep (for tests). */
60
+ sleepImpl?: (ms: number) => Promise<void>;
61
+ }
62
+ interface RequestOptions {
63
+ method?: string;
64
+ path: string;
65
+ query?: Record<string, string | number | boolean | undefined>;
66
+ body?: unknown;
67
+ headers?: Record<string, string>;
68
+ idempotencyKey?: string;
69
+ signal?: AbortSignal;
70
+ }
71
+ declare class HttpClient {
72
+ private readonly baseUrl;
73
+ private readonly token;
74
+ private readonly fetchImpl;
75
+ private readonly telemetry;
76
+ readonly maxRetries: number;
77
+ readonly maxRedirects: number;
78
+ readonly timeoutMs: number;
79
+ private readonly retryBaseMs;
80
+ private readonly maxBackoffMs;
81
+ private readonly onDeprecation;
82
+ private readonly sleepImpl;
83
+ constructor(opts: HttpClientOptions);
84
+ /** Build the standard header set for a control-plane request. */
85
+ private baseHeaders;
86
+ private buildUrl;
87
+ /** Perform a JSON control-plane request with retries and typed errors. */
88
+ requestJson<T = unknown>(opts: RequestOptions): Promise<T>;
89
+ /**
90
+ * Send a request whose body is a (possibly streamed) factory, retrying with a
91
+ * fresh body each attempt. Used for presigned PUT uploads. Returns the raw
92
+ * Response. Presigned URLs must never be logged.
93
+ */
94
+ sendStream(url: string, opts: {
95
+ method: string;
96
+ bodyFactory: BodyFactory;
97
+ headers?: Record<string, string>;
98
+ signal?: AbortSignal;
99
+ /** Extra fetch init (e.g. `duplex: "half"`). */
100
+ init?: RequestInit;
101
+ }): Promise<Response>;
102
+ /** Open a streaming GET (presigned download). Returns the raw Response. */
103
+ openStream(url: string, opts?: {
104
+ signal?: AbortSignal;
105
+ }): Promise<Response>;
106
+ private executeWithRetry;
107
+ /** Follow redirects manually, bounded by {@link maxRedirects}. */
108
+ private fetchWithRedirects;
109
+ private armSignal;
110
+ private backoff;
111
+ private retryAfterMs;
112
+ private safeDeprecation;
113
+ private toError;
114
+ private parseJson;
115
+ }
116
+
117
+ /**
118
+ * Public type definitions for the CAVS SDK.
119
+ *
120
+ * Wire responses use snake_case; the SDK surfaces camelCase. The resource
121
+ * modules perform the mapping. Fields marked optional may be absent depending on
122
+ * the endpoint and server version.
123
+ */
124
+ /** Result of `GET /api/v1/users/me`. */
125
+ interface Me {
126
+ id: string;
127
+ email?: string;
128
+ name?: string;
129
+ /** Organizations the caller belongs to. */
130
+ organizations?: Org[];
131
+ /** Present when the token is a service account. */
132
+ serviceAccount?: {
133
+ id: string;
134
+ name?: string;
135
+ org?: string;
136
+ };
137
+ }
138
+ /** An organization. */
139
+ interface Org {
140
+ id: string;
141
+ slug: string;
142
+ name?: string;
143
+ }
144
+ /** A repository (a "project"). */
145
+ interface Repo {
146
+ id: string;
147
+ slug: string;
148
+ name?: string;
149
+ org?: string;
150
+ generation?: number;
151
+ }
152
+ /** An artifact (a named, versioned bundle of objects). */
153
+ interface Artifact {
154
+ id: string;
155
+ name: string;
156
+ kind: string;
157
+ project?: string;
158
+ org?: string;
159
+ reference?: string;
160
+ latestVersion?: string;
161
+ metadata?: Record<string, unknown>;
162
+ }
163
+ /** One version of an artifact. */
164
+ interface ArtifactVersion {
165
+ version: string;
166
+ sha256: string;
167
+ reference?: string;
168
+ createdAt?: string;
169
+ metadata?: Record<string, unknown>;
170
+ files?: ArtifactFile[];
171
+ }
172
+ /** A single stored object within an artifact version. */
173
+ interface ArtifactFile {
174
+ path: string;
175
+ oid: string;
176
+ size: number;
177
+ }
178
+ /** Dedup + identity result returned by a completed upload (finalize). */
179
+ interface UploadResult {
180
+ artifactId: string;
181
+ /** Canonical `cavs://` reference for the created version. */
182
+ reference: string;
183
+ version: string;
184
+ /** sha256 of the artifact (its manifest / root oid). */
185
+ sha256: string;
186
+ logicalBytes: number;
187
+ physicalBytes: number;
188
+ deduplicatedBytes: number;
189
+ deduplicationRatio: number;
190
+ /** Per-file breakdown of what was uploaded vs. deduplicated. */
191
+ files: UploadedFile[];
192
+ }
193
+ /** Per-object upload outcome. */
194
+ interface UploadedFile {
195
+ path: string;
196
+ oid: string;
197
+ size: number;
198
+ /** `true` when the object already existed server-side and the PUT was skipped. */
199
+ deduplicated: boolean;
200
+ }
201
+ /** Result of a completed download. */
202
+ interface DownloadResult {
203
+ /** Destination directory the files were written to. */
204
+ dest: string;
205
+ files: DownloadedFile[];
206
+ }
207
+ /** Per-object download outcome. */
208
+ interface DownloadedFile {
209
+ path: string;
210
+ oid: string;
211
+ size: number;
212
+ }
213
+ /** A repository snapshot. */
214
+ interface Snapshot {
215
+ id: string;
216
+ generation?: number;
217
+ createdAt?: string;
218
+ message?: string;
219
+ metadata?: Record<string, unknown>;
220
+ }
221
+ /** A named release. */
222
+ interface Release {
223
+ tag: string;
224
+ snapshotId?: string;
225
+ createdAt?: string;
226
+ notes?: string;
227
+ metadata?: Record<string, unknown>;
228
+ }
229
+ /** A pipeline run. */
230
+ interface Run {
231
+ id: string;
232
+ status?: string;
233
+ name?: string;
234
+ createdAt?: string;
235
+ updatedAt?: string;
236
+ metadata?: Record<string, unknown>;
237
+ }
238
+ /** A lineage edge between two nodes in the artifact graph. */
239
+ interface LineageEdge {
240
+ id?: string;
241
+ from: string;
242
+ to: string;
243
+ relation?: string;
244
+ metadata?: Record<string, unknown>;
245
+ }
246
+ /** The lineage graph for a repository. */
247
+ interface LineageGraph {
248
+ nodes: Array<Record<string, unknown>>;
249
+ edges: LineageEdge[];
250
+ }
251
+ /** Usage / billing snapshot for an org. */
252
+ interface Usage {
253
+ org?: string;
254
+ logicalBytes?: number;
255
+ physicalBytes?: number;
256
+ deduplicatedBytes?: number;
257
+ deduplicationRatio?: number;
258
+ artifactCount?: number;
259
+ [key: string]: unknown;
260
+ }
261
+ /** A service account. */
262
+ interface ServiceAccount {
263
+ id: string;
264
+ name: string;
265
+ org?: string;
266
+ disabled?: boolean;
267
+ createdAt?: string;
268
+ }
269
+ /** A service-account API key. The `secret` is only returned once, on creation/rotation. */
270
+ interface ServiceAccountKey {
271
+ id: string;
272
+ serviceAccountId?: string;
273
+ /** Present only in the create/rotate response. */
274
+ secret?: string;
275
+ createdAt?: string;
276
+ lastUsedAt?: string;
277
+ }
278
+ /** Progress event emitted during upload/download/hashing. */
279
+ interface ProgressEvent {
280
+ phase: "hash" | "upload" | "download";
281
+ /** The relative path of the file being processed. */
282
+ path: string;
283
+ /** Bytes processed so far for this file. */
284
+ loaded: number;
285
+ /** Total bytes for this file, when known. */
286
+ total: number;
287
+ }
288
+ /** A progress callback. */
289
+ type ProgressCallback = (event: ProgressEvent) => void;
290
+
291
+ /**
292
+ * Artifacts resource — the upload/download data plane plus artifact discovery
293
+ * (CONTRACT.md §4, §5).
294
+ *
295
+ * `project` is an alias for `repository`: the caller passes `project` (a repo
296
+ * slug or id) and it is used directly as `{repo}` in the repository-scoped
297
+ * endpoints. `org` is only needed for org-scoped listing.
298
+ */
299
+
300
+ interface UploadOptions {
301
+ /** Local file or directory to upload. */
302
+ path: string;
303
+ /** Project (repository slug or id) to upload into. */
304
+ project: string;
305
+ /** Artifact name. */
306
+ name: string;
307
+ /** Artifact kind (e.g. `model`, `dataset`, `game-build`). */
308
+ kind: string;
309
+ /** Logical version tag. */
310
+ version: string;
311
+ /** Arbitrary metadata attached to the version. */
312
+ metadata?: Record<string, unknown>;
313
+ /** Organization slug (only recorded; defaults to the client's org). */
314
+ org?: string;
315
+ /** Stable idempotency key; a deterministic one is derived when omitted. */
316
+ idempotencyKey?: string;
317
+ /** Progress callback (hashing + upload phases). */
318
+ onProgress?: ProgressCallback;
319
+ /** Cancellation signal. */
320
+ signal?: AbortSignal;
321
+ }
322
+ interface DownloadOptions {
323
+ /** Destination directory. */
324
+ dest: string;
325
+ /** Organization slug override (defaults to the reference's org). */
326
+ org?: string;
327
+ /** Progress callback (download phase). */
328
+ onProgress?: ProgressCallback;
329
+ /** Cancellation signal. */
330
+ signal?: AbortSignal;
331
+ }
332
+ declare class ArtifactsResource {
333
+ private readonly ctx;
334
+ constructor(ctx: ClientContext);
335
+ /** `GET /api/v1/artifacts/{id}`. */
336
+ get(artifactId: string, signal?: AbortSignal): Promise<Artifact>;
337
+ /** `GET /api/v1/artifacts/{id}/versions`. */
338
+ versions(artifactId: string, signal?: AbortSignal): Promise<ArtifactVersion[]>;
339
+ /** `GET /api/v1/organizations/{org}/artifacts`. */
340
+ list(opts?: {
341
+ org?: string;
342
+ limit?: number;
343
+ type?: string;
344
+ q?: string;
345
+ signal?: AbortSignal;
346
+ }): Promise<Artifact[]>;
347
+ /**
348
+ * Upload a file or directory as a new artifact version, following the
349
+ * choreography in CONTRACT.md §5. Streams every object; skips objects that
350
+ * already exist (dedup); resumable because step 3 re-reports `exists`.
351
+ */
352
+ upload(opts: UploadOptions): Promise<UploadResult>;
353
+ private putObject;
354
+ private reportUpload;
355
+ private uploadProgress?;
356
+ /**
357
+ * Download an artifact by its `cavs://` reference into `opts.dest`, verifying
358
+ * each object's sha256 and writing atomically (CONTRACT.md §5).
359
+ */
360
+ download(reference: string, opts: DownloadOptions): Promise<DownloadResult>;
361
+ }
362
+
363
+ /** Snapshots resource (CONTRACT.md §4). `project` is a repository slug/id. */
364
+
365
+ interface CreateSnapshotOptions {
366
+ message?: string;
367
+ metadata?: Record<string, unknown>;
368
+ idempotencyKey?: string;
369
+ signal?: AbortSignal;
370
+ }
371
+ declare class SnapshotsResource {
372
+ private readonly ctx;
373
+ constructor(ctx: ClientContext);
374
+ /** `GET /api/v1/repositories/{repo}/snapshots`. */
375
+ list(project: string, signal?: AbortSignal): Promise<Snapshot[]>;
376
+ /** `POST /api/v1/repositories/{repo}/snapshots`. */
377
+ create(project: string, opts?: CreateSnapshotOptions): Promise<Snapshot>;
378
+ }
379
+
380
+ /** Releases resource (CONTRACT.md §4). `project` is a repository slug/id. */
381
+
382
+ declare class ReleasesResource {
383
+ private readonly ctx;
384
+ constructor(ctx: ClientContext);
385
+ /** `GET /api/v1/repositories/{repo}/releases`. */
386
+ list(project: string, signal?: AbortSignal): Promise<Release[]>;
387
+ /** `GET /api/v1/repositories/{repo}/releases/{tag}`. */
388
+ get(project: string, tag: string, signal?: AbortSignal): Promise<Release>;
389
+ }
390
+
391
+ /** Runs resource (CONTRACT.md §4 — runs & lineage). `project` is a repo slug/id. */
392
+
393
+ interface CreateRunOptions {
394
+ name: string;
395
+ system: string;
396
+ externalId?: string;
397
+ gitCommit?: string;
398
+ pipeline?: string;
399
+ environment?: string;
400
+ status?: string;
401
+ metadata?: Record<string, unknown>;
402
+ idempotencyKey?: string;
403
+ signal?: AbortSignal;
404
+ }
405
+ interface UpdateRunOptions {
406
+ status?: string;
407
+ endedAt?: string;
408
+ metadata?: Record<string, unknown>;
409
+ idempotencyKey?: string;
410
+ signal?: AbortSignal;
411
+ }
412
+ /** An artifact association to record on a run (creates lineage edges). */
413
+ interface RunArtifact {
414
+ oid?: string;
415
+ reference?: string;
416
+ role: "input" | "output";
417
+ [key: string]: unknown;
418
+ }
419
+ declare class RunsResource {
420
+ private readonly ctx;
421
+ constructor(ctx: ClientContext);
422
+ private base;
423
+ /** `POST /api/v1/repositories/{repo}/runs`. */
424
+ create(project: string, opts: CreateRunOptions): Promise<Run>;
425
+ /** `GET /api/v1/repositories/{repo}/runs`. */
426
+ list(project: string, signal?: AbortSignal): Promise<Run[]>;
427
+ /** `GET /api/v1/repositories/{repo}/runs/{run}`. */
428
+ get(project: string, runId: string, signal?: AbortSignal): Promise<Run>;
429
+ /** `PATCH /api/v1/repositories/{repo}/runs/{run}`. */
430
+ update(project: string, runId: string, opts: UpdateRunOptions): Promise<Run>;
431
+ /** `POST /api/v1/repositories/{repo}/runs/{run}/artifacts` — record lineage. */
432
+ addArtifacts(project: string, runId: string, artifacts: RunArtifact[], opts?: {
433
+ idempotencyKey?: string;
434
+ signal?: AbortSignal;
435
+ }): Promise<unknown>;
436
+ }
437
+
438
+ /** Lineage graph resource (CONTRACT.md §4). `project` is a repository slug/id. */
439
+
440
+ interface AddEdgeOptions {
441
+ fromType: string;
442
+ fromKey: string;
443
+ toType: string;
444
+ toKey: string;
445
+ relation: string;
446
+ metadata?: Record<string, unknown>;
447
+ idempotencyKey?: string;
448
+ signal?: AbortSignal;
449
+ }
450
+ declare class LineageResource {
451
+ private readonly ctx;
452
+ constructor(ctx: ClientContext);
453
+ /** `GET /api/v1/repositories/{repo}/graph`. */
454
+ graph(project: string, signal?: AbortSignal): Promise<LineageGraph>;
455
+ /** `POST /api/v1/repositories/{repo}/graph/edges`. */
456
+ addEdge(project: string, opts: AddEdgeOptions): Promise<LineageEdge>;
457
+ }
458
+
459
+ /** Usage / dedup-stats resource (CONTRACT.md §4). */
460
+
461
+ declare class UsageResource {
462
+ private readonly ctx;
463
+ constructor(ctx: ClientContext);
464
+ /** `GET /api/v1/organizations/{org}/usage`. */
465
+ get(opts?: {
466
+ org?: string;
467
+ signal?: AbortSignal;
468
+ }): Promise<Usage>;
469
+ }
470
+
471
+ /** Service accounts resource (org admin, CONTRACT.md §4). */
472
+
473
+ interface CreateServiceAccountOptions {
474
+ name: string;
475
+ description?: string;
476
+ scopes?: string[];
477
+ repositoryIds?: string[];
478
+ environment?: string;
479
+ org?: string;
480
+ signal?: AbortSignal;
481
+ }
482
+ declare class ServiceAccountsResource {
483
+ private readonly ctx;
484
+ constructor(ctx: ClientContext);
485
+ private org;
486
+ private base;
487
+ /** `GET …/service-accounts`. */
488
+ list(opts?: {
489
+ org?: string;
490
+ signal?: AbortSignal;
491
+ }): Promise<ServiceAccount[]>;
492
+ /** `POST …/service-accounts`. */
493
+ create(opts: CreateServiceAccountOptions): Promise<ServiceAccount>;
494
+ /** `PATCH …/service-accounts/{id}` — enable/disable, edit scopes/repos. */
495
+ update(id: string, patch: {
496
+ disabled?: boolean;
497
+ scopes?: string[];
498
+ repositoryIds?: string[];
499
+ }, opts?: {
500
+ org?: string;
501
+ signal?: AbortSignal;
502
+ }): Promise<ServiceAccount>;
503
+ /** `DELETE …/service-accounts/{id}`. */
504
+ delete(id: string, opts?: {
505
+ org?: string;
506
+ signal?: AbortSignal;
507
+ }): Promise<void>;
508
+ /** `POST …/service-accounts/{id}/keys` — the secret is returned once. */
509
+ createKey(id: string, opts?: {
510
+ org?: string;
511
+ signal?: AbortSignal;
512
+ }): Promise<ServiceAccountKey>;
513
+ /** `POST …/service-accounts/{id}/keys/{key}/rotate`. */
514
+ rotateKey(id: string, keyId: string, opts?: {
515
+ org?: string;
516
+ signal?: AbortSignal;
517
+ }): Promise<ServiceAccountKey>;
518
+ /** `DELETE …/service-accounts/{id}/keys/{key}`. */
519
+ deleteKey(id: string, keyId: string, opts?: {
520
+ org?: string;
521
+ signal?: AbortSignal;
522
+ }): Promise<void>;
523
+ }
524
+
525
+ /**
526
+ * The {@link CAVS} client — the entry point of the SDK.
527
+ *
528
+ * ```ts
529
+ * import { CAVS } from "@cavsnode/cavs-sdk";
530
+ * const client = CAVS.fromEnv();
531
+ * const art = await client.artifacts.upload({ path: "./model", project: "vision-models",
532
+ * name: "resnet50", kind: "model", version: "1.4.0" });
533
+ * await client.artifacts.download(art.reference, { dest: "./out" });
534
+ * ```
535
+ */
536
+
537
+ /** The default control-plane base URL. */
538
+ declare const DEFAULT_API = "https://api.cavs.dev";
539
+ interface CAVSOptions {
540
+ /** Auth token. Falls back to `$CAVS_TOKEN`. */
541
+ token?: string;
542
+ /** Base URL of the CAVS Hub. Falls back to `$CAVS_API` then {@link DEFAULT_API}. */
543
+ api?: string;
544
+ /**
545
+ * Default organization slug for org-scoped calls. Falls back to `$CAVS_ORG`.
546
+ * Repository/upload/download calls do not require it (they key on the repo).
547
+ */
548
+ org?: string;
549
+ /** Injectable `fetch` — makes the client trivial to mock in tests. */
550
+ fetch?: FetchLike;
551
+ /** Override the `X-CAVS-Integration` header (default `javascript-sdk`). */
552
+ integration?: string;
553
+ /** Override the `X-CAVS-Integration-Version` header. */
554
+ integrationVersion?: string;
555
+ /** Optional `X-CAVS-Run-ID` correlation id. */
556
+ runId?: string;
557
+ /** Per-attempt request timeout in ms (default 30000). */
558
+ timeoutMs?: number;
559
+ /** Max retries on 429/5xx/network (default 4). */
560
+ maxRetries?: number;
561
+ /** Called when the server sends `X-CAVS-Deprecation`. */
562
+ onDeprecation?: (message: string) => void;
563
+ /** Internal/testing knobs forwarded to the transport. */
564
+ retryBaseMs?: number;
565
+ sleepImpl?: (ms: number) => Promise<void>;
566
+ }
567
+ /** Context handed to each resource module. */
568
+ interface ClientContext {
569
+ http: HttpClient;
570
+ defaultOrg?: string;
571
+ }
572
+ declare class CAVS {
573
+ readonly http: HttpClient;
574
+ private readonly defaultOrg?;
575
+ readonly artifacts: ArtifactsResource;
576
+ readonly snapshots: SnapshotsResource;
577
+ readonly releases: ReleasesResource;
578
+ readonly runs: RunsResource;
579
+ readonly lineage: LineageResource;
580
+ readonly usage: UsageResource;
581
+ readonly serviceAccounts: ServiceAccountsResource;
582
+ constructor(options?: CAVSOptions);
583
+ /** Construct a client from the environment (`CAVS_TOKEN`, `CAVS_API`, `CAVS_ORG`). */
584
+ static fromEnv(options?: CAVSOptions): CAVS;
585
+ /** Resolve the org to use for org-scoped calls. */
586
+ resolveOrg(explicit?: string): string;
587
+ /** `GET /api/v1/users/me` — the authenticated identity. */
588
+ me(signal?: AbortSignal): Promise<Me>;
589
+ /** `GET /api/v1/search?q=` — cross-org search. */
590
+ search(q: string, signal?: AbortSignal): Promise<unknown>;
591
+ /** `GET /api/v1/resolve?uri=` — resolve a `cavs://` reference to concrete objects. */
592
+ resolve(reference: string, signal?: AbortSignal): Promise<unknown>;
593
+ /** `GET /api/v1/organizations/{org}/repositories`. */
594
+ listRepositories(org?: string, signal?: AbortSignal): Promise<unknown>;
595
+ }
596
+
597
+ /**
598
+ * Typed error hierarchy for the CAVS SDK.
599
+ *
600
+ * The server returns errors using the envelope described in CONTRACT.md §8:
601
+ *
602
+ * { "error": { "code": "quota_exceeded", "message": "human readable" } }
603
+ *
604
+ * {@link toCAVSError} maps an HTTP status + envelope to the correct subclass.
605
+ * All errors extend {@link CAVSError}. Tokens and presigned URLs are NEVER
606
+ * included in error messages (CONTRACT.md §2).
607
+ */
608
+ interface CAVSErrorOptions {
609
+ /** Machine-readable error code from the server envelope. */
610
+ code?: string;
611
+ /** HTTP status code, when the error originated from a response. */
612
+ status?: number;
613
+ /** Server-supplied request id (from `X-Request-Id`/`X-CAVS-Request-Id`), if any. */
614
+ requestId?: string;
615
+ /** Underlying cause (e.g. a network error). */
616
+ cause?: unknown;
617
+ /** Retry-After hint in milliseconds, when the server supplied one. */
618
+ retryAfterMs?: number;
619
+ }
620
+ /** Base class for every error thrown by the SDK. */
621
+ declare class CAVSError extends Error {
622
+ readonly code?: string;
623
+ readonly status?: number;
624
+ readonly requestId?: string;
625
+ readonly retryAfterMs?: number;
626
+ constructor(message: string, options?: CAVSErrorOptions);
627
+ }
628
+ /** 401 — the token is missing, malformed or rejected. */
629
+ declare class AuthenticationError extends CAVSError {
630
+ }
631
+ /** 403 — the token is valid but not permitted to perform the action. */
632
+ declare class AuthorizationError extends CAVSError {
633
+ }
634
+ /** 404 — the requested resource does not exist. */
635
+ declare class NotFoundError extends CAVSError {
636
+ }
637
+ /** 409 — the request conflicts with the current state of the resource. */
638
+ declare class ConflictError extends CAVSError {
639
+ }
640
+ /** 429 — rate limited. Honour {@link CAVSError.retryAfterMs}. */
641
+ declare class RateLimitError extends CAVSError {
642
+ }
643
+ /** 413 / 402 — a storage/billing quota has been exceeded. */
644
+ declare class QuotaExceededError extends CAVSError {
645
+ }
646
+ /** A downloaded object's sha256 did not match its oid. */
647
+ declare class ChecksumError extends CAVSError {
648
+ }
649
+ /** The upload data-plane transfer failed. */
650
+ declare class UploadError extends CAVSError {
651
+ }
652
+ /** The download data-plane transfer failed. */
653
+ declare class DownloadError extends CAVSError {
654
+ }
655
+ /** 5xx / network / timeout — a transient failure that is retried. */
656
+ declare class TemporaryServiceError extends CAVSError {
657
+ }
658
+
659
+ /**
660
+ * `cavs://` URI parsing and formatting (CONTRACT.md §9).
661
+ *
662
+ * cavs://{org}/{project}/{kind}/{name}:{version} logical (mutable)
663
+ * cavs://{org}/{project}/{kind}/{name}@sha256:{oid} immutable
664
+ *
665
+ * Behaviour is pinned by spec/contract/uri-vectors.json — every valid vector
666
+ * must parse to its `parsed` object and reformat to its `canonical` string, and
667
+ * every invalid vector must throw.
668
+ */
669
+
670
+ /** A parsed `cavs://` URI. Exactly one of {@link version} / {@link oid} is set. */
671
+ interface ParsedURI {
672
+ org: string;
673
+ project: string;
674
+ kind: string;
675
+ name: string;
676
+ /** Logical version tag, or `null` for immutable references. */
677
+ version: string | null;
678
+ /** 64-char lowercase hex sha256, or `null` for logical references. */
679
+ oid: string | null;
680
+ /** `true` when the reference is pinned to an oid. */
681
+ immutable: boolean;
682
+ }
683
+ /** Raised when a string is not a valid `cavs://` URI. */
684
+ declare class InvalidURIError extends CAVSError {
685
+ }
686
+ /**
687
+ * Parse a `cavs://` URI into its components.
688
+ *
689
+ * @throws {InvalidURIError} when the URI is malformed.
690
+ */
691
+ declare function parse(uri: string): ParsedURI;
692
+ /** Format a {@link ParsedURI} (or the equivalent fields) back to a canonical string. */
693
+ declare function format(parsed: {
694
+ org: string;
695
+ project: string;
696
+ kind: string;
697
+ name: string;
698
+ version?: string | null;
699
+ oid?: string | null;
700
+ }): string;
701
+
702
+ type uri_InvalidURIError = InvalidURIError;
703
+ declare const uri_InvalidURIError: typeof InvalidURIError;
704
+ type uri_ParsedURI = ParsedURI;
705
+ declare const uri_format: typeof format;
706
+ declare const uri_parse: typeof parse;
707
+ declare namespace uri {
708
+ export { uri_InvalidURIError as InvalidURIError, type uri_ParsedURI as ParsedURI, uri_format as format, uri_parse as parse };
709
+ }
710
+
711
+ /**
712
+ * Streaming data-plane primitives (CONTRACT.md §5, §6, §P6).
713
+ *
714
+ * Everything here streams: files are hashed and transferred chunk-by-chunk and
715
+ * are NEVER read whole into memory. Downloads are verified (sha256 === oid) and
716
+ * atomically renamed; temp files are removed on failure; path traversal is
717
+ * guarded.
718
+ */
719
+
720
+ interface HashOptions {
721
+ signal?: AbortSignal;
722
+ onProgress?: (loaded: number) => void;
723
+ /** Chunk size for the read stream; the resulting oid is independent of this. */
724
+ highWaterMark?: number;
725
+ }
726
+ /**
727
+ * Compute the streaming sha256 ("oid") and byte size of a file. The whole file
728
+ * is never buffered in memory.
729
+ */
730
+ declare function sha256File(filePath: string, opts?: HashOptions): Promise<{
731
+ oid: string;
732
+ size: number;
733
+ }>;
734
+
735
+ export { type AddEdgeOptions, type Artifact, type ArtifactFile, type ArtifactVersion, AuthenticationError, AuthorizationError, CAVS, CAVSError, type CAVSErrorOptions, type CAVSOptions, ChecksumError, type ClientContext, ConflictError, type CreateRunOptions, type CreateServiceAccountOptions, type CreateSnapshotOptions, DEFAULT_API, DownloadError, type DownloadOptions, type DownloadResult, type DownloadedFile, InvalidURIError, type LineageEdge, type LineageGraph, type Me, NotFoundError, type Org, type ParsedURI, type ProgressCallback, type ProgressEvent, QuotaExceededError, RateLimitError, type Release, type Repo, type Run, type RunArtifact, type ServiceAccount, type ServiceAccountKey, type Snapshot, TemporaryServiceError, type UpdateRunOptions, UploadError, type UploadOptions, type UploadResult, type UploadedFile, type Usage, VERSION, sha256File, uri };