@memberjunction/ai 5.40.2 → 5.42.0

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.
@@ -0,0 +1,134 @@
1
+ import { BaseModel } from "./baseModel.js";
2
+ /**
3
+ * Base class for real-time, full-duplex, tool-calling models.
4
+ *
5
+ * `BaseRealtimeModel` is the lowest-level primitive for streaming, bidirectional models
6
+ * (e.g. Google Gemini Live, OpenAI GPT Realtime, and — as a fast-follow — the Eleven Labs
7
+ * stack). It is a sibling of {@link BaseModel}-derived capability classes such as `BaseLLM`
8
+ * and `BaseAudioGenerator`, and is resolved through the MemberJunction `ClassFactory` by
9
+ * `AIModelType` + `DriverClass`.
10
+ *
11
+ * The contract is deliberately **modality-agnostic** — *streaming, full-duplex, tool-calling* —
12
+ * so the same primitive covers voice now and video later. It is distinct from
13
+ * `BaseAudioGenerator`, which is request/response STT/TTS (a different shape, not the
14
+ * real-time path).
15
+ *
16
+ * **Driver registration:** Concrete drivers ship in the respective `@memberjunction/ai-*`
17
+ * provider packages and self-register via the class factory, e.g.
18
+ * `@RegisterClass(BaseRealtimeModel, 'GeminiRealtime')`. The associated `MJ: AI Models`
19
+ * are typed with the `AIModelType` value **`Realtime`**.
20
+ *
21
+ * ## DRIVER AUTHOR OBLIGATIONS
22
+ *
23
+ * Hard-won, provider-independent rules every server-side realtime driver (and its
24
+ * client-direct twin — see `BaseRealtimeClient` in `@memberjunction/ai-realtime-client`)
25
+ * MUST honor. Most were paid for in live debugging; do not relearn them:
26
+ *
27
+ * 1. **Silent exit from "speaking" after a tool call.** When the model emits a tool call,
28
+ * the host typically shows its own busy ("thinking") indicator while the tool executes.
29
+ * A driver that surfaces UI state must leave any "speaking" state *silently* (no state
30
+ * emission) at tool-call time so the turn's trailing frames don't clobber the host's
31
+ * indicator.
32
+ * 2. **Busy-flag release on tool-call emission (deadlock guard).** A tool-call frame means
33
+ * the model has yielded the floor pending the result. Any internal "response active" /
34
+ * busy flag MUST be cleared at that point — otherwise the eventual `SendToolResult` (or
35
+ * a queued send) deadlocks waiting for a turn boundary that will never arrive until
36
+ * after the result is sent.
37
+ * 3. **Playback flush + honest playback reporting on interruption.** On a true barge-in the
38
+ * driver (or its client twin) must flush any locally-owned audio playback and report
39
+ * "audio playing = false" promptly — stale queued audio after an interruption is a
40
+ * product bug, not a nicety.
41
+ * 4. **Text injection must NOT echo a user transcript.** A "send typed text" capability
42
+ * must not synthesize a user-role transcript event for the injected text — the host owns
43
+ * the local echo and would render the message twice.
44
+ * 5. **Tool-result delivery invariant.** Every tool result fed back via
45
+ * {@link IRealtimeSession.SendToolResult} must EVENTUALLY be voiced/processed by the
46
+ * model and must never be dropped. If the provider rejects overlapping generation
47
+ * triggers, the driver queues the result's trigger behind the in-flight response and
48
+ * flushes it at the next turn boundary.
49
+ * 6. **Token/credential expiry surfaces as a FATAL error.** When the session's credential
50
+ * dies (ephemeral token expiry, auth revocation), the driver must surface it through
51
+ * {@link IRealtimeSession.OnError} with `Fatal: true` so the consumer finalizes cleanly
52
+ * instead of idling forever on a dead socket.
53
+ * 7. **"Ready" only after the session config is applied.** A driver (or client twin) must
54
+ * not report the session as live/listening until the server-built session config
55
+ * (system prompt + tools) has actually been applied to the provider socket — otherwise
56
+ * early turns run against an unconfigured model.
57
+ * 8. **`SessionConfig` is a private pact.** The {@link ClientRealtimeSessionConfig.SessionConfig}
58
+ * payload a server driver mints is consumed ONLY by the same-keyed client driver. Hosts
59
+ * and intermediaries treat it as an opaque blob; its shape may change between the two
60
+ * driver halves without notice.
61
+ *
62
+ * @abstract
63
+ */
64
+ export class BaseRealtimeModel extends BaseModel {
65
+ /**
66
+ * Whether this driver can mint an ephemeral, server-scoped client credential for a
67
+ * **client-direct** realtime session (the browser opens its own provider socket using a
68
+ * short-lived token the server minted).
69
+ *
70
+ * Defaults to `false`. Providers that support browser-direct sessions override this to `true`
71
+ * and implement {@link CreateClientSession}. The server-bridged topology (where the provider
72
+ * socket lives on the server, via {@link StartSession}) is supported by every driver regardless
73
+ * of this flag.
74
+ *
75
+ * @returns `true` if {@link CreateClientSession} is supported; `false` otherwise.
76
+ */
77
+ get SupportsClientDirect() {
78
+ return false;
79
+ }
80
+ /**
81
+ * Mints an ephemeral, server-scoped client credential plus a provider-native session config for
82
+ * a **client-direct** realtime session.
83
+ *
84
+ * In the client-direct topology the browser owns the provider socket (e.g. WebRTC), but the
85
+ * **server** still controls the prompt and tool set: it mints a short-lived token and hands back
86
+ * a {@link ClientRealtimeSessionConfig} whose `SessionConfig` the matching client driver applies
87
+ * when it opens its socket. This keeps prompt/tool authority server-side even though the media
88
+ * plane is client-direct.
89
+ *
90
+ * Not every provider supports this (some only expose a server-bridged socket), so this is a
91
+ * concrete method that throws by default rather than an abstract one — that would force every
92
+ * existing and future driver to implement it. Providers that support it override
93
+ * {@link SupportsClientDirect} to `true` and override this method.
94
+ *
95
+ * @param _params The session parameters (system prompt, tools, model, config bag).
96
+ * @returns A promise resolving to the minted {@link ClientRealtimeSessionConfig}.
97
+ * @throws Always, unless overridden by a provider that supports client-direct sessions.
98
+ */
99
+ async CreateClientSession(_params) {
100
+ throw new Error(`${this.constructor.name} does not support client-direct realtime sessions`);
101
+ }
102
+ /**
103
+ * Whether this driver's sessions carry a **video** track in addition to audio — i.e. the model
104
+ * accepts video input (it can "see" the user's camera) and/or emits video output (a talking-head
105
+ * avatar / generated video), in sync with audio.
106
+ *
107
+ * Defaults to `false` (audio-only — today's realtime models). Video-capable drivers (a native
108
+ * multimodal realtime model, or an avatar provider) override this to `true`. The session's media
109
+ * plane is media-tagged ({@link IRealtimeSession.SendInput} takes a {@link RealtimeMediaKind};
110
+ * {@link IRealtimeSession.OnVideoOutput} delivers video-out), so a video session reuses the entire
111
+ * realtime contract — only the media frames gain a `video` kind. Resolution prefers a video-capable
112
+ * model when an agent requests video, and degrades to audio-only otherwise.
113
+ *
114
+ * @returns `true` if sessions can carry video; `false` (audio-only) otherwise.
115
+ */
116
+ get SupportsVideo() {
117
+ return false;
118
+ }
119
+ /**
120
+ * The provider-native voice ids this model can speak with (e.g. OpenAI `alloy`/`echo`/`shimmer`). The
121
+ * model/driver is the authoritative owner of "what voices do I support", so each driver declares its
122
+ * own — used to populate the dev voice picker. Default empty (a driver that hasn't declared voices
123
+ * yields no picker options, falling back to the configured/default voice).
124
+ *
125
+ * NOTE: this is the near-term, driver-owned source of truth. Long term this should move to metadata so
126
+ * providers that let users add their OWN voices (e.g. ElevenLabs) can be enumerated dynamically.
127
+ *
128
+ * @returns The supported voice ids (id + human label), or `[]` when none are declared.
129
+ */
130
+ get SupportedVoices() {
131
+ return [];
132
+ }
133
+ }
134
+ //# sourceMappingURL=baseRealtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"baseRealtime.js","sourceRoot":"","sources":["../../src/generic/baseRealtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAoBxC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6DG;AACH,MAAM,OAAgB,iBAAkB,SAAQ,SAAS;IAcrD;;;;;;;;;;;OAWG;IACH,IAAW,oBAAoB;QAC3B,OAAO,KAAK,CAAC;IACjB,CAAC;IAED;;;;;;;;;;;;;;;;;;OAkBG;IACI,KAAK,CAAC,mBAAmB,CAAC,OAA8B;QAC3D,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,mDAAmD,CAAC,CAAC;IACjG,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,IAAW,aAAa;QACpB,OAAO,KAAK,CAAC;IACjB,CAAC;IAED;;;;;;;;;;OAUG;IACH,IAAW,eAAe;QACtB,OAAO,EAAE,CAAC;IACd,CAAC;CACJ"}
@@ -0,0 +1,235 @@
1
+ /**
2
+ * @fileoverview Base class for SERVER-SIDE interactive-channel plugins — the server half of the
3
+ * channel plugin registry (`MJ: AI Agent Channels.ServerPluginClass`), mirroring the client half
4
+ * (`BaseRealtimeChannelClient` in `@memberjunction/ng-conversations`, resolved from the same
5
+ * registry's `ClientPluginClass`).
6
+ *
7
+ * Lives beside {@link import('./baseRealtime.js').BaseRealtimeModel} because it is a server-side
8
+ * realtime primitive with the same constraint: zero MJ dependencies past `@memberjunction/global`.
9
+ * The DB-aware resolution/orchestration half (reading the channel registry, one-instance-per-session
10
+ * bookkeeping) lives in `@memberjunction/ai-agents` (`RealtimeChannelServerHost`).
11
+ *
12
+ * @module @memberjunction/ai
13
+ * @author MemberJunction.com
14
+ */
15
+ import { RealtimeToolDefinition } from './baseRealtime.js';
16
+ /**
17
+ * Why an agent session was closed — the server-side channel plugin's view of the session-close
18
+ * provenance. Mirrors the `MJ: AI Agent Sessions.CloseReason` value list (`SessionCloseReason` in
19
+ * `@memberjunction/server`): `'Explicit'` (user hang-up), `'Janitor'` (orphan reconciliation),
20
+ * `'Shutdown'` (graceful host drain), `'Error'` (failure-path teardown). `null` reaches the plugin
21
+ * only for legacy rows closed before the column existed (or when the reason was never stamped).
22
+ */
23
+ export type RealtimeChannelCloseReason = 'Explicit' | 'Janitor' | 'Shutdown' | 'Error';
24
+ /**
25
+ * Immutable session facts handed to a {@link BaseRealtimeChannelServer} at
26
+ * {@link BaseRealtimeChannelServer.Initialize}. Deliberately **plain data** (string ids, no entity
27
+ * or `UserInfo` objects) so the base contract stays free of `@memberjunction/core` — concrete
28
+ * plugins that need richer server context load it themselves in the packages they ship in.
29
+ */
30
+ export interface RealtimeChannelServerContext {
31
+ /** The durable `MJ: AI Agent Sessions` row id this plugin instance is bound to. */
32
+ AgentSessionID: string;
33
+ /** The session's agent id (`AIAgentSession.AgentID` — the co-agent on realtime voice sessions). */
34
+ AgentID: string;
35
+ /** The owning user's id (`AIAgentSession.UserID`) — ownership is enforced host-side on every relay. */
36
+ UserID: string;
37
+ /** The conversation the session is attached to, or `null` when the session carries none. */
38
+ ConversationID: string | null;
39
+ /**
40
+ * **Optional perception sink** — feeds a background context note into the live realtime model
41
+ * (the server-side counterpart of the client channel's `RealtimeChannelContext.SendContextNote`).
42
+ * The host wires this to `IRealtimeSession.SendContextNote` when the provider supports mid-session
43
+ * context injection; a server-side channel calls it to keep the agent aware of what is happening
44
+ * on its surface (a hand went up, who is speaking, time remaining) WITHOUT forcing a spoken reply.
45
+ *
46
+ * Optional because not every provider supports injecting conversation items into an open session
47
+ * (some only accept media frames + tool results), and because the host may construct the context
48
+ * before a live session exists. Channels MUST call it null-safely (`this.Context?.SendContextNote?.(…)`).
49
+ *
50
+ * @param text The perception note to surface to the model (plain text; the channel owns any framing).
51
+ */
52
+ SendContextNote?(text: string): void;
53
+ }
54
+ /**
55
+ * The result of a server-side channel tool execution ({@link BaseRealtimeChannelServer.ExecuteServerTool}),
56
+ * fed back to the realtime model as the `tool_response`.
57
+ *
58
+ * Deliberately small and serializable — the host (`RealtimeChannelServerHost`) wraps a thrown error
59
+ * into a `{ Success: false }` result so the model always receives a consistent response, and the
60
+ * transport layer (`RealtimeSessionRunner`) serializes `{ success, output }` to the exact JSON shape
61
+ * the model expects (identical to {@link import('../..').RealtimeToolBrokerDeps} non-target tooling).
62
+ */
63
+ export interface ServerChannelToolResult {
64
+ /** Whether the tool executed successfully. */
65
+ Success: boolean;
66
+ /**
67
+ * The textual outcome to feed back to the model: a description of what changed on success, or
68
+ * the error to surface on failure (so the model can narrate it — spoken-error-handling).
69
+ */
70
+ Output: string;
71
+ }
72
+ /**
73
+ * Base class for SERVER-SIDE interactive-channel plugins (per `plans/ai-agent-sessions.md` →
74
+ * "Pluggable Interfaces (`IAgentChannelServer` & `IAgentChannelClient`)").
75
+ *
76
+ * ### Relationship to the plan's `IAgentChannelServer`
77
+ * The plan's interface anticipates **server-bridged media** — a channel that owns sockets, receives
78
+ * demultiplexed `OnClientMessage` payloads from a unified `ISessionTransport`, and streams data back.
79
+ * That transport plane is an independent, not-yet-built track. What exists TODAY is the
80
+ * **client-direct** topology: channel plugins execute in the browser
81
+ * (`BaseRealtimeChannelClient`), and the server's per-channel touchpoints are the durable lifecycle
82
+ * events — session minted, channel state-of-record saved, session closed. This base class is the
83
+ * pragmatic adaptation to that reality:
84
+ *
85
+ * - `Initialize(ctx)` / `Dispose()` keep the plan's lifecycle bracket (and mirror the client half).
86
+ * - `OnClientMessage` / `SendToClient` / socket ownership are **deferred** with the transport track —
87
+ * when `ISessionTransport` lands, this class grows an injected-transport overload rather than the
88
+ * plan's raw-socket form (the plan itself refines them away; see its "Unified Session Transport").
89
+ * - The lifecycle hooks below ({@link OnSessionStarted} / {@link OnChannelStateSave} /
90
+ * {@link OnSessionClosed}) are the events the shipping session machinery actually emits.
91
+ *
92
+ * ### Registration & resolution (mirrors the client half exactly)
93
+ * Concrete plugins are `@RegisterClass(BaseRealtimeChannelServer, '<ServerPluginClass>')` and are
94
+ * resolved at session start from the ACTIVE `MJ: AI Agent Channels` rows: each row's
95
+ * `ServerPluginClass` is the ClassFactory key. Rows whose key has no registration are skipped with
96
+ * a log — never fatal; a session always proceeds with whatever server plugins resolve. Ship a
97
+ * `Load<YourChannel>Server()` no-op beside the class and call it from a static code path so
98
+ * bundlers cannot tree-shake the registration away.
99
+ *
100
+ * ### Lifecycle — ONE INSTANCE PER SESSION (not a singleton)
101
+ * `ClassFactory.CreateInstance` → {@link Initialize}(ctx) → {@link OnSessionStarted} → zero or more
102
+ * {@link OnChannelStateSave} calls (one per debounced client state-save landing on the server) →
103
+ * {@link OnSessionClosed}(reason) → {@link Dispose}. Disposal is deliberately **deferred briefly**
104
+ * after close by the host so the client's final post-close state flush (a legitimate, contract-
105
+ * sanctioned late save) still routes through the plugin.
106
+ *
107
+ * ### Failure tolerance (hard contract)
108
+ * Every hook is invoked inside a host-side try/catch: a throwing plugin is logged and the session
109
+ * proceeds untouched — a channel plugin can never break a live call or block persistence.
110
+ * Implementations should still prefer returning benign results over throwing.
111
+ *
112
+ * ### Server-executed tool contribution (Phase 2 — now wired)
113
+ * A server-side channel may contribute a **dynamic, runtime-computed** tool vocabulary the agent can
114
+ * invoke server-side (a bot has no browser, so these execute on the server rather than client-side
115
+ * like the {@link import('../..').BaseRealtimeChannelClient} half). The two hooks:
116
+ *
117
+ * - {@link GetServerToolDefinitions} — returns the channel's server-executed tool declarations. May
118
+ * be **runtime-computed** (per session / per platform state), not only constants — this is what
119
+ * lets a bridge-contributed channel (e.g. Meeting Controls, a Zoom native whiteboard) declare a
120
+ * tool set that only exists because of the live connection. Default: `[]` (a state-only channel
121
+ * like the whiteboard contributes no server tools).
122
+ * - {@link ExecuteServerTool} — executes ONE of this channel's tools and returns the result. Default:
123
+ * a structured "not implemented" error (never throws), so a channel that declares tools but forgets
124
+ * to implement execution fails loudly-but-safely rather than crashing the session.
125
+ *
126
+ * The per-session host ({@link RealtimeChannelServerHost}) aggregates every live plugin's
127
+ * {@link GetServerToolDefinitions} into the session's tool set (feeding
128
+ * `RealtimeSessionRunner.ServerChannelTools`) and routes each `{@link ToolNamePrefix}*` tool call back
129
+ * to the owning plugin's {@link ExecuteServerTool}. Tool-name collisions across channels are avoided
130
+ * by each channel's {@link ToolNamePrefix} (mirroring the client half's `ToolNamePrefix`).
131
+ *
132
+ * @remarks
133
+ * Socket/media members (`OnClientMessage`, `SendToClient`) remain deferred with the unified-transport
134
+ * track — when `ISessionTransport` lands, this class grows an injected-transport overload rather than
135
+ * the plan's raw-socket form.
136
+ */
137
+ export declare abstract class BaseRealtimeChannelServer {
138
+ /**
139
+ * The bound session context, available from {@link Initialize} until {@link Dispose}.
140
+ * `null` outside that window — guard with `?.` in any code that can run early/late.
141
+ */
142
+ protected Context: RealtimeChannelServerContext | null;
143
+ /**
144
+ * The channel definition name — MUST match the `MJ: AI Agent Channels` row's `Name`
145
+ * (e.g. `'Whiteboard'`). The host routes {@link OnChannelStateSave} by the registry row's
146
+ * name and warns when a resolved plugin's `ChannelName` disagrees with its row.
147
+ */
148
+ abstract get ChannelName(): string;
149
+ /**
150
+ * The shared name prefix of every server-executed tool this channel contributes (e.g.
151
+ * `'MeetingControls_'`). The host routes any tool call whose name starts with this prefix to
152
+ * THIS plugin's {@link ExecuteServerTool}, which is what prevents tool-name collisions when
153
+ * multiple channels are active in one session. A channel that contributes no server tools may
154
+ * leave the default empty string (the host then never routes any call to it).
155
+ *
156
+ * Mirrors the client half's `ToolNamePrefix`. Default: `''` (no server tools).
157
+ */
158
+ get ToolNamePrefix(): string;
159
+ /**
160
+ * Returns this channel's **server-executed** tool declarations — the tools the agent can invoke
161
+ * on this channel that run server-side (a bot has no browser). May be **runtime-computed**: the
162
+ * returned set can depend on the live session, the connected platform, or current channel state,
163
+ * so a bridge-contributed channel can declare a vocabulary that only exists because of the live
164
+ * connection. Every tool's `Name` SHOULD start with {@link ToolNamePrefix} so the host can route
165
+ * its execution back here unambiguously.
166
+ *
167
+ * Invoked by {@link RealtimeChannelServerHost} when assembling the session's tool set (after the
168
+ * plugin's {@link OnSessionStarted}). Default: `[]` (a state-only channel contributes none).
169
+ *
170
+ * @returns The channel's server-executed tool definitions (possibly empty).
171
+ */
172
+ GetServerToolDefinitions(): RealtimeToolDefinition[];
173
+ /**
174
+ * Executes ONE of this channel's server-side tools (a tool whose name starts with
175
+ * {@link ToolNamePrefix}) and returns the result fed back to the model as the `tool_response`.
176
+ *
177
+ * Implementations should NOT throw — return a `{ Success: false, Output }` result so the model can
178
+ * narrate the failure. The host additionally wraps anything thrown into a structured error, so a
179
+ * throwing implementation can never break the live session. The default implementation returns a
180
+ * structured "not implemented" error, so a channel that declares tools via
181
+ * {@link GetServerToolDefinitions} but forgets to implement execution fails safely and visibly.
182
+ *
183
+ * @param toolName The full tool name the model invoked (begins with {@link ToolNamePrefix}).
184
+ * @param argsJson The raw arguments JSON string the model emitted for the call.
185
+ * @returns The execution result (or a structured error), synchronously or as a promise.
186
+ */
187
+ ExecuteServerTool(toolName: string, argsJson: string): ServerChannelToolResult | Promise<ServerChannelToolResult>;
188
+ /**
189
+ * Binds the session context and invokes the {@link OnInitialize} hook. Called exactly once per
190
+ * session by the host, right after ClassFactory instantiation and before any lifecycle hook.
191
+ */
192
+ Initialize(ctx: RealtimeChannelServerContext): void;
193
+ /**
194
+ * Subclass hook invoked from {@link Initialize} once {@link Context} is bound — allocate any
195
+ * per-session state here. Default: no-op.
196
+ */
197
+ protected OnInitialize(): void;
198
+ /**
199
+ * Invoked by the host immediately after {@link Initialize}, when the durable session record has
200
+ * been persisted (`Status = 'Active'`) — the session id, agent, and conversation are all in
201
+ * {@link Context}. Default: no-op.
202
+ */
203
+ OnSessionStarted(): Promise<void>;
204
+ /**
205
+ * Invoked when the client's debounced channel-state save for THIS channel lands on the server,
206
+ * BEFORE the state is persisted onto the session's `MJ: AI Agent Session Channels` row.
207
+ *
208
+ * The plugin may **validate/normalize** the payload: return a replacement JSON string to persist
209
+ * instead of `stateJson`, or `null` to persist the original unchanged (the default). The host
210
+ * treats a thrown error, a non-string, or an empty string as "keep the original" — a plugin can
211
+ * therefore never lose a state save, only improve it.
212
+ *
213
+ * @param stateJson The raw state-of-record payload the client submitted (already size-capped
214
+ * host-side).
215
+ * @returns The normalized payload to persist, or `null` to keep `stateJson` as-is.
216
+ */
217
+ OnChannelStateSave(stateJson: string): Promise<string | null>;
218
+ /**
219
+ * Invoked when the session is closed — from ANY close path: the user's explicit hang-up, the
220
+ * janitor's orphan/staleness sweeps, the graceful shutdown drain, or an error-path teardown
221
+ * (the reason says which). Fired once per session; {@link Dispose} follows after the host's
222
+ * brief post-close linger window (during which late state saves still route here first).
223
+ * Default: no-op.
224
+ *
225
+ * @param closeReason The persisted close provenance, or `null` for legacy/unstamped rows.
226
+ */
227
+ OnSessionClosed(closeReason: RealtimeChannelCloseReason | null): Promise<void>;
228
+ /**
229
+ * Tears the plugin down: release any per-session resources, then drop the context. Subclasses
230
+ * overriding this MUST call `super.Dispose()`. Invoked by the host after the post-close linger
231
+ * window elapses (or immediately when the host is configured with no linger).
232
+ */
233
+ Dispose(): void;
234
+ }
235
+ //# sourceMappingURL=baseRealtimeChannelServer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"baseRealtimeChannelServer.d.ts","sourceRoot":"","sources":["../../src/generic/baseRealtimeChannelServer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAExD;;;;;;GAMG;AACH,MAAM,MAAM,0BAA0B,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,OAAO,CAAC;AAEvF;;;;;GAKG;AACH,MAAM,WAAW,4BAA4B;IACzC,mFAAmF;IACnF,cAAc,EAAE,MAAM,CAAC;IAEvB,mGAAmG;IACnG,OAAO,EAAE,MAAM,CAAC;IAEhB,uGAAuG;IACvG,MAAM,EAAE,MAAM,CAAC;IAEf,4FAA4F;IAC5F,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAE9B;;;;;;;;;;;;OAYG;IACH,eAAe,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACxC;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,uBAAuB;IACpC,8CAA8C;IAC9C,OAAO,EAAE,OAAO,CAAC;IAEjB;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgEG;AACH,8BAAsB,yBAAyB;IAC3C;;;OAGG;IACH,SAAS,CAAC,OAAO,EAAE,4BAA4B,GAAG,IAAI,CAAQ;IAE9D;;;;OAIG;IACH,aAAoB,WAAW,IAAI,MAAM,CAAC;IAE1C;;;;;;;;OAQG;IACH,IAAW,cAAc,IAAI,MAAM,CAElC;IAED;;;;;;;;;;;;OAYG;IACI,wBAAwB,IAAI,sBAAsB,EAAE;IAI3D;;;;;;;;;;;;;OAaG;IACI,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,uBAAuB,GAAG,OAAO,CAAC,uBAAuB,CAAC;IAIxH;;;OAGG;IACI,UAAU,CAAC,GAAG,EAAE,4BAA4B,GAAG,IAAI;IAK1D;;;OAGG;IACH,SAAS,CAAC,YAAY,IAAI,IAAI;IAI9B;;;;OAIG;IACU,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IAI9C;;;;;;;;;;;;OAYG;IACU,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAI1E;;;;;;;;OAQG;IACU,eAAe,CAAC,WAAW,EAAE,0BAA0B,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3F;;;;OAIG;IACI,OAAO,IAAI,IAAI;CAGzB"}
@@ -0,0 +1,193 @@
1
+ /**
2
+ * @fileoverview Base class for SERVER-SIDE interactive-channel plugins — the server half of the
3
+ * channel plugin registry (`MJ: AI Agent Channels.ServerPluginClass`), mirroring the client half
4
+ * (`BaseRealtimeChannelClient` in `@memberjunction/ng-conversations`, resolved from the same
5
+ * registry's `ClientPluginClass`).
6
+ *
7
+ * Lives beside {@link import('./baseRealtime.js').BaseRealtimeModel} because it is a server-side
8
+ * realtime primitive with the same constraint: zero MJ dependencies past `@memberjunction/global`.
9
+ * The DB-aware resolution/orchestration half (reading the channel registry, one-instance-per-session
10
+ * bookkeeping) lives in `@memberjunction/ai-agents` (`RealtimeChannelServerHost`).
11
+ *
12
+ * @module @memberjunction/ai
13
+ * @author MemberJunction.com
14
+ */
15
+ /**
16
+ * Base class for SERVER-SIDE interactive-channel plugins (per `plans/ai-agent-sessions.md` →
17
+ * "Pluggable Interfaces (`IAgentChannelServer` & `IAgentChannelClient`)").
18
+ *
19
+ * ### Relationship to the plan's `IAgentChannelServer`
20
+ * The plan's interface anticipates **server-bridged media** — a channel that owns sockets, receives
21
+ * demultiplexed `OnClientMessage` payloads from a unified `ISessionTransport`, and streams data back.
22
+ * That transport plane is an independent, not-yet-built track. What exists TODAY is the
23
+ * **client-direct** topology: channel plugins execute in the browser
24
+ * (`BaseRealtimeChannelClient`), and the server's per-channel touchpoints are the durable lifecycle
25
+ * events — session minted, channel state-of-record saved, session closed. This base class is the
26
+ * pragmatic adaptation to that reality:
27
+ *
28
+ * - `Initialize(ctx)` / `Dispose()` keep the plan's lifecycle bracket (and mirror the client half).
29
+ * - `OnClientMessage` / `SendToClient` / socket ownership are **deferred** with the transport track —
30
+ * when `ISessionTransport` lands, this class grows an injected-transport overload rather than the
31
+ * plan's raw-socket form (the plan itself refines them away; see its "Unified Session Transport").
32
+ * - The lifecycle hooks below ({@link OnSessionStarted} / {@link OnChannelStateSave} /
33
+ * {@link OnSessionClosed}) are the events the shipping session machinery actually emits.
34
+ *
35
+ * ### Registration & resolution (mirrors the client half exactly)
36
+ * Concrete plugins are `@RegisterClass(BaseRealtimeChannelServer, '<ServerPluginClass>')` and are
37
+ * resolved at session start from the ACTIVE `MJ: AI Agent Channels` rows: each row's
38
+ * `ServerPluginClass` is the ClassFactory key. Rows whose key has no registration are skipped with
39
+ * a log — never fatal; a session always proceeds with whatever server plugins resolve. Ship a
40
+ * `Load<YourChannel>Server()` no-op beside the class and call it from a static code path so
41
+ * bundlers cannot tree-shake the registration away.
42
+ *
43
+ * ### Lifecycle — ONE INSTANCE PER SESSION (not a singleton)
44
+ * `ClassFactory.CreateInstance` → {@link Initialize}(ctx) → {@link OnSessionStarted} → zero or more
45
+ * {@link OnChannelStateSave} calls (one per debounced client state-save landing on the server) →
46
+ * {@link OnSessionClosed}(reason) → {@link Dispose}. Disposal is deliberately **deferred briefly**
47
+ * after close by the host so the client's final post-close state flush (a legitimate, contract-
48
+ * sanctioned late save) still routes through the plugin.
49
+ *
50
+ * ### Failure tolerance (hard contract)
51
+ * Every hook is invoked inside a host-side try/catch: a throwing plugin is logged and the session
52
+ * proceeds untouched — a channel plugin can never break a live call or block persistence.
53
+ * Implementations should still prefer returning benign results over throwing.
54
+ *
55
+ * ### Server-executed tool contribution (Phase 2 — now wired)
56
+ * A server-side channel may contribute a **dynamic, runtime-computed** tool vocabulary the agent can
57
+ * invoke server-side (a bot has no browser, so these execute on the server rather than client-side
58
+ * like the {@link import('../..').BaseRealtimeChannelClient} half). The two hooks:
59
+ *
60
+ * - {@link GetServerToolDefinitions} — returns the channel's server-executed tool declarations. May
61
+ * be **runtime-computed** (per session / per platform state), not only constants — this is what
62
+ * lets a bridge-contributed channel (e.g. Meeting Controls, a Zoom native whiteboard) declare a
63
+ * tool set that only exists because of the live connection. Default: `[]` (a state-only channel
64
+ * like the whiteboard contributes no server tools).
65
+ * - {@link ExecuteServerTool} — executes ONE of this channel's tools and returns the result. Default:
66
+ * a structured "not implemented" error (never throws), so a channel that declares tools but forgets
67
+ * to implement execution fails loudly-but-safely rather than crashing the session.
68
+ *
69
+ * The per-session host ({@link RealtimeChannelServerHost}) aggregates every live plugin's
70
+ * {@link GetServerToolDefinitions} into the session's tool set (feeding
71
+ * `RealtimeSessionRunner.ServerChannelTools`) and routes each `{@link ToolNamePrefix}*` tool call back
72
+ * to the owning plugin's {@link ExecuteServerTool}. Tool-name collisions across channels are avoided
73
+ * by each channel's {@link ToolNamePrefix} (mirroring the client half's `ToolNamePrefix`).
74
+ *
75
+ * @remarks
76
+ * Socket/media members (`OnClientMessage`, `SendToClient`) remain deferred with the unified-transport
77
+ * track — when `ISessionTransport` lands, this class grows an injected-transport overload rather than
78
+ * the plan's raw-socket form.
79
+ */
80
+ export class BaseRealtimeChannelServer {
81
+ constructor() {
82
+ /**
83
+ * The bound session context, available from {@link Initialize} until {@link Dispose}.
84
+ * `null` outside that window — guard with `?.` in any code that can run early/late.
85
+ */
86
+ this.Context = null;
87
+ }
88
+ /**
89
+ * The shared name prefix of every server-executed tool this channel contributes (e.g.
90
+ * `'MeetingControls_'`). The host routes any tool call whose name starts with this prefix to
91
+ * THIS plugin's {@link ExecuteServerTool}, which is what prevents tool-name collisions when
92
+ * multiple channels are active in one session. A channel that contributes no server tools may
93
+ * leave the default empty string (the host then never routes any call to it).
94
+ *
95
+ * Mirrors the client half's `ToolNamePrefix`. Default: `''` (no server tools).
96
+ */
97
+ get ToolNamePrefix() {
98
+ return '';
99
+ }
100
+ /**
101
+ * Returns this channel's **server-executed** tool declarations — the tools the agent can invoke
102
+ * on this channel that run server-side (a bot has no browser). May be **runtime-computed**: the
103
+ * returned set can depend on the live session, the connected platform, or current channel state,
104
+ * so a bridge-contributed channel can declare a vocabulary that only exists because of the live
105
+ * connection. Every tool's `Name` SHOULD start with {@link ToolNamePrefix} so the host can route
106
+ * its execution back here unambiguously.
107
+ *
108
+ * Invoked by {@link RealtimeChannelServerHost} when assembling the session's tool set (after the
109
+ * plugin's {@link OnSessionStarted}). Default: `[]` (a state-only channel contributes none).
110
+ *
111
+ * @returns The channel's server-executed tool definitions (possibly empty).
112
+ */
113
+ GetServerToolDefinitions() {
114
+ return [];
115
+ }
116
+ /**
117
+ * Executes ONE of this channel's server-side tools (a tool whose name starts with
118
+ * {@link ToolNamePrefix}) and returns the result fed back to the model as the `tool_response`.
119
+ *
120
+ * Implementations should NOT throw — return a `{ Success: false, Output }` result so the model can
121
+ * narrate the failure. The host additionally wraps anything thrown into a structured error, so a
122
+ * throwing implementation can never break the live session. The default implementation returns a
123
+ * structured "not implemented" error, so a channel that declares tools via
124
+ * {@link GetServerToolDefinitions} but forgets to implement execution fails safely and visibly.
125
+ *
126
+ * @param toolName The full tool name the model invoked (begins with {@link ToolNamePrefix}).
127
+ * @param argsJson The raw arguments JSON string the model emitted for the call.
128
+ * @returns The execution result (or a structured error), synchronously or as a promise.
129
+ */
130
+ ExecuteServerTool(toolName, argsJson) {
131
+ return { Success: false, Output: `Server tool '${toolName}' is declared by channel '${this.ChannelName}' but has no execution implementation.` };
132
+ }
133
+ /**
134
+ * Binds the session context and invokes the {@link OnInitialize} hook. Called exactly once per
135
+ * session by the host, right after ClassFactory instantiation and before any lifecycle hook.
136
+ */
137
+ Initialize(ctx) {
138
+ this.Context = ctx;
139
+ this.OnInitialize();
140
+ }
141
+ /**
142
+ * Subclass hook invoked from {@link Initialize} once {@link Context} is bound — allocate any
143
+ * per-session state here. Default: no-op.
144
+ */
145
+ OnInitialize() {
146
+ // default: nothing to initialize
147
+ }
148
+ /**
149
+ * Invoked by the host immediately after {@link Initialize}, when the durable session record has
150
+ * been persisted (`Status = 'Active'`) — the session id, agent, and conversation are all in
151
+ * {@link Context}. Default: no-op.
152
+ */
153
+ async OnSessionStarted() {
154
+ // default: nothing to do at session start
155
+ }
156
+ /**
157
+ * Invoked when the client's debounced channel-state save for THIS channel lands on the server,
158
+ * BEFORE the state is persisted onto the session's `MJ: AI Agent Session Channels` row.
159
+ *
160
+ * The plugin may **validate/normalize** the payload: return a replacement JSON string to persist
161
+ * instead of `stateJson`, or `null` to persist the original unchanged (the default). The host
162
+ * treats a thrown error, a non-string, or an empty string as "keep the original" — a plugin can
163
+ * therefore never lose a state save, only improve it.
164
+ *
165
+ * @param stateJson The raw state-of-record payload the client submitted (already size-capped
166
+ * host-side).
167
+ * @returns The normalized payload to persist, or `null` to keep `stateJson` as-is.
168
+ */
169
+ async OnChannelStateSave(stateJson) {
170
+ return null; // default: persist the client's payload untouched
171
+ }
172
+ /**
173
+ * Invoked when the session is closed — from ANY close path: the user's explicit hang-up, the
174
+ * janitor's orphan/staleness sweeps, the graceful shutdown drain, or an error-path teardown
175
+ * (the reason says which). Fired once per session; {@link Dispose} follows after the host's
176
+ * brief post-close linger window (during which late state saves still route here first).
177
+ * Default: no-op.
178
+ *
179
+ * @param closeReason The persisted close provenance, or `null` for legacy/unstamped rows.
180
+ */
181
+ async OnSessionClosed(closeReason) {
182
+ // default: nothing to do at session close
183
+ }
184
+ /**
185
+ * Tears the plugin down: release any per-session resources, then drop the context. Subclasses
186
+ * overriding this MUST call `super.Dispose()`. Invoked by the host after the post-close linger
187
+ * window elapses (or immediately when the host is configured with no linger).
188
+ */
189
+ Dispose() {
190
+ this.Context = null;
191
+ }
192
+ }
193
+ //# sourceMappingURL=baseRealtimeChannelServer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"baseRealtimeChannelServer.js","sourceRoot":"","sources":["../../src/generic/baseRealtimeChannelServer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAoEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgEG;AACH,MAAM,OAAgB,yBAAyB;IAA/C;QACI;;;WAGG;QACO,YAAO,GAAwC,IAAI,CAAC;IAyHlE,CAAC;IAhHG;;;;;;;;OAQG;IACH,IAAW,cAAc;QACrB,OAAO,EAAE,CAAC;IACd,CAAC;IAED;;;;;;;;;;;;OAYG;IACI,wBAAwB;QAC3B,OAAO,EAAE,CAAC;IACd,CAAC;IAED;;;;;;;;;;;;;OAaG;IACI,iBAAiB,CAAC,QAAgB,EAAE,QAAgB;QACvD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,QAAQ,6BAA6B,IAAI,CAAC,WAAW,wCAAwC,EAAE,CAAC;IACrJ,CAAC;IAED;;;OAGG;IACI,UAAU,CAAC,GAAiC;QAC/C,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC;QACnB,IAAI,CAAC,YAAY,EAAE,CAAC;IACxB,CAAC;IAED;;;OAGG;IACO,YAAY;QAClB,iCAAiC;IACrC,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,gBAAgB;QACzB,0CAA0C;IAC9C,CAAC;IAED;;;;;;;;;;;;OAYG;IACI,KAAK,CAAC,kBAAkB,CAAC,SAAiB;QAC7C,OAAO,IAAI,CAAC,CAAC,kDAAkD;IACnE,CAAC;IAED;;;;;;;;OAQG;IACI,KAAK,CAAC,eAAe,CAAC,WAA8C;QACvE,0CAA0C;IAC9C,CAAC;IAED;;;;OAIG;IACI,OAAO;QACV,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;IACxB,CAAC;CACJ"}
@@ -1,10 +1,14 @@
1
1
  import { BaseParams, ModelUsage } from "./baseModel.js";
