Simplify chat panel wiring indirection

This commit is contained in:
murashit 2026-06-30 21:06:27 +09:00
parent 82ef80ece4
commit 8b25c32ce9
3 changed files with 38 additions and 88 deletions

View file

@ -30,33 +30,14 @@ export function createComposerBundle(
runtimeSettings: ChatPanelRuntimeSettingsActions;
},
): ChatPanelComposerBundle {
const surface = createSessionComposerSurface(input.runtimeSettings);
const controller = createSessionComposerController(host, surface, input.runtimeSettings);
return {
controller,
dispose: () => {
controller.dispose();
},
};
}
function createSessionComposerSurface(runtimeSettings: ChatPanelRuntimeSettingsActions): ChatPanelComposerSurface {
return {
runtime: {
requestModel: (model) => runtimeSettings.requestModelFromUi(model),
requestReasoningEffort: (effort) => runtimeSettings.requestReasoningEffortFromUi(effort),
},
};
}
function createSessionComposerController(
host: ChatPanelComposerHost,
composerSurface: ChatPanelComposerSurface,
runtimeSettings: ChatPanelRuntimeSettingsActions,
): ChatComposerController {
const { environment, stateStore } = host;
return new ChatComposerController({
const surface = {
runtime: {
requestModel: (model: string) => input.runtimeSettings.requestModelFromUi(model),
requestReasoningEffort: (effort) => input.runtimeSettings.requestReasoningEffortFromUi(effort),
},
} satisfies ChatPanelComposerSurface;
const controller = new ChatComposerController({
noteCandidateProvider: new VaultNoteCandidateProvider(environment.obsidian.app),
contextReferenceProvider: new VaultComposerContextReferenceProvider(environment.obsidian.app),
attachmentHandler: createVaultComposerAttachmentHandler({
@ -71,7 +52,7 @@ function createSessionComposerController(
canInterrupt: (model) => {
return model.turnBusy.value && Boolean(model.activeThreadId.value && model.activeTurnId.value);
},
composerProjection: (model) => chatPanelComposerProjection(composerSurface, model),
composerProjection: (model) => chatPanelComposerProjection(surface, model),
currentModelForSuggestions: () => {
const current = stateStore.getState();
const config = runtimeConfigOrDefault(current.connection.runtimeConfig);
@ -80,9 +61,9 @@ function createSessionComposerController(
threadScrollFromComposer: (action) => {
host.messageScrollController.scrollFromComposer(action);
},
togglePlan: () => void runtimeSettings.toggleCollaborationMode(),
toggleAutoReview: () => void runtimeSettings.toggleAutoReview(),
toggleFast: () => void runtimeSettings.toggleFastMode(),
togglePlan: () => void input.runtimeSettings.toggleCollaborationMode(),
toggleAutoReview: () => void input.runtimeSettings.toggleAutoReview(),
toggleFast: () => void input.runtimeSettings.toggleFastMode(),
onDraftChange: () => {
environment.plugin.workspace.refreshThreadsViewLiveState();
},
@ -91,4 +72,11 @@ function createSessionComposerController(
new Notice(message);
},
});
return {
controller,
dispose: () => {
controller.dispose();
},
};
}

View file

@ -32,36 +32,24 @@ export function createRuntimeBundle(
},
): ChatPanelRuntimeBundle {
return {
settings: createSessionRuntimeSettingsActions(host, input.appServer, input.status),
projection: createSessionRuntimeProjection(host, input.connection),
settings: createChatRuntimeSettingsActions({
stateStore: host.stateStore,
runtimeTransport: input.appServer.runtimeSettings,
runtimeSnapshotForState: runtimeSnapshotForChatState,
collaborationModeLabel: () => collaborationModeLabel(host.stateStore),
addSystemMessage: (text) => {
input.status.addSystemMessage(text);
},
}),
projection: createChatPanelRuntimeProjection({
state: () => host.stateStore.getState(),
connected: () => input.connection.isConnected(),
configuredCommand: () => host.environment.plugin.settingsRef.settings.codexPath(),
nowMs: () => Date.now(),
}),
};
}
function createSessionRuntimeSettingsActions(
host: ChatPanelRuntimeHost,
appServer: ChatAppServerGateway,
status: ChatPanelRuntimeStatus,
): ChatPanelRuntimeSettingsActions {
return createChatRuntimeSettingsActions({
stateStore: host.stateStore,
runtimeTransport: appServer.runtimeSettings,
runtimeSnapshotForState: runtimeSnapshotForChatState,
collaborationModeLabel: () => collaborationModeLabel(host.stateStore),
addSystemMessage: (text) => {
status.addSystemMessage(text);
},
});
}
function collaborationModeLabel(stateStore: ChatStateStore): string {
return formatCollaborationModeLabel(stateStore.getState().runtime.pending.collaborationMode);
}
function createSessionRuntimeProjection(host: ChatPanelRuntimeHost, connection: ConnectionManager): ChatPanelRuntimeProjection {
return createChatPanelRuntimeProjection({
state: () => host.stateStore.getState(),
connected: () => connection.isConnected(),
configuredCommand: () => host.environment.plugin.settingsRef.settings.codexPath(),
nowMs: () => Date.now(),
});
}

View file

@ -7,39 +7,13 @@ import { compactReasoningEffortLabel } from "../../domain/runtime/labels";
import { resolveRuntimeControls } from "../../domain/runtime/resolution";
import type { RuntimeSnapshot } from "../../domain/runtime/snapshot";
import { contextSummary } from "../../presentation/runtime/status";
import { ComposerShell, type ComposerShellProps } from "../../ui/composer";
import { type ComposerMetaViewModel, ComposerShell, type ComposerShellProps } from "../../ui/composer";
import type { ChatPanelComposerReadModel } from "../shell-read-model";
interface ChatPanelComposerContextMeterCell {
text: string;
placeholder: boolean;
}
interface ChatPanelComposerContextMeter {
cells: ChatPanelComposerContextMeterCell[];
percent: string;
}
interface ChatPanelComposerRuntimeChoice {
label: string;
selected?: boolean;
disabled?: boolean;
meta?: string;
onClick: () => void;
}
interface ChatPanelComposerMeta {
fatal: string | null;
context: ChatPanelComposerContextMeter;
statusSummary: string;
model: string;
effort: string | null;
planActive: boolean;
autoReviewActive: boolean;
fastActive: boolean;
modelChoices?: ChatPanelComposerRuntimeChoice[];
effortChoices?: ChatPanelComposerRuntimeChoice[];
}
type ChatPanelComposerMeta = ComposerMetaViewModel;
type ChatPanelComposerContextMeter = ComposerMetaViewModel["context"];
type ChatPanelComposerContextMeterCell = ComposerMetaViewModel["context"]["cells"][number];
type ChatPanelComposerRuntimeChoice = NonNullable<ComposerMetaViewModel["modelChoices"]>[number];
export interface ChatPanelComposerProjection {
placeholder: string;