@blueking/chat-helper 0.0.12-beta.10 → 0.0.12-beta.12
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.md +8 -2
- package/dist/agent/type.d.ts +69 -0
- package/dist/agent/type.ts.js +1 -1
- package/dist/agent/use-agent.d.ts +170 -10
- package/dist/agent/use-agent.ts.js +257 -17
- package/dist/event/ag-ui.d.ts +3 -0
- package/dist/event/ag-ui.ts.js +42 -3
- package/dist/event/type.d.ts +13 -2
- package/dist/event/type.ts.js +2 -0
- package/dist/http/index.d.ts +2 -0
- package/dist/http/module/agent.d.ts +2 -0
- package/dist/http/module/agent.ts.js +19 -2
- package/dist/http/module/index.d.ts +2 -0
- package/dist/http/module/message.ts.js +2 -2
- package/dist/http/module/session.d.ts +2 -1
- package/dist/http/module/session.ts.js +44 -7
- package/dist/http/transform/agent.d.ts +9 -1
- package/dist/http/transform/agent.ts.js +27 -0
- package/dist/http/transform/message.d.ts +6 -0
- package/dist/http/transform/message.ts.js +56 -0
- package/dist/index.d.ts +792 -6
- package/dist/message/type.d.ts +18 -3
- package/dist/message/type.ts.js +2 -0
- package/dist/message/use-message.d.ts +208 -0
- package/dist/session/type.d.ts +14 -0
- package/dist/session/use-session.d.ts +418 -1
- package/dist/session/use-session.ts.js +5 -0
- package/package.json +1 -1
|
@@ -80,9 +80,38 @@ function _object_spread(target) {
|
|
|
80
80
|
return target;
|
|
81
81
|
}
|
|
82
82
|
import { ref } from 'vue';
|
|
83
|
-
import { AGUIProtocol, ApprovalInterruptTicketStatus, ResumeStatus, RunFinishedOutcomeType } from '../event/index.ts.js';
|
|
83
|
+
import { AGUIProtocol, ApprovalInterruptTicketStatus, EventType, ResumeStatus, RunFinishedOutcomeType } from '../event/index.ts.js';
|
|
84
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 - 配置选项
|
|
@@ -91,10 +120,39 @@ import { SessionStatus } from '../session/type.ts.js';
|
|
|
91
120
|
const info = ref(null);
|
|
92
121
|
const isInfoLoading = ref(false);
|
|
93
122
|
const isChatting = ref(false);
|
|
123
|
+
const models = ref([]);
|
|
124
|
+
const isModelsLoading = ref(false);
|
|
94
125
|
let usedProtocol = protocol || new AGUIProtocol();
|
|
95
126
|
let chatAbortController = null;
|
|
96
127
|
let resumeAbortController = null;
|
|
97
128
|
let longPollTimer = null;
|
|
129
|
+
/** 用户主动中止(abortChat),禁止自动重连 */ let manualAbort = false;
|
|
130
|
+
/** 当前轮次已静默重连次数 */ let reconnectAttempt = 0;
|
|
131
|
+
/** 本轮流是否已收到 RUN_FINISHED */ let runFinished = false;
|
|
132
|
+
let reconnectTimer = null;
|
|
133
|
+
let reconnectWaitResolve = null;
|
|
134
|
+
let activeStreamContext = null;
|
|
135
|
+
/**
|
|
136
|
+
* 获取可用模型列表,写入 models;失败时清空列表并抛出
|
|
137
|
+
*/ const getLlms = (params, config)=>{
|
|
138
|
+
var _mediator_http;
|
|
139
|
+
isModelsLoading.value = true;
|
|
140
|
+
const request = (_mediator_http = mediator.http) === null || _mediator_http === void 0 ? void 0 : _mediator_http.agent.getLlms(params, config);
|
|
141
|
+
if (!request) {
|
|
142
|
+
isModelsLoading.value = false;
|
|
143
|
+
models.value = [];
|
|
144
|
+
return Promise.resolve([]);
|
|
145
|
+
}
|
|
146
|
+
return request.then((res)=>{
|
|
147
|
+
models.value = res;
|
|
148
|
+
return res;
|
|
149
|
+
})['catch']((error)=>{
|
|
150
|
+
models.value = [];
|
|
151
|
+
throw error;
|
|
152
|
+
})['finally'](()=>{
|
|
153
|
+
isModelsLoading.value = false;
|
|
154
|
+
});
|
|
155
|
+
};
|
|
98
156
|
const getAgentInfo = ()=>{
|
|
99
157
|
var _mediator_http;
|
|
100
158
|
isInfoLoading.value = true;
|
|
@@ -123,23 +181,132 @@ import { SessionStatus } from '../session/type.ts.js';
|
|
|
123
181
|
});
|
|
124
182
|
}
|
|
125
183
|
};
|
|
126
|
-
const userOperationStreamRequest = (sessionCode, operation, payload, config)=>{
|
|
184
|
+
const userOperationStreamRequest = (sessionCode, operation, payload, config, model)=>{
|
|
127
185
|
var _mediator_http;
|
|
128
186
|
return (_mediator_http = mediator.http) === null || _mediator_http === void 0 ? void 0 : _mediator_http.message.userOperation(sessionCode, operation, payload, config).then(()=>{
|
|
129
187
|
if (operation !== UserOperation.ApprovalCancel) {
|
|
130
188
|
streamRequest({
|
|
131
189
|
sessionCode,
|
|
132
|
-
config
|
|
190
|
+
config,
|
|
191
|
+
model
|
|
133
192
|
});
|
|
134
193
|
} else {
|
|
135
194
|
clearLongPollTimer();
|
|
136
|
-
pollResumeSession(sessionCode);
|
|
195
|
+
pollResumeSession(sessionCode, model);
|
|
137
196
|
}
|
|
138
197
|
});
|
|
139
198
|
};
|
|
199
|
+
const clearReconnectTimer = (continued = false)=>{
|
|
200
|
+
if (reconnectTimer) {
|
|
201
|
+
clearTimeout(reconnectTimer);
|
|
202
|
+
reconnectTimer = null;
|
|
203
|
+
}
|
|
204
|
+
if (reconnectWaitResolve) {
|
|
205
|
+
const resolve = reconnectWaitResolve;
|
|
206
|
+
reconnectWaitResolve = null;
|
|
207
|
+
resolve(continued);
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
const waitForReconnectDelay = (ms)=>new Promise((resolve)=>{
|
|
211
|
+
reconnectWaitResolve = resolve;
|
|
212
|
+
reconnectTimer = setTimeout(()=>{
|
|
213
|
+
reconnectTimer = null;
|
|
214
|
+
reconnectWaitResolve = null;
|
|
215
|
+
resolve(true);
|
|
216
|
+
}, ms);
|
|
217
|
+
});
|
|
218
|
+
const resetStreamReconnectState = ()=>{
|
|
219
|
+
manualAbort = false;
|
|
220
|
+
reconnectAttempt = 0;
|
|
221
|
+
runFinished = false;
|
|
222
|
+
clearReconnectTimer(false);
|
|
223
|
+
};
|
|
224
|
+
/** 裁掉尾部尚未完成的非用户消息,避免 DLQ 重放时重复气泡 */ const pruneTrailingIncompleteMessages = ()=>{
|
|
225
|
+
var _mediator_message;
|
|
226
|
+
const list = (_mediator_message = mediator.message) === null || _mediator_message === void 0 ? void 0 : _mediator_message.list.value;
|
|
227
|
+
if (!(list === null || list === void 0 ? void 0 : list.length)) {
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
while(list.length > 0){
|
|
231
|
+
const last = list[list.length - 1];
|
|
232
|
+
if (last.role === MessageRole.User) {
|
|
233
|
+
break;
|
|
234
|
+
}
|
|
235
|
+
if (last.status === MessageStatus.Streaming || last.status === MessageStatus.Pending) {
|
|
236
|
+
list.pop();
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
break;
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
const isSameActiveSession = (sessionCode)=>{
|
|
243
|
+
var _mediator_session_current_value, _mediator_session_current, _mediator_session;
|
|
244
|
+
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);
|
|
245
|
+
};
|
|
246
|
+
/**
|
|
247
|
+
* 尝试静默重连。
|
|
248
|
+
* @returns reconnected | finished(服务端已结束)| failed(需对外报错或中止)
|
|
249
|
+
*/ const attemptSilentReconnect = function() {
|
|
250
|
+
var _ref = _async_to_generator(function*(sessionCode) {
|
|
251
|
+
var _mediator_session_current_value, _mediator_session, _mediator_session_current_value1, _mediator_session1, _mediator_message_list_value_at, _mediator_message;
|
|
252
|
+
if (manualAbort || !isSameActiveSession(sessionCode)) {
|
|
253
|
+
return 'failed';
|
|
254
|
+
}
|
|
255
|
+
try {
|
|
256
|
+
var _mediator_session2;
|
|
257
|
+
yield (_mediator_session2 = mediator.session) === null || _mediator_session2 === void 0 ? void 0 : _mediator_session2.getSession(sessionCode);
|
|
258
|
+
} catch (e) {
|
|
259
|
+
// 状态刷新失败时沿用本地 session.status
|
|
260
|
+
}
|
|
261
|
+
if (manualAbort || !isSameActiveSession(sessionCode)) {
|
|
262
|
+
return 'failed';
|
|
263
|
+
}
|
|
264
|
+
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) {
|
|
265
|
+
return 'finished';
|
|
266
|
+
}
|
|
267
|
+
if (reconnectAttempt >= MAX_RECONNECT_ATTEMPTS) {
|
|
268
|
+
return 'failed';
|
|
269
|
+
}
|
|
270
|
+
reconnectAttempt += 1;
|
|
271
|
+
// 静默重连期间保持「生成中」态
|
|
272
|
+
isChatting.value = true;
|
|
273
|
+
const delayMs = getReconnectDelayMs(reconnectAttempt);
|
|
274
|
+
const waited = yield waitForReconnectDelay(delayMs);
|
|
275
|
+
if (!waited || manualAbort || !isSameActiveSession(sessionCode)) {
|
|
276
|
+
return 'failed';
|
|
277
|
+
}
|
|
278
|
+
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) {
|
|
279
|
+
return 'finished';
|
|
280
|
+
}
|
|
281
|
+
pruneTrailingIncompleteMessages();
|
|
282
|
+
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;
|
|
283
|
+
const ctx = activeStreamContext;
|
|
284
|
+
streamRequest({
|
|
285
|
+
sessionCode,
|
|
286
|
+
model: ctx === null || ctx === void 0 ? void 0 : ctx.model,
|
|
287
|
+
url: ctx === null || ctx === void 0 ? void 0 : ctx.url,
|
|
288
|
+
config: ctx === null || ctx === void 0 ? void 0 : ctx.config,
|
|
289
|
+
lastMessageId: lastMessageId !== undefined ? String(lastMessageId) : undefined,
|
|
290
|
+
isReconnect: true
|
|
291
|
+
});
|
|
292
|
+
return 'reconnected';
|
|
293
|
+
});
|
|
294
|
+
return function attemptSilentReconnect(sessionCode) {
|
|
295
|
+
return _ref.apply(this, arguments);
|
|
296
|
+
};
|
|
297
|
+
}();
|
|
140
298
|
const streamRequest = function() {
|
|
141
|
-
var _ref = _async_to_generator(function*({ sessionCode, url, config, resume, input, lastMessageId }) {
|
|
299
|
+
var _ref = _async_to_generator(function*({ sessionCode, model, url, config, resume, input, lastMessageId, isReconnect = false }) {
|
|
142
300
|
var _mediator_http;
|
|
301
|
+
if (!isReconnect) {
|
|
302
|
+
resetStreamReconnectState();
|
|
303
|
+
}
|
|
304
|
+
activeStreamContext = {
|
|
305
|
+
sessionCode,
|
|
306
|
+
model: model,
|
|
307
|
+
url,
|
|
308
|
+
config
|
|
309
|
+
};
|
|
143
310
|
// ag-ui 协议需要注入消息模块
|
|
144
311
|
if (usedProtocol instanceof AGUIProtocol) {
|
|
145
312
|
usedProtocol.injectMessageModule(mediator.message);
|
|
@@ -154,8 +321,7 @@ import { SessionStatus } from '../session/type.ts.js';
|
|
|
154
321
|
sessionCode
|
|
155
322
|
});
|
|
156
323
|
}
|
|
157
|
-
|
|
158
|
-
const onDone = ()=>{
|
|
324
|
+
const finishSuccessfully = ()=>{
|
|
159
325
|
var _usedProtocol_onDone;
|
|
160
326
|
isChatting.value = false;
|
|
161
327
|
(_usedProtocol_onDone = usedProtocol.onDone) === null || _usedProtocol_onDone === void 0 ? void 0 : _usedProtocol_onDone.call(usedProtocol);
|
|
@@ -166,19 +332,73 @@ import { SessionStatus } from '../session/type.ts.js';
|
|
|
166
332
|
var _mediator_message;
|
|
167
333
|
const lastUserMessage = (_mediator_message = mediator.message) === null || _mediator_message === void 0 ? void 0 : _mediator_message.list.value.findLast((item)=>item.role === MessageRole.User);
|
|
168
334
|
const lastApiUserMessage = res.findLast((item)=>item.role === MessageRole.User);
|
|
169
|
-
lastUserMessage
|
|
335
|
+
if (lastUserMessage && lastApiUserMessage) {
|
|
336
|
+
lastUserMessage.id = lastApiUserMessage.id;
|
|
337
|
+
}
|
|
170
338
|
});
|
|
171
339
|
}
|
|
172
340
|
// 轮询接口,判断是否可以继续聊天
|
|
173
341
|
pollResumeSession(sessionCode);
|
|
174
342
|
};
|
|
175
|
-
const
|
|
343
|
+
const failWithError = (error)=>{
|
|
176
344
|
var _usedProtocol_onError;
|
|
177
345
|
isChatting.value = false;
|
|
178
346
|
(_usedProtocol_onError = usedProtocol.onError) === null || _usedProtocol_onError === void 0 ? void 0 : _usedProtocol_onError.call(usedProtocol, error);
|
|
179
347
|
};
|
|
348
|
+
// 事件代理
|
|
349
|
+
const onDone = ()=>{
|
|
350
|
+
// 用户 abort:FetchClient 将 AbortError 转为 onDone,不重连
|
|
351
|
+
if (manualAbort || runFinished) {
|
|
352
|
+
finishSuccessfully();
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
// 连接被干净掐断且未收到 RUN_FINISHED:尝试静默重连
|
|
356
|
+
void attemptSilentReconnect(sessionCode).then((result)=>{
|
|
357
|
+
if (result === 'reconnected') {
|
|
358
|
+
// 保持 isChatting=true,不展示错误
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
if (result === 'finished') {
|
|
362
|
+
finishSuccessfully();
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
// abort / 切会话导致的失败:静默结束,不展示错误气泡
|
|
366
|
+
if (manualAbort || !isSameActiveSession(sessionCode)) {
|
|
367
|
+
isChatting.value = false;
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
failWithError(new Error('Connection lost, please try again'));
|
|
371
|
+
});
|
|
372
|
+
};
|
|
373
|
+
const onError = (error)=>{
|
|
374
|
+
if (manualAbort) {
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
if (!isRecoverableStreamError(error)) {
|
|
378
|
+
failWithError(error);
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
void attemptSilentReconnect(sessionCode).then((result)=>{
|
|
382
|
+
if (result === 'reconnected') {
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
if (result === 'finished') {
|
|
386
|
+
finishSuccessfully();
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
if (manualAbort || !isSameActiveSession(sessionCode)) {
|
|
390
|
+
isChatting.value = false;
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
failWithError(error);
|
|
394
|
+
});
|
|
395
|
+
};
|
|
180
396
|
const onMessage = (event)=>{
|
|
181
397
|
var _usedProtocol_onMessage;
|
|
398
|
+
const typedEvent = event;
|
|
399
|
+
if ((typedEvent === null || typedEvent === void 0 ? void 0 : typedEvent.type) === EventType.RunFinished) {
|
|
400
|
+
runFinished = true;
|
|
401
|
+
}
|
|
182
402
|
(_usedProtocol_onMessage = usedProtocol.onMessage) === null || _usedProtocol_onMessage === void 0 ? void 0 : _usedProtocol_onMessage.call(usedProtocol, event);
|
|
183
403
|
};
|
|
184
404
|
const onStart = ()=>{
|
|
@@ -194,6 +414,7 @@ import { SessionStatus } from '../session/type.ts.js';
|
|
|
194
414
|
method: 'POST',
|
|
195
415
|
data: {
|
|
196
416
|
session_code: sessionCode,
|
|
417
|
+
model,
|
|
197
418
|
input,
|
|
198
419
|
execute_kwargs: {
|
|
199
420
|
stream: true,
|
|
@@ -222,8 +443,9 @@ import { SessionStatus } from '../session/type.ts.js';
|
|
|
222
443
|
* @param url - 请求 URL(可选)
|
|
223
444
|
* @param config - 请求配置(可选)
|
|
224
445
|
* @param property - 消息属性,用于传递引用内容或快捷键相关信息(可选)
|
|
446
|
+
* @param model - 模型标识(可选)
|
|
225
447
|
*/ const chat = function() {
|
|
226
|
-
var _ref = _async_to_generator(function*(userInput, sessionCode, url, config, property) {
|
|
448
|
+
var _ref = _async_to_generator(function*(userInput, sessionCode, url, config, property, model) {
|
|
227
449
|
var _mediator_message;
|
|
228
450
|
// 先新增一个 message
|
|
229
451
|
yield (_mediator_message = mediator.message) === null || _mediator_message === void 0 ? void 0 : _mediator_message.createAndPlusMessage(_object_spread({
|
|
@@ -237,11 +459,12 @@ import { SessionStatus } from '../session/type.ts.js';
|
|
|
237
459
|
// 发起聊天
|
|
238
460
|
streamRequest({
|
|
239
461
|
sessionCode,
|
|
462
|
+
model,
|
|
240
463
|
url,
|
|
241
464
|
config
|
|
242
465
|
});
|
|
243
466
|
});
|
|
244
|
-
return function chat(userInput, sessionCode, url, config, property) {
|
|
467
|
+
return function chat(userInput, sessionCode, url, config, property, model) {
|
|
245
468
|
return _ref.apply(this, arguments);
|
|
246
469
|
};
|
|
247
470
|
}();
|
|
@@ -251,13 +474,15 @@ import { SessionStatus } from '../session/type.ts.js';
|
|
|
251
474
|
* @param sessionCode - 会话代码
|
|
252
475
|
* @param url - 请求 URL(可选)
|
|
253
476
|
* @param config - 请求配置(可选)
|
|
254
|
-
|
|
477
|
+
* @param model - 模型标识(可选)
|
|
478
|
+
*/ const resumeStreamingChat = (sessionCode, url, config, model)=>{
|
|
255
479
|
var _mediator_session_current_value, _mediator_session;
|
|
256
480
|
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) {
|
|
257
481
|
var _mediator_message_list_value_at, _mediator_message;
|
|
258
482
|
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
483
|
streamRequest({
|
|
260
484
|
sessionCode,
|
|
485
|
+
model,
|
|
261
486
|
url,
|
|
262
487
|
config,
|
|
263
488
|
lastMessageId
|
|
@@ -268,7 +493,7 @@ import { SessionStatus } from '../session/type.ts.js';
|
|
|
268
493
|
* 轮询接口,判断是否可以继续聊天
|
|
269
494
|
* @param sessionCode - 会话编码
|
|
270
495
|
* @returns 是否可以继续聊天
|
|
271
|
-
*/ const pollResumeSession = (sessionCode)=>{
|
|
496
|
+
*/ const pollResumeSession = (sessionCode, model)=>{
|
|
272
497
|
var _mediator_message, _lastMessage_content_outcome, _lastMessage_content;
|
|
273
498
|
const lastMessage = (_mediator_message = mediator.message) === null || _mediator_message === void 0 ? void 0 : _mediator_message.list.value.at(-1);
|
|
274
499
|
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)=>{
|
|
@@ -295,6 +520,7 @@ import { SessionStatus } from '../session/type.ts.js';
|
|
|
295
520
|
// 可以继续聊天,重新发起聊天(携带 execute_kwargs.resume 通知后端恢复中断)
|
|
296
521
|
streamRequest({
|
|
297
522
|
sessionCode,
|
|
523
|
+
model,
|
|
298
524
|
resume: {
|
|
299
525
|
interruptId: pendingApprovalInterrupt.id,
|
|
300
526
|
status: ResumeStatus.Resolved
|
|
@@ -305,7 +531,7 @@ import { SessionStatus } from '../session/type.ts.js';
|
|
|
305
531
|
var _mediator_session_current_value, _mediator_session_current, _mediator_session;
|
|
306
532
|
// 如果会话不匹配,则不继续轮询
|
|
307
533
|
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;
|
|
308
|
-
pollResumeSession(sessionCode);
|
|
534
|
+
pollResumeSession(sessionCode, model);
|
|
309
535
|
}, 10000);
|
|
310
536
|
}
|
|
311
537
|
});
|
|
@@ -322,6 +548,8 @@ import { SessionStatus } from '../session/type.ts.js';
|
|
|
322
548
|
* 中止聊天(纯前端中止,后端继续处理)
|
|
323
549
|
*/ const abortChat = ()=>{
|
|
324
550
|
var _chatAbortController_abort;
|
|
551
|
+
manualAbort = true;
|
|
552
|
+
clearReconnectTimer(false);
|
|
325
553
|
chatAbortController === null || chatAbortController === void 0 ? void 0 : (_chatAbortController_abort = chatAbortController.abort) === null || _chatAbortController_abort === void 0 ? void 0 : _chatAbortController_abort.call(chatAbortController);
|
|
326
554
|
chatAbortController = null;
|
|
327
555
|
};
|
|
@@ -346,8 +574,9 @@ import { SessionStatus } from '../session/type.ts.js';
|
|
|
346
574
|
* @param newContent - 新内容(可选,不传则使用原消息内容;支持多模态)
|
|
347
575
|
* @param url - 请求 URL(可选)
|
|
348
576
|
* @param config - 请求配置(可选)
|
|
577
|
+
* @param model - 模型标识(可选)
|
|
349
578
|
*/ const resendMessage = function() {
|
|
350
|
-
var _ref = _async_to_generator(function*(messageId, sessionCode, newContent, url, config) {
|
|
579
|
+
var _ref = _async_to_generator(function*(messageId, sessionCode, newContent, url, config, model) {
|
|
351
580
|
var _mediator_message, _mediator_message1, _mediator_message2;
|
|
352
581
|
const messages = ((_mediator_message = mediator.message) === null || _mediator_message === void 0 ? void 0 : _mediator_message.list.value) || [];
|
|
353
582
|
// 1. 找到目标用户消息
|
|
@@ -380,6 +609,7 @@ import { SessionStatus } from '../session/type.ts.js';
|
|
|
380
609
|
// 6. 立即发起流式请求(不等待删除和创建的 API 完成)
|
|
381
610
|
streamRequest({
|
|
382
611
|
sessionCode,
|
|
612
|
+
model,
|
|
383
613
|
url,
|
|
384
614
|
config
|
|
385
615
|
});
|
|
@@ -391,20 +621,29 @@ import { SessionStatus } from '../session/type.ts.js';
|
|
|
391
621
|
console.error('[resendMessage] API error:', error);
|
|
392
622
|
});
|
|
393
623
|
});
|
|
394
|
-
return function resendMessage(messageId, sessionCode, newContent, url, config) {
|
|
624
|
+
return function resendMessage(messageId, sessionCode, newContent, url, config, model) {
|
|
395
625
|
return _ref.apply(this, arguments);
|
|
396
626
|
};
|
|
397
627
|
}();
|
|
398
628
|
const reset = (protocol)=>{
|
|
399
|
-
|
|
629
|
+
abortChat();
|
|
630
|
+
// 重置状态(保留 manualAbort=true,避免 abort 异步 onDone 误触发重连;下次 streamRequest 会复位)
|
|
400
631
|
usedProtocol = protocol || new AGUIProtocol();
|
|
401
632
|
info.value = null;
|
|
402
633
|
isInfoLoading.value = false;
|
|
634
|
+
isChatting.value = false;
|
|
635
|
+
models.value = [];
|
|
636
|
+
isModelsLoading.value = false;
|
|
637
|
+
activeStreamContext = null;
|
|
638
|
+
reconnectAttempt = 0;
|
|
639
|
+
runFinished = false;
|
|
403
640
|
};
|
|
404
641
|
return {
|
|
405
642
|
info,
|
|
406
643
|
isInfoLoading,
|
|
407
644
|
isChatting,
|
|
645
|
+
models,
|
|
646
|
+
isModelsLoading,
|
|
408
647
|
chat,
|
|
409
648
|
handleRole,
|
|
410
649
|
resendMessage,
|
|
@@ -412,6 +651,7 @@ import { SessionStatus } from '../session/type.ts.js';
|
|
|
412
651
|
abortChat,
|
|
413
652
|
stopChat,
|
|
414
653
|
getAgentInfo,
|
|
654
|
+
getLlms,
|
|
415
655
|
reset,
|
|
416
656
|
pollResumeSession,
|
|
417
657
|
clearLongPollTimer,
|
package/dist/event/ag-ui.d.ts
CHANGED
|
@@ -27,6 +27,7 @@ export declare class AGUIProtocol implements ISSEProtocol {
|
|
|
27
27
|
* 记录活动的完整状态
|
|
28
28
|
*/
|
|
29
29
|
handleActivitySnapshotEvent(event: IActivitySnapshotEvent): void;
|
|
30
|
+
handleArtifactsGeneratedCustomEvent(event: ICustomEvent): void;
|
|
30
31
|
/**
|
|
31
32
|
* 处理自定义事件
|
|
32
33
|
*/
|
|
@@ -51,6 +52,7 @@ export declare class AGUIProtocol implements ISSEProtocol {
|
|
|
51
52
|
* 自定义事件 处理流程编排任务更新
|
|
52
53
|
*/
|
|
53
54
|
handleFlowAgentUpdateCustomEvent(event: ICustomEvent): void;
|
|
55
|
+
handleInfoCustomEvent(event: ICustomEvent): void;
|
|
54
56
|
/**
|
|
55
57
|
* 自定义事件 处理意图识别结束
|
|
56
58
|
*/
|
|
@@ -131,6 +133,7 @@ export declare class AGUIProtocol implements ISSEProtocol {
|
|
|
131
133
|
handleTextMessageEndEvent(event: ITextMessageEndEvent): void;
|
|
132
134
|
/**
|
|
133
135
|
* 处理文本消息开始事件
|
|
136
|
+
* 断线续传时 DLQ 会重放事件:同 messageId 已存在则重置内容,避免重复气泡/文本翻倍
|
|
134
137
|
*/
|
|
135
138
|
handleTextMessageStartEvent(event: ITextMessageStartEvent): void;
|
|
136
139
|
/**
|
package/dist/event/ag-ui.ts.js
CHANGED
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
}
|
|
36
36
|
return obj;
|
|
37
37
|
}
|
|
38
|
-
import { transferMessageApi2Message } from '../http/transform/index.ts.js';
|
|
38
|
+
import { mergeArtifactsActivityIntoMessages, transferMessageApi2Message } from '../http/transform/index.ts.js';
|
|
39
39
|
import { ActivityType, MessageRole, MessageStatus, MessageType } from '../message/index.ts.js';
|
|
40
40
|
import { CustomEventName, EventType, FlowTaskState, RunFinishedOutcomeType } from './type.ts.js';
|
|
41
41
|
/**
|
|
@@ -50,18 +50,38 @@ import { CustomEventName, EventType, FlowTaskState, RunFinishedOutcomeType } fro
|
|
|
50
50
|
* 处理活动快照事件
|
|
51
51
|
* 记录活动的完整状态
|
|
52
52
|
*/ handleActivitySnapshotEvent(event) {
|
|
53
|
-
|
|
53
|
+
if (event.activityType === ActivityType.Info) {
|
|
54
|
+
const message = this.messageModule.getMessageByMessageId(event.messageId);
|
|
55
|
+
if ((message === null || message === void 0 ? void 0 : message.role) === MessageRole.Info) {
|
|
56
|
+
message.content = event.content;
|
|
57
|
+
}
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
54
60
|
if (event.activityType === ActivityType.Interrupt) {
|
|
61
|
+
const message = this.messageModule.getCurrentLoadingMessage();
|
|
55
62
|
if ((message === null || message === void 0 ? void 0 : message.role) === MessageRole.Interrupt) {
|
|
56
63
|
message.content = event.content;
|
|
57
64
|
message.status = MessageStatus.Complete;
|
|
58
65
|
}
|
|
59
66
|
}
|
|
60
67
|
}
|
|
68
|
+
handleArtifactsGeneratedCustomEvent(event) {
|
|
69
|
+
const message = this.messageModule.list.value.findLast((item)=>item.role === MessageRole.Assistant);
|
|
70
|
+
if (message) {
|
|
71
|
+
var _message;
|
|
72
|
+
const value = event.value;
|
|
73
|
+
var _property;
|
|
74
|
+
(_property = (_message = message).property) !== null && _property !== void 0 ? _property : _message.property = {};
|
|
75
|
+
message.property.artifacts = value.artifacts;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
61
78
|
/**
|
|
62
79
|
* 处理自定义事件
|
|
63
80
|
*/ handleCustomEvent(event) {
|
|
64
81
|
switch(event.name){
|
|
82
|
+
case CustomEventName.ArtifactsGenerated:
|
|
83
|
+
this.handleArtifactsGeneratedCustomEvent(event);
|
|
84
|
+
break;
|
|
65
85
|
case CustomEventName.FlowAgentStart:
|
|
66
86
|
this.handleFlowAgentStartCustomEvent(event);
|
|
67
87
|
break;
|
|
@@ -98,6 +118,9 @@ import { CustomEventName, EventType, FlowTaskState, RunFinishedOutcomeType } fro
|
|
|
98
118
|
case CustomEventName.FlowAgentUpdate:
|
|
99
119
|
this.handleFlowAgentUpdateCustomEvent(event);
|
|
100
120
|
break;
|
|
121
|
+
case CustomEventName.Info:
|
|
122
|
+
this.handleInfoCustomEvent(event);
|
|
123
|
+
break;
|
|
101
124
|
default:
|
|
102
125
|
break;
|
|
103
126
|
}
|
|
@@ -171,6 +194,15 @@ import { CustomEventName, EventType, FlowTaskState, RunFinishedOutcomeType } fro
|
|
|
171
194
|
}
|
|
172
195
|
});
|
|
173
196
|
}
|
|
197
|
+
handleInfoCustomEvent(event) {
|
|
198
|
+
const value = event.value;
|
|
199
|
+
this.messageModule.plusMessage({
|
|
200
|
+
role: MessageRole.Info,
|
|
201
|
+
messageId: value.messageId,
|
|
202
|
+
content: value.content,
|
|
203
|
+
status: MessageStatus.Complete
|
|
204
|
+
});
|
|
205
|
+
}
|
|
174
206
|
/**
|
|
175
207
|
* 自定义事件 处理意图识别结束
|
|
176
208
|
*/ handleKnowledgeRagEndCustomEvent(_event) {
|
|
@@ -214,7 +246,7 @@ import { CustomEventName, EventType, FlowTaskState, RunFinishedOutcomeType } fro
|
|
|
214
246
|
* 用于同步多端消息状态
|
|
215
247
|
*/ handleMessagesSnapshotEvent(event) {
|
|
216
248
|
if (event.messages && event.messages.length > 0) {
|
|
217
|
-
this.messageModule.list.value = event.messages.map(transferMessageApi2Message);
|
|
249
|
+
this.messageModule.list.value = mergeArtifactsActivityIntoMessages(event.messages.map(transferMessageApi2Message));
|
|
218
250
|
}
|
|
219
251
|
}
|
|
220
252
|
/**
|
|
@@ -349,7 +381,14 @@ import { CustomEventName, EventType, FlowTaskState, RunFinishedOutcomeType } fro
|
|
|
349
381
|
}
|
|
350
382
|
/**
|
|
351
383
|
* 处理文本消息开始事件
|
|
384
|
+
* 断线续传时 DLQ 会重放事件:同 messageId 已存在则重置内容,避免重复气泡/文本翻倍
|
|
352
385
|
*/ handleTextMessageStartEvent(event) {
|
|
386
|
+
const existing = this.messageModule.getMessageByMessageId(event.messageId);
|
|
387
|
+
if (existing) {
|
|
388
|
+
existing.content = '';
|
|
389
|
+
existing.status = MessageStatus.Streaming;
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
353
392
|
this.messageModule.plusMessage({
|
|
354
393
|
role: event.role,
|
|
355
394
|
content: '',
|
package/dist/event/type.d.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import { type IMessageApi, type MessageRole, type MessageStatus } from '../message/type';
|
|
1
|
+
import { type IMessageApi, type IMessageArtifact, type MessageRole, type MessageStatus } from '../message/type';
|
|
2
2
|
import type { JSONSchema4 } from 'json-schema';
|
|
3
3
|
export declare enum CustomEventName {
|
|
4
|
+
ArtifactsGenerated = "artifacts_generated",
|
|
4
5
|
FlowAgentEnd = "flow_agent_end",
|
|
5
6
|
FlowAgentResult = "flow_agent_result",
|
|
6
7
|
FlowAgentStart = "flow_agent_start",
|
|
7
8
|
FlowAgentUpdate = "flow_agent_update",
|
|
8
9
|
FlowAgentRestart = "flow_agent_restart",
|
|
10
|
+
Info = "info",
|
|
9
11
|
KnowledgeRagEnd = "knowledge_rag_end",
|
|
10
12
|
KnowledgeRagResult = "knowledge_rag_result",
|
|
11
13
|
KnowledgeRagStart = "knowledge_rag_start",
|
|
@@ -114,6 +116,11 @@ export interface IActivitySnapshotEvent extends IBaseEvent {
|
|
|
114
116
|
replace?: boolean;
|
|
115
117
|
type: EventType.ActivitySnapshot;
|
|
116
118
|
}
|
|
119
|
+
export interface IArtifactsGeneratedCustomValue {
|
|
120
|
+
artifacts: IMessageArtifact[];
|
|
121
|
+
runId: string;
|
|
122
|
+
status: 'complete' | 'empty';
|
|
123
|
+
}
|
|
117
124
|
export interface IBaseEvent {
|
|
118
125
|
timestamp?: number;
|
|
119
126
|
type: EventType;
|
|
@@ -125,7 +132,7 @@ export interface IBaseEvent {
|
|
|
125
132
|
export interface ICustomEvent extends IBaseEvent {
|
|
126
133
|
name: CustomEventName;
|
|
127
134
|
type: EventType.Custom;
|
|
128
|
-
value: IFlowAgentEndCustomValue | IFlowAgentResultCustomValue | IFlowAgentStartCustomValue | IFlowAgentRestartCustomValue | IKnowledgeRagResultCustomValue | IKnowledgeRagTextContentCustomValue | IReferenceDocumentCustomValue | ITempMessageCustomValue | IApprovalResultCustomValue;
|
|
135
|
+
value: IArtifactsGeneratedCustomValue | IFlowAgentEndCustomValue | IFlowAgentResultCustomValue | IFlowAgentStartCustomValue | IFlowAgentRestartCustomValue | IInfoCustomValue | IKnowledgeRagResultCustomValue | IKnowledgeRagTextContentCustomValue | IReferenceDocumentCustomValue | ITempMessageCustomValue | IApprovalResultCustomValue;
|
|
129
136
|
}
|
|
130
137
|
export type IEvent = IActivityDeltaEvent | IActivitySnapshotEvent | ICustomEvent | IMessagesSnapshotEvent | IRawEvent | IRunErrorEvent | IRunFinishedEvent | IRunStartedEvent | IStateDeltaEvent | IStateSnapshotEvent | IStepFinishedEvent | IStepStartedEvent | ITextMessageChunkEvent | ITextMessageContentEvent | ITextMessageEndEvent | ITextMessageStartEvent | IThinkingEndEvent | IThinkingStartEvent | IThinkingTextMessageContentEvent | IThinkingTextMessageEndEvent | IThinkingTextMessageStartEvent | IToolCallArgsEvent | IToolCallChunkEvent | IToolCallEndEvent | IToolCallResultEvent | IToolCallStartEvent;
|
|
131
138
|
export type IFlowAgentEndCustomValue = {
|
|
@@ -152,6 +159,10 @@ export type IFlowAgentStartCustomValue = {
|
|
|
152
159
|
task_id: string;
|
|
153
160
|
}[];
|
|
154
161
|
export type IFlowAgentRestartCustomValue = IFlowAgentStartCustomValue;
|
|
162
|
+
export interface IInfoCustomValue {
|
|
163
|
+
content: string;
|
|
164
|
+
messageId: string;
|
|
165
|
+
}
|
|
155
166
|
export type IKnowledgeRagResultCustomValue = IReferenceDocumentCustomValue;
|
|
156
167
|
export interface IKnowledgeRagTextContentCustomValue {
|
|
157
168
|
cover: boolean;
|
package/dist/event/type.ts.js
CHANGED
|
@@ -24,11 +24,13 @@
|
|
|
24
24
|
* IN THE SOFTWARE.
|
|
25
25
|
*/ export var CustomEventName;
|
|
26
26
|
(function(CustomEventName) {
|
|
27
|
+
CustomEventName["ArtifactsGenerated"] = "artifacts_generated";
|
|
27
28
|
CustomEventName["FlowAgentEnd"] = "flow_agent_end";
|
|
28
29
|
CustomEventName["FlowAgentResult"] = "flow_agent_result";
|
|
29
30
|
CustomEventName["FlowAgentStart"] = "flow_agent_start";
|
|
30
31
|
CustomEventName["FlowAgentUpdate"] = "flow_agent_update";
|
|
31
32
|
CustomEventName["FlowAgentRestart"] = "flow_agent_restart";
|
|
33
|
+
CustomEventName["Info"] = "info";
|
|
32
34
|
CustomEventName["KnowledgeRagEnd"] = "knowledge_rag_end";
|
|
33
35
|
CustomEventName["KnowledgeRagResult"] = "knowledge_rag_result";
|
|
34
36
|
CustomEventName["KnowledgeRagStart"] = "knowledge_rag_start";
|
package/dist/http/index.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export declare const useHttp: (options: IUseChatHelperOptions) => {
|
|
|
12
12
|
onError: (handler: import("./fetch").GlobalErrorHandler, options?: import("./fetch").ErrorHandlerOptions) => void;
|
|
13
13
|
agent: {
|
|
14
14
|
getAgentInfo: (config?: import("./fetch").IRequestConfig) => Promise<import("..").IAgentInfo>;
|
|
15
|
+
getLlms: (params?: import("..").ILlmListQuery, config?: import("./fetch").IRequestConfig) => Promise<import("..").ILlmItem[]>;
|
|
15
16
|
};
|
|
16
17
|
session: {
|
|
17
18
|
clearSession: (sessionCode: string, config?: import("./fetch").IRequestConfig) => Promise<unknown>;
|
|
@@ -38,6 +39,7 @@ export declare const useHttp: (options: IUseChatHelperOptions) => {
|
|
|
38
39
|
uploadFile: (sessionCode: string, file: File, config?: import("./fetch").IRequestConfig) => Promise<{
|
|
39
40
|
download_url?: string;
|
|
40
41
|
}>;
|
|
42
|
+
getPvFileDownloadUrl: (sessionCode: string, path: string, options?: import("..").GetPvFileDownloadUrlOptions, config?: import("./fetch").IRequestConfig) => Promise<import("..").IPvFileDownloadUrlResult>;
|
|
41
43
|
isResumeSession: (sessionCode: string, config?: import("./fetch").IRequestConfig) => Promise<boolean>;
|
|
42
44
|
};
|
|
43
45
|
message: {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ILlmItem, ILlmListQuery } from '../../agent/type';
|
|
1
2
|
import type { FetchClient, IRequestConfig } from '../fetch';
|
|
2
3
|
/**
|
|
3
4
|
* agent 相关 http 接口
|
|
@@ -6,4 +7,5 @@ import type { FetchClient, IRequestConfig } from '../fetch';
|
|
|
6
7
|
*/
|
|
7
8
|
export declare const useAgent: (fetchClient: FetchClient) => {
|
|
8
9
|
getAgentInfo: (config?: IRequestConfig) => Promise<import("../../agent/type").IAgentInfo>;
|
|
10
|
+
getLlms: (params?: ILlmListQuery, config?: IRequestConfig) => Promise<ILlmItem[]>;
|
|
9
11
|
};
|