@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.
- 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 +61 -4
- 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 +21 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -1
- package/dist/session/RealtimeSessionRuntime.d.ts +730 -70
- package/dist/session/RealtimeSessionRuntime.d.ts.map +1 -1
- package/dist/session/RealtimeSessionRuntime.js +1761 -241
- package/dist/session/RealtimeSessionRuntime.js.map +1 -1
- package/dist/session/RecordingShardQueue.d.ts +77 -0
- package/dist/session/RecordingShardQueue.d.ts.map +1 -0
- package/dist/session/RecordingShardQueue.js +172 -0
- package/dist/session/RecordingShardQueue.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 +9 -9
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
const DEFAULTS = {
|
|
2
|
+
MaxReconnectAttempts: 6,
|
|
3
|
+
BaseBackoffMs: 1000,
|
|
4
|
+
MaxBackoffMs: 15_000,
|
|
5
|
+
StableAfterMs: 30_000
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Keeps one session's event stream open for the session's life and delivers every event to a sink.
|
|
9
|
+
*
|
|
10
|
+
* The stream is a long-lived subscription that ends when the transport recycles its connection (token
|
|
11
|
+
* refresh, network blip) — and delivery has no replay, so an event published during the gap is gone.
|
|
12
|
+
* The hub therefore, on every re-subscribe: opens the new subscription FIRST (so nothing published
|
|
13
|
+
* from now on is missed), THEN reads the verification status once, and if the person verified while the
|
|
14
|
+
* hub was away, delivers the `identity.verified` event it missed (marked `Recovered`).
|
|
15
|
+
*
|
|
16
|
+
* Reconnects are capped: a stream that keeps failing is given up on (once, loudly) rather than retried
|
|
17
|
+
* forever; a stream that stayed up long enough counts as healthy and resets the cap.
|
|
18
|
+
*
|
|
19
|
+
* Framework-agnostic and clock-driven by `setTimeout`, so tests drive it with fake timers.
|
|
20
|
+
*/
|
|
21
|
+
export class RealtimeSessionEventHub {
|
|
22
|
+
constructor(source, deliver, options = {}) {
|
|
23
|
+
this.source = source;
|
|
24
|
+
this.deliver = deliver;
|
|
25
|
+
this.sessionId = null;
|
|
26
|
+
this.subscription = null;
|
|
27
|
+
this.reconnectTimer = null;
|
|
28
|
+
this.attempts = 0;
|
|
29
|
+
this.verifiedDelivered = false;
|
|
30
|
+
/** Bumped by every Start/Stop so a late callback from a previous run can tell it is stale. */
|
|
31
|
+
this.generation = 0;
|
|
32
|
+
this.options = { ...DEFAULTS, ...options };
|
|
33
|
+
}
|
|
34
|
+
/** Whether the hub currently has (or is about to re-open) a subscription. */
|
|
35
|
+
get IsRunning() {
|
|
36
|
+
return this.sessionId !== null;
|
|
37
|
+
}
|
|
38
|
+
/** Opens the stream for `agentSessionId`. Replaces any run in progress. */
|
|
39
|
+
Start(agentSessionId) {
|
|
40
|
+
this.Stop();
|
|
41
|
+
this.sessionId = agentSessionId;
|
|
42
|
+
this.attempts = 0;
|
|
43
|
+
this.verifiedDelivered = false;
|
|
44
|
+
this.connect(false);
|
|
45
|
+
}
|
|
46
|
+
/** Closes the stream and cancels any pending reconnect. Safe to call when not running. */
|
|
47
|
+
Stop() {
|
|
48
|
+
this.generation++;
|
|
49
|
+
this.sessionId = null;
|
|
50
|
+
if (this.reconnectTimer !== null) {
|
|
51
|
+
clearTimeout(this.reconnectTimer);
|
|
52
|
+
this.reconnectTimer = null;
|
|
53
|
+
}
|
|
54
|
+
this.subscription?.unsubscribe();
|
|
55
|
+
this.subscription = null;
|
|
56
|
+
}
|
|
57
|
+
connect(isReconnect) {
|
|
58
|
+
const sessionId = this.sessionId;
|
|
59
|
+
if (sessionId === null) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const generation = this.generation;
|
|
63
|
+
const openedAt = Date.now();
|
|
64
|
+
this.subscription?.unsubscribe();
|
|
65
|
+
try {
|
|
66
|
+
this.subscription = this.source.SubscribeToSessionEvents(sessionId).subscribe({
|
|
67
|
+
next: (event) => this.onEvent(generation, event),
|
|
68
|
+
error: (error) => {
|
|
69
|
+
console.warn('[RealtimeSession] The session event stream failed:', error);
|
|
70
|
+
this.onStreamEnded(generation, openedAt);
|
|
71
|
+
},
|
|
72
|
+
complete: () => this.onStreamEnded(generation, openedAt)
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
console.warn('[RealtimeSession] Could not open the session event stream:', error);
|
|
77
|
+
this.onStreamEnded(generation, openedAt);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (isReconnect) {
|
|
81
|
+
void this.recoverMissedVerification(generation, sessionId);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
onEvent(generation, event) {
|
|
85
|
+
if (generation !== this.generation) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
if (event.Type === 'identity.verified') {
|
|
89
|
+
this.verifiedDelivered = true;
|
|
90
|
+
}
|
|
91
|
+
this.deliver(event);
|
|
92
|
+
}
|
|
93
|
+
onStreamEnded(generation, openedAt) {
|
|
94
|
+
if (generation !== this.generation || this.sessionId === null) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (Date.now() - openedAt >= this.options.StableAfterMs) {
|
|
98
|
+
this.attempts = 0;
|
|
99
|
+
}
|
|
100
|
+
this.attempts++;
|
|
101
|
+
if (this.attempts > this.options.MaxReconnectAttempts) {
|
|
102
|
+
console.error(`[RealtimeSession] The session event stream for ${this.sessionId} kept ending; giving up after ${this.options.MaxReconnectAttempts} attempts. ` +
|
|
103
|
+
'Session events (such as identity verification) will not arrive until the next session.');
|
|
104
|
+
this.sessionId = null;
|
|
105
|
+
this.subscription = null;
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const delay = Math.min(this.options.BaseBackoffMs * 2 ** (this.attempts - 1), this.options.MaxBackoffMs);
|
|
109
|
+
this.reconnectTimer = setTimeout(() => {
|
|
110
|
+
this.reconnectTimer = null;
|
|
111
|
+
if (generation === this.generation) {
|
|
112
|
+
this.connect(true);
|
|
113
|
+
}
|
|
114
|
+
}, delay);
|
|
115
|
+
}
|
|
116
|
+
/** Reads the verification status once and delivers the `identity.verified` event the hub missed, if any. */
|
|
117
|
+
async recoverMissedVerification(generation, sessionId) {
|
|
118
|
+
if (this.verifiedDelivered) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
let status;
|
|
122
|
+
try {
|
|
123
|
+
status = await this.source.GetVerificationStatus(sessionId);
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
console.warn('[RealtimeSession] Could not read the verification status after reconnecting:', error);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
if (generation !== this.generation || this.verifiedDelivered) {
|
|
130
|
+
return; // stopped, restarted, or the live event arrived while the status was in flight
|
|
131
|
+
}
|
|
132
|
+
if (status.VerificationState !== 'verified' || !status.VerifiedEmail || !status.VerifiedAt) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
this.verifiedDelivered = true;
|
|
136
|
+
this.deliver({
|
|
137
|
+
Type: 'identity.verified',
|
|
138
|
+
AgentSessionID: sessionId,
|
|
139
|
+
OccurredAt: status.VerifiedAt,
|
|
140
|
+
Payload: {
|
|
141
|
+
VerifiedEmail: status.VerifiedEmail,
|
|
142
|
+
VerifiedName: '',
|
|
143
|
+
VerifiedAt: status.VerifiedAt,
|
|
144
|
+
Method: 'link',
|
|
145
|
+
...(status.MaxSessionDeadlineIso ? { MaxSessionDeadlineIso: status.MaxSessionDeadlineIso } : {}),
|
|
146
|
+
Recovered: true
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=session-event-hub.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-event-hub.js","sourceRoot":"","sources":["../../src/session/session-event-hub.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import type { IMetadataProvider } from '@memberjunction/core';
|
|
2
|
+
import { type RealtimeToolDefinition } from '@memberjunction/ai';
|
|
3
|
+
import type { AppContextSnapshot } from '@memberjunction/ai-core-plus';
|
|
4
|
+
import type { StartRealtimeClientSessionResult } from './RealtimeSessionRuntime.js';
|
|
5
|
+
/**
|
|
6
|
+
* Everything the runtime knows when it needs a session minted — the inputs of the stock
|
|
7
|
+
* `StartRealtimeClientSession` mutation, as typed values rather than a GraphQL variable bag.
|
|
8
|
+
*
|
|
9
|
+
* A launcher may use all, some or none of it: the default sends it to the stock mutation; a
|
|
10
|
+
* host-specific launcher can map it onto its own mint (a deployment-specific mutation, a REST
|
|
11
|
+
* endpoint, a guest-session exchange) so long as it returns a {@link StartRealtimeClientSessionResult}.
|
|
12
|
+
*/
|
|
13
|
+
export interface RealtimeSessionLaunchRequest {
|
|
14
|
+
/** The agent the session fronts. */
|
|
15
|
+
TargetAgentId: string;
|
|
16
|
+
/** The conversation the session belongs to, when it continues one. */
|
|
17
|
+
ConversationId: string | null;
|
|
18
|
+
/** A prior session whose saved channel state this one resumes. */
|
|
19
|
+
LastSessionId: string | null;
|
|
20
|
+
/** A realtime model the user picked, when the host exposes a model picker. */
|
|
21
|
+
PreferredModelId: string | null;
|
|
22
|
+
/**
|
|
23
|
+
* Client-executed tools to declare to the model at mint: the host's own plus the native tools of the
|
|
24
|
+
* channels mounted with the session. A launcher that mints through its own endpoint must pass them on,
|
|
25
|
+
* or the model never learns it can call them.
|
|
26
|
+
*/
|
|
27
|
+
ClientTools: readonly RealtimeToolDefinition[];
|
|
28
|
+
/** The co-agent override, or `null` to let server metadata choose. */
|
|
29
|
+
CoAgentId: string | null;
|
|
30
|
+
/** Session-config overrides (authorization-gated server side), as JSON. */
|
|
31
|
+
ConfigOverridesJson: string | null;
|
|
32
|
+
/** Whether the user consented to recording this session. */
|
|
33
|
+
RecordingConsent: boolean;
|
|
34
|
+
/** When the recording started (ISO), or `null` when the session is not being recorded. */
|
|
35
|
+
RecordingStartedAt: string | null;
|
|
36
|
+
/** A per-session media-kit collection override. */
|
|
37
|
+
MediaCollectionId: string | null;
|
|
38
|
+
/** The application the session runs in. */
|
|
39
|
+
ApplicationId: string | null;
|
|
40
|
+
/** The live app-context snapshot to inject into the companion prompt. */
|
|
41
|
+
AppContext: AppContextSnapshot | null;
|
|
42
|
+
/**
|
|
43
|
+
* The channels this host can mount (JSON), which the server scopes against the agent's and the app's
|
|
44
|
+
* configuration and answers with the resolved policy. `null` when the host brings none.
|
|
45
|
+
*/
|
|
46
|
+
ChannelCandidatesJson: string | null;
|
|
47
|
+
/** The fork (`MJ: Conversation Branches.ID`) the session starts on; `null` is Main. */
|
|
48
|
+
ConversationBranchId: string | null;
|
|
49
|
+
/**
|
|
50
|
+
* Whether this host can show the agent's video: one of its channels shows it (the Avatar channel). `false` for a host
|
|
51
|
+
* with none (the embeddable widget, the mobile app): the server then asks the model for no avatar, so a video model is
|
|
52
|
+
* not chosen for a face nobody would see, and says why (`host`). A launcher that mints through its own endpoint should
|
|
53
|
+
* pass a `false` on. Absent: not stated, and the server assumes the host may show it.
|
|
54
|
+
*/
|
|
55
|
+
ShowsAgentVideo?: boolean;
|
|
56
|
+
}
|
|
57
|
+
/** What the runtime hands a launcher besides the request: the provider the session runs on. */
|
|
58
|
+
export interface RealtimeSessionLaunchContext {
|
|
59
|
+
/**
|
|
60
|
+
* The MJ provider this session is authenticated on. The default launcher mints through it; a custom
|
|
61
|
+
* launcher that talks to MJ should do the same so the call rides the session's credential.
|
|
62
|
+
*/
|
|
63
|
+
Provider: IMetadataProvider;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* How a realtime session gets MINTED — the seam between "a host wants a session" and "the server has
|
|
67
|
+
* created one and handed back a token".
|
|
68
|
+
*
|
|
69
|
+
* The runtime owns everything either side of it (channel scoping, driver resolution, connecting,
|
|
70
|
+
* transcripts, teardown). A launcher owns only the exchange. That is what lets an app change how a
|
|
71
|
+
* session is minted — a guest-session exchange, a deployment-specific mutation that carries server-side
|
|
72
|
+
* context the stock one cannot — without proxying the runtime's provider or re-implementing the run
|
|
73
|
+
* half. Install one with {@link RealtimeSessionRuntime.Launcher}.
|
|
74
|
+
*
|
|
75
|
+
* A launcher must either resolve a usable result (one carrying an ephemeral token, or a relay session's relay URL) or
|
|
76
|
+
* throw; the runtime turns a throw into a failed start with the error on `LastStartError`.
|
|
77
|
+
*/
|
|
78
|
+
export interface IRealtimeSessionLauncher {
|
|
79
|
+
/**
|
|
80
|
+
* Mints one session.
|
|
81
|
+
*
|
|
82
|
+
* @param request The inputs the runtime resolved for this start.
|
|
83
|
+
* @param context The provider the session runs on.
|
|
84
|
+
* @returns The minted session, including `ClientPolicyJson` when the launcher's mint scoped channels,
|
|
85
|
+
* `AvatarStatusJson` when the server reports the session's avatar status, and `Transport` and `RelayUrl` for a
|
|
86
|
+
* session that runs through MJAPI's realtime relay.
|
|
87
|
+
*/
|
|
88
|
+
Launch(request: RealtimeSessionLaunchRequest, context: RealtimeSessionLaunchContext): Promise<StartRealtimeClientSessionResult>;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Whether a minted session carries what its client driver connects with: an ephemeral token, or, for a relay session
|
|
92
|
+
* (`Transport` `'relay'`), its relay URL.
|
|
93
|
+
*
|
|
94
|
+
* @param result The minted session, or nothing.
|
|
95
|
+
*/
|
|
96
|
+
export declare function HasClientCredential(result: Pick<StartRealtimeClientSessionResult, 'EphemeralToken' | 'Transport' | 'RelayUrl'> | null | undefined): boolean;
|
|
97
|
+
/**
|
|
98
|
+
* The stock launcher: mints through the `StartRealtimeClientSession` GraphQL mutation on the session's
|
|
99
|
+
* provider. This is what every host gets unless it installs another.
|
|
100
|
+
*
|
|
101
|
+
* When the session has channel candidates it asks the server to scope them (`channelCandidatesJson`)
|
|
102
|
+
* and to return the resolved policy (`ClientPolicyJson`). It also asks for the session's live-avatar status
|
|
103
|
+
* (`AvatarStatusJson`), which the call reads to say why it shows no avatar, and for how the browser reaches the
|
|
104
|
+
* provider (`Transport` and `RelayUrl`), which a relay session's client driver connects with. A host that shows no agent
|
|
105
|
+
* video ({@link RealtimeSessionLaunchRequest.ShowsAgentVideo} `false`) says so (`showsAgentVideo: false`), so the
|
|
106
|
+
* server asks the model for no avatar. A server that predates an extension rejects it at validation, in which case the
|
|
107
|
+
* launcher mints without that extension alone (the runtime then resolves the channel scope locally, shows no avatar
|
|
108
|
+
* notice, treats every session as direct, or leaves the avatar to the browser's audio-only fallback at connect) — a new
|
|
109
|
+
* client must keep working against an older server, and a failed mint over an optional extension would be the worst way
|
|
110
|
+
* to find out they differ. Each fallback is remembered per launcher instance so a long-lived runtime asks once.
|
|
111
|
+
*/
|
|
112
|
+
export declare class DefaultRealtimeSessionLauncher implements IRealtimeSessionLauncher {
|
|
113
|
+
/** The extensions of the mint the server rejected; each is added once and kept. */
|
|
114
|
+
private readonly serverLacks;
|
|
115
|
+
Launch(request: RealtimeSessionLaunchRequest, context: RealtimeSessionLaunchContext): Promise<StartRealtimeClientSessionResult>;
|
|
116
|
+
/** The mutation's variables for one request. */
|
|
117
|
+
private buildVariables;
|
|
118
|
+
/**
|
|
119
|
+
* Runs the mint with every extension this server has not rejected, dropping one at a time when the server rejects it
|
|
120
|
+
* at validation. Each retry asks for one extension fewer, so the loop ends.
|
|
121
|
+
*/
|
|
122
|
+
private executeMintMutation;
|
|
123
|
+
/** Remembers that the server lacks an extension of the mint, and says so once. */
|
|
124
|
+
private rememberUnsupported;
|
|
125
|
+
/** The `StartRealtimeClientSession` document, with the extensions asked for. */
|
|
126
|
+
private buildMintMutation;
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=session-launcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-launcher.d.ts","sourceRoot":"","sources":["../../src/session/session-launcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,OAAO,EAAgD,KAAK,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC/G,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,KAAK,EAAE,gCAAgC,EAAE,MAAM,0BAA0B,CAAC;AAEjF;;;;;;;GAOG;AACH,MAAM,WAAW,4BAA4B;IAC3C,oCAAoC;IACpC,aAAa,EAAE,MAAM,CAAC;IACtB,sEAAsE;IACtE,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,kEAAkE;IAClE,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,8EAA8E;IAC9E,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC;;;;OAIG;IACH,WAAW,EAAE,SAAS,sBAAsB,EAAE,CAAC;IAC/C,sEAAsE;IACtE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,2EAA2E;IAC3E,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,4DAA4D;IAC5D,gBAAgB,EAAE,OAAO,CAAC;IAC1B,0FAA0F;IAC1F,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,mDAAmD;IACnD,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,2CAA2C;IAC3C,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,yEAAyE;IACzE,UAAU,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACtC;;;OAGG;IACH,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,uFAAuF;IACvF,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC;;;;;OAKG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,+FAA+F;AAC/F,MAAM,WAAW,4BAA4B;IAC3C;;;OAGG;IACH,QAAQ,EAAE,iBAAiB,CAAC;CAC7B;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,wBAAwB;IACvC;;;;;;;;OAQG;IACH,MAAM,CAAC,OAAO,EAAE,4BAA4B,EAAE,OAAO,EAAE,4BAA4B,GAAG,OAAO,CAAC,gCAAgC,CAAC,CAAC;CACjI;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,IAAI,CAAC,gCAAgC,EAAE,gBAAgB,GAAG,WAAW,GAAG,UAAU,CAAC,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAK3J;AAoDD;;;;;;;;;;;;;;GAcG;AACH,qBAAa,8BAA+B,YAAW,wBAAwB;IAC7E,mFAAmF;IACnF,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAmC;IAElD,MAAM,CAAC,OAAO,EAAE,4BAA4B,EAAE,OAAO,EAAE,4BAA4B,GAAG,OAAO,CAAC,gCAAgC,CAAC;IAW5I,gDAAgD;IAChD,OAAO,CAAC,cAAc;IAkBtB;;;OAGG;YACW,mBAAmB;IA+BjC,kFAAkF;IAClF,OAAO,CAAC,mBAAmB;IAK3B,gFAAgF;IAChF,OAAO,CAAC,iBAAiB;CA8B1B"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { ParseRealtimeClientTransport } from '@memberjunction/ai';
|
|
2
|
+
/**
|
|
3
|
+
* Whether a minted session carries what its client driver connects with: an ephemeral token, or, for a relay session
|
|
4
|
+
* (`Transport` `'relay'`), its relay URL.
|
|
5
|
+
*
|
|
6
|
+
* @param result The minted session, or nothing.
|
|
7
|
+
*/
|
|
8
|
+
export function HasClientCredential(result) {
|
|
9
|
+
if (!result) {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
return !!result.EphemeralToken || (ParseRealtimeClientTransport(result.Transport) === 'relay' && !!result.RelayUrl);
|
|
13
|
+
}
|
|
14
|
+
/** What the launcher says, once, when the server rejects an extension of the mint. */
|
|
15
|
+
const UNSUPPORTED_EXTENSION_WARNINGS = {
|
|
16
|
+
ChannelScoping: '[RealtimeSession] The server does not support channel scoping — minting without it and resolving channels locally.',
|
|
17
|
+
AvatarStatus: '[RealtimeSession] The server does not report the avatar status — minting without it; the call shows no avatar notice.',
|
|
18
|
+
RelayTransport: '[RealtimeSession] The server does not report the session transport — minting without it; every session connects directly.',
|
|
19
|
+
NoAgentVideo: "[RealtimeSession] The server does not take showsAgentVideo — minting without it; it may ask for an avatar this app can't show (the call stays audio only).",
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* The extension a mint failure rejects, when the failure is a GraphQL validation rejection of one the mint asked for —
|
|
23
|
+
* the signature of a server that predates it ("Unknown argument "channelCandidatesJson"…", "Cannot query field
|
|
24
|
+
* "ClientPolicyJson"…", "Cannot query field "AvatarStatusJson"…", "Cannot query field "Transport"…", "Unknown argument
|
|
25
|
+
* "showsAgentVideo"…"). Only that case is recoverable; any other failure is a real mint failure and must surface. A
|
|
26
|
+
* rejection names one field at a time, so a server that predates several extensions is found out one step at a time.
|
|
27
|
+
*/
|
|
28
|
+
function unsupportedExtension(error, asked) {
|
|
29
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
30
|
+
if (asked.NoAgentVideo && message.includes('showsAgentVideo')) {
|
|
31
|
+
return 'NoAgentVideo';
|
|
32
|
+
}
|
|
33
|
+
if (asked.AvatarStatus && message.includes('AvatarStatusJson')) {
|
|
34
|
+
return 'AvatarStatus';
|
|
35
|
+
}
|
|
36
|
+
// The quoted field names, not the bare words: "Transport" alone could be any transport error, and "RelayUrl"
|
|
37
|
+
// any message that names the field.
|
|
38
|
+
if (asked.RelayTransport && (message.includes('field "Transport"') || message.includes('field "RelayUrl"'))) {
|
|
39
|
+
return 'RelayTransport';
|
|
40
|
+
}
|
|
41
|
+
if (asked.ChannelScoping && (message.includes('channelCandidatesJson') || message.includes('ClientPolicyJson'))) {
|
|
42
|
+
return 'ChannelScoping';
|
|
43
|
+
}
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The stock launcher: mints through the `StartRealtimeClientSession` GraphQL mutation on the session's
|
|
48
|
+
* provider. This is what every host gets unless it installs another.
|
|
49
|
+
*
|
|
50
|
+
* When the session has channel candidates it asks the server to scope them (`channelCandidatesJson`)
|
|
51
|
+
* and to return the resolved policy (`ClientPolicyJson`). It also asks for the session's live-avatar status
|
|
52
|
+
* (`AvatarStatusJson`), which the call reads to say why it shows no avatar, and for how the browser reaches the
|
|
53
|
+
* provider (`Transport` and `RelayUrl`), which a relay session's client driver connects with. A host that shows no agent
|
|
54
|
+
* video ({@link RealtimeSessionLaunchRequest.ShowsAgentVideo} `false`) says so (`showsAgentVideo: false`), so the
|
|
55
|
+
* server asks the model for no avatar. A server that predates an extension rejects it at validation, in which case the
|
|
56
|
+
* launcher mints without that extension alone (the runtime then resolves the channel scope locally, shows no avatar
|
|
57
|
+
* notice, treats every session as direct, or leaves the avatar to the browser's audio-only fallback at connect) — a new
|
|
58
|
+
* client must keep working against an older server, and a failed mint over an optional extension would be the worst way
|
|
59
|
+
* to find out they differ. Each fallback is remembered per launcher instance so a long-lived runtime asks once.
|
|
60
|
+
*/
|
|
61
|
+
export class DefaultRealtimeSessionLauncher {
|
|
62
|
+
constructor() {
|
|
63
|
+
/** The extensions of the mint the server rejected; each is added once and kept. */
|
|
64
|
+
this.serverLacks = new Set();
|
|
65
|
+
}
|
|
66
|
+
async Launch(request, context) {
|
|
67
|
+
// The session's provider is the GraphQL one in every shipped host; this is the same narrowing the runtime applies for its relay mutations.
|
|
68
|
+
const transport = context.Provider;
|
|
69
|
+
const result = await this.executeMintMutation(transport, this.buildVariables(request), request.ChannelCandidatesJson, request.ShowsAgentVideo === false);
|
|
70
|
+
const payload = result?.StartRealtimeClientSession;
|
|
71
|
+
if (!payload || !HasClientCredential(payload)) {
|
|
72
|
+
throw new Error('StartRealtimeClientSession returned no ephemeral token (or, for a relay session, no relay URL)');
|
|
73
|
+
}
|
|
74
|
+
return payload;
|
|
75
|
+
}
|
|
76
|
+
/** The mutation's variables for one request. */
|
|
77
|
+
buildVariables(request) {
|
|
78
|
+
return {
|
|
79
|
+
targetAgentId: request.TargetAgentId,
|
|
80
|
+
conversationId: request.ConversationId,
|
|
81
|
+
lastSessionId: request.LastSessionId,
|
|
82
|
+
preferredModelId: request.PreferredModelId,
|
|
83
|
+
clientToolsJson: request.ClientTools.length > 0 ? JSON.stringify(request.ClientTools) : null,
|
|
84
|
+
coAgentId: request.CoAgentId,
|
|
85
|
+
configOverridesJson: request.ConfigOverridesJson,
|
|
86
|
+
recordingConsent: request.RecordingConsent,
|
|
87
|
+
recordingStartedAt: request.RecordingStartedAt,
|
|
88
|
+
mediaCollectionId: request.MediaCollectionId,
|
|
89
|
+
applicationId: request.ApplicationId,
|
|
90
|
+
appContextJson: request.AppContext ? JSON.stringify(request.AppContext) : null,
|
|
91
|
+
conversationBranchId: request.ConversationBranchId
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Runs the mint with every extension this server has not rejected, dropping one at a time when the server rejects it
|
|
96
|
+
* at validation. Each retry asks for one extension fewer, so the loop ends.
|
|
97
|
+
*/
|
|
98
|
+
async executeMintMutation(transport, variables, channelCandidatesJson, noAgentVideo) {
|
|
99
|
+
let asked = {
|
|
100
|
+
ChannelScoping: channelCandidatesJson !== null && !this.serverLacks.has('ChannelScoping'),
|
|
101
|
+
AvatarStatus: !this.serverLacks.has('AvatarStatus'),
|
|
102
|
+
RelayTransport: !this.serverLacks.has('RelayTransport'),
|
|
103
|
+
NoAgentVideo: noAgentVideo && !this.serverLacks.has('NoAgentVideo'),
|
|
104
|
+
};
|
|
105
|
+
for (;;) {
|
|
106
|
+
try {
|
|
107
|
+
const mintVariables = {
|
|
108
|
+
...variables,
|
|
109
|
+
...(asked.ChannelScoping ? { channelCandidatesJson } : {}),
|
|
110
|
+
...(asked.NoAgentVideo ? { showsAgentVideo: false } : {}),
|
|
111
|
+
};
|
|
112
|
+
return await transport.ExecuteGQL(this.buildMintMutation(asked), mintVariables);
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
const unsupported = unsupportedExtension(error, asked);
|
|
116
|
+
if (!unsupported) {
|
|
117
|
+
throw error;
|
|
118
|
+
}
|
|
119
|
+
this.rememberUnsupported(unsupported);
|
|
120
|
+
asked = { ...asked, [unsupported]: false };
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/** Remembers that the server lacks an extension of the mint, and says so once. */
|
|
125
|
+
rememberUnsupported(extension) {
|
|
126
|
+
console.warn(UNSUPPORTED_EXTENSION_WARNINGS[extension]);
|
|
127
|
+
this.serverLacks.add(extension);
|
|
128
|
+
}
|
|
129
|
+
/** The `StartRealtimeClientSession` document, with the extensions asked for. */
|
|
130
|
+
buildMintMutation(asked) {
|
|
131
|
+
const extraVariable = (asked.ChannelScoping ? ', $channelCandidatesJson: String' : '') + (asked.NoAgentVideo ? ', $showsAgentVideo: Boolean' : '');
|
|
132
|
+
const extraArgument = (asked.ChannelScoping ? ', channelCandidatesJson: $channelCandidatesJson' : '') + (asked.NoAgentVideo ? ', showsAgentVideo: $showsAgentVideo' : '');
|
|
133
|
+
const extraField = [
|
|
134
|
+
asked.ChannelScoping ? 'ClientPolicyJson' : '',
|
|
135
|
+
asked.AvatarStatus ? 'AvatarStatusJson' : '',
|
|
136
|
+
asked.RelayTransport ? 'Transport' : '',
|
|
137
|
+
asked.RelayTransport ? 'RelayUrl' : '',
|
|
138
|
+
]
|
|
139
|
+
.filter((field) => field.length > 0)
|
|
140
|
+
.map((field) => `\n ${field}`)
|
|
141
|
+
.join('');
|
|
142
|
+
return `
|
|
143
|
+
mutation StartRealtimeClientSession($targetAgentId: String!, $conversationId: String, $lastSessionId: String, $preferredModelId: String, $clientToolsJson: String, $coAgentId: String, $configOverridesJson: String, $recordingConsent: Boolean, $recordingStartedAt: String, $mediaCollectionId: String, $applicationId: String, $appContextJson: String, $conversationBranchId: String${extraVariable}) {
|
|
144
|
+
StartRealtimeClientSession(targetAgentId: $targetAgentId, conversationId: $conversationId, lastSessionId: $lastSessionId, preferredModelId: $preferredModelId, clientToolsJson: $clientToolsJson, coAgentId: $coAgentId, configOverridesJson: $configOverridesJson, recordingConsent: $recordingConsent, recordingStartedAt: $recordingStartedAt, mediaCollectionId: $mediaCollectionId, applicationId: $applicationId, appContextJson: $appContextJson, conversationBranchId: $conversationBranchId${extraArgument}) {
|
|
145
|
+
AgentSessionId
|
|
146
|
+
ConversationId
|
|
147
|
+
Provider
|
|
148
|
+
Model
|
|
149
|
+
EphemeralToken
|
|
150
|
+
ExpiresAt
|
|
151
|
+
SessionConfigJson
|
|
152
|
+
ModelName
|
|
153
|
+
NarrationInstructionsTemplate
|
|
154
|
+
PriorChannelStatesJson${extraField}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
`;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=session-launcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-launcher.js","sourceRoot":"","sources":["../../src/session/session-launcher.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/realtime-runtime",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "6.2.0-edge.
|
|
4
|
+
"version": "6.2.0-edge.4",
|
|
5
5
|
"description": "MemberJunction: Framework-agnostic Realtime Session Runtime — client-direct realtime co-agent session orchestration (mint, driver resolution, transcripts, tool relay, delegation narration, channel lifecycle, usage relay). Pure TypeScript, zero UX dependencies. Consumable from browser (Angular/React/Vue), React Native, or Node test harnesses.",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -11,14 +11,14 @@
|
|
|
11
11
|
"author": "MemberJunction.com",
|
|
12
12
|
"license": "BUSL-1.1",
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@memberjunction/ai": "6.2.0-edge.
|
|
15
|
-
"@memberjunction/ai-core-plus": "6.2.0-edge.
|
|
16
|
-
"@memberjunction/ai-engine-base": "6.2.0-edge.
|
|
17
|
-
"@memberjunction/ai-realtime-client": "6.2.0-edge.
|
|
18
|
-
"@memberjunction/core": "6.2.0-edge.
|
|
19
|
-
"@memberjunction/core-entities": "6.2.0-edge.
|
|
20
|
-
"@memberjunction/global": "6.2.0-edge.
|
|
21
|
-
"@memberjunction/graphql-dataprovider": "6.2.0-edge.
|
|
14
|
+
"@memberjunction/ai": "6.2.0-edge.4",
|
|
15
|
+
"@memberjunction/ai-core-plus": "6.2.0-edge.4",
|
|
16
|
+
"@memberjunction/ai-engine-base": "6.2.0-edge.4",
|
|
17
|
+
"@memberjunction/ai-realtime-client": "6.2.0-edge.4",
|
|
18
|
+
"@memberjunction/core": "6.2.0-edge.4",
|
|
19
|
+
"@memberjunction/core-entities": "6.2.0-edge.4",
|
|
20
|
+
"@memberjunction/global": "6.2.0-edge.4",
|
|
21
|
+
"@memberjunction/graphql-dataprovider": "6.2.0-edge.4",
|
|
22
22
|
"rxjs": "^7.8.2"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|