@fabric-harness/sdk 1.9.0 → 1.10.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,330 @@
1
+ import { applyEstimatedCost } from './model-pricing.js';
2
+ import { toOpenAITool } from './model.js';
3
+ const DEFAULT_BASE = 'wss://api.openai.com/v1/realtime';
4
+ /**
5
+ * OpenAI Realtime voice provider. Connects via WebSocket; emits
6
+ * `audio_delta` / `text_delta` / `transcript` / `tool_call` / `response_done`
7
+ * events. No transitive dependency on `ws` — uses the global `WebSocket`
8
+ * available on Node 22+ and browsers.
9
+ *
10
+ * ```ts
11
+ * const provider = new OpenAIRealtimeVoiceProvider({ apiKey });
12
+ * const session = await provider.connect({
13
+ * instructions: 'You are a friendly intake agent.',
14
+ * voice: 'alloy',
15
+ * tools: [submitField],
16
+ * });
17
+ * for await (const event of session.events()) {
18
+ * if (event.type === 'audio_delta') speaker.write(event.audio);
19
+ * if (event.type === 'tool_call') {
20
+ * const output = await runTool(event.name, event.input);
21
+ * await session.submitToolResult({ id: event.id, output });
22
+ * }
23
+ * if (event.type === 'response_done') break;
24
+ * }
25
+ * ```
26
+ */
27
+ export class OpenAIRealtimeVoiceProvider {
28
+ name;
29
+ apiKey;
30
+ model;
31
+ baseUrl;
32
+ extraHeaders;
33
+ constructor(options) {
34
+ if (!options.apiKey)
35
+ throw new Error('OpenAIRealtimeVoiceProvider: apiKey is required.');
36
+ this.apiKey = options.apiKey;
37
+ this.model = options.model ?? 'gpt-4o-realtime-preview';
38
+ this.baseUrl = options.baseUrl ?? DEFAULT_BASE;
39
+ this.name = options.name ?? 'openai-realtime';
40
+ this.extraHeaders = options.headers ?? {};
41
+ }
42
+ async connect(options = {}) {
43
+ const url = `${this.baseUrl}?model=${encodeURIComponent(this.model)}`;
44
+ const ws = await openWebSocket(url, this.apiKey, this.extraHeaders);
45
+ return new RealtimeVoiceSession(ws, this.model, options);
46
+ }
47
+ }
48
+ async function openWebSocket(url, apiKey, headers) {
49
+ const WebSocketImpl = globalThis.WebSocket;
50
+ if (!WebSocketImpl) {
51
+ throw new Error('OpenAIRealtimeVoiceProvider: global WebSocket not available. Use Node 22+ or polyfill.');
52
+ }
53
+ // Node's WebSocket accepts `headers` via the second argument's options bag
54
+ // (non-standard but widely supported); browsers ignore options.
55
+ const ws = new WebSocketImpl(url, {
56
+ headers: {
57
+ Authorization: `Bearer ${apiKey}`,
58
+ 'OpenAI-Beta': 'realtime=v1',
59
+ ...headers,
60
+ },
61
+ });
62
+ // Wait for the connection to open so subsequent `send` calls succeed.
63
+ await new Promise((resolve, reject) => {
64
+ const onOpen = () => { cleanup(); resolve(); };
65
+ const onError = (ev) => { cleanup(); reject(toError(ev, 'WebSocket open failed')); };
66
+ const cleanup = () => {
67
+ // No removeEventListener on the structural type; rely on once-firing semantics.
68
+ };
69
+ ws.addEventListener('open', onOpen);
70
+ ws.addEventListener('error', onError);
71
+ });
72
+ return ws;
73
+ }
74
+ function toError(value, fallback) {
75
+ if (value instanceof Error)
76
+ return value;
77
+ if (value && typeof value === 'object' && 'message' in value) {
78
+ return new Error(String(value.message));
79
+ }
80
+ return new Error(fallback);
81
+ }
82
+ /** Base64-encode a Uint8Array. Works on Node and browsers. */
83
+ function bytesToBase64(bytes) {
84
+ if (typeof Buffer !== 'undefined')
85
+ return Buffer.from(bytes).toString('base64');
86
+ let binary = '';
87
+ for (let i = 0; i < bytes.byteLength; i += 1)
88
+ binary += String.fromCharCode(bytes[i]);
89
+ return btoa(binary);
90
+ }
91
+ /** Decode a base64 string to a Uint8Array. */
92
+ function base64ToBytes(value) {
93
+ if (typeof Buffer !== 'undefined')
94
+ return new Uint8Array(Buffer.from(value, 'base64'));
95
+ const bin = atob(value);
96
+ const out = new Uint8Array(bin.length);
97
+ for (let i = 0; i < bin.length; i += 1)
98
+ out[i] = bin.charCodeAt(i);
99
+ return out;
100
+ }
101
+ class RealtimeVoiceSession {
102
+ ws;
103
+ modelRef;
104
+ queue = [];
105
+ waiters = [];
106
+ closed = false;
107
+ modelHint;
108
+ constructor(ws, model, options) {
109
+ this.ws = ws;
110
+ this.modelRef = `openai/${model}`;
111
+ ws.addEventListener('message', (ev) => this.onMessage(ev.data));
112
+ ws.addEventListener('close', () => this.fail({ type: 'session_open' }, true));
113
+ ws.addEventListener('error', (ev) => this.push({ type: 'error', message: toError(ev, 'WebSocket error').message }));
114
+ // Send the initial session.update.
115
+ const audioFormat = options.audioFormat ?? 'pcm16';
116
+ const sessionUpdate = {
117
+ type: 'session.update',
118
+ session: {
119
+ ...(options.instructions ? { instructions: options.instructions } : {}),
120
+ ...(options.voice ? { voice: options.voice } : {}),
121
+ input_audio_format: audioFormat,
122
+ output_audio_format: audioFormat,
123
+ turn_detection: options.turnDetection === 'none' ? null : { type: 'server_vad' },
124
+ ...(options.tools && options.tools.length > 0 ? { tools: options.tools.map(toolToRealtime) } : {}),
125
+ },
126
+ };
127
+ ws.send(JSON.stringify(sessionUpdate));
128
+ this.push({ type: 'session_open' });
129
+ if (options.signal) {
130
+ if (options.signal.aborted)
131
+ void this.close();
132
+ else
133
+ options.signal.addEventListener('abort', () => void this.close(), { once: true });
134
+ }
135
+ }
136
+ async sendAudio(frame) {
137
+ if (this.closed)
138
+ throw new Error('Voice session closed');
139
+ this.ws.send(JSON.stringify({ type: 'input_audio_buffer.append', audio: bytesToBase64(frame) }));
140
+ }
141
+ async sendText(text) {
142
+ if (this.closed)
143
+ throw new Error('Voice session closed');
144
+ this.ws.send(JSON.stringify({
145
+ type: 'conversation.item.create',
146
+ item: { type: 'message', role: 'user', content: [{ type: 'input_text', text }] },
147
+ }));
148
+ this.ws.send(JSON.stringify({ type: 'response.create' }));
149
+ }
150
+ async submitToolResult(input) {
151
+ if (this.closed)
152
+ throw new Error('Voice session closed');
153
+ this.ws.send(JSON.stringify({
154
+ type: 'conversation.item.create',
155
+ item: {
156
+ type: 'function_call_output',
157
+ call_id: input.id,
158
+ output: typeof input.output === 'string' ? input.output : JSON.stringify(input.output),
159
+ },
160
+ }));
161
+ this.ws.send(JSON.stringify({ type: 'response.create' }));
162
+ }
163
+ async cancelResponse() {
164
+ if (this.closed)
165
+ return;
166
+ this.ws.send(JSON.stringify({ type: 'response.cancel' }));
167
+ }
168
+ events() {
169
+ return {
170
+ [Symbol.asyncIterator]: () => ({
171
+ next: () => this.next(),
172
+ return: async () => {
173
+ await this.close();
174
+ return { value: undefined, done: true };
175
+ },
176
+ }),
177
+ };
178
+ }
179
+ async close() {
180
+ if (this.closed)
181
+ return;
182
+ this.closed = true;
183
+ try {
184
+ this.ws.close();
185
+ }
186
+ catch { }
187
+ while (this.waiters.length > 0) {
188
+ const waiter = this.waiters.shift();
189
+ waiter?.({ value: undefined, done: true });
190
+ }
191
+ }
192
+ next() {
193
+ if (this.queue.length > 0) {
194
+ return Promise.resolve({ value: this.queue.shift(), done: false });
195
+ }
196
+ if (this.closed)
197
+ return Promise.resolve({ value: undefined, done: true });
198
+ return new Promise((resolve) => this.waiters.push(resolve));
199
+ }
200
+ push(event) {
201
+ if (this.closed)
202
+ return;
203
+ const waiter = this.waiters.shift();
204
+ if (waiter)
205
+ waiter({ value: event, done: false });
206
+ else
207
+ this.queue.push(event);
208
+ }
209
+ fail(_event, _close) {
210
+ void this.close();
211
+ }
212
+ onMessage(raw) {
213
+ let payload;
214
+ try {
215
+ const text = typeof raw === 'string' ? raw : (raw && typeof raw === 'object' && 'toString' in raw)
216
+ ? String(raw)
217
+ : '';
218
+ payload = JSON.parse(text);
219
+ }
220
+ catch {
221
+ return;
222
+ }
223
+ const type = String(payload.type ?? '');
224
+ switch (type) {
225
+ case 'session.created':
226
+ case 'session.updated': {
227
+ const session = payload.session;
228
+ if (session?.model)
229
+ this.modelHint = session.model;
230
+ return;
231
+ }
232
+ case 'response.audio.delta': {
233
+ const audio = typeof payload.delta === 'string' ? base64ToBytes(payload.delta) : undefined;
234
+ if (audio)
235
+ this.push({ type: 'audio_delta', audio });
236
+ return;
237
+ }
238
+ case 'response.audio_transcript.delta': {
239
+ const delta = typeof payload.delta === 'string' ? payload.delta : '';
240
+ if (delta)
241
+ this.push({ type: 'text_delta', delta, role: 'assistant' });
242
+ return;
243
+ }
244
+ case 'response.audio_transcript.done': {
245
+ const text = typeof payload.transcript === 'string' ? payload.transcript : '';
246
+ if (text)
247
+ this.push({ type: 'transcript', text, role: 'assistant' });
248
+ return;
249
+ }
250
+ case 'conversation.item.input_audio_transcription.completed': {
251
+ const text = typeof payload.transcript === 'string' ? payload.transcript : '';
252
+ if (text)
253
+ this.push({ type: 'transcript', text, role: 'user' });
254
+ return;
255
+ }
256
+ case 'response.function_call_arguments.done': {
257
+ const id = String(payload.call_id ?? '');
258
+ const name = String(payload.name ?? '');
259
+ const args = typeof payload.arguments === 'string' ? safeJson(payload.arguments) : payload.arguments;
260
+ if (id && name)
261
+ this.push({ type: 'tool_call', id, name, input: args });
262
+ return;
263
+ }
264
+ case 'response.done': {
265
+ const usage = parseRealtimeUsage(payload);
266
+ const modelKey = this.modelHint ? `openai/${this.modelHint}` : this.modelRef;
267
+ if (usage)
268
+ applyEstimatedCost(modelKey, usage);
269
+ this.push({ type: 'response_done', ...(usage ? { usage } : {}) });
270
+ return;
271
+ }
272
+ case 'error': {
273
+ const message = typeof payload.error?.message === 'string'
274
+ ? String(payload.error.message)
275
+ : 'Realtime error';
276
+ this.push({ type: 'error', message });
277
+ return;
278
+ }
279
+ default:
280
+ return;
281
+ }
282
+ }
283
+ }
284
+ function safeJson(value) {
285
+ try {
286
+ return JSON.parse(value);
287
+ }
288
+ catch {
289
+ return value;
290
+ }
291
+ }
292
+ function toolToRealtime(tool) {
293
+ // toOpenAITool returns { type: 'function', function: {...} }.
294
+ // Realtime wants { type: 'function', name, description, parameters }.
295
+ const wrapped = toOpenAITool({
296
+ name: tool.name,
297
+ ...(tool.description !== undefined ? { description: tool.description } : {}),
298
+ ...(tool.inputSchema !== undefined ? { inputSchema: tool.inputSchema } : {}),
299
+ });
300
+ const fn = wrapped.function ?? {};
301
+ return {
302
+ type: 'function',
303
+ name: fn.name ?? tool.name,
304
+ description: fn.description ?? '',
305
+ parameters: fn.parameters ?? { type: 'object', properties: {}, required: [], additionalProperties: false },
306
+ };
307
+ }
308
+ function parseRealtimeUsage(payload) {
309
+ const responseObj = payload.response;
310
+ const usage = (responseObj?.usage ?? payload.usage);
311
+ if (!usage)
312
+ return undefined;
313
+ const inputDetails = usage.input_token_details;
314
+ const outputDetails = usage.output_token_details;
315
+ const result = {};
316
+ if (typeof usage.input_tokens === 'number')
317
+ result.inputTokens = usage.input_tokens;
318
+ if (typeof usage.output_tokens === 'number')
319
+ result.outputTokens = usage.output_tokens;
320
+ if (typeof usage.total_tokens === 'number')
321
+ result.totalTokens = usage.total_tokens;
322
+ if (typeof inputDetails?.audio_tokens === 'number')
323
+ result.audioInputTokens = inputDetails.audio_tokens;
324
+ if (typeof outputDetails?.audio_tokens === 'number')
325
+ result.audioOutputTokens = outputDetails.audio_tokens;
326
+ if (typeof inputDetails?.cached_tokens === 'number')
327
+ result.cachedInputTokens = inputDetails.cached_tokens;
328
+ return result;
329
+ }
330
+ //# sourceMappingURL=voice-openai-realtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voice-openai-realtime.js","sourceRoot":"","sources":["../src/voice-openai-realtime.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,90 @@
1
+ import type { ModelUsage } from './model.js';
2
+ import type { ToolDef } from './tools.js';
3
+ /**
4
+ * Bidirectional voice / audio streaming surface. fabric-harness ships an
5
+ * OpenAI Realtime implementation; bring-your-own-vendor for Anthropic /
6
+ * Gemini Live / on-prem TTS+ASR pipelines.
7
+ *
8
+ * Audio frames flow in raw bytes — the standard format is PCM 16-bit
9
+ * little-endian at 24kHz mono (OpenAI Realtime default). Telephony
10
+ * bridges (Twilio Media Streams μ-law 8kHz, etc.) resample at the edge.
11
+ *
12
+ * Tool execution is the *caller's* responsibility: a `tool_call` event
13
+ * surfaces, the host code runs the tool through whatever governance gates
14
+ * apply (approvals, cost caps, rate limits), then calls
15
+ * `submitToolResult({ id, output })`. Voice sessions deliberately don't
16
+ * own the loop machinery — this keeps the audio path lean and lets users
17
+ * apply the v1-era policy primitives unchanged.
18
+ */
19
+ export type VoiceAudioFormat = 'pcm16' | 'g711_ulaw' | 'g711_alaw';
20
+ export interface VoiceConnectOptions {
21
+ /** Initial system instructions / persona. */
22
+ instructions?: string;
23
+ /** Voice timbre id (provider-specific, e.g. 'alloy', 'nova', 'verse'). */
24
+ voice?: string;
25
+ /** Audio format used on both directions. Default 'pcm16' at 24kHz mono. */
26
+ audioFormat?: VoiceAudioFormat;
27
+ /** Tools the model can call. Same shape as session.prompt() tools. */
28
+ tools?: ToolDef[];
29
+ /** Turn-detection mode (provider-specific). Default 'server_vad'. */
30
+ turnDetection?: 'server_vad' | 'none';
31
+ /** Sample rate hint for the provider. Default 24000 (PCM16). */
32
+ sampleRate?: number;
33
+ /** Abort signal — closes the session when fired. */
34
+ signal?: AbortSignal;
35
+ }
36
+ /**
37
+ * Events streamed from a `VoiceSession`. `audio_delta` carries raw audio
38
+ * bytes; `text_delta` and `transcript` carry text; `tool_call` and
39
+ * `response_done` mark structured boundaries; `error` is fatal.
40
+ */
41
+ export type VoiceEvent = {
42
+ type: 'session_open';
43
+ } | {
44
+ type: 'audio_delta';
45
+ audio: Uint8Array;
46
+ } | {
47
+ type: 'text_delta';
48
+ delta: string;
49
+ role: 'assistant' | 'user';
50
+ } | {
51
+ type: 'transcript';
52
+ text: string;
53
+ role: 'assistant' | 'user';
54
+ } | {
55
+ type: 'tool_call';
56
+ id: string;
57
+ name: string;
58
+ input: unknown;
59
+ } | {
60
+ type: 'response_done';
61
+ usage?: ModelUsage;
62
+ } | {
63
+ type: 'error';
64
+ message: string;
65
+ };
66
+ export interface VoiceToolResultInput {
67
+ /** Tool-call id from the matching `tool_call` event. */
68
+ id: string;
69
+ /** JSON-serializable output — stringified before sending. */
70
+ output: unknown;
71
+ }
72
+ export interface VoiceSession {
73
+ /** Append a raw audio frame. Format matches `VoiceConnectOptions.audioFormat`. */
74
+ sendAudio(frame: Uint8Array): Promise<void>;
75
+ /** Send a text turn (the model responds with audio + text). */
76
+ sendText(text: string): Promise<void>;
77
+ /** Submit a tool-call result back to the model after a `tool_call` event. */
78
+ submitToolResult(input: VoiceToolResultInput): Promise<void>;
79
+ /** Cancel the in-progress response (barge-in). */
80
+ cancelResponse(): Promise<void>;
81
+ /** Async iterable of events. Closes when the session ends or aborts. */
82
+ events(): AsyncIterable<VoiceEvent>;
83
+ /** Tear down the underlying connection. */
84
+ close(): Promise<void>;
85
+ }
86
+ export interface VoiceProvider {
87
+ name: string;
88
+ connect(options: VoiceConnectOptions): Promise<VoiceSession>;
89
+ }
90
+ //# sourceMappingURL=voice.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voice.d.ts","sourceRoot":"","sources":["../src/voice.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,WAAW,GAAG,WAAW,CAAC;AAEnE,MAAM,WAAW,mBAAmB;IAClC,6CAA6C;IAC7C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0EAA0E;IAC1E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,WAAW,CAAC,EAAE,gBAAgB,CAAC;IAC/B,sEAAsE;IACtE,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC;IAClB,qEAAqE;IACrE,aAAa,CAAC,EAAE,YAAY,GAAG,MAAM,CAAC;IACtC,gEAAgE;IAChE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oDAAoD;IACpD,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE,GACxB;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,KAAK,EAAE,UAAU,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,WAAW,GAAG,MAAM,CAAA;CAAE,GACjE;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,WAAW,GAAG,MAAM,CAAA;CAAE,GAChE;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAC/D;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,KAAK,CAAC,EAAE,UAAU,CAAA;CAAE,GAC7C;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvC,MAAM,WAAW,oBAAoB;IACnC,wDAAwD;IACxD,EAAE,EAAE,MAAM,CAAC;IACX,6DAA6D;IAC7D,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,kFAAkF;IAClF,SAAS,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,+DAA+D;IAC/D,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,6EAA6E;IAC7E,gBAAgB,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7D,kDAAkD;IAClD,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAChC,wEAAwE;IACxE,MAAM,IAAI,aAAa,CAAC,UAAU,CAAC,CAAC;IACpC,2CAA2C;IAC3C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CAC9D"}
package/dist/voice.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=voice.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voice.js","sourceRoot":"","sources":["../src/voice.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fabric-harness/sdk",
3
- "version": "1.9.0",
3
+ "version": "1.10.0",
4
4
  "description": "Headless TypeScript framework for building durable, deployable autonomous agents — core SDK.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Fabric",