@covia/covia-sdk 1.7.1 → 1.7.3

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
@@ -577,12 +577,14 @@ The SDK provides a hierarchy of typed errors:
577
577
 
578
578
  ```typescript
579
579
  import {
580
+ Venue,
580
581
  CoviaError, // Base error
581
582
  GridError, // HTTP API errors (4xx/5xx)
582
583
  NotFoundError, // 404 responses
583
584
  AssetNotFoundError, // Asset not found
584
585
  JobNotFoundError, // Job not found
585
- CoviaConnectionError,// Connection failures
586
+ CoviaConnectionError,// Transport/connect failures (url, method, attempts)
587
+ VenueIdentityChangedError, // Same address now reports a different DID
586
588
  CoviaTimeoutError, // Timeout exceeded
587
589
  JobFailedError, // Job finished with non-COMPLETE status
588
590
  RateLimitError, // 429 after bounded retries (carries retryAfterSeconds)
@@ -609,6 +611,32 @@ try {
609
611
  }
610
612
  ```
611
613
 
614
+ Transport failures include the exact request target and method. A failed
615
+ `Venue.connect()` additionally includes every candidate and failed validation
616
+ request:
617
+
618
+ ```typescript
619
+ try {
620
+ await Venue.connect("localhost:8080");
621
+ } catch (err) {
622
+ if (err instanceof CoviaConnectionError) {
623
+ console.error(err.candidates);
624
+ for (const attempt of err.attempts) {
625
+ console.error(attempt.method, attempt.url, attempt.error.message);
626
+ }
627
+ }
628
+ }
629
+
630
+ try {
631
+ await venue.status();
632
+ } catch (err) {
633
+ if (err instanceof VenueIdentityChangedError) {
634
+ console.error(`Venue changed from ${err.oldDid} to ${err.newDid}`);
635
+ // Reconnect and re-authorise explicitly; the old handle is not rebound.
636
+ }
637
+ }
638
+ ```
639
+
612
640
  ## Job Status
613
641
 
