diff --git a/src/features/chat/app-server/actions/threads.ts b/src/features/chat/app-server/actions/threads.ts index 390991f3..b5c39fc7 100644 --- a/src/features/chat/app-server/actions/threads.ts +++ b/src/features/chat/app-server/actions/threads.ts @@ -3,7 +3,7 @@ import { threadActivationSnapshotFromAppServerResponse } from "../../../../app-s import type { RuntimeSnapshot } from "../../application/runtime/snapshot"; import { runtimeConfigOrDefault } from "../../domain/runtime/effective"; import { serviceTierRequestForThreadStart } from "../../application/runtime/thread-settings-update"; -import { resumedThreadAction } from "../../application/threads/resume"; +import { resumedThreadAction } from "../../application/state/actions"; import type { ChatServerActionHost } from "./host"; import type { ChatState } from "../../application/state/root-reducer"; diff --git a/src/features/chat/application/state/actions.ts b/src/features/chat/application/state/actions.ts index cf9de393..72b0eaa5 100644 --- a/src/features/chat/application/state/actions.ts +++ b/src/features/chat/application/state/actions.ts @@ -1,5 +1,6 @@ import type { ServerInitialization } from "../../../../domain/server/initialization"; -import type { Thread } from "../../../../domain/threads/model"; +import type { ThreadActivationSnapshot } from "../../../../domain/threads/activation"; +import { upsertThread, type Thread } from "../../../../domain/threads/model"; import { parseServiceTier, type ServiceTier } from "../../../../domain/runtime/policy"; import { normalizeReasoningEffort, type ReasoningEffort } from "../../../../domain/catalog/metadata"; import type { ChatRuntimeState } from "../../domain/runtime/state"; @@ -7,6 +8,29 @@ import type { CollaborationMode } from "../../domain/runtime/pending-settings"; import type { MessageStreamItem } from "../../domain/message-stream/items"; import type { PendingTurnStart } from "../conversation/turn-state"; +interface ResumedThreadActionParams { + response: ThreadActivationSnapshot; + listedThreads?: readonly Thread[]; + items?: readonly MessageStreamItem[]; + preserveRequestedRuntimeSettings?: boolean; +} + +interface ResumedThreadFromActiveRuntimeParams { + thread: Thread; + cwd: string; + runtime: Pick< + ChatRuntimeState, + | "activeModel" + | "activeReasoningEffort" + | "activeServiceTier" + | "activeApprovalPolicy" + | "activeApprovalsReviewer" + | "activePermissionProfile" + >; + listedThreads?: readonly Thread[]; + items?: readonly MessageStreamItem[]; +} + export interface ActiveThreadResumedAction { type: "active-thread/resumed"; thread: Thread; @@ -98,6 +122,41 @@ export interface TurnStartFailedAction { items: readonly MessageStreamItem[]; } +export function resumedThreadActionFromActiveRuntime(params: ResumedThreadFromActiveRuntimeParams): ActiveThreadResumedAction { + return resumedThreadAction({ + response: { + thread: params.thread, + cwd: params.cwd, + model: params.runtime.activeModel, + reasoningEffort: params.runtime.activeReasoningEffort, + serviceTier: params.runtime.activeServiceTier, + approvalPolicy: params.runtime.activeApprovalPolicy, + approvalsReviewer: params.runtime.activeApprovalsReviewer, + activePermissionProfile: params.runtime.activePermissionProfile, + }, + ...(params.listedThreads ? { listedThreads: params.listedThreads } : {}), + ...(params.items ? { items: params.items } : {}), + }); +} + +export function resumedThreadAction(params: ResumedThreadActionParams): ActiveThreadResumedAction { + const { response } = params; + return { + type: "active-thread/resumed", + thread: response.thread, + cwd: response.cwd, + model: response.model, + reasoningEffort: response.reasoningEffort, + serviceTier: response.serviceTier, + approvalPolicy: response.approvalPolicy, + approvalsReviewer: response.approvalsReviewer, + activePermissionProfile: response.activePermissionProfile, + ...(params.items ? { items: params.items } : {}), + ...(params.listedThreads ? { listedThreads: upsertThread(params.listedThreads, response.thread) } : {}), + ...(params.preserveRequestedRuntimeSettings ? { preserveRequestedRuntimeSettings: true } : {}), + }; +} + export function activeThreadSettingsAppliedAction(settings: ActiveThreadSettingsAppliedActionSettings): ActiveThreadSettingsAppliedAction { return { type: "active-thread/settings-applied", diff --git a/src/features/chat/application/threads/resume-controller.ts b/src/features/chat/application/threads/resume-controller.ts index b6f795e3..12c5fc65 100644 --- a/src/features/chat/application/threads/resume-controller.ts +++ b/src/features/chat/application/threads/resume-controller.ts @@ -1,10 +1,10 @@ import type { AppServerClient } from "../../../../app-server/connection/client"; import type { ThreadTokenUsage } from "../../../../domain/runtime/metrics"; import { resumeChatThread, type ChatThreadResumeSnapshot } from "../../app-server/threads/resume"; +import { resumedThreadAction } from "../state/actions"; import { activeThreadId, canSwitchToThread, listedThreads, messageStreamItemsEmpty } from "../state/selectors"; import type { ChatStateStore } from "../state/store"; import type { RestorationController } from "./restoration-controller"; -import { resumedThreadAction } from "./resume"; import type { HistoryController } from "./history-controller"; import type { ChatResumeWorkTracker, ActiveChatResume } from "../lifecycle"; diff --git a/src/features/chat/application/threads/resume.ts b/src/features/chat/application/threads/resume.ts deleted file mode 100644 index 53598dae..00000000 --- a/src/features/chat/application/threads/resume.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { upsertThread } from "../../../../domain/threads/model"; -import type { Thread } from "../../../../domain/threads/model"; -import type { ThreadActivationSnapshot } from "../../../../domain/threads/activation"; -import type { ChatRuntimeState } from "../../domain/runtime/state"; -import type { MessageStreamItem } from "../../domain/message-stream/items"; -import type { ActiveThreadResumedAction } from "../state/actions"; - -interface ResumedThreadActionParams { - response: ThreadActivationSnapshot; - listedThreads?: readonly Thread[]; - items?: readonly MessageStreamItem[]; - preserveRequestedRuntimeSettings?: boolean; -} - -interface ResumedThreadFromActiveRuntimeParams { - thread: Thread; - cwd: string; - runtime: Pick< - ChatRuntimeState, - | "activeModel" - | "activeReasoningEffort" - | "activeServiceTier" - | "activeApprovalPolicy" - | "activeApprovalsReviewer" - | "activePermissionProfile" - >; - listedThreads?: readonly Thread[]; - items?: readonly MessageStreamItem[]; -} - -export function resumedThreadActionFromActiveRuntime(params: ResumedThreadFromActiveRuntimeParams): ActiveThreadResumedAction { - return resumedThreadAction({ - response: { - thread: params.thread, - cwd: params.cwd, - model: params.runtime.activeModel, - reasoningEffort: params.runtime.activeReasoningEffort, - serviceTier: params.runtime.activeServiceTier, - approvalPolicy: params.runtime.activeApprovalPolicy, - approvalsReviewer: params.runtime.activeApprovalsReviewer, - activePermissionProfile: params.runtime.activePermissionProfile, - }, - ...(params.listedThreads ? { listedThreads: params.listedThreads } : {}), - ...(params.items ? { items: params.items } : {}), - }); -} - -export function resumedThreadAction(params: ResumedThreadActionParams): ActiveThreadResumedAction { - const { response } = params; - return { - type: "active-thread/resumed", - thread: response.thread, - cwd: response.cwd, - model: response.model, - reasoningEffort: response.reasoningEffort, - serviceTier: response.serviceTier, - approvalPolicy: response.approvalPolicy, - approvalsReviewer: response.approvalsReviewer, - activePermissionProfile: response.activePermissionProfile, - ...(params.items ? { items: params.items } : {}), - ...(params.listedThreads ? { listedThreads: upsertThread(params.listedThreads, response.thread) } : {}), - ...(params.preserveRequestedRuntimeSettings ? { preserveRequestedRuntimeSettings: true } : {}), - }; -} diff --git a/src/features/chat/application/threads/thread-management-actions.ts b/src/features/chat/application/threads/thread-management-actions.ts index f617fe32..c81da326 100644 --- a/src/features/chat/application/threads/thread-management-actions.ts +++ b/src/features/chat/application/threads/thread-management-actions.ts @@ -3,10 +3,10 @@ import { forkThread as forkThreadOnAppServer, rollbackThread as rollbackThreadOn import { inheritedForkThreadName, type Thread } from "../../../../domain/threads/model"; import type { ThreadOperations } from "../../../threads/thread-operations"; import { messageStreamItemsFromTurns } from "../../app-server/mappers/message-stream/turn-items"; +import { resumedThreadActionFromActiveRuntime } from "../state/actions"; import { messageStreamRollbackCandidate, messageStreamTurnsAfterTurnId } from "../state/message-stream"; import { chatTurnBusy, type ChatAction, type ChatState } from "../state/root-reducer"; import type { ChatStateStore } from "../state/store"; -import { resumedThreadActionFromActiveRuntime } from "./resume"; const STATUS_COMPACTION_REQUESTED = "Compaction requested."; const STATUS_ROLLBACK_STARTING = "Rolling back latest turn..."; diff --git a/tests/features/chat/threads/resume.test.ts b/tests/features/chat/state-actions.test.ts similarity index 90% rename from tests/features/chat/threads/resume.test.ts rename to tests/features/chat/state-actions.test.ts index 5425ec8d..6d408e7c 100644 --- a/tests/features/chat/threads/resume.test.ts +++ b/tests/features/chat/state-actions.test.ts @@ -1,8 +1,8 @@ import { describe, expect, it } from "vitest"; -import { resumedThreadActionFromActiveRuntime, resumedThreadAction } from "../../../../src/features/chat/application/threads/resume"; -import type { ThreadActivationSnapshot } from "../../../../src/domain/threads/activation"; -import type { Thread } from "../../../../src/domain/threads/model"; +import { resumedThreadActionFromActiveRuntime, resumedThreadAction } from "../../../src/features/chat/application/state/actions"; +import type { ThreadActivationSnapshot } from "../../../src/domain/threads/activation"; +import type { Thread } from "../../../src/domain/threads/model"; describe("chat thread resume helpers", () => { it("builds thread resumed actions from response snapshots", () => {