@memberjunction/realtime-runtime 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 (98) hide show
  1. package/README.md +75 -0
  2. package/dist/channels/base-realtime-channel-client.d.ts +535 -28
  3. package/dist/channels/base-realtime-channel-client.d.ts.map +1 -1
  4. package/dist/channels/base-realtime-channel-client.js +864 -10
  5. package/dist/channels/base-realtime-channel-client.js.map +1 -1
  6. package/dist/channels/channel-action-dispatcher.d.ts +70 -0
  7. package/dist/channels/channel-action-dispatcher.d.ts.map +1 -0
  8. package/dist/channels/channel-action-dispatcher.js +136 -0
  9. package/dist/channels/channel-action-dispatcher.js.map +1 -0
  10. package/dist/channels/channel-catalog-note.d.ts +48 -0
  11. package/dist/channels/channel-catalog-note.d.ts.map +1 -0
  12. package/dist/channels/channel-catalog-note.js +119 -0
  13. package/dist/channels/channel-catalog-note.js.map +1 -0
  14. package/dist/channels/channel-contract-types.d.ts +107 -0
  15. package/dist/channels/channel-contract-types.d.ts.map +1 -0
  16. package/dist/channels/channel-contract-types.js +12 -0
  17. package/dist/channels/channel-contract-types.js.map +1 -0
  18. package/dist/channels/channel-descriptor-synthesis.d.ts +56 -0
  19. package/dist/channels/channel-descriptor-synthesis.d.ts.map +1 -0
  20. package/dist/channels/channel-descriptor-synthesis.js +90 -0
  21. package/dist/channels/channel-descriptor-synthesis.js.map +1 -0
  22. package/dist/channels/channel-perception.d.ts +82 -0
  23. package/dist/channels/channel-perception.d.ts.map +1 -0
  24. package/dist/channels/channel-perception.js +120 -0
  25. package/dist/channels/channel-perception.js.map +1 -0
  26. package/dist/channels/channel-schema-format.d.ts +17 -0
  27. package/dist/channels/channel-schema-format.d.ts.map +1 -0
  28. package/dist/channels/channel-schema-format.js +45 -0
  29. package/dist/channels/channel-schema-format.js.map +1 -0
  30. package/dist/channels/channel-state-delta.d.ts +59 -0
  31. package/dist/channels/channel-state-delta.d.ts.map +1 -0
  32. package/dist/channels/channel-state-delta.js +116 -0
  33. package/dist/channels/channel-state-delta.js.map +1 -0
  34. package/dist/channels/channel-surface-placement.d.ts +25 -0
  35. package/dist/channels/channel-surface-placement.d.ts.map +1 -0
  36. package/dist/channels/channel-surface-placement.js +29 -0
  37. package/dist/channels/channel-surface-placement.js.map +1 -0
  38. package/dist/channels/channel-visual-pump.d.ts +126 -0
  39. package/dist/channels/channel-visual-pump.d.ts.map +1 -0
  40. package/dist/channels/channel-visual-pump.js +174 -0
  41. package/dist/channels/channel-visual-pump.js.map +1 -0
  42. package/dist/hosts/IRealtimeMediaHost.d.ts +61 -4
  43. package/dist/hosts/IRealtimeMediaHost.d.ts.map +1 -1
  44. package/dist/hosts/IRealtimeMediaHost.js +2 -1
  45. package/dist/hosts/IRealtimeMediaHost.js.map +1 -1
  46. package/dist/index.d.ts +21 -2
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +24 -0
  49. package/dist/index.js.map +1 -1
  50. package/dist/session/RealtimeSessionRuntime.d.ts +730 -70
  51. package/dist/session/RealtimeSessionRuntime.d.ts.map +1 -1
  52. package/dist/session/RealtimeSessionRuntime.js +1761 -241
  53. package/dist/session/RealtimeSessionRuntime.js.map +1 -1
  54. package/dist/session/RecordingShardQueue.d.ts +77 -0
  55. package/dist/session/RecordingShardQueue.d.ts.map +1 -0
  56. package/dist/session/RecordingShardQueue.js +172 -0
  57. package/dist/session/RecordingShardQueue.js.map +1 -0
  58. package/dist/session/app-client-tool-registry.d.ts +76 -0
  59. package/dist/session/app-client-tool-registry.d.ts.map +1 -0
  60. package/dist/session/app-client-tool-registry.js +100 -0
  61. package/dist/session/app-client-tool-registry.js.map +1 -0
  62. package/dist/session/avatar-notice.d.ts +43 -0
  63. package/dist/session/avatar-notice.d.ts.map +1 -0
  64. package/dist/session/avatar-notice.js +60 -0
  65. package/dist/session/avatar-notice.js.map +1 -0
  66. package/dist/session/call-end.d.ts +21 -0
  67. package/dist/session/call-end.d.ts.map +1 -0
  68. package/dist/session/call-end.js +19 -0
  69. package/dist/session/call-end.js.map +1 -0
  70. package/dist/session/channel-exposure-preferences.d.ts +70 -0
  71. package/dist/session/channel-exposure-preferences.d.ts.map +1 -0
  72. package/dist/session/channel-exposure-preferences.js +138 -0
  73. package/dist/session/channel-exposure-preferences.js.map +1 -0
  74. package/dist/session/channel-session-scope.d.ts +142 -0
  75. package/dist/session/channel-session-scope.d.ts.map +1 -0
  76. package/dist/session/channel-session-scope.js +128 -0
  77. package/dist/session/channel-session-scope.js.map +1 -0
  78. package/dist/session/client-session-deadline.d.ts +28 -0
  79. package/dist/session/client-session-deadline.d.ts.map +1 -0
  80. package/dist/session/client-session-deadline.js +50 -0
  81. package/dist/session/client-session-deadline.js.map +1 -0
  82. package/dist/session/realtime-captures.d.ts +236 -0
  83. package/dist/session/realtime-captures.d.ts.map +1 -0
  84. package/dist/session/realtime-captures.js +383 -0
  85. package/dist/session/realtime-captures.js.map +1 -0
  86. package/dist/session/realtime-microphone.d.ts +50 -0
  87. package/dist/session/realtime-microphone.d.ts.map +1 -0
  88. package/dist/session/realtime-microphone.js +51 -0
  89. package/dist/session/realtime-microphone.js.map +1 -0
  90. package/dist/session/session-event-hub.d.ts +72 -0
  91. package/dist/session/session-event-hub.d.ts.map +1 -0
  92. package/dist/session/session-event-hub.js +151 -0
  93. package/dist/session/session-event-hub.js.map +1 -0
  94. package/dist/session/session-launcher.d.ts +128 -0
  95. package/dist/session/session-launcher.d.ts.map +1 -0
  96. package/dist/session/session-launcher.js +160 -0
  97. package/dist/session/session-launcher.js.map +1 -0
  98. package/package.json +9 -9
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RecordingShardQueue.js","sourceRoot":"","sources":["../../src/session/RecordingShardQueue.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * @fileoverview The **owner-keyed registry of app client tools** a host registers with a realtime
3
+ * session (the tools the `ContextTool` proxy can run in the browser).
4
+ *
5
+ * The first version of this registry had one operation: *replace everything*. That is a trap the
6
+ * moment a host has two sources of tools. Explorer has two — a set of always-available globals
7
+ * (navigate, open a record, set the theme) and the tools of whichever surface the user is looking
8
+ * at — and registering the surface's tools replaced the globals unless the caller remembered to
9
+ * merge them back, and left the *previous* surface's tools registered if it forgot to clear them
10
+ * (the stale-tools-after-app-switch bug).
11
+ *
12
+ * The fix is ownership. Each source registers under an **owner key** and a registration replaces
13
+ * **only that owner's set**:
14
+ *
15
+ * ```
16
+ * Register('explorer.global', [NavigateToApp, NavigateToRecord, …]) // once
17
+ * Register('explorer.surface', [SetFilter, …]) // on every surface change
18
+ * Register('explorer.surface', []) // surface gone → ONLY its tools go
19
+ * ```
20
+ *
21
+ * When two owners register a tool with the same name, the **later-registered owner wins** (an
22
+ * owner keeps its slot when it re-registers, so precedence does not flip every time a surface
23
+ * refreshes) — the more specific source is registered after the more general one.
24
+ *
25
+ * @module @memberjunction/realtime-runtime
26
+ */
27
+ import type { ClientToolMetadata } from '@memberjunction/ai-core-plus';
28
+ /** Runs a client tool in the browser and returns its result (may be sync or async). */
29
+ export type RealtimeAppClientToolHandler = (params: Record<string, unknown>) => Promise<unknown> | unknown;
30
+ /**
31
+ * One tool a host registers. Only `Name` and `Handler` are required; the optional metadata makes the
32
+ * tool describable (in "available tools" error messages and the resolved capability set) without the
33
+ * host publishing a separate manifest.
34
+ */
35
+ export interface AppClientToolRegistration {
36
+ /** The tool name the model calls (matched case-insensitively). */
37
+ Name: string;
38
+ /** Executes the tool. */
39
+ Handler: RealtimeAppClientToolHandler;
40
+ /** What the tool does, for the model. */
41
+ Description?: string;
42
+ /** JSON Schema of the tool's parameters. */
43
+ InputSchema?: Record<string, unknown>;
44
+ /** Grouping label. */
45
+ Category?: string;
46
+ }
47
+ /** The owner key used by the single-argument `RegisterAppClientTools(tools)` form. */
48
+ export declare const DEFAULT_APP_TOOL_OWNER = "default";
49
+ /** Owner-keyed registry; see the module documentation. */
50
+ export declare class AppClientToolRegistry {
51
+ /** Owner → (lower-cased tool name → registration). Map insertion order = owner precedence (later wins). */
52
+ private readonly owners;
53
+ /**
54
+ * Replaces the tool set of ONE owner; every other owner's tools are untouched. Invalid entries
55
+ * (no name, no handler) are skipped. An empty list clears the owner's tools (it keeps its place in the
56
+ * precedence order; {@link Unregister} gives the place up too).
57
+ *
58
+ * @param owner A stable key naming the source (`'explorer.surface'`). Blank → {@link DEFAULT_APP_TOOL_OWNER}.
59
+ * @param tools The owner's complete current set.
60
+ */
61
+ Register(owner: string, tools: ReadonlyArray<AppClientToolRegistration>): void;
62
+ /** Removes one owner's tools (no-op when it has none). */
63
+ Unregister(owner: string): void;
64
+ /** Removes every owner's tools. */
65
+ Clear(): void;
66
+ /** Finds a tool by name (case-insensitive); on a collision the later-registered owner wins. */
67
+ Find(name: string): AppClientToolRegistration | undefined;
68
+ /** The distinct registered tool names, in registration form. */
69
+ Names(): string[];
70
+ /**
71
+ * The registered tools as {@link ClientToolMetadata} — the *session tier* of `ResolveClientTools`.
72
+ * Ordered later-owner-first, so the resolver's first-match-wins agrees with {@link Find}.
73
+ */
74
+ ToMetadata(): ClientToolMetadata[];
75
+ }
76
+ //# sourceMappingURL=app-client-tool-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-client-tool-registry.d.ts","sourceRoot":"","sources":["../../src/session/app-client-tool-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAEvE,uFAAuF;AACvF,MAAM,MAAM,4BAA4B,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;AAE3G;;;;GAIG;AACH,MAAM,WAAW,yBAAyB;IACtC,kEAAkE;IAClE,IAAI,EAAE,MAAM,CAAC;IACb,yBAAyB;IACzB,OAAO,EAAE,4BAA4B,CAAC;IACtC,yCAAyC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4CAA4C;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,sBAAsB;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,sFAAsF;AACtF,eAAO,MAAM,sBAAsB,YAAY,CAAC;AAEhD,0DAA0D;AAC1D,qBAAa,qBAAqB;IAC9B,2GAA2G;IAC3G,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA6D;IAEpF;;;;;;;OAOG;IACI,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,CAAC,yBAAyB,CAAC,GAAG,IAAI;IAarF,0DAA0D;IACnD,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAItC,mCAAmC;IAC5B,KAAK,IAAI,IAAI;IAIpB,+FAA+F;IACxF,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,yBAAyB,GAAG,SAAS;IAShE,gEAAgE;IACzD,KAAK,IAAI,MAAM,EAAE;IAUxB;;;OAGG;IACI,UAAU,IAAI,kBAAkB,EAAE;CAW5C"}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * @fileoverview The **owner-keyed registry of app client tools** a host registers with a realtime
3
+ * session (the tools the `ContextTool` proxy can run in the browser).
4
+ *
5
+ * The first version of this registry had one operation: *replace everything*. That is a trap the
6
+ * moment a host has two sources of tools. Explorer has two — a set of always-available globals
7
+ * (navigate, open a record, set the theme) and the tools of whichever surface the user is looking
8
+ * at — and registering the surface's tools replaced the globals unless the caller remembered to
9
+ * merge them back, and left the *previous* surface's tools registered if it forgot to clear them
10
+ * (the stale-tools-after-app-switch bug).
11
+ *
12
+ * The fix is ownership. Each source registers under an **owner key** and a registration replaces
13
+ * **only that owner's set**:
14
+ *
15
+ * ```
16
+ * Register('explorer.global', [NavigateToApp, NavigateToRecord, …]) // once
17
+ * Register('explorer.surface', [SetFilter, …]) // on every surface change
18
+ * Register('explorer.surface', []) // surface gone → ONLY its tools go
19
+ * ```
20
+ *
21
+ * When two owners register a tool with the same name, the **later-registered owner wins** (an
22
+ * owner keeps its slot when it re-registers, so precedence does not flip every time a surface
23
+ * refreshes) — the more specific source is registered after the more general one.
24
+ *
25
+ * @module @memberjunction/realtime-runtime
26
+ */
27
+ /** The owner key used by the single-argument `RegisterAppClientTools(tools)` form. */
28
+ export const DEFAULT_APP_TOOL_OWNER = 'default';
29
+ /** Owner-keyed registry; see the module documentation. */
30
+ export class AppClientToolRegistry {
31
+ constructor() {
32
+ /** Owner → (lower-cased tool name → registration). Map insertion order = owner precedence (later wins). */
33
+ this.owners = new Map();
34
+ }
35
+ /**
36
+ * Replaces the tool set of ONE owner; every other owner's tools are untouched. Invalid entries
37
+ * (no name, no handler) are skipped. An empty list clears the owner's tools (it keeps its place in the
38
+ * precedence order; {@link Unregister} gives the place up too).
39
+ *
40
+ * @param owner A stable key naming the source (`'explorer.surface'`). Blank → {@link DEFAULT_APP_TOOL_OWNER}.
41
+ * @param tools The owner's complete current set.
42
+ */
43
+ Register(owner, tools) {
44
+ const key = normalizeOwner(owner);
45
+ const set = new Map();
46
+ for (const tool of tools) {
47
+ if (tool?.Name?.trim() && typeof tool.Handler === 'function') {
48
+ set.set(tool.Name.trim().toLowerCase(), tool);
49
+ }
50
+ }
51
+ // Map#set on an existing key keeps its insertion slot, so an owner that re-registers (even with
52
+ // an empty set) keeps its place in the precedence order; only Unregister() gives the slot up.
53
+ this.owners.set(key, set);
54
+ }
55
+ /** Removes one owner's tools (no-op when it has none). */
56
+ Unregister(owner) {
57
+ this.owners.delete(normalizeOwner(owner));
58
+ }
59
+ /** Removes every owner's tools. */
60
+ Clear() {
61
+ this.owners.clear();
62
+ }
63
+ /** Finds a tool by name (case-insensitive); on a collision the later-registered owner wins. */
64
+ Find(name) {
65
+ const wanted = (name ?? '').trim().toLowerCase();
66
+ let found;
67
+ for (const set of this.owners.values()) {
68
+ found = set.get(wanted) ?? found;
69
+ }
70
+ return found;
71
+ }
72
+ /** The distinct registered tool names, in registration form. */
73
+ Names() {
74
+ const names = new Map();
75
+ for (const set of this.owners.values()) {
76
+ for (const [lower, tool] of set) {
77
+ names.set(lower, tool.Name);
78
+ }
79
+ }
80
+ return [...names.values()];
81
+ }
82
+ /**
83
+ * The registered tools as {@link ClientToolMetadata} — the *session tier* of `ResolveClientTools`.
84
+ * Ordered later-owner-first, so the resolver's first-match-wins agrees with {@link Find}.
85
+ */
86
+ ToMetadata() {
87
+ const ordered = [...this.owners.values()].reverse();
88
+ return ordered.flatMap((set) => [...set.values()].map((tool) => ({
89
+ Name: tool.Name,
90
+ Description: tool.Description ?? '',
91
+ InputSchema: tool.InputSchema ?? {},
92
+ Category: tool.Category,
93
+ })));
94
+ }
95
+ }
96
+ /** Normalizes an owner key; blank falls back to the default owner. */
97
+ function normalizeOwner(owner) {
98
+ return owner?.trim() ? owner.trim() : DEFAULT_APP_TOOL_OWNER;
99
+ }
100
+ //# sourceMappingURL=app-client-tool-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-client-tool-registry.js","sourceRoot":"","sources":["../../src/session/app-client-tool-registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * @fileoverview Whether a connected call tells the user it shows no avatar, and why.
3
+ *
4
+ * The server decides the reasons it can see at mint (the model renders no avatar, the persona has no face for it, a
5
+ * custom avatar, an app that said at mint it shows no agent video: `host`) and returns them as the session's avatar
6
+ * status. Two more show only in the browser, once the call is connected: the app asked for no agent video (`host`), or
7
+ * it asked and the browser could not play it (`browser`). {@link ResolveAvatarNotice} puts the three facts together; the
8
+ * runtime publishes the result once per call.
9
+ *
10
+ * @module @memberjunction/realtime-runtime
11
+ */
12
+ import type { ClientRealtimeSessionConfig, ParsedRealtimeAvatarStatus, RealtimeAvatarUnavailableReason } from '@memberjunction/ai';
13
+ /** Why a call shows no avatar, told once after it connects. A host turns the reason into words. */
14
+ export interface RealtimeAvatarNotice {
15
+ /**
16
+ * Why the call is audio only. Absent when the mint gave a reason this version doesn't know, such as a newer server's:
17
+ * the avatar was asked for and isn't shown, and a host says so without a reason.
18
+ */
19
+ readonly Reason?: RealtimeAvatarUnavailableReason;
20
+ }
21
+ /**
22
+ * Whether a connected call should say it shows no avatar, and why.
23
+ *
24
+ * - No status, or the session asked for no avatar: nothing to say.
25
+ * - Asked for and not granted: the status's reason; a notice without one when the reason is one this version doesn't
26
+ * know (`ReasonUnknown`); nothing when the status gives no reason.
27
+ * - Granted, but the app asked for no agent video: `host`.
28
+ * - Granted and asked for, but the agent's video track is not live: `browser`.
29
+ * - Granted, asked for and live: nothing to say; the avatar shows.
30
+ *
31
+ * @param status The mint's avatar status as `ParseRealtimeAvatarStatus` reads it, or `null` when the mint reported none.
32
+ * @param requested Whether the session asked for the agent's video (an outbound video track).
33
+ * @param established Whether the agent's video track is live once connected.
34
+ * @returns The notice, or `null` when there is nothing to say.
35
+ */
36
+ export declare function ResolveAvatarNotice(status: ParsedRealtimeAvatarStatus | null, requested: boolean, established: boolean): RealtimeAvatarNotice | null;
37
+ /**
38
+ * Whether a client config asks for the agent's video: an outbound video track among the tracks the session requests.
39
+ *
40
+ * @param config The config the session connected with.
41
+ */
42
+ export declare function RequestsAgentVideo(config: ClientRealtimeSessionConfig): boolean;
43
+ //# sourceMappingURL=avatar-notice.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"avatar-notice.d.ts","sourceRoot":"","sources":["../../src/session/avatar-notice.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,2BAA2B,EAAa,0BAA0B,EAAE,+BAA+B,EAAE,MAAM,oBAAoB,CAAC;AAG9I,mGAAmG;AACnG,MAAM,WAAW,oBAAoB;IACnC;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,+BAA+B,CAAC;CACnD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,0BAA0B,GAAG,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,GAAG,oBAAoB,GAAG,IAAI,CAcpJ;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,2BAA2B,GAAG,OAAO,CAG/E"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * @fileoverview Whether a connected call tells the user it shows no avatar, and why.
3
+ *
4
+ * The server decides the reasons it can see at mint (the model renders no avatar, the persona has no face for it, a
5
+ * custom avatar, an app that said at mint it shows no agent video: `host`) and returns them as the session's avatar
6
+ * status. Two more show only in the browser, once the call is connected: the app asked for no agent video (`host`), or
7
+ * it asked and the browser could not play it (`browser`). {@link ResolveAvatarNotice} puts the three facts together; the
8
+ * runtime publishes the result once per call.
9
+ *
10
+ * @module @memberjunction/realtime-runtime
11
+ */
12
+ import { REQUESTED_TRACKS_SESSION_KEY } from '@memberjunction/ai-realtime-client';
13
+ /**
14
+ * Whether a connected call should say it shows no avatar, and why.
15
+ *
16
+ * - No status, or the session asked for no avatar: nothing to say.
17
+ * - Asked for and not granted: the status's reason; a notice without one when the reason is one this version doesn't
18
+ * know (`ReasonUnknown`); nothing when the status gives no reason.
19
+ * - Granted, but the app asked for no agent video: `host`.
20
+ * - Granted and asked for, but the agent's video track is not live: `browser`.
21
+ * - Granted, asked for and live: nothing to say; the avatar shows.
22
+ *
23
+ * @param status The mint's avatar status as `ParseRealtimeAvatarStatus` reads it, or `null` when the mint reported none.
24
+ * @param requested Whether the session asked for the agent's video (an outbound video track).
25
+ * @param established Whether the agent's video track is live once connected.
26
+ * @returns The notice, or `null` when there is nothing to say.
27
+ */
28
+ export function ResolveAvatarNotice(status, requested, established) {
29
+ if (!status?.Requested) {
30
+ return null;
31
+ }
32
+ if (!status.Granted) {
33
+ if (status.Reason) {
34
+ return { Reason: status.Reason };
35
+ }
36
+ return status.ReasonUnknown ? {} : null;
37
+ }
38
+ if (!requested) {
39
+ return { Reason: 'host' };
40
+ }
41
+ return established ? null : { Reason: 'browser' };
42
+ }
43
+ /**
44
+ * Whether a client config asks for the agent's video: an outbound video track among the tracks the session requests.
45
+ *
46
+ * @param config The config the session connected with.
47
+ */
48
+ export function RequestsAgentVideo(config) {
49
+ const tracks = config.SessionConfig[REQUESTED_TRACKS_SESSION_KEY];
50
+ return Array.isArray(tracks) && tracks.some(isAgentVideoTrack);
51
+ }
52
+ /** Whether a requested-track entry is the agent's video: outbound, video. */
53
+ function isAgentVideoTrack(raw) {
54
+ if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {
55
+ return false;
56
+ }
57
+ const modality = raw['Modality'];
58
+ return raw['Direction'] === 'outbound' && typeof modality === 'string' && modality.trim().toLowerCase() === 'video';
59
+ }
60
+ //# sourceMappingURL=avatar-notice.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"avatar-notice.js","sourceRoot":"","sources":["../../src/session/avatar-notice.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EAAE,4BAA4B,EAAE,MAAM,oCAAoC,CAAC;AAWlF;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAyC,EAAE,SAAkB,EAAE,WAAoB;IACrH,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YAClB,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;QACnC,CAAC;QACD,OAAO,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAC1C,CAAC;IACD,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAC5B,CAAC;IACD,OAAO,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;AACpD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAmC;IACpE,MAAM,MAAM,GAAG,MAAM,CAAC,aAAa,CAAC,4BAA4B,CAAC,CAAC;IAClE,OAAO,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;AACjE,CAAC;AAED,6EAA6E;AAC7E,SAAS,iBAAiB,CAAC,GAAc;IACvC,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAClE,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,QAAQ,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC;IACjC,OAAO,GAAG,CAAC,WAAW,CAAC,KAAK,UAAU,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,OAAO,CAAC;AACtH,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { type RealtimeClientError } from '@memberjunction/ai-realtime-client';
2
+ /** How a host words why a call ended: a short status label, and a sentence for a screen or a notice. */
3
+ export interface RealtimeCallEndDescription {
4
+ /** A short status label, such as a call bar's state chip shows. */
5
+ Label: string;
6
+ /** A sentence saying what happened and what to do next. */
7
+ Message: string;
8
+ }
9
+ /**
10
+ * What a call says when it ended because its session reached its time limit (MJAPI's relay ends a relayed call at
11
+ * 30 minutes, or sooner when the session has a shorter cap), in place of a connection error.
12
+ */
13
+ export declare const REALTIME_CALL_TIME_LIMIT_END: Readonly<RealtimeCallEndDescription>;
14
+ /**
15
+ * Why a call ended, in words a host can show, when the call's client said why (`RealtimeSessionRuntime.LastSessionError`);
16
+ * `null` when it ended for a reason with no words of its own, such as a dropped connection, which a host words itself.
17
+ *
18
+ * @param error The call's fatal client error, or `null` when it reported none.
19
+ */
20
+ export declare function DescribeCallEnd(error: RealtimeClientError | null): Readonly<RealtimeCallEndDescription> | null;
21
+ //# sourceMappingURL=call-end.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"call-end.d.ts","sourceRoot":"","sources":["../../src/session/call-end.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyC,KAAK,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AAErH,wGAAwG;AACxG,MAAM,WAAW,0BAA0B;IACvC,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,OAAO,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,eAAO,MAAM,4BAA4B,EAAE,QAAQ,CAAC,0BAA0B,CAG5E,CAAC;AAEH;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,mBAAmB,GAAG,IAAI,GAAG,QAAQ,CAAC,0BAA0B,CAAC,GAAG,IAAI,CAE9G"}
@@ -0,0 +1,19 @@
1
+ import { REALTIME_CLIENT_TIME_LIMIT_ERROR_CODE } from '@memberjunction/ai-realtime-client';
2
+ /**
3
+ * What a call says when it ended because its session reached its time limit (MJAPI's relay ends a relayed call at
4
+ * 30 minutes, or sooner when the session has a shorter cap), in place of a connection error.
5
+ */
6
+ export const REALTIME_CALL_TIME_LIMIT_END = Object.freeze({
7
+ Label: 'Time limit reached',
8
+ Message: 'This call reached its time limit. Start a new call to keep talking.',
9
+ });
10
+ /**
11
+ * Why a call ended, in words a host can show, when the call's client said why (`RealtimeSessionRuntime.LastSessionError`);
12
+ * `null` when it ended for a reason with no words of its own, such as a dropped connection, which a host words itself.
13
+ *
14
+ * @param error The call's fatal client error, or `null` when it reported none.
15
+ */
16
+ export function DescribeCallEnd(error) {
17
+ return error?.Code === REALTIME_CLIENT_TIME_LIMIT_ERROR_CODE ? REALTIME_CALL_TIME_LIMIT_END : null;
18
+ }
19
+ //# sourceMappingURL=call-end.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"call-end.js","sourceRoot":"","sources":["../../src/session/call-end.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qCAAqC,EAA4B,MAAM,oCAAoC,CAAC;AAUrH;;;GAGG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAyC,MAAM,CAAC,MAAM,CAAC;IAC5F,KAAK,EAAE,oBAAoB;IAC3B,OAAO,EAAE,qEAAqE;CACjF,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,KAAiC;IAC7D,OAAO,KAAK,EAAE,IAAI,KAAK,qCAAqC,CAAC,CAAC,CAAC,4BAA4B,CAAC,CAAC,CAAC,IAAI,CAAC;AACvG,CAAC"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * @fileoverview The user's own choice of how much of each channel the agent may perceive.
3
+ *
4
+ * Exposure policy has four layers (see `ResolveChannelExposure` in `@memberjunction/ai-core-plus`); the
5
+ * fourth is the USER's, set from the "agent can see" control in the realtime overlay and remembered per
6
+ * channel key so a person who turned the agent's view of their whiteboard off does not have to do it
7
+ * again next call.
8
+ *
9
+ * Where it is remembered is the host's business, which is why this is an interface: the runtime is
10
+ * framework-neutral and does not know whether the person is signed in. Signed-in hosts back it with the
11
+ * user's persisted settings (`mj.realtime.visualPerception.v1`, via `UserInfoEngine`); an anonymous
12
+ * principal or a connect-only embed has no settings to write to and uses the in-memory store, so the
13
+ * choice lasts for the page and no longer.
14
+ *
15
+ * @module @memberjunction/realtime-runtime
16
+ */
17
+ import { type RealtimeChannelExposure } from '@memberjunction/ai-core-plus';
18
+ /**
19
+ * The `UserInfoEngine` setting key the choices are persisted under, per user. The `v1` is the shape of
20
+ * the stored JSON ({@link SerializeExposurePreferences}); bump it if that shape ever changes so old
21
+ * values can be read and migrated rather than misread.
22
+ */
23
+ export declare const VISUAL_PERCEPTION_SETTING_KEY = "mj.realtime.visualPerception.v1";
24
+ /** Where the user's per-channel exposure choices are kept. */
25
+ export interface IChannelExposurePreferences {
26
+ /** The user's choice for a channel (key matched case-insensitively), or `undefined` when they made none. */
27
+ Get(channelKey: string): RealtimeChannelExposure | undefined;
28
+ /** Records the user's choice for a channel. `undefined` clears it (back to "no choice"). */
29
+ Set(channelKey: string, level: RealtimeChannelExposure | undefined): void;
30
+ }
31
+ /**
32
+ * Reads persisted choices tolerantly: a hand-edited or corrupt value contributes nothing (never throws), and
33
+ * only valid levels survive. Keys come back normalized.
34
+ *
35
+ * @param json The stored setting value, or `undefined`/`null`/blank when there is none.
36
+ */
37
+ export declare function ParseExposurePreferences(json: string | null | undefined): Map<string, RealtimeChannelExposure>;
38
+ /**
39
+ * Serializes choices for persistence. Only the choices themselves are stored (`{"whiteboard":"state"}`):
40
+ * a channel the user never touched has no entry, so a later change to a channel's default is not
41
+ * frozen in by an old write.
42
+ */
43
+ export declare function SerializeExposurePreferences(preferences: ReadonlyMap<string, RealtimeChannelExposure>): string;
44
+ /** The default store: choices last for this object's lifetime only. */
45
+ export declare class InMemoryChannelExposurePreferences implements IChannelExposurePreferences {
46
+ private readonly values;
47
+ Get(channelKey: string): RealtimeChannelExposure | undefined;
48
+ Set(channelKey: string, level: RealtimeChannelExposure | undefined): void;
49
+ }
50
+ /**
51
+ * The default store: persisted in the signed-in user's settings (`MJ: User Settings`, key
52
+ * {@link VISUAL_PERCEPTION_SETTING_KEY}) via `UserInfoEngine`, so the choice follows the person across
53
+ * devices; kept in memory when there is no user to persist for (an anonymous principal, a connect-only embed).
54
+ *
55
+ * Writes always go to memory first, so a choice takes effect and is read back even if persisting it
56
+ * fails or is not possible. Reads prefer the persisted value when persistence is available, since
57
+ * `UserInfoEngine.GetSetting` is a synchronous cache hit that already reflects a pending debounced write.
58
+ */
59
+ export declare class UserSettingsExposurePreferences implements IChannelExposurePreferences {
60
+ private readonly canPersist;
61
+ private readonly memory;
62
+ private warnedAboutRead;
63
+ /** @param canPersist Whether user settings can be read and written right now (a signed-in user on a metadata-bearing provider). */
64
+ constructor(canPersist: () => boolean);
65
+ Get(channelKey: string): RealtimeChannelExposure | undefined;
66
+ Set(channelKey: string, level: RealtimeChannelExposure | undefined): void;
67
+ /** The persisted choices; empty (and logged once) when the settings cache cannot be read. */
68
+ private readPersisted;
69
+ }
70
+ //# sourceMappingURL=channel-exposure-preferences.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel-exposure-preferences.d.ts","sourceRoot":"","sources":["../../src/session/channel-exposure-preferences.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EAAwC,KAAK,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAElH;;;;GAIG;AACH,eAAO,MAAM,6BAA6B,oCAAoC,CAAC;AAE/E,8DAA8D;AAC9D,MAAM,WAAW,2BAA2B;IAC1C,4GAA4G;IAC5G,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,uBAAuB,GAAG,SAAS,CAAC;IAC7D,4FAA4F;IAC5F,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,uBAAuB,GAAG,SAAS,GAAG,IAAI,CAAC;CAC3E;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,GAAG,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAqB9G;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,WAAW,EAAE,WAAW,CAAC,MAAM,EAAE,uBAAuB,CAAC,GAAG,MAAM,CAS9G;AAED,uEAAuE;AACvE,qBAAa,kCAAmC,YAAW,2BAA2B;IACpF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA8C;IAE9D,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,uBAAuB,GAAG,SAAS;IAI5D,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,uBAAuB,GAAG,SAAS,GAAG,IAAI;CAQjF;AAED;;;;;;;;GAQG;AACH,qBAAa,+BAAgC,YAAW,2BAA2B;IAKrE,OAAO,CAAC,QAAQ,CAAC,UAAU;IAJvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA4C;IACnE,OAAO,CAAC,eAAe,CAAS;IAEhC,mIAAmI;gBACtG,UAAU,EAAE,MAAM,OAAO;IAE/C,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,uBAAuB,GAAG,SAAS;IAO5D,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,uBAAuB,GAAG,SAAS,GAAG,IAAI;IAehF,6FAA6F;IAC7F,OAAO,CAAC,aAAa;CAWtB"}
@@ -0,0 +1,138 @@
1
+ /**
2
+ * @fileoverview The user's own choice of how much of each channel the agent may perceive.
3
+ *
4
+ * Exposure policy has four layers (see `ResolveChannelExposure` in `@memberjunction/ai-core-plus`); the
5
+ * fourth is the USER's, set from the "agent can see" control in the realtime overlay and remembered per
6
+ * channel key so a person who turned the agent's view of their whiteboard off does not have to do it
7
+ * again next call.
8
+ *
9
+ * Where it is remembered is the host's business, which is why this is an interface: the runtime is
10
+ * framework-neutral and does not know whether the person is signed in. Signed-in hosts back it with the
11
+ * user's persisted settings (`mj.realtime.visualPerception.v1`, via `UserInfoEngine`); an anonymous
12
+ * principal or a connect-only embed has no settings to write to and uses the in-memory store, so the
13
+ * choice lasts for the page and no longer.
14
+ *
15
+ * @module @memberjunction/realtime-runtime
16
+ */
17
+ import { UserInfoEngine } from '@memberjunction/core-entities';
18
+ import { IsExposureLevel, NormalizeChannelKey } from '@memberjunction/ai-core-plus';
19
+ /**
20
+ * The `UserInfoEngine` setting key the choices are persisted under, per user. The `v1` is the shape of
21
+ * the stored JSON ({@link SerializeExposurePreferences}); bump it if that shape ever changes so old
22
+ * values can be read and migrated rather than misread.
23
+ */
24
+ export const VISUAL_PERCEPTION_SETTING_KEY = 'mj.realtime.visualPerception.v1';
25
+ /**
26
+ * Reads persisted choices tolerantly: a hand-edited or corrupt value contributes nothing (never throws), and
27
+ * only valid levels survive. Keys come back normalized.
28
+ *
29
+ * @param json The stored setting value, or `undefined`/`null`/blank when there is none.
30
+ */
31
+ export function ParseExposurePreferences(json) {
32
+ const result = new Map();
33
+ if (typeof json !== 'string' || json.trim().length === 0) {
34
+ return result;
35
+ }
36
+ let parsed;
37
+ try {
38
+ parsed = JSON.parse(json);
39
+ }
40
+ catch {
41
+ return result;
42
+ }
43
+ if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
44
+ return result;
45
+ }
46
+ for (const [key, value] of Object.entries(parsed)) {
47
+ const id = NormalizeChannelKey(key);
48
+ if (id.length > 0 && IsExposureLevel(value)) {
49
+ result.set(id, value);
50
+ }
51
+ }
52
+ return result;
53
+ }
54
+ /**
55
+ * Serializes choices for persistence. Only the choices themselves are stored (`{"whiteboard":"state"}`):
56
+ * a channel the user never touched has no entry, so a later change to a channel's default is not
57
+ * frozen in by an old write.
58
+ */
59
+ export function SerializeExposurePreferences(preferences) {
60
+ const record = {};
61
+ for (const [key, level] of preferences) {
62
+ if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
63
+ continue;
64
+ }
65
+ record[key] = level;
66
+ }
67
+ return JSON.stringify(record);
68
+ }
69
+ /** The default store: choices last for this object's lifetime only. */
70
+ export class InMemoryChannelExposurePreferences {
71
+ constructor() {
72
+ this.values = new Map();
73
+ }
74
+ Get(channelKey) {
75
+ return this.values.get(NormalizeChannelKey(channelKey));
76
+ }
77
+ Set(channelKey, level) {
78
+ const id = NormalizeChannelKey(channelKey);
79
+ if (level === undefined) {
80
+ this.values.delete(id);
81
+ }
82
+ else {
83
+ this.values.set(id, level);
84
+ }
85
+ }
86
+ }
87
+ /**
88
+ * The default store: persisted in the signed-in user's settings (`MJ: User Settings`, key
89
+ * {@link VISUAL_PERCEPTION_SETTING_KEY}) via `UserInfoEngine`, so the choice follows the person across
90
+ * devices; kept in memory when there is no user to persist for (an anonymous principal, a connect-only embed).
91
+ *
92
+ * Writes always go to memory first, so a choice takes effect and is read back even if persisting it
93
+ * fails or is not possible. Reads prefer the persisted value when persistence is available, since
94
+ * `UserInfoEngine.GetSetting` is a synchronous cache hit that already reflects a pending debounced write.
95
+ */
96
+ export class UserSettingsExposurePreferences {
97
+ /** @param canPersist Whether user settings can be read and written right now (a signed-in user on a metadata-bearing provider). */
98
+ constructor(canPersist) {
99
+ this.canPersist = canPersist;
100
+ this.memory = new InMemoryChannelExposurePreferences();
101
+ this.warnedAboutRead = false;
102
+ }
103
+ Get(channelKey) {
104
+ if (!this.canPersist()) {
105
+ return this.memory.Get(channelKey);
106
+ }
107
+ return this.readPersisted().get(NormalizeChannelKey(channelKey)) ?? this.memory.Get(channelKey);
108
+ }
109
+ Set(channelKey, level) {
110
+ this.memory.Set(channelKey, level);
111
+ if (!this.canPersist()) {
112
+ return;
113
+ }
114
+ const persisted = this.readPersisted();
115
+ const id = NormalizeChannelKey(channelKey);
116
+ if (level === undefined) {
117
+ persisted.delete(id);
118
+ }
119
+ else {
120
+ persisted.set(id, level);
121
+ }
122
+ UserInfoEngine.Instance.SetSettingDebounced(VISUAL_PERCEPTION_SETTING_KEY, SerializeExposurePreferences(persisted));
123
+ }
124
+ /** The persisted choices; empty (and logged once) when the settings cache cannot be read. */
125
+ readPersisted() {
126
+ try {
127
+ return ParseExposurePreferences(UserInfoEngine.Instance.GetSetting(VISUAL_PERCEPTION_SETTING_KEY));
128
+ }
129
+ catch (error) {
130
+ if (!this.warnedAboutRead) {
131
+ this.warnedAboutRead = true;
132
+ console.warn('[RealtimeSession] Could not read the saved visual-perception choices; using this page\'s choices only:', error);
133
+ }
134
+ return new Map();
135
+ }
136
+ }
137
+ }
138
+ //# sourceMappingURL=channel-exposure-preferences.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel-exposure-preferences.js","sourceRoot":"","sources":["../../src/session/channel-exposure-preferences.ts"],"names":[],"mappings":"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"}