fix(conversation): topic chips after warmup + English chip copy

- Buffer topic_suggestions until chat UI attaches (uiOwner + callback); replay on attach
- build_topic_chips respects user language for label/text; router passes user_language

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Kevin
2026-05-12 11:10:21 +08:00
parent 7e64fc3faf
commit d155e45a44
5 changed files with 101 additions and 16 deletions

View File

@@ -250,4 +250,52 @@ describe('RealtimeSession sync TTS / agent ordering', () => {
expect(staleScreenOnTts).not.toHaveBeenCalled();
session.dispose();
});
it('replays topic_suggestions after attachUiCallbacks with owner (warmup path)', async () => {
const onTopic = jest.fn();
const owner = Symbol('ui');
const session = new RealtimeSession({
conversationId: 'conv-x',
queryClient: qc,
});
await session.connect();
await new Promise((r) => setImmediate(r));
const ws = MockWebSocket.instances[0]!;
ws.simulateMessage({
type: 'topic_suggestions',
conversation_id: 'conv-x',
data: {
reason: 'opening',
stage: 'childhood',
suggestions: [
{
id: 'place',
label: 'where you grew up',
text: "I'd like to talk about where you grew up.",
},
],
},
timestamp: new Date().toISOString(),
});
expect(onTopic).not.toHaveBeenCalled();
session.attachUiCallbacks(
{
onTopicSuggestions: onTopic,
onStreamingText: () => {},
onTtsSegment: () => {},
onError: () => {},
onStateChange: () => {},
},
owner,
);
expect(onTopic).toHaveBeenCalledTimes(1);
expect(onTopic.mock.calls[0]![0].suggestions[0]!.id).toBe('place');
session.dispose();
});
});