@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.
Files changed (46) hide show
  1. package/README.md +104 -0
  2. package/dist/CallWorker.d.ts +56 -0
  3. package/dist/CallWorker.d.ts.map +1 -0
  4. package/dist/CallWorker.js +172 -0
  5. package/dist/CallWorker.js.map +1 -0
  6. package/dist/CapabilityCallWorker.d.ts +46 -0
  7. package/dist/CapabilityCallWorker.d.ts.map +1 -0
  8. package/dist/CapabilityCallWorker.js +319 -0
  9. package/dist/CapabilityCallWorker.js.map +1 -0
  10. package/dist/GeminiLiveSession.d.ts +86 -0
  11. package/dist/GeminiLiveSession.d.ts.map +1 -0
  12. package/dist/GeminiLiveSession.js +297 -0
  13. package/dist/GeminiLiveSession.js.map +1 -0
  14. package/dist/RealtimeCallWorker.d.ts +47 -0
  15. package/dist/RealtimeCallWorker.d.ts.map +1 -0
  16. package/dist/RealtimeCallWorker.js +55 -0
  17. package/dist/RealtimeCallWorker.js.map +1 -0
  18. package/dist/VoiceEngine.d.ts +67 -0
  19. package/dist/VoiceEngine.d.ts.map +1 -0
  20. package/dist/VoiceEngine.js +156 -0
  21. package/dist/VoiceEngine.js.map +1 -0
  22. package/dist/factories.d.ts +32 -0
  23. package/dist/factories.d.ts.map +1 -0
  24. package/dist/factories.js +43 -0
  25. package/dist/factories.js.map +1 -0
  26. package/dist/index.d.ts +13 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +12 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/openai/OpenAIRealtimeClient.d.ts +51 -0
  31. package/dist/openai/OpenAIRealtimeClient.d.ts.map +1 -0
  32. package/dist/openai/OpenAIRealtimeClient.js +327 -0
  33. package/dist/openai/OpenAIRealtimeClient.js.map +1 -0
  34. package/dist/openai/index.d.ts +3 -0
  35. package/dist/openai/index.d.ts.map +1 -0
  36. package/dist/openai/index.js +2 -0
  37. package/dist/openai/index.js.map +1 -0
  38. package/dist/schema-bridge.d.ts +14 -0
  39. package/dist/schema-bridge.d.ts.map +1 -0
  40. package/dist/schema-bridge.js +20 -0
  41. package/dist/schema-bridge.js.map +1 -0
  42. package/dist/types.d.ts +150 -0
  43. package/dist/types.d.ts.map +1 -0
  44. package/dist/types.js +2 -0
  45. package/dist/types.js.map +1 -0
  46. package/package.json +44 -0
