diff --git a/src/features/chat/chat-app-server-controller.ts b/src/features/chat/chat-app-server-controller.ts index 7f540677..52a99b65 100644 --- a/src/features/chat/chat-app-server-controller.ts +++ b/src/features/chat/chat-app-server-controller.ts @@ -21,6 +21,7 @@ export interface ChatAppServerControllerHost { currentClient: () => AppServerClient | null; runtimeSnapshot: () => RuntimeSnapshot; forceMessagesToBottom: () => void; + publishAppServerMetadata: (metadata: SharedAppServerMetadata) => void; } export interface RefreshCapabilityDiagnosticsOptions { @@ -94,6 +95,16 @@ export class ChatAppServerController { return metadata; } + async refreshPublishedAppServerMetadata(): Promise { + const metadata = await this.refreshAppServerMetadata(); + if (metadata) this.host.publishAppServerMetadata(metadata); + return metadata; + } + + publishAppServerMetadataSnapshot(): void { + this.host.publishAppServerMetadata(this.appServerMetadataSnapshot()); + } + async startThread(): Promise> | null> { const client = this.host.currentClient(); if (!client) return null; @@ -129,6 +140,11 @@ export class ChatAppServerController { this.dispatch({ type: "thread/list-applied", availableSkills: skills.data, appServerDiagnostics: diagnostics }); } + async refreshPublishedSkills(forceReload = false): Promise { + await this.refreshSkills(forceReload); + this.publishAppServerMetadataSnapshot(); + } + async loadSkills(forceReload = false): Promise<{ data: SkillMetadata[]; probe: AppServerDiagnostics["probes"]["skills/list"] }> { const client = this.host.currentClient(); if (!client) return { data: [], probe: capabilityProbeError("skills/list", new Error("Codex app-server is not connected.")) }; @@ -243,6 +259,11 @@ export class ChatAppServerController { await Promise.all(probes); } + async refreshPublishedCapabilityDiagnostics(options: RefreshCapabilityDiagnosticsOptions = {}): Promise { + await this.refreshCapabilityDiagnostics(options); + this.publishAppServerMetadataSnapshot(); + } + recordMcpStartupStatus(name: string, startupStatus: "starting" | "ready" | "failed" | "cancelled", message: string | null): void { this.dispatch({ type: "thread/list-applied", diff --git a/src/features/chat/view.ts b/src/features/chat/view.ts index d87c4972..725572ec 100644 --- a/src/features/chat/view.ts +++ b/src/features/chat/view.ts @@ -237,6 +237,9 @@ export class CodexChatView extends ItemView { forceMessagesToBottom: () => { this.queueMessagesBottomScroll(); }, + publishAppServerMetadata: (metadata) => { + this.plugin.publishAppServerMetadata(metadata); + }, }); this.history = new ThreadHistoryLoader({ stateStore: this.chatState, @@ -549,9 +552,8 @@ export class CodexChatView extends ItemView { if (this.connectionWork.isStale(connection)) return; this.client = this.connection.currentClient(); if (!this.client) throw new Error("Codex app-server connection did not initialize."); - const metadata = await this.appServer.refreshAppServerMetadata(); + await this.appServer.refreshPublishedAppServerMetadata(); if (this.connectionWork.isStale(connection)) return; - if (metadata) this.plugin.publishAppServerMetadata(metadata); await this.loadSharedThreadList(); if (this.connectionWork.isStale(connection)) return; this.scheduleDeferredDiagnostics(); @@ -595,8 +597,7 @@ export class CodexChatView extends ItemView { if (!this.client) return; try { await this.loadSharedThreadList(); - const metadata = await this.appServer.refreshAppServerMetadata(); - if (metadata) this.plugin.publishAppServerMetadata(metadata); + await this.appServer.refreshPublishedAppServerMetadata(); this.refreshTabHeader(); this.render(); } catch (error) { @@ -609,8 +610,7 @@ export class CodexChatView extends ItemView { await this.ensureConnected(); if (!this.client) return; this.clearDeferredDiagnostics(); - await this.appServer.refreshCapabilityDiagnostics(); - this.publishAppServerMetadataSnapshot(); + await this.appServer.refreshPublishedCapabilityDiagnostics(); this.render(); } @@ -626,8 +626,7 @@ export class CodexChatView extends ItemView { private async refreshSkills(forceReload = false): Promise { this.client = this.connection.currentClient(); if (!this.client) return; - await this.appServer.refreshSkills(forceReload); - this.publishAppServerMetadataSnapshot(); + await this.appServer.refreshPublishedSkills(forceReload); this.render(); } @@ -693,7 +692,7 @@ export class CodexChatView extends ItemView { } private publishAppServerMetadataSnapshot(): void { - this.plugin.publishAppServerMetadata(this.appServer.appServerMetadataSnapshot()); + this.appServer.publishAppServerMetadataSnapshot(); } private applyCachedSharedAppServerState(): void { @@ -1281,8 +1280,7 @@ export class CodexChatView extends ItemView { private async refreshDeferredDiagnostics(): Promise { if (!this.connection.isConnected()) return; - await this.appServer.refreshCapabilityDiagnostics({ cachedAppServerMetadata: true }); - this.publishAppServerMetadataSnapshot(); + await this.appServer.refreshPublishedCapabilityDiagnostics({ cachedAppServerMetadata: true }); this.render(); } diff --git a/tests/features/chat/chat-app-server-controller.test.ts b/tests/features/chat/chat-app-server-controller.test.ts index 1b362e13..adf072ae 100644 --- a/tests/features/chat/chat-app-server-controller.test.ts +++ b/tests/features/chat/chat-app-server-controller.test.ts @@ -33,6 +33,7 @@ describe("ChatAppServerController", () => { currentClient: () => client, runtimeSnapshot: () => ({}) as never, forceMessagesToBottom: () => undefined, + publishAppServerMetadata: () => undefined, }); await controller.refreshAppServerMetadata();