@agentscope-ai/chat 1.1.66 → 1.1.67
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/components/AgentScopeRuntimeWebUI/core/AgentScopeRuntime/Request/Actions.tsx +8 -4
- package/components/AgentScopeRuntimeWebUI/core/AgentScopeRuntime/Request/Builder.tsx +7 -1
- package/components/AgentScopeRuntimeWebUI/core/AgentScopeRuntime/Request/Card.tsx +5 -1
- package/components/AgentScopeRuntimeWebUI/core/AgentScopeRuntime/Response/Actions.tsx +1 -1
- package/components/AgentScopeRuntimeWebUI/core/AgentScopeRuntime/Response/Builder.tsx +34 -3
- package/components/AgentScopeRuntimeWebUI/core/AgentScopeRuntime/Response/Message.tsx +2 -1
- package/components/AgentScopeRuntimeWebUI/core/AgentScopeRuntime/types.tsx +1 -0
- package/components/AgentScopeRuntimeWebUI/core/Chat/hooks/useChatController.tsx +129 -33
- package/components/AgentScopeRuntimeWebUI/core/Chat/hooks/useChatRequest.tsx +74 -39
- package/components/AgentScopeRuntimeWebUI/core/types/IChatAnywhere.ts +10 -0
- package/components/DefaultCards/Files/index.tsx +5 -1
- package/components/Markdown/Markdown.tsx +2 -1
- package/lib/AgentScopeRuntimeWebUI/core/AgentScopeRuntime/Request/Actions.js +8 -1
- package/lib/AgentScopeRuntimeWebUI/core/AgentScopeRuntime/Request/Builder.js +4 -0
- package/lib/AgentScopeRuntimeWebUI/core/AgentScopeRuntime/Request/Card.js +8 -2
- package/lib/AgentScopeRuntimeWebUI/core/AgentScopeRuntime/Response/Actions.js +1 -1
- package/lib/AgentScopeRuntimeWebUI/core/AgentScopeRuntime/Response/Builder.js +58 -12
- package/lib/AgentScopeRuntimeWebUI/core/AgentScopeRuntime/Response/Message.js +6 -1
- package/lib/AgentScopeRuntimeWebUI/core/AgentScopeRuntime/types.d.ts +1 -0
- package/lib/AgentScopeRuntimeWebUI/core/Chat/hooks/useChatController.d.ts +1 -1
- package/lib/AgentScopeRuntimeWebUI/core/Chat/hooks/useChatController.js +167 -68
- package/lib/AgentScopeRuntimeWebUI/core/Chat/hooks/useChatRequest.d.ts +7 -3
- package/lib/AgentScopeRuntimeWebUI/core/Chat/hooks/useChatRequest.js +151 -117
- package/lib/AgentScopeRuntimeWebUI/core/types/IChatAnywhere.d.ts +15 -0
- package/lib/DefaultCards/Files/index.js +5 -1
- package/lib/Markdown/Markdown.js +1 -0
- package/package.json +1 -1
|
@@ -11,11 +11,12 @@ import useChatAnywhereEventEmitter from "../../Context/useChatAnywhereEventEmitt
|
|
|
11
11
|
import useChatMessageHandler from "./useChatMessageHandler";
|
|
12
12
|
import useChatRequest from "./useChatRequest";
|
|
13
13
|
import useChatSessionHandler from "./useChatSessionHandler";
|
|
14
|
+
import { useChatAnywhereOptions } from "../../Context/ChatAnywhereOptionsContext";
|
|
14
15
|
import ReactDOM from "react-dom";
|
|
15
16
|
// import mockdata from '../../mock/mock.json'
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
|
-
*
|
|
19
|
+
* Chat controller hook — coordinates all chat-related operations.
|
|
19
20
|
*/
|
|
20
21
|
export default function useChatController() {
|
|
21
22
|
var setLoading = useContextSelector(ChatAnywhereInputContext, function (v) {
|
|
@@ -24,18 +25,27 @@ export default function useChatController() {
|
|
|
24
25
|
var currentSessionId = useContextSelector(ChatAnywhereSessionsContext, function (v) {
|
|
25
26
|
return v.currentSessionId;
|
|
26
27
|
});
|
|
27
|
-
var
|
|
28
|
+
var apiOptions = useChatAnywhereOptions(function (v) {
|
|
29
|
+
return v.api;
|
|
30
|
+
});
|
|
31
|
+
var apiOptionsRef = useRef(apiOptions);
|
|
32
|
+
useEffect(function () {
|
|
33
|
+
apiOptionsRef.current = apiOptions;
|
|
34
|
+
}, [apiOptions]);
|
|
35
|
+
var currentQARef = useRef({
|
|
36
|
+
activeRequestId: 0
|
|
37
|
+
});
|
|
28
38
|
|
|
29
|
-
//
|
|
39
|
+
// Message handler
|
|
30
40
|
var messageHandler = useChatMessageHandler({
|
|
31
41
|
currentQARef: currentQARef
|
|
32
42
|
});
|
|
33
43
|
|
|
34
|
-
//
|
|
44
|
+
// Session handler
|
|
35
45
|
var sessionHandler = useChatSessionHandler();
|
|
36
46
|
|
|
37
47
|
/**
|
|
38
|
-
*
|
|
48
|
+
* Finalize the current response and reset UI loading state.
|
|
39
49
|
*/
|
|
40
50
|
var finishResponse = useCallback(function () {
|
|
41
51
|
var status = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'finished';
|
|
@@ -48,7 +58,7 @@ export default function useChatController() {
|
|
|
48
58
|
sessionHandler.syncSessionMessages(messageHandler.getMessages());
|
|
49
59
|
}, [setLoading, messageHandler, sessionHandler]);
|
|
50
60
|
|
|
51
|
-
// API
|
|
61
|
+
// API request handling
|
|
52
62
|
var _useChatRequest = useChatRequest({
|
|
53
63
|
currentQARef: currentQARef,
|
|
54
64
|
updateMessage: messageHandler.updateMessage,
|
|
@@ -61,43 +71,65 @@ export default function useChatController() {
|
|
|
61
71
|
reconnect = _useChatRequest.reconnect;
|
|
62
72
|
|
|
63
73
|
/**
|
|
64
|
-
*
|
|
74
|
+
* Handle user message submission.
|
|
65
75
|
*/
|
|
66
76
|
var handleSubmit = useCallback( /*#__PURE__*/function () {
|
|
67
77
|
var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(data) {
|
|
68
|
-
var
|
|
78
|
+
var _currentQARef$current;
|
|
79
|
+
var myRequestId, messages, historyMessages;
|
|
69
80
|
return _regeneratorRuntime().wrap(function _callee$(_context) {
|
|
70
81
|
while (1) switch (_context.prev = _context.next) {
|
|
71
82
|
case 0:
|
|
72
|
-
|
|
83
|
+
// 0. Abort any previous in-flight SSE. We do NOT call the cancel API here
|
|
84
|
+
// — the user is sending a new message, not explicitly cancelling.
|
|
85
|
+
// Cancel is only invoked from handleCancel.
|
|
86
|
+
(_currentQARef$current = currentQARef.current.abortController) === null || _currentQARef$current === void 0 || _currentQARef$current.abort();
|
|
87
|
+
|
|
88
|
+
// 1. Ensure session exists FIRST. Bumping activeRequestId before this can
|
|
89
|
+
// race with the [currentSessionId] effect below: ensureSession may set
|
|
90
|
+
// a new sessionId, that effect then bumps activeRequestId again, and
|
|
91
|
+
// our own myRequestId becomes stale → the guard after sleep(100) bails
|
|
92
|
+
// out and the request is silently dropped. Establishing the session
|
|
93
|
+
// first guarantees the effect (if any) has flushed before we snapshot
|
|
94
|
+
// myRequestId.
|
|
95
|
+
_context.next = 3;
|
|
73
96
|
return sessionHandler.ensureSession(data.query);
|
|
74
|
-
case
|
|
75
|
-
|
|
97
|
+
case 3:
|
|
98
|
+
myRequestId = ++currentQARef.current.activeRequestId; // Snapshot current session id for downstream SSE guard checks
|
|
99
|
+
currentQARef.current.activeSessionId = sessionHandler.getCurrentSessionId();
|
|
100
|
+
|
|
101
|
+
// 2. Update session name (only for the first message)
|
|
76
102
|
messages = messageHandler.getMessages();
|
|
77
103
|
if (!sessionHandler.getCurrentSessionId()) {
|
|
78
|
-
_context.next =
|
|
104
|
+
_context.next = 9;
|
|
79
105
|
break;
|
|
80
106
|
}
|
|
81
|
-
_context.next =
|
|
107
|
+
_context.next = 9;
|
|
82
108
|
return sessionHandler.updateSessionName(data.query, messages);
|
|
83
|
-
case
|
|
84
|
-
// 3.
|
|
109
|
+
case 9:
|
|
110
|
+
// 3. Create user request message
|
|
85
111
|
messageHandler.createRequestMessage(data);
|
|
86
112
|
setLoading(true);
|
|
87
|
-
_context.next =
|
|
113
|
+
_context.next = 13;
|
|
88
114
|
return sleep(100);
|
|
89
|
-
case
|
|
90
|
-
|
|
115
|
+
case 13:
|
|
116
|
+
if (!(myRequestId !== currentQARef.current.activeRequestId)) {
|
|
117
|
+
_context.next = 15;
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
return _context.abrupt("return");
|
|
121
|
+
case 15:
|
|
122
|
+
// 4. Create assistant response placeholder
|
|
91
123
|
messageHandler.createResponseMessage();
|
|
92
124
|
|
|
93
|
-
// 5.
|
|
125
|
+
// 5. Gather history messages and fire the request
|
|
94
126
|
historyMessages = messageHandler.getHistoryMessages();
|
|
95
|
-
_context.next =
|
|
127
|
+
_context.next = 19;
|
|
96
128
|
return sessionHandler.syncSessionMessages(messageHandler.getMessages());
|
|
97
|
-
case
|
|
98
|
-
_context.next =
|
|
99
|
-
return request(historyMessages, data.biz_params);
|
|
100
|
-
case
|
|
129
|
+
case 19:
|
|
130
|
+
_context.next = 21;
|
|
131
|
+
return request(historyMessages, data.biz_params, myRequestId);
|
|
132
|
+
case 21:
|
|
101
133
|
case "end":
|
|
102
134
|
return _context.stop();
|
|
103
135
|
}
|
|
@@ -106,27 +138,40 @@ export default function useChatController() {
|
|
|
106
138
|
return function (_x) {
|
|
107
139
|
return _ref.apply(this, arguments);
|
|
108
140
|
};
|
|
109
|
-
}(), [messageHandler, sessionHandler, request]);
|
|
141
|
+
}(), [messageHandler, sessionHandler, request, setLoading]);
|
|
110
142
|
var handleApproval = useCallback( /*#__PURE__*/function () {
|
|
111
143
|
var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(_ref2) {
|
|
112
|
-
var
|
|
144
|
+
var _currentQARef$current2;
|
|
145
|
+
var input, myRequestId, historyMessages;
|
|
113
146
|
return _regeneratorRuntime().wrap(function _callee2$(_context2) {
|
|
114
147
|
while (1) switch (_context2.prev = _context2.next) {
|
|
115
148
|
case 0:
|
|
116
149
|
input = _ref2.input;
|
|
150
|
+
(_currentQARef$current2 = currentQARef.current.abortController) === null || _currentQARef$current2 === void 0 || _currentQARef$current2.abort();
|
|
151
|
+
// Snapshot the current session id BEFORE bumping requestId, then bump.
|
|
152
|
+
// Order matches handleSubmit so a concurrent session-change effect cannot
|
|
153
|
+
// invalidate myRequestId between the bump and the sleep guard below.
|
|
154
|
+
currentQARef.current.activeSessionId = sessionHandler.getCurrentSessionId();
|
|
155
|
+
myRequestId = ++currentQARef.current.activeRequestId;
|
|
117
156
|
messageHandler.createApprovalMessage(input);
|
|
118
157
|
setLoading(true);
|
|
119
|
-
_context2.next =
|
|
158
|
+
_context2.next = 8;
|
|
120
159
|
return sleep(100);
|
|
121
|
-
case
|
|
160
|
+
case 8:
|
|
161
|
+
if (!(myRequestId !== currentQARef.current.activeRequestId)) {
|
|
162
|
+
_context2.next = 10;
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
return _context2.abrupt("return");
|
|
166
|
+
case 10:
|
|
122
167
|
messageHandler.createResponseMessage();
|
|
123
168
|
historyMessages = messageHandler.getHistoryMessages();
|
|
124
|
-
_context2.next =
|
|
169
|
+
_context2.next = 14;
|
|
125
170
|
return sessionHandler.syncSessionMessages(messageHandler.getMessages());
|
|
126
|
-
case
|
|
127
|
-
_context2.next =
|
|
128
|
-
return request(historyMessages);
|
|
129
|
-
case
|
|
171
|
+
case 14:
|
|
172
|
+
_context2.next = 16;
|
|
173
|
+
return request(historyMessages, undefined, myRequestId);
|
|
174
|
+
case 16:
|
|
130
175
|
case "end":
|
|
131
176
|
return _context2.stop();
|
|
132
177
|
}
|
|
@@ -135,43 +180,71 @@ export default function useChatController() {
|
|
|
135
180
|
return function (_x2) {
|
|
136
181
|
return _ref3.apply(this, arguments);
|
|
137
182
|
};
|
|
138
|
-
}(), [messageHandler, sessionHandler, request]);
|
|
183
|
+
}(), [messageHandler, sessionHandler, request, setLoading]);
|
|
139
184
|
|
|
140
185
|
/**
|
|
141
|
-
*
|
|
142
|
-
* 1.
|
|
143
|
-
* 2.
|
|
144
|
-
*
|
|
186
|
+
* Handle cancel / stop.
|
|
187
|
+
* 1. Mark response as interrupted and reset UI (finishResponse).
|
|
188
|
+
* 2. Invoke the cancel API immediately — do NOT wait for the next SSE
|
|
189
|
+
* chunk to deliver the cancellation (fixes "backend keeps running
|
|
190
|
+
* after stop" issue).
|
|
191
|
+
* 3. Abort the SSE connection — its catch branch will see
|
|
192
|
+
* msgStatus === 'interrupted' and call builder.cancel() to flip the
|
|
193
|
+
* in-progress TEXT content to Canceled, so the trailing Markdown
|
|
194
|
+
* cursor ("...") disappears.
|
|
195
|
+
*
|
|
196
|
+
* NOTE: we intentionally do NOT bump activeRequestId here. Doing so
|
|
197
|
+
* would make isStillActive() in processSSEResponse return false for
|
|
198
|
+
* this very cancel, which would short-circuit the catch branch before
|
|
199
|
+
* builder.cancel() runs and leave the trailing cursor blinking forever.
|
|
200
|
+
* Stale-chunk protection still holds: abort() breaks the SSE loop
|
|
201
|
+
* immediately, and the next submit / session switch will bump
|
|
202
|
+
* activeRequestId on its own.
|
|
145
203
|
*/
|
|
146
204
|
var handleCancel = useCallback(function () {
|
|
147
|
-
var _currentQARef$
|
|
205
|
+
var _currentQARef$current3;
|
|
148
206
|
finishResponse('interrupted');
|
|
149
|
-
|
|
150
|
-
|
|
207
|
+
var sessionId = sessionHandler.getCurrentSessionId();
|
|
208
|
+
var cancelFn = apiOptionsRef.current.cancel;
|
|
209
|
+
if (cancelFn && sessionId) {
|
|
210
|
+
try {
|
|
211
|
+
cancelFn({
|
|
212
|
+
session_id: sessionId
|
|
213
|
+
});
|
|
214
|
+
} catch (e) {
|
|
215
|
+
console.error('cancel api failed:', e);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
(_currentQARef$current3 = currentQARef.current.abortController) === null || _currentQARef$current3 === void 0 || _currentQARef$current3.abort();
|
|
219
|
+
}, [finishResponse, sessionHandler]);
|
|
151
220
|
|
|
152
221
|
/**
|
|
153
|
-
*
|
|
222
|
+
* Handle regenerate (retry the last assistant response).
|
|
154
223
|
*/
|
|
155
224
|
var handleRegenerate = useCallback( /*#__PURE__*/function () {
|
|
156
225
|
var _ref4 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(messageId) {
|
|
157
|
-
var
|
|
226
|
+
var _currentQARef$current4;
|
|
227
|
+
var myRequestId, historyMessages;
|
|
158
228
|
return _regeneratorRuntime().wrap(function _callee3$(_context3) {
|
|
159
229
|
while (1) switch (_context3.prev = _context3.next) {
|
|
160
230
|
case 0:
|
|
231
|
+
(_currentQARef$current4 = currentQARef.current.abortController) === null || _currentQARef$current4 === void 0 || _currentQARef$current4.abort();
|
|
232
|
+
currentQARef.current.activeSessionId = sessionHandler.getCurrentSessionId();
|
|
233
|
+
myRequestId = ++currentQARef.current.activeRequestId;
|
|
161
234
|
setLoading(true);
|
|
162
235
|
|
|
163
|
-
// 1.
|
|
236
|
+
// 1. Remove old message
|
|
164
237
|
messageHandler.removeMessageById(messageId);
|
|
165
238
|
|
|
166
|
-
// 2.
|
|
239
|
+
// 2. Create new response placeholder
|
|
167
240
|
currentQARef.current.abortController = new AbortController();
|
|
168
241
|
messageHandler.createResponseMessage();
|
|
169
242
|
|
|
170
|
-
// 3.
|
|
243
|
+
// 3. Fire the request
|
|
171
244
|
historyMessages = messageHandler.getHistoryMessages();
|
|
172
|
-
_context3.next =
|
|
173
|
-
return request(historyMessages);
|
|
174
|
-
case
|
|
245
|
+
_context3.next = 10;
|
|
246
|
+
return request(historyMessages, undefined, myRequestId);
|
|
247
|
+
case 10:
|
|
175
248
|
case "end":
|
|
176
249
|
return _context3.stop();
|
|
177
250
|
}
|
|
@@ -180,40 +253,48 @@ export default function useChatController() {
|
|
|
180
253
|
return function (_x3) {
|
|
181
254
|
return _ref4.apply(this, arguments);
|
|
182
255
|
};
|
|
183
|
-
}(), [messageHandler, request]);
|
|
256
|
+
}(), [messageHandler, request, sessionHandler, setLoading]);
|
|
184
257
|
|
|
185
258
|
/**
|
|
186
|
-
*
|
|
259
|
+
* Handle SSE reconnection (when switching back to an unfinished conversation).
|
|
187
260
|
* If the reconnect API returns no body or the stream ends without a completion event,
|
|
188
261
|
* treat it as idle: remove the empty placeholder and reset loading.
|
|
189
262
|
*/
|
|
190
263
|
var handleReconnect = useCallback( /*#__PURE__*/function () {
|
|
191
264
|
var _ref5 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4(sessionId) {
|
|
192
|
-
var _currentQARef$
|
|
193
|
-
var _currentQARef$
|
|
265
|
+
var _currentQARef$current5, _currentQARef$current6;
|
|
266
|
+
var myRequestId, _currentQARef$current7;
|
|
194
267
|
return _regeneratorRuntime().wrap(function _callee4$(_context4) {
|
|
195
268
|
while (1) switch (_context4.prev = _context4.next) {
|
|
196
269
|
case 0:
|
|
197
|
-
(_currentQARef$
|
|
270
|
+
(_currentQARef$current5 = currentQARef.current.abortController) === null || _currentQARef$current5 === void 0 || _currentQARef$current5.abort();
|
|
198
271
|
currentQARef.current.abortController = new AbortController();
|
|
272
|
+
myRequestId = ++currentQARef.current.activeRequestId;
|
|
273
|
+
currentQARef.current.activeSessionId = sessionId;
|
|
199
274
|
setLoading(true);
|
|
200
275
|
messageHandler.createResponseMessage();
|
|
201
|
-
_context4.next =
|
|
202
|
-
return reconnect(sessionId);
|
|
203
|
-
case
|
|
276
|
+
_context4.next = 8;
|
|
277
|
+
return reconnect(sessionId, myRequestId);
|
|
278
|
+
case 8:
|
|
279
|
+
if (!(myRequestId !== currentQARef.current.activeRequestId)) {
|
|
280
|
+
_context4.next = 10;
|
|
281
|
+
break;
|
|
282
|
+
}
|
|
283
|
+
return _context4.abrupt("return");
|
|
284
|
+
case 10:
|
|
204
285
|
// If the response is still in 'generating' state after reconnect completes,
|
|
205
286
|
// onFinish() was never called (no response body, or stream closed without a completion event).
|
|
206
287
|
// Treat as idle: remove the empty placeholder and reset loading.
|
|
207
288
|
// HTTP errors and normal SSE completions both call onFinish() → msgStatus becomes 'finished',
|
|
208
289
|
// so they are correctly excluded from this cleanup.
|
|
209
|
-
if (((_currentQARef$
|
|
290
|
+
if (((_currentQARef$current6 = currentQARef.current.response) === null || _currentQARef$current6 === void 0 ? void 0 : _currentQARef$current6.msgStatus) === 'generating') {
|
|
210
291
|
setLoading(false);
|
|
211
|
-
if ((_currentQARef$
|
|
292
|
+
if ((_currentQARef$current7 = currentQARef.current.response) !== null && _currentQARef$current7 !== void 0 && _currentQARef$current7.id) {
|
|
212
293
|
messageHandler.removeMessageById(currentQARef.current.response.id);
|
|
213
294
|
}
|
|
214
295
|
currentQARef.current.response = undefined;
|
|
215
296
|
}
|
|
216
|
-
case
|
|
297
|
+
case 11:
|
|
217
298
|
case "end":
|
|
218
299
|
return _context4.stop();
|
|
219
300
|
}
|
|
@@ -224,22 +305,40 @@ export default function useChatController() {
|
|
|
224
305
|
};
|
|
225
306
|
}(), [messageHandler, reconnect, setLoading]);
|
|
226
307
|
|
|
227
|
-
//
|
|
308
|
+
// On session switch: abort current SSE (without notifying backend cancel)
|
|
309
|
+
// and reset state. Also increment activeRequestId so any residual SSE
|
|
310
|
+
// chunks from the old session are discarded, preventing cross-session leakage.
|
|
311
|
+
//
|
|
312
|
+
// IMPORTANT: only bump on a real session change. Running this on initial
|
|
313
|
+
// mount or when sessionId merely transitions from undefined → <same id>
|
|
314
|
+
// (e.g. after route navigate / refreshKey churn) would invalidate the
|
|
315
|
+
// myRequestId taken by an in-flight handleSubmit and silently drop the
|
|
316
|
+
// outgoing chat request — that was the regression that made existing
|
|
317
|
+
// sessions unable to send messages until a new chat was created.
|
|
228
318
|
useEffect(function () {
|
|
229
|
-
var _currentQARef$
|
|
230
|
-
|
|
319
|
+
var _currentQARef$current8;
|
|
320
|
+
var prevSessionId = currentQARef.current.activeSessionId;
|
|
321
|
+
if (!prevSessionId || prevSessionId === currentSessionId) {
|
|
322
|
+
// First mount, or no real switch: just sync the snapshot, do not bump.
|
|
323
|
+
currentQARef.current.activeSessionId = currentSessionId;
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
(_currentQARef$current8 = currentQARef.current.abortController) === null || _currentQARef$current8 === void 0 || _currentQARef$current8.abort();
|
|
231
327
|
currentQARef.current = {
|
|
232
328
|
request: undefined,
|
|
233
329
|
response: undefined,
|
|
234
|
-
abortController: undefined
|
|
330
|
+
abortController: undefined,
|
|
331
|
+
activeRequestId: currentQARef.current.activeRequestId + 1,
|
|
332
|
+
activeSessionId: currentSessionId
|
|
235
333
|
};
|
|
236
334
|
return function () {
|
|
237
|
-
var _currentQARef$
|
|
238
|
-
(_currentQARef$
|
|
335
|
+
var _currentQARef$current9;
|
|
336
|
+
(_currentQARef$current9 = currentQARef.current.abortController) === null || _currentQARef$current9 === void 0 || _currentQARef$current9.abort();
|
|
337
|
+
currentQARef.current.activeRequestId += 1;
|
|
239
338
|
};
|
|
240
339
|
}, [currentSessionId]);
|
|
241
340
|
|
|
242
|
-
//
|
|
341
|
+
// Listen for reconnect events
|
|
243
342
|
useChatAnywhereEventEmitter({
|
|
244
343
|
type: 'handleReconnect',
|
|
245
344
|
callback: function () {
|
|
@@ -262,7 +361,7 @@ export default function useChatController() {
|
|
|
262
361
|
}()
|
|
263
362
|
}, [handleReconnect]);
|
|
264
363
|
|
|
265
|
-
//
|
|
364
|
+
// Listen for regenerate events
|
|
266
365
|
useChatAnywhereEventEmitter({
|
|
267
366
|
type: 'handleReplace',
|
|
268
367
|
callback: function () {
|
|
@@ -6,17 +6,21 @@ interface UseChatRequestOptions {
|
|
|
6
6
|
request?: IAgentScopeRuntimeWebUIMessage;
|
|
7
7
|
response?: IAgentScopeRuntimeWebUIMessage;
|
|
8
8
|
abortController?: AbortController;
|
|
9
|
+
/** Active request id, maintained by the controller. Incrementing it invalidates any in-flight SSE. */
|
|
10
|
+
activeRequestId: number;
|
|
11
|
+
/** Session id snapshot for the active request. */
|
|
12
|
+
activeSessionId?: string;
|
|
9
13
|
}>;
|
|
10
14
|
updateMessage: (message: IAgentScopeRuntimeWebUIMessage) => void;
|
|
11
15
|
getCurrentSessionId: () => string;
|
|
12
16
|
onFinish: () => void;
|
|
13
17
|
}
|
|
14
18
|
/**
|
|
15
|
-
*
|
|
19
|
+
* Hook for handling API requests and streaming SSE responses.
|
|
16
20
|
*/
|
|
17
21
|
export default function useChatRequest(options: UseChatRequestOptions): {
|
|
18
|
-
request: (historyMessages: any[], biz_params?: IAgentScopeRuntimeWebUIInputData['biz_params']) => Promise<void>;
|
|
19
|
-
reconnect: (sessionId: string) => Promise<void>;
|
|
22
|
+
request: (historyMessages: any[], biz_params?: IAgentScopeRuntimeWebUIInputData['biz_params'], myRequestId?: number) => Promise<void>;
|
|
23
|
+
reconnect: (sessionId: string, myRequestId?: number) => Promise<void>;
|
|
20
24
|
mockRequest: (mockdata: any) => Promise<void>;
|
|
21
25
|
};
|
|
22
26
|
export {};
|