@@ -0,0 +1,319 @@
1
+ import { CapabilityHost, FlowCapability, toGeminiDeclarations, DefaultLivePromptAssembler, } from '@ariaflowagents/core/capabilities';
2
+ import { GeminiLiveSession } from './GeminiLiveSession.js';
3
+ import { z } from 'zod';
4
+ // ─── CapabilityCallWorker ─────────────────────────────────────────────────────
5
+ /**
6
+ * Flow-aware variant of CallWorker.
7
+ *
8
+ * Builds a `CapabilityHost` from the agent config and routes every tool result
9
+ * through `host.processToolResult()`. This enables:
10
+ * - Flow node transitions → Gemini session reconfigure with updated prompt/tools
11
+ * - Handoffs → call stop + upstream notification
12
+ * - End signals → call stop
13
+ * - Extraction → data merge, continue conversation
14
+ *
15
+ * Use when `VoiceAgentConfig.flow` is set. For flat tool-only agents, the
16
+ * regular `CallWorker` is lighter and equivalent.
17
+ */
18
+ export class CapabilityCallWorker {
19
+ config;
20
+ geminiSession;
21
+ host;
22
+ promptAssembler;
23
+ session = null;
24
+ abortController = new AbortController();
25
+ constructor(config) {
26
+ this.config = config;
27
+ // Build CapabilityHost synchronously — no async needed here.
28
+ this.host = this.buildHost(config.agent);
29
+ // Use injected assembler or default. The assembler is the PORT that
30
+ // bridges CapabilityHost sections with runtime context (memory, policies,
31
+ // voice rules) into a prompt structured for audio-native models.
32
+ this.promptAssembler = config.promptAssembler ?? new DefaultLivePromptAssembler();
33
+ // Derive initial system prompt and tools from the host via the assembler.
34
+ const basePrompt = resolveAgentPrompt(config.agent);
35
+ const systemInstruction = this.promptAssembler.assembleSync({
36
+ host: this.host,
37
+ basePrompt,
38
+ });
39
+ const tools = toGeminiDeclarations(this.host.getAllTools());
40
+ this.geminiSession = new GeminiLiveSession({
41
+ gemini: config.gemini,
42
+ agent: config.agent,
43
+ onEvent: (event) => this.handleGeminiEvent(event),
44
+ overrides: { systemInstruction, tools },
45
+ });
46
+ // Baseline: capability host is now in sync with the session config.
47
+ this.host.markConfigured();
48
+ }
49
+ get callId() {
50
+ return this.config.callId;
51
+ }
52
+ /**
53
+ * Start the call: load session, connect to Gemini with capability config, wire audio.
54
+ */
55
+ async start() {
56
+ const { conversationState, sessionId, userId, agentState, agent, transport } = this.config;
57
+ this.session = await conversationState.load(sessionId, userId);
58
+ agentState.setActiveAgent(this.session, agent.id);
59
+ conversationState.bumpSessionTurn(this.session);
60
+ await this.geminiSession.connect();
61
+ transport.onAudio((data) => {
62
+ if (this.abortController.signal.aborted)
63
+ return;
64
+ this.geminiSession.sendAudio(data);
65
+ });
66
+ transport.onClose(() => {
67
+ this.stop();
68
+ });
69
+ }
70
+ /**
71
+ * Stop the call: disconnect Gemini, save session, close transport.
72
+ */
73
+ async stop() {
74
+ this.abortController.abort();
75
+ await this.geminiSession.disconnect();
76
+ if (this.session) {
77
+ this.config.eventLog.cleanup(this.session);
78
+ await this.config.conversationState.save(this.session);
79
+ }
80
+ try {
81
+ this.config.transport.close();
82
+ }
83
+ catch {
84
+ // Ignore transport close errors
85
+ }
86
+ }
87
+ // --- Private: Gemini event handling ---
88
+ handleGeminiEvent(event) {
89
+ switch (event.type) {
90
+ case 'audio':
91
+ this.config.transport.sendAudio(event.data);
92
+ break;
93
+ case 'transcript':
94
+ if (this.session && event.role === 'user') {
95
+ this.config.conversationState.appendUserMessage(this.session, event.text);
96
+ }
97
+ else if (this.session && event.role === 'assistant') {
98
+ this.config.conversationState.appendAssistantMessage(this.session, event.text);
99
+ }
100
+ break;
101
+ case 'tool-call':
102
+ this.handleToolCall(event.id, event.name, event.args).catch((err) => {
103
+ console.error(`[CapabilityCallWorker] Tool call error for ${event.name}:`, err);
104
+ });
105
+ break;
106
+ case 'turn-complete':
107
+ if (this.session) {
108
+ this.config.conversationState.save(this.session).catch((err) => {
109
+ console.error('[CapabilityCallWorker] Failed to save session on turn-complete:', err);
110
+ });
111
+ }
112
+ break;
113
+ case 'error':
114
+ console.error(`[CapabilityCallWorker] Gemini error: ${event.error}`);
115
+ break;
116
+ default:
117
+ break;
118
+ }
119
+ }
120
+ async handleToolCall(id, name, args) {
121
+ if (!this.session)
122
+ return;
123
+ const { toolExecutor, conversationState, eventLog, agent } = this.config;
124
+ // Look up by name across all capability tools (implicit + explicit).
125
+ const tool = this.host.getAllTools().find((t) => t.name === name);
126
+ if (!tool) {
127
+ console.warn(`[CapabilityCallWorker] Unknown tool: ${name}`);
128
+ this.geminiSession.sendToolResponse([{
129
+ id,
130
+ name,
131
+ output: { error: `Unknown tool: ${name}` },
132
+ }]);
133
+ return;
134
+ }
135
+ const ctx = {
136
+ session: this.session,
137
+ agentId: agent.id,
138
+ stepCount: 0,
139
+ totalTokens: 0,
140
+ handoffStack: [],
141
+ startTime: Date.now(),
142
+ consecutiveErrors: 0,
143
+ toolCallHistory: [],
144
+ };
145
+ eventLog.record(ctx, {
146
+ type: 'tool-call',
147
+ toolCallId: id,
148
+ toolName: name,
149
+ args,
150
+ });
151
+ try {
152
+ // Execute through the tool's own execute() — capability tools (flow transitions,
153
+ // extraction submissions) are self-contained; regular tools use the agent executor.
154
+ let result;
155
+ const isCapabilityTool = isFlowOrExtractionTool(name, tool);
156
+ if (isCapabilityTool) {
157
+ result = await tool.execute(args);
158
+ }
159
+ else {
160
+ // For regular agent tools, route through the shared ToolExecutor so
161
+ // event logging, timeouts, and guards apply consistently.
162
+ const voiceTool = agent.tools?.[name];
163
+ if (voiceTool) {
164
+ result = await toolExecutor.execute({
165
+ session: this.session,
166
+ userId: this.config.userId,
167
+ agentId: agent.id,
168
+ toolName: name,
169
+ tool: voiceTool,
170
+ input: args,
171
+ toolCallId: id,
172
+ abortSignal: this.abortController.signal,
173
+ });
174
+ }
175
+ else {
176
+ result = await tool.execute(args);
177
+ }
178
+ }
179
+ eventLog.record(ctx, {
180
+ type: 'tool-result',
181
+ toolCallId: id,
182
+ toolName: name,
183
+ result,
184
+ });
185
+ await conversationState.save(this.session);
186
+ // Send tool response to Gemini BEFORE acting on the capability action.
187
+ // The model needs the result to continue its turn even if we reconfigure.
188
+ this.geminiSession.sendToolResponse([{ id, name, output: result }]);
189
+ // Route through CapabilityHost to determine next action.
190
+ const action = this.host.processToolResult(name, args, result);
191
+ switch (action.type) {
192
+ case 'continue':
193
+ case 'extraction-complete':
194
+ // Data collected or regular tool result — model drives the next response.
195
+ break;
196
+ case 'reconfigure':
197
+ // Flow transitioned to a new node: update Gemini session with new
198
+ // prompt and tools so the model operates in the correct node context.
199
+ await this.reconfigureSession();
200
+ break;
201
+ case 'handoff': {
202
+ const reason = action.reason ?? `Handoff to ${action.targetAgent}`;
203
+ console.log(`[CapabilityCallWorker] Handoff to "${action.targetAgent}": ${reason}`);
204
+ await this.stop();
205
+ break;
206
+ }
207
+ case 'end': {
208
+ const reason = action.reason ?? 'Flow ended';
209
+ console.log(`[CapabilityCallWorker] Flow ended: ${reason}`);
210
+ await this.stop();
211
+ break;
212
+ }
213
+ }
214
+ }
215
+ catch (error) {
216
+ const errorMsg = error instanceof Error ? error.message : String(error);
217
+ eventLog.record(ctx, {
218
+ type: 'tool-error',
219
+ toolCallId: id,
220
+ toolName: name,
221
+ error: errorMsg,
222
+ });
223
+ this.geminiSession.sendToolResponse([{
224
+ id,
225
+ name,
226
+ output: { error: errorMsg },
227
+ }]);
228
+ }
229
+ }
230
+ /**
231
+ * Rebuild Gemini Live session config from the current capability host state.
232
+ * Called after a flow transition so the model receives the updated node
233
+ * system prompt and tool set.
234
+ *
235
+ * Uses the LivePromptAssembler to build a prompt that includes runtime
236
+ * context (working memory, long-term memory, policy injections) alongside
237
+ * capability sections — matching the richness of ContextAssembleStage.
238
+ */
239
+ async reconfigureSession() {
240
+ const basePrompt = resolveAgentPrompt(this.config.agent);
241
+ const systemInstruction = await this.promptAssembler.assemble({
242
+ host: this.host,
243
+ basePrompt,
244
+ session: this.session ?? undefined,
245
+ memoryService: this.config.memoryService,
246
+ });
247
+ const tools = toGeminiDeclarations(this.host.getAllTools());
248
+ await this.geminiSession.updateConfig({ systemInstruction, tools });
249
+ this.host.markConfigured();
250
+ }
251
+ // --- Private: Host setup ---
252
+ buildHost(agent) {
253
+ const host = new CapabilityHost();
254
+ if (agent.flow) {
255
+ const initialNode = agent.initialNode ?? agent.flow.nodes[0]?.id;
256
+ if (!initialNode) {
257
+ throw new Error('[CapabilityCallWorker] agent.flow has no nodes');
258
+ }
259
+ const flowCap = new FlowCapability({ flow: agent.flow, initialNode });
260
+ // Initialize so currentNode is set and getTools()/getPromptSections() are populated.
261
+ flowCap.initialize();
262
+ host.use(flowCap);
263
+ }
264
+ if (agent.tools) {
265
+ host.addTools(voiceToolsToDeclarations(agent.tools));
266
+ }
267
+ return host;
268
+ }
269
+ }
270
+ // ─── Helpers ─────────────────────────────────────────────────────────────────
271
+ /**
272
+ * Resolve the base agent prompt text from VoiceAgentConfig.
273
+ * PromptTemplate (with sections) is joined; plain strings are returned as-is.
274
+ */
275
+ function resolveAgentPrompt(agent) {
276
+ const raw = agent.prompt;
277
+ if (!raw)
278
+ return '';
279
+ if (typeof raw === 'string')
280
+ return raw;
281
+ return raw.sections
282
+ .map(s => s.content)
283
+ .join('\n\n');
284
+ }
285
+ /**
286
+ * Convert an AI SDK ToolSet to the backend-agnostic ToolDeclaration format
287
+ * expected by CapabilityHost.addTools().
288
+ */
289
+ function voiceToolsToDeclarations(tools) {
290
+ return Object.entries(tools).map(([name, toolDef]) => {
291
+ const def = toolDef;
292
+ return {
293
+ name,
294
+ description: def.description ?? '',
295
+ parameters: (def.inputSchema ?? z.object({})),
296
+ execute: def.execute ?? (async () => ({})),
297
+ };
298
+ });
299
+ }
300
+ /**
301
+ * Returns true if this tool is a flow/extraction capability tool rather than
302
+ * a regular agent tool. Capability tools (implicit transitions + extraction)
303
+ * have self-contained execute() functions and don't need the ToolExecutor.
304
+ *
305
+ * Heuristic: transition tool names come from `transition.on` (arbitrary strings),
306
+ * extraction submit tools match `submit_<nodeId>_data`. Regular agent tools are
307
+ * registered via addTools() and will be found in agent.tools.
308
+ */
309
+ function isFlowOrExtractionTool(name, _tool) {
310
+ // Extraction submit tools always have this naming pattern.
311
+ if (name.startsWith('submit_') && name.endsWith('_data'))
312
+ return true;
313
+ // All other capability tools (implicit transitions) are identified by NOT
314
+ // having a matching key in agent.tools — but we resolve that at the call site
315
+ // above by checking agent.tools first. This function is a fast-path for
316
+ // extraction tools only.
317
+ return false;
318
+ }
319
+ //# sourceMappingURL=CapabilityCallWorker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CapabilityCallWorker.js","sourceRoot":"","sources":["../src/CapabilityCallWorker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,86 @@
1
+ import type { GeminiConfig, VoiceAgentConfig, RealtimeEvent } from './types.js';
2
+ import type { GeminiFunctionDeclaration } from './schema-bridge.js';
3
+ import type { RealtimeAudioClient, RealtimeSessionConfig, RealtimeToolResponse, RealtimeEventMap } from '@ariaflowagents/core/realtime';
4
+ export interface GeminiLiveSessionConfig {
5
+ gemini: GeminiConfig;
6
+ agent: VoiceAgentConfig;
7
+ onEvent: (event: RealtimeEvent) => void;
8
+ /**
9
+ * Optional overrides applied during connect(). When set, these take
10
+ * precedence over values derived from the agent config. Used by
11
+ * CapabilityCallWorker to inject capability-aware prompts and tools.
12
+ */
13
+ overrides?: {
14
+ systemInstruction?: string;
15
+ tools?: GeminiFunctionDeclaration[];
16
+ };
17
+ }
18
+ /**
19
+ * Thin wrapper around @google/genai ai.live.connect().
20
+ *
21
+ * Manages:
22
+ * - Connection lifecycle (connect/disconnect)
23
+ * - Audio input/output encoding (base64 PCM ↔ Uint8Array)
24
+ * - Tool call dispatch → onEvent callback
25
+ * - Session resumption via newHandle
26
+ */
27
+ export declare class GeminiLiveSession implements RealtimeAudioClient {
28
+ private ai;
29
+ private session;
30
+ private config;
31
+ private resumptionHandle?;
32
+ private _connected;
33
+ /** True during updateConfig() reconnect cycle — suppresses 'disconnected' event. */
34
+ private _reconfiguring;
35
+ /** Mutable overrides updated by updateConfig(). Merged with config.overrides. */
36
+ private runtimeOverrides?;
37
+ /** Typed event listener registry for the RealtimeAudioClient interface. */
38
+ private listeners;
39
+ constructor(config: GeminiLiveSessionConfig);
40
+ get connected(): boolean;
41
+ on<K extends keyof RealtimeEventMap>(event: K, handler: RealtimeEventMap[K]): void;
42
+ off<K extends keyof RealtimeEventMap>(event: K, handler: RealtimeEventMap[K]): void;
43
+ private emitEvent;
44
+ /**
45
+ * Gemini Live wraps the underlying WebSocket via @google/genai SDK.
46
+ * There is no direct ping API, so we return connection state as a health check.
47
+ */
48
+ ping(): Promise<boolean>;
49
+ /**
50
+ * Connect to Gemini Live.
51
+ *
52
+ * @param config Optional RealtimeSessionConfig. When provided, systemInstruction
53
+ * and tools are applied as runtimeOverrides (takes precedence over constructor
54
+ * config.overrides and agent config). This satisfies the RealtimeAudioClient
55
+ * interface while preserving backward compatibility with CapabilityCallWorker,
56
+ * which calls connect() with no arguments.
57
+ */
58
+ connect(config?: RealtimeSessionConfig): Promise<void>;
59
+ disconnect(): Promise<void>;
60
+ /**
61
+ * Send a raw PCM audio frame to Gemini Live.
62
+ * Input: Uint8Array of 16-bit PCM samples at 24kHz.
63
+ */
64
+ sendAudio(frame: Uint8Array): void;
65
+ /**
66
+ * Send a tool response back to Gemini Live.
67
+ */
68
+ sendToolResponse(responses: RealtimeToolResponse[]): void;
69
+ /**
70
+ * Update the session config (system prompt and/or tools) by disconnecting
71
+ * and reconnecting with the new overrides. The existing resumption handle is
72
+ * preserved so the conversation context is not lost.
73
+ *
74
+ * Accepts Partial<RealtimeSessionConfig> to satisfy the RealtimeAudioClient
75
+ * interface. Only systemInstruction and tools fields are applied; other fields
76
+ * (voice, model, audio) require a full reconnect via connect().
77
+ */
78
+ updateConfig(config: Partial<RealtimeSessionConfig>): Promise<void>;
79
+ /**
80
+ * Nudge the model to speak after reconfigure. Tries sendClientContent first;
81
+ * falls back to sendRealtimeInput with text for models that restrict client content.
82
+ */
83
+ requestResponse(instruction?: string): void;
84
+ private handleServerMessage;
85
+ }
86
+ //# sourceMappingURL=GeminiLiveSession.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GeminiLiveSession.d.ts","sourceRoot":"","sources":["../src/GeminiLiveSession.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChF,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAEpE,OAAO,KAAK,EACV,mBAAmB,EACnB,qBAAqB,EACrB,oBAAoB,EACpB,gBAAgB,EACjB,MAAM,+BAA+B,CAAC;AAKvC,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,YAAY,CAAC;IACrB,KAAK,EAAE,gBAAgB,CAAC;IACxB,OAAO,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IACxC;;;;OAIG;IACH,SAAS,CAAC,EAAE;QACV,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,KAAK,CAAC,EAAE,yBAAyB,EAAE,CAAC;KACrC,CAAC;CACH;AAED;;;;;;;;GAQG;AACH,qBAAa,iBAAkB,YAAW,mBAAmB;IAC3D,OAAO,CAAC,EAAE,CAAmC;IAC7C,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,gBAAgB,CAAC,CAAS;IAClC,OAAO,CAAC,UAAU,CAAS;IAC3B,oFAAoF;IACpF,OAAO,CAAC,cAAc,CAAS;IAC/B,iFAAiF;IACjF,OAAO,CAAC,gBAAgB,CAAC,CAAsE;IAC/F,2EAA2E;IAC3E,OAAO,CAAC,SAAS,CAA6E;gBAElF,MAAM,EAAE,uBAAuB;IAK3C,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,SAAS;IAWjB;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC;IAI9B;;;;;;;;OAQG;IACG,OAAO,CAAC,MAAM,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IA0FtD,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAYjC;;;OAGG;IACH,SAAS,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAYlC;;OAEG;IACH,gBAAgB,CAAC,SAAS,EAAE,oBAAoB,EAAE,GAAG,IAAI;IAYzD;;;;;;;;OAQG;IACG,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,qBAAqB,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBzE;;;OAGG;IACH,eAAe,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI;IAsB3C,OAAO,CAAC,mBAAmB;CA2D5B"}