@covia/covia-sdk 1.3.0 → 1.5.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.
package/README.md CHANGED
@@ -1,528 +1,592 @@
1
- # @covia/covia-sdk
2
-
3
- [![npm version](https://badge.fury.io/js/@covia%2Fcovia-sdk.svg)](https://www.npmjs.com/package/@covia/covia-sdk)
4
- [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
5
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
-
7
- TypeScript SDK for [Covia.ai](https://covia.ai) — The Universal Grid for AI Orchestration & Multi-Agent Workflows.
8
-
9
- Covia.ai provides federated execution, cryptographic verification, and shared state management for AI agents across organizations, clouds, and platforms.
10
-
11
- ## Installation
12
-
13
- ```bash
14
- npm install @covia/covia-sdk
15
- ```
16
-
17
- ```bash
18
- pnpm add @covia/covia-sdk
19
- ```
20
-
21
- ```bash
22
- yarn add @covia/covia-sdk
23
- ```
24
-
25
- ## Quick Start
26
-
27
- ```typescript
28
- import { Grid, KeyPairAuth } from "@covia/covia-sdk";
29
-
30
- // Connect to a venue (URL, DNS name, or DID)
31
- const venue = await Grid.connect("https://venue.covia.ai");
32
-
33
- // Or connect with keypair authentication
34
- const auth = KeyPairAuth.generate();
35
- const venue = await Grid.connect("did:web:venue.covia.ai", auth);
36
-
37
- // Run an operation and get the result
38
- const result = await venue.operations.run("test:echo", { message: "hello" });
39
-
40
- // Invoke an operation asynchronously and track the job
41
- const job = await venue.operations.invoke("test:echo", { message: "hello" });
42
- console.log(`Job ${job.id} status: ${job.metadata.status}`);
43
- const output = await job.result({ timeout: 30000 });
44
-
45
- // Work with assets
46
- const assets = await venue.listAssets();
47
- const operation = await venue.getAsset("my-operation-id");
48
- await operation.invoke({ param: "value" });
49
-
50
- // Upload data
51
- const dataAsset = await venue.getAsset("my-data-id");
52
- await dataAsset.putContent(new Blob(["Hello World"], { type: "text/plain" }));
53
- const stream = await dataAsset.getContent();
54
-
55
- // Clean up
56
- venue.close();
57
- ```
58
-
59
- ## Connecting to a Venue
60
-
61
- The SDK supports three connection methods:
62
-
63
- ```typescript
64
- import { Grid, Venue, KeyPairAuth, BearerAuth } from "@covia/covia-sdk";
65
-
66
- // Via Grid (cached — same ID returns the same Venue instance)
67
- const venue = await Grid.connect("https://venue.covia.ai");
68
- const venue = await Grid.connect("did:web:venue.covia.ai");
69
- const venue = await Grid.connect("venue.covia.ai"); // DNS name → https://
70
-
71
- // Via Venue directly (no caching)
72
- const venue = await Venue.connect("https://venue.covia.ai");
73
- ```
74
-
75
- ### Authentication
76
-
77
- ```typescript
78
- // No auth (default)
79
- const venue = await Grid.connect("https://venue.covia.ai");
80
-
81
- // Ed25519 keypair (self-issued JWT per request)
82
- const auth = KeyPairAuth.generate();
83
- console.log(auth.getDID()); // did:key:z6Mk...
84
- const venue = await Grid.connect("https://venue.covia.ai", auth);
85
-
86
- // From a saved private key
87
- const auth = KeyPairAuth.fromHex("abcdef1234...");
88
-
89
- // Bearer token
90
- const auth = new BearerAuth("my-api-token");
91
- const venue = await Grid.connect("https://venue.covia.ai", auth);
92
- ```
93
-
94
- ## API Reference
95
-
96
- ### Venue
97
-
98
- The `Venue` is the primary entry point. All domain-specific functionality is accessed through manager objects.
99
-
100
- ```typescript
101
- venue.baseUrl; // string — the venue's base URL
102
- venue.venueId; // string the venue's DID
103
- venue.metadata; // { name, description }
104
- ```
105
-
106
- | Method | Description |
107
- |---|---|
108
- | `venue.status()` | Get venue status (health, stats) |
109
- | `venue.getAsset(assetId)` | Get an asset by ID (returns `Operation` or `DataAsset`) |
110
- | `venue.listAssets(options?)` | List assets with pagination (`{ offset, limit }`) |
111
- | `venue.getJob(jobId)` | Get a job by ID |
112
- | `venue.listJobs()` | List all job IDs |
113
- | `venue.didDocument()` | Get the venue's DID document |
114
- | `venue.mcpDiscovery()` | Get MCP (Model Context Protocol) discovery info |
115
- | `venue.agentCard()` | Get A2A (Agent-to-Agent) agent card |
116
- | `venue.close()` | Release resources and clear caches |
117
-
118
- ---
119
-
120
- ### Operations — `venue.operations`
121
-
122
- Execute named operations or asset-based operations.
123
-
124
- ```typescript
125
- // List available operations
126
- const ops = await venue.operations.list();
127
- ops.forEach((op) => console.log(`${op.name}: ${op.description}`));
128
-
129
- // Get operation details
130
- const info = await venue.operations.get("test:echo");
131
-
132
- // Run synchronously (invoke + wait for result)
133
- const result = await venue.operations.run("test:echo", { message: "hi" });
134
-
135
- // Invoke asynchronously (returns a Job)
136
- const job = await venue.operations.invoke("test:echo", { message: "hi" });
137
- const output = await job.result({ timeout: 10000 });
138
-
139
- // With UCAN capability tokens
140
- const job = await venue.operations.invoke("sensitive:op", input, {
141
- ucans: ["eyJhbGc..."],
142
- });
143
- ```
144
-
145
- | Method | Returns | Description |
146
- |---|---|---|
147
- | `operations.list()` | `OperationInfo[]` | List all named operations |
148
- | `operations.get(name)` | `OperationInfo` | Get operation details |
149
- | `operations.run(id, input, options?)` | `any` | Execute and wait for result |
150
- | `operations.invoke(id, input, options?)` | `Job` | Execute and return a Job |
151
-
152
- ---
153
-
154
- ### Assets `venue.assets`
155
-
156
- Manage data assets and operations registered on the venue.
157
-
158
- ```typescript
159
- // List and retrieve assets
160
- const list = await venue.assets.list({ offset: 0, limit: 50 });
161
- const asset = await venue.assets.get("asset-id");
162
-
163
- // Register a new asset
164
- const newAsset = await venue.assets.register({
165
- name: "My Dataset",
166
- description: "Training data",
167
- content: { contentType: "text/csv", sha256: "abc123..." },
168
- });
169
-
170
- // Upload and download content
171
- await venue.assets.putContent("asset-id", new Blob(["data"]));
172
- const stream = await venue.assets.getContent("asset-id");
173
-
174
- // Get metadata
175
- const meta = await venue.assets.getMetadata("asset-id");
176
- ```
177
-
178
- | Method | Returns | Description |
179
- |---|---|---|
180
- | `assets.get(assetId)` | `Asset` | Get asset by ID (`Operation` or `DataAsset`) |
181
- | `assets.list(options?)` | `AssetList` | List assets with pagination |
182
- | `assets.register(data)` | `Asset` | Register a new asset |
183
- | `assets.getMetadata(assetId)` | `AssetMetadata` | Get asset metadata |
184
- | `assets.putContent(assetId, content)` | `ContentHashResult` | Upload content |
185
- | `assets.getContent(assetId)` | `ReadableStream \| null` | Download content stream |
186
- | `assets.clearCache()` | `void` | Clear the asset cache |
187
-
188
- ---
189
-
190
- ### Jobs `venue.jobs`
191
-
192
- Manage job lifecycle. Jobs are also returned by `operations.invoke()` and `asset.invoke()`.
193
-
194
- ```typescript
195
- // List and retrieve jobs
196
- const jobIds = await venue.jobs.list();
197
- const job = await venue.jobs.get(jobIds[0]);
198
-
199
- // Job lifecycle via manager
200
- await venue.jobs.pause(jobId);
201
- await venue.jobs.resume(jobId);
202
- await venue.jobs.cancel(jobId);
203
- await venue.jobs.delete(jobId);
204
-
205
- // Send a message to a running job
206
- await venue.jobs.sendMessage(jobId, { text: "user input" });
207
-
208
- // Stream server-sent events
209
- for await (const event of venue.jobs.stream(jobId)) {
210
- console.log(event.event, event.json());
211
- }
212
- ```
213
-
214
- | Method | Returns | Description |
215
- |---|---|---|
216
- | `jobs.list()` | `string[]` | List all job IDs |
217
- | `jobs.get(jobId)` | `Job` | Get a job by ID |
218
- | `jobs.cancel(jobId)` | `JobMetadata` | Cancel a job |
219
- | `jobs.delete(jobId)` | `void` | Delete a job |
220
- | `jobs.pause(jobId)` | `JobMetadata` | Pause a job |
221
- | `jobs.resume(jobId)` | `JobMetadata` | Resume a paused job |
222
- | `jobs.sendMessage(jobId, msg)` | `any` | Send a message to a job |
223
- | `jobs.stream(jobId)` | `AsyncGenerator<SSEEvent>` | Stream SSE events |
224
-
225
- ---
226
-
227
- ### Job Instance
228
-
229
- Once you have a `Job` object, you can interact with it directly.
230
-
231
- ```typescript
232
- const job = await venue.operations.invoke("long:task", input);
233
-
234
- // Status helpers
235
- job.isFinished; // true for COMPLETE, FAILED, CANCELLED, REJECTED, TIMEOUT
236
- job.isComplete; // true only for COMPLETE
237
- job.isPaused; // true for PAUSED, INPUT_REQUIRED, AUTH_REQUIRED
238
- job.needsInput; // true for INPUT_REQUIRED
239
- job.needsAuth; // true for AUTH_REQUIRED
240
-
241
- // Wait for completion
242
- await job.wait({ timeout: 60000 });
243
- const output = job.output; // throws JobFailedError if not COMPLETE
244
-
245
- // Or wait + get output in one call
246
- const result = await job.result({ timeout: 60000 });
247
-
248
- // Refresh status from server
249
- await job.refresh();
250
-
251
- // Lifecycle
252
- await job.cancel();
253
- await job.delete();
254
- await job.pause();
255
- await job.resume();
256
-
257
- // Interactive jobs
258
- if (job.needsInput) {
259
- await job.sendMessage({ text: "user response" });
260
- }
261
-
262
- // Stream events
263
- for await (const event of job.stream()) {
264
- console.log(event.event, event.json());
265
- }
266
- ```
267
-
268
- | Property / Method | Type | Description |
269
- |---|---|---|
270
- | `job.id` | `string` | Job identifier |
271
- | `job.metadata` | `JobMetadata` | Status, input, output, timestamps |
272
- | `job.isFinished` | `boolean` | Terminal state reached |
273
- | `job.isComplete` | `boolean` | Completed successfully |
274
- | `job.isPaused` | `boolean` | Paused / awaiting input or auth |
275
- | `job.needsInput` | `boolean` | Requires user input |
276
- | `job.needsAuth` | `boolean` | Requires authentication |
277
- | `job.output` | `any` | Get output (throws if not complete) |
278
- | `job.refresh()` | `Promise<void>` | Poll latest status from server |
279
- | `job.wait(options?)` | `Promise<void>` | Wait until finished (exponential backoff) |
280
- | `job.result(options?)` | `Promise<any>` | Wait and return output |
281
- | `job.cancel()` | `Promise<JobMetadata>` | Cancel the job |
282
- | `job.delete()` | `Promise<void>` | Delete the job |
283
- | `job.pause()` | `Promise<JobMetadata>` | Pause the job |
284
- | `job.resume()` | `Promise<JobMetadata>` | Resume the job |
285
- | `job.sendMessage(msg)` | `Promise<any>` | Send a message to the job |
286
- | `job.stream()` | `AsyncGenerator<SSEEvent>` | Stream SSE events |
287
-
288
- ---
289
-
290
- ### Asset Instance
291
-
292
- Assets returned by `venue.getAsset()` or `venue.assets.get()` are either an `Operation` or a `DataAsset`.
293
-
294
- ```typescript
295
- const asset = await venue.getAsset("my-asset-id");
296
-
297
- // Metadata
298
- const meta = await asset.getMetadata();
299
-
300
- // Content (DataAsset)
301
- await asset.putContent(new Blob(["data"], { type: "text/plain" }));
302
- const stream = await asset.getContent();
303
- const url = asset.getContentURL(); // direct download URL
304
-
305
- // Execution (Operation)
306
- const result = await asset.run({ param: "value" }); // sync
307
- const job = await asset.invoke({ param: "value" }); // async → Job
308
- ```
309
-
310
- | Method | Returns | Description |
311
- |---|---|---|
312
- | `asset.id` | `string` | Asset identifier |
313
- | `asset.metadata` | `AssetMetadata` | Asset metadata |
314
- | `asset.getMetadata()` | `Promise<AssetMetadata>` | Fetch metadata (cached) |
315
- | `asset.putContent(content)` | `Promise<ContentHashResult>` | Upload content |
316
- | `asset.getContent()` | `Promise<ReadableStream \| null>` | Download content stream |
317
- | `asset.getContentURL()` | `string` | Direct content download URL |
318
- | `asset.run(input)` | `Promise<any>` | Execute and wait for result |
319
- | `asset.invoke(input)` | `Promise<Job>` | Execute and return a Job |
320
-
321
- ---
322
-
323
- ### Agents `venue.agents`
324
-
325
- Create and manage persistent AI agents.
326
-
327
- ```typescript
328
- // Create an agent
329
- const result = await venue.agents.create({
330
- agentId: "my-agent",
331
- config: { model: "gpt-4", instructions: "..." },
332
- });
333
-
334
- // Interact with an agent
335
- const response = await venue.agents.request("my-agent", { text: "hello" });
336
- await venue.agents.message("my-agent", { event: "update" });
337
- await venue.agents.trigger("my-agent");
338
- const state = await venue.agents.query("my-agent");
339
-
340
- // Lifecycle
341
- const agents = await venue.agents.list();
342
- await venue.agents.suspend("my-agent");
343
- await venue.agents.resume("my-agent");
344
- await venue.agents.update({ agentId: "my-agent", config: { ... } });
345
- await venue.agents.cancelTask("my-agent", "task-123");
346
- await venue.agents.delete("my-agent");
347
- ```
348
-
349
- | Method | Returns | Description |
350
- |---|---|---|
351
- | `agents.create(input)` | `AgentCreateResult` | Create an agent |
352
- | `agents.request(id, input?, wait?)` | `AgentRequestResult` | Send request to agent |
353
- | `agents.message(id, message)` | `AgentMessageResult` | Send a message |
354
- | `agents.trigger(id)` | `AgentTriggerResult` | Trigger agent execution |
355
- | `agents.query(id)` | `AgentQueryResult` | Query agent state |
356
- | `agents.list(includeTerminated?)` | `AgentListResult` | List agents |
357
- | `agents.delete(id, remove?)` | `AgentDeleteResult` | Delete an agent |
358
- | `agents.suspend(id)` | `AgentSuspendResult` | Suspend an agent |
359
- | `agents.resume(id, autoWake?)` | `AgentSuspendResult` | Resume an agent |
360
- | `agents.update(input)` | `any` | Update agent config/state |
361
- | `agents.cancelTask(agentId, taskId)` | `any` | Cancel an agent task |
362
-
363
- ---
364
-
365
- ### Workspace `venue.workspace`
366
-
367
- Read and write shared state in the venue's workspace.
368
-
369
- ```typescript
370
- // CRUD
371
- await venue.workspace.write("w/my-app/config", { theme: "dark" });
372
- const data = await venue.workspace.read("w/my-app/config");
373
- await venue.workspace.append("w/my-app/log", "new entry");
374
- await venue.workspace.delete("w/my-app/config");
375
-
376
- // List and slice
377
- const entries = await venue.workspace.list("w/my-app/", 100, 0);
378
- const slice = await venue.workspace.slice("w/my-app/log", 0, 10);
379
-
380
- // Discovery
381
- const funcs = await venue.workspace.functions();
382
- const desc = await venue.workspace.describe("myFunction");
383
- const adapters = await venue.workspace.adapters();
384
- ```
385
-
386
- | Method | Returns | Description |
387
- |---|---|---|
388
- | `workspace.read(path, maxSize?)` | `WorkspaceReadResult` | Read a value |
389
- | `workspace.write(path, value)` | `WorkspaceWriteResult` | Write a value |
390
- | `workspace.delete(path)` | `WorkspaceDeleteResult` | Delete an entry |
391
- | `workspace.append(path, value)` | `WorkspaceAppendResult` | Append to an entry |
392
- | `workspace.list(path?, limit?, offset?)` | `WorkspaceListResult` | List entries |
393
- | `workspace.slice(path, offset?, limit?)` | `WorkspaceSliceResult` | Slice an entry |
394
- | `workspace.functions()` | `FunctionsResult` | List available functions |
395
- | `workspace.describe(name)` | `any` | Describe a function |
396
- | `workspace.adapters()` | `AdaptersResult` | List adapters |
397
-
398
- ---
399
-
400
- ### Secrets `venue.secrets`
401
-
402
- Manage secrets stored on the venue.
403
-
404
- ```typescript
405
- // Store and retrieve
406
- await venue.secrets.put("API_KEY", "sk-...");
407
- await venue.secrets.set("API_KEY", "sk-..."); // via secret:set operation
408
-
409
- // List
410
- const names = await venue.secrets.list(); // ["API_KEY", "DB_PASS"]
411
-
412
- // Extract (requires UCAN capability)
413
- const secret = await venue.secrets.extract("API_KEY");
414
-
415
- // Delete
416
- await venue.secrets.delete("API_KEY");
417
- ```
418
-
419
- | Method | Returns | Description |
420
- |---|---|---|
421
- | `secrets.list()` | `string[]` | List secret names |
422
- | `secrets.put(name, value)` | `void` | Store a secret via REST |
423
- | `secrets.set(name, value)` | `SecretSetResult` | Store via `secret:set` operation |
424
- | `secrets.extract(name)` | `SecretExtractResult` | Extract value (requires UCAN) |
425
- | `secrets.delete(name)` | `void` | Delete a secret |
426
-
427
- ---
428
-
429
- ### UCAN — `venue.ucan`
430
-
431
- Issue UCAN (User Controlled Authorization Network) capability tokens.
432
-
433
- ```typescript
434
- const att = [{ with: "/w/my-app/", can: "crud/read" }];
435
- const exp = Math.floor(Date.now() / 1000) + 3600; // 1 hour
436
-
437
- const token = await venue.ucan.issue("did:key:z6MkBob", att, exp);
438
- ```
439
-
440
- | Method | Returns | Description |
441
- |---|---|---|
442
- | `ucan.issue(aud, att, exp)` | `UCANIssueResult` | Issue a UCAN token |
443
-
444
- ---
445
-
446
- ## Error Handling
447
-
448
- The SDK provides a hierarchy of typed errors:
449
-
450
- ```typescript
451
- import {
452
- CoviaError, // Base error
453
- GridError, // HTTP API errors (4xx/5xx)
454
- NotFoundError, // 404 responses
455
- AssetNotFoundError, // Asset not found
456
- JobNotFoundError, // Job not found
457
- CoviaConnectionError,// Connection failures
458
- CoviaTimeoutError, // Timeout exceeded
459
- JobFailedError, // Job finished with non-COMPLETE status
460
- } from "@covia/covia-sdk";
461
-
462
- try {
463
- const asset = await venue.getAsset("nonexistent");
464
- } catch (err) {
465
- if (err instanceof AssetNotFoundError) {
466
- console.log(`Asset ${err.assetId} not found`);
467
- } else if (err instanceof GridError) {
468
- console.log(`HTTP ${err.statusCode}: ${err.message}`);
469
- }
470
- }
471
-
472
- try {
473
- const result = await job.result({ timeout: 5000 });
474
- } catch (err) {
475
- if (err instanceof CoviaTimeoutError) {
476
- console.log("Job took too long");
477
- } else if (err instanceof JobFailedError) {
478
- console.log(`Job failed: ${err.jobData.status}`);
479
- }
480
- }
481
- ```
482
-
483
- ## Job Status
484
-
485
- ```typescript
486
- import { RunStatus } from "@covia/covia-sdk";
487
-
488
- RunStatus.PENDING; // Queued, not yet started
489
- RunStatus.STARTED; // Running
490
- RunStatus.COMPLETE; // Finished successfully
491
- RunStatus.FAILED; // Finished with error
492
- RunStatus.CANCELLED; // Cancelled by user
493
- RunStatus.TIMEOUT; // Timed out
494
- RunStatus.REJECTED; // Rejected by venue
495
- RunStatus.PAUSED; // Paused
496
- RunStatus.INPUT_REQUIRED; // Waiting for user input
497
- RunStatus.AUTH_REQUIRED; // Waiting for authentication
498
- ```
499
-
500
- ## Requirements
501
-
502
- - Node.js >= 18
503
- - TypeScript >= 5.3 (for TypeScript users)
504
-
505
- ## TypeScript
506
-
507
- `@covia/covia-sdk` is written in TypeScript and ships with full type declarations. No `@types/` package is needed.
508
-
509
- ```typescript
510
- import {
511
- Venue, Grid, Job, Asset, Operation, DataAsset,
512
- AssetManager, OperationManager, JobManager,
513
- AgentManager, WorkspaceManager, SecretManager, UCANManager,
514
- KeyPairAuth, BearerAuth,
515
- RunStatus, CoviaError,
516
- } from "@covia/covia-sdk";
517
- ```
518
-
519
- ## Resources
520
-
521
- - [Covia.ai Platform](https://covia.ai)
522
- - [Documentation](https://docs.covia.ai/)
523
- - [GitHub Repository](https://github.com/covia-ai/covia-sdk)
524
- - [npm Package](https://www.npmjs.com/package/@covia/covia-sdk)
525
-
526
- ## License
527
-
528
- MIT - [Covia AI](https://covia.ai)
1
+ # @covia/covia-sdk
2
+
3
+ [![npm version](https://badge.fury.io/js/@covia%2Fcovia-sdk.svg)](https://www.npmjs.com/package/@covia/covia-sdk)
4
+ [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
5
+ [![License: Apache-2.0](https://img.shields.io/badge/License-Apache--2.0-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)
6
+
7
+ TypeScript SDK for [Covia.ai](https://covia.ai) — The Universal Grid for AI Orchestration & Multi-Agent Workflows.
8
+
9
+ Covia.ai provides federated execution, cryptographic verification, and shared state management for AI agents across organizations, clouds, and platforms.
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ npm install @covia/covia-sdk
15
+ ```
16
+
17
+ ```bash
18
+ pnpm add @covia/covia-sdk
19
+ ```
20
+
21
+ ```bash
22
+ yarn add @covia/covia-sdk
23
+ ```
24
+
25
+ ## Quick Start
26
+
27
+ ```typescript
28
+ import { Grid, KeyPairAuth } from "@covia/covia-sdk";
29
+
30
+ // Connect to a venue (URL, DNS name, or DID)
31
+ const venue = await Grid.connect("https://venue.covia.ai");
32
+
33
+ // Or connect with keypair authentication
34
+ const auth = KeyPairAuth.generate();
35
+ const venue = await Grid.connect("did:web:venue.covia.ai", auth);
36
+
37
+ // Run an operation and get the result
38
+ const result = await venue.operations.run("v/ops/schema/infer", {
39
+ value: { name: "Ada", age: 36, admin: true },
40
+ });
41
+
42
+ // Invoke an operation asynchronously and track the job
43
+ const job = await venue.operations.invoke("v/ops/schema/infer", {
44
+ value: { name: "Ada", age: 36, admin: true },
45
+ });
46
+ console.log(`Job ${job.id} status: ${job.metadata.status}`);
47
+ const output = await job.result({ timeout: 30000 });
48
+
49
+ // Work with assets
50
+ const assets = await venue.listAssets();
51
+ const operation = await venue.getAsset("my-operation-id");
52
+ await operation.invoke({ param: "value" });
53
+
54
+ // Upload data
55
+ const dataAsset = await venue.getAsset("my-data-id");
56
+ await dataAsset.putContent(new Blob(["Hello World"], { type: "text/plain" }));
57
+ const stream = await dataAsset.getContent();
58
+
59
+ // Clean up
60
+ venue.close();
61
+ ```
62
+
63
+ ## Connecting to a Venue
64
+
65
+ The SDK supports three connection methods:
66
+
67
+ ```typescript
68
+ import { Grid, Venue, KeyPairAuth, BearerAuth } from "@covia/covia-sdk";
69
+
70
+ // Via Grid (cached — same ID returns the same Venue instance)
71
+ const venue = await Grid.connect("https://venue.covia.ai");
72
+ const venue = await Grid.connect("did:web:venue.covia.ai");
73
+ const venue = await Grid.connect("venue.covia.ai"); // DNS name → https://
74
+
75
+ // Via Venue directly (no caching)
76
+ const venue = await Venue.connect("https://venue.covia.ai");
77
+ ```
78
+
79
+ ### Authentication
80
+
81
+ ```typescript
82
+ // No auth (default)
83
+ const venue = await Grid.connect("https://venue.covia.ai");
84
+
85
+ // Ed25519 keypair (self-issued JWT per request)
86
+ const auth = KeyPairAuth.generate();
87
+ console.log(auth.getDID()); // did:key:z6Mk...
88
+ const venue = await Grid.connect("https://venue.covia.ai", auth);
89
+
90
+ // From a saved private key
91
+ const auth = KeyPairAuth.fromHex("abcdef1234...");
92
+
93
+ // Bearer token
94
+ const auth = new BearerAuth("my-api-token");
95
+ const venue = await Grid.connect("https://venue.covia.ai", auth);
96
+ ```
97
+
98
+ ## API Reference
99
+
100
+ ### Venue
101
+
102
+ The `Venue` is the primary entry point. All domain-specific functionality is accessed through manager objects.
103
+
104
+ ```typescript
105
+ venue.baseUrl; // string — the venue's base URL
106
+ venue.venueId; // string the venue's DID
107
+ venue.metadata; // { name, description }
108
+ ```
109
+
110
+ | Method | Description |
111
+ |---|---|
112
+ | `venue.status()` | Get venue status (health, stats) |
113
+ | `venue.getAsset(assetId)` | Get an asset by ID (returns `Operation` or `DataAsset`) |
114
+ | `venue.listAssets(options?)` | List assets with pagination (`{ offset, limit }`) |
115
+ | `venue.agent(agentId)` | Get a lazy `Agent` handle (no round-trip) |
116
+ | `venue.getJob(jobId)` | Get a job by ID |
117
+ | `venue.listJobs()` | List all job IDs |
118
+ | `venue.didDocument()` | Get the venue's DID document |
119
+ | `venue.mcpDiscovery()` | Get MCP (Model Context Protocol) discovery info |
120
+ | `venue.agentCard()` | Get A2A (Agent-to-Agent) agent card |
121
+ | `venue.close()` | Release resources and clear caches |
122
+
123
+ ---
124
+
125
+ ### Operations `venue.operations`
126
+
127
+ Execute named operations or asset-based operations.
128
+
129
+ ```typescript
130
+ // List available operations
131
+ const ops = await venue.operations.list();
132
+ ops.forEach((op) => console.log(`${op.name}: ${op.description}`));
133
+
134
+ // Get operation details
135
+ const info = await venue.operations.get("v/ops/schema/infer");
136
+
137
+ // Run synchronously (invoke + wait for result)
138
+ const result = await venue.operations.run("v/ops/schema/infer", {
139
+ value: { name: "Ada", age: 36 },
140
+ });
141
+
142
+ // Invoke asynchronously (returns a Job)
143
+ const job = await venue.operations.invoke("v/ops/schema/infer", {
144
+ value: { name: "Ada", age: 36 },
145
+ });
146
+ const output = await job.result({ timeout: 10000 });
147
+
148
+ // With UCAN capability tokens
149
+ const job = await venue.operations.invoke("sensitive:op", input, {
150
+ ucans: ["eyJhbGc..."],
151
+ });
152
+ ```
153
+
154
+ | Method | Returns | Description |
155
+ |---|---|---|
156
+ | `operations.list()` | `OperationInfo[]` | List all named operations |
157
+ | `operations.get(name)` | `OperationInfo` | Get operation details |
158
+ | `operations.run(id, input, options?)` | `any` | Execute and wait for result |
159
+ | `operations.invoke(id, input, options?)` | `Job` | Execute and return a Job |
160
+
161
+ ---
162
+
163
+ ### Assets `venue.assets`
164
+
165
+ Manage data assets and operations registered on the venue.
166
+
167
+ ```typescript
168
+ // List and retrieve assets
169
+ const list = await venue.assets.list({ offset: 0, limit: 50 });
170
+ const asset = await venue.assets.get("asset-id");
171
+
172
+ // Register a new asset
173
+ const newAsset = await venue.assets.register({
174
+ name: "My Dataset",
175
+ description: "Training data",
176
+ content: { contentType: "text/csv", sha256: "abc123..." },
177
+ });
178
+
179
+ // Upload and download content
180
+ await venue.assets.putContent("asset-id", new Blob(["data"]));
181
+ const stream = await venue.assets.getContent("asset-id");
182
+
183
+ // Get metadata
184
+ const meta = await venue.assets.getMetadata("asset-id");
185
+ ```
186
+
187
+ | Method | Returns | Description |
188
+ |---|---|---|
189
+ | `assets.get(assetId)` | `Asset` | Get asset by ID (`Operation` or `DataAsset`) |
190
+ | `assets.list(options?)` | `AssetList` | List assets with pagination |
191
+ | `assets.register(data)` | `Asset` | Register a new asset |
192
+ | `assets.getMetadata(assetId)` | `AssetMetadata` | Get asset metadata |
193
+ | `assets.putContent(assetId, content)` | `ContentHashResult` | Upload content |
194
+ | `assets.getContent(assetId)` | `ReadableStream \| null` | Download content stream |
195
+ | `assets.clearCache()` | `void` | Clear the asset cache |
196
+
197
+ ---
198
+
199
+ ### Jobs `venue.jobs`
200
+
201
+ Manage job lifecycle. Jobs are also returned by `operations.invoke()` and `asset.invoke()`.
202
+
203
+ ```typescript
204
+ // List and retrieve jobs
205
+ const jobIds = await venue.jobs.list();
206
+ const job = await venue.jobs.get(jobIds[0]);
207
+
208
+ // Job lifecycle via manager
209
+ await venue.jobs.pause(jobId);
210
+ await venue.jobs.resume(jobId);
211
+ await venue.jobs.cancel(jobId);
212
+ await venue.jobs.delete(jobId);
213
+
214
+ // Send a message to a running job
215
+ await venue.jobs.sendMessage(jobId, { text: "user input" });
216
+
217
+ // Stream server-sent events
218
+ for await (const event of venue.jobs.stream(jobId)) {
219
+ console.log(event.event, event.json());
220
+ }
221
+ ```
222
+
223
+ | Method | Returns | Description |
224
+ |---|---|---|
225
+ | `jobs.list()` | `string[]` | List all job IDs |
226
+ | `jobs.get(jobId)` | `Job` | Get a job by ID |
227
+ | `jobs.cancel(jobId)` | `JobMetadata` | Cancel a job |
228
+ | `jobs.delete(jobId)` | `void` | Delete a job |
229
+ | `jobs.pause(jobId)` | `JobMetadata` | Pause a job |
230
+ | `jobs.resume(jobId)` | `JobMetadata` | Resume a paused job |
231
+ | `jobs.sendMessage(jobId, msg)` | `any` | Send a message to a job |
232
+ | `jobs.stream(jobId)` | `AsyncGenerator<SSEEvent>` | Stream SSE events |
233
+
234
+ ---
235
+
236
+ ### Job Instance
237
+
238
+ Once you have a `Job` object, you can interact with it directly.
239
+
240
+ ```typescript
241
+ const job = await venue.operations.invoke("long:task", input);
242
+
243
+ // Status helpers
244
+ job.isFinished; // true for COMPLETE, FAILED, CANCELLED, REJECTED, TIMEOUT
245
+ job.isComplete; // true only for COMPLETE
246
+ job.isPaused; // true for PAUSED, INPUT_REQUIRED, AUTH_REQUIRED
247
+ job.needsInput; // true for INPUT_REQUIRED
248
+ job.needsAuth; // true for AUTH_REQUIRED
249
+
250
+ // Wait for completion
251
+ await job.wait({ timeout: 60000 });
252
+ const output = job.output; // throws JobFailedError if not COMPLETE
253
+
254
+ // Or wait + get output in one call
255
+ const result = await job.result({ timeout: 60000 });
256
+
257
+ // Refresh status from server
258
+ await job.refresh();
259
+
260
+ // Lifecycle
261
+ await job.cancel();
262
+ await job.delete();
263
+ await job.pause();
264
+ await job.resume();
265
+
266
+ // Interactive jobs
267
+ if (job.needsInput) {
268
+ await job.sendMessage({ text: "user response" });
269
+ }
270
+
271
+ // Stream events
272
+ for await (const event of job.stream()) {
273
+ console.log(event.event, event.json());
274
+ }
275
+ ```
276
+
277
+ | Property / Method | Type | Description |
278
+ |---|---|---|
279
+ | `job.id` | `string` | Job identifier |
280
+ | `job.metadata` | `JobMetadata` | Status, input, output, timestamps |
281
+ | `job.isFinished` | `boolean` | Terminal state reached |
282
+ | `job.isComplete` | `boolean` | Completed successfully |
283
+ | `job.isPaused` | `boolean` | Paused / awaiting input or auth |
284
+ | `job.needsInput` | `boolean` | Requires user input |
285
+ | `job.needsAuth` | `boolean` | Requires authentication |
286
+ | `job.output` | `any` | Get output (throws if not complete) |
287
+ | `job.refresh()` | `Promise<void>` | Poll latest status from server |
288
+ | `job.wait(options?)` | `Promise<void>` | Wait until finished (exponential backoff) |
289
+ | `job.result(options?)` | `Promise<any>` | Wait and return output |
290
+ | `job.cancel()` | `Promise<JobMetadata>` | Cancel the job |
291
+ | `job.delete()` | `Promise<void>` | Delete the job |
292
+ | `job.pause()` | `Promise<JobMetadata>` | Pause the job |
293
+ | `job.resume()` | `Promise<JobMetadata>` | Resume the job |
294
+ | `job.sendMessage(msg)` | `Promise<any>` | Send a message to the job |
295
+ | `job.stream()` | `AsyncGenerator<SSEEvent>` | Stream SSE events |
296
+
297
+ ---
298
+
299
+ ### Asset Instance
300
+
301
+ Assets returned by `venue.getAsset()` or `venue.assets.get()` are either an `Operation` or a `DataAsset`.
302
+
303
+ ```typescript
304
+ const asset = await venue.getAsset("my-asset-id");
305
+
306
+ // Metadata
307
+ const meta = await asset.getMetadata();
308
+
309
+ // Content (DataAsset)
310
+ await asset.putContent(new Blob(["data"], { type: "text/plain" }));
311
+ const stream = await asset.getContent();
312
+ const url = asset.getContentURL(); // direct download URL
313
+
314
+ // Execution (Operation)
315
+ const result = await asset.run({ param: "value" }); // sync
316
+ const job = await asset.invoke({ param: "value" }); // async Job
317
+ ```
318
+
319
+ | Method | Returns | Description |
320
+ |---|---|---|
321
+ | `asset.id` | `string` | Asset identifier |
322
+ | `asset.metadata` | `AssetMetadata` | Asset metadata |
323
+ | `asset.getMetadata()` | `Promise<AssetMetadata>` | Fetch metadata (cached) |
324
+ | `asset.putContent(content)` | `Promise<ContentHashResult>` | Upload content |
325
+ | `asset.getContent()` | `Promise<ReadableStream \| null>` | Download content stream |
326
+ | `asset.getContentURL()` | `string` | Direct content download URL |
327
+ | `asset.run(input)` | `Promise<any>` | Execute and wait for result |
328
+ | `asset.invoke(input)` | `Promise<Job>` | Execute and return a Job |
329
+
330
+ ---
331
+
332
+ ### Agents — `venue.agent(id)` / `venue.agents`
333
+
334
+ The preferred way to work with agents is through the `Agent` instance returned by `venue.agent(id)`. This is a lazy handle — no network call is made until you invoke a method.
335
+
336
+ ```typescript
337
+ // Get a handle to an agent (no round-trip)
338
+ const mina = venue.agent("Mina");
339
+
340
+ // Interact
341
+ const response = await mina.request({ text: "hello" });
342
+ await mina.message({ event: "update" });
343
+ await mina.trigger();
344
+ const state = await mina.query();
345
+ const info = await mina.info();
346
+
347
+ // Session-scoped chat — ChatSession manages the sessionId for you
348
+ const chat = mina.chatSession();
349
+ await chat.send("hi"); // mints a new session
350
+ await chat.send("and now?"); // reuses the session automatically
351
+ chat.sessionId; // available for persistence
352
+
353
+ // Resume a previous session
354
+ const resumed = mina.chatSession(storedSessionId);
355
+ await resumed.send("I'm back");
356
+
357
+ // Lifecycle
358
+ await mina.suspend();
359
+ await mina.resume();
360
+ await mina.update({ config: { model: "gpt-4" } });
361
+ await mina.cancelTask("task-123");
362
+ await mina.delete();
363
+
364
+ // Fork into a new agent
365
+ const clone = await mina.fork("Mina-v2", { includeTimeline: true });
366
+ ```
367
+
368
+ #### Agent Instance
369
+
370
+ | Method | Returns | Description |
371
+ |---|---|---|
372
+ | `agent.request(input?, wait?)` | `AgentRequestResult` | Send request to agent |
373
+ | `agent.message(message)` | `AgentMessageResult` | Send a message |
374
+ | `agent.chat(message, sessionId?)` | `AgentChatResult` | Single chat call (manual sessionId) |
375
+ | `agent.chatSession(sessionId?)` | `ChatSession` | Create a session that manages sessionId |
376
+ | `agent.trigger()` | `AgentTriggerResult` | Trigger agent execution |
377
+ | `agent.query()` | `AgentQueryResult` | Query agent state |
378
+ | `agent.info()` | `AgentInfoResult` | Get agent info |
379
+ | `agent.context(task?)` | `string` | Get agent context |
380
+ | `agent.suspend()` | `AgentSuspendResult` | Suspend the agent |
381
+ | `agent.resume(autoWake?)` | `AgentSuspendResult` | Resume the agent |
382
+ | `agent.update(options)` | `any` | Update agent config/state |
383
+ | `agent.cancelTask(taskId)` | `any` | Cancel an agent task |
384
+ | `agent.fork(agentId, options?)` | `Agent` | Fork into a new agent |
385
+ | `agent.delete(remove?)` | `AgentDeleteResult` | Delete the agent |
386
+
387
+ #### ChatSession
388
+
389
+ | Property / Method | Type | Description |
390
+ |---|---|---|
391
+ | `chat.sessionId` | `string \| undefined` | Current session ID (undefined until first send) |
392
+ | `chat.send(message)` | `Promise<AgentChatResult>` | Send a message, auto-managing sessionId |
393
+
394
+ #### AgentManager `venue.agents`
395
+
396
+ The `AgentManager` is still available for collection-level operations and flat-style dispatch.
397
+
398
+ ```typescript
399
+ // Create an agent
400
+ await venue.agents.create({ agentId: "my-agent", config: { ... } });
401
+
402
+ // List agents
403
+ const agents = await venue.agents.list();
404
+
405
+ // Flat-style dispatch (all manager methods still work)
406
+ await venue.agents.chat("my-agent", "hi");
407
+ ```
408
+
409
+ | Method | Returns | Description |
410
+ |---|---|---|
411
+ | `agents.create(input)` | `AgentCreateResult` | Create an agent |
412
+ | `agents.list(includeTerminated?)` | `AgentListResult` | List agents |
413
+ | `agents.request(id, input?, wait?)` | `AgentRequestResult` | Send request to agent |
414
+ | `agents.message(id, message)` | `AgentMessageResult` | Send a message |
415
+ | `agents.chat(id, message, sessionId?)` | `AgentChatResult` | Session-scoped chat |
416
+ | `agents.trigger(id)` | `AgentTriggerResult` | Trigger agent execution |
417
+ | `agents.query(id)` | `AgentQueryResult` | Query agent state |
418
+ | `agents.info(id)` | `AgentInfoResult` | Get agent info |
419
+ | `agents.suspend(id)` | `AgentSuspendResult` | Suspend an agent |
420
+ | `agents.resume(id, autoWake?)` | `AgentSuspendResult` | Resume an agent |
421
+ | `agents.update(input)` | `any` | Update agent config/state |
422
+ | `agents.cancelTask(agentId, taskId)` | `any` | Cancel an agent task |
423
+ | `agents.fork(input)` | `AgentForkResult` | Fork an agent |
424
+ | `agents.context(id, task?)` | `string` | Get agent context |
425
+ | `agents.delete(id, remove?)` | `AgentDeleteResult` | Delete an agent |
426
+
427
+ ---
428
+
429
+ ### Workspace — `venue.workspace`
430
+
431
+ Read and write shared state in the venue's workspace.
432
+
433
+ ```typescript
434
+ // CRUD
435
+ await venue.workspace.write("w/my-app/config", { theme: "dark" });
436
+ const data = await venue.workspace.read("w/my-app/config");
437
+ await venue.workspace.append("w/my-app/log", "new entry");
438
+ await venue.workspace.delete("w/my-app/config");
439
+
440
+ // List and slice
441
+ const entries = await venue.workspace.list("w/my-app/", 100, 0);
442
+ const slice = await venue.workspace.slice("w/my-app/log", 0, 10);
443
+
444
+ // Discovery
445
+ const funcs = await venue.workspace.functions();
446
+ const desc = await venue.workspace.describe("myFunction");
447
+ const adapters = await venue.workspace.adapters();
448
+ ```
449
+
450
+ | Method | Returns | Description |
451
+ |---|---|---|
452
+ | `workspace.read(path, maxSize?)` | `WorkspaceReadResult` | Read a value |
453
+ | `workspace.write(path, value)` | `WorkspaceWriteResult` | Write a value |
454
+ | `workspace.delete(path)` | `WorkspaceDeleteResult` | Delete an entry |
455
+ | `workspace.append(path, value)` | `WorkspaceAppendResult` | Append to an entry |
456
+ | `workspace.list(path?, limit?, offset?)` | `WorkspaceListResult` | List entries |
457
+ | `workspace.slice(path, offset?, limit?)` | `WorkspaceSliceResult` | Slice an entry |
458
+ | `workspace.functions()` | `FunctionsResult` | List available functions |
459
+ | `workspace.describe(name)` | `any` | Describe a function |
460
+ | `workspace.adapters()` | `AdaptersResult` | List adapters |
461
+
462
+ ---
463
+
464
+ ### Secrets `venue.secrets`
465
+
466
+ Manage secrets stored on the venue.
467
+
468
+ ```typescript
469
+ // Store and retrieve
470
+ await venue.secrets.put("API_KEY", "sk-...");
471
+ await venue.secrets.set("API_KEY", "sk-..."); // via secret:set operation
472
+
473
+ // List
474
+ const names = await venue.secrets.list(); // ["API_KEY", "DB_PASS"]
475
+
476
+ // Extract (requires UCAN capability)
477
+ const secret = await venue.secrets.extract("API_KEY");
478
+
479
+ // Delete
480
+ await venue.secrets.delete("API_KEY");
481
+ ```
482
+
483
+ | Method | Returns | Description |
484
+ |---|---|---|
485
+ | `secrets.list()` | `string[]` | List secret names |
486
+ | `secrets.put(name, value)` | `void` | Store a secret via REST |
487
+ | `secrets.set(name, value)` | `SecretSetResult` | Store via `secret:set` operation |
488
+ | `secrets.extract(name)` | `SecretExtractResult` | Extract value (requires UCAN) |
489
+ | `secrets.delete(name)` | `void` | Delete a secret |
490
+
491
+ ---
492
+
493
+ ### UCAN — `venue.ucan`
494
+
495
+ Issue UCAN (User Controlled Authorization Network) capability tokens.
496
+
497
+ ```typescript
498
+ const att = [{ with: "/w/my-app/", can: "crud/read" }];
499
+ const exp = Math.floor(Date.now() / 1000) + 3600; // 1 hour
500
+
501
+ const token = await venue.ucan.issue("did:key:z6MkBob", att, exp);
502
+ ```
503
+
504
+ | Method | Returns | Description |
505
+ |---|---|---|
506
+ | `ucan.issue(aud, att, exp)` | `UCANIssueResult` | Issue a UCAN token |
507
+
508
+ ---
509
+
510
+ ## Error Handling
511
+
512
+ The SDK provides a hierarchy of typed errors:
513
+
514
+ ```typescript
515
+ import {
516
+ CoviaError, // Base error
517
+ GridError, // HTTP API errors (4xx/5xx)
518
+ NotFoundError, // 404 responses
519
+ AssetNotFoundError, // Asset not found
520
+ JobNotFoundError, // Job not found
521
+ CoviaConnectionError,// Connection failures
522
+ CoviaTimeoutError, // Timeout exceeded
523
+ JobFailedError, // Job finished with non-COMPLETE status
524
+ } from "@covia/covia-sdk";
525
+
526
+ try {
527
+ const asset = await venue.getAsset("nonexistent");
528
+ } catch (err) {
529
+ if (err instanceof AssetNotFoundError) {
530
+ console.log(`Asset ${err.assetId} not found`);
531
+ } else if (err instanceof GridError) {
532
+ console.log(`HTTP ${err.statusCode}: ${err.message}`);
533
+ }
534
+ }
535
+
536
+ try {
537
+ const result = await job.result({ timeout: 5000 });
538
+ } catch (err) {
539
+ if (err instanceof CoviaTimeoutError) {
540
+ console.log("Job took too long");
541
+ } else if (err instanceof JobFailedError) {
542
+ console.log(`Job failed: ${err.jobData.status}`);
543
+ }
544
+ }
545
+ ```
546
+
547
+ ## Job Status
548
+
549
+ ```typescript
550
+ import { RunStatus } from "@covia/covia-sdk";
551
+
552
+ RunStatus.PENDING; // Queued, not yet started
553
+ RunStatus.STARTED; // Running
554
+ RunStatus.COMPLETE; // Finished successfully
555
+ RunStatus.FAILED; // Finished with error
556
+ RunStatus.CANCELLED; // Cancelled by user
557
+ RunStatus.TIMEOUT; // Timed out
558
+ RunStatus.REJECTED; // Rejected by venue
559
+ RunStatus.PAUSED; // Paused
560
+ RunStatus.INPUT_REQUIRED; // Waiting for user input
561
+ RunStatus.AUTH_REQUIRED; // Waiting for authentication
562
+ ```
563
+
564
+ ## Requirements
565
+
566
+ - Node.js >= 18
567
+ - TypeScript >= 5.3 (for TypeScript users)
568
+
569
+ ## TypeScript
570
+
571
+ `@covia/covia-sdk` is written in TypeScript and ships with full type declarations. No `@types/` package is needed.
572
+
573
+ ```typescript
574
+ import {
575
+ Venue, Grid, Job, Agent, ChatSession, Asset, Operation, DataAsset,
576
+ AssetManager, OperationManager, JobManager,
577
+ AgentManager, WorkspaceManager, SecretManager, UCANManager,
578
+ KeyPairAuth, BearerAuth,
579
+ RunStatus, CoviaError,
580
+ } from "@covia/covia-sdk";
581
+ ```
582
+
583
+ ## Resources
584
+
585
+ - [Covia.ai Platform](https://covia.ai)
586
+ - [Documentation](https://docs.covia.ai/)
587
+ - [GitHub Repository](https://github.com/covia-ai/covia-sdk)
588
+ - [npm Package](https://www.npmjs.com/package/@covia/covia-sdk)
589
+
590
+ ## License
591
+
592
+ Apache-2.0 - [Covia AI](https://covia.ai)