Flatten server request responder adapter

This commit is contained in:
murashit 2026-06-10 12:45:04 +09:00
parent 7a065a6e87
commit 92d98ed767
6 changed files with 85 additions and 90 deletions

View file

@ -13,7 +13,7 @@ import type { ToolbarPanelController } from "./toolbar-controller";
import type { ChatConnectionController } from "../session/connection-controller";
import type { ChatReconnectActions } from "../session/reconnect-actions";
import type { PendingRequestController } from "../requests/pending-request-controller";
import { createServerRequestActions } from "../requests/server-request-actions";
import { rejectServerRequest, respondToServerRequest } from "../requests/server-request-responder";
import type { ComposerSubmissionActions } from "../turns/composer-submission-actions";
import type { RestoredThreadController } from "../threads/restored-thread-controller";
import type { ThreadIdentityActions } from "../threads/thread-identity-actions";
@ -105,14 +105,15 @@ export function createChatViewControllers(ports: ChatControllerCompositionPorts)
connection,
goals,
});
const serverRequestResponder = createServerRequestActions({
const serverRequestHost = {
currentClient: ports.client.getClient,
});
};
const controller = createChatInboundController(ports, {
serverMetadata,
serverDiagnostics,
threadRename,
serverRequestResponder,
respondToServerRequest: (requestId, result) => respondToServerRequest(serverRequestHost, requestId, result),
rejectServerRequest: (requestId, code, message) => rejectServerRequest(serverRequestHost, requestId, code, message),
});
const { connectionController } = createChatConnectionControllers(ports, {
connection,

View file

@ -1,40 +0,0 @@
import type { AppServerClient } from "../../../app-server/client";
type RespondRequestId = Parameters<AppServerClient["respondToServerRequest"]>[0];
type RejectRequestId = Parameters<AppServerClient["rejectServerRequest"]>[0];
export interface ServerRequestActionsHost {
currentClient: () => AppServerClient | null;
}
export interface ServerRequestActions {
respond: (requestId: RespondRequestId, result: unknown) => boolean;
reject: (requestId: RejectRequestId, code: number, message: string) => boolean;
}
export function createServerRequestActions(host: ServerRequestActionsHost): ServerRequestActions {
return {
respond: (requestId, result) => respondToServerRequest(host, requestId, result),
reject: (requestId, code, message) => rejectServerRequest(host, requestId, code, message),
};
}
function respondToServerRequest(host: ServerRequestActionsHost, requestId: RespondRequestId, result: unknown): boolean {
try {
const client = host.currentClient();
client?.respondToServerRequest(requestId, result);
return Boolean(client);
} catch {
return false;
}
}
function rejectServerRequest(host: ServerRequestActionsHost, requestId: RejectRequestId, code: number, message: string): boolean {
try {
const client = host.currentClient();
client?.rejectServerRequest(requestId, code, message);
return Boolean(client);
} catch {
return false;
}
}

View file

@ -0,0 +1,28 @@
import type { AppServerClient } from "../../../app-server/client";
type RespondRequestId = Parameters<AppServerClient["respondToServerRequest"]>[0];
type RejectRequestId = Parameters<AppServerClient["rejectServerRequest"]>[0];
export interface ServerRequestResponderHost {
currentClient: () => AppServerClient | null;
}
export function respondToServerRequest(host: ServerRequestResponderHost, requestId: RespondRequestId, result: unknown): boolean {
try {
const client = host.currentClient();
client?.respondToServerRequest(requestId, result);
return Boolean(client);
} catch {
return false;
}
}
export function rejectServerRequest(host: ServerRequestResponderHost, requestId: RejectRequestId, code: number, message: string): boolean {
try {
const client = host.currentClient();
client?.rejectServerRequest(requestId, code, message);
return Boolean(client);
} catch {
return false;
}
}

View file

@ -6,7 +6,7 @@ import { createChatServerMetadataActions, type ChatServerMetadataActions } from
import { createChatServerThreadActions } from "../server-actions/thread-actions";
import { ChatConnectionController } from "./connection-controller";
import { createChatReconnectActions } from "./reconnect-actions";
import type { ServerRequestActions } from "../requests/server-request-actions";
import type { rejectServerRequest, respondToServerRequest } from "../requests/server-request-responder";
import type { ChatThreadGoalActions } from "../threads/thread-goal-actions";
import type { ThreadRenameController } from "../threads/thread-rename-controller";
import { ChatInboundController } from "../inbound/controller";
@ -63,7 +63,8 @@ export function createChatInboundController(
serverMetadata: ChatServerMetadataActions;
serverDiagnostics: ChatServerDiagnosticsActions;
threadRename: ThreadRenameController;
serverRequestResponder: ServerRequestActions;
respondToServerRequest: (requestId: Parameters<typeof respondToServerRequest>[1], result: unknown) => boolean;
rejectServerRequest: (requestId: Parameters<typeof rejectServerRequest>[1], code: number, message: string) => boolean;
},
): ChatInboundController {
const { plugin, thread, render } = context;
@ -86,8 +87,8 @@ export function createChatInboundController(
refs.serverDiagnostics.recordMcpStartupStatus(name, status, message);
render.schedule();
},
respondToServerRequest: (requestId, result) => refs.serverRequestResponder.respond(requestId, result),
rejectServerRequest: (requestId, code, message) => refs.serverRequestResponder.reject(requestId, code, message),
respondToServerRequest: refs.respondToServerRequest,
rejectServerRequest: refs.rejectServerRequest,
});
}