2
+ import { ChatMessageContent } from "./chat.types.js";
2
3
  export type EmbedTextParams = BaseParams & {
3
4
  text: string;
4
5
  };
5
6
  export type EmbedTextsParams = BaseParams & {
6
7
  texts: string[];
7
8
  };
9
+ export type EmbedContentParams = BaseParams & {
10
+ content: ChatMessageContent;
11
+ };
8
12
  export type EmbedResult = {
9
13
  object: 'object' | 'list';
10
14
  model: string;
@@ -16,4 +20,5 @@ export type EmbedTextResult = EmbedResult & {
16
20
  export type EmbedTextsResult = EmbedResult & {
17
21
  vectors: number[][];
18
22
  };
23
+ export type EmbedContentResult = EmbedTextResult;
19
24
  //# sourceMappingURL=embed.types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"embed.types.d.ts","sourceRoot":"","sources":["../../src/generic/embed.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAErD,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG;IACvC,IAAI,EAAE,MAAM,CAAA;CACf,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG;IACxC,KAAK,EAAE,MAAM,EAAE,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACtB,MAAM,EAAE,QAAQ,GAAG,MAAM,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,UAAU,CAAC;CAC1B,CAAA;AAED,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG;IACxC,MAAM,EAAE,MAAM,EAAE,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG,WAAW,GAAG;IACzC,OAAO,EAAE,MAAM,EAAE,EAAE,CAAA;CACtB,CAAA"}
1
+ {"version":3,"file":"embed.types.d.ts","sourceRoot":"","sources":["../../src/generic/embed.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAElD,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG;IACvC,IAAI,EAAE,MAAM,CAAA;CACf,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG;IACxC,KAAK,EAAE,MAAM,EAAE,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,kBAAkB,GAAG,UAAU,GAAG;IAC1C,OAAO,EAAE,kBAAkB,CAAA;CAC9B,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACtB,MAAM,EAAE,QAAQ,GAAG,MAAM,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,UAAU,CAAC;CAC1B,CAAA;AAED,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG;IACxC,MAAM,EAAE,MAAM,EAAE,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG,WAAW,GAAG;IACzC,OAAO,EAAE,MAAM,EAAE,EAAE,CAAA;CACtB,CAAA;AAED,MAAM,MAAM,kBAAkB,GAAG,eAAe,CAAA"}
package/dist/index.d.ts CHANGED
@@ -11,6 +11,8 @@ export * from './generic/embed.types.js';
11
11
  export * from './generic/baseEmbeddings.js';
12
12
  export * from './generic/baseAudio.js';
13
13
  export * from './generic/baseVideo.js';
14
+ export * from './generic/baseRealtime.js';
15
+ export * from './generic/baseRealtimeChannelServer.js';
14
16
  export * from './generic/errorTypes.js';
15
17
  export * from './generic/errorAnalyzer.js';
16
18
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAA;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAA;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qCAAqC,CAAC;AACpD,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC"}
package/dist/index.js CHANGED
@@ -11,6 +11,8 @@ export * from './generic/embed.types.js';
11
11
  export * from './generic/baseEmbeddings.js';
12
12
  export * from './generic/baseAudio.js';
13
13
  export * from './generic/baseVideo.js';
14
+ export * from './generic/baseRealtime.js';
15
+ export * from './generic/baseRealtimeChannelServer.js';
14
16
  export * from './generic/errorTypes.js';
15
17
  export * from './generic/errorAnalyzer.js';
16
18
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAA;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAA;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qCAAqC,CAAC;AACpD,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC"}