@xcanwin/manyoyo 5.9.0 → 5.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/web/frontend/app.js +152 -9
- package/lib/web/server.js +144 -11
- package/package.json +1 -1
package/lib/web/frontend/app.js
CHANGED
|
@@ -92,6 +92,10 @@
|
|
|
92
92
|
controller: null,
|
|
93
93
|
traceMessageId: ''
|
|
94
94
|
},
|
|
95
|
+
agentRecovery: {
|
|
96
|
+
sessionName: '',
|
|
97
|
+
timer: null
|
|
98
|
+
},
|
|
95
99
|
terminal: {
|
|
96
100
|
term: null,
|
|
97
101
|
fitAddon: null,
|
|
@@ -1334,6 +1338,114 @@
|
|
|
1334
1338
|
);
|
|
1335
1339
|
}
|
|
1336
1340
|
|
|
1341
|
+
function clearAgentRecoveryPoll() {
|
|
1342
|
+
if (state.agentRecovery && state.agentRecovery.timer) {
|
|
1343
|
+
window.clearTimeout(state.agentRecovery.timer);
|
|
1344
|
+
state.agentRecovery.timer = null;
|
|
1345
|
+
}
|
|
1346
|
+
if (state.agentRecovery) {
|
|
1347
|
+
state.agentRecovery.sessionName = '';
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
|
|
1351
|
+
function hasPendingAgentMessagesForSession(sessionName) {
|
|
1352
|
+
const targetSession = String(sessionName || '').trim();
|
|
1353
|
+
if (!targetSession || state.active !== targetSession) {
|
|
1354
|
+
return false;
|
|
1355
|
+
}
|
|
1356
|
+
return state.messages.some(function (message) {
|
|
1357
|
+
return Boolean(
|
|
1358
|
+
message
|
|
1359
|
+
&& message.mode === 'agent'
|
|
1360
|
+
&& (message.pending === true || message.streamingReply === true)
|
|
1361
|
+
);
|
|
1362
|
+
});
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1365
|
+
function scheduleAgentRecoveryPoll(sessionName, immediate) {
|
|
1366
|
+
const targetSession = String(sessionName || '').trim();
|
|
1367
|
+
if (!targetSession || state.active !== targetSession) {
|
|
1368
|
+
clearAgentRecoveryPoll();
|
|
1369
|
+
return;
|
|
1370
|
+
}
|
|
1371
|
+
if (isAgentRunActiveForSession(targetSession)) {
|
|
1372
|
+
clearAgentRecoveryPoll();
|
|
1373
|
+
return;
|
|
1374
|
+
}
|
|
1375
|
+
if (!hasPendingAgentMessagesForSession(targetSession)) {
|
|
1376
|
+
clearAgentRecoveryPoll();
|
|
1377
|
+
return;
|
|
1378
|
+
}
|
|
1379
|
+
if (state.agentRecovery.sessionName !== targetSession) {
|
|
1380
|
+
clearAgentRecoveryPoll();
|
|
1381
|
+
state.agentRecovery.sessionName = targetSession;
|
|
1382
|
+
}
|
|
1383
|
+
if (state.agentRecovery.timer) {
|
|
1384
|
+
return;
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
const delay = immediate === true ? 0 : 1500;
|
|
1388
|
+
state.agentRecovery.timer = window.setTimeout(async function () {
|
|
1389
|
+
state.agentRecovery.timer = null;
|
|
1390
|
+
if (state.active !== targetSession || isAgentRunActiveForSession(targetSession)) {
|
|
1391
|
+
clearAgentRecoveryPoll();
|
|
1392
|
+
syncUi();
|
|
1393
|
+
return;
|
|
1394
|
+
}
|
|
1395
|
+
try {
|
|
1396
|
+
await refreshSessionsSilent({ preferredName: targetSession });
|
|
1397
|
+
await Promise.all([
|
|
1398
|
+
loadMessagesForSession(targetSession, { silent: true }),
|
|
1399
|
+
loadSessionDetailForSession(targetSession)
|
|
1400
|
+
]);
|
|
1401
|
+
} catch (e) {
|
|
1402
|
+
// 静默失败,等待下一轮轮询
|
|
1403
|
+
}
|
|
1404
|
+
if (state.active === targetSession && !isAgentRunActiveForSession(targetSession) && hasPendingAgentMessagesForSession(targetSession)) {
|
|
1405
|
+
scheduleAgentRecoveryPoll(targetSession, false);
|
|
1406
|
+
} else {
|
|
1407
|
+
clearAgentRecoveryPoll();
|
|
1408
|
+
}
|
|
1409
|
+
syncUi();
|
|
1410
|
+
}, delay);
|
|
1411
|
+
}
|
|
1412
|
+
|
|
1413
|
+
function syncAgentRecoveryForSession(sessionName) {
|
|
1414
|
+
const targetSession = String(sessionName || '').trim();
|
|
1415
|
+
if (!targetSession || state.active !== targetSession) {
|
|
1416
|
+
clearAgentRecoveryPoll();
|
|
1417
|
+
return;
|
|
1418
|
+
}
|
|
1419
|
+
if (isAgentRunActiveForSession(targetSession)) {
|
|
1420
|
+
clearAgentRecoveryPoll();
|
|
1421
|
+
return;
|
|
1422
|
+
}
|
|
1423
|
+
if (hasPendingAgentMessagesForSession(targetSession)) {
|
|
1424
|
+
scheduleAgentRecoveryPoll(targetSession, false);
|
|
1425
|
+
return;
|
|
1426
|
+
}
|
|
1427
|
+
if (state.agentRecovery.sessionName === targetSession) {
|
|
1428
|
+
clearAgentRecoveryPoll();
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
async function recoverAgentRunFromServer(sessionName) {
|
|
1433
|
+
const targetSession = String(sessionName || '').trim();
|
|
1434
|
+
if (!targetSession) {
|
|
1435
|
+
return false;
|
|
1436
|
+
}
|
|
1437
|
+
try {
|
|
1438
|
+
await refreshSessionsSilent({ preferredName: targetSession });
|
|
1439
|
+
await Promise.all([
|
|
1440
|
+
loadMessagesForSession(targetSession, { silent: true }),
|
|
1441
|
+
loadSessionDetailForSession(targetSession)
|
|
1442
|
+
]);
|
|
1443
|
+
} catch (e) {
|
|
1444
|
+
return false;
|
|
1445
|
+
}
|
|
1446
|
+
return hasPendingAgentMessagesForSession(targetSession);
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1337
1449
|
function isActiveSessionHistoryOnly() {
|
|
1338
1450
|
const session = getActiveSession();
|
|
1339
1451
|
return sessionStatusInfo(session && session.status).tone === 'history';
|
|
@@ -2076,7 +2188,7 @@
|
|
|
2076
2188
|
});
|
|
2077
2189
|
}
|
|
2078
2190
|
|
|
2079
|
-
const activeAgentRunning = isAgentRunActiveForSession(state.active);
|
|
2191
|
+
const activeAgentRunning = isAgentRunActiveForSession(state.active) || hasPendingAgentMessagesForSession(state.active);
|
|
2080
2192
|
const busy = state.loadingSessions || state.loadingMessages || state.sending;
|
|
2081
2193
|
refreshBtn.disabled = busy;
|
|
2082
2194
|
if (addAgentBtn) {
|
|
@@ -2084,14 +2196,14 @@
|
|
|
2084
2196
|
}
|
|
2085
2197
|
removeBtn.disabled = !state.active || busy;
|
|
2086
2198
|
removeAllBtn.disabled = !state.active || busy;
|
|
2087
|
-
sendBtn.disabled = !activityTab || !state.active || busy || (agentMode && !agentEnabled);
|
|
2199
|
+
sendBtn.disabled = !activityTab || !state.active || busy || (agentMode && (!agentEnabled || activeAgentRunning));
|
|
2088
2200
|
if (stopBtn) {
|
|
2089
2201
|
stopBtn.disabled = !activityTab || !agentMode || !activeAgentRunning || state.agentRun.stopping;
|
|
2090
2202
|
}
|
|
2091
2203
|
if (agentTemplateBtn) {
|
|
2092
2204
|
agentTemplateBtn.disabled = !state.active || state.agentTemplateSaving;
|
|
2093
2205
|
}
|
|
2094
|
-
commandInput.disabled = !activityTab || !state.active || (agentMode && !agentEnabled);
|
|
2206
|
+
commandInput.disabled = !activityTab || !state.active || (agentMode && (!agentEnabled || activeAgentRunning));
|
|
2095
2207
|
if (commandInput) {
|
|
2096
2208
|
commandInput.placeholder = agentMode
|
|
2097
2209
|
? '输入提示词,例如:请帮我分析当前项目结构并给出重构建议'
|
|
@@ -3282,6 +3394,7 @@
|
|
|
3282
3394
|
state.messageRequestId += 1;
|
|
3283
3395
|
state.messages = [];
|
|
3284
3396
|
state.loadingMessages = false;
|
|
3397
|
+
clearAgentRecoveryPoll();
|
|
3285
3398
|
renderMessages(state.messages);
|
|
3286
3399
|
syncUi();
|
|
3287
3400
|
return;
|
|
@@ -3314,6 +3427,9 @@
|
|
|
3314
3427
|
state.messages = Array.isArray(data && data.messages) ? data.messages : [];
|
|
3315
3428
|
}
|
|
3316
3429
|
if (!requestError || targetSession === state.active) {
|
|
3430
|
+
if (targetSession === state.active) {
|
|
3431
|
+
syncAgentRecoveryForSession(targetSession);
|
|
3432
|
+
}
|
|
3317
3433
|
renderMessages(state.messages);
|
|
3318
3434
|
syncUi();
|
|
3319
3435
|
} else {
|
|
@@ -3451,6 +3567,7 @@
|
|
|
3451
3567
|
state.agentRun.stopping = false;
|
|
3452
3568
|
state.agentRun.sessionName = '';
|
|
3453
3569
|
state.agentRun.traceMessageId = '';
|
|
3570
|
+
clearAgentRecoveryPoll();
|
|
3454
3571
|
}
|
|
3455
3572
|
|
|
3456
3573
|
function appendAssistantMessageLocal(sessionName, result, mode) {
|
|
@@ -3524,6 +3641,7 @@
|
|
|
3524
3641
|
state.agentRun.stopping = false;
|
|
3525
3642
|
state.agentRun.controller = new window.AbortController();
|
|
3526
3643
|
state.agentRun.traceMessageId = traceMessageId;
|
|
3644
|
+
clearAgentRecoveryPoll();
|
|
3527
3645
|
renderMessages(state.messages, { stickToBottom: true });
|
|
3528
3646
|
syncUi();
|
|
3529
3647
|
|
|
@@ -3884,13 +4002,20 @@
|
|
|
3884
4002
|
});
|
|
3885
4003
|
}
|
|
3886
4004
|
} catch (e) {
|
|
3887
|
-
if (
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
4005
|
+
if (mode === 'agent') {
|
|
4006
|
+
const recovered = await recoverAgentRunFromServer(submitSession);
|
|
4007
|
+
if (!recovered && document.visibilityState !== 'hidden') {
|
|
4008
|
+
alert(e.message);
|
|
4009
|
+
}
|
|
4010
|
+
} else {
|
|
4011
|
+
if (state.active === submitSession) {
|
|
4012
|
+
state.messages = state.messages.filter(function (message) {
|
|
4013
|
+
return !(message && message.id === pendingMessage.id);
|
|
4014
|
+
});
|
|
4015
|
+
renderMessages(state.messages, { stickToBottom: true });
|
|
4016
|
+
}
|
|
4017
|
+
alert(e.message);
|
|
3892
4018
|
}
|
|
3893
|
-
alert(e.message);
|
|
3894
4019
|
} finally {
|
|
3895
4020
|
state.sending = false;
|
|
3896
4021
|
syncUi();
|
|
@@ -4153,6 +4278,24 @@
|
|
|
4153
4278
|
}
|
|
4154
4279
|
});
|
|
4155
4280
|
|
|
4281
|
+
document.addEventListener('visibilitychange', function () {
|
|
4282
|
+
if (document.visibilityState !== 'visible' || !state.active) {
|
|
4283
|
+
return;
|
|
4284
|
+
}
|
|
4285
|
+
recoverAgentRunFromServer(state.active).catch(function () {
|
|
4286
|
+
// 静默恢复失败不打断当前交互
|
|
4287
|
+
});
|
|
4288
|
+
});
|
|
4289
|
+
|
|
4290
|
+
window.addEventListener('focus', function () {
|
|
4291
|
+
if (!state.active) {
|
|
4292
|
+
return;
|
|
4293
|
+
}
|
|
4294
|
+
recoverAgentRunFromServer(state.active).catch(function () {
|
|
4295
|
+
// 静默恢复失败不打断当前交互
|
|
4296
|
+
});
|
|
4297
|
+
});
|
|
4298
|
+
|
|
4156
4299
|
if (typeof MOBILE_LAYOUT_MEDIA.addEventListener === 'function') {
|
|
4157
4300
|
MOBILE_LAYOUT_MEDIA.addEventListener('change', onLayoutMediaChange);
|
|
4158
4301
|
} else if (typeof MOBILE_LAYOUT_MEDIA.addListener === 'function') {
|
package/lib/web/server.js
CHANGED
|
@@ -384,6 +384,10 @@ function listWebAgentSessions(history, options = {}) {
|
|
|
384
384
|
});
|
|
385
385
|
}
|
|
386
386
|
|
|
387
|
+
function createWebSessionMessageId() {
|
|
388
|
+
return `${Date.now()}-${Math.random().toString(16).slice(2, 8)}`;
|
|
389
|
+
}
|
|
390
|
+
|
|
387
391
|
function appendWebSessionMessage(webHistoryDir, sessionRefOrContainerName, role, content, extra = {}) {
|
|
388
392
|
const sessionRef = typeof sessionRefOrContainerName === 'string'
|
|
389
393
|
? { containerName: sessionRefOrContainerName, agentId: WEB_DEFAULT_AGENT_ID }
|
|
@@ -391,13 +395,14 @@ function appendWebSessionMessage(webHistoryDir, sessionRefOrContainerName, role,
|
|
|
391
395
|
const history = loadWebSessionHistory(webHistoryDir, sessionRef.containerName);
|
|
392
396
|
const agentSession = getWebAgentSession(history, sessionRef.agentId, { create: true });
|
|
393
397
|
const timestamp = new Date().toISOString();
|
|
394
|
-
|
|
395
|
-
id:
|
|
398
|
+
const message = {
|
|
399
|
+
id: createWebSessionMessageId(),
|
|
396
400
|
role,
|
|
397
401
|
content,
|
|
398
402
|
timestamp,
|
|
399
403
|
...extra
|
|
400
|
-
}
|
|
404
|
+
};
|
|
405
|
+
agentSession.messages.push(message);
|
|
401
406
|
|
|
402
407
|
if (agentSession.messages.length > WEB_HISTORY_MAX_MESSAGES) {
|
|
403
408
|
agentSession.messages = agentSession.messages.slice(-WEB_HISTORY_MAX_MESSAGES);
|
|
@@ -406,6 +411,57 @@ function appendWebSessionMessage(webHistoryDir, sessionRefOrContainerName, role,
|
|
|
406
411
|
agentSession.updatedAt = timestamp;
|
|
407
412
|
history.updatedAt = timestamp;
|
|
408
413
|
saveWebSessionHistory(webHistoryDir, sessionRef.containerName, history);
|
|
414
|
+
return message;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
function patchWebSessionMessage(webHistoryDir, sessionRefOrContainerName, messageId, patch) {
|
|
418
|
+
const sessionRef = typeof sessionRefOrContainerName === 'string'
|
|
419
|
+
? { containerName: sessionRefOrContainerName, agentId: WEB_DEFAULT_AGENT_ID }
|
|
420
|
+
: sessionRefOrContainerName;
|
|
421
|
+
const targetId = String(messageId || '').trim();
|
|
422
|
+
if (!targetId) {
|
|
423
|
+
return null;
|
|
424
|
+
}
|
|
425
|
+
const history = loadWebSessionHistory(webHistoryDir, sessionRef.containerName);
|
|
426
|
+
const agentSession = getWebAgentSession(history, sessionRef.agentId, { create: true });
|
|
427
|
+
const nextPatch = patch && typeof patch === 'object' ? patch : {};
|
|
428
|
+
const message = agentSession.messages.find(item => item && String(item.id || '') === targetId);
|
|
429
|
+
if (!message) {
|
|
430
|
+
return null;
|
|
431
|
+
}
|
|
432
|
+
Object.keys(nextPatch).forEach(key => {
|
|
433
|
+
if (key === 'id') {
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
message[key] = nextPatch[key];
|
|
437
|
+
});
|
|
438
|
+
const timestamp = new Date().toISOString();
|
|
439
|
+
agentSession.updatedAt = timestamp;
|
|
440
|
+
history.updatedAt = timestamp;
|
|
441
|
+
saveWebSessionHistory(webHistoryDir, sessionRef.containerName, history);
|
|
442
|
+
return message;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
function removeWebSessionMessage(webHistoryDir, sessionRefOrContainerName, messageId) {
|
|
446
|
+
const sessionRef = typeof sessionRefOrContainerName === 'string'
|
|
447
|
+
? { containerName: sessionRefOrContainerName, agentId: WEB_DEFAULT_AGENT_ID }
|
|
448
|
+
: sessionRefOrContainerName;
|
|
449
|
+
const targetId = String(messageId || '').trim();
|
|
450
|
+
if (!targetId) {
|
|
451
|
+
return null;
|
|
452
|
+
}
|
|
453
|
+
const history = loadWebSessionHistory(webHistoryDir, sessionRef.containerName);
|
|
454
|
+
const agentSession = getWebAgentSession(history, sessionRef.agentId, { create: true });
|
|
455
|
+
const index = agentSession.messages.findIndex(item => item && String(item.id || '') === targetId);
|
|
456
|
+
if (index === -1) {
|
|
457
|
+
return null;
|
|
458
|
+
}
|
|
459
|
+
const removed = agentSession.messages.splice(index, 1)[0] || null;
|
|
460
|
+
const timestamp = new Date().toISOString();
|
|
461
|
+
agentSession.updatedAt = timestamp;
|
|
462
|
+
history.updatedAt = timestamp;
|
|
463
|
+
saveWebSessionHistory(webHistoryDir, sessionRef.containerName, history);
|
|
464
|
+
return removed;
|
|
409
465
|
}
|
|
410
466
|
|
|
411
467
|
function setWebSessionAgentPromptCommand(webHistoryDir, containerName, agentPromptCommand) {
|
|
@@ -816,6 +872,7 @@ function hasAgentConversationHistory(history) {
|
|
|
816
872
|
for (const message of messages) {
|
|
817
873
|
if (!message || typeof message !== 'object') continue;
|
|
818
874
|
if (message.mode !== 'agent') continue;
|
|
875
|
+
if (message.pending === true) continue;
|
|
819
876
|
if (message.streamTrace === true) continue;
|
|
820
877
|
if (message.role === 'user' || message.role === 'assistant') {
|
|
821
878
|
return true;
|
|
@@ -838,6 +895,7 @@ function buildAgentPromptWithHistory(history, prompt) {
|
|
|
838
895
|
.filter(message => (
|
|
839
896
|
message
|
|
840
897
|
&& message.mode === 'agent'
|
|
898
|
+
&& message.pending !== true
|
|
841
899
|
&& message.streamTrace !== true
|
|
842
900
|
&& (message.role === 'user' || message.role === 'assistant')
|
|
843
901
|
))
|
|
@@ -1547,9 +1605,9 @@ function finalizeWebAgentExecution(state, sessionRef, agentSession, agentMeta, m
|
|
|
1547
1605
|
function appendWebAgentTraceMessage(webHistoryDir, sessionRefOrContainerName, content, extra = {}) {
|
|
1548
1606
|
const text = String(content || '').trim();
|
|
1549
1607
|
if (!text) {
|
|
1550
|
-
return;
|
|
1608
|
+
return null;
|
|
1551
1609
|
}
|
|
1552
|
-
appendWebSessionMessage(webHistoryDir, sessionRefOrContainerName, 'assistant', text, {
|
|
1610
|
+
return appendWebSessionMessage(webHistoryDir, sessionRefOrContainerName, 'assistant', text, {
|
|
1553
1611
|
mode: 'agent',
|
|
1554
1612
|
streamTrace: true,
|
|
1555
1613
|
...extra
|
|
@@ -3827,10 +3885,26 @@ async function handleWebApi(req, res, pathname, ctx, state) {
|
|
|
3827
3885
|
return;
|
|
3828
3886
|
}
|
|
3829
3887
|
|
|
3888
|
+
const userMessage = appendWebSessionMessage(state.webHistoryDir, sessionRef, 'user', prompt, {
|
|
3889
|
+
mode: 'agent',
|
|
3890
|
+
pending: true
|
|
3891
|
+
});
|
|
3892
|
+
const traceMessage = appendWebAgentTraceMessage(
|
|
3893
|
+
state.webHistoryDir,
|
|
3894
|
+
sessionRef,
|
|
3895
|
+
'[执行过程]\n等待 Agent 启动…',
|
|
3896
|
+
{
|
|
3897
|
+
traceEvents: [],
|
|
3898
|
+
pending: true
|
|
3899
|
+
}
|
|
3900
|
+
);
|
|
3901
|
+
|
|
3830
3902
|
let prepared = null;
|
|
3831
3903
|
try {
|
|
3832
3904
|
prepared = await prepareWebAgentExecution(ctx, state, sessionRef, prompt);
|
|
3833
3905
|
} catch (e) {
|
|
3906
|
+
removeWebSessionMessage(state.webHistoryDir, sessionRef, traceMessage && traceMessage.id);
|
|
3907
|
+
removeWebSessionMessage(state.webHistoryDir, sessionRef, userMessage && userMessage.id);
|
|
3834
3908
|
sendJson(res, 400, { error: e && e.message ? e.message : 'Agent 执行准备失败' });
|
|
3835
3909
|
return;
|
|
3836
3910
|
}
|
|
@@ -3838,8 +3912,9 @@ async function handleWebApi(req, res, pathname, ctx, state) {
|
|
|
3838
3912
|
const { agentSession, agentMeta, command, contextMode, resumeAttempted, resumeSucceeded, resumeError } = prepared;
|
|
3839
3913
|
const traceLines = ['[执行过程]'];
|
|
3840
3914
|
const traceEvents = [];
|
|
3841
|
-
|
|
3842
|
-
|
|
3915
|
+
let streamingReplyMessageId = '';
|
|
3916
|
+
patchWebSessionMessage(state.webHistoryDir, sessionRef, userMessage && userMessage.id, {
|
|
3917
|
+
pending: true,
|
|
3843
3918
|
contextMode
|
|
3844
3919
|
});
|
|
3845
3920
|
|
|
@@ -3863,6 +3938,14 @@ async function handleWebApi(req, res, pathname, ctx, state) {
|
|
|
3863
3938
|
if (resumeAttempted) {
|
|
3864
3939
|
traceLines.push(resumeSucceeded ? '会话恢复成功' : '会话恢复失败,已回退到历史注入');
|
|
3865
3940
|
}
|
|
3941
|
+
patchWebSessionMessage(state.webHistoryDir, sessionRef, traceMessage && traceMessage.id, {
|
|
3942
|
+
content: traceLines.join('\n'),
|
|
3943
|
+
traceEvents: traceEvents.slice(),
|
|
3944
|
+
contextMode,
|
|
3945
|
+
resumeAttempted,
|
|
3946
|
+
resumeSucceeded,
|
|
3947
|
+
pending: true
|
|
3948
|
+
});
|
|
3866
3949
|
|
|
3867
3950
|
try {
|
|
3868
3951
|
const result = await execAgentInWebContainerStream(ctx, state, sessionRef, command, {
|
|
@@ -3873,18 +3956,57 @@ async function handleWebApi(req, res, pathname, ctx, state) {
|
|
|
3873
3956
|
if (event.traceEvent && typeof event.traceEvent === 'object') {
|
|
3874
3957
|
traceEvents.push(event.traceEvent);
|
|
3875
3958
|
}
|
|
3959
|
+
patchWebSessionMessage(state.webHistoryDir, sessionRef, traceMessage && traceMessage.id, {
|
|
3960
|
+
content: traceLines.join('\n'),
|
|
3961
|
+
traceEvents: traceEvents.slice(),
|
|
3962
|
+
pending: true
|
|
3963
|
+
});
|
|
3964
|
+
}
|
|
3965
|
+
if (event && event.type === 'content_delta' && typeof event.content === 'string') {
|
|
3966
|
+
if (!streamingReplyMessageId) {
|
|
3967
|
+
const streamingReplyMessage = appendWebSessionMessage(
|
|
3968
|
+
state.webHistoryDir,
|
|
3969
|
+
sessionRef,
|
|
3970
|
+
'assistant',
|
|
3971
|
+
event.content,
|
|
3972
|
+
{
|
|
3973
|
+
mode: 'agent',
|
|
3974
|
+
streamingReply: true,
|
|
3975
|
+
pending: true
|
|
3976
|
+
}
|
|
3977
|
+
);
|
|
3978
|
+
streamingReplyMessageId = streamingReplyMessage && streamingReplyMessage.id
|
|
3979
|
+
? streamingReplyMessage.id
|
|
3980
|
+
: '';
|
|
3981
|
+
} else {
|
|
3982
|
+
patchWebSessionMessage(state.webHistoryDir, sessionRef, streamingReplyMessageId, {
|
|
3983
|
+
content: event.content,
|
|
3984
|
+
pending: true
|
|
3985
|
+
});
|
|
3986
|
+
}
|
|
3876
3987
|
}
|
|
3877
3988
|
sendNdjson(res, event);
|
|
3878
3989
|
}
|
|
3879
3990
|
});
|
|
3880
3991
|
traceLines.push(result.interrupted === true ? '[任务] 已停止' : '[任务] 已完成');
|
|
3881
|
-
|
|
3992
|
+
patchWebSessionMessage(state.webHistoryDir, sessionRef, userMessage && userMessage.id, {
|
|
3993
|
+
pending: false,
|
|
3994
|
+
contextMode,
|
|
3995
|
+
resumeAttempted,
|
|
3996
|
+
resumeSucceeded
|
|
3997
|
+
});
|
|
3998
|
+
patchWebSessionMessage(state.webHistoryDir, sessionRef, traceMessage && traceMessage.id, {
|
|
3999
|
+
content: traceLines.join('\n'),
|
|
3882
4000
|
traceEvents,
|
|
3883
4001
|
contextMode,
|
|
3884
4002
|
resumeAttempted,
|
|
3885
4003
|
resumeSucceeded,
|
|
3886
|
-
interrupted: result.interrupted === true
|
|
4004
|
+
interrupted: result.interrupted === true,
|
|
4005
|
+
pending: false
|
|
3887
4006
|
});
|
|
4007
|
+
if (streamingReplyMessageId) {
|
|
4008
|
+
removeWebSessionMessage(state.webHistoryDir, sessionRef, streamingReplyMessageId);
|
|
4009
|
+
}
|
|
3888
4010
|
finalizeWebAgentExecution(state, sessionRef, agentSession, agentMeta, {
|
|
3889
4011
|
contextMode,
|
|
3890
4012
|
resumeAttempted,
|
|
@@ -3902,13 +4024,24 @@ async function handleWebApi(req, res, pathname, ctx, state) {
|
|
|
3902
4024
|
});
|
|
3903
4025
|
} catch (e) {
|
|
3904
4026
|
traceLines.push(`[错误] ${e && e.message ? e.message : 'Agent 执行失败'}`);
|
|
3905
|
-
|
|
4027
|
+
patchWebSessionMessage(state.webHistoryDir, sessionRef, userMessage && userMessage.id, {
|
|
4028
|
+
pending: false,
|
|
4029
|
+
contextMode,
|
|
4030
|
+
resumeAttempted,
|
|
4031
|
+
resumeSucceeded
|
|
4032
|
+
});
|
|
4033
|
+
patchWebSessionMessage(state.webHistoryDir, sessionRef, traceMessage && traceMessage.id, {
|
|
4034
|
+
content: traceLines.join('\n'),
|
|
3906
4035
|
traceEvents,
|
|
3907
4036
|
contextMode,
|
|
3908
4037
|
resumeAttempted,
|
|
3909
4038
|
resumeSucceeded,
|
|
3910
|
-
interrupted: true
|
|
4039
|
+
interrupted: true,
|
|
4040
|
+
pending: false
|
|
3911
4041
|
});
|
|
4042
|
+
if (streamingReplyMessageId) {
|
|
4043
|
+
removeWebSessionMessage(state.webHistoryDir, sessionRef, streamingReplyMessageId);
|
|
4044
|
+
}
|
|
3912
4045
|
sendNdjson(res, {
|
|
3913
4046
|
type: 'error',
|
|
3914
4047
|
error: e && e.message ? e.message : 'Agent 执行失败'
|