@ray-js/t-agent-plugin-aistream 0.2.0-beta-17 → 0.2.0-beta.18
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/AIStreamTypes.d.ts +200 -38
- package/dist/AIStreamTypes.js +57 -20
- package/dist/buildIn/withBuildIn.js +50 -18
- package/dist/global.d.ts +1 -1
- package/dist/global.js +1 -1
- package/dist/utils/AIStream.d.ts +4 -3
- package/dist/utils/AIStream.js +117 -56
- package/dist/utils/createAsrAgent.d.ts +1 -1
- package/dist/utils/createAsrAgent.js +11 -10
- package/dist/utils/defaultMock.js +35 -28
- package/dist/utils/errors.d.ts +4 -11
- package/dist/utils/errors.js +77 -14
- package/dist/utils/sendMessage.d.ts +1 -4
- package/dist/utils/sendMessage.js +31 -48
- package/dist/utils/ttt.d.ts +10 -1
- package/dist/utils/ttt.js +7 -3
- package/dist/withAIStream.d.ts +2 -0
- package/dist/withAIStream.js +8 -3
- package/package.json +2 -2
package/dist/utils/AIStream.js
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
|
+
import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
|
|
1
2
|
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
|
|
2
3
|
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
|
|
4
|
+
const _excluded = ["signal"];
|
|
3
5
|
import "core-js/modules/esnext.iterator.constructor.js";
|
|
4
6
|
import "core-js/modules/esnext.iterator.find.js";
|
|
5
7
|
import "core-js/modules/esnext.iterator.for-each.js";
|
|
6
8
|
import "core-js/modules/esnext.iterator.map.js";
|
|
7
9
|
import "core-js/modules/web.dom-collections.iterator.js";
|
|
8
|
-
import { AIStreamErrorCode, BizTag, ConnectClientType, ConnectState, EventType, SessionState } from '../AIStreamTypes';
|
|
9
|
-
import { closeSession, connect, createSession, disconnect, getCurrentHomeInfo, isConnected, queryAgentToken, registerRecordAmplitudes, sendEventChatBreak, sendEventEnd, sendEventPayloadEnd, sendEventStart, sendImageData, sendTextData, startRecordAndSendAudioData, stopRecordAndSendAudioData, unregisterVoiceAmplitudes } from './ttt';
|
|
10
|
+
import { AIStreamAttributeType, AIStreamErrorCode, AIStreamServerErrorCode, BizTag, ConnectClientType, ConnectState, EventType, NetworkType, SessionState } from '../AIStreamTypes';
|
|
11
|
+
import { closeSession, connect, createSession, disconnect, getCurrentHomeInfo, getNetworkType, isConnected, queryAgentToken, registerRecordAmplitudes, sendEventChatBreak, sendEventEnd, sendEventPayloadEnd, sendEventStart, sendImageData, sendTextData, startRecordAndSendAudioData, stopRecordAndSendAudioData, unregisterVoiceAmplitudes } from './ttt';
|
|
10
12
|
import { AIStreamObserver, AIStreamObserverPool } from './observer';
|
|
11
13
|
import { isAbortError } from '@ray-js/t-agent';
|
|
12
14
|
import logger from './logger';
|
|
13
|
-
import {
|
|
14
|
-
import { tryCatch } from './misc';
|
|
15
|
+
import { AIStreamError, tryCatchTTT } from './errors';
|
|
15
16
|
export class AIStreamClient {
|
|
16
17
|
constructor() {
|
|
17
18
|
_defineProperty(this, "pool", new AIStreamObserverPool());
|
|
@@ -72,12 +73,24 @@ export class AIStreamConnection {
|
|
|
72
73
|
}
|
|
73
74
|
};
|
|
74
75
|
this.promise = (async () => {
|
|
76
|
+
// 检查网络状态
|
|
77
|
+
{
|
|
78
|
+
const [error, result] = await tryCatchTTT(() => getNetworkType());
|
|
79
|
+
if (error || (result === null || result === void 0 ? void 0 : result.networkType) === NetworkType.NONE) {
|
|
80
|
+
this.cleanup();
|
|
81
|
+
this.state = ConnectState.DISCONNECTED;
|
|
82
|
+
// 未连接网络
|
|
83
|
+
throw new AIStreamError('Network is offline', AIStreamErrorCode.NETWORK_OFFLINE);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
75
87
|
// 检查连接状态
|
|
76
88
|
{
|
|
77
|
-
const [error, result] = await
|
|
89
|
+
const [error, result] = await tryCatchTTT(() => isConnected(this.options));
|
|
78
90
|
if (error) {
|
|
79
|
-
this.
|
|
80
|
-
|
|
91
|
+
this.cleanup();
|
|
92
|
+
this.state = ConnectState.DISCONNECTED;
|
|
93
|
+
throw error;
|
|
81
94
|
}
|
|
82
95
|
if (result.connected) {
|
|
83
96
|
this.state = result.state;
|
|
@@ -89,10 +102,11 @@ export class AIStreamConnection {
|
|
|
89
102
|
|
|
90
103
|
// 未连接的情况,调用 connect
|
|
91
104
|
{
|
|
92
|
-
const [error, result] = await
|
|
105
|
+
const [error, result] = await tryCatchTTT(() => connect(this.options));
|
|
93
106
|
if (error) {
|
|
94
|
-
this.
|
|
95
|
-
|
|
107
|
+
this.cleanup();
|
|
108
|
+
this.state = ConnectState.DISCONNECTED;
|
|
109
|
+
throw error;
|
|
96
110
|
}
|
|
97
111
|
this.connectionId = result.connectionId;
|
|
98
112
|
this.state = ConnectState.CONNECTED;
|
|
@@ -122,7 +136,7 @@ export class AIStreamConnection {
|
|
|
122
136
|
if (session.sessionId && this.connectionId) {
|
|
123
137
|
await closeSession({
|
|
124
138
|
sessionId: session.sessionId,
|
|
125
|
-
code:
|
|
139
|
+
code: AIStreamServerErrorCode.OK
|
|
126
140
|
});
|
|
127
141
|
}
|
|
128
142
|
this.activeSessions.delete(session);
|
|
@@ -164,12 +178,27 @@ export class AIStreamSession {
|
|
|
164
178
|
(_this$activeEvent2 = this.activeEvent) === null || _this$activeEvent2 === void 0 || _this$activeEvent2.emit('data', entry);
|
|
165
179
|
if (entry.type === 'event' && entry.body.eventId === this.activeEvent.eventId) {
|
|
166
180
|
const {
|
|
167
|
-
eventType
|
|
181
|
+
eventType,
|
|
182
|
+
userData
|
|
168
183
|
} = entry.body;
|
|
169
184
|
if (eventType === EventType.EVENT_END || eventType === EventType.CHAT_BREAK || eventType === EventType.ONE_SHOT) {
|
|
170
185
|
var _this$activeEvent3;
|
|
171
186
|
(_this$activeEvent3 = this.activeEvent) === null || _this$activeEvent3 === void 0 || _this$activeEvent3.emit('finish');
|
|
172
187
|
this.cleanupEvent();
|
|
188
|
+
} else if (eventType === EventType.SERVER_ERROR) {
|
|
189
|
+
var _this$activeEvent4;
|
|
190
|
+
let code = '';
|
|
191
|
+
let message = '';
|
|
192
|
+
for (const item of userData) {
|
|
193
|
+
if (item.type === AIStreamAttributeType.ERROR_CODE) {
|
|
194
|
+
code = item.value;
|
|
195
|
+
} else if (item.type === AIStreamAttributeType.ERROR_MESSAGE) {
|
|
196
|
+
message = item.value;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
const error = new AIStreamError(message || 'Event error occurred', code || AIStreamErrorCode.UNKNOWN_ERROR);
|
|
200
|
+
(_this$activeEvent4 = this.activeEvent) === null || _this$activeEvent4 === void 0 || _this$activeEvent4.emit('error', error);
|
|
201
|
+
this.cleanupEvent();
|
|
173
202
|
}
|
|
174
203
|
}
|
|
175
204
|
});
|
|
@@ -187,58 +216,87 @@ export class AIStreamSession {
|
|
|
187
216
|
this.promise = (async () => {
|
|
188
217
|
try {
|
|
189
218
|
await this.connection._ensureConnected();
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
219
|
+
} catch (e) {
|
|
220
|
+
this.promise = null;
|
|
221
|
+
throw e;
|
|
222
|
+
}
|
|
223
|
+
let ownerId = this.options.ownerId;
|
|
224
|
+
if (!ownerId) {
|
|
225
|
+
if (this.connection.options.clientType === ConnectClientType.APP) {
|
|
226
|
+
try {
|
|
193
227
|
const {
|
|
194
228
|
homeId
|
|
195
229
|
} = await getCurrentHomeInfo();
|
|
196
230
|
ownerId = homeId;
|
|
197
|
-
}
|
|
198
|
-
|
|
231
|
+
} catch (e) {
|
|
232
|
+
this.promise = null;
|
|
233
|
+
throw new AIStreamError('Cannot get current home info by getCurrentHomeInfo', AIStreamErrorCode.INVALID_PARAMS);
|
|
199
234
|
}
|
|
200
|
-
|
|
235
|
+
} else {
|
|
236
|
+
ownerId = this.connection.options.deviceId;
|
|
201
237
|
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
238
|
+
this.options.ownerId = ownerId;
|
|
239
|
+
}
|
|
240
|
+
const options = _objectSpread({
|
|
241
|
+
bizTag: BizTag.DEFAULT,
|
|
242
|
+
ownerId,
|
|
243
|
+
extParams: {}
|
|
244
|
+
}, this.options);
|
|
245
|
+
const [error, result] = await tryCatchTTT(() => queryAgentToken(options));
|
|
246
|
+
if (error) {
|
|
247
|
+
this.promise = null;
|
|
248
|
+
throw error;
|
|
249
|
+
}
|
|
250
|
+
const {
|
|
251
|
+
agentToken,
|
|
252
|
+
bizConfig
|
|
253
|
+
} = result;
|
|
254
|
+
{
|
|
255
|
+
const [err, res] = await tryCatchTTT(() => createSession({
|
|
212
256
|
bizTag: options.bizTag,
|
|
213
257
|
agentToken,
|
|
214
258
|
bizConfig,
|
|
215
259
|
userData: options.userData
|
|
216
|
-
});
|
|
260
|
+
}));
|
|
261
|
+
if (err) {
|
|
262
|
+
this.promise = null;
|
|
263
|
+
throw err;
|
|
264
|
+
}
|
|
217
265
|
this.sessionId = res.sessionId;
|
|
218
266
|
this.sendDataChannels = res.sendDataChannels;
|
|
219
267
|
this.revDataChannels = res.revDataChannels;
|
|
220
|
-
} finally {
|
|
221
268
|
this.promise = null;
|
|
222
269
|
}
|
|
223
270
|
})();
|
|
224
271
|
return this.promise;
|
|
225
272
|
}
|
|
226
273
|
async startEvent() {
|
|
227
|
-
var _options$signal;
|
|
228
274
|
let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
229
275
|
if (this.disposed) {
|
|
230
|
-
throw new
|
|
276
|
+
throw new AIStreamError('Event has been disposed', AIStreamErrorCode.EVENT_DISPOSED);
|
|
231
277
|
}
|
|
232
278
|
if (this.activeEvent) {
|
|
233
|
-
throw new
|
|
279
|
+
throw new AIStreamError('Cannot start a new event while another is active', AIStreamErrorCode.EVENT_EXISTS);
|
|
234
280
|
}
|
|
281
|
+
const {
|
|
282
|
+
signal
|
|
283
|
+
} = options,
|
|
284
|
+
rest = _objectWithoutProperties(options, _excluded);
|
|
235
285
|
await this.ensureSession();
|
|
236
|
-
(
|
|
286
|
+
if (signal !== null && signal !== void 0 && signal.aborted) {
|
|
287
|
+
const error = new AIStreamError('start event was aborted', AIStreamErrorCode.EVENT_ABORTED);
|
|
288
|
+
error.name = 'AbortError';
|
|
289
|
+
throw error;
|
|
290
|
+
}
|
|
291
|
+
const [error, result] = await tryCatchTTT(() => sendEventStart(_objectSpread({
|
|
292
|
+
sessionId: this.sessionId
|
|
293
|
+
}, rest)));
|
|
294
|
+
if (error) {
|
|
295
|
+
throw error;
|
|
296
|
+
}
|
|
237
297
|
const {
|
|
238
298
|
eventId
|
|
239
|
-
} =
|
|
240
|
-
sessionId: this.sessionId
|
|
241
|
-
}, options));
|
|
299
|
+
} = result;
|
|
242
300
|
this.activeEvent = new AIStreamEvent({
|
|
243
301
|
eventId,
|
|
244
302
|
sessionId: this.sessionId,
|
|
@@ -277,11 +335,11 @@ export class AIStreamSession {
|
|
|
277
335
|
return this.activeEvent;
|
|
278
336
|
}
|
|
279
337
|
cleanupEvent() {
|
|
280
|
-
var _this$activeObserver, _this$
|
|
338
|
+
var _this$activeObserver, _this$activeEvent5;
|
|
281
339
|
logger.debug('AIStreamSession cleanupEvent');
|
|
282
340
|
(_this$activeObserver = this.activeObserver) === null || _this$activeObserver === void 0 || _this$activeObserver.disconnect();
|
|
283
341
|
this.activeObserver = null;
|
|
284
|
-
(_this$
|
|
342
|
+
(_this$activeEvent5 = this.activeEvent) === null || _this$activeEvent5 === void 0 || _this$activeEvent5.emit('close');
|
|
285
343
|
this.activeEvent = null;
|
|
286
344
|
}
|
|
287
345
|
cleanup() {
|
|
@@ -318,13 +376,13 @@ export class AIStreamEvent {
|
|
|
318
376
|
findFirstCode(type) {
|
|
319
377
|
const code = this.sendDataChannels.find(code => code.startsWith(type));
|
|
320
378
|
if (!code) {
|
|
321
|
-
throw new
|
|
379
|
+
throw new AIStreamError("No available data code for type: ".concat(type), AIStreamErrorCode.EVENT_NO_DATA_CODE);
|
|
322
380
|
}
|
|
323
381
|
return code;
|
|
324
382
|
}
|
|
325
383
|
write(chunk) {
|
|
326
384
|
if (this.closed) {
|
|
327
|
-
throw new
|
|
385
|
+
throw new AIStreamError('Cannot write to a closed event', AIStreamErrorCode.EVENT_CLOSED);
|
|
328
386
|
}
|
|
329
387
|
const dataChannel = chunk.dataChannel || this.findFirstCode(chunk.type);
|
|
330
388
|
let promise = this.chains[dataChannel];
|
|
@@ -336,13 +394,17 @@ export class AIStreamEvent {
|
|
|
336
394
|
return;
|
|
337
395
|
}
|
|
338
396
|
if (chunk.type === 'text') {
|
|
339
|
-
await sendTextData({
|
|
397
|
+
const [error] = await tryCatchTTT(() => sendTextData({
|
|
340
398
|
sessionId: this.sessionId,
|
|
341
399
|
text: chunk.text,
|
|
342
400
|
dataChannel,
|
|
343
401
|
userData: chunk.userData
|
|
344
|
-
});
|
|
402
|
+
}));
|
|
403
|
+
if (error) {
|
|
404
|
+
throw error;
|
|
405
|
+
}
|
|
345
406
|
} else if (chunk.type === 'file') {
|
|
407
|
+
logger.warn('File data sending is not implemented yet');
|
|
346
408
|
// await sendFileData({
|
|
347
409
|
// sessionId: this.sessionId,
|
|
348
410
|
// path: chunk.path,
|
|
@@ -351,11 +413,12 @@ export class AIStreamEvent {
|
|
|
351
413
|
// userData: chunk.userData,
|
|
352
414
|
// });
|
|
353
415
|
} else if (chunk.type === 'image') {
|
|
354
|
-
await sendImageData({
|
|
416
|
+
const [error] = await tryCatchTTT(() => sendImageData({
|
|
355
417
|
sessionId: this.sessionId,
|
|
356
418
|
path: chunk.path,
|
|
357
419
|
userData: chunk.userData
|
|
358
|
-
});
|
|
420
|
+
}));
|
|
421
|
+
throw error;
|
|
359
422
|
}
|
|
360
423
|
sendEventPayloadEnd({
|
|
361
424
|
eventId: this.eventId,
|
|
@@ -363,18 +426,19 @@ export class AIStreamEvent {
|
|
|
363
426
|
dataChannel
|
|
364
427
|
});
|
|
365
428
|
}).catch(error => {
|
|
366
|
-
|
|
367
|
-
|
|
429
|
+
const e = new AIStreamError(error.message, error.code || AIStreamErrorCode.EVENT_WRITE_FAILED);
|
|
430
|
+
this.emit('error', e);
|
|
431
|
+
throw e;
|
|
368
432
|
});
|
|
369
433
|
return this.chains[dataChannel];
|
|
370
434
|
}
|
|
371
435
|
stream(source) {
|
|
372
436
|
if (this.closed) {
|
|
373
|
-
throw new
|
|
437
|
+
throw new AIStreamError('Cannot stream to a closed event', AIStreamErrorCode.EVENT_CLOSED);
|
|
374
438
|
}
|
|
375
439
|
const dataChannel = source.dataChannel || this.findFirstCode(source.type);
|
|
376
440
|
if (this.streams[dataChannel]) {
|
|
377
|
-
throw new
|
|
441
|
+
throw new AIStreamError("".concat(dataChannel, " stream already exists"), AIStreamErrorCode.STREAM_EXISTS);
|
|
378
442
|
}
|
|
379
443
|
let startPromise = null;
|
|
380
444
|
const stream = {
|
|
@@ -383,7 +447,7 @@ export class AIStreamEvent {
|
|
|
383
447
|
started: false,
|
|
384
448
|
start: async () => {
|
|
385
449
|
if (this.closed) {
|
|
386
|
-
throw new
|
|
450
|
+
throw new AIStreamError('Cannot stream to a closed event', AIStreamErrorCode.EVENT_CLOSED);
|
|
387
451
|
}
|
|
388
452
|
if (stream.started) {
|
|
389
453
|
return;
|
|
@@ -416,11 +480,7 @@ export class AIStreamEvent {
|
|
|
416
480
|
}
|
|
417
481
|
// 一定要等录音开始,才能结束
|
|
418
482
|
if (startPromise) {
|
|
419
|
-
|
|
420
|
-
await startPromise;
|
|
421
|
-
} catch (e) {
|
|
422
|
-
// pass
|
|
423
|
-
}
|
|
483
|
+
await tryCatchTTT(() => startPromise);
|
|
424
484
|
startPromise = null;
|
|
425
485
|
}
|
|
426
486
|
if (source.type === 'audio') {
|
|
@@ -435,6 +495,7 @@ export class AIStreamEvent {
|
|
|
435
495
|
userData: source.userData
|
|
436
496
|
});
|
|
437
497
|
} else if (source.type === 'video') {
|
|
498
|
+
logger.warn('Video data sending is not implemented yet');
|
|
438
499
|
// const cameraType = source.cameraType || VideoCameraType.BACK;
|
|
439
500
|
// await stopRecordAndSendVideoData({
|
|
440
501
|
// dataChannel,
|
|
@@ -477,7 +538,7 @@ export class AIStreamEvent {
|
|
|
477
538
|
userData: options === null || options === void 0 ? void 0 : options.userData
|
|
478
539
|
});
|
|
479
540
|
}
|
|
480
|
-
const error = new
|
|
541
|
+
const error = new AIStreamError('This operation was aborted', AIStreamErrorCode.EVENT_ABORTED);
|
|
481
542
|
error.name = 'AbortError';
|
|
482
543
|
// 发送 break 后,stream 自动会关掉,在这里提前关闭
|
|
483
544
|
Object.values(this.streams).forEach(s => {
|
|
@@ -49,7 +49,7 @@ declare class AsrAgent {
|
|
|
49
49
|
* @example
|
|
50
50
|
* const asrAgent = createAsrAgent({
|
|
51
51
|
* agentId: 'asr-agent',
|
|
52
|
-
* tokenApi: '
|
|
52
|
+
* tokenApi: 'xxxx',
|
|
53
53
|
* tokenApiVersion: '1.0',
|
|
54
54
|
* clientType: ConnectClientType.APP,
|
|
55
55
|
* deviceId: 'deviceId',
|
|
@@ -2,7 +2,7 @@ import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
|
|
|
2
2
|
import "core-js/modules/es.json.stringify.js";
|
|
3
3
|
import { authorize } from './ttt';
|
|
4
4
|
import { DEFAULT_TOKEN_API, DEFAULT_TOKEN_API_VERSION, globalAIStreamClient } from '../global';
|
|
5
|
-
import { ConnectClientType, AIStreamAttributePayloadType, AIStreamAttributeType
|
|
5
|
+
import { ConnectClientType, AIStreamAttributePayloadType, AIStreamAttributeType } from '../AIStreamTypes';
|
|
6
6
|
import logger from './logger';
|
|
7
7
|
class AsrAgent {
|
|
8
8
|
constructor(options) {
|
|
@@ -51,7 +51,10 @@ class AsrAgent {
|
|
|
51
51
|
const activeSession = streamConn.createSession({
|
|
52
52
|
api: tokenApi || DEFAULT_TOKEN_API,
|
|
53
53
|
apiVersion: tokenApiVersion || DEFAULT_TOKEN_API_VERSION,
|
|
54
|
-
solutionCode: agentId
|
|
54
|
+
solutionCode: agentId,
|
|
55
|
+
extParams: {
|
|
56
|
+
onlyAsr: true
|
|
57
|
+
}
|
|
55
58
|
});
|
|
56
59
|
this.activeSession = activeSession;
|
|
57
60
|
return this.activeSession;
|
|
@@ -81,17 +84,15 @@ class AsrAgent {
|
|
|
81
84
|
onFinish,
|
|
82
85
|
onError
|
|
83
86
|
} = this.options || {};
|
|
84
|
-
const activeSession =
|
|
85
|
-
const attribute = {
|
|
86
|
-
'processing.interrupt': 'false',
|
|
87
|
-
'asr.enableVad': 'false',
|
|
88
|
-
'sys.workflow': AIStreamChatSysWorkflow.ASR
|
|
89
|
-
};
|
|
87
|
+
const activeSession = this.createSession();
|
|
90
88
|
const activeEvent = await activeSession.startEvent({
|
|
91
89
|
userData: [{
|
|
92
90
|
type: AIStreamAttributeType.AI_CHAT,
|
|
93
91
|
payloadType: AIStreamAttributePayloadType.STRING,
|
|
94
|
-
value: JSON.stringify(
|
|
92
|
+
value: JSON.stringify({
|
|
93
|
+
'processing.interrupt': 'false',
|
|
94
|
+
'asr.enableVad': 'false'
|
|
95
|
+
})
|
|
95
96
|
}]
|
|
96
97
|
});
|
|
97
98
|
this.activeEvent = activeEvent;
|
|
@@ -165,7 +166,7 @@ class AsrAgent {
|
|
|
165
166
|
* @example
|
|
166
167
|
* const asrAgent = createAsrAgent({
|
|
167
168
|
* agentId: 'asr-agent',
|
|
168
|
-
* tokenApi: '
|
|
169
|
+
* tokenApi: 'xxxx',
|
|
169
170
|
* tokenApiVersion: '1.0',
|
|
170
171
|
* clientType: ConnectClientType.APP,
|
|
171
172
|
* deviceId: 'deviceId',
|
|
@@ -8,9 +8,10 @@ import "core-js/modules/esnext.iterator.map.js";
|
|
|
8
8
|
import "core-js/modules/web.dom-collections.iterator.js";
|
|
9
9
|
import { mock } from './mock';
|
|
10
10
|
import { EmitterEvent, generateId } from '@ray-js/t-agent';
|
|
11
|
-
import {
|
|
11
|
+
import { AIStreamAppErrorCode, AIStreamServerErrorCode, BizCode, ConnectState, EventType, NetworkType, ReceivedTextPacketEof, ReceivedTextPacketType, SessionState, StreamFlag } from '../AIStreamTypes';
|
|
12
12
|
import AbortController from './abort';
|
|
13
13
|
import { tryCatch } from './misc';
|
|
14
|
+
import { TTTError } from './errors';
|
|
14
15
|
function splitString(input) {
|
|
15
16
|
return input.match(/[a-zA-Z0-9]+\s*|[\u4e00-\u9fff]+\s*|[^\w\s\u4e00-\u9fff]+\s*|[\s]+/g) || [];
|
|
16
17
|
}
|
|
@@ -18,31 +19,37 @@ mock.data.set('sessionMap', new Map());
|
|
|
18
19
|
const getSession = (sessionId, eventId) => {
|
|
19
20
|
const connection = getCurrentConnection();
|
|
20
21
|
if (!connection) {
|
|
21
|
-
throw new
|
|
22
|
+
throw new TTTError('not connect', AIStreamAppErrorCode.CONNECTION_INVALID);
|
|
22
23
|
}
|
|
23
24
|
const map = mock.data.get('sessionMap');
|
|
24
25
|
const session = map.get(sessionId);
|
|
25
26
|
if (!session) {
|
|
26
|
-
throw new
|
|
27
|
+
throw new TTTError('session is invalid', AIStreamAppErrorCode.SESSION_ID_INVALID);
|
|
27
28
|
}
|
|
28
29
|
if (eventId) {
|
|
29
30
|
if (!session.currentEvent) {
|
|
30
|
-
throw new
|
|
31
|
+
throw new TTTError('eventId is invalid', AIStreamAppErrorCode.EVENT_ID_INVALID);
|
|
31
32
|
}
|
|
32
33
|
if (session.currentEvent.eventId !== eventId) {
|
|
33
|
-
throw new
|
|
34
|
+
throw new TTTError('eventId is invalid', AIStreamAppErrorCode.EVENT_ID_INVALID);
|
|
34
35
|
}
|
|
35
36
|
}
|
|
36
37
|
return session;
|
|
37
38
|
};
|
|
39
|
+
const getCurrentConnection = () => {
|
|
40
|
+
return mock.data.get('currentConnection');
|
|
41
|
+
};
|
|
42
|
+
mock.hooks.hook('getNetworkType', context => {
|
|
43
|
+
context.result = {
|
|
44
|
+
networkType: NetworkType.WIFI,
|
|
45
|
+
signalStrength: 85
|
|
46
|
+
};
|
|
47
|
+
});
|
|
38
48
|
mock.hooks.hook('getMiniAppConfig', context => {
|
|
39
49
|
context.result = {
|
|
40
50
|
config: {}
|
|
41
51
|
};
|
|
42
52
|
});
|
|
43
|
-
const getCurrentConnection = () => {
|
|
44
|
-
return mock.data.get('currentConnection');
|
|
45
|
-
};
|
|
46
53
|
mock.hooks.hook('isConnected', context => {
|
|
47
54
|
const connection = getCurrentConnection();
|
|
48
55
|
if (connection) {
|
|
@@ -61,13 +68,13 @@ mock.hooks.hook('isConnected', context => {
|
|
|
61
68
|
mock.hooks.hook('connect', context => {
|
|
62
69
|
let connection = getCurrentConnection();
|
|
63
70
|
if (connection) {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
connection = {
|
|
67
|
-
connectionId: generateId()
|
|
68
|
-
};
|
|
69
|
-
mock.data.set('currentConnection', connection);
|
|
71
|
+
context.result = connection;
|
|
72
|
+
return;
|
|
70
73
|
}
|
|
74
|
+
connection = {
|
|
75
|
+
connectionId: generateId()
|
|
76
|
+
};
|
|
77
|
+
mock.data.set('currentConnection', connection);
|
|
71
78
|
context.result = connection;
|
|
72
79
|
});
|
|
73
80
|
mock.hooks.hook('disconnect', context => {
|
|
@@ -78,10 +85,10 @@ mock.hooks.hook('disconnect', context => {
|
|
|
78
85
|
} = context;
|
|
79
86
|
const connection = getCurrentConnection();
|
|
80
87
|
if (!connection) {
|
|
81
|
-
|
|
88
|
+
return;
|
|
82
89
|
}
|
|
83
90
|
if (connection.connectionId !== connectionId) {
|
|
84
|
-
throw new
|
|
91
|
+
throw new TTTError('not connect', AIStreamAppErrorCode.CONNECTION_INVALID);
|
|
85
92
|
}
|
|
86
93
|
mock.data.set('currentConnection', null);
|
|
87
94
|
mock.data.set('sessionMap', new Map());
|
|
@@ -104,7 +111,7 @@ const dispatch = (type, detail) => {
|
|
|
104
111
|
mock.hooks.hook('createSession', context => {
|
|
105
112
|
const connection = getCurrentConnection();
|
|
106
113
|
if (!connection) {
|
|
107
|
-
throw new
|
|
114
|
+
throw new TTTError('not connect', AIStreamAppErrorCode.CONNECTION_INVALID);
|
|
108
115
|
}
|
|
109
116
|
const map = mock.data.get('sessionMap');
|
|
110
117
|
const session = {
|
|
@@ -161,12 +168,12 @@ mock.hooks.hook('sendEventStart', async context => {
|
|
|
161
168
|
sessionId
|
|
162
169
|
} = options;
|
|
163
170
|
|
|
164
|
-
// throw new
|
|
171
|
+
// throw new TTTError('sendEventStart is deprecated, use sendEventStartV2 instead');
|
|
165
172
|
|
|
166
173
|
const session = getSession(sessionId);
|
|
167
174
|
await mock.sleep(200);
|
|
168
175
|
if (session.currentEvent) {
|
|
169
|
-
throw new
|
|
176
|
+
throw new TTTError('sendEventStart already in event', AIStreamAppErrorCode.EVENT_ID_INVALID);
|
|
170
177
|
}
|
|
171
178
|
const eventId = generateId();
|
|
172
179
|
const event = {
|
|
@@ -176,7 +183,7 @@ mock.hooks.hook('sendEventStart', async context => {
|
|
|
176
183
|
return;
|
|
177
184
|
}
|
|
178
185
|
if (!session.currentEvent || session.currentEvent.eventId !== eventId) {
|
|
179
|
-
throw new
|
|
186
|
+
throw new TTTError('replyEvent event not exists or not in current event', AIStreamAppErrorCode.DATA_SEND_FAILED);
|
|
180
187
|
}
|
|
181
188
|
dispatch('onTextReceived', {
|
|
182
189
|
dataChannel: 'text',
|
|
@@ -190,7 +197,7 @@ mock.hooks.hook('sendEventStart', async context => {
|
|
|
190
197
|
return;
|
|
191
198
|
}
|
|
192
199
|
if (!session.currentEvent || session.currentEvent.eventId !== eventId) {
|
|
193
|
-
throw new
|
|
200
|
+
throw new TTTError('replyEvent event not exists or not in current event', AIStreamAppErrorCode.DATA_SEND_FAILED);
|
|
194
201
|
}
|
|
195
202
|
dispatch('onEventReceived', {
|
|
196
203
|
eventId,
|
|
@@ -225,7 +232,7 @@ mock.hooks.hook('sendEventEnd', async context => {
|
|
|
225
232
|
context.result = true;
|
|
226
233
|
const event = session.currentEvent;
|
|
227
234
|
if (event.eventId !== context.options.eventId) {
|
|
228
|
-
throw new
|
|
235
|
+
throw new TTTError('sendEventEnd eventId mismatch', AIStreamAppErrorCode.EVENT_ID_INVALID);
|
|
229
236
|
}
|
|
230
237
|
await mock.sleep(100);
|
|
231
238
|
(async () => {
|
|
@@ -240,7 +247,7 @@ mock.hooks.hook('sendEventEnd', async context => {
|
|
|
240
247
|
dispatch('onSessionStateChanged', {
|
|
241
248
|
sessionId: session.sessionId,
|
|
242
249
|
sessionState: SessionState.CLOSED,
|
|
243
|
-
code:
|
|
250
|
+
code: AIStreamServerErrorCode.INTERNAL_SERVER_ERROR
|
|
244
251
|
});
|
|
245
252
|
session.closed = true;
|
|
246
253
|
const map = mock.data.get('sessionMap');
|
|
@@ -340,7 +347,7 @@ mock.hooks.hook('sendEventChatBreak', async context => {
|
|
|
340
347
|
mock.hooks.hook('startRecordAndSendAudioData', async context => {
|
|
341
348
|
const session = getSession(context.options.sessionId);
|
|
342
349
|
if (!session.currentEvent) {
|
|
343
|
-
throw new
|
|
350
|
+
throw new TTTError('startRecordAndSendAudioData event not exists', AIStreamAppErrorCode.EVENT_ID_INVALID);
|
|
344
351
|
}
|
|
345
352
|
const event = session.currentEvent;
|
|
346
353
|
context.result = true;
|
|
@@ -444,7 +451,7 @@ mock.hooks.hook('startRecordAndSendAudioData', async context => {
|
|
|
444
451
|
mock.hooks.hook('stopRecordAndSendAudioData', async context => {
|
|
445
452
|
const session = getSession(context.options.sessionId);
|
|
446
453
|
if (!session.currentEvent) {
|
|
447
|
-
throw new
|
|
454
|
+
throw new TTTError('stopRecordAndSendAudioData event not exists', AIStreamAppErrorCode.SESSION_ID_INVALID);
|
|
448
455
|
}
|
|
449
456
|
session.currentEvent.asr.finishController.abort(new Error('stopRecordAndSendAudioData'));
|
|
450
457
|
context.result = true;
|
|
@@ -459,7 +466,7 @@ mock.hooks.hook('stopRecordAndSendVideoData', context => {
|
|
|
459
466
|
mock.hooks.hook('sendImageData', context => {
|
|
460
467
|
const session = getSession(context.options.sessionId);
|
|
461
468
|
if (!session.currentEvent) {
|
|
462
|
-
throw new
|
|
469
|
+
throw new TTTError('sendImageData event not exists', AIStreamAppErrorCode.SESSION_ID_INVALID);
|
|
463
470
|
}
|
|
464
471
|
session.currentEvent.data.push({
|
|
465
472
|
type: 'image',
|
|
@@ -472,7 +479,7 @@ mock.hooks.hook('sendTextData', context => {
|
|
|
472
479
|
context.result = true;
|
|
473
480
|
const session = getSession(context.options.sessionId);
|
|
474
481
|
if (!session.currentEvent) {
|
|
475
|
-
throw new
|
|
482
|
+
throw new TTTError('sendTextData event not exists', AIStreamAppErrorCode.SESSION_ID_INVALID);
|
|
476
483
|
}
|
|
477
484
|
session.currentEvent.data.push({
|
|
478
485
|
type: 'text',
|
|
@@ -595,7 +602,7 @@ mock.hooks.hook('updateRecord', context => {
|
|
|
595
602
|
id: [id]
|
|
596
603
|
});
|
|
597
604
|
if (!records.length) {
|
|
598
|
-
throw new
|
|
605
|
+
throw new TTTError('record not exists', AIStreamAppErrorCode.INVALID_PARAMS);
|
|
599
606
|
}
|
|
600
607
|
const newRecord = _objectSpread(_objectSpread({}, records[0]), options);
|
|
601
608
|
mock.setRecord({
|
package/dist/utils/errors.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { AIStreamErrorCode } from '../AIStreamTypes';
|
|
1
2
|
export declare class BaseError extends Error {
|
|
2
3
|
message: string;
|
|
3
4
|
code: string | number;
|
|
@@ -9,18 +10,10 @@ export declare class TTTError extends BaseError {
|
|
|
9
10
|
code: string | number;
|
|
10
11
|
constructor(message: string, code: string | number);
|
|
11
12
|
}
|
|
12
|
-
export declare class
|
|
13
|
-
message: string;
|
|
14
|
-
code: string | number;
|
|
15
|
-
constructor(message: string, code: string | number);
|
|
16
|
-
}
|
|
17
|
-
export declare class AIStreamSessionError extends BaseError {
|
|
18
|
-
message: string;
|
|
19
|
-
code: string | number;
|
|
20
|
-
constructor(message: string, code: string | number);
|
|
21
|
-
}
|
|
22
|
-
export declare class AIStreamEventError extends BaseError {
|
|
13
|
+
export declare class AIStreamError extends BaseError {
|
|
23
14
|
message: string;
|
|
24
15
|
code: string | number;
|
|
25
16
|
constructor(message: string, code: string | number);
|
|
26
17
|
}
|
|
18
|
+
export declare const transformErrorCode: (code: string | number) => AIStreamErrorCode;
|
|
19
|
+
export declare function tryCatchTTT<T>(fn: () => Promise<T>): Promise<[AIStreamError, null] | [null, T]>;
|