@q9labsai/chalk-client 5.2.3 → 5.2.5

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.
Files changed (37) hide show
  1. package/README.md +1 -1
  2. package/dist/access/grant.d.ts +2 -1
  3. package/dist/access/manager.d.ts +1 -0
  4. package/dist/{chunk-IMMT22US.js → chunk-5YPQNMJE.js} +11 -0
  5. package/dist/{chunk-4ZUN55Z2.js → chunk-BUNSEDXL.js} +840 -185
  6. package/dist/{chunk-DWKTGBHR.js → chunk-FD25AMLG.js} +322 -206
  7. package/dist/{chunk-6LNRDKJF.js → chunk-LKNT6XFD.js} +1 -1
  8. package/dist/{chunk-GA3JDPFI.js → chunk-UMAE5GCV.js} +205 -5
  9. package/dist/client.d.ts +131 -0
  10. package/dist/connection/dependencies.d.ts +10 -1
  11. package/dist/connection/diagnostics.d.ts +4 -0
  12. package/dist/connection/episode-status.d.ts +7 -0
  13. package/dist/connection/index.d.ts +2 -0
  14. package/dist/connection/lifecycle.d.ts +2 -0
  15. package/dist/connection/report.d.ts +21 -0
  16. package/dist/effect.js +30 -4
  17. package/dist/generated/http-api.d.ts +129 -0
  18. package/dist/generated/schemas.d.ts +219 -0
  19. package/dist/index.js +5 -5
  20. package/dist/media/client.d.ts +1 -1
  21. package/dist/media/failure-diagnostics.d.ts +10 -0
  22. package/dist/media/index.js +1 -1
  23. package/dist/media/plane.d.ts +1 -0
  24. package/dist/media/types.d.ts +5 -1
  25. package/dist/public-invites/index.js +2 -2
  26. package/dist/server/access-refresh.d.cts +1 -1
  27. package/dist/server/access-refresh.d.ts +1 -1
  28. package/dist/server/index.cjs +15 -5
  29. package/dist/server/index.js +15 -5
  30. package/dist/server/types.d.cts +2 -1
  31. package/dist/server/types.d.ts +2 -1
  32. package/dist/space-client/media-projection-monitor.d.ts +26 -0
  33. package/dist/space-client/types.d.ts +4 -0
  34. package/dist/sync/index.js +1 -1
  35. package/dist/sync/v1-types.d.ts +3 -0
  36. package/dist/transport-diagnostics.d.ts +3 -0
  37. package/package.json +2 -2
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createChalkEffectClient,
3
3
  parseAccessGrant
4
- } from "./chunk-GA3JDPFI.js";
4
+ } from "./chunk-UMAE5GCV.js";
5
5
 
6
6
  // src/public-invites/client.ts
7
7
  import { Effect } from "effect";
@@ -243,6 +243,79 @@ var CloudflareSFUTracksRequestSchema = Schema.Struct({
243
243
  })
244
244
  )
245
245
  });
