whio-api-sdk 1.0.202-beta-staging → 1.0.204-beta-staging
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/src/sdk/modules/template.module.d.ts +1 -0
- package/dist/src/sdk/modules/template.module.js +8 -0
- package/dist/src/sdk/modules/websocket.module.d.ts +6 -1
- package/dist/src/sdk/modules/websocket.module.js +54 -10
- package/dist/src/sdk/sdk.d.ts +1 -1
- package/dist/src/sdk/types/template.types.d.ts +3 -0
- package/package.json +1 -1
- package/src/sdk/modules/template.module.ts +8 -0
- package/src/sdk/modules/websocket.module.ts +52 -5
- package/src/sdk/types/template.types.ts +4 -0
|
@@ -26,6 +26,7 @@ export declare class TemplateModule extends BaseClient {
|
|
|
26
26
|
getTranscriptionSummary(id: string): Promise<TranscriptionSummary>;
|
|
27
27
|
getTranscriptionSummariesByUser(userId: string): Promise<TranscriptionSummary[]>;
|
|
28
28
|
getByOrganizationTranscriptionSummaries(organizationId: string): Promise<TranscriptionSummary[]>;
|
|
29
|
+
cloneTranscriptionSummary(id: string, content: string): Promise<TranscriptionSummary>;
|
|
29
30
|
deleteTranscriptionSummary(id: string): Promise<void>;
|
|
30
31
|
uploadLargeAudioFile(formData: FormData): Promise<string>;
|
|
31
32
|
uploadAudioFile(formData: FormData): Promise<TranscriptionAudioUploadResponse | null>;
|
|
@@ -208,6 +208,14 @@ export class TemplateModule extends BaseClient {
|
|
|
208
208
|
return this.request(`${urls.transcriptionSummaries}/organization/${organizationId}`, 'GET');
|
|
209
209
|
});
|
|
210
210
|
}
|
|
211
|
+
cloneTranscriptionSummary(id, content) {
|
|
212
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
213
|
+
const cloneDto = {
|
|
214
|
+
content,
|
|
215
|
+
};
|
|
216
|
+
return this.request(`${urls.transcriptionSummaries}/${id}/clone`, 'POST', cloneDto);
|
|
217
|
+
});
|
|
218
|
+
}
|
|
211
219
|
deleteTranscriptionSummary(id) {
|
|
212
220
|
return __awaiter(this, void 0, void 0, function* () {
|
|
213
221
|
yield this.request(`${urls.transcriptionSummaries}/${id}`, 'DELETE');
|
|
@@ -30,10 +30,15 @@ export declare class WebSocketModule extends BaseClient {
|
|
|
30
30
|
* Get connection statistics
|
|
31
31
|
*/
|
|
32
32
|
getConnectionStats(): WebSocketConnectionStats;
|
|
33
|
+
/**
|
|
34
|
+
* Ensure WebSocket connection has a valid token
|
|
35
|
+
* Reconnects with fresh token if current token is expired
|
|
36
|
+
*/
|
|
37
|
+
private ensureValidConnection;
|
|
33
38
|
/**
|
|
34
39
|
* Stream audio chunk to server
|
|
35
40
|
*/
|
|
36
|
-
streamAudioChunk(sessionId: string, audioChunk: string): void
|
|
41
|
+
streamAudioChunk(sessionId: string, audioChunk: string): Promise<void>;
|
|
37
42
|
/**
|
|
38
43
|
* Stream multiple audio chunks
|
|
39
44
|
*/
|
|
@@ -94,19 +94,48 @@ export class WebSocketModule extends BaseClient {
|
|
|
94
94
|
getConnectionStats() {
|
|
95
95
|
return Object.assign({}, this.connectionStats);
|
|
96
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* Ensure WebSocket connection has a valid token
|
|
99
|
+
* Reconnects with fresh token if current token is expired
|
|
100
|
+
*/
|
|
101
|
+
ensureValidConnection() {
|
|
102
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
103
|
+
const currentToken = this.getAccessToken();
|
|
104
|
+
// Check if we have a token and if it's expired
|
|
105
|
+
if (!currentToken || this.isTokenExpired(currentToken)) {
|
|
106
|
+
console.log('[WebSocket] Token expired or missing, refreshing and reconnecting...');
|
|
107
|
+
try {
|
|
108
|
+
// Refresh token
|
|
109
|
+
yield this.getToken();
|
|
110
|
+
// Disconnect current connection and reconnect with fresh token
|
|
111
|
+
this.disconnect();
|
|
112
|
+
yield this.connect();
|
|
113
|
+
console.log('[WebSocket] Successfully reconnected with fresh token');
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
console.error('[WebSocket] Failed to refresh token and reconnect:', error);
|
|
117
|
+
throw new Error('Authentication failed: Unable to refresh token for WebSocket streaming');
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
}
|
|
97
122
|
/**
|
|
98
123
|
* Stream audio chunk to server
|
|
99
124
|
*/
|
|
100
125
|
streamAudioChunk(sessionId, audioChunk) {
|
|
101
126
|
var _a;
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
127
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
128
|
+
// CRITICAL: Validate token and reconnect if needed BEFORE sending
|
|
129
|
+
yield this.ensureValidConnection();
|
|
130
|
+
if (!((_a = this.socket) === null || _a === void 0 ? void 0 : _a.connected)) {
|
|
131
|
+
throw new Error('WebSocket not connected after token validation');
|
|
132
|
+
}
|
|
133
|
+
const payload = {
|
|
134
|
+
sessionId,
|
|
135
|
+
audioChunk
|
|
136
|
+
};
|
|
137
|
+
this.socket.emit('audio-chunk', payload);
|
|
138
|
+
});
|
|
110
139
|
}
|
|
111
140
|
/**
|
|
112
141
|
* Stream multiple audio chunks
|
|
@@ -114,12 +143,15 @@ export class WebSocketModule extends BaseClient {
|
|
|
114
143
|
streamAudioChunks(sessionId, audioChunks, options = {}) {
|
|
115
144
|
var _a;
|
|
116
145
|
return __awaiter(this, void 0, void 0, function* () {
|
|
146
|
+
// Validate token once before streaming multiple chunks
|
|
147
|
+
yield this.ensureValidConnection();
|
|
117
148
|
if (!((_a = this.socket) === null || _a === void 0 ? void 0 : _a.connected)) {
|
|
118
|
-
throw new Error('WebSocket not connected
|
|
149
|
+
throw new Error('WebSocket not connected after token validation.');
|
|
119
150
|
}
|
|
120
151
|
const delay = options.delayBetweenChunks || 100; // ms between chunks
|
|
121
152
|
for (let i = 0; i < audioChunks.length; i++) {
|
|
122
|
-
|
|
153
|
+
// Note: streamAudioChunk will also validate token, but we've already done it once
|
|
154
|
+
yield this.streamAudioChunk(sessionId, audioChunks[i]);
|
|
123
155
|
// Small delay between chunks to prevent overwhelming the server
|
|
124
156
|
if (i < audioChunks.length - 1) {
|
|
125
157
|
yield new Promise(resolve => setTimeout(resolve, delay));
|
|
@@ -197,29 +229,41 @@ export class WebSocketModule extends BaseClient {
|
|
|
197
229
|
});
|
|
198
230
|
// Application-specific events
|
|
199
231
|
this.socket.on('connected', (data) => {
|
|
232
|
+
console.log('[WebSocket] Connected event received:', JSON.stringify(data, null, 2));
|
|
200
233
|
this.emit('connected', data);
|
|
201
234
|
});
|
|
202
235
|
this.socket.on('audio-chunk-received', (data) => {
|
|
236
|
+
console.log('[WebSocket] Audio chunk received event:', JSON.stringify(data, null, 2));
|
|
203
237
|
this.emit('audio-chunk-received', data);
|
|
204
238
|
});
|
|
205
239
|
this.socket.on('transcription-complete', (data) => {
|
|
240
|
+
console.log('[WebSocket] Transcription complete event received:', JSON.stringify(data, null, 2));
|
|
206
241
|
this.emit('transcription-complete', data);
|
|
207
242
|
});
|
|
208
243
|
this.socket.on('transcription-queued', (data) => {
|
|
244
|
+
console.log('[WebSocket] Transcription queued event received:', JSON.stringify(data, null, 2));
|
|
209
245
|
this.emit('transcription-queued', data);
|
|
210
246
|
});
|
|
211
247
|
this.socket.on('summary-complete', (data) => {
|
|
248
|
+
console.log('[WebSocket] Summary complete event received:', JSON.stringify(data, null, 2));
|
|
212
249
|
this.emit('summary-complete', data);
|
|
213
250
|
});
|
|
214
251
|
this.socket.on('summary-queued', (data) => {
|
|
252
|
+
console.log('[WebSocket] Summary queued event received:', JSON.stringify(data, null, 2));
|
|
215
253
|
this.emit('summary-queued', data);
|
|
216
254
|
});
|
|
217
255
|
this.socket.on('audio-error', (error) => {
|
|
256
|
+
console.log('[WebSocket] Audio error event received:', JSON.stringify(error, null, 2));
|
|
218
257
|
this.emit('audio-error', error);
|
|
219
258
|
});
|
|
220
259
|
this.socket.on('transcription-error', (error) => {
|
|
260
|
+
console.log('[WebSocket] Transcription error event received:', JSON.stringify(error, null, 2));
|
|
221
261
|
this.emit('transcription-error', error);
|
|
222
262
|
});
|
|
263
|
+
// Catch-all event listener for debugging
|
|
264
|
+
this.socket.onAny((eventName, ...args) => {
|
|
265
|
+
console.log(`[WebSocket] Raw event received: "${eventName}"`, JSON.stringify(args, null, 2));
|
|
266
|
+
});
|
|
223
267
|
}
|
|
224
268
|
/**
|
|
225
269
|
* Determine if should attempt reconnection
|
package/dist/src/sdk/sdk.d.ts
CHANGED
|
@@ -186,7 +186,7 @@ export declare class ApiSDK extends BaseClient {
|
|
|
186
186
|
connectWebSocket(): Promise<void>;
|
|
187
187
|
disconnectWebSocket(): void;
|
|
188
188
|
isWebSocketConnected(): boolean;
|
|
189
|
-
streamAudioChunk(...args: Parameters<WebSocketModule['streamAudioChunk']>): void
|
|
189
|
+
streamAudioChunk(...args: Parameters<WebSocketModule['streamAudioChunk']>): Promise<void>;
|
|
190
190
|
streamAudioChunks(...args: Parameters<WebSocketModule['streamAudioChunks']>): Promise<void>;
|
|
191
191
|
onWebSocketEvent(...args: Parameters<WebSocketModule['on']>): void;
|
|
192
192
|
offWebSocketEvent(...args: Parameters<WebSocketModule['off']>): void;
|
package/package.json
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
AssignTeamTemplateDto,
|
|
14
14
|
GenerateTranscriptionSummaryDto,
|
|
15
15
|
UpdateTranscriptionSummaryDto,
|
|
16
|
+
CloneTranscriptionSummaryDto,
|
|
16
17
|
TranscriptionAudioUploadResponse,
|
|
17
18
|
} from '../types';
|
|
18
19
|
import urls from '../urls';
|
|
@@ -207,6 +208,13 @@ export class TemplateModule extends BaseClient {
|
|
|
207
208
|
return this.request<TranscriptionSummary[]>(`${urls.transcriptionSummaries}/organization/${organizationId}`, 'GET');
|
|
208
209
|
}
|
|
209
210
|
|
|
211
|
+
public async cloneTranscriptionSummary(id: string, content: string): Promise<TranscriptionSummary> {
|
|
212
|
+
const cloneDto: CloneTranscriptionSummaryDto = {
|
|
213
|
+
content,
|
|
214
|
+
};
|
|
215
|
+
return this.request<TranscriptionSummary>(`${urls.transcriptionSummaries}/${id}/clone`, 'POST', cloneDto);
|
|
216
|
+
}
|
|
217
|
+
|
|
210
218
|
public async deleteTranscriptionSummary(id: string): Promise<void> {
|
|
211
219
|
await this.request(`${urls.transcriptionSummaries}/${id}`, 'DELETE');
|
|
212
220
|
}
|
|
@@ -117,15 +117,45 @@ export class WebSocketModule extends BaseClient {
|
|
|
117
117
|
return { ...this.connectionStats };
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
+
/**
|
|
121
|
+
* Ensure WebSocket connection has a valid token
|
|
122
|
+
* Reconnects with fresh token if current token is expired
|
|
123
|
+
*/
|
|
124
|
+
private async ensureValidConnection(): Promise<void> {
|
|
125
|
+
const currentToken = this.getAccessToken();
|
|
126
|
+
|
|
127
|
+
// Check if we have a token and if it's expired
|
|
128
|
+
if (!currentToken || this.isTokenExpired(currentToken)) {
|
|
129
|
+
console.log('[WebSocket] Token expired or missing, refreshing and reconnecting...');
|
|
130
|
+
|
|
131
|
+
try {
|
|
132
|
+
// Refresh token
|
|
133
|
+
await this.getToken();
|
|
134
|
+
|
|
135
|
+
// Disconnect current connection and reconnect with fresh token
|
|
136
|
+
this.disconnect();
|
|
137
|
+
await this.connect();
|
|
138
|
+
|
|
139
|
+
console.log('[WebSocket] Successfully reconnected with fresh token');
|
|
140
|
+
} catch (error) {
|
|
141
|
+
console.error('[WebSocket] Failed to refresh token and reconnect:', error);
|
|
142
|
+
throw new Error('Authentication failed: Unable to refresh token for WebSocket streaming');
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
120
147
|
/**
|
|
121
148
|
* Stream audio chunk to server
|
|
122
149
|
*/
|
|
123
|
-
public streamAudioChunk(
|
|
150
|
+
public async streamAudioChunk(
|
|
124
151
|
sessionId: string,
|
|
125
152
|
audioChunk: string
|
|
126
|
-
): void {
|
|
153
|
+
): Promise<void> {
|
|
154
|
+
// CRITICAL: Validate token and reconnect if needed BEFORE sending
|
|
155
|
+
await this.ensureValidConnection();
|
|
156
|
+
|
|
127
157
|
if (!this.socket?.connected) {
|
|
128
|
-
throw new Error('WebSocket not connected
|
|
158
|
+
throw new Error('WebSocket not connected after token validation');
|
|
129
159
|
}
|
|
130
160
|
|
|
131
161
|
const payload: AudioChunkPayload = {
|
|
@@ -144,14 +174,18 @@ export class WebSocketModule extends BaseClient {
|
|
|
144
174
|
audioChunks: string[],
|
|
145
175
|
options: AudioStreamingOptions = {}
|
|
146
176
|
): Promise<void> {
|
|
177
|
+
// Validate token once before streaming multiple chunks
|
|
178
|
+
await this.ensureValidConnection();
|
|
179
|
+
|
|
147
180
|
if (!this.socket?.connected) {
|
|
148
|
-
throw new Error('WebSocket not connected
|
|
181
|
+
throw new Error('WebSocket not connected after token validation.');
|
|
149
182
|
}
|
|
150
183
|
|
|
151
184
|
const delay = options.delayBetweenChunks || 100; // ms between chunks
|
|
152
185
|
|
|
153
186
|
for (let i = 0; i < audioChunks.length; i++) {
|
|
154
|
-
|
|
187
|
+
// Note: streamAudioChunk will also validate token, but we've already done it once
|
|
188
|
+
await this.streamAudioChunk(sessionId, audioChunks[i]);
|
|
155
189
|
|
|
156
190
|
// Small delay between chunks to prevent overwhelming the server
|
|
157
191
|
if (i < audioChunks.length - 1) {
|
|
@@ -248,36 +282,49 @@ export class WebSocketModule extends BaseClient {
|
|
|
248
282
|
|
|
249
283
|
// Application-specific events
|
|
250
284
|
this.socket.on('connected', (data: any) => {
|
|
285
|
+
console.log('[WebSocket] Connected event received:', JSON.stringify(data, null, 2));
|
|
251
286
|
this.emit('connected', data);
|
|
252
287
|
});
|
|
253
288
|
|
|
254
289
|
this.socket.on('audio-chunk-received', (data: any) => {
|
|
290
|
+
console.log('[WebSocket] Audio chunk received event:', JSON.stringify(data, null, 2));
|
|
255
291
|
this.emit('audio-chunk-received', data);
|
|
256
292
|
});
|
|
257
293
|
|
|
258
294
|
this.socket.on('transcription-complete', (data: any) => {
|
|
295
|
+
console.log('[WebSocket] Transcription complete event received:', JSON.stringify(data, null, 2));
|
|
259
296
|
this.emit('transcription-complete', data);
|
|
260
297
|
});
|
|
261
298
|
|
|
262
299
|
this.socket.on('transcription-queued', (data: any) => {
|
|
300
|
+
console.log('[WebSocket] Transcription queued event received:', JSON.stringify(data, null, 2));
|
|
263
301
|
this.emit('transcription-queued', data);
|
|
264
302
|
});
|
|
265
303
|
|
|
266
304
|
this.socket.on('summary-complete', (data: any) => {
|
|
305
|
+
console.log('[WebSocket] Summary complete event received:', JSON.stringify(data, null, 2));
|
|
267
306
|
this.emit('summary-complete', data);
|
|
268
307
|
});
|
|
269
308
|
|
|
270
309
|
this.socket.on('summary-queued', (data: any) => {
|
|
310
|
+
console.log('[WebSocket] Summary queued event received:', JSON.stringify(data, null, 2));
|
|
271
311
|
this.emit('summary-queued', data);
|
|
272
312
|
});
|
|
273
313
|
|
|
274
314
|
this.socket.on('audio-error', (error: any) => {
|
|
315
|
+
console.log('[WebSocket] Audio error event received:', JSON.stringify(error, null, 2));
|
|
275
316
|
this.emit('audio-error', error);
|
|
276
317
|
});
|
|
277
318
|
|
|
278
319
|
this.socket.on('transcription-error', (error: any) => {
|
|
320
|
+
console.log('[WebSocket] Transcription error event received:', JSON.stringify(error, null, 2));
|
|
279
321
|
this.emit('transcription-error', error);
|
|
280
322
|
});
|
|
323
|
+
|
|
324
|
+
// Catch-all event listener for debugging
|
|
325
|
+
this.socket.onAny((eventName: string, ...args: any[]) => {
|
|
326
|
+
console.log(`[WebSocket] Raw event received: "${eventName}"`, JSON.stringify(args, null, 2));
|
|
327
|
+
});
|
|
281
328
|
}
|
|
282
329
|
|
|
283
330
|
/**
|