@kernl-sdk/protocol 0.3.1 → 0.4.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.
@@ -1,4 +1,4 @@
1
1
 
2
- > @kernl-sdk/protocol@0.3.1 build /home/runner/work/kernl/kernl/packages/protocol
2
+ > @kernl-sdk/protocol@0.4.0 build /home/runner/work/kernl/kernl/packages/protocol
3
3
  > tsc && tsc-alias --resolve-full-paths
4
4
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @kernl/protocol
2
2
 
3
+ ## 0.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - f593374: Add realtime voice agents with multi-provider support.
8
+ - `RealtimeAgent` and `RealtimeSession` for voice-enabled AI agents
9
+ - OpenAI GPT-4o realtime with WebSocket streaming
10
+ - xAI Grok realtime with OpenAI-compatible protocol
11
+ - React hooks: `useRealtime`, `useBrowserAudio`, `LiveWaveform`
12
+ - Ephemeral credential pattern for secure browser connections
13
+ - Tool execution with client-side context support
14
+
3
15
  ## 0.3.1
4
16
 
5
17
  ### Patch Changes
@@ -58,4 +58,8 @@ export declare const ZOMBIE = "zombie";
58
58
  * Final cleanup in progress, about to be fully deleted.
59
59
  */
60
60
  export declare const DEAD = "dead";
61
+ export declare const WS_CONNECTING = 0;
62
+ export declare const WS_OPEN = 1;
63
+ export declare const WS_CLOSING = 2;
64
+ export declare const WS_CLOSED = 3;
61
65
  //# sourceMappingURL=constants.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,eAAO,MAAM,WAAW,gBAAgB,CAAC;AACzC,eAAO,MAAM,SAAS,cAAc,CAAC;AACrC,eAAO,MAAM,MAAM,WAAW,CAAC;AAM/B;;;;GAIG;AACH,eAAO,MAAM,OAAO,YAAY,CAAC;AAEjC;;;;;;;;;;GAUG;AACH,eAAO,MAAM,aAAa,kBAAkB,CAAC;AAE7C;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,oBAAoB,CAAC;AAEjD;;;;;;;GAOG;AACH,eAAO,MAAM,OAAO,YAAY,CAAC;AAEjC;;;;;;;GAOG;AACH,eAAO,MAAM,MAAM,WAAW,CAAC;AAE/B;;;GAGG;AACH,eAAO,MAAM,IAAI,SAAS,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,eAAO,MAAM,WAAW,gBAAgB,CAAC;AACzC,eAAO,MAAM,SAAS,cAAc,CAAC;AACrC,eAAO,MAAM,MAAM,WAAW,CAAC;AAM/B;;;;GAIG;AACH,eAAO,MAAM,OAAO,YAAY,CAAC;AAEjC;;;;;;;;;;GAUG;AACH,eAAO,MAAM,aAAa,kBAAkB,CAAC;AAE7C;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,oBAAoB,CAAC;AAEjD;;;;;;;GAOG;AACH,eAAO,MAAM,OAAO,YAAY,CAAC;AAEjC;;;;;;;GAOG;AACH,eAAO,MAAM,MAAM,WAAW,CAAC;AAE/B;;;GAGG;AACH,eAAO,MAAM,IAAI,SAAS,CAAC;AAM3B,eAAO,MAAM,aAAa,IAAI,CAAC;AAC/B,eAAO,MAAM,OAAO,IAAI,CAAC;AACzB,eAAO,MAAM,UAAU,IAAI,CAAC;AAC5B,eAAO,MAAM,SAAS,IAAI,CAAC"}
package/dist/constants.js CHANGED
@@ -64,3 +64,10 @@ export const ZOMBIE = "zombie";
64
64
  * Final cleanup in progress, about to be fully deleted.
65
65
  */
66
66
  export const DEAD = "dead";
67
+ // ----------------------------
68
+ // WebSocket ready states
69
+ // ----------------------------
70
+ export const WS_CONNECTING = 0;
71
+ export const WS_OPEN = 1;
72
+ export const WS_CLOSING = 2;
73
+ export const WS_CLOSED = 3;
@@ -1,6 +1,16 @@
1
+ import { TypedEmitter } from "@kernl-sdk/shared";
1
2
  import { SharedProviderMetadata } from "../provider/index.js";
