@yeaft/webchat-agent 1.0.22 → 1.0.24
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/package.json +1 -1
- package/yeaft/vp-status-broker.js +8 -3
- package/yeaft/web-bridge.js +46 -12
package/package.json
CHANGED
|
@@ -17,6 +17,11 @@ export const VALID_STATES = new Set([
|
|
|
17
17
|
]);
|
|
18
18
|
|
|
19
19
|
const RUNNING_STATES = new Set(['typing', 'thinking', 'streaming', 'tool']);
|
|
20
|
+
|
|
21
|
+
export function isVpStatusRunning(state) {
|
|
22
|
+
return RUNNING_STATES.has(state || 'idle');
|
|
23
|
+
}
|
|
24
|
+
|
|
20
25
|
const STATE_PRIORITY = ['tool', 'streaming', 'thinking', 'typing', 'error', 'idle'];
|
|
21
26
|
const MAX_RETAINED_THREADS_PER_VP = 20;
|
|
22
27
|
const COMPLETED_TTL_MS = 30 * 60 * 1000;
|
|
@@ -52,7 +57,7 @@ export function createVpStatusBroker({ send, now = Date.now } = {}) {
|
|
|
52
57
|
}
|
|
53
58
|
}
|
|
54
59
|
|
|
55
|
-
const runningThreadCount = rows.filter(r =>
|
|
60
|
+
const runningThreadCount = rows.filter(r => isVpStatusRunning(r.state)).length;
|
|
56
61
|
const latest = rows[0] || null;
|
|
57
62
|
return {
|
|
58
63
|
sessionId: sessionId || null,
|
|
@@ -83,14 +88,14 @@ export function createVpStatusBroker({ send, now = Date.now } = {}) {
|
|
|
83
88
|
}
|
|
84
89
|
const cutoff = now() - COMPLETED_TTL_MS;
|
|
85
90
|
for (const [key, row] of rows) {
|
|
86
|
-
if (
|
|
91
|
+
if (isVpStatusRunning(row.state)) continue;
|
|
87
92
|
if ((row.updatedAt || row.since || 0) < cutoff) threads.delete(key);
|
|
88
93
|
}
|
|
89
94
|
const remaining = rows
|
|
90
95
|
.filter(([key]) => threads.has(key))
|
|
91
96
|
.sort((a, b) => (b[1].updatedAt || b[1].since || 0) - (a[1].updatedAt || a[1].since || 0));
|
|
92
97
|
for (const [key, row] of remaining.slice(MAX_RETAINED_THREADS_PER_VP)) {
|
|
93
|
-
if (!
|
|
98
|
+
if (!isVpStatusRunning(row.state)) threads.delete(key);
|
|
94
99
|
}
|
|
95
100
|
}
|
|
96
101
|
|
package/yeaft/web-bridge.js
CHANGED
|
@@ -66,7 +66,7 @@ import { isHiddenConversationRow } from './conversation/internal-control.js';
|
|
|
66
66
|
import { sliceLastNTurns } from './turn-utils.js';
|
|
67
67
|
import { pairSanitize } from './pair-sanitize.js';
|
|
68
68
|
import { filterSnapshotForVp } from './snapshot-filter.js';
|
|
69
|
-
import { createVpStatusBroker } from './vp-status-broker.js';
|
|
69
|
+
import { createVpStatusBroker, isVpStatusRunning } from './vp-status-broker.js';
|
|
70
70
|
import { classifyThread as defaultClassifyThread, fallbackTitle } from './vp/thread-classifier.js';
|
|
71
71
|
import { listMcpServers, upsertMcpServer, removeMcpServer } from './config-api.js';
|
|
72
72
|
import { buildMcpFlattenedTools } from './tools/mcp-tools.js';
|
|
@@ -433,6 +433,32 @@ function buildVpPromptPayload(vpId, envelope) {
|
|
|
433
433
|
return { text, prompt, promptParts };
|
|
434
434
|
}
|
|
435
435
|
|
|
436
|
+
function buildPendingRescueEnvelope({ sessionId, taskId = null, threadId = 'main', followUpId, leftover, replayText, replayParts = null }) {
|
|
437
|
+
const leftoverIsInternal = Boolean(leftover?.internal);
|
|
438
|
+
const leftoverInjectedBy = leftoverIsInternal && typeof leftover?.injectedBy === 'string'
|
|
439
|
+
? leftover.injectedBy
|
|
440
|
+
: null;
|
|
441
|
+
return {
|
|
442
|
+
sessionId,
|
|
443
|
+
taskId,
|
|
444
|
+
trigger: 'pending_rescue',
|
|
445
|
+
msg: {
|
|
446
|
+
id: followUpId,
|
|
447
|
+
from: leftoverIsInternal && leftover.senderVpId ? leftover.senderVpId : 'user',
|
|
448
|
+
role: leftoverIsInternal ? 'assistant' : 'user',
|
|
449
|
+
text: replayText,
|
|
450
|
+
meta: {
|
|
451
|
+
rescuedFrom: 'pendingQueries',
|
|
452
|
+
threadId,
|
|
453
|
+
...(leftoverInjectedBy ? { injectedBy: leftoverInjectedBy } : {}),
|
|
454
|
+
...(leftoverIsInternal && leftover.senderVpId ? { senderVpId: leftover.senderVpId } : {}),
|
|
455
|
+
...(leftoverIsInternal && leftover.sourceThreadId ? { sourceThreadId: leftover.sourceThreadId } : {}),
|
|
456
|
+
},
|
|
457
|
+
},
|
|
458
|
+
...(Array.isArray(replayParts) && replayParts.length > 0 ? { _promptParts: replayParts } : {}),
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
|
|
436
462
|
export function visibleInboundThreadId(envelope, fallbackThreadId = 'main') {
|
|
437
463
|
const meta = envelope?.msg?.meta || {};
|
|
438
464
|
if (
|
|
@@ -1350,6 +1376,9 @@ async function routeEnvelopeToVpThread(sessionId, vpId, envelope) {
|
|
|
1350
1376
|
originalText: text,
|
|
1351
1377
|
originalParts: Array.isArray(envelope?._promptParts) ? envelope._promptParts : null,
|
|
1352
1378
|
internal: isInternalAppend,
|
|
1379
|
+
injectedBy: isInternalAppend ? injectedBy : null,
|
|
1380
|
+
senderVpId: isInternalAppend ? (envelope?.msg?.meta?.senderVpId || envelope?.msg?.from || null) : null,
|
|
1381
|
+
sourceThreadId: isInternalAppend ? visibleInboundThreadId(envelope, thread.threadId) : null,
|
|
1353
1382
|
});
|
|
1354
1383
|
persistInboundMessageOnceByMsgId({
|
|
1355
1384
|
msgId: envelope?.msg?.id,
|
|
@@ -1534,18 +1563,15 @@ function ensureDriverRunning(sessionId, vpId, threadId = 'main') {
|
|
|
1534
1563
|
: null;
|
|
1535
1564
|
if (!replayText && !replayParts) continue;
|
|
1536
1565
|
const followUpId = `followup_${Date.now().toString(36)}_${randomUUID().slice(0, 8)}`;
|
|
1537
|
-
const followUpEnvelope = {
|
|
1566
|
+
const followUpEnvelope = buildPendingRescueEnvelope({
|
|
1538
1567
|
sessionId,
|
|
1539
1568
|
taskId: envelope?.taskId || null,
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
},
|
|
1547
|
-
...(replayParts ? { _promptParts: replayParts } : {}),
|
|
1548
|
-
};
|
|
1569
|
+
threadId: thread.threadId,
|
|
1570
|
+
followUpId,
|
|
1571
|
+
leftover,
|
|
1572
|
+
replayText,
|
|
1573
|
+
replayParts,
|
|
1574
|
+
});
|
|
1549
1575
|
const followUpTurnId = `${randomUUID().slice(0, 8)}:${vpId}`;
|
|
1550
1576
|
inbox.push({ envelope: followUpEnvelope, turnId: followUpTurnId, thread });
|
|
1551
1577
|
try {
|
|
@@ -1825,7 +1851,7 @@ function decorateSessionsWithRuntimeState(sessions) {
|
|
|
1825
1851
|
const sessionId = status?.sessionId || status?.groupId || null;
|
|
1826
1852
|
if (!sessionId) continue;
|
|
1827
1853
|
const state = status.state || 'idle';
|
|
1828
|
-
const running =
|
|
1854
|
+
const running = isVpStatusRunning(state);
|
|
1829
1855
|
const updatedAt = status.updatedAt || status.since || Date.now();
|
|
1830
1856
|
const prev = bySession.get(sessionId) || { running: false, runningVpCount: 0, latestActivityAt: 0 };
|
|
1831
1857
|
if (running) prev.runningVpCount += 1;
|
|
@@ -5260,6 +5286,7 @@ export async function handleYeaftMcpReload(msg = {}) {
|
|
|
5260
5286
|
export const __testHooks = {
|
|
5261
5287
|
loadVisibleGroupHistoryPage,
|
|
5262
5288
|
persistInboundMessageOnceByMsgId,
|
|
5289
|
+
buildPendingRescueEnvelope,
|
|
5263
5290
|
setSessionForTest(nextSession) {
|
|
5264
5291
|
session = nextSession || null;
|
|
5265
5292
|
},
|
|
@@ -5269,6 +5296,13 @@ export const __testHooks = {
|
|
|
5269
5296
|
vpAborts.clear();
|
|
5270
5297
|
vpInboxes.clear();
|
|
5271
5298
|
},
|
|
5299
|
+
resetVpStatusBroker() {
|
|
5300
|
+
if (vpStatusBroker) vpStatusBroker.reset();
|
|
5301
|
+
},
|
|
5302
|
+
seedVpStatus(status) {
|
|
5303
|
+
return getVpStatusBroker().transition(status);
|
|
5304
|
+
},
|
|
5305
|
+
decorateSessionsWithRuntimeState,
|
|
5272
5306
|
seedQueuedVpTurn({ sessionId = 'session-test', vpId = 'vp-test', threadId = 'main', turnId = 'turn-test' } = {}) {
|
|
5273
5307
|
const key = threadKey(sessionId, vpId, threadId);
|
|
5274
5308
|
const inbox = vpInboxes.get(key) || [];
|