whio-api-sdk 1.0.203-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 +42 -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 +39 -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));
|
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) {
|