hci-atrium 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +182 -0
  3. package/dist/atrium.d.ts +522 -0
  4. package/dist/atrium.d.ts.map +1 -0
  5. package/dist/atrium.js +806 -0
  6. package/dist/atrium.js.map +1 -0
  7. package/dist/auth.d.ts +85 -0
  8. package/dist/auth.d.ts.map +1 -0
  9. package/dist/auth.js +369 -0
  10. package/dist/auth.js.map +1 -0
  11. package/dist/by.d.ts +84 -0
  12. package/dist/by.d.ts.map +1 -0
  13. package/dist/by.js +87 -0
  14. package/dist/by.js.map +1 -0
  15. package/dist/decider.d.ts +40 -0
  16. package/dist/decider.d.ts.map +1 -0
  17. package/dist/decider.js +76 -0
  18. package/dist/decider.js.map +1 -0
  19. package/dist/discovery.d.ts +15 -0
  20. package/dist/discovery.d.ts.map +1 -0
  21. package/dist/discovery.js +38 -0
  22. package/dist/discovery.js.map +1 -0
  23. package/dist/env.d.ts +11 -0
  24. package/dist/env.d.ts.map +1 -0
  25. package/dist/env.js +28 -0
  26. package/dist/env.js.map +1 -0
  27. package/dist/errors.d.ts +67 -0
  28. package/dist/errors.d.ts.map +1 -0
  29. package/dist/errors.js +86 -0
  30. package/dist/errors.js.map +1 -0
  31. package/dist/files.d.ts +7 -0
  32. package/dist/files.d.ts.map +1 -0
  33. package/dist/files.js +2 -0
  34. package/dist/files.js.map +1 -0
  35. package/dist/http.d.ts +11 -0
  36. package/dist/http.d.ts.map +1 -0
  37. package/dist/http.js +21 -0
  38. package/dist/http.js.map +1 -0
  39. package/dist/index.d.ts +17 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +14 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/models.d.ts +456 -0
  44. package/dist/models.d.ts.map +1 -0
  45. package/dist/models.js +487 -0
  46. package/dist/models.js.map +1 -0
  47. package/dist/pkce.d.ts +16 -0
  48. package/dist/pkce.d.ts.map +1 -0
  49. package/dist/pkce.js +40 -0
  50. package/dist/pkce.js.map +1 -0
  51. package/dist/react/index.d.ts +37 -0
  52. package/dist/react/index.d.ts.map +1 -0
  53. package/dist/react/index.js +89 -0
  54. package/dist/react/index.js.map +1 -0
  55. package/dist/rooms/armed-set.d.ts +33 -0
  56. package/dist/rooms/armed-set.d.ts.map +1 -0
  57. package/dist/rooms/armed-set.js +65 -0
  58. package/dist/rooms/armed-set.js.map +1 -0
  59. package/dist/rooms/brokers.d.ts +62 -0
  60. package/dist/rooms/brokers.d.ts.map +1 -0
  61. package/dist/rooms/brokers.js +109 -0
  62. package/dist/rooms/brokers.js.map +1 -0
  63. package/dist/rooms/codec.d.ts +100 -0
  64. package/dist/rooms/codec.d.ts.map +1 -0
  65. package/dist/rooms/codec.js +101 -0
  66. package/dist/rooms/codec.js.map +1 -0
  67. package/dist/rooms/index.d.ts +40 -0
  68. package/dist/rooms/index.d.ts.map +1 -0
  69. package/dist/rooms/index.js +45 -0
  70. package/dist/rooms/index.js.map +1 -0
  71. package/dist/rooms/offer-capture.d.ts +96 -0
  72. package/dist/rooms/offer-capture.d.ts.map +1 -0
  73. package/dist/rooms/offer-capture.js +338 -0
  74. package/dist/rooms/offer-capture.js.map +1 -0
  75. package/dist/rooms/offer-transcription.d.ts +63 -0
  76. package/dist/rooms/offer-transcription.d.ts.map +1 -0
  77. package/dist/rooms/offer-transcription.js +231 -0
  78. package/dist/rooms/offer-transcription.js.map +1 -0
  79. package/dist/rooms/participant.d.ts +35 -0
  80. package/dist/rooms/participant.d.ts.map +1 -0
  81. package/dist/rooms/participant.js +53 -0
  82. package/dist/rooms/participant.js.map +1 -0
  83. package/dist/rooms/recorder.d.ts +74 -0
  84. package/dist/rooms/recorder.d.ts.map +1 -0
  85. package/dist/rooms/recorder.js +157 -0
  86. package/dist/rooms/recorder.js.map +1 -0
  87. package/dist/rooms/room.d.ts +542 -0
  88. package/dist/rooms/room.d.ts.map +1 -0
  89. package/dist/rooms/room.js +1357 -0
  90. package/dist/rooms/room.js.map +1 -0
  91. package/dist/rooms/snippet.d.ts +48 -0
  92. package/dist/rooms/snippet.d.ts.map +1 -0
  93. package/dist/rooms/snippet.js +70 -0
  94. package/dist/rooms/snippet.js.map +1 -0
  95. package/dist/rooms/sse.d.ts +102 -0
  96. package/dist/rooms/sse.d.ts.map +1 -0
  97. package/dist/rooms/sse.js +347 -0
  98. package/dist/rooms/sse.js.map +1 -0
  99. package/dist/rooms/standing-source.d.ts +190 -0
  100. package/dist/rooms/standing-source.d.ts.map +1 -0
  101. package/dist/rooms/standing-source.js +431 -0
  102. package/dist/rooms/standing-source.js.map +1 -0
  103. package/dist/rooms/transcriber.d.ts +81 -0
  104. package/dist/rooms/transcriber.d.ts.map +1 -0
  105. package/dist/rooms/transcriber.js +111 -0
  106. package/dist/rooms/transcriber.js.map +1 -0
  107. package/dist/rooms/transport-shared.d.ts +28 -0
  108. package/dist/rooms/transport-shared.d.ts.map +1 -0
  109. package/dist/rooms/transport-shared.js +42 -0
  110. package/dist/rooms/transport-shared.js.map +1 -0
  111. package/dist/rooms/transport.d.ts +161 -0
  112. package/dist/rooms/transport.d.ts.map +1 -0
  113. package/dist/rooms/transport.js +258 -0
  114. package/dist/rooms/transport.js.map +1 -0
  115. package/dist/shaping/assets.d.ts +42 -0
  116. package/dist/shaping/assets.d.ts.map +1 -0
  117. package/dist/shaping/assets.js +77 -0
  118. package/dist/shaping/assets.js.map +1 -0
  119. package/dist/shaping/chat.d.ts +39 -0
  120. package/dist/shaping/chat.d.ts.map +1 -0
  121. package/dist/shaping/chat.js +62 -0
  122. package/dist/shaping/chat.js.map +1 -0
  123. package/dist/shaping/index.d.ts +14 -0
  124. package/dist/shaping/index.d.ts.map +1 -0
  125. package/dist/shaping/index.js +13 -0
  126. package/dist/shaping/index.js.map +1 -0
  127. package/dist/shaping/library.d.ts +84 -0
  128. package/dist/shaping/library.d.ts.map +1 -0
  129. package/dist/shaping/library.js +288 -0
  130. package/dist/shaping/library.js.map +1 -0
  131. package/dist/shaping/request.d.ts +47 -0
  132. package/dist/shaping/request.d.ts.map +1 -0
  133. package/dist/shaping/request.js +25 -0
  134. package/dist/shaping/request.js.map +1 -0
  135. package/dist/shaping/rooms.d.ts +128 -0
  136. package/dist/shaping/rooms.d.ts.map +1 -0
  137. package/dist/shaping/rooms.js +330 -0
  138. package/dist/shaping/rooms.js.map +1 -0
  139. package/dist/shaping/sources.d.ts +29 -0
  140. package/dist/shaping/sources.d.ts.map +1 -0
  141. package/dist/shaping/sources.js +51 -0
  142. package/dist/shaping/sources.js.map +1 -0
  143. package/dist/shaping/structured.d.ts +47 -0
  144. package/dist/shaping/structured.d.ts.map +1 -0
  145. package/dist/shaping/structured.js +115 -0
  146. package/dist/shaping/structured.js.map +1 -0
  147. package/dist/storage.d.ts +36 -0
  148. package/dist/storage.d.ts.map +1 -0
  149. package/dist/storage.js +86 -0
  150. package/dist/storage.js.map +1 -0
  151. package/dist/transcribe-stream.d.ts +81 -0
  152. package/dist/transcribe-stream.d.ts.map +1 -0
  153. package/dist/transcribe-stream.js +253 -0
  154. package/dist/transcribe-stream.js.map +1 -0
  155. package/dist/transcribe.d.ts +57 -0
  156. package/dist/transcribe.d.ts.map +1 -0
  157. package/dist/transcribe.js +267 -0
  158. package/dist/transcribe.js.map +1 -0
  159. package/dist/types.d.ts +20 -0
  160. package/dist/types.d.ts.map +1 -0
  161. package/dist/types.js +3 -0
  162. package/dist/types.js.map +1 -0
  163. package/package.json +56 -0
@@ -0,0 +1,89 @@
1
+ import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
+ /**
3
+ * React bindings for ``hci-atrium`` — ``hci-atrium/react``.
4
+ *
5
+ * ``<AtriumProvider>`` subscribes to auth changes and exposes the client + user via context;
6
+ * ``useAtrium`` / ``useUser`` read it; ``<RequireSignIn>`` gates a subtree behind sign-in.
7
+ *
8
+ * ``useUser()`` distinguishes three states: ``undefined`` while the initial auth check is still in
9
+ * flight, ``null`` when signed out, and a ``User`` when signed in.
10
+ */
11
+ import { createContext, useContext, useEffect, useState } from "react";
12
+ const AtriumContext = createContext(null);
13
+ /** Provides the ``Atrium`` client and the live user to the ``useAtrium`` / ``useUser`` hooks. */
14
+ export function AtriumProvider({ atrium, children }) {
15
+ const [user, setUser] = useState(undefined);
16
+ const [error, setError] = useState(null);
17
+ useEffect(() => {
18
+ let active = true;
19
+ const unsubscribe = atrium.auth.onChange((next) => {
20
+ if (active) {
21
+ setUser(next);
22
+ // A successful sign-in clears any prior error; a sign-out leaves the last error in place
23
+ // so the surface (e.g. a state-mismatch) is still readable.
24
+ if (next) {
25
+ setError(null);
26
+ }
27
+ }
28
+ });
29
+ const unsubscribeError = atrium.auth.onError((err) => {
30
+ if (active) {
31
+ setError(err);
32
+ }
33
+ });
34
+ // Once initial auth settles, adopt the resolved state (null or a user) + any surfaced error.
35
+ atrium.ready().then(() => {
36
+ if (active) {
37
+ setUser(atrium.auth.user);
38
+ setError(atrium.auth.error);
39
+ }
40
+ });
41
+ return () => {
42
+ active = false;
43
+ unsubscribe();
44
+ unsubscribeError();
45
+ };
46
+ }, [atrium]);
47
+ return _jsx(AtriumContext.Provider, { value: { atrium, user, error }, children: children });
48
+ }
49
+ function useAtriumContext() {
50
+ const ctx = useContext(AtriumContext);
51
+ if (!ctx) {
52
+ throw new Error("Atrium React hooks must be used within an <AtriumProvider>");
53
+ }
54
+ return ctx;
55
+ }
56
+ /** The ``Atrium`` client from the nearest provider. */
57
+ export function useAtrium() {
58
+ return useAtriumContext().atrium;
59
+ }
60
+ /** The signed-in user: ``undefined`` while loading, ``null`` when signed out, else the ``User``. */
61
+ export function useUser() {
62
+ return useAtriumContext().user;
63
+ }
64
+ /** The most recent auth error (state mismatch, exchange or refresh failure), or ``null``. */
65
+ export function useAuthError() {
66
+ return useAtriumContext().error;
67
+ }
68
+ /**
69
+ * Render ``children`` only once signed in; otherwise render ``fallback`` (or a default sign-in
70
+ * button). Renders nothing while the initial auth check is still in flight.
71
+ *
72
+ * This is a UX guard, not a security boundary — see the README caveat.
73
+ */
74
+ export function RequireSignIn({ children, fallback }) {
75
+ const { atrium, user } = useAtriumContext();
76
+ if (user === undefined) {
77
+ return null;
78
+ }
79
+ if (user === null) {
80
+ return fallback !== undefined ? fallback : _jsx(DefaultSignIn, { atrium: atrium });
81
+ }
82
+ return _jsx(_Fragment, { children: children });
83
+ }
84
+ function DefaultSignIn({ atrium }) {
85
+ return (_jsx("button", { type: "button", onClick: () => {
86
+ void atrium.auth.signIn();
87
+ }, children: "Sign in with Atrium" }));
88
+ }
89
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/react/index.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * The armed-set state machine shared by both standing offers (multi-mic scoping,
3
+ * docs/reference/rooms-sessions-protocol.md) — the TypeScript port of Python's ``_ArmedSet``
4
+ * (aio.py). Sources are **connection ids** (the ``from`` the server stamps on a ``*.start`` /
5
+ * ``*.stop`` request, never a client-supplied field).
6
+ *
7
+ * Membership = explicit per-source arms ∪ (an all-arm minus the per-source stops issued *since*
8
+ * that all-arm). A fresh all-arm resets those exclusions (every device shows ON again); an all-stop
9
+ * clears everything. A ``null`` source — a v1 (single implicit source) frame that carries no id — is
10
+ * armed **only under an all-arm** (the v1 compatibility rule, since an unscoped ``start`` arms all):
11
+ * a scoped per-source arm deliberately excludes id-less v1 audio so it can't bleed into a scoped
12
+ * session.
13
+ */
14
+ export declare class ArmedSet {
15
+ private all;
16
+ private readonly explicitSet;
17
+ private readonly excludedSet;
18
+ arm(source: string): void;
19
+ armAll(): void;
20
+ disarm(source: string): void;
21
+ /** Move an explicit arm from a departed connection id to its same-name reconnect (a new id), so a
22
+ * per-source-armed device that drops and returns within grace stays admitted (its consent — they
23
+ * pressed ON — survives a wifi blip). No-op unless ``old`` was explicitly armed. */
24
+ migrate(oldId: string, newId: string): void;
25
+ clear(): void;
26
+ isArmed(source: string | null): boolean;
27
+ /** The explicitly per-source-armed connection ids (drives the arm-time source cap). */
28
+ get explicit(): Set<string>;
29
+ /** True while a standing all-arm is in effect (drives the roster-enumerated active set). */
30
+ get allArmed(): boolean;
31
+ get any(): boolean;
32
+ }
33
+ //# sourceMappingURL=armed-set.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"armed-set.d.ts","sourceRoot":"","sources":["../../src/rooms/armed-set.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,GAAG,CAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAoB;IAChD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAoB;IAEhD,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAKzB,MAAM,IAAI,IAAI;IAKd,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAK5B;;wFAEoF;IACpF,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAQ3C,KAAK,IAAI,IAAI;IAMb,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO;IAMvC,uFAAuF;IACvF,IAAI,QAAQ,IAAI,GAAG,CAAC,MAAM,CAAC,CAE1B;IAED,4FAA4F;IAC5F,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,IAAI,GAAG,IAAI,OAAO,CAEjB;CACF"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * The armed-set state machine shared by both standing offers (multi-mic scoping,
3
+ * docs/reference/rooms-sessions-protocol.md) — the TypeScript port of Python's ``_ArmedSet``
4
+ * (aio.py). Sources are **connection ids** (the ``from`` the server stamps on a ``*.start`` /
5
+ * ``*.stop`` request, never a client-supplied field).
6
+ *
7
+ * Membership = explicit per-source arms ∪ (an all-arm minus the per-source stops issued *since*
8
+ * that all-arm). A fresh all-arm resets those exclusions (every device shows ON again); an all-stop
9
+ * clears everything. A ``null`` source — a v1 (single implicit source) frame that carries no id — is
10
+ * armed **only under an all-arm** (the v1 compatibility rule, since an unscoped ``start`` arms all):
11
+ * a scoped per-source arm deliberately excludes id-less v1 audio so it can't bleed into a scoped
12
+ * session.
13
+ */
14
+ export class ArmedSet {
15
+ all = false;
16
+ explicitSet = new Set();
17
+ excludedSet = new Set();
18
+ arm(source) {
19
+ this.explicitSet.add(source);
20
+ this.excludedSet.delete(source);
21
+ }
22
+ armAll() {
23
+ this.all = true;
24
+ this.excludedSet.clear(); // a fresh all-arm forgets prior per-source stops
25
+ }
26
+ disarm(source) {
27
+ this.explicitSet.delete(source);
28
+ if (this.all)
29
+ this.excludedSet.add(source); // excluded from the standing all-arm
30
+ }
31
+ /** Move an explicit arm from a departed connection id to its same-name reconnect (a new id), so a
32
+ * per-source-armed device that drops and returns within grace stays admitted (its consent — they
33
+ * pressed ON — survives a wifi blip). No-op unless ``old`` was explicitly armed. */
34
+ migrate(oldId, newId) {
35
+ if (this.explicitSet.has(oldId)) {
36
+ this.explicitSet.delete(oldId);
37
+ this.explicitSet.add(newId);
38
+ this.excludedSet.delete(newId);
39
+ }
40
+ }
41
+ clear() {
42
+ this.all = false;
43
+ this.explicitSet.clear();
44
+ this.excludedSet.clear();
45
+ }
46
+ isArmed(source) {
47
+ if (source === null)
48
+ return this.all; // a v1 id-less frame rides ONLY on an all-arm (the v1 rule)
49
+ if (this.explicitSet.has(source))
50
+ return true;
51
+ return this.all && !this.excludedSet.has(source);
52
+ }
53
+ /** The explicitly per-source-armed connection ids (drives the arm-time source cap). */
54
+ get explicit() {
55
+ return this.explicitSet;
56
+ }
57
+ /** True while a standing all-arm is in effect (drives the roster-enumerated active set). */
58
+ get allArmed() {
59
+ return this.all;
60
+ }
61
+ get any() {
62
+ return this.all || this.explicitSet.size > 0;
63
+ }
64
+ }
65
+ //# sourceMappingURL=armed-set.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"armed-set.js","sourceRoot":"","sources":["../../src/rooms/armed-set.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,QAAQ;IACX,GAAG,GAAG,KAAK,CAAA;IACF,WAAW,GAAG,IAAI,GAAG,EAAU,CAAA;IAC/B,WAAW,GAAG,IAAI,GAAG,EAAU,CAAA;IAEhD,GAAG,CAAC,MAAc;QAChB,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;QAC5B,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IACjC,CAAC;IAED,MAAM;QACJ,IAAI,CAAC,GAAG,GAAG,IAAI,CAAA;QACf,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAA,CAAC,iDAAiD;IAC5E,CAAC;IAED,MAAM,CAAC,MAAc;QACnB,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;QAC/B,IAAI,IAAI,CAAC,GAAG;YAAE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA,CAAC,qCAAqC;IAClF,CAAC;IAED;;wFAEoF;IACpF,OAAO,CAAC,KAAa,EAAE,KAAa;QAClC,IAAI,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YAChC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;YAC9B,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;YAC3B,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QAChC,CAAC;IACH,CAAC;IAED,KAAK;QACH,IAAI,CAAC,GAAG,GAAG,KAAK,CAAA;QAChB,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAA;QACxB,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAA;IAC1B,CAAC;IAED,OAAO,CAAC,MAAqB;QAC3B,IAAI,MAAM,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC,GAAG,CAAA,CAAC,4DAA4D;QACjG,IAAI,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC;YAAE,OAAO,IAAI,CAAA;QAC7C,OAAO,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;IAClD,CAAC;IAED,uFAAuF;IACvF,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,WAAW,CAAA;IACzB,CAAC;IAED,4FAA4F;IAC5F,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,GAAG,CAAA;IACjB,CAAC;IAED,IAAI,GAAG;QACL,OAAO,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,GAAG,CAAC,CAAA;IAC9C,CAAC;CACF"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Pure request-shaping for a {@link ./room.Room}'s capability brokers (``offerEmbeds`` /
3
+ * ``offerChat``, docs/reference/rooms-sessions-protocol.md) plus the standing-offer roles — the
4
+ * TypeScript port of Python's ``_brokers.py``. Validation only, no I/O, so it's cheaply unit-testable
5
+ * independent of a transport.
6
+ */
7
+ import { AtriumError } from "../errors.js";
8
+ /** Discoverable presence roles for the capability brokers — merged into ``announce.roles`` so a
9
+ * code-joined peer can find a broker in the presence roster. */
10
+ export declare const EMBED_BROKER_ROLE = "embed-broker";
11
+ export declare const CHAT_BROKER_ROLE = "chat-broker";
12
+ /** Standing-service offer roles (the third broker kind — peer-toggleable via ``<service>.start`` /
13
+ * ``<service>.stop`` requests; see ``offerTranscription`` / ``offerAudioCapture``). */
14
+ export declare const TRANSCRIPTION_OFFER_ROLE = "transcription-offer";
15
+ export declare const CAPTURE_OFFER_ROLE = "capture-offer";
16
+ /** ``offerEmbeds``'s default anchor-count cap on one ``embed.resolve`` request. */
17
+ export declare const DEFAULT_MAX_ANCHORS = 64;
18
+ /** ``offerChat``'s default ``maxTokens`` cap on one ``chat.generate`` reply. */
19
+ export declare const DEFAULT_CHAT_MAX_TOKENS = 512;
20
+ /** A sane request-payload cap for ``chat.generate`` — independent of ``maxTokens`` (which caps the
21
+ * *reply*, not the incoming prompt). */
22
+ export declare const CHAT_MAX_MESSAGES = 50;
23
+ export declare const CHAT_MAX_PAYLOAD_CHARS = 20000;
24
+ /** One anchor, or a whole ``chat.generate`` request, failed to validate/resolve — the message is
25
+ * safe to send back verbatim in an error reply. Under {@link AtriumError} so one ``catch`` covers the
26
+ * whole SDK surface (errors.ts: everything derives from ``AtriumError``). */
27
+ export declare class BrokerError extends AtriumError {
28
+ }
29
+ /** A validated ``embed.resolve`` anchor descriptor — one of text / concept / vector / asset. */
30
+ export type AnchorDescriptor = {
31
+ kind: "text";
32
+ text: string;
33
+ } | {
34
+ kind: "concept";
35
+ concept: string;
36
+ collection: string | null;
37
+ } | {
38
+ kind: "vector";
39
+ vector: number[];
40
+ } | {
41
+ kind: "asset";
42
+ asset: string;
43
+ matchBy: string | null;
44
+ };
45
+ /**
46
+ * Validate one ``embed.resolve`` anchor descriptor (the compare operand JSON shapes) and return its
47
+ * parsed form. Throws {@link BrokerError} on anything malformed. An ``asset`` descriptor resolves
48
+ * through the per-asset vectors endpoint (the broker looks up the asset's stored vector in the
49
+ * request's space).
50
+ */
51
+ export declare function parseAnchorDescriptor(desc: unknown): AnchorDescriptor;
52
+ /** One validated ``chat.generate`` message. */
53
+ export interface ChatMessage {
54
+ role: string;
55
+ content: string;
56
+ }
57
+ /**
58
+ * Validate a ``chat.generate`` request's ``messages`` — a non-empty list of ``{ role, content }``
59
+ * (both strings), under the payload cap. Throws {@link BrokerError} otherwise.
60
+ */
61
+ export declare function validateChatMessages(messages: unknown): ChatMessage[];
62
+ //# sourceMappingURL=brokers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brokers.d.ts","sourceRoot":"","sources":["../../src/rooms/brokers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAE1C;gEACgE;AAChE,eAAO,MAAM,iBAAiB,iBAAiB,CAAA;AAC/C,eAAO,MAAM,gBAAgB,gBAAgB,CAAA;AAE7C;uFACuF;AACvF,eAAO,MAAM,wBAAwB,wBAAwB,CAAA;AAC7D,eAAO,MAAM,kBAAkB,kBAAkB,CAAA;AAEjD,mFAAmF;AACnF,eAAO,MAAM,mBAAmB,KAAK,CAAA;AAErC,gFAAgF;AAChF,eAAO,MAAM,uBAAuB,MAAM,CAAA;AAE1C;wCACwC;AACxC,eAAO,MAAM,iBAAiB,KAAK,CAAA;AACnC,eAAO,MAAM,sBAAsB,QAAS,CAAA;AAE5C;;6EAE6E;AAC7E,qBAAa,WAAY,SAAQ,WAAW;CAAG;AAE/C,gGAAgG;AAChG,MAAM,MAAM,gBAAgB,GACxB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAC/D;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAA;AAM5D;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,OAAO,GAAG,gBAAgB,CA4CrE;AAED,+CAA+C;AAC/C,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CAChB;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,OAAO,GAAG,WAAW,EAAE,CAuBrE"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Pure request-shaping for a {@link ./room.Room}'s capability brokers (``offerEmbeds`` /
3
+ * ``offerChat``, docs/reference/rooms-sessions-protocol.md) plus the standing-offer roles — the
4
+ * TypeScript port of Python's ``_brokers.py``. Validation only, no I/O, so it's cheaply unit-testable
5
+ * independent of a transport.
6
+ */
7
+ import { AtriumError } from "../errors.js";
8
+ /** Discoverable presence roles for the capability brokers — merged into ``announce.roles`` so a
9
+ * code-joined peer can find a broker in the presence roster. */
10
+ export const EMBED_BROKER_ROLE = "embed-broker";
11
+ export const CHAT_BROKER_ROLE = "chat-broker";
12
+ /** Standing-service offer roles (the third broker kind — peer-toggleable via ``<service>.start`` /
13
+ * ``<service>.stop`` requests; see ``offerTranscription`` / ``offerAudioCapture``). */
14
+ export const TRANSCRIPTION_OFFER_ROLE = "transcription-offer";
15
+ export const CAPTURE_OFFER_ROLE = "capture-offer";
16
+ /** ``offerEmbeds``'s default anchor-count cap on one ``embed.resolve`` request. */
17
+ export const DEFAULT_MAX_ANCHORS = 64;
18
+ /** ``offerChat``'s default ``maxTokens`` cap on one ``chat.generate`` reply. */
19
+ export const DEFAULT_CHAT_MAX_TOKENS = 512;
20
+ /** A sane request-payload cap for ``chat.generate`` — independent of ``maxTokens`` (which caps the
21
+ * *reply*, not the incoming prompt). */
22
+ export const CHAT_MAX_MESSAGES = 50;
23
+ export const CHAT_MAX_PAYLOAD_CHARS = 20_000;
24
+ /** One anchor, or a whole ``chat.generate`` request, failed to validate/resolve — the message is
25
+ * safe to send back verbatim in an error reply. Under {@link AtriumError} so one ``catch`` covers the
26
+ * whole SDK surface (errors.ts: everything derives from ``AtriumError``). */
27
+ export class BrokerError extends AtriumError {
28
+ }
29
+ function isNumber(x) {
30
+ return typeof x === "number" && !Number.isNaN(x);
31
+ }
32
+ /**
33
+ * Validate one ``embed.resolve`` anchor descriptor (the compare operand JSON shapes) and return its
34
+ * parsed form. Throws {@link BrokerError} on anything malformed. An ``asset`` descriptor resolves
35
+ * through the per-asset vectors endpoint (the broker looks up the asset's stored vector in the
36
+ * request's space).
37
+ */
38
+ export function parseAnchorDescriptor(desc) {
39
+ if (typeof desc !== "object" || desc === null || Array.isArray(desc)) {
40
+ throw new BrokerError("anchor descriptor must be a JSON object");
41
+ }
42
+ const obj = desc;
43
+ const present = ["text", "concept", "vector", "asset"].filter((k) => k in obj);
44
+ if (present.length !== 1) {
45
+ throw new BrokerError("anchor descriptor needs exactly one of text/concept/vector/asset");
46
+ }
47
+ const kind = present[0];
48
+ if (kind === "asset") {
49
+ const asset = obj.asset;
50
+ if (typeof asset !== "string" || asset.trim() === "") {
51
+ throw new BrokerError("asset must be a non-empty id string");
52
+ }
53
+ const matchBy = obj.match_by;
54
+ if (matchBy !== undefined && matchBy !== null && typeof matchBy !== "string") {
55
+ throw new BrokerError("match_by must be a string");
56
+ }
57
+ return { kind: "asset", asset, matchBy: matchBy ?? null };
58
+ }
59
+ if (kind === "vector") {
60
+ const vec = obj.vector;
61
+ if (!Array.isArray(vec) || vec.length === 0 || !vec.every(isNumber)) {
62
+ throw new BrokerError("vector must be a non-empty list of numbers");
63
+ }
64
+ return { kind: "vector", vector: vec.map(Number) };
65
+ }
66
+ if (kind === "text") {
67
+ const text = obj.text;
68
+ if (typeof text !== "string" || text.trim() === "") {
69
+ throw new BrokerError("text must be a non-empty string");
70
+ }
71
+ return { kind: "text", text };
72
+ }
73
+ const concept = obj.concept;
74
+ if (typeof concept !== "string" || concept.trim() === "") {
75
+ throw new BrokerError("concept must be a non-empty string");
76
+ }
77
+ const collection = obj.collection;
78
+ if (collection !== undefined && collection !== null && typeof collection !== "string") {
79
+ throw new BrokerError("collection must be a string");
80
+ }
81
+ return { kind: "concept", concept, collection: collection ?? null };
82
+ }
83
+ /**
84
+ * Validate a ``chat.generate`` request's ``messages`` — a non-empty list of ``{ role, content }``
85
+ * (both strings), under the payload cap. Throws {@link BrokerError} otherwise.
86
+ */
87
+ export function validateChatMessages(messages) {
88
+ if (!Array.isArray(messages) || messages.length === 0) {
89
+ throw new BrokerError("messages must be a non-empty list");
90
+ }
91
+ if (messages.length > CHAT_MAX_MESSAGES) {
92
+ throw new BrokerError(`too many messages (${messages.length} > ${CHAT_MAX_MESSAGES})`);
93
+ }
94
+ let totalChars = 0;
95
+ for (const message of messages) {
96
+ if (typeof message !== "object" ||
97
+ message === null ||
98
+ typeof message.role !== "string" ||
99
+ typeof message.content !== "string") {
100
+ throw new BrokerError("each message needs a string role and content");
101
+ }
102
+ totalChars += message.content.length;
103
+ }
104
+ if (totalChars > CHAT_MAX_PAYLOAD_CHARS) {
105
+ throw new BrokerError(`messages exceed ${CHAT_MAX_PAYLOAD_CHARS} characters`);
106
+ }
107
+ return messages;
108
+ }
109
+ //# sourceMappingURL=brokers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brokers.js","sourceRoot":"","sources":["../../src/rooms/brokers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Audio-signal wire protocol — extracted verbatim from the Player/tools implementation
3
+ * (``tools/src/lib/audio-frame.ts`` + ``audio-protocol.ts``) so the SDK decodes exactly what a
4
+ * hosted Player produces.
5
+ *
6
+ * Two channels ride a room (see ``docs/plans/audio-signal-streaming.md``):
7
+ * • the continuous per-frame analysis stream → **raw binary** frames (this file's
8
+ * {@link decodeAudioFrame}), quantized to bytes; visualization doesn't need float precision.
9
+ * • everything else (track context, discrete beats, producer discovery) → **text signals**, whose
10
+ * type names and payload shapes are pinned by {@link AUDIO_SIGNAL} / the interfaces below.
11
+ */
12
+ export declare const AUDIO_FRAME_MAGIC = 161;
13
+ export declare const AUDIO_FRAME_VERSION = 1;
14
+ /** One analysis frame in normalized units — every scalar 0..1 except ``bpm`` (BPM) and ``onsetRate``. */
15
+ export interface AudioFrame {
16
+ level: number;
17
+ peak: number;
18
+ centroid: number;
19
+ flatness: number;
20
+ rolloff: number;
21
+ beatPhase: number;
22
+ energyTrend: number;
23
+ onsetRate: number;
24
+ bpm: number;
25
+ bands: number[];
26
+ }
27
+ /** Pack a frame into a compact binary buffer. Bands are capped at 255. */
28
+ export declare function encodeAudioFrame(f: AudioFrame): ArrayBuffer;
29
+ /** Decode a binary frame, or ``null`` if it isn't a recognized audio frame (foreign/short/bad magic). */
30
+ export declare function decodeAudioFrame(data: ArrayBuffer): AudioFrame | null;
31
+ /** True if a binary frame looks like an audio frame (cheap magic check before a full decode). */
32
+ export declare function isAudioFrame(data: ArrayBuffer): boolean;
33
+ export declare const AUDIO_SIGNAL: {
34
+ /** Producer → room: structural track context (bpm/key/beat grid). Low-rate, re-emitted to joiners. */
35
+ readonly track: "audio.track";
36
+ /** Producer → room: an instantaneous beat event. */
37
+ readonly beat: "audio.beat";
38
+ /** Consumer → room: "who can provide audio analysis?" (carries an ack_id). */
39
+ readonly discover: "audio.discover";
40
+ /** Producer → consumer: availability announcement (reply_to a discover, or a proactive broadcast). */
41
+ readonly announce: "audio.announce";
42
+ };
43
+ /**
44
+ * Presence roles announced on room join (in ``announce.role``). Producers and consumers advertise
45
+ * themselves so a producer can tell whether a consumer is present (demand) and which producer is
46
+ * elected to broadcast (lowest connection_id among producers).
47
+ */
48
+ export declare const AUDIO_ROLE: {
49
+ readonly producer: "audio-analysis";
50
+ readonly consumer: "audio-consumer";
51
+ };
52
+ export type AudioInputKind = "playback" | "mic";
53
+ export interface AudioTrack {
54
+ /** Producer identity (e.g. ``analyzer:studio``). */
55
+ source: string;
56
+ input: AudioInputKind;
57
+ name?: string;
58
+ assetId?: string;
59
+ bpm?: number | null;
60
+ key?: string;
61
+ mode?: string;
62
+ durationS?: number;
63
+ /** Precomputed beat times in seconds (playback input only). */
64
+ beatGrid?: number[];
65
+ sections?: {
66
+ t: number;
67
+ label?: string;
68
+ }[];
69
+ }
70
+ export interface AudioBeatEvent {
71
+ /** Producer clock (ms). */
72
+ t: number;
73
+ strength: number;
74
+ kind?: "beat" | "onset" | "downbeat";
75
+ }
76
+ export interface AudioAnnounce {
77
+ identity: string;
78
+ input: AudioInputKind;
79
+ name?: string;
80
+ }
81
+ /**
82
+ * A decoded audio-signal event, as delivered to a {@link "./room".Room.audioSignals} subscriber.
83
+ * Discriminated by ``kind`` so a consumer switches on it: continuous ``frame``s carry the
84
+ * loudness/spectrum stream, ``beat``s the discrete onsets, ``track`` the structural context, and
85
+ * ``announce`` a producer's availability.
86
+ */
87
+ export type AudioSignal = {
88
+ kind: "frame";
89
+ frame: AudioFrame;
90
+ } | {
91
+ kind: "beat";
92
+ beat: AudioBeatEvent;
93
+ } | {
94
+ kind: "track";
95
+ track: AudioTrack;
96
+ } | {
97
+ kind: "announce";
98
+ announce: AudioAnnounce;
99
+ };
100
+ //# sourceMappingURL=codec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codec.d.ts","sourceRoot":"","sources":["../../src/rooms/codec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,eAAO,MAAM,iBAAiB,MAAO,CAAA;AACrC,eAAO,MAAM,mBAAmB,IAAI,CAAA;AAGpC,yGAAyG;AACzG,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,EAAE,CAAA;CAChB;AAUD,0EAA0E;AAC1E,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,UAAU,GAAG,WAAW,CAsB3D;AAED,yGAAyG;AACzG,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,WAAW,GAAG,UAAU,GAAG,IAAI,CAuBrE;AAED,iGAAiG;AACjG,wBAAgB,YAAY,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAEvD;AAID,eAAO,MAAM,YAAY;IACvB,sGAAsG;;IAEtG,oDAAoD;;IAEpD,8EAA8E;;IAE9E,sGAAsG;;CAE9F,CAAA;AAEV;;;;GAIG;AACH,eAAO,MAAM,UAAU;;;CAGb,CAAA;AAEV,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,KAAK,CAAA;AAE/C,MAAM,WAAW,UAAU;IACzB,oDAAoD;IACpD,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,cAAc,CAAA;IACrB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB,QAAQ,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAC3C;AAED,MAAM,WAAW,cAAc;IAC7B,2BAA2B;IAC3B,CAAC,EAAE,MAAM,CAAA;IACT,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,UAAU,CAAA;CACrC;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,cAAc,CAAA;IACrB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED;;;;;GAKG;AACH,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,UAAU,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,cAAc,CAAA;CAAE,GACtC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,UAAU,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,aAAa,CAAA;CAAE,CAAA"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Audio-signal wire protocol — extracted verbatim from the Player/tools implementation
3
+ * (``tools/src/lib/audio-frame.ts`` + ``audio-protocol.ts``) so the SDK decodes exactly what a
4
+ * hosted Player produces.
5
+ *
6
+ * Two channels ride a room (see ``docs/plans/audio-signal-streaming.md``):
7
+ * • the continuous per-frame analysis stream → **raw binary** frames (this file's
8
+ * {@link decodeAudioFrame}), quantized to bytes; visualization doesn't need float precision.
9
+ * • everything else (track context, discrete beats, producer discovery) → **text signals**, whose
10
+ * type names and payload shapes are pinned by {@link AUDIO_SIGNAL} / the interfaces below.
11
+ */
12
+ // --- binary frame codec (the "hot" channel) ----------------------------------------------------
13
+ export const AUDIO_FRAME_MAGIC = 0xa1;
14
+ export const AUDIO_FRAME_VERSION = 1;
15
+ const HEADER_BYTES = 13; // magic, version, nBands, 8 scalar u8s, bpm u16
16
+ const clamp01 = (x) => (x <= 0 ? 0 : x >= 1 ? 1 : x);
17
+ const q8 = (x) => Math.round(clamp01(x) * 255); // 0..1 → byte
18
+ const dq8 = (b) => b / 255; // byte → 0..1
19
+ // onsetRate spans ~0..25 /s; store at 0.1 resolution in a byte (0..25.5).
20
+ const qOnset = (x) => Math.round(Math.min(Math.max(x, 0), 25.5) * 10);
21
+ const dqOnset = (b) => b / 10;
22
+ /** Pack a frame into a compact binary buffer. Bands are capped at 255. */
23
+ export function encodeAudioFrame(f) {
24
+ const n = Math.min(f.bands.length, 255);
25
+ const buf = new ArrayBuffer(HEADER_BYTES + n);
26
+ const view = new DataView(buf);
27
+ view.setUint8(0, AUDIO_FRAME_MAGIC);
28
+ view.setUint8(1, AUDIO_FRAME_VERSION);
29
+ view.setUint8(2, n);
30
+ view.setUint8(3, q8(f.level));
31
+ view.setUint8(4, q8(f.peak));
32
+ view.setUint8(5, q8(f.centroid));
33
+ view.setUint8(6, q8(f.flatness));
34
+ view.setUint8(7, q8(f.rolloff));
35
+ view.setUint8(8, q8(f.beatPhase));
36
+ view.setUint8(9, q8(f.energyTrend));
37
+ view.setUint8(10, qOnset(f.onsetRate));
38
+ view.setUint16(11, Math.min(Math.round(Math.max(f.bpm, 0)), 65535), true);
39
+ const bytes = new Uint8Array(buf);
40
+ // The `?? 0` here and in `decodeAudioFrame` are the only deliberate divergences from the source
41
+ // `tools/src/lib/audio-frame.ts` (which indexes `f.bands[i]` bare) — the SDK's stricter
42
+ // `noUncheckedIndexedAccess` needs the guard. tools/ migrates onto this module later (plan step 3).
43
+ for (let i = 0; i < n; i++)
44
+ bytes[HEADER_BYTES + i] = q8(f.bands[i] ?? 0);
45
+ return buf;
46
+ }
47
+ /** Decode a binary frame, or ``null`` if it isn't a recognized audio frame (foreign/short/bad magic). */
48
+ export function decodeAudioFrame(data) {
49
+ if (data.byteLength < HEADER_BYTES)
50
+ return null;
51
+ const view = new DataView(data);
52
+ if (view.getUint8(0) !== AUDIO_FRAME_MAGIC)
53
+ return null;
54
+ if (view.getUint8(1) !== AUDIO_FRAME_VERSION)
55
+ return null;
56
+ const n = view.getUint8(2);
57
+ if (data.byteLength < HEADER_BYTES + n)
58
+ return null;
59
+ const bytes = new Uint8Array(data);
60
+ const bands = new Array(n);
61
+ // `?? 0`: see the note in `encodeAudioFrame` — a `noUncheckedIndexedAccess` guard, not in tools/.
62
+ for (let i = 0; i < n; i++)
63
+ bands[i] = dq8(bytes[HEADER_BYTES + i] ?? 0);
64
+ return {
65
+ level: dq8(view.getUint8(3)),
66
+ peak: dq8(view.getUint8(4)),
67
+ centroid: dq8(view.getUint8(5)),
68
+ flatness: dq8(view.getUint8(6)),
69
+ rolloff: dq8(view.getUint8(7)),
70
+ beatPhase: dq8(view.getUint8(8)),
71
+ energyTrend: dq8(view.getUint8(9)),
72
+ onsetRate: dqOnset(view.getUint8(10)),
73
+ bpm: view.getUint16(11, true),
74
+ bands,
75
+ };
76
+ }
77
+ /** True if a binary frame looks like an audio frame (cheap magic check before a full decode). */
78
+ export function isAudioFrame(data) {
79
+ return data.byteLength >= 2 && new Uint8Array(data)[0] === AUDIO_FRAME_MAGIC;
80
+ }
81
+ // --- text-signal names + payload shapes (the reliable channel) ---------------------------------
82
+ export const AUDIO_SIGNAL = {
83
+ /** Producer → room: structural track context (bpm/key/beat grid). Low-rate, re-emitted to joiners. */
84
+ track: "audio.track",
85
+ /** Producer → room: an instantaneous beat event. */
86
+ beat: "audio.beat",
87
+ /** Consumer → room: "who can provide audio analysis?" (carries an ack_id). */
88
+ discover: "audio.discover",
89
+ /** Producer → consumer: availability announcement (reply_to a discover, or a proactive broadcast). */
90
+ announce: "audio.announce",
91
+ };
92
+ /**
93
+ * Presence roles announced on room join (in ``announce.role``). Producers and consumers advertise
94
+ * themselves so a producer can tell whether a consumer is present (demand) and which producer is
95
+ * elected to broadcast (lowest connection_id among producers).
96
+ */
97
+ export const AUDIO_ROLE = {
98
+ producer: "audio-analysis",
99
+ consumer: "audio-consumer",
100
+ };
101
+ //# sourceMappingURL=codec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codec.js","sourceRoot":"","sources":["../../src/rooms/codec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /** The live rooms surface — the {@link Room} handle, its audio codec, and the loginless
2
+ * {@link joinRoom} entry (no client needed, just a connect code). */
3
+ import { Room, type RoomTransportMode } from "./room.js";
4
+ import type { FetchImpl } from "./sse.js";
5
+ import type { WebSocketCtor } from "./transport.js";
6
+ export { ArmedSet } from "./armed-set.js";
7
+ export { type AnchorDescriptor, BrokerError, CAPTURE_OFFER_ROLE, CHAT_BROKER_ROLE, DEFAULT_CHAT_MAX_TOKENS, DEFAULT_MAX_ANCHORS, EMBED_BROKER_ROLE, parseAnchorDescriptor, TRANSCRIPTION_OFFER_ROLE, validateChatMessages, } from "./brokers.js";
8
+ export { AUDIO_ROLE, AUDIO_SIGNAL, type AudioAnnounce, type AudioBeatEvent, type AudioFrame, type AudioInputKind, type AudioSignal, type AudioTrack, decodeAudioFrame, encodeAudioFrame, isAudioFrame, } from "./codec.js";
9
+ export { type CaptureOfferDeps, type CaptureRecorder, OfferedCapture } from "./offer-capture.js";
10
+ export { OfferedTranscription, type TranscriptionOfferDeps } from "./offer-transcription.js";
11
+ export { mergeRoles, type Participant, type ParticipantPredicate, parseParticipant, participantMatches, } from "./participant.js";
12
+ export { Recorder, type RecorderStopReason } from "./recorder.js";
13
+ export { type AudioClip, type AudioVector, type Handler, Room, type RoomAudioClient, type RoomDeps, type RoomEvent, type RoomTransportMode, type ScoredAudio, } from "./room.js";
14
+ export { AUDIO_SNIPPET_CONSUMER_ROLE, AUDIO_SNIPPET_MAGIC, AUDIO_SNIPPET_SOURCE_ROLE, AUDIO_SNIPPET_VERSION, AUDIO_SNIPPET_VERSION_2, type AudioSnippetFrame, CAPTURE_SOURCE_ROLE, decodeAudioSnippetFrame, isAudioSnippetFrame, } from "./snippet.js";
15
+ export { type FetchImpl, RoomEventStream, readObserveRoster } from "./sse.js";
16
+ export { type ActiveSource, OFFER_MAX_SOURCES, type OfferDeps, StandingSource, } from "./standing-source.js";
17
+ export { TRANSCRIBER_SOURCE, Transcriber, type TranscriberDeps } from "./transcriber.js";
18
+ export type { RoomEndReason, RoomSignal, RoomTransport, RosterEntry, WebSocketCtor, WebSocketLike, } from "./transport.js";
19
+ /** Options for the loginless {@link joinRoom} (a subset of {@link RoomDeps} — no account). */
20
+ export interface JoinRoomOptions {
21
+ /** The instance base URL. Falls back to ``ATRIUM_BASE_URL``. */
22
+ baseUrl?: string;
23
+ identity?: string;
24
+ announce?: Record<string, unknown>;
25
+ requestTimeout?: number;
26
+ reconnect?: boolean;
27
+ /** Signal transport preference (default ``"auto"`` — WS, falling back to SSE behind a proxy). */
28
+ transport?: RoomTransportMode;
29
+ WebSocketCtor?: WebSocketCtor;
30
+ /** Injected ``fetch`` for the SSE transport / roster reads — the test seam. */
31
+ fetchImpl?: FetchImpl;
32
+ signal?: AbortSignal;
33
+ }
34
+ /**
35
+ * Join a room by its connect code — **no account, no client**. Resolves the code to a room, then
36
+ * returns a live {@link Room} handle that can ``send`` / ``on`` / ``request`` / play / consume audio
37
+ * signals (but not manage the room — that needs the owner). Mirrors the Python SDK's ``join_room``.
38
+ */
39
+ export declare function joinRoom(code: string, opts?: JoinRoomOptions): Promise<Room>;
40
+ //# sourceMappingURL=index.d.ts.map