@q9labsai/chalk-client 5.2.4 → 5.2.6

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 (35) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/access/grant.d.ts +2 -1
  3. package/dist/access/manager.d.ts +1 -0
  4. package/dist/{chunk-AZONR3Q3.js → chunk-CJVLTSIO.js} +120 -8
  5. package/dist/{chunk-LDPC2JZB.js → chunk-I7Y4HR2P.js} +711 -194
  6. package/dist/{chunk-SYUGRHZ5.js → chunk-WFRTUBN6.js} +1 -1
  7. package/dist/{chunk-3ASKGMD3.js → chunk-YIDKETOX.js} +410 -232
  8. package/dist/client.d.ts +74 -2
  9. package/dist/connection/dependencies.d.ts +4 -1
  10. package/dist/connection/diagnostics.d.ts +4 -0
  11. package/dist/connection/episode-status.d.ts +7 -0
  12. package/dist/connection/index.d.ts +2 -0
  13. package/dist/connection/lifecycle.d.ts +2 -0
  14. package/dist/connection/production.d.ts +1 -1
  15. package/dist/effect.js +19 -3
  16. package/dist/generated/http-api.d.ts +73 -2
  17. package/dist/generated/schemas.d.ts +126 -4
  18. package/dist/index.js +4 -4
  19. package/dist/media/client.d.ts +4 -3
  20. package/dist/media/failure-diagnostics.d.ts +10 -0
  21. package/dist/media/index.js +1 -1
  22. package/dist/media/plane.d.ts +7 -2
  23. package/dist/media/types.d.ts +4 -2
  24. package/dist/public-invites/index.js +2 -2
  25. package/dist/server/access-refresh.d.cts +1 -1
  26. package/dist/server/access-refresh.d.ts +1 -1
  27. package/dist/server/index.cjs +15 -5
  28. package/dist/server/index.js +15 -5
  29. package/dist/server/types.d.cts +2 -1
  30. package/dist/server/types.d.ts +2 -1
  31. package/dist/space-client/media-projection-monitor.d.ts +26 -0
  32. package/dist/space-client/promise-facade.d.ts +5 -5
  33. package/dist/space-client/types.d.ts +4 -0
  34. package/dist/transport-diagnostics.d.ts +1 -1
  35. package/package.json +1 -1
@@ -226,15 +226,22 @@ export declare const ConnectionReportRequestSchema: Schema.Struct<{
226
226
  readonly code: Schema.optional<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"]>>;
227
227
  readonly duration_ms: Schema.optional<Schema.NullOr<Schema.Number>>;
228
228
  readonly elapsed_ms: Schema.Number;
229
- readonly event: 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"]>;
229
+ readonly event: 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"]>;
230
+ readonly granted_audio: Schema.optional<Schema.Literals<readonly ["granted", "not_granted", "unknown"]>>;
231
+ readonly granted_video: Schema.optional<Schema.Literals<readonly ["granted", "not_granted", "unknown"]>>;
230
232
  readonly heartbeat_gap_ms: Schema.optional<Schema.NullOr<Schema.Number>>;
231
233
  readonly http_status: Schema.optional<Schema.NullOr<Schema.Number>>;
234
+ readonly media_error_kind: Schema.optional<Schema.Literals<readonly ["NotAllowedError", "NotReadableError", "NotFoundError", "OverconstrainedError", "AbortError", "SecurityError", "InvalidStateError", "OperationError", "NotSupportedError", "CloudflareSFUError", "network", "timeout", "unknown"]>>;
235
+ readonly media_error_step: Schema.optional<Schema.Literals<readonly ["local_capture", "peer_connection", "access_refresh", "sfu_tracks", "sfu_close_tracks", "sfu_renegotiate", "sfu_publications"]>>;
232
236
  readonly outcome: Schema.optional<Schema.Literals<readonly ["started", "succeeded", "failed", "cancelled"]>>;
233
237
  readonly phase: Schema.optional<Schema.Literals<readonly ["idle", "connecting", "live", "recovering", "failed", "stopped", "new", "connected", "disconnected", "closed"]>>;
238
+ readonly projection_state: Schema.optional<Schema.Literals<readonly ["on", "off"]>>;
239
+ readonly publication_state: Schema.optional<Schema.Literals<readonly ["on", "off"]>>;
240
+ readonly source: Schema.optional<Schema.Literals<readonly ["microphone", "camera"]>>;
234
241
  readonly state: Schema.optional<Schema.Literals<readonly ["idle", "joining", "live", "reconnecting", "leaving", "left", "failed"]>>;
235
242
  readonly step: Schema.optional<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"]>>;
236
243
  }>>;
237
- readonly trigger: Schema.Literals<readonly ["join_failed", "connection_lost", "recovery_exhausted"]>;
244
+ readonly trigger: Schema.Literals<readonly ["join_failed", "connection_lost", "recovery_exhausted", "media_projection_mismatch"]>;
238
245
  readonly version: Schema.Literal<1>;
239
246
  }>;
240
247
  export type ConnectionReportRequest = typeof ConnectionReportRequestSchema.Type;
@@ -443,6 +450,7 @@ export declare const IntegrationServiceIdSchema: Schema.brand<Schema.String, "In
443
450
  export type IntegrationServiceId = typeof IntegrationServiceIdSchema.Type;
