@ray-js/t-agent-plugin-aistream 0.2.0-beta-4 → 0.2.0-beta-6
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 +28 -0
- package/dist/AIStreamTypes.js +1 -0
- package/dist/utils/AIStream.d.ts +1 -0
- package/dist/utils/AIStream.js +55 -36
- package/dist/utils/defaultMock.js +66 -3
- package/dist/utils/errors.d.ts +26 -0
- package/dist/utils/errors.js +42 -0
- package/dist/utils/promisify.d.ts +0 -6
- package/dist/utils/promisify.js +2 -11
- package/dist/utils/sendMessage.d.ts +0 -4
- package/dist/utils/sendMessage.js +13 -10
- package/dist/utils/ttt.d.ts +6 -2
- package/dist/utils/ttt.js +1 -13
- package/dist/withAIStream.js +1 -4
- package/package.json +2 -2
package/dist/AIStreamTypes.d.ts
CHANGED
|
@@ -86,6 +86,7 @@ export type ImagePathInputBlock = {
|
|
|
86
86
|
type: 'image_path';
|
|
87
87
|
image_path: {
|
|
88
88
|
path: string;
|
|
89
|
+
size: number;
|
|
89
90
|
};
|
|
90
91
|
};
|
|
91
92
|
export type FileUrlInputBlock = {
|
|
@@ -101,12 +102,15 @@ export type FilePathInputBlock = {
|
|
|
101
102
|
file_path: {
|
|
102
103
|
mimeType: string;
|
|
103
104
|
path: string;
|
|
105
|
+
size: number;
|
|
104
106
|
};
|
|
105
107
|
};
|
|
106
108
|
export type VideoPathInputBlock = {
|
|
107
109
|
type: 'video_path';
|
|
108
110
|
video_path: {
|
|
109
111
|
path: string;
|
|
112
|
+
thumb_path: string;
|
|
113
|
+
size: number;
|
|
110
114
|
};
|
|
111
115
|
};
|
|
112
116
|
/**
|
|
@@ -651,6 +655,7 @@ export declare enum FileFormat {
|
|
|
651
655
|
SWEEPER_MAP = 6
|
|
652
656
|
}
|
|
653
657
|
export declare enum AIStreamErrorCode {
|
|
658
|
+
AIStreamError = -1,
|
|
654
659
|
OK = 200,
|
|
655
660
|
BadRequest = 400,
|
|
656
661
|
Unauthenticated = 401,
|
|
@@ -828,6 +833,29 @@ export type CheckConnectResult = {
|
|
|
828
833
|
/** 连接的唯一标识 */
|
|
829
834
|
connectionId?: string;
|
|
830
835
|
};
|
|
836
|
+
export type IsConnectedParams = {
|
|
837
|
+
/** client 类型: 1-作为设备代理, 2-作为 App */
|
|
838
|
+
clientType: number;
|
|
839
|
+
/** 代理的设备ID, clientType == 1 时必传 */
|
|
840
|
+
deviceId?: string;
|
|
841
|
+
success?: (params: {
|
|
842
|
+
/** 是否已连接 */
|
|
843
|
+
connected: boolean;
|
|
844
|
+
/** 通道连接状态: 0-初始化,1-连接中,2-鉴权中,3-已连接,4-被云端断开,5-主动关闭 */
|
|
845
|
+
state: number;
|
|
846
|
+
/** 连接的唯一标识 */
|
|
847
|
+
connectionId?: string;
|
|
848
|
+
}) => void;
|
|
849
|
+
fail?: (params: {
|
|
850
|
+
errorMsg: string;
|
|
851
|
+
errorCode: string | number;
|
|
852
|
+
innerError: {
|
|
853
|
+
errorCode: string | number;
|
|
854
|
+
errorMsg: string;
|
|
855
|
+
};
|
|
856
|
+
}) => void;
|
|
857
|
+
complete?: () => void;
|
|
858
|
+
};
|
|
831
859
|
/**
|
|
832
860
|
*@description 发起通道连接,若此前已连接会直接回调成功
|
|
833
861
|
*/
|
package/dist/AIStreamTypes.js
CHANGED
|
@@ -118,6 +118,7 @@ export let FileFormat = /*#__PURE__*/function (FileFormat) {
|
|
|
118
118
|
return FileFormat;
|
|
119
119
|
}({});
|
|
120
120
|
export let AIStreamErrorCode = /*#__PURE__*/function (AIStreamErrorCode) {
|
|
121
|
+
AIStreamErrorCode[AIStreamErrorCode["AIStreamError"] = -1] = "AIStreamError";
|
|
121
122
|
AIStreamErrorCode[AIStreamErrorCode["OK"] = 200] = "OK";
|
|
122
123
|
AIStreamErrorCode[AIStreamErrorCode["BadRequest"] = 400] = "BadRequest";
|
|
123
124
|
AIStreamErrorCode[AIStreamErrorCode["Unauthenticated"] = 401] = "Unauthenticated";
|
package/dist/utils/AIStream.d.ts
CHANGED
package/dist/utils/AIStream.js
CHANGED
|
@@ -6,9 +6,12 @@ import "core-js/modules/esnext.iterator.for-each.js";
|
|
|
6
6
|
import "core-js/modules/esnext.iterator.map.js";
|
|
7
7
|
import "core-js/modules/web.dom-collections.iterator.js";
|
|
8
8
|
import { AIStreamErrorCode, BizTag, ConnectClientType, ConnectState, EventType, SessionState } from '../AIStreamTypes';
|
|
9
|
-
import { closeSession, connect, createSession, disconnect, getCurrentHomeInfo,
|
|
9
|
+
import { closeSession, connect, createSession, disconnect, getCurrentHomeInfo, isConnected, queryAgentToken, registerRecordAmplitudes, sendEventChatBreak, sendEventEnd, sendEventPayloadEnd, sendEventStart, sendImageData, sendTextData, startRecordAndSendAudioData, stopRecordAndSendAudioData, unregisterVoiceAmplitudes } from './ttt';
|
|
10
10
|
import { AIStreamObserver, AIStreamObserverPool } from './observer';
|
|
11
11
|
import { isAbortError } from '@ray-js/t-agent';
|
|
12
|
+
import logger from './logger';
|
|
13
|
+
import { AIStreamConnectionError, AIStreamEventError } from './errors';
|
|
14
|
+
import { tryCatch } from './misc';
|
|
12
15
|
export class AIStreamClient {
|
|
13
16
|
constructor() {
|
|
14
17
|
_defineProperty(this, "pool", new AIStreamObserverPool());
|
|
@@ -38,8 +41,8 @@ export class AIStreamConnection {
|
|
|
38
41
|
session._onStateChanged(entry);
|
|
39
42
|
}
|
|
40
43
|
});
|
|
41
|
-
if (entry.body.connectState === ConnectState.DISCONNECTED || entry.body.connectState === ConnectState.CLOSED) {
|
|
42
|
-
//
|
|
44
|
+
if (entry.body.connectState === ConnectState.DISCONNECTED || entry.body.connectState === ConnectState.CLOSED || entry.body.connectState === ConnectState.CONNECTING || entry.body.connectState === ConnectState.AUTHORIZING) {
|
|
45
|
+
// 断开事件触发时只做清理,因为连接已经关掉了
|
|
43
46
|
this.cleanup();
|
|
44
47
|
}
|
|
45
48
|
}
|
|
@@ -47,9 +50,6 @@ export class AIStreamConnection {
|
|
|
47
50
|
this.activeSessions.forEach(session => {
|
|
48
51
|
if (session.sessionId && session.sessionId === entry.body.sessionId) {
|
|
49
52
|
session._onStateChanged(entry);
|
|
50
|
-
if (entry.body.sessionState === SessionState.CLOSED || entry.body.sessionState === SessionState.CREATE_FAILED) {
|
|
51
|
-
this.activeSessions.delete(session);
|
|
52
|
-
}
|
|
53
53
|
}
|
|
54
54
|
});
|
|
55
55
|
}
|
|
@@ -61,39 +61,52 @@ export class AIStreamConnection {
|
|
|
61
61
|
if (this.promise) {
|
|
62
62
|
return this.promise;
|
|
63
63
|
}
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
74
|
-
if (result.connected) {
|
|
75
|
-
this.state = result.state;
|
|
76
|
-
this.connectionId = result.connectionId;
|
|
77
|
-
return Promise.resolve();
|
|
78
|
-
}
|
|
64
|
+
const observe = () => {
|
|
65
|
+
if (!this.observer) {
|
|
66
|
+
this.observer = new AIStreamObserver(this.onStateChanged, this.pool);
|
|
67
|
+
this.observer.observe({
|
|
68
|
+
connectionState: true,
|
|
69
|
+
sessionState: true
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
};
|
|
79
73
|
this.promise = (async () => {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
74
|
+
{
|
|
75
|
+
const [error, result] = await tryCatch(() => isConnected(this.options));
|
|
76
|
+
if (error) {
|
|
77
|
+
throw new AIStreamConnectionError(error.message, error.code || AIStreamErrorCode.AIStreamError);
|
|
78
|
+
}
|
|
79
|
+
if (result.connected) {
|
|
80
|
+
this.state = result.state;
|
|
81
|
+
this.connectionId = result.connectionId;
|
|
82
|
+
observe();
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
{
|
|
87
|
+
// 调用 SDK connect
|
|
88
|
+
const [error, result] = await tryCatch(() => connect(this.options));
|
|
89
|
+
if (error) {
|
|
90
|
+
throw new AIStreamConnectionError(error.message, error.code || AIStreamErrorCode.AIStreamError);
|
|
91
|
+
}
|
|
92
|
+
this.connectionId = result.connectionId;
|
|
93
|
+
this.state = ConnectState.CONNECTED;
|
|
94
|
+
this.promise = null;
|
|
95
|
+
observe();
|
|
96
|
+
}
|
|
85
97
|
})();
|
|
86
98
|
return this.promise;
|
|
87
99
|
}
|
|
88
100
|
cleanup() {
|
|
89
101
|
var _this$observer;
|
|
102
|
+
logger.debug('AIStreamConnection cleanup');
|
|
90
103
|
(_this$observer = this.observer) === null || _this$observer === void 0 || _this$observer.disconnect();
|
|
91
104
|
this.observer = null;
|
|
92
105
|
this.state = ConnectState.CLOSED;
|
|
93
106
|
this.connectionId = null;
|
|
94
107
|
this.promise = null;
|
|
95
108
|
this.activeSessions.forEach(s => s.cleanup());
|
|
96
|
-
|
|
109
|
+
// session 不清空,closeSession 被调用时才清空
|
|
97
110
|
}
|
|
98
111
|
createSession(options) {
|
|
99
112
|
const session = new AIStreamSession(this, this.pool, options);
|
|
@@ -129,6 +142,7 @@ export class AIStreamSession {
|
|
|
129
142
|
_defineProperty(this, "sessionId", null);
|
|
130
143
|
_defineProperty(this, "sendDataChannels", []);
|
|
131
144
|
_defineProperty(this, "revDataChannels", []);
|
|
145
|
+
_defineProperty(this, "disposed", false);
|
|
132
146
|
_defineProperty(this, "promise", null);
|
|
133
147
|
_defineProperty(this, "_onStateChanged", entry => {
|
|
134
148
|
var _this$activeEvent;
|
|
@@ -203,8 +217,11 @@ export class AIStreamSession {
|
|
|
203
217
|
}
|
|
204
218
|
async startEvent() {
|
|
205
219
|
let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
220
|
+
if (this.disposed) {
|
|
221
|
+
throw new AIStreamEventError('Event has been disposed', AIStreamErrorCode.AIStreamError);
|
|
222
|
+
}
|
|
206
223
|
if (this.activeEvent) {
|
|
207
|
-
throw new
|
|
224
|
+
throw new AIStreamEventError('Cannot start a new event while another is active', AIStreamErrorCode.AIStreamError);
|
|
208
225
|
}
|
|
209
226
|
await this.ensureSession();
|
|
210
227
|
const {
|
|
@@ -251,12 +268,14 @@ export class AIStreamSession {
|
|
|
251
268
|
}
|
|
252
269
|
cleanupEvent() {
|
|
253
270
|
var _this$activeObserver, _this$activeEvent4;
|
|
271
|
+
logger.debug('AIStreamSession cleanupEvent');
|
|
254
272
|
(_this$activeObserver = this.activeObserver) === null || _this$activeObserver === void 0 || _this$activeObserver.disconnect();
|
|
255
273
|
this.activeObserver = null;
|
|
256
274
|
(_this$activeEvent4 = this.activeEvent) === null || _this$activeEvent4 === void 0 || _this$activeEvent4.emit('close');
|
|
257
275
|
this.activeEvent = null;
|
|
258
276
|
}
|
|
259
277
|
cleanup() {
|
|
278
|
+
logger.debug('AIStreamSession cleanup');
|
|
260
279
|
this.cleanupEvent();
|
|
261
280
|
this.sessionId = null;
|
|
262
281
|
this.sendDataChannels = [];
|
|
@@ -265,10 +284,10 @@ export class AIStreamSession {
|
|
|
265
284
|
|
|
266
285
|
// 会话关闭清理
|
|
267
286
|
async close() {
|
|
287
|
+
logger.debug('AIStreamSession close');
|
|
288
|
+
this.disposed = true;
|
|
268
289
|
await this.connection.closeSession(this);
|
|
269
|
-
|
|
270
|
-
this.cleanup();
|
|
271
|
-
}
|
|
290
|
+
this.cleanup();
|
|
272
291
|
}
|
|
273
292
|
}
|
|
274
293
|
export class AIStreamEvent {
|
|
@@ -289,13 +308,13 @@ export class AIStreamEvent {
|
|
|
289
308
|
findFirstCode(type) {
|
|
290
309
|
const code = this.sendDataChannels.find(code => code.startsWith(type));
|
|
291
310
|
if (!code) {
|
|
292
|
-
throw new
|
|
311
|
+
throw new AIStreamEventError("No available data code for type: ".concat(type), AIStreamErrorCode.AIStreamError);
|
|
293
312
|
}
|
|
294
313
|
return code;
|
|
295
314
|
}
|
|
296
315
|
write(chunk) {
|
|
297
316
|
if (this.closed) {
|
|
298
|
-
throw new
|
|
317
|
+
throw new AIStreamEventError('Cannot write to a closed event', AIStreamErrorCode.AIStreamError);
|
|
299
318
|
}
|
|
300
319
|
const dataChannel = chunk.dataChannel || this.findFirstCode(chunk.type);
|
|
301
320
|
let promise = this.chains[dataChannel];
|
|
@@ -341,11 +360,11 @@ export class AIStreamEvent {
|
|
|
341
360
|
}
|
|
342
361
|
stream(source) {
|
|
343
362
|
if (this.closed) {
|
|
344
|
-
throw new
|
|
363
|
+
throw new AIStreamEventError('Cannot stream to a closed event', AIStreamErrorCode.AIStreamError);
|
|
345
364
|
}
|
|
346
365
|
const dataChannel = source.dataChannel || this.findFirstCode(source.type);
|
|
347
366
|
if (this.streams[dataChannel]) {
|
|
348
|
-
throw new
|
|
367
|
+
throw new AIStreamEventError("".concat(dataChannel, " stream already exists"), AIStreamErrorCode.AIStreamError);
|
|
349
368
|
}
|
|
350
369
|
const stream = {
|
|
351
370
|
dataChannel,
|
|
@@ -353,7 +372,7 @@ export class AIStreamEvent {
|
|
|
353
372
|
started: false,
|
|
354
373
|
start: async () => {
|
|
355
374
|
if (this.closed) {
|
|
356
|
-
throw new
|
|
375
|
+
throw new AIStreamEventError('Cannot stream to a closed event', AIStreamErrorCode.AIStreamError);
|
|
357
376
|
}
|
|
358
377
|
if (stream.started) {
|
|
359
378
|
return;
|
|
@@ -8,13 +8,18 @@ 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 { BizCode, EventType, ReceivedTextPacketEof, ReceivedTextPacketType, StreamFlag } from '../AIStreamTypes';
|
|
11
|
+
import { AIStreamErrorCode, BizCode, ConnectState, EventType, ReceivedTextPacketEof, ReceivedTextPacketType, SessionState, StreamFlag } from '../AIStreamTypes';
|
|
12
12
|
import AbortController from './abort';
|
|
13
|
+
import { tryCatch } from './misc';
|
|
13
14
|
function splitString(input) {
|
|
14
15
|
return input.match(/[a-zA-Z0-9]+\s*|[\u4e00-\u9fff]+\s*|[^\w\s\u4e00-\u9fff]+\s*|[\s]+/g) || [];
|
|
15
16
|
}
|
|
16
17
|
mock.data.set('sessionMap', new Map());
|
|
17
18
|
const getSession = (sessionId, eventId) => {
|
|
19
|
+
const connection = getCurrentConnection();
|
|
20
|
+
if (!connection) {
|
|
21
|
+
throw new Error('not connected');
|
|
22
|
+
}
|
|
18
23
|
const map = mock.data.get('sessionMap');
|
|
19
24
|
const session = map.get(sessionId);
|
|
20
25
|
if (!session) {
|
|
@@ -38,6 +43,21 @@ mock.hooks.hook('getMiniAppConfig', context => {
|
|
|
38
43
|
const getCurrentConnection = () => {
|
|
39
44
|
return mock.data.get('currentConnection');
|
|
40
45
|
};
|
|
46
|
+
mock.hooks.hook('isConnected', context => {
|
|
47
|
+
const connection = getCurrentConnection();
|
|
48
|
+
if (connection) {
|
|
49
|
+
context.result = {
|
|
50
|
+
connected: true,
|
|
51
|
+
state: ConnectState.CONNECTED,
|
|
52
|
+
connectionId: connection.connectionId
|
|
53
|
+
};
|
|
54
|
+
} else {
|
|
55
|
+
context.result = {
|
|
56
|
+
connected: false,
|
|
57
|
+
state: ConnectState.DISCONNECTED
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
});
|
|
41
61
|
mock.hooks.hook('connect', context => {
|
|
42
62
|
let connection = getCurrentConnection();
|
|
43
63
|
if (connection) {
|
|
@@ -82,14 +102,25 @@ const dispatch = (type, detail) => {
|
|
|
82
102
|
}));
|
|
83
103
|
};
|
|
84
104
|
mock.hooks.hook('createSession', context => {
|
|
105
|
+
const connection = getCurrentConnection();
|
|
106
|
+
if (!connection) {
|
|
107
|
+
throw new Error('not connected');
|
|
108
|
+
}
|
|
85
109
|
const map = mock.data.get('sessionMap');
|
|
86
110
|
const session = {
|
|
111
|
+
closed: false,
|
|
87
112
|
sessionId: generateId(),
|
|
88
113
|
sendDataChannels: ['audio', 'video', 'text', 'image'],
|
|
89
114
|
revDataChannels: ['text', 'audio'],
|
|
90
115
|
currentEvent: null,
|
|
91
116
|
replyText: function (streamFlag) {
|
|
92
117
|
let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
118
|
+
if (session.closed) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
if (!session.currentEvent) {
|
|
122
|
+
throw new Error('replyText event not exists');
|
|
123
|
+
}
|
|
93
124
|
dispatch('onTextReceived', {
|
|
94
125
|
dataChannel: 'text',
|
|
95
126
|
sessionIdList: [session.sessionId],
|
|
@@ -98,6 +129,9 @@ mock.hooks.hook('createSession', context => {
|
|
|
98
129
|
});
|
|
99
130
|
},
|
|
100
131
|
replyEvent: eventType => {
|
|
132
|
+
if (session.closed) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
101
135
|
if (!session.currentEvent) {
|
|
102
136
|
throw new Error('replyEvent event not exists');
|
|
103
137
|
}
|
|
@@ -115,13 +149,31 @@ mock.hooks.hook('createSession', context => {
|
|
|
115
149
|
revDataChannels: session.revDataChannels
|
|
116
150
|
};
|
|
117
151
|
|
|
152
|
+
// 用于测试断开连接;
|
|
118
153
|
// setTimeout(() => {
|
|
119
154
|
// dispatch('onConnectStateChanged', {
|
|
120
155
|
// connectionId: getCurrentConnection().connectionId,
|
|
121
156
|
// connectState: ConnectState.DISCONNECTED,
|
|
122
157
|
// code: 200,
|
|
123
158
|
// });
|
|
124
|
-
//
|
|
159
|
+
// mock.data.set('currentConnection', null);
|
|
160
|
+
// const map: Map<string, MockSession> = mock.data.get('sessionMap');
|
|
161
|
+
// map.forEach(s => {
|
|
162
|
+
// s.closed = true;
|
|
163
|
+
// });
|
|
164
|
+
// mock.data.set('sessionMap', new Map());
|
|
165
|
+
// }, 3000);
|
|
166
|
+
|
|
167
|
+
// 用于测试断开会话
|
|
168
|
+
// setTimeout(() => {
|
|
169
|
+
// dispatch('onSessionStateChanged', {
|
|
170
|
+
// sessionId: session.sessionId,
|
|
171
|
+
// sessionState: SessionState.CREATE_FAILED,
|
|
172
|
+
// code: 200,
|
|
173
|
+
// });
|
|
174
|
+
// session.closed = true;
|
|
175
|
+
// map.delete(session.sessionId);
|
|
176
|
+
// }, 3000);
|
|
125
177
|
});
|
|
126
178
|
mock.hooks.hook('closeSession', context => {
|
|
127
179
|
const map = mock.data.get('sessionMap');
|
|
@@ -172,7 +224,18 @@ mock.hooks.hook('sendEventEnd', context => {
|
|
|
172
224
|
data: event.data,
|
|
173
225
|
responseText: ''
|
|
174
226
|
};
|
|
175
|
-
await mock.hooks.callHook('sendToAIStream', ctx);
|
|
227
|
+
const [error] = await tryCatch(() => mock.hooks.callHook('sendToAIStream', ctx));
|
|
228
|
+
if (error) {
|
|
229
|
+
dispatch('onSessionStateChanged', {
|
|
230
|
+
sessionId: session.sessionId,
|
|
231
|
+
sessionState: SessionState.CLOSED,
|
|
232
|
+
code: AIStreamErrorCode.InternalServerError
|
|
233
|
+
});
|
|
234
|
+
session.closed = true;
|
|
235
|
+
const map = mock.data.get('sessionMap');
|
|
236
|
+
map.delete(session.sessionId);
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
176
239
|
const text = ctx.responseText || '⚠️ No mock text response matched!';
|
|
177
240
|
const words = splitString(text);
|
|
178
241
|
if (event.controller.signal.aborted) {
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export declare class BaseError extends Error {
|
|
2
|
+
message: string;
|
|
3
|
+
code: string | number;
|
|
4
|
+
constructor(message: string, code: string | number);
|
|
5
|
+
toString(): string;
|
|
6
|
+
}
|
|
7
|
+
export declare class TTTError extends BaseError {
|
|
8
|
+
message: string;
|
|
9
|
+
code: string | number;
|
|
10
|
+
constructor(message: string, code: string | number);
|
|
11
|
+
}
|
|
12
|
+
export declare class AIStreamConnectionError extends BaseError {
|
|
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 {
|
|
23
|
+
message: string;
|
|
24
|
+
code: string | number;
|
|
25
|
+
constructor(message: string, code: string | number);
|
|
26
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export class BaseError extends Error {
|
|
2
|
+
constructor(message, code) {
|
|
3
|
+
super(message);
|
|
4
|
+
this.message = message;
|
|
5
|
+
this.code = code;
|
|
6
|
+
}
|
|
7
|
+
toString() {
|
|
8
|
+
return "".concat(this.name, "(").concat(this.code, "): ").concat(this.message);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export class TTTError extends BaseError {
|
|
12
|
+
constructor(message, code) {
|
|
13
|
+
super(message, code);
|
|
14
|
+
this.message = message;
|
|
15
|
+
this.code = code;
|
|
16
|
+
this.name = 'TTTError';
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export class AIStreamConnectionError extends BaseError {
|
|
20
|
+
constructor(message, code) {
|
|
21
|
+
super(message, code);
|
|
22
|
+
this.message = message;
|
|
23
|
+
this.code = code;
|
|
24
|
+
this.name = 'AIStreamConnectionError';
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export class AIStreamSessionError extends BaseError {
|
|
28
|
+
constructor(message, code) {
|
|
29
|
+
super(message, code);
|
|
30
|
+
this.message = message;
|
|
31
|
+
this.code = code;
|
|
32
|
+
this.name = 'AIStreamSessionError';
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export class AIStreamEventError extends BaseError {
|
|
36
|
+
constructor(message, code) {
|
|
37
|
+
super(message, code);
|
|
38
|
+
this.message = message;
|
|
39
|
+
this.code = code;
|
|
40
|
+
this.name = 'AIStreamEventError';
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -11,12 +11,6 @@ interface AsyncTTTFnParams<P> {
|
|
|
11
11
|
}) => void;
|
|
12
12
|
[key: string]: any;
|
|
13
13
|
}
|
|
14
|
-
export declare class TTTError extends Error {
|
|
15
|
-
message: string;
|
|
16
|
-
errorCode: string | number;
|
|
17
|
-
constructor(message: string, errorCode: string | number);
|
|
18
|
-
toString(): string;
|
|
19
|
-
}
|
|
20
14
|
export declare const getEnableMock: () => boolean;
|
|
21
15
|
export declare const setEnableMock: (enable: boolean) => boolean;
|
|
22
16
|
export declare function promisify<T extends AsyncTTTFnParams<any>>(fn: (options: any) => void, enableMock?: boolean): (options?: Omit<T, 'success' | 'fail'>) => Promise<Parameters<NonNullable<T["success"]>>[0]>;
|
package/dist/utils/promisify.js
CHANGED
|
@@ -2,16 +2,7 @@ import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
|
|
|
2
2
|
import { isDevTools } from './ttt';
|
|
3
3
|
import logger from './logger';
|
|
4
4
|
import { mock } from './mock';
|
|
5
|
-
|
|
6
|
-
constructor(message, errorCode) {
|
|
7
|
-
super(message);
|
|
8
|
-
this.message = message;
|
|
9
|
-
this.errorCode = errorCode;
|
|
10
|
-
}
|
|
11
|
-
toString() {
|
|
12
|
-
return "TTTError: ".concat(this.message, ", errorCode: ").concat(this.errorCode);
|
|
13
|
-
}
|
|
14
|
-
}
|
|
5
|
+
import { TTTError } from './errors';
|
|
15
6
|
let callId = 100000;
|
|
16
7
|
export const getEnableMock = () => {
|
|
17
8
|
try {
|
|
@@ -44,7 +35,7 @@ export function promisify(fn) {
|
|
|
44
35
|
return options => {
|
|
45
36
|
return new Promise((_resolve, _reject) => {
|
|
46
37
|
if (!fn) {
|
|
47
|
-
_reject(new Error('fn is not a function'));
|
|
38
|
+
_reject(new Error('promisify: fn is not a function'));
|
|
48
39
|
}
|
|
49
40
|
const id = callId++;
|
|
50
41
|
logger.debug("TTT call #".concat(id, " %c").concat(fn.name), 'background: blue; color: white', options);
|
|
@@ -11,10 +11,6 @@ export declare class AIStreamSessionError extends Error {
|
|
|
11
11
|
readonly code: number;
|
|
12
12
|
constructor(message: string, code: number);
|
|
13
13
|
}
|
|
14
|
-
export declare class AIStreamConnectionError extends Error {
|
|
15
|
-
readonly code: number;
|
|
16
|
-
constructor(message: string, code: number);
|
|
17
|
-
}
|
|
18
14
|
export declare function sendBlocksToAIStream(params: SendBlocksToAIStreamParams): {
|
|
19
15
|
response: StreamResponse;
|
|
20
16
|
metaPromise: Promise<Record<string, any>>;
|
|
@@ -6,6 +6,7 @@ import { ReadableStream } from 'web-streams-polyfill';
|
|
|
6
6
|
import { AIStreamAttributePayloadType, AIStreamAttributeType, AIStreamChatSysWorkflow, ConnectState, FileFormat, ReceivedTextPacketEof, ReceivedTextPacketType, SessionState, StreamFlag } from '../AIStreamTypes';
|
|
7
7
|
import { EmitterEvent, generateId, safeParseJSON, StreamResponse } from '@ray-js/t-agent';
|
|
8
8
|
import { tryCatch } from './misc';
|
|
9
|
+
import { AIStreamConnectionError } from './errors';
|
|
9
10
|
const mimeTypeToFormatMap = {
|
|
10
11
|
'video/mp4': FileFormat.MP4,
|
|
11
12
|
'text/json': FileFormat.JSON,
|
|
@@ -19,13 +20,6 @@ export class AIStreamSessionError extends Error {
|
|
|
19
20
|
this.code = code;
|
|
20
21
|
}
|
|
21
22
|
}
|
|
22
|
-
export class AIStreamConnectionError extends Error {
|
|
23
|
-
constructor(message, code) {
|
|
24
|
-
super(message);
|
|
25
|
-
this.name = 'AIStreamConnectionError';
|
|
26
|
-
this.code = code;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
23
|
export function sendBlocksToAIStream(params) {
|
|
30
24
|
const {
|
|
31
25
|
session,
|
|
@@ -48,6 +42,7 @@ export function sendBlocksToAIStream(params) {
|
|
|
48
42
|
'sys.workflow': audioEmitter ? AIStreamChatSysWorkflow.ASR_LLM : AIStreamChatSysWorkflow.LLM
|
|
49
43
|
}, params.attribute);
|
|
50
44
|
let canceled = false;
|
|
45
|
+
let closed = false;
|
|
51
46
|
let event = null;
|
|
52
47
|
let metaResolve;
|
|
53
48
|
const metaPromise = new Promise(resolve => {
|
|
@@ -56,7 +51,7 @@ export function sendBlocksToAIStream(params) {
|
|
|
56
51
|
const stream = new ReadableStream({
|
|
57
52
|
async start(controller) {
|
|
58
53
|
const enqueue = part => {
|
|
59
|
-
if (canceled) {
|
|
54
|
+
if (canceled || closed) {
|
|
60
55
|
return;
|
|
61
56
|
}
|
|
62
57
|
controller.enqueue(part);
|
|
@@ -71,6 +66,7 @@ export function sendBlocksToAIStream(params) {
|
|
|
71
66
|
}));
|
|
72
67
|
if (error) {
|
|
73
68
|
controller.error(error);
|
|
69
|
+
closed = true;
|
|
74
70
|
controller.close();
|
|
75
71
|
return;
|
|
76
72
|
}
|
|
@@ -155,7 +151,7 @@ export function sendBlocksToAIStream(params) {
|
|
|
155
151
|
audioId = null;
|
|
156
152
|
}
|
|
157
153
|
} else if (data.type === 'sessionState') {
|
|
158
|
-
if (data.body.sessionState === SessionState.CLOSED) {
|
|
154
|
+
if (data.body.sessionState === SessionState.CLOSED || data.body.sessionState === SessionState.CREATE_FAILED) {
|
|
159
155
|
enqueue({
|
|
160
156
|
type: 'error',
|
|
161
157
|
error: new AIStreamSessionError('Session closed', data.body.code),
|
|
@@ -164,7 +160,7 @@ export function sendBlocksToAIStream(params) {
|
|
|
164
160
|
});
|
|
165
161
|
}
|
|
166
162
|
} else if (data.type === 'connectionState') {
|
|
167
|
-
if (data.body.connectState === ConnectState.DISCONNECTED) {
|
|
163
|
+
if (data.body.connectState === ConnectState.DISCONNECTED || data.body.connectState === ConnectState.CLOSED) {
|
|
168
164
|
enqueue({
|
|
169
165
|
type: 'error',
|
|
170
166
|
error: new AIStreamConnectionError('Connection disconnected', data.body.code),
|
|
@@ -174,8 +170,15 @@ export function sendBlocksToAIStream(params) {
|
|
|
174
170
|
}
|
|
175
171
|
}
|
|
176
172
|
});
|
|
173
|
+
event.on('close', () => {
|
|
174
|
+
if (!canceled && !closed) {
|
|
175
|
+
// 当取消后,不需要关闭控制器
|
|
176
|
+
controller.close();
|
|
177
|
+
}
|
|
178
|
+
});
|
|
177
179
|
event.on('finish', () => {
|
|
178
180
|
if (!canceled) {
|
|
181
|
+
closed = true;
|
|
179
182
|
// 当取消后,不需要关闭控制器
|
|
180
183
|
controller.close();
|
|
181
184
|
}
|
package/dist/utils/ttt.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ApiRequestByAtopParams, ApiRequestByHighwayParams, AudioBody, AuthorizeParams, AuthorizePolicyStatusParams, CanIUseRouterParams,
|
|
1
|
+
import { ApiRequestByAtopParams, ApiRequestByHighwayParams, AudioBody, AuthorizeParams, AuthorizePolicyStatusParams, CanIUseRouterParams, CloseSessionParams, ConnectParams, ConnectStateBody, CreateSessionParams, DeleteRecordListParams, DisconnectParams, EventBody, EventChannelMessageParams, GetAppInfoParams, GetCurrentHomeInfoParams, GetMiniAppConfigParams, GetAccountInfoParams, ImageBody, InsertRecordParams, NavigateToMiniProgramParams, OpenInnerH5Params, OpenMiniWidgetParams, QueryAgentTokenParams, QueryRecordListParams, RecordAmplitudesBody, RegisterChannelParams, RouterParams, SendEventChatBreakParams, SendEventEndParams, SendEventPayloadEndParams, SendEventStartParams, SendImageDataParams, SendTextDataParams, SessionStateBody, StartRecordAndSendAudioDataParams, StopRecordAndSendAudioDataParams, TextBody, UpdateRecordParams, IsConnectedParams } from '../AIStreamTypes';
|
|
2
2
|
export declare const getMiniAppConfig: (options?: Omit<GetMiniAppConfigParams, "success" | "fail"> | undefined) => Promise<{
|
|
3
3
|
config: any;
|
|
4
4
|
}>;
|
|
@@ -52,7 +52,11 @@ export declare const authorizePolicyStatus: (options?: Omit<AuthorizePolicyStatu
|
|
|
52
52
|
export declare const registerChannel: (options?: Omit<RegisterChannelParams, "success" | "fail"> | undefined) => Promise<null>;
|
|
53
53
|
export declare const listenReceiveMessage: (listener: (params: EventChannelMessageParams) => void) => () => void;
|
|
54
54
|
export declare const openMiniWidget: (options?: Omit<OpenMiniWidgetParams, "success" | "fail"> | undefined) => Promise<null>;
|
|
55
|
-
export declare const
|
|
55
|
+
export declare const isConnected: (options?: Omit<IsConnectedParams, "success" | "fail"> | undefined) => Promise<{
|
|
56
|
+
connected: boolean;
|
|
57
|
+
state: number;
|
|
58
|
+
connectionId?: string | undefined;
|
|
59
|
+
}>;
|
|
56
60
|
export declare const connect: (options?: Omit<ConnectParams, "success" | "fail"> | undefined) => Promise<{
|
|
57
61
|
connectionId: string;
|
|
58
62
|
}>;
|
package/dist/utils/ttt.js
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { listening, promisify } from './promisify';
|
|
2
|
-
import { ConnectClientType, ConnectState } from '../AIStreamTypes';
|
|
3
|
-
import { generateId } from '@ray-js/t-agent';
|
|
4
2
|
export const getMiniAppConfig = promisify(ty.getMiniAppConfig, true);
|
|
5
3
|
export const getAccountInfo = promisify(ty.getAccountInfo);
|
|
6
4
|
export const isDevTools = () => {
|
|
@@ -30,17 +28,7 @@ ty.authorizePolicyStatus);
|
|
|
30
28
|
export const registerChannel = promisify(ty.registerChannel);
|
|
31
29
|
export const listenReceiveMessage = listening(ty.onReceiveMessage, ty.offReceiveMessage);
|
|
32
30
|
export const openMiniWidget = promisify(ty.openMiniWidget);
|
|
33
|
-
export const
|
|
34
|
-
if (isDevTools()) {
|
|
35
|
-
return {
|
|
36
|
-
connected: true,
|
|
37
|
-
state: ConnectState.CONNECTED,
|
|
38
|
-
connectionId: generateId(),
|
|
39
|
-
clientType: ConnectClientType.APP
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
return ty.aistream.isConnectedSync(params);
|
|
43
|
-
};
|
|
31
|
+
export const isConnected = promisify(ty.aistream.isConnected, true);
|
|
44
32
|
export const connect = promisify(ty.aistream.connect, true);
|
|
45
33
|
export const disconnect = promisify(ty.aistream.disconnect, true);
|
|
46
34
|
export const queryAgentToken = promisify(ty.aistream.queryAgentToken, true);
|
package/dist/withAIStream.js
CHANGED
|
@@ -5,7 +5,6 @@ import "core-js/modules/es.array.flat.js";
|
|
|
5
5
|
import "core-js/modules/es.array.reverse.js";
|
|
6
6
|
import "core-js/modules/es.array.unscopables.flat.js";
|
|
7
7
|
import "core-js/modules/esnext.iterator.constructor.js";
|
|
8
|
-
import "core-js/modules/esnext.iterator.for-each.js";
|
|
9
8
|
import "core-js/modules/esnext.iterator.map.js";
|
|
10
9
|
import "core-js/modules/web.dom-collections.iterator.js";
|
|
11
10
|
import { BubbleTileStatus, ChatMessageStatus, createHooks } from '@ray-js/t-agent';
|
|
@@ -449,9 +448,7 @@ export function withAIStream() {
|
|
|
449
448
|
clearAllMessages: async () => {
|
|
450
449
|
// 删除内存中的消息
|
|
451
450
|
const messages = agent.session.messages.values();
|
|
452
|
-
Array.from(messages).
|
|
453
|
-
message.remove();
|
|
454
|
-
});
|
|
451
|
+
await Promise.all(Array.from(messages).map(message => message.remove()));
|
|
455
452
|
// 清空缓存的数据
|
|
456
453
|
const historyStore = getHistoryStore();
|
|
457
454
|
if (historyStore) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ray-js/t-agent-plugin-aistream",
|
|
3
|
-
"version": "0.2.0-beta-
|
|
3
|
+
"version": "0.2.0-beta-6",
|
|
4
4
|
"author": "Tuya.inc",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"private": false,
|
|
@@ -35,5 +35,5 @@
|
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@types/url-parse": "^1.4.11"
|
|
37
37
|
},
|
|
38
|
-
"gitHead": "
|
|
38
|
+
"gitHead": "a09b74682949c5860f34105b4a5f8f60fc34a582"
|
|
39
39
|
}
|