2
3
  import { RealtimeClientEvent, RealtimeServerEvent } from "./events.js";
3
- import { RealtimeConnectOptions, TransportStatus } from "./types.js";
4
+ import { RealtimeConnectOptions, RealtimeAuthenticateOptions, TransportStatus, ClientCredential } from "./types.js";
5
+ /**
6
+ * Events emitted by a realtime connection.
7
+ */
8
+ export type RealtimeConnectionEvents = {
9
+ event: [event: RealtimeServerEvent];
10
+ status: [status: TransportStatus];
11
+ error: [error: Error];
12
+ interrupted: [];
13
+ };
4
14
  /**
5
15
  * A realtime model that can establish bidirectional streaming connections.
6
16
  *
@@ -24,13 +34,22 @@ export interface RealtimeModel {
24
34
  * Establish a connection and return a connection instance.
25
35
  */
26
36
  connect(options?: RealtimeConnectOptions): Promise<RealtimeConnection>;
37
+ /**
38
+ * Create ephemeral credential for client-side connections.
39
+ *
40
+ * Call server-side where API key is available, pass result to client.
41
+ * Client then uses credential in connect() options.
42
+ *
43
+ * @param options - Provider-specific options (e.g., agentId for ElevenLabs)
44
+ */
45
+ authenticate(options?: RealtimeAuthenticateOptions): Promise<ClientCredential>;
27
46
  }
28
47
  /**
29
48
  * An active bidirectional connection to a realtime model.
30
49
  *
31
50
  * One connection per session. Providers implement this interface.
32
51
  */