246
+ var ConnectionReportRequestSchema = Schema.Struct({
247
+ events: Schema.Array(
248
+ Schema.Struct({
249
+ attempt: Schema.optional(Schema.NullOr(Schema.Number)),
250
+ close_code: Schema.optional(Schema.NullOr(Schema.Number)),
251
+ code: Schema.optional(
252
+ Schema.Literals([
253
+ "invalid_state",
254
+ "invalid_access",
255
+ "access_unavailable",
256
+ "permission_denied",
257
+ "device_not_found",
258
+ "device_busy",
259
+ "device_constraint_invalid",
260
+ "media_capture_failed",
261
+ "sync_start_failed",
262
+ "state_digest_recovery_failed",
263
+ "sync_hello_timeout",
264
+ "media_start_failed",
265
+ "join_cleanup_unconfirmed",
266
+ "sync_recovery_exhausted",
267
+ "media_recovery_exhausted",
268
+ "command_rejected",
269
+ "leave_unconfirmed",
270
+ "episode_ended",
271
+ "unsupported_environment",
272
+ "internal_error",
273
+ "collaboration_unavailable",
274
+ "chat_cursor_reset_required",
275
+ "rate_limited",
276
+ "invalid_payload"
277
+ ])
278
+ ),
279
+ duration_ms: Schema.optional(Schema.NullOr(Schema.Number)),
280
+ elapsed_ms: Schema.Number,
281
+ event: Schema.Literals([
282
+ "space_join_span",
283
+ "state_changed",
284
+ "connection_failed",
285
+ "sync_connect_failed",
286
+ "sync_dial_timeout",
287
+ "access_refreshed",
288
+ "access_refresh_failed",
289
+ "recovery_attempt",
290
+ "recovery_succeeded",
291
+ "recovery_exhausted",
292
+ "cleanup_completed",
293
+ "cleanup_unconfirmed",
294
+ "sync_socket_open",
295
+ "sync_socket_close",
296
+ "sync_heartbeat_gap",
297
+ "media_state",
298
+ "media_http_error",
299
+ "media_projection_mismatch"
300
+ ]),
301
+ granted_audio: Schema.optional(Schema.Literals(["granted", "not_granted", "unknown"])),
302
+ granted_video: Schema.optional(Schema.Literals(["granted", "not_granted", "unknown"])),
303
+ heartbeat_gap_ms: Schema.optional(Schema.NullOr(Schema.Number)),
304
+ http_status: Schema.optional(Schema.NullOr(Schema.Number)),
305
+ media_error_kind: Schema.optional(Schema.Literals(["NotAllowedError", "NotReadableError", "NotFoundError", "OverconstrainedError", "AbortError", "SecurityError", "InvalidStateError", "OperationError", "NotSupportedError", "CloudflareSFUError", "network", "timeout", "unknown"])),
306
+ media_error_step: Schema.optional(Schema.Literals(["local_capture", "peer_connection", "access_refresh", "sfu_tracks", "sfu_close_tracks", "sfu_renegotiate", "sfu_publications"])),
307
+ outcome: Schema.optional(Schema.Literals(["started", "succeeded", "failed", "cancelled"])),
308
+ phase: Schema.optional(Schema.Literals(["idle", "connecting", "live", "recovering", "failed", "stopped", "new", "connected", "disconnected", "closed"])),
309
+ projection_state: Schema.optional(Schema.Literals(["on", "off"])),
310
+ publication_state: Schema.optional(Schema.Literals(["on", "off"])),
311
+ source: Schema.optional(Schema.Literals(["microphone", "camera"])),
312
+ state: Schema.optional(Schema.Literals(["idle", "joining", "live", "reconnecting", "leaving", "left", "failed"])),
313
+ step: Schema.optional(Schema.Literals(["join", "acquire_initial_media", "access_initialize", "create_media_client", "create_sync_client", "start_media", "start_sync", "wait_for_sync_live", "confirm_entered"]))
314
+ })
315
+ ).check(Schema.isMinLength(1), Schema.isMaxLength(64)),
316
+ trigger: Schema.Literals(["join_failed", "connection_lost", "recovery_exhausted", "media_projection_mismatch"]),
317
+ version: Schema.Literal(1)
318
+ });
246
319
  var CreateAPIKeyRequestSchema = Schema.Struct({
247
320
  expires_at: DateTimeStringSchema,
248
321
  name: Schema.String.check(Schema.isMinLength(1)),
@@ -410,6 +483,7 @@ var IntegrationActionIdSchema = Schema.String.check(Schema.isMinLength(1)).pipe(
410
483
  var IntegrationServiceIdSchema = Schema.String.check(Schema.isMinLength(1)).pipe(Schema.brand("IntegrationServiceId"));
411
484
  var IssueAccessGrantRequestSchema = Schema.Struct({
412
485
  current_media_token: Schema.optional(Schema.String.check(Schema.isMinLength(1))),
486
+ expected_media_connection_id: Schema.optional(Schema.NullOr(Schema.String.check(Schema.isMinLength(1)))),
413
487
  participant_generation: Schema.Number,
414
488
  replace_media_connection: Schema.Boolean
415
489
  });
@@ -428,6 +502,9 @@ var MembershipListSchema = Schema.Struct({
428
502
  memberships: Schema.Array(MembershipSchema),
429
503
  pagination: PaginationSchema
430
504
  });
505
+ var ParticipantEpisodeStatusSchema = Schema.Struct({
506
+ status: Schema.Literals(["active", "ending", "ended"])
507
+ });
431
508
  var ParticipantJoinCancellationSchema = Schema.Struct({
432
509
  cancelled: Schema.Boolean
433
510
  });
@@ -1318,6 +1395,18 @@ var GetEpisodeAttendance429ResponseHeadersSchema = Schema.Struct({
1318
1395
  "X-RateLimit-Limit": RateLimitLimitHeaderSchema,
1319
1396
  "X-RateLimit-Remaining": RateLimitRemainingHeaderSchema
1320
1397
  });
1398
+ var GetParticipantEpisodeStatusPathParamsSchema = Schema.Struct({
1399
+ episode_id: EpisodeIdSchema,
1400
+ participant_id: ParticipantIdSchema,
1401
+ space_id: SpaceIdSchema,
1402
+ tenant_id: TenantIdSchema
1403
+ });
1404
+ var GetParticipantEpisodeStatusResponseSchema = ParticipantEpisodeStatusSchema;
1405
+ var GetParticipantEpisodeStatus429ResponseHeadersSchema = Schema.Struct({
1406
+ "Retry-After": RetryAfterHeaderSchema,
1407
+ "X-RateLimit-Limit": RateLimitLimitHeaderSchema,
1408
+ "X-RateLimit-Remaining": RateLimitRemainingHeaderSchema
1409
+ });
1321
1410
  var GetProblemReportAvailabilityPathParamsSchema = Schema.Struct({
1322
1411
  tenant_id: TenantIdSchema
1323
1412
  });
@@ -1687,6 +1776,15 @@ var RenegotiateCloudflareSFU429ResponseHeadersSchema = Schema.Struct({
1687
1776
  "X-RateLimit-Limit": RateLimitLimitHeaderSchema,
1688
1777
  "X-RateLimit-Remaining": RateLimitRemainingHeaderSchema
1689
1778
  });
1779
+ var ReportConnectionFailurePathParamsSchema = Schema.Struct({
1780
+ tenant_id: TenantIdSchema
1781
+ });
1782
+ var ReportConnectionFailureRequestBodySchema = ConnectionReportRequestSchema;
1783
+ var ReportConnectionFailure429ResponseHeadersSchema = Schema.Struct({
1784
+ "Retry-After": RetryAfterHeaderSchema,
1785
+ "X-RateLimit-Limit": RateLimitLimitHeaderSchema,
1786
+ "X-RateLimit-Remaining": RateLimitRemainingHeaderSchema
1787
+ });
1690
1788
  var RequestRecordingExportPathParamsSchema = Schema.Struct({
1691
1789
  recording_id: RecordingIdSchema,
1692
1790
  tenant_id: TenantIdSchema
@@ -2815,6 +2913,25 @@ var ParticipantInvalidIdErrorSchema = ParticipantInvalidIdErrorWireSchema.pipe(
2815
2913
  encode: SchemaGetter.transform((error) => ({ error: error.error }))
2816
2914
  })
2817
2915
  );
2916
+ var ParticipantMediaReplacementPendingError = class extends Schema.TaggedErrorClass()("ParticipantMediaReplacementPendingError", {
2917
+ error: Schema.Struct({
2918
+ code: Schema.Literal("participant.media_replacement_pending"),
2919
+ message: Schema.String
2920
+ })
2921
+ }) {
2922
+ };
2923
+ var ParticipantMediaReplacementPendingErrorWireSchema = Schema.Struct({
2924
+ error: Schema.Struct({
2925
+ code: Schema.Literal("participant.media_replacement_pending"),
2926
+ message: Schema.String
2927
+ })
2928
+ });
2929
+ var ParticipantMediaReplacementPendingErrorSchema = ParticipantMediaReplacementPendingErrorWireSchema.pipe(
2930
+ Schema.decodeTo(ParticipantMediaReplacementPendingError, {
2931
+ decode: SchemaGetter.transform((wire) => ({ _tag: "ParticipantMediaReplacementPendingError", ...wire })),
2932
+ encode: SchemaGetter.transform((error) => ({ error: error.error }))
2933
+ })
2934
+ );
2818
2935
  var ParticipantNotActiveError = class extends Schema.TaggedErrorClass()("ParticipantNotActiveError", {
2819
2936
  error: Schema.Struct({
2820
2937
  code: Schema.Literal("participant.not_active"),
@@ -4416,6 +4533,18 @@ var GetEpisodeErrorSchema = Schema.Union([
4416
4533
  SpaceNotFoundErrorSchema,
4417
4534
  TenantInvalidIdErrorSchema
4418
4535
  ]);
4536
+ var GetParticipantEpisodeStatusErrorSchema = Schema.Union([
4537
+ AccessForbiddenErrorSchema,
4538
+ AccessUnauthenticatedErrorSchema,
4539
+ EpisodeInvalidIdErrorSchema,
4540
+ EpisodeNotFoundErrorSchema,
4541
+ ParticipantInvalidIdErrorSchema,
4542
+ RequestRateLimitedErrorSchema,
4543
+ ServiceInternalErrorSchema,
4544
+ ServiceUnavailableErrorSchema,
4545
+ SpaceInvalidIdErrorSchema,
4546
+ TenantInvalidIdErrorSchema
4547
+ ]);
4419
4548
  var GetProblemReportAvailabilityErrorSchema = TenantInvalidIdErrorSchema;
4420
4549
  var GetRecordingErrorSchema = Schema.Union([AccessForbiddenErrorSchema, AccessUnauthenticatedErrorSchema, RecordingInvalidIdErrorSchema, RecordingNotFoundErrorSchema, ServiceInternalErrorSchema, ServiceUnavailableErrorSchema, TenantInvalidIdErrorSchema]);
4421
4550
  var GetSpaceErrorSchema = Schema.Union([AccessForbiddenErrorSchema, AccessUnauthenticatedErrorSchema, ServiceInternalErrorSchema, ServiceUnavailableErrorSchema, SpaceInvalidIdErrorSchema, SpaceNotFoundErrorSchema, TenantInvalidIdErrorSchema]);
@@ -4547,6 +4676,7 @@ var IssueAccessGrantErrorSchema = Schema.Union([
4547
4676
  ParticipantConnectionSupersededErrorSchema,
4548
4677
  ParticipantGenerationMismatchErrorSchema,
4549
4678
  ParticipantInvalidIdErrorSchema,
4679
+ ParticipantMediaReplacementPendingErrorSchema,
4550
4680
  ParticipantNotFoundErrorSchema,
4551
4681
  RequestInvalidErrorSchema,
4552
4682
  RequestPayloadTooLargeErrorSchema,
@@ -4794,6 +4924,16 @@ var RenegotiateCloudflareSFUErrorSchema = Schema.Union([
4794
4924
  SpaceInvalidIdErrorSchema,
4795
4925
  TenantInvalidIdErrorSchema
4796
4926
  ]);
4927
+ var ReportConnectionFailureErrorSchema = Schema.Union([
4928
+ AccessForbiddenErrorSchema,
4929
+ AccessUnauthenticatedErrorSchema,
4930
+ RequestInvalidErrorSchema,
4931
+ RequestPayloadTooLargeErrorSchema,
4932
+ RequestRateLimitedErrorSchema,
4933
+ ServiceInternalErrorSchema,
4934
+ ServiceUnavailableErrorSchema,
4935
+ TenantInvalidIdErrorSchema
4936
+ ]);
4797
4937
  var RequestRecordingExportErrorSchema = Schema.Union([
4798
4938
  AccessForbiddenErrorSchema,
4799
4939
  AccessUnauthenticatedErrorSchema,
@@ -5064,6 +5204,7 @@ var ChalkOperationPolicies = {
5064
5204
  findTenantByExternalID: { rateLimit: { limit: 300, policy: "v1.authenticated.read", windowSeconds: 60 } },
5065
5205
  getEpisode: { rateLimit: { limit: 300, policy: "v1.authenticated.read", windowSeconds: 60 } },
5066
5206
  getEpisodeAttendance: { rateLimit: { limit: 300, policy: "v1.authenticated.read", windowSeconds: 60 } },
5207
+ getParticipantEpisodeStatus: { rateLimit: { limit: 300, policy: "v1.authenticated.read", windowSeconds: 60 } },
5067
5208
  getSpacePublicInvite: { rateLimit: { limit: 300, policy: "v1.authenticated.read", windowSeconds: 60 } },
5068
5209
  getSpacePublicInviteArrival: { rateLimit: { limit: 300, policy: "v1.authenticated.read", windowSeconds: 60 } },
5069
5210
  getTenant: { rateLimit: { limit: 300, policy: "v1.authenticated.read", windowSeconds: 60 } },
@@ -5087,6 +5228,7 @@ var ChalkOperationPolicies = {
5087
5228
  refreshSpacePublicInviteAccess: { maxBodyBytes: 1048576, rateLimit: { limit: 60, policy: "v1.authenticated.write", windowSeconds: 60 } },
5088
5229
  removeEpisodeParticipant: { maxBodyBytes: 1048576, rateLimit: { limit: 60, policy: "v1.authenticated.write", windowSeconds: 60 } },
5089
5230
  renegotiateCloudflareSFU: { maxBodyBytes: 1048576, rateLimit: { limit: 60, policy: "v1.authenticated.write", windowSeconds: 60 } },
5231
+ reportConnectionFailure: { maxBodyBytes: 32768, rateLimit: { limit: 6, policy: "connection_reports.participant", windowSeconds: 600 } },
5090
5232
  requestRecordingExport: { maxBodyBytes: 1048576, rateLimit: { limit: 60, policy: "v1.authenticated.write", windowSeconds: 60 } },
5091
5233
  requestTranscript: { maxBodyBytes: 1048576, rateLimit: { limit: 60, policy: "v1.authenticated.write", windowSeconds: 60 } },
5092
5234
  restoreSpace: { rateLimit: { limit: 60, policy: "v1.authenticated.write", windowSeconds: 60 } },
@@ -5390,6 +5532,7 @@ var defaultGroup = HttpApiGroup.make("default").add(
5390
5532
  ParticipantNotFoundErrorSchema.pipe(HttpApiSchema.status(404)),
5391
5533
  ParticipantConnectionSupersededErrorSchema.pipe(HttpApiSchema.status(409)),
5392
5534
  ParticipantGenerationMismatchErrorSchema.pipe(HttpApiSchema.status(409)),
5535
+ ParticipantMediaReplacementPendingErrorSchema.pipe(HttpApiSchema.status(409)),
5393
5536
  RequestPayloadTooLargeErrorSchema.pipe(HttpApiSchema.status(413)),
5394
5537
  RequestRateLimitedErrorSchema.pipe(HttpApiSchema.status(429)),
5395
5538
  ServiceInternalErrorSchema.pipe(HttpApiSchema.status(500)),
@@ -5528,6 +5671,22 @@ var defaultGroup = HttpApiGroup.make("default").add(
5528
5671
  ServiceUnavailableErrorSchema.pipe(HttpApiSchema.status(503))
5529
5672
  ]
5530
5673
  })
5674
+ ).add(
5675
+ HttpApiEndpoint.post("reportConnectionFailure", "/v1/tenants/:tenant_id/connection-reports", {
5676
+ params: ReportConnectionFailurePathParamsSchema,
5677
+ payload: ReportConnectionFailureRequestBodySchema,
5678
+ success: HttpApiSchema.Empty(204).pipe(HttpApiSchema.status(204)),
5679
+ error: [
5680
+ RequestInvalidErrorSchema.pipe(HttpApiSchema.status(400)),
5681
+ TenantInvalidIdErrorSchema.pipe(HttpApiSchema.status(400)),
5682
+ AccessUnauthenticatedErrorSchema.pipe(HttpApiSchema.status(401)),
5683
+ AccessForbiddenErrorSchema.pipe(HttpApiSchema.status(403)),
5684
+ RequestPayloadTooLargeErrorSchema.pipe(HttpApiSchema.status(413)),
5685
+ RequestRateLimitedErrorSchema.pipe(HttpApiSchema.status(429)),
5686
+ ServiceInternalErrorSchema.pipe(HttpApiSchema.status(500)),
5687
+ ServiceUnavailableErrorSchema.pipe(HttpApiSchema.status(503))
5688
+ ]
5689
+ })
5531
5690
  ).add(
5532
5691
  HttpApiEndpoint.delete("revokeAPIKey", "/v1/tenants/:tenant_id/api-keys/:api_key_id", {
5533
5692
  params: RevokeAPIKeyPathParamsSchema,
@@ -5810,6 +5969,23 @@ var episodesGroup = HttpApiGroup.make("episodes").add(
5810
5969
  ServiceUnavailableErrorSchema.pipe(HttpApiSchema.status(503))
5811
5970
  ]
5812
5971
  })
5972
+ ).add(
5973
+ HttpApiEndpoint.get("getParticipantEpisodeStatus", "/v1/tenants/:tenant_id/spaces/:space_id/episodes/:episode_id/participants/:participant_id/episode-status", {
5974
+ params: GetParticipantEpisodeStatusPathParamsSchema,
5975
+ success: GetParticipantEpisodeStatusResponseSchema.pipe(HttpApiSchema.status(200)),
5976
+ error: [
5977
+ EpisodeInvalidIdErrorSchema.pipe(HttpApiSchema.status(400)),
5978
+ ParticipantInvalidIdErrorSchema.pipe(HttpApiSchema.status(400)),
5979
+ SpaceInvalidIdErrorSchema.pipe(HttpApiSchema.status(400)),
5980
+ TenantInvalidIdErrorSchema.pipe(HttpApiSchema.status(400)),
5981
+ AccessUnauthenticatedErrorSchema.pipe(HttpApiSchema.status(401)),
5982
+ AccessForbiddenErrorSchema.pipe(HttpApiSchema.status(403)),
5983
+ EpisodeNotFoundErrorSchema.pipe(HttpApiSchema.status(404)),
5984
+ RequestRateLimitedErrorSchema.pipe(HttpApiSchema.status(429)),
5985
+ ServiceInternalErrorSchema.pipe(HttpApiSchema.status(500)),
5986
+ ServiceUnavailableErrorSchema.pipe(HttpApiSchema.status(503))
5987
+ ]
5988
+ })
5813
5989
  ).add(
5814
5990
  HttpApiEndpoint.post("issueEpisodeParticipantSyncToken", "/v1/tenants/:tenant_id/spaces/:space_id/episodes/:episode_id/participants/:participant_id/sync-token", {
5815
5991
  params: IssueEpisodeParticipantSyncTokenPathParamsSchema,
@@ -6696,11 +6872,13 @@ function decodeBase64Url(value) {
6696
6872
  // src/access/grant.ts
6697
6873
  var accessGrantBrand = /* @__PURE__ */ Symbol("AccessGrant");
6698
6874
  var AccessGrantError = class extends TypeError {
6699
- code = "access.invalid";
6700
- constructor(message = "Access grant is invalid") {
6875
+ constructor(message = "Access grant is invalid", reason) {
6701
6876
  super(message);
6877
+ this.reason = reason;
6702
6878
  this.name = "AccessGrantError";
6703
6879
  }
6880
+ reason;
6881
+ code = "access.invalid";
6704
6882
  };
6705
6883
  var AccessUnavailableError = class extends Error {
6706
6884
  code = "access.unavailable";
@@ -6709,12 +6887,21 @@ var AccessUnavailableError = class extends Error {
6709
6887
  this.name = "AccessUnavailableError";
6710
6888
  }
6711
6889
  };
6712
- function requireSuccessfulResponse(response) {
6890
+ async function requireSuccessfulResponse(response) {
6713
6891
  if (response.ok) return;
6714
6892
  const status = response.status;
6715
6893
  if (status === 408 || status === 425 || status === 429 || status >= 500) throw new AccessUnavailableError(status);
6894
+ if (status === 409) {
6895
+ const body = await response.json().catch(() => null);
6896
+ const code = conflictResponseCode(body);
6897
+ if (code === "participant.media_replacement_pending") throw new AccessUnavailableError(status);
6898
+ if (code === "participant.connection_superseded") throw new AccessGrantError(void 0, "connection_superseded");
6899
+ }
6716
6900
  throw new AccessGrantError(`Access grant request failed with HTTP ${status}`);
6717
6901
  }
6902
+ function conflictResponseCode(body) {
6903
+ return typeof body === "object" && body !== null && "error" in body && typeof body.error === "object" && body.error !== null && "code" in body.error ? body.error.code : void 0;
6904
+ }
6718
6905
  function parseParsedAccessGrant(value) {
6719
6906
  if (!isRecord(value)) throw new AccessGrantError();
6720
6907
  const subject = parseSubject(value.subject);
@@ -6751,7 +6938,7 @@ function accessGrantFromParsed(value) {
6751
6938
  }
6752
6939
  async function requireParsedAccessGrant(value) {
6753
6940
  if (typeof Response !== "undefined" && value instanceof Response) {
6754
- requireSuccessfulResponse(value);
6941
+ await requireSuccessfulResponse(value);
6755
6942
  try {
6756
6943
  return parseParsedAccessGrant(await value.json());
6757
6944
  } catch (error) {
@@ -6763,7 +6950,7 @@ async function requireParsedAccessGrant(value) {
6763
6950
  }
6764
6951
  async function requireAccessGrant(value) {
6765
6952
  if (typeof Response !== "undefined" && value instanceof Response) {
6766
- requireSuccessfulResponse(value);
6953
+ await requireSuccessfulResponse(value);
6767
6954
  try {
6768
6955
  return parseAccessGrant(await value.json());
6769
6956
  } catch (error) {
@@ -6877,6 +7064,7 @@ export {
6877
7064
  CloudflareSFURenegotiateResponseSchema,
6878
7065
  CloudflareSFUTracksAPIResponseSchema,
6879
7066
  CloudflareSFUTracksRequestSchema,
7067
+ ConnectionReportRequestSchema,
6880
7068
  CreateAPIKeyRequestSchema,
6881
7069
  CreateEpisodeRequestSchema,
6882
7070
  CreateMembershipRequestSchema,
@@ -6905,6 +7093,7 @@ export {
6905
7093
  MembershipIdSchema,
6906
7094
  MembershipSchema,
6907
7095
  MembershipListSchema,
7096
+ ParticipantEpisodeStatusSchema,
6908
7097
  ParticipantJoinCancellationSchema,
6909
7098
  ParticipantLifecycleSchema,
6910
7099
  ParticipantRemovalSchema,
@@ -7061,6 +7250,9 @@ export {
7061
7250
  GetEpisodeAttendancePathParamsSchema,
7062
7251
  GetEpisodeAttendanceResponseSchema,
7063
7252
  GetEpisodeAttendance429ResponseHeadersSchema,
7253
+ GetParticipantEpisodeStatusPathParamsSchema,
7254
+ GetParticipantEpisodeStatusResponseSchema,
7255
+ GetParticipantEpisodeStatus429ResponseHeadersSchema,
7064
7256
  GetProblemReportAvailabilityPathParamsSchema,
7065
7257
  GetProblemReportAvailabilityResponseSchema,
7066
7258
  GetRecordingPathParamsSchema,
@@ -7174,6 +7366,9 @@ export {
7174
7366
  RenegotiateCloudflareSFURequestBodySchema,
7175
7367
  RenegotiateCloudflareSFUResponseSchema,
7176
7368
  RenegotiateCloudflareSFU429ResponseHeadersSchema,
7369
+ ReportConnectionFailurePathParamsSchema,
7370
+ ReportConnectionFailureRequestBodySchema,
7371
+ ReportConnectionFailure429ResponseHeadersSchema,
7177
7372
  RequestRecordingExportPathParamsSchema,
7178
7373
  RequestRecordingExportRequestBodySchema,
7179
7374
  RequestRecordingExportResponseSchema,
@@ -7385,6 +7580,9 @@ export {
7385
7580
  ParticipantInvalidIdError,
7386
7581
  ParticipantInvalidIdErrorWireSchema,
7387
7582
  ParticipantInvalidIdErrorSchema,
7583
+ ParticipantMediaReplacementPendingError,
7584
+ ParticipantMediaReplacementPendingErrorWireSchema,
7585
+ ParticipantMediaReplacementPendingErrorSchema,
7388
7586
  ParticipantNotActiveError,
7389
7587
  ParticipantNotActiveErrorWireSchema,
7390
7588
  ParticipantNotActiveErrorSchema,
@@ -7606,6 +7804,7 @@ export {
7606
7804
  GetChatAttachmentDownloadErrorSchema,
7607
7805
  GetEpisodeAttendanceErrorSchema,
7608
7806
  GetEpisodeErrorSchema,
7807
+ GetParticipantEpisodeStatusErrorSchema,
7609
7808
  GetProblemReportAvailabilityErrorSchema,
7610
7809
  GetRecordingErrorSchema,
7611
7810
  GetSpaceErrorSchema,
@@ -7642,6 +7841,7 @@ export {
7642
7841
  RefreshSpacePublicInviteAccessErrorSchema,
7643
7842
  RemoveEpisodeParticipantErrorSchema,
7644
7843
  RenegotiateCloudflareSFUErrorSchema,
7844
+ ReportConnectionFailureErrorSchema,
7645
7845
  RequestRecordingExportErrorSchema,
7646
7846
  RequestTranscriptErrorSchema,
7647
7847
  RestoreSpaceErrorSchema,
package/dist/client.d.ts CHANGED
@@ -1065,6 +1065,7 @@ export declare const createChalkEffectClient: (options: ChalkEffectClientOptions
1065
1065
  readonly tenant_id: import("effect/Schema").brand<import("effect/Schema").String, "TenantId">;
1066
1066
  }>>, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
1067
1067
  readonly current_media_token: import("effect/Schema").optional<import("effect/Schema").String>;
1068
+ readonly expected_media_connection_id: import("effect/Schema").optional<import("effect/Schema").NullOr<import("effect/Schema").String>>;
1068
1069
  readonly participant_generation: import("effect/Schema").Number;
1069
1070
  readonly replace_media_connection: import("effect/Schema").Boolean;
1070
1071
  }>>, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
@@ -1186,6 +1187,11 @@ export declare const createChalkEffectClient: (options: ChalkEffectClientOptions
1186
1187
  readonly code: import("effect/Schema").Literal<"participant.invalid_id">;
1187
1188
  readonly message: import("effect/Schema").String;
1188
1189
  }>;
1190
+ }>, never, never> | import("effect/Schema").decodeTo<typeof import("./effect").ParticipantMediaReplacementPendingError, import("effect/Schema").Struct<{
1191
+ readonly error: import("effect/Schema").Struct<{
1192
+ readonly code: import("effect/Schema").Literal<"participant.media_replacement_pending">;
1193
+ readonly message: import("effect/Schema").String;
1194
+ }>;
1189
1195
  }>, never, never> | import("effect/Schema").decodeTo<typeof import("./effect").ParticipantNotFoundError, import("effect/Schema").Struct<{
1190
1196
  readonly error: import("effect/Schema").Struct<{
1191
1197
  readonly code: import("effect/Schema").Literal<"participant.not_found">;
@@ -1761,6 +1767,73 @@ export declare const createChalkEffectClient: (options: ChalkEffectClientOptions
1761
1767
  readonly message: import("effect/Schema").String;
1762
1768
  }>;
1763
1769
  }>, never, never>>, never, never>, never, never>;
1770
+ readonly reportConnectionFailure: HttpApiClient.Client.Method<import("effect/unstable/httpapi/HttpApiEndpoint").HttpApiEndpoint<"reportConnectionFailure", "POST", "/v1/tenants/:tenant_id/connection-reports", import("effect/Schema").toCodecStringTree<import("effect/Schema").Struct<{
1771
+ readonly tenant_id: import("effect/Schema").brand<import("effect/Schema").String, "TenantId">;
1772
+ }>>, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
1773
+ readonly events: import("effect/Schema").$Array<import("effect/Schema").Struct<{
1774
+ readonly attempt: import("effect/Schema").optional<import("effect/Schema").NullOr<import("effect/Schema").Number>>;
1775
+ readonly close_code: import("effect/Schema").optional<import("effect/Schema").NullOr<import("effect/Schema").Number>>;
1776
+ readonly code: import("effect/Schema").optional<import("effect/Schema").Literals<readonly ["invalid_state", "invalid_access", "access_unavailable", "permission_denied", "device_not_found", "device_busy", "device_constraint_invalid", "media_capture_failed", "sync_start_failed", "state_digest_recovery_failed", "sync_hello_timeout", "media_start_failed", "join_cleanup_unconfirmed", "sync_recovery_exhausted", "media_recovery_exhausted", "command_rejected", "leave_unconfirmed", "episode_ended", "unsupported_environment", "internal_error", "collaboration_unavailable", "chat_cursor_reset_required", "rate_limited", "invalid_payload"]>>;
1777
+ readonly duration_ms: import("effect/Schema").optional<import("effect/Schema").NullOr<import("effect/Schema").Number>>;
1778
+ readonly elapsed_ms: import("effect/Schema").Number;
1779
+ readonly event: import("effect/Schema").Literals<readonly ["space_join_span", "state_changed", "connection_failed", "sync_connect_failed", "sync_dial_timeout", "access_refreshed", "access_refresh_failed", "recovery_attempt", "recovery_succeeded", "recovery_exhausted", "cleanup_completed", "cleanup_unconfirmed", "sync_socket_open", "sync_socket_close", "sync_heartbeat_gap", "media_state", "media_http_error", "media_projection_mismatch"]>;
1780
+ readonly granted_audio: import("effect/Schema").optional<import("effect/Schema").Literals<readonly ["granted", "not_granted", "unknown"]>>;
1781
+ readonly granted_video: import("effect/Schema").optional<import("effect/Schema").Literals<readonly ["granted", "not_granted", "unknown"]>>;
1782
+ readonly heartbeat_gap_ms: import("effect/Schema").optional<import("effect/Schema").NullOr<import("effect/Schema").Number>>;
1783
+ readonly http_status: import("effect/Schema").optional<import("effect/Schema").NullOr<import("effect/Schema").Number>>;
1784
+ readonly media_error_kind: import("effect/Schema").optional<import("effect/Schema").Literals<readonly ["NotAllowedError", "NotReadableError", "NotFoundError", "OverconstrainedError", "AbortError", "SecurityError", "InvalidStateError", "OperationError", "NotSupportedError", "CloudflareSFUError", "network", "timeout", "unknown"]>>;
1785
+ readonly media_error_step: import("effect/Schema").optional<import("effect/Schema").Literals<readonly ["local_capture", "peer_connection", "access_refresh", "sfu_tracks", "sfu_close_tracks", "sfu_renegotiate", "sfu_publications"]>>;
1786
+ readonly outcome: import("effect/Schema").optional<import("effect/Schema").Literals<readonly ["started", "succeeded", "failed", "cancelled"]>>;
1787
+ readonly phase: import("effect/Schema").optional<import("effect/Schema").Literals<readonly ["idle", "connecting", "live", "recovering", "failed", "stopped", "new", "connected", "disconnected", "closed"]>>;
1788
+ readonly projection_state: import("effect/Schema").optional<import("effect/Schema").Literals<readonly ["on", "off"]>>;
1789
+ readonly publication_state: import("effect/Schema").optional<import("effect/Schema").Literals<readonly ["on", "off"]>>;
1790
+ readonly source: import("effect/Schema").optional<import("effect/Schema").Literals<readonly ["microphone", "camera"]>>;
1791
+ readonly state: import("effect/Schema").optional<import("effect/Schema").Literals<readonly ["idle", "joining", "live", "reconnecting", "leaving", "left", "failed"]>>;
1792
+ readonly step: import("effect/Schema").optional<import("effect/Schema").Literals<readonly ["join", "acquire_initial_media", "access_initialize", "create_media_client", "create_sync_client", "start_media", "start_sync", "wait_for_sync_live", "confirm_entered"]>>;
1793
+ }>>;
1794
+ readonly trigger: import("effect/Schema").Literals<readonly ["join_failed", "connection_lost", "recovery_exhausted", "media_projection_mismatch"]>;
1795
+ readonly version: import("effect/Schema").Literal<1>;
1796
+ }>>, never, import("effect/Schema").toCodecJson<import("effect/Schema").Void>, import("effect/Schema").toCodecJson<import("effect/Schema").decodeTo<typeof import("./effect").AccessForbiddenError, import("effect/Schema").Struct<{
1797
+ readonly error: import("effect/Schema").Struct<{
1798
+ readonly code: import("effect/Schema").Literal<"access.forbidden">;
1799
+ readonly message: import("effect/Schema").String;
1800
+ }>;
1801
+ }>, never, never> | import("effect/Schema").decodeTo<typeof import("./effect").AccessUnauthenticatedError, import("effect/Schema").Struct<{
1802
+ readonly error: import("effect/Schema").Struct<{
1803
+ readonly code: import("effect/Schema").Literal<"access.unauthenticated">;
1804
+ readonly message: import("effect/Schema").String;
1805
+ }>;
1806
+ }>, never, never> | import("effect/Schema").decodeTo<typeof import("./effect").RequestInvalidError, import("effect/Schema").Struct<{
1807
+ readonly error: import("effect/Schema").Struct<{
1808
+ readonly code: import("effect/Schema").Literal<"request.invalid">;
1809
+ readonly message: import("effect/Schema").String;
1810
+ }>;
1811
+ }>, never, never> | import("effect/Schema").decodeTo<typeof import("./effect").RequestPayloadTooLargeError, import("effect/Schema").Struct<{
1812
+ readonly error: import("effect/Schema").Struct<{
1813
+ readonly code: import("effect/Schema").Literal<"request.payload_too_large">;
1814
+ readonly message: import("effect/Schema").String;
1815
+ }>;
1816
+ }>, never, never> | import("effect/Schema").decodeTo<typeof import("./effect").RequestRateLimitedError, import("effect/Schema").Struct<{
1817
+ readonly error: import("effect/Schema").Struct<{
1818
+ readonly code: import("effect/Schema").Literal<"request.rate_limited">;
1819
+ readonly message: import("effect/Schema").String;
1820
+ }>;
1821
+ }>, never, never> | import("effect/Schema").decodeTo<typeof import("./effect").ServiceInternalError, import("effect/Schema").Struct<{
1822
+ readonly error: import("effect/Schema").Struct<{
1823
+ readonly code: import("effect/Schema").Literal<"service.internal_error">;
1824
+ readonly message: import("effect/Schema").String;
1825
+ }>;
1826
+ }>, never, never> | import("effect/Schema").decodeTo<typeof import("./effect").ServiceUnavailableError, import("effect/Schema").Struct<{
1827
+ readonly error: import("effect/Schema").Struct<{
1828
+ readonly code: import("effect/Schema").Literal<"service.unavailable">;
1829
+ readonly message: import("effect/Schema").String;
1830
+ }>;
1831
+ }>, never, never> | import("effect/Schema").decodeTo<typeof import("./effect").TenantInvalidIdError, import("effect/Schema").Struct<{
1832
+ readonly error: import("effect/Schema").Struct<{
1833
+ readonly code: import("effect/Schema").Literal<"tenant.invalid_id">;
1834
+ readonly message: import("effect/Schema").String;
1835
+ }>;
1836
+ }>, never, never>>, never, never>, never, never>;
1764
1837
  readonly revokeAPIKey: HttpApiClient.Client.Method<import("effect/unstable/httpapi/HttpApiEndpoint").HttpApiEndpoint<"revokeAPIKey", "DELETE", "/v1/tenants/:tenant_id/api-keys/:api_key_id", import("effect/Schema").toCodecStringTree<import("effect/Schema").Struct<{
1765
1838
  readonly api_key_id: import("effect/Schema").brand<import("effect/Schema").String, "UUID">;
1766
1839
  readonly tenant_id: import("effect/Schema").brand<import("effect/Schema").String, "TenantId">;
@@ -2920,6 +2993,64 @@ export declare const createChalkEffectClient: (options: ChalkEffectClientOptions
2920
2993
  readonly message: import("effect/Schema").String;
2921
2994
  }>;
2922
2995
  }>, never, never>>, never, never>, never, never>;
2996
+ readonly getParticipantEpisodeStatus: HttpApiClient.Client.Method<import("effect/unstable/httpapi/HttpApiEndpoint").HttpApiEndpoint<"getParticipantEpisodeStatus", "GET", "/v1/tenants/:tenant_id/spaces/:space_id/episodes/:episode_id/participants/:participant_id/episode-status", import("effect/Schema").toCodecStringTree<import("effect/Schema").Struct<{
2997
+ readonly episode_id: import("effect/Schema").brand<import("effect/Schema").String, "EpisodeId">;
2998
+ readonly participant_id: import("effect/Schema").brand<import("effect/Schema").String, "ParticipantId">;
2999
+ readonly space_id: import("effect/Schema").brand<import("effect/Schema").String, "SpaceId">;
3000
+ readonly tenant_id: import("effect/Schema").brand<import("effect/Schema").String, "TenantId">;
3001
+ }>>, never, never, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
3002
+ readonly status: import("effect/Schema").Literals<readonly ["active", "ending", "ended"]>;
3003
+ }>>, import("effect/Schema").toCodecJson<import("effect/Schema").decodeTo<typeof import("./effect").AccessForbiddenError, import("effect/Schema").Struct<{
3004
+ readonly error: import("effect/Schema").Struct<{
3005
+ readonly code: import("effect/Schema").Literal<"access.forbidden">;
3006
+ readonly message: import("effect/Schema").String;
3007
+ }>;
3008
+ }>, never, never> | import("effect/Schema").decodeTo<typeof import("./effect").AccessUnauthenticatedError, import("effect/Schema").Struct<{
3009
+ readonly error: import("effect/Schema").Struct<{
3010
+ readonly code: import("effect/Schema").Literal<"access.unauthenticated">;
3011
+ readonly message: import("effect/Schema").String;
3012
+ }>;
3013
+ }>, never, never> | import("effect/Schema").decodeTo<typeof import("./effect").EpisodeInvalidIdError, import("effect/Schema").Struct<{
3014
+ readonly error: import("effect/Schema").Struct<{
3015
+ readonly code: import("effect/Schema").Literal<"episode.invalid_id">;
3016
+ readonly message: import("effect/Schema").String;
3017
+ }>;
3018
+ }>, never, never> | import("effect/Schema").decodeTo<typeof import("./effect").EpisodeNotFoundError, import("effect/Schema").Struct<{
3019
+ readonly error: import("effect/Schema").Struct<{
3020
+ readonly code: import("effect/Schema").Literal<"episode.not_found">;
3021
+ readonly message: import("effect/Schema").String;
3022
+ }>;
3023
+ }>, never, never> | import("effect/Schema").decodeTo<typeof import("./effect").ParticipantInvalidIdError, import("effect/Schema").Struct<{
3024
+ readonly error: import("effect/Schema").Struct<{
3025
+ readonly code: import("effect/Schema").Literal<"participant.invalid_id">;
3026
+ readonly message: import("effect/Schema").String;
3027
+ }>;
3028
+ }>, never, never> | import("effect/Schema").decodeTo<typeof import("./effect").RequestRateLimitedError, import("effect/Schema").Struct<{
3029
+ readonly error: import("effect/Schema").Struct<{
3030
+ readonly code: import("effect/Schema").Literal<"request.rate_limited">;
3031
+ readonly message: import("effect/Schema").String;
3032
+ }>;
3033
+ }>, never, never> | import("effect/Schema").decodeTo<typeof import("./effect").ServiceInternalError, import("effect/Schema").Struct<{
3034
+ readonly error: import("effect/Schema").Struct<{
3035
+ readonly code: import("effect/Schema").Literal<"service.internal_error">;
3036
+ readonly message: import("effect/Schema").String;
3037
+ }>;
3038
+ }>, never, never> | import("effect/Schema").decodeTo<typeof import("./effect").ServiceUnavailableError, import("effect/Schema").Struct<{
3039
+ readonly error: import("effect/Schema").Struct<{
3040
+ readonly code: import("effect/Schema").Literal<"service.unavailable">;
3041
+ readonly message: import("effect/Schema").String;
3042
+ }>;
3043
+ }>, never, never> | import("effect/Schema").decodeTo<typeof import("./effect").SpaceInvalidIdError, import("effect/Schema").Struct<{
3044
+ readonly error: import("effect/Schema").Struct<{
3045
+ readonly code: import("effect/Schema").Literal<"space.invalid_id">;
3046
+ readonly message: import("effect/Schema").String;
3047
+ }>;
3048
+ }>, never, never> | import("effect/Schema").decodeTo<typeof import("./effect").TenantInvalidIdError, import("effect/Schema").Struct<{
3049
+ readonly error: import("effect/Schema").Struct<{
3050
+ readonly code: import("effect/Schema").Literal<"tenant.invalid_id">;
3051
+ readonly message: import("effect/Schema").String;
3052
+ }>;
3053
+ }>, never, never>>, never, never>, never, never>;
2923
3054
  readonly issueEpisodeParticipantSyncToken: HttpApiClient.Client.Method<import("effect/unstable/httpapi/HttpApiEndpoint").HttpApiEndpoint<"issueEpisodeParticipantSyncToken", "POST", "/v1/tenants/:tenant_id/spaces/:space_id/episodes/:episode_id/participants/:participant_id/sync-token", import("effect/Schema").toCodecStringTree<import("effect/Schema").Struct<{
2924
3055
  readonly episode_id: import("effect/Schema").brand<import("effect/Schema").String, "EpisodeId">;
2925
3056
  readonly participant_id: import("effect/Schema").brand<import("effect/Schema").String, "ParticipantId">;
@@ -1,3 +1,5 @@
1
+ import type { ParticipantEpisodeStatus } from "../generated/schemas";
2
+ import type { ConnectionReporter, ConnectionReportTransportEvent } from "./report";
1
3
  import type { ClientMediaPlane, CloudflareSFUBootstrap, ConnectionMediaSnapshot } from "../media";
2
4
  import type { ChalkChatFileTransport } from "../chat-files";
3
5
  import type { V1AdmissionTarget, V1AssignableRole, V1CommandResult, V1EpisodeSnapshot, V1SelfMediaTargetResult } from "../sync";
@@ -12,6 +14,7 @@ export type ConnectionAccessRequest = {
12
14
  readonly signal?: AbortSignal;
13
15
  readonly currentMediaToken?: ParticipantMediaCredential;
14
16
  readonly expectedParticipantGeneration?: number;
17
+ readonly expectedMediaConnectionId?: string;
15
18
  };
16
19
  export type ConnectionAccessProvider = (request?: ConnectionAccessRequest) => ParsedAccessGrant | Promise<ParsedAccessGrant>;
17
20
  export type ConnectionClock = {
@@ -79,13 +82,17 @@ export type ConnectionMediaFactoryInput = {
79
82
  readonly access: ParsedAccessGrant;
80
83
  readonly credential: () => Promise<string>;
81
84
  readonly replaceMediaConnection?: () => Promise<ParticipantMediaAccess>;
82
- readonly onFailure: (error: unknown) => void;
85
+ readonly traceparent?: string;
86
+ readonly onTransportDiagnostic?: (event: ConnectionReportTransportEvent) => void;
87
+ readonly onFailure: (error: unknown, mediaConnectionId?: string) => void;
83
88
  readonly onScreenEnded: () => void;
84
89
  };
85
90
  export type ConnectionSyncFactoryInput = {
86
91
  readonly access: ParsedAccessGrant;
87
92
  readonly token: () => Promise<string>;
88
93
  readonly media: ConnectionMediaClient;
94
+ readonly traceparent?: string;
95
+ readonly onTransportDiagnostic?: (event: ConnectionReportTransportEvent) => void;
89
96
  };
90
97
  export type ConnectionWhiteboardFactoryInput = {
91
98
  readonly onWatchdogReplacement?: ChalkWhiteboardV1ClientOptions["onWatchdogReplacement"];
@@ -97,6 +104,8 @@ export type ConnectionChatFileFactoryInput = {
97
104
  };
98
105
  export type ConnectionDependencies = {
99
106
  readonly clock: ConnectionClock;
107
+ readonly createConnectionReporter?: (access: () => ParsedAccessGrant | null) => ConnectionReporter | undefined;
108
+ readonly getEpisodeStatus?: (access: ParsedAccessGrant, signal: AbortSignal) => Promise<ParticipantEpisodeStatus["status"]>;
100
109
  readonly cancelPendingAdmission?: (access: ParsedAccessGrant, signal: AbortSignal) => Promise<boolean>;
101
110
  readonly mediaDevices: ConnectionMediaDevices;
102
111
  readonly createMediaClient: (input: ConnectionMediaFactoryInput) => ConnectionMediaClient;
@@ -18,8 +18,10 @@ export type ConnectionJoinTraceEnd = {
18
18
  readonly epoch: number;
19
19
  readonly outcome: Exclude<ConnectionJoinTraceOutcome, "started">;
20
20
  readonly code?: ConnectionErrorCode;
21
+ readonly media?: import("../media/failure-diagnostics").MediaFailureDiagnostic & import("../media/failure-diagnostics").GrantedMedia;
21
22
  };
22
23
  export type ConnectionDiagnostic = {
24
+ readonly media?: import("../media/failure-diagnostics").MediaFailureDiagnostic & import("../media/failure-diagnostics").GrantedMedia;
23
25
  readonly timestamp: number;
24
26
  readonly event: ConnectionDiagnosticEventName;
25
27
  readonly state: ConnectionState;
@@ -54,6 +56,8 @@ export declare class ConnectionDiagnostics {
54
56
  readonly code: "sync_recovery_exhausted" | "media_recovery_exhausted";
55
57
  readonly attempts: number;
56
58
  readonly transport: import("../sync/connect-diagnostics").SyncRecoveryDiagnostic | null;
59
+ readonly media?: ConnectionDiagnostic["media"];
60
+ readonly grantedMedia: import("../media/failure-diagnostics").GrantedMedia;
57
61
  }): void;
58
62
  snapshot(): readonly ConnectionDiagnostic[];
59
63
  startSpan(input: {
@@ -0,0 +1,7 @@
1
+ export declare class EpisodeStatusError extends Error {
2
+ readonly status: number;
3
+ readonly retryAfterMs: number;
4
+ constructor(status: number, retryAfterMs?: number);
5
+ }
6
+ export declare function episodeStatusRetryDelay(attempt: number, error: unknown): number;
7
+ export declare function retryAfterMilliseconds(value: string | null, now: number): number;
@@ -34,7 +34,9 @@ export type ConnectionOptions = {
34
34
  readonly initialCameraEnabled?: boolean;
35
35
  readonly accessRefreshWindowMs?: number;
36
36
  readonly recovery?: {
37
+ /** Sync attempt cap. Recoverable media failures retry until budgetMs expires. */
37
38
  readonly maxAttempts?: number;
39
+ /** Foreground recovery budget for either transport; defaults to 60 seconds. */
38
40
  readonly budgetMs?: number;
39
41
  readonly backoffMs?: readonly number[];
40
42
  };