444
451
  export declare const IssueAccessGrantRequestSchema: Schema.Struct<{
445
452
  readonly current_media_token: Schema.optional<Schema.String>;
453
+ readonly expected_media_connection_id: Schema.optional<Schema.NullOr<Schema.String>>;
446
454
  readonly participant_generation: Schema.Number;
447
455
  readonly replace_media_connection: Schema.Boolean;
448
456
  }>;
@@ -478,6 +486,10 @@ export declare const MembershipListSchema: Schema.Struct<{
478
486
  }>;
479
487
  }>;
480
488
  export type MembershipList = typeof MembershipListSchema.Type;
489
+ export declare const ParticipantEpisodeStatusSchema: Schema.Struct<{
490
+ readonly status: Schema.Literals<readonly ["active", "ending", "ended"]>;
491
+ }>;
492
+ export type ParticipantEpisodeStatus = typeof ParticipantEpisodeStatusSchema.Type;
481
493
  export declare const ParticipantJoinCancellationSchema: Schema.Struct<{
482
494
  readonly cancelled: Schema.Boolean;
483
495
  }>;
@@ -1346,6 +1358,7 @@ export declare const AddCloudflareSFUTracksPathParamsSchema: Schema.Struct<{
1346
1358
  export type AddCloudflareSFUTracksPathParams = typeof AddCloudflareSFUTracksPathParamsSchema.Type;
1347
1359
  export declare const AddCloudflareSFUTracksQueryParamsSchema: Schema.Struct<{
1348
1360
  readonly allow_partial_remote_tracks: Schema.optional<Schema.Boolean>;
1361
+ readonly replacement_cause: Schema.optional<Schema.Literals<readonly ["user_pause", "moderation_pause", "sync_recovery_loss", "discovery_absent", "capture_cleanup", "consent_revoked", "publish_failure", "enable_failure", "projection_mismatch", "forced_pause", "local_signaling_failure", "remote_signaling_failure", "dormant_connection", "access_refresh"]>>;
1349
1362
  }>;
1350
1363
  export type AddCloudflareSFUTracksQueryParams = typeof AddCloudflareSFUTracksQueryParamsSchema.Type;
1351
1364
  export declare const AddCloudflareSFUTracksRequestBodySchema: Schema.Struct<{
@@ -2235,6 +2248,23 @@ export declare const GetEpisodeAttendance429ResponseHeadersSchema: Schema.Struct
2235
2248
  readonly "X-RateLimit-Remaining": Schema.NumberFromString;
2236
2249
  }>;
2237
2250
  export type GetEpisodeAttendance429ResponseHeaders = typeof GetEpisodeAttendance429ResponseHeadersSchema.Type;
2251
+ export declare const GetParticipantEpisodeStatusPathParamsSchema: Schema.Struct<{
2252
+ readonly episode_id: Schema.brand<Schema.String, "EpisodeId">;
2253
+ readonly participant_id: Schema.brand<Schema.String, "ParticipantId">;
2254
+ readonly space_id: Schema.brand<Schema.String, "SpaceId">;
2255
+ readonly tenant_id: Schema.brand<Schema.String, "TenantId">;
2256
+ }>;
2257
+ export type GetParticipantEpisodeStatusPathParams = typeof GetParticipantEpisodeStatusPathParamsSchema.Type;
2258
+ export declare const GetParticipantEpisodeStatusResponseSchema: Schema.Struct<{
2259
+ readonly status: Schema.Literals<readonly ["active", "ending", "ended"]>;
2260
+ }>;
2261
+ export type GetParticipantEpisodeStatusResponse = typeof GetParticipantEpisodeStatusResponseSchema.Type;
2262
+ export declare const GetParticipantEpisodeStatus429ResponseHeadersSchema: Schema.Struct<{
2263
+ readonly "Retry-After": Schema.NumberFromString;
2264
+ readonly "X-RateLimit-Limit": Schema.NumberFromString;
2265
+ readonly "X-RateLimit-Remaining": Schema.NumberFromString;
2266
+ }>;
2267
+ export type GetParticipantEpisodeStatus429ResponseHeaders = typeof GetParticipantEpisodeStatus429ResponseHeadersSchema.Type;
2238
2268
  export declare const GetProblemReportAvailabilityPathParamsSchema: Schema.Struct<{
2239
2269
  readonly tenant_id: Schema.brand<Schema.String, "TenantId">;
2240
2270
  }>;
@@ -2599,6 +2629,7 @@ export declare const IssueAccessGrantPathParamsSchema: Schema.Struct<{
2599
2629
  export type IssueAccessGrantPathParams = typeof IssueAccessGrantPathParamsSchema.Type;
2600
2630
  export declare const IssueAccessGrantRequestBodySchema: Schema.Struct<{
2601
2631
  readonly current_media_token: Schema.optional<Schema.String>;
2632
+ readonly expected_media_connection_id: Schema.optional<Schema.NullOr<Schema.String>>;
2602
2633
  readonly participant_generation: Schema.Number;
2603
2634
  readonly replace_media_connection: Schema.Boolean;
2604
2635
  }>;
@@ -3314,15 +3345,22 @@ export declare const ReportConnectionFailureRequestBodySchema: Schema.Struct<{
3314
3345
  readonly code: Schema.optional<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"]>>;
3315
3346
  readonly duration_ms: Schema.optional<Schema.NullOr<Schema.Number>>;
3316
3347
  readonly elapsed_ms: Schema.Number;
3317
- readonly event: 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"]>;
3348
+ readonly event: 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"]>;
3349
+ readonly granted_audio: Schema.optional<Schema.Literals<readonly ["granted", "not_granted", "unknown"]>>;
3350
+ readonly granted_video: Schema.optional<Schema.Literals<readonly ["granted", "not_granted", "unknown"]>>;
3318
3351
  readonly heartbeat_gap_ms: Schema.optional<Schema.NullOr<Schema.Number>>;
3319
3352
  readonly http_status: Schema.optional<Schema.NullOr<Schema.Number>>;
3353
+ readonly media_error_kind: Schema.optional<Schema.Literals<readonly ["NotAllowedError", "NotReadableError", "NotFoundError", "OverconstrainedError", "AbortError", "SecurityError", "InvalidStateError", "OperationError", "NotSupportedError", "CloudflareSFUError", "network", "timeout", "unknown"]>>;
3354
+ readonly media_error_step: Schema.optional<Schema.Literals<readonly ["local_capture", "peer_connection", "access_refresh", "sfu_tracks", "sfu_close_tracks", "sfu_renegotiate", "sfu_publications"]>>;
3320
3355
  readonly outcome: Schema.optional<Schema.Literals<readonly ["started", "succeeded", "failed", "cancelled"]>>;
3321
3356
  readonly phase: Schema.optional<Schema.Literals<readonly ["idle", "connecting", "live", "recovering", "failed", "stopped", "new", "connected", "disconnected", "closed"]>>;
3357
+ readonly projection_state: Schema.optional<Schema.Literals<readonly ["on", "off"]>>;
3358
+ readonly publication_state: Schema.optional<Schema.Literals<readonly ["on", "off"]>>;
3359
+ readonly source: Schema.optional<Schema.Literals<readonly ["microphone", "camera"]>>;
3322
3360
  readonly state: Schema.optional<Schema.Literals<readonly ["idle", "joining", "live", "reconnecting", "leaving", "left", "failed"]>>;
3323
3361
  readonly step: Schema.optional<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"]>>;
3324
3362
  }>>;
3325
- readonly trigger: Schema.Literals<readonly ["join_failed", "connection_lost", "recovery_exhausted"]>;
3363
+ readonly trigger: Schema.Literals<readonly ["join_failed", "connection_lost", "recovery_exhausted", "media_projection_mismatch"]>;
3326
3364
  readonly version: Schema.Literal<1>;
3327
3365
  }>;
3328
3366
  export type ReportConnectionFailureRequestBody = typeof ReportConnectionFailureRequestBodySchema.Type;
@@ -4862,6 +4900,26 @@ export declare const ParticipantInvalidIdErrorSchema: Schema.decodeTo<typeof Par
4862
4900
  readonly message: Schema.String;
4863
4901
  }>;