614
642
  ```typescript
package/dist/index.d.mts CHANGED
@@ -715,6 +715,8 @@ declare class Venue implements VenueInterface {
715
715
  * responded (the https candidate if an http fallback failed; the resolved
716
716
  * endpoint for a did:web id), and `venue.venueId` is the DID the venue
717
717
  * reported. The validated API root is `${venue.baseUrl}/api/v1`.
718
+ * @throws {CoviaConnectionError} If no candidate can be validated.
719
+ * @throws {VenueIdentityChangedError} If a known/resolved DID reports a different identity.
718
720
  */
719
721
  static connect(venueId: string | Venue, auth?: Auth): Promise<Venue>;
720
722
  /**
@@ -760,6 +762,7 @@ declare class Venue implements VenueInterface {
760
762
  /**
761
763
  * Get venue status
762
764
  * @returns {Promise<StatusData>}
765
+ * @throws {VenueIdentityChangedError} If this address reports a different known DID.
763
766
  */
764
767
  status(): Promise<StatusData>;
765
768
  /**
@@ -774,6 +777,7 @@ declare class Venue implements VenueInterface {
774
777
  * @param options.pollIntervalMs - Delay between polls (default 1000).
775
778
  * @returns The ready {@link StatusData}.
776
779
  * @throws {CoviaTimeoutError} If the venue is not ready within the timeout.
780
+ * @throws {VenueIdentityChangedError} Immediately if the venue's DID changed.
777
781
  */
778
782
  waitUntilReady(options?: {
779
783
  timeoutMs?: number;
@@ -1323,9 +1327,47 @@ declare class GridError extends CoviaError {
1323
1327
  responseBody: unknown;
1324
1328
  constructor(statusCode: number, message: string, responseBody?: unknown);
1325
1329
  }
1326
- /** Raised when the SDK cannot connect to the venue. */
1330
+ /** One failed HTTP request made while resolving/validating a venue connection. */
1331
+ interface ConnectionAttempt {
1332
+ readonly url: string;
1333
+ readonly method: string;
1334
+ readonly error: CoviaError;
1335
+ }
1336
+ interface CoviaConnectionErrorOptions {
1337
+ /** Exact request target for a single transport failure. */
1338
+ url?: string;
1339
+ /** HTTP method for a single transport failure. */
1340
+ method?: string;
1341
+ /** Original exception, or the final failed attempt for an aggregate error. */
1342
+ cause?: unknown;
1343
+ /** Ordered venue base URLs considered by `Venue.connect()`. */
1344
+ candidates?: readonly string[];
1345
+ /** Ordered failed requests made while validating those candidates. */
1346
+ attempts?: readonly ConnectionAttempt[];
1347
+ }
1348
+ /**
1349
+ * Raised when an HTTP request cannot be made, or when `Venue.connect()` cannot
1350
+ * validate any candidate. HTTP responses still use `GridError`; this class is
1351
+ * for transport failures and connection-attempt aggregation.
1352
+ */
1327
1353
  declare class CoviaConnectionError extends CoviaError {
1328
- constructor(message: string);
1354
+ readonly url: string | null;
1355
+ readonly method: string | null;
1356
+ readonly cause: unknown;
1357
+ readonly candidates: readonly string[];
1358
+ readonly attempts: readonly ConnectionAttempt[];
1359
+ constructor(message: string, options?: CoviaConnectionErrorOptions);
1360
+ }
1361
+ /**
1362
+ * Raised when a known venue address reports a different DID. The instance
1363
+ * remains bound to `oldDid`; callers must explicitly reconnect/re-authorise
1364
+ * against `newDid` rather than silently continuing under a new identity.
1365
+ */
1366
+ declare class VenueIdentityChangedError extends CoviaError {
1367
+ readonly oldDid: string;
1368
+ readonly newDid: string;
1369
+ readonly baseUrl: string;
1370
+ constructor(oldDid: string, newDid: string, baseUrl: string);
1329
1371
  }
1330
1372
  /** Raised when an operation or polling loop times out. */
1331
1373
  declare class CoviaTimeoutError extends CoviaError {
@@ -1638,4 +1680,4 @@ declare function grant(ownerPrivateKey: Uint8Array, audienceDID: string, withRes
1638
1680
  */
1639
1681
  declare function relayDelegation(privateKey: Uint8Array, venueDID: string, lifetimeSeconds: number, caps?: UCANCapability[]): string;
1640
1682
 
1641
- export { type AdapterInfo, AdapterManager, type AdaptersResult, Agent, type AgentCancelTaskInput, type AgentCard, type AgentChatInput, type AgentChatResult, type AgentCompleteTaskResult, type AgentContextInput, type AgentCreateInput, type AgentCreateResult, type AgentDeleteInput, type AgentDeleteResult, type AgentFailTaskResult, type AgentForkInput, type AgentForkResult, type AgentInfoResult, type AgentListInput, type AgentListResult, AgentManager, type AgentMessageInput, type AgentMessageResult, type AgentRequestInput, type AgentRequestResult, type AgentResumeInput, AgentStatus, type AgentSuspendResult, type AgentTriggerInput, type AgentTriggerResult, type AgentUpdateInput, Asset, type AssetID, type AssetList, type AssetListOptions, AssetManager, type AssetMetadata, type AssetMetadataStore, AssetNotFoundError, type AssetPinResult, Auth, BasicAuth, BearerAuth, ChatSession, type ContentDetails, type ContentHashResult, CoviaConnectionError, CoviaError, CoviaTimeoutError, type Credentials, CredentialsHTTP, type DIDDocument, type DIDURL, DataAsset, Ed25519Auth, type FunctionInfo, type FunctionsResult, Grid, GridError, type GroupCount, type InvokeOptions, type InvokePayload, Job, JobFailedError, JobManager, type JobMetadata, JobNotFoundError, JobStatus, KeyPairAuth, type MCPDiscovery, Namespace, NoAuth, NotFoundError, Operation, type OperationDetails, type OperationInfo, OperationManager, type OperationPayload, type OperationRunner, RateLimitError, RunStatus, type SSEEvent, type SecretExtractInput, type SecretExtractResult, SecretManager, type SecretSetInput, type SecretSetResult, type StatsData, type StatusData, type UCANAttenuation, type UCANCapability, type UCANIssueInput, type UCANIssueResult, UCANManager, type UCANVerifyResult, VENUE_RELAY, Venue, type VenueConstructor, type VenueData, type VenueInterface, type VenueOptions, type WorkspaceAggregateResult, type WorkspaceAppendInput, type WorkspaceAppendResult, type WorkspaceCopyResult, type WorkspaceCountResult, type WorkspaceDeleteInput, type WorkspaceDeleteResult, type WorkspaceInspectInput, type WorkspaceInspectResult, type WorkspaceListInput, type WorkspaceListResult, WorkspaceManager, type WorkspaceReadInput, type WorkspaceReadResult, type WorkspaceSliceInput, type WorkspaceSliceResult, type WorkspaceWriteInput, type WorkspaceWriteResult, 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 };
1683
+ export { type AdapterInfo, AdapterManager, type AdaptersResult, Agent, type AgentCancelTaskInput, type AgentCard, type AgentChatInput, type AgentChatResult, type AgentCompleteTaskResult, type AgentContextInput, type AgentCreateInput, type AgentCreateResult, type AgentDeleteInput, type AgentDeleteResult, type AgentFailTaskResult, type AgentForkInput, type AgentForkResult, type AgentInfoResult, type AgentListInput, type AgentListResult, AgentManager, type AgentMessageInput, type AgentMessageResult, type AgentRequestInput, type AgentRequestResult, type AgentResumeInput, AgentStatus, type AgentSuspendResult, type AgentTriggerInput, type AgentTriggerResult, type AgentUpdateInput, Asset, type AssetID, type AssetList, type AssetListOptions, AssetManager, type AssetMetadata, type AssetMetadataStore, AssetNotFoundError, type AssetPinResult, Auth, BasicAuth, BearerAuth, ChatSession, type ConnectionAttempt, type ContentDetails, type ContentHashResult, CoviaConnectionError, type CoviaConnectionErrorOptions, CoviaError, CoviaTimeoutError, type Credentials, CredentialsHTTP, type DIDDocument, type DIDURL, DataAsset, Ed25519Auth, type FunctionInfo, type FunctionsResult, Grid, GridError, type GroupCount, type InvokeOptions, type InvokePayload, Job, JobFailedError, JobManager, type JobMetadata, JobNotFoundError, JobStatus, KeyPairAuth, type MCPDiscovery, Namespace, NoAuth, NotFoundError, Operation, type OperationDetails, type OperationInfo, OperationManager, type OperationPayload, type OperationRunner, RateLimitError, RunStatus, type SSEEvent, type SecretExtractInput, type SecretExtractResult, SecretManager, type SecretSetInput, type SecretSetResult, type StatsData, type StatusData, type UCANAttenuation, type UCANCapability, type UCANIssueInput, type UCANIssueResult, UCANManager, type UCANVerifyResult, VENUE_RELAY, Venue, type VenueConstructor, type VenueData, VenueIdentityChangedError, type VenueInterface, type VenueOptions, type WorkspaceAggregateResult, type WorkspaceAppendInput, type WorkspaceAppendResult, type WorkspaceCopyResult, type WorkspaceCountResult, type WorkspaceDeleteInput, type WorkspaceDeleteResult, type WorkspaceInspectInput, type WorkspaceInspectResult, type WorkspaceListInput, type WorkspaceListResult, WorkspaceManager, type WorkspaceReadInput, type WorkspaceReadResult, type WorkspaceSliceInput, type WorkspaceSliceResult, type WorkspaceWriteInput, type WorkspaceWriteResult, 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/dist/index.d.ts CHANGED
@@ -715,6 +715,8 @@ declare class Venue implements VenueInterface {
715
715
  * responded (the https candidate if an http fallback failed; the resolved
716
716
  * endpoint for a did:web id), and `venue.venueId` is the DID the venue
717
717
  * reported. The validated API root is `${venue.baseUrl}/api/v1`.
718
+ * @throws {CoviaConnectionError} If no candidate can be validated.
719
+ * @throws {VenueIdentityChangedError} If a known/resolved DID reports a different identity.
718
720
  */
719
721
  static connect(venueId: string | Venue, auth?: Auth): Promise<Venue>;
720
722
  /**
@@ -760,6 +762,7 @@ declare class Venue implements VenueInterface {
760
762
  /**
761
763
  * Get venue status
762
764
  * @returns {Promise<StatusData>}
765
+ * @throws {VenueIdentityChangedError} If this address reports a different known DID.
763
766
  */
764
767
  status(): Promise<StatusData>;
765
768
  /**
@@ -774,6 +777,7 @@ declare class Venue implements VenueInterface {
774
777
  * @param options.pollIntervalMs - Delay between polls (default 1000).
775
778
  * @returns The ready {@link StatusData}.
776
779
  * @throws {CoviaTimeoutError} If the venue is not ready within the timeout.
780
+ * @throws {VenueIdentityChangedError} Immediately if the venue's DID changed.
777
781
  */
778
782
  waitUntilReady(options?: {
779
783
  timeoutMs?: number;
@@ -1323,9 +1327,47 @@ declare class GridError extends CoviaError {
1323
1327
  responseBody: unknown;
1324
1328
  constructor(statusCode: number, message: string, responseBody?: unknown);
1325
1329
  }
1326
- /** Raised when the SDK cannot connect to the venue. */
1330
+ /** One failed HTTP request made while resolving/validating a venue connection. */
1331
+ interface ConnectionAttempt {
1332
+ readonly url: string;
1333
+ readonly method: string;
1334
+ readonly error: CoviaError;
1335
+ }
1336
+ interface CoviaConnectionErrorOptions {
1337
+ /** Exact request target for a single transport failure. */
1338
+ url?: string;
1339
+ /** HTTP method for a single transport failure. */
1340
+ method?: string;
1341
+ /** Original exception, or the final failed attempt for an aggregate error. */
1342
+ cause?: unknown;
1343
+ /** Ordered venue base URLs considered by `Venue.connect()`. */
1344
+ candidates?: readonly string[];
1345
+ /** Ordered failed requests made while validating those candidates. */
1346
+ attempts?: readonly ConnectionAttempt[];
1347
+ }
1348
+ /**
1349
+ * Raised when an HTTP request cannot be made, or when `Venue.connect()` cannot
1350
+ * validate any candidate. HTTP responses still use `GridError`; this class is
1351
+ * for transport failures and connection-attempt aggregation.
1352
+ */
1327
1353
  declare class CoviaConnectionError extends CoviaError {
1328
- constructor(message: string);
1354
+ readonly url: string | null;
1355
+ readonly method: string | null;
1356
+ readonly cause: unknown;
1357
+ readonly candidates: readonly string[];
1358
+ readonly attempts: readonly ConnectionAttempt[];
1359
+ constructor(message: string, options?: CoviaConnectionErrorOptions);
1360
+ }
1361
+ /**
1362
+ * Raised when a known venue address reports a different DID. The instance
1363
+ * remains bound to `oldDid`; callers must explicitly reconnect/re-authorise
1364
+ * against `newDid` rather than silently continuing under a new identity.
1365
+ */
1366
+ declare class VenueIdentityChangedError extends CoviaError {
1367
+ readonly oldDid: string;
1368
+ readonly newDid: string;
1369
+ readonly baseUrl: string;
1370
+ constructor(oldDid: string, newDid: string, baseUrl: string);
1329
1371
  }
1330
1372
  /** Raised when an operation or polling loop times out. */
1331
1373
  declare class CoviaTimeoutError extends CoviaError {
@@ -1638,4 +1680,4 @@ declare function grant(ownerPrivateKey: Uint8Array, audienceDID: string, withRes
1638
1680
  */
1639
1681
  declare function relayDelegation(privateKey: Uint8Array, venueDID: string, lifetimeSeconds: number, caps?: UCANCapability[]): string;
1640
1682
 
1641
- export { type AdapterInfo, AdapterManager, type AdaptersResult, Agent, type AgentCancelTaskInput, type AgentCard, type AgentChatInput, type AgentChatResult, type AgentCompleteTaskResult, type AgentContextInput, type AgentCreateInput, type AgentCreateResult, type AgentDeleteInput, type AgentDeleteResult, type AgentFailTaskResult, type AgentForkInput, type AgentForkResult, type AgentInfoResult, type AgentListInput, type AgentListResult, AgentManager, type AgentMessageInput, type AgentMessageResult, type AgentRequestInput, type AgentRequestResult, type AgentResumeInput, AgentStatus, type AgentSuspendResult, type AgentTriggerInput, type AgentTriggerResult, type AgentUpdateInput, Asset, type AssetID, type AssetList, type AssetListOptions, AssetManager, type AssetMetadata, type AssetMetadataStore, AssetNotFoundError, type AssetPinResult, Auth, BasicAuth, BearerAuth, ChatSession, type ContentDetails, type ContentHashResult, CoviaConnectionError, CoviaError, CoviaTimeoutError, type Credentials, CredentialsHTTP, type DIDDocument, type DIDURL, DataAsset, Ed25519Auth, type FunctionInfo, type FunctionsResult, Grid, GridError, type GroupCount, type InvokeOptions, type InvokePayload, Job, JobFailedError, JobManager, type JobMetadata, JobNotFoundError, JobStatus, KeyPairAuth, type MCPDiscovery, Namespace, NoAuth, NotFoundError, Operation, type OperationDetails, type OperationInfo, OperationManager, type OperationPayload, type OperationRunner, RateLimitError, RunStatus, type SSEEvent, type SecretExtractInput, type SecretExtractResult, SecretManager, type SecretSetInput, type SecretSetResult, type StatsData, type StatusData, type UCANAttenuation, type UCANCapability, type UCANIssueInput, type UCANIssueResult, UCANManager, type UCANVerifyResult, VENUE_RELAY, Venue, type VenueConstructor, type VenueData, type VenueInterface, type VenueOptions, type WorkspaceAggregateResult, type WorkspaceAppendInput, type WorkspaceAppendResult, type WorkspaceCopyResult, type WorkspaceCountResult, type WorkspaceDeleteInput, type WorkspaceDeleteResult, type WorkspaceInspectInput, type WorkspaceInspectResult, type WorkspaceListInput, type WorkspaceListResult, WorkspaceManager, type WorkspaceReadInput, type WorkspaceReadResult, type WorkspaceSliceInput, type WorkspaceSliceResult, type WorkspaceWriteInput, type WorkspaceWriteResult, 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 };
1683
+ export { type AdapterInfo, AdapterManager, type AdaptersResult, Agent, type AgentCancelTaskInput, type AgentCard, type AgentChatInput, type AgentChatResult, type AgentCompleteTaskResult, type AgentContextInput, type AgentCreateInput, type AgentCreateResult, type AgentDeleteInput, type AgentDeleteResult, type AgentFailTaskResult, type AgentForkInput, type AgentForkResult, type AgentInfoResult, type AgentListInput, type AgentListResult, AgentManager, type AgentMessageInput, type AgentMessageResult, type AgentRequestInput, type AgentRequestResult, type AgentResumeInput, AgentStatus, type AgentSuspendResult, type AgentTriggerInput, type AgentTriggerResult, type AgentUpdateInput, Asset, type AssetID, type AssetList, type AssetListOptions, AssetManager, type AssetMetadata, type AssetMetadataStore, AssetNotFoundError, type AssetPinResult, Auth, BasicAuth, BearerAuth, ChatSession, type ConnectionAttempt, type ContentDetails, type ContentHashResult, CoviaConnectionError, type CoviaConnectionErrorOptions, CoviaError, CoviaTimeoutError, type Credentials, CredentialsHTTP, type DIDDocument, type DIDURL, DataAsset, Ed25519Auth, type FunctionInfo, type FunctionsResult, Grid, GridError, type GroupCount, type InvokeOptions, type InvokePayload, Job, JobFailedError, JobManager, type JobMetadata, JobNotFoundError, JobStatus, KeyPairAuth, type MCPDiscovery, Namespace, NoAuth, NotFoundError, Operation, type OperationDetails, type OperationInfo, OperationManager, type OperationPayload, type OperationRunner, RateLimitError, RunStatus, type SSEEvent, type SecretExtractInput, type SecretExtractResult, SecretManager, type SecretSetInput, type SecretSetResult, type StatsData, type StatusData, type UCANAttenuation, type UCANCapability, type UCANIssueInput, type UCANIssueResult, UCANManager, type UCANVerifyResult, VENUE_RELAY, Venue, type VenueConstructor, type VenueData, VenueIdentityChangedError, type VenueInterface, type VenueOptions, type WorkspaceAggregateResult, type WorkspaceAppendInput, type WorkspaceAppendResult, type WorkspaceCopyResult, type WorkspaceCountResult, type WorkspaceDeleteInput, type WorkspaceDeleteResult, type WorkspaceInspectInput, type WorkspaceInspectResult, type WorkspaceListInput, type WorkspaceListResult, WorkspaceManager, type WorkspaceReadInput, type WorkspaceReadResult, type WorkspaceSliceInput, type WorkspaceSliceResult, type WorkspaceWriteInput, type WorkspaceWriteResult, 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/dist/index.js CHANGED
@@ -46,9 +46,23 @@ var GridError = class extends CoviaError {
46
46
  }
47
47
  };
48
48
  var CoviaConnectionError = class extends CoviaError {
49
- constructor(message) {
49
+ constructor(message, options = {}) {
50
50
  super(message);
51
51
  this.name = "CoviaConnectionError";
52
+ this.url = options.url ?? null;
53
+ this.method = options.method?.toUpperCase() ?? null;
54
+ this.cause = options.cause;
55
+ this.candidates = [...options.candidates ?? []];
56
+ this.attempts = [...options.attempts ?? []];
57
+ }
58
+ };
59
+ var VenueIdentityChangedError = class extends CoviaError {
60
+ constructor(oldDid, newDid, baseUrl) {
61
+ super(`Venue identity changed at ${baseUrl}: expected ${oldDid}, received ${newDid}`);
62
+ this.oldDid = oldDid;
63
+ this.newDid = newDid;
64
+ this.baseUrl = baseUrl;
65
+ this.name = "VenueIdentityChangedError";
52
66
  }
53
67
  };
54
68
  var CoviaTimeoutError = class extends CoviaError {
@@ -1308,13 +1322,14 @@ async function throwHttpError(response) {
1308
1322
  }
1309
1323
  throw new GridError(response.status, message, body);
1310
1324
  }
1311
- function wrapError(error) {
1312
- if (error instanceof CoviaError) return error;
1313
- const msg = error.message ?? String(error);
1314
- if (error instanceof TypeError) {
1315
- return new CoviaConnectionError(msg);
1316
- }
1317
- return new CoviaError(`Request failed: ${msg}`);
1325
+ function wrapConnectionError(error, url, method) {
1326
+ if (error instanceof CoviaConnectionError && error.url && error.method) return error;
1327
+ const detail = error instanceof Error ? error.message : String(error);
1328
+ return new CoviaConnectionError(`${method} ${url} failed: ${detail}`, {
1329
+ url,
1330
+ method,
1331
+ cause: error
1332
+ });
1318
1333
  }
1319
1334
  var RETRY_MAX_ATTEMPTS = 4;
1320
1335
  var RETRY_BASE_MS = 200;
@@ -1335,7 +1350,7 @@ function retryDelayMs(attempt, retryAfterMs, remainingBudgetMs, random) {
1335
1350
  }
1336
1351
  var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
1337
1352
  async function fetchWithError(url, options) {
1338
- const method = options?.method ?? "GET";
1353
+ const method = (options?.method ?? "GET").toUpperCase();
1339
1354
  const deadline = Date.now() + RETRY_BUDGET_MS;
1340
1355
  for (let attempt = 1; ; attempt++) {
1341
1356
  logger.debug(`${method} ${url}`);
@@ -1345,7 +1360,7 @@ async function fetchWithError(url, options) {
1345
1360
  } catch (error) {
1346
1361
  const msg = error.message ?? String(error);
1347
1362
  logger.debug(`Connection failed: ${method} ${url} \u2014 ${msg}`);
1348
- throw wrapError(error);
1363
+ throw wrapConnectionError(error, url, method);
1349
1364
  }
1350
1365
  logger.debug(`${method} ${url} \u2192 ${response.status}`);
1351
1366
  if (response.status === 429) {
@@ -1367,7 +1382,7 @@ async function fetchWithError(url, options) {
1367
1382
  }
1368
1383
  }
1369
1384
  async function fetchStreamWithError(url, options) {
1370
- const method = options?.method ?? "GET";
1385
+ const method = (options?.method ?? "GET").toUpperCase();
1371
1386
  logger.debug(`${method} ${url}`);
1372
1387
  let response;
1373
1388
  try {
@@ -1375,7 +1390,7 @@ async function fetchStreamWithError(url, options) {
1375
1390
  } catch (error) {
1376
1391
  const msg = error.message ?? String(error);
1377
1392
  logger.debug(`Connection failed: ${method} ${url} \u2014 ${msg}`);
1378
- throw wrapError(error);
1393
+ throw wrapConnectionError(error, url, method);
1379
1394
  }
1380
1395
  logger.debug(`${method} ${url} \u2192 ${response.status}`);
1381
1396
  if (!response.ok) {
@@ -1866,9 +1881,12 @@ var JobManager = class {
1866
1881
  this.venue = venue;
1867
1882
  }
1868
1883
  async list() {
1869
- return fetchWithError(`${this.venue.baseUrl}/api/v1/jobs`, {
1884
+ const body = await fetchWithError(`${this.venue.baseUrl}/api/v1/jobs`, {
1870
1885
  headers: this._buildHeaders()
1871
1886
  });
1887
+ if (Array.isArray(body)) return body;
1888
+ const items = body?.items;
1889
+ return Array.isArray(items) ? items : [];
1872
1890
  }
1873
1891
  async get(jobId) {
1874
1892
  try {
@@ -2067,7 +2085,9 @@ var AssetManager = class {
2067
2085
  }
2068
2086
  }
2069
2087
  try {
2070
- const data = await fetchWithError(`${this.venue.baseUrl}/api/v1/assets/${assetId}`);
2088
+ const data = await fetchWithError(`${this.venue.baseUrl}/api/v1/assets/${assetId}`, {
2089
+ headers: this._buildHeaders(null)
2090
+ });
2071
2091
  if (hash) {
2072
2092
  cache.set(assetId, data);
2073
2093
  getAssetMetadataStore()?.put(normaliseHash(hash), data);
@@ -2096,7 +2116,9 @@ var AssetManager = class {
2096
2116
  if (options.limit !== void 0) {
2097
2117
  params.set("limit", String(options.limit));
2098
2118
  }
2099
- return fetchWithError(`${this.venue.baseUrl}/api/v1/assets?${params.toString()}`);
2119
+ return fetchWithError(`${this.venue.baseUrl}/api/v1/assets?${params.toString()}`, {
2120
+ headers: this._buildHeaders(null)
2121
+ });
2100
2122
  }
2101
2123
  /**
2102
2124
  * Register a new asset
@@ -2115,7 +2137,9 @@ var AssetManager = class {
2115
2137
  */
2116
2138
  async getMetadata(assetId) {
2117
2139
  try {
2118
- return await fetchWithError(`${this.venue.baseUrl}/api/v1/assets/${assetId}`);
2140
+ return await fetchWithError(`${this.venue.baseUrl}/api/v1/assets/${assetId}`, {
2141
+ headers: this._buildHeaders(null)
2142
+ });
2119
2143
  } catch (error) {
2120
2144
  if (error instanceof NotFoundError) {
2121
2145
  throw new AssetNotFoundError(assetId);
@@ -2149,7 +2173,9 @@ var AssetManager = class {
2149
2173
  */
2150
2174
  async getContent(assetId) {
2151
2175
  try {
2152
- const response = await fetchStreamWithError(`${this.venue.baseUrl}/api/v1/assets/${assetId}/content`);
2176
+ const response = await fetchStreamWithError(`${this.venue.baseUrl}/api/v1/assets/${assetId}/content`, {
2177
+ headers: this._buildHeaders(null)
2178
+ });
2153
2179
  return response.body;
2154
2180
  } catch (error) {
2155
2181
  if (error instanceof NotFoundError) {
@@ -2546,6 +2572,20 @@ function venueBaseUrlCandidates(venueId) {
2546
2572
  }
2547
2573
  return schemelessVenueCandidates(venueId);
2548
2574
  }
2575
+ function asCoviaError(error) {
2576
+ if (error instanceof CoviaError) return error;
2577
+ const message = error instanceof Error ? error.message : String(error);
2578
+ return new CoviaError(message);
2579
+ }
2580
+ function assertVenueIdentity(expectedDid, actualDid, baseUrl) {
2581
+ if (expectedDid && actualDid && expectedDid !== actualDid) {
2582
+ throw new VenueIdentityChangedError(expectedDid, actualDid, baseUrl);
2583
+ }
2584
+ }
2585
+ function connectionFailureMessage(venueId, attempts) {
2586
+ const detail = attempts.map(({ method, url, error }) => `${method} ${url}: ${error.message}`).join("; ");
2587
+ return `Could not connect to venue ${venueId}${detail ? `. Attempts: ${detail}` : ""}`;
2588
+ }
2549
2589
  var Venue = class _Venue {
2550
2590
  constructor(options = {}) {
2551
2591
  /** Connection-level private-jobs mode — see {@link setPrivate}. */
@@ -2616,20 +2656,26 @@ var Venue = class _Venue {
2616
2656
  * responded (the https candidate if an http fallback failed; the resolved
2617
2657
  * endpoint for a did:web id), and `venue.venueId` is the DID the venue
2618
2658
  * reported. The validated API root is `${venue.baseUrl}/api/v1`.
2659
+ * @throws {CoviaConnectionError} If no candidate can be validated.
2660
+ * @throws {VenueIdentityChangedError} If a known/resolved DID reports a different identity.
2619
2661
  */
2620
2662
  static async connect(venueId, auth) {
2621
2663
  if (venueId instanceof _Venue) {
2622
- return new _Venue({
2664
+ const connected = new _Venue({
2623
2665
  baseUrl: venueId.baseUrl,
2624
2666
  venueId: venueId.venueId,
2625
2667
  name: venueId.metadata.name,
2626
2668
  auth,
2627
2669
  status: venueId.lastKnownStatus
2628
2670
  });
2671
+ await connected.status();
2672
+ return connected;
2629
2673
  }
2630
2674
  if (typeof venueId === "string") {
2631
2675
  let candidates;
2676
+ let expectedDid;
2632
2677
  if (venueId.startsWith("did:web:")) {
2678
+ expectedDid = venueId;
2633
2679
  const didDoc = await resolver.resolve(venueId);
2634
2680
  if (!didDoc.didDocument) {
2635
2681
  throw new CoviaError("Invalid DID document");
@@ -2642,10 +2688,15 @@ var Venue = class _Venue {
2642
2688
  } else {
2643
2689
  candidates = venueBaseUrlCandidates(venueId);
2644
2690
  }
2645
- let lastError;
2691
+ const attempts = [];
2646
2692
  for (const baseUrl of candidates) {
2693
+ const statusUrl = baseUrl + "/api/v1/status";
2647
2694
  try {
2648
- const data = await fetchWithError(baseUrl + "/api/v1/status");
2695
+ const data = await fetchWithError(statusUrl);
2696
+ if (!data.did) {
2697
+ throw new CoviaError(`Venue status at ${statusUrl} did not include a DID`);
2698
+ }
2699
+ assertVenueIdentity(expectedDid, data.did, baseUrl);
2649
2700
  return new _Venue({
2650
2701
  baseUrl,
2651
2702
  venueId: data.did,
@@ -2654,19 +2705,30 @@ var Venue = class _Venue {
2654
2705
  status: data
2655
2706
  });
2656
2707
  } catch (error) {
2657
- if (error instanceof GridError && (error.statusCode === 401 || error.statusCode === 403)) {
2708
+ if (error instanceof VenueIdentityChangedError) throw error;
2709
+ const statusError = asCoviaError(error);
2710
+ attempts.push({ url: statusUrl, method: "GET", error: statusError });
2711
+ if (statusError instanceof GridError && (statusError.statusCode === 401 || statusError.statusCode === 403)) {
2712
+ const didDocumentUrl = baseUrl + "/.well-known/did.json";
2658
2713
  try {
2659
- const doc = await fetchWithError(baseUrl + "/.well-known/did.json");
2714
+ const doc = await fetchWithError(didDocumentUrl);
2660
2715
  if (doc?.id) {
2716
+ assertVenueIdentity(expectedDid, doc.id, baseUrl);
2661
2717
  return new _Venue({ baseUrl, venueId: doc.id, auth });
2662
2718
  }
2663
- } catch {
2719
+ throw new CoviaError(`DID document at ${didDocumentUrl} did not include an id`);
2720
+ } catch (fallbackError) {
2721
+ if (fallbackError instanceof VenueIdentityChangedError) throw fallbackError;
2722
+ attempts.push({ url: didDocumentUrl, method: "GET", error: asCoviaError(fallbackError) });
2664
2723
  }
2665
2724
  }
2666
- lastError = error;
2667
2725
  }
2668
2726
  }
2669
- throw lastError instanceof Error ? lastError : new CoviaError(`Could not connect to venue: ${venueId}`);
2727
+ throw new CoviaConnectionError(connectionFailureMessage(venueId, attempts), {
2728
+ candidates,
2729
+ attempts,
2730
+ cause: attempts.length > 0 ? attempts[attempts.length - 1].error : void 0
2731
+ });
2670
2732
  }
2671
2733
  throw new CoviaError("Invalid venue ID parameter. Must be a string (URL/DNS) or Venue instance.");
2672
2734
  }
@@ -2733,9 +2795,17 @@ var Venue = class _Venue {
2733
2795
  /**
2734
2796
  * Get venue status
2735
2797
  * @returns {Promise<StatusData>}
2798
+ * @throws {VenueIdentityChangedError} If this address reports a different known DID.
2736
2799
  */
2737
2800
  async status() {
2738
2801
  const data = await fetchWithError(`${this.baseUrl}/api/v1/status`);
2802
+ if (data.did) {
2803
+ if (this.venueId) {
2804
+ assertVenueIdentity(this.venueId, data.did, this.baseUrl);
2805
+ } else {
2806
+ this.venueId = data.did;
2807
+ }
2808
+ }
2739
2809
  this.lastKnownStatus = data;
2740
2810
  return data;
2741
2811
  }
@@ -2751,6 +2821,7 @@ var Venue = class _Venue {
2751
2821
  * @param options.pollIntervalMs - Delay between polls (default 1000).
2752
2822
  * @returns The ready {@link StatusData}.
2753
2823
  * @throws {CoviaTimeoutError} If the venue is not ready within the timeout.
2824
+ * @throws {VenueIdentityChangedError} Immediately if the venue's DID changed.
2754
2825
  */
2755
2826
  async waitUntilReady(options = {}) {
2756
2827
  const timeoutMs = options.timeoutMs ?? 6e4;
@@ -2760,7 +2831,8 @@ var Venue = class _Venue {
2760
2831
  try {
2761
2832
  const data = await this.status();
2762
2833
  if (data.status == null || data.status.toUpperCase() === "OK") return data;
2763
- } catch {
2834
+ } catch (error) {
2835
+ if (error instanceof VenueIdentityChangedError) throw error;
2764
2836
  }
2765
2837
  if (Date.now() - start >= timeoutMs) {
2766
2838
  throw new CoviaTimeoutError(`Venue ${this.baseUrl} not ready within ${timeoutMs}ms`);
@@ -2901,6 +2973,7 @@ exports.SecretManager = SecretManager;
2901
2973
  exports.UCANManager = UCANManager;
2902
2974
  exports.VENUE_RELAY = VENUE_RELAY;
2903
2975
  exports.Venue = Venue;
2976
+ exports.VenueIdentityChangedError = VenueIdentityChangedError;
2904
2977
  exports.WorkspaceManager = WorkspaceManager;
2905
2978
  exports.assetHash = assetHash;
2906
2979
  exports.createSSEEvent = createSSEEvent;
package/dist/index.mjs CHANGED
@@ -44,9 +44,23 @@ var GridError = class extends CoviaError {
44
44
  }
45
45
  };
46
46
  var CoviaConnectionError = class extends CoviaError {
47
- constructor(message) {
47
+ constructor(message, options = {}) {
48
48
  super(message);
49
49
  this.name = "CoviaConnectionError";
50
+ this.url = options.url ?? null;
51
+ this.method = options.method?.toUpperCase() ?? null;
52
+ this.cause = options.cause;
53
+ this.candidates = [...options.candidates ?? []];
54
+ this.attempts = [...options.attempts ?? []];
55
+ }
56
+ };
57
+ var VenueIdentityChangedError = class extends CoviaError {
58
+ constructor(oldDid, newDid, baseUrl) {
59
+ super(`Venue identity changed at ${baseUrl}: expected ${oldDid}, received ${newDid}`);
60
+ this.oldDid = oldDid;
61
+ this.newDid = newDid;
62
+ this.baseUrl = baseUrl;
63
+ this.name = "VenueIdentityChangedError";
50
64
  }
51
65
  };
52
66
  var CoviaTimeoutError = class extends CoviaError {
@@ -1306,13 +1320,14 @@ async function throwHttpError(response) {
1306
1320
  }
1307
1321
  throw new GridError(response.status, message, body);
1308
1322
  }
1309
- function wrapError(error) {
1310
- if (error instanceof CoviaError) return error;
1311
- const msg = error.message ?? String(error);
1312
- if (error instanceof TypeError) {
1313
- return new CoviaConnectionError(msg);
1314
- }
1315
- return new CoviaError(`Request failed: ${msg}`);
1323
+ function wrapConnectionError(error, url, method) {
1324
+ if (error instanceof CoviaConnectionError && error.url && error.method) return error;
1325
+ const detail = error instanceof Error ? error.message : String(error);
1326
+ return new CoviaConnectionError(`${method} ${url} failed: ${detail}`, {
1327
+ url,
1328
+ method,
1329
+ cause: error
1330
+ });
1316
1331
  }
1317
1332
  var RETRY_MAX_ATTEMPTS = 4;
1318
1333
  var RETRY_BASE_MS = 200;
@@ -1333,7 +1348,7 @@ function retryDelayMs(attempt, retryAfterMs, remainingBudgetMs, random) {
1333
1348
  }
1334
1349
  var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
1335
1350
  async function fetchWithError(url, options) {
1336
- const method = options?.method ?? "GET";
1351
+ const method = (options?.method ?? "GET").toUpperCase();
1337
1352
  const deadline = Date.now() + RETRY_BUDGET_MS;
1338
1353
  for (let attempt = 1; ; attempt++) {
1339
1354
  logger.debug(`${method} ${url}`);
@@ -1343,7 +1358,7 @@ async function fetchWithError(url, options) {
1343
1358
  } catch (error) {
1344
1359
  const msg = error.message ?? String(error);
1345
1360
  logger.debug(`Connection failed: ${method} ${url} \u2014 ${msg}`);
1346
- throw wrapError(error);
1361
+ throw wrapConnectionError(error, url, method);
1347
1362
  }
1348
1363
  logger.debug(`${method} ${url} \u2192 ${response.status}`);
1349
1364
  if (response.status === 429) {
@@ -1365,7 +1380,7 @@ async function fetchWithError(url, options) {
1365
1380
  }
1366
1381
  }
1367
1382
  async function fetchStreamWithError(url, options) {
1368
- const method = options?.method ?? "GET";
1383
+ const method = (options?.method ?? "GET").toUpperCase();
1369
1384
  logger.debug(`${method} ${url}`);
1370
1385
  let response;
1371
1386
  try {
@@ -1373,7 +1388,7 @@ async function fetchStreamWithError(url, options) {
1373
1388
  } catch (error) {
1374
1389
  const msg = error.message ?? String(error);
1375
1390
  logger.debug(`Connection failed: ${method} ${url} \u2014 ${msg}`);
1376
- throw wrapError(error);
1391
+ throw wrapConnectionError(error, url, method);
1377
1392
  }
1378
1393
  logger.debug(`${method} ${url} \u2192 ${response.status}`);
1379
1394
  if (!response.ok) {
@@ -1864,9 +1879,12 @@ var JobManager = class {
1864
1879
  this.venue = venue;
1865
1880
  }
1866
1881
  async list() {
1867
- return fetchWithError(`${this.venue.baseUrl}/api/v1/jobs`, {
1882
+ const body = await fetchWithError(`${this.venue.baseUrl}/api/v1/jobs`, {
1868
1883
  headers: this._buildHeaders()
1869
1884
  });
1885
+ if (Array.isArray(body)) return body;
1886
+ const items = body?.items;
1887
+ return Array.isArray(items) ? items : [];
1870
1888
  }
1871
1889
  async get(jobId) {
1872
1890
  try {
@@ -2065,7 +2083,9 @@ var AssetManager = class {
2065
2083
  }
2066
2084
  }
2067
2085
  try {
2068
- const data = await fetchWithError(`${this.venue.baseUrl}/api/v1/assets/${assetId}`);
2086
+ const data = await fetchWithError(`${this.venue.baseUrl}/api/v1/assets/${assetId}`, {
2087
+ headers: this._buildHeaders(null)
2088
+ });
2069
2089
  if (hash) {
2070
2090
  cache.set(assetId, data);
2071
2091
  getAssetMetadataStore()?.put(normaliseHash(hash), data);
@@ -2094,7 +2114,9 @@ var AssetManager = class {
2094
2114
  if (options.limit !== void 0) {
2095
2115
  params.set("limit", String(options.limit));
2096
2116
  }
2097
- return fetchWithError(`${this.venue.baseUrl}/api/v1/assets?${params.toString()}`);
2117
+ return fetchWithError(`${this.venue.baseUrl}/api/v1/assets?${params.toString()}`, {
2118
+ headers: this._buildHeaders(null)
2119
+ });
2098
2120
  }
2099
2121
  /**
2100
2122
  * Register a new asset
@@ -2113,7 +2135,9 @@ var AssetManager = class {
2113
2135
  */
2114
2136
  async getMetadata(assetId) {
2115
2137
  try {
2116
- return await fetchWithError(`${this.venue.baseUrl}/api/v1/assets/${assetId}`);
2138
+ return await fetchWithError(`${this.venue.baseUrl}/api/v1/assets/${assetId}`, {
2139
+ headers: this._buildHeaders(null)
2140
+ });
2117
2141
  } catch (error) {
2118
2142
  if (error instanceof NotFoundError) {
2119
2143
  throw new AssetNotFoundError(assetId);
@@ -2147,7 +2171,9 @@ var AssetManager = class {
2147
2171
  */
2148
2172
  async getContent(assetId) {
2149
2173
  try {
2150
- const response = await fetchStreamWithError(`${this.venue.baseUrl}/api/v1/assets/${assetId}/content`);
2174
+ const response = await fetchStreamWithError(`${this.venue.baseUrl}/api/v1/assets/${assetId}/content`, {
2175
+ headers: this._buildHeaders(null)
2176
+ });
2151
2177
  return response.body;
2152
2178
  } catch (error) {
2153
2179
  if (error instanceof NotFoundError) {
@@ -2544,6 +2570,20 @@ function venueBaseUrlCandidates(venueId) {
2544
2570
  }
2545
2571
  return schemelessVenueCandidates(venueId);
2546
2572
  }
2573
+ function asCoviaError(error) {
2574
+ if (error instanceof CoviaError) return error;
2575
+ const message = error instanceof Error ? error.message : String(error);
2576
+ return new CoviaError(message);
2577
+ }
2578
+ function assertVenueIdentity(expectedDid, actualDid, baseUrl) {
2579
+ if (expectedDid && actualDid && expectedDid !== actualDid) {
2580
+ throw new VenueIdentityChangedError(expectedDid, actualDid, baseUrl);
2581
+ }
2582
+ }
2583
+ function connectionFailureMessage(venueId, attempts) {
2584
+ const detail = attempts.map(({ method, url, error }) => `${method} ${url}: ${error.message}`).join("; ");
2585
+ return `Could not connect to venue ${venueId}${detail ? `. Attempts: ${detail}` : ""}`;
2586
+ }
2547
2587
  var Venue = class _Venue {
2548
2588
  constructor(options = {}) {
2549
2589
  /** Connection-level private-jobs mode — see {@link setPrivate}. */
@@ -2614,20 +2654,26 @@ var Venue = class _Venue {
2614
2654
  * responded (the https candidate if an http fallback failed; the resolved
2615
2655
  * endpoint for a did:web id), and `venue.venueId` is the DID the venue
2616
2656
  * reported. The validated API root is `${venue.baseUrl}/api/v1`.
2657
+ * @throws {CoviaConnectionError} If no candidate can be validated.
2658
+ * @throws {VenueIdentityChangedError} If a known/resolved DID reports a different identity.
2617
2659
  */
2618
2660
  static async connect(venueId, auth) {
2619
2661
  if (venueId instanceof _Venue) {
2620
- return new _Venue({
2662
+ const connected = new _Venue({
2621
2663
  baseUrl: venueId.baseUrl,
2622
2664
  venueId: venueId.venueId,
2623
2665
  name: venueId.metadata.name,
2624
2666
  auth,
2625
2667
  status: venueId.lastKnownStatus
2626
2668
  });
2669
+ await connected.status();
2670
+ return connected;
2627
2671
  }
2628
2672
  if (typeof venueId === "string") {
2629
2673
  let candidates;
2674
+ let expectedDid;
2630
2675
  if (venueId.startsWith("did:web:")) {
2676
+ expectedDid = venueId;
2631
2677
  const didDoc = await resolver.resolve(venueId);
2632
2678
  if (!didDoc.didDocument) {
2633
2679
  throw new CoviaError("Invalid DID document");
@@ -2640,10 +2686,15 @@ var Venue = class _Venue {
2640
2686
  } else {
2641
2687
  candidates = venueBaseUrlCandidates(venueId);
2642
2688
  }
2643
- let lastError;
2689
+ const attempts = [];
2644
2690
  for (const baseUrl of candidates) {
2691
+ const statusUrl = baseUrl + "/api/v1/status";
2645
2692
  try {
2646
- const data = await fetchWithError(baseUrl + "/api/v1/status");
2693
+ const data = await fetchWithError(statusUrl);
2694
+ if (!data.did) {
2695
+ throw new CoviaError(`Venue status at ${statusUrl} did not include a DID`);
2696
+ }
2697
+ assertVenueIdentity(expectedDid, data.did, baseUrl);
2647
2698
  return new _Venue({
2648
2699
  baseUrl,
2649
2700
  venueId: data.did,
@@ -2652,19 +2703,30 @@ var Venue = class _Venue {
2652
2703
  status: data
2653
2704
  });
2654
2705
  } catch (error) {
2655
- if (error instanceof GridError && (error.statusCode === 401 || error.statusCode === 403)) {
2706
+ if (error instanceof VenueIdentityChangedError) throw error;
2707
+ const statusError = asCoviaError(error);
2708
+ attempts.push({ url: statusUrl, method: "GET", error: statusError });
2709
+ if (statusError instanceof GridError && (statusError.statusCode === 401 || statusError.statusCode === 403)) {
2710
+ const didDocumentUrl = baseUrl + "/.well-known/did.json";
2656
2711
  try {
2657
- const doc = await fetchWithError(baseUrl + "/.well-known/did.json");
2712
+ const doc = await fetchWithError(didDocumentUrl);
2658
2713
  if (doc?.id) {
2714
+ assertVenueIdentity(expectedDid, doc.id, baseUrl);
2659
2715
  return new _Venue({ baseUrl, venueId: doc.id, auth });
2660
2716
  }
2661
- } catch {
2717
+ throw new CoviaError(`DID document at ${didDocumentUrl} did not include an id`);
2718
+ } catch (fallbackError) {
2719
+ if (fallbackError instanceof VenueIdentityChangedError) throw fallbackError;
2720
+ attempts.push({ url: didDocumentUrl, method: "GET", error: asCoviaError(fallbackError) });
2662
2721
  }
2663
2722
  }
2664
- lastError = error;
2665
2723
  }
2666
2724
  }
2667
- throw lastError instanceof Error ? lastError : new CoviaError(`Could not connect to venue: ${venueId}`);
2725
+ throw new CoviaConnectionError(connectionFailureMessage(venueId, attempts), {
2726
+ candidates,
2727
+ attempts,
2728
+ cause: attempts.length > 0 ? attempts[attempts.length - 1].error : void 0
2729
+ });
2668
2730
  }
2669
2731
  throw new CoviaError("Invalid venue ID parameter. Must be a string (URL/DNS) or Venue instance.");
2670
2732
  }
@@ -2731,9 +2793,17 @@ var Venue = class _Venue {
2731
2793
  /**
2732
2794
  * Get venue status
2733
2795
  * @returns {Promise<StatusData>}
2796
+ * @throws {VenueIdentityChangedError} If this address reports a different known DID.
2734
2797
  */
2735
2798
  async status() {
2736
2799
  const data = await fetchWithError(`${this.baseUrl}/api/v1/status`);
2800
+ if (data.did) {
2801
+ if (this.venueId) {
2802
+ assertVenueIdentity(this.venueId, data.did, this.baseUrl);
2803
+ } else {
2804
+ this.venueId = data.did;
2805
+ }
2806
+ }
2737
2807
  this.lastKnownStatus = data;
2738
2808
  return data;
2739
2809
  }
@@ -2749,6 +2819,7 @@ var Venue = class _Venue {
2749
2819
  * @param options.pollIntervalMs - Delay between polls (default 1000).
2750
2820
  * @returns The ready {@link StatusData}.
2751
2821
  * @throws {CoviaTimeoutError} If the venue is not ready within the timeout.
2822
+ * @throws {VenueIdentityChangedError} Immediately if the venue's DID changed.
2752
2823
  */
2753
2824
  async waitUntilReady(options = {}) {
2754
2825
  const timeoutMs = options.timeoutMs ?? 6e4;
@@ -2758,7 +2829,8 @@ var Venue = class _Venue {
2758
2829
  try {
2759
2830
  const data = await this.status();
2760
2831
  if (data.status == null || data.status.toUpperCase() === "OK") return data;
2761
- } catch {
2832
+ } catch (error) {
2833
+ if (error instanceof VenueIdentityChangedError) throw error;
2762
2834
  }
2763
2835
  if (Date.now() - start >= timeoutMs) {
2764
2836
  throw new CoviaTimeoutError(`Venue ${this.baseUrl} not ready within ${timeoutMs}ms`);
@@ -2863,4 +2935,4 @@ function relayDelegation(privateKey, venueDID, lifetimeSeconds, caps = []) {
2863
2935
  (*! noble-ed25519 - MIT License (c) 2019 Paul Miller (paulmillr.com) *)
2864
2936
  */
2865
2937
 
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 };
2938
+ 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, VenueIdentityChangedError, 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.7.1",
3
+ "version": "1.7.3",
4
4
  "description": "Typescript library for covia-ai",
5
5
  "packageManager": "pnpm@11.9.0",
6
6
  "main": "./dist/index.js",