@covia/covia-sdk 1.6.0 → 1.7.1
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 +61 -2
- package/dist/index.d.mts +221 -9
- package/dist/index.d.ts +221 -9
- package/dist/index.js +360 -50
- package/dist/index.mjs +349 -51
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -6,18 +6,18 @@ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { en
|
|
|
6
6
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
7
7
|
|
|
8
8
|
// src/types.ts
|
|
9
|
-
var RunStatus = /* @__PURE__ */ ((
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
return
|
|
9
|
+
var RunStatus = /* @__PURE__ */ ((RunStatus3) => {
|
|
10
|
+
RunStatus3["COMPLETE"] = "COMPLETE";
|
|
11
|
+
RunStatus3["FAILED"] = "FAILED";
|
|
12
|
+
RunStatus3["PENDING"] = "PENDING";
|
|
13
|
+
RunStatus3["STARTED"] = "STARTED";
|
|
14
|
+
RunStatus3["CANCELLED"] = "CANCELLED";
|
|
15
|
+
RunStatus3["TIMEOUT"] = "TIMEOUT";
|
|
16
|
+
RunStatus3["REJECTED"] = "REJECTED";
|
|
17
|
+
RunStatus3["INPUT_REQUIRED"] = "INPUT_REQUIRED";
|
|
18
|
+
RunStatus3["AUTH_REQUIRED"] = "AUTH_REQUIRED";
|
|
19
|
+
RunStatus3["PAUSED"] = "PAUSED";
|
|
20
|
+
return RunStatus3;
|
|
21
21
|
})(RunStatus || {});
|
|
22
22
|
var JobStatus = RunStatus;
|
|
23
23
|
var AgentStatus = /* @__PURE__ */ ((AgentStatus2) => {
|
|
@@ -70,6 +70,13 @@ var JobFailedError = class extends CoviaError {
|
|
|
70
70
|
this.jobData = jobData;
|
|
71
71
|
}
|
|
72
72
|
};
|
|
73
|
+
var RateLimitError = class extends GridError {
|
|
74
|
+
constructor(message, retryAfterSeconds, body) {
|
|
75
|
+
super(429, message, body);
|
|
76
|
+
this.retryAfterSeconds = retryAfterSeconds;
|
|
77
|
+
this.name = "RateLimitError";
|
|
78
|
+
}
|
|
79
|
+
};
|
|
73
80
|
var NotFoundError = class extends GridError {
|
|
74
81
|
constructor(message) {
|
|
75
82
|
super(404, message);
|
|
@@ -1307,22 +1314,55 @@ function wrapError(error) {
|
|
|
1307
1314
|
}
|
|
1308
1315
|
return new CoviaError(`Request failed: ${msg}`);
|
|
1309
1316
|
}
|
|
1317
|
+
var RETRY_MAX_ATTEMPTS = 4;
|
|
1318
|
+
var RETRY_BASE_MS = 200;
|
|
1319
|
+
var RETRY_MAX_DELAY_MS = 1e4;
|
|
1320
|
+
var RETRY_BUDGET_MS = 3e4;
|
|
1321
|
+
function parseRetryAfterMs(header, nowMs) {
|
|
1322
|
+
if (!header) return 0;
|
|
1323
|
+
const secs = Number(header);
|
|
1324
|
+
if (Number.isFinite(secs)) return Math.max(0, secs * 1e3);
|
|
1325
|
+
const date = Date.parse(header);
|
|
1326
|
+
return Number.isFinite(date) ? Math.max(0, date - nowMs) : 0;
|
|
1327
|
+
}
|
|
1328
|
+
function retryDelayMs(attempt, retryAfterMs, remainingBudgetMs, random) {
|
|
1329
|
+
if (attempt >= RETRY_MAX_ATTEMPTS) return -1;
|
|
1330
|
+
const backoff = Math.min(RETRY_MAX_DELAY_MS, RETRY_BASE_MS * 2 ** (attempt - 1));
|
|
1331
|
+
const delay = Math.max(retryAfterMs, Math.floor(random * backoff));
|
|
1332
|
+
return delay > remainingBudgetMs ? -1 : delay;
|
|
1333
|
+
}
|
|
1334
|
+
var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
1310
1335
|
async function fetchWithError(url, options) {
|
|
1311
1336
|
const method = options?.method ?? "GET";
|
|
1312
|
-
|
|
1313
|
-
let
|
|
1314
|
-
|
|
1315
|
-
response
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1337
|
+
const deadline = Date.now() + RETRY_BUDGET_MS;
|
|
1338
|
+
for (let attempt = 1; ; attempt++) {
|
|
1339
|
+
logger.debug(`${method} ${url}`);
|
|
1340
|
+
let response;
|
|
1341
|
+
try {
|
|
1342
|
+
response = await fetch(url, options);
|
|
1343
|
+
} catch (error) {
|
|
1344
|
+
const msg = error.message ?? String(error);
|
|
1345
|
+
logger.debug(`Connection failed: ${method} ${url} \u2014 ${msg}`);
|
|
1346
|
+
throw wrapError(error);
|
|
1347
|
+
}
|
|
1348
|
+
logger.debug(`${method} ${url} \u2192 ${response.status}`);
|
|
1349
|
+
if (response.status === 429) {
|
|
1350
|
+
const now = Date.now();
|
|
1351
|
+
const retryAfterMs = parseRetryAfterMs(response.headers?.get?.("Retry-After") ?? null, now);
|
|
1352
|
+
const delay = retryDelayMs(attempt, retryAfterMs, deadline - now, Math.random());
|
|
1353
|
+
if (delay < 0) {
|
|
1354
|
+
const { message, body } = await parseErrorBody(response);
|
|
1355
|
+
throw new RateLimitError(message, Math.max(1, Math.ceil(retryAfterMs / 1e3)), body);
|
|
1356
|
+
}
|
|
1357
|
+
logger.debug(`429 from ${url}; retrying in ${delay}ms (attempt ${attempt})`);
|
|
1358
|
+
await sleep(delay);
|
|
1359
|
+
continue;
|
|
1360
|
+
}
|
|
1361
|
+
if (!response.ok) {
|
|
1362
|
+
await throwHttpError(response);
|
|
1363
|
+
}
|
|
1364
|
+
return response.json();
|
|
1324
1365
|
}
|
|
1325
|
-
return response.json();
|
|
1326
1366
|
}
|
|
1327
1367
|
async function fetchStreamWithError(url, options) {
|
|
1328
1368
|
const method = options?.method ?? "GET";
|
|
@@ -1457,10 +1497,145 @@ async function* parseSSEStream(response) {
|
|
|
1457
1497
|
}
|
|
1458
1498
|
}
|
|
1459
1499
|
|
|
1500
|
+
// src/asset-cache.ts
|
|
1501
|
+
var PREFIX = "covia:asset-meta:";
|
|
1502
|
+
var LocalStorageMetadataStore = class {
|
|
1503
|
+
get(hash) {
|
|
1504
|
+
try {
|
|
1505
|
+
const raw = localStorage.getItem(PREFIX + hash);
|
|
1506
|
+
return raw ? JSON.parse(raw) : void 0;
|
|
1507
|
+
} catch {
|
|
1508
|
+
return void 0;
|
|
1509
|
+
}
|
|
1510
|
+
}
|
|
1511
|
+
put(hash, metadata) {
|
|
1512
|
+
try {
|
|
1513
|
+
localStorage.setItem(PREFIX + hash, JSON.stringify(metadata));
|
|
1514
|
+
} catch {
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
clear() {
|
|
1518
|
+
try {
|
|
1519
|
+
const doomed = [];
|
|
1520
|
+
for (let i = 0; i < localStorage.length; i++) {
|
|
1521
|
+
const key = localStorage.key(i);
|
|
1522
|
+
if (key?.startsWith(PREFIX)) doomed.push(key);
|
|
1523
|
+
}
|
|
1524
|
+
doomed.forEach((k) => localStorage.removeItem(k));
|
|
1525
|
+
} catch {
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
};
|
|
1529
|
+
function detectDefaultStore() {
|
|
1530
|
+
try {
|
|
1531
|
+
return typeof localStorage !== "undefined" ? new LocalStorageMetadataStore() : null;
|
|
1532
|
+
} catch {
|
|
1533
|
+
return null;
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1536
|
+
var store = detectDefaultStore();
|
|
1537
|
+
function setAssetMetadataStore(s) {
|
|
1538
|
+
store = s;
|
|
1539
|
+
}
|
|
1540
|
+
function getAssetMetadataStore() {
|
|
1541
|
+
return store;
|
|
1542
|
+
}
|
|
1543
|
+
function normaliseHash(hash) {
|
|
1544
|
+
return (hash.startsWith("0x") ? hash.slice(2) : hash).toLowerCase();
|
|
1545
|
+
}
|
|
1546
|
+
|
|
1547
|
+
// src/AdapterManager.ts
|
|
1548
|
+
var ADAPTERS_PATH = "v/info/adapters";
|
|
1549
|
+
var LIST_LIMIT = 1e3;
|
|
1550
|
+
function toAdapterInfo(name, value) {
|
|
1551
|
+
return {
|
|
1552
|
+
name: value?.name ?? name ?? "",
|
|
1553
|
+
description: value?.description,
|
|
1554
|
+
operations: Array.isArray(value?.operations) ? value.operations : []
|
|
1555
|
+
};
|
|
1556
|
+
}
|
|
1557
|
+
var AdapterManager = class {
|
|
1558
|
+
constructor(venue) {
|
|
1559
|
+
this.venue = venue;
|
|
1560
|
+
}
|
|
1561
|
+
/**
|
|
1562
|
+
* List the adapters registered on the venue, with their descriptions and
|
|
1563
|
+
* invocable operation catalog paths. Registered-but-inactive or zero-op
|
|
1564
|
+
* adapters are included — this is the true registry, not an inference
|
|
1565
|
+
* from the operations catalog.
|
|
1566
|
+
*/
|
|
1567
|
+
async list() {
|
|
1568
|
+
const r = await this.venue.workspace.slice(ADAPTERS_PATH, 0, LIST_LIMIT);
|
|
1569
|
+
if (!r.exists || !Array.isArray(r.values)) return [];
|
|
1570
|
+
const out = [];
|
|
1571
|
+
for (const entry of r.values) {
|
|
1572
|
+
if (!entry || typeof entry !== "object") continue;
|
|
1573
|
+
const key = "key" in entry && typeof entry.key === "string" ? entry.key : void 0;
|
|
1574
|
+
const value = "value" in entry ? entry.value : entry;
|
|
1575
|
+
out.push(toAdapterInfo(key, value));
|
|
1576
|
+
}
|
|
1577
|
+
return out;
|
|
1578
|
+
}
|
|
1579
|
+
/**
|
|
1580
|
+
* Get a single adapter's summary by name.
|
|
1581
|
+
* @param name - Adapter name, e.g. "mcp"
|
|
1582
|
+
* @returns {Promise<AdapterInfo | null>} `null` if no adapter with that name is registered
|
|
1583
|
+
*/
|
|
1584
|
+
async get(name) {
|
|
1585
|
+
const r = await this.venue.workspace.read(`${ADAPTERS_PATH}/${encodeURIComponent(name)}`);
|
|
1586
|
+
if (!r.exists) return null;
|
|
1587
|
+
return toAdapterInfo(name, r.value);
|
|
1588
|
+
}
|
|
1589
|
+
};
|
|
1590
|
+
|
|
1460
1591
|
// src/AgentManager.ts
|
|
1592
|
+
function versionAtLeast(version, major, minor) {
|
|
1593
|
+
const m = version?.match(/^(\d+)\.(\d+)/);
|
|
1594
|
+
if (!m) return true;
|
|
1595
|
+
const [maj, min] = [Number(m[1]), Number(m[2])];
|
|
1596
|
+
return maj > major || maj === major && min >= minor;
|
|
1597
|
+
}
|
|
1461
1598
|
var AgentManager = class {
|
|
1462
1599
|
constructor(venue) {
|
|
1463
1600
|
this.venue = venue;
|
|
1601
|
+
// Whether this venue serves GET /api/v1/agents — flipped on the first 404 so
|
|
1602
|
+
// pre-0.4 venues pay the probe once, not one failed GET per read (covia#180).
|
|
1603
|
+
this.agentsGetSupported = true;
|
|
1604
|
+
}
|
|
1605
|
+
_headers() {
|
|
1606
|
+
const headers = { "Content-Type": "application/json" };
|
|
1607
|
+
this.venue.auth.apply(headers, this.venue.venueId);
|
|
1608
|
+
return headers;
|
|
1609
|
+
}
|
|
1610
|
+
/** Whether the venue serves `GET /api/v1/agents`: no if a probe already
|
|
1611
|
+
* 404'd, or if the venue's last known status identifies it as pre-0.4. */
|
|
1612
|
+
supportsAgentsGet() {
|
|
1613
|
+
if (!this.agentsGetSupported) return false;
|
|
1614
|
+
const status = this.venue.lastKnownStatus;
|
|
1615
|
+
if (status && (!status.version || !versionAtLeast(status.version, 0, 4))) {
|
|
1616
|
+
this.agentsGetSupported = false;
|
|
1617
|
+
}
|
|
1618
|
+
return this.agentsGetSupported;
|
|
1619
|
+
}
|
|
1620
|
+
/** A job-free agents GET, falling back to the invoke path on pre-0.4 venues. */
|
|
1621
|
+
async _agentsOr(path, params, fallback) {
|
|
1622
|
+
if (this.supportsAgentsGet()) {
|
|
1623
|
+
try {
|
|
1624
|
+
const qs = new URLSearchParams();
|
|
1625
|
+
for (const [k, v] of Object.entries(params)) if (v !== void 0) qs.set(k, String(v));
|
|
1626
|
+
const q = qs.toString();
|
|
1627
|
+
return await fetchWithError(
|
|
1628
|
+
`${this.venue.baseUrl}/api/v1/agents${path}${q ? `?${q}` : ""}`,
|
|
1629
|
+
{ headers: this._headers() }
|
|
1630
|
+
);
|
|
1631
|
+
} catch (e) {
|
|
1632
|
+
if (!(e instanceof NotFoundError)) throw e;
|
|
1633
|
+
const routeMissing = path === "" || /\bEndpoint (GET|POST|PUT|DELETE|PATCH|HEAD) /.test(e.message);
|
|
1634
|
+
if (!routeMissing) throw e;
|
|
1635
|
+
this.agentsGetSupported = false;
|
|
1636
|
+
}
|
|
1637
|
+
}
|
|
1638
|
+
return fallback();
|
|
1464
1639
|
}
|
|
1465
1640
|
async create(input) {
|
|
1466
1641
|
return this.venue.operations.run("v/ops/agent/create", input);
|
|
@@ -1493,8 +1668,16 @@ var AgentManager = class {
|
|
|
1493
1668
|
async trigger(agentId) {
|
|
1494
1669
|
return this.venue.operations.run("v/ops/agent/trigger", { agentId });
|
|
1495
1670
|
}
|
|
1671
|
+
/**
|
|
1672
|
+
* List the caller's agents. **Job-free** on covia ≥ 0.4: goes through
|
|
1673
|
+
* `GET /api/v1/agents` (covia#180) — synchronous, no Job persisted. Older
|
|
1674
|
+
* venues transparently fall back to the invoke path (one probe, remembered).
|
|
1675
|
+
*/
|
|
1496
1676
|
async list(includeTerminated) {
|
|
1497
|
-
|
|
1677
|
+
const result = await this._agentsOr("", { includeTerminated }, () => this.venue.operations.run("v/ops/agent/list", { includeTerminated }));
|
|
1678
|
+
const raw = result?.agents ?? [];
|
|
1679
|
+
const agents = raw.map((a) => typeof a === "string" ? { agentId: a } : a);
|
|
1680
|
+
return { agents };
|
|
1498
1681
|
}
|
|
1499
1682
|
async delete(agentId, remove) {
|
|
1500
1683
|
return this.venue.operations.run("v/ops/agent/delete", { agentId, remove });
|
|
@@ -1511,8 +1694,10 @@ var AgentManager = class {
|
|
|
1511
1694
|
async cancelTask(agentId, taskId) {
|
|
1512
1695
|
return this.venue.operations.run("v/ops/agent/cancel-task", { agentId, taskId });
|
|
1513
1696
|
}
|
|
1697
|
+
/** Agent info. **Job-free** on covia ≥ 0.4 (`GET /api/v1/agents/{id}`,
|
|
1698
|
+
* covia#180); older venues fall back to the invoke path. */
|
|
1514
1699
|
async info(agentId) {
|
|
1515
|
-
return this.venue.operations.run("v/ops/agent/info", { agentId });
|
|
1700
|
+
return this._agentsOr(`/${encodeURIComponent(agentId)}`, {}, () => this.venue.operations.run("v/ops/agent/info", { agentId }));
|
|
1516
1701
|
}
|
|
1517
1702
|
async fork(input) {
|
|
1518
1703
|
return this.venue.operations.run("v/ops/agent/fork", input);
|
|
@@ -1869,21 +2054,23 @@ var AssetManager = class {
|
|
|
1869
2054
|
*/
|
|
1870
2055
|
async get(assetId) {
|
|
1871
2056
|
if (cache.has(assetId)) {
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
2057
|
+
return this._wrap(assetId, cache.get(assetId));
|
|
2058
|
+
}
|
|
2059
|
+
const hash = assetHash(assetId);
|
|
2060
|
+
if (hash) {
|
|
2061
|
+
const persisted = getAssetMetadataStore()?.get(normaliseHash(hash));
|
|
2062
|
+
if (persisted) {
|
|
2063
|
+
cache.set(assetId, persisted);
|
|
2064
|
+
return this._wrap(assetId, persisted);
|
|
1877
2065
|
}
|
|
1878
2066
|
}
|
|
1879
2067
|
try {
|
|
1880
2068
|
const data = await fetchWithError(`${this.venue.baseUrl}/api/v1/assets/${assetId}`);
|
|
1881
|
-
if (
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
} else {
|
|
1885
|
-
return new DataAsset(assetId, this.venue, data);
|
|
2069
|
+
if (hash) {
|
|
2070
|
+
cache.set(assetId, data);
|
|
2071
|
+
getAssetMetadataStore()?.put(normaliseHash(hash), data);
|
|
1886
2072
|
}
|
|
2073
|
+
return this._wrap(assetId, data);
|
|
1887
2074
|
} catch (error) {
|
|
1888
2075
|
if (error instanceof NotFoundError) {
|
|
1889
2076
|
throw new AssetNotFoundError(assetId);
|
|
@@ -1891,6 +2078,12 @@ var AssetManager = class {
|
|
|
1891
2078
|
throw error;
|
|
1892
2079
|
}
|
|
1893
2080
|
}
|
|
2081
|
+
_wrap(assetId, data) {
|
|
2082
|
+
if (data.operation) {
|
|
2083
|
+
return new Operation(assetId, this.venue, data);
|
|
2084
|
+
}
|
|
2085
|
+
return new DataAsset(assetId, this.venue, data);
|
|
2086
|
+
}
|
|
1894
2087
|
/**
|
|
1895
2088
|
* List assets with pagination support
|
|
1896
2089
|
* @param options - Pagination options (offset, limit)
|
|
@@ -1976,6 +2169,7 @@ var AssetManager = class {
|
|
|
1976
2169
|
*/
|
|
1977
2170
|
clearCache() {
|
|
1978
2171
|
cache.clear();
|
|
2172
|
+
getAssetMetadataStore()?.clear();
|
|
1979
2173
|
}
|
|
1980
2174
|
// `contentType` defaults to JSON for the metadata/register endpoints. Pass
|
|
1981
2175
|
// `undefined` for binary content upload so fetch infers the type from the
|
|
@@ -2013,9 +2207,47 @@ var OperationManager = class {
|
|
|
2013
2207
|
* @param options - Invoke options (e.g., ucans)
|
|
2014
2208
|
*/
|
|
2015
2209
|
async run(assetId, input, options) {
|
|
2210
|
+
if (this.venue.privateJobs) {
|
|
2211
|
+
return this._runPrivate(assetId, input, options);
|
|
2212
|
+
}
|
|
2016
2213
|
const job = await this.invoke(assetId, input, options);
|
|
2017
2214
|
return await job.result();
|
|
2018
2215
|
}
|
|
2216
|
+
/**
|
|
2217
|
+
* Private-mode execution (covia #192): a memory-only job whose result is
|
|
2218
|
+
* collected through the invoke `wait` window — a completed private job is
|
|
2219
|
+
* immediately forgotten by the venue, so polling cannot be used. If the
|
|
2220
|
+
* operation outlives the venue's wait cap, polling continues while the job
|
|
2221
|
+
* runs; a job that completes between polls is unobservable and surfaces as
|
|
2222
|
+
* a clear error rather than a confusing 404.
|
|
2223
|
+
*/
|
|
2224
|
+
async _runPrivate(assetId, input, options) {
|
|
2225
|
+
const payload = {
|
|
2226
|
+
operation: assetId,
|
|
2227
|
+
input,
|
|
2228
|
+
private: true,
|
|
2229
|
+
wait: true
|
|
2230
|
+
};
|
|
2231
|
+
if (options?.ucans) payload.ucans = options.ucans;
|
|
2232
|
+
const rec = await fetchWithError(`${this.venue.baseUrl}/api/v1/invoke`, {
|
|
2233
|
+
method: "POST",
|
|
2234
|
+
headers: this._buildHeaders(),
|
|
2235
|
+
body: JSON.stringify(payload)
|
|
2236
|
+
});
|
|
2237
|
+
const status = rec.status;
|
|
2238
|
+
if (isJobComplete(status)) return rec.output;
|
|
2239
|
+
if (isJobFinished(status)) {
|
|
2240
|
+
throw new JobFailedError(rec);
|
|
2241
|
+
}
|
|
2242
|
+
try {
|
|
2243
|
+
const job = new Job(rec.id ?? "", this.venue, rec);
|
|
2244
|
+
return await job.result();
|
|
2245
|
+
} catch (e) {
|
|
2246
|
+
throw new CoviaError(
|
|
2247
|
+
`Private job completed while unobserved \u2014 its record is already forgotten, so the result could not be collected. Private jobs that outlive the venue wait window cannot be reliably collected; consider a non-private run for long operations. (${e.message})`
|
|
2248
|
+
);
|
|
2249
|
+
}
|
|
2250
|
+
}
|
|
2019
2251
|
/**
|
|
2020
2252
|
* Execute an operation and return a Job for tracking
|
|
2021
2253
|
* @param assetId - Operation asset ID or named operation
|
|
@@ -2023,6 +2255,11 @@ var OperationManager = class {
|
|
|
2023
2255
|
* @param options - Invoke options (e.g., ucans)
|
|
2024
2256
|
*/
|
|
2025
2257
|
async invoke(assetId, input, options) {
|
|
2258
|
+
if (this.venue.privateJobs) {
|
|
2259
|
+
throw new CoviaError(
|
|
2260
|
+
"Private-jobs mode requires run(): a completed private job is immediately forgotten by the venue, so a poll-style Job cannot collect its result."
|
|
2261
|
+
);
|
|
2262
|
+
}
|
|
2026
2263
|
const payload = {
|
|
2027
2264
|
operation: assetId,
|
|
2028
2265
|
input
|
|
@@ -2045,7 +2282,7 @@ var OperationManager = class {
|
|
|
2045
2282
|
};
|
|
2046
2283
|
|
|
2047
2284
|
// src/WorkspaceManager.ts
|
|
2048
|
-
function
|
|
2285
|
+
function versionAtLeast2(version, major, minor) {
|
|
2049
2286
|
const m = version?.match(/^(\d+)\.(\d+)/);
|
|
2050
2287
|
if (!m) return true;
|
|
2051
2288
|
const [maj, min] = [Number(m[1]), Number(m[2])];
|
|
@@ -2078,7 +2315,7 @@ var WorkspaceManager = class {
|
|
|
2078
2315
|
supportsValues() {
|
|
2079
2316
|
if (!this.valuesSupported) return false;
|
|
2080
2317
|
const status = this.venue.lastKnownStatus;
|
|
2081
|
-
if (status && (!status.version || !
|
|
2318
|
+
if (status && (!status.version || !versionAtLeast2(status.version, 0, 3))) {
|
|
2082
2319
|
this.valuesSupported = false;
|
|
2083
2320
|
}
|
|
2084
2321
|
return this.valuesSupported;
|
|
@@ -2101,7 +2338,8 @@ var WorkspaceManager = class {
|
|
|
2101
2338
|
return this._valuesOr("read", { path, maxSize }, () => this.venue.operations.run("v/ops/covia/read", { path, maxSize }));
|
|
2102
2339
|
}
|
|
2103
2340
|
async list(path, limit, offset, ucans) {
|
|
2104
|
-
|
|
2341
|
+
path = path || "/";
|
|
2342
|
+
if (ucans?.length) return this.venue.operations.run("v/ops/covia/list", { path, limit, offset }, { ucans });
|
|
2105
2343
|
return this._valuesOr("list", { path, limit, offset }, () => this.venue.operations.run("v/ops/covia/list", { path, limit, offset }));
|
|
2106
2344
|
}
|
|
2107
2345
|
async slice(path, offset, limit, ucans) {
|
|
@@ -2161,6 +2399,16 @@ var UCANManager = class {
|
|
|
2161
2399
|
async issue(aud, att, exp) {
|
|
2162
2400
|
return this.venue.operations.run("v/ops/ucan/issue", { aud, att, exp });
|
|
2163
2401
|
}
|
|
2402
|
+
/**
|
|
2403
|
+
* Verify a UCAN against the venue's trust policy and get the verdict
|
|
2404
|
+
* explained — validity with a diagnosable reason, chain depth and root
|
|
2405
|
+
* issuer, per-capability root-authority (owner / venue / refused), and,
|
|
2406
|
+
* when `check` is supplied, whether the token would authorise that request
|
|
2407
|
+
* here. The diagnostic counterpart to an enforcement "Access denied".
|
|
2408
|
+
*/
|
|
2409
|
+
async verify(token, check) {
|
|
2410
|
+
return this.venue.operations.run("v/ops/ucan/verify", { token, ...check });
|
|
2411
|
+
}
|
|
2164
2412
|
};
|
|
2165
2413
|
|
|
2166
2414
|
// src/SecretManager.ts
|
|
@@ -2297,6 +2545,34 @@ function venueBaseUrlCandidates(venueId) {
|
|
|
2297
2545
|
return schemelessVenueCandidates(venueId);
|
|
2298
2546
|
}
|
|
2299
2547
|
var Venue = class _Venue {
|
|
2548
|
+
constructor(options = {}) {
|
|
2549
|
+
/** Connection-level private-jobs mode — see {@link setPrivate}. */
|
|
2550
|
+
this.privateJobs = false;
|
|
2551
|
+
this.baseUrl = options.baseUrl || "";
|
|
2552
|
+
this.venueId = options.venueId || "";
|
|
2553
|
+
this.auth = options.auth || new NoAuth();
|
|
2554
|
+
this.lastKnownStatus = options.status;
|
|
2555
|
+
this.metadata = {
|
|
2556
|
+
name: options.name || "default",
|
|
2557
|
+
description: options.description || ""
|
|
2558
|
+
};
|
|
2559
|
+
}
|
|
2560
|
+
/**
|
|
2561
|
+
* Puts this connection in **private-jobs mode**: every subsequent
|
|
2562
|
+
* `operations.run(...)` executes as a memory-only job (covia #192) — never
|
|
2563
|
+
* persisted to the venue's job index, no durable record, gone on venue
|
|
2564
|
+
* restart. Requires `enablePrivateJobs` on the venue.
|
|
2565
|
+
*
|
|
2566
|
+
* Because a completed private job is immediately forgotten, results are
|
|
2567
|
+
* collected through the invoke `wait` window rather than polling — so
|
|
2568
|
+
* private mode works with `run()`; a poll-style `invoke()` throws.
|
|
2569
|
+
*/
|
|
2570
|
+
setPrivate(enabled) {
|
|
2571
|
+
this.privateJobs = enabled;
|
|
2572
|
+
}
|
|
2573
|
+
get adapters() {
|
|
2574
|
+
return this._adapters ?? (this._adapters = new AdapterManager(this));
|
|
2575
|
+
}
|
|
2300
2576
|
get agents() {
|
|
2301
2577
|
return this._agents ?? (this._agents = new AgentManager(this));
|
|
2302
2578
|
}
|
|
@@ -2318,16 +2594,6 @@ var Venue = class _Venue {
|
|
|
2318
2594
|
get secrets() {
|
|
2319
2595
|
return this._secrets ?? (this._secrets = new SecretManager(this));
|
|
2320
2596
|
}
|
|
2321
|
-
constructor(options = {}) {
|
|
2322
|
-
this.baseUrl = options.baseUrl || "";
|
|
2323
|
-
this.venueId = options.venueId || "";
|
|
2324
|
-
this.auth = options.auth || new NoAuth();
|
|
2325
|
-
this.lastKnownStatus = options.status;
|
|
2326
|
-
this.metadata = {
|
|
2327
|
-
name: options.name || "default",
|
|
2328
|
-
description: options.description || ""
|
|
2329
|
-
};
|
|
2330
|
-
}
|
|
2331
2597
|
/**
|
|
2332
2598
|
* Connect to a venue, validating it with `GET {base}/api/v1/status`. If the
|
|
2333
2599
|
* venue is auth-gated (status answers 401/403 — public access disabled), the
|
|
@@ -2559,10 +2825,42 @@ var Grid = class {
|
|
|
2559
2825
|
return connectedVenue;
|
|
2560
2826
|
}
|
|
2561
2827
|
};
|
|
2828
|
+
|
|
2829
|
+
// src/crypto/ucan.ts
|
|
2830
|
+
var encoder2 = new TextEncoder();
|
|
2831
|
+
var VENUE_RELAY = "venue/relay";
|
|
2832
|
+
function didFor(privateKey) {
|
|
2833
|
+
return `did:key:${encodePublicKey(getPublicKey2(privateKey))}`;
|
|
2834
|
+
}
|
|
2835
|
+
function createUCANJWT(privateKey, audienceDID, att, lifetimeSeconds, proofs = []) {
|
|
2836
|
+
const multikey = encodePublicKey(getPublicKey2(privateKey));
|
|
2837
|
+
const nowSecs = Math.floor(Date.now() / 1e3);
|
|
2838
|
+
const header = JSON.stringify({ alg: "EdDSA", typ: "JWT", kid: multikey });
|
|
2839
|
+
const claims = {
|
|
2840
|
+
iss: `did:key:${multikey}`,
|
|
2841
|
+
aud: audienceDID,
|
|
2842
|
+
att,
|
|
2843
|
+
exp: nowSecs + lifetimeSeconds
|
|
2844
|
+
};
|
|
2845
|
+
if (proofs.length) claims.prf = proofs;
|
|
2846
|
+
const signingInput = `${base64UrlEncode(encoder2.encode(header))}.${base64UrlEncode(encoder2.encode(JSON.stringify(claims)))}`;
|
|
2847
|
+
const signature = sign(encoder2.encode(signingInput), privateKey);
|
|
2848
|
+
return `${signingInput}.${base64UrlEncode(signature)}`;
|
|
2849
|
+
}
|
|
2850
|
+
function identityToken(privateKey, venueDID, lifetimeSeconds = 300) {
|
|
2851
|
+
return createUCANJWT(privateKey, venueDID, [], lifetimeSeconds);
|
|
2852
|
+
}
|
|
2853
|
+
function grant(ownerPrivateKey, audienceDID, withResource, can, lifetimeSeconds) {
|
|
2854
|
+
return createUCANJWT(ownerPrivateKey, audienceDID, [{ with: withResource, can }], lifetimeSeconds);
|
|
2855
|
+
}
|
|
2856
|
+
function relayDelegation(privateKey, venueDID, lifetimeSeconds, caps = []) {
|
|
2857
|
+
const att = [{ with: didFor(privateKey), can: VENUE_RELAY }, ...caps];
|
|
2858
|
+
return createUCANJWT(privateKey, venueDID, att, lifetimeSeconds);
|
|
2859
|
+
}
|
|
2562
2860
|
/*! Bundled license information:
|
|
2563
2861
|
|
|
2564
2862
|
@noble/ed25519/index.js:
|
|
2565
2863
|
(*! noble-ed25519 - MIT License (c) 2019 Paul Miller (paulmillr.com) *)
|
|
2566
2864
|
*/
|
|
2567
2865
|
|
|
2568
|
-
export { Agent, AgentManager, AgentStatus, Asset, AssetManager, AssetNotFoundError, Auth, BasicAuth, BearerAuth, ChatSession, CoviaConnectionError, CoviaError, CoviaTimeoutError, CredentialsHTTP, DataAsset, Ed25519Auth, Grid, GridError, Job, JobFailedError, JobManager, JobNotFoundError, JobStatus, KeyPairAuth, Namespace, NoAuth, NotFoundError, Operation, OperationManager, RunStatus, SecretManager, UCANManager, Venue, WorkspaceManager, assetHash, createSSEEvent, decodePublicKey, didFromPublicKey, didMethod, didUrl, encodePublicKey, fetchStreamWithError, fetchWithError, generateKeyPair, getAssetIdFromPath, getAssetIdFromVenueId, getParsedAssetId, hexToPrivateKey, isDid, isJobComplete, isJobFinished, isJobPaused, logger, parseDidUrl, parseSSEStream, privateKeyToHex, venueBaseUrlCandidates };
|
|
2866
|
+
export { AdapterManager, Agent, AgentManager, AgentStatus, Asset, AssetManager, AssetNotFoundError, Auth, BasicAuth, BearerAuth, ChatSession, CoviaConnectionError, CoviaError, CoviaTimeoutError, CredentialsHTTP, DataAsset, Ed25519Auth, Grid, GridError, Job, JobFailedError, JobManager, JobNotFoundError, JobStatus, KeyPairAuth, Namespace, NoAuth, NotFoundError, Operation, OperationManager, RateLimitError, RunStatus, SecretManager, UCANManager, VENUE_RELAY, Venue, WorkspaceManager, assetHash, createSSEEvent, createUCANJWT, decodePublicKey, didFor, didFromPublicKey, didMethod, didUrl, encodePublicKey, fetchStreamWithError, fetchWithError, generateKeyPair, getAssetIdFromPath, getAssetIdFromVenueId, getAssetMetadataStore, getParsedAssetId, grant, hexToPrivateKey, identityToken, isDid, isJobComplete, isJobFinished, isJobPaused, logger, parseDidUrl, parseRetryAfterMs, parseSSEStream, privateKeyToHex, relayDelegation, retryDelayMs, setAssetMetadataStore, venueBaseUrlCandidates };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@covia/covia-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.1",
|
|
4
4
|
"description": "Typescript library for covia-ai",
|
|
5
5
|
"packageManager": "pnpm@11.9.0",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -69,4 +69,4 @@
|
|
|
69
69
|
"did-resolver": "^4.1.0",
|
|
70
70
|
"web-did-resolver": "^2.0.32"
|
|
71
71
|
}
|
|
72
|
-
}
|
|
72
|
+
}
|