Clarify app-server query adapter boundaries

This commit is contained in:
murashit 2026-06-16 08:07:51 +09:00
parent 3f93959a5b
commit 2f7885a1f8
23 changed files with 29 additions and 47 deletions

View file

@ -1,9 +1,9 @@
import { MutationObserver, QueryClient, QueryObserver, type QueryObserverResult } from "@tanstack/query-core";
import type { AppServerClient } from "../connection/client";
import { listModelMetadata } from "../services/catalog";
import { readRateLimitMetadataProbe, readRuntimeConfigSnapshot, readSkillMetadataProbe } from "../services/metadata";
import { listThreads } from "../services/threads";
import { listModelMetadata } from "../catalog/data";
import { readRateLimitMetadataProbe, readRuntimeConfigSnapshot, readSkillMetadataProbe } from "./metadata-probes";
import { listThreads } from "../threads/data";
import type { ModelMetadata } from "../../domain/catalog/metadata";
import { createServerDiagnostics, diagnosticProbeError, diagnosticProbeOk, diagnosticsWithProbe } from "../../domain/server/diagnostics";
import type { Thread } from "../../domain/threads/model";

View file

@ -1,7 +1,7 @@
import type { AppServerClient } from "../connection/client";
import { runtimeConfigSnapshotFromAppServerConfig } from "../protocol/runtime-config";
import { accountRateLimitsSummaryFromResponse, rateLimitSnapshotFromAccountRateLimitsResponse } from "../protocol/runtime-metrics";
import { listSkillCatalog } from "./catalog";
import { listSkillCatalog } from "../catalog/data";
import { diagnosticProbeError, diagnosticProbeOk, type Diagnostics } from "../../domain/server/diagnostics";
import type { SkillMetadata } from "../../domain/catalog/metadata";
import type { RuntimeConfigSnapshot } from "../../domain/runtime/config";

View file

