From 5e7eb469ae7c225e4196113f85cfd6e279efa8c9 Mon Sep 17 00:00:00 2001 From: Bijit Mondal Date: Mon, 23 Feb 2026 16:15:49 +0530 Subject: [PATCH] feat: Introduce new core components for conversation and speech management - Added ConversationManager for managing conversation history with configurable limits. - Implemented InputQueue for serial processing of input items. - Created SpeechManager for handling text-to-speech generation and streaming. - Developed StreamProcessor for processing LLM streams and forwarding events. - Added TranscriptionManager for audio transcription using AI SDK. - Introduced WebSocketManager for managing WebSocket connections and messaging. - Updated VoiceAgent to support new architecture and improved socket handling. - Refactored index files to export new core components. --- dist/VideoAgent.js | 2 +- dist/VideoAgent.js.map | 2 +- dist/VideoAgent.new.d.ts | 175 ++++ dist/VideoAgent.new.d.ts.map | 1 + dist/VideoAgent.new.js | 571 ++++++++++++ dist/VideoAgent.new.js.map | 1 + dist/VoiceAgent.d.ts | 23 + dist/VoiceAgent.d.ts.map | 2 +- dist/VoiceAgent.js | 25 +- dist/VoiceAgent.js.map | 2 +- dist/VoiceAgent.new.d.ts | 137 +++ dist/VoiceAgent.new.d.ts.map | 1 + dist/VoiceAgent.new.js | 379 ++++++++ dist/VoiceAgent.new.js.map | 1 + dist/core/ConversationManager.d.ts | 46 + dist/core/ConversationManager.d.ts.map | 1 + dist/core/ConversationManager.js | 106 +++ dist/core/ConversationManager.js.map | 1 + dist/core/InputQueue.d.ts | 33 + dist/core/InputQueue.d.ts.map | 1 + dist/core/InputQueue.js | 61 ++ dist/core/InputQueue.js.map | 1 + dist/core/SpeechManager.d.ts | 83 ++ dist/core/SpeechManager.d.ts.map | 1 + dist/core/SpeechManager.js | 356 ++++++++ dist/core/SpeechManager.js.map | 1 + dist/core/StreamProcessor.d.ts | 42 + dist/core/StreamProcessor.d.ts.map | 1 + dist/core/StreamProcessor.js | 228 +++++ dist/core/StreamProcessor.js.map | 1 + dist/core/TranscriptionManager.d.ts | 28 + dist/core/TranscriptionManager.d.ts.map | 1 + dist/core/TranscriptionManager.js | 106 +++ dist/core/TranscriptionManager.js.map | 1 + dist/core/WebSocketManager.d.ts | 35 + dist/core/WebSocketManager.d.ts.map | 1 + dist/core/WebSocketManager.js | 126 +++ dist/core/WebSocketManager.js.map | 1 + dist/core/index.d.ts | 7 + dist/core/index.d.ts.map | 1 + dist/core/index.js | 17 + dist/core/index.js.map | 1 + dist/index.d.ts | 4 +- dist/index.d.ts.map | 2 +- dist/index.js | 8 +- dist/index.js.map | 2 +- .../frame_00000_2026-02-23T10-41-46-424Z.webp | Bin 0 -> 10886 bytes .../frame_00001_2026-02-23T10-41-50-271Z.webp | Bin 0 -> 11722 bytes .../frame_00002_2026-02-23T10-41-51-387Z.webp | Bin 0 -> 11814 bytes .../frame_00003_2026-02-23T10-41-56-374Z.webp | Bin 0 -> 11326 bytes .../frame_00004_2026-02-23T10-42-01-379Z.webp | Bin 0 -> 12402 bytes .../frame_00005_2026-02-23T10-42-06-375Z.webp | Bin 0 -> 9884 bytes .../frame_00006_2026-02-23T10-42-07-405Z.webp | Bin 0 -> 10960 bytes .../frame_00007_2026-02-23T10-42-11-278Z.webp | Bin 0 -> 11592 bytes .../frame_00008_2026-02-23T10-42-11-381Z.webp | Bin 0 -> 11090 bytes .../frame_00009_2026-02-23T10-42-16-395Z.webp | Bin 0 -> 9950 bytes .../frame_00010_2026-02-23T10-42-21-373Z.webp | Bin 0 -> 11262 bytes .../frame_00011_2026-02-23T10-42-26-364Z.webp | Bin 0 -> 10670 bytes example/ws-server-video.ts | 4 +- src/VideoAgent.new.ts | 818 ++++++++++++++++++ src/VideoAgent.ts | 2 +- src/VoiceAgent.new.ts | 484 +++++++++++ src/VoiceAgent.ts | 25 +- src/core/ConversationManager.ts | 122 +++ src/core/InputQueue.ts | 71 ++ src/core/SpeechManager.ts | 453 ++++++++++ src/core/StreamProcessor.ts | 293 +++++++ src/core/TranscriptionManager.ts | 142 +++ src/core/WebSocketManager.ts | 133 +++ src/core/index.ts | 17 + src/index.ts | 4 +- 71 files changed, 5175 insertions(+), 19 deletions(-) create mode 100644 dist/VideoAgent.new.d.ts create mode 100644 dist/VideoAgent.new.d.ts.map create mode 100644 dist/VideoAgent.new.js create mode 100644 dist/VideoAgent.new.js.map create mode 100644 dist/VoiceAgent.new.d.ts create mode 100644 dist/VoiceAgent.new.d.ts.map create mode 100644 dist/VoiceAgent.new.js create mode 100644 dist/VoiceAgent.new.js.map create mode 100644 dist/core/ConversationManager.d.ts create mode 100644 dist/core/ConversationManager.d.ts.map create mode 100644 dist/core/ConversationManager.js create mode 100644 dist/core/ConversationManager.js.map create mode 100644 dist/core/InputQueue.d.ts create mode 100644 dist/core/InputQueue.d.ts.map create mode 100644 dist/core/InputQueue.js create mode 100644 dist/core/InputQueue.js.map create mode 100644 dist/core/SpeechManager.d.ts create mode 100644 dist/core/SpeechManager.d.ts.map create mode 100644 dist/core/SpeechManager.js create mode 100644 dist/core/SpeechManager.js.map create mode 100644 dist/core/StreamProcessor.d.ts create mode 100644 dist/core/StreamProcessor.d.ts.map create mode 100644 dist/core/StreamProcessor.js create mode 100644 dist/core/StreamProcessor.js.map create mode 100644 dist/core/TranscriptionManager.d.ts create mode 100644 dist/core/TranscriptionManager.d.ts.map create mode 100644 dist/core/TranscriptionManager.js create mode 100644 dist/core/TranscriptionManager.js.map create mode 100644 dist/core/WebSocketManager.d.ts create mode 100644 dist/core/WebSocketManager.d.ts.map create mode 100644 dist/core/WebSocketManager.js create mode 100644 dist/core/WebSocketManager.js.map create mode 100644 dist/core/index.d.ts create mode 100644 dist/core/index.d.ts.map create mode 100644 dist/core/index.js create mode 100644 dist/core/index.js.map create mode 100644 example/frames/frame_00000_2026-02-23T10-41-46-424Z.webp create mode 100644 example/frames/frame_00001_2026-02-23T10-41-50-271Z.webp create mode 100644 example/frames/frame_00002_2026-02-23T10-41-51-387Z.webp create mode 100644 example/frames/frame_00003_2026-02-23T10-41-56-374Z.webp create mode 100644 example/frames/frame_00004_2026-02-23T10-42-01-379Z.webp create mode 100644 example/frames/frame_00005_2026-02-23T10-42-06-375Z.webp create mode 100644 example/frames/frame_00006_2026-02-23T10-42-07-405Z.webp create mode 100644 example/frames/frame_00007_2026-02-23T10-42-11-278Z.webp create mode 100644 example/frames/frame_00008_2026-02-23T10-42-11-381Z.webp create mode 100644 example/frames/frame_00009_2026-02-23T10-42-16-395Z.webp create mode 100644 example/frames/frame_00010_2026-02-23T10-42-21-373Z.webp create mode 100644 example/frames/frame_00011_2026-02-23T10-42-26-364Z.webp create mode 100644 src/VideoAgent.new.ts create mode 100644 src/VoiceAgent.new.ts create mode 100644 src/core/ConversationManager.ts create mode 100644 src/core/InputQueue.ts create mode 100644 src/core/SpeechManager.ts create mode 100644 src/core/StreamProcessor.ts create mode 100644 src/core/TranscriptionManager.ts create mode 100644 src/core/WebSocketManager.ts create mode 100644 src/core/index.ts diff --git a/dist/VideoAgent.js b/dist/VideoAgent.js index bce0020..cabf4a2 100644 --- a/dist/VideoAgent.js +++ b/dist/VideoAgent.js @@ -71,7 +71,7 @@ Use tools when needed to provide accurate information.`; this.endpoint = options.endpoint; this.voice = options.voice || "alloy"; this.speechInstructions = options.speechInstructions; - this.outputFormat = options.outputFormat || "mp3"; + this.outputFormat = options.outputFormat || "opus"; this.maxAudioInputSize = options.maxAudioInputSize ?? types_1.DEFAULT_MAX_AUDIO_SIZE; this.maxFrameInputSize = options.maxFrameInputSize ?? DEFAULT_MAX_FRAME_SIZE; // Generate or use provided session ID diff --git a/dist/VideoAgent.js.map b/dist/VideoAgent.js.map index db9e59b..7df5e66 100644 --- a/dist/VideoAgent.js.map +++ b/dist/VideoAgent.js.map @@ -1 +1 @@ -{"version":3,"file":"VideoAgent.js","sourceRoot":"","sources":["../src/VideoAgent.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"VideoAgent.js","sourceRoot":"","sources":["../src/VideoAgent.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/VideoAgent.new.d.ts b/dist/VideoAgent.new.d.ts new file mode 100644 index 0000000..8287b32 --- /dev/null +++ b/dist/VideoAgent.new.d.ts @@ -0,0 +1,175 @@ +import { WebSocket } from "ws"; +import { EventEmitter } from "events"; +import { streamText, type LanguageModel, type Tool, type ModelMessage, type TranscriptionModel, type SpeechModel } from "ai"; +import { type StreamingSpeechConfig, type HistoryConfig } from "./types"; +/** + * Trigger reasons for frame capture + */ +type FrameTriggerReason = "scene_change" | "user_request" | "timer" | "initial"; +/** + * Video frame data structure sent to/from the client + */ +interface VideoFrame { + type: "video_frame"; + sessionId: string; + sequence: number; + timestamp: number; + triggerReason: FrameTriggerReason; + previousFrameRef?: string; + image: { + data: string; + format: string; + width: number; + height: number; + }; +} +/** + * Audio data structure + */ +interface AudioData { + type: "audio"; + sessionId: string; + data: string; + format: string; + sampleRate?: number; + duration?: number; + timestamp: number; +} +/** + * Backend configuration for video processing + */ +interface VideoAgentConfig { + /** Maximum frames to keep in context buffer for conversation history */ + maxContextFrames: number; +} +/** + * Frame context for maintaining visual conversation history + */ +interface FrameContext { + sequence: number; + timestamp: number; + triggerReason: FrameTriggerReason; + frameHash: string; + description?: string; +} +export interface VideoAgentOptions { + /** + * AI SDK Model for chat. Must be a vision-enabled model (e.g., openai('gpt-4o'), + * anthropic('claude-3.5-sonnet'), google('gemini-1.5-pro')) to process video frames. + */ + model: LanguageModel; + transcriptionModel?: TranscriptionModel; + speechModel?: SpeechModel; + instructions?: string; + stopWhen?: NonNullable[0]["stopWhen"]>; + tools?: Record; + endpoint?: string; + voice?: string; + speechInstructions?: string; + outputFormat?: string; + streamingSpeech?: Partial; + history?: Partial; + maxAudioInputSize?: number; + /** Maximum frame input size in bytes (default: 5 MB) */ + maxFrameInputSize?: number; + /** Maximum frames to keep in context buffer (default: 10) */ + maxContextFrames?: number; + /** Session ID for this video agent instance */ + sessionId?: string; +} +export declare class VideoAgent extends EventEmitter { + private model; + private instructions; + private stopWhen; + private endpoint?; + private tools; + private isDestroyed; + private _isProcessing; + private currentStreamAbortController?; + private ws; + private speech; + private conversation; + private transcription; + private inputQueue; + private sessionId; + private frameSequence; + private lastFrameTimestamp; + private lastFrameHash?; + private frameContextBuffer; + private currentFrameData?; + private videoConfig; + private maxFrameInputSize; + constructor(options: VideoAgentOptions); + registerTools(tools: Record): void; + transcribeAudio(audioData: Buffer | Uint8Array): Promise; + generateSpeechFromText(text: string, abortSignal?: AbortSignal): Promise; + interruptSpeech(reason?: string): void; + interruptCurrentResponse(reason?: string): void; + connect(url?: string): Promise; + handleSocket(socket: WebSocket): void; + sendText(text: string): Promise; + sendAudio(audioData: string): Promise; + sendAudioBuffer(audioBuffer: Buffer | Uint8Array): Promise; + /** + * Send a video frame with optional text query for vision analysis + */ + sendFrame(frameData: string, query?: string, options?: { + width?: number; + height?: number; + format?: string; + }): Promise; + /** + * Request client to capture and send a frame + */ + requestFrameCapture(reason: FrameTriggerReason): void; + getConfig(): VideoAgentConfig; + updateConfig(config: Partial): void; + startListening(): void; + stopListening(): void; + clearHistory(): void; + getHistory(): ModelMessage[]; + setHistory(history: ModelMessage[]): void; + getFrameContext(): FrameContext[]; + getSessionId(): string; + disconnect(): void; + destroy(): void; + get connected(): boolean; + get processing(): boolean; + get speaking(): boolean; + get pendingSpeechChunks(): number; + get destroyed(): boolean; + get currentFrameSequence(): number; + get hasVisualContext(): boolean; + private handleMessage; + private handleClientReady; + private handleAudioInput; + private handleVideoFrame; + private addFrameToContext; + private hashFrame; + private generateSessionId; + private enqueueTextInput; + private enqueueMultimodalInput; + /** + * Route queued items to the correct processor. + */ + private processQueueItem; + private buildMultimodalContent; + /** + * Shared streamText invocation used by both processUserInput and processMultimodalInput. + */ + private runStream; + /** + * Process text-only input (with optional visual context from latest frame). + */ + private processUserInput; + /** + * Process multimodal input (text + explicit video frame). + */ + private processMultimodalInput; + private ensureNotDestroyed; + private cleanupOnDisconnect; + private bubbleEvents; +} +export type { VideoFrame, AudioData, VideoAgentConfig, FrameContext, FrameTriggerReason, }; +export type { StreamingSpeechConfig, HistoryConfig } from "./types"; +//# sourceMappingURL=VideoAgent.new.d.ts.map \ No newline at end of file diff --git a/dist/VideoAgent.new.d.ts.map b/dist/VideoAgent.new.d.ts.map new file mode 100644 index 0000000..8e6b8b8 --- /dev/null +++ b/dist/VideoAgent.new.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VideoAgent.new.d.ts","sourceRoot":"","sources":["../src/VideoAgent.new.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/VideoAgent.new.js b/dist/VideoAgent.new.js new file mode 100644 index 0000000..5fba234 --- /dev/null +++ b/dist/VideoAgent.new.js @@ -0,0 +1,571 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.VideoAgent = void 0; +const events_1 = require("events"); +const ai_1 = require("ai"); +const core_1 = require("./core"); +/** Default maximum frame input size (5 MB) */ +const DEFAULT_MAX_FRAME_SIZE = 5 * 1024 * 1024; +/** Default video agent config */ +const DEFAULT_VIDEO_AGENT_CONFIG = { + maxContextFrames: 10, +}; +// ── VideoAgent class ──────────────────────────────────── +class VideoAgent extends events_1.EventEmitter { + model; + instructions; + stopWhen; + endpoint; + tools = {}; + isDestroyed = false; + _isProcessing = false; + // Abort controller for the current LLM stream + currentStreamAbortController; + // ── Managers ───────────────────────────────────────── + ws; + speech; + conversation; + transcription; + inputQueue; + // ── Video-specific state ──────────────────────────── + sessionId; + frameSequence = 0; + lastFrameTimestamp = 0; + lastFrameHash; + frameContextBuffer = []; + currentFrameData; + videoConfig; + maxFrameInputSize; + constructor(options) { + super(); + this.model = options.model; + this.instructions = + options.instructions || + `You are a helpful multimodal AI assistant that can see through the user's camera and hear their voice. +When analyzing images, be concise but informative. Describe what you see when asked. +Keep responses conversational since they will be spoken aloud. +Use tools when needed to provide accurate information.`; + this.stopWhen = options.stopWhen || (0, ai_1.stepCountIs)(5); + this.endpoint = options.endpoint; + this.maxFrameInputSize = options.maxFrameInputSize ?? DEFAULT_MAX_FRAME_SIZE; + this.sessionId = options.sessionId || this.generateSessionId(); + this.videoConfig = { + ...DEFAULT_VIDEO_AGENT_CONFIG, + maxContextFrames: options.maxContextFrames ?? DEFAULT_VIDEO_AGENT_CONFIG.maxContextFrames, + }; + if (options.tools) { + this.tools = { ...options.tools }; + } + // ── Initialize managers ───────────────────────── + this.ws = new core_1.WebSocketManager(); + this.speech = new core_1.SpeechManager({ + speechModel: options.speechModel, + voice: options.voice, + speechInstructions: options.speechInstructions, + outputFormat: options.outputFormat, + streamingSpeech: options.streamingSpeech, + }); + this.conversation = new core_1.ConversationManager({ + history: options.history, + }); + this.transcription = new core_1.TranscriptionManager({ + transcriptionModel: options.transcriptionModel, + maxAudioInputSize: options.maxAudioInputSize, + }); + this.inputQueue = new core_1.InputQueue(); + // ── Wire managers to WebSocket send ───────────── + const sendMsg = (msg) => this.ws.send(msg); + this.speech.sendMessage = sendMsg; + this.transcription.sendMessage = sendMsg; + // ── Wire input queue processor ────────────────── + this.inputQueue.processor = (item) => this.processQueueItem(item); + // ── Bubble events from managers ───────────────── + this.bubbleEvents(this.ws, ["connected", "error"]); + this.bubbleEvents(this.speech, [ + "speech_start", + "speech_complete", + "speech_interrupted", + "speech_chunk_queued", + "audio_chunk", + "audio", + "error", + ]); + this.bubbleEvents(this.conversation, [ + "history_cleared", + "history_trimmed", + ]); + this.bubbleEvents(this.transcription, [ + "transcription", + "audio_received", + "error", + "warning", + ]); + // ── Handle WebSocket lifecycle ────────────────── + this.ws.on("disconnected", () => { + this.cleanupOnDisconnect(); + this.emit("disconnected"); + }); + this.ws.on("message", (message) => this.handleMessage(message)); + } + // ══════════════════════════════════════════════════════ + // Public API + // ══════════════════════════════════════════════════════ + registerTools(tools) { + this.tools = { ...this.tools, ...tools }; + } + async transcribeAudio(audioData) { + return this.transcription.transcribeAudio(audioData); + } + async generateSpeechFromText(text, abortSignal) { + return this.speech.generateSpeechFromText(text, abortSignal); + } + interruptSpeech(reason = "interrupted") { + this.speech.interruptSpeech(reason); + } + interruptCurrentResponse(reason = "interrupted") { + if (this.currentStreamAbortController) { + this.currentStreamAbortController.abort(); + this.currentStreamAbortController = undefined; + } + this.speech.interruptSpeech(reason); + } + async connect(url) { + this.ensureNotDestroyed(); + const wsUrl = url || this.endpoint || "ws://localhost:8080"; + await this.ws.connect(wsUrl); + } + handleSocket(socket) { + this.ensureNotDestroyed(); + this.ws.handleSocket(socket); + } + async sendText(text) { + this.ensureNotDestroyed(); + if (!text || !text.trim()) { + throw new Error("Text input cannot be empty"); + } + return this.enqueueTextInput(text); + } + async sendAudio(audioData) { + this.ensureNotDestroyed(); + await this.handleAudioInput(audioData); + } + async sendAudioBuffer(audioBuffer) { + this.ensureNotDestroyed(); + const base64Audio = Buffer.from(audioBuffer).toString("base64"); + await this.handleAudioInput(base64Audio); + } + /** + * Send a video frame with optional text query for vision analysis + */ + async sendFrame(frameData, query, options) { + this.ensureNotDestroyed(); + const frame = { + type: "video_frame", + sessionId: this.sessionId, + sequence: this.frameSequence++, + timestamp: Date.now(), + triggerReason: "user_request", + previousFrameRef: this.lastFrameHash, + image: { + data: frameData, + format: options?.format || "webp", + width: options?.width || 640, + height: options?.height || 480, + }, + }; + // Update local frame state + await this.handleVideoFrame(frame); + if (query) { + return this.enqueueMultimodalInput(query, frame); + } + return ""; + } + /** + * Request client to capture and send a frame + */ + requestFrameCapture(reason) { + this.ws.send({ + type: "capture_frame", + reason, + timestamp: Date.now(), + }); + this.emit("frame_requested", { reason }); + } + getConfig() { + return { ...this.videoConfig }; + } + updateConfig(config) { + this.videoConfig = { ...this.videoConfig, ...config }; + this.emit("config_changed", this.videoConfig); + } + startListening() { + this.emit("listening"); + } + stopListening() { + this.emit("stopped"); + } + clearHistory() { + this.conversation.clearHistory(); + this.frameContextBuffer = []; + } + getHistory() { + return this.conversation.getHistory(); + } + setHistory(history) { + this.conversation.setHistory(history); + } + getFrameContext() { + return [...this.frameContextBuffer]; + } + getSessionId() { + return this.sessionId; + } + disconnect() { + this.ws.disconnect(); + } + destroy() { + this.isDestroyed = true; + this.cleanupOnDisconnect(); + this.ws.disconnect(); + this.conversation.clearHistory(); + this.frameContextBuffer = []; + this.tools = {}; + this.removeAllListeners(); + } + // ── Getters ───────────────────────────────────────── + get connected() { + return this.ws.isConnected; + } + get processing() { + return this._isProcessing; + } + get speaking() { + return this.speech.isSpeaking; + } + get pendingSpeechChunks() { + return this.speech.pendingChunkCount; + } + get destroyed() { + return this.isDestroyed; + } + get currentFrameSequence() { + return this.frameSequence; + } + get hasVisualContext() { + return !!this.currentFrameData; + } + // ══════════════════════════════════════════════════════ + // Private — message handling + // ══════════════════════════════════════════════════════ + async handleMessage(message) { + try { + switch (message.type) { + case "transcript": + if (typeof message.text !== "string" || !message.text.trim()) { + this.emit("warning", "Received empty or invalid transcript message"); + return; + } + this.interruptCurrentResponse("user_speaking"); + this.requestFrameCapture("user_request"); + await this.enqueueTextInput(message.text); + break; + case "audio": + if (typeof message.data !== "string" || !message.data) { + this.emit("warning", "Received empty or invalid audio message"); + return; + } + this.interruptCurrentResponse("user_speaking"); + this.requestFrameCapture("user_request"); + try { + await this.handleAudioInput(message.data, message.format); + } + catch (audioError) { + this.emit("error", audioError); + } + break; + case "video_frame": + await this.handleVideoFrame(message); + break; + case "interrupt": + this.interruptCurrentResponse(message.reason || "client_request"); + break; + case "client_ready": + this.handleClientReady(message); + break; + } + } + catch (err) { + this.emit("error", err); + } + } + handleClientReady(message) { + this.ws.send({ + type: "session_init", + sessionId: this.sessionId, + }); + this.emit("client_ready", message.capabilities); + } + // ══════════════════════════════════════════════════════ + // Private — audio + // ══════════════════════════════════════════════════════ + async handleAudioInput(base64Audio, format) { + const text = await this.transcription.processAudioInput(base64Audio, format); + if (text) { + await this.enqueueTextInput(text); + } + } + // ══════════════════════════════════════════════════════ + // Private — video frames + // ══════════════════════════════════════════════════════ + async handleVideoFrame(frame) { + try { + if (!frame.image?.data) { + this.emit("warning", "Received empty or invalid video frame"); + return; + } + const frameSize = Buffer.from(frame.image.data, "base64").length; + if (frameSize > this.maxFrameInputSize) { + const sizeMB = (frameSize / (1024 * 1024)).toFixed(1); + const maxMB = (this.maxFrameInputSize / (1024 * 1024)).toFixed(1); + this.emit("error", new Error(`Frame too large (${sizeMB} MB). Maximum allowed: ${maxMB} MB`)); + return; + } + const frameHash = this.hashFrame(frame.image.data); + this.lastFrameTimestamp = frame.timestamp; + this.lastFrameHash = frameHash; + this.currentFrameData = frame.image.data; + this.addFrameToContext({ + sequence: frame.sequence, + timestamp: frame.timestamp, + triggerReason: frame.triggerReason, + frameHash, + }); + this.emit("frame_received", { + sequence: frame.sequence, + timestamp: frame.timestamp, + triggerReason: frame.triggerReason, + size: frameSize, + dimensions: { width: frame.image.width, height: frame.image.height }, + }); + this.ws.send({ + type: "frame_ack", + sequence: frame.sequence, + timestamp: Date.now(), + }); + } + catch (error) { + this.emit("error", error); + } + } + addFrameToContext(context) { + this.frameContextBuffer.push(context); + if (this.frameContextBuffer.length > this.videoConfig.maxContextFrames) { + this.frameContextBuffer.shift(); + } + } + hashFrame(data) { + let hash = 0; + for (let i = 0; i < data.length; i++) { + const char = data.charCodeAt(i); + hash = ((hash << 5) - hash) + char; + hash = hash & hash; + } + return `frame_${this.frameSequence}_${Math.abs(hash).toString(16)}`; + } + generateSessionId() { + const timestamp = Date.now().toString(36); + const randomPart = Math.random().toString(36).substring(2, 10); + return `vs_${timestamp}_${randomPart}`; + } + // ══════════════════════════════════════════════════════ + // Private — input queue + // ══════════════════════════════════════════════════════ + enqueueTextInput(text) { + return new Promise((resolve, reject) => { + this.inputQueue.enqueue({ text, resolve, reject }); + }); + } + enqueueMultimodalInput(text, frame) { + return new Promise((resolve, reject) => { + this.inputQueue.enqueue({ text, frame, resolve, reject }); + }); + } + /** + * Route queued items to the correct processor. + */ + async processQueueItem(item) { + if (item.frame && item.text) { + return this.processMultimodalInput(item.text, item.frame); + } + else if (item.text) { + return this.processUserInput(item.text); + } + return ""; + } + // ══════════════════════════════════════════════════════ + // Private — multimodal content building + // ══════════════════════════════════════════════════════ + buildMultimodalContent(text, frameData) { + const content = []; + if (this.frameContextBuffer.length > 0) { + const contextSummary = `[Visual context: ${this.frameContextBuffer.length} frames captured, latest at ${new Date(this.lastFrameTimestamp).toISOString()}]`; + content.push({ type: "text", text: contextSummary }); + } + const imageData = frameData || this.currentFrameData; + if (imageData) { + content.push({ type: "image", image: imageData }); + } + content.push({ type: "text", text }); + return content; + } + // ══════════════════════════════════════════════════════ + // Private — LLM processing + // ══════════════════════════════════════════════════════ + /** + * Shared streamText invocation used by both processUserInput and processMultimodalInput. + */ + async runStream(messages, abortSignal) { + const result = (0, ai_1.streamText)({ + model: this.model, + system: this.instructions, + messages, + tools: this.tools, + stopWhen: this.stopWhen, + abortSignal, + onChunk: ({ chunk }) => { + (0, core_1.handleStreamChunk)(chunk, (event, data) => this.emit(event, data)); + }, + onFinish: async (event) => { + for (const step of event.steps) { + for (const toolResult of step.toolResults) { + this.emit("tool_result", { + name: toolResult.toolName, + toolCallId: toolResult.toolCallId, + result: toolResult.output, + }); + } + } + }, + onError: ({ error }) => { + this.emit("error", error); + }, + }); + const streamResult = await (0, core_1.processFullStream)(result, { + onTextDelta: (delta) => this.speech.processTextDelta(delta), + onTextEnd: () => this.speech.flushPendingText(), + sendMessage: (msg) => this.ws.send(msg), + emitEvent: (event, data) => this.emit(event, data), + }, { + sessionId: this.sessionId, + frameContext: this.frameContextBuffer.length > 0 + ? { + frameCount: this.frameContextBuffer.length, + lastFrameSequence: this.frameContextBuffer[this.frameContextBuffer.length - 1] + ?.sequence, + } + : undefined, + }); + // Add assistant response to history + if (streamResult.fullText) { + this.conversation.addMessage({ + role: "assistant", + content: streamResult.fullText, + }); + } + // Flush remaining speech & wait for queue + this.speech.flushPendingText(); + if (this.speech.queueDonePromise) { + await this.speech.queueDonePromise; + } + return streamResult.fullText; + } + /** + * Process text-only input (with optional visual context from latest frame). + */ + async processUserInput(text) { + this._isProcessing = true; + this.currentStreamAbortController = new AbortController(); + try { + this.emit("text", { role: "user", text }); + const hasVisual = !!this.currentFrameData; + let messages; + if (hasVisual) { + const content = this.buildMultimodalContent(text); + this.conversation.addMessage({ + role: "user", + content: [{ type: "text", text: `[Visual context] ${text}` }], + }); + messages = [ + ...this.conversation.getHistoryRef().slice(0, -1), + { role: "user", content }, + ]; + } + else { + this.conversation.addMessage({ role: "user", content: text }); + messages = this.conversation.getHistoryRef(); + } + return await this.runStream(messages, this.currentStreamAbortController.signal); + } + catch (error) { + this.speech.reset(); + throw error; + } + finally { + this._isProcessing = false; + this.currentStreamAbortController = undefined; + } + } + /** + * Process multimodal input (text + explicit video frame). + */ + async processMultimodalInput(text, frame) { + this._isProcessing = true; + this.currentStreamAbortController = new AbortController(); + try { + this.emit("text", { role: "user", text, hasImage: true }); + const content = this.buildMultimodalContent(text, frame.image.data); + this.conversation.addMessage({ + role: "user", + content: [{ type: "text", text: `[Image attached] ${text}` }], + }); + const messages = [ + ...this.conversation.getHistoryRef().slice(0, -1), + { role: "user", content }, + ]; + return await this.runStream(messages, this.currentStreamAbortController.signal); + } + catch (error) { + this.speech.reset(); + throw error; + } + finally { + this._isProcessing = false; + this.currentStreamAbortController = undefined; + } + } + // ══════════════════════════════════════════════════════ + // Private — helpers + // ══════════════════════════════════════════════════════ + ensureNotDestroyed() { + if (this.isDestroyed) { + throw new Error("VideoAgent has been destroyed and cannot be used"); + } + } + cleanupOnDisconnect() { + if (this.currentStreamAbortController) { + this.currentStreamAbortController.abort(); + this.currentStreamAbortController = undefined; + } + this.speech.reset(); + this._isProcessing = false; + this.currentFrameData = undefined; + this.inputQueue.rejectAll(new Error("Connection closed")); + } + bubbleEvents(source, events) { + for (const event of events) { + source.on(event, (...args) => this.emit(event, ...args)); + } + } +} +exports.VideoAgent = VideoAgent; +//# sourceMappingURL=VideoAgent.new.js.map \ No newline at end of file diff --git a/dist/VideoAgent.new.js.map b/dist/VideoAgent.new.js.map new file mode 100644 index 0000000..b94ad4d --- /dev/null +++ b/dist/VideoAgent.new.js.map @@ -0,0 +1 @@ +{"version":3,"file":"VideoAgent.new.js","sourceRoot":"","sources":["../src/VideoAgent.new.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/VoiceAgent.d.ts b/dist/VoiceAgent.d.ts index b7ac216..ef1678f 100644 --- a/dist/VoiceAgent.d.ts +++ b/dist/VoiceAgent.d.ts @@ -20,6 +20,25 @@ export interface VoiceAgentOptions { /** Maximum audio input size in bytes (default: 10 MB) */ maxAudioInputSize?: number; } +/** + * A single-session voice agent that manages one WebSocket connection at a time. + * + * **Important:** Each `VoiceAgent` instance holds its own conversation history, + * input queue, speech state, and WebSocket. It is designed for **one user per + * instance**. To support multiple concurrent users, create a separate + * `VoiceAgent` for each connection: + * + * ```ts + * wss.on("connection", (socket) => { + * const agent = new VoiceAgent({ model, ... }); + * agent.handleSocket(socket); + * agent.on("disconnected", () => agent.destroy()); + * }); + * ``` + * + * Sharing a single instance across multiple users will cause conversation + * history cross-contamination, interleaved audio, and unpredictable behavior. + */ export declare class VoiceAgent extends EventEmitter { private socket?; private tools; @@ -120,6 +139,10 @@ export declare class VoiceAgent extends EventEmitter { * Attach an existing WebSocket (server-side usage). * Use this when a WS server accepts a connection and you want the * agent to handle messages on that socket. + * + * **Note:** Calling this while a socket is already attached will cleanly + * tear down the previous connection first. Each `VoiceAgent` instance + * supports only one socket at a time — create a new agent per user. */ handleSocket(socket: WebSocket): void; /** diff --git a/dist/VoiceAgent.d.ts.map b/dist/VoiceAgent.d.ts.map index b558a9b..eef9944 100644 --- a/dist/VoiceAgent.d.ts.map +++ b/dist/VoiceAgent.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"VoiceAgent.d.ts","sourceRoot":"","sources":["../src/VoiceAgent.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"VoiceAgent.d.ts","sourceRoot":"","sources":["../src/VoiceAgent.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/VoiceAgent.js b/dist/VoiceAgent.js index 8bf06b3..a9e6566 100644 --- a/dist/VoiceAgent.js +++ b/dist/VoiceAgent.js @@ -5,6 +5,25 @@ const ws_1 = require("ws"); const events_1 = require("events"); const ai_1 = require("ai"); const types_1 = require("./types"); +/** + * A single-session voice agent that manages one WebSocket connection at a time. + * + * **Important:** Each `VoiceAgent` instance holds its own conversation history, + * input queue, speech state, and WebSocket. It is designed for **one user per + * instance**. To support multiple concurrent users, create a separate + * `VoiceAgent` for each connection: + * + * ```ts + * wss.on("connection", (socket) => { + * const agent = new VoiceAgent({ model, ... }); + * agent.handleSocket(socket); + * agent.on("disconnected", () => agent.destroy()); + * }); + * ``` + * + * Sharing a single instance across multiple users will cause conversation + * history cross-contamination, interleaved audio, and unpredictable behavior. + */ class VoiceAgent extends events_1.EventEmitter { socket; tools = {}; @@ -50,7 +69,7 @@ class VoiceAgent extends events_1.EventEmitter { this.endpoint = options.endpoint; this.voice = options.voice || "alloy"; this.speechInstructions = options.speechInstructions; - this.outputFormat = options.outputFormat || "mp3"; + this.outputFormat = options.outputFormat || "opus"; this.maxAudioInputSize = options.maxAudioInputSize ?? types_1.DEFAULT_MAX_AUDIO_SIZE; if (options.tools) { this.tools = { ...options.tools }; @@ -576,6 +595,10 @@ class VoiceAgent extends events_1.EventEmitter { * Attach an existing WebSocket (server-side usage). * Use this when a WS server accepts a connection and you want the * agent to handle messages on that socket. + * + * **Note:** Calling this while a socket is already attached will cleanly + * tear down the previous connection first. Each `VoiceAgent` instance + * supports only one socket at a time — create a new agent per user. */ handleSocket(socket) { this.ensureNotDestroyed(); diff --git a/dist/VoiceAgent.js.map b/dist/VoiceAgent.js.map index 50a5ae2..9640f63 100644 --- a/dist/VoiceAgent.js.map +++ b/dist/VoiceAgent.js.map @@ -1 +1 @@ -{"version":3,"file":"VoiceAgent.js","sourceRoot":"","sources":["../src/VoiceAgent.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"VoiceAgent.js","sourceRoot":"","sources":["../src/VoiceAgent.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/VoiceAgent.new.d.ts b/dist/VoiceAgent.new.d.ts new file mode 100644 index 0000000..7786ae6 --- /dev/null +++ b/dist/VoiceAgent.new.d.ts @@ -0,0 +1,137 @@ +import { WebSocket } from "ws"; +import { EventEmitter } from "events"; +import { streamText, type LanguageModel, type Tool, type ModelMessage, type TranscriptionModel, type SpeechModel } from "ai"; +import { type StreamingSpeechConfig, type HistoryConfig } from "./types"; +export interface VoiceAgentOptions { + model: LanguageModel; + transcriptionModel?: TranscriptionModel; + speechModel?: SpeechModel; + instructions?: string; + stopWhen?: NonNullable[0]["stopWhen"]>; + tools?: Record; + endpoint?: string; + voice?: string; + speechInstructions?: string; + outputFormat?: string; + /** Configuration for streaming speech generation */ + streamingSpeech?: Partial; + /** Configuration for conversation history memory limits */ + history?: Partial; + /** Maximum audio input size in bytes (default: 10 MB) */ + maxAudioInputSize?: number; +} +/** + * A single-session voice agent that manages one WebSocket connection at a time. + * + * **Important:** Each `VoiceAgent` instance holds its own conversation history, + * input queue, speech state, and WebSocket. It is designed for **one user per + * instance**. To support multiple concurrent users, create a separate + * `VoiceAgent` for each connection: + * + * ```ts + * wss.on("connection", (socket) => { + * const agent = new VoiceAgent({ model, ... }); + * agent.handleSocket(socket); + * agent.on("disconnected", () => agent.destroy()); + * }); + * ``` + * + * Sharing a single instance across multiple users will cause conversation + * history cross-contamination, interleaved audio, and unpredictable behavior. + */ +export declare class VoiceAgent extends EventEmitter { + private model; + private instructions; + private stopWhen; + private endpoint?; + private tools; + private isDestroyed; + private _isProcessing; + private currentStreamAbortController?; + private ws; + private speech; + private conversation; + private transcription; + private inputQueue; + constructor(options: VoiceAgentOptions); + registerTools(tools: Record): void; + /** + * Transcribe audio data to text using the configured transcription model. + */ + transcribeAudio(audioData: Buffer | Uint8Array): Promise; + /** + * Generate speech from text using the configured speech model. + */ + generateSpeechFromText(text: string, abortSignal?: AbortSignal): Promise; + /** + * Interrupt ongoing speech generation and playback (barge-in support). + */ + interruptSpeech(reason?: string): void; + /** + * Interrupt both the current LLM stream and ongoing speech. + */ + interruptCurrentResponse(reason?: string): void; + /** + * Connect to a WebSocket server by URL. + */ + connect(url?: string): Promise; + /** + * Attach an existing WebSocket (server-side usage). + */ + handleSocket(socket: WebSocket): void; + /** + * Send text input for processing (bypasses transcription). + */ + sendText(text: string): Promise; + /** + * Send base64 audio data to be transcribed and processed. + */ + sendAudio(audioData: string): Promise; + /** + * Send raw audio buffer to be transcribed and processed. + */ + sendAudioBuffer(audioBuffer: Buffer | Uint8Array): Promise; + /** + * Generate speech for full text at once (non-streaming fallback). + */ + generateAndSendSpeechFull(text: string): Promise; + /** Start listening for voice input */ + startListening(): void; + /** Stop listening for voice input */ + stopListening(): void; + /** Clear conversation history */ + clearHistory(): void; + /** Get current conversation history */ + getHistory(): ModelMessage[]; + /** Set conversation history (useful for restoring sessions) */ + setHistory(history: ModelMessage[]): void; + /** Disconnect from WebSocket and stop all in-flight work */ + disconnect(): void; + /** + * Permanently destroy the agent, releasing all resources. + */ + destroy(): void; + get connected(): boolean; + get processing(): boolean; + get speaking(): boolean; + get pendingSpeechChunks(): number; + get destroyed(): boolean; + private handleMessage; + private handleAudioInput; + private enqueueInput; + /** + * Process user input with streaming text generation. + * Called serially by the input queue. + */ + private processUserInput; + private ensureNotDestroyed; + /** + * Clean up all in-flight state when the connection drops. + */ + private cleanupOnDisconnect; + /** + * Forward select events from a child emitter to this agent. + */ + private bubbleEvents; +} +//# sourceMappingURL=VoiceAgent.new.d.ts.map \ No newline at end of file diff --git a/dist/VoiceAgent.new.d.ts.map b/dist/VoiceAgent.new.d.ts.map new file mode 100644 index 0000000..0c98d1f --- /dev/null +++ b/dist/VoiceAgent.new.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VoiceAgent.new.d.ts","sourceRoot":"","sources":["../src/VoiceAgent.new.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/VoiceAgent.new.js b/dist/VoiceAgent.new.js new file mode 100644 index 0000000..a43f8fc --- /dev/null +++ b/dist/VoiceAgent.new.js @@ -0,0 +1,379 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.VoiceAgent = void 0; +const events_1 = require("events"); +const ai_1 = require("ai"); +const core_1 = require("./core"); +/** + * A single-session voice agent that manages one WebSocket connection at a time. + * + * **Important:** Each `VoiceAgent` instance holds its own conversation history, + * input queue, speech state, and WebSocket. It is designed for **one user per + * instance**. To support multiple concurrent users, create a separate + * `VoiceAgent` for each connection: + * + * ```ts + * wss.on("connection", (socket) => { + * const agent = new VoiceAgent({ model, ... }); + * agent.handleSocket(socket); + * agent.on("disconnected", () => agent.destroy()); + * }); + * ``` + * + * Sharing a single instance across multiple users will cause conversation + * history cross-contamination, interleaved audio, and unpredictable behavior. + */ +class VoiceAgent extends events_1.EventEmitter { + model; + instructions; + stopWhen; + endpoint; + tools = {}; + isDestroyed = false; + _isProcessing = false; + // Abort controller for the current LLM stream + currentStreamAbortController; + // ── Managers ────────────────────────────────────────── + ws; + speech; + conversation; + transcription; + inputQueue; + constructor(options) { + super(); + this.model = options.model; + this.instructions = + options.instructions || "You are a helpful voice assistant."; + this.stopWhen = options.stopWhen || (0, ai_1.stepCountIs)(5); + this.endpoint = options.endpoint; + if (options.tools) { + this.tools = { ...options.tools }; + } + // ── Initialize managers ────────────────────────────── + this.ws = new core_1.WebSocketManager(); + this.speech = new core_1.SpeechManager({ + speechModel: options.speechModel, + voice: options.voice, + speechInstructions: options.speechInstructions, + outputFormat: options.outputFormat, + streamingSpeech: options.streamingSpeech, + }); + this.conversation = new core_1.ConversationManager({ + history: options.history, + }); + this.transcription = new core_1.TranscriptionManager({ + transcriptionModel: options.transcriptionModel, + maxAudioInputSize: options.maxAudioInputSize, + }); + this.inputQueue = new core_1.InputQueue(); + // ── Wire managers to the WebSocket send function ───── + const sendMsg = (msg) => this.ws.send(msg); + this.speech.sendMessage = sendMsg; + this.transcription.sendMessage = sendMsg; + // ── Wire the input queue processor ─────────────────── + this.inputQueue.processor = (item) => this.processUserInput(item.text); + // ── Bubble events from managers ────────────────────── + this.bubbleEvents(this.ws, [ + "connected", + "error", + ]); + this.bubbleEvents(this.speech, [ + "speech_start", + "speech_complete", + "speech_interrupted", + "speech_chunk_queued", + "audio_chunk", + "audio", + "error", + ]); + this.bubbleEvents(this.conversation, [ + "history_cleared", + "history_trimmed", + ]); + this.bubbleEvents(this.transcription, [ + "transcription", + "audio_received", + "error", + "warning", + ]); + // ── Handle WebSocket lifecycle events ──────────────── + this.ws.on("disconnected", () => { + this.cleanupOnDisconnect(); + this.emit("disconnected"); + }); + this.ws.on("message", (message) => this.handleMessage(message)); + } + // ── Public API ──────────────────────────────────────── + registerTools(tools) { + this.tools = { ...this.tools, ...tools }; + } + /** + * Transcribe audio data to text using the configured transcription model. + */ + async transcribeAudio(audioData) { + return this.transcription.transcribeAudio(audioData); + } + /** + * Generate speech from text using the configured speech model. + */ + async generateSpeechFromText(text, abortSignal) { + return this.speech.generateSpeechFromText(text, abortSignal); + } + /** + * Interrupt ongoing speech generation and playback (barge-in support). + */ + interruptSpeech(reason = "interrupted") { + this.speech.interruptSpeech(reason); + } + /** + * Interrupt both the current LLM stream and ongoing speech. + */ + interruptCurrentResponse(reason = "interrupted") { + if (this.currentStreamAbortController) { + this.currentStreamAbortController.abort(); + this.currentStreamAbortController = undefined; + } + this.speech.interruptSpeech(reason); + } + /** + * Connect to a WebSocket server by URL. + */ + async connect(url) { + this.ensureNotDestroyed(); + const wsUrl = url || this.endpoint || "ws://localhost:8080"; + await this.ws.connect(wsUrl); + } + /** + * Attach an existing WebSocket (server-side usage). + */ + handleSocket(socket) { + this.ensureNotDestroyed(); + this.ws.handleSocket(socket); + } + /** + * Send text input for processing (bypasses transcription). + */ + async sendText(text) { + this.ensureNotDestroyed(); + if (!text || !text.trim()) { + throw new Error("Text input cannot be empty"); + } + return this.enqueueInput(text); + } + /** + * Send base64 audio data to be transcribed and processed. + */ + async sendAudio(audioData) { + this.ensureNotDestroyed(); + await this.handleAudioInput(audioData); + } + /** + * Send raw audio buffer to be transcribed and processed. + */ + async sendAudioBuffer(audioBuffer) { + this.ensureNotDestroyed(); + const base64Audio = Buffer.from(audioBuffer).toString("base64"); + await this.handleAudioInput(base64Audio); + } + /** + * Generate speech for full text at once (non-streaming fallback). + */ + async generateAndSendSpeechFull(text) { + return this.speech.generateAndSendSpeechFull(text); + } + /** Start listening for voice input */ + startListening() { + console.log("Starting voice agent..."); + this.emit("listening"); + } + /** Stop listening for voice input */ + stopListening() { + console.log("Stopping voice agent..."); + this.emit("stopped"); + } + /** Clear conversation history */ + clearHistory() { + this.conversation.clearHistory(); + } + /** Get current conversation history */ + getHistory() { + return this.conversation.getHistory(); + } + /** Set conversation history (useful for restoring sessions) */ + setHistory(history) { + this.conversation.setHistory(history); + } + /** Disconnect from WebSocket and stop all in-flight work */ + disconnect() { + this.ws.disconnect(); + } + /** + * Permanently destroy the agent, releasing all resources. + */ + destroy() { + this.isDestroyed = true; + this.cleanupOnDisconnect(); + this.ws.disconnect(); + this.conversation.clearHistory(); + this.tools = {}; + this.removeAllListeners(); + } + // ── Getters ─────────────────────────────────────────── + get connected() { + return this.ws.isConnected; + } + get processing() { + return this._isProcessing; + } + get speaking() { + return this.speech.isSpeaking; + } + get pendingSpeechChunks() { + return this.speech.pendingChunkCount; + } + get destroyed() { + return this.isDestroyed; + } + // ── Private: message handling ───────────────────────── + async handleMessage(message) { + try { + console.log(`Received WebSocket message of type: ${message.type}`); + if (message.type === "transcript") { + if (typeof message.text !== "string" || !message.text.trim()) { + this.emit("warning", "Received empty or invalid transcript message"); + return; + } + this.interruptCurrentResponse("user_speaking"); + console.log(`Processing transcript: "${message.text}"`); + await this.enqueueInput(message.text); + } + else if (message.type === "audio") { + if (typeof message.data !== "string" || !message.data) { + this.emit("warning", "Received empty or invalid audio message"); + return; + } + this.interruptCurrentResponse("user_speaking"); + console.log(`Received audio data (${message.data.length / 1000}KB) for processing, format: ${message.format || "unknown"}`); + await this.handleAudioInput(message.data, message.format); + } + else if (message.type === "interrupt") { + console.log(`Received interrupt request: ${message.reason || "client_request"}`); + this.interruptCurrentResponse(message.reason || "client_request"); + } + } + catch (err) { + console.error("Failed to process message:", err); + this.emit("error", err); + } + } + // ── Private: audio ──────────────────────────────────── + async handleAudioInput(base64Audio, format) { + const text = await this.transcription.processAudioInput(base64Audio, format); + if (text) { + await this.enqueueInput(text); + } + } + // ── Private: input queue ────────────────────────────── + enqueueInput(text) { + return new Promise((resolve, reject) => { + this.inputQueue.enqueue({ text, resolve, reject }); + }); + } + // ── Private: LLM processing ─────────────────────────── + /** + * Process user input with streaming text generation. + * Called serially by the input queue. + */ + async processUserInput(text) { + this._isProcessing = true; + this.currentStreamAbortController = new AbortController(); + const streamAbortSignal = this.currentStreamAbortController.signal; + try { + this.emit("text", { role: "user", text }); + this.conversation.addMessage({ role: "user", content: text }); + const result = (0, ai_1.streamText)({ + model: this.model, + system: this.instructions, + messages: this.conversation.getHistoryRef(), + tools: this.tools, + stopWhen: this.stopWhen, + abortSignal: streamAbortSignal, + onChunk: ({ chunk }) => { + (0, core_1.handleStreamChunk)(chunk, (event, data) => this.emit(event, data)); + }, + onFinish: async (event) => { + for (const step of event.steps) { + for (const toolResult of step.toolResults) { + this.emit("tool_result", { + name: toolResult.toolName, + toolCallId: toolResult.toolCallId, + result: toolResult.output, + }); + } + } + }, + onError: ({ error }) => { + console.error("Stream error:", error); + this.emit("error", error); + }, + }); + const streamResult = await (0, core_1.processFullStream)(result, { + onTextDelta: (delta) => this.speech.processTextDelta(delta), + onTextEnd: () => this.speech.flushPendingText(), + sendMessage: (msg) => this.ws.send(msg), + emitEvent: (event, data) => this.emit(event, data), + }); + // Add assistant response to history + if (streamResult.fullText) { + this.conversation.addMessage({ + role: "assistant", + content: streamResult.fullText, + }); + } + // Flush any remaining speech + this.speech.flushPendingText(); + // Wait for all speech chunks to complete + if (this.speech.queueDonePromise) { + await this.speech.queueDonePromise; + } + return streamResult.fullText; + } + catch (error) { + // Clean up speech state on error + this.speech.reset(); + throw error; + } + finally { + this._isProcessing = false; + this.currentStreamAbortController = undefined; + } + } + // ── Private: helpers ────────────────────────────────── + ensureNotDestroyed() { + if (this.isDestroyed) { + throw new Error("VoiceAgent has been destroyed and cannot be used"); + } + } + /** + * Clean up all in-flight state when the connection drops. + */ + cleanupOnDisconnect() { + if (this.currentStreamAbortController) { + this.currentStreamAbortController.abort(); + this.currentStreamAbortController = undefined; + } + this.speech.reset(); + this._isProcessing = false; + this.inputQueue.rejectAll(new Error("Connection closed")); + } + /** + * Forward select events from a child emitter to this agent. + */ + bubbleEvents(source, events) { + for (const event of events) { + source.on(event, (...args) => this.emit(event, ...args)); + } + } +} +exports.VoiceAgent = VoiceAgent; +//# sourceMappingURL=VoiceAgent.new.js.map \ No newline at end of file diff --git a/dist/VoiceAgent.new.js.map b/dist/VoiceAgent.new.js.map new file mode 100644 index 0000000..99d711c --- /dev/null +++ b/dist/VoiceAgent.new.js.map @@ -0,0 +1 @@ +{"version":3,"file":"VoiceAgent.new.js","sourceRoot":"","sources":["../src/VoiceAgent.new.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/core/ConversationManager.d.ts b/dist/core/ConversationManager.d.ts new file mode 100644 index 0000000..c3c1216 --- /dev/null +++ b/dist/core/ConversationManager.d.ts @@ -0,0 +1,46 @@ +import { EventEmitter } from "events"; +import { type ModelMessage } from "ai"; +import { type HistoryConfig } from "../types"; +export interface ConversationManagerOptions { + history?: Partial; +} +/** + * Manages conversation history (ModelMessage[]) with configurable + * limits on message count and total character size. + */ +export declare class ConversationManager extends EventEmitter { + private conversationHistory; + private historyConfig; + constructor(options?: ConversationManagerOptions); + /** + * Add a message to history and trim if needed. + */ + addMessage(message: ModelMessage): void; + /** + * Get a copy of the current history. + */ + getHistory(): ModelMessage[]; + /** + * Get a direct reference to the history array. + * Use with caution — prefer getHistory() for safety. + */ + getHistoryRef(): ModelMessage[]; + /** + * Replace the entire conversation history. + */ + setHistory(history: ModelMessage[]): void; + /** + * Clear all conversation history. + */ + clearHistory(): void; + /** + * Get the number of messages in history. + */ + get length(): number; + /** + * Trim conversation history to stay within configured limits. + * Removes oldest messages (always in pairs to preserve user/assistant turns). + */ + private trimHistory; +} +//# sourceMappingURL=ConversationManager.d.ts.map \ No newline at end of file diff --git a/dist/core/ConversationManager.d.ts.map b/dist/core/ConversationManager.d.ts.map new file mode 100644 index 0000000..95deab8 --- /dev/null +++ b/dist/core/ConversationManager.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"ConversationManager.d.ts","sourceRoot":"","sources":["../../src/core/ConversationManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,IAAI,CAAC;AACvC,OAAO,EAAE,KAAK,aAAa,EAA0B,MAAM,UAAU,CAAC;AAEtE,MAAM,WAAW,0BAA0B;IACzC,OAAO,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;CAClC;AAED;;;GAGG;AACH,qBAAa,mBAAoB,SAAQ,YAAY;IACnD,OAAO,CAAC,mBAAmB,CAAsB;IACjD,OAAO,CAAC,aAAa,CAAgB;gBAEzB,OAAO,GAAE,0BAA+B;IAQpD;;OAEG;IACH,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI;IAKvC;;OAEG;IACH,UAAU,IAAI,YAAY,EAAE;IAI5B;;;OAGG;IACH,aAAa,IAAI,YAAY,EAAE;IAI/B;;OAEG;IACH,UAAU,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,IAAI;IAIzC;;OAEG;IACH,YAAY,IAAI,IAAI;IAKpB;;OAEG;IACH,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED;;;OAGG;IACH,OAAO,CAAC,WAAW;CAgDpB"} \ No newline at end of file diff --git a/dist/core/ConversationManager.js b/dist/core/ConversationManager.js new file mode 100644 index 0000000..1d17a6d --- /dev/null +++ b/dist/core/ConversationManager.js @@ -0,0 +1,106 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ConversationManager = void 0; +const events_1 = require("events"); +const types_1 = require("../types"); +/** + * Manages conversation history (ModelMessage[]) with configurable + * limits on message count and total character size. + */ +class ConversationManager extends events_1.EventEmitter { + conversationHistory = []; + historyConfig; + constructor(options = {}) { + super(); + this.historyConfig = { + ...types_1.DEFAULT_HISTORY_CONFIG, + ...options.history, + }; + } + /** + * Add a message to history and trim if needed. + */ + addMessage(message) { + this.conversationHistory.push(message); + this.trimHistory(); + } + /** + * Get a copy of the current history. + */ + getHistory() { + return [...this.conversationHistory]; + } + /** + * Get a direct reference to the history array. + * Use with caution — prefer getHistory() for safety. + */ + getHistoryRef() { + return this.conversationHistory; + } + /** + * Replace the entire conversation history. + */ + setHistory(history) { + this.conversationHistory = [...history]; + } + /** + * Clear all conversation history. + */ + clearHistory() { + this.conversationHistory = []; + this.emit("history_cleared"); + } + /** + * Get the number of messages in history. + */ + get length() { + return this.conversationHistory.length; + } + /** + * Trim conversation history to stay within configured limits. + * Removes oldest messages (always in pairs to preserve user/assistant turns). + */ + trimHistory() { + const { maxMessages, maxTotalChars } = this.historyConfig; + // Trim by message count + if (maxMessages > 0 && this.conversationHistory.length > maxMessages) { + const excess = this.conversationHistory.length - maxMessages; + // Round up to even number to preserve turn pairs + const toRemove = excess % 2 === 0 ? excess : excess + 1; + this.conversationHistory.splice(0, toRemove); + this.emit("history_trimmed", { + removedCount: toRemove, + reason: "max_messages", + }); + } + // Trim by total character count + if (maxTotalChars > 0) { + let totalChars = this.conversationHistory.reduce((sum, msg) => { + const content = typeof msg.content === "string" + ? msg.content + : JSON.stringify(msg.content); + return sum + content.length; + }, 0); + let removedCount = 0; + while (totalChars > maxTotalChars && + this.conversationHistory.length > 2) { + const removed = this.conversationHistory.shift(); + if (removed) { + const content = typeof removed.content === "string" + ? removed.content + : JSON.stringify(removed.content); + totalChars -= content.length; + removedCount++; + } + } + if (removedCount > 0) { + this.emit("history_trimmed", { + removedCount, + reason: "max_total_chars", + }); + } + } + } +} +exports.ConversationManager = ConversationManager; +//# sourceMappingURL=ConversationManager.js.map \ No newline at end of file diff --git a/dist/core/ConversationManager.js.map b/dist/core/ConversationManager.js.map new file mode 100644 index 0000000..9e2f8d3 --- /dev/null +++ b/dist/core/ConversationManager.js.map @@ -0,0 +1 @@ +{"version":3,"file":"ConversationManager.js","sourceRoot":"","sources":["../../src/core/ConversationManager.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/core/InputQueue.d.ts b/dist/core/InputQueue.d.ts new file mode 100644 index 0000000..0a1620a --- /dev/null +++ b/dist/core/InputQueue.d.ts @@ -0,0 +1,33 @@ +/** + * A generic serial input queue that ensures only one processor runs at a time. + * + * @template T The shape of each queued item (must include resolve/reject) + */ +export interface QueueItem { + resolve: (v: T) => void; + reject: (e: unknown) => void; +} +export declare class InputQueue> { + private queue; + private processing; + /** Callback invoked for each item — must return a resolved value */ + processor: (item: T) => Promise; + /** + * Enqueue an item for serial processing. + */ + enqueue(item: T): void; + /** + * Reject all pending items (used on disconnect/destroy). + */ + rejectAll(reason: Error): void; + /** + * Number of items waiting in the queue. + */ + get length(): number; + /** + * Whether the queue is currently processing an item. + */ + get isProcessing(): boolean; + private drain; +} +//# sourceMappingURL=InputQueue.d.ts.map \ No newline at end of file diff --git a/dist/core/InputQueue.d.ts.map b/dist/core/InputQueue.d.ts.map new file mode 100644 index 0000000..e797083 --- /dev/null +++ b/dist/core/InputQueue.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"InputQueue.d.ts","sourceRoot":"","sources":["../../src/core/InputQueue.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,WAAW,SAAS,CAAC,CAAC,GAAG,MAAM;IACnC,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC;IACxB,MAAM,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;CAC9B;AAED,qBAAa,UAAU,CAAC,CAAC,SAAS,SAAS,CAAC,GAAG,CAAC;IAC9C,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,UAAU,CAAS;IAE3B,oEAAoE;IAC7D,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,GAAG,CAAC,CAAkB;IAE7D;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI;IAKtB;;OAEG;IACH,SAAS,CAAC,MAAM,EAAE,KAAK,GAAG,IAAI;IAQ9B;;OAEG;IACH,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED;;OAEG;IACH,IAAI,YAAY,IAAI,OAAO,CAE1B;YAIa,KAAK;CAkBpB"} \ No newline at end of file diff --git a/dist/core/InputQueue.js b/dist/core/InputQueue.js new file mode 100644 index 0000000..fa101ae --- /dev/null +++ b/dist/core/InputQueue.js @@ -0,0 +1,61 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.InputQueue = void 0; +class InputQueue { + queue = []; + processing = false; + /** Callback invoked for each item — must return a resolved value */ + processor = async () => ""; + /** + * Enqueue an item for serial processing. + */ + enqueue(item) { + this.queue.push(item); + this.drain(); + } + /** + * Reject all pending items (used on disconnect/destroy). + */ + rejectAll(reason) { + for (const item of this.queue) { + item.reject(reason); + } + this.queue = []; + this.processing = false; + } + /** + * Number of items waiting in the queue. + */ + get length() { + return this.queue.length; + } + /** + * Whether the queue is currently processing an item. + */ + get isProcessing() { + return this.processing; + } + // ── Private ────────────────────────────────────────── + async drain() { + if (this.processing) + return; + this.processing = true; + try { + while (this.queue.length > 0) { + const item = this.queue.shift(); + try { + const result = await this.processor(item); + item.resolve(result); + } + catch (error) { + item.reject(error); + } + } + } + finally { + this.processing = false; + } + } +} +exports.InputQueue = InputQueue; +//# sourceMappingURL=InputQueue.js.map \ No newline at end of file diff --git a/dist/core/InputQueue.js.map b/dist/core/InputQueue.js.map new file mode 100644 index 0000000..28d6f54 --- /dev/null +++ b/dist/core/InputQueue.js.map @@ -0,0 +1 @@ +{"version":3,"file":"InputQueue.js","sourceRoot":"","sources":["../../src/core/InputQueue.ts"],"names":[],"mappings":";;;AAUA,MAAa,UAAU;IACb,KAAK,GAAQ,EAAE,CAAC;IAChB,UAAU,GAAG,KAAK,CAAC;IAE3B,oEAAoE;IAC7D,SAAS,GAA8B,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC;IAE7D;;OAEG;IACH,OAAO,CAAC,IAAO;QACb,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtB,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;IAED;;OAEG;IACH,SAAS,CAAC,MAAa;QACrB,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC9B,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACtB,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAChB,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;IAC1B,CAAC;IAED;;OAEG;IACH,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,IAAI,YAAY;QACd,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAED,wDAAwD;IAEhD,KAAK,CAAC,KAAK;QACjB,IAAI,IAAI,CAAC,UAAU;YAAE,OAAO;QAC5B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QAEvB,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAG,CAAC;gBACjC,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;oBAC1C,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBACvB,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACrB,CAAC;YACH,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QAC1B,CAAC;IACH,CAAC;CACF;AA5DD,gCA4DC"} \ No newline at end of file diff --git a/dist/core/SpeechManager.d.ts b/dist/core/SpeechManager.d.ts new file mode 100644 index 0000000..5e30778 --- /dev/null +++ b/dist/core/SpeechManager.d.ts @@ -0,0 +1,83 @@ +import { EventEmitter } from "events"; +import { type SpeechModel } from "ai"; +import { type StreamingSpeechConfig } from "../types"; +export interface SpeechManagerOptions { + speechModel?: SpeechModel; + voice?: string; + speechInstructions?: string; + outputFormat?: string; + streamingSpeech?: Partial; +} +/** + * Manages text-to-speech generation, streaming speech chunking, + * parallel TTS requests, and speech interruption. + */ +export declare class SpeechManager extends EventEmitter { + private speechModel?; + private voice; + private speechInstructions?; + private outputFormat; + private streamingSpeechConfig; + private currentSpeechAbortController?; + private speechChunkQueue; + private nextChunkId; + private _isSpeaking; + private pendingTextBuffer; + private speechQueueDonePromise?; + private speechQueueDoneResolve?; + /** Callback to send messages over the WebSocket */ + sendMessage: (message: Record) => void; + constructor(options: SpeechManagerOptions); + get isSpeaking(): boolean; + get pendingChunkCount(): number; + get hasSpeechModel(): boolean; + /** + * Returns a promise that resolves when the speech queue is fully drained. + * Returns undefined if there is nothing queued. + */ + get queueDonePromise(): Promise | undefined; + /** + * Generate speech from text using the configured speech model. + */ + generateSpeechFromText(text: string, abortSignal?: AbortSignal): Promise; + /** + * Generate speech for full text at once (non-streaming fallback). + */ + generateAndSendSpeechFull(text: string): Promise; + /** + * Interrupt ongoing speech generation and playback (barge-in support). + */ + interruptSpeech(reason?: string): void; + /** + * Process a text delta for streaming speech. + * Call this as text chunks arrive from the LLM. + */ + processTextDelta(textDelta: string): void; + /** + * Flush any remaining text in the buffer to speech. + * Call this when the LLM stream ends. + */ + flushPendingText(): void; + /** + * Reset all speech state (used on disconnect / cleanup). + */ + reset(): void; + /** + * Extract complete sentences from text buffer. + * Returns [extractedSentences, remainingBuffer]. + */ + private extractSentences; + /** + * Queue a text chunk for speech generation. + */ + private queueSpeechChunk; + /** + * Generate audio for a single chunk. + */ + private generateChunkAudio; + /** + * Process the speech queue and send audio chunks in order. + */ + private processSpeechQueue; +} +//# sourceMappingURL=SpeechManager.d.ts.map \ No newline at end of file diff --git a/dist/core/SpeechManager.d.ts.map b/dist/core/SpeechManager.d.ts.map new file mode 100644 index 0000000..c3df2be --- /dev/null +++ b/dist/core/SpeechManager.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"SpeechManager.d.ts","sourceRoot":"","sources":["../../src/core/SpeechManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAEL,KAAK,WAAW,EACjB,MAAM,IAAI,CAAC;AACZ,OAAO,EAEL,KAAK,qBAAqB,EAE3B,MAAM,UAAU,CAAC;AAElB,MAAM,WAAW,oBAAoB;IACnC,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;CAClD;AAED;;;GAGG;AACH,qBAAa,aAAc,SAAQ,YAAY;IAC7C,OAAO,CAAC,WAAW,CAAC,CAAc;IAClC,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,kBAAkB,CAAC,CAAS;IACpC,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,qBAAqB,CAAwB;IAErD,OAAO,CAAC,4BAA4B,CAAC,CAAkB;IACvD,OAAO,CAAC,gBAAgB,CAAqB;IAC7C,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,iBAAiB,CAAM;IAG/B,OAAO,CAAC,sBAAsB,CAAC,CAAgB;IAC/C,OAAO,CAAC,sBAAsB,CAAC,CAAa;IAE5C,mDAAmD;IAC5C,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAa;gBAE/D,OAAO,EAAE,oBAAoB;IAYzC,IAAI,UAAU,IAAI,OAAO,CAExB;IAED,IAAI,iBAAiB,IAAI,MAAM,CAE9B;IAED,IAAI,cAAc,IAAI,OAAO,CAE5B;IAED;;;OAGG;IACH,IAAI,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,SAAS,CAEhD;IAED;;OAEG;IACG,sBAAsB,CAC1B,IAAI,EAAE,MAAM,EACZ,WAAW,CAAC,EAAE,WAAW,GACxB,OAAO,CAAC,UAAU,CAAC;IAiBtB;;OAEG;IACG,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA4B5D;;OAEG;IACH,eAAe,CAAC,MAAM,GAAE,MAAsB,GAAG,IAAI;IAgCrD;;;OAGG;IACH,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAazC;;;OAGG;IACH,gBAAgB,IAAI,IAAI;IAOxB;;OAEG;IACH,KAAK,IAAI,IAAI;IAkBb;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IA+CxB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAwCxB;;OAEG;YACW,kBAAkB;IAiChC;;OAEG;YACW,kBAAkB;CA0GjC"} \ No newline at end of file diff --git a/dist/core/SpeechManager.js b/dist/core/SpeechManager.js new file mode 100644 index 0000000..fa53659 --- /dev/null +++ b/dist/core/SpeechManager.js @@ -0,0 +1,356 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.SpeechManager = void 0; +const events_1 = require("events"); +const ai_1 = require("ai"); +const types_1 = require("../types"); +/** + * Manages text-to-speech generation, streaming speech chunking, + * parallel TTS requests, and speech interruption. + */ +class SpeechManager extends events_1.EventEmitter { + speechModel; + voice; + speechInstructions; + outputFormat; + streamingSpeechConfig; + currentSpeechAbortController; + speechChunkQueue = []; + nextChunkId = 0; + _isSpeaking = false; + pendingTextBuffer = ""; + // Promise-based signal for speech queue completion + speechQueueDonePromise; + speechQueueDoneResolve; + /** Callback to send messages over the WebSocket */ + sendMessage = () => { }; + constructor(options) { + super(); + this.speechModel = options.speechModel; + this.voice = options.voice || "alloy"; + this.speechInstructions = options.speechInstructions; + this.outputFormat = options.outputFormat || "opus"; + this.streamingSpeechConfig = { + ...types_1.DEFAULT_STREAMING_SPEECH_CONFIG, + ...options.streamingSpeech, + }; + } + get isSpeaking() { + return this._isSpeaking; + } + get pendingChunkCount() { + return this.speechChunkQueue.length; + } + get hasSpeechModel() { + return !!this.speechModel; + } + /** + * Returns a promise that resolves when the speech queue is fully drained. + * Returns undefined if there is nothing queued. + */ + get queueDonePromise() { + return this.speechQueueDonePromise; + } + /** + * Generate speech from text using the configured speech model. + */ + async generateSpeechFromText(text, abortSignal) { + if (!this.speechModel) { + throw new Error("Speech model not configured"); + } + const result = await (0, ai_1.experimental_generateSpeech)({ + model: this.speechModel, + text, + voice: this.voice, + instructions: this.speechInstructions, + outputFormat: this.outputFormat, + abortSignal, + }); + return result.audio.uint8Array; + } + /** + * Generate speech for full text at once (non-streaming fallback). + */ + async generateAndSendSpeechFull(text) { + if (!this.speechModel) + return; + try { + this.emit("speech_start", { text, streaming: false }); + const audioData = await this.generateSpeechFromText(text); + const base64Audio = Buffer.from(audioData).toString("base64"); + this.sendMessage({ + type: "audio", + data: base64Audio, + format: this.outputFormat, + }); + this.emit("audio", { + data: base64Audio, + format: this.outputFormat, + uint8Array: audioData, + }); + this.emit("speech_complete", { text, streaming: false }); + } + catch (error) { + console.error("Failed to generate speech:", error); + this.emit("error", error); + } + } + /** + * Interrupt ongoing speech generation and playback (barge-in support). + */ + interruptSpeech(reason = "interrupted") { + if (!this._isSpeaking && this.speechChunkQueue.length === 0) { + return; + } + // Abort any pending speech generation requests + if (this.currentSpeechAbortController) { + this.currentSpeechAbortController.abort(); + this.currentSpeechAbortController = undefined; + } + // Clear the speech queue + this.speechChunkQueue = []; + this.pendingTextBuffer = ""; + this._isSpeaking = false; + // Resolve any pending speech-done waiters so callers can finish + if (this.speechQueueDoneResolve) { + this.speechQueueDoneResolve(); + this.speechQueueDoneResolve = undefined; + this.speechQueueDonePromise = undefined; + } + // Notify clients to stop audio playback + this.sendMessage({ + type: "speech_interrupted", + reason, + }); + this.emit("speech_interrupted", { reason }); + } + /** + * Process a text delta for streaming speech. + * Call this as text chunks arrive from the LLM. + */ + processTextDelta(textDelta) { + if (!this.speechModel) + return; + this.pendingTextBuffer += textDelta; + const [sentences, remaining] = this.extractSentences(this.pendingTextBuffer); + this.pendingTextBuffer = remaining; + for (const sentence of sentences) { + this.queueSpeechChunk(sentence); + } + } + /** + * Flush any remaining text in the buffer to speech. + * Call this when the LLM stream ends. + */ + flushPendingText() { + if (!this.speechModel || !this.pendingTextBuffer.trim()) + return; + this.queueSpeechChunk(this.pendingTextBuffer); + this.pendingTextBuffer = ""; + } + /** + * Reset all speech state (used on disconnect / cleanup). + */ + reset() { + if (this.currentSpeechAbortController) { + this.currentSpeechAbortController.abort(); + this.currentSpeechAbortController = undefined; + } + this.speechChunkQueue = []; + this.pendingTextBuffer = ""; + this._isSpeaking = false; + if (this.speechQueueDoneResolve) { + this.speechQueueDoneResolve(); + this.speechQueueDoneResolve = undefined; + this.speechQueueDonePromise = undefined; + } + } + // ── Private helpers ───────────────────────────────────────── + /** + * Extract complete sentences from text buffer. + * Returns [extractedSentences, remainingBuffer]. + */ + extractSentences(text) { + const sentences = []; + let remaining = text; + // Match sentences ending with . ! ? followed by space or end of string + const sentenceEndPattern = /[.!?]+(?:\s+|$)/g; + let lastIndex = 0; + let match; + while ((match = sentenceEndPattern.exec(text)) !== null) { + const sentence = text + .slice(lastIndex, match.index + match[0].length) + .trim(); + if (sentence.length >= this.streamingSpeechConfig.minChunkSize) { + sentences.push(sentence); + lastIndex = match.index + match[0].length; + } + else if (sentences.length > 0) { + // Append short sentence to previous one + sentences[sentences.length - 1] += " " + sentence; + lastIndex = match.index + match[0].length; + } + } + remaining = text.slice(lastIndex); + // If remaining text is too long, force split at clause boundaries + if (remaining.length > this.streamingSpeechConfig.maxChunkSize) { + const clausePattern = /[,;:]\s+/g; + let clauseMatch; + let splitIndex = 0; + while ((clauseMatch = clausePattern.exec(remaining)) !== null) { + if (clauseMatch.index >= this.streamingSpeechConfig.minChunkSize) { + splitIndex = clauseMatch.index + clauseMatch[0].length; + break; + } + } + if (splitIndex > 0) { + sentences.push(remaining.slice(0, splitIndex).trim()); + remaining = remaining.slice(splitIndex); + } + } + return [sentences, remaining]; + } + /** + * Queue a text chunk for speech generation. + */ + queueSpeechChunk(text) { + if (!this.speechModel || !text.trim()) + return; + // Wrap chunk ID to prevent unbounded growth in very long sessions + if (this.nextChunkId >= Number.MAX_SAFE_INTEGER) { + this.nextChunkId = 0; + } + const chunk = { + id: this.nextChunkId++, + text: text.trim(), + }; + // Create the speech-done promise if not already present + if (!this.speechQueueDonePromise) { + this.speechQueueDonePromise = new Promise((resolve) => { + this.speechQueueDoneResolve = resolve; + }); + } + // Start generating audio immediately (parallel generation) + if (this.streamingSpeechConfig.parallelGeneration) { + const activeRequests = this.speechChunkQueue.filter((c) => c.audioPromise).length; + if (activeRequests < this.streamingSpeechConfig.maxParallelRequests) { + chunk.audioPromise = this.generateChunkAudio(chunk); + } + } + this.speechChunkQueue.push(chunk); + this.emit("speech_chunk_queued", { id: chunk.id, text: chunk.text }); + // Start processing queue if not already + if (!this._isSpeaking) { + this.processSpeechQueue(); + } + } + /** + * Generate audio for a single chunk. + */ + async generateChunkAudio(chunk) { + if (!this.currentSpeechAbortController) { + this.currentSpeechAbortController = new AbortController(); + } + try { + console.log(`Generating audio for chunk ${chunk.id}: "${chunk.text.substring(0, 50)}${chunk.text.length > 50 ? "..." : ""}"`); + const audioData = await this.generateSpeechFromText(chunk.text, this.currentSpeechAbortController.signal); + console.log(`Generated audio for chunk ${chunk.id}: ${audioData.length} bytes`); + return audioData; + } + catch (error) { + if (error.name === "AbortError") { + console.log(`Audio generation aborted for chunk ${chunk.id}`); + return null; + } + console.error(`Failed to generate audio for chunk ${chunk.id}:`, error); + this.emit("error", error); + return null; + } + } + /** + * Process the speech queue and send audio chunks in order. + */ + async processSpeechQueue() { + if (this._isSpeaking) + return; + this._isSpeaking = true; + console.log(`Starting speech queue processing with ${this.speechChunkQueue.length} chunks`); + this.emit("speech_start", { streaming: true }); + this.sendMessage({ type: "speech_stream_start" }); + try { + while (this.speechChunkQueue.length > 0) { + const chunk = this.speechChunkQueue[0]; + console.log(`Processing speech chunk #${chunk.id} (${this.speechChunkQueue.length - 1} remaining)`); + // Ensure audio generation has started + if (!chunk.audioPromise) { + chunk.audioPromise = this.generateChunkAudio(chunk); + } + // Wait for this chunk's audio + const audioData = await chunk.audioPromise; + // Check if we were interrupted while waiting + if (!this._isSpeaking) { + console.log(`Speech interrupted during chunk #${chunk.id}`); + break; + } + // Remove from queue after processing + this.speechChunkQueue.shift(); + if (audioData) { + const base64Audio = Buffer.from(audioData).toString("base64"); + console.log(`Sending audio chunk #${chunk.id} (${audioData.length} bytes, ${this.outputFormat})`); + // Send audio chunk via WebSocket + this.sendMessage({ + type: "audio_chunk", + chunkId: chunk.id, + data: base64Audio, + format: this.outputFormat, + text: chunk.text, + }); + // Emit for local handling + this.emit("audio_chunk", { + chunkId: chunk.id, + data: base64Audio, + format: this.outputFormat, + text: chunk.text, + uint8Array: audioData, + }); + } + else { + console.log(`No audio data generated for chunk #${chunk.id}`); + } + // Start generating next chunks in parallel + if (this.streamingSpeechConfig.parallelGeneration) { + const activeRequests = this.speechChunkQueue.filter((c) => c.audioPromise).length; + const toStart = Math.min(this.streamingSpeechConfig.maxParallelRequests - activeRequests, this.speechChunkQueue.length); + if (toStart > 0) { + console.log(`Starting parallel generation for ${toStart} more chunks`); + for (let i = 0; i < toStart; i++) { + const nextChunk = this.speechChunkQueue.find((c) => !c.audioPromise); + if (nextChunk) { + nextChunk.audioPromise = this.generateChunkAudio(nextChunk); + } + } + } + } + } + } + catch (error) { + console.error("Error in speech queue processing:", error); + this.emit("error", error); + } + finally { + this._isSpeaking = false; + this.currentSpeechAbortController = undefined; + // Signal that the speech queue is fully drained + if (this.speechQueueDoneResolve) { + this.speechQueueDoneResolve(); + this.speechQueueDoneResolve = undefined; + this.speechQueueDonePromise = undefined; + } + console.log(`Speech queue processing complete`); + this.sendMessage({ type: "speech_stream_end" }); + this.emit("speech_complete", { streaming: true }); + } + } +} +exports.SpeechManager = SpeechManager; +//# sourceMappingURL=SpeechManager.js.map \ No newline at end of file diff --git a/dist/core/SpeechManager.js.map b/dist/core/SpeechManager.js.map new file mode 100644 index 0000000..073d1aa --- /dev/null +++ b/dist/core/SpeechManager.js.map @@ -0,0 +1 @@ +{"version":3,"file":"SpeechManager.js","sourceRoot":"","sources":["../../src/core/SpeechManager.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/core/StreamProcessor.d.ts b/dist/core/StreamProcessor.d.ts new file mode 100644 index 0000000..7e15f84 --- /dev/null +++ b/dist/core/StreamProcessor.d.ts @@ -0,0 +1,42 @@ +import { type streamText } from "ai"; +/** + * Result of processing a full LLM stream. + */ +export interface StreamResult { + fullText: string; + fullReasoning: string; + allToolCalls: Array<{ + toolName: string; + toolCallId: string; + input: unknown; + }>; + allToolResults: Array<{ + toolName: string; + toolCallId: string; + output: unknown; + }>; + allSources: Array; + allFiles: Array; +} +export interface StreamProcessorCallbacks { + /** Called when a text delta arrives (for streaming speech, etc.) */ + onTextDelta?: (text: string) => void; + /** Called when a text-end part arrives (flush speech, etc.) */ + onTextEnd?: () => void; + /** Send a WebSocket message */ + sendMessage: (message: Record) => void; + /** Emit an event on the agent */ + emitEvent: (event: string, data?: unknown) => void; +} +/** + * Processes the fullStream from an AI SDK `streamText` call, + * forwarding events to WebSocket clients and collecting the complete response. + * + * This is a standalone function (not a class) because it has no persistent state. + */ +export declare function processFullStream(result: ReturnType, callbacks: StreamProcessorCallbacks, extraResponseFields?: Record): Promise; +/** + * Handle onChunk callback events and emit them. + */ +export declare function handleStreamChunk(chunk: any, emitEvent: (event: string, data?: unknown) => void): void; +//# sourceMappingURL=StreamProcessor.d.ts.map \ No newline at end of file diff --git a/dist/core/StreamProcessor.d.ts.map b/dist/core/StreamProcessor.d.ts.map new file mode 100644 index 0000000..a886f9e --- /dev/null +++ b/dist/core/StreamProcessor.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"StreamProcessor.d.ts","sourceRoot":"","sources":["../../src/core/StreamProcessor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,IAAI,CAAC;AAErC;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,KAAK,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,EAAE,OAAO,CAAC;KAChB,CAAC,CAAC;IACH,cAAc,EAAE,KAAK,CAAC;QACpB,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,OAAO,CAAC;KACjB,CAAC,CAAC;IACH,UAAU,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAC3B,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;CAC1B;AAED,MAAM,WAAW,wBAAwB;IACvC,oEAAoE;IACpE,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,+BAA+B;IAC/B,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACxD,iCAAiC;IACjC,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;CACpD;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,EACrC,SAAS,EAAE,wBAAwB,EACnC,mBAAmB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5C,OAAO,CAAC,YAAY,CAAC,CAkMvB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,GAAG,EACV,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,GACjD,IAAI,CA+CN"} \ No newline at end of file diff --git a/dist/core/StreamProcessor.js b/dist/core/StreamProcessor.js new file mode 100644 index 0000000..4f84d0c --- /dev/null +++ b/dist/core/StreamProcessor.js @@ -0,0 +1,228 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.processFullStream = processFullStream; +exports.handleStreamChunk = handleStreamChunk; +/** + * Processes the fullStream from an AI SDK `streamText` call, + * forwarding events to WebSocket clients and collecting the complete response. + * + * This is a standalone function (not a class) because it has no persistent state. + */ +async function processFullStream(result, callbacks, extraResponseFields) { + const { onTextDelta, onTextEnd, sendMessage, emitEvent } = callbacks; + let fullText = ""; + let fullReasoning = ""; + const allToolCalls = []; + const allToolResults = []; + const allSources = []; + const allFiles = []; + for await (const part of result.fullStream) { + switch (part.type) { + // ── Stream lifecycle ────────────────────────────── + case "start": + sendMessage({ type: "stream_start" }); + break; + case "finish": + emitEvent("text", { role: "assistant", text: fullText }); + sendMessage({ + type: "stream_finish", + finishReason: part.finishReason, + usage: part.totalUsage, + }); + break; + case "error": + emitEvent("error", part.error); + sendMessage({ + type: "stream_error", + error: String(part.error), + }); + break; + case "abort": + emitEvent("abort", { reason: part.reason }); + sendMessage({ + type: "stream_abort", + reason: part.reason, + }); + break; + // ── Step lifecycle ──────────────────────────────── + case "start-step": + sendMessage({ + type: "step_start", + warnings: part.warnings, + }); + break; + case "finish-step": + sendMessage({ + type: "step_finish", + finishReason: part.finishReason, + usage: part.usage, + }); + break; + // ── Text streaming ──────────────────────────────── + case "text-start": + sendMessage({ type: "text_start", id: part.id }); + break; + case "text-delta": + fullText += part.text; + onTextDelta?.(part.text); + sendMessage({ + type: "text_delta", + id: part.id, + text: part.text, + }); + break; + case "text-end": + onTextEnd?.(); + sendMessage({ type: "text_end", id: part.id }); + break; + // ── Reasoning streaming ─────────────────────────── + case "reasoning-start": + sendMessage({ type: "reasoning_start", id: part.id }); + break; + case "reasoning-delta": + fullReasoning += part.text; + sendMessage({ + type: "reasoning_delta", + id: part.id, + text: part.text, + }); + break; + case "reasoning-end": + sendMessage({ type: "reasoning_end", id: part.id }); + break; + // ── Tool input streaming ────────────────────────── + case "tool-input-start": + sendMessage({ + type: "tool_input_start", + id: part.id, + toolName: part.toolName, + }); + break; + case "tool-input-delta": + sendMessage({ + type: "tool_input_delta", + id: part.id, + delta: part.delta, + }); + break; + case "tool-input-end": + sendMessage({ type: "tool_input_end", id: part.id }); + break; + // ── Tool execution ──────────────────────────────── + case "tool-call": + allToolCalls.push({ + toolName: part.toolName, + toolCallId: part.toolCallId, + input: part.input, + }); + sendMessage({ + type: "tool_call", + toolName: part.toolName, + toolCallId: part.toolCallId, + input: part.input, + }); + break; + case "tool-result": + allToolResults.push({ + toolName: part.toolName, + toolCallId: part.toolCallId, + output: part.output, + }); + sendMessage({ + type: "tool_result", + toolName: part.toolName, + toolCallId: part.toolCallId, + result: part.output, + }); + break; + case "tool-error": + sendMessage({ + type: "tool_error", + toolName: part.toolName, + toolCallId: part.toolCallId, + error: String(part.error), + }); + break; + // ── Sources and files ───────────────────────────── + case "source": + allSources.push(part); + sendMessage({ + type: "source", + source: part, + }); + break; + case "file": + allFiles.push(part.file); + sendMessage({ + type: "file", + file: part.file, + }); + break; + } + } + // Send the complete response + sendMessage({ + type: "response_complete", + text: fullText, + reasoning: fullReasoning || undefined, + toolCalls: allToolCalls, + toolResults: allToolResults, + sources: allSources.length > 0 ? allSources : undefined, + files: allFiles.length > 0 ? allFiles : undefined, + ...extraResponseFields, + }); + return { + fullText, + fullReasoning, + allToolCalls, + allToolResults, + allSources, + allFiles, + }; +} +/** + * Handle onChunk callback events and emit them. + */ +function handleStreamChunk(chunk, emitEvent) { + switch (chunk.type) { + case "text-delta": + emitEvent("chunk:text_delta", { id: chunk.id, text: chunk.text }); + break; + case "reasoning-delta": + emitEvent("chunk:reasoning_delta", { + id: chunk.id, + text: chunk.text, + }); + break; + case "tool-call": + emitEvent("chunk:tool_call", { + toolName: chunk.toolName, + toolCallId: chunk.toolCallId, + input: chunk.input, + }); + break; + case "tool-result": + emitEvent("chunk:tool_result", { + toolName: chunk.toolName, + toolCallId: chunk.toolCallId, + result: chunk.output, + }); + break; + case "tool-input-start": + emitEvent("chunk:tool_input_start", { + id: chunk.id, + toolName: chunk.toolName, + }); + break; + case "tool-input-delta": + emitEvent("chunk:tool_input_delta", { + id: chunk.id, + delta: chunk.delta, + }); + break; + case "source": + emitEvent("chunk:source", chunk); + break; + } +} +//# sourceMappingURL=StreamProcessor.js.map \ No newline at end of file diff --git a/dist/core/StreamProcessor.js.map b/dist/core/StreamProcessor.js.map new file mode 100644 index 0000000..3a7c7bc --- /dev/null +++ b/dist/core/StreamProcessor.js.map @@ -0,0 +1 @@ +{"version":3,"file":"StreamProcessor.js","sourceRoot":"","sources":["../../src/core/StreamProcessor.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/core/TranscriptionManager.d.ts b/dist/core/TranscriptionManager.d.ts new file mode 100644 index 0000000..646de97 --- /dev/null +++ b/dist/core/TranscriptionManager.d.ts @@ -0,0 +1,28 @@ +import { EventEmitter } from "events"; +import { type TranscriptionModel } from "ai"; +export interface TranscriptionManagerOptions { + transcriptionModel?: TranscriptionModel; + maxAudioInputSize?: number; +} +/** + * Handles audio transcription using the AI SDK transcription model + * and validation of incoming audio data. + */ +export declare class TranscriptionManager extends EventEmitter { + private transcriptionModel?; + private maxAudioInputSize; + /** Callback to send messages over the WebSocket */ + sendMessage: (message: Record) => void; + constructor(options?: TranscriptionManagerOptions); + get hasTranscriptionModel(): boolean; + /** + * Transcribe audio data to text. + */ + transcribeAudio(audioData: Buffer | Uint8Array): Promise; + /** + * Process incoming base64-encoded audio: validate, decode, transcribe. + * Returns the transcribed text, or null if invalid / empty. + */ + processAudioInput(base64Audio: string, format?: string): Promise; +} +//# sourceMappingURL=TranscriptionManager.d.ts.map \ No newline at end of file diff --git a/dist/core/TranscriptionManager.d.ts.map b/dist/core/TranscriptionManager.d.ts.map new file mode 100644 index 0000000..acd5ae8 --- /dev/null +++ b/dist/core/TranscriptionManager.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"TranscriptionManager.d.ts","sourceRoot":"","sources":["../../src/core/TranscriptionManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAEL,KAAK,kBAAkB,EACxB,MAAM,IAAI,CAAC;AAGZ,MAAM,WAAW,2BAA2B;IAC1C,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;GAGG;AACH,qBAAa,oBAAqB,SAAQ,YAAY;IACpD,OAAO,CAAC,kBAAkB,CAAC,CAAqB;IAChD,OAAO,CAAC,iBAAiB,CAAS;IAElC,mDAAmD;IAC5C,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAY;gBAE9D,OAAO,GAAE,2BAAgC;IAOrD,IAAI,qBAAqB,IAAI,OAAO,CAEnC;IAED;;OAEG;IACG,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;IAsCtE;;;OAGG;IACG,iBAAiB,CACrB,WAAW,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CA2D1B"} \ No newline at end of file diff --git a/dist/core/TranscriptionManager.js b/dist/core/TranscriptionManager.js new file mode 100644 index 0000000..410a3be --- /dev/null +++ b/dist/core/TranscriptionManager.js @@ -0,0 +1,106 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TranscriptionManager = void 0; +const events_1 = require("events"); +const ai_1 = require("ai"); +const types_1 = require("../types"); +/** + * Handles audio transcription using the AI SDK transcription model + * and validation of incoming audio data. + */ +class TranscriptionManager extends events_1.EventEmitter { + transcriptionModel; + maxAudioInputSize; + /** Callback to send messages over the WebSocket */ + sendMessage = () => { }; + constructor(options = {}) { + super(); + this.transcriptionModel = options.transcriptionModel; + this.maxAudioInputSize = + options.maxAudioInputSize ?? types_1.DEFAULT_MAX_AUDIO_SIZE; + } + get hasTranscriptionModel() { + return !!this.transcriptionModel; + } + /** + * Transcribe audio data to text. + */ + async transcribeAudio(audioData) { + if (!this.transcriptionModel) { + throw new Error("Transcription model not configured"); + } + console.log(`Sending ${audioData.byteLength} bytes to Whisper for transcription`); + try { + const result = await (0, ai_1.experimental_transcribe)({ + model: this.transcriptionModel, + audio: audioData, + }); + console.log(`Whisper transcription result: "${result.text}", language: ${result.language || "unknown"}`); + this.emit("transcription", { + text: result.text, + language: result.language, + }); + // Send transcription to client for immediate feedback + this.sendMessage({ + type: "transcription_result", + text: result.text, + language: result.language, + }); + return result.text; + } + catch (error) { + console.error("Whisper transcription failed:", error); + throw error; + } + } + /** + * Process incoming base64-encoded audio: validate, decode, transcribe. + * Returns the transcribed text, or null if invalid / empty. + */ + async processAudioInput(base64Audio, format) { + if (!this.transcriptionModel) { + const error = new Error("Transcription model not configured for audio input"); + this.emit("error", error); + this.sendMessage({ type: "error", error: error.message }); + return null; + } + try { + const audioBuffer = Buffer.from(base64Audio, "base64"); + // Validate audio size + if (audioBuffer.length > this.maxAudioInputSize) { + const sizeMB = (audioBuffer.length / (1024 * 1024)).toFixed(1); + const maxMB = (this.maxAudioInputSize / (1024 * 1024)).toFixed(1); + this.emit("error", new Error(`Audio input too large (${sizeMB} MB). Maximum allowed: ${maxMB} MB`)); + return null; + } + if (audioBuffer.length === 0) { + this.emit("warning", "Received empty audio data"); + return null; + } + this.emit("audio_received", { size: audioBuffer.length, format }); + console.log(`Processing audio input: ${audioBuffer.length} bytes, format: ${format || "unknown"}`); + const transcribedText = await this.transcribeAudio(audioBuffer); + console.log(`Transcribed text: "${transcribedText}"`); + if (!transcribedText.trim()) { + this.emit("warning", "Transcription returned empty text"); + this.sendMessage({ + type: "transcription_error", + error: "Whisper returned empty text", + }); + return null; + } + return transcribedText; + } + catch (error) { + console.error("Failed to process audio input:", error); + this.emit("error", error); + this.sendMessage({ + type: "transcription_error", + error: `Transcription failed: ${error.message || String(error)}`, + }); + return null; + } + } +} +exports.TranscriptionManager = TranscriptionManager; +//# sourceMappingURL=TranscriptionManager.js.map \ No newline at end of file diff --git a/dist/core/TranscriptionManager.js.map b/dist/core/TranscriptionManager.js.map new file mode 100644 index 0000000..0046c14 --- /dev/null +++ b/dist/core/TranscriptionManager.js.map @@ -0,0 +1 @@ +{"version":3,"file":"TranscriptionManager.js","sourceRoot":"","sources":["../../src/core/TranscriptionManager.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/core/WebSocketManager.d.ts b/dist/core/WebSocketManager.d.ts new file mode 100644 index 0000000..df556ae --- /dev/null +++ b/dist/core/WebSocketManager.d.ts @@ -0,0 +1,35 @@ +import { WebSocket } from "ws"; +import { EventEmitter } from "events"; +/** + * Manages a single WebSocket connection lifecycle. + * Handles connecting, attaching existing sockets, sending messages, + * and clean disconnection. + */ +export declare class WebSocketManager extends EventEmitter { + private socket?; + private _isConnected; + get isConnected(): boolean; + get currentSocket(): WebSocket | undefined; + /** + * Connect to a WebSocket server by URL. + */ + connect(url: string): Promise; + /** + * Attach an existing WebSocket (server-side usage). + */ + handleSocket(socket: WebSocket): void; + /** + * Send a JSON message via WebSocket if connected. + * Gracefully handles send failures (e.g., socket closing mid-send). + */ + send(message: Record): void; + /** + * Disconnect and clean up the current socket. + */ + disconnect(): void; + /** + * Attach internal event listeners on the current socket. + */ + private attachListeners; +} +//# sourceMappingURL=WebSocketManager.d.ts.map \ No newline at end of file diff --git a/dist/core/WebSocketManager.d.ts.map b/dist/core/WebSocketManager.d.ts.map new file mode 100644 index 0000000..14fe38c --- /dev/null +++ b/dist/core/WebSocketManager.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"WebSocketManager.d.ts","sourceRoot":"","sources":["../../src/core/WebSocketManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC;;;;GAIG;AACH,qBAAa,gBAAiB,SAAQ,YAAY;IAChD,OAAO,CAAC,MAAM,CAAC,CAAY;IAC3B,OAAO,CAAC,YAAY,CAAS;IAE7B,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED,IAAI,aAAa,IAAI,SAAS,GAAG,SAAS,CAEzC;IAED;;OAEG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA0BnC;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI;IAYrC;;;OAGG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAgB5C;;OAEG;IACH,UAAU,IAAI,IAAI;IAmBlB;;OAEG;IACH,OAAO,CAAC,eAAe;CAuBxB"} \ No newline at end of file diff --git a/dist/core/WebSocketManager.js b/dist/core/WebSocketManager.js new file mode 100644 index 0000000..dfe009f --- /dev/null +++ b/dist/core/WebSocketManager.js @@ -0,0 +1,126 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.WebSocketManager = void 0; +const ws_1 = require("ws"); +const events_1 = require("events"); +/** + * Manages a single WebSocket connection lifecycle. + * Handles connecting, attaching existing sockets, sending messages, + * and clean disconnection. + */ +class WebSocketManager extends events_1.EventEmitter { + socket; + _isConnected = false; + get isConnected() { + return this._isConnected; + } + get currentSocket() { + return this.socket; + } + /** + * Connect to a WebSocket server by URL. + */ + connect(url) { + // Clean up any existing connection first + if (this.socket) { + this.disconnect(); + } + return new Promise((resolve, reject) => { + try { + this.socket = new ws_1.WebSocket(url); + this.attachListeners(); + this.socket.once("open", () => { + this._isConnected = true; + this.emit("connected"); + resolve(); + }); + this.socket.once("error", (error) => { + reject(error); + }); + } + catch (error) { + reject(error); + } + }); + } + /** + * Attach an existing WebSocket (server-side usage). + */ + handleSocket(socket) { + // Clean up any existing connection first + if (this.socket) { + this.disconnect(); + } + this.socket = socket; + this._isConnected = true; + this.attachListeners(); + this.emit("connected"); + } + /** + * Send a JSON message via WebSocket if connected. + * Gracefully handles send failures (e.g., socket closing mid-send). + */ + send(message) { + if (!this.socket || !this._isConnected) + return; + try { + if (this.socket.readyState === ws_1.WebSocket.OPEN) { + this.socket.send(JSON.stringify(message)); + } + else { + console.warn(`Cannot send message, socket state: ${this.socket.readyState}`); + } + } + catch (error) { + // Socket may have closed between the readyState check and send() + console.error("Failed to send WebSocket message:", error); + this.emit("error", error); + } + } + /** + * Disconnect and clean up the current socket. + */ + disconnect() { + if (!this.socket) + return; + try { + this.socket.removeAllListeners(); + if (this.socket.readyState === ws_1.WebSocket.OPEN || + this.socket.readyState === ws_1.WebSocket.CONNECTING) { + this.socket.close(); + } + } + catch { + // Ignore close errors — socket may already be dead + } + this.socket = undefined; + this._isConnected = false; + } + /** + * Attach internal event listeners on the current socket. + */ + attachListeners() { + if (!this.socket) + return; + this.socket.on("message", (data) => { + try { + const message = JSON.parse(data.toString()); + this.emit("message", message); + } + catch (err) { + console.error("Failed to parse WebSocket message:", err); + this.emit("error", err); + } + }); + this.socket.on("close", () => { + this._isConnected = false; + this.emit("disconnected"); + }); + this.socket.on("error", (error) => { + console.error("WebSocket error:", error); + this.emit("error", error); + }); + } +} +exports.WebSocketManager = WebSocketManager; +//# sourceMappingURL=WebSocketManager.js.map \ No newline at end of file diff --git a/dist/core/WebSocketManager.js.map b/dist/core/WebSocketManager.js.map new file mode 100644 index 0000000..2479602 --- /dev/null +++ b/dist/core/WebSocketManager.js.map @@ -0,0 +1 @@ +{"version":3,"file":"WebSocketManager.js","sourceRoot":"","sources":["../../src/core/WebSocketManager.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/core/index.d.ts b/dist/core/index.d.ts new file mode 100644 index 0000000..4e06329 --- /dev/null +++ b/dist/core/index.d.ts @@ -0,0 +1,7 @@ +export { WebSocketManager } from "./WebSocketManager"; +export { SpeechManager, type SpeechManagerOptions } from "./SpeechManager"; +export { ConversationManager, type ConversationManagerOptions, } from "./ConversationManager"; +export { TranscriptionManager, type TranscriptionManagerOptions, } from "./TranscriptionManager"; +export { processFullStream, handleStreamChunk, type StreamResult, type StreamProcessorCallbacks, } from "./StreamProcessor"; +export { InputQueue, type QueueItem } from "./InputQueue"; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/core/index.d.ts.map b/dist/core/index.d.ts.map new file mode 100644 index 0000000..ecff749 --- /dev/null +++ b/dist/core/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAC3E,OAAO,EACL,mBAAmB,EACnB,KAAK,0BAA0B,GAChC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,oBAAoB,EACpB,KAAK,2BAA2B,GACjC,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,KAAK,YAAY,EACjB,KAAK,wBAAwB,GAC9B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC"} \ No newline at end of file diff --git a/dist/core/index.js b/dist/core/index.js new file mode 100644 index 0000000..1c94c1e --- /dev/null +++ b/dist/core/index.js @@ -0,0 +1,17 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.InputQueue = exports.handleStreamChunk = exports.processFullStream = exports.TranscriptionManager = exports.ConversationManager = exports.SpeechManager = exports.WebSocketManager = void 0; +var WebSocketManager_1 = require("./WebSocketManager"); +Object.defineProperty(exports, "WebSocketManager", { enumerable: true, get: function () { return WebSocketManager_1.WebSocketManager; } }); +var SpeechManager_1 = require("./SpeechManager"); +Object.defineProperty(exports, "SpeechManager", { enumerable: true, get: function () { return SpeechManager_1.SpeechManager; } }); +var ConversationManager_1 = require("./ConversationManager"); +Object.defineProperty(exports, "ConversationManager", { enumerable: true, get: function () { return ConversationManager_1.ConversationManager; } }); +var TranscriptionManager_1 = require("./TranscriptionManager"); +Object.defineProperty(exports, "TranscriptionManager", { enumerable: true, get: function () { return TranscriptionManager_1.TranscriptionManager; } }); +var StreamProcessor_1 = require("./StreamProcessor"); +Object.defineProperty(exports, "processFullStream", { enumerable: true, get: function () { return StreamProcessor_1.processFullStream; } }); +Object.defineProperty(exports, "handleStreamChunk", { enumerable: true, get: function () { return StreamProcessor_1.handleStreamChunk; } }); +var InputQueue_1 = require("./InputQueue"); +Object.defineProperty(exports, "InputQueue", { enumerable: true, get: function () { return InputQueue_1.InputQueue; } }); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/core/index.js.map b/dist/core/index.js.map new file mode 100644 index 0000000..d094aee --- /dev/null +++ b/dist/core/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":";;;AAAA,uDAAsD;AAA7C,oHAAA,gBAAgB,OAAA;AACzB,iDAA2E;AAAlE,8GAAA,aAAa,OAAA;AACtB,6DAG+B;AAF7B,0HAAA,mBAAmB,OAAA;AAGrB,+DAGgC;AAF9B,4HAAA,oBAAoB,OAAA;AAGtB,qDAK2B;AAJzB,oHAAA,iBAAiB,OAAA;AACjB,oHAAA,iBAAiB,OAAA;AAInB,2CAA0D;AAAjD,wGAAA,UAAU,OAAA"} \ No newline at end of file diff --git a/dist/index.d.ts b/dist/index.d.ts index 90c8d3b..173425f 100644 --- a/dist/index.d.ts +++ b/dist/index.d.ts @@ -1,4 +1,4 @@ -export { VoiceAgent, type VoiceAgentOptions } from "./VoiceAgent"; -export { VideoAgent, type VideoAgentOptions, type VideoFrame, type AudioData, type VideoAgentConfig, type FrameContext, type FrameTriggerReason, } from "./VideoAgent"; +export { VoiceAgent, type VoiceAgentOptions } from "./VoiceAgent.new"; +export { VideoAgent, type VideoAgentOptions, type VideoFrame, type AudioData, type VideoAgentConfig, type FrameContext, type FrameTriggerReason, } from "./VideoAgent.new"; export { type SpeechChunk, type StreamingSpeechConfig, type HistoryConfig, type StopWhenCondition, DEFAULT_STREAMING_SPEECH_CONFIG, DEFAULT_HISTORY_CONFIG, DEFAULT_MAX_AUDIO_SIZE, } from "./types"; //# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/index.d.ts.map b/dist/index.d.ts.map index b9bc9e7..212cc18 100644 --- a/dist/index.d.ts.map +++ b/dist/index.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,EACH,UAAU,EACV,KAAK,iBAAiB,EACtB,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,kBAAkB,GAC1B,MAAM,cAAc,CAAC;AAGtB,OAAO,EACH,KAAK,WAAW,EAChB,KAAK,qBAAqB,EAC1B,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,+BAA+B,EAC/B,sBAAsB,EACtB,sBAAsB,GACzB,MAAM,SAAS,CAAC"} \ No newline at end of file +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EACH,UAAU,EACV,KAAK,iBAAiB,EACtB,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,kBAAkB,GAC1B,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACH,KAAK,WAAW,EAChB,KAAK,qBAAqB,EAC1B,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,+BAA+B,EAC/B,sBAAsB,EACtB,sBAAsB,GACzB,MAAM,SAAS,CAAC"} \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index af8affb..608b052 100644 --- a/dist/index.js +++ b/dist/index.js @@ -2,10 +2,10 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.DEFAULT_MAX_AUDIO_SIZE = exports.DEFAULT_HISTORY_CONFIG = exports.DEFAULT_STREAMING_SPEECH_CONFIG = exports.VideoAgent = exports.VoiceAgent = void 0; // Agents -var VoiceAgent_1 = require("./VoiceAgent"); -Object.defineProperty(exports, "VoiceAgent", { enumerable: true, get: function () { return VoiceAgent_1.VoiceAgent; } }); -var VideoAgent_1 = require("./VideoAgent"); -Object.defineProperty(exports, "VideoAgent", { enumerable: true, get: function () { return VideoAgent_1.VideoAgent; } }); +var VoiceAgent_new_1 = require("./VoiceAgent.new"); +Object.defineProperty(exports, "VoiceAgent", { enumerable: true, get: function () { return VoiceAgent_new_1.VoiceAgent; } }); +var VideoAgent_new_1 = require("./VideoAgent.new"); +Object.defineProperty(exports, "VideoAgent", { enumerable: true, get: function () { return VideoAgent_new_1.VideoAgent; } }); // Shared types var types_1 = require("./types"); Object.defineProperty(exports, "DEFAULT_STREAMING_SPEECH_CONFIG", { enumerable: true, get: function () { return types_1.DEFAULT_STREAMING_SPEECH_CONFIG; } }); diff --git a/dist/index.js.map b/dist/index.js.map index 8c027fb..c9fdd12 100644 --- a/dist/index.js.map +++ b/dist/index.js.map @@ -1 +1 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,SAAS;AACT,2CAAkE;AAAzD,wGAAA,UAAU,OAAA;AACnB,2CAQsB;AAPlB,wGAAA,UAAU,OAAA;AASd,eAAe;AACf,iCAQiB;AAHb,wHAAA,+BAA+B,OAAA;AAC/B,+GAAA,sBAAsB,OAAA;AACtB,+GAAA,sBAAsB,OAAA"} \ No newline at end of file +{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,SAAS;AACT,mDAAsE;AAA7D,4GAAA,UAAU,OAAA;AACnB,mDAQ0B;AAPtB,4GAAA,UAAU,OAAA;AASd,eAAe;AACf,iCAQiB;AAHb,wHAAA,+BAA+B,OAAA;AAC/B,+GAAA,sBAAsB,OAAA;AACtB,+GAAA,sBAAsB,OAAA"} \ No newline at end of file diff --git a/example/frames/frame_00000_2026-02-23T10-41-46-424Z.webp b/example/frames/frame_00000_2026-02-23T10-41-46-424Z.webp new file mode 100644 index 0000000000000000000000000000000000000000..7085b89cf6f78d1a65a4ea07d1b513c6b8b16226 GIT binary patch literal 10886 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 literal 0 HcmV?d00001 diff --git a/example/frames/frame_00001_2026-02-23T10-41-50-271Z.webp b/example/frames/frame_00001_2026-02-23T10-41-50-271Z.webp new file mode 100644 index 0000000000000000000000000000000000000000..a76772ee038d5447e07f6982a67de9f43a19d74d GIT binary patch literal 11722 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 UcW&2FB>F`YXgEN)@q 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 =b!9uK#+ksU>%(-fVOH==Jyzte&W z0jsAWP$|iO@~3zu)Ye^$<7WS0Q|Gpf$xdCymdoM~ou!*KNkP;442R?Iu zB!_;)iZLj?s|`n*>yiOj(`9ri3H>-8w0JGI;GkdYYVgvUZK@LRktEt%t%d9D&WHfZ zFHPX~6cymIL?ouRcfT4VgL^WZO7zP-;}cjP4Ib!1o$uBw93J4E)qhJhhYWL_9)K)N zyiDj;^nG0}XT%A4QW2f99Q!znY>N0mK$=F7GF#y1q?mJQVH>)Oq$D=NHJ%0!K>7j$Q>~)>8>l#jlxpm5x#H}gr;n@pWm5g;4%{)=jCU0J;d9~6u2&J-i_6CdxRADeyBLF{uHYQ^jM7YM zPew+mMribB6YYptM3);-bV65Yn=mt$m{4ojCy2`cl!`iFE{0uuQ`izJk?(YplW#}B z!WN21ke1yY1&M{$K$SuMR$wNLu|{uBSXv)9KrQs94h}!zRoV+62BbPVPSW2kA*KOh zGLfM{?_9mRYP_qd$9-NpH-VVtv`koo?ID_2V4mfRhkJhrdUdH9dkq(r96TV$|jeb+)0Hw8V{8R!bkM`qqdnx;@-y~1%loG)T__N6F_5!DAJo8xm431tEv?_Lv0h@J2S3MQJSW-v z`(%(t`TARm7b*<(!tRF6H5;B|PncpU+_|uRuK}1wjcsL0>RhN}Yyknr@0wDii<$Vp z$pG$-mEd?3o=2$C=F`DS%{watn7C1sl}<-1CNHsjU2f~0%V6l+qoR!zyg?|dk+L0$R9CL!fHN+_ z{$rkR&uj=}4R%0R#yaD)IP-EsB%g|y`}|+^sM&U1 zl^HxHYPPO5m!R`sd5>TaBJwM&jwvNhtG6Wo96EyeE6dJFM7ayS$|!nq&oHgR^hrk& zx6E^flO8`aSP(Rf85Ls7o(`p8E6%+r)H0gvJOJz%>5Mb50hI{F{FetNA!C{i?$!ieq=ACtwHk&cnF@1ZTbHB=a(s56sFepk%|Wqi#}8mlrvFKFI>@J|4kOWl1}^(LGtFmid{rOfk;UaP^ORnm+=$s_gg;h zZ#QQ*SU#6cO(*%vjA>!ejf_1Frn8F}3(q5f#6&&*u8*GXJzNP3Z9WAm_j-k8C%!vqp^cm|*d+=poTN!Ml1 z;Q2}bk^hh{D>bE8#pt}i16`<$tNpNoCe0DJWa_U85Qwdkv= zAkLKWCtzyeK>(CA^}&|qTm)Qx#u)PwGX2MaCTA3(=_7mc`L za3k&#mMn<6We&-Af1~H<)yavf1%AJJuXS%+nmrnfEV|JjHB+3mLjO<#;I(1Y{Fft2 ztCIG=BVScj0@$-5*{2 zMzm7~b9bKC29`L#=AxAGQTg2ch?-fwKs>(~P>kM89Mnri#Z4)@_T-Ab!VlmVMqXeF zOWCZ@=j$2ir))&OVZjrnc;N9#-ywazYRpA8B|v&KIQjh}?28XfH(-^a)A^igcnEaJ zjH1o`5|r>8Fpd9+3|L6}556YphdOm4oGMHSuvwGdt%|6e@iO7>Of6On3Y&%-vN$k< zq)~wqia z)<{Sj7>Qfv0G4wU$FoBL$inK^SBoaIhYr|SvKW+5YAJ#)U6DD-UPzrycot_Cg~fF) zj0tSpCg022B_({HCQ}#4P&5nGwu5PM)PI01^oF8k4(w)sQp_(J`lNF!>q$C!h?df3 z8bpOyJf&eXC(D_S)*MXr;*AjpssiZGMRXZ$E7G+mpqy{VL|k;gWky<(lCC!pf#R&l zg@g=tju(^~NX5TW{ngoES+UXUU_YK)N2oy_?ai57w%ZzHGFnn$%HYyVx3iBfI~k^^`RnEdZVOJ?m7W+=~vH9<> zm>_-7K3bBZk5MLDKVqz!F$!hW;CgYBp>Db8y?`-r4~OMjPJ7wFIN$CY)sj+{FSptX zHNh)=kCu{5jT4}qswl{-D%&JM&w$TUtOSNm--PH@lYN0k^he`+AnNFGSlOm(uT9xp z@^pG?v%60Vi7CsET@#N>ObVSxhLLv_nXPvuN+w=7E*A{2eBmZ}tjh?CE@7cmMzjSTAS* literal 0 HcmV?d00001 diff --git a/example/frames/frame_00007_2026-02-23T10-42-11-278Z.webp b/example/frames/frame_00007_2026-02-23T10-42-11-278Z.webp new file mode 100644 index 0000000000000000000000000000000000000000..f6fb56c456ec0b86f449e4e4889009136c1553f0 GIT binary patch literal 11592 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 G;eY@ykAklN literal 0 HcmV?d00001 diff --git a/example/frames/frame_00008_2026-02-23T10-42-11-381Z.webp b/example/frames/frame_00008_2026-02-23T10-42-11-381Z.webp new file mode 100644 index 0000000000000000000000000000000000000000..65c799ab9c5d9d3b02c47ff9743520ac61372e9c GIT binary patch literal 11090 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 literal 0 HcmV?d00001 diff --git a/example/frames/frame_00009_2026-02-23T10-42-16-395Z.webp b/example/frames/frame_00009_2026-02-23T10-42-16-395Z.webp new file mode 100644 index 0000000000000000000000000000000000000000..a45bcf747d871f009fa2af576fd1e27fd05b15f2 GIT binary patch literal 9950 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 literal 0 HcmV?d00001 diff --git a/example/frames/frame_00010_2026-02-23T10-42-21-373Z.webp b/example/frames/frame_00010_2026-02-23T10-42-21-373Z.webp new file mode 100644 index 0000000000000000000000000000000000000000..e10ef666173baa08eacc885defe56d4fd870f031 GIT binary patch literal 11262 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 literal 0 HcmV?d00001 diff --git a/example/frames/frame_00011_2026-02-23T10-42-26-364Z.webp b/example/frames/frame_00011_2026-02-23T10-42-26-364Z.webp new file mode 100644 index 0000000000000000000000000000000000000000..d4ee1921821e7bb2036a29b90f52e02dd4b95ebe GIT binary patch literal 10670 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 literal 0 HcmV?d00001 diff --git a/example/ws-server-video.ts b/example/ws-server-video.ts index e155194..b7f8e4f 100644 --- a/example/ws-server-video.ts +++ b/example/ws-server-video.ts @@ -1,7 +1,7 @@ // ws-server-video.ts import "dotenv/config"; import { WebSocketServer } from "ws"; -import { VideoAgent } from "../src/VideoAgent"; // adjust path +import { VideoAgent } from "../src/VideoAgent.new"; // adjust path import { tool } from "ai"; import { z } from "zod"; import { openai } from "@ai-sdk/openai"; @@ -91,7 +91,7 @@ wss.on("connection", (socket) => { You can SEE what the user is showing via webcam. Describe what you see when it helps answer the question. Keep spoken answers concise and natural.`, - voice: "alloy", + voice: "echo", streamingSpeech: { minChunkSize: 25, maxChunkSize: 140, diff --git a/src/VideoAgent.new.ts b/src/VideoAgent.new.ts new file mode 100644 index 0000000..18e00a7 --- /dev/null +++ b/src/VideoAgent.new.ts @@ -0,0 +1,818 @@ +import { WebSocket } from "ws"; +import { EventEmitter } from "events"; +import { + streamText, + type LanguageModel, + stepCountIs, + type Tool, + type ModelMessage, + type TranscriptionModel, + type SpeechModel, +} from "ai"; +import { + type StreamingSpeechConfig, + type HistoryConfig, +} from "./types"; +import { + WebSocketManager, + SpeechManager, + ConversationManager, + TranscriptionManager, + InputQueue, + type QueueItem, + processFullStream, + handleStreamChunk, +} from "./core"; + +// ── Video-specific types ──────────────────────────────── + +/** + * Trigger reasons for frame capture + */ +type FrameTriggerReason = "scene_change" | "user_request" | "timer" | "initial"; + +/** + * Video frame data structure sent to/from the client + */ +interface VideoFrame { + type: "video_frame"; + sessionId: string; + sequence: number; + timestamp: number; + triggerReason: FrameTriggerReason; + previousFrameRef?: string; + image: { + data: string; + format: string; + width: number; + height: number; + }; +} + +/** + * Audio data structure + */ +interface AudioData { + type: "audio"; + sessionId: string; + data: string; + format: string; + sampleRate?: number; + duration?: number; + timestamp: number; +} + +/** + * Backend configuration for video processing + */ +interface VideoAgentConfig { + /** Maximum frames to keep in context buffer for conversation history */ + maxContextFrames: number; +} + +/** + * Frame context for maintaining visual conversation history + */ +interface FrameContext { + sequence: number; + timestamp: number; + triggerReason: FrameTriggerReason; + frameHash: string; + description?: string; +} + +/** Default maximum frame input size (5 MB) */ +const DEFAULT_MAX_FRAME_SIZE = 5 * 1024 * 1024; + +/** Default video agent config */ +const DEFAULT_VIDEO_AGENT_CONFIG: VideoAgentConfig = { + maxContextFrames: 10, +}; + +// ── Options & queue item ──────────────────────────────── + +export interface VideoAgentOptions { + /** + * AI SDK Model for chat. Must be a vision-enabled model (e.g., openai('gpt-4o'), + * anthropic('claude-3.5-sonnet'), google('gemini-1.5-pro')) to process video frames. + */ + model: LanguageModel; + transcriptionModel?: TranscriptionModel; + speechModel?: SpeechModel; + instructions?: string; + stopWhen?: NonNullable[0]["stopWhen"]>; + tools?: Record; + endpoint?: string; + voice?: string; + speechInstructions?: string; + outputFormat?: string; + streamingSpeech?: Partial; + history?: Partial; + maxAudioInputSize?: number; + /** Maximum frame input size in bytes (default: 5 MB) */ + maxFrameInputSize?: number; + /** Maximum frames to keep in context buffer (default: 10) */ + maxContextFrames?: number; + /** Session ID for this video agent instance */ + sessionId?: string; +} + +/** Shape of items in the video agent's input queue */ +interface VideoInputItem extends QueueItem { + text?: string; + frame?: VideoFrame; +} + +// ── VideoAgent class ──────────────────────────────────── + +export class VideoAgent extends EventEmitter { + private model: LanguageModel; + private instructions: string; + private stopWhen: NonNullable[0]["stopWhen"]>; + private endpoint?: string; + private tools: Record = {}; + private isDestroyed = false; + private _isProcessing = false; + + // Abort controller for the current LLM stream + private currentStreamAbortController?: AbortController; + + // ── Managers ───────────────────────────────────────── + private ws: WebSocketManager; + private speech: SpeechManager; + private conversation: ConversationManager; + private transcription: TranscriptionManager; + private inputQueue: InputQueue; + + // ── Video-specific state ──────────────────────────── + private sessionId: string; + private frameSequence = 0; + private lastFrameTimestamp = 0; + private lastFrameHash?: string; + private frameContextBuffer: FrameContext[] = []; + private currentFrameData?: string; + private videoConfig: VideoAgentConfig; + private maxFrameInputSize: number; + + constructor(options: VideoAgentOptions) { + super(); + this.model = options.model; + this.instructions = + options.instructions || + `You are a helpful multimodal AI assistant that can see through the user's camera and hear their voice. +When analyzing images, be concise but informative. Describe what you see when asked. +Keep responses conversational since they will be spoken aloud. +Use tools when needed to provide accurate information.`; + this.stopWhen = options.stopWhen || stepCountIs(5); + this.endpoint = options.endpoint; + this.maxFrameInputSize = options.maxFrameInputSize ?? DEFAULT_MAX_FRAME_SIZE; + this.sessionId = options.sessionId || this.generateSessionId(); + this.videoConfig = { + ...DEFAULT_VIDEO_AGENT_CONFIG, + maxContextFrames: + options.maxContextFrames ?? DEFAULT_VIDEO_AGENT_CONFIG.maxContextFrames, + }; + if (options.tools) { + this.tools = { ...options.tools }; + } + + // ── Initialize managers ───────────────────────── + this.ws = new WebSocketManager(); + this.speech = new SpeechManager({ + speechModel: options.speechModel, + voice: options.voice, + speechInstructions: options.speechInstructions, + outputFormat: options.outputFormat, + streamingSpeech: options.streamingSpeech, + }); + this.conversation = new ConversationManager({ + history: options.history, + }); + this.transcription = new TranscriptionManager({ + transcriptionModel: options.transcriptionModel, + maxAudioInputSize: options.maxAudioInputSize, + }); + this.inputQueue = new InputQueue(); + + // ── Wire managers to WebSocket send ───────────── + const sendMsg = (msg: Record) => this.ws.send(msg); + this.speech.sendMessage = sendMsg; + this.transcription.sendMessage = sendMsg; + + // ── Wire input queue processor ────────────────── + this.inputQueue.processor = (item) => this.processQueueItem(item); + + // ── Bubble events from managers ───────────────── + this.bubbleEvents(this.ws, ["connected", "error"]); + this.bubbleEvents(this.speech, [ + "speech_start", + "speech_complete", + "speech_interrupted", + "speech_chunk_queued", + "audio_chunk", + "audio", + "error", + ]); + this.bubbleEvents(this.conversation, [ + "history_cleared", + "history_trimmed", + ]); + this.bubbleEvents(this.transcription, [ + "transcription", + "audio_received", + "error", + "warning", + ]); + + // ── Handle WebSocket lifecycle ────────────────── + this.ws.on("disconnected", () => { + this.cleanupOnDisconnect(); + this.emit("disconnected"); + }); + + this.ws.on("message", (message: any) => this.handleMessage(message)); + } + + // ══════════════════════════════════════════════════════ + // Public API + // ══════════════════════════════════════════════════════ + + public registerTools(tools: Record) { + this.tools = { ...this.tools, ...tools }; + } + + public async transcribeAudio(audioData: Buffer | Uint8Array): Promise { + return this.transcription.transcribeAudio(audioData); + } + + public async generateSpeechFromText( + text: string, + abortSignal?: AbortSignal + ): Promise { + return this.speech.generateSpeechFromText(text, abortSignal); + } + + public interruptSpeech(reason: string = "interrupted"): void { + this.speech.interruptSpeech(reason); + } + + public interruptCurrentResponse(reason: string = "interrupted"): void { + if (this.currentStreamAbortController) { + this.currentStreamAbortController.abort(); + this.currentStreamAbortController = undefined; + } + this.speech.interruptSpeech(reason); + } + + public async connect(url?: string): Promise { + this.ensureNotDestroyed(); + const wsUrl = url || this.endpoint || "ws://localhost:8080"; + await this.ws.connect(wsUrl); + } + + public handleSocket(socket: WebSocket): void { + this.ensureNotDestroyed(); + this.ws.handleSocket(socket); + } + + public async sendText(text: string): Promise { + this.ensureNotDestroyed(); + if (!text || !text.trim()) { + throw new Error("Text input cannot be empty"); + } + return this.enqueueTextInput(text); + } + + public async sendAudio(audioData: string): Promise { + this.ensureNotDestroyed(); + await this.handleAudioInput(audioData); + } + + public async sendAudioBuffer(audioBuffer: Buffer | Uint8Array): Promise { + this.ensureNotDestroyed(); + const base64Audio = Buffer.from(audioBuffer).toString("base64"); + await this.handleAudioInput(base64Audio); + } + + /** + * Send a video frame with optional text query for vision analysis + */ + public async sendFrame( + frameData: string, + query?: string, + options?: { width?: number; height?: number; format?: string } + ): Promise { + this.ensureNotDestroyed(); + + const frame: VideoFrame = { + type: "video_frame", + sessionId: this.sessionId, + sequence: this.frameSequence++, + timestamp: Date.now(), + triggerReason: "user_request", + previousFrameRef: this.lastFrameHash, + image: { + data: frameData, + format: options?.format || "webp", + width: options?.width || 640, + height: options?.height || 480, + }, + }; + + // Update local frame state + await this.handleVideoFrame(frame); + + if (query) { + return this.enqueueMultimodalInput(query, frame); + } + + return ""; + } + + /** + * Request client to capture and send a frame + */ + public requestFrameCapture(reason: FrameTriggerReason): void { + this.ws.send({ + type: "capture_frame", + reason, + timestamp: Date.now(), + }); + this.emit("frame_requested", { reason }); + } + + public getConfig(): VideoAgentConfig { + return { ...this.videoConfig }; + } + + public updateConfig(config: Partial): void { + this.videoConfig = { ...this.videoConfig, ...config }; + this.emit("config_changed", this.videoConfig); + } + + startListening() { + this.emit("listening"); + } + + stopListening() { + this.emit("stopped"); + } + + clearHistory() { + this.conversation.clearHistory(); + this.frameContextBuffer = []; + } + + getHistory(): ModelMessage[] { + return this.conversation.getHistory(); + } + + setHistory(history: ModelMessage[]) { + this.conversation.setHistory(history); + } + + getFrameContext(): FrameContext[] { + return [...this.frameContextBuffer]; + } + + getSessionId(): string { + return this.sessionId; + } + + disconnect() { + this.ws.disconnect(); + } + + destroy() { + this.isDestroyed = true; + this.cleanupOnDisconnect(); + this.ws.disconnect(); + this.conversation.clearHistory(); + this.frameContextBuffer = []; + this.tools = {}; + this.removeAllListeners(); + } + + // ── Getters ───────────────────────────────────────── + + get connected(): boolean { + return this.ws.isConnected; + } + + get processing(): boolean { + return this._isProcessing; + } + + get speaking(): boolean { + return this.speech.isSpeaking; + } + + get pendingSpeechChunks(): number { + return this.speech.pendingChunkCount; + } + + get destroyed(): boolean { + return this.isDestroyed; + } + + get currentFrameSequence(): number { + return this.frameSequence; + } + + get hasVisualContext(): boolean { + return !!this.currentFrameData; + } + + // ══════════════════════════════════════════════════════ + // Private — message handling + // ══════════════════════════════════════════════════════ + + private async handleMessage(message: any): Promise { + try { + switch (message.type) { + case "transcript": + if (typeof message.text !== "string" || !message.text.trim()) { + this.emit("warning", "Received empty or invalid transcript message"); + return; + } + this.interruptCurrentResponse("user_speaking"); + this.requestFrameCapture("user_request"); + await this.enqueueTextInput(message.text); + break; + + case "audio": + if (typeof message.data !== "string" || !message.data) { + this.emit("warning", "Received empty or invalid audio message"); + return; + } + this.interruptCurrentResponse("user_speaking"); + this.requestFrameCapture("user_request"); + try { + await this.handleAudioInput(message.data, message.format); + } catch (audioError) { + this.emit("error", audioError); + } + break; + + case "video_frame": + await this.handleVideoFrame(message); + break; + + case "interrupt": + this.interruptCurrentResponse(message.reason || "client_request"); + break; + + case "client_ready": + this.handleClientReady(message); + break; + } + } catch (err) { + this.emit("error", err); + } + } + + private handleClientReady(message: any): void { + this.ws.send({ + type: "session_init", + sessionId: this.sessionId, + }); + this.emit("client_ready", message.capabilities); + } + + // ══════════════════════════════════════════════════════ + // Private — audio + // ══════════════════════════════════════════════════════ + + private async handleAudioInput( + base64Audio: string, + format?: string + ): Promise { + const text = await this.transcription.processAudioInput(base64Audio, format); + if (text) { + await this.enqueueTextInput(text); + } + } + + // ══════════════════════════════════════════════════════ + // Private — video frames + // ══════════════════════════════════════════════════════ + + private async handleVideoFrame(frame: VideoFrame): Promise { + try { + if (!frame.image?.data) { + this.emit("warning", "Received empty or invalid video frame"); + return; + } + + const frameSize = Buffer.from(frame.image.data, "base64").length; + if (frameSize > this.maxFrameInputSize) { + const sizeMB = (frameSize / (1024 * 1024)).toFixed(1); + const maxMB = (this.maxFrameInputSize / (1024 * 1024)).toFixed(1); + this.emit( + "error", + new Error(`Frame too large (${sizeMB} MB). Maximum allowed: ${maxMB} MB`) + ); + return; + } + + const frameHash = this.hashFrame(frame.image.data); + this.lastFrameTimestamp = frame.timestamp; + this.lastFrameHash = frameHash; + this.currentFrameData = frame.image.data; + + this.addFrameToContext({ + sequence: frame.sequence, + timestamp: frame.timestamp, + triggerReason: frame.triggerReason, + frameHash, + }); + + this.emit("frame_received", { + sequence: frame.sequence, + timestamp: frame.timestamp, + triggerReason: frame.triggerReason, + size: frameSize, + dimensions: { width: frame.image.width, height: frame.image.height }, + }); + + this.ws.send({ + type: "frame_ack", + sequence: frame.sequence, + timestamp: Date.now(), + }); + } catch (error) { + this.emit("error", error); + } + } + + private addFrameToContext(context: FrameContext): void { + this.frameContextBuffer.push(context); + if (this.frameContextBuffer.length > this.videoConfig.maxContextFrames) { + this.frameContextBuffer.shift(); + } + } + + private hashFrame(data: string): string { + let hash = 0; + for (let i = 0; i < data.length; i++) { + const char = data.charCodeAt(i); + hash = ((hash << 5) - hash) + char; + hash = hash & hash; + } + return `frame_${this.frameSequence}_${Math.abs(hash).toString(16)}`; + } + + private generateSessionId(): string { + const timestamp = Date.now().toString(36); + const randomPart = Math.random().toString(36).substring(2, 10); + return `vs_${timestamp}_${randomPart}`; + } + + // ══════════════════════════════════════════════════════ + // Private — input queue + // ══════════════════════════════════════════════════════ + + private enqueueTextInput(text: string): Promise { + return new Promise((resolve, reject) => { + this.inputQueue.enqueue({ text, resolve, reject }); + }); + } + + private enqueueMultimodalInput(text: string, frame: VideoFrame): Promise { + return new Promise((resolve, reject) => { + this.inputQueue.enqueue({ text, frame, resolve, reject }); + }); + } + + /** + * Route queued items to the correct processor. + */ + private async processQueueItem(item: VideoInputItem): Promise { + if (item.frame && item.text) { + return this.processMultimodalInput(item.text, item.frame); + } else if (item.text) { + return this.processUserInput(item.text); + } + return ""; + } + + // ══════════════════════════════════════════════════════ + // Private — multimodal content building + // ══════════════════════════════════════════════════════ + + private buildMultimodalContent( + text: string, + frameData?: string + ): Array<{ type: "text"; text: string } | { type: "image"; image: string }> { + const content: Array< + { type: "text"; text: string } | { type: "image"; image: string } + > = []; + + if (this.frameContextBuffer.length > 0) { + const contextSummary = `[Visual context: ${this.frameContextBuffer.length} frames captured, latest at ${new Date(this.lastFrameTimestamp).toISOString()}]`; + content.push({ type: "text", text: contextSummary }); + } + + const imageData = frameData || this.currentFrameData; + if (imageData) { + content.push({ type: "image", image: imageData }); + } + + content.push({ type: "text", text }); + return content; + } + + // ══════════════════════════════════════════════════════ + // Private — LLM processing + // ══════════════════════════════════════════════════════ + + /** + * Shared streamText invocation used by both processUserInput and processMultimodalInput. + */ + private async runStream( + messages: ModelMessage[], + abortSignal: AbortSignal + ): Promise { + const result = streamText({ + model: this.model, + system: this.instructions, + messages, + tools: this.tools, + stopWhen: this.stopWhen, + abortSignal, + onChunk: ({ chunk }) => { + handleStreamChunk(chunk, (event, data) => this.emit(event, data)); + }, + onFinish: async (event) => { + for (const step of event.steps) { + for (const toolResult of step.toolResults) { + this.emit("tool_result", { + name: toolResult.toolName, + toolCallId: toolResult.toolCallId, + result: toolResult.output, + }); + } + } + }, + onError: ({ error }) => { + this.emit("error", error); + }, + }); + + const streamResult = await processFullStream( + result, + { + onTextDelta: (delta) => this.speech.processTextDelta(delta), + onTextEnd: () => this.speech.flushPendingText(), + sendMessage: (msg) => this.ws.send(msg), + emitEvent: (event, data) => this.emit(event, data), + }, + { + sessionId: this.sessionId, + frameContext: + this.frameContextBuffer.length > 0 + ? { + frameCount: this.frameContextBuffer.length, + lastFrameSequence: + this.frameContextBuffer[this.frameContextBuffer.length - 1] + ?.sequence, + } + : undefined, + } + ); + + // Add assistant response to history + if (streamResult.fullText) { + this.conversation.addMessage({ + role: "assistant", + content: streamResult.fullText, + }); + } + + // Flush remaining speech & wait for queue + this.speech.flushPendingText(); + if (this.speech.queueDonePromise) { + await this.speech.queueDonePromise; + } + + return streamResult.fullText; + } + + /** + * Process text-only input (with optional visual context from latest frame). + */ + private async processUserInput(text: string): Promise { + this._isProcessing = true; + this.currentStreamAbortController = new AbortController(); + + try { + this.emit("text", { role: "user", text }); + + const hasVisual = !!this.currentFrameData; + let messages: ModelMessage[]; + + if (hasVisual) { + const content = this.buildMultimodalContent(text); + this.conversation.addMessage({ + role: "user", + content: [{ type: "text", text: `[Visual context] ${text}` }], + }); + messages = [ + ...this.conversation.getHistoryRef().slice(0, -1), + { role: "user", content }, + ]; + } else { + this.conversation.addMessage({ role: "user", content: text }); + messages = this.conversation.getHistoryRef(); + } + + return await this.runStream( + messages, + this.currentStreamAbortController.signal + ); + } catch (error) { + this.speech.reset(); + throw error; + } finally { + this._isProcessing = false; + this.currentStreamAbortController = undefined; + } + } + + /** + * Process multimodal input (text + explicit video frame). + */ + private async processMultimodalInput( + text: string, + frame: VideoFrame + ): Promise { + this._isProcessing = true; + this.currentStreamAbortController = new AbortController(); + + try { + this.emit("text", { role: "user", text, hasImage: true }); + + const content = this.buildMultimodalContent(text, frame.image.data); + + this.conversation.addMessage({ + role: "user", + content: [{ type: "text", text: `[Image attached] ${text}` }], + }); + + const messages: ModelMessage[] = [ + ...this.conversation.getHistoryRef().slice(0, -1), + { role: "user", content }, + ]; + + return await this.runStream( + messages, + this.currentStreamAbortController.signal + ); + } catch (error) { + this.speech.reset(); + throw error; + } finally { + this._isProcessing = false; + this.currentStreamAbortController = undefined; + } + } + + // ══════════════════════════════════════════════════════ + // Private — helpers + // ══════════════════════════════════════════════════════ + + private ensureNotDestroyed(): void { + if (this.isDestroyed) { + throw new Error("VideoAgent has been destroyed and cannot be used"); + } + } + + private cleanupOnDisconnect(): void { + if (this.currentStreamAbortController) { + this.currentStreamAbortController.abort(); + this.currentStreamAbortController = undefined; + } + this.speech.reset(); + this._isProcessing = false; + this.currentFrameData = undefined; + this.inputQueue.rejectAll(new Error("Connection closed")); + } + + private bubbleEvents(source: EventEmitter, events: string[]): void { + for (const event of events) { + source.on(event, (...args: any[]) => this.emit(event, ...args)); + } + } +} + +// Export types for external use +export type { + VideoFrame, + AudioData, + VideoAgentConfig, + FrameContext, + FrameTriggerReason, +}; + +// Re-export shared types +export type { StreamingSpeechConfig, HistoryConfig } from "./types"; \ No newline at end of file diff --git a/src/VideoAgent.ts b/src/VideoAgent.ts index baf72b6..6d65110 100644 --- a/src/VideoAgent.ts +++ b/src/VideoAgent.ts @@ -187,7 +187,7 @@ Use tools when needed to provide accurate information.`; this.endpoint = options.endpoint; this.voice = options.voice || "alloy"; this.speechInstructions = options.speechInstructions; - this.outputFormat = options.outputFormat || "mp3"; + this.outputFormat = options.outputFormat || "opus"; this.maxAudioInputSize = options.maxAudioInputSize ?? DEFAULT_MAX_AUDIO_SIZE; this.maxFrameInputSize = options.maxFrameInputSize ?? DEFAULT_MAX_FRAME_SIZE; diff --git a/src/VoiceAgent.new.ts b/src/VoiceAgent.new.ts new file mode 100644 index 0000000..db6940f --- /dev/null +++ b/src/VoiceAgent.new.ts @@ -0,0 +1,484 @@ +import { WebSocket } from "ws"; +import { EventEmitter } from "events"; +import { + streamText, + type LanguageModel, + stepCountIs, + type Tool, + type ModelMessage, + type TranscriptionModel, + type SpeechModel, +} from "ai"; +import { + type StreamingSpeechConfig, + type HistoryConfig, +} from "./types"; +import { + WebSocketManager, + SpeechManager, + ConversationManager, + TranscriptionManager, + InputQueue, + type QueueItem, + processFullStream, + handleStreamChunk, +} from "./core"; + +export interface VoiceAgentOptions { + model: LanguageModel; + transcriptionModel?: TranscriptionModel; + speechModel?: SpeechModel; + instructions?: string; + stopWhen?: NonNullable[0]["stopWhen"]>; + tools?: Record; + endpoint?: string; + voice?: string; + speechInstructions?: string; + outputFormat?: string; + /** Configuration for streaming speech generation */ + streamingSpeech?: Partial; + /** Configuration for conversation history memory limits */ + history?: Partial; + /** Maximum audio input size in bytes (default: 10 MB) */ + maxAudioInputSize?: number; +} + +/** Shape of items in the voice agent's input queue */ +interface VoiceInputItem extends QueueItem { + text: string; +} + +/** + * A single-session voice agent that manages one WebSocket connection at a time. + * + * **Important:** Each `VoiceAgent` instance holds its own conversation history, + * input queue, speech state, and WebSocket. It is designed for **one user per + * instance**. To support multiple concurrent users, create a separate + * `VoiceAgent` for each connection: + * + * ```ts + * wss.on("connection", (socket) => { + * const agent = new VoiceAgent({ model, ... }); + * agent.handleSocket(socket); + * agent.on("disconnected", () => agent.destroy()); + * }); + * ``` + * + * Sharing a single instance across multiple users will cause conversation + * history cross-contamination, interleaved audio, and unpredictable behavior. + */ +export class VoiceAgent extends EventEmitter { + private model: LanguageModel; + private instructions: string; + private stopWhen: NonNullable[0]["stopWhen"]>; + private endpoint?: string; + private tools: Record = {}; + private isDestroyed = false; + private _isProcessing = false; + + // Abort controller for the current LLM stream + private currentStreamAbortController?: AbortController; + + // ── Managers ────────────────────────────────────────── + private ws: WebSocketManager; + private speech: SpeechManager; + private conversation: ConversationManager; + private transcription: TranscriptionManager; + private inputQueue: InputQueue; + + constructor(options: VoiceAgentOptions) { + super(); + this.model = options.model; + this.instructions = + options.instructions || "You are a helpful voice assistant."; + this.stopWhen = options.stopWhen || stepCountIs(5); + this.endpoint = options.endpoint; + if (options.tools) { + this.tools = { ...options.tools }; + } + + // ── Initialize managers ────────────────────────────── + this.ws = new WebSocketManager(); + this.speech = new SpeechManager({ + speechModel: options.speechModel, + voice: options.voice, + speechInstructions: options.speechInstructions, + outputFormat: options.outputFormat, + streamingSpeech: options.streamingSpeech, + }); + this.conversation = new ConversationManager({ + history: options.history, + }); + this.transcription = new TranscriptionManager({ + transcriptionModel: options.transcriptionModel, + maxAudioInputSize: options.maxAudioInputSize, + }); + this.inputQueue = new InputQueue(); + + // ── Wire managers to the WebSocket send function ───── + const sendMsg = (msg: Record) => this.ws.send(msg); + this.speech.sendMessage = sendMsg; + this.transcription.sendMessage = sendMsg; + + // ── Wire the input queue processor ─────────────────── + this.inputQueue.processor = (item) => this.processUserInput(item.text); + + // ── Bubble events from managers ────────────────────── + this.bubbleEvents(this.ws, [ + "connected", + "error", + ]); + this.bubbleEvents(this.speech, [ + "speech_start", + "speech_complete", + "speech_interrupted", + "speech_chunk_queued", + "audio_chunk", + "audio", + "error", + ]); + this.bubbleEvents(this.conversation, [ + "history_cleared", + "history_trimmed", + ]); + this.bubbleEvents(this.transcription, [ + "transcription", + "audio_received", + "error", + "warning", + ]); + + // ── Handle WebSocket lifecycle events ──────────────── + this.ws.on("disconnected", () => { + this.cleanupOnDisconnect(); + this.emit("disconnected"); + }); + + this.ws.on("message", (message: any) => this.handleMessage(message)); + } + + // ── Public API ──────────────────────────────────────── + + public registerTools(tools: Record) { + this.tools = { ...this.tools, ...tools }; + } + + /** + * Transcribe audio data to text using the configured transcription model. + */ + public async transcribeAudio(audioData: Buffer | Uint8Array): Promise { + return this.transcription.transcribeAudio(audioData); + } + + /** + * Generate speech from text using the configured speech model. + */ + public async generateSpeechFromText( + text: string, + abortSignal?: AbortSignal + ): Promise { + return this.speech.generateSpeechFromText(text, abortSignal); + } + + /** + * Interrupt ongoing speech generation and playback (barge-in support). + */ + public interruptSpeech(reason: string = "interrupted"): void { + this.speech.interruptSpeech(reason); + } + + /** + * Interrupt both the current LLM stream and ongoing speech. + */ + public interruptCurrentResponse(reason: string = "interrupted"): void { + if (this.currentStreamAbortController) { + this.currentStreamAbortController.abort(); + this.currentStreamAbortController = undefined; + } + this.speech.interruptSpeech(reason); + } + + /** + * Connect to a WebSocket server by URL. + */ + public async connect(url?: string): Promise { + this.ensureNotDestroyed(); + const wsUrl = url || this.endpoint || "ws://localhost:8080"; + await this.ws.connect(wsUrl); + } + + /** + * Attach an existing WebSocket (server-side usage). + */ + public handleSocket(socket: WebSocket): void { + this.ensureNotDestroyed(); + this.ws.handleSocket(socket); + } + + /** + * Send text input for processing (bypasses transcription). + */ + public async sendText(text: string): Promise { + this.ensureNotDestroyed(); + if (!text || !text.trim()) { + throw new Error("Text input cannot be empty"); + } + return this.enqueueInput(text); + } + + /** + * Send base64 audio data to be transcribed and processed. + */ + public async sendAudio(audioData: string): Promise { + this.ensureNotDestroyed(); + await this.handleAudioInput(audioData); + } + + /** + * Send raw audio buffer to be transcribed and processed. + */ + public async sendAudioBuffer(audioBuffer: Buffer | Uint8Array): Promise { + this.ensureNotDestroyed(); + const base64Audio = Buffer.from(audioBuffer).toString("base64"); + await this.handleAudioInput(base64Audio); + } + + /** + * Generate speech for full text at once (non-streaming fallback). + */ + public async generateAndSendSpeechFull(text: string): Promise { + return this.speech.generateAndSendSpeechFull(text); + } + + /** Start listening for voice input */ + startListening() { + console.log("Starting voice agent..."); + this.emit("listening"); + } + + /** Stop listening for voice input */ + stopListening() { + console.log("Stopping voice agent..."); + this.emit("stopped"); + } + + /** Clear conversation history */ + clearHistory() { + this.conversation.clearHistory(); + } + + /** Get current conversation history */ + getHistory(): ModelMessage[] { + return this.conversation.getHistory(); + } + + /** Set conversation history (useful for restoring sessions) */ + setHistory(history: ModelMessage[]) { + this.conversation.setHistory(history); + } + + /** Disconnect from WebSocket and stop all in-flight work */ + disconnect() { + this.ws.disconnect(); + } + + /** + * Permanently destroy the agent, releasing all resources. + */ + destroy() { + this.isDestroyed = true; + this.cleanupOnDisconnect(); + this.ws.disconnect(); + this.conversation.clearHistory(); + this.tools = {}; + this.removeAllListeners(); + } + + // ── Getters ─────────────────────────────────────────── + + get connected(): boolean { + return this.ws.isConnected; + } + + get processing(): boolean { + return this._isProcessing; + } + + get speaking(): boolean { + return this.speech.isSpeaking; + } + + get pendingSpeechChunks(): number { + return this.speech.pendingChunkCount; + } + + get destroyed(): boolean { + return this.isDestroyed; + } + + // ── Private: message handling ───────────────────────── + + private async handleMessage(message: any): Promise { + try { + console.log(`Received WebSocket message of type: ${message.type}`); + + if (message.type === "transcript") { + if (typeof message.text !== "string" || !message.text.trim()) { + this.emit("warning", "Received empty or invalid transcript message"); + return; + } + this.interruptCurrentResponse("user_speaking"); + console.log(`Processing transcript: "${message.text}"`); + await this.enqueueInput(message.text); + } else if (message.type === "audio") { + if (typeof message.data !== "string" || !message.data) { + this.emit("warning", "Received empty or invalid audio message"); + return; + } + this.interruptCurrentResponse("user_speaking"); + console.log( + `Received audio data (${message.data.length / 1000}KB) for processing, format: ${message.format || "unknown"}` + ); + await this.handleAudioInput(message.data, message.format); + } else if (message.type === "interrupt") { + console.log( + `Received interrupt request: ${message.reason || "client_request"}` + ); + this.interruptCurrentResponse(message.reason || "client_request"); + } + } catch (err) { + console.error("Failed to process message:", err); + this.emit("error", err); + } + } + + // ── Private: audio ──────────────────────────────────── + + private async handleAudioInput( + base64Audio: string, + format?: string + ): Promise { + const text = await this.transcription.processAudioInput( + base64Audio, + format + ); + if (text) { + await this.enqueueInput(text); + } + } + + // ── Private: input queue ────────────────────────────── + + private enqueueInput(text: string): Promise { + return new Promise((resolve, reject) => { + this.inputQueue.enqueue({ text, resolve, reject }); + }); + } + + // ── Private: LLM processing ─────────────────────────── + + /** + * Process user input with streaming text generation. + * Called serially by the input queue. + */ + private async processUserInput(text: string): Promise { + this._isProcessing = true; + this.currentStreamAbortController = new AbortController(); + const streamAbortSignal = this.currentStreamAbortController.signal; + + try { + this.emit("text", { role: "user", text }); + + this.conversation.addMessage({ role: "user", content: text }); + + const result = streamText({ + model: this.model, + system: this.instructions, + messages: this.conversation.getHistoryRef(), + tools: this.tools, + stopWhen: this.stopWhen, + abortSignal: streamAbortSignal, + onChunk: ({ chunk }) => { + handleStreamChunk(chunk, (event, data) => this.emit(event, data)); + }, + onFinish: async (event) => { + for (const step of event.steps) { + for (const toolResult of step.toolResults) { + this.emit("tool_result", { + name: toolResult.toolName, + toolCallId: toolResult.toolCallId, + result: toolResult.output, + }); + } + } + }, + onError: ({ error }) => { + console.error("Stream error:", error); + this.emit("error", error); + }, + }); + + const streamResult = await processFullStream(result, { + onTextDelta: (delta) => this.speech.processTextDelta(delta), + onTextEnd: () => this.speech.flushPendingText(), + sendMessage: (msg) => this.ws.send(msg), + emitEvent: (event, data) => this.emit(event, data), + }); + + // Add assistant response to history + if (streamResult.fullText) { + this.conversation.addMessage({ + role: "assistant", + content: streamResult.fullText, + }); + } + + // Flush any remaining speech + this.speech.flushPendingText(); + + // Wait for all speech chunks to complete + if (this.speech.queueDonePromise) { + await this.speech.queueDonePromise; + } + + return streamResult.fullText; + } catch (error) { + // Clean up speech state on error + this.speech.reset(); + throw error; + } finally { + this._isProcessing = false; + this.currentStreamAbortController = undefined; + } + } + + // ── Private: helpers ────────────────────────────────── + + private ensureNotDestroyed(): void { + if (this.isDestroyed) { + throw new Error("VoiceAgent has been destroyed and cannot be used"); + } + } + + /** + * Clean up all in-flight state when the connection drops. + */ + private cleanupOnDisconnect(): void { + if (this.currentStreamAbortController) { + this.currentStreamAbortController.abort(); + this.currentStreamAbortController = undefined; + } + this.speech.reset(); + this._isProcessing = false; + this.inputQueue.rejectAll(new Error("Connection closed")); + } + + /** + * Forward select events from a child emitter to this agent. + */ + private bubbleEvents(source: EventEmitter, events: string[]): void { + for (const event of events) { + source.on(event, (...args: any[]) => this.emit(event, ...args)); + } + } +} diff --git a/src/VoiceAgent.ts b/src/VoiceAgent.ts index 2a20753..b3c5a68 100644 --- a/src/VoiceAgent.ts +++ b/src/VoiceAgent.ts @@ -39,6 +39,25 @@ export interface VoiceAgentOptions { maxAudioInputSize?: number; } +/** + * A single-session voice agent that manages one WebSocket connection at a time. + * + * **Important:** Each `VoiceAgent` instance holds its own conversation history, + * input queue, speech state, and WebSocket. It is designed for **one user per + * instance**. To support multiple concurrent users, create a separate + * `VoiceAgent` for each connection: + * + * ```ts + * wss.on("connection", (socket) => { + * const agent = new VoiceAgent({ model, ... }); + * agent.handleSocket(socket); + * agent.on("disconnected", () => agent.destroy()); + * }); + * ``` + * + * Sharing a single instance across multiple users will cause conversation + * history cross-contamination, interleaved audio, and unpredictable behavior. + */ export class VoiceAgent extends EventEmitter { private socket?: WebSocket; private tools: Record = {}; @@ -90,7 +109,7 @@ export class VoiceAgent extends EventEmitter { this.endpoint = options.endpoint; this.voice = options.voice || "alloy"; this.speechInstructions = options.speechInstructions; - this.outputFormat = options.outputFormat || "mp3"; + this.outputFormat = options.outputFormat || "opus"; this.maxAudioInputSize = options.maxAudioInputSize ?? DEFAULT_MAX_AUDIO_SIZE; if (options.tools) { this.tools = { ...options.tools }; @@ -695,6 +714,10 @@ export class VoiceAgent extends EventEmitter { * Attach an existing WebSocket (server-side usage). * Use this when a WS server accepts a connection and you want the * agent to handle messages on that socket. + * + * **Note:** Calling this while a socket is already attached will cleanly + * tear down the previous connection first. Each `VoiceAgent` instance + * supports only one socket at a time — create a new agent per user. */ public handleSocket(socket: WebSocket): void { this.ensureNotDestroyed(); diff --git a/src/core/ConversationManager.ts b/src/core/ConversationManager.ts new file mode 100644 index 0000000..a42b805 --- /dev/null +++ b/src/core/ConversationManager.ts @@ -0,0 +1,122 @@ +import { EventEmitter } from "events"; +import { type ModelMessage } from "ai"; +import { type HistoryConfig, DEFAULT_HISTORY_CONFIG } from "../types"; + +export interface ConversationManagerOptions { + history?: Partial; +} + +/** + * Manages conversation history (ModelMessage[]) with configurable + * limits on message count and total character size. + */ +export class ConversationManager extends EventEmitter { + private conversationHistory: ModelMessage[] = []; + private historyConfig: HistoryConfig; + + constructor(options: ConversationManagerOptions = {}) { + super(); + this.historyConfig = { + ...DEFAULT_HISTORY_CONFIG, + ...options.history, + }; + } + + /** + * Add a message to history and trim if needed. + */ + addMessage(message: ModelMessage): void { + this.conversationHistory.push(message); + this.trimHistory(); + } + + /** + * Get a copy of the current history. + */ + getHistory(): ModelMessage[] { + return [...this.conversationHistory]; + } + + /** + * Get a direct reference to the history array. + * Use with caution — prefer getHistory() for safety. + */ + getHistoryRef(): ModelMessage[] { + return this.conversationHistory; + } + + /** + * Replace the entire conversation history. + */ + setHistory(history: ModelMessage[]): void { + this.conversationHistory = [...history]; + } + + /** + * Clear all conversation history. + */ + clearHistory(): void { + this.conversationHistory = []; + this.emit("history_cleared"); + } + + /** + * Get the number of messages in history. + */ + get length(): number { + return this.conversationHistory.length; + } + + /** + * Trim conversation history to stay within configured limits. + * Removes oldest messages (always in pairs to preserve user/assistant turns). + */ + private trimHistory(): void { + const { maxMessages, maxTotalChars } = this.historyConfig; + + // Trim by message count + if (maxMessages > 0 && this.conversationHistory.length > maxMessages) { + const excess = this.conversationHistory.length - maxMessages; + // Round up to even number to preserve turn pairs + const toRemove = excess % 2 === 0 ? excess : excess + 1; + this.conversationHistory.splice(0, toRemove); + this.emit("history_trimmed", { + removedCount: toRemove, + reason: "max_messages", + }); + } + + // Trim by total character count + if (maxTotalChars > 0) { + let totalChars = this.conversationHistory.reduce((sum, msg) => { + const content = + typeof msg.content === "string" + ? msg.content + : JSON.stringify(msg.content); + return sum + content.length; + }, 0); + + let removedCount = 0; + while ( + totalChars > maxTotalChars && + this.conversationHistory.length > 2 + ) { + const removed = this.conversationHistory.shift(); + if (removed) { + const content = + typeof removed.content === "string" + ? removed.content + : JSON.stringify(removed.content); + totalChars -= content.length; + removedCount++; + } + } + if (removedCount > 0) { + this.emit("history_trimmed", { + removedCount, + reason: "max_total_chars", + }); + } + } + } +} diff --git a/src/core/InputQueue.ts b/src/core/InputQueue.ts new file mode 100644 index 0000000..511323e --- /dev/null +++ b/src/core/InputQueue.ts @@ -0,0 +1,71 @@ +/** + * A generic serial input queue that ensures only one processor runs at a time. + * + * @template T The shape of each queued item (must include resolve/reject) + */ +export interface QueueItem { + resolve: (v: T) => void; + reject: (e: unknown) => void; +} + +export class InputQueue> { + private queue: T[] = []; + private processing = false; + + /** Callback invoked for each item — must return a resolved value */ + public processor: (item: T) => Promise = async () => ""; + + /** + * Enqueue an item for serial processing. + */ + enqueue(item: T): void { + this.queue.push(item); + this.drain(); + } + + /** + * Reject all pending items (used on disconnect/destroy). + */ + rejectAll(reason: Error): void { + for (const item of this.queue) { + item.reject(reason); + } + this.queue = []; + this.processing = false; + } + + /** + * Number of items waiting in the queue. + */ + get length(): number { + return this.queue.length; + } + + /** + * Whether the queue is currently processing an item. + */ + get isProcessing(): boolean { + return this.processing; + } + + // ── Private ────────────────────────────────────────── + + private async drain(): Promise { + if (this.processing) return; + this.processing = true; + + try { + while (this.queue.length > 0) { + const item = this.queue.shift()!; + try { + const result = await this.processor(item); + item.resolve(result); + } catch (error) { + item.reject(error); + } + } + } finally { + this.processing = false; + } + } +} diff --git a/src/core/SpeechManager.ts b/src/core/SpeechManager.ts new file mode 100644 index 0000000..4a9efac --- /dev/null +++ b/src/core/SpeechManager.ts @@ -0,0 +1,453 @@ +import { EventEmitter } from "events"; +import { + experimental_generateSpeech as generateSpeech, + type SpeechModel, +} from "ai"; +import { + type SpeechChunk, + type StreamingSpeechConfig, + DEFAULT_STREAMING_SPEECH_CONFIG, +} from "../types"; + +export interface SpeechManagerOptions { + speechModel?: SpeechModel; + voice?: string; + speechInstructions?: string; + outputFormat?: string; + streamingSpeech?: Partial; +} + +/** + * Manages text-to-speech generation, streaming speech chunking, + * parallel TTS requests, and speech interruption. + */ +export class SpeechManager extends EventEmitter { + private speechModel?: SpeechModel; + private voice: string; + private speechInstructions?: string; + private outputFormat: string; + private streamingSpeechConfig: StreamingSpeechConfig; + + private currentSpeechAbortController?: AbortController; + private speechChunkQueue: SpeechChunk[] = []; + private nextChunkId = 0; + private _isSpeaking = false; + private pendingTextBuffer = ""; + + // Promise-based signal for speech queue completion + private speechQueueDonePromise?: Promise; + private speechQueueDoneResolve?: () => void; + + /** Callback to send messages over the WebSocket */ + public sendMessage: (message: Record) => void = () => { }; + + constructor(options: SpeechManagerOptions) { + super(); + this.speechModel = options.speechModel; + this.voice = options.voice || "alloy"; + this.speechInstructions = options.speechInstructions; + this.outputFormat = options.outputFormat || "opus"; + this.streamingSpeechConfig = { + ...DEFAULT_STREAMING_SPEECH_CONFIG, + ...options.streamingSpeech, + }; + } + + get isSpeaking(): boolean { + return this._isSpeaking; + } + + get pendingChunkCount(): number { + return this.speechChunkQueue.length; + } + + get hasSpeechModel(): boolean { + return !!this.speechModel; + } + + /** + * Returns a promise that resolves when the speech queue is fully drained. + * Returns undefined if there is nothing queued. + */ + get queueDonePromise(): Promise | undefined { + return this.speechQueueDonePromise; + } + + /** + * Generate speech from text using the configured speech model. + */ + async generateSpeechFromText( + text: string, + abortSignal?: AbortSignal + ): Promise { + if (!this.speechModel) { + throw new Error("Speech model not configured"); + } + + const result = await generateSpeech({ + model: this.speechModel, + text, + voice: this.voice, + instructions: this.speechInstructions, + outputFormat: this.outputFormat, + abortSignal, + }); + + return result.audio.uint8Array; + } + + /** + * Generate speech for full text at once (non-streaming fallback). + */ + async generateAndSendSpeechFull(text: string): Promise { + if (!this.speechModel) return; + + try { + this.emit("speech_start", { text, streaming: false }); + + const audioData = await this.generateSpeechFromText(text); + const base64Audio = Buffer.from(audioData).toString("base64"); + + this.sendMessage({ + type: "audio", + data: base64Audio, + format: this.outputFormat, + }); + + this.emit("audio", { + data: base64Audio, + format: this.outputFormat, + uint8Array: audioData, + }); + + this.emit("speech_complete", { text, streaming: false }); + } catch (error) { + console.error("Failed to generate speech:", error); + this.emit("error", error); + } + } + + /** + * Interrupt ongoing speech generation and playback (barge-in support). + */ + interruptSpeech(reason: string = "interrupted"): void { + if (!this._isSpeaking && this.speechChunkQueue.length === 0) { + return; + } + + // Abort any pending speech generation requests + if (this.currentSpeechAbortController) { + this.currentSpeechAbortController.abort(); + this.currentSpeechAbortController = undefined; + } + + // Clear the speech queue + this.speechChunkQueue = []; + this.pendingTextBuffer = ""; + this._isSpeaking = false; + + // Resolve any pending speech-done waiters so callers can finish + if (this.speechQueueDoneResolve) { + this.speechQueueDoneResolve(); + this.speechQueueDoneResolve = undefined; + this.speechQueueDonePromise = undefined; + } + + // Notify clients to stop audio playback + this.sendMessage({ + type: "speech_interrupted", + reason, + }); + + this.emit("speech_interrupted", { reason }); + } + + /** + * Process a text delta for streaming speech. + * Call this as text chunks arrive from the LLM. + */ + processTextDelta(textDelta: string): void { + if (!this.speechModel) return; + + this.pendingTextBuffer += textDelta; + + const [sentences, remaining] = this.extractSentences(this.pendingTextBuffer); + this.pendingTextBuffer = remaining; + + for (const sentence of sentences) { + this.queueSpeechChunk(sentence); + } + } + + /** + * Flush any remaining text in the buffer to speech. + * Call this when the LLM stream ends. + */ + flushPendingText(): void { + if (!this.speechModel || !this.pendingTextBuffer.trim()) return; + + this.queueSpeechChunk(this.pendingTextBuffer); + this.pendingTextBuffer = ""; + } + + /** + * Reset all speech state (used on disconnect / cleanup). + */ + reset(): void { + if (this.currentSpeechAbortController) { + this.currentSpeechAbortController.abort(); + this.currentSpeechAbortController = undefined; + } + this.speechChunkQueue = []; + this.pendingTextBuffer = ""; + this._isSpeaking = false; + + if (this.speechQueueDoneResolve) { + this.speechQueueDoneResolve(); + this.speechQueueDoneResolve = undefined; + this.speechQueueDonePromise = undefined; + } + } + + // ── Private helpers ───────────────────────────────────────── + + /** + * Extract complete sentences from text buffer. + * Returns [extractedSentences, remainingBuffer]. + */ + private extractSentences(text: string): [string[], string] { + const sentences: string[] = []; + let remaining = text; + + // Match sentences ending with . ! ? followed by space or end of string + const sentenceEndPattern = /[.!?]+(?:\s+|$)/g; + let lastIndex = 0; + let match; + + while ((match = sentenceEndPattern.exec(text)) !== null) { + const sentence = text + .slice(lastIndex, match.index + match[0].length) + .trim(); + if (sentence.length >= this.streamingSpeechConfig.minChunkSize) { + sentences.push(sentence); + lastIndex = match.index + match[0].length; + } else if (sentences.length > 0) { + // Append short sentence to previous one + sentences[sentences.length - 1] += " " + sentence; + lastIndex = match.index + match[0].length; + } + } + + remaining = text.slice(lastIndex); + + // If remaining text is too long, force split at clause boundaries + if (remaining.length > this.streamingSpeechConfig.maxChunkSize) { + const clausePattern = /[,;:]\s+/g; + let clauseMatch; + let splitIndex = 0; + + while ((clauseMatch = clausePattern.exec(remaining)) !== null) { + if (clauseMatch.index >= this.streamingSpeechConfig.minChunkSize) { + splitIndex = clauseMatch.index + clauseMatch[0].length; + break; + } + } + + if (splitIndex > 0) { + sentences.push(remaining.slice(0, splitIndex).trim()); + remaining = remaining.slice(splitIndex); + } + } + + return [sentences, remaining]; + } + + /** + * Queue a text chunk for speech generation. + */ + private queueSpeechChunk(text: string): void { + if (!this.speechModel || !text.trim()) return; + + // Wrap chunk ID to prevent unbounded growth in very long sessions + if (this.nextChunkId >= Number.MAX_SAFE_INTEGER) { + this.nextChunkId = 0; + } + + const chunk: SpeechChunk = { + id: this.nextChunkId++, + text: text.trim(), + }; + + // Create the speech-done promise if not already present + if (!this.speechQueueDonePromise) { + this.speechQueueDonePromise = new Promise((resolve) => { + this.speechQueueDoneResolve = resolve; + }); + } + + // Start generating audio immediately (parallel generation) + if (this.streamingSpeechConfig.parallelGeneration) { + const activeRequests = this.speechChunkQueue.filter( + (c) => c.audioPromise + ).length; + + if (activeRequests < this.streamingSpeechConfig.maxParallelRequests) { + chunk.audioPromise = this.generateChunkAudio(chunk); + } + } + + this.speechChunkQueue.push(chunk); + this.emit("speech_chunk_queued", { id: chunk.id, text: chunk.text }); + + // Start processing queue if not already + if (!this._isSpeaking) { + this.processSpeechQueue(); + } + } + + /** + * Generate audio for a single chunk. + */ + private async generateChunkAudio( + chunk: SpeechChunk + ): Promise { + if (!this.currentSpeechAbortController) { + this.currentSpeechAbortController = new AbortController(); + } + + try { + console.log( + `Generating audio for chunk ${chunk.id}: "${chunk.text.substring(0, 50)}${chunk.text.length > 50 ? "..." : ""}"` + ); + const audioData = await this.generateSpeechFromText( + chunk.text, + this.currentSpeechAbortController.signal + ); + console.log( + `Generated audio for chunk ${chunk.id}: ${audioData.length} bytes` + ); + return audioData; + } catch (error) { + if ((error as Error).name === "AbortError") { + console.log(`Audio generation aborted for chunk ${chunk.id}`); + return null; + } + console.error( + `Failed to generate audio for chunk ${chunk.id}:`, + error + ); + this.emit("error", error); + return null; + } + } + + /** + * Process the speech queue and send audio chunks in order. + */ + private async processSpeechQueue(): Promise { + if (this._isSpeaking) return; + this._isSpeaking = true; + + console.log( + `Starting speech queue processing with ${this.speechChunkQueue.length} chunks` + ); + this.emit("speech_start", { streaming: true }); + this.sendMessage({ type: "speech_stream_start" }); + + try { + while (this.speechChunkQueue.length > 0) { + const chunk = this.speechChunkQueue[0]; + + console.log( + `Processing speech chunk #${chunk.id} (${this.speechChunkQueue.length - 1} remaining)` + ); + + // Ensure audio generation has started + if (!chunk.audioPromise) { + chunk.audioPromise = this.generateChunkAudio(chunk); + } + + // Wait for this chunk's audio + const audioData = await chunk.audioPromise; + + // Check if we were interrupted while waiting + if (!this._isSpeaking) { + console.log(`Speech interrupted during chunk #${chunk.id}`); + break; + } + + // Remove from queue after processing + this.speechChunkQueue.shift(); + + if (audioData) { + const base64Audio = Buffer.from(audioData).toString("base64"); + console.log( + `Sending audio chunk #${chunk.id} (${audioData.length} bytes, ${this.outputFormat})` + ); + + // Send audio chunk via WebSocket + this.sendMessage({ + type: "audio_chunk", + chunkId: chunk.id, + data: base64Audio, + format: this.outputFormat, + text: chunk.text, + }); + + // Emit for local handling + this.emit("audio_chunk", { + chunkId: chunk.id, + data: base64Audio, + format: this.outputFormat, + text: chunk.text, + uint8Array: audioData, + }); + } else { + console.log(`No audio data generated for chunk #${chunk.id}`); + } + + // Start generating next chunks in parallel + if (this.streamingSpeechConfig.parallelGeneration) { + const activeRequests = this.speechChunkQueue.filter( + (c) => c.audioPromise + ).length; + const toStart = Math.min( + this.streamingSpeechConfig.maxParallelRequests - activeRequests, + this.speechChunkQueue.length + ); + + if (toStart > 0) { + console.log( + `Starting parallel generation for ${toStart} more chunks` + ); + for (let i = 0; i < toStart; i++) { + const nextChunk = this.speechChunkQueue.find( + (c) => !c.audioPromise + ); + if (nextChunk) { + nextChunk.audioPromise = this.generateChunkAudio(nextChunk); + } + } + } + } + } + } catch (error) { + console.error("Error in speech queue processing:", error); + this.emit("error", error); + } finally { + this._isSpeaking = false; + this.currentSpeechAbortController = undefined; + + // Signal that the speech queue is fully drained + if (this.speechQueueDoneResolve) { + this.speechQueueDoneResolve(); + this.speechQueueDoneResolve = undefined; + this.speechQueueDonePromise = undefined; + } + + console.log(`Speech queue processing complete`); + this.sendMessage({ type: "speech_stream_end" }); + this.emit("speech_complete", { streaming: true }); + } + } +} diff --git a/src/core/StreamProcessor.ts b/src/core/StreamProcessor.ts new file mode 100644 index 0000000..2034b07 --- /dev/null +++ b/src/core/StreamProcessor.ts @@ -0,0 +1,293 @@ +import { type streamText } from "ai"; + +/** + * Result of processing a full LLM stream. + */ +export interface StreamResult { + fullText: string; + fullReasoning: string; + allToolCalls: Array<{ + toolName: string; + toolCallId: string; + input: unknown; + }>; + allToolResults: Array<{ + toolName: string; + toolCallId: string; + output: unknown; + }>; + allSources: Array; + allFiles: Array; +} + +export interface StreamProcessorCallbacks { + /** Called when a text delta arrives (for streaming speech, etc.) */ + onTextDelta?: (text: string) => void; + /** Called when a text-end part arrives (flush speech, etc.) */ + onTextEnd?: () => void; + /** Send a WebSocket message */ + sendMessage: (message: Record) => void; + /** Emit an event on the agent */ + emitEvent: (event: string, data?: unknown) => void; +} + +/** + * Processes the fullStream from an AI SDK `streamText` call, + * forwarding events to WebSocket clients and collecting the complete response. + * + * This is a standalone function (not a class) because it has no persistent state. + */ +export async function processFullStream( + result: ReturnType, + callbacks: StreamProcessorCallbacks, + extraResponseFields?: Record +): Promise { + const { onTextDelta, onTextEnd, sendMessage, emitEvent } = callbacks; + + let fullText = ""; + let fullReasoning = ""; + const allToolCalls: StreamResult["allToolCalls"] = []; + const allToolResults: StreamResult["allToolResults"] = []; + const allSources: unknown[] = []; + const allFiles: unknown[] = []; + + for await (const part of result.fullStream) { + switch (part.type) { + // ── Stream lifecycle ────────────────────────────── + case "start": + sendMessage({ type: "stream_start" }); + break; + + case "finish": + emitEvent("text", { role: "assistant", text: fullText }); + sendMessage({ + type: "stream_finish", + finishReason: part.finishReason, + usage: part.totalUsage, + }); + break; + + case "error": + emitEvent("error", part.error); + sendMessage({ + type: "stream_error", + error: String(part.error), + }); + break; + + case "abort": + emitEvent("abort", { reason: part.reason }); + sendMessage({ + type: "stream_abort", + reason: part.reason, + }); + break; + + // ── Step lifecycle ──────────────────────────────── + case "start-step": + sendMessage({ + type: "step_start", + warnings: part.warnings, + }); + break; + + case "finish-step": + sendMessage({ + type: "step_finish", + finishReason: part.finishReason, + usage: part.usage, + }); + break; + + // ── Text streaming ──────────────────────────────── + case "text-start": + sendMessage({ type: "text_start", id: part.id }); + break; + + case "text-delta": + fullText += part.text; + onTextDelta?.(part.text); + sendMessage({ + type: "text_delta", + id: part.id, + text: part.text, + }); + break; + + case "text-end": + onTextEnd?.(); + sendMessage({ type: "text_end", id: part.id }); + break; + + // ── Reasoning streaming ─────────────────────────── + case "reasoning-start": + sendMessage({ type: "reasoning_start", id: part.id }); + break; + + case "reasoning-delta": + fullReasoning += part.text; + sendMessage({ + type: "reasoning_delta", + id: part.id, + text: part.text, + }); + break; + + case "reasoning-end": + sendMessage({ type: "reasoning_end", id: part.id }); + break; + + // ── Tool input streaming ────────────────────────── + case "tool-input-start": + sendMessage({ + type: "tool_input_start", + id: part.id, + toolName: part.toolName, + }); + break; + + case "tool-input-delta": + sendMessage({ + type: "tool_input_delta", + id: part.id, + delta: part.delta, + }); + break; + + case "tool-input-end": + sendMessage({ type: "tool_input_end", id: part.id }); + break; + + // ── Tool execution ──────────────────────────────── + case "tool-call": + allToolCalls.push({ + toolName: part.toolName, + toolCallId: part.toolCallId, + input: part.input, + }); + sendMessage({ + type: "tool_call", + toolName: part.toolName, + toolCallId: part.toolCallId, + input: part.input, + }); + break; + + case "tool-result": + allToolResults.push({ + toolName: part.toolName, + toolCallId: part.toolCallId, + output: part.output, + }); + sendMessage({ + type: "tool_result", + toolName: part.toolName, + toolCallId: part.toolCallId, + result: part.output, + }); + break; + + case "tool-error": + sendMessage({ + type: "tool_error", + toolName: part.toolName, + toolCallId: part.toolCallId, + error: String(part.error), + }); + break; + + // ── Sources and files ───────────────────────────── + case "source": + allSources.push(part); + sendMessage({ + type: "source", + source: part, + }); + break; + + case "file": + allFiles.push(part.file); + sendMessage({ + type: "file", + file: part.file, + }); + break; + } + } + + // Send the complete response + sendMessage({ + type: "response_complete", + text: fullText, + reasoning: fullReasoning || undefined, + toolCalls: allToolCalls, + toolResults: allToolResults, + sources: allSources.length > 0 ? allSources : undefined, + files: allFiles.length > 0 ? allFiles : undefined, + ...extraResponseFields, + }); + + return { + fullText, + fullReasoning, + allToolCalls, + allToolResults, + allSources, + allFiles, + }; +} + +/** + * Handle onChunk callback events and emit them. + */ +export function handleStreamChunk( + chunk: any, + emitEvent: (event: string, data?: unknown) => void +): void { + switch (chunk.type) { + case "text-delta": + emitEvent("chunk:text_delta", { id: chunk.id, text: chunk.text }); + break; + + case "reasoning-delta": + emitEvent("chunk:reasoning_delta", { + id: chunk.id, + text: chunk.text, + }); + break; + + case "tool-call": + emitEvent("chunk:tool_call", { + toolName: chunk.toolName, + toolCallId: chunk.toolCallId, + input: chunk.input, + }); + break; + + case "tool-result": + emitEvent("chunk:tool_result", { + toolName: chunk.toolName, + toolCallId: chunk.toolCallId, + result: chunk.output, + }); + break; + + case "tool-input-start": + emitEvent("chunk:tool_input_start", { + id: chunk.id, + toolName: chunk.toolName, + }); + break; + + case "tool-input-delta": + emitEvent("chunk:tool_input_delta", { + id: chunk.id, + delta: chunk.delta, + }); + break; + + case "source": + emitEvent("chunk:source", chunk); + break; + } +} diff --git a/src/core/TranscriptionManager.ts b/src/core/TranscriptionManager.ts new file mode 100644 index 0000000..2510648 --- /dev/null +++ b/src/core/TranscriptionManager.ts @@ -0,0 +1,142 @@ +import { EventEmitter } from "events"; +import { + experimental_transcribe as transcribe, + type TranscriptionModel, +} from "ai"; +import { DEFAULT_MAX_AUDIO_SIZE } from "../types"; + +export interface TranscriptionManagerOptions { + transcriptionModel?: TranscriptionModel; + maxAudioInputSize?: number; +} + +/** + * Handles audio transcription using the AI SDK transcription model + * and validation of incoming audio data. + */ +export class TranscriptionManager extends EventEmitter { + private transcriptionModel?: TranscriptionModel; + private maxAudioInputSize: number; + + /** Callback to send messages over the WebSocket */ + public sendMessage: (message: Record) => void = () => {}; + + constructor(options: TranscriptionManagerOptions = {}) { + super(); + this.transcriptionModel = options.transcriptionModel; + this.maxAudioInputSize = + options.maxAudioInputSize ?? DEFAULT_MAX_AUDIO_SIZE; + } + + get hasTranscriptionModel(): boolean { + return !!this.transcriptionModel; + } + + /** + * Transcribe audio data to text. + */ + async transcribeAudio(audioData: Buffer | Uint8Array): Promise { + if (!this.transcriptionModel) { + throw new Error("Transcription model not configured"); + } + + console.log( + `Sending ${audioData.byteLength} bytes to Whisper for transcription` + ); + + try { + const result = await transcribe({ + model: this.transcriptionModel, + audio: audioData, + }); + + console.log( + `Whisper transcription result: "${result.text}", language: ${result.language || "unknown"}` + ); + + this.emit("transcription", { + text: result.text, + language: result.language, + }); + + // Send transcription to client for immediate feedback + this.sendMessage({ + type: "transcription_result", + text: result.text, + language: result.language, + }); + + return result.text; + } catch (error) { + console.error("Whisper transcription failed:", error); + throw error; + } + } + + /** + * Process incoming base64-encoded audio: validate, decode, transcribe. + * Returns the transcribed text, or null if invalid / empty. + */ + async processAudioInput( + base64Audio: string, + format?: string + ): Promise { + if (!this.transcriptionModel) { + const error = new Error( + "Transcription model not configured for audio input" + ); + this.emit("error", error); + this.sendMessage({ type: "error", error: error.message }); + return null; + } + + try { + const audioBuffer = Buffer.from(base64Audio, "base64"); + + // Validate audio size + if (audioBuffer.length > this.maxAudioInputSize) { + const sizeMB = (audioBuffer.length / (1024 * 1024)).toFixed(1); + const maxMB = (this.maxAudioInputSize / (1024 * 1024)).toFixed(1); + this.emit( + "error", + new Error( + `Audio input too large (${sizeMB} MB). Maximum allowed: ${maxMB} MB` + ) + ); + return null; + } + + if (audioBuffer.length === 0) { + this.emit("warning", "Received empty audio data"); + return null; + } + + this.emit("audio_received", { size: audioBuffer.length, format }); + console.log( + `Processing audio input: ${audioBuffer.length} bytes, format: ${format || "unknown"}` + ); + + const transcribedText = await this.transcribeAudio(audioBuffer); + console.log(`Transcribed text: "${transcribedText}"`); + + if (!transcribedText.trim()) { + this.emit("warning", "Transcription returned empty text"); + this.sendMessage({ + type: "transcription_error", + error: "Whisper returned empty text", + }); + return null; + } + + return transcribedText; + } catch (error) { + console.error("Failed to process audio input:", error); + this.emit("error", error); + this.sendMessage({ + type: "transcription_error", + error: `Transcription failed: ${(error as Error).message || String(error)}`, + }); + return null; + } + } +} diff --git a/src/core/WebSocketManager.ts b/src/core/WebSocketManager.ts new file mode 100644 index 0000000..1211ca6 --- /dev/null +++ b/src/core/WebSocketManager.ts @@ -0,0 +1,133 @@ +import { WebSocket } from "ws"; +import { EventEmitter } from "events"; + +/** + * Manages a single WebSocket connection lifecycle. + * Handles connecting, attaching existing sockets, sending messages, + * and clean disconnection. + */ +export class WebSocketManager extends EventEmitter { + private socket?: WebSocket; + private _isConnected = false; + + get isConnected(): boolean { + return this._isConnected; + } + + get currentSocket(): WebSocket | undefined { + return this.socket; + } + + /** + * Connect to a WebSocket server by URL. + */ + connect(url: string): Promise { + // Clean up any existing connection first + if (this.socket) { + this.disconnect(); + } + + return new Promise((resolve, reject) => { + try { + this.socket = new WebSocket(url); + this.attachListeners(); + + this.socket.once("open", () => { + this._isConnected = true; + this.emit("connected"); + resolve(); + }); + + this.socket.once("error", (error) => { + reject(error); + }); + } catch (error) { + reject(error); + } + }); + } + + /** + * Attach an existing WebSocket (server-side usage). + */ + handleSocket(socket: WebSocket): void { + // Clean up any existing connection first + if (this.socket) { + this.disconnect(); + } + + this.socket = socket; + this._isConnected = true; + this.attachListeners(); + this.emit("connected"); + } + + /** + * Send a JSON message via WebSocket if connected. + * Gracefully handles send failures (e.g., socket closing mid-send). + */ + send(message: Record): void { + if (!this.socket || !this._isConnected) return; + + try { + if (this.socket.readyState === WebSocket.OPEN) { + this.socket.send(JSON.stringify(message)); + } else { + console.warn(`Cannot send message, socket state: ${this.socket.readyState}`); + } + } catch (error) { + // Socket may have closed between the readyState check and send() + console.error("Failed to send WebSocket message:", error); + this.emit("error", error); + } + } + + /** + * Disconnect and clean up the current socket. + */ + disconnect(): void { + if (!this.socket) return; + + try { + this.socket.removeAllListeners(); + if ( + this.socket.readyState === WebSocket.OPEN || + this.socket.readyState === WebSocket.CONNECTING + ) { + this.socket.close(); + } + } catch { + // Ignore close errors — socket may already be dead + } + + this.socket = undefined; + this._isConnected = false; + } + + /** + * Attach internal event listeners on the current socket. + */ + private attachListeners(): void { + if (!this.socket) return; + + this.socket.on("message", (data) => { + try { + const message = JSON.parse(data.toString()); + this.emit("message", message); + } catch (err) { + console.error("Failed to parse WebSocket message:", err); + this.emit("error", err); + } + }); + + this.socket.on("close", () => { + this._isConnected = false; + this.emit("disconnected"); + }); + + this.socket.on("error", (error) => { + console.error("WebSocket error:", error); + this.emit("error", error); + }); + } +} diff --git a/src/core/index.ts b/src/core/index.ts new file mode 100644 index 0000000..f81898b --- /dev/null +++ b/src/core/index.ts @@ -0,0 +1,17 @@ +export { WebSocketManager } from "./WebSocketManager"; +export { SpeechManager, type SpeechManagerOptions } from "./SpeechManager"; +export { + ConversationManager, + type ConversationManagerOptions, +} from "./ConversationManager"; +export { + TranscriptionManager, + type TranscriptionManagerOptions, +} from "./TranscriptionManager"; +export { + processFullStream, + handleStreamChunk, + type StreamResult, + type StreamProcessorCallbacks, +} from "./StreamProcessor"; +export { InputQueue, type QueueItem } from "./InputQueue"; diff --git a/src/index.ts b/src/index.ts index 5b5786a..14183f6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,5 @@ // Agents -export { VoiceAgent, type VoiceAgentOptions } from "./VoiceAgent"; +export { VoiceAgent, type VoiceAgentOptions } from "./VoiceAgent.new"; export { VideoAgent, type VideoAgentOptions, @@ -8,7 +8,7 @@ export { type VideoAgentConfig, type FrameContext, type FrameTriggerReason, -} from "./VideoAgent"; +} from "./VideoAgent.new"; // Shared types export {