@blueking/chat-helper 0.0.12-beta.1 → 0.0.12-beta.11
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/agent/use-agent.d.ts +1278 -4
- package/dist/agent/use-agent.ts.js +341 -23
- package/dist/event/ag-ui.d.ts +15 -2
- package/dist/event/ag-ui.ts.js +82 -7
- package/dist/event/type.d.ts +90 -24
- package/dist/event/type.ts.js +44 -16
- package/dist/http/fetch/fetch.d.ts +20 -0
- package/dist/http/fetch/fetch.ts.js +67 -18
- package/dist/http/index.d.ts +14 -3
- package/dist/http/index.ts.js +2 -1
- package/dist/http/module/index.d.ts +12 -3
- package/dist/http/module/message.d.ts +6 -3
- package/dist/http/module/message.ts.js +18 -1
- package/dist/http/module/session.d.ts +8 -2
- package/dist/http/module/session.ts.js +47 -8
- package/dist/http/transform/message.ts.js +10 -0
- package/dist/index.d.ts +8868 -18
- package/dist/index.ts.js +2 -1
- package/dist/message/type.d.ts +26 -5
- package/dist/message/type.ts.js +8 -0
- package/dist/message/use-message.d.ts +2524 -4
- package/dist/session/type.d.ts +19 -0
- package/dist/session/use-session.d.ts +5056 -10
- package/dist/session/use-session.ts.js +68 -5
- package/package.json +4 -1
|
@@ -80,9 +80,38 @@ function _object_spread(target) {
|
|
|
80
80
|
return target;
|
|
81
81
|
}
|
|
82
82
|
import { ref } from 'vue';
|
|
83
|
-
import { AGUIProtocol } from '../event/index.ts.js';
|
|
84
|
-
import { MessageRole, MessageStatus } from '../message/index.ts.js';
|
|
83
|
+
import { AGUIProtocol, ApprovalInterruptTicketStatus, EventType, ResumeStatus, RunFinishedOutcomeType } from '../event/index.ts.js';
|
|
84
|
+
import { MessageRole, MessageStatus, UserOperation } from '../message/index.ts.js';
|
|
85
85
|
import { SessionStatus } from '../session/type.ts.js';
|
|
86
|
+
/** SSE 静默重连最大次数(退避总时长约 23s,落在后端 orphan grace ~30s 内) */ const MAX_RECONNECT_ATTEMPTS = 5;
|
|
87
|
+
const RECONNECT_BASE_DELAY_MS = 1000;
|
|
88
|
+
const RECONNECT_MAX_DELAY_MS = 8000;
|
|
89
|
+
const getReconnectDelayMs = (attempt)=>Math.min(RECONNECT_BASE_DELAY_MS * Math.pow(2, attempt - 1), RECONNECT_MAX_DELAY_MS);
|
|
90
|
+
/**
|
|
91
|
+
* 判断流式错误是否可静默重连。
|
|
92
|
+
* 不重试:Abort、401/403 等业务 4xx(408/429 除外);可重试:网络错误、5xx、无状态码的中断。
|
|
93
|
+
*/ const isRecoverableStreamError = (error)=>{
|
|
94
|
+
var _requestError_response;
|
|
95
|
+
if (error.name === 'AbortError') {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
const requestError = error;
|
|
99
|
+
const statusFromResponse = (_requestError_response = requestError.response) === null || _requestError_response === void 0 ? void 0 : _requestError_response.status;
|
|
100
|
+
const statusFromMessage = error.message.match(/status code (\d+)/i);
|
|
101
|
+
const status = statusFromResponse !== null && statusFromResponse !== void 0 ? statusFromResponse : statusFromMessage ? Number(statusFromMessage[1]) : undefined;
|
|
102
|
+
if (status !== undefined) {
|
|
103
|
+
if (status === 408 || status === 429) {
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
if (status >= 400 && status < 500) {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
if (status >= 500) {
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return true;
|
|
114
|
+
};
|
|
86
115
|
/**
|
|
87
116
|
* Agent 模块
|
|
88
117
|
* @param options - 配置选项
|
|
@@ -92,7 +121,15 @@ import { SessionStatus } from '../session/type.ts.js';
|
|
|
92
121
|
const isInfoLoading = ref(false);
|
|
93
122
|
const isChatting = ref(false);
|
|
94
123
|
let usedProtocol = protocol || new AGUIProtocol();
|
|
95
|
-
let
|
|
124
|
+
let chatAbortController = null;
|
|
125
|
+
let resumeAbortController = null;
|
|
126
|
+
let longPollTimer = null;
|
|
127
|
+
/** 用户主动中止(abortChat),禁止自动重连 */ let manualAbort = false;
|
|
128
|
+
/** 当前轮次已静默重连次数 */ let reconnectAttempt = 0;
|
|
129
|
+
/** 本轮流是否已收到 RUN_FINISHED */ let runFinished = false;
|
|
130
|
+
let reconnectTimer = null;
|
|
131
|
+
let reconnectWaitResolve = null;
|
|
132
|
+
let activeStreamContext = null;
|
|
96
133
|
const getAgentInfo = ()=>{
|
|
97
134
|
var _mediator_http;
|
|
98
135
|
isInfoLoading.value = true;
|
|
@@ -121,27 +158,221 @@ import { SessionStatus } from '../session/type.ts.js';
|
|
|
121
158
|
});
|
|
122
159
|
}
|
|
123
160
|
};
|
|
161
|
+
const userOperationStreamRequest = (sessionCode, operation, payload, config)=>{
|
|
162
|
+
var _mediator_http;
|
|
163
|
+
return (_mediator_http = mediator.http) === null || _mediator_http === void 0 ? void 0 : _mediator_http.message.userOperation(sessionCode, operation, payload, config).then(()=>{
|
|
164
|
+
if (operation !== UserOperation.ApprovalCancel) {
|
|
165
|
+
streamRequest({
|
|
166
|
+
sessionCode,
|
|
167
|
+
config
|
|
168
|
+
});
|
|
169
|
+
} else {
|
|
170
|
+
clearLongPollTimer();
|
|
171
|
+
pollResumeSession(sessionCode);
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
};
|
|
175
|
+
const clearReconnectTimer = (continued = false)=>{
|
|
176
|
+
if (reconnectTimer) {
|
|
177
|
+
clearTimeout(reconnectTimer);
|
|
178
|
+
reconnectTimer = null;
|
|
179
|
+
}
|
|
180
|
+
if (reconnectWaitResolve) {
|
|
181
|
+
const resolve = reconnectWaitResolve;
|
|
182
|
+
reconnectWaitResolve = null;
|
|
183
|
+
resolve(continued);
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
const waitForReconnectDelay = (ms)=>new Promise((resolve)=>{
|
|
187
|
+
reconnectWaitResolve = resolve;
|
|
188
|
+
reconnectTimer = setTimeout(()=>{
|
|
189
|
+
reconnectTimer = null;
|
|
190
|
+
reconnectWaitResolve = null;
|
|
191
|
+
resolve(true);
|
|
192
|
+
}, ms);
|
|
193
|
+
});
|
|
194
|
+
const resetStreamReconnectState = ()=>{
|
|
195
|
+
manualAbort = false;
|
|
196
|
+
reconnectAttempt = 0;
|
|
197
|
+
runFinished = false;
|
|
198
|
+
clearReconnectTimer(false);
|
|
199
|
+
};
|
|
200
|
+
/** 裁掉尾部尚未完成的非用户消息,避免 DLQ 重放时重复气泡 */ const pruneTrailingIncompleteMessages = ()=>{
|
|
201
|
+
var _mediator_message;
|
|
202
|
+
const list = (_mediator_message = mediator.message) === null || _mediator_message === void 0 ? void 0 : _mediator_message.list.value;
|
|
203
|
+
if (!(list === null || list === void 0 ? void 0 : list.length)) {
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
while(list.length > 0){
|
|
207
|
+
const last = list[list.length - 1];
|
|
208
|
+
if (last.role === MessageRole.User) {
|
|
209
|
+
break;
|
|
210
|
+
}
|
|
211
|
+
if (last.status === MessageStatus.Streaming || last.status === MessageStatus.Pending) {
|
|
212
|
+
list.pop();
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
break;
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
const isSameActiveSession = (sessionCode)=>{
|
|
219
|
+
var _mediator_session_current_value, _mediator_session_current, _mediator_session;
|
|
220
|
+
return sessionCode === ((_mediator_session = mediator.session) === null || _mediator_session === void 0 ? void 0 : (_mediator_session_current = _mediator_session.current) === null || _mediator_session_current === void 0 ? void 0 : (_mediator_session_current_value = _mediator_session_current.value) === null || _mediator_session_current_value === void 0 ? void 0 : _mediator_session_current_value.sessionCode);
|
|
221
|
+
};
|
|
222
|
+
/**
|
|
223
|
+
* 尝试静默重连。
|
|
224
|
+
* @returns reconnected | finished(服务端已结束)| failed(需对外报错或中止)
|
|
225
|
+
*/ const attemptSilentReconnect = function() {
|
|
226
|
+
var _ref = _async_to_generator(function*(sessionCode) {
|
|
227
|
+
var _mediator_session_current_value, _mediator_session, _mediator_session_current_value1, _mediator_session1, _mediator_message_list_value_at, _mediator_message;
|
|
228
|
+
if (manualAbort || !isSameActiveSession(sessionCode)) {
|
|
229
|
+
return 'failed';
|
|
230
|
+
}
|
|
231
|
+
try {
|
|
232
|
+
var _mediator_session2;
|
|
233
|
+
yield (_mediator_session2 = mediator.session) === null || _mediator_session2 === void 0 ? void 0 : _mediator_session2.getSession(sessionCode);
|
|
234
|
+
} catch (e) {
|
|
235
|
+
// 状态刷新失败时沿用本地 session.status
|
|
236
|
+
}
|
|
237
|
+
if (manualAbort || !isSameActiveSession(sessionCode)) {
|
|
238
|
+
return 'failed';
|
|
239
|
+
}
|
|
240
|
+
if (((_mediator_session = mediator.session) === null || _mediator_session === void 0 ? void 0 : (_mediator_session_current_value = _mediator_session.current.value) === null || _mediator_session_current_value === void 0 ? void 0 : _mediator_session_current_value.status) !== SessionStatus.Running) {
|
|
241
|
+
return 'finished';
|
|
242
|
+
}
|
|
243
|
+
if (reconnectAttempt >= MAX_RECONNECT_ATTEMPTS) {
|
|
244
|
+
return 'failed';
|
|
245
|
+
}
|
|
246
|
+
reconnectAttempt += 1;
|
|
247
|
+
// 静默重连期间保持「生成中」态
|
|
248
|
+
isChatting.value = true;
|
|
249
|
+
const delayMs = getReconnectDelayMs(reconnectAttempt);
|
|
250
|
+
const waited = yield waitForReconnectDelay(delayMs);
|
|
251
|
+
if (!waited || manualAbort || !isSameActiveSession(sessionCode)) {
|
|
252
|
+
return 'failed';
|
|
253
|
+
}
|
|
254
|
+
if (((_mediator_session1 = mediator.session) === null || _mediator_session1 === void 0 ? void 0 : (_mediator_session_current_value1 = _mediator_session1.current.value) === null || _mediator_session_current_value1 === void 0 ? void 0 : _mediator_session_current_value1.status) !== SessionStatus.Running) {
|
|
255
|
+
return 'finished';
|
|
256
|
+
}
|
|
257
|
+
pruneTrailingIncompleteMessages();
|
|
258
|
+
const lastMessageId = (_mediator_message = mediator.message) === null || _mediator_message === void 0 ? void 0 : (_mediator_message_list_value_at = _mediator_message.list.value.at(-1)) === null || _mediator_message_list_value_at === void 0 ? void 0 : _mediator_message_list_value_at.id;
|
|
259
|
+
const ctx = activeStreamContext;
|
|
260
|
+
streamRequest({
|
|
261
|
+
sessionCode,
|
|
262
|
+
url: ctx === null || ctx === void 0 ? void 0 : ctx.url,
|
|
263
|
+
config: ctx === null || ctx === void 0 ? void 0 : ctx.config,
|
|
264
|
+
lastMessageId: lastMessageId !== undefined ? String(lastMessageId) : undefined,
|
|
265
|
+
isReconnect: true
|
|
266
|
+
});
|
|
267
|
+
return 'reconnected';
|
|
268
|
+
});
|
|
269
|
+
return function attemptSilentReconnect(sessionCode) {
|
|
270
|
+
return _ref.apply(this, arguments);
|
|
271
|
+
};
|
|
272
|
+
}();
|
|
124
273
|
const streamRequest = function() {
|
|
125
|
-
var _ref = _async_to_generator(function*(sessionCode, url, config) {
|
|
126
|
-
var
|
|
127
|
-
|
|
274
|
+
var _ref = _async_to_generator(function*({ sessionCode, url, config, resume, input, lastMessageId, isReconnect = false }) {
|
|
275
|
+
var _mediator_http;
|
|
276
|
+
if (!isReconnect) {
|
|
277
|
+
resetStreamReconnectState();
|
|
278
|
+
}
|
|
279
|
+
activeStreamContext = {
|
|
280
|
+
sessionCode,
|
|
281
|
+
url,
|
|
282
|
+
config
|
|
283
|
+
};
|
|
128
284
|
// ag-ui 协议需要注入消息模块
|
|
129
285
|
if (usedProtocol instanceof AGUIProtocol) {
|
|
130
286
|
usedProtocol.injectMessageModule(mediator.message);
|
|
131
287
|
}
|
|
132
|
-
|
|
133
|
-
|
|
288
|
+
if (input) {
|
|
289
|
+
var // 列表新增一个用户消息
|
|
290
|
+
_mediator_message;
|
|
291
|
+
(_mediator_message = mediator.message) === null || _mediator_message === void 0 ? void 0 : _mediator_message.list.value.push({
|
|
292
|
+
role: MessageRole.User,
|
|
293
|
+
content: input,
|
|
294
|
+
status: MessageStatus.Complete,
|
|
295
|
+
sessionCode
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
const finishSuccessfully = ()=>{
|
|
134
299
|
var _usedProtocol_onDone;
|
|
135
300
|
isChatting.value = false;
|
|
136
301
|
(_usedProtocol_onDone = usedProtocol.onDone) === null || _usedProtocol_onDone === void 0 ? void 0 : _usedProtocol_onDone.call(usedProtocol);
|
|
302
|
+
if (input) {
|
|
303
|
+
var // 刷新列表,获取前端 mock message 的 id,并更新到列表中
|
|
304
|
+
_mediator_http_message, _mediator_http;
|
|
305
|
+
(_mediator_http = mediator.http) === null || _mediator_http === void 0 ? void 0 : (_mediator_http_message = _mediator_http.message) === null || _mediator_http_message === void 0 ? void 0 : _mediator_http_message.getMessages(sessionCode).then((res)=>{
|
|
306
|
+
var _mediator_message;
|
|
307
|
+
const lastUserMessage = (_mediator_message = mediator.message) === null || _mediator_message === void 0 ? void 0 : _mediator_message.list.value.findLast((item)=>item.role === MessageRole.User);
|
|
308
|
+
const lastApiUserMessage = res.findLast((item)=>item.role === MessageRole.User);
|
|
309
|
+
if (lastUserMessage && lastApiUserMessage) {
|
|
310
|
+
lastUserMessage.id = lastApiUserMessage.id;
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
// 轮询接口,判断是否可以继续聊天
|
|
315
|
+
pollResumeSession(sessionCode);
|
|
137
316
|
};
|
|
138
|
-
const
|
|
317
|
+
const failWithError = (error)=>{
|
|
139
318
|
var _usedProtocol_onError;
|
|
140
319
|
isChatting.value = false;
|
|
141
320
|
(_usedProtocol_onError = usedProtocol.onError) === null || _usedProtocol_onError === void 0 ? void 0 : _usedProtocol_onError.call(usedProtocol, error);
|
|
142
321
|
};
|
|
322
|
+
// 事件代理
|
|
323
|
+
const onDone = ()=>{
|
|
324
|
+
// 用户 abort:FetchClient 将 AbortError 转为 onDone,不重连
|
|
325
|
+
if (manualAbort || runFinished) {
|
|
326
|
+
finishSuccessfully();
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
// 连接被干净掐断且未收到 RUN_FINISHED:尝试静默重连
|
|
330
|
+
void attemptSilentReconnect(sessionCode).then((result)=>{
|
|
331
|
+
if (result === 'reconnected') {
|
|
332
|
+
// 保持 isChatting=true,不展示错误
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
if (result === 'finished') {
|
|
336
|
+
finishSuccessfully();
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
// abort / 切会话导致的失败:静默结束,不展示错误气泡
|
|
340
|
+
if (manualAbort || !isSameActiveSession(sessionCode)) {
|
|
341
|
+
isChatting.value = false;
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
failWithError(new Error('Connection lost, please try again'));
|
|
345
|
+
});
|
|
346
|
+
};
|
|
347
|
+
const onError = (error)=>{
|
|
348
|
+
if (manualAbort) {
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
if (!isRecoverableStreamError(error)) {
|
|
352
|
+
failWithError(error);
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
void attemptSilentReconnect(sessionCode).then((result)=>{
|
|
356
|
+
if (result === 'reconnected') {
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
if (result === 'finished') {
|
|
360
|
+
finishSuccessfully();
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
if (manualAbort || !isSameActiveSession(sessionCode)) {
|
|
364
|
+
isChatting.value = false;
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
failWithError(error);
|
|
368
|
+
});
|
|
369
|
+
};
|
|
143
370
|
const onMessage = (event)=>{
|
|
144
371
|
var _usedProtocol_onMessage;
|
|
372
|
+
const typedEvent = event;
|
|
373
|
+
if ((typedEvent === null || typedEvent === void 0 ? void 0 : typedEvent.type) === EventType.RunFinished) {
|
|
374
|
+
runFinished = true;
|
|
375
|
+
}
|
|
145
376
|
(_usedProtocol_onMessage = usedProtocol.onMessage) === null || _usedProtocol_onMessage === void 0 ? void 0 : _usedProtocol_onMessage.call(usedProtocol, event);
|
|
146
377
|
};
|
|
147
378
|
const onStart = ()=>{
|
|
@@ -150,24 +381,31 @@ import { SessionStatus } from '../session/type.ts.js';
|
|
|
150
381
|
(_usedProtocol_onStart = usedProtocol.onStart) === null || _usedProtocol_onStart === void 0 ? void 0 : _usedProtocol_onStart.call(usedProtocol);
|
|
151
382
|
};
|
|
152
383
|
// 创建 AbortController
|
|
153
|
-
|
|
154
|
-
|
|
384
|
+
chatAbortController = new AbortController();
|
|
385
|
+
// 发起聊天
|
|
386
|
+
void ((_mediator_http = mediator.http) === null || _mediator_http === void 0 ? void 0 : _mediator_http.fetchClient.streamRequest(_object_spread({
|
|
155
387
|
url: url || 'chat_completion/',
|
|
156
388
|
method: 'POST',
|
|
157
389
|
data: {
|
|
158
390
|
session_code: sessionCode,
|
|
391
|
+
input,
|
|
159
392
|
execute_kwargs: {
|
|
160
|
-
stream: true
|
|
393
|
+
stream: true,
|
|
394
|
+
persist_input: !!input,
|
|
395
|
+
last_message_id: lastMessageId,
|
|
396
|
+
resume
|
|
161
397
|
}
|
|
162
398
|
},
|
|
163
|
-
controller:
|
|
399
|
+
controller: chatAbortController,
|
|
164
400
|
onDone,
|
|
165
401
|
onError,
|
|
166
402
|
onMessage,
|
|
167
403
|
onStart
|
|
168
|
-
}, config))
|
|
404
|
+
}, config)).catch(()=>{
|
|
405
|
+
// 非 abort 错误已通过 onError 回调处理;abort 为正常结束
|
|
406
|
+
}));
|
|
169
407
|
});
|
|
170
|
-
return function streamRequest(
|
|
408
|
+
return function streamRequest(_) {
|
|
171
409
|
return _ref.apply(this, arguments);
|
|
172
410
|
};
|
|
173
411
|
}();
|
|
@@ -191,7 +429,11 @@ import { SessionStatus } from '../session/type.ts.js';
|
|
|
191
429
|
property
|
|
192
430
|
}));
|
|
193
431
|
// 发起聊天
|
|
194
|
-
streamRequest(
|
|
432
|
+
streamRequest({
|
|
433
|
+
sessionCode,
|
|
434
|
+
url,
|
|
435
|
+
config
|
|
436
|
+
});
|
|
195
437
|
});
|
|
196
438
|
return function chat(userInput, sessionCode, url, config, property) {
|
|
197
439
|
return _ref.apply(this, arguments);
|
|
@@ -206,15 +448,78 @@ import { SessionStatus } from '../session/type.ts.js';
|
|
|
206
448
|
*/ const resumeStreamingChat = (sessionCode, url, config)=>{
|
|
207
449
|
var _mediator_session_current_value, _mediator_session;
|
|
208
450
|
if (((_mediator_session = mediator.session) === null || _mediator_session === void 0 ? void 0 : (_mediator_session_current_value = _mediator_session.current.value) === null || _mediator_session_current_value === void 0 ? void 0 : _mediator_session_current_value.status) === SessionStatus.Running) {
|
|
209
|
-
|
|
451
|
+
var _mediator_message_list_value_at, _mediator_message;
|
|
452
|
+
const lastMessageId = (_mediator_message = mediator.message) === null || _mediator_message === void 0 ? void 0 : (_mediator_message_list_value_at = _mediator_message.list.value.at(-1)) === null || _mediator_message_list_value_at === void 0 ? void 0 : _mediator_message_list_value_at.id;
|
|
453
|
+
streamRequest({
|
|
454
|
+
sessionCode,
|
|
455
|
+
url,
|
|
456
|
+
config,
|
|
457
|
+
lastMessageId
|
|
458
|
+
});
|
|
210
459
|
}
|
|
211
460
|
};
|
|
212
461
|
/**
|
|
462
|
+
* 轮询接口,判断是否可以继续聊天
|
|
463
|
+
* @param sessionCode - 会话编码
|
|
464
|
+
* @returns 是否可以继续聊天
|
|
465
|
+
*/ const pollResumeSession = (sessionCode)=>{
|
|
466
|
+
var _mediator_message, _lastMessage_content_outcome, _lastMessage_content;
|
|
467
|
+
const lastMessage = (_mediator_message = mediator.message) === null || _mediator_message === void 0 ? void 0 : _mediator_message.list.value.at(-1);
|
|
468
|
+
const pendingApprovalInterrupt = (lastMessage === null || lastMessage === void 0 ? void 0 : (_lastMessage_content = lastMessage.content) === null || _lastMessage_content === void 0 ? void 0 : (_lastMessage_content_outcome = _lastMessage_content.outcome) === null || _lastMessage_content_outcome === void 0 ? void 0 : _lastMessage_content_outcome.type) === RunFinishedOutcomeType.Interrupt ? lastMessage.content.outcome.interrupts.find((interrupt)=>{
|
|
469
|
+
var _interrupt_metadata_ticket, _interrupt_metadata;
|
|
470
|
+
return [
|
|
471
|
+
ApprovalInterruptTicketStatus.Pending,
|
|
472
|
+
ApprovalInterruptTicketStatus.Draft
|
|
473
|
+
].includes((_interrupt_metadata = interrupt.metadata) === null || _interrupt_metadata === void 0 ? void 0 : (_interrupt_metadata_ticket = _interrupt_metadata.ticket) === null || _interrupt_metadata_ticket === void 0 ? void 0 : _interrupt_metadata_ticket.status);
|
|
474
|
+
}) : undefined;
|
|
475
|
+
const getIsTicketLoading = ()=>{
|
|
476
|
+
const isInterruptMessage = (lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.role) === MessageRole.Interrupt;
|
|
477
|
+
return isInterruptMessage && !!pendingApprovalInterrupt;
|
|
478
|
+
};
|
|
479
|
+
if (getIsTicketLoading()) {
|
|
480
|
+
var // 轮询接口,判断是否可以继续聊天
|
|
481
|
+
_mediator_http;
|
|
482
|
+
// 清除轮询定时器和中断轮询控制器
|
|
483
|
+
clearLongPollTimer();
|
|
484
|
+
resumeAbortController = new AbortController();
|
|
485
|
+
(_mediator_http = mediator.http) === null || _mediator_http === void 0 ? void 0 : _mediator_http.session.isResumeSession(sessionCode, {
|
|
486
|
+
controller: resumeAbortController
|
|
487
|
+
}).then((res)=>{
|
|
488
|
+
if (res) {
|
|
489
|
+
// 可以继续聊天,重新发起聊天(携带 execute_kwargs.resume 通知后端恢复中断)
|
|
490
|
+
streamRequest({
|
|
491
|
+
sessionCode,
|
|
492
|
+
resume: {
|
|
493
|
+
interruptId: pendingApprovalInterrupt.id,
|
|
494
|
+
status: ResumeStatus.Resolved
|
|
495
|
+
}
|
|
496
|
+
});
|
|
497
|
+
} else {
|
|
498
|
+
longPollTimer = setTimeout(()=>{
|
|
499
|
+
var _mediator_session_current_value, _mediator_session_current, _mediator_session;
|
|
500
|
+
// 如果会话不匹配,则不继续轮询
|
|
501
|
+
if (sessionCode !== ((_mediator_session = mediator.session) === null || _mediator_session === void 0 ? void 0 : (_mediator_session_current = _mediator_session.current) === null || _mediator_session_current === void 0 ? void 0 : (_mediator_session_current_value = _mediator_session_current.value) === null || _mediator_session_current_value === void 0 ? void 0 : _mediator_session_current_value.sessionCode)) return;
|
|
502
|
+
pollResumeSession(sessionCode);
|
|
503
|
+
}, 10000);
|
|
504
|
+
}
|
|
505
|
+
});
|
|
506
|
+
}
|
|
507
|
+
};
|
|
508
|
+
const clearLongPollTimer = ()=>{
|
|
509
|
+
var _resumeAbortController_abort;
|
|
510
|
+
clearTimeout(longPollTimer);
|
|
511
|
+
longPollTimer = null;
|
|
512
|
+
resumeAbortController === null || resumeAbortController === void 0 ? void 0 : (_resumeAbortController_abort = resumeAbortController.abort) === null || _resumeAbortController_abort === void 0 ? void 0 : _resumeAbortController_abort.call(resumeAbortController);
|
|
513
|
+
resumeAbortController = null;
|
|
514
|
+
};
|
|
515
|
+
/**
|
|
213
516
|
* 中止聊天(纯前端中止,后端继续处理)
|
|
214
517
|
*/ const abortChat = ()=>{
|
|
215
|
-
var
|
|
216
|
-
|
|
217
|
-
|
|
518
|
+
var _chatAbortController_abort;
|
|
519
|
+
manualAbort = true;
|
|
520
|
+
clearReconnectTimer(false);
|
|
521
|
+
chatAbortController === null || chatAbortController === void 0 ? void 0 : (_chatAbortController_abort = chatAbortController.abort) === null || _chatAbortController_abort === void 0 ? void 0 : _chatAbortController_abort.call(chatAbortController);
|
|
522
|
+
chatAbortController = null;
|
|
218
523
|
};
|
|
219
524
|
/**
|
|
220
525
|
* 停止会话,后端中止
|
|
@@ -269,7 +574,11 @@ import { SessionStatus } from '../session/type.ts.js';
|
|
|
269
574
|
property: originalProperty
|
|
270
575
|
}));
|
|
271
576
|
// 6. 立即发起流式请求(不等待删除和创建的 API 完成)
|
|
272
|
-
streamRequest(
|
|
577
|
+
streamRequest({
|
|
578
|
+
sessionCode,
|
|
579
|
+
url,
|
|
580
|
+
config
|
|
581
|
+
});
|
|
273
582
|
// 7. 在后台等待 API 完成,处理可能的错误
|
|
274
583
|
Promise.all([
|
|
275
584
|
deletePromise,
|
|
@@ -283,10 +592,15 @@ import { SessionStatus } from '../session/type.ts.js';
|
|
|
283
592
|
};
|
|
284
593
|
}();
|
|
285
594
|
const reset = (protocol)=>{
|
|
286
|
-
|
|
595
|
+
abortChat();
|
|
596
|
+
// 重置状态(保留 manualAbort=true,避免 abort 异步 onDone 误触发重连;下次 streamRequest 会复位)
|
|
287
597
|
usedProtocol = protocol || new AGUIProtocol();
|
|
288
598
|
info.value = null;
|
|
289
599
|
isInfoLoading.value = false;
|
|
600
|
+
isChatting.value = false;
|
|
601
|
+
activeStreamContext = null;
|
|
602
|
+
reconnectAttempt = 0;
|
|
603
|
+
runFinished = false;
|
|
290
604
|
};
|
|
291
605
|
return {
|
|
292
606
|
info,
|
|
@@ -299,6 +613,10 @@ import { SessionStatus } from '../session/type.ts.js';
|
|
|
299
613
|
abortChat,
|
|
300
614
|
stopChat,
|
|
301
615
|
getAgentInfo,
|
|
302
|
-
reset
|
|
616
|
+
reset,
|
|
617
|
+
pollResumeSession,
|
|
618
|
+
clearLongPollTimer,
|
|
619
|
+
userOperationStreamRequest,
|
|
620
|
+
streamRequest
|
|
303
621
|
};
|
|
304
622
|
};
|
package/dist/event/ag-ui.d.ts
CHANGED
|
@@ -26,7 +26,7 @@ export declare class AGUIProtocol implements ISSEProtocol {
|
|
|
26
26
|
* 处理活动快照事件
|
|
27
27
|
* 记录活动的完整状态
|
|
28
28
|
*/
|
|
29
|
-
handleActivitySnapshotEvent(
|
|
29
|
+
handleActivitySnapshotEvent(event: IActivitySnapshotEvent): void;
|
|
30
30
|
/**
|
|
31
31
|
* 处理自定义事件
|
|
32
32
|
*/
|
|
@@ -35,6 +35,10 @@ export declare class AGUIProtocol implements ISSEProtocol {
|
|
|
35
35
|
* 自定义事件 处理流程编排任务结束
|
|
36
36
|
*/
|
|
37
37
|
handleFlowAgentEndCustomEvent(event: ICustomEvent): void;
|
|
38
|
+
/**
|
|
39
|
+
* 自定义事件 处理流程编排任务重启
|
|
40
|
+
*/
|
|
41
|
+
handleFlowAgentRestartCustomEvent(event: ICustomEvent): void;
|
|
38
42
|
/**
|
|
39
43
|
* 自定义事件 处理流程编排任务结果(增量更新节点状态)
|
|
40
44
|
*/
|
|
@@ -43,6 +47,10 @@ export declare class AGUIProtocol implements ISSEProtocol {
|
|
|
43
47
|
* 自定义事件 处理流程编排任务开始
|
|
44
48
|
*/
|
|
45
49
|
handleFlowAgentStartCustomEvent(event: ICustomEvent): void;
|
|
50
|
+
/**
|
|
51
|
+
* 自定义事件 处理流程编排任务更新
|
|
52
|
+
*/
|
|
53
|
+
handleFlowAgentUpdateCustomEvent(event: ICustomEvent): void;
|
|
46
54
|
/**
|
|
47
55
|
* 自定义事件 处理意图识别结束
|
|
48
56
|
*/
|
|
@@ -80,7 +88,7 @@ export declare class AGUIProtocol implements ISSEProtocol {
|
|
|
80
88
|
/**
|
|
81
89
|
* 处理运行完成事件
|
|
82
90
|
*/
|
|
83
|
-
handleRunFinishedEvent(
|
|
91
|
+
handleRunFinishedEvent(event: IRunFinishedEvent): void;
|
|
84
92
|
/**
|
|
85
93
|
* 处理运行开始事件
|
|
86
94
|
*/
|
|
@@ -105,6 +113,10 @@ export declare class AGUIProtocol implements ISSEProtocol {
|
|
|
105
113
|
* 自定义事件 处理临时消息,转换为 AI 文本消息
|
|
106
114
|
*/
|
|
107
115
|
handleTempMessageCustomEvent(event: ICustomEvent): void;
|
|
116
|
+
/**
|
|
117
|
+
* 自定义事件 处理审批结果
|
|
118
|
+
*/
|
|
119
|
+
handleApprovalResultCustomEvent(event: ICustomEvent): void;
|
|
108
120
|
/**
|
|
109
121
|
* 处理文本消息块事件
|
|
110
122
|
*/
|
|
@@ -119,6 +131,7 @@ export declare class AGUIProtocol implements ISSEProtocol {
|
|
|
119
131
|
handleTextMessageEndEvent(event: ITextMessageEndEvent): void;
|
|
120
132
|
/**
|
|
121
133
|
* 处理文本消息开始事件
|
|
134
|
+
* 断线续传时 DLQ 会重放事件:同 messageId 已存在则重置内容,避免重复气泡/文本翻倍
|
|
122
135
|
*/
|
|
123
136
|
handleTextMessageStartEvent(event: ITextMessageStartEvent): void;
|
|
124
137
|
/**
|