@agentscope-ai/chat 1.1.58 → 1.1.59
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/Chat/hooks/useChatController.tsx +15 -0
- package/components/AgentScopeRuntimeWebUI/core/Chat/hooks/useChatRequest.tsx +6 -3
- package/lib/AgentScopeRuntimeWebUI/core/Chat/hooks/useChatController.js +19 -2
- package/lib/AgentScopeRuntimeWebUI/core/Chat/hooks/useChatRequest.js +72 -63
- package/package.json +1 -1
|
@@ -124,6 +124,8 @@ export default function useChatController() {
|
|
|
124
124
|
|
|
125
125
|
/**
|
|
126
126
|
* 处理 SSE 重连(切回未完成的对话时)
|
|
127
|
+
* If the reconnect API returns no body or the stream ends without a completion event,
|
|
128
|
+
* treat it as idle: remove the empty placeholder and reset loading.
|
|
127
129
|
*/
|
|
128
130
|
const handleReconnect = useCallback(async (sessionId: string) => {
|
|
129
131
|
currentQARef.current.abortController = new AbortController();
|
|
@@ -132,6 +134,19 @@ export default function useChatController() {
|
|
|
132
134
|
messageHandler.createResponseMessage();
|
|
133
135
|
|
|
134
136
|
await reconnect(sessionId);
|
|
137
|
+
|
|
138
|
+
// If the response is still in 'generating' state after reconnect completes,
|
|
139
|
+
// onFinish() was never called (no response body, or stream closed without a completion event).
|
|
140
|
+
// Treat as idle: remove the empty placeholder and reset loading.
|
|
141
|
+
// HTTP errors and normal SSE completions both call onFinish() → msgStatus becomes 'finished',
|
|
142
|
+
// so they are correctly excluded from this cleanup.
|
|
143
|
+
if (currentQARef.current.response?.msgStatus === 'generating') {
|
|
144
|
+
setLoading(false);
|
|
145
|
+
if (currentQARef.current.response?.id) {
|
|
146
|
+
messageHandler.removeMessageById(currentQARef.current.response.id);
|
|
147
|
+
}
|
|
148
|
+
currentQARef.current.response = undefined;
|
|
149
|
+
}
|
|
135
150
|
}, [messageHandler, reconnect, setLoading]);
|
|
136
151
|
|
|
137
152
|
// 监听会话切换,断开当前 SSE 连接(不通知后端取消)并重置状态
|
|
@@ -66,7 +66,8 @@ export default function useChatRequest(options: UseChatRequestOptions) {
|
|
|
66
66
|
});
|
|
67
67
|
|
|
68
68
|
if (!response.ok) {
|
|
69
|
-
|
|
69
|
+
try {
|
|
70
|
+
const data = await response.json();
|
|
70
71
|
const res = agentScopeRuntimeResponseBuilder.handle({
|
|
71
72
|
object: 'message',
|
|
72
73
|
type: AgentScopeRuntimeMessageType.ERROR,
|
|
@@ -84,8 +85,10 @@ export default function useChatRequest(options: UseChatRequestOptions) {
|
|
|
84
85
|
data: res,
|
|
85
86
|
}
|
|
86
87
|
];
|
|
87
|
-
|
|
88
|
-
|
|
88
|
+
} catch {
|
|
89
|
+
// Ignore JSON parse errors — still call onFinish to reset loading state
|
|
90
|
+
}
|
|
91
|
+
onFinish();
|
|
89
92
|
return;
|
|
90
93
|
}
|
|
91
94
|
|
|
@@ -179,9 +179,13 @@ export default function useChatController() {
|
|
|
179
179
|
|
|
180
180
|
/**
|
|
181
181
|
* 处理 SSE 重连(切回未完成的对话时)
|
|
182
|
+
* If the reconnect API returns no body or the stream ends without a completion event,
|
|
183
|
+
* treat it as idle: remove the empty placeholder and reset loading.
|
|
182
184
|
*/
|
|
183
185
|
var handleReconnect = useCallback( /*#__PURE__*/function () {
|
|
184
186
|
var _ref5 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4(sessionId) {
|
|
187
|
+
var _currentQARef$current;
|
|
188
|
+
var _currentQARef$current2;
|
|
185
189
|
return _regeneratorRuntime().wrap(function _callee4$(_context4) {
|
|
186
190
|
while (1) switch (_context4.prev = _context4.next) {
|
|
187
191
|
case 0:
|
|
@@ -191,6 +195,19 @@ export default function useChatController() {
|
|
|
191
195
|
_context4.next = 5;
|
|
192
196
|
return reconnect(sessionId);
|
|
193
197
|
case 5:
|
|
198
|
+
// If the response is still in 'generating' state after reconnect completes,
|
|
199
|
+
// onFinish() was never called (no response body, or stream closed without a completion event).
|
|
200
|
+
// Treat as idle: remove the empty placeholder and reset loading.
|
|
201
|
+
// HTTP errors and normal SSE completions both call onFinish() → msgStatus becomes 'finished',
|
|
202
|
+
// so they are correctly excluded from this cleanup.
|
|
203
|
+
if (((_currentQARef$current = currentQARef.current.response) === null || _currentQARef$current === void 0 ? void 0 : _currentQARef$current.msgStatus) === 'generating') {
|
|
204
|
+
setLoading(false);
|
|
205
|
+
if ((_currentQARef$current2 = currentQARef.current.response) !== null && _currentQARef$current2 !== void 0 && _currentQARef$current2.id) {
|
|
206
|
+
messageHandler.removeMessageById(currentQARef.current.response.id);
|
|
207
|
+
}
|
|
208
|
+
currentQARef.current.response = undefined;
|
|
209
|
+
}
|
|
210
|
+
case 6:
|
|
194
211
|
case "end":
|
|
195
212
|
return _context4.stop();
|
|
196
213
|
}
|
|
@@ -203,8 +220,8 @@ export default function useChatController() {
|
|
|
203
220
|
|
|
204
221
|
// 监听会话切换,断开当前 SSE 连接(不通知后端取消)并重置状态
|
|
205
222
|
useEffect(function () {
|
|
206
|
-
var _currentQARef$
|
|
207
|
-
(_currentQARef$
|
|
223
|
+
var _currentQARef$current3;
|
|
224
|
+
(_currentQARef$current3 = currentQARef.current.abortController) === null || _currentQARef$current3 === void 0 || _currentQARef$current3.abort();
|
|
208
225
|
currentQARef.current = {
|
|
209
226
|
request: undefined,
|
|
210
227
|
response: undefined,
|
|
@@ -102,7 +102,7 @@ export default function useChatRequest(options) {
|
|
|
102
102
|
}(), []);
|
|
103
103
|
var processSSEResponse = useCallback( /*#__PURE__*/function () {
|
|
104
104
|
var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(response) {
|
|
105
|
-
var currentApiOptions, agentScopeRuntimeResponseBuilder, _iteratorAbruptCompletion2, _didIteratorError2, _iteratorError2, _iterator2, _step2, chunk, _currentQARef$current, _res$output, _currentQARef$current2, responseParser, chunkData,
|
|
105
|
+
var currentApiOptions, agentScopeRuntimeResponseBuilder, data, res, _iteratorAbruptCompletion2, _didIteratorError2, _iteratorError2, _iterator2, _step2, chunk, _currentQARef$current, _res$output, _currentQARef$current2, responseParser, chunkData, _res;
|
|
106
106
|
return _regeneratorRuntime().wrap(function _callee2$(_context2) {
|
|
107
107
|
while (1) switch (_context2.prev = _context2.next) {
|
|
108
108
|
case 0:
|
|
@@ -113,46 +113,55 @@ export default function useChatRequest(options) {
|
|
|
113
113
|
created_at: 0
|
|
114
114
|
});
|
|
115
115
|
if (response.ok) {
|
|
116
|
-
_context2.next =
|
|
116
|
+
_context2.next = 15;
|
|
117
117
|
break;
|
|
118
118
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
}];
|
|
134
|
-
onFinish();
|
|
119
|
+
_context2.prev = 3;
|
|
120
|
+
_context2.next = 6;
|
|
121
|
+
return response.json();
|
|
122
|
+
case 6:
|
|
123
|
+
data = _context2.sent;
|
|
124
|
+
res = agentScopeRuntimeResponseBuilder.handle({
|
|
125
|
+
object: 'message',
|
|
126
|
+
type: AgentScopeRuntimeMessageType.ERROR,
|
|
127
|
+
content: [],
|
|
128
|
+
id: 'error',
|
|
129
|
+
role: 'assistant',
|
|
130
|
+
status: AgentScopeRuntimeRunStatus.Failed,
|
|
131
|
+
code: String(response.status),
|
|
132
|
+
message: JSON.stringify(data)
|
|
135
133
|
});
|
|
134
|
+
currentQARef.current.response.cards = [{
|
|
135
|
+
code: 'AgentScopeRuntimeResponseCard',
|
|
136
|
+
data: res
|
|
137
|
+
}];
|
|
138
|
+
_context2.next = 13;
|
|
139
|
+
break;
|
|
140
|
+
case 11:
|
|
141
|
+
_context2.prev = 11;
|
|
142
|
+
_context2.t0 = _context2["catch"](3);
|
|
143
|
+
case 13:
|
|
144
|
+
onFinish();
|
|
136
145
|
return _context2.abrupt("return");
|
|
137
|
-
case
|
|
138
|
-
_context2.prev =
|
|
146
|
+
case 15:
|
|
147
|
+
_context2.prev = 15;
|
|
139
148
|
_iteratorAbruptCompletion2 = false;
|
|
140
149
|
_didIteratorError2 = false;
|
|
141
|
-
_context2.prev =
|
|
150
|
+
_context2.prev = 18;
|
|
142
151
|
_iterator2 = _asyncIterator(Stream({
|
|
143
152
|
readableStream: response.body
|
|
144
153
|
}));
|
|
145
|
-
case
|
|
146
|
-
_context2.next =
|
|
154
|
+
case 20:
|
|
155
|
+
_context2.next = 22;
|
|
147
156
|
return _iterator2.next();
|
|
148
|
-
case
|
|
157
|
+
case 22:
|
|
149
158
|
if (!(_iteratorAbruptCompletion2 = !(_step2 = _context2.sent).done)) {
|
|
150
|
-
_context2.next =
|
|
159
|
+
_context2.next = 39;
|
|
151
160
|
break;
|
|
152
161
|
}
|
|
153
162
|
chunk = _step2.value;
|
|
154
163
|
if (!(((_currentQARef$current = currentQARef.current.response) === null || _currentQARef$current === void 0 ? void 0 : _currentQARef$current.msgStatus) === 'interrupted')) {
|
|
155
|
-
_context2.next =
|
|
164
|
+
_context2.next = 30;
|
|
156
165
|
break;
|
|
157
166
|
}
|
|
158
167
|
(_currentQARef$current2 = currentQARef.current.abortController) === null || _currentQARef$current2 === void 0 || _currentQARef$current2.abort();
|
|
@@ -166,72 +175,72 @@ export default function useChatRequest(options) {
|
|
|
166
175
|
data: agentScopeRuntimeResponseBuilder.cancel()
|
|
167
176
|
}];
|
|
168
177
|
updateMessage(currentQARef.current.response);
|
|
169
|
-
return _context2.abrupt("break",
|
|
170
|
-
case
|
|
178
|
+
return _context2.abrupt("break", 39);
|
|
179
|
+
case 30:
|
|
171
180
|
responseParser = apiOptionsRef.current.responseParser || JSON.parse;
|
|
172
181
|
chunkData = responseParser(chunk.data);
|
|
173
|
-
|
|
174
|
-
if (!(
|
|
175
|
-
_context2.next =
|
|
182
|
+
_res = agentScopeRuntimeResponseBuilder.handle(chunkData);
|
|
183
|
+
if (!(_res.status !== AgentScopeRuntimeRunStatus.Failed && !((_res$output = _res.output) !== null && _res$output !== void 0 && (_res$output = _res$output[0]) !== null && _res$output !== void 0 && (_res$output = _res$output.content) !== null && _res$output !== void 0 && _res$output.length))) {
|
|
184
|
+
_context2.next = 35;
|
|
176
185
|
break;
|
|
177
186
|
}
|
|
178
|
-
return _context2.abrupt("continue",
|
|
179
|
-
case
|
|
187
|
+
return _context2.abrupt("continue", 36);
|
|
188
|
+
case 35:
|
|
180
189
|
if (currentQARef.current.response) {
|
|
181
190
|
currentQARef.current.response.cards = [{
|
|
182
191
|
code: 'AgentScopeRuntimeResponseCard',
|
|
183
|
-
data:
|
|
192
|
+
data: _res
|
|
184
193
|
}];
|
|
185
|
-
if (
|
|
194
|
+
if (_res.status === AgentScopeRuntimeRunStatus.Completed || _res.status === AgentScopeRuntimeRunStatus.Failed) {
|
|
186
195
|
onFinish();
|
|
187
196
|
} else {
|
|
188
197
|
updateMessage(currentQARef.current.response);
|
|
189
198
|
}
|
|
190
199
|
}
|
|
191
|
-
case
|
|
200
|
+
case 36:
|
|
192
201
|
_iteratorAbruptCompletion2 = false;
|
|
193
|
-
_context2.next =
|
|
202
|
+
_context2.next = 20;
|
|
194
203
|
break;
|
|
195
|
-
case
|
|
196
|
-
_context2.next =
|
|
204
|
+
case 39:
|
|
205
|
+
_context2.next = 45;
|
|
197
206
|
break;
|
|
198
|
-
case
|
|
199
|
-
_context2.prev =
|
|
200
|
-
_context2.
|
|
207
|
+
case 41:
|
|
208
|
+
_context2.prev = 41;
|
|
209
|
+
_context2.t1 = _context2["catch"](18);
|
|
201
210
|
_didIteratorError2 = true;
|
|
202
|
-
_iteratorError2 = _context2.
|
|
203
|
-
case
|
|
204
|
-
_context2.prev =
|
|
205
|
-
_context2.prev =
|
|
211
|
+
_iteratorError2 = _context2.t1;
|
|
212
|
+
case 45:
|
|
213
|
+
_context2.prev = 45;
|
|
214
|
+
_context2.prev = 46;
|
|
206
215
|
if (!(_iteratorAbruptCompletion2 && _iterator2.return != null)) {
|
|
207
|
-
_context2.next =
|
|
216
|
+
_context2.next = 50;
|
|
208
217
|
break;
|
|
209
218
|
}
|
|
210
|
-
_context2.next =
|
|
219
|
+
_context2.next = 50;
|
|
211
220
|
return _iterator2.return();
|
|
212
|
-
case
|
|
213
|
-
_context2.prev =
|
|
221
|
+
case 50:
|
|
222
|
+
_context2.prev = 50;
|
|
214
223
|
if (!_didIteratorError2) {
|
|
215
|
-
_context2.next =
|
|
224
|
+
_context2.next = 53;
|
|
216
225
|
break;
|
|
217
226
|
}
|
|
218
227
|
throw _iteratorError2;
|
|
219
|
-
case
|
|
220
|
-
return _context2.finish(
|
|
221
|
-
case
|
|
222
|
-
return _context2.finish(
|
|
223
|
-
case
|
|
224
|
-
_context2.next =
|
|
228
|
+
case 53:
|
|
229
|
+
return _context2.finish(50);
|
|
230
|
+
case 54:
|
|
231
|
+
return _context2.finish(45);
|
|
232
|
+
case 55:
|
|
233
|
+
_context2.next = 60;
|
|
225
234
|
break;
|
|
226
|
-
case
|
|
227
|
-
_context2.prev =
|
|
228
|
-
_context2.
|
|
229
|
-
console.error(_context2.
|
|
230
|
-
case
|
|
235
|
+
case 57:
|
|
236
|
+
_context2.prev = 57;
|
|
237
|
+
_context2.t2 = _context2["catch"](15);
|
|
238
|
+
console.error(_context2.t2);
|
|
239
|
+
case 60:
|
|
231
240
|
case "end":
|
|
232
241
|
return _context2.stop();
|
|
233
242
|
}
|
|
234
|
-
}, _callee2, null, [[
|
|
243
|
+
}, _callee2, null, [[3, 11], [15, 57], [18, 41, 45, 55], [46,, 50, 54]]);
|
|
235
244
|
}));
|
|
236
245
|
return function (_x2) {
|
|
237
246
|
return _ref2.apply(this, arguments);
|