@volley/recognition-client-sdk 0.1.296 → 0.1.381
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.bundled.d.ts +1163 -0
- package/dist/index.bundled.d.ts +2342 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +146 -90
- package/dist/index.js.map +4 -4
- package/dist/recog-client-sdk.browser.js +85 -81
- package/dist/recog-client-sdk.browser.js.map +4 -4
- package/dist/recognition-client.d.ts +4 -0
- package/dist/recognition-client.d.ts.map +1 -1
- package/dist/simplified-vgf-recognition-client.d.ts +2 -0
- package/dist/simplified-vgf-recognition-client.d.ts.map +1 -1
- package/dist/vgf-recognition-state.d.ts +9 -0
- package/dist/vgf-recognition-state.d.ts.map +1 -1
- package/package.json +27 -25
- package/src/index.ts +2 -0
- package/src/recognition-client.ts +54 -2
- package/src/simplified-vgf-recognition-client.spec.ts +302 -17
- package/src/simplified-vgf-recognition-client.ts +68 -12
- package/src/vgf-recognition-state.ts +12 -0
|
@@ -150,34 +150,44 @@ export class SimplifiedVGFRecognitionClient implements ISimplifiedVGFRecognition
|
|
|
150
150
|
private state: RecognitionState;
|
|
151
151
|
private isRecordingAudio: boolean = false;
|
|
152
152
|
private stateChangeCallback: ((state: RecognitionState) => void) | undefined;
|
|
153
|
+
private expectedUuid: string;
|
|
154
|
+
private logger: IRecognitionClientConfig['logger'];
|
|
153
155
|
|
|
154
156
|
constructor(config: SimplifiedVGFClientConfig) {
|
|
155
157
|
const { onStateChange, initialState, ...clientConfig } = config;
|
|
156
158
|
this.stateChangeCallback = onStateChange;
|
|
159
|
+
this.logger = clientConfig.logger;
|
|
157
160
|
|
|
158
161
|
// Use provided initial state or create from config
|
|
159
162
|
if (initialState) {
|
|
160
|
-
//
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
163
|
+
// Check if initial state has a valid UUID
|
|
164
|
+
const needsNewUuid = !initialState.audioUtteranceId ||
|
|
165
|
+
initialState.audioUtteranceId === '' ||
|
|
166
|
+
initialState.transcriptionStatus === TranscriptionStatus.ABORTED ||
|
|
167
|
+
initialState.transcriptionStatus === TranscriptionStatus.FINALIZED;
|
|
164
168
|
|
|
169
|
+
if (needsNewUuid) {
|
|
165
170
|
// Generate new UUID for fresh session
|
|
166
171
|
const newUUID = crypto.randomUUID();
|
|
167
172
|
|
|
168
173
|
if (clientConfig.logger) {
|
|
169
|
-
|
|
174
|
+
const reason = !initialState.audioUtteranceId ? 'Missing UUID' :
|
|
175
|
+
initialState.audioUtteranceId === '' ? 'Empty UUID' :
|
|
176
|
+
`Terminal session (${initialState.transcriptionStatus})`;
|
|
177
|
+
clientConfig.logger('info', `${reason} detected, generating new UUID: ${newUUID}`);
|
|
170
178
|
}
|
|
171
179
|
|
|
172
|
-
// Update state with new UUID and reset session-specific fields
|
|
180
|
+
// Update state with new UUID and reset session-specific fields if terminal
|
|
173
181
|
this.state = {
|
|
174
182
|
...initialState,
|
|
175
183
|
audioUtteranceId: newUUID,
|
|
176
|
-
// Reset status fields for fresh session
|
|
177
|
-
transcriptionStatus
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
184
|
+
// Reset status fields for fresh session if terminal state
|
|
185
|
+
...(initialState.transcriptionStatus === TranscriptionStatus.ABORTED ||
|
|
186
|
+
initialState.transcriptionStatus === TranscriptionStatus.FINALIZED ? {
|
|
187
|
+
transcriptionStatus: TranscriptionStatus.NOT_STARTED,
|
|
188
|
+
startRecordingStatus: RecordingStatus.READY,
|
|
189
|
+
finalTranscript: undefined
|
|
190
|
+
} : {})
|
|
181
191
|
};
|
|
182
192
|
|
|
183
193
|
// Use new UUID in client config
|
|
@@ -188,7 +198,7 @@ export class SimplifiedVGFRecognitionClient implements ISimplifiedVGFRecognition
|
|
|
188
198
|
onStateChange(this.state);
|
|
189
199
|
}
|
|
190
200
|
} else {
|
|
191
|
-
// Non-terminal state - safe to reuse
|
|
201
|
+
// Non-terminal state with valid UUID - safe to reuse (e.g., reconnecting to IN_PROGRESS session)
|
|
192
202
|
this.state = initialState;
|
|
193
203
|
// Override audioUtteranceId in config if state has one
|
|
194
204
|
if (initialState.audioUtteranceId && !clientConfig.audioUtteranceId) {
|
|
@@ -203,6 +213,9 @@ export class SimplifiedVGFRecognitionClient implements ISimplifiedVGFRecognition
|
|
|
203
213
|
// Client is immediately ready to accept audio (will buffer if not connected)
|
|
204
214
|
this.state = { ...this.state, startRecordingStatus: 'READY' };
|
|
205
215
|
|
|
216
|
+
// Track the expected UUID for this session
|
|
217
|
+
this.expectedUuid = this.state.audioUtteranceId;
|
|
218
|
+
|
|
206
219
|
// If VGF state has promptSlotMap, configure gameContext to use it
|
|
207
220
|
if (this.state.promptSlotMap) {
|
|
208
221
|
// Set useContext=true in ASR config to enable context processing
|
|
@@ -229,6 +242,20 @@ export class SimplifiedVGFRecognitionClient implements ISimplifiedVGFRecognition
|
|
|
229
242
|
|
|
230
243
|
// These callbacks ONLY update the VGF state sink
|
|
231
244
|
onTranscript: (result) => {
|
|
245
|
+
// Skip update if UUID doesn't match (stale callback from previous session)
|
|
246
|
+
if (result.audioUtteranceId && result.audioUtteranceId !== this.expectedUuid) {
|
|
247
|
+
if (this.logger) {
|
|
248
|
+
this.logger('warn',
|
|
249
|
+
`[VGF] Skipping transcript update: UUID mismatch (expected: ${this.expectedUuid}, got: ${result.audioUtteranceId})`
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
// Still call original callback if provided
|
|
253
|
+
if (clientConfig.onTranscript) {
|
|
254
|
+
clientConfig.onTranscript(result);
|
|
255
|
+
}
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
|
|
232
259
|
// Update VGF state based on transcript
|
|
233
260
|
this.state = mapTranscriptionResultToState(this.state, result, this.isRecordingAudio);
|
|
234
261
|
this.notifyStateChange();
|
|
@@ -240,6 +267,20 @@ export class SimplifiedVGFRecognitionClient implements ISimplifiedVGFRecognition
|
|
|
240
267
|
},
|
|
241
268
|
|
|
242
269
|
onMetadata: (metadata) => {
|
|
270
|
+
// Skip update if UUID doesn't match (stale callback from previous session)
|
|
271
|
+
if (metadata.audioUtteranceId && metadata.audioUtteranceId !== this.expectedUuid) {
|
|
272
|
+
if (this.logger) {
|
|
273
|
+
this.logger('warn',
|
|
274
|
+
`[VGF] Skipping metadata update: UUID mismatch (expected: ${this.expectedUuid}, got: ${metadata.audioUtteranceId})`
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
// Still call original callback if provided
|
|
278
|
+
if (clientConfig.onMetadata) {
|
|
279
|
+
clientConfig.onMetadata(metadata);
|
|
280
|
+
}
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
|
|
243
284
|
this.state = mapMetadataToState(this.state, metadata);
|
|
244
285
|
this.notifyStateChange();
|
|
245
286
|
|
|
@@ -256,6 +297,20 @@ export class SimplifiedVGFRecognitionClient implements ISimplifiedVGFRecognition
|
|
|
256
297
|
},
|
|
257
298
|
|
|
258
299
|
onError: (error) => {
|
|
300
|
+
// Skip update if UUID doesn't match (stale callback from previous session)
|
|
301
|
+
if (error.audioUtteranceId && error.audioUtteranceId !== this.expectedUuid) {
|
|
302
|
+
if (this.logger) {
|
|
303
|
+
this.logger('warn',
|
|
304
|
+
`[VGF] Skipping error update: UUID mismatch (expected: ${this.expectedUuid}, got: ${error.audioUtteranceId})`
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
// Still call original callback if provided
|
|
308
|
+
if (clientConfig.onError) {
|
|
309
|
+
clientConfig.onError(error);
|
|
310
|
+
}
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
|
|
259
314
|
this.isRecordingAudio = false; // Reset on error
|
|
260
315
|
this.state = mapErrorToState(this.state, error);
|
|
261
316
|
this.notifyStateChange();
|
|
@@ -382,6 +437,7 @@ export class SimplifiedVGFRecognitionClient implements ISimplifiedVGFRecognition
|
|
|
382
437
|
}
|
|
383
438
|
|
|
384
439
|
private notifyStateChange(): void {
|
|
440
|
+
// State has already been validated for correct UUID before this is called
|
|
385
441
|
if (this.stateChangeCallback) {
|
|
386
442
|
this.stateChangeCallback({ ...this.state });
|
|
387
443
|
}
|
|
@@ -39,6 +39,9 @@ export const RecognitionVGFStateSchema = z.object({
|
|
|
39
39
|
|
|
40
40
|
// Support for prompt slot mapping - passed to recognition context when present
|
|
41
41
|
promptSlotMap: z.record(z.string(), z.array(z.string())).optional(), // Optional map of slot names to prompt values for recognition context
|
|
42
|
+
|
|
43
|
+
// Recognition action processing state - managed externally, SDK preserves but never modifies
|
|
44
|
+
recognitionActionProcessingState: z.string().optional(), // "NOT_STARTED", "IN_PROGRESS", "COMPLETED"
|
|
42
45
|
})
|
|
43
46
|
|
|
44
47
|
export type RecognitionState = z.infer<typeof RecognitionVGFStateSchema>
|
|
@@ -63,6 +66,14 @@ export const TranscriptionStatus = {
|
|
|
63
66
|
|
|
64
67
|
export type TranscriptionStatusType = typeof TranscriptionStatus[keyof typeof TranscriptionStatus]
|
|
65
68
|
|
|
69
|
+
export const RecognitionActionProcessingState = {
|
|
70
|
+
NOT_STARTED: "NOT_STARTED",
|
|
71
|
+
IN_PROGRESS: "IN_PROGRESS",
|
|
72
|
+
COMPLETED: "COMPLETED",
|
|
73
|
+
} as const
|
|
74
|
+
|
|
75
|
+
export type RecognitionActionProcessingStateType = typeof RecognitionActionProcessingState[keyof typeof RecognitionActionProcessingState]
|
|
76
|
+
|
|
66
77
|
// Helper function to create initial state
|
|
67
78
|
export function createInitialRecognitionState(audioUtteranceId: string): RecognitionState {
|
|
68
79
|
return {
|
|
@@ -70,6 +81,7 @@ export function createInitialRecognitionState(audioUtteranceId: string): Recogni
|
|
|
70
81
|
startRecordingStatus: RecordingStatus.NOT_READY,
|
|
71
82
|
transcriptionStatus: TranscriptionStatus.NOT_STARTED,
|
|
72
83
|
pendingTranscript: "",
|
|
84
|
+
recognitionActionProcessingState: RecognitionActionProcessingState.NOT_STARTED,
|
|
73
85
|
}
|
|
74
86
|
}
|
|
75
87
|
|