View file

@ -1,42 +0,0 @@
import { describe, expect, it, vi } from "vitest";
import type { AppServerClient } from "../../../../src/app-server/client";
import { createServerRequestActions } from "../../../../src/features/chat/requests/server-request-actions";
describe("createServerRequestActions", () => {
it("responds through the current app-server client", () => {
const respondToServerRequest = vi.fn();
const responder = createServerRequestActions({
currentClient: () => ({ respondToServerRequest }) as unknown as AppServerClient,
});
expect(responder.respond(7, { ok: true })).toBe(true);
expect(respondToServerRequest).toHaveBeenCalledWith(7, { ok: true });
});
it("rejects through the current app-server client", () => {
const rejectServerRequest = vi.fn();
const responder = createServerRequestActions({
currentClient: () => ({ rejectServerRequest }) as unknown as AppServerClient,
});
expect(responder.reject(7, -32000, "No")).toBe(true);
expect(rejectServerRequest).toHaveBeenCalledWith(7, -32000, "No");
});
it("reports failure when there is no client or the client throws", () => {
expect(createServerRequestActions({ currentClient: () => null }).respond(7, null)).toBe(false);
expect(
createServerRequestActions({
currentClient: () =>
({
rejectServerRequest: () => {
throw new Error("closed");
},
}) as unknown as AppServerClient,
}).reject(7, -32000, "No"),
).toBe(false);
});
});

View file

@ -0,0 +1,47 @@
import { describe, expect, it, vi } from "vitest";
import type { AppServerClient } from "../../../../src/app-server/client";
import { rejectServerRequest, respondToServerRequest } from "../../../../src/features/chat/requests/server-request-responder";
describe("server request responder", () => {
it("responds through the current app-server client", () => {
const respond = vi.fn();
const host = {
currentClient: () => ({ respondToServerRequest: respond }) as unknown as AppServerClient,
};
expect(respondToServerRequest(host, 7, { ok: true })).toBe(true);
expect(respond).toHaveBeenCalledWith(7, { ok: true });
});
it("rejects through the current app-server client", () => {
const reject = vi.fn();
const host = {
currentClient: () => ({ rejectServerRequest: reject }) as unknown as AppServerClient,
};
expect(rejectServerRequest(host, 7, -32000, "No")).toBe(true);
expect(reject).toHaveBeenCalledWith(7, -32000, "No");
});
it("reports failure when there is no client or the client throws", () => {
expect(respondToServerRequest({ currentClient: () => null }, 7, null)).toBe(false);
expect(
rejectServerRequest(
{
currentClient: () =>
({
rejectServerRequest: () => {
throw new Error("closed");
},
}) as unknown as AppServerClient,
},
7,
-32000,
"No",
),
).toBe(false);
});
});