diff --git a/src/features/thread-operations/archive.ts b/src/app-server/services/thread-archive.ts similarity index 68% rename from src/features/thread-operations/archive.ts rename to src/app-server/services/thread-archive.ts index 107ee4c1..a8dd2b41 100644 --- a/src/features/thread-operations/archive.ts +++ b/src/app-server/services/thread-archive.ts @@ -1,10 +1,10 @@ -import type { AppServerClient } from "../../app-server/connection/client"; -import { readThreadForArchiveExport } from "../../app-server/services/threads"; -import type { CodexPanelSettings } from "../../settings/model"; -import { exportArchivedThreadMarkdown, type ArchiveExportAdapter } from "./archive-markdown"; +import type { ArchiveExportAdapter, ArchiveExportSettings } from "../../domain/threads/archive-markdown"; +import type { AppServerClient } from "../connection/client"; +import { exportArchivedThreadMarkdown } from "../../domain/threads/archive-markdown"; +import { readThreadForArchiveExport } from "./threads"; export interface ArchiveThreadOptions { - settings: CodexPanelSettings; + settings: ArchiveExportSettings; vaultPath: string; archiveAdapter: () => ArchiveExportAdapter; saveMarkdown: boolean; diff --git a/src/features/thread-operations/rename.ts b/src/app-server/services/thread-rename.ts similarity index 88% rename from src/features/thread-operations/rename.ts rename to src/app-server/services/thread-rename.ts index 869dd916..931c4e2a 100644 --- a/src/features/thread-operations/rename.ts +++ b/src/app-server/services/thread-rename.ts @@ -1,4 +1,4 @@ -import type { AppServerClient } from "../../app-server/connection/client"; +import type { AppServerClient } from "../connection/client"; import { normalizeExplicitThreadName } from "../../domain/threads/model"; export interface RenameThreadResult { diff --git a/src/features/thread-operations/title-generation.ts b/src/app-server/services/thread-title-generation.ts similarity index 92% rename from src/features/thread-operations/title-generation.ts rename to src/app-server/services/thread-title-generation.ts index 6d7e5fba..071dad36 100644 --- a/src/features/thread-operations/title-generation.ts +++ b/src/app-server/services/thread-title-generation.ts @@ -4,12 +4,16 @@ import { type EphemeralStructuredTurnClientFactory, type EphemeralStructuredTurnRuntimeClient, type StructuredTurnOutputSchema, -} from "../../app-server/services/ephemeral-structured-turn"; -import { listModelMetadata } from "../../app-server/services/catalog"; -import { conversationAssistantTextFromTurnRecord, type TurnRecord } from "../../app-server/protocol/turn"; +} from "./ephemeral-structured-turn"; +import { listModelMetadata } from "./catalog"; +import { conversationAssistantTextFromTurnRecord, type TurnRecord } from "../protocol/turn"; import type { ModelMetadata, ReasoningEffort } from "../../domain/catalog/metadata"; import { runtimeOverride, validatedRuntimeOverrideForModelMetadata } from "../../domain/runtime/overrides"; -import { threadTitleFromGeneratedText, threadTitlePrompt, type ThreadTitleContext } from "./title-model"; +import { + threadTitleFromGeneratedText, + threadTitlePrompt, + type ThreadTitleContext, +} from "../../domain/threads/title-generation-model"; const THREAD_TITLE_SERVICE_NAME = "codex-panel-naming"; const THREAD_TITLE_TIMEOUT_MS = 60_000; diff --git a/src/features/thread-operations/archive-markdown.ts b/src/domain/threads/archive-markdown.ts similarity index 98% rename from src/features/thread-operations/archive-markdown.ts rename to src/domain/threads/archive-markdown.ts index b12b3438..49e484bd 100644 --- a/src/features/thread-operations/archive-markdown.ts +++ b/src/domain/threads/archive-markdown.ts @@ -1,7 +1,7 @@ import { shortThreadId } from "../../utils"; -import { getThreadTitle, type Thread } from "../../domain/threads/model"; -import { referencedThreadMetadataFromPrompt } from "../../domain/threads/reference"; -import type { ThreadTranscriptEntry } from "../../domain/threads/transcript"; +import { getThreadTitle, type Thread } from "./model"; +import { referencedThreadMetadataFromPrompt } from "./reference"; +import type { ThreadTranscriptEntry } from "./transcript"; export interface ArchiveExportAdapter { exists(path: string): Promise; diff --git a/src/features/thread-operations/title-model.ts b/src/domain/threads/title-generation-model.ts similarity index 98% rename from src/features/thread-operations/title-model.ts rename to src/domain/threads/title-generation-model.ts index 8b89faff..f2ce1441 100644 --- a/src/features/thread-operations/title-model.ts +++ b/src/domain/threads/title-generation-model.ts @@ -1,4 +1,4 @@ -import type { ThreadConversationSummary } from "../../domain/threads/transcript"; +import type { ThreadConversationSummary } from "./transcript"; import { truncate } from "../../utils"; const MAX_CONTEXT_CHARS = 4_000; diff --git a/src/features/chat/application/threads/auto-title-controller.ts b/src/features/chat/application/threads/auto-title-controller.ts index d0f3e7de..d664779b 100644 --- a/src/features/chat/application/threads/auto-title-controller.ts +++ b/src/features/chat/application/threads/auto-title-controller.ts @@ -2,9 +2,9 @@ import type { AppServerClient } from "../../../../app-server/connection/client"; import type { Thread } from "../../../../domain/threads/model"; import type { ThreadConversationSummary } from "../../../../domain/threads/transcript"; import type { CodexPanelSettings } from "../../../../settings/model"; -import { renameThreadOnAppServer, threadRenameFromValue } from "../../../thread-operations/rename"; -import { generateThreadTitleWithCodex } from "../../../thread-operations/title-generation"; -import { threadTitleContextFromConversationSummary, type ThreadTitleContext } from "../../../thread-operations/title-model"; +import { renameThreadOnAppServer, threadRenameFromValue } from "../../../../app-server/services/thread-rename"; +import { generateThreadTitleWithCodex } from "../../../../app-server/services/thread-title-generation"; +import { threadTitleContextFromConversationSummary, type ThreadTitleContext } from "../../../../domain/threads/title-generation-model"; import type { ChatAction, ChatState } from "../state/root-reducer"; import type { ChatStateStore } from "../state/store"; import { messageStreamItems } from "../state/message-stream"; diff --git a/src/features/chat/application/threads/composition.ts b/src/features/chat/application/threads/composition.ts index 3295cf6b..1f33135c 100644 --- a/src/features/chat/application/threads/composition.ts +++ b/src/features/chat/application/threads/composition.ts @@ -1,5 +1,5 @@ import type { AppServerClient } from "../../../../app-server/connection/client"; -import type { ArchiveExportAdapter } from "../../../thread-operations/archive-markdown"; +import type { ArchiveExportAdapter } from "../../../../domain/threads/archive-markdown"; import { createGoalActions } from "./goal-actions"; import { createSelectionActions } from "./selection-actions"; import type { ChatResumeWorkTracker, ChatViewDeferredTasks } from "../lifecycle"; diff --git a/src/features/chat/application/threads/rename-editor-controller.ts b/src/features/chat/application/threads/rename-editor-controller.ts index 20a8957b..7013f9c7 100644 --- a/src/features/chat/application/threads/rename-editor-controller.ts +++ b/src/features/chat/application/threads/rename-editor-controller.ts @@ -3,13 +3,13 @@ import { readCompletedConversationSummariesPage } from "../../../../app-server/s import { getThreadTitle } from "../../../../domain/threads/model"; import type { Thread } from "../../../../domain/threads/model"; import type { CodexPanelSettings } from "../../../../settings/model"; -import { threadRenameFromValue } from "../../../thread-operations/rename"; -import { generateThreadTitleWithCodex } from "../../../thread-operations/title-generation"; +import { threadRenameFromValue } from "../../../../app-server/services/thread-rename"; +import { generateThreadTitleWithCodex } from "../../../../app-server/services/thread-title-generation"; import { findThreadTitleContext, THREAD_TITLE_CONTEXT_UNAVAILABLE_MESSAGE, type ThreadTitleContext, -} from "../../../thread-operations/title-model"; +} from "../../../../domain/threads/title-generation-model"; import { renameGenerationStillActive, type ChatAction, diff --git a/src/features/chat/application/threads/thread-management-actions.ts b/src/features/chat/application/threads/thread-management-actions.ts index d96a9274..a0c9fbcb 100644 --- a/src/features/chat/application/threads/thread-management-actions.ts +++ b/src/features/chat/application/threads/thread-management-actions.ts @@ -2,9 +2,9 @@ import type { AppServerClient } from "../../../../app-server/connection/client"; import { rollbackThread as rollbackThreadOnAppServer } from "../../../../app-server/services/threads"; import { inheritedForkThreadName } from "../../../../domain/threads/model"; import type { CodexPanelSettings } from "../../../../settings/model"; -import type { ArchiveExportAdapter } from "../../../thread-operations/archive-markdown"; -import { archiveThreadOnAppServer } from "../../../thread-operations/archive"; -import { renameThreadOnAppServer, threadRenameFromValue, type ThreadRename } from "../../../thread-operations/rename"; +import type { ArchiveExportAdapter } from "../../../../domain/threads/archive-markdown"; +import { archiveThreadOnAppServer } from "../../../../app-server/services/thread-archive"; +import { renameThreadOnAppServer, threadRenameFromValue, type ThreadRename } from "../../../../app-server/services/thread-rename"; import { archivedSourceOpenForkFailedMessage, finishBeforeArchivingThreadsMessage, diff --git a/src/features/chat/application/threads/title-context.ts b/src/features/chat/application/threads/title-context.ts index d3269f4a..f7a2a422 100644 --- a/src/features/chat/application/threads/title-context.ts +++ b/src/features/chat/application/threads/title-context.ts @@ -1,4 +1,4 @@ -import type { ThreadTitleContext } from "../../../thread-operations/title-model"; +import type { ThreadTitleContext } from "../../../../domain/threads/title-generation-model"; import { truncate } from "../../../../utils"; import { isCompletedTurnOutcomeMessage } from "../../domain/message-stream/selectors"; import type { MessageStreamItem, MessageStreamMessageItem } from "../../domain/message-stream/items"; diff --git a/src/features/chat/host/session.ts b/src/features/chat/host/session.ts index 86100366..79665ceb 100644 --- a/src/features/chat/host/session.ts +++ b/src/features/chat/host/session.ts @@ -8,7 +8,7 @@ import { getThreadTitle } from "../../../domain/threads/model"; import type { SharedServerMetadata } from "../../../domain/server/metadata"; import { shortThreadId } from "../../../utils"; import type { OpenCodexPanelSnapshot } from "../../../workspace/open-panel-snapshot"; -import type { ArchiveExportAdapter } from "../../thread-operations/archive-markdown"; +import type { ArchiveExportAdapter } from "../../../domain/threads/archive-markdown"; import type { CodexChatHost } from "../application/ports/chat-host"; import { ChatConnectionController } from "../application/connection/connection-controller"; import { reconnectPanel, type ChatReconnectActionsHost } from "../application/connection/reconnect-actions"; diff --git a/src/features/threads-view/session.ts b/src/features/threads-view/session.ts index 37d0ca0c..313f28ca 100644 --- a/src/features/threads-view/session.ts +++ b/src/features/threads-view/session.ts @@ -6,11 +6,11 @@ import { listThreads, readCompletedConversationSummariesPage } from "../../app-s import type { Thread } from "../../domain/threads/model"; import type { CodexPanelSettings } from "../../settings/model"; import type { OpenCodexPanelSnapshot } from "../../workspace/open-panel-snapshot"; -import { archiveThreadOnAppServer } from "../thread-operations/archive"; -import type { ArchiveExportAdapter } from "../thread-operations/archive-markdown"; -import { renameThreadOnAppServer, threadRenameFromValue } from "../thread-operations/rename"; -import { generateThreadTitleWithCodex } from "../thread-operations/title-generation"; -import { findThreadTitleContext, THREAD_TITLE_CONTEXT_UNAVAILABLE_MESSAGE } from "../thread-operations/title-model"; +import { archiveThreadOnAppServer } from "../../app-server/services/thread-archive"; +import type { ArchiveExportAdapter } from "../../domain/threads/archive-markdown"; +import { renameThreadOnAppServer, threadRenameFromValue } from "../../app-server/services/thread-rename"; +import { generateThreadTitleWithCodex } from "../../app-server/services/thread-title-generation"; +import { findThreadTitleContext, THREAD_TITLE_CONTEXT_UNAVAILABLE_MESSAGE } from "../../domain/threads/title-generation-model"; import { renderThreadsView, unmountThreadsView } from "./renderer"; import { completedThreadAutoNameState, diff --git a/tests/features/thread-operations/archive.test.ts b/tests/app-server/thread-archive.test.ts similarity index 88% rename from tests/features/thread-operations/archive.test.ts rename to tests/app-server/thread-archive.test.ts index 6f331bce..4ec10ab2 100644 --- a/tests/features/thread-operations/archive.test.ts +++ b/tests/app-server/thread-archive.test.ts @@ -1,10 +1,10 @@ import { describe, expect, it, vi } from "vitest"; -import type { AppServerClient } from "../../../src/app-server/connection/client"; -import type { ThreadRecord } from "../../../src/app-server/protocol/thread"; -import type { ArchiveExportAdapter } from "../../../src/features/thread-operations/archive-markdown"; -import { archiveThreadOnAppServer } from "../../../src/features/thread-operations/archive"; -import { DEFAULT_SETTINGS } from "../../../src/settings/model"; +import type { AppServerClient } from "../../src/app-server/connection/client"; +import type { ThreadRecord } from "../../src/app-server/protocol/thread"; +import type { ArchiveExportAdapter } from "../../src/domain/threads/archive-markdown"; +import { archiveThreadOnAppServer } from "../../src/app-server/services/thread-archive"; +import { DEFAULT_SETTINGS } from "../../src/settings/model"; describe("thread archive operation", () => { it("exports markdown before archiving when requested", async () => { diff --git a/tests/features/thread-operations/rename.test.ts b/tests/app-server/thread-rename.test.ts similarity index 89% rename from tests/features/thread-operations/rename.test.ts rename to tests/app-server/thread-rename.test.ts index 48cd6911..b05bbf30 100644 --- a/tests/features/thread-operations/rename.test.ts +++ b/tests/app-server/thread-rename.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it, vi } from "vitest"; -import type { AppServerClient } from "../../../src/app-server/connection/client"; -import { renameThreadOnAppServer, threadRenameFromValue } from "../../../src/features/thread-operations/rename"; +import type { AppServerClient } from "../../src/app-server/connection/client"; +import { renameThreadOnAppServer, threadRenameFromValue } from "../../src/app-server/services/thread-rename"; describe("thread rename operation", () => { it("normalizes thread names before saving them", async () => { diff --git a/tests/features/thread-operations/title.test.ts b/tests/app-server/thread-title-generation.test.ts similarity index 96% rename from tests/features/thread-operations/title.test.ts rename to tests/app-server/thread-title-generation.test.ts index 6bacd93f..29ccd672 100644 --- a/tests/features/thread-operations/title.test.ts +++ b/tests/app-server/thread-title-generation.test.ts @@ -6,21 +6,21 @@ import type { AppServerClient, AppServerClientHandlers, AppServerStartStructuredTurnOptions, -} from "../../../src/app-server/connection/client"; -import type { TurnItem, TurnRecord } from "../../../src/app-server/protocol/turn"; -import type { RequestId, ServerNotification } from "../../../src/app-server/connection/rpc-messages"; -import type { ServerInitialization } from "../../../src/domain/server/initialization"; +} from "../../src/app-server/connection/client"; +import type { TurnItem, TurnRecord } from "../../src/app-server/protocol/turn"; +import type { RequestId, ServerNotification } from "../../src/app-server/connection/rpc-messages"; +import type { ServerInitialization } from "../../src/domain/server/initialization"; import { generateThreadTitleWithCodex, type ThreadTitleClient, type ThreadTitleClientFactory, -} from "../../../src/features/thread-operations/title-generation"; +} from "../../src/app-server/services/thread-title-generation"; import { findThreadTitleContext, threadTitleContextFromConversationSummary, threadTitleFromGeneratedText, threadTitlePrompt, -} from "../../../src/features/thread-operations/title-model"; +} from "../../src/domain/threads/title-generation-model"; type InitializeResponse = ServerInitialization; type ModelListResponse = Awaited>; diff --git a/tests/features/thread-operations/archive-markdown.test.ts b/tests/domain/threads/archive-markdown.test.ts similarity index 99% rename from tests/features/thread-operations/archive-markdown.test.ts rename to tests/domain/threads/archive-markdown.test.ts index 9372c5f1..17d91f08 100644 --- a/tests/features/thread-operations/archive-markdown.test.ts +++ b/tests/domain/threads/archive-markdown.test.ts @@ -4,7 +4,7 @@ import { exportArchivedThreadMarkdown, type ArchiveExportAdapter, type ArchiveExportSettings, -} from "../../../src/features/thread-operations/archive-markdown"; +} from "../../../src/domain/threads/archive-markdown"; import type { Thread } from "../../../src/domain/threads/model"; import { referencedThreadPromptBundle } from "../../../src/domain/threads/reference"; import type { ThreadTranscriptEntry } from "../../../src/domain/threads/transcript"; diff --git a/tests/features/chat/threads/thread-management-actions.test.ts b/tests/features/chat/threads/thread-management-actions.test.ts index 0b79c6b2..212cf93d 100644 --- a/tests/features/chat/threads/thread-management-actions.test.ts +++ b/tests/features/chat/threads/thread-management-actions.test.ts @@ -2,7 +2,7 @@ import { describe, expect, it, vi } from "vitest"; import type { AppServerClient } from "../../../../src/app-server/connection/client"; import type { ThreadRecord } from "../../../../src/app-server/protocol/thread"; -import type { ArchiveExportAdapter } from "../../../../src/features/thread-operations/archive-markdown"; +import type { ArchiveExportAdapter } from "../../../../src/domain/threads/archive-markdown"; import { createChatState } from "../../../../src/features/chat/application/state/root-reducer"; import { createChatStateStore } from "../../../../src/features/chat/application/state/store"; import { diff --git a/tests/features/threads-view/view.test.ts b/tests/features/threads-view/view.test.ts index 1687aef7..05a4a178 100644 --- a/tests/features/threads-view/view.test.ts +++ b/tests/features/threads-view/view.test.ts @@ -4,7 +4,7 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; import { DEFAULT_SETTINGS } from "../../../src/settings/model"; import type { TurnRecord } from "../../../src/app-server/protocol/turn"; -import type * as ThreadTitleGeneratorModule from "../../../src/features/thread-operations/title-generation"; +import type * as ThreadTitleGeneratorModule from "../../../src/app-server/services/thread-title-generation"; import { deferred, waitForAsyncWork } from "../../support/async"; import { changeInputValue, installObsidianDomShims } from "../../support/dom"; @@ -66,7 +66,7 @@ vi.mock("../../../src/app-server/connection/connection-manager", () => { return { ConnectionManager, StaleConnectionError }; }); -vi.mock("../../../src/features/thread-operations/title-generation", async (importOriginal) => { +vi.mock("../../../src/app-server/services/thread-title-generation", async (importOriginal) => { const actual = await importOriginal(); return { ...actual,