@ -1,7 +1,7 @@
import type { RuntimeOverride, RuntimeOverrideSettings } from "../../domain/runtime/overrides";
import { runtimeOverride, validatedRuntimeOverrideForModelMetadata } from "../../domain/runtime/overrides";
import type { ModelListResponse } from "../../generated/app-server/v2/ModelListResponse";
import { listModelMetadata } from "./catalog";
import { listModelMetadata } from "../catalog/data";
interface RuntimeOverrideModelClient {
listModels(includeHidden: boolean): Promise<ModelListResponse>;

View file

@ -1,7 +1,7 @@
import type { ArchiveExportSettings } from "../../domain/threads/archive-markdown";
import type { AppServerClient } from "../connection/client";
import { exportArchivedThreadMarkdown, type ArchiveExportAdapter } from "./thread-archive-markdown";
import { readThreadForArchiveExport } from "./threads";
import { readThreadForArchiveExport } from "../threads/data";
export interface ArchiveThreadOptions {
settings: ArchiveExportSettings;

View file

@ -11,7 +11,7 @@ import {
type McpServerStartupStatus,
type McpServerStatusSummary,
} from "../../../../domain/server/diagnostics";
import { readRateLimitMetadataProbe } from "../../../../app-server/services/metadata";
import { readRateLimitMetadataProbe } from "../../../../app-server/query/metadata-probes";
import type { SharedServerMetadata } from "../../../../domain/server/metadata";
import { mcpStatusLines as buildMcpStatusLines } from "../../application/connection/diagnostics-display";
import { cloneServerDiagnostics, type ChatServerActionHost } from "./host";

View file

@ -3,7 +3,7 @@ import {
readSkillMetadataProbe,
type RateLimitMetadataProbeResult,
type SkillMetadataProbeResult,
} from "../../../../app-server/services/metadata";
} from "../../../../app-server/query/metadata-probes";
import { diagnosticsWithProbe } from "../../../../domain/server/diagnostics";
import type { SharedServerMetadata } from "../../../../domain/server/metadata";
import { cloneServerDiagnostics, type ChatServerActionHost } from "./host";

View file

@ -1,6 +1,6 @@
import type { AppServerClient } from "../../../../app-server/connection/client";
import { codexTextInputWithAttachments, type CodexInput } from "../../../../domain/chat/input";
import { readReferencedThreadConversationSummaries } from "../../../../app-server/services/threads";
import { readReferencedThreadConversationSummaries } from "../../../../app-server/threads/data";
import { referencedThreadPromptBundle, REFERENCED_THREAD_TURN_LIMIT } from "../../../../domain/threads/reference";
import type { Thread } from "../../../../domain/threads/model";
import { referencedThreadStatus, referencedThreadUnreadableMessage } from "./messages";

View file

@ -1,5 +1,5 @@
import type { AppServerClient } from "../../../../app-server/connection/client";
import { rollbackThread as rollbackThreadOnAppServer } from "../../../../app-server/services/threads";
import { rollbackThread as rollbackThreadOnAppServer } from "../../../../app-server/threads/data";
import { inheritedForkThreadName } from "../../../../domain/threads/model";
import type { ThreadOperations } from "../../../threads/thread-operations";
import {

View file

@ -1,7 +1,6 @@
import { Notice } from "obsidian";
import type { ConnectionManager } from "../../../app-server/connection/connection-manager";
import type { ModelMetadata } from "../../../domain/catalog/metadata";
import type { SharedServerMetadata } from "../../../domain/server/metadata";
import type { Thread } from "../../../domain/threads/model";
import type { ConnectionWorkTracker } from "../../../shared/lifecycle/connection-work";
@ -51,9 +50,6 @@ export interface ChatConnectionBundleContext {
fetchAppServerMetadata(): Promise<SharedServerMetadata | null>;
refreshAppServerMetadata(options?: { forceSkills?: boolean }): Promise<SharedServerMetadata | null>;
refreshActiveThreads(): Promise<readonly Thread[]>;
modelsSnapshot(): readonly ModelMetadata[] | null;
fetchModels(): Promise<readonly ModelMetadata[]>;
refreshModels(): Promise<readonly ModelMetadata[]>;
archiveThreadInCatalog(threadId: string): void;
renameThreadInCatalog(threadId: string, name: string | null): void;
};

View file

@ -71,7 +71,6 @@ type ChatThreadCatalog = Pick<
| "archiveThreadInCatalog"
| "renameThreadInCatalog"
| "refreshThreadsViewLiveState"
| "refreshFromOpenSurface"
| "setActiveThreads"
| "updateAppServerMetadata"
| "refreshActiveThreads"

View file

@ -41,12 +41,7 @@ export interface CodexThreadsHost {
type ThreadsThreadCatalog = Pick<
SharedThreadCatalog,
| "archiveThreadInCatalog"
| "renameThreadInCatalog"
| "refreshFromOpenSurface"
| "refreshActiveThreads"
| "activeThreadsSnapshot"
| "observeActiveThreadsResult"
"archiveThreadInCatalog" | "renameThreadInCatalog" | "refreshActiveThreads" | "activeThreadsSnapshot" | "observeActiveThreadsResult"
>;
export interface CodexThreadsSessionEnvironment {

View file

@ -1,6 +1,6 @@
import type { AppServerClient } from "../../app-server/connection/client";
import { generateThreadTitleWithCodex } from "../../app-server/services/thread-title-generation";
import { readCompletedConversationSummariesPage } from "../../app-server/services/threads";
import { readCompletedConversationSummariesPage } from "../../app-server/threads/data";
import type { ThreadConversationSummary } from "../../domain/threads/transcript";
import {
findThreadTitleContext,

View file

@ -1,6 +1,6 @@
import type { AppServerClient } from "../app-server/connection/client";
import { listHookData, type HookData } from "../app-server/services/catalog";
import { listThreads } from "../app-server/services/threads";
import { listHookData, type HookData } from "../app-server/catalog/data";
import { listThreads } from "../app-server/threads/data";
import type { Thread } from "../domain/threads/model";
import { errorMessage } from "../utils";

View file

@ -1,8 +1,8 @@
import type { AppServerClient } from "../app-server/connection/client";
import type { AppServerObservedQueryResult } from "../app-server/query/cache";
import { withShortLivedAppServerClient } from "../app-server/connection/short-lived-client";
import { setHookItemEnabled, trustHookItem } from "../app-server/services/catalog";
import { restoreArchivedThread as restoreArchivedThreadOnAppServer } from "../app-server/services/threads";
import { setHookItemEnabled, trustHookItem } from "../app-server/catalog/data";
import { restoreArchivedThread as restoreArchivedThreadOnAppServer } from "../app-server/threads/data";
import type { HookItem, ModelMetadata, ReasoningEffort } from "../domain/catalog/metadata";
import { findModelMetadataByIdOrName, sortedModelMetadata, supportedEffortsForModelMetadata } from "../domain/catalog/metadata";
import type { Thread } from "../domain/threads/model";
@ -27,7 +27,7 @@ export interface SettingsDynamicDataHost {
type SettingsThreadCatalog = Pick<
SharedThreadCatalog,
| "refreshFromOpenSurface"
| "invalidateThreadsFromOpenSurface"
| "modelsSnapshot"
| "observeModelsResult"
| "fetchModels"
@ -331,7 +331,7 @@ export class SettingsDynamicDataController {
status: `Restored "${archivedThreadDisplayTitle(restoredThread)}".`,
operationId,
});
this.host.threadCatalog.refreshFromOpenSurface();
this.host.threadCatalog.invalidateThreadsFromOpenSurface();
} catch (error) {
if (this.isStaleSettingsDynamicOperation(operationId)) return;
this.archivedThreadsLifecycle = transitionSettingsDynamicSectionLifecycle(this.archivedThreadsLifecycle, {

View file

@ -106,10 +106,6 @@ export class SharedThreadCatalog {
}
}
refreshFromOpenSurface(): void {
this.invalidateThreadsFromOpenSurface();
}
invalidateThreadsFromOpenSurface(): void {
this.options.surfaces.invalidateThreadsFromOpenSurface();
}

View file

@ -1,9 +1,9 @@
import { describe, expect, it, vi } from "vitest";
import type { AppServerClient } from "../../src/app-server/connection/client";
import { listHookData, listSkillCatalog } from "../../src/app-server/services/catalog";
import { listHookData, listSkillCatalog } from "../../src/app-server/catalog/data";
describe("app-server catalog services", () => {
describe("app-server catalog data adapters", () => {
it("returns enabled skill options while preserving total app-server skill count", async () => {
const client = {
listSkills: vi.fn().mockResolvedValue({

View file

@ -1,9 +1,9 @@
import { describe, expect, it, vi } from "vitest";
import type { AppServerClient } from "../../src/app-server/connection/client";
import { listThreads } from "../../src/app-server/services/threads";
import { listThreads } from "../../src/app-server/threads/data";
describe("app-server thread services", () => {
describe("app-server thread data adapters", () => {
it("maps listed threads to domain threads with archive state", async () => {
const clientListThreads = vi.fn().mockResolvedValue({
data: [{ id: "thread-1", preview: "Preview", name: null, createdAt: 10, updatedAt: 20 }],

View file

@ -1288,7 +1288,6 @@ interface ChatHostFixtureOverrides {
openTurnDiff?: CodexChatHost["workspace"]["openTurnDiff"];
archiveThreadInCatalog?: CodexChatHost["threadCatalog"]["archiveThreadInCatalog"];
renameThreadInCatalog?: CodexChatHost["threadCatalog"]["renameThreadInCatalog"];
refreshFromOpenSurface?: CodexChatHost["threadCatalog"]["refreshFromOpenSurface"];
refreshThreadsViewLiveState?: CodexChatHost["threadCatalog"]["refreshThreadsViewLiveState"];
setActiveThreads?: CodexChatHost["threadCatalog"]["setActiveThreads"];
updateAppServerMetadata?: CodexChatHost["threadCatalog"]["updateAppServerMetadata"];
@ -1365,7 +1364,6 @@ function chatHost(overrides: ChatHostFixtureOverrides = {}): CodexChatHost {
threadCatalog: {
archiveThreadInCatalog: overrides.archiveThreadInCatalog ?? vi.fn(),
renameThreadInCatalog: overrides.renameThreadInCatalog ?? vi.fn(),
refreshFromOpenSurface: overrides.refreshFromOpenSurface ?? vi.fn(),
refreshThreadsViewLiveState: overrides.refreshThreadsViewLiveState ?? vi.fn(),
setActiveThreads:
overrides.setActiveThreads ??

View file

@ -427,7 +427,6 @@ function threadsHost(overrides: Record<string, unknown> = {}) {
threadCatalog: {
archiveThreadInCatalog: vi.fn(),
renameThreadInCatalog: vi.fn(),
refreshFromOpenSurface: vi.fn(),
refreshActiveThreads: vi.fn(async () => {
const client = connectionMock.state.client;
if (!client) return [];

View file

@ -524,7 +524,7 @@ describe("CodexPanelPlugin boot restored panel loading", () => {
const plugin = await pluginWithLeaves([disconnectedLeaf, connectedLeaf]);
threadCatalog(plugin).refreshFromOpenSurface();
plugin.runtime.settingTabHost().threadCatalog.invalidateThreadsFromOpenSurface();
expect(disconnectedRefresh).not.toHaveBeenCalled();
expect(connectedRefresh).toHaveBeenCalledOnce();
@ -648,7 +648,6 @@ function chatHostFixture(): CodexChatHost {
threadCatalog: {
archiveThreadInCatalog: vi.fn(),
renameThreadInCatalog: vi.fn(),
refreshFromOpenSurface: vi.fn(),
refreshThreadsViewLiveState: vi.fn(),
setActiveThreads: vi.fn(),
updateAppServerMetadata: vi.fn(() => null),

View file

@ -348,7 +348,7 @@ describe("settings tab", () => {
it("ignores stale archived restore results after a newer dynamic operation completes", async () => {
const staleRestore = deferred<{ thread: ThreadRecord }>();
const refreshFromOpenSurface = vi.fn();
const invalidateThreadsFromOpenSurface = vi.fn();
const initialClient = settingsClient({
threads: [appServerThread({ id: "thread-old", preview: "Old archived" })],
});
@ -368,7 +368,7 @@ describe("settings tab", () => {
.mockImplementationOnce((_codexPath: string, _cwd: string, operation: (client: unknown) => Promise<unknown>) =>
operation(newerClient),
);
const controller = new SettingsDynamicDataController(settingsTabHost({ refreshFromOpenSurface }), {
const controller = new SettingsDynamicDataController(settingsTabHost({ invalidateThreadsFromOpenSurface }), {
display: vi.fn(),
notify: vi.fn(),
});
@ -383,7 +383,7 @@ describe("settings tab", () => {
staleRestore.resolve({ thread: appServerThread({ id: "thread-old", preview: "Restored old" }) });
await restore;
expect(refreshFromOpenSurface).not.toHaveBeenCalled();
expect(invalidateThreadsFromOpenSurface).not.toHaveBeenCalled();
expect(controller.snapshot().archivedThreads.map((thread) => thread.preview)).toEqual(["New archived"]);
});
@ -611,7 +611,7 @@ function newSettingsTab(
observeModels?: CodexPanelSettingTabHost["threadCatalog"]["observeModelsResult"];
notifyAppServerQueryContextChanged?: () => void;
refreshOpenViews?: () => void;
refreshFromOpenSurface?: () => void;
invalidateThreadsFromOpenSurface?: () => void;
settings?: Partial<{
threadNamingModel: string | null;
threadNamingEffort: string | null;
@ -633,7 +633,7 @@ function settingsTabHost(
observeModels?: CodexPanelSettingTabHost["threadCatalog"]["observeModelsResult"];
notifyAppServerQueryContextChanged?: () => void;
refreshOpenViews?: () => void;
refreshFromOpenSurface?: () => void;
invalidateThreadsFromOpenSurface?: () => void;
settings?: Partial<{
threadNamingModel: string | null;
threadNamingEffort: string | null;
@ -661,7 +661,7 @@ function settingsTabHost(
saveSettings: options.saveSettings ?? vi.fn().mockResolvedValue(undefined),
refreshOpenViews: options.refreshOpenViews ?? vi.fn(),
threadCatalog: {
refreshFromOpenSurface: options.refreshFromOpenSurface ?? vi.fn(),
invalidateThreadsFromOpenSurface: options.invalidateThreadsFromOpenSurface ?? vi.fn(),
modelsSnapshot: vi.fn(() => options.modelsSnapshot ?? []),
fetchModels: options.fetchModels ?? vi.fn().mockResolvedValue(options.modelsSnapshot ?? []),
refreshModels: options.refreshModels ?? vi.fn().mockResolvedValue(options.modelsSnapshot ?? []),