4864
4902
  }>, never, never>;
4903
+ declare const ParticipantMediaReplacementPendingError_base: Schema.Class<ParticipantMediaReplacementPendingError, Schema.TaggedStruct<"ParticipantMediaReplacementPendingError", {
4904
+ readonly error: Schema.Struct<{
4905
+ readonly code: Schema.Literal<"participant.media_replacement_pending">;
4906
+ readonly message: Schema.String;
4907
+ }>;
4908
+ }>, import("effect/Cause").YieldableError>;
4909
+ export declare class ParticipantMediaReplacementPendingError extends ParticipantMediaReplacementPendingError_base {
4910
+ }
4911
+ export declare const ParticipantMediaReplacementPendingErrorWireSchema: Schema.Struct<{
4912
+ readonly error: Schema.Struct<{
4913
+ readonly code: Schema.Literal<"participant.media_replacement_pending">;
4914
+ readonly message: Schema.String;
4915
+ }>;
4916
+ }>;
4917
+ export declare const ParticipantMediaReplacementPendingErrorSchema: Schema.decodeTo<typeof ParticipantMediaReplacementPendingError, Schema.Struct<{
4918
+ readonly error: Schema.Struct<{
4919
+ readonly code: Schema.Literal<"participant.media_replacement_pending">;
4920
+ readonly message: Schema.String;
4921
+ }>;
4922
+ }>, never, never>;
4865
4923
  declare const ParticipantNotActiveError_base: Schema.Class<ParticipantNotActiveError, Schema.TaggedStruct<"ParticipantNotActiveError", {
4866
4924
  readonly error: Schema.Struct<{
4867
4925
  readonly code: Schema.Literal<"participant.not_active">;
@@ -7869,6 +7927,58 @@ export declare const GetEpisodeErrorSchema: Schema.Union<readonly [Schema.decode
7869
7927
  }>;
7870
7928
  }>, never, never>]>;
7871
7929
  export type GetEpisodeError = typeof GetEpisodeErrorSchema.Type;
