fix: unblock agent events after portal direct chat escalation

When a session starts with LLM direct chat then escalates to goosed,
invalidate the portal-direct-chat snapshot and stop replaying stale SSE
so page-generation turns stream and finish correctly.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
john
2026-07-04 23:15:44 +08:00
parent e45c9300bf
commit a29158d589
5 changed files with 231 additions and 5 deletions
+114
View File
@@ -3,7 +3,9 @@ import test from 'node:test';
import {
createDirectChatService,
isDirectChatSessionId,
isPortalDirectChatSnapshot,
sendDirectChatSessionEvents,
shouldExpirePortalDirectChatSnapshot,
} from './direct-chat-service.mjs';
test('direct chat is enabled by default', () => {
@@ -285,3 +287,115 @@ test('direct chat run saves portal reply into an existing agent session', async
assert.equal(saved[1].messages.at(-1)?.metadata?.source, 'portal-direct-chat');
assert.match(saved[1].messages.at(-1)?.content?.[0]?.text ?? '', /太湖/);
});
test('portal direct chat snapshot replay stays enabled for dedicated h5direct sessions', () => {
const now = new Date().toISOString();
const snapshot = {
session: { updated_at: now },
messages: [
{ role: 'user', content: [{ type: 'text', text: 'hi' }] },
{
role: 'assistant',
metadata: { source: 'portal-direct-chat' },
content: [{ type: 'text', text: '你好' }],
},
],
};
assert.equal(
isPortalDirectChatSnapshot(snapshot, { sessionId: 'h5direct_abc' }),
true,
);
});
test('portal direct chat snapshot is disabled after agent escalation on regular sessions', () => {
const now = new Date().toISOString();
const snapshot = {
session: { updated_at: now },
messages: [
{ role: 'user', content: [{ type: 'text', text: 'hi' }] },
{
role: 'assistant',
metadata: { source: 'portal-direct-chat' },
content: [{ type: 'text', text: '你好' }],
},
{
role: 'user',
content: [{ type: 'text', text: '帮我写一个 200 字散文,做成页面' }],
},
],
};
assert.equal(
isPortalDirectChatSnapshot(snapshot, { sessionId: '20260704_31' }),
false,
);
});
test('portal direct chat snapshot still replays a completed direct turn on regular sessions', () => {
const now = new Date().toISOString();
const snapshot = {
session: { updated_at: now },
messages: [
{ role: 'user', content: [{ type: 'text', text: '我想对太湖有更多的了解' }] },
{
role: 'assistant',
metadata: { source: 'portal-direct-chat' },
content: [{ type: 'text', text: '太湖是中国第三大淡水湖。' }],
},
],
};
assert.equal(
isPortalDirectChatSnapshot(snapshot, { sessionId: '20260704_11' }),
true,
);
});
test('shouldExpirePortalDirectChatSnapshot detects agent runs after a portal direct turn', async () => {
const now = new Date().toISOString();
const snapshot = {
session: { updated_at: now },
meta: { synced_at: 1000 },
messages: [
{ role: 'user', content: [{ type: 'text', text: 'hi' }] },
{
role: 'assistant',
metadata: { source: 'portal-direct-chat' },
content: [{ type: 'text', text: '你好' }],
},
],
};
const pool = {
async query(_sql, params) {
assert.deepEqual(params, ['20260704_31', 1000]);
return [[{ id: 'agent-run-1' }]];
},
};
assert.equal(
await shouldExpirePortalDirectChatSnapshot(pool, '20260704_31', snapshot),
true,
);
});
test('shouldExpirePortalDirectChatSnapshot keeps pure direct chat sessions fast', async () => {
const now = new Date().toISOString();
const snapshot = {
session: { updated_at: now },
meta: { synced_at: 1000 },
messages: [
{ role: 'user', content: [{ type: 'text', text: '太湖' }] },
{
role: 'assistant',
metadata: { source: 'portal-direct-chat' },
content: [{ type: 'text', text: '太湖是中国第三大淡水湖。' }],
},
],
};
const pool = {
async query() {
return [[]];
},
};
assert.equal(
await shouldExpirePortalDirectChatSnapshot(pool, '20260704_11', snapshot),
false,
);
});