33
- export interface RealtimeConnection {
52
+ export interface RealtimeConnection extends TypedEmitter<RealtimeConnectionEvents> {
34
53
  /**
35
54
  * Current connection status.
36
55
  */
@@ -69,15 +88,6 @@ export interface RealtimeConnection {
69
88
  * Convenience for sending response.cancel event.
70
89
  */
71
90
  interrupt(): void;
72
- on(event: "event", listener: (event: RealtimeServerEvent) => void): this;
73
- on(event: "status", listener: (status: TransportStatus) => void): this;
74
- on(event: "error", listener: (error: Error) => void): this;
75
- off(event: "event", listener: (event: RealtimeServerEvent) => void): this;
76
- off(event: "status", listener: (status: TransportStatus) => void): this;
77
- off(event: "error", listener: (error: Error) => void): this;
78
- once(event: "event", listener: (event: RealtimeServerEvent) => void): this;
79
- once(event: "status", listener: (status: TransportStatus) => void): this;
80
- once(event: "error", listener: (error: Error) => void): this;
81
91
  }
82
92
  /**
83
93
  * A transport factory for custom connection mechanisms (e.g., WebRTC).
@@ -1 +1 @@
1
- {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/realtime/model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AACpE,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAElE;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IAErB;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB;;OAEG;IACH,OAAO,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;CACxE;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IAEjC;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IAE/B;;OAEG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAElC;;OAEG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,sBAAsB,CAAC;IAEnD;;OAEG;IACH,IAAI,CAAC,KAAK,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAEvC;;OAEG;IACH,KAAK,IAAI,IAAI,CAAC;IAEd;;OAEG;IACH,IAAI,IAAI,IAAI,CAAC;IAEb;;OAEG;IACH,MAAM,IAAI,IAAI,CAAC;IAEf;;;OAGG;IACH,SAAS,IAAI,IAAI,CAAC;IAIlB,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,GAAG,IAAI,CAAC;IACzE,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,GAAG,IAAI,CAAC;IACvE,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI,CAAC;IAE3D,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,GAAG,IAAI,CAAC;IAC1E,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,GAAG,IAAI,CAAC;IACxE,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI,CAAC;IAE5D,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,GAAG,IAAI,CAAC;IAC3E,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,GAAG,IAAI,CAAC;IACzE,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI,CAAC;CAC9D;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAE/B;;OAEG;IACH,OAAO,CACL,KAAK,EAAE,aAAa,EACpB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,kBAAkB,CAAC,CAAC;CAChC"}
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/realtime/model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AACpE,OAAO,EACL,sBAAsB,EACtB,2BAA2B,EAC3B,eAAe,EACf,gBAAgB,EACjB,MAAM,SAAS,CAAC;AAEjB;;GAEG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACrC,KAAK,EAAE,CAAC,KAAK,EAAE,mBAAmB,CAAC,CAAC;IACpC,MAAM,EAAE,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAClC,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACtB,WAAW,EAAE,EAAE,CAAC;CACjB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IAErB;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB;;OAEG;IACH,OAAO,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAEvE;;;;;;;OAOG;IACH,YAAY,CACV,OAAO,CAAC,EAAE,2BAA2B,GACpC,OAAO,CAAC,gBAAgB,CAAC,CAAC;CAC9B;AAED;;;;GAIG;AACH,MAAM,WAAW,kBACf,SAAQ,YAAY,CAAC,wBAAwB,CAAC;IAC9C;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IAEjC;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IAE/B;;OAEG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAElC;;OAEG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,sBAAsB,CAAC;IAEnD;;OAEG;IACH,IAAI,CAAC,KAAK,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAEvC;;OAEG;IACH,KAAK,IAAI,IAAI,CAAC;IAEd;;OAEG;IACH,IAAI,IAAI,IAAI,CAAC;IAEb;;OAEG;IACH,MAAM,IAAI,IAAI,CAAC;IAEf;;;OAGG;IACH,SAAS,IAAI,IAAI,CAAC;CACnB;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAE/B;;OAEG;IACH,OAAO,CACL,KAAK,EAAE,aAAa,EACpB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,kBAAkB,CAAC,CAAC;CAChC"}
@@ -1,5 +1,37 @@
1
+ import { TypedEmitter } from "@kernl-sdk/shared";
1
2
  import { SharedProviderOptions } from "../provider/index.js";
2
3
  import { LanguageModelTool } from "../language-model/index.js";
4
+ /**
5
+ * Events emitted by a realtime channel.
6
+ */
7
+ export type RealtimeChannelEvents = {
8
+ audio: [audio: string];
9
+ commit: [];
10
+ interrupt: [];
11
+ };
12
+ /**
13
+ * Base interface for audio I/O channels.
14
+ *
15
+ * Channels bridge between audio sources (browser mic, Twilio, Discord)
16
+ * and the realtime session. They handle audio capture/playback and emit
17
+ * events that the session listens to.
18
+ */
19
+ export interface RealtimeChannel extends TypedEmitter<RealtimeChannelEvents> {
20
+ /**
21
+ * Send audio to be played/transmitted by the channel.
22
+ * Called by session when audio is received from the model.
23
+ */
24
+ sendAudio(audio: string): void;
25
+ /**
26
+ * Interrupt current audio playback.
27
+ * Called by session when response is cancelled.
28
+ */
29
+ interrupt(): void;
30
+ /**
31
+ * Clean up resources and close the channel.
32
+ */
33
+ close(): void;
34
+ }
3
35
  export interface RealtimeConnectOptions {
4
36
  /**
5
37
  * Initial session configuration.
@@ -17,6 +49,51 @@ export interface RealtimeConnectOptions {
17
49
  * Provider-specific options.
18
50
  */
19
51
  providerOptions?: SharedProviderOptions;
52
+ /**
53
+ * Ephemeral credential for client-side connections.
54
+ *
55
+ * Obtained from model.authenticate() on the server.
56
+ * When provided, used instead of the model's API key.
57
+ */
58
+ credential?: ClientCredential;
59
+ /**
60
+ * WebSocket constructor for browser/Node compatibility.
61
+ *
62
+ * Defaults to globalThis.WebSocket (available in browsers and Node 22+).
63
+ * For Node.js <22, provide the 'ws' package.
64
+ *
65
+ * @example
66
+ * ```ts
67
+ * import WebSocket from 'ws';
68
+ * await model.connect({ websocket: WebSocket });
69
+ * ```
70
+ */
71
+ websocket?: WebSocketConstructor;
72
+ }
73
+ /**
74
+ * Options for authenticating with a realtime provider.
75
+ *
76
+ * Provider-specific options can be added via extension.
77
+ */
78
+ export interface RealtimeAuthenticateOptions {
79
+ /**
80
+ * Agent ID for providers that use pre-configured agents (e.g., ElevenLabs).
81
+ */
82
+ agentId?: string;
83
+ }
84
+ /**
85
+ * WebSocket constructor type for cross-platform compatibility.
86
+ */
87
+ export type WebSocketConstructor = new (url: string | URL, protocols?: string | string[]) => WebSocketLike;
88
+ /**
89
+ * Minimal WebSocket interface matching the standard WebSocket API.
90
+ */
91
+ export interface WebSocketLike {
92
+ readonly readyState: number;
93
+ send(data: string | ArrayBuffer): void;
94
+ close(code?: number, reason?: string): void;
95
+ addEventListener(type: string, listener: (event: unknown) => void): void;
96
+ removeEventListener(type: string, listener: (event: unknown) => void): void;
20
97
  }
21
98
  /**
22
99
  * Configuration for a realtime session.
@@ -187,19 +264,10 @@ export interface RealtimeSession {
187
264
  /**
188
265
  * Error from a realtime session.
189
266
  */
190
- export interface RealtimeError {
191
- /**
192
- * Error code.
193
- */
194
- code: string;
195
- /**
196
- * Human-readable error message.
197
- */
198
- message: string;
199
- /**
200
- * Additional error details.
201
- */
202
- details?: Record<string, unknown>;
267
+ export declare class RealtimeError extends Error {
268
+ readonly code: string;
269
+ readonly details?: Record<string, unknown>;
270
+ constructor(code: string, message: string, details?: Record<string, unknown>);
203
271
  }
204
272
  /**
205
273
  * Token usage information for a response.
@@ -226,4 +294,21 @@ export type ResponseStatus = "completed" | "interrupted" | "cancelled" | "failed
226
294
  * Status of a realtime transport connection.
227
295
  */
228
296
  export type TransportStatus = "disconnected" | "connecting" | "connected" | "reconnecting" | "closed";
297
+ /**
298
+ * A client credential for browser-based realtime connections.
299
+ *
300
+ * Created server-side via model.authenticate(), passed to client
301
+ * for secure connection without exposing API keys.
302
+ */
303
+ export type ClientCredential = {
304
+ /** Ephemeral token for auth header (OpenAI style). */
305
+ readonly kind: "token";
306
+ token: string;
307
+ expiresAt: Date;
308
+ } | {
309
+ /** Signed URL to connect directly (ElevenLabs style). */
310
+ readonly kind: "url";
311
+ url: string;
312
+ expiresAt: Date;
313
+ };
229
314
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/realtime/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/realtime/types.ts"],"names":[],"mappings":"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"}
@@ -1 +1,13 @@
1
- export {};
1
+ /**
2
+ * Error from a realtime session.
3
+ */
4
+ export class RealtimeError extends Error {
5
+ code;
6
+ details;
7
+ constructor(code, message, details) {
8
+ super(message);
9
+ this.name = "RealtimeError";
10
+ this.code = code;
11
+ this.details = details;
12
+ }
13
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kernl-sdk/protocol",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "description": "Protocol specification for kernl",
5
5
  "keywords": [
6
6
  "kernl",
package/src/constants.ts CHANGED
@@ -73,3 +73,12 @@ export const ZOMBIE = "zombie";
73
73
  * Final cleanup in progress, about to be fully deleted.
74
74
  */
75
75
  export const DEAD = "dead";
76
+
77
+ // ----------------------------
78
+ // WebSocket ready states
79
+ // ----------------------------
80
+
81
+ export const WS_CONNECTING = 0;
82
+ export const WS_OPEN = 1;
83
+ export const WS_CLOSING = 2;
84
+ export const WS_CLOSED = 3;
@@ -1,6 +1,23 @@
1
+ import { TypedEmitter } from "@kernl-sdk/shared";
2
+
1
3
  import { SharedProviderMetadata } from "@/provider";
2
4
  import { RealtimeClientEvent, RealtimeServerEvent } from "./events";
3
- import { RealtimeConnectOptions, TransportStatus } from "./types";
5
+ import {
6
+ RealtimeConnectOptions,
7
+ RealtimeAuthenticateOptions,
8
+ TransportStatus,
9
+ ClientCredential,
10
+ } from "./types";
11
+
12
+ /**
13
+ * Events emitted by a realtime connection.
14
+ */
15
+ export type RealtimeConnectionEvents = {
16
+ event: [event: RealtimeServerEvent];
17
+ status: [status: TransportStatus];
18
+ error: [error: Error];
19
+ interrupted: [];
20
+ };
4
21
 
5
22
  /**
6
23
  * A realtime model that can establish bidirectional streaming connections.
@@ -28,6 +45,18 @@ export interface RealtimeModel {
28
45
  * Establish a connection and return a connection instance.
29
46
  */
30
47
  connect(options?: RealtimeConnectOptions): Promise<RealtimeConnection>;
48
+
49
+ /**
50
+ * Create ephemeral credential for client-side connections.
51
+ *
52
+ * Call server-side where API key is available, pass result to client.
53
+ * Client then uses credential in connect() options.
54
+ *
55
+ * @param options - Provider-specific options (e.g., agentId for ElevenLabs)
56
+ */
57
+ authenticate(
58
+ options?: RealtimeAuthenticateOptions,
59
+ ): Promise<ClientCredential>;
31
60
  }
32
61
 
33
62
  /**
@@ -35,7 +64,8 @@ export interface RealtimeModel {
35
64
  *
36
65
  * One connection per session. Providers implement this interface.
37
66
  */
38
- export interface RealtimeConnection {
67
+ export interface RealtimeConnection
68
+ extends TypedEmitter<RealtimeConnectionEvents> {
39
69
  /**
40
70
  * Current connection status.
41
71
  */
@@ -82,20 +112,6 @@ export interface RealtimeConnection {
82
112
  * Convenience for sending response.cancel event.
83
113
  */
84
114
  interrupt(): void;
85
-
86
- // --- event subscription ---
87
-
88
- on(event: "event", listener: (event: RealtimeServerEvent) => void): this;
89
- on(event: "status", listener: (status: TransportStatus) => void): this;
90
- on(event: "error", listener: (error: Error) => void): this;
91
-
92
- off(event: "event", listener: (event: RealtimeServerEvent) => void): this;
93
- off(event: "status", listener: (status: TransportStatus) => void): this;
94
- off(event: "error", listener: (error: Error) => void): this;
95
-
96
- once(event: "event", listener: (event: RealtimeServerEvent) => void): this;
97
- once(event: "status", listener: (status: TransportStatus) => void): this;
98
- once(event: "error", listener: (error: Error) => void): this;
99
115
  }
100
116
 
101
117
  /**
@@ -1,6 +1,42 @@
1
+ import { TypedEmitter } from "@kernl-sdk/shared";
1
2
  import { SharedProviderOptions } from "@/provider";
2
3
  import { LanguageModelTool } from "@/language-model";
3
4
 
5
+ /**
6
+ * Events emitted by a realtime channel.
7
+ */
8
+ export type RealtimeChannelEvents = {
9
+ audio: [audio: string];
10
+ commit: [];
11
+ interrupt: [];
12
+ };
13
+
14
+ /**
15
+ * Base interface for audio I/O channels.
16
+ *
17
+ * Channels bridge between audio sources (browser mic, Twilio, Discord)
18
+ * and the realtime session. They handle audio capture/playback and emit
19
+ * events that the session listens to.
20
+ */
21
+ export interface RealtimeChannel extends TypedEmitter<RealtimeChannelEvents> {
22
+ /**
23
+ * Send audio to be played/transmitted by the channel.
24
+ * Called by session when audio is received from the model.
25
+ */
26
+ sendAudio(audio: string): void;
27
+
28
+ /**
29
+ * Interrupt current audio playback.
30
+ * Called by session when response is cancelled.
31
+ */
32
+ interrupt(): void;
33
+
34
+ /**
35
+ * Clean up resources and close the channel.
36
+ */
37
+ close(): void;
38
+ }
39
+
4
40
  export interface RealtimeConnectOptions {
5
41
  /**
6
42
  * Initial session configuration.
@@ -21,6 +57,59 @@ export interface RealtimeConnectOptions {
21
57
  * Provider-specific options.
22
58
  */
23
59
  providerOptions?: SharedProviderOptions;
60
+
61
+ /**
62
+ * Ephemeral credential for client-side connections.
63
+ *
64
+ * Obtained from model.authenticate() on the server.
65
+ * When provided, used instead of the model's API key.
66
+ */
67
+ credential?: ClientCredential;
68
+
69
+ /**
70
+ * WebSocket constructor for browser/Node compatibility.
71
+ *
72
+ * Defaults to globalThis.WebSocket (available in browsers and Node 22+).
73
+ * For Node.js <22, provide the 'ws' package.
74
+ *
75
+ * @example
76
+ * ```ts
77
+ * import WebSocket from 'ws';
78
+ * await model.connect({ websocket: WebSocket });
79
+ * ```
80
+ */
81
+ websocket?: WebSocketConstructor;
82
+ }
83
+
84
+ /**
85
+ * Options for authenticating with a realtime provider.
86
+ *
87
+ * Provider-specific options can be added via extension.
88
+ */
89
+ export interface RealtimeAuthenticateOptions {
90
+ /**
91
+ * Agent ID for providers that use pre-configured agents (e.g., ElevenLabs).
92
+ */
93
+ agentId?: string;
94
+ }
95
+
96
+ /**
97
+ * WebSocket constructor type for cross-platform compatibility.
98
+ */
99
+ export type WebSocketConstructor = new (
100
+ url: string | URL,
101
+ protocols?: string | string[],
102
+ ) => WebSocketLike;
103
+
104
+ /**
105
+ * Minimal WebSocket interface matching the standard WebSocket API.
106
+ */
107
+ export interface WebSocketLike {
108
+ readonly readyState: number;
109
+ send(data: string | ArrayBuffer): void;
110
+ close(code?: number, reason?: string): void;
111
+ addEventListener(type: string, listener: (event: unknown) => void): void;
112
+ removeEventListener(type: string, listener: (event: unknown) => void): void;
24
113
  }
25
114
 
26
115
  /**
@@ -219,21 +308,16 @@ export interface RealtimeSession {
219
308
  /**
220
309
  * Error from a realtime session.
221
310
  */
222
- export interface RealtimeError {
223
- /**
224
- * Error code.
225
- */
226
- code: string;
227
-
228
- /**
229
- * Human-readable error message.
230
- */
231
- message: string;
232
-
233
- /**
234
- * Additional error details.
235
- */
236
- details?: Record<string, unknown>;
311
+ export class RealtimeError extends Error {
312
+ readonly code: string;
313
+ readonly details?: Record<string, unknown>;
314
+
315
+ constructor(code: string, message: string, details?: Record<string, unknown>) {
316
+ super(message);
317
+ this.name = "RealtimeError";
318
+ this.code = code;
319
+ this.details = details;
320
+ }
237
321
  }
238
322
 
239
323
  /**
@@ -274,3 +358,24 @@ export type TransportStatus =
274
358
  | "connected"
275
359
  | "reconnecting"
276
360
  | "closed";
361
+
362
+ /**
363
+ * A client credential for browser-based realtime connections.
364
+ *
365
+ * Created server-side via model.authenticate(), passed to client
366
+ * for secure connection without exposing API keys.
367
+ */
368
+ export type ClientCredential =
369
+ | {
370
+ /** Ephemeral token for auth header (OpenAI style). */
371
+ readonly kind: "token";
372
+ token: string;
373
+ expiresAt: Date;
374
+ }
375
+ | {
376
+ /** Signed URL to connect directly (ElevenLabs style). */
377
+ readonly kind: "url";
378
+ url: string;
379
+ expiresAt: Date;
380
+ };
381
+