@ray-js/t-agent-plugin-aistream 0.2.7-beta.9 → 0.2.8-beta.1
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/README-zh_CN.md +286 -95
- package/dist/AIStreamTypes.d.ts +41 -3
- package/dist/AIStreamTypes.js +6 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -1
- package/dist/mcp/McpServer.d.ts +11 -0
- package/dist/mcp/McpServer.js +162 -0
- package/dist/mcp/index.d.ts +3 -0
- package/dist/mcp/index.js +3 -0
- package/dist/mcp/types.d.ts +114 -0
- package/dist/mcp/types.js +1 -0
- package/dist/mcp/withMCP.d.ts +15 -0
- package/dist/mcp/withMCP.js +98 -0
- package/dist/utils/AIStream.d.ts +14 -1
- package/dist/utils/AIStream.js +60 -10
- package/dist/utils/defaultMock.js +285 -79
- package/dist/utils/mock.d.ts +14 -0
- package/dist/utils/object.d.ts +0 -1
- package/dist/utils/object.js +1 -24
- package/dist/utils/observer.d.ts +6 -2
- package/dist/utils/observer.js +17 -6
- package/dist/utils/sendMessage.js +48 -15
- package/dist/utils/track.js +2 -2
- package/dist/utils/ttt.d.ts +3 -2
- package/dist/utils/ttt.js +2 -1
- package/dist/withAIStream.d.ts +4 -1
- package/dist/withAIStream.js +66 -17
- package/package.json +2 -2
|
@@ -7,7 +7,7 @@ import { EmitterEvent, generateId, safeParseJSON, StreamResponse } from '@ray-js
|
|
|
7
7
|
import { tryCatch } from './misc';
|
|
8
8
|
import { AIStreamError, transformErrorCode } from './errors';
|
|
9
9
|
import logger from './logger';
|
|
10
|
-
import {
|
|
10
|
+
import { deepmerge } from '@ray-js/t-agent';
|
|
11
11
|
const mimeTypeToFormatMap = {
|
|
12
12
|
'video/mp4': FileFormat.MP4,
|
|
13
13
|
'text/json': FileFormat.JSON,
|
|
@@ -42,6 +42,7 @@ export function sendBlocksToAIStream(params) {
|
|
|
42
42
|
});
|
|
43
43
|
const stream = new ReadableStream({
|
|
44
44
|
async start(controller) {
|
|
45
|
+
var _cleanupPreEventListe2;
|
|
45
46
|
const enqueue = part => {
|
|
46
47
|
if (signal !== null && signal !== void 0 && signal.aborted || canceled || closed) {
|
|
47
48
|
return;
|
|
@@ -84,22 +85,28 @@ export function sendBlocksToAIStream(params) {
|
|
|
84
85
|
});
|
|
85
86
|
};
|
|
86
87
|
let pendingCancel = false;
|
|
88
|
+
// phase-1: 事件创建前监听 confirm/cancel,用于捕获"边界竞态"时的取消意图
|
|
89
|
+
// 使用具名函数以便在 startEvent 后统一解绑,避免监听器残留在 audioEmitter 上
|
|
90
|
+
let cleanupPreEventListeners;
|
|
87
91
|
if (audioEmitter) {
|
|
88
|
-
|
|
89
|
-
// 在确认发送时,如果事件还没创建,则取消发送
|
|
92
|
+
const onPreEventConfirm = () => {
|
|
90
93
|
if (!event) {
|
|
91
94
|
logger.debug('sendBlocksToAIStream audioEmitter confirm before event start');
|
|
92
|
-
// event 留到后面再关
|
|
93
95
|
pendingCancel = true;
|
|
94
96
|
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
+
};
|
|
98
|
+
const onPreEventCancel = () => {
|
|
97
99
|
if (!event) {
|
|
98
100
|
logger.debug('sendBlocksToAIStream audioEmitter cancel before event start');
|
|
99
|
-
// event 留到后面再关
|
|
100
101
|
pendingCancel = true;
|
|
101
102
|
}
|
|
102
|
-
}
|
|
103
|
+
};
|
|
104
|
+
audioEmitter.addEventListener('confirm', onPreEventConfirm);
|
|
105
|
+
audioEmitter.addEventListener('cancel', onPreEventCancel);
|
|
106
|
+
cleanupPreEventListeners = () => {
|
|
107
|
+
audioEmitter.removeEventListener('confirm', onPreEventConfirm);
|
|
108
|
+
audioEmitter.removeEventListener('cancel', onPreEventCancel);
|
|
109
|
+
};
|
|
103
110
|
}
|
|
104
111
|
const chatAttributes = {
|
|
105
112
|
'processing.interrupt': 'false',
|
|
@@ -109,7 +116,7 @@ export function sendBlocksToAIStream(params) {
|
|
|
109
116
|
if (getUserData) {
|
|
110
117
|
eventUserData = await getUserData();
|
|
111
118
|
}
|
|
112
|
-
const userData =
|
|
119
|
+
const userData = deepmerge({
|
|
113
120
|
chatAttributes
|
|
114
121
|
}, eventUserData);
|
|
115
122
|
let error;
|
|
@@ -124,7 +131,10 @@ export function sendBlocksToAIStream(params) {
|
|
|
124
131
|
}]
|
|
125
132
|
}));
|
|
126
133
|
if (error) {
|
|
134
|
+
var _cleanupPreEventListe;
|
|
127
135
|
emitError(error);
|
|
136
|
+
// startEvent 失败,phase-1 监听已无用,立即解绑
|
|
137
|
+
(_cleanupPreEventListe = cleanupPreEventListeners) === null || _cleanupPreEventListe === void 0 || _cleanupPreEventListe();
|
|
128
138
|
if (audioEmitter) {
|
|
129
139
|
audioEmitter.dispatchEvent(new EmitterEvent('error', {
|
|
130
140
|
detail: error
|
|
@@ -133,6 +143,9 @@ export function sendBlocksToAIStream(params) {
|
|
|
133
143
|
close();
|
|
134
144
|
return;
|
|
135
145
|
}
|
|
146
|
+
|
|
147
|
+
// startEvent 已成功(event 已创建),phase-1 监听完成使命,解绑
|
|
148
|
+
(_cleanupPreEventListe2 = cleanupPreEventListeners) === null || _cleanupPreEventListe2 === void 0 || _cleanupPreEventListe2();
|
|
136
149
|
if (signal !== null && signal !== void 0 && signal.aborted || pendingCancel) {
|
|
137
150
|
logger.debug('sendBlocksToAIStream pendingCancel aborted');
|
|
138
151
|
abort();
|
|
@@ -306,20 +319,40 @@ export function sendBlocksToAIStream(params) {
|
|
|
306
319
|
const s = event.stream({
|
|
307
320
|
type: 'audio'
|
|
308
321
|
});
|
|
309
|
-
|
|
322
|
+
let audioDone = false;
|
|
323
|
+
|
|
324
|
+
// cleanupPostEventListeners 先初始化为 noop,让两个 handler 可在闭包里安全引用
|
|
325
|
+
// 后面赋值为真正的清理函数
|
|
326
|
+
let cleanupPostEventListeners = () => {};
|
|
327
|
+
const onPostEventConfirm = async () => {
|
|
328
|
+
// 任一监听触发后,立即同时解绑两者,防止另一个因偶发二次触发产生副作用
|
|
329
|
+
cleanupPostEventListeners();
|
|
310
330
|
if (!canceled) {
|
|
311
331
|
await s.stop();
|
|
312
332
|
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
333
|
+
if (!audioDone) {
|
|
334
|
+
audioDone = true;
|
|
335
|
+
resolve();
|
|
336
|
+
}
|
|
337
|
+
};
|
|
338
|
+
const onPostEventCancel = async () => {
|
|
339
|
+
cleanupPostEventListeners();
|
|
316
340
|
if (!canceled) {
|
|
317
341
|
await s.stop();
|
|
318
342
|
}
|
|
319
343
|
logger.debug('sendBlocksToAIStream audio cancel aborted');
|
|
320
344
|
abort();
|
|
321
|
-
|
|
322
|
-
|
|
345
|
+
if (!audioDone) {
|
|
346
|
+
audioDone = true;
|
|
347
|
+
resolve();
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
cleanupPostEventListeners = () => {
|
|
351
|
+
audioEmitter.removeEventListener('confirm', onPostEventConfirm);
|
|
352
|
+
audioEmitter.removeEventListener('cancel', onPostEventCancel);
|
|
353
|
+
};
|
|
354
|
+
audioEmitter.addEventListener('confirm', onPostEventConfirm);
|
|
355
|
+
audioEmitter.addEventListener('cancel', onPostEventCancel);
|
|
323
356
|
s.start();
|
|
324
357
|
});
|
|
325
358
|
if (signal !== null && signal !== void 0 && signal.aborted) {
|
package/dist/utils/track.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "core-js/modules/es.json.stringify.js";
|
|
2
|
-
import { getAccountInfo,
|
|
2
|
+
import { getAccountInfo, sendTrackEvent } from './ttt';
|
|
3
3
|
const eventId = 'thing_jKaquNvaV2qMDvTpKcNQvb1ZppBZnlNq';
|
|
4
4
|
let accountInfoPromise = null;
|
|
5
5
|
export async function trackEvent(agent_code, type) {
|
|
@@ -11,7 +11,7 @@ export async function trackEvent(agent_code, type) {
|
|
|
11
11
|
miniProgram
|
|
12
12
|
} = await accountInfoPromise;
|
|
13
13
|
try {
|
|
14
|
-
await
|
|
14
|
+
await sendTrackEvent({
|
|
15
15
|
eventId,
|
|
16
16
|
event: {
|
|
17
17
|
type,
|
package/dist/utils/ttt.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
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, GetNetworkTypeParams, StartPlayAudioParams, InitAudioRecorderParams, StopPlayAudioParams, AudioPlayChangedBody, EventParams } from '../AIStreamTypes';
|
|
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, SendAIStreamEventParams, SendEventChatBreakParams, SendEventEndParams, SendEventPayloadEndParams, SendEventStartParams, SendImageDataParams, SendTextDataParams, SessionStateBody, StartRecordAndSendAudioDataParams, StopRecordAndSendAudioDataParams, TextBody, UpdateRecordParams, IsConnectedParams, GetNetworkTypeParams, StartPlayAudioParams, InitAudioRecorderParams, StopPlayAudioParams, AudioPlayChangedBody, EventParams } from '../AIStreamTypes';
|
|
2
2
|
export declare const getMiniAppConfig: (options?: Omit<GetMiniAppConfigParams, "success" | "fail"> | undefined) => Promise<{
|
|
3
3
|
config: any;
|
|
4
4
|
}>;
|
|
@@ -81,6 +81,7 @@ export declare const sendEventStart: (options?: Omit<SendEventStartParams, "succ
|
|
|
81
81
|
export declare const sendEventPayloadEnd: (options?: Omit<SendEventPayloadEndParams, "success" | "fail"> | undefined) => Promise<null>;
|
|
82
82
|
export declare const sendEventEnd: (options?: Omit<SendEventEndParams, "success" | "fail"> | undefined) => Promise<null>;
|
|
83
83
|
export declare const sendEventChatBreak: (options?: Omit<SendEventChatBreakParams, "success" | "fail"> | undefined) => Promise<null>;
|
|
84
|
+
export declare const sendEventToAIStream: (options?: Omit<SendAIStreamEventParams, "success" | "fail"> | undefined) => Promise<null>;
|
|
84
85
|
export declare const startRecordAndSendAudioData: (options?: Omit<StartRecordAndSendAudioDataParams, "success" | "fail"> | undefined) => Promise<null>;
|
|
85
86
|
export declare const stopRecordAndSendAudioData: (options?: Omit<StopRecordAndSendAudioDataParams, "success" | "fail"> | undefined) => Promise<import("../AIStreamTypes").AIStreamAudioFile | null>;
|
|
86
87
|
export declare const sendImageData: (options?: Omit<SendImageDataParams, "success" | "fail"> | undefined) => Promise<null>;
|
|
@@ -113,4 +114,4 @@ export declare const getNetworkType: (options?: Omit<GetNetworkTypeParams, "succ
|
|
|
113
114
|
networkType: import("../AIStreamTypes").NetworkType;
|
|
114
115
|
signalStrength: number;
|
|
115
116
|
}>;
|
|
116
|
-
export declare const
|
|
117
|
+
export declare const sendTrackEvent: (options?: Omit<EventParams, "success" | "fail"> | undefined) => Promise<null>;
|
package/dist/utils/ttt.js
CHANGED
|
@@ -42,6 +42,7 @@ export const sendEventStart = promisify(ty.aistream.sendEventStart, true);
|
|
|
42
42
|
export const sendEventPayloadEnd = promisify(ty.aistream.sendEventPayloadEnd, true);
|
|
43
43
|
export const sendEventEnd = promisify(ty.aistream.sendEventEnd, true);
|
|
44
44
|
export const sendEventChatBreak = promisify(ty.aistream.sendEventChatBreak, true);
|
|
45
|
+
export const sendEventToAIStream = promisify(ty.aistream.sendEvent, true);
|
|
45
46
|
export const startRecordAndSendAudioData = promisify(ty.aistream.startRecordAndSendAudioData, true);
|
|
46
47
|
export const stopRecordAndSendAudioData = promisify(ty.aistream.stopRecordAndSendAudioData, true);
|
|
47
48
|
|
|
@@ -92,4 +93,4 @@ export const deleteRecordList = promisify(ty.aistream.deleteRecordList, true);
|
|
|
92
93
|
export const updateRecord = promisify(ty.aistream.updateRecord, true);
|
|
93
94
|
export const insertRecord = promisify(ty.aistream.insertRecord, true);
|
|
94
95
|
export const getNetworkType = promisify(ty.getNetworkType, true);
|
|
95
|
-
export const
|
|
96
|
+
export const sendTrackEvent = promisify(ty.event);
|
package/dist/withAIStream.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AbortSignalObject, ChatAgent, ChatCardObject, ChatMessage, ChatMessageStatus, ChatTile, GetChatPluginHandler, InputBlock } from '@ray-js/t-agent';
|
|
2
2
|
import { TTTAction } from './utils';
|
|
3
|
-
import { AIStreamUserData, ConnectClientType, ReceivedTextSkillPacketBody } from './AIStreamTypes';
|
|
3
|
+
import { AIStreamUserData, ConnectClientType, ReceivedTextSkillPacketBody, SendAIStreamEventParams, SessionEventBody } from './AIStreamTypes';
|
|
4
4
|
import { ChatHistoryStore, StoredMessageObject } from './ChatHistoryStore';
|
|
5
5
|
export interface AIStreamOptions {
|
|
6
6
|
/** client 类型: 1-作为设备代理, 2-作为 App,3-作为开发者(行业 App) */
|
|
@@ -63,6 +63,7 @@ export interface AIStreamHooks {
|
|
|
63
63
|
}, result: {
|
|
64
64
|
userData: AIStreamUserData;
|
|
65
65
|
}) => void;
|
|
66
|
+
onSessionEventReceived: (event: SessionEventBody) => void;
|
|
66
67
|
}
|
|
67
68
|
export declare function withAIStream(options?: AIStreamOptions): (agent: ChatAgent) => {
|
|
68
69
|
hooks: import("hookable").Hookable<AIStreamHooks, import("hookable").HookKeys<AIStreamHooks>>;
|
|
@@ -92,6 +93,8 @@ export declare function withAIStream(options?: AIStreamOptions): (agent: ChatAge
|
|
|
92
93
|
onSkillsEnd: (fn: AIStreamHooks['onSkillsEnd']) => () => void;
|
|
93
94
|
onCardsReceived: (fn: AIStreamHooks['onCardsReceived']) => () => void;
|
|
94
95
|
onUserDataRead: (fn: AIStreamHooks['onUserDataRead']) => () => void;
|
|
96
|
+
onSessionEventReceived: (fn: AIStreamHooks['onSessionEventReceived']) => () => void;
|
|
97
|
+
sendEvent: (params: SendAIStreamEventParams) => Promise<null>;
|
|
95
98
|
onTTTAction: (fn: AIStreamHooks['onTTTAction']) => () => void;
|
|
96
99
|
getChatId: () => Promise<string>;
|
|
97
100
|
};
|
package/dist/withAIStream.js
CHANGED
|
@@ -1,20 +1,27 @@
|
|
|
1
1
|
import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
|
|
2
2
|
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
|
|
3
|
+
import _wrapAsyncGenerator from "@babel/runtime/helpers/esm/wrapAsyncGenerator";
|
|
4
|
+
import _awaitAsyncGenerator from "@babel/runtime/helpers/esm/awaitAsyncGenerator";
|
|
5
|
+
import _asyncGeneratorDelegate from "@babel/runtime/helpers/esm/asyncGeneratorDelegate";
|
|
3
6
|
const _excluded = ["message"];
|
|
7
|
+
import "core-js/modules/es.symbol.description.js";
|
|
8
|
+
import "core-js/modules/es.symbol.async-iterator.js";
|
|
4
9
|
import "core-js/modules/es.array.flat.js";
|
|
5
10
|
import "core-js/modules/es.array.reverse.js";
|
|
6
11
|
import "core-js/modules/es.array.unscopables.flat.js";
|
|
7
12
|
import "core-js/modules/esnext.iterator.constructor.js";
|
|
8
13
|
import "core-js/modules/esnext.iterator.map.js";
|
|
9
14
|
import "core-js/modules/web.dom-collections.iterator.js";
|
|
15
|
+
function _asyncIterator(r) { var n, t, o, e = 2; for ("undefined" != typeof Symbol && (t = Symbol.asyncIterator, o = Symbol.iterator); e--;) { if (t && null != (n = r[t])) return n.call(r); if (o && null != (n = r[o])) return new AsyncFromSyncIterator(n.call(r)); t = "@@asyncIterator", o = "@@iterator"; } throw new TypeError("Object is not async iterable"); }
|
|
16
|
+
function AsyncFromSyncIterator(r) { function AsyncFromSyncIteratorContinuation(r) { if (Object(r) !== r) return Promise.reject(new TypeError(r + " is not an object.")); var n = r.done; return Promise.resolve(r.value).then(function (r) { return { value: r, done: n }; }); } return AsyncFromSyncIterator = function (r) { this.s = r, this.n = r.next; }, AsyncFromSyncIterator.prototype = { s: null, n: null, next: function () { return AsyncFromSyncIteratorContinuation(this.n.apply(this.s, arguments)); }, return: function (r) { var n = this.s.return; return void 0 === n ? Promise.resolve({ value: r, done: !0 }) : AsyncFromSyncIteratorContinuation(n.apply(this.s, arguments)); }, throw: function (r) { var n = this.s.return; return void 0 === n ? Promise.reject(r) : AsyncFromSyncIteratorContinuation(n.apply(this.s, arguments)); } }, new AsyncFromSyncIterator(r); }
|
|
10
17
|
import { BubbleTileStatus, ChatMessageStatus, createHooks, EmitterEvent } from '@ray-js/t-agent';
|
|
11
18
|
import { messageAppraise } from './utils/apis';
|
|
12
|
-
import { getAccountInfo, getCurrentHomeInfo, runTTTAction, sendBlocksToAIStream } from './utils';
|
|
19
|
+
import { getAccountInfo, getCurrentHomeInfo, runTTTAction, sendBlocksToAIStream, sendEventToAIStream } from './utils';
|
|
13
20
|
import { BizCode, ConnectClientType } from './AIStreamTypes';
|
|
14
21
|
import { DEFAULT_TOKEN_API, DEFAULT_TOKEN_API_VERSION, globalAIStreamClient } from './global';
|
|
15
22
|
import logger from './utils/logger';
|
|
16
23
|
import { ChatHistoryLocalStore } from './ChatHistoryLocalStore';
|
|
17
|
-
import {
|
|
24
|
+
import { deepmerge } from '@ray-js/t-agent';
|
|
18
25
|
import { trackEvent } from './utils/track';
|
|
19
26
|
export function withAIStream() {
|
|
20
27
|
let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
@@ -103,6 +110,9 @@ export function withAIStream() {
|
|
|
103
110
|
return result.userData;
|
|
104
111
|
}
|
|
105
112
|
});
|
|
113
|
+
streamSession.on('sessionEvent', event => {
|
|
114
|
+
hooks.callHook('onSessionEventReceived', event);
|
|
115
|
+
});
|
|
106
116
|
await session.set('AIStream.streamSession', streamSession);
|
|
107
117
|
if (options.earlyStart) {
|
|
108
118
|
// 故意异步,不阻塞消息列表加载
|
|
@@ -248,19 +258,42 @@ export function withAIStream() {
|
|
|
248
258
|
await hooks.callHook('onUserDataRead', 'start-event', {
|
|
249
259
|
blocks
|
|
250
260
|
}, userDataResult);
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
deepMerge(userData, eventUserData);
|
|
261
|
+
let userData = deepmerge({}, userDataResult.userData);
|
|
262
|
+
userData = deepmerge(userData, eventUserData);
|
|
254
263
|
return userData;
|
|
255
264
|
}
|
|
256
265
|
});
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
result.response.
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
266
|
+
if (signal) {
|
|
267
|
+
const onAbort = event => {
|
|
268
|
+
logger.debug('withAIStream signal aborted, response.started:', result.response.started);
|
|
269
|
+
if (result.response.started) {
|
|
270
|
+
result.response.cancel(event.reason);
|
|
271
|
+
}
|
|
272
|
+
agent.hooks.callHook('onUserAbort', event.reason);
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
// once:true 保证 abort 触发后自动解绑,避免监听器残留
|
|
276
|
+
signal.addEventListener('abort', onAbort, {
|
|
277
|
+
once: true
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
// 正常消费流时(未触发 abort)在 parts() 的 finally 里解绑,防止 signal 长期持有闭包
|
|
281
|
+
const _parts = result.response.parts.bind(result.response);
|
|
282
|
+
result.response.parts = () => {
|
|
283
|
+
const iterable = _parts();
|
|
284
|
+
return {
|
|
285
|
+
[Symbol.asyncIterator]() {
|
|
286
|
+
return _wrapAsyncGenerator(function* () {
|
|
287
|
+
try {
|
|
288
|
+
yield* _asyncGeneratorDelegate(_asyncIterator(iterable), _awaitAsyncGenerator);
|
|
289
|
+
} finally {
|
|
290
|
+
signal.removeEventListener('abort', onAbort);
|
|
291
|
+
}
|
|
292
|
+
})();
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
};
|
|
296
|
+
}
|
|
264
297
|
signal === null || signal === void 0 || signal.throwIfAborted();
|
|
265
298
|
return result;
|
|
266
299
|
};
|
|
@@ -291,8 +324,18 @@ export function withAIStream() {
|
|
|
291
324
|
if (audioEmitter) {
|
|
292
325
|
let end = false;
|
|
293
326
|
audioPromise = new Promise((resolve, reject) => {
|
|
294
|
-
// 当确认发送时,展示 loading
|
|
295
327
|
let userMsgShow = false;
|
|
328
|
+
|
|
329
|
+
// onAbort 先定义,让后续终态处理器可引用它来解绑
|
|
330
|
+
const onAbort = () => {
|
|
331
|
+
logger.debug('withAIStream chat agent.chat audioEmitter onAbort');
|
|
332
|
+
audioEmitter.dispatchEvent(new EmitterEvent('cancel'));
|
|
333
|
+
};
|
|
334
|
+
// signal 可选:仅在传入时注册
|
|
335
|
+
signal === null || signal === void 0 || signal.addEventListener('abort', onAbort);
|
|
336
|
+
|
|
337
|
+
// 当确认发送时,展示 loading
|
|
338
|
+
|
|
296
339
|
audioEmitter.addEventListener('confirm', async () => {
|
|
297
340
|
logger.debug('withAIStream chat agent.chat audioEmitter onConfirm');
|
|
298
341
|
if (end) {
|
|
@@ -316,6 +359,8 @@ export function withAIStream() {
|
|
|
316
359
|
return;
|
|
317
360
|
}
|
|
318
361
|
end = true;
|
|
362
|
+
// 终态:解绑 signal 上的 abort 监听,避免 signal 长期持有本轮闭包
|
|
363
|
+
signal === null || signal === void 0 || signal.removeEventListener('abort', onAbort);
|
|
319
364
|
if (!event.detail.text && userMsgShow) {
|
|
320
365
|
await userMsg.remove();
|
|
321
366
|
reject(new Error('No text found in audio event'));
|
|
@@ -335,6 +380,8 @@ export function withAIStream() {
|
|
|
335
380
|
audioEmitter.addEventListener('cancel', async () => {
|
|
336
381
|
logger.debug('withAIStream chat agent.chat audioEmitter onCancel');
|
|
337
382
|
end = true;
|
|
383
|
+
// 终态:解绑 signal 上的 abort 监听
|
|
384
|
+
signal === null || signal === void 0 || signal.removeEventListener('abort', onAbort);
|
|
338
385
|
// 取消时,有可能 userMsg.persist 还在执行,所以这里不 await,先 reject
|
|
339
386
|
reject(new Error('User cancel'));
|
|
340
387
|
if (!response.started && userMsgShow) {
|
|
@@ -343,13 +390,11 @@ export function withAIStream() {
|
|
|
343
390
|
}, {
|
|
344
391
|
once: true
|
|
345
392
|
});
|
|
346
|
-
signal.addEventListener('abort', () => {
|
|
347
|
-
logger.debug('withAIStream chat agent.chat audioEmitter onAbort');
|
|
348
|
-
audioEmitter.dispatchEvent(new EmitterEvent('cancel'));
|
|
349
|
-
});
|
|
350
393
|
audioEmitter.addEventListener('error', async () => {
|
|
351
394
|
logger.debug('withAIStream chat agent.chat audioEmitter onError');
|
|
352
395
|
end = true;
|
|
396
|
+
// 终态:解绑 signal 上的 abort 监听
|
|
397
|
+
signal === null || signal === void 0 || signal.removeEventListener('abort', onAbort);
|
|
353
398
|
reject(new Error('Audio emitter error'));
|
|
354
399
|
if (userMsgShow && userMsg.status !== ChatMessageStatus.FINISH) {
|
|
355
400
|
await userMsg.remove();
|
|
@@ -616,6 +661,10 @@ export function withAIStream() {
|
|
|
616
661
|
onUserDataRead: fn => {
|
|
617
662
|
return hooks.hook('onUserDataRead', fn);
|
|
618
663
|
},
|
|
664
|
+
onSessionEventReceived: fn => {
|
|
665
|
+
return hooks.hook('onSessionEventReceived', fn);
|
|
666
|
+
},
|
|
667
|
+
sendEvent: params => sendEventToAIStream(params),
|
|
619
668
|
onTTTAction: fn => {
|
|
620
669
|
return hooks.hook('onTTTAction', fn);
|
|
621
670
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ray-js/t-agent-plugin-aistream",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.8-beta.1",
|
|
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": "040499ca11aedda3246121f880807da0f8af3cc9"
|
|
39
39
|
}
|