@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
|
@@ -1,8 +1,15 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Observable } from 'rxjs';
|
|
2
2
|
import { IMetadataProvider } from '@memberjunction/core';
|
|
3
|
-
import { JSONValue, RealtimeToolDefinition, RealtimeTrackDescriptor, RealtimeTrackDirection } from '@memberjunction/ai';
|
|
4
|
-
import type
|
|
5
|
-
import type
|
|
3
|
+
import { JSONObject, JSONValue, RealtimeToolDefinition, RealtimeTrackDescriptor, RealtimeTrackDirection } from '@memberjunction/ai';
|
|
4
|
+
import { ChannelInboundVideoBridge, type BaseRealtimeClient, type IChannelFrameProvider, type MediaPlacement, type MediaVideoSource, type VideoSourceState } from '@memberjunction/ai-realtime-client';
|
|
5
|
+
import { type AppContextSnapshot, type RealtimeChannelActor, type RealtimeChannelDescriptor, type RealtimeChannelExposure, type RealtimeChannelVerb } from '@memberjunction/ai-core-plus';
|
|
6
|
+
import type { RealtimeChannelEvent, RealtimeChannelOutput, RealtimeChannelVerbResult, RealtimeContextActionRequest, RealtimeContextActionResult } from './channel-contract-types.js';
|
|
7
|
+
import type { RealtimeSessionStreamEvent } from '../session/session-event-hub.js';
|
|
8
|
+
import { type ChannelPerceptionOptions } from './channel-perception.js';
|
|
9
|
+
import { type ChannelSurfacePlacement } from './channel-surface-placement.js';
|
|
10
|
+
import type { RealtimeCaptureKind, RealtimeCaptureState, RealtimeCaptureStates } from '../session/realtime-captures.js';
|
|
11
|
+
import type { RealtimeConnectionState } from '../session/RealtimeSessionRuntime.js';
|
|
12
|
+
import type { ParsedDelegationArtifact } from '../session/delegation-result-parser.js';
|
|
6
13
|
/**
|
|
7
14
|
* A UI framework's component-class reference, as far as this runtime is concerned.
|
|
8
15
|
*
|
|
@@ -63,7 +70,7 @@ export interface RealtimeChannelContext {
|
|
|
63
70
|
RequestSave(stateJson: string): void;
|
|
64
71
|
/**
|
|
65
72
|
* Requests (or releases) the FOCUS layout for this channel's surface: the overlay
|
|
66
|
-
* collapses the main call column
|
|
73
|
+
* collapses the main call column and fills its stage with the surface, with a compact floating
|
|
67
74
|
* call pill keeping mute / thread / end reachable. Any channel may request it; the host
|
|
68
75
|
* tracks which channel holds focus and routes the pill's "exit" back to it via
|
|
69
76
|
* {@link BaseRealtimeChannelClient.RequestFocusExit}.
|
|
@@ -140,10 +147,47 @@ export interface RealtimeChannelContext {
|
|
|
140
147
|
ErrorMessage?: string;
|
|
141
148
|
}>;
|
|
142
149
|
/**
|
|
143
|
-
* OPTIONAL —
|
|
144
|
-
*
|
|
145
|
-
*
|
|
150
|
+
* OPTIONAL — runs a CHANNEL-ADDRESSED `ContextTool` call: `{ action, params, target: { channel, instance? } }`.
|
|
151
|
+
* The headless `ClientContextChannel`'s proxy routes a call here when the model named a target; the
|
|
152
|
+
* host runtime resolves the channel, validates `params` against the verb's declared schema (a failure
|
|
153
|
+
* comes back as a structured, model-recoverable error — never a half-applied mutation), enforces
|
|
154
|
+
* `InvokableBy`, and opens an `on-demand` channel when the action is `'open'`. Never throws.
|
|
146
155
|
*
|
|
156
|
+
* Absent on hosts that do not scope channels; the proxy then reports that channel addressing is
|
|
157
|
+
* unavailable instead of guessing.
|
|
158
|
+
*
|
|
159
|
+
* @param request The addressed call.
|
|
160
|
+
* @returns A structured outcome the proxy serializes back to the model.
|
|
161
|
+
*/
|
|
162
|
+
DispatchContextAction?(request: RealtimeContextActionRequest): Promise<RealtimeContextActionResult>;
|
|
163
|
+
/**
|
|
164
|
+
* The resolved per-channel configuration for THIS channel: the host's defaults beneath the agent's
|
|
165
|
+
* and the app's `channels.config[<key>]` (see `ResolveRealtimeChannelScope`). Empty (`{}`) when none
|
|
166
|
+
* was configured. A channel reads its policy knobs from here (e.g. an identity channel's allowed
|
|
167
|
+
* email domains); it never reads the cascade itself.
|
|
168
|
+
*
|
|
169
|
+
* Treat it as untrusted, validated input: it is JSON authored by an operator, not typed code.
|
|
170
|
+
*/
|
|
171
|
+
ChannelConfig?: Readonly<JSONObject>;
|
|
172
|
+
/**
|
|
173
|
+
* OPTIONAL — the events the SERVER publishes to this session (identity verification today; app-defined
|
|
174
|
+
* types too), hot with no replay. A channel that reacts to them (an identity channel learning that the
|
|
175
|
+
* user verified) subscribes in {@link BaseRealtimeChannelClient.OnInitialize} and unsubscribes at
|
|
176
|
+
* {@link BaseRealtimeChannelClient.Dispose}. Absent on hosts whose session has no event transport.
|
|
177
|
+
*/
|
|
178
|
+
SessionEvents$?: Observable<RealtimeSessionStreamEvent>;
|
|
179
|
+
/**
|
|
180
|
+
* OPTIONAL — sends a visual frame into the live session's inbound video track, as this channel's source at the
|
|
181
|
+
* session's `VideoSourceArbiter` (the id its own frame bridge uses, {@link ChannelVideoSourceID}). The frame reaches
|
|
182
|
+
* the model only while the arbiter picks this channel, and the model is told when that changes; nothing is sent while
|
|
183
|
+
* the channel's exposure is below `pixels`. No-op when the session has not established an inbound video track or is
|
|
184
|
+
* not live.
|
|
185
|
+
*
|
|
186
|
+
* @deprecated Use a `ChannelInboundVideoBridge` (`@memberjunction/ai-realtime-client`), or
|
|
187
|
+
* {@link BaseRealtimeChannelClient.EnableVisualPerception}, which runs one for the channel: the bridge lists the
|
|
188
|
+
* source before its first frame, removes it when stopped, and says whether each frame was sent. The context's
|
|
189
|
+
* {@link Client} still bypasses the arbiter: a frame sent with its own `SendVideoFrame` overrides the source the
|
|
190
|
+
* arbiter picked, and the model is not told.
|
|
147
191
|
* @param base64Image The image data (base64-encoded JPEG/PNG).
|
|
148
192
|
* @param mimeType The image MIME type (defaults to 'image/jpeg').
|
|
149
193
|
*/
|
|
@@ -153,9 +197,48 @@ export interface RealtimeChannelContext {
|
|
|
153
197
|
*/
|
|
154
198
|
IsTrackEstablished?(modality: string, direction: RealtimeTrackDirection): boolean;
|
|
155
199
|
/**
|
|
156
|
-
* OPTIONAL — the underlying {@link BaseRealtimeClient} driving the media and transport planes.
|
|
200
|
+
* OPTIONAL — the underlying {@link BaseRealtimeClient} driving the media and transport planes. Send video through a
|
|
201
|
+
* `ChannelInboundVideoBridge` over it, not through its own `SendVideoFrame`, which bypasses the session's
|
|
202
|
+
* `VideoSourceArbiter`.
|
|
157
203
|
*/
|
|
158
204
|
Client?: BaseRealtimeClient | null;
|
|
205
|
+
/**
|
|
206
|
+
* OPTIONAL — the session's camera and screen share, now and on every change (the runtime's `Captures$`). A channel that
|
|
207
|
+
* fronts a capture ({@link BaseRealtimeChannelClient.CaptureKind}) follows it here.
|
|
208
|
+
*/
|
|
209
|
+
Captures$?: Observable<RealtimeCaptureStates>;
|
|
210
|
+
/**
|
|
211
|
+
* OPTIONAL — starts the camera or a screen share for the user's click on the channel's surface: the runtime's
|
|
212
|
+
* `StartCamera` or `StartScreenShare`, under the same policy. Resolves with the capture's state; a failure is a state,
|
|
213
|
+
* never a throw.
|
|
214
|
+
*/
|
|
215
|
+
StartCapture?(kind: RealtimeCaptureKind): Promise<RealtimeCaptureState>;
|
|
216
|
+
/** OPTIONAL — stops the camera or the screen share (the runtime's `StopCamera` / `StopScreenShare`). */
|
|
217
|
+
StopCapture?(kind: RealtimeCaptureKind): void;
|
|
218
|
+
/**
|
|
219
|
+
* OPTIONAL — the session's video sources, now and on every change (the runtime's `VideoSources$`): each source the
|
|
220
|
+
* video source arbiter knows, whether it is on (`Enabled`) and whether the model is being sent its frames (`Active`).
|
|
221
|
+
* On a model that takes one video stream, a capture that is on can still be one the model is not sent. A channel that
|
|
222
|
+
* fronts a capture finds its source by `REALTIME_CAPTURE_SOURCE_IDS`, and says the agent sees the capture only while
|
|
223
|
+
* that source is both.
|
|
224
|
+
*/
|
|
225
|
+
VideoSources$?: Observable<readonly VideoSourceState[]>;
|
|
226
|
+
/**
|
|
227
|
+
* OPTIONAL — the agent's video while the model sends it, `null` otherwise (the runtime's `AgentVideo$`). A channel that
|
|
228
|
+
* shows the agent, one that sinks outbound video ({@link BaseRealtimeChannelClient.GetSunkTracks}), follows it here.
|
|
229
|
+
*/
|
|
230
|
+
AgentVideo$?: Observable<MediaVideoSource | null>;
|
|
231
|
+
/**
|
|
232
|
+
* OPTIONAL — the call's state, now and on every change (the runtime's `ConnectionState$`): connecting, listening,
|
|
233
|
+
* speaking, thinking, an error, or closed. A channel that shows the agent follows the agent's turn here.
|
|
234
|
+
*/
|
|
235
|
+
ConnectionState$?: Observable<RealtimeConnectionState>;
|
|
236
|
+
/**
|
|
237
|
+
* OPTIONAL — whether the call is resuming on a new provider connection mid-call, now and on every change (the runtime's
|
|
238
|
+
* `Resuming$`). The agent's video can stop for a few seconds while it does, so a channel that shows the agent holds the
|
|
239
|
+
* last frame through the gap rather than showing that the video has stalled.
|
|
240
|
+
*/
|
|
241
|
+
Resuming$?: Observable<boolean>;
|
|
159
242
|
}
|
|
160
243
|
/**
|
|
161
244
|
* The first-run INTRO content for an interactive channel — the concise "what is this surface
|
|
@@ -210,10 +293,13 @@ export interface ChannelOnboardingDetails {
|
|
|
210
293
|
*
|
|
211
294
|
* ### Lifecycle — ONE INSTANCE PER SESSION (not a singleton)
|
|
212
295
|
* `ClassFactory.CreateInstance` → {@link Initialize}(ctx) → zero or more
|
|
213
|
-
* {@link BindSurface}/{@link UnbindSurface} cycles (the
|
|
214
|
-
*
|
|
296
|
+
* {@link BindSurface}/{@link UnbindSurface} cycles (the Angular overlay creates the surface the
|
|
297
|
+
* first time it is shown and keeps it until the channel leaves the session; another host may
|
|
298
|
+
* recreate it), each telling the plugin when its surface goes in and out of sight
|
|
299
|
+
* ({@link OnSurfaceVisibilityChange}) and where it is placed ({@link OnSurfacePlacementChange})
|
|
300
|
+
* → {@link Dispose} at teardown.
|
|
215
301
|
* {@link ApplyAgentTool} MUST work with NO surface bound (apply to the state engine
|
|
216
|
-
* directly; skip the UI garnish) — tool calls can arrive
|
|
302
|
+
* directly; skip the UI garnish) — tool calls can arrive before the surface is first shown.
|
|
217
303
|
*
|
|
218
304
|
* @typeParam TSurface The plugin's Angular surface component type. The host only ever
|
|
219
305
|
* sees the default (`object`) — the typed parameter exists so concrete plugins get a
|
|
@@ -235,12 +321,16 @@ export declare abstract class BaseRealtimeChannelClient<TSurface extends object
|
|
|
235
321
|
* The shared name prefix of every tool this channel exposes (e.g. `'Whiteboard_'`).
|
|
236
322
|
* The host registers ONE local-execution route per plugin: tool calls whose name starts
|
|
237
323
|
* with this prefix go to {@link ApplyAgentTool} instead of the server relay.
|
|
324
|
+
*
|
|
325
|
+
* Default `''` — a v2 channel with NO native tools (it is reached only through the `ContextTool`
|
|
326
|
+
* proxy). The host registers no route for an empty prefix: an empty prefix would match *every*
|
|
327
|
+
* tool name and hijack the server relay.
|
|
238
328
|
*/
|
|
239
|
-
|
|
240
|
-
/** Label for the channel's tab on the overlay's surface panel (e.g. `'Whiteboard'`). */
|
|
241
|
-
|
|
242
|
-
/** Font Awesome icon class for the channel's tab (e.g. `'fa-solid fa-chalkboard'`). */
|
|
243
|
-
|
|
329
|
+
get ToolNamePrefix(): string;
|
|
330
|
+
/** Label for the channel's tab on the overlay's surface panel (e.g. `'Whiteboard'`). Defaults to {@link ChannelName}. */
|
|
331
|
+
get TabTitle(): string;
|
|
332
|
+
/** Font Awesome icon class for the channel's tab (e.g. `'fa-solid fa-chalkboard'`). Defaults to a generic puzzle-piece. */
|
|
333
|
+
get TabIcon(): string;
|
|
244
334
|
/**
|
|
245
335
|
* OPTIONAL accent color for the channel's tab (a CSS color string, e.g. an `hsl()` /
|
|
246
336
|
* token). When a plugin supplies one, the overlay paints the tab's dot + active underline
|
|
@@ -253,18 +343,26 @@ export declare abstract class BaseRealtimeChannelClient<TSurface extends object
|
|
|
253
343
|
* The channel's CLIENT-EXECUTED tool declarations, aggregated by the session service
|
|
254
344
|
* into the `clientTools` set declared to the realtime model at session mint. The server
|
|
255
345
|
* only DECLARES these — execution stays in the browser via {@link ApplyAgentTool}.
|
|
346
|
+
*
|
|
347
|
+
* Default `[]` — a v2 channel whose verbs are reached through the proxy only.
|
|
256
348
|
*/
|
|
257
|
-
|
|
349
|
+
GetToolDefinitions(): RealtimeToolDefinition[];
|
|
258
350
|
/**
|
|
259
351
|
* Executes ONE agent tool call locally (the ACTION direction) and returns the result
|
|
260
352
|
* JSON string fed back to the model as the `tool_response`. Called for every tool whose
|
|
261
353
|
* name starts with {@link ToolNamePrefix}. Must work both WITH a bound surface (apply +
|
|
262
|
-
* UI garnish) and WITHOUT one (apply to the state engine directly — the
|
|
263
|
-
* exist, e.g.
|
|
354
|
+
* UI garnish) and WITHOUT one (apply to the state engine directly — the surface may not
|
|
355
|
+
* exist yet, e.g. it has not been shown). Should not throw: return a
|
|
264
356
|
* `{ success: false, error }` payload so the model can narrate the failure (the host
|
|
265
357
|
* additionally wraps anything thrown).
|
|
358
|
+
*
|
|
359
|
+
* **This is the LEGACY entry point.** Channels written against the v2 contract override
|
|
360
|
+
* {@link ApplyVerb} instead and inherit this method: the default maps the tool name back to its verb,
|
|
361
|
+
* calls {@link ApplyVerb} as the agent, and serializes the structured result. Channels written
|
|
362
|
+
* against v1 override THIS and inherit {@link ApplyVerb}, which adapts it. A channel must override
|
|
363
|
+
* at least one of the two — overriding neither is reported as a failure result, never a recursion.
|
|
266
364
|
*/
|
|
267
|
-
|
|
365
|
+
ApplyAgentTool(toolName: string, argsJson: string): string | Promise<string>;
|
|
268
366
|
/**
|
|
269
367
|
* The Angular component the overlay creates dynamically as this channel's tab pane, or `null`
|
|
270
368
|
* for a **server-only** channel that renders no MJ surface (its surface, if any, lives on the
|
|
@@ -305,16 +403,57 @@ export declare abstract class BaseRealtimeChannelClient<TSurface extends object
|
|
|
305
403
|
* The plugin — which knows its own component type — sets inputs (state engine, agent
|
|
306
404
|
* name, …) and subscribes outputs here, wiring perception/garnish flows back through
|
|
307
405
|
* {@link Context}. May be called again with a NEW instance after an
|
|
308
|
-
* {@link UnbindSurface} (the
|
|
406
|
+
* {@link UnbindSurface} (the host recreated the surface).
|
|
309
407
|
*/
|
|
310
|
-
|
|
408
|
+
BindSurface(_instance: TSurface): void;
|
|
311
409
|
/**
|
|
312
|
-
* Called by the host when the surface component is being destroyed (
|
|
313
|
-
*
|
|
410
|
+
* Called by the host when the surface component is being destroyed (the channel left
|
|
411
|
+
* the session / the overlay was torn down). Drop the instance reference and unsubscribe any
|
|
314
412
|
* output subscriptions — after this, {@link ApplyAgentTool} runs in its no-surface
|
|
315
413
|
* mode. Default: no-op.
|
|
316
414
|
*/
|
|
317
415
|
UnbindSurface(): void;
|
|
416
|
+
/**
|
|
417
|
+
* Called by the host when the bound surface comes into sight or goes out of it (the panel collapsed or hidden,
|
|
418
|
+
* another tab active, the call minimized). The surface stays bound and keeps its state; a channel can pause work
|
|
419
|
+
* nobody sees, such as a screenshot poll, and resume it when the surface is shown again. The host calls it right
|
|
420
|
+
* after {@link BindSurface} with the surface's current visibility, then on every change, and not after
|
|
421
|
+
* {@link UnbindSurface}. Default: no-op, so a surface keeps running out of sight.
|
|
422
|
+
*/
|
|
423
|
+
OnSurfaceVisibilityChange(_visible: boolean): void;
|
|
424
|
+
/**
|
|
425
|
+
* Called by the host when the bound surface moves: to the stage (it fills the call), to its tab, or out of sight
|
|
426
|
+
* because the user hid it. A channel can adapt its own chrome, such as a "Move to stage" button that has nothing to
|
|
427
|
+
* do once the surface is on the stage. Called right after {@link BindSurface} with the current placement, then on
|
|
428
|
+
* every move, and not after {@link UnbindSurface}. Default: no-op.
|
|
429
|
+
*/
|
|
430
|
+
OnSurfacePlacementChange(_placement: MediaPlacement): void;
|
|
431
|
+
private surfacePlacement;
|
|
432
|
+
/**
|
|
433
|
+
* Where this channel's surface shows when a call starts, and where the user may move it: from the channel's registry
|
|
434
|
+
* row (`UIConfig.Placement` and `UIConfig.AllowedPlacements`). A channel without a row, or whose row says nothing,
|
|
435
|
+
* starts on its tab and can go anywhere.
|
|
436
|
+
*/
|
|
437
|
+
get SurfacePlacement(): ChannelSurfacePlacement;
|
|
438
|
+
/**
|
|
439
|
+
* Sets {@link SurfacePlacement}. The runtime calls it with the registry row's placement when it builds the channel, before
|
|
440
|
+
* the channel mounts, as it applies exposure policy with {@link ApplyExposure}.
|
|
441
|
+
*/
|
|
442
|
+
ApplySurfacePlacement(placement: ChannelSurfacePlacement): void;
|
|
443
|
+
/**
|
|
444
|
+
* Whether the user may share this channel's surface on its own: a host that offers it lists the surface, named by
|
|
445
|
+
* {@link TabTitle} with {@link TabIcon}, under "This panel" in its Share menu while the surface is on screen, and the
|
|
446
|
+
* share then shows only that surface. Default `false`, so a channel opts in with this getter. A surface that shows the
|
|
447
|
+
* agent its own call (the camera, the screen share, the agent's video) never should.
|
|
448
|
+
*/
|
|
449
|
+
get SurfaceShareable(): boolean;
|
|
450
|
+
/**
|
|
451
|
+
* The runtime capture this channel fronts (`'camera'` or `'screen'`), or `null`. Such a channel is the capture's policy:
|
|
452
|
+
* the runtime starts the capture only while the channel is in the session and the session's policy lets the agent see
|
|
453
|
+
* pixels through it, and the user's "agent can see" choice for the channel decides whether the capture's frames reach
|
|
454
|
+
* the model. Default `null`.
|
|
455
|
+
*/
|
|
456
|
+
get CaptureKind(): RealtimeCaptureKind | null;
|
|
318
457
|
/**
|
|
319
458
|
* Binds the host context and invokes the {@link OnInitialize} hook. Called exactly once
|
|
320
459
|
* per session, right after ClassFactory instantiation and before any tool call or
|
|
@@ -329,11 +468,21 @@ export declare abstract class BaseRealtimeChannelClient<TSurface extends object
|
|
|
329
468
|
protected OnInitialize(): void;
|
|
330
469
|
/**
|
|
331
470
|
* Subclass hook invoked once the realtime session is connected and live (the client driver
|
|
332
|
-
* is created, connected, and media tracks negotiated)
|
|
333
|
-
* (e.g. video streaming) can start them here when
|
|
334
|
-
*
|
|
471
|
+
* is created, connected, and media tracks negotiated), or when the channel is opened in a live
|
|
472
|
+
* session. Channels that establish media bridges (e.g. video streaming) can start them here when
|
|
473
|
+
* `Context.Client` is available.
|
|
474
|
+
* Default: a channel with visual perception adds the inbound video track it sources when the call
|
|
475
|
+
* has none (it was opened mid-call) and brings its frame bridge up; any other channel does nothing.
|
|
476
|
+
* An override that keeps visual perception calls `super.OnSessionStarted()`.
|
|
335
477
|
*/
|
|
336
478
|
OnSessionStarted(): void;
|
|
479
|
+
/**
|
|
480
|
+
* Adds the inbound video track this channel sources ({@link GetSourcedTracks}) when the call is live without one. A
|
|
481
|
+
* channel open when the call connected had its track negotiated then, so this does nothing for it. A channel opened
|
|
482
|
+
* mid-call (`on-demand`) was not part of that negotiation: without its own track it could only send on a track a camera
|
|
483
|
+
* or screen share added, which goes when that capture stops. Only on a model that takes inbound video.
|
|
484
|
+
*/
|
|
485
|
+
private addVisualTrackMidCall;
|
|
337
486
|
/**
|
|
338
487
|
* Max time {@link ResolveAgentSessionId} waits for the session id to bind before giving up, and the
|
|
339
488
|
* poll interval it re-checks on. Protected so tests can shrink the wait; production keeps the
|
|
@@ -389,8 +538,326 @@ export declare abstract class BaseRealtimeChannelClient<TSurface extends object
|
|
|
389
538
|
/**
|
|
390
539
|
* Media tracks this client channel can SINK — samples flowing from the model OUT.
|
|
391
540
|
* Default `[]`.
|
|
541
|
+
*
|
|
542
|
+
* The session requests them when it connects, so the driver establishes the ones the model supports. A channel that
|
|
543
|
+
* sinks outbound video shows the agent's video: it follows {@link RealtimeChannelContext.AgentVideo$}, and counts as
|
|
544
|
+
* used once the video arrives, so the host shows its surface.
|
|
392
545
|
*/
|
|
393
546
|
GetSunkTracks(): readonly RealtimeTrackDescriptor[];
|
|
547
|
+
/**
|
|
548
|
+
* Whether this channel shows the agent's video: it sinks outbound video ({@link GetSunkTracks}). The runtime marks it
|
|
549
|
+
* as used when the video arrives, and a host presents its surface as the agent (the call overlay puts it in the agent's
|
|
550
|
+
* place in the call rather than in the focus layout).
|
|
551
|
+
*/
|
|
552
|
+
get ShowsAgentVideo(): boolean;
|
|
553
|
+
/**
|
|
554
|
+
* The channel's stable primary-instance id. A single-instance channel has exactly one; a
|
|
555
|
+
* {@link RealtimeChannelDescriptor.MultiInstance} channel owns further instance ids itself and
|
|
556
|
+
* routes by the `instanceId` argument of {@link ApplyVerb}. Appears in every structured note
|
|
557
|
+
* (`[channel:<Key>#<instance>] …`) and every {@link RealtimeChannelEvent}.
|
|
558
|
+
*/
|
|
559
|
+
get InstanceId(): string;
|
|
560
|
+
/**
|
|
561
|
+
* The channel's SELF-DESCRIPTION — what it is, what it holds, what it accepts, how it behaves in a
|
|
562
|
+
* session. This is the contract an agent reads to operate a channel it has never seen, and what the
|
|
563
|
+
* runtime reads to scope, advertise and validate. Pure data; called often, so keep it cheap.
|
|
564
|
+
*
|
|
565
|
+
* Default: a descriptor SYNTHESIZED from the v1 members (tools → verbs, intro → instructions),
|
|
566
|
+
* stamped with the legacy contract version — so a channel that implements nothing new is still
|
|
567
|
+
* describable and works exactly as before. A v2 channel overrides this with an authored descriptor.
|
|
568
|
+
* (Build verbs from {@link GetToolDefinitions} with `BuildToolBackedVerbs` when they are the
|
|
569
|
+
* native tools, so a subclass that adds a tool does not leave the descriptor lying.)
|
|
570
|
+
*/
|
|
571
|
+
GetDescriptor(): RealtimeChannelDescriptor;
|
|
572
|
+
/**
|
|
573
|
+
* A snapshot of the channel's things (the descriptor's nouns), keyed by noun name. Perception notes
|
|
574
|
+
* are computed as deltas between successive snapshots, so this must be a pure read.
|
|
575
|
+
*
|
|
576
|
+
* Default: the parsed {@link SerializeState} when that is a JSON object, else `{}` — which makes a
|
|
577
|
+
* v1 channel's state of record its (single, opaque) snapshot with no code change.
|
|
578
|
+
*/
|
|
579
|
+
GetState(): JSONObject;
|
|
580
|
+
/**
|
|
581
|
+
* Checks the current {@link GetState} snapshot against the descriptor's noun schemas and returns
|
|
582
|
+
* every violation (empty when valid). Useful in a channel's own tests; the runtime also runs it on
|
|
583
|
+
* every perception note when {@link StrictStateChecks} is on.
|
|
584
|
+
*/
|
|
585
|
+
ValidateState(): string[];
|
|
586
|
+
/**
|
|
587
|
+
* Whether state snapshots are validated against the descriptor's noun schemas as notes are built —
|
|
588
|
+
* a development aid that surfaces a channel whose state drifted from its own declaration. On by
|
|
589
|
+
* default only when a Node-style environment reports a non-production `NODE_ENV` (tests, tooling);
|
|
590
|
+
* a browser production build never pays for it. Hosts may set it explicitly.
|
|
591
|
+
*/
|
|
592
|
+
static StrictStateChecks: boolean;
|
|
593
|
+
/**
|
|
594
|
+
* Runs one verb of this channel — the contract-v2 entry point, reached through the `ContextTool`
|
|
595
|
+
* proxy (and, via {@link ApplyAgentTool}, by native tool calls).
|
|
596
|
+
*
|
|
597
|
+
* The runtime has ALREADY resolved the verb against the descriptor, enforced `InvokableBy`, and
|
|
598
|
+
* validated `args` against the verb's parameter schema before calling this, so an override can
|
|
599
|
+
* trust its inputs' shape. It must work with no surface bound, and should not throw — return a
|
|
600
|
+
* failure result so the model can recover.
|
|
601
|
+
*
|
|
602
|
+
* Default: adapts the legacy {@link ApplyAgentTool} (the verb's native tool name, args as JSON),
|
|
603
|
+
* so every v1 channel is reachable through the proxy with no change. A v2 channel overrides this.
|
|
604
|
+
*
|
|
605
|
+
* @param verb The verb name (as declared in the descriptor).
|
|
606
|
+
* @param args The validated parameters.
|
|
607
|
+
* @param actor Who is acting: the agent (a model call) or the user (their own interaction).
|
|
608
|
+
* @param instanceId Which instance of a multi-instance channel; `undefined` for the primary instance.
|
|
609
|
+
*/
|
|
610
|
+
ApplyVerb(verb: string, args: JSONObject, actor: RealtimeChannelActor, instanceId?: string): RealtimeChannelVerbResult | Promise<RealtimeChannelVerbResult>;
|
|
611
|
+
/**
|
|
612
|
+
* Maps a native tool name back to its verb: the descriptor's `NativeToolName` match first, then the
|
|
613
|
+
* name minus {@link ToolNamePrefix}. Protected so a channel with an unusual naming scheme can
|
|
614
|
+
* override it.
|
|
615
|
+
*/
|
|
616
|
+
protected ResolveVerbForTool(toolName: string): string;
|
|
617
|
+
/** Maps a verb to the native tool name it is reachable as (inverse of {@link ResolveVerbForTool}). */
|
|
618
|
+
protected ResolveNativeToolName(verb: string): string;
|
|
619
|
+
/**
|
|
620
|
+
* The descriptor verb a native tool call runs, or `undefined` when the tool is not one of the channel's verbs
|
|
621
|
+
* (the runtime uses it to apply {@link RefuseVerbForExposure} on the native-tool route as well as the `ContextTool` one).
|
|
622
|
+
*
|
|
623
|
+
* @param toolName The native tool name the model called.
|
|
624
|
+
*/
|
|
625
|
+
FindVerbForNativeTool(toolName: string): RealtimeChannelVerb | undefined;
|
|
626
|
+
/**
|
|
627
|
+
* Whether the agent may be given this verb's result at the channel's current exposure. A verb that declares
|
|
628
|
+
* `ReturnsChannelData` is refused whole when exposure is below that level, because its result would hand the agent
|
|
629
|
+
* what the user or a zero-data-retention policy held back from it. Policy, not redaction: the result is never filtered.
|
|
630
|
+
*
|
|
631
|
+
* Applies to the AGENT (the dispatcher and the native-tool route call it); a user acting through the surface is not restricted.
|
|
632
|
+
*
|
|
633
|
+
* @param verb The verb the agent is calling.
|
|
634
|
+
* @returns The sentence to give the agent, or `null` when the call may proceed.
|
|
635
|
+
*/
|
|
636
|
+
RefuseVerbForExposure(verb: Pick<RealtimeChannelVerb, 'Name' | 'ReturnsChannelData'>): string | null;
|
|
637
|
+
/** Why a channel that overrides neither entry point cannot run anything. */
|
|
638
|
+
private implementsNeitherMessage;
|
|
639
|
+
private readonly channelEventsSubject;
|
|
640
|
+
private readonly channelOutputSubject;
|
|
641
|
+
/**
|
|
642
|
+
* Everything this channel streams out, as typed events: state changes, discrete user actions, frames
|
|
643
|
+
* pushed, opened/completed. Hosts subscribe (the embeddable element re-emits these as DOM events);
|
|
644
|
+
* the model is told about a change through a coalesced note instead — see {@link RecordChange}.
|
|
645
|
+
* Completes at {@link Dispose}.
|
|
646
|
+
*/
|
|
647
|
+
readonly Events$: Observable<RealtimeChannelEvent>;
|
|
648
|
+
/** What the channel handed back when it completed (see {@link Complete}). Completes at {@link Dispose}. */
|
|
649
|
+
readonly Output$: Observable<RealtimeChannelOutput>;
|
|
650
|
+
/**
|
|
651
|
+
* Opens the channel — mounts it for use and seeds it with `inputs`. Called by the runtime when the
|
|
652
|
+
* agent (or user) opens an `on-demand` channel, after the channel has been initialized.
|
|
653
|
+
*
|
|
654
|
+
* Validates `inputs` against the descriptor's `Inputs` schema (a violation is a structured
|
|
655
|
+
* `'invalid_params'` failure, never a half-opened channel), runs the {@link OnOpen} hook, then tells
|
|
656
|
+
* the model the channel is open and what it currently holds (`opened` note with a state snapshot) —
|
|
657
|
+
* and takes that snapshot as the baseline later changes are described against.
|
|
658
|
+
*
|
|
659
|
+
* @param inputs What the agent asked to seed the channel with.
|
|
660
|
+
*/
|
|
661
|
+
Open(inputs?: JSONObject): Promise<RealtimeChannelVerbResult>;
|
|
662
|
+
/**
|
|
663
|
+
* Subclass hook for {@link Open}: apply the (already validated) seed `inputs`. Return a failure
|
|
664
|
+
* result to refuse the open; return nothing for success. Default: nothing to do.
|
|
665
|
+
*/
|
|
666
|
+
protected OnOpen(_inputs: JSONObject): void | RealtimeChannelVerbResult | Promise<void | RealtimeChannelVerbResult>;
|
|
667
|
+
/**
|
|
668
|
+
* The channel finished and is handing something back (a submitted form, a chosen option, a
|
|
669
|
+
* finished game). Emits on {@link Output$} and {@link Events$} and tells the model with a
|
|
670
|
+
* `completed` note. The output is validated against the descriptor's `Output` schema when
|
|
671
|
+
* {@link StrictStateChecks} is on; a mismatch is logged, never swallowed into silence or thrown.
|
|
672
|
+
*
|
|
673
|
+
* @param output What the channel hands back.
|
|
674
|
+
* @param instanceId The instance that completed, for a multi-instance channel (default: the primary instance).
|
|
675
|
+
*/
|
|
676
|
+
Complete(output: JSONObject, instanceId?: string): void;
|
|
677
|
+
/** Monotonic id of the latest state change; tags state events and the frames that describe them. */
|
|
678
|
+
private channelChangeSeq;
|
|
679
|
+
/** Re-entrancy guard for the default {@link ApplyVerb} ↔ {@link ApplyAgentTool} bridge. */
|
|
680
|
+
private bridgingVerbAndNativeTool;
|
|
681
|
+
private channelPerception;
|
|
682
|
+
/** Dev-check messages already logged, so a drifting state warns once, not on every note. */
|
|
683
|
+
private readonly warnedStateIssueKeys;
|
|
684
|
+
/** Tuning for the perception coalescer (debounce window, max note size). Override to change it. */
|
|
685
|
+
protected PerceptionOptions: ChannelPerceptionOptions;
|
|
686
|
+
/** The id of the latest state change (0 before any). */
|
|
687
|
+
protected get CurrentChangeId(): number;
|
|
688
|
+
/**
|
|
689
|
+
* Records that the channel's state changed. Call this on EVERY mutation, whoever caused it.
|
|
690
|
+
*
|
|
691
|
+
* It (1) assigns the change a monotonic id, (2) emits a `state_changed` event on {@link Events$}
|
|
692
|
+
* immediately (observers see every change), and (3) — unless `Perceive` is `false` — schedules a
|
|
693
|
+
* COALESCED structured note to the model: a burst of N changes inside the debounce window produces
|
|
694
|
+
* ONE `[channel:<Key>#<instance>] state_changed {"changeId":…,"changes":N,"delta":{…}}` note carrying
|
|
695
|
+
* what differs from what the model was last told (the first note is a full snapshot). Notes that
|
|
696
|
+
* would be too large degrade to a list of changed paths.
|
|
697
|
+
*
|
|
698
|
+
* @param options `Author` — who made the change (carried on the event); `Perceive` — whether the
|
|
699
|
+
* model should be told (default `true`; a channel that already feeds the model its own perception
|
|
700
|
+
* — like the Whiteboard's scene deltas — passes `false`).
|
|
701
|
+
* @returns The change's id.
|
|
702
|
+
*/
|
|
703
|
+
protected RecordChange(options?: {
|
|
704
|
+
Author?: RealtimeChannelActor | 'system';
|
|
705
|
+
Perceive?: boolean;
|
|
706
|
+
}): number;
|
|
707
|
+
/**
|
|
708
|
+
* Emits a typed event on {@link Events$} (NOT to the model — use {@link RecordChange} for state the
|
|
709
|
+
* model should perceive, or send an explicit note for a discrete event it must hear about).
|
|
710
|
+
*
|
|
711
|
+
* @param name The event name (declare it in the descriptor's `Events`).
|
|
712
|
+
* @param payload The event payload.
|
|
713
|
+
* @param changeId The change id the event relates to, when it relates to one.
|
|
714
|
+
* @param instanceId The instance the event is about, for a multi-instance channel (default: the primary instance).
|
|
715
|
+
*/
|
|
716
|
+
protected EmitChannelEvent(name: string, payload?: JSONObject, changeId?: number, instanceId?: string): void;
|
|
717
|
+
/** Sends any pending coalesced perception note now (e.g. before a surface is torn down). */
|
|
718
|
+
protected FlushPerception(): void;
|
|
719
|
+
/** The perception coalescer, created on first use. */
|
|
720
|
+
private ensurePerception;
|
|
721
|
+
/** {@link GetState}, with the development-time schema check applied when {@link StrictStateChecks} is on. */
|
|
722
|
+
private getStateChecked;
|
|
723
|
+
/** Logs a state problem once per channel instance — these checks run on every perception note. */
|
|
724
|
+
private warnStateIssueOnce;
|
|
725
|
+
/**
|
|
726
|
+
* Whether this channel wants to be offered the artifacts a delegated run just produced (the agent asked
|
|
727
|
+
* Skip or Sage to build something, and it came back as artifacts). A channel that hosts artifacts says yes
|
|
728
|
+
* for the ones it can show — and for an artifact it ALREADY shows, so a newer version replaces it in place.
|
|
729
|
+
*
|
|
730
|
+
* Asked of every channel in the session, mounted or merely advertised. For an advertised channel it is
|
|
731
|
+
* asked before the channel has been initialized, so it must not depend on {@link Context}; the channel's
|
|
732
|
+
* resolved configuration is passed in for exactly that reason. Saying yes for an advertised channel
|
|
733
|
+
* mounts it, so only answer yes when you will do something with the artifacts.
|
|
734
|
+
*
|
|
735
|
+
* Default: `false` — a channel that does not host artifacts is never bothered.
|
|
736
|
+
*
|
|
737
|
+
* @param artifacts What the delegated run produced.
|
|
738
|
+
* @param config This channel's resolved configuration (host defaults beneath agent/app config).
|
|
739
|
+
*/
|
|
740
|
+
AcceptsDelegationArtifacts(_artifacts: readonly ParsedDelegationArtifact[], _config: JSONObject): boolean;
|
|
741
|
+
/**
|
|
742
|
+
* A delegated run produced artifacts this channel said it wants ({@link AcceptsDelegationArtifacts}). The
|
|
743
|
+
* channel is mounted and initialized by now. Never throw into the runtime: handle your own failures and
|
|
744
|
+
* report them (the runtime logs anything that escapes, but cannot recover the work).
|
|
745
|
+
*
|
|
746
|
+
* Default: nothing.
|
|
747
|
+
*
|
|
748
|
+
* @param artifacts What the delegated run produced.
|
|
749
|
+
*/
|
|
750
|
+
OnDelegationArtifacts(_artifacts: readonly ParsedDelegationArtifact[]): void | Promise<void>;
|
|
751
|
+
/** The exposure the SERVER's policy allows (agent cap, zero data retention); `undefined` until the runtime applies one. */
|
|
752
|
+
private policyExposure;
|
|
753
|
+
/** The user's own choice for this channel; `undefined` when they made none. */
|
|
754
|
+
private userExposure;
|
|
755
|
+
/** Why exposure is below the channel's ceiling, as sentences the agent can be told. */
|
|
756
|
+
private exposureReasons;
|
|
757
|
+
/**
|
|
758
|
+
* How much of this channel the model may perceive without asking: the lowest of the channel's own ceiling
|
|
759
|
+
* (`GetDescriptor().MaxExposure`), the server policy and the user's choice. A channel nobody has applied a
|
|
760
|
+
* policy to simply has its ceiling, which is what every channel had before exposure policy existed.
|
|
761
|
+
*
|
|
762
|
+
* - `'none'`: no state notes and no frames.
|
|
763
|
+
* - `'state'`: structured state notes; no frames.
|
|
764
|
+
* - `'pixels'`: state notes and frames.
|
|
765
|
+
*
|
|
766
|
+
* It governs what flows to the model UNPROMPTED (perception notes, the contents of `opened` / `completed`
|
|
767
|
+
* notes, frames). It does not REDACT what a verb's result contains: a verb is all-or-nothing. A verb whose
|
|
768
|
+
* result would show the model something above this level declares `ReturnsChannelData` on the verb, and
|
|
769
|
+
* when this level is below it the verb is refused whole (`exposure_restricted`) and listed to the model as
|
|
770
|
+
* unavailable; see {@link RefuseVerbForExposure}. A verb that does not declare it returns what the channel
|
|
771
|
+
* says it returns, so a channel whose verbs reveal sensitive data must either declare it or lower its own
|
|
772
|
+
* `MaxExposure`.
|
|
773
|
+
*/
|
|
774
|
+
get Exposure(): RealtimeChannelExposure;
|
|
775
|
+
/** Why {@link Exposure} is below the channel's ceiling; empty when it is not. */
|
|
776
|
+
get ExposureReasons(): readonly string[];
|
|
777
|
+
/**
|
|
778
|
+
* Whether the server policy (not the user) leaves room for pixels. Deliberately does not consult the
|
|
779
|
+
* descriptor: a synthesized descriptor derives its `MaxExposure` from {@link GetSourcedTracks}, which asks
|
|
780
|
+
* this, so reading it here would recurse. A channel that enabled visual perception has declared pixels.
|
|
781
|
+
*/
|
|
782
|
+
private policyAllowsPixels;
|
|
783
|
+
/**
|
|
784
|
+
* Applies exposure policy: the server's decision and the user's own choice. The runtime calls this when
|
|
785
|
+
* it mounts the channel and again whenever the user changes their choice.
|
|
786
|
+
*
|
|
787
|
+
* Withdrawing exposure takes effect immediately: a pending perception note is dropped, a pending frame
|
|
788
|
+
* is dropped, and the channel's video source stops being forwarded. Restoring it re-baselines (the
|
|
789
|
+
* model's picture of the channel is stale, so the next note is a full snapshot) and sends a fresh frame.
|
|
790
|
+
* When the call is live the model is told about the change, with the reason, so it never assumes it
|
|
791
|
+
* can still see what it can't.
|
|
792
|
+
*
|
|
793
|
+
* @param settings `Policy` — the server-decided exposure; `User` — the user's choice (omit for none);
|
|
794
|
+
* `Reasons` — why the policy lowered it, from the server's limits.
|
|
795
|
+
*/
|
|
796
|
+
ApplyExposure(settings: ChannelExposureSettings): void;
|
|
797
|
+
/** Makes a change in exposure real: stops what is no longer allowed, restarts what is again. */
|
|
798
|
+
private applyExposureEffects;
|
|
799
|
+
/** Emits the change on {@link Events$} and, when the call is live, tells the model what it can now perceive and why. */
|
|
800
|
+
private announceExposureChange;
|
|
801
|
+
/** The frame source the visual pump captures from, once {@link EnableVisualPerception} ran. */
|
|
802
|
+
private visualFrameProvider;
|
|
803
|
+
private visualPerceptionOptions;
|
|
804
|
+
private visualFramePump;
|
|
805
|
+
/**
|
|
806
|
+
* The shared frame bridge that carries frames to the model's inbound video track. Deliberately NOT named
|
|
807
|
+
* `videoBridge`: channels that predate the pump (the Remote Browser, app channels) declare their own
|
|
808
|
+
* private `videoBridge`, and a second private of the same name in the base class would stop them compiling.
|
|
809
|
+
*/
|
|
810
|
+
protected VisualVideoBridge: ChannelInboundVideoBridge | null;
|
|
811
|
+
/** Stops refreshing the model's picture when the bridge's source is sent again; set while the bridge exists. */
|
|
812
|
+
private stopRefreshOnSourceActivated;
|
|
813
|
+
/** Default frame cadence when the track negotiated none (1 fps — the Gemini Live ceiling). */
|
|
814
|
+
private static readonly DEFAULT_VISUAL_CADENCE_MS;
|
|
815
|
+
/** Floor for the negotiated cadence (4 fps) so a fast model never makes a channel spin. */
|
|
816
|
+
private static readonly MIN_VISUAL_CADENCE_MS;
|
|
817
|
+
/**
|
|
818
|
+
* Opts this channel into VISUAL perception: its surface can be shown to a video-capable model as
|
|
819
|
+
* frames. Call it from {@link OnInitialize} with the channel's frame source.
|
|
820
|
+
*
|
|
821
|
+
* The channel then needs only to say *when* its picture changed — {@link NotifyVisualChange} after a
|
|
822
|
+
* user edit, {@link ConfirmVisualChange} after a successful agent edit — and the base class does the
|
|
823
|
+
* rest: change-driven (no idle heartbeat), paced to the negotiated cadence, a trailing settle so the
|
|
824
|
+
* model ends on the final state of a burst, dedupe of identical frames, and a single confirmation
|
|
825
|
+
* frame (with a "do not narrate" note) after an agent edit. Every frame is tagged with the change id
|
|
826
|
+
* of the state it was captured at (`frame_pushed` events), so state and pixels can be cross-checked.
|
|
827
|
+
*
|
|
828
|
+
* Also makes {@link GetSourcedTracks} report the inbound video track, which is what gets it
|
|
829
|
+
* negotiated. Idempotent: calling it again replaces the provider and options.
|
|
830
|
+
*
|
|
831
|
+
* @param provider Renders the channel's current picture as a base64 JPEG (or `null`).
|
|
832
|
+
* @param options See {@link VisualPerceptionOptions}.
|
|
833
|
+
*/
|
|
834
|
+
protected EnableVisualPerception(provider: IChannelFrameProvider, options?: VisualPerceptionOptions): void;
|
|
835
|
+
/**
|
|
836
|
+
* The channel's picture changed because of a USER action (or a scene replacement): push a frame,
|
|
837
|
+
* respecting the cadence. Resolves when the decision has been carried out; never rejects. A no-op
|
|
838
|
+
* until {@link EnableVisualPerception} ran and the session has an inbound video track.
|
|
839
|
+
*/
|
|
840
|
+
protected NotifyVisualChange(): Promise<void>;
|
|
841
|
+
/**
|
|
842
|
+
* An AGENT action succeeded and changed the channel's picture: push exactly one confirmation frame
|
|
843
|
+
* now and tell the model not to narrate its own change. Call only on SUCCESS — confirming a failed
|
|
844
|
+
* action would assert an edit landed that did not. A no-op until {@link EnableVisualPerception} ran.
|
|
845
|
+
*/
|
|
846
|
+
protected ConfirmVisualChange(): Promise<void>;
|
|
847
|
+
/**
|
|
848
|
+
* Returns the shared frame bridge, creating it if needed and (only when the channel opted into the
|
|
849
|
+
* legacy poller) starting its fixed-rate poll once the video track is up. `null` when no context is bound.
|
|
850
|
+
*/
|
|
851
|
+
protected EnsureVideoBridge(): ChannelInboundVideoBridge | null;
|
|
852
|
+
/** Builds the pump, wiring it to this channel's context, bridge and event stream. */
|
|
853
|
+
private createVisualPump;
|
|
854
|
+
/** The "do not narrate your own change" note sent with a confirmation frame. */
|
|
855
|
+
private confirmationNote;
|
|
856
|
+
/**
|
|
857
|
+
* The frame cadence in ms: the rate the inbound video track negotiated (`1000 / Rate`), clamped to
|
|
858
|
+
* a 250ms floor; 1000ms when nothing was negotiated.
|
|
859
|
+
*/
|
|
860
|
+
private getNegotiatedVisualCadenceMs;
|
|
394
861
|
/**
|
|
395
862
|
* Tears the plugin down at session end: release the surface binding, unsubscribe
|
|
396
863
|
* state-engine subscriptions, then drop the context. Subclasses overriding this MUST
|
|
@@ -399,4 +866,44 @@ export declare abstract class BaseRealtimeChannelClient<TSurface extends object
|
|
|
399
866
|
*/
|
|
400
867
|
Dispose(): void;
|
|
401
868
|
}
|
|
869
|
+
/**
|
|
870
|
+
* The id of a channel's video source at the session's `VideoSourceArbiter`: `<channel key>#<instance id>`. The channel's
|
|
871
|
+
* own frame bridge and the runtime's {@link RealtimeChannelContext.SendVideoFrame} register under it, so a channel is
|
|
872
|
+
* one source however it sends, and the "agent can see" control lists it once.
|
|
873
|
+
*
|
|
874
|
+
* @param channelKey The channel's descriptor key.
|
|
875
|
+
* @param instanceId The channel instance.
|
|
876
|
+
*/
|
|
877
|
+
export declare function ChannelVideoSourceID(channelKey: string, instanceId: string): string;
|
|
878
|
+
/**
|
|
879
|
+
* Settings for {@link BaseRealtimeChannelClient.ApplyExposure}.
|
|
880
|
+
*/
|
|
881
|
+
export interface ChannelExposureSettings {
|
|
882
|
+
/** The exposure the server's policy allows (agent cap and zero-data-retention requirement). Omit when no server policy applies. */
|
|
883
|
+
Policy?: RealtimeChannelExposure;
|
|
884
|
+
/** The user's own choice for this channel. Omit when they made none. */
|
|
885
|
+
User?: RealtimeChannelExposure;
|
|
886
|
+
/** Why the policy lowered exposure, as sentences the agent can be told. */
|
|
887
|
+
Reasons?: readonly string[];
|
|
888
|
+
}
|
|
889
|
+
/**
|
|
890
|
+
* Options for {@link BaseRealtimeChannelClient.EnableVisualPerception}.
|
|
891
|
+
*/
|
|
892
|
+
export interface VisualPerceptionOptions {
|
|
893
|
+
/**
|
|
894
|
+
* The note sent after a confirmation frame — a literal string, or a function of the change id.
|
|
895
|
+
* Default: a structured `frame_confirmed` note carrying a do-not-narrate instruction. The Whiteboard
|
|
896
|
+
* passes its original wording to stay byte-for-byte what it was.
|
|
897
|
+
*/
|
|
898
|
+
ConfirmationNote?: string | ((changeId: number) => string);
|
|
899
|
+
/**
|
|
900
|
+
* Also start the shared bridge's fixed-rate poller (1 fps) once the video track is up.
|
|
901
|
+
*
|
|
902
|
+
* Default `false`: the pump is purely change-driven. This exists ONLY so the Whiteboard keeps the
|
|
903
|
+
* behavior it had before the pump was lifted: it has always started the bridge's poller (which
|
|
904
|
+
* re-sends the board every second regardless of change) despite its own comments and design
|
|
905
|
+
* stating it is heartbeat-free. Nothing new should set this.
|
|
906
|
+
*/
|
|
907
|
+
StartBridgePoller?: boolean;
|
|
908
|
+
}
|
|
402
909
|
//# sourceMappingURL=base-realtime-channel-client.d.ts.map
|