Move shared thread operations out of features

This commit is contained in:
murashit 2026-06-15 08:20:32 +09:00
parent 7ee4c3c354
commit 6df921adfc
18 changed files with 52 additions and 48 deletions

View file

@ -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;

View file

@ -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 {

View file

@ -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;

View file

@ -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<boolean>;

View file

@ -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;

View file

@ -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";

View file

@ -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";

View file

@ -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,

View file

@ -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,

View file

@ -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";

View file

@ -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";

View file

@ -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,

View file

@ -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 () => {

View file

@ -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 () => {

View file

@ -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<ReturnType<AppServerClient["listModels"]>>;

View file

@ -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";

View file

@ -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 {

View file

@ -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<typeof ThreadTitleGeneratorModule>();
return {
...actual,