fix: prevent config overwrite, session history race, and streaming message loss (#663)
Co-authored-by: zuolingxuan <zuolingxuan@bytedance.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
committed by
GitHub
Unverified
parent
8c3a6a5f7a
commit
83858fdf73
@@ -142,6 +142,46 @@ describe('chat runtime event handlers', () => {
|
||||
expect(next.streamingTools).toEqual([]);
|
||||
});
|
||||
|
||||
it('delta with empty object does not overwrite existing streamingMessage', async () => {
|
||||
// Regression test for multi-model fallback: Gateway emits {} during model switch.
|
||||
// The existing streamingMessage content must be preserved.
|
||||
const { handleRuntimeEventState } = await import('@/stores/chat/runtime-event-handlers');
|
||||
const existing = { role: 'assistant', content: [{ type: 'text', text: 'hello' }] };
|
||||
const h = makeHarness({ streamingMessage: existing });
|
||||
|
||||
handleRuntimeEventState(h.set as never, h.get as never, { message: {} }, 'delta', 'run-x');
|
||||
expect(h.read().streamingMessage).toEqual(existing);
|
||||
});
|
||||
|
||||
it('delta with role-only object does not overwrite existing streamingMessage', async () => {
|
||||
const { handleRuntimeEventState } = await import('@/stores/chat/runtime-event-handlers');
|
||||
const existing = { role: 'assistant', content: [{ type: 'text', text: 'partial' }] };
|
||||
const h = makeHarness({ streamingMessage: existing });
|
||||
|
||||
handleRuntimeEventState(h.set as never, h.get as never, { message: { role: 'assistant' } }, 'delta', 'run-x');
|
||||
expect(h.read().streamingMessage).toEqual(existing);
|
||||
});
|
||||
|
||||
it('delta with empty object is accepted when streamingMessage is null (initial state)', async () => {
|
||||
// When streaming hasn't started yet, even an empty delta should be let
|
||||
// through so the UI can show a typing indicator immediately.
|
||||
const { handleRuntimeEventState } = await import('@/stores/chat/runtime-event-handlers');
|
||||
const h = makeHarness({ streamingMessage: null });
|
||||
|
||||
handleRuntimeEventState(h.set as never, h.get as never, { message: { role: 'assistant' } }, 'delta', 'run-x');
|
||||
expect(h.read().streamingMessage).toEqual({ role: 'assistant' });
|
||||
});
|
||||
|
||||
it('delta with actual content replaces streamingMessage', async () => {
|
||||
const { handleRuntimeEventState } = await import('@/stores/chat/runtime-event-handlers');
|
||||
const existing = { role: 'assistant', content: [{ type: 'text', text: 'old' }] };
|
||||
const incoming = { role: 'assistant', content: [{ type: 'text', text: 'new' }] };
|
||||
const h = makeHarness({ streamingMessage: existing });
|
||||
|
||||
handleRuntimeEventState(h.set as never, h.get as never, { message: incoming }, 'delta', 'run-x');
|
||||
expect(h.read().streamingMessage).toEqual(incoming);
|
||||
});
|
||||
|
||||
it('clears runtime state on aborted event', async () => {
|
||||
const { handleRuntimeEventState } = await import('@/stores/chat/runtime-event-handlers');
|
||||
const h = makeHarness({
|
||||
|
||||
Reference in New Issue
Block a user