UNPKG

@volley/recognition-client-sdk

Version:

Recognition Service TypeScript/Node.js Client SDK

203 lines (177 loc) 6.23 kB
/** * VGF Recognition Mapper * * Maps between the existing recognition client types and the simplified VGF state. * This provides a clean abstraction layer for game developers. */ import { RecognitionState, RecordingStatus, TranscriptionStatus, createInitialRecognitionState } from './vgf-recognition-state.js'; import { ClientState, IRecognitionClientConfig } from './recognition-client.types.js'; import { TranscriptionResultV1, ErrorResultV1 } from '@recog/shared-types'; /** * Maps ClientState to RecordingStatus for VGF state */ export function mapClientStateToRecordingStatus(clientState: ClientState): string { switch (clientState) { case ClientState.INITIAL: case ClientState.CONNECTING: case ClientState.CONNECTED: return RecordingStatus.NOT_READY; case ClientState.READY: // Ready to record, but not recording yet return RecordingStatus.READY; case ClientState.STOPPING: case ClientState.STOPPED: case ClientState.FAILED: return RecordingStatus.FINISHED; default: return RecordingStatus.NOT_READY; } } /** * Creates a VGF state from transcription result */ export function mapTranscriptionResultToState( currentState: RecognitionState, result: TranscriptionResultV1, isRecording: boolean ): RecognitionState { const newState = { ...currentState }; // Update recording status if actively recording if (isRecording && currentState.startRecordingStatus !== RecordingStatus.FINISHED) { newState.startRecordingStatus = RecordingStatus.RECORDING; // Set start timestamp on first audio if (!newState.startRecordingTimestamp) { newState.startRecordingTimestamp = new Date().toISOString(); } } // Update transcription status if (!result.is_finished) { // Has pending transcript - STEP 2 support newState.transcriptionStatus = TranscriptionStatus.IN_PROGRESS; // Direct copy of pending transcript without any combination newState.pendingTranscript = result.pendingTranscript || ""; // Direct copy of pending confidence if (result.pendingTranscriptConfidence !== undefined) { newState.pendingConfidence = result.pendingTranscriptConfidence; } // Also update final transcript if we have it (even if not finished) if (result.finalTranscript) { newState.finalTranscript = result.finalTranscript; if (result.finalTranscriptConfidence !== undefined) { newState.finalConfidence = result.finalTranscriptConfidence; } } } else { // Transcription is finished newState.transcriptionStatus = TranscriptionStatus.FINALIZED; newState.finalTranscript = result.finalTranscript || ""; if (result.finalTranscriptConfidence !== undefined) { newState.finalConfidence = result.finalTranscriptConfidence; } newState.finalTranscriptionTimestamp = new Date().toISOString(); // Clear pending when we have final newState.pendingTranscript = ""; newState.pendingConfidence = undefined; } return newState; } /** * Maps error to state */ export function mapErrorToState( currentState: RecognitionState, error: ErrorResultV1 ): RecognitionState { return { ...currentState, transcriptionStatus: TranscriptionStatus.ERROR, startRecordingStatus: RecordingStatus.FINISHED, finalRecordingTimestamp: new Date().toISOString() }; } /** * Creates initial VGF state from client config */ export function createVGFStateFromConfig(config: IRecognitionClientConfig): RecognitionState { const audioUtteranceId = config.audioUtteranceId || generateUUID(); const state = createInitialRecognitionState(audioUtteranceId); // Store ASR config as JSON if provided if (config.asrRequestConfig) { state.asrConfig = JSON.stringify(config.asrRequestConfig); } return state; } /** * Updates state when recording stops */ export function updateStateOnStop(currentState: RecognitionState): RecognitionState { return { ...currentState, startRecordingStatus: RecordingStatus.FINISHED, finalRecordingTimestamp: new Date().toISOString() }; } /** * Updates state when client becomes ready */ export function updateStateOnReady(currentState: RecognitionState): RecognitionState { return { ...currentState, startRecordingStatus: RecordingStatus.READY }; } /** * Parses function call from transcript (STEP 3 support) * This is a placeholder - actual implementation would use NLP/LLM */ export function extractFunctionCallFromTranscript( transcript: string, gameContext?: any ): { metadata?: string; confidence?: number } | null { // This would be replaced with actual function call extraction logic // For example, using an LLM to parse intent from the transcript // and map it to game actions // Example stub implementation: const lowerTranscript = transcript.toLowerCase(); // Simple pattern matching for demo if (lowerTranscript.includes("play") && lowerTranscript.includes("artist")) { return { metadata: JSON.stringify({ action: "play", target: "artist" }), confidence: 0.8 }; } return null; } /** * Updates state with function call results (STEP 3) */ export function updateStateWithFunctionCall( currentState: RecognitionState, functionCall: { metadata?: string; confidence?: number } ): RecognitionState { return { ...currentState, functionCallMetadata: functionCall.metadata, functionCallConfidence: functionCall.confidence, finalFunctionCallTimestamp: new Date().toISOString() }; } // Helper function to generate UUID (simplified version) function generateUUID(): string { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { const r = Math.random() * 16 | 0; const v = c === 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); }); }