diff --git a/src/features/chat/application/state/clone.ts b/src/features/chat/application/state/clone.ts deleted file mode 100644 index 290d5e3e..00000000 --- a/src/features/chat/application/state/clone.ts +++ /dev/null @@ -1,61 +0,0 @@ -import type { ChatState } from "./root-reducer"; -import { cloneDisclosureUiState } from "./ui-state"; -import type { ChatMessageStreamActiveSegment, ChatMessageStreamState } from "./message-stream"; - -export function cloneChatState(state: ChatState): ChatState { - return { - connection: { - ...state.connection, - availableModels: [...state.connection.availableModels], - availableSkills: [...state.connection.availableSkills], - }, - threadList: { - listedThreads: [...state.threadList.listedThreads], - threadsLoaded: state.threadList.threadsLoaded, - }, - activeThread: { ...state.activeThread }, - runtime: { ...state.runtime }, - turn: { lifecycle: state.turn.lifecycle }, - messageStream: cloneMessageStreamState(state.messageStream), - requests: { - approvals: [...state.requests.approvals], - pendingUserInputs: [...state.requests.pendingUserInputs], - pendingMcpElicitations: [...state.requests.pendingMcpElicitations], - userInputDrafts: new Map(state.requests.userInputDrafts), - mcpElicitationDrafts: new Map(state.requests.mcpElicitationDrafts), - }, - composer: { - ...state.composer, - suggestions: [...state.composer.suggestions], - }, - ui: { - toolbarPanel: state.ui.toolbarPanel, - archiveConfirmThreadId: state.ui.archiveConfirmThreadId, - rename: { ...state.ui.rename }, - goalEditor: { ...state.ui.goalEditor }, - messageActionMenu: { ...state.ui.messageActionMenu }, - disclosures: cloneDisclosureUiState(state.ui.disclosures), - }, - }; -} - -function cloneMessageStreamState(state: ChatMessageStreamState): ChatMessageStreamState { - return { - stableItems: [...state.stableItems], - activeSegment: cloneActiveSegment(state.activeSegment), - turnDiffs: new Map(state.turnDiffs), - historyCursor: state.historyCursor, - loadingHistory: state.loadingHistory, - reportedLogs: new Set(state.reportedLogs), - }; -} - -function cloneActiveSegment(segment: ChatMessageStreamActiveSegment | null): ChatMessageStreamActiveSegment | null { - if (!segment) return null; - return { - turnId: segment.turnId, - items: [...segment.items], - indexById: new Map(segment.indexById), - indexBySourceItemId: new Map(segment.indexBySourceItemId), - }; -} diff --git a/src/features/chat/application/state/store.ts b/src/features/chat/application/state/store.ts index 8d32bcd3..f166ee37 100644 --- a/src/features/chat/application/state/store.ts +++ b/src/features/chat/application/state/store.ts @@ -1,4 +1,5 @@ -import { cloneChatState } from "./clone"; +import { cloneDisclosureUiState } from "./ui-state"; +import type { ChatMessageStreamActiveSegment, ChatMessageStreamState } from "./message-stream"; import { chatReducer, createChatState, type ChatAction, type ChatState } from "./root-reducer"; export interface ChatStateStore { @@ -27,3 +28,61 @@ export function createChatStateStore(initialState: ChatState = createChatState() }, }; } + +function cloneChatState(state: ChatState): ChatState { + return { + connection: { + ...state.connection, + availableModels: [...state.connection.availableModels], + availableSkills: [...state.connection.availableSkills], + }, + threadList: { + listedThreads: [...state.threadList.listedThreads], + threadsLoaded: state.threadList.threadsLoaded, + }, + activeThread: { ...state.activeThread }, + runtime: { ...state.runtime }, + turn: { lifecycle: state.turn.lifecycle }, + messageStream: cloneMessageStreamState(state.messageStream), + requests: { + approvals: [...state.requests.approvals], + pendingUserInputs: [...state.requests.pendingUserInputs], + pendingMcpElicitations: [...state.requests.pendingMcpElicitations], + userInputDrafts: new Map(state.requests.userInputDrafts), + mcpElicitationDrafts: new Map(state.requests.mcpElicitationDrafts), + }, + composer: { + ...state.composer, + suggestions: [...state.composer.suggestions], + }, + ui: { + toolbarPanel: state.ui.toolbarPanel, + archiveConfirmThreadId: state.ui.archiveConfirmThreadId, + rename: { ...state.ui.rename }, + goalEditor: { ...state.ui.goalEditor }, + messageActionMenu: { ...state.ui.messageActionMenu }, + disclosures: cloneDisclosureUiState(state.ui.disclosures), + }, + }; +} + +function cloneMessageStreamState(state: ChatMessageStreamState): ChatMessageStreamState { + return { + stableItems: [...state.stableItems], + activeSegment: cloneActiveSegment(state.activeSegment), + turnDiffs: new Map(state.turnDiffs), + historyCursor: state.historyCursor, + loadingHistory: state.loadingHistory, + reportedLogs: new Set(state.reportedLogs), + }; +} + +function cloneActiveSegment(segment: ChatMessageStreamActiveSegment | null): ChatMessageStreamActiveSegment | null { + if (!segment) return null; + return { + turnId: segment.turnId, + items: [...segment.items], + indexById: new Map(segment.indexById), + indexBySourceItemId: new Map(segment.indexBySourceItemId), + }; +}