@memberjunction/realtime-runtime 6.2.0-edge.3 → 6.2.0-edge.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +75 -0
- package/dist/channels/base-realtime-channel-client.d.ts +535 -28
- package/dist/channels/base-realtime-channel-client.d.ts.map +1 -1
- package/dist/channels/base-realtime-channel-client.js +864 -10
- package/dist/channels/base-realtime-channel-client.js.map +1 -1
- package/dist/channels/channel-action-dispatcher.d.ts +70 -0
- package/dist/channels/channel-action-dispatcher.d.ts.map +1 -0
- package/dist/channels/channel-action-dispatcher.js +136 -0
- package/dist/channels/channel-action-dispatcher.js.map +1 -0
- package/dist/channels/channel-catalog-note.d.ts +48 -0
- package/dist/channels/channel-catalog-note.d.ts.map +1 -0
- package/dist/channels/channel-catalog-note.js +119 -0
- package/dist/channels/channel-catalog-note.js.map +1 -0
- package/dist/channels/channel-contract-types.d.ts +107 -0
- package/dist/channels/channel-contract-types.d.ts.map +1 -0
- package/dist/channels/channel-contract-types.js +12 -0
- package/dist/channels/channel-contract-types.js.map +1 -0
- package/dist/channels/channel-descriptor-synthesis.d.ts +56 -0
- package/dist/channels/channel-descriptor-synthesis.d.ts.map +1 -0
- package/dist/channels/channel-descriptor-synthesis.js +90 -0
- package/dist/channels/channel-descriptor-synthesis.js.map +1 -0
- package/dist/channels/channel-perception.d.ts +82 -0
- package/dist/channels/channel-perception.d.ts.map +1 -0
- package/dist/channels/channel-perception.js +120 -0
- package/dist/channels/channel-perception.js.map +1 -0
- package/dist/channels/channel-schema-format.d.ts +17 -0
- package/dist/channels/channel-schema-format.d.ts.map +1 -0
- package/dist/channels/channel-schema-format.js +45 -0
- package/dist/channels/channel-schema-format.js.map +1 -0
- package/dist/channels/channel-state-delta.d.ts +59 -0
- package/dist/channels/channel-state-delta.d.ts.map +1 -0
- package/dist/channels/channel-state-delta.js +116 -0
- package/dist/channels/channel-state-delta.js.map +1 -0
- package/dist/channels/channel-surface-placement.d.ts +25 -0
- package/dist/channels/channel-surface-placement.d.ts.map +1 -0
- package/dist/channels/channel-surface-placement.js +29 -0
- package/dist/channels/channel-surface-placement.js.map +1 -0
- package/dist/channels/channel-visual-pump.d.ts +126 -0
- package/dist/channels/channel-visual-pump.d.ts.map +1 -0
- package/dist/channels/channel-visual-pump.js +174 -0
- package/dist/channels/channel-visual-pump.js.map +1 -0
- package/dist/hosts/IRealtimeMediaHost.d.ts +86 -34
- package/dist/hosts/IRealtimeMediaHost.d.ts.map +1 -1
- package/dist/hosts/IRealtimeMediaHost.js +2 -1
- package/dist/hosts/IRealtimeMediaHost.js.map +1 -1
- package/dist/index.d.ts +26 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +28 -1
- package/dist/index.js.map +1 -1
- package/dist/session/RealtimeSessionRuntime.d.ts +984 -111
- package/dist/session/RealtimeSessionRuntime.d.ts.map +1 -1
- package/dist/session/RealtimeSessionRuntime.js +2396 -381
- package/dist/session/RealtimeSessionRuntime.js.map +1 -1
- package/dist/session/RecordingShardDrain.d.ts +59 -0
- package/dist/session/RecordingShardDrain.d.ts.map +1 -0
- package/dist/session/RecordingShardDrain.js +135 -0
- package/dist/session/RecordingShardDrain.js.map +1 -0
- package/dist/session/RecordingShardQueue.d.ts +94 -0
- package/dist/session/RecordingShardQueue.d.ts.map +1 -0
- package/dist/session/RecordingShardQueue.js +176 -0
- package/dist/session/RecordingShardQueue.js.map +1 -0
- package/dist/session/RecordingShardStore.d.ts +57 -0
- package/dist/session/RecordingShardStore.d.ts.map +1 -0
- package/dist/session/RecordingShardStore.js +184 -0
- package/dist/session/RecordingShardStore.js.map +1 -0
- package/dist/session/RecordingShardWindow.d.ts +42 -0
- package/dist/session/RecordingShardWindow.d.ts.map +1 -0
- package/dist/session/RecordingShardWindow.js +88 -0
- package/dist/session/RecordingShardWindow.js.map +1 -0
- package/dist/session/RecordingTransport.d.ts +66 -0
- package/dist/session/RecordingTransport.d.ts.map +1 -0
- package/dist/session/RecordingTransport.js +61 -0
- package/dist/session/RecordingTransport.js.map +1 -0
- package/dist/session/app-client-tool-registry.d.ts +76 -0
- package/dist/session/app-client-tool-registry.d.ts.map +1 -0
- package/dist/session/app-client-tool-registry.js +100 -0
- package/dist/session/app-client-tool-registry.js.map +1 -0
- package/dist/session/avatar-notice.d.ts +43 -0
- package/dist/session/avatar-notice.d.ts.map +1 -0
- package/dist/session/avatar-notice.js +60 -0
- package/dist/session/avatar-notice.js.map +1 -0
- package/dist/session/call-end.d.ts +21 -0
- package/dist/session/call-end.d.ts.map +1 -0
- package/dist/session/call-end.js +19 -0
- package/dist/session/call-end.js.map +1 -0
- package/dist/session/channel-exposure-preferences.d.ts +70 -0
- package/dist/session/channel-exposure-preferences.d.ts.map +1 -0
- package/dist/session/channel-exposure-preferences.js +138 -0
- package/dist/session/channel-exposure-preferences.js.map +1 -0
- package/dist/session/channel-session-scope.d.ts +142 -0
- package/dist/session/channel-session-scope.d.ts.map +1 -0
- package/dist/session/channel-session-scope.js +128 -0
- package/dist/session/channel-session-scope.js.map +1 -0
- package/dist/session/client-session-deadline.d.ts +28 -0
- package/dist/session/client-session-deadline.d.ts.map +1 -0
- package/dist/session/client-session-deadline.js +50 -0
- package/dist/session/client-session-deadline.js.map +1 -0
- package/dist/session/realtime-captures.d.ts +236 -0
- package/dist/session/realtime-captures.d.ts.map +1 -0
- package/dist/session/realtime-captures.js +383 -0
- package/dist/session/realtime-captures.js.map +1 -0
- package/dist/session/realtime-microphone.d.ts +50 -0
- package/dist/session/realtime-microphone.d.ts.map +1 -0
- package/dist/session/realtime-microphone.js +51 -0
- package/dist/session/realtime-microphone.js.map +1 -0
- package/dist/session/session-event-hub.d.ts +72 -0
- package/dist/session/session-event-hub.d.ts.map +1 -0
- package/dist/session/session-event-hub.js +151 -0
- package/dist/session/session-event-hub.js.map +1 -0
- package/dist/session/session-launcher.d.ts +128 -0
- package/dist/session/session-launcher.d.ts.map +1 -0
- package/dist/session/session-launcher.js +160 -0
- package/dist/session/session-launcher.js.map +1 -0
- package/package.json +10 -9
|
@@ -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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"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview The **session-scoping helpers** of the realtime runtime — turning the channel plugins
|
|
3
|
+
* a session *could* have into the channels it *does* have.
|
|
4
|
+
*
|
|
5
|
+
* The decision itself (`ResolveRealtimeChannelScope`) is pure and lives in `@memberjunction/ai-core-plus`
|
|
6
|
+
* so the server and the browser make it identically. What lives here is the browser-side plumbing around it:
|
|
7
|
+
*
|
|
8
|
+
* - {@link PreparedChannel} — a plugin that has been *resolved* (from the registry or declared by the
|
|
9
|
+
* host) but not yet *initialized*. Preparing is side-effect free, which is what lets the runtime
|
|
10
|
+
* report candidates to the server at mint without having started anything the server may then veto.
|
|
11
|
+
* - {@link BuildChannelCandidate} / {@link ResolveLocalChannelScope} — the facts the browser reports,
|
|
12
|
+
* and the scope it resolves on its own when no server policy comes back (a legacy server, or a host
|
|
13
|
+
* that mints through its own proxy).
|
|
14
|
+
* - {@link ReconcileChannelsWithPolicy} — maps a resolved policy back onto the prepared plugins.
|
|
15
|
+
* - {@link MergeToolMetadata} — layers a host's registered tool handlers over the manifest the host
|
|
16
|
+
* streamed, so "available tools" messages can describe them.
|
|
17
|
+
*
|
|
18
|
+
* Framework-free and DOM-free: importable in plain Node tests.
|
|
19
|
+
*
|
|
20
|
+
* @module @memberjunction/realtime-runtime
|
|
21
|
+
*/
|
|
22
|
+
import type { JSONObject, RealtimeToolDefinition } from '@memberjunction/ai';
|
|
23
|
+
import { type ClientToolMetadata, type RealtimeChannelCandidate, type RealtimeChannelDescriptor, type RealtimeChannelDisplayPolicy, type RealtimeChannelRegistryState, type RealtimeChannelScopeResult, type ResolvedRealtimeChannel } from '@memberjunction/ai-core-plus';
|
|
24
|
+
import type { BaseRealtimeChannelClient } from '../channels/base-realtime-channel-client.js';
|
|
25
|
+
/**
|
|
26
|
+
* A channel the HOST brings to a session — the way a page or app adds a channel that has no
|
|
27
|
+
* `MJ: AI Agent Channels` row, which is the ONLY way a connect-only (anonymous embed) session
|
|
28
|
+
* gets channels, because that kind of session has no entity metadata to read the registry from.
|
|
29
|
+
*
|
|
30
|
+
* Supply either {@link ClientPluginClass} (a ClassFactory key, exactly like a registry row's
|
|
31
|
+
* `ClientPluginClass`) or {@link Create} (a factory — for a channel the host constructs itself, e.g.
|
|
32
|
+
* with injected collaborators). If both are given, {@link Create} wins.
|
|
33
|
+
*
|
|
34
|
+
* A host *adds* channels and supplies *defaults*; it cannot lift an agent or app `exclude`, and its
|
|
35
|
+
* `Config` / `DisplayPolicy` are overridden by the agent/app layers. An inactive registry row for the
|
|
36
|
+
* same channel still switches it off.
|
|
37
|
+
*/
|
|
38
|
+
export interface RealtimeHostChannelDeclaration {
|
|
39
|
+
/** ClassFactory key of the channel plugin (`@RegisterClass(BaseRealtimeChannelClient, '<key>')`). */
|
|
40
|
+
ClientPluginClass?: string;
|
|
41
|
+
/** Factory that builds the plugin; use when the host constructs it with its own collaborators. */
|
|
42
|
+
Create?: () => BaseRealtimeChannelClient;
|
|
43
|
+
/** Default per-channel configuration; agent/app `channels.config` overrides it. */
|
|
44
|
+
Config?: JSONObject;
|
|
45
|
+
/** Default display for this host; agent/app `channels.displayPolicy` overrides it. */
|
|
46
|
+
DisplayPolicy?: RealtimeChannelDisplayPolicy;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Per-start options of {@link RealtimeSessionRuntime.StartRealtimeSession} that are not part of the
|
|
50
|
+
* mint contract. Every field is optional; omit the whole object for the behavior hosts always had.
|
|
51
|
+
*/
|
|
52
|
+
export interface RealtimeSessionStartOptions {
|
|
53
|
+
/** Channels the host brings to this session (see {@link RealtimeHostChannelDeclaration}). */
|
|
54
|
+
HostChannels?: RealtimeHostChannelDeclaration[];
|
|
55
|
+
/** The fork (`MJ: Conversation Branches.ID`) the session starts on; omitted or null is Main. */
|
|
56
|
+
ConversationBranchID?: string | null;
|
|
57
|
+
/**
|
|
58
|
+
* Have the user check the camera before the agent sees it. The call's first camera start opens the camera for the
|
|
59
|
+
* user only: the camera's state is `starting` with `Checking` set and the stream to preview, and nothing reaches the
|
|
60
|
+
* agent until the host calls `ConfirmCamera`. Later starts in the same call skip the check. Set it only when the host
|
|
61
|
+
* shows the check; otherwise the camera waits for a confirmation that never comes.
|
|
62
|
+
*/
|
|
63
|
+
CameraCheck?: boolean;
|
|
64
|
+
}
|
|
65
|
+
/** A resolved-but-not-yet-initialized channel plugin, with what the scope decision needs to know about it. */
|
|
66
|
+
export interface PreparedChannel {
|
|
67
|
+
/** The plugin instance (constructed, NOT initialized). */
|
|
68
|
+
Plugin: BaseRealtimeChannelClient;
|
|
69
|
+
/** Its key (the plugin's `ChannelName`). */
|
|
70
|
+
Key: string;
|
|
71
|
+
/** Registry state: `'active'`, `'inactive'` (the kill switch), or `'none'` (host-declared only). */
|
|
72
|
+
Registry: RealtimeChannelRegistryState;
|
|
73
|
+
/** The host declaration that brought it, when one did. */
|
|
74
|
+
HostDeclaration?: RealtimeHostChannelDeclaration;
|
|
75
|
+
}
|
|
76
|
+
/** Looks a prepared channel up by key, case-insensitively. */
|
|
77
|
+
export declare function FindPreparedChannel(prepared: ReadonlyArray<PreparedChannel>, key: string): PreparedChannel | undefined;
|
|
78
|
+
/**
|
|
79
|
+
* Whether a session with these prepared channels could show the agent's video: one of them shows it (it sinks outbound
|
|
80
|
+
* video, as the Avatar channel does) and is not switched off in the registry. A policy can only select among the
|
|
81
|
+
* prepared plugins, so with none the session never asks for the agent's video at connect, whatever the server scopes:
|
|
82
|
+
* the mint can then ask the model for no avatar (`showsAgentVideo: false`).
|
|
83
|
+
*
|
|
84
|
+
* @param prepared The channels prepared for the session.
|
|
85
|
+
*/
|
|
86
|
+
export declare function PreparedChannelsShowAgentVideo(prepared: ReadonlyArray<PreparedChannel>): boolean;
|
|
87
|
+
/**
|
|
88
|
+
* The facts the browser reports about one channel at mint (also the input to the local scope
|
|
89
|
+
* decision). Reads the plugin's descriptor and tools; never initializes it.
|
|
90
|
+
*
|
|
91
|
+
* @param prepared The prepared channel.
|
|
92
|
+
* @param descriptor The plugin's descriptor (passed in so callers read it once).
|
|
93
|
+
*/
|
|
94
|
+
export declare function BuildChannelCandidate(prepared: PreparedChannel, descriptor: RealtimeChannelDescriptor): RealtimeChannelCandidate & {
|
|
95
|
+
Registry: RealtimeChannelRegistryState;
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* Resolves the scope from code defaults and host declarations alone — what the browser decides when
|
|
99
|
+
* no server policy arrives. Identical to the server's decision in the absence of an agent/app layer.
|
|
100
|
+
*
|
|
101
|
+
* @param candidates The reported candidates (with registry state).
|
|
102
|
+
*/
|
|
103
|
+
export declare function ResolveLocalChannelScope(candidates: ReadonlyArray<RealtimeChannelCandidate & {
|
|
104
|
+
Registry: RealtimeChannelRegistryState;
|
|
105
|
+
}>): RealtimeChannelScopeResult;
|
|
106
|
+
/** The tools of each candidate, keyed by channel key — the input `SelectNativeChannelTools` wants. */
|
|
107
|
+
export declare function ToolsByChannelKey(candidates: ReadonlyArray<RealtimeChannelCandidate>): Map<string, ReadonlyArray<RealtimeToolDefinition>>;
|
|
108
|
+
/** A policy channel paired with the prepared plugin it names. */
|
|
109
|
+
export interface ReconciledChannel {
|
|
110
|
+
/** The prepared plugin. */
|
|
111
|
+
Prepared: PreparedChannel;
|
|
112
|
+
/** What the policy resolved for it. */
|
|
113
|
+
Resolved: ResolvedRealtimeChannel;
|
|
114
|
+
}
|
|
115
|
+
/** The outcome of {@link ReconcileChannelsWithPolicy}. */
|
|
116
|
+
export interface ChannelReconciliation {
|
|
117
|
+
/** Channels the policy puts in the session, in policy order. */
|
|
118
|
+
InSession: ReconciledChannel[];
|
|
119
|
+
/** Prepared plugins the policy left out — never initialized; the runtime just drops them. */
|
|
120
|
+
Dropped: PreparedChannel[];
|
|
121
|
+
/** Policy channels the browser has no plugin for (a stale or foreign policy); logged by the caller. */
|
|
122
|
+
Unknown: string[];
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Maps a resolved policy back onto the prepared plugins. A policy can only select among plugins the
|
|
126
|
+
* browser actually has — it can never conjure one — so a key with no plugin is reported, not honored.
|
|
127
|
+
*
|
|
128
|
+
* @param prepared Every prepared plugin.
|
|
129
|
+
* @param channels The policy's in-session channels.
|
|
130
|
+
*/
|
|
131
|
+
export declare function ReconcileChannelsWithPolicy(prepared: ReadonlyArray<PreparedChannel>, channels: ReadonlyArray<ResolvedRealtimeChannel>): ChannelReconciliation;
|
|
132
|
+
/**
|
|
133
|
+
* Overlays the metadata of tools a host registered handlers for onto the manifest it streamed, by
|
|
134
|
+
* name (case-insensitive). A registered tool's own description/schema wins when it supplied one; a
|
|
135
|
+
* bare `{ Name, Handler }` registration (what most hosts do) inherits the manifest's description and
|
|
136
|
+
* schema instead of showing up with none.
|
|
137
|
+
*
|
|
138
|
+
* @param registered The registry's tools as metadata.
|
|
139
|
+
* @param manifest The tools the host's app-context snapshot advertises (may be empty).
|
|
140
|
+
*/
|
|
141
|
+
export declare function MergeToolMetadata(registered: ReadonlyArray<ClientToolMetadata>, manifest: ReadonlyArray<ClientToolMetadata>): ClientToolMetadata[];
|
|
142
|
+
//# sourceMappingURL=channel-session-scope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channel-session-scope.d.ts","sourceRoot":"","sources":["../../src/session/channel-session-scope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC7E,OAAO,EAGH,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,EAC7B,KAAK,yBAAyB,EAC9B,KAAK,4BAA4B,EACjC,KAAK,4BAA4B,EACjC,KAAK,0BAA0B,EAC/B,KAAK,uBAAuB,EAC/B,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,0CAA0C,CAAC;AAE1F;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,8BAA8B;IAC3C,qGAAqG;IACrG,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,kGAAkG;IAClG,MAAM,CAAC,EAAE,MAAM,yBAAyB,CAAC;IACzC,mFAAmF;IACnF,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,sFAAsF;IACtF,aAAa,CAAC,EAAE,4BAA4B,CAAC;CAChD;AAED;;;GAGG;AACH,MAAM,WAAW,2BAA2B;IACxC,6FAA6F;IAC7F,YAAY,CAAC,EAAE,8BAA8B,EAAE,CAAC;IAChD,gGAAgG;IAChG,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC;;;;;OAKG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,8GAA8G;AAC9G,MAAM,WAAW,eAAe;IAC5B,0DAA0D;IAC1D,MAAM,EAAE,yBAAyB,CAAC;IAClC,4CAA4C;IAC5C,GAAG,EAAE,MAAM,CAAC;IACZ,oGAAoG;IACpG,QAAQ,EAAE,4BAA4B,CAAC;IACvC,0DAA0D;IAC1D,eAAe,CAAC,EAAE,8BAA8B,CAAC;CACpD;AAED,8DAA8D;AAC9D,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,aAAa,CAAC,eAAe,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAGtH;AAED;;;;;;;GAOG;AACH,wBAAgB,8BAA8B,CAAC,QAAQ,EAAE,aAAa,CAAC,eAAe,CAAC,GAAG,OAAO,CAEhG;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,eAAe,EAAE,UAAU,EAAE,yBAAyB,GAAG,wBAAwB,GAAG;IAAE,QAAQ,EAAE,4BAA4B,CAAA;CAAE,CAqB7K;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACpC,UAAU,EAAE,aAAa,CAAC,wBAAwB,GAAG;IAAE,QAAQ,EAAE,4BAA4B,CAAA;CAAE,CAAC,GACjG,0BAA0B,CAE5B;AAED,sGAAsG;AACtG,wBAAgB,iBAAiB,CAC7B,UAAU,EAAE,aAAa,CAAC,wBAAwB,CAAC,GACpD,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,sBAAsB,CAAC,CAAC,CAEpD;AAED,iEAAiE;AACjE,MAAM,WAAW,iBAAiB;IAC9B,2BAA2B;IAC3B,QAAQ,EAAE,eAAe,CAAC;IAC1B,uCAAuC;IACvC,QAAQ,EAAE,uBAAuB,CAAC;CACrC;AAED,0DAA0D;AAC1D,MAAM,WAAW,qBAAqB;IAClC,gEAAgE;IAChE,SAAS,EAAE,iBAAiB,EAAE,CAAC;IAC/B,6FAA6F;IAC7F,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,uGAAuG;IACvG,OAAO,EAAE,MAAM,EAAE,CAAC;CACrB;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CACvC,QAAQ,EAAE,aAAa,CAAC,eAAe,CAAC,EACxC,QAAQ,EAAE,aAAa,CAAC,uBAAuB,CAAC,GACjD,qBAAqB,CAcvB;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC7B,UAAU,EAAE,aAAa,CAAC,kBAAkB,CAAC,EAC7C,QAAQ,EAAE,aAAa,CAAC,kBAAkB,CAAC,GAC5C,kBAAkB,EAAE,CActB"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview The **session-scoping helpers** of the realtime runtime — turning the channel plugins
|
|
3
|
+
* a session *could* have into the channels it *does* have.
|
|
4
|
+
*
|
|
5
|
+
* The decision itself (`ResolveRealtimeChannelScope`) is pure and lives in `@memberjunction/ai-core-plus`
|
|
6
|
+
* so the server and the browser make it identically. What lives here is the browser-side plumbing around it:
|
|
7
|
+
*
|
|
8
|
+
* - {@link PreparedChannel} — a plugin that has been *resolved* (from the registry or declared by the
|
|
9
|
+
* host) but not yet *initialized*. Preparing is side-effect free, which is what lets the runtime
|
|
10
|
+
* report candidates to the server at mint without having started anything the server may then veto.
|
|
11
|
+
* - {@link BuildChannelCandidate} / {@link ResolveLocalChannelScope} — the facts the browser reports,
|
|
12
|
+
* and the scope it resolves on its own when no server policy comes back (a legacy server, or a host
|
|
13
|
+
* that mints through its own proxy).
|
|
14
|
+
* - {@link ReconcileChannelsWithPolicy} — maps a resolved policy back onto the prepared plugins.
|
|
15
|
+
* - {@link MergeToolMetadata} — layers a host's registered tool handlers over the manifest the host
|
|
16
|
+
* streamed, so "available tools" messages can describe them.
|
|
17
|
+
*
|
|
18
|
+
* Framework-free and DOM-free: importable in plain Node tests.
|
|
19
|
+
*
|
|
20
|
+
* @module @memberjunction/realtime-runtime
|
|
21
|
+
*/
|
|
22
|
+
import { NormalizeChannelKey, ResolveRealtimeChannelScope, } from '@memberjunction/ai-core-plus';
|
|
23
|
+
/** Looks a prepared channel up by key, case-insensitively. */
|
|
24
|
+
export function FindPreparedChannel(prepared, key) {
|
|
25
|
+
const id = NormalizeChannelKey(key);
|
|
26
|
+
return prepared.find((p) => NormalizeChannelKey(p.Key) === id);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Whether a session with these prepared channels could show the agent's video: one of them shows it (it sinks outbound
|
|
30
|
+
* video, as the Avatar channel does) and is not switched off in the registry. A policy can only select among the
|
|
31
|
+
* prepared plugins, so with none the session never asks for the agent's video at connect, whatever the server scopes:
|
|
32
|
+
* the mint can then ask the model for no avatar (`showsAgentVideo: false`).
|
|
33
|
+
*
|
|
34
|
+
* @param prepared The channels prepared for the session.
|
|
35
|
+
*/
|
|
36
|
+
export function PreparedChannelsShowAgentVideo(prepared) {
|
|
37
|
+
return prepared.some((p) => p.Registry !== 'inactive' && p.Plugin.ShowsAgentVideo);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* The facts the browser reports about one channel at mint (also the input to the local scope
|
|
41
|
+
* decision). Reads the plugin's descriptor and tools; never initializes it.
|
|
42
|
+
*
|
|
43
|
+
* @param prepared The prepared channel.
|
|
44
|
+
* @param descriptor The plugin's descriptor (passed in so callers read it once).
|
|
45
|
+
*/
|
|
46
|
+
export function BuildChannelCandidate(prepared, descriptor) {
|
|
47
|
+
const candidate = {
|
|
48
|
+
Key: prepared.Key,
|
|
49
|
+
DefaultAvailability: descriptor.DefaultAvailability,
|
|
50
|
+
DisplayPolicy: descriptor.DisplayPolicy,
|
|
51
|
+
MaxExposure: descriptor.MaxExposure,
|
|
52
|
+
ToolNamePrefix: prepared.Plugin.ToolNamePrefix,
|
|
53
|
+
Tools: prepared.Plugin.GetToolDefinitions(),
|
|
54
|
+
Registry: prepared.Registry,
|
|
55
|
+
};
|
|
56
|
+
const declaration = prepared.HostDeclaration;
|
|
57
|
+
if (declaration) {
|
|
58
|
+
candidate.HostDeclared = true;
|
|
59
|
+
if (declaration.Config) {
|
|
60
|
+
candidate.HostConfig = declaration.Config;
|
|
61
|
+
}
|
|
62
|
+
if (declaration.DisplayPolicy) {
|
|
63
|
+
candidate.HostDisplayPolicy = declaration.DisplayPolicy;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return candidate;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Resolves the scope from code defaults and host declarations alone — what the browser decides when
|
|
70
|
+
* no server policy arrives. Identical to the server's decision in the absence of an agent/app layer.
|
|
71
|
+
*
|
|
72
|
+
* @param candidates The reported candidates (with registry state).
|
|
73
|
+
*/
|
|
74
|
+
export function ResolveLocalChannelScope(candidates) {
|
|
75
|
+
return ResolveRealtimeChannelScope({ Candidates: candidates.map((c) => ({ ...c })) });
|
|
76
|
+
}
|
|
77
|
+
/** The tools of each candidate, keyed by channel key — the input `SelectNativeChannelTools` wants. */
|
|
78
|
+
export function ToolsByChannelKey(candidates) {
|
|
79
|
+
return new Map(candidates.map((c) => [c.Key, c.Tools]));
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Maps a resolved policy back onto the prepared plugins. A policy can only select among plugins the
|
|
83
|
+
* browser actually has — it can never conjure one — so a key with no plugin is reported, not honored.
|
|
84
|
+
*
|
|
85
|
+
* @param prepared Every prepared plugin.
|
|
86
|
+
* @param channels The policy's in-session channels.
|
|
87
|
+
*/
|
|
88
|
+
export function ReconcileChannelsWithPolicy(prepared, channels) {
|
|
89
|
+
const inSession = [];
|
|
90
|
+
const unknown = [];
|
|
91
|
+
const used = new Set();
|
|
92
|
+
for (const resolved of channels) {
|
|
93
|
+
const match = FindPreparedChannel(prepared, resolved.Key);
|
|
94
|
+
if (match && !used.has(match)) {
|
|
95
|
+
used.add(match);
|
|
96
|
+
inSession.push({ Prepared: match, Resolved: resolved });
|
|
97
|
+
}
|
|
98
|
+
else if (!match) {
|
|
99
|
+
unknown.push(resolved.Key);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return { InSession: inSession, Dropped: prepared.filter((p) => !used.has(p)), Unknown: unknown };
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Overlays the metadata of tools a host registered handlers for onto the manifest it streamed, by
|
|
106
|
+
* name (case-insensitive). A registered tool's own description/schema wins when it supplied one; a
|
|
107
|
+
* bare `{ Name, Handler }` registration (what most hosts do) inherits the manifest's description and
|
|
108
|
+
* schema instead of showing up with none.
|
|
109
|
+
*
|
|
110
|
+
* @param registered The registry's tools as metadata.
|
|
111
|
+
* @param manifest The tools the host's app-context snapshot advertises (may be empty).
|
|
112
|
+
*/
|
|
113
|
+
export function MergeToolMetadata(registered, manifest) {
|
|
114
|
+
const fromManifest = new Map(manifest.map((t) => [t.Name.trim().toLowerCase(), t]));
|
|
115
|
+
return registered.map((tool) => {
|
|
116
|
+
const advertised = fromManifest.get(tool.Name.trim().toLowerCase());
|
|
117
|
+
if (!advertised) {
|
|
118
|
+
return tool;
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
...advertised,
|
|
122
|
+
...tool,
|
|
123
|
+
Description: tool.Description || advertised.Description,
|
|
124
|
+
InputSchema: Object.keys(tool.InputSchema ?? {}).length > 0 ? tool.InputSchema : advertised.InputSchema,
|
|
125
|
+
};
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=channel-session-scope.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channel-session-scope.js","sourceRoot":"","sources":["../../src/session/channel-session-scope.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Observable } from 'rxjs';
|
|
2
|
+
/**
|
|
3
|
+
* The client's view of when its session must end — the CLIENT half of a limit the server enforces
|
|
4
|
+
* authoritatively (the janitor closes a session past its stored deadline whatever a client does).
|
|
5
|
+
*
|
|
6
|
+
* The client keeps a copy so it can end the call gracefully before the server does, and show a
|
|
7
|
+
* countdown. It follows one rule: **the server's word moves the deadline only later** when it arrives
|
|
8
|
+
* as an extension (identity verification relaxes a session's limits) — a stale or hostile value can
|
|
9
|
+
* therefore never cut a session short here, and nothing a client does with this class extends the
|
|
10
|
+
* server's deadline.
|
|
11
|
+
*/
|
|
12
|
+
export declare class ClientSessionDeadline {
|
|
13
|
+
private readonly subject;
|
|
14
|
+
/** Emits the current deadline (or `null` when none is known), then every change. */
|
|
15
|
+
readonly Deadline$: Observable<Date | null>;
|
|
16
|
+
/** The current deadline, or `null` when none is known. */
|
|
17
|
+
get Value(): Date | null;
|
|
18
|
+
/** Sets the baseline deadline outright (a host that knows the session's cap at start). `null` clears it. */
|
|
19
|
+
Set(deadline: Date | null): void;
|
|
20
|
+
/**
|
|
21
|
+
* Applies a server-announced deadline: adopted when none is known or when it is LATER than the one
|
|
22
|
+
* held; ignored when earlier, equal or unparseable. Returns whether the deadline changed.
|
|
23
|
+
*/
|
|
24
|
+
Extend(deadlineIso: string | undefined): boolean;
|
|
25
|
+
/** Forgets the deadline (session ended). */
|
|
26
|
+
Clear(): void;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=client-session-deadline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-session-deadline.d.ts","sourceRoot":"","sources":["../../src/session/client-session-deadline.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,UAAU,EAAE,MAAM,MAAM,CAAC;AAEnD;;;;;;;;;GASG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0C;IAElE,oFAAoF;IACpF,SAAgB,SAAS,EAAE,UAAU,CAAC,IAAI,GAAG,IAAI,CAAC,CAA+B;IAEjF,0DAA0D;IAC1D,IAAW,KAAK,IAAI,IAAI,GAAG,IAAI,CAE9B;IAED,4GAA4G;IACrG,GAAG,CAAC,QAAQ,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI;IAIvC;;;OAGG;IACI,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO;IAgBvD,4CAA4C;IACrC,KAAK,IAAI,IAAI;CAGrB"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { BehaviorSubject } from 'rxjs';
|
|
2
|
+
/**
|
|
3
|
+
* The client's view of when its session must end — the CLIENT half of a limit the server enforces
|
|
4
|
+
* authoritatively (the janitor closes a session past its stored deadline whatever a client does).
|
|
5
|
+
*
|
|
6
|
+
* The client keeps a copy so it can end the call gracefully before the server does, and show a
|
|
7
|
+
* countdown. It follows one rule: **the server's word moves the deadline only later** when it arrives
|
|
8
|
+
* as an extension (identity verification relaxes a session's limits) — a stale or hostile value can
|
|
9
|
+
* therefore never cut a session short here, and nothing a client does with this class extends the
|
|
10
|
+
* server's deadline.
|
|
11
|
+
*/
|
|
12
|
+
export class ClientSessionDeadline {
|
|
13
|
+
constructor() {
|
|
14
|
+
this.subject = new BehaviorSubject(null);
|
|
15
|
+
/** Emits the current deadline (or `null` when none is known), then every change. */
|
|
16
|
+
this.Deadline$ = this.subject.asObservable();
|
|
17
|
+
}
|
|
18
|
+
/** The current deadline, or `null` when none is known. */
|
|
19
|
+
get Value() {
|
|
20
|
+
return this.subject.value;
|
|
21
|
+
}
|
|
22
|
+
/** Sets the baseline deadline outright (a host that knows the session's cap at start). `null` clears it. */
|
|
23
|
+
Set(deadline) {
|
|
24
|
+
this.subject.next(deadline && Number.isFinite(deadline.getTime()) ? deadline : null);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Applies a server-announced deadline: adopted when none is known or when it is LATER than the one
|
|
28
|
+
* held; ignored when earlier, equal or unparseable. Returns whether the deadline changed.
|
|
29
|
+
*/
|
|
30
|
+
Extend(deadlineIso) {
|
|
31
|
+
if (!deadlineIso) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
const parsed = new Date(deadlineIso);
|
|
35
|
+
if (!Number.isFinite(parsed.getTime())) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
const current = this.subject.value;
|
|
39
|
+
if (current !== null && parsed.getTime() <= current.getTime()) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
this.subject.next(parsed);
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
/** Forgets the deadline (session ended). */
|
|
46
|
+
Clear() {
|
|
47
|
+
this.subject.next(null);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=client-session-deadline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-session-deadline.js","sourceRoot":"","sources":["../../src/session/client-session-deadline.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAc,MAAM,MAAM,CAAC;AAEnD;;;;;;;;;GASG;AACH,MAAM,OAAO,qBAAqB;IAAlC;QACmB,YAAO,GAAG,IAAI,eAAe,CAAc,IAAI,CAAC,CAAC;QAElE,oFAAoF;QACpE,cAAS,GAA4B,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC;IAoCnF,CAAC;IAlCC,0DAA0D;IAC1D,IAAW,KAAK;QACd,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;IAC5B,CAAC;IAED,4GAA4G;IACrG,GAAG,CAAC,QAAqB;QAC9B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACvF,CAAC;IAED;;;OAGG;IACI,MAAM,CAAC,WAA+B;QAC3C,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,WAAW,CAAC,CAAC;QACrC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;YACvC,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;QACnC,IAAI,OAAO,KAAK,IAAI,IAAI,MAAM,CAAC,OAAO,EAAE,IAAI,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;YAC9D,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,4CAA4C;IACrC,KAAK;QACV,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;CACF"}
|