mirror of
https://github.com/MoonshotAI/kimi-code.git
synced 2026-07-09 17:29:12 +00:00
perf(web): reuse sessions reference to stop sidebar re-render on streaming deltas (#1113)
This commit is contained in:
parent
6a97d0bf43
commit
6194d3fad3
3 changed files with 56 additions and 1 deletions
8
.changeset/web-sidebar-sessions-ref.md
Normal file
8
.changeset/web-sidebar-sessions-ref.md
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
"@moonshot-ai/kimi-code": patch
|
||||
---
|
||||
|
||||
Keep the web session sidebar from re-rendering on every streaming token. The
|
||||
event reducer now reuses the `sessions` array reference for events that do not
|
||||
change sessions, so the sidebar computeds (`sessionsForView` / `workspaceGroups`
|
||||
/ `mergedWorkspaces`) are no longer dirtied by unrelated high-frequency events.
|
||||
|
|
@ -84,7 +84,13 @@ export function createInitialState(): KimiClientState {
|
|||
function cloneState(s: KimiClientState): KimiClientState {
|
||||
return {
|
||||
...s,
|
||||
sessions: [...s.sessions],
|
||||
// Reuse the `sessions` array reference when an event does not touch it.
|
||||
// Every session-mutating case below already builds its own array via
|
||||
// `[...]` / `.map` / `.filter`, so sharing the reference is safe — and it
|
||||
// keeps `rawState.sessions` stable for events that don't change sessions,
|
||||
// so the sidebar computeds (sessionsForView / workspaceGroups /
|
||||
// mergedWorkspaces) are not dirtied by unrelated events.
|
||||
sessions: s.sessions,
|
||||
messagesBySession: { ...s.messagesBySession },
|
||||
approvalsBySession: { ...s.approvalsBySession },
|
||||
planReviewByToolCallId: { ...s.planReviewByToolCallId },
|
||||
|
|
|
|||
|
|
@ -149,3 +149,44 @@ describe('reduceAppEvent taskProgress', () => {
|
|||
expect(lines?.at(-1)).toBe('line 59');
|
||||
});
|
||||
});
|
||||
|
||||
describe('reduceAppEvent sessions reference stability', () => {
|
||||
// The sidebar computeds (sessionsForView / workspaceGroups / mergedWorkspaces)
|
||||
// depend on `rawState.sessions`. Events that do not change sessions must keep
|
||||
// the SAME array reference so those computeds are not dirtied; events that do
|
||||
// change sessions must produce a NEW array.
|
||||
|
||||
it('reuses the sessions reference for an event that does not touch sessions', () => {
|
||||
const state = {
|
||||
...createInitialState(),
|
||||
sessions: [makeSession('s1', '2026-01-01T00:00:00.000Z')],
|
||||
messagesBySession: { s1: [makeMessage('s1', '2026-01-01T00:00:00.000Z')] },
|
||||
};
|
||||
const next = reduceAppEvent(
|
||||
state,
|
||||
{
|
||||
type: 'messageUpdated',
|
||||
sessionId: 's1',
|
||||
messageId: 'msg_2026-01-01T00:00:00.000Z',
|
||||
content: [{ type: 'text', text: 'updated' }],
|
||||
status: 'completed',
|
||||
},
|
||||
{ sessionId: 's1', seq: 2 },
|
||||
);
|
||||
expect(next.sessions).toBe(state.sessions);
|
||||
});
|
||||
|
||||
it('produces a new sessions array for an event that changes sessions', () => {
|
||||
const state = {
|
||||
...createInitialState(),
|
||||
sessions: [makeSession('s1', '2026-01-01T00:00:00.000Z')],
|
||||
};
|
||||
const next = reduceAppEvent(
|
||||
state,
|
||||
{ type: 'sessionCreated', session: makeSession('s2', '2026-02-01T00:00:00.000Z') },
|
||||
{ sessionId: 's2', seq: 3 },
|
||||
);
|
||||
expect(next.sessions).not.toBe(state.sessions);
|
||||
expect(next.sessions.map((s) => s.id)).toEqual(['s2', 's1']);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue