@ariaflowagents/gemini-native-audio 0.9.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.
- package/README.md +104 -0
- package/dist/CallWorker.d.ts +56 -0
- package/dist/CallWorker.d.ts.map +1 -0
- package/dist/CallWorker.js +172 -0
- package/dist/CallWorker.js.map +1 -0
- package/dist/CapabilityCallWorker.d.ts +46 -0
- package/dist/CapabilityCallWorker.d.ts.map +1 -0
- package/dist/CapabilityCallWorker.js +319 -0
- package/dist/CapabilityCallWorker.js.map +1 -0
- package/dist/GeminiLiveSession.d.ts +86 -0
- package/dist/GeminiLiveSession.d.ts.map +1 -0
- package/dist/GeminiLiveSession.js +297 -0
- package/dist/GeminiLiveSession.js.map +1 -0
- package/dist/RealtimeCallWorker.d.ts +47 -0
- package/dist/RealtimeCallWorker.d.ts.map +1 -0
- package/dist/RealtimeCallWorker.js +55 -0
- package/dist/RealtimeCallWorker.js.map +1 -0
- package/dist/VoiceEngine.d.ts +67 -0
- package/dist/VoiceEngine.d.ts.map +1 -0
- package/dist/VoiceEngine.js +156 -0
- package/dist/VoiceEngine.js.map +1 -0
- package/dist/factories.d.ts +32 -0
- package/dist/factories.d.ts.map +1 -0
- package/dist/factories.js +43 -0
- package/dist/factories.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/openai/OpenAIRealtimeClient.d.ts +51 -0
- package/dist/openai/OpenAIRealtimeClient.d.ts.map +1 -0
- package/dist/openai/OpenAIRealtimeClient.js +327 -0
- package/dist/openai/OpenAIRealtimeClient.js.map +1 -0
- package/dist/openai/index.d.ts +3 -0
- package/dist/openai/index.d.ts.map +1 -0
- package/dist/openai/index.js +2 -0
- package/dist/openai/index.js.map +1 -0
- package/dist/schema-bridge.d.ts +14 -0
- package/dist/schema-bridge.d.ts.map +1 -0
- package/dist/schema-bridge.js +20 -0
- package/dist/schema-bridge.js.map +1 -0
- package/dist/types.d.ts +150 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +44 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { RealtimeAudioClient } from '@ariaflowagents/core/realtime';
|
|
2
|
+
import type { VoiceAgentConfig, GeminiConfig } from './types.js';
|
|
3
|
+
import type { OpenAIRealtimeClientConfig } from './openai/OpenAIRealtimeClient.js';
|
|
4
|
+
/**
|
|
5
|
+
* Create a Gemini model client factory for VoiceEngine.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* ```typescript
|
|
9
|
+
* const engine = new VoiceEngine({
|
|
10
|
+
* ...config,
|
|
11
|
+
* createModelClient: createGeminiClientFactory({ apiKey: '...' }),
|
|
12
|
+
* });
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export declare function createGeminiClientFactory(gemini: GeminiConfig): (agent: VoiceAgentConfig) => RealtimeAudioClient;
|
|
16
|
+
/**
|
|
17
|
+
* Create an OpenAI Realtime model client factory for VoiceEngine.
|
|
18
|
+
*
|
|
19
|
+
* Usage:
|
|
20
|
+
* ```typescript
|
|
21
|
+
* const engine = new VoiceEngine({
|
|
22
|
+
* ...config,
|
|
23
|
+
* createModelClient: createOpenAIClientFactory({ apiKey: '...' }),
|
|
24
|
+
* });
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* This plugs OpenAI Realtime into the same OrchestrationAuthority and
|
|
28
|
+
* RealtimeRuntime as Gemini — same hooks, same persistence, same
|
|
29
|
+
* extraction, same memory ingestion. Zero orchestration duplication.
|
|
30
|
+
*/
|
|
31
|
+
export declare function createOpenAIClientFactory(openai: OpenAIRealtimeClientConfig): (agent: VoiceAgentConfig) => RealtimeAudioClient;
|
|
32
|
+
//# sourceMappingURL=factories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factories.d.ts","sourceRoot":"","sources":["../src/factories.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACjE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,kCAAkC,CAAC;AAInF;;;;;;;;;;GAUG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,YAAY,GACnB,CAAC,KAAK,EAAE,gBAAgB,KAAK,mBAAmB,CAQlD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,0BAA0B,GACjC,CAAC,KAAK,EAAE,gBAAgB,KAAK,mBAAmB,CAIlD"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { GeminiLiveSession } from './GeminiLiveSession.js';
|
|
2
|
+
import { OpenAIRealtimeClient } from './openai/OpenAIRealtimeClient.js';
|
|
3
|
+
/**
|
|
4
|
+
* Create a Gemini model client factory for VoiceEngine.
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* ```typescript
|
|
8
|
+
* const engine = new VoiceEngine({
|
|
9
|
+
* ...config,
|
|
10
|
+
* createModelClient: createGeminiClientFactory({ apiKey: '...' }),
|
|
11
|
+
* });
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export function createGeminiClientFactory(gemini) {
|
|
15
|
+
return (agent) => {
|
|
16
|
+
return new GeminiLiveSession({
|
|
17
|
+
gemini,
|
|
18
|
+
agent,
|
|
19
|
+
onEvent: () => { }, // Events go through the on() interface
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Create an OpenAI Realtime model client factory for VoiceEngine.
|
|
25
|
+
*
|
|
26
|
+
* Usage:
|
|
27
|
+
* ```typescript
|
|
28
|
+
* const engine = new VoiceEngine({
|
|
29
|
+
* ...config,
|
|
30
|
+
* createModelClient: createOpenAIClientFactory({ apiKey: '...' }),
|
|
31
|
+
* });
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* This plugs OpenAI Realtime into the same OrchestrationAuthority and
|
|
35
|
+
* RealtimeRuntime as Gemini — same hooks, same persistence, same
|
|
36
|
+
* extraction, same memory ingestion. Zero orchestration duplication.
|
|
37
|
+
*/
|
|
38
|
+
export function createOpenAIClientFactory(openai) {
|
|
39
|
+
return (_agent) => {
|
|
40
|
+
return new OpenAIRealtimeClient(openai);
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=factories.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factories.js","sourceRoot":"","sources":["../src/factories.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AAExE;;;;;;;;;;GAUG;AACH,MAAM,UAAU,yBAAyB,CACvC,MAAoB;IAEpB,OAAO,CAAC,KAAuB,EAAE,EAAE;QACjC,OAAO,IAAI,iBAAiB,CAAC;YAC3B,MAAM;YACN,KAAK;YACL,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,uCAAuC;SAC3D,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,yBAAyB,CACvC,MAAkC;IAElC,OAAO,CAAC,MAAwB,EAAE,EAAE;QAClC,OAAO,IAAI,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC1C,CAAC,CAAC;AACJ,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { VoiceEngine, voiceAgentToCoreAgent } from './VoiceEngine.js';
|
|
2
|
+
export { RealtimeCallWorker } from './RealtimeCallWorker.js';
|
|
3
|
+
export type { ModelClientFactory } from './RealtimeCallWorker.js';
|
|
4
|
+
export { GeminiLiveSession } from './GeminiLiveSession.js';
|
|
5
|
+
export { OpenAIRealtimeClient } from './openai/index.js';
|
|
6
|
+
export { createGeminiClientFactory, createOpenAIClientFactory } from './factories.js';
|
|
7
|
+
export { CallWorker } from './CallWorker.js';
|
|
8
|
+
export { CapabilityCallWorker } from './CapabilityCallWorker.js';
|
|
9
|
+
export { toolSetToGeminiDeclarations } from './schema-bridge.js';
|
|
10
|
+
export type { VoiceEngineConfig, VoiceAgentConfig, VoiceToolDef, VoiceToolSet, GeminiConfig, TransportSession, AcceptCallParams, RealtimeEvent, WorkerLike, } from './types.js';
|
|
11
|
+
export type { GeminiFunctionDeclaration } from './schema-bridge.js';
|
|
12
|
+
export type { OpenAIRealtimeClientConfig } from './openai/index.js';
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,YAAY,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAGzD,OAAO,EAAE,yBAAyB,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAItF,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEjE,OAAO,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAC;AAEjE,YAAY,EACV,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,EACb,UAAU,GACX,MAAM,YAAY,CAAC;AAEpB,YAAY,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AACpE,YAAY,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { VoiceEngine, voiceAgentToCoreAgent } from './VoiceEngine.js';
|
|
2
|
+
export { RealtimeCallWorker } from './RealtimeCallWorker.js';
|
|
3
|
+
export { GeminiLiveSession } from './GeminiLiveSession.js';
|
|
4
|
+
export { OpenAIRealtimeClient } from './openai/index.js';
|
|
5
|
+
// Provider client factories — plug any provider into the same core boundary
|
|
6
|
+
export { createGeminiClientFactory, createOpenAIClientFactory } from './factories.js';
|
|
7
|
+
// Legacy workers — retained for backward compatibility.
|
|
8
|
+
// New code should use VoiceEngine which delegates to RealtimeRuntime.
|
|
9
|
+
export { CallWorker } from './CallWorker.js';
|
|
10
|
+
export { CapabilityCallWorker } from './CapabilityCallWorker.js';
|
|
11
|
+
export { toolSetToGeminiDeclarations } from './schema-bridge.js';
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAE7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAEzD,4EAA4E;AAC5E,OAAO,EAAE,yBAAyB,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAEtF,wDAAwD;AACxD,sEAAsE;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEjE,OAAO,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAIRealtimeClient — implements RealtimeAudioClient for OpenAI Realtime API.
|
|
3
|
+
*
|
|
4
|
+
* Key features:
|
|
5
|
+
* - WebSocket connection via `ws` package
|
|
6
|
+
* - Native G.711 μ-law (audio/pcmu) support — zero resampling for SIP/telephony
|
|
7
|
+
* - PCM16 support for non-telephony use
|
|
8
|
+
* - Session lifecycle: connect → session.created → session.update → session.updated
|
|
9
|
+
* - Tool calling: function_call_arguments.done → tool-call event → sendToolResponse
|
|
10
|
+
*
|
|
11
|
+
* Ported from research/sip-to-ai/app/ai/openai_realtime.py
|
|
12
|
+
*/
|
|
13
|
+
import type { RealtimeAudioClient, RealtimeSessionConfig, RealtimeToolResponse, RealtimeEventMap } from '@ariaflowagents/core/realtime';
|
|
14
|
+
export interface OpenAIRealtimeClientConfig {
|
|
15
|
+
apiKey: string;
|
|
16
|
+
/** OpenAI Realtime model. Default: 'gpt-realtime' */
|
|
17
|
+
model?: string;
|
|
18
|
+
}
|
|
19
|
+
export declare class OpenAIRealtimeClient implements RealtimeAudioClient {
|
|
20
|
+
private readonly apiKey;
|
|
21
|
+
private readonly defaultModel;
|
|
22
|
+
private ws;
|
|
23
|
+
private _connected;
|
|
24
|
+
private sessionConfig;
|
|
25
|
+
private listeners;
|
|
26
|
+
private sessionCreatedResolve;
|
|
27
|
+
private sessionUpdatedResolve;
|
|
28
|
+
constructor(config: OpenAIRealtimeClientConfig);
|
|
29
|
+
get connected(): boolean;
|
|
30
|
+
on<K extends keyof RealtimeEventMap>(event: K, handler: RealtimeEventMap[K]): void;
|
|
31
|
+
off<K extends keyof RealtimeEventMap>(event: K, handler: RealtimeEventMap[K]): void;
|
|
32
|
+
private emit;
|
|
33
|
+
connect(config: RealtimeSessionConfig): Promise<void>;
|
|
34
|
+
disconnect(): Promise<void>;
|
|
35
|
+
sendAudio(frame: Uint8Array): void;
|
|
36
|
+
sendToolResponse(responses: RealtimeToolResponse[]): void;
|
|
37
|
+
updateConfig(config: Partial<RealtimeSessionConfig>): Promise<void>;
|
|
38
|
+
ping(): Promise<boolean>;
|
|
39
|
+
private handleMessage;
|
|
40
|
+
private sendRaw;
|
|
41
|
+
/**
|
|
42
|
+
* Build a session.update message from a RealtimeSessionConfig.
|
|
43
|
+
*
|
|
44
|
+
* Uses the new OpenAI Realtime API schema (no OpenAI-Beta header required).
|
|
45
|
+
* Audio format:
|
|
46
|
+
* - 'pcmu' → audio/pcmu (G.711 μ-law, native 8kHz, zero-resample for SIP)
|
|
47
|
+
* - 'pcm16' → audio/pcm16 (PCM16 at configured sample rate)
|
|
48
|
+
*/
|
|
49
|
+
private buildSessionUpdate;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=OpenAIRealtimeClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OpenAIRealtimeClient.d.ts","sourceRoot":"","sources":["../../src/openai/OpenAIRealtimeClient.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EACV,mBAAmB,EACnB,qBAAqB,EACrB,oBAAoB,EACpB,gBAAgB,EACjB,MAAM,+BAA+B,CAAC;AAKvC,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,qDAAqD;IACrD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAkBD,qBAAa,oBAAqB,YAAW,mBAAmB;IAC9D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,aAAa,CAAsC;IAG3D,OAAO,CAAC,SAAS,CAA6E;IAG9F,OAAO,CAAC,qBAAqB,CAA6B;IAC1D,OAAO,CAAC,qBAAqB,CAA6B;gBAE9C,MAAM,EAAE,0BAA0B;IAO9C,IAAI,SAAS,IAAI,OAAO,CAEvB;IAID,EAAE,CAAC,CAAC,SAAS,MAAM,gBAAgB,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,IAAI;IAOlF,GAAG,CAAC,CAAC,SAAS,MAAM,gBAAgB,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,IAAI;IAInF,OAAO,CAAC,IAAI;IAaN,OAAO,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IA0ErD,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAmBjC,SAAS,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IASlC,gBAAgB,CAAC,SAAS,EAAE,oBAAoB,EAAE,GAAG,IAAI;IAqBnD,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,qBAAqB,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAuBnE,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC;IAe9B,OAAO,CAAC,aAAa;IAqFrB,OAAO,CAAC,OAAO;IASf;;;;;;;OAOG;IACH,OAAO,CAAC,kBAAkB;CAuC3B"}
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAIRealtimeClient — implements RealtimeAudioClient for OpenAI Realtime API.
|
|
3
|
+
*
|
|
4
|
+
* Key features:
|
|
5
|
+
* - WebSocket connection via `ws` package
|
|
6
|
+
* - Native G.711 μ-law (audio/pcmu) support — zero resampling for SIP/telephony
|
|
7
|
+
* - PCM16 support for non-telephony use
|
|
8
|
+
* - Session lifecycle: connect → session.created → session.update → session.updated
|
|
9
|
+
* - Tool calling: function_call_arguments.done → tool-call event → sendToolResponse
|
|
10
|
+
*
|
|
11
|
+
* Ported from research/sip-to-ai/app/ai/openai_realtime.py
|
|
12
|
+
*/
|
|
13
|
+
import WebSocket from 'ws';
|
|
14
|
+
// ─── Client ──────────────────────────────────────────────────────────────────
|
|
15
|
+
export class OpenAIRealtimeClient {
|
|
16
|
+
apiKey;
|
|
17
|
+
defaultModel;
|
|
18
|
+
ws = null;
|
|
19
|
+
_connected = false;
|
|
20
|
+
sessionConfig = null;
|
|
21
|
+
// Typed event listener registry
|
|
22
|
+
listeners = new Map();
|
|
23
|
+
// Promise resolvers for session lifecycle
|
|
24
|
+
sessionCreatedResolve = null;
|
|
25
|
+
sessionUpdatedResolve = null;
|
|
26
|
+
constructor(config) {
|
|
27
|
+
this.apiKey = config.apiKey;
|
|
28
|
+
this.defaultModel = config.model ?? 'gpt-realtime';
|
|
29
|
+
}
|
|
30
|
+
// ─── RealtimeAudioClient: connected ────────────────────────────────────────
|
|
31
|
+
get connected() {
|
|
32
|
+
return this._connected;
|
|
33
|
+
}
|
|
34
|
+
// ─── RealtimeAudioClient: on / off ─────────────────────────────────────────
|
|
35
|
+
on(event, handler) {
|
|
36
|
+
if (!this.listeners.has(event)) {
|
|
37
|
+
this.listeners.set(event, new Set());
|
|
38
|
+
}
|
|
39
|
+
this.listeners.get(event).add(handler);
|
|
40
|
+
}
|
|
41
|
+
off(event, handler) {
|
|
42
|
+
this.listeners.get(event)?.delete(handler);
|
|
43
|
+
}
|
|
44
|
+
emit(event, ...args) {
|
|
45
|
+
const handlers = this.listeners.get(event);
|
|
46
|
+
if (!handlers)
|
|
47
|
+
return;
|
|
48
|
+
for (const handler of handlers) {
|
|
49
|
+
handler(...args);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// ─── RealtimeAudioClient: connect ──────────────────────────────────────────
|
|
53
|
+
async connect(config) {
|
|
54
|
+
if (this._connected)
|
|
55
|
+
return;
|
|
56
|
+
this.sessionConfig = config;
|
|
57
|
+
const model = config.model ?? this.defaultModel;
|
|
58
|
+
const ws = new WebSocket(`wss://api.openai.com/v1/realtime?model=${model}`, {
|
|
59
|
+
headers: {
|
|
60
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
this.ws = ws;
|
|
64
|
+
// Register all handlers before waiting for open so no messages are missed.
|
|
65
|
+
ws.on('message', (data) => {
|
|
66
|
+
try {
|
|
67
|
+
this.handleMessage(JSON.parse(data.toString()));
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
console.error('[OpenAIRealtimeClient] Message parse error:', err);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
ws.on('close', () => {
|
|
74
|
+
this._connected = false;
|
|
75
|
+
this.emit('disconnected');
|
|
76
|
+
});
|
|
77
|
+
ws.on('error', (err) => {
|
|
78
|
+
console.error('[OpenAIRealtimeClient] WebSocket error:', err);
|
|
79
|
+
this.emit('error', err.message);
|
|
80
|
+
});
|
|
81
|
+
// Wait for the WebSocket to open.
|
|
82
|
+
await new Promise((resolve, reject) => {
|
|
83
|
+
const onOpen = () => { cleanup(); resolve(); };
|
|
84
|
+
const onError = (err) => { cleanup(); reject(err); };
|
|
85
|
+
const cleanup = () => { ws.off('open', onOpen); ws.off('error', onError); };
|
|
86
|
+
ws.once('open', onOpen);
|
|
87
|
+
ws.once('error', onError);
|
|
88
|
+
});
|
|
89
|
+
// Wait for session.created from OpenAI (signals model is ready to configure).
|
|
90
|
+
await new Promise((resolve, reject) => {
|
|
91
|
+
const timeout = setTimeout(() => reject(new Error('[OpenAIRealtimeClient] Timeout waiting for session.created')), 10_000);
|
|
92
|
+
this.sessionCreatedResolve = () => {
|
|
93
|
+
clearTimeout(timeout);
|
|
94
|
+
resolve();
|
|
95
|
+
};
|
|
96
|
+
});
|
|
97
|
+
// Send session.update with our config.
|
|
98
|
+
this.sendRaw(this.buildSessionUpdate(config));
|
|
99
|
+
// Wait for session.updated to confirm the config was applied.
|
|
100
|
+
await new Promise((resolve, reject) => {
|
|
101
|
+
const timeout = setTimeout(() => reject(new Error('[OpenAIRealtimeClient] Timeout waiting for session.updated')), 10_000);
|
|
102
|
+
this.sessionUpdatedResolve = () => {
|
|
103
|
+
clearTimeout(timeout);
|
|
104
|
+
resolve();
|
|
105
|
+
};
|
|
106
|
+
});
|
|
107
|
+
this._connected = true;
|
|
108
|
+
}
|
|
109
|
+
// ─── RealtimeAudioClient: disconnect ───────────────────────────────────────
|
|
110
|
+
async disconnect() {
|
|
111
|
+
if (!this._connected && !this.ws)
|
|
112
|
+
return;
|
|
113
|
+
this._connected = false;
|
|
114
|
+
this.sessionCreatedResolve = null;
|
|
115
|
+
this.sessionUpdatedResolve = null;
|
|
116
|
+
if (this.ws) {
|
|
117
|
+
try {
|
|
118
|
+
this.ws.close();
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
// Ignore close errors
|
|
122
|
+
}
|
|
123
|
+
this.ws = null;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// ─── RealtimeAudioClient: sendAudio ────────────────────────────────────────
|
|
127
|
+
sendAudio(frame) {
|
|
128
|
+
if (!this._connected || !this.ws)
|
|
129
|
+
return;
|
|
130
|
+
const base64 = Buffer.from(frame).toString('base64');
|
|
131
|
+
this.sendRaw({ type: 'input_audio_buffer.append', audio: base64 });
|
|
132
|
+
}
|
|
133
|
+
// ─── RealtimeAudioClient: sendToolResponse ─────────────────────────────────
|
|
134
|
+
sendToolResponse(responses) {
|
|
135
|
+
if (!this._connected || !this.ws)
|
|
136
|
+
return;
|
|
137
|
+
// Create a conversation item for each tool result.
|
|
138
|
+
for (const response of responses) {
|
|
139
|
+
this.sendRaw({
|
|
140
|
+
type: 'conversation.item.create',
|
|
141
|
+
item: {
|
|
142
|
+
type: 'function_call_output',
|
|
143
|
+
call_id: response.id,
|
|
144
|
+
output: JSON.stringify(response.output),
|
|
145
|
+
},
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
// Trigger model response continuation.
|
|
149
|
+
this.sendRaw({ type: 'response.create' });
|
|
150
|
+
}
|
|
151
|
+
// ─── RealtimeAudioClient: updateConfig ─────────────────────────────────────
|
|
152
|
+
async updateConfig(config) {
|
|
153
|
+
if (!this._connected || !this.ws)
|
|
154
|
+
return;
|
|
155
|
+
// Merge with existing session config.
|
|
156
|
+
this.sessionConfig = { ...this.sessionConfig, ...config };
|
|
157
|
+
this.sendRaw(this.buildSessionUpdate(this.sessionConfig));
|
|
158
|
+
// Wait for the updated acknowledgement.
|
|
159
|
+
await new Promise((resolve, reject) => {
|
|
160
|
+
const timeout = setTimeout(() => reject(new Error('[OpenAIRealtimeClient] Timeout waiting for session.updated')), 10_000);
|
|
161
|
+
this.sessionUpdatedResolve = () => {
|
|
162
|
+
clearTimeout(timeout);
|
|
163
|
+
resolve();
|
|
164
|
+
};
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
// ─── RealtimeAudioClient: ping ─────────────────────────────────────────────
|
|
168
|
+
async ping() {
|
|
169
|
+
if (!this._connected || !this.ws)
|
|
170
|
+
return false;
|
|
171
|
+
return new Promise((resolve) => {
|
|
172
|
+
const timeout = setTimeout(() => resolve(false), 5_000);
|
|
173
|
+
this.ws.once('pong', () => {
|
|
174
|
+
clearTimeout(timeout);
|
|
175
|
+
resolve(true);
|
|
176
|
+
});
|
|
177
|
+
this.ws.ping();
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
// ─── Private: message handling ─────────────────────────────────────────────
|
|
181
|
+
handleMessage(data) {
|
|
182
|
+
const type = data.type;
|
|
183
|
+
switch (type) {
|
|
184
|
+
case 'session.created':
|
|
185
|
+
this.sessionCreatedResolve?.();
|
|
186
|
+
this.sessionCreatedResolve = null;
|
|
187
|
+
break;
|
|
188
|
+
case 'session.updated':
|
|
189
|
+
this.sessionUpdatedResolve?.();
|
|
190
|
+
this.sessionUpdatedResolve = null;
|
|
191
|
+
break;
|
|
192
|
+
case 'response.output_audio.delta': {
|
|
193
|
+
// Audio chunk: base64-encoded G.711 μ-law or PCM16 from OpenAI.
|
|
194
|
+
const audioBase64 = data.delta;
|
|
195
|
+
if (audioBase64) {
|
|
196
|
+
const audioBytes = new Uint8Array(Buffer.from(audioBase64, 'base64'));
|
|
197
|
+
this.emit('audio', audioBytes);
|
|
198
|
+
}
|
|
199
|
+
break;
|
|
200
|
+
}
|
|
201
|
+
case 'conversation.item.input_audio_transcription.completed': {
|
|
202
|
+
// Final user speech transcription.
|
|
203
|
+
const transcript = data.transcript;
|
|
204
|
+
if (transcript) {
|
|
205
|
+
this.emit('transcript', transcript, 'user');
|
|
206
|
+
}
|
|
207
|
+
break;
|
|
208
|
+
}
|
|
209
|
+
case 'response.audio_transcript.done': {
|
|
210
|
+
// Final assistant speech transcription.
|
|
211
|
+
const transcript = data.transcript;
|
|
212
|
+
if (transcript) {
|
|
213
|
+
this.emit('transcript', transcript, 'assistant');
|
|
214
|
+
}
|
|
215
|
+
break;
|
|
216
|
+
}
|
|
217
|
+
case 'response.function_call_arguments.done': {
|
|
218
|
+
// Tool call from the model.
|
|
219
|
+
const callId = data.call_id;
|
|
220
|
+
const name = data.name;
|
|
221
|
+
const rawArgs = data.arguments;
|
|
222
|
+
let args = {};
|
|
223
|
+
try {
|
|
224
|
+
args = rawArgs ? JSON.parse(rawArgs) : {};
|
|
225
|
+
}
|
|
226
|
+
catch {
|
|
227
|
+
args = rawArgs;
|
|
228
|
+
}
|
|
229
|
+
this.emit('tool-call', callId, name, args);
|
|
230
|
+
break;
|
|
231
|
+
}
|
|
232
|
+
case 'response.done': {
|
|
233
|
+
// Model finished its response turn.
|
|
234
|
+
this.emit('turn-complete');
|
|
235
|
+
break;
|
|
236
|
+
}
|
|
237
|
+
case 'input_audio_buffer.speech_started': {
|
|
238
|
+
// User barge-in detected.
|
|
239
|
+
this.emit('interrupted');
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
case 'error': {
|
|
243
|
+
const errObj = data.error;
|
|
244
|
+
const message = errObj?.message ?? String(data.error ?? 'Unknown OpenAI error');
|
|
245
|
+
console.error('[OpenAIRealtimeClient] API error:', message);
|
|
246
|
+
this.emit('error', message);
|
|
247
|
+
break;
|
|
248
|
+
}
|
|
249
|
+
default:
|
|
250
|
+
// Silently ignore unhandled event types (e.g. rate_limits, response.created, etc.)
|
|
251
|
+
break;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
// ─── Private: helpers ──────────────────────────────────────────────────────
|
|
255
|
+
sendRaw(message) {
|
|
256
|
+
if (!this.ws)
|
|
257
|
+
return;
|
|
258
|
+
try {
|
|
259
|
+
this.ws.send(JSON.stringify(message));
|
|
260
|
+
}
|
|
261
|
+
catch (err) {
|
|
262
|
+
console.error('[OpenAIRealtimeClient] Send error:', err);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Build a session.update message from a RealtimeSessionConfig.
|
|
267
|
+
*
|
|
268
|
+
* Uses the new OpenAI Realtime API schema (no OpenAI-Beta header required).
|
|
269
|
+
* Audio format:
|
|
270
|
+
* - 'pcmu' → audio/pcmu (G.711 μ-law, native 8kHz, zero-resample for SIP)
|
|
271
|
+
* - 'pcm16' → audio/pcm16 (PCM16 at configured sample rate)
|
|
272
|
+
*/
|
|
273
|
+
buildSessionUpdate(config) {
|
|
274
|
+
const inputFormat = config.audio?.inputFormat ?? 'pcm16';
|
|
275
|
+
const outputFormat = config.audio?.outputFormat ?? 'pcm16';
|
|
276
|
+
const audioInputMime = formatToMime(inputFormat);
|
|
277
|
+
const audioOutputMime = formatToMime(outputFormat);
|
|
278
|
+
const tools = (config.tools ?? []).map(geminiDeclToOpenAITool);
|
|
279
|
+
const session = {
|
|
280
|
+
type: 'realtime',
|
|
281
|
+
model: config.model ?? this.defaultModel,
|
|
282
|
+
output_modalities: ['audio'],
|
|
283
|
+
audio: {
|
|
284
|
+
input: {
|
|
285
|
+
format: { type: audioInputMime },
|
|
286
|
+
transcription: { model: 'whisper-1' },
|
|
287
|
+
noise_reduction: { type: 'near_field' },
|
|
288
|
+
turn_detection: {
|
|
289
|
+
type: 'semantic_vad',
|
|
290
|
+
create_response: true,
|
|
291
|
+
eagerness: 'medium',
|
|
292
|
+
},
|
|
293
|
+
},
|
|
294
|
+
output: {
|
|
295
|
+
format: { type: audioOutputMime },
|
|
296
|
+
...(config.voice ? { voice: config.voice } : {}),
|
|
297
|
+
},
|
|
298
|
+
},
|
|
299
|
+
instructions: config.systemInstruction,
|
|
300
|
+
};
|
|
301
|
+
if (tools.length > 0) {
|
|
302
|
+
session.tools = tools;
|
|
303
|
+
session.tool_choice = 'auto';
|
|
304
|
+
}
|
|
305
|
+
return { type: 'session.update', session };
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
// ─── Internal helpers ────────────────────────────────────────────────────────
|
|
309
|
+
function formatToMime(format) {
|
|
310
|
+
switch (format) {
|
|
311
|
+
case 'pcmu': return 'audio/pcmu';
|
|
312
|
+
case 'pcma': return 'audio/pcma';
|
|
313
|
+
case 'pcm16':
|
|
314
|
+
default:
|
|
315
|
+
return 'audio/pcm16';
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
function geminiDeclToOpenAITool(decl) {
|
|
319
|
+
// GeminiFunctionDeclaration already carries parameters as a JSON Schema object.
|
|
320
|
+
return {
|
|
321
|
+
type: 'function',
|
|
322
|
+
name: decl.name,
|
|
323
|
+
description: decl.description,
|
|
324
|
+
parameters: decl.parameters,
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
//# sourceMappingURL=OpenAIRealtimeClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OpenAIRealtimeClient.js","sourceRoot":"","sources":["../../src/openai/OpenAIRealtimeClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/openai/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,YAAY,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/openai/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ToolSet } from '@ariaflowagents/core/types';
|
|
2
|
+
export interface GeminiFunctionDeclaration {
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
parameters: Record<string, unknown>;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Convert an AI SDK ToolSet to Gemini FunctionDeclarations.
|
|
9
|
+
* Gemini expects OpenAPI 3.x style JSON Schema for parameters.
|
|
10
|
+
*
|
|
11
|
+
* Reads `inputSchema` from each AI SDK tool definition.
|
|
12
|
+
*/
|
|
13
|
+
export declare function toolSetToGeminiDeclarations(tools: ToolSet): GeminiFunctionDeclaration[];
|
|
14
|
+
//# sourceMappingURL=schema-bridge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-bridge.d.ts","sourceRoot":"","sources":["../src/schema-bridge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAI1D,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,GAAG,yBAAyB,EAAE,CAYvF"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { zodToJsonSchema } from 'zod-to-json-schema';
|
|
2
|
+
/**
|
|
3
|
+
* Convert an AI SDK ToolSet to Gemini FunctionDeclarations.
|
|
4
|
+
* Gemini expects OpenAPI 3.x style JSON Schema for parameters.
|
|
5
|
+
*
|
|
6
|
+
* Reads `inputSchema` from each AI SDK tool definition.
|
|
7
|
+
*/
|
|
8
|
+
export function toolSetToGeminiDeclarations(tools) {
|
|
9
|
+
return Object.entries(tools).map(([name, toolDef]) => {
|
|
10
|
+
const schema = toolDef.inputSchema;
|
|
11
|
+
return {
|
|
12
|
+
name,
|
|
13
|
+
description: (toolDef.description ?? ''),
|
|
14
|
+
parameters: schema
|
|
15
|
+
? zodToJsonSchema(schema, { target: 'openApi3' })
|
|
16
|
+
: { type: 'object', properties: {} },
|
|
17
|
+
};
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=schema-bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-bridge.js","sourceRoot":"","sources":["../src/schema-bridge.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AASrD;;;;;GAKG;AACH,MAAM,UAAU,2BAA2B,CAAC,KAAc;IACxD,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,EAAE;QACnD,MAAM,MAAM,GAAI,OAAqC,CAAC,WAAW,CAAC;QAElE,OAAO;YACL,IAAI;YACJ,WAAW,EAAE,CAAE,OAAoC,CAAC,WAAW,IAAI,EAAE,CAAC;YACtE,UAAU,EAAE,MAAM;gBAChB,CAAC,CAAC,eAAe,CAAC,MAAoB,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,CAA4B;gBAC1F,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE;SACvC,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
|