@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
|
@@ -100,6 +100,10 @@ export declare class RealTimeTwoWayWebSocketRecognitionClient extends WebSocketA
|
|
|
100
100
|
getStats(): IRecognitionClientStats;
|
|
101
101
|
protected onConnected(): void;
|
|
102
102
|
protected onDisconnected(code: number, reason: string): void;
|
|
103
|
+
/**
|
|
104
|
+
* Get human-readable description for WebSocket close code
|
|
105
|
+
*/
|
|
106
|
+
private getCloseCodeDescription;
|
|
103
107
|
protected onError(error: Event): void;
|
|
104
108
|
protected onMessage(msg: {
|
|
105
109
|
v: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recognition-client.d.ts","sourceRoot":"","sources":["../src/recognition-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAML,KAAK,qBAAqB,EAS3B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC5D,OAAO,KAAK,EACV,kBAAkB,EAClB,uBAAuB,EACvB,8CAA8C,EAE/C,MAAM,+BAA+B,CAAC;AAUvC;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE3D;AAgCD;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,qBAAqB,CAAC;AAGxD,YAAY,EAAE,8CAA8C,EAAE,MAAM,+BAA+B,CAAC;AAgCpG;;;;;GAKG;AACH,qBAAa,wCACX,SAAQ,oBAAoB,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,CAC7C,YAAW,kBAAkB;IAE7B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAK;IAE7C,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,KAAK,CAAoC;IACjD,OAAO,CAAC,iBAAiB,CAA4B;IAGrD,OAAO,CAAC,iBAAiB,CAAS;IAGlC,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,qBAAqB,CAAO;IACpC,OAAO,CAAC,iBAAiB,CAAK;gBAElB,MAAM,EAAE,8CAA8C;IA8ElE;;;;;;OAMG;IACH,OAAO,CAAC,GAAG;IAWX;;;OAGG;IACH,OAAO,CAAC,OAAO;IAmBA,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IA6BvC;;;OAGG;YACW,gBAAgB;IAkIrB,SAAS,CAAC,SAAS,EAAE,WAAW,GAAG,eAAe,GAAG,IAAI,GAAG,IAAI;IAiBzE,OAAO,CAAC,iBAAiB;IAsCnB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAoCpC,cAAc,IAAI,IAAI;IAwBtB,mBAAmB,IAAI,MAAM;IAI7B,MAAM,IAAI,MAAM;IAIhB,QAAQ,IAAI,WAAW;IAIvB,WAAW,IAAI,OAAO;IAItB,YAAY,IAAI,OAAO;IAIvB,UAAU,IAAI,OAAO;IAIrB,uBAAuB,IAAI,OAAO;IAIlC,mBAAmB,IAAI,OAAO;IAI9B,QAAQ,IAAI,uBAAuB;IAgBnC,SAAS,CAAC,WAAW,IAAI,IAAI;IAiE7B,SAAS,CAAC,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;
|
|
1
|
+
{"version":3,"file":"recognition-client.d.ts","sourceRoot":"","sources":["../src/recognition-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAML,KAAK,qBAAqB,EAS3B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC5D,OAAO,KAAK,EACV,kBAAkB,EAClB,uBAAuB,EACvB,8CAA8C,EAE/C,MAAM,+BAA+B,CAAC;AAUvC;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE3D;AAgCD;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,qBAAqB,CAAC;AAGxD,YAAY,EAAE,8CAA8C,EAAE,MAAM,+BAA+B,CAAC;AAgCpG;;;;;GAKG;AACH,qBAAa,wCACX,SAAQ,oBAAoB,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,CAC7C,YAAW,kBAAkB;IAE7B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAK;IAE7C,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,KAAK,CAAoC;IACjD,OAAO,CAAC,iBAAiB,CAA4B;IAGrD,OAAO,CAAC,iBAAiB,CAAS;IAGlC,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,qBAAqB,CAAO;IACpC,OAAO,CAAC,iBAAiB,CAAK;gBAElB,MAAM,EAAE,8CAA8C;IA8ElE;;;;;;OAMG;IACH,OAAO,CAAC,GAAG;IAWX;;;OAGG;IACH,OAAO,CAAC,OAAO;IAmBA,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IA6BvC;;;OAGG;YACW,gBAAgB;IAkIrB,SAAS,CAAC,SAAS,EAAE,WAAW,GAAG,eAAe,GAAG,IAAI,GAAG,IAAI;IAiBzE,OAAO,CAAC,iBAAiB;IAsCnB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAoCpC,cAAc,IAAI,IAAI;IAwBtB,mBAAmB,IAAI,MAAM;IAI7B,MAAM,IAAI,MAAM;IAIhB,QAAQ,IAAI,WAAW;IAIvB,WAAW,IAAI,OAAO;IAItB,YAAY,IAAI,OAAO;IAIvB,UAAU,IAAI,OAAO;IAIrB,uBAAuB,IAAI,OAAO;IAIlC,mBAAmB,IAAI,OAAO;IAI9B,QAAQ,IAAI,uBAAuB;IAgBnC,SAAS,CAAC,WAAW,IAAI,IAAI;IAiE7B,SAAS,CAAC,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IA8C5D;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAwB/B,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;cAYlB,SAAS,CAAC,GAAG,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,GAAG,CAAA;KAAE,GAAG,IAAI;IAQ/E;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAyB5B;;;OAGG;IACH,OAAO,CAAC,YAAY;CAuBrB"}
|
|
@@ -111,6 +111,8 @@ export declare class SimplifiedVGFRecognitionClient implements ISimplifiedVGFRec
|
|
|
111
111
|
private state;
|
|
112
112
|
private isRecordingAudio;
|
|
113
113
|
private stateChangeCallback;
|
|
114
|
+
private expectedUuid;
|
|
115
|
+
private logger;
|
|
114
116
|
constructor(config: SimplifiedVGFClientConfig);
|
|
115
117
|
connect(): Promise<void>;
|
|
116
118
|
sendAudio(audioData: ArrayBuffer | ArrayBufferView | Blob): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"simplified-vgf-recognition-client.d.ts","sourceRoot":"","sources":["../src/simplified-vgf-recognition-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACH,gBAAgB,EAGnB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAEH,wBAAwB,EACxB,WAAW,EACd,MAAM,+BAA+B,CAAC;AAWvC;;GAEG;AACH,MAAM,WAAW,yBAA0B,SAAQ,wBAAwB;IACvE;;;OAGG;IACH,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAElD;;;OAGG;IACH,YAAY,CAAC,EAAE,gBAAgB,CAAC;CACnC;AAED;;;;;GAKG;AACH,MAAM,WAAW,+BAA+B;IAE5C;;;OAGG;IACH,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzB;;;OAGG;IACH,SAAS,CAAC,SAAS,EAAE,WAAW,GAAG,eAAe,GAAG,IAAI,GAAG,IAAI,CAAC;IAEjE;;;OAGG;IACH,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAE/B;;;;;;;;;;;;;;;;OAgBG;IACH,cAAc,IAAI,IAAI,CAAC;IAGvB;;;OAGG;IACH,WAAW,IAAI,gBAAgB,CAAC;IAGhC;;OAEG;IACH,WAAW,IAAI,OAAO,CAAC;IAEvB;;OAEG;IACH,YAAY,IAAI,OAAO,CAAC;IAExB;;OAEG;IACH,UAAU,IAAI,OAAO,CAAC;IAEtB;;OAEG;IACH,uBAAuB,IAAI,OAAO,CAAC;IAEnC;;OAEG;IACH,mBAAmB,IAAI,OAAO,CAAC;IAG/B;;OAEG;IACH,mBAAmB,IAAI,MAAM,CAAC;IAE9B;;OAEG;IACH,MAAM,IAAI,MAAM,CAAC;IAEjB;;OAEG;IACH,QAAQ,IAAI,WAAW,CAAC;CAE3B;AAED;;;GAGG;AACH,qBAAa,8BAA+B,YAAW,+BAA+B;IAClF,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,KAAK,CAAmB;IAChC,OAAO,CAAC,gBAAgB,CAAkB;IAC1C,OAAO,CAAC,mBAAmB,CAAkD;
|
|
1
|
+
{"version":3,"file":"simplified-vgf-recognition-client.d.ts","sourceRoot":"","sources":["../src/simplified-vgf-recognition-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACH,gBAAgB,EAGnB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAEH,wBAAwB,EACxB,WAAW,EACd,MAAM,+BAA+B,CAAC;AAWvC;;GAEG;AACH,MAAM,WAAW,yBAA0B,SAAQ,wBAAwB;IACvE;;;OAGG;IACH,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAElD;;;OAGG;IACH,YAAY,CAAC,EAAE,gBAAgB,CAAC;CACnC;AAED;;;;;GAKG;AACH,MAAM,WAAW,+BAA+B;IAE5C;;;OAGG;IACH,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzB;;;OAGG;IACH,SAAS,CAAC,SAAS,EAAE,WAAW,GAAG,eAAe,GAAG,IAAI,GAAG,IAAI,CAAC;IAEjE;;;OAGG;IACH,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAE/B;;;;;;;;;;;;;;;;OAgBG;IACH,cAAc,IAAI,IAAI,CAAC;IAGvB;;;OAGG;IACH,WAAW,IAAI,gBAAgB,CAAC;IAGhC;;OAEG;IACH,WAAW,IAAI,OAAO,CAAC;IAEvB;;OAEG;IACH,YAAY,IAAI,OAAO,CAAC;IAExB;;OAEG;IACH,UAAU,IAAI,OAAO,CAAC;IAEtB;;OAEG;IACH,uBAAuB,IAAI,OAAO,CAAC;IAEnC;;OAEG;IACH,mBAAmB,IAAI,OAAO,CAAC;IAG/B;;OAEG;IACH,mBAAmB,IAAI,MAAM,CAAC;IAE9B;;OAEG;IACH,MAAM,IAAI,MAAM,CAAC;IAEjB;;OAEG;IACH,QAAQ,IAAI,WAAW,CAAC;CAE3B;AAED;;;GAGG;AACH,qBAAa,8BAA+B,YAAW,+BAA+B;IAClF,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,KAAK,CAAmB;IAChC,OAAO,CAAC,gBAAgB,CAAkB;IAC1C,OAAO,CAAC,mBAAmB,CAAkD;IAC7E,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,MAAM,CAAqC;gBAEvC,MAAM,EAAE,yBAAyB;IA0LvC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAK9B,SAAS,CAAC,SAAS,EAAE,WAAW,GAAG,eAAe,GAAG,IAAI,GAAG,IAAI;IAc1D,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAOpC,cAAc,IAAI,IAAI;IAiCtB,mBAAmB,IAAI,MAAM;IAI7B,MAAM,IAAI,MAAM;IAIhB,QAAQ,IAAI,WAAW;IAIvB,WAAW,IAAI,OAAO;IAItB,YAAY,IAAI,OAAO;IAIvB,UAAU,IAAI,OAAO;IAIrB,uBAAuB,IAAI,OAAO;IAIlC,mBAAmB,IAAI,OAAO;IAM9B,WAAW,IAAI,gBAAgB;IAI/B,OAAO,CAAC,iBAAiB;CAM5B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,yBAAyB,GAAG,+BAA+B,CAE5G"}
|
|
@@ -28,6 +28,7 @@ export declare const RecognitionVGFStateSchema: z.ZodObject<{
|
|
|
28
28
|
functionCallConfidence: z.ZodOptional<z.ZodNumber>;
|
|
29
29
|
finalFunctionCallTimestamp: z.ZodOptional<z.ZodString>;
|
|
30
30
|
promptSlotMap: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString, "many">>>;
|
|
31
|
+
recognitionActionProcessingState: z.ZodOptional<z.ZodString>;
|
|
31
32
|
}, "strip", z.ZodTypeAny, {
|
|
32
33
|
audioUtteranceId: string;
|
|
33
34
|
pendingTranscript: string;
|
|
@@ -44,6 +45,7 @@ export declare const RecognitionVGFStateSchema: z.ZodObject<{
|
|
|
44
45
|
functionCallConfidence?: number | undefined;
|
|
45
46
|
finalFunctionCallTimestamp?: string | undefined;
|
|
46
47
|
promptSlotMap?: Record<string, string[]> | undefined;
|
|
48
|
+
recognitionActionProcessingState?: string | undefined;
|
|
47
49
|
}, {
|
|
48
50
|
audioUtteranceId: string;
|
|
49
51
|
startRecordingStatus?: string | undefined;
|
|
@@ -60,6 +62,7 @@ export declare const RecognitionVGFStateSchema: z.ZodObject<{
|
|
|
60
62
|
functionCallConfidence?: number | undefined;
|
|
61
63
|
finalFunctionCallTimestamp?: string | undefined;
|
|
62
64
|
promptSlotMap?: Record<string, string[]> | undefined;
|
|
65
|
+
recognitionActionProcessingState?: string | undefined;
|
|
63
66
|
}>;
|
|
64
67
|
export type RecognitionState = z.infer<typeof RecognitionVGFStateSchema>;
|
|
65
68
|
export declare const RecordingStatus: {
|
|
@@ -77,6 +80,12 @@ export declare const TranscriptionStatus: {
|
|
|
77
80
|
readonly ERROR: "ERROR";
|
|
78
81
|
};
|
|
79
82
|
export type TranscriptionStatusType = typeof TranscriptionStatus[keyof typeof TranscriptionStatus];
|
|
83
|
+
export declare const RecognitionActionProcessingState: {
|
|
84
|
+
readonly NOT_STARTED: "NOT_STARTED";
|
|
85
|
+
readonly IN_PROGRESS: "IN_PROGRESS";
|
|
86
|
+
readonly COMPLETED: "COMPLETED";
|
|
87
|
+
};
|
|
88
|
+
export type RecognitionActionProcessingStateType = typeof RecognitionActionProcessingState[keyof typeof RecognitionActionProcessingState];
|
|
80
89
|
export declare function createInitialRecognitionState(audioUtteranceId: string): RecognitionState;
|
|
81
90
|
export declare function isValidRecordingStatusTransition(from: string | undefined, to: string): boolean;
|
|
82
91
|
//# sourceMappingURL=vgf-recognition-state.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vgf-recognition-state.d.ts","sourceRoot":"","sources":["../src/vgf-recognition-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,yBAAyB
|
|
1
|
+
{"version":3,"file":"vgf-recognition-state.d.ts","sourceRoot":"","sources":["../src/vgf-recognition-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6BpC,CAAA;AAEF,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAA;AAGxE,eAAO,MAAM,eAAe;;;;;CAKlB,CAAA;AAEV,MAAM,MAAM,mBAAmB,GAAG,OAAO,eAAe,CAAC,MAAM,OAAO,eAAe,CAAC,CAAA;AAEtF,eAAO,MAAM,mBAAmB;;;;;;CAMtB,CAAA;AAEV,MAAM,MAAM,uBAAuB,GAAG,OAAO,mBAAmB,CAAC,MAAM,OAAO,mBAAmB,CAAC,CAAA;AAElG,eAAO,MAAM,gCAAgC;;;;CAInC,CAAA;AAEV,MAAM,MAAM,oCAAoC,GAAG,OAAO,gCAAgC,CAAC,MAAM,OAAO,gCAAgC,CAAC,CAAA;AAGzI,wBAAgB,6BAA6B,CAAC,gBAAgB,EAAE,MAAM,GAAG,gBAAgB,CAQxF;AAGD,wBAAgB,gCAAgC,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAa9F"}
|
package/package.json
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volley/recognition-client-sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.381",
|
|
4
4
|
"description": "Recognition Service TypeScript/Node.js Client SDK",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"module": "dist/index.js",
|
|
8
|
-
"types": "dist/index.d.ts",
|
|
8
|
+
"types": "dist/index.bundled.d.ts",
|
|
9
9
|
"engines": {
|
|
10
10
|
"node": ">=22.0.0"
|
|
11
11
|
},
|
|
12
12
|
"exports": {
|
|
13
13
|
".": {
|
|
14
|
-
"types": "./dist/index.d.ts",
|
|
14
|
+
"types": "./dist/index.bundled.d.ts",
|
|
15
15
|
"import": "./dist/index.js",
|
|
16
16
|
"default": "./dist/index.js"
|
|
17
17
|
},
|
|
18
18
|
"./browser": {
|
|
19
|
-
"types": "./dist/
|
|
19
|
+
"types": "./dist/browser.bundled.d.ts",
|
|
20
20
|
"import": "./dist/recog-client-sdk.browser.js",
|
|
21
21
|
"default": "./dist/recog-client-sdk.browser.js"
|
|
22
22
|
}
|
|
@@ -31,31 +31,33 @@
|
|
|
31
31
|
"provenance": true
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"uuid": "
|
|
34
|
+
"uuid": "11.0.0",
|
|
35
35
|
"ws": "8.18.3",
|
|
36
|
-
"zod": "
|
|
36
|
+
"zod": "3.22.4"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@semantic-release/changelog": "
|
|
40
|
-
"@semantic-release/commit-analyzer": "
|
|
41
|
-
"@semantic-release/exec": "
|
|
42
|
-
"@semantic-release/git": "
|
|
43
|
-
"@semantic-release/github": "
|
|
44
|
-
"@semantic-release/npm": "
|
|
45
|
-
"@semantic-release/release-notes-generator": "
|
|
46
|
-
"@types/jest": "
|
|
47
|
-
"@types/node": "
|
|
48
|
-
"@types/uuid": "
|
|
49
|
-
"@types/ws": "
|
|
50
|
-
"esbuild": "
|
|
51
|
-
"jest": "
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
39
|
+
"@semantic-release/changelog": "6.0.3",
|
|
40
|
+
"@semantic-release/commit-analyzer": "13.0.1",
|
|
41
|
+
"@semantic-release/exec": "7.1.0",
|
|
42
|
+
"@semantic-release/git": "10.0.1",
|
|
43
|
+
"@semantic-release/github": "12.0.0",
|
|
44
|
+
"@semantic-release/npm": "13.1.1",
|
|
45
|
+
"@semantic-release/release-notes-generator": "14.1.0",
|
|
46
|
+
"@types/jest": "30.0.0",
|
|
47
|
+
"@types/node": "20.4.5",
|
|
48
|
+
"@types/uuid": "10.0.0",
|
|
49
|
+
"@types/ws": "8.5.5",
|
|
50
|
+
"esbuild": "0.25.0",
|
|
51
|
+
"jest": "29.6.1",
|
|
52
|
+
"rollup": "4.52.5",
|
|
53
|
+
"rollup-plugin-dts": "6.2.3",
|
|
54
|
+
"semantic-release": "25.0.1",
|
|
55
|
+
"ts-jest": "29.4.5",
|
|
56
|
+
"typescript": "5.1.6",
|
|
57
57
|
"@recog/shared-config": "1.0.0",
|
|
58
|
-
"@recog/websocket": "1.0.0"
|
|
58
|
+
"@recog/websocket": "1.0.0",
|
|
59
|
+
"@recog/shared-utils": "1.0.0",
|
|
60
|
+
"@recog/shared-types": "1.0.0"
|
|
59
61
|
},
|
|
60
62
|
"keywords": [
|
|
61
63
|
"recognition",
|
package/src/index.ts
CHANGED
|
@@ -682,7 +682,20 @@ export class RealTimeTwoWayWebSocketRecognitionClient
|
|
|
682
682
|
}
|
|
683
683
|
|
|
684
684
|
protected onDisconnected(code: number, reason: string): void {
|
|
685
|
-
|
|
685
|
+
// DIAGNOSTIC: Enhanced logging for disconnections
|
|
686
|
+
const closeCodeDescription = this.getCloseCodeDescription(code);
|
|
687
|
+
const is1006 = code === 1006;
|
|
688
|
+
|
|
689
|
+
this.log('debug', '[DIAGNOSTIC] WebSocket disconnected', {
|
|
690
|
+
code,
|
|
691
|
+
codeDescription: closeCodeDescription,
|
|
692
|
+
reason: reason || '(empty)',
|
|
693
|
+
previousState: this.state,
|
|
694
|
+
is1006Abnormal: is1006,
|
|
695
|
+
audioChunksSent: this.audioChunksSent,
|
|
696
|
+
audioBytesSent: this.audioBytesSent,
|
|
697
|
+
bufferStats: this.audioBuffer.getStats()
|
|
698
|
+
});
|
|
686
699
|
|
|
687
700
|
// Update state based on disconnection type
|
|
688
701
|
if (this.state === ClientState.STOPPING) {
|
|
@@ -692,7 +705,19 @@ export class RealTimeTwoWayWebSocketRecognitionClient
|
|
|
692
705
|
this.state === ClientState.READY ||
|
|
693
706
|
this.state === ClientState.CONNECTING
|
|
694
707
|
) {
|
|
695
|
-
this.log('error', 'Unexpected disconnection', {
|
|
708
|
+
this.log('error', '[DIAGNOSTIC] Unexpected disconnection', {
|
|
709
|
+
code,
|
|
710
|
+
codeDescription: closeCodeDescription,
|
|
711
|
+
reason: reason || '(empty)',
|
|
712
|
+
is1006: is1006,
|
|
713
|
+
possibleCauses: is1006 ? [
|
|
714
|
+
'Network connection lost',
|
|
715
|
+
'Server process crashed',
|
|
716
|
+
'Provider (Deepgram/AssemblyAI) WebSocket closed abnormally',
|
|
717
|
+
'Firewall/proxy terminated connection',
|
|
718
|
+
'Browser/tab suspended (mobile)'
|
|
719
|
+
] : []
|
|
720
|
+
});
|
|
696
721
|
this.state = ClientState.FAILED;
|
|
697
722
|
}
|
|
698
723
|
|
|
@@ -702,6 +727,33 @@ export class RealTimeTwoWayWebSocketRecognitionClient
|
|
|
702
727
|
this.config.onDisconnected(code, reason);
|
|
703
728
|
}
|
|
704
729
|
|
|
730
|
+
/**
|
|
731
|
+
* Get human-readable description for WebSocket close code
|
|
732
|
+
*/
|
|
733
|
+
private getCloseCodeDescription(code: number): string {
|
|
734
|
+
const descriptions: Record<number, string> = {
|
|
735
|
+
1000: 'Normal Closure',
|
|
736
|
+
1001: 'Going Away',
|
|
737
|
+
1002: 'Protocol Error',
|
|
738
|
+
1003: 'Unsupported Data',
|
|
739
|
+
1005: 'No Status Received',
|
|
740
|
+
1006: 'Abnormal Closure (no close frame received)',
|
|
741
|
+
1007: 'Invalid Frame Payload',
|
|
742
|
+
1008: 'Policy Violation',
|
|
743
|
+
1009: 'Message Too Big',
|
|
744
|
+
1010: 'Mandatory Extension',
|
|
745
|
+
1011: 'Internal Server Error',
|
|
746
|
+
1012: 'Service Restart',
|
|
747
|
+
1013: 'Try Again Later',
|
|
748
|
+
4000: 'Auth Required',
|
|
749
|
+
4001: 'Auth Failed',
|
|
750
|
+
4002: 'Rate Limit Exceeded',
|
|
751
|
+
4003: 'Invalid Session',
|
|
752
|
+
4004: 'Session Expired'
|
|
753
|
+
};
|
|
754
|
+
return descriptions[code] || `Unknown (${code})`;
|
|
755
|
+
}
|
|
756
|
+
|
|
705
757
|
protected onError(error: Event): void {
|
|
706
758
|
this.state = ClientState.FAILED;
|
|
707
759
|
|
|
@@ -65,6 +65,65 @@ describe('SimplifiedVGFRecognitionClient', () => {
|
|
|
65
65
|
expect(state.pendingTranscript).toBe('');
|
|
66
66
|
});
|
|
67
67
|
|
|
68
|
+
it('should generate new UUID when initial state has no audioUtteranceId', () => {
|
|
69
|
+
const initialState: RecognitionState = {
|
|
70
|
+
// No audioUtteranceId provided
|
|
71
|
+
startRecordingStatus: RecordingStatus.READY,
|
|
72
|
+
transcriptionStatus: TranscriptionStatus.NOT_STARTED,
|
|
73
|
+
pendingTranscript: ''
|
|
74
|
+
} as RecognitionState;
|
|
75
|
+
|
|
76
|
+
simplifiedClient = new SimplifiedVGFRecognitionClient({
|
|
77
|
+
initialState,
|
|
78
|
+
asrRequestConfig: {
|
|
79
|
+
provider: 'deepgram',
|
|
80
|
+
language: 'en',
|
|
81
|
+
sampleRate: 16000,
|
|
82
|
+
encoding: AudioEncoding.LINEAR16
|
|
83
|
+
},
|
|
84
|
+
onStateChange: stateChangeCallback
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
const state = simplifiedClient.getVGFState();
|
|
88
|
+
// Should have generated a new UUID
|
|
89
|
+
expect(state.audioUtteranceId).toBeDefined();
|
|
90
|
+
expect(state.audioUtteranceId).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i);
|
|
91
|
+
// Should preserve other fields
|
|
92
|
+
expect(state.startRecordingStatus).toBe(RecordingStatus.READY);
|
|
93
|
+
expect(state.transcriptionStatus).toBe(TranscriptionStatus.NOT_STARTED);
|
|
94
|
+
|
|
95
|
+
// onStateChange should be called with the new UUID
|
|
96
|
+
expect(stateChangeCallback).toHaveBeenCalledTimes(1);
|
|
97
|
+
const callbackState = stateChangeCallback.mock.calls[0][0];
|
|
98
|
+
expect(callbackState.audioUtteranceId).toBe(state.audioUtteranceId);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('should generate new UUID when initial state has empty audioUtteranceId', () => {
|
|
102
|
+
const initialState: RecognitionState = {
|
|
103
|
+
audioUtteranceId: '', // Empty UUID
|
|
104
|
+
startRecordingStatus: RecordingStatus.READY,
|
|
105
|
+
transcriptionStatus: TranscriptionStatus.NOT_STARTED,
|
|
106
|
+
pendingTranscript: ''
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
simplifiedClient = new SimplifiedVGFRecognitionClient({
|
|
110
|
+
initialState,
|
|
111
|
+
asrRequestConfig: {
|
|
112
|
+
provider: 'deepgram',
|
|
113
|
+
language: 'en',
|
|
114
|
+
sampleRate: 16000,
|
|
115
|
+
encoding: AudioEncoding.LINEAR16
|
|
116
|
+
},
|
|
117
|
+
onStateChange: stateChangeCallback
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
const state = simplifiedClient.getVGFState();
|
|
121
|
+
// Should have generated a new UUID
|
|
122
|
+
expect(state.audioUtteranceId).toBeDefined();
|
|
123
|
+
expect(state.audioUtteranceId).not.toBe('');
|
|
124
|
+
expect(state.audioUtteranceId).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i);
|
|
125
|
+
});
|
|
126
|
+
|
|
68
127
|
it('should accept initial state and use its audioUtteranceId', () => {
|
|
69
128
|
const initialState: RecognitionState = {
|
|
70
129
|
audioUtteranceId: 'existing-session-id',
|
|
@@ -83,10 +142,11 @@ describe('SimplifiedVGFRecognitionClient', () => {
|
|
|
83
142
|
// FINALIZED session gets new UUID to prevent server session reuse
|
|
84
143
|
expect(state.audioUtteranceId).not.toBe('existing-session-id');
|
|
85
144
|
expect(state.audioUtteranceId).toBeDefined();
|
|
86
|
-
//
|
|
87
|
-
expect(state.finalTranscript).
|
|
88
|
-
//
|
|
145
|
+
// finalTranscript is cleared for fresh session
|
|
146
|
+
expect(state.finalTranscript).toBeUndefined();
|
|
147
|
+
// Statuses reset for fresh session
|
|
89
148
|
expect(state.transcriptionStatus).toBe(TranscriptionStatus.NOT_STARTED);
|
|
149
|
+
expect(state.startRecordingStatus).toBe(RecordingStatus.READY);
|
|
90
150
|
|
|
91
151
|
// Verify NEW audioUtteranceId was passed to underlying client
|
|
92
152
|
const constructorCalls = (RealTimeTwoWayWebSocketRecognitionClient as jest.MockedClass<typeof RealTimeTwoWayWebSocketRecognitionClient>).mock.calls;
|
|
@@ -228,8 +288,11 @@ describe('SimplifiedVGFRecognitionClient', () => {
|
|
|
228
288
|
});
|
|
229
289
|
|
|
230
290
|
it('should handle metadata and mark recording as finished', () => {
|
|
291
|
+
// Get the actual UUID from the client
|
|
292
|
+
const actualUuid = simplifiedClient.getVGFState().audioUtteranceId;
|
|
293
|
+
|
|
231
294
|
const metadata = {
|
|
232
|
-
audioUtteranceId:
|
|
295
|
+
audioUtteranceId: actualUuid,
|
|
233
296
|
duration: 5000
|
|
234
297
|
};
|
|
235
298
|
|
|
@@ -386,9 +449,22 @@ describe('SimplifiedVGFRecognitionClient', () => {
|
|
|
386
449
|
|
|
387
450
|
describe('Thin Layer Verification', () => {
|
|
388
451
|
it('should pass transcript result directly to mapper without modification', () => {
|
|
452
|
+
simplifiedClient = new SimplifiedVGFRecognitionClient({
|
|
453
|
+
asrRequestConfig: {
|
|
454
|
+
provider: 'deepgram',
|
|
455
|
+
language: 'en',
|
|
456
|
+
sampleRate: 16000,
|
|
457
|
+
encoding: AudioEncoding.LINEAR16
|
|
458
|
+
},
|
|
459
|
+
onStateChange: stateChangeCallback
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
// Get actual UUID from client
|
|
463
|
+
const actualUuid = simplifiedClient.getVGFState().audioUtteranceId;
|
|
464
|
+
|
|
389
465
|
const transcriptResult = {
|
|
390
466
|
type: 'Transcription',
|
|
391
|
-
audioUtteranceId:
|
|
467
|
+
audioUtteranceId: actualUuid,
|
|
392
468
|
finalTranscript: 'Final text',
|
|
393
469
|
pendingTranscript: 'Pending text',
|
|
394
470
|
finalTranscriptConfidence: 0.99,
|
|
@@ -400,16 +476,6 @@ describe('SimplifiedVGFRecognitionClient', () => {
|
|
|
400
476
|
extraField: 'should be ignored by VGF state'
|
|
401
477
|
};
|
|
402
478
|
|
|
403
|
-
simplifiedClient = new SimplifiedVGFRecognitionClient({
|
|
404
|
-
asrRequestConfig: {
|
|
405
|
-
provider: 'deepgram',
|
|
406
|
-
language: 'en',
|
|
407
|
-
sampleRate: 16000,
|
|
408
|
-
encoding: AudioEncoding.LINEAR16
|
|
409
|
-
},
|
|
410
|
-
onStateChange: stateChangeCallback
|
|
411
|
-
});
|
|
412
|
-
|
|
413
479
|
const constructorCall = (RealTimeTwoWayWebSocketRecognitionClient as jest.MockedClass<typeof RealTimeTwoWayWebSocketRecognitionClient>).mock.calls[0]?.[0];
|
|
414
480
|
const wrappedCallback = constructorCall?.onTranscript;
|
|
415
481
|
if (!wrappedCallback) throw new Error('onTranscript callback not found');
|
|
@@ -575,14 +641,14 @@ describe('SimplifiedVGFRecognitionClient', () => {
|
|
|
575
641
|
expect(client.getVGFState().audioUtteranceId).toBe(newState.audioUtteranceId);
|
|
576
642
|
});
|
|
577
643
|
|
|
578
|
-
it('should auto-generate new UUID for FINALIZED session', () => {
|
|
644
|
+
it('should auto-generate new UUID for FINALIZED session and reset fields', () => {
|
|
579
645
|
const stateChangeCallback = jest.fn();
|
|
580
646
|
const finalizedState: RecognitionState = {
|
|
581
647
|
audioUtteranceId: 'old-finalized-uuid',
|
|
582
648
|
transcriptionStatus: TranscriptionStatus.FINALIZED,
|
|
583
649
|
startRecordingStatus: RecordingStatus.FINISHED,
|
|
584
650
|
pendingTranscript: '',
|
|
585
|
-
finalTranscript: 'completed transcript'
|
|
651
|
+
finalTranscript: 'completed transcript from previous session'
|
|
586
652
|
};
|
|
587
653
|
|
|
588
654
|
const client = createSimplifiedVGFClient({
|
|
@@ -602,6 +668,8 @@ describe('SimplifiedVGFRecognitionClient', () => {
|
|
|
602
668
|
|
|
603
669
|
expect(newState.audioUtteranceId).not.toBe('old-finalized-uuid');
|
|
604
670
|
expect(newState.transcriptionStatus).toBe(TranscriptionStatus.NOT_STARTED);
|
|
671
|
+
expect(newState.startRecordingStatus).toBe(RecordingStatus.READY);
|
|
672
|
+
expect(newState.finalTranscript).toBeUndefined();
|
|
605
673
|
});
|
|
606
674
|
|
|
607
675
|
it('should preserve UUID for IN_PROGRESS session (valid resumption)', () => {
|
|
@@ -1046,4 +1114,221 @@ describe('SimplifiedVGFRecognitionClient', () => {
|
|
|
1046
1114
|
});
|
|
1047
1115
|
});
|
|
1048
1116
|
});
|
|
1117
|
+
|
|
1118
|
+
describe('UUID Change Detection', () => {
|
|
1119
|
+
it('should skip onStateChange callback when UUID changes by default', () => {
|
|
1120
|
+
// Create client with initial state
|
|
1121
|
+
const initialState: RecognitionState = {
|
|
1122
|
+
audioUtteranceId: 'session-123',
|
|
1123
|
+
startRecordingStatus: RecordingStatus.READY,
|
|
1124
|
+
transcriptionStatus: TranscriptionStatus.NOT_STARTED,
|
|
1125
|
+
pendingTranscript: ''
|
|
1126
|
+
};
|
|
1127
|
+
|
|
1128
|
+
simplifiedClient = new SimplifiedVGFRecognitionClient({
|
|
1129
|
+
initialState,
|
|
1130
|
+
asrRequestConfig: {
|
|
1131
|
+
provider: 'deepgram',
|
|
1132
|
+
language: 'en',
|
|
1133
|
+
sampleRate: 16000,
|
|
1134
|
+
encoding: AudioEncoding.LINEAR16
|
|
1135
|
+
},
|
|
1136
|
+
onStateChange: stateChangeCallback
|
|
1137
|
+
});
|
|
1138
|
+
|
|
1139
|
+
// Get the callbacks that were passed to the underlying client
|
|
1140
|
+
const constructorCalls = (RealTimeTwoWayWebSocketRecognitionClient as jest.MockedClass<typeof RealTimeTwoWayWebSocketRecognitionClient>).mock.calls;
|
|
1141
|
+
const clientConfig = constructorCalls[0]?.[0];
|
|
1142
|
+
const onTranscriptCallback = clientConfig?.onTranscript;
|
|
1143
|
+
|
|
1144
|
+
// Simulate transcript with a different UUID (stale callback from previous session)
|
|
1145
|
+
onTranscriptCallback?.({
|
|
1146
|
+
type: 'transcript',
|
|
1147
|
+
is_finished: false,
|
|
1148
|
+
pendingTranscript: 'test transcript',
|
|
1149
|
+
audioUtteranceId: 'different-uuid-456' // Different UUID
|
|
1150
|
+
} as any);
|
|
1151
|
+
|
|
1152
|
+
// State should NOT be updated - callback should be skipped
|
|
1153
|
+
expect(stateChangeCallback).not.toHaveBeenCalled();
|
|
1154
|
+
|
|
1155
|
+
// Internal state should still have original UUID
|
|
1156
|
+
const state = simplifiedClient.getVGFState();
|
|
1157
|
+
expect(state.audioUtteranceId).toBe('session-123');
|
|
1158
|
+
expect(state.pendingTranscript).toBe(''); // Not updated
|
|
1159
|
+
});
|
|
1160
|
+
|
|
1161
|
+
|
|
1162
|
+
it('should process callbacks with matching UUID', () => {
|
|
1163
|
+
// Create client with initial state
|
|
1164
|
+
const initialState: RecognitionState = {
|
|
1165
|
+
audioUtteranceId: 'session-123',
|
|
1166
|
+
startRecordingStatus: RecordingStatus.READY,
|
|
1167
|
+
transcriptionStatus: TranscriptionStatus.NOT_STARTED,
|
|
1168
|
+
pendingTranscript: ''
|
|
1169
|
+
};
|
|
1170
|
+
|
|
1171
|
+
simplifiedClient = new SimplifiedVGFRecognitionClient({
|
|
1172
|
+
initialState,
|
|
1173
|
+
asrRequestConfig: {
|
|
1174
|
+
provider: 'deepgram',
|
|
1175
|
+
language: 'en',
|
|
1176
|
+
sampleRate: 16000,
|
|
1177
|
+
encoding: AudioEncoding.LINEAR16
|
|
1178
|
+
},
|
|
1179
|
+
onStateChange: stateChangeCallback
|
|
1180
|
+
});
|
|
1181
|
+
|
|
1182
|
+
// Get the callbacks that were passed to the underlying client
|
|
1183
|
+
const constructorCalls = (RealTimeTwoWayWebSocketRecognitionClient as jest.MockedClass<typeof RealTimeTwoWayWebSocketRecognitionClient>).mock.calls;
|
|
1184
|
+
const clientConfig = constructorCalls[0]?.[0];
|
|
1185
|
+
const onTranscriptCallback = clientConfig?.onTranscript;
|
|
1186
|
+
|
|
1187
|
+
// Simulate transcript with matching UUID
|
|
1188
|
+
onTranscriptCallback?.({
|
|
1189
|
+
type: 'transcript',
|
|
1190
|
+
is_finished: false,
|
|
1191
|
+
pendingTranscript: 'test transcript',
|
|
1192
|
+
audioUtteranceId: 'session-123' // Same UUID
|
|
1193
|
+
} as any);
|
|
1194
|
+
|
|
1195
|
+
// State should be updated normally
|
|
1196
|
+
expect(stateChangeCallback).toHaveBeenCalledTimes(1);
|
|
1197
|
+
const updatedState = stateChangeCallback.mock.calls[0][0];
|
|
1198
|
+
expect(updatedState.audioUtteranceId).toBe('session-123');
|
|
1199
|
+
expect(updatedState.pendingTranscript).toBe('test transcript');
|
|
1200
|
+
});
|
|
1201
|
+
|
|
1202
|
+
it('should skip metadata callback with different UUID', () => {
|
|
1203
|
+
// Create client with initial state
|
|
1204
|
+
const initialState: RecognitionState = {
|
|
1205
|
+
audioUtteranceId: 'session-123',
|
|
1206
|
+
startRecordingStatus: RecordingStatus.READY,
|
|
1207
|
+
transcriptionStatus: TranscriptionStatus.NOT_STARTED,
|
|
1208
|
+
pendingTranscript: ''
|
|
1209
|
+
};
|
|
1210
|
+
|
|
1211
|
+
simplifiedClient = new SimplifiedVGFRecognitionClient({
|
|
1212
|
+
initialState,
|
|
1213
|
+
asrRequestConfig: {
|
|
1214
|
+
provider: 'deepgram',
|
|
1215
|
+
language: 'en',
|
|
1216
|
+
sampleRate: 16000,
|
|
1217
|
+
encoding: AudioEncoding.LINEAR16
|
|
1218
|
+
},
|
|
1219
|
+
onStateChange: stateChangeCallback
|
|
1220
|
+
});
|
|
1221
|
+
|
|
1222
|
+
// Get the metadata callback
|
|
1223
|
+
const constructorCalls = (RealTimeTwoWayWebSocketRecognitionClient as jest.MockedClass<typeof RealTimeTwoWayWebSocketRecognitionClient>).mock.calls;
|
|
1224
|
+
const clientConfig = constructorCalls[0]?.[0];
|
|
1225
|
+
const onMetadataCallback = clientConfig?.onMetadata;
|
|
1226
|
+
|
|
1227
|
+
// Simulate metadata with different UUID
|
|
1228
|
+
onMetadataCallback?.({
|
|
1229
|
+
type: 'metadata',
|
|
1230
|
+
event: 'recording_stopped',
|
|
1231
|
+
audioUtteranceId: 'different-uuid-456'
|
|
1232
|
+
} as any);
|
|
1233
|
+
|
|
1234
|
+
// Callback should be skipped
|
|
1235
|
+
expect(stateChangeCallback).not.toHaveBeenCalled();
|
|
1236
|
+
});
|
|
1237
|
+
|
|
1238
|
+
it('should skip error callback with different UUID', () => {
|
|
1239
|
+
// Create client with initial state
|
|
1240
|
+
const initialState: RecognitionState = {
|
|
1241
|
+
audioUtteranceId: 'session-123',
|
|
1242
|
+
startRecordingStatus: RecordingStatus.READY,
|
|
1243
|
+
transcriptionStatus: TranscriptionStatus.NOT_STARTED,
|
|
1244
|
+
pendingTranscript: ''
|
|
1245
|
+
};
|
|
1246
|
+
|
|
1247
|
+
simplifiedClient = new SimplifiedVGFRecognitionClient({
|
|
1248
|
+
initialState,
|
|
1249
|
+
asrRequestConfig: {
|
|
1250
|
+
provider: 'deepgram',
|
|
1251
|
+
language: 'en',
|
|
1252
|
+
sampleRate: 16000,
|
|
1253
|
+
encoding: AudioEncoding.LINEAR16
|
|
1254
|
+
},
|
|
1255
|
+
onStateChange: stateChangeCallback
|
|
1256
|
+
});
|
|
1257
|
+
|
|
1258
|
+
// Get the error callback
|
|
1259
|
+
const constructorCalls = (RealTimeTwoWayWebSocketRecognitionClient as jest.MockedClass<typeof RealTimeTwoWayWebSocketRecognitionClient>).mock.calls;
|
|
1260
|
+
const clientConfig = constructorCalls[0]?.[0];
|
|
1261
|
+
const onErrorCallback = clientConfig?.onError;
|
|
1262
|
+
|
|
1263
|
+
// Simulate error with different UUID
|
|
1264
|
+
onErrorCallback?.({
|
|
1265
|
+
type: 'error',
|
|
1266
|
+
error: 'test error',
|
|
1267
|
+
audioUtteranceId: 'different-uuid-456'
|
|
1268
|
+
} as any);
|
|
1269
|
+
|
|
1270
|
+
// Callback should be skipped
|
|
1271
|
+
expect(stateChangeCallback).not.toHaveBeenCalled();
|
|
1272
|
+
});
|
|
1273
|
+
|
|
1274
|
+
it('should track UUID after terminal state regeneration', () => {
|
|
1275
|
+
// Create client with terminal initial state (forces UUID regeneration)
|
|
1276
|
+
const initialState: RecognitionState = {
|
|
1277
|
+
audioUtteranceId: 'old-session-123',
|
|
1278
|
+
startRecordingStatus: RecordingStatus.FINISHED,
|
|
1279
|
+
transcriptionStatus: TranscriptionStatus.FINALIZED, // Terminal state
|
|
1280
|
+
pendingTranscript: '',
|
|
1281
|
+
finalTranscript: 'Previous transcript'
|
|
1282
|
+
};
|
|
1283
|
+
|
|
1284
|
+
simplifiedClient = new SimplifiedVGFRecognitionClient({
|
|
1285
|
+
initialState,
|
|
1286
|
+
asrRequestConfig: {
|
|
1287
|
+
provider: 'deepgram',
|
|
1288
|
+
language: 'en',
|
|
1289
|
+
sampleRate: 16000,
|
|
1290
|
+
encoding: AudioEncoding.LINEAR16
|
|
1291
|
+
},
|
|
1292
|
+
onStateChange: stateChangeCallback
|
|
1293
|
+
});
|
|
1294
|
+
|
|
1295
|
+
// Get the new UUID that was generated
|
|
1296
|
+
const newState = simplifiedClient.getVGFState();
|
|
1297
|
+
const newUuid = newState.audioUtteranceId;
|
|
1298
|
+
expect(newUuid).not.toBe('old-session-123');
|
|
1299
|
+
|
|
1300
|
+
// Get the transcript callback
|
|
1301
|
+
const constructorCalls = (RealTimeTwoWayWebSocketRecognitionClient as jest.MockedClass<typeof RealTimeTwoWayWebSocketRecognitionClient>).mock.calls;
|
|
1302
|
+
const clientConfig = constructorCalls[0]?.[0];
|
|
1303
|
+
const onTranscriptCallback = clientConfig?.onTranscript;
|
|
1304
|
+
|
|
1305
|
+
// Clear initial state change callback from UUID regeneration
|
|
1306
|
+
jest.clearAllMocks();
|
|
1307
|
+
|
|
1308
|
+
// Simulate transcript with the NEW UUID
|
|
1309
|
+
onTranscriptCallback?.({
|
|
1310
|
+
type: 'transcript',
|
|
1311
|
+
is_finished: false,
|
|
1312
|
+
pendingTranscript: 'new transcript',
|
|
1313
|
+
audioUtteranceId: newUuid // New UUID
|
|
1314
|
+
} as any);
|
|
1315
|
+
|
|
1316
|
+
// Should process normally with new UUID
|
|
1317
|
+
expect(stateChangeCallback).toHaveBeenCalledTimes(1);
|
|
1318
|
+
const updatedState = stateChangeCallback.mock.calls[0][0];
|
|
1319
|
+
expect(updatedState.pendingTranscript).toBe('new transcript');
|
|
1320
|
+
|
|
1321
|
+
// Simulate transcript with OLD UUID (stale callback)
|
|
1322
|
+
jest.clearAllMocks();
|
|
1323
|
+
onTranscriptCallback?.({
|
|
1324
|
+
type: 'transcript',
|
|
1325
|
+
is_finished: false,
|
|
1326
|
+
pendingTranscript: 'stale transcript',
|
|
1327
|
+
audioUtteranceId: 'old-session-123' // Old UUID
|
|
1328
|
+
} as any);
|
|
1329
|
+
|
|
1330
|
+
// Should skip callback with old UUID
|
|
1331
|
+
expect(stateChangeCallback).not.toHaveBeenCalled();
|
|
1332
|
+
});
|
|
1333
|
+
});
|
|
1049
1334
|
});
|