7930
+ export declare const GetParticipantEpisodeStatusErrorSchema: Schema.Union<readonly [Schema.decodeTo<typeof AccessForbiddenError, Schema.Struct<{
7931
+ readonly error: Schema.Struct<{
7932
+ readonly code: Schema.Literal<"access.forbidden">;
7933
+ readonly message: Schema.String;
7934
+ }>;
7935
+ }>, never, never>, Schema.decodeTo<typeof AccessUnauthenticatedError, Schema.Struct<{
7936
+ readonly error: Schema.Struct<{
7937
+ readonly code: Schema.Literal<"access.unauthenticated">;
7938
+ readonly message: Schema.String;
7939
+ }>;
7940
+ }>, never, never>, Schema.decodeTo<typeof EpisodeInvalidIdError, Schema.Struct<{
7941
+ readonly error: Schema.Struct<{
7942
+ readonly code: Schema.Literal<"episode.invalid_id">;
7943
+ readonly message: Schema.String;
7944
+ }>;
7945
+ }>, never, never>, Schema.decodeTo<typeof EpisodeNotFoundError, Schema.Struct<{
7946
+ readonly error: Schema.Struct<{
7947
+ readonly code: Schema.Literal<"episode.not_found">;
7948
+ readonly message: Schema.String;
7949
+ }>;
7950
+ }>, never, never>, Schema.decodeTo<typeof ParticipantInvalidIdError, Schema.Struct<{
7951
+ readonly error: Schema.Struct<{
7952
+ readonly code: Schema.Literal<"participant.invalid_id">;
7953
+ readonly message: Schema.String;
7954
+ }>;
7955
+ }>, never, never>, Schema.decodeTo<typeof RequestRateLimitedError, Schema.Struct<{
7956
+ readonly error: Schema.Struct<{
7957
+ readonly code: Schema.Literal<"request.rate_limited">;
7958
+ readonly message: Schema.String;
7959
+ }>;
7960
+ }>, never, never>, Schema.decodeTo<typeof ServiceInternalError, Schema.Struct<{
7961
+ readonly error: Schema.Struct<{
7962
+ readonly code: Schema.Literal<"service.internal_error">;
7963
+ readonly message: Schema.String;
7964
+ }>;
7965
+ }>, never, never>, Schema.decodeTo<typeof ServiceUnavailableError, Schema.Struct<{
7966
+ readonly error: Schema.Struct<{
7967
+ readonly code: Schema.Literal<"service.unavailable">;
7968
+ readonly message: Schema.String;
7969
+ }>;
7970
+ }>, never, never>, Schema.decodeTo<typeof SpaceInvalidIdError, Schema.Struct<{
7971
+ readonly error: Schema.Struct<{
7972
+ readonly code: Schema.Literal<"space.invalid_id">;
7973
+ readonly message: Schema.String;
7974
+ }>;
7975
+ }>, never, never>, Schema.decodeTo<typeof TenantInvalidIdError, Schema.Struct<{
7976
+ readonly error: Schema.Struct<{
7977
+ readonly code: Schema.Literal<"tenant.invalid_id">;
7978
+ readonly message: Schema.String;
7979
+ }>;
7980
+ }>, never, never>]>;
7981
+ export type GetParticipantEpisodeStatusError = typeof GetParticipantEpisodeStatusErrorSchema.Type;
7872
7982
  export declare const GetProblemReportAvailabilityErrorSchema: Schema.decodeTo<typeof TenantInvalidIdError, Schema.Struct<{
7873
7983
  readonly error: Schema.Struct<{
7874
7984
  readonly code: Schema.Literal<"tenant.invalid_id">;
@@ -8585,6 +8695,11 @@ export declare const IssueAccessGrantErrorSchema: Schema.Union<readonly [Schema.
8585
8695
  readonly code: Schema.Literal<"participant.invalid_id">;
8586
8696
  readonly message: Schema.String;
8587
8697
  }>;
8698
+ }>, never, never>, Schema.decodeTo<typeof ParticipantMediaReplacementPendingError, Schema.Struct<{
8699
+ readonly error: Schema.Struct<{
8700
+ readonly code: Schema.Literal<"participant.media_replacement_pending">;
8701
+ readonly message: Schema.String;
8702
+ }>;
8588
8703
  }>, never, never>, Schema.decodeTo<typeof ParticipantNotFoundError, Schema.Struct<{
8589
8704
  readonly error: Schema.Struct<{
8590
8705
  readonly code: Schema.Literal<"participant.not_found">;
@@ -11268,6 +11383,13 @@ export declare const ChalkOperationPolicies: {
11268
11383
  readonly windowSeconds: 60;
11269
11384
  };
11270
11385
  };
11386
+ readonly getParticipantEpisodeStatus: {
11387
+ readonly rateLimit: {
11388
+ readonly limit: 300;
11389
+ readonly policy: "v1.authenticated.read";
11390
+ readonly windowSeconds: 60;
11391
+ };
11392
+ };
11271
11393
  readonly getSpacePublicInvite: {
11272
11394
  readonly rateLimit: {
11273
11395
  readonly limit: 300;
package/dist/index.js CHANGED
@@ -15,7 +15,7 @@ import {
15
15
  createSpaceClient,
16
16
  decodeWhiteboardV1ServerFrame,
17
17
  encodeWhiteboardV1ClientFrame
18
- } from "./chunk-LDPC2JZB.js";
18
+ } from "./chunk-I7Y4HR2P.js";
19
19
  import {
20
20
  CloudflareSFUClient,
21
21
  CloudflareSFUError,
@@ -28,19 +28,19 @@ import {
28
28
  requireSFUDescription,
29
29
  validatePublicationSnapshot,
30
30
  waitFor
31
- } from "./chunk-3ASKGMD3.js";
31
+ } from "./chunk-YIDKETOX.js";
32
32
  import {
33
33
  createChalkPublicClient,
34
34
  createChalkPublicInviteClient,
35
35
  parseInviteCode
36
- } from "./chunk-SYUGRHZ5.js";
36
+ } from "./chunk-WFRTUBN6.js";
37
37
  import {
38
38
  ArrivalInvalidHandleError,
39
39
  ArrivalUnavailableError,
40
40
  SpacePublicInviteUnavailableError,
41
41
  parseParsedAccessGrant,
42
42
  requireAccessGrant
43
- } from "./chunk-AZONR3Q3.js";
43
+ } from "./chunk-CJVLTSIO.js";
44
44
  import {
45
45
  AsyncStorageV1PendingTargetStore,
46
46
  InMemoryV1PendingTargetStore,
@@ -1,4 +1,4 @@
1
- import type { ClientMediaPlane, MediaPlaneResult, MediaPlaneTarget, MediaPublication, MediaPublicationSource } from "./plane";
1
+ import type { ClientMediaPlane, LocalPublicationRetirementCause, MediaPlaneResult, MediaPlaneTarget, MediaPublication, MediaPublicationSource } from "./plane";
2
2
  import type { CloudflareSFUBootstrap, CloudflareSFUClientOptions, CloudflareSFURestartOptions, CloudflareSFUSnapshot } from "./types";
3
3
  export declare class CloudflareSFUClient implements ClientMediaPlane {
4
4
  #private;
@@ -15,8 +15,9 @@ export declare class CloudflareSFUClient implements ClientMediaPlane {
15
15
  start(localMedia: MediaStream): Promise<void>;
16
16
  refreshRemotePublications(): Promise<void>;
17
17
  setLocalPublicationTarget(target: MediaPlaneTarget): Promise<MediaPlaneResult>;
18
- setLocalSourceIntent(source: MediaPublicationSource, enabled: boolean): void;
19
- closeForcedLocalPublication(source: MediaPublicationSource): Promise<void>;
18
+ pauseLocalCapture(source: "microphone" | "camera"): Promise<void>;
19
+ setLocalSourceIntent(source: MediaPublicationSource, enabled: boolean, cause?: LocalPublicationRetirementCause): Promise<void>;
20
+ closeForcedLocalPublication(source: MediaPublicationSource, cause?: LocalPublicationRetirementCause): Promise<void>;
20
21
  observeLocalPublications(listener: (publications: readonly MediaPublication[]) => void): () => void;
21
22
  observeRemotePublications(listener: (publications: readonly MediaPublication[]) => void): () => void;
22
23
  restart(input: CloudflareSFUBootstrap | CloudflareSFURestartOptions): Promise<void>;
@@ -0,0 +1,10 @@
1
+ import type { ConnectionReport } from "../transport-diagnostics";
2
+ type ReportEvent = ConnectionReport["events"][number];
3
+ export type MediaFailureDiagnostic = Required<Pick<ReportEvent, "media_error_kind" | "media_error_step">> & Pick<ReportEvent, "http_status">;
4
+ export type GrantedMedia = Required<Pick<ReportEvent, "granted_audio" | "granted_video">>;
5
+ type MediaFailureStep = NonNullable<ReportEvent["media_error_step"]>;
6
+ export declare function grantedMediaFromStream(stream: MediaStream): GrantedMedia;
7
+ export declare function markMediaFetchFailure(error: unknown): void;
8
+ export declare function markMediaFailure(error: unknown, step: MediaFailureStep): void;
9
+ export declare function classifyMediaFailure(cause: unknown, fallbackStep: MediaFailureStep): MediaFailureDiagnostic;
10
+ export {};
@@ -10,7 +10,7 @@ import {
10
10
  requireSFUDescription,
11
11
  validatePublicationSnapshot,
12
12
  waitFor
13
- } from "../chunk-3ASKGMD3.js";
13
+ } from "../chunk-YIDKETOX.js";
14
14
  export {
15
15
  CloudflareSFUClient,
16
16
  CloudflareSFUError,
@@ -1,3 +1,6 @@
1
+ import type { operations } from "../generated/openapi-types";
2
+ export type MediaConnectionReplacementCause = NonNullable<NonNullable<operations["addCloudflareSFUTracks"]["parameters"]["query"]>["replacement_cause"]>;
3
+ export type LocalPublicationRetirementCause = Exclude<MediaConnectionReplacementCause, "local_signaling_failure" | "remote_signaling_failure" | "dormant_connection" | "access_refresh">;
1
4
  export type ScreenShareSurface = "monitor" | "window" | "browser";
2
5
  export type ScreenShareOptions = {
3
6
  readonly surface?: ScreenShareSurface;
@@ -38,6 +41,7 @@ export type ConnectionMediaSnapshot = {
38
41
  readonly failure: {
39
42
  readonly code: string;
40
43
  readonly recoverable: boolean;
44
+ readonly diagnostic?: import("./failure-diagnostics").MediaFailureDiagnostic;
41
45
  } | null;
42
46
  };
43
47
  export type MediaPlaneOutcome = "confirmed" | "satisfied" | "retryable_failure" | "terminal_failure" | "ambiguous";
@@ -53,8 +57,9 @@ export type MediaPlaneResult = {
53
57
  };
54
58
  export type ClientMediaPlane = {
55
59
  readonly setLocalPublicationTarget: (target: MediaPlaneTarget) => Promise<MediaPlaneResult>;
56
- readonly setLocalSourceIntent?: (source: MediaSource, enabled: boolean) => void;
57
- readonly closeForcedLocalPublication?: (source: MediaSource) => Promise<void>;
60
+ readonly pauseLocalCapture?: (source: "microphone" | "camera") => Promise<void>;
61
+ readonly setLocalSourceIntent?: (source: MediaSource, enabled: boolean, cause?: LocalPublicationRetirementCause) => void;
62
+ readonly closeForcedLocalPublication?: (source: MediaSource, cause?: LocalPublicationRetirementCause) => Promise<void>;
58
63
  readonly observeLocalPublications: (listener: (publications: readonly MediaPublication[]) => void) => () => void;
59
64
  readonly observeRemotePublications: (listener: (publications: readonly MediaPublication[]) => void) => () => void;
60
65
  readonly remotePublicationsChanged?: () => void;
@@ -1,5 +1,5 @@
1
1
  import type { ConnectionReportTransportEvent } from "../transport-diagnostics";
2
- import type { MediaPublication, MediaPublicationSource } from "./plane";
2
+ import type { MediaConnectionReplacementCause, MediaPublication, MediaPublicationSource } from "./plane";
3
3
  export type CloudflareSFUBootstrap = {
4
4
  readonly connectionId: string;
5
5
  readonly stunServer: string;
@@ -52,6 +52,7 @@ export type CloudflareSFUSignalingTransport = {
52
52
  readonly sessionDescription?: CloudflareSFUSessionDescription;
53
53
  readonly tracks: readonly CloudflareSFUTrackRequest[];
54
54
  readonly allowPartialRemoteTracks?: boolean;
55
+ readonly replacementCause?: MediaConnectionReplacementCause;
55
56
  }) => Promise<CloudflareSFUTracksResponse>;
56
57
  readonly closeTracks: (input: {
57
58
  readonly connectionId: string;
@@ -90,6 +91,7 @@ export type CloudflareSFUSnapshot = {
90
91
  readonly failure: {
91
92
  readonly code: CloudflareSFUFailureCode;
92
93
  readonly recoverable: boolean;
94
+ readonly diagnostic?: import("./failure-diagnostics").MediaFailureDiagnostic;
93
95
  } | null;
94
96
  };
95
97
  export type CloudflareSFUClientOptions = {
@@ -98,7 +100,7 @@ export type CloudflareSFUClientOptions = {
98
100
  readonly transport: CloudflareSFUSignalingTransport;
99
101
  readonly replaceMediaConnection?: () => Promise<CloudflareSFUBootstrap>;
100
102
  readonly pollIntervalMs?: number;
101
- readonly onError?: (error: unknown) => void;
103
+ readonly onError?: (error: unknown, mediaConnectionId: string) => void;
102
104
  readonly onRemoteTrack?: (publication: CloudflareSFURemoteTrack) => void;
103
105
  readonly onScreenEnded?: () => void;
104
106
  readonly peerConnectionFactory?: (configuration: RTCConfiguration) => RTCPeerConnection;
@@ -2,12 +2,12 @@ import {
2
2
  createChalkPublicClient,
3
3
  createChalkPublicInviteClient,
4
4
  parseInviteCode
5
- } from "../chunk-SYUGRHZ5.js";
5
+ } from "../chunk-WFRTUBN6.js";
6
6
  import {
7
7
  ArrivalInvalidHandleError,
8
8
  ArrivalUnavailableError,
9
9
  SpacePublicInviteUnavailableError
10
- } from "../chunk-AZONR3Q3.js";
10
+ } from "../chunk-CJVLTSIO.js";
11
11
  export {
12
12
  ArrivalInvalidHandleError,
13
13
  ArrivalUnavailableError,
@@ -2,7 +2,7 @@ import type { AccessContext } from "../space-client/types.cjs";
2
2
  import type { IssueAccessGrantInput } from "./types.cjs";
3
3
  import { type AccessGrant, type ParticipantMediaCredential } from "../access/grant.cjs";
4
4
  /** Forward the browser request unchanged; only Chalk decides whether media needs replacing. */
5
- export type AccessRefreshRequest = Pick<AccessContext, "replaceMediaConnection">;
5
+ export type AccessRefreshRequest = Pick<AccessContext, "replaceMediaConnection" | "expectedMediaConnectionId" | "currentMediaToken">;
6
6
  /** Keep this on your backend, scoped to the authenticated Participant. Never send it to a browser or log it. */
7
7
  export type AccessRefreshState = {
8
8
  readonly participantGeneration: number;
@@ -2,7 +2,7 @@ import type { AccessContext } from "../space-client/types.js";
2
2
  import type { IssueAccessGrantInput } from "./types.js";
3
3
  import { type AccessGrant, type ParticipantMediaCredential } from "../access/grant.js";
4
4
  /** Forward the browser request unchanged; only Chalk decides whether media needs replacing. */
5
- export type AccessRefreshRequest = Pick<AccessContext, "replaceMediaConnection">;
5
+ export type AccessRefreshRequest = Pick<AccessContext, "replaceMediaConnection" | "expectedMediaConnectionId" | "currentMediaToken">;
6
6
  /** Keep this on your backend, scoped to the authenticated Participant. Never send it to a browser or log it. */
7
7
  export type AccessRefreshState = {
8
8
  readonly participantGeneration: number;
@@ -38,11 +38,13 @@ function decodeBase64Url(value) {
38
38
  // src/access/grant.ts
39
39
  var accessGrantBrand = /* @__PURE__ */ Symbol("AccessGrant");
40
40
  var AccessGrantError = class extends TypeError {
41
- code = "access.invalid";
42
- constructor(message = "Access grant is invalid") {
41
+ constructor(message = "Access grant is invalid", reason) {
43
42
  super(message);
43
+ this.reason = reason;
44
44
  this.name = "AccessGrantError";
45
45
  }
46
+ reason;
47
+ code = "access.invalid";
46
48
  };
47
49
  function parseParsedAccessGrant(value) {
48
50
  if (!isRecord(value)) throw new AccessGrantError();
@@ -165,7 +167,12 @@ function getAccessRefreshState(access) {
165
167
  });
166
168
  }
167
169
  function accessRefreshInput(state, request) {
168
- if (request?.replaceMediaConnection === true) return { participantGeneration: state.participantGeneration, replaceMediaConnection: true };
170
+ if (request?.replaceMediaConnection === true)
171
+ return {
172
+ participantGeneration: state.participantGeneration,
173
+ replaceMediaConnection: true,
174
+ ...request.expectedMediaConnectionId === void 0 ? {} : { expectedMediaConnectionId: request.expectedMediaConnectionId, ...request.currentMediaToken === void 0 ? {} : { currentMediaToken: request.currentMediaToken } }
175
+ };
169
176
  return state;
170
177
  }
171
178
 
@@ -326,7 +333,9 @@ function setOptionalHeader(headers, name, value) {
326
333
  if (value !== void 0) headers.set(name, value);
327
334
  }
328
335
  async function responseError(response, retryable) {
329
- return new ChalkAPIError({ code: errorCode(await errorBody(response)), requestId: requestId(response.headers), retryable: retryable && retryableStatuses.has(response.status), status: response.status });
336
+ const code = errorCode(await errorBody(response));
337
+ const pendingReplacement = response.status === 409 && code === "participant.media_replacement_pending";
338
+ return new ChalkAPIError({ code, requestId: requestId(response.headers), retryable: pendingReplacement || retryable && retryableStatuses.has(response.status), status: response.status });
330
339
  }
331
340
  async function errorBody(response) {
332
341
  try {
@@ -601,7 +610,8 @@ function accessGrantRequest(input) {
601
610
  return {
602
611
  participant_generation: input.participantGeneration,
603
612
  replace_media_connection: input.replaceMediaConnection ?? false,
604
- ...input.currentMediaToken ? { current_media_token: input.currentMediaToken } : {}
613
+ ...input.currentMediaToken ? { current_media_token: input.currentMediaToken } : {},
614
+ ...input.replaceMediaConnection && input.expectedMediaConnectionId !== void 0 ? { expected_media_connection_id: input.expectedMediaConnectionId } : {}
605
615
  };
606
616
  }
607
617
  function participantRemovalRequest(input) {
@@ -16,11 +16,13 @@ function decodeBase64Url(value) {
16
16
  // src/access/grant.ts
17
17
  var accessGrantBrand = /* @__PURE__ */ Symbol("AccessGrant");
18
18
  var AccessGrantError = class extends TypeError {
19
- code = "access.invalid";
20
- constructor(message = "Access grant is invalid") {
19
+ constructor(message = "Access grant is invalid", reason) {
21
20
  super(message);
21
+ this.reason = reason;
22
22
  this.name = "AccessGrantError";
23
23
  }
24
+ reason;
25
+ code = "access.invalid";
24
26
  };
25
27
  function parseParsedAccessGrant(value) {
26
28
  if (!isRecord(value)) throw new AccessGrantError();
@@ -143,7 +145,12 @@ function getAccessRefreshState(access) {
143
145
  });
144
146
  }
145
147
  function accessRefreshInput(state, request) {
146
- if (request?.replaceMediaConnection === true) return { participantGeneration: state.participantGeneration, replaceMediaConnection: true };
148
+ if (request?.replaceMediaConnection === true)
149
+ return {
150
+ participantGeneration: state.participantGeneration,
151
+ replaceMediaConnection: true,
152
+ ...request.expectedMediaConnectionId === void 0 ? {} : { expectedMediaConnectionId: request.expectedMediaConnectionId, ...request.currentMediaToken === void 0 ? {} : { currentMediaToken: request.currentMediaToken } }
153
+ };
147
154
  return state;
148
155
  }
149
156
 
@@ -228,7 +235,9 @@ function setOptionalHeader(headers, name, value) {
228
235
  if (value !== void 0) headers.set(name, value);
229
236
  }
230
237
  async function responseError(response, retryable) {
231
- return new ChalkAPIError({ code: errorCode(await errorBody(response)), requestId: requestId(response.headers), retryable: retryable && retryableStatuses.has(response.status), status: response.status });
238
+ const code = errorCode(await errorBody(response));
239
+ const pendingReplacement = response.status === 409 && code === "participant.media_replacement_pending";
240
+ return new ChalkAPIError({ code, requestId: requestId(response.headers), retryable: pendingReplacement || retryable && retryableStatuses.has(response.status), status: response.status });
232
241
  }
233
242
  async function errorBody(response) {
234
243
  try {
@@ -503,7 +512,8 @@ function accessGrantRequest(input) {
503
512
  return {
504
513
  participant_generation: input.participantGeneration,
505
514
  replace_media_connection: input.replaceMediaConnection ?? false,
506
- ...input.currentMediaToken ? { current_media_token: input.currentMediaToken } : {}
515
+ ...input.currentMediaToken ? { current_media_token: input.currentMediaToken } : {},
516
+ ...input.replaceMediaConnection && input.expectedMediaConnectionId !== void 0 ? { expected_media_connection_id: input.expectedMediaConnectionId } : {}
507
517
  };
508
518
  }
509
519
  function participantRemovalRequest(input) {
@@ -158,8 +158,9 @@ export type IssueAccessGrantInput = {
158
158
  readonly replaceMediaConnection?: false;
159
159
  } | {
160
160
  readonly participantGeneration: number;
161
- readonly currentMediaToken?: never;
161
+ readonly currentMediaToken?: string;
162
162
  readonly replaceMediaConnection: true;
163
+ readonly expectedMediaConnectionId?: string;
163
164
  };
164
165
  export type APIKey = {
165
166
  readonly created_at: string;
@@ -158,8 +158,9 @@ export type IssueAccessGrantInput = {
158
158
  readonly replaceMediaConnection?: false;
159
159
  } | {
160
160
  readonly participantGeneration: number;
161
- readonly currentMediaToken?: never;
161
+ readonly currentMediaToken?: string;
162
162
  readonly replaceMediaConnection: true;
163
+ readonly expectedMediaConnectionId?: string;
163
164
  };
164
165
  export type APIKey = {
165
166
  readonly created_at: string;
@@ -0,0 +1,26 @@
1
+ import type { ConnectionReportTransportEvent } from "../transport-diagnostics";
2
+ type Source = "microphone" | "camera";
3
+ type Observation = {
4
+ readonly revision: number;
5
+ readonly publicationId: string | null;
6
+ readonly enabled: boolean;
7
+ readonly projectedEnabled: boolean;
8
+ readonly projectedPublicationId: string | null;
9
+ };
10
+ type Options = {
11
+ readonly now: () => number;
12
+ readonly schedule: (callback: () => void, milliseconds: number) => unknown;
13
+ readonly cancel: (timer: unknown) => void;
14
+ readonly report: (event: ConnectionReportTransportEvent) => void;
15
+ readonly pause: (source: Source, revision: number) => void;
16
+ readonly changed: () => void;
17
+ };
18
+ /** Observes authority without sending targets that could affect another client. */
19
+ export declare class MediaProjectionMonitor {
20
+ #private;
21
+ constructor(options: Options);
22
+ observe(source: Source, observation: Observation): void;
23
+ state(source: Source): "requesting" | "failed" | null;
24
+ reset(): void;
25
+ }
26
+ export {};
@@ -1,11 +1,11 @@
1
1
  import { Effect } from "effect";
2
- type ControllerCommand = (...args: any[]) => unknown;
3
- type PromiseRuntime = {
4
- readonly runPromise: (effect: Effect.Effect<any, any, any>) => Promise<any>;
2
+ type ControllerCommand = (...args: never[]) => unknown;
3
+ type PromiseRuntime<Services> = {
4
+ readonly runPromise: (effect: Effect.Effect<unknown, unknown, Services>) => Promise<unknown>;
5
5
  };
6
- export type PromiseCommand<Command> = Command extends (...args: infer Arguments) => infer Result ? (Result extends Effect.Effect<infer Success, any, any> ? (...args: Arguments) => Promise<Success> : (...args: Arguments) => Result) : never;
6
+ export type PromiseCommand<Command> = Command extends (...args: infer Arguments) => infer Result ? (Result extends Effect.Effect<infer Success, unknown, unknown> ? (...args: Arguments) => Promise<Success> : (...args: Arguments) => Result) : never;
7
7
  export type PromiseController<Controller extends Record<string, ControllerCommand>> = {
8
8
  readonly [Key in keyof Controller]: PromiseCommand<Controller[Key]>;
9
9
  };
10
- export declare function toPromiseController<Controller extends Record<string, ControllerCommand>>(runtime: PromiseRuntime, controller: Controller): PromiseController<Omit<Controller, "configure" | "dispose">>;
10
+ export declare function toPromiseController<Services, Controller extends Record<string, ControllerCommand>>(runtime: PromiseRuntime<Services>, controller: Controller): PromiseController<Omit<Controller, "configure" | "dispose">>;
11
11
  export {};
@@ -17,6 +17,10 @@ export type AccessContext = {
17
17
  readonly reason: AccessReason;
18
18
  /** Forward to the access endpoint so media recovery can obtain a fresh connection. */
19
19
  readonly replaceMediaConnection: boolean;
20
+ /** Automatic replacement succeeds only while this media binding is current. Omit for explicit takeover. */
21
+ readonly expectedMediaConnectionId?: string;
22
+ /** Forward unchanged for replay-safe recovery. Never log credentials. */
23
+ readonly currentMediaToken?: string;
20
24
  readonly signal?: AbortSignal;
21
25
  };
22
26
  /**
@@ -1,3 +1,3 @@
1
1
  import type { components } from "./generated/openapi-types";
2
2
  export type ConnectionReport = components["schemas"]["ConnectionReportRequest"];
3
- export type ConnectionReportTransportEvent = Pick<ConnectionReport["events"][number], "event" | "phase" | "attempt" | "duration_ms" | "heartbeat_gap_ms" | "close_code" | "http_status">;
3
+ export type ConnectionReportTransportEvent = Pick<ConnectionReport["events"][number], "event" | "phase" | "attempt" | "duration_ms" | "heartbeat_gap_ms" | "close_code" | "http_status" | "source" | "publication_state" | "projection_state" | "outcome">;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@q9labsai/chalk-client",
3
- "version": "5.2.4",
3
+ "version": "5.2.6",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",