@memberjunction/livekit-room-server 6.2.0-edge.2 → 6.2.0-edge.4

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 (82) hide show
  1. package/README.md +85 -0
  2. package/dist/index.d.ts +18 -2
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +18 -1
  5. package/dist/index.js.map +1 -1
  6. package/dist/livekit-agent-room-coordinator.d.ts +220 -13
  7. package/dist/livekit-agent-room-coordinator.d.ts.map +1 -1
  8. package/dist/livekit-agent-room-coordinator.js +409 -65
  9. package/dist/livekit-agent-room-coordinator.js.map +1 -1
  10. package/dist/livekit-egress-service.d.ts +7 -0
  11. package/dist/livekit-egress-service.d.ts.map +1 -1
  12. package/dist/livekit-egress-service.js +11 -0
  13. package/dist/livekit-egress-service.js.map +1 -1
  14. package/dist/livekit-native-module.d.ts +18 -0
  15. package/dist/livekit-native-module.d.ts.map +1 -0
  16. package/dist/livekit-native-module.js +27 -0
  17. package/dist/livekit-native-module.js.map +1 -0
  18. package/dist/livekit-participant-service.d.ts +47 -0
  19. package/dist/livekit-participant-service.d.ts.map +1 -0
  20. package/dist/livekit-participant-service.js +64 -0
  21. package/dist/livekit-participant-service.js.map +1 -0
  22. package/dist/livekit-sip-service.d.ts +141 -0
  23. package/dist/livekit-sip-service.d.ts.map +1 -0
  24. package/dist/livekit-sip-service.js +169 -0
  25. package/dist/livekit-sip-service.js.map +1 -0
  26. package/dist/livekit-token-service.d.ts +26 -5
  27. package/dist/livekit-token-service.d.ts.map +1 -1
  28. package/dist/livekit-token-service.js +22 -7
  29. package/dist/livekit-token-service.js.map +1 -1
  30. package/dist/livekit-webhook.d.ts +65 -0
  31. package/dist/livekit-webhook.d.ts.map +1 -0
  32. package/dist/livekit-webhook.js +65 -0
  33. package/dist/livekit-webhook.js.map +1 -0
  34. package/dist/meeting-dial-in-service.d.ts +83 -0
  35. package/dist/meeting-dial-in-service.d.ts.map +1 -0
  36. package/dist/meeting-dial-in-service.js +202 -0
  37. package/dist/meeting-dial-in-service.js.map +1 -0
  38. package/dist/room-audio/audio-decoder.d.ts +40 -0
  39. package/dist/room-audio/audio-decoder.d.ts.map +1 -0
  40. package/dist/room-audio/audio-decoder.js +205 -0
  41. package/dist/room-audio/audio-decoder.js.map +1 -0
  42. package/dist/room-audio/comfort-tone.d.ts +23 -0
  43. package/dist/room-audio/comfort-tone.d.ts.map +1 -0
  44. package/dist/room-audio/comfort-tone.js +70 -0
  45. package/dist/room-audio/comfort-tone.js.map +1 -0
  46. package/dist/room-audio/pcm-frame-pump.d.ts +134 -0
  47. package/dist/room-audio/pcm-frame-pump.d.ts.map +1 -0
  48. package/dist/room-audio/pcm-frame-pump.js +253 -0
  49. package/dist/room-audio/pcm-frame-pump.js.map +1 -0
  50. package/dist/room-audio/room-audio-decode-cache.d.ts +37 -0
  51. package/dist/room-audio/room-audio-decode-cache.d.ts.map +1 -0
  52. package/dist/room-audio/room-audio-decode-cache.js +75 -0
  53. package/dist/room-audio/room-audio-decode-cache.js.map +1 -0
  54. package/dist/room-audio/room-audio-player.d.ts +178 -0
  55. package/dist/room-audio/room-audio-player.d.ts.map +1 -0
  56. package/dist/room-audio/room-audio-player.js +404 -0
  57. package/dist/room-audio/room-audio-player.js.map +1 -0
  58. package/dist/room-audio/room-audio-sources.d.ts +47 -0
  59. package/dist/room-audio/room-audio-sources.d.ts.map +1 -0
  60. package/dist/room-audio/room-audio-sources.js +116 -0
  61. package/dist/room-audio/room-audio-sources.js.map +1 -0
  62. package/dist/room-audio/room-speech-synthesizer.d.ts +55 -0
  63. package/dist/room-audio/room-speech-synthesizer.d.ts.map +1 -0
  64. package/dist/room-audio/room-speech-synthesizer.js +56 -0
  65. package/dist/room-audio/room-speech-synthesizer.js.map +1 -0
  66. package/dist/room-authorization.d.ts +58 -0
  67. package/dist/room-authorization.d.ts.map +1 -0
  68. package/dist/room-authorization.js +212 -0
  69. package/dist/room-authorization.js.map +1 -0
  70. package/dist/room-handoff/handoff-offer-registry.d.ts +147 -0
  71. package/dist/room-handoff/handoff-offer-registry.d.ts.map +1 -0
  72. package/dist/room-handoff/handoff-offer-registry.js +548 -0
  73. package/dist/room-handoff/handoff-offer-registry.js.map +1 -0
  74. package/dist/room-handoff/handoff-types.d.ts +172 -0
  75. package/dist/room-handoff/handoff-types.d.ts.map +1 -0
  76. package/dist/room-handoff/handoff-types.js +16 -0
  77. package/dist/room-handoff/handoff-types.js.map +1 -0
  78. package/dist/room-handoff/room-handoff-engine.d.ts +149 -0
  79. package/dist/room-handoff/room-handoff-engine.d.ts.map +1 -0
  80. package/dist/room-handoff/room-handoff-engine.js +563 -0
  81. package/dist/room-handoff/room-handoff-engine.js.map +1 -0
  82. package/package.json +15 -9
@@ -64,6 +64,17 @@ export class LiveKitEgressService {
64
64
  const list = await this.client.listEgress({ roomName, active: true });
65
65
  return list.map((info) => this.toRecordingInfo(info, roomName));
66
66
  }
67
+ /**
68
+ * Looks up the room name for an egress id.
69
+ *
70
+ * @param egressId The egress id to query.
71
+ * @returns The room name, or `undefined` if not found.
72
+ */
73
+ async GetRoomForEgress(egressId) {
74
+ const list = await this.client.listEgress({ egressId });
75
+ const info = list?.[0];
76
+ return info?.roomName || undefined;
77
+ }
67
78
  /** Maps an SDK `EgressInfo` to the normalized {@link RecordingInfo}. */
68
79
  toRecordingInfo(info, roomName) {
69
80
  const result = {
@@ -1 +1 @@
1
- {"version":3,"file":"livekit-egress-service.js","sourceRoot":"","sources":["../src/livekit-egress-service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"livekit-egress-service.js","sourceRoot":"","sources":["../src/livekit-egress-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @fileoverview Where a server-side LiveKit bot (an agent voice, a hold-music player) finds the native room-client
3
+ * wrapper it joins a room with. One resolution rule for every bot in this package, so an operator who points
4
+ * `LIVEKIT_NATIVE_MODULE` at a custom wrapper changes all of them at once.
5
+ *
6
+ * @module @memberjunction/livekit-room-server
7
+ */
8
+ /** The default native room-client wrapper — the `@livekit/rtc-node`-backed package this repo ships. */
9
+ export declare const DEFAULT_LIVEKIT_NATIVE_MODULE = "@memberjunction/ai-bridge-livekit-native";
10
+ /**
11
+ * Resolves the module specifier of the native LiveKit room-client wrapper: an explicit override (tests, a host that
12
+ * wires its own), else the `LIVEKIT_NATIVE_MODULE` environment variable (e.g. a deployment's custom-sample-rate
13
+ * wrapper), else {@link DEFAULT_LIVEKIT_NATIVE_MODULE}.
14
+ *
15
+ * @param override An explicit specifier that wins over the environment and the default.
16
+ */
17
+ export declare function ResolveLiveKitNativeModuleSpecifier(override?: string): string;
18
+ //# sourceMappingURL=livekit-native-module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"livekit-native-module.d.ts","sourceRoot":"","sources":["../src/livekit-native-module.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,uGAAuG;AACvG,eAAO,MAAM,6BAA6B,6CAA6C,CAAC;AAExF;;;;;;GAMG;AACH,wBAAgB,mCAAmC,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAE7E"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * @fileoverview Where a server-side LiveKit bot (an agent voice, a hold-music player) finds the native room-client
3
+ * wrapper it joins a room with. One resolution rule for every bot in this package, so an operator who points
4
+ * `LIVEKIT_NATIVE_MODULE` at a custom wrapper changes all of them at once.
5
+ *
6
+ * @module @memberjunction/livekit-room-server
7
+ */
8
+ import { RegisterNativeRoomModule } from '@memberjunction/ai-bridge-livekit';
9
+ import NativeRoomModuleDefault from '@memberjunction/ai-bridge-livekit-native';
10
+ /** The default native room-client wrapper — the `@livekit/rtc-node`-backed package this repo ships. */
11
+ export const DEFAULT_LIVEKIT_NATIVE_MODULE = '@memberjunction/ai-bridge-livekit-native';
12
+ /**
13
+ * Resolves the module specifier of the native LiveKit room-client wrapper: an explicit override (tests, a host that
14
+ * wires its own), else the `LIVEKIT_NATIVE_MODULE` environment variable (e.g. a deployment's custom-sample-rate
15
+ * wrapper), else {@link DEFAULT_LIVEKIT_NATIVE_MODULE}.
16
+ *
17
+ * @param override An explicit specifier that wins over the environment and the default.
18
+ */
19
+ export function ResolveLiveKitNativeModuleSpecifier(override) {
20
+ return override ?? process.env.LIVEKIT_NATIVE_MODULE ?? DEFAULT_LIVEKIT_NATIVE_MODULE;
21
+ }
22
+ // The bridge package's loader cannot `import()` the default wrapper itself: it does not (and, to avoid a dependency
23
+ // cycle, must not) declare it, so the bare specifier does not resolve from there under pnpm's strict layout. This
24
+ // package declares the wrapper, so it imports it statically and registers it for the loader to find. An override
25
+ // specifier (`LIVEKIT_NATIVE_MODULE`) that is not registered still goes through the loader's `import()`.
26
+ RegisterNativeRoomModule(DEFAULT_LIVEKIT_NATIVE_MODULE, NativeRoomModuleDefault);
27
+ //# sourceMappingURL=livekit-native-module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"livekit-native-module.js","sourceRoot":"","sources":["../src/livekit-native-module.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,wBAAwB,EAAE,MAAM,mCAAmC,CAAC;AAC7E,OAAO,uBAAuB,MAAM,0CAA0C,CAAC;AAE/E,uGAAuG;AACvG,MAAM,CAAC,MAAM,6BAA6B,GAAG,0CAA0C,CAAC;AAExF;;;;;;GAMG;AACH,MAAM,UAAU,mCAAmC,CAAC,QAAiB;IACnE,OAAO,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAI,6BAA6B,CAAC;AACxF,CAAC;AAED,oHAAoH;AACpH,kHAAkH;AAClH,iHAAiH;AACjH,yGAAyG;AACzG,wBAAwB,CAAC,6BAA6B,EAAE,uBAAuB,CAAC,CAAC"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * @fileoverview {@link LiveKitParticipantService} — changes a participant in a live room through LiveKit's
3
+ * `RoomServiceClient` (`livekit-server-sdk`). Today it records whether a person lets agents see their camera and shared
4
+ * screen. A participant's token can't change its own attributes: MJ's tokens carry no `canUpdateOwnMetadata`, because
5
+ * the same right would let anyone rename themselves and rewrite the metadata that carries their role. So the server
6
+ * sets the attribute for them, once MJAPI has worked out who is asking.
7
+ *
8
+ * @module @memberjunction/livekit-room-server
9
+ */
10
+ import { RoomServiceClient } from 'livekit-server-sdk';
11
+ import { type LiveKitServerConfig } from './livekit-token-service.js';
12
+ /** The subset of {@link RoomServiceClient} the service drives — an injectable seam for unit testing. */
13
+ export type ParticipantUpdateClientLike = Pick<RoomServiceClient, 'updateParticipant'>;
14
+ /** The outcome of changing a participant. */
15
+ export interface ParticipantUpdateResult {
16
+ /** Whether LiveKit applied the change. */
17
+ Success: boolean;
18
+ /** `true` when LiveKit refused because that participant (or the room) does not exist. */
19
+ NotInRoom?: boolean;
20
+ /** What went wrong, when it failed. */
21
+ ErrorMessage?: string;
22
+ }
23
+ /** Changes participants in live LiveKit rooms, on the server's authority. */
24
+ export declare class LiveKitParticipantService {
25
+ private readonly configured;
26
+ private readonly client;
27
+ /**
28
+ * @param config Explicit credentials; omitted fields fall back to environment variables (via
29
+ * {@link LiveKitTokenService}). The room service client uses the HTTP(S) form of the server URL.
30
+ * @param client An injectable room service client (primarily for unit testing); defaults to a real
31
+ * `RoomServiceClient` built from the resolved credentials.
32
+ */
33
+ constructor(config?: Partial<LiveKitServerConfig>, client?: ParticipantUpdateClientLike);
34
+ /**
35
+ * Records whether a person lets agents see their camera and shared screen: sets their `mj.agentCanSee` attribute to
36
+ * `'true'`, or removes it. The caller must already have established that `identity` is the person asking.
37
+ *
38
+ * @param roomName The room the person is in.
39
+ * @param identity The person's participant identity.
40
+ * @param allow `true` to let agents see, `false` to stop.
41
+ * @returns Whether LiveKit applied it; never throws.
42
+ */
43
+ SetAgentVision(roomName: string, identity: string, allow: boolean): Promise<ParticipantUpdateResult>;
44
+ /** Sets (or, with `''`, removes) a participant's attributes; reports LiveKit's refusal instead of throwing. */
45
+ private updateAttributes;
46
+ }
47
+ //# sourceMappingURL=livekit-participant-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"livekit-participant-service.d.ts","sourceRoot":"","sources":["../src/livekit-participant-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,iBAAiB,EAAc,MAAM,oBAAoB,CAAC;AAEnE,OAAO,EAAuB,KAAK,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAGxF,wGAAwG;AACxG,MAAM,MAAM,2BAA2B,GAAG,IAAI,CAAC,iBAAiB,EAAE,mBAAmB,CAAC,CAAC;AAEvF,6CAA6C;AAC7C,MAAM,WAAW,uBAAuB;IACtC,0CAA0C;IAC1C,OAAO,EAAE,OAAO,CAAC;IACjB,yFAAyF;IACzF,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,uCAAuC;IACvC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,6EAA6E;AAC7E,qBAAa,yBAAyB;IACpC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAU;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA8B;IAErD;;;;;OAKG;gBACS,MAAM,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC,EAAE,2BAA2B;IAOvF;;;;;;;;OAQG;IACU,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,uBAAuB,CAAC;IAIjH,+GAA+G;YACjG,gBAAgB;CAc/B"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * @fileoverview {@link LiveKitParticipantService} — changes a participant in a live room through LiveKit's
3
+ * `RoomServiceClient` (`livekit-server-sdk`). Today it records whether a person lets agents see their camera and shared
4
+ * screen. A participant's token can't change its own attributes: MJ's tokens carry no `canUpdateOwnMetadata`, because
5
+ * the same right would let anyone rename themselves and rewrite the metadata that carries their role. So the server
6
+ * sets the attribute for them, once MJAPI has worked out who is asking.
7
+ *
8
+ * @module @memberjunction/livekit-room-server
9
+ */
10
+ import { RoomServiceClient, TwirpError } from 'livekit-server-sdk';
11
+ import { AgentVisionAttributes } from '@memberjunction/ai';
12
+ import { LiveKitTokenService } from './livekit-token-service.js';
13
+ import { WsToHttpUrl } from './livekit-egress-service.js';
14
+ /** Changes participants in live LiveKit rooms, on the server's authority. */
15
+ export class LiveKitParticipantService {
16
+ /**
17
+ * @param config Explicit credentials; omitted fields fall back to environment variables (via
18
+ * {@link LiveKitTokenService}). The room service client uses the HTTP(S) form of the server URL.
19
+ * @param client An injectable room service client (primarily for unit testing); defaults to a real
20
+ * `RoomServiceClient` built from the resolved credentials.
21
+ */
22
+ constructor(config, client) {
23
+ const token = new LiveKitTokenService(config);
24
+ this.configured = token.IsConfigured;
25
+ this.client =
26
+ client ?? new RoomServiceClient(WsToHttpUrl(token.ServerUrl), config?.ApiKey ?? process.env.LIVEKIT_API_KEY, config?.ApiSecret ?? process.env.LIVEKIT_API_SECRET);
27
+ }
28
+ /**
29
+ * Records whether a person lets agents see their camera and shared screen: sets their `mj.agentCanSee` attribute to
30
+ * `'true'`, or removes it. The caller must already have established that `identity` is the person asking.
31
+ *
32
+ * @param roomName The room the person is in.
33
+ * @param identity The person's participant identity.
34
+ * @param allow `true` to let agents see, `false` to stop.
35
+ * @returns Whether LiveKit applied it; never throws.
36
+ */
37
+ async SetAgentVision(roomName, identity, allow) {
38
+ return this.updateAttributes(roomName, identity, AgentVisionAttributes(allow));
39
+ }
40
+ /** Sets (or, with `''`, removes) a participant's attributes; reports LiveKit's refusal instead of throwing. */
41
+ async updateAttributes(roomName, identity, attributes) {
42
+ if (!this.configured) {
43
+ return { Success: false, ErrorMessage: 'LiveKit is not configured on this server.' };
44
+ }
45
+ try {
46
+ await this.client.updateParticipant(roomName, identity, { attributes });
47
+ return { Success: true };
48
+ }
49
+ catch (error) {
50
+ if (isNotFound(error)) {
51
+ return { Success: false, NotInRoom: true, ErrorMessage: `${identity} is not in room ${roomName}.` };
52
+ }
53
+ return { Success: false, ErrorMessage: error instanceof Error ? error.message : String(error) };
54
+ }
55
+ }
56
+ }
57
+ /**
58
+ * Whether LiveKit refused because the room or the participant does not exist. Only LiveKit's own `not_found` code
59
+ * counts: a bare HTTP 404 more likely means the server URL is wrong.
60
+ */
61
+ function isNotFound(error) {
62
+ return error instanceof TwirpError && error.code === 'not_found';
63
+ }
64
+ //# sourceMappingURL=livekit-participant-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"livekit-participant-service.js","sourceRoot":"","sources":["../src/livekit-participant-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAA4B,MAAM,yBAAyB,CAAC;AACxF,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAevD,6EAA6E;AAC7E,MAAM,OAAO,yBAAyB;IAIpC;;;;;OAKG;IACH,YAAY,MAAqC,EAAE,MAAoC;QACrF,MAAM,KAAK,GAAG,IAAI,mBAAmB,CAAC,MAAM,CAAC,CAAC;QAC9C,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC,YAAY,CAAC;QACrC,IAAI,CAAC,MAAM;YACT,MAAM,IAAI,IAAI,iBAAiB,CAAC,WAAW,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,MAAM,EAAE,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IACtK,CAAC;IAED;;;;;;;;OAQG;IACI,KAAK,CAAC,cAAc,CAAC,QAAgB,EAAE,QAAgB,EAAE,KAAc;QAC5E,OAAO,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,EAAE,qBAAqB,CAAC,KAAK,CAAC,CAAC,CAAC;IACjF,CAAC;IAED,+GAA+G;IACvG,KAAK,CAAC,gBAAgB,CAAC,QAAgB,EAAE,QAAgB,EAAE,UAAkC;QACnG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACrB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,2CAA2C,EAAE,CAAC;QACvF,CAAC;QACD,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC;YACxE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;gBACtB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,QAAQ,mBAAmB,QAAQ,GAAG,EAAE,CAAC;YACtG,CAAC;YACD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QAClG,CAAC;IACH,CAAC;CACF;AAED;;;GAGG;AACH,SAAS,UAAU,CAAC,KAAc;IAChC,OAAO,KAAK,YAAY,UAAU,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,CAAC;AACnE,CAAC"}
@@ -0,0 +1,141 @@
1
+ /**
2
+ * @fileoverview {@link LiveKitSipService}: the server-side LiveKit SIP and room-presence operations MJ needs to put
3
+ * phone calls into rooms.
4
+ *
5
+ * LiveKit SIP is the SIP gateway in front of a LiveKit deployment. A carrier's SIP trunk (Twilio Elastic SIP Trunking,
6
+ * Telnyx, …) points at it; an **inbound trunk** says which numbers LiveKit accepts calls for and a **dispatch rule** says
7
+ * which room an accepted call lands in. This service wraps the three things MJ does with it:
8
+ *
9
+ * - **inbound routing**: make sure an inbound trunk and an `individual` dispatch rule exist, so a call to one of the
10
+ * configured numbers lands in a fresh room named `<prefix>…` (idempotent: it finds before it creates);
11
+ * - **dial out**: `createSipParticipant`, which makes the room call a phone number and adds that call to the room as a
12
+ * participant (an outbound call, a fallback leg, a blind transfer to a number);
13
+ * - **presence**: whether a given participant is currently in a room, and removing one (hanging up a SIP leg).
14
+ *
15
+ * The SDK clients are injected (`SipClientLike`, `RoomServiceClientLike`) so the logic is unit-tested without a network.
16
+ * Credentials come from the same `LIVEKIT_URL` / `LIVEKIT_API_KEY` / `LIVEKIT_API_SECRET` the token service uses.
17
+ *
18
+ * @module @memberjunction/livekit-room-server
19
+ */
20
+ import { RoomServiceClient, SipClient } from 'livekit-server-sdk';
21
+ import { type LiveKitServerConfig } from './livekit-token-service.js';
22
+ /** The `ParticipantInfo.Kind` value LiveKit gives a SIP participant (`ParticipantInfo.Kind.SIP`). */
23
+ export declare const LIVEKIT_PARTICIPANT_KIND_SIP = 3;
24
+ /** Participant attributes LiveKit SIP sets on a phone participant. */
25
+ export declare const LIVEKIT_SIP_ATTRIBUTES: {
26
+ /** The caller's number. */
27
+ readonly CallerNumber: "sip.phoneNumber";
28
+ /** The number that was dialed (the trunk number). */
29
+ readonly DialedNumber: "sip.trunkPhoneNumber";
30
+ readonly CallStatus: "sip.callStatus";
31
+ readonly CallID: "sip.callID";
32
+ };
33
+ /** How long the LiveKit API is given to answer a dial request that waits for the call to be answered. */
34
+ export declare const SIP_DIAL_REQUEST_TIMEOUT_SECONDS = 60;
35
+ /** The longest one dialed call may last. A safety ceiling; the call's own duration cap is enforced by MJ. */
36
+ export declare const SIP_DIAL_MAX_DURATION_SECONDS = 3600;
37
+ /** The SIP operations the service uses (a `Pick` so tests inject a fake). */
38
+ export type SipClientLike = Pick<SipClient, 'createSipParticipant' | 'listSipInboundTrunk' | 'listSipOutboundTrunk' | 'createSipInboundTrunk' | 'listSipDispatchRule' | 'createSipDispatchRule'>;
39
+ /** The room operations the service uses (a `Pick` so tests inject a fake). */
40
+ export type RoomServiceClientLike = Pick<RoomServiceClient, 'listParticipants' | 'removeParticipant'>;
41
+ /** One participant in a room, reduced to what MJ looks at. */
42
+ export interface RoomParticipantSummary {
43
+ Identity: string;
44
+ Name: string;
45
+ /** True for a phone (SIP) participant. */
46
+ IsSip: boolean;
47
+ /** True once the participant's media connection is established. */
48
+ IsConnected: boolean;
49
+ Attributes: Record<string, string>;
50
+ }
51
+ /** A SIP trunk, reduced to what MJ validates and reports. */
52
+ export interface SipTrunkSummary {
53
+ TrunkID: string;
54
+ Name: string;
55
+ Numbers: string[];
56
+ }
57
+ /** What a dial-out needs. */
58
+ export interface DialSipParticipantParams {
59
+ RoomName: string;
60
+ /** The outbound trunk to dial through. */
61
+ TrunkID: string;
62
+ /** The number to dial, E.164. */
63
+ Number: string;
64
+ /** The identity the call joins the room with (stable, so presence can be checked). */
65
+ ParticipantIdentity: string;
66
+ DisplayName?: string;
67
+ /** The caller ID to present. Defaults to the trunk's number. */
68
+ FromNumber?: string;
69
+ /** Seconds the number may ring. */
70
+ RingTimeoutSeconds?: number;
71
+ /** Block until the call is answered (default true). */
72
+ WaitUntilAnswered?: boolean;
73
+ }
74
+ /** What inbound routing needs. */
75
+ export interface EnsureInboundRoutingParams {
76
+ /** The numbers LiveKit accepts calls for. */
77
+ Numbers: string[];
78
+ /** Calls land in a room whose name starts with this. */
79
+ RoomPrefix: string;
80
+ /** A name for anything created. */
81
+ Name?: string;
82
+ /** Source addresses allowed to call the trunk (the carrier's signalling addresses). Empty allows any. */
83
+ AllowedAddresses?: string[];
84
+ /** SIP digest credentials the carrier must present, when the trunk uses them. */
85
+ AuthUsername?: string;
86
+ AuthPassword?: string;
87
+ }
88
+ /** The outcome of {@link LiveKitSipService.EnsureInboundRouting}. */
89
+ export interface InboundRoutingResult {
90
+ TrunkID: string;
91
+ DispatchRuleID: string;
92
+ /** True when this call created the trunk. */
93
+ CreatedTrunk: boolean;
94
+ /** True when this call created the dispatch rule. */
95
+ CreatedDispatchRule: boolean;
96
+ }
97
+ /** SIP and presence operations against a LiveKit deployment. */
98
+ export declare class LiveKitSipService {
99
+ private readonly config;
100
+ private sip?;
101
+ private rooms?;
102
+ /**
103
+ * @param config Explicit credentials; omitted fields fall back to the `LIVEKIT_*` environment variables.
104
+ * @param sip Injectable SIP client (tests); defaults to a real `SipClient`, built on first use.
105
+ * @param rooms Injectable room-service client (tests); defaults to a real `RoomServiceClient`, built on first use.
106
+ */
107
+ constructor(config?: Partial<LiveKitServerConfig>, sip?: SipClientLike, rooms?: RoomServiceClientLike);
108
+ /** Whether the LiveKit credentials needed to call the API are present. */
109
+ get IsConfigured(): boolean;
110
+ /** The participants currently in a room. A room that does not exist (nobody has joined) has none. */
111
+ ListParticipants(roomName: string): Promise<RoomParticipantSummary[]>;
112
+ /** Whether a participant with this identity is in the room with an established connection. */
113
+ IsParticipantPresent(roomName: string, identity: string): Promise<boolean>;
114
+ /** Removes a participant from a room (hangs up a phone leg). */
115
+ RemoveParticipant(roomName: string, identity: string): Promise<void>;
116
+ /**
117
+ * Calls a number and adds the call to the room. By default the request blocks until the call is answered, so a
118
+ * resolved promise means the other side picked up; a throw means it did not (busy, no answer, refused).
119
+ */
120
+ DialIntoRoom(params: DialSipParticipantParams): Promise<void>;
121
+ /** The inbound trunks LiveKit has, optionally only those that include one of the numbers. */
122
+ ListInboundTrunks(numbers?: string[]): Promise<SipTrunkSummary[]>;
123
+ /** The outbound trunks LiveKit has. */
124
+ ListOutboundTrunks(): Promise<SipTrunkSummary[]>;
125
+ /** Whether the outbound trunk id exists on this LiveKit deployment. */
126
+ OutboundTrunkExists(trunkID: string): Promise<boolean>;
127
+ /**
128
+ * Makes sure calls to `Numbers` land in a new room named `<RoomPrefix>…`: finds (or creates) the inbound trunk for
129
+ * the numbers and an `individual` dispatch rule with the prefix on it. Safe to run on every start: it only creates
130
+ * what is missing.
131
+ */
132
+ EnsureInboundRouting(params: EnsureInboundRoutingParams): Promise<InboundRoutingResult>;
133
+ private createInboundTrunk;
134
+ /** The id of an `individual` dispatch rule on the trunk whose room prefix matches, if there is one. */
135
+ private findDispatchRule;
136
+ private sipClient;
137
+ private roomClient;
138
+ /** The HTTP(S) host and API credentials, or a clear error when they are not configured. */
139
+ private credentials;
140
+ }
141
+ //# sourceMappingURL=livekit-sip-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"livekit-sip-service.d.ts","sourceRoot":"","sources":["../src/livekit-sip-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,169 @@
1
+ /**
2
+ * @fileoverview {@link LiveKitSipService}: the server-side LiveKit SIP and room-presence operations MJ needs to put
3
+ * phone calls into rooms.
4
+ *
5
+ * LiveKit SIP is the SIP gateway in front of a LiveKit deployment. A carrier's SIP trunk (Twilio Elastic SIP Trunking,
6
+ * Telnyx, …) points at it; an **inbound trunk** says which numbers LiveKit accepts calls for and a **dispatch rule** says
7
+ * which room an accepted call lands in. This service wraps the three things MJ does with it:
8
+ *
9
+ * - **inbound routing**: make sure an inbound trunk and an `individual` dispatch rule exist, so a call to one of the
10
+ * configured numbers lands in a fresh room named `<prefix>…` (idempotent: it finds before it creates);
11
+ * - **dial out**: `createSipParticipant`, which makes the room call a phone number and adds that call to the room as a
12
+ * participant (an outbound call, a fallback leg, a blind transfer to a number);
13
+ * - **presence**: whether a given participant is currently in a room, and removing one (hanging up a SIP leg).
14
+ *
15
+ * The SDK clients are injected (`SipClientLike`, `RoomServiceClientLike`) so the logic is unit-tested without a network.
16
+ * Credentials come from the same `LIVEKIT_URL` / `LIVEKIT_API_KEY` / `LIVEKIT_API_SECRET` the token service uses.
17
+ *
18
+ * @module @memberjunction/livekit-room-server
19
+ */
20
+ import { ParticipantInfo_State, RoomServiceClient, SipClient } from 'livekit-server-sdk';
21
+ import { LogStatus } from '@memberjunction/core';
22
+ import { LiveKitTokenService } from './livekit-token-service.js';
23
+ import { WsToHttpUrl } from './livekit-egress-service.js';
24
+ /** The `ParticipantInfo.Kind` value LiveKit gives a SIP participant (`ParticipantInfo.Kind.SIP`). */
25
+ export const LIVEKIT_PARTICIPANT_KIND_SIP = 3;
26
+ /** Participant attributes LiveKit SIP sets on a phone participant. */
27
+ export const LIVEKIT_SIP_ATTRIBUTES = {
28
+ /** The caller's number. */
29
+ CallerNumber: 'sip.phoneNumber',
30
+ /** The number that was dialed (the trunk number). */
31
+ DialedNumber: 'sip.trunkPhoneNumber',
32
+ CallStatus: 'sip.callStatus',
33
+ CallID: 'sip.callID',
34
+ };
35
+ /** How long the LiveKit API is given to answer a dial request that waits for the call to be answered. */
36
+ export const SIP_DIAL_REQUEST_TIMEOUT_SECONDS = 60;
37
+ /** The longest one dialed call may last. A safety ceiling; the call's own duration cap is enforced by MJ. */
38
+ export const SIP_DIAL_MAX_DURATION_SECONDS = 3600;
39
+ /** SIP and presence operations against a LiveKit deployment. */
40
+ export class LiveKitSipService {
41
+ /**
42
+ * @param config Explicit credentials; omitted fields fall back to the `LIVEKIT_*` environment variables.
43
+ * @param sip Injectable SIP client (tests); defaults to a real `SipClient`, built on first use.
44
+ * @param rooms Injectable room-service client (tests); defaults to a real `RoomServiceClient`, built on first use.
45
+ */
46
+ constructor(config, sip, rooms) {
47
+ this.config = config ?? {};
48
+ this.sip = sip;
49
+ this.rooms = rooms;
50
+ }
51
+ /** Whether the LiveKit credentials needed to call the API are present. */
52
+ get IsConfigured() {
53
+ return new LiveKitTokenService(this.config).IsConfigured;
54
+ }
55
+ // ── presence ─────────────────────────────────────────────────────────────────
56
+ /** The participants currently in a room. A room that does not exist (nobody has joined) has none. */
57
+ async ListParticipants(roomName) {
58
+ const participants = await this.roomClient().listParticipants(roomName);
59
+ return participants.map((p) => ({
60
+ Identity: p.identity,
61
+ Name: p.name,
62
+ IsSip: p.kind === LIVEKIT_PARTICIPANT_KIND_SIP,
63
+ IsConnected: p.state === ParticipantInfo_State.JOINED || p.state === ParticipantInfo_State.ACTIVE,
64
+ Attributes: { ...p.attributes },
65
+ }));
66
+ }
67
+ /** Whether a participant with this identity is in the room with an established connection. */
68
+ async IsParticipantPresent(roomName, identity) {
69
+ const wanted = identity.toLowerCase();
70
+ const participants = await this.ListParticipants(roomName);
71
+ return participants.some((p) => p.IsConnected && p.Identity.toLowerCase() === wanted);
72
+ }
73
+ /** Removes a participant from a room (hangs up a phone leg). */
74
+ async RemoveParticipant(roomName, identity) {
75
+ await this.roomClient().removeParticipant(roomName, identity);
76
+ }
77
+ // ── dial out ─────────────────────────────────────────────────────────────────
78
+ /**
79
+ * Calls a number and adds the call to the room. By default the request blocks until the call is answered, so a
80
+ * resolved promise means the other side picked up; a throw means it did not (busy, no answer, refused).
81
+ */
82
+ async DialIntoRoom(params) {
83
+ await this.sipClient().createSipParticipant(params.TrunkID, params.Number, params.RoomName, {
84
+ participantIdentity: params.ParticipantIdentity,
85
+ participantName: params.DisplayName,
86
+ fromNumber: params.FromNumber,
87
+ ringingTimeout: params.RingTimeoutSeconds,
88
+ maxCallDuration: SIP_DIAL_MAX_DURATION_SECONDS,
89
+ waitUntilAnswered: params.WaitUntilAnswered ?? true,
90
+ timeout: SIP_DIAL_REQUEST_TIMEOUT_SECONDS,
91
+ });
92
+ }
93
+ // ── trunks and routing ───────────────────────────────────────────────────────
94
+ /** The inbound trunks LiveKit has, optionally only those that include one of the numbers. */
95
+ async ListInboundTrunks(numbers) {
96
+ const trunks = await this.sipClient().listSipInboundTrunk(numbers?.length ? { numbers } : undefined);
97
+ return trunks.map((t) => ({ TrunkID: t.sipTrunkId, Name: t.name, Numbers: [...t.numbers] }));
98
+ }
99
+ /** The outbound trunks LiveKit has. */
100
+ async ListOutboundTrunks() {
101
+ const trunks = await this.sipClient().listSipOutboundTrunk();
102
+ return trunks.map((t) => ({ TrunkID: t.sipTrunkId, Name: t.name, Numbers: [...t.numbers] }));
103
+ }
104
+ /** Whether the outbound trunk id exists on this LiveKit deployment. */
105
+ async OutboundTrunkExists(trunkID) {
106
+ const trunks = await this.ListOutboundTrunks();
107
+ return trunks.some((t) => t.TrunkID === trunkID);
108
+ }
109
+ /**
110
+ * Makes sure calls to `Numbers` land in a new room named `<RoomPrefix>…`: finds (or creates) the inbound trunk for
111
+ * the numbers and an `individual` dispatch rule with the prefix on it. Safe to run on every start: it only creates
112
+ * what is missing.
113
+ */
114
+ async EnsureInboundRouting(params) {
115
+ const name = params.Name ?? 'MemberJunction inbound';
116
+ const existingTrunk = (await this.ListInboundTrunks(params.Numbers)).find((t) => params.Numbers.every((n) => t.Numbers.includes(n)));
117
+ const trunk = existingTrunk ?? (await this.createInboundTrunk(name, params));
118
+ const rule = await this.findDispatchRule(trunk.TrunkID, params.RoomPrefix);
119
+ if (rule) {
120
+ return { TrunkID: trunk.TrunkID, DispatchRuleID: rule, CreatedTrunk: !existingTrunk, CreatedDispatchRule: false };
121
+ }
122
+ const created = await this.sipClient().createSipDispatchRule({ type: 'individual', roomPrefix: params.RoomPrefix }, { name: `${name} dispatch`, trunkIds: [trunk.TrunkID] });
123
+ LogStatus(`[LiveKitSip] created dispatch rule ${created.sipDispatchRuleId} (rooms '${params.RoomPrefix}…') on trunk ${trunk.TrunkID}.`);
124
+ return { TrunkID: trunk.TrunkID, DispatchRuleID: created.sipDispatchRuleId, CreatedTrunk: !existingTrunk, CreatedDispatchRule: true };
125
+ }
126
+ async createInboundTrunk(name, params) {
127
+ const created = await this.sipClient().createSipInboundTrunk(name, params.Numbers, {
128
+ allowedAddresses: params.AllowedAddresses?.length ? params.AllowedAddresses : undefined,
129
+ authUsername: params.AuthUsername,
130
+ authPassword: params.AuthPassword,
131
+ });
132
+ LogStatus(`[LiveKitSip] created inbound trunk ${created.sipTrunkId} for ${params.Numbers.length} number(s).`);
133
+ return { TrunkID: created.sipTrunkId, Name: created.name, Numbers: [...created.numbers] };
134
+ }
135
+ /** The id of an `individual` dispatch rule on the trunk whose room prefix matches, if there is one. */
136
+ async findDispatchRule(trunkID, roomPrefix) {
137
+ const rules = await this.sipClient().listSipDispatchRule({ trunkIds: [trunkID] });
138
+ const match = rules.find((r) => r.rule?.rule.case === 'dispatchRuleIndividual' && r.rule.rule.value.roomPrefix === roomPrefix);
139
+ return match?.sipDispatchRuleId;
140
+ }
141
+ // ── clients ──────────────────────────────────────────────────────────────────
142
+ sipClient() {
143
+ if (!this.sip) {
144
+ const { host, apiKey, apiSecret } = this.credentials();
145
+ this.sip = new SipClient(host, apiKey, apiSecret);
146
+ }
147
+ return this.sip;
148
+ }
149
+ roomClient() {
150
+ if (!this.rooms) {
151
+ const { host, apiKey, apiSecret } = this.credentials();
152
+ this.rooms = new RoomServiceClient(host, apiKey, apiSecret);
153
+ }
154
+ return this.rooms;
155
+ }
156
+ /** The HTTP(S) host and API credentials, or a clear error when they are not configured. */
157
+ credentials() {
158
+ const tokens = new LiveKitTokenService(this.config);
159
+ if (!tokens.IsConfigured) {
160
+ throw new Error('LiveKit is not configured. Set LIVEKIT_URL, LIVEKIT_API_KEY and LIVEKIT_API_SECRET.');
161
+ }
162
+ return {
163
+ host: WsToHttpUrl(tokens.ServerUrl),
164
+ apiKey: this.config.ApiKey ?? process.env.LIVEKIT_API_KEY ?? '',
165
+ apiSecret: this.config.ApiSecret ?? process.env.LIVEKIT_API_SECRET ?? '',
166
+ };
167
+ }
168
+ }
169
+ //# sourceMappingURL=livekit-sip-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"livekit-sip-service.js","sourceRoot":"","sources":["../src/livekit-sip-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACzF,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAA4B,MAAM,yBAAyB,CAAC;AACxF,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEvD,qGAAqG;AACrG,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,CAAC;AAE9C,sEAAsE;AACtE,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,2BAA2B;IAC3B,YAAY,EAAE,iBAAiB;IAC/B,qDAAqD;IACrD,YAAY,EAAE,sBAAsB;IACpC,UAAU,EAAE,gBAAgB;IAC5B,MAAM,EAAE,YAAY;CACZ,CAAC;AAEX,yGAAyG;AACzG,MAAM,CAAC,MAAM,gCAAgC,GAAG,EAAE,CAAC;AAEnD,6GAA6G;AAC7G,MAAM,CAAC,MAAM,6BAA6B,GAAG,IAAI,CAAC;AAwElD,gEAAgE;AAChE,MAAM,OAAO,iBAAiB;IAK5B;;;;OAIG;IACH,YAAY,MAAqC,EAAE,GAAmB,EAAE,KAA6B;QACnG,IAAI,CAAC,MAAM,GAAG,MAAM,IAAI,EAAE,CAAC;QAC3B,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAED,0EAA0E;IAC1E,IAAW,YAAY;QACrB,OAAO,IAAI,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC;IAC3D,CAAC;IAED,gFAAgF;IAEhF,qGAAqG;IAC9F,KAAK,CAAC,gBAAgB,CAAC,QAAgB;QAC5C,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QACxE,OAAO,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC9B,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,KAAK,EAAE,CAAC,CAAC,IAAI,KAAK,4BAA4B;YAC9C,WAAW,EAAE,CAAC,CAAC,KAAK,KAAK,qBAAqB,CAAC,MAAM,IAAI,CAAC,CAAC,KAAK,KAAK,qBAAqB,CAAC,MAAM;YACjG,UAAU,EAAE,EAAE,GAAG,CAAC,CAAC,UAAU,EAAE;SAChC,CAAC,CAAC,CAAC;IACN,CAAC;IAED,8FAA8F;IACvF,KAAK,CAAC,oBAAoB,CAAC,QAAgB,EAAE,QAAgB;QAClE,MAAM,MAAM,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;QACtC,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAC3D,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,CAAC;IACxF,CAAC;IAED,gEAAgE;IACzD,KAAK,CAAC,iBAAiB,CAAC,QAAgB,EAAE,QAAgB;QAC/D,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAChE,CAAC;IAED,gFAAgF;IAEhF;;;OAGG;IACI,KAAK,CAAC,YAAY,CAAC,MAAgC;QACxD,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC,oBAAoB,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE;YAC1F,mBAAmB,EAAE,MAAM,CAAC,mBAAmB;YAC/C,eAAe,EAAE,MAAM,CAAC,WAAW;YACnC,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,cAAc,EAAE,MAAM,CAAC,kBAAkB;YACzC,eAAe,EAAE,6BAA6B;YAC9C,iBAAiB,EAAE,MAAM,CAAC,iBAAiB,IAAI,IAAI;YACnD,OAAO,EAAE,gCAAgC;SAC1C,CAAC,CAAC;IACL,CAAC;IAED,gFAAgF;IAEhF,6FAA6F;IACtF,KAAK,CAAC,iBAAiB,CAAC,OAAkB;QAC/C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC,mBAAmB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QACrG,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;IAC/F,CAAC;IAED,uCAAuC;IAChC,KAAK,CAAC,kBAAkB;QAC7B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC,oBAAoB,EAAE,CAAC;QAC7D,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;IAC/F,CAAC;IAED,uEAAuE;IAChE,KAAK,CAAC,mBAAmB,CAAC,OAAe;QAC9C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC/C,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC;IACnD,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,oBAAoB,CAAC,MAAkC;QAClE,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,wBAAwB,CAAC;QACrD,MAAM,aAAa,GAAG,CAAC,MAAM,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACrI,MAAM,KAAK,GAAG,aAAa,IAAI,CAAC,MAAM,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;QAC7E,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;QAC3E,IAAI,IAAI,EAAE,CAAC;YACT,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,aAAa,EAAE,mBAAmB,EAAE,KAAK,EAAE,CAAC;QACpH,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC,qBAAqB,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,IAAI,WAAW,EAAE,QAAQ,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC7K,SAAS,CAAC,sCAAsC,OAAO,CAAC,iBAAiB,YAAY,MAAM,CAAC,UAAU,gBAAgB,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC;QACxI,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,CAAC,iBAAiB,EAAE,YAAY,EAAE,CAAC,aAAa,EAAE,mBAAmB,EAAE,IAAI,EAAE,CAAC;IACxI,CAAC;IAEO,KAAK,CAAC,kBAAkB,CAAC,IAAY,EAAE,MAAkC;QAC/E,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC,qBAAqB,CAAC,IAAI,EAAE,MAAM,CAAC,OAAO,EAAE;YACjF,gBAAgB,EAAE,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS;YACvF,YAAY,EAAE,MAAM,CAAC,YAAY;YACjC,YAAY,EAAE,MAAM,CAAC,YAAY;SAClC,CAAC,CAAC;QACH,SAAS,CAAC,sCAAsC,OAAO,CAAC,UAAU,QAAQ,MAAM,CAAC,OAAO,CAAC,MAAM,aAAa,CAAC,CAAC;QAC9G,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;IAC5F,CAAC;IAED,uGAAuG;IAC/F,KAAK,CAAC,gBAAgB,CAAC,OAAe,EAAE,UAAkB;QAChE,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC,mBAAmB,CAAC,EAAE,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAClF,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,KAAK,wBAAwB,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,KAAK,UAAU,CAAC,CAAC;QAC/H,OAAO,KAAK,EAAE,iBAAiB,CAAC;IAClC,CAAC;IAED,gFAAgF;IAExE,SAAS;QACf,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YACd,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;YACvD,IAAI,CAAC,GAAG,GAAG,IAAI,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;QACpD,CAAC;QACD,OAAO,IAAI,CAAC,GAAG,CAAC;IAClB,CAAC;IAEO,UAAU;QAChB,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YAChB,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;YACvD,IAAI,CAAC,KAAK,GAAG,IAAI,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;QAC9D,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,2FAA2F;IACnF,WAAW;QACjB,MAAM,MAAM,GAAG,IAAI,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACpD,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,qFAAqF,CAAC,CAAC;QACzG,CAAC;QACD,OAAO;YACL,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC;YACnC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,EAAE;YAC/D,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,EAAE;SACzE,CAAC;IACJ,CAAC;CACF"}
@@ -40,6 +40,16 @@ export interface MintTokenParams {
40
40
  TtlSeconds?: number;
41
41
  /** Extra metadata merged into the participant metadata JSON. */
42
42
  Metadata?: Record<string, unknown>;
43
+ /**
44
+ * LiveKit participant attributes the participant carries from the moment it joins (e.g. `mj.agentWatches` on an
45
+ * agent's bot). Attributes are shared with every participant and announced on change.
46
+ */
47
+ Attributes?: Record<string, string>;
48
+ /**
49
+ * Whether the participant may change its own name, metadata and attributes. Default: false (LiveKit's default). Agent
50
+ * bots get it, so a bot can say when its avatar was taken down (`mj.agentAvatar`).
51
+ */
52
+ CanUpdateOwnMetadata?: boolean;
43
53
  }
44
54
  /** A minted token plus the connection coordinates a client needs to join. */
45
55
  export interface MintedToken {
@@ -52,6 +62,12 @@ export interface MintedToken {
52
62
  /** The room name the token authorizes. */
53
63
  RoomName: string;
54
64
  }
65
+ /**
66
+ * The LiveKit participant identity a signed-in MJ user joins a room with. Everything that mints a token for a user, and
67
+ * everything that later looks for that user in a room (the handoff engine watching for a person to appear), derives it
68
+ * here so the two can never disagree.
69
+ */
70
+ export declare function LiveKitUserIdentity(userID: string): string;
55
71
  /** Mints scoped LiveKit access tokens. Stateless apart from its resolved credentials. */
56
72
  export declare class LiveKitTokenService {
57
73
  private readonly config;
@@ -83,18 +99,23 @@ export declare class LiveKitTokenService {
83
99
  MintClientToken(roomName: string, identity: string, displayName?: string, ttlSeconds?: number): Promise<MintedToken>;
84
100
  /**
85
101
  * Mints a token for the AGENT bot (publish + subscribe + data, `agent` role metadata so the UI badges
86
- * it correctly). The bridge passes this in its session `Configuration.AccessToken`.
102
+ * it correctly, and leave to update its own attributes, so it can say when its avatar was taken down). The bridge
103
+ * passes this in its session `Configuration.AccessToken`.
87
104
  *
88
105
  * @param roomName The room to join.
89
106
  * @param identity The bot identity.
90
107
  * @param displayName The bot display name.
108
+ * @param attributes Participant attributes the bot carries from the moment it joins (e.g. `mj.agentWatches`).
91
109
  */
92
- MintBotToken(roomName: string, identity: string, displayName?: string): Promise<MintedToken>;
93
- /** Builds the LiveKit video grant from the params (defaults: publish + subscribe + data all on). */
110
+ MintBotToken(roomName: string, identity: string, displayName?: string, attributes?: Record<string, string>): Promise<MintedToken>;
111
+ /** Builds the LiveKit video grant from the params (defaults: publish + subscribe + data all on; own metadata off). */
94
112
  private buildGrant;
95
113
  /** Builds the participant metadata JSON string, always stamping the role for UI resolution. */
96
114
  private buildMetadata;
97
- /** Throws a clear error when credentials are missing. */
98
- private assertConfigured;
115
+ /**
116
+ * Throws a clear error when credentials are missing. Public so a caller that must fail before doing costly work (the
117
+ * room coordinator, before it opens a model session) gets the same error minting would.
118
+ */
119
+ AssertConfigured(): void;
99
120
  }
100
121
  //# sourceMappingURL=livekit-token-service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"livekit-token-service.d.ts","sourceRoot":"","sources":["../src/livekit-token-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,iDAAiD;AACjD,MAAM,WAAW,mBAAmB;IAClC,kFAAkF;IAClF,SAAS,EAAE,MAAM,CAAC;IAClB,2BAA2B;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,oEAAoE;IACpE,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,gGAAgG;AAChG,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,OAAO,GAAG,aAAa,CAAC;AAEhE,oDAAoD;AACpD,MAAM,WAAW,eAAe;IAC9B,kDAAkD;IAClD,QAAQ,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,QAAQ,EAAE,MAAM,CAAC;IACjB,mCAAmC;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sFAAsF;IACtF,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,gEAAgE;IAChE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,sEAAsE;IACtE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gFAAgF;IAChF,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,yDAAyD;IACzD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,6EAA6E;AAC7E,MAAM,WAAW,WAAW;IAC1B,4CAA4C;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,mCAAmC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,sDAAsD;IACtD,QAAQ,EAAE,MAAM,CAAC;IACjB,0CAA0C;IAC1C,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,yFAAyF;AACzF,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsB;IAE7C;;;OAGG;gBACS,MAAM,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC;IAQjD,qEAAqE;IACrE,IAAW,YAAY,IAAI,OAAO,CAEjC;IAED,iFAAiF;IACjF,IAAW,SAAS,IAAI,MAAM,CAE7B;IAED;;;;;;OAMG;IACU,SAAS,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,WAAW,CAAC;IAarE;;;;;;;OAOG;IACI,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAI3H;;;;;;;OAOG;IACI,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAInG,oGAAoG;IACpG,OAAO,CAAC,UAAU;IAUlB,+FAA+F;IAC/F,OAAO,CAAC,aAAa;IAIrB,yDAAyD;IACzD,OAAO,CAAC,gBAAgB;CAQzB"}
1
+ {"version":3,"file":"livekit-token-service.d.ts","sourceRoot":"","sources":["../src/livekit-token-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,iDAAiD;AACjD,MAAM,WAAW,mBAAmB;IAClC,kFAAkF;IAClF,SAAS,EAAE,MAAM,CAAC;IAClB,2BAA2B;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,oEAAoE;IACpE,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,gGAAgG;AAChG,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,OAAO,GAAG,aAAa,CAAC;AAEhE,oDAAoD;AACpD,MAAM,WAAW,eAAe;IAC9B,kDAAkD;IAClD,QAAQ,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,QAAQ,EAAE,MAAM,CAAC;IACjB,mCAAmC;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sFAAsF;IACtF,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,gEAAgE;IAChE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,sEAAsE;IACtE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gFAAgF;IAChF,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,yDAAyD;IACzD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC;;;OAGG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,6EAA6E;AAC7E,MAAM,WAAW,WAAW;IAC1B,4CAA4C;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,mCAAmC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,sDAAsD;IACtD,QAAQ,EAAE,MAAM,CAAC;IACjB,0CAA0C;IAC1C,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,yFAAyF;AACzF,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsB;IAE7C;;;OAGG;gBACS,MAAM,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC;IAQjD,qEAAqE;IACrE,IAAW,YAAY,IAAI,OAAO,CAEjC;IAED,iFAAiF;IACjF,IAAW,SAAS,IAAI,MAAM,CAE7B;IAED;;;;;;OAMG;IACU,SAAS,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,WAAW,CAAC;IAcrE;;;;;;;OAOG;IACI,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAI3H;;;;;;;;;OASG;IACI,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC;IAIxI,sHAAsH;IACtH,OAAO,CAAC,UAAU;IAWlB,+FAA+F;IAC/F,OAAO,CAAC,aAAa;IAIrB;;;OAGG;IACI,gBAAgB,IAAI,IAAI;CAQhC"}