From e39d4b90a4d772cc678fa95b889eec98263cef77 Mon Sep 17 00:00:00 2001 From: murashit Date: Sat, 27 Jun 2026 14:15:44 +0900 Subject: [PATCH] Remove unjustified test-only exports --- src/domain/server/diagnostics.ts | 2 +- .../app-server/inbound/notification-plan.ts | 16 -- .../inbound/notification-routing.ts | 11 +- .../app-server/app-server-diagnostics.test.ts | 10 +- .../chat/app-server/inbound/routing.test.ts | 139 ++++++++++++++---- 5 files changed, 119 insertions(+), 59 deletions(-) diff --git a/src/domain/server/diagnostics.ts b/src/domain/server/diagnostics.ts index f0e572eb..5b1f672a 100644 --- a/src/domain/server/diagnostics.ts +++ b/src/domain/server/diagnostics.ts @@ -1,7 +1,7 @@ import type { ServerInitialization } from "./initialization"; import { cloneToolInventorySnapshot, type ToolInventorySnapshot } from "./tool-inventory"; -export const DIAGNOSTIC_PROBE_METHODS = [ +const DIAGNOSTIC_PROBE_METHODS = [ "model/list", "skills/list", "app/list", diff --git a/src/features/chat/app-server/inbound/notification-plan.ts b/src/features/chat/app-server/inbound/notification-plan.ts index aa361492..107441b0 100644 --- a/src/features/chat/app-server/inbound/notification-plan.ts +++ b/src/features/chat/app-server/inbound/notification-plan.ts @@ -316,18 +316,6 @@ const THREAD_LIFECYCLE_PLANNERS = { }, } satisfies ServerNotificationStatePlannerMap; -export const PLANNED_SERVER_NOTIFICATION_METHODS_BY_ROUTE_KIND = { - streamUpdate: plannerMethods(STREAM_UPDATE_PLANNERS), - turnLifecycle: plannerMethods(TURN_LIFECYCLE_PLANNERS), - threadLifecycle: plannerMethods(THREAD_LIFECYCLE_PLANNERS), - requestResolved: ["serverRequest/resolved"], - diagnosticStatus: plannerMethods(DIAGNOSTIC_STATUS_PLANNERS), - userVisibleNotice: plannerMethods(USER_VISIBLE_NOTICE_PLANNERS), -} satisfies Record< - Exclude["kind"], "inactive" | "unhandled" | "ignored">, - readonly ServerNotification["method"][] ->; - export function planChatNotification( state: ChatState, notification: ServerNotification, @@ -419,10 +407,6 @@ function planNotificationWithStateByMethod(planners: Record): readonly M[] { - return Object.keys(planners) as M[]; -} - function jsonNoticePlan( notification: Extract }>, localItemId: LocalItemIdProvider, diff --git a/src/features/chat/app-server/inbound/notification-routing.ts b/src/features/chat/app-server/inbound/notification-routing.ts index 8afd45b8..68a25fae 100644 --- a/src/features/chat/app-server/inbound/notification-routing.ts +++ b/src/features/chat/app-server/inbound/notification-routing.ts @@ -103,7 +103,7 @@ const USER_VISIBLE_NOTICE_NOTIFICATION_METHODS = [ export type UserVisibleNoticeNotificationMethod = (typeof USER_VISIBLE_NOTICE_NOTIFICATION_METHODS)[number]; -export const IGNORED_SERVER_NOTIFICATION_METHODS = [ +const IGNORED_SERVER_NOTIFICATION_METHODS = [ "thread/status/changed", "thread/closed", "rawResponseItem/completed", @@ -134,15 +134,6 @@ export const IGNORED_SERVER_NOTIFICATION_METHODS = [ type IgnoredServerNotificationMethod = (typeof IGNORED_SERVER_NOTIFICATION_METHODS)[number]; -export const ROUTED_SERVER_NOTIFICATION_METHODS_BY_ROUTE_KIND = { - streamUpdate: STREAM_UPDATE_NOTIFICATION_METHODS, - turnLifecycle: TURN_LIFECYCLE_NOTIFICATION_METHODS, - threadLifecycle: THREAD_LIFECYCLE_NOTIFICATION_METHODS, - requestResolved: ["serverRequest/resolved"], - diagnosticStatus: DIAGNOSTIC_STATUS_NOTIFICATION_METHODS, - userVisibleNotice: USER_VISIBLE_NOTICE_NOTIFICATION_METHODS, -} satisfies Record, readonly ServerNotificationMethod[]>; - const SERVER_NOTIFICATION_SCOPE_EXTRACTORS: ServerNotificationScopeExtractors = { error: threadTurnNotificationScope, "thread/started": threadStartedNotificationScope, diff --git a/tests/app-server/app-server-diagnostics.test.ts b/tests/app-server/app-server-diagnostics.test.ts index 72febf45..b84667c1 100644 --- a/tests/app-server/app-server-diagnostics.test.ts +++ b/tests/app-server/app-server-diagnostics.test.ts @@ -2,7 +2,6 @@ import { describe, expect, it } from "vitest"; import { createServerDiagnostics, - DIAGNOSTIC_PROBE_METHODS, diagnosticProbeError, diagnosticProbeOk, serverIdentity, @@ -27,7 +26,14 @@ describe("app-server diagnostics", () => { it("creates generic capability probe defaults", () => { const diagnostics = createServerDiagnostics(); - expect(Object.keys(diagnostics.probes)).toEqual([...DIAGNOSTIC_PROBE_METHODS]); + expect(Object.keys(diagnostics.probes)).toEqual([ + "model/list", + "skills/list", + "app/list", + "plugin/installed", + "account/rateLimits/read", + "mcpServerStatus/list", + ]); expect(diagnostics.probes["model/list"]).toMatchObject({ method: "model/list", status: "unknown", diff --git a/tests/features/chat/app-server/inbound/routing.test.ts b/tests/features/chat/app-server/inbound/routing.test.ts index 798a6a99..32f44c46 100644 --- a/tests/features/chat/app-server/inbound/routing.test.ts +++ b/tests/features/chat/app-server/inbound/routing.test.ts @@ -3,15 +3,8 @@ import path from "node:path"; import { describe, expect, it } from "vitest"; import type { ServerNotification, ServerRequest } from "../../../../../src/app-server/connection/rpc-messages"; import { routeServerRequest } from "../../../../../src/app-server/server-requests"; -import { - PLANNED_SERVER_NOTIFICATION_METHODS_BY_ROUTE_KIND, - planChatNotification, -} from "../../../../../src/features/chat/app-server/inbound/notification-plan"; -import { - IGNORED_SERVER_NOTIFICATION_METHODS, - ROUTED_SERVER_NOTIFICATION_METHODS_BY_ROUTE_KIND, - routeServerNotification, -} from "../../../../../src/features/chat/app-server/inbound/notification-routing"; +import { planChatNotification } from "../../../../../src/features/chat/app-server/inbound/notification-plan"; +import { routeServerNotification } from "../../../../../src/features/chat/app-server/inbound/notification-routing"; import { chatStateFixture, chatStateWith } from "../../support/state"; const activeScope = { activeThreadId: "thread-active", activeTurnId: "turn-active" }; @@ -20,18 +13,28 @@ type NotificationRouteKind = ReturnType["kind"]; type RequestRouteKind = ReturnType["kind"]; describe("chat inbound routing", () => { - it("keeps routed notification methods covered by matching planners", () => { - expect(sortedMethods(PLANNED_SERVER_NOTIFICATION_METHODS_BY_ROUTE_KIND)).toEqual( - sortedMethods(ROUTED_SERVER_NOTIFICATION_METHODS_BY_ROUTE_KIND), + it("keeps generated app-server notifications explicitly routed or ignored", () => { + const unhandled = generatedServerNotificationMethods().filter( + (method) => routeServerNotification(notificationFixture(method), activeScope).kind === "unhandled", ); + + expect(unhandled).toEqual([]); }); - it("keeps generated app-server notifications explicitly routed or ignored", () => { - const routed = flattenedMethods(ROUTED_SERVER_NOTIFICATION_METHODS_BY_ROUTE_KIND); - const ignored = [...IGNORED_SERVER_NOTIFICATION_METHODS]; + it("keeps routed notification methods covered by matching planners", () => { + let state = chatStateFixture(); + state = chatStateWith(state, { activeThread: { id: "thread-active" } }); + state = chatStateWith(state, { turn: { lifecycle: { kind: "running", turnId: "turn-active" } } }); + const plannedMethods = generatedServerNotificationMethods().filter((method) => { + const kind = routeServerNotification(notificationFixture(method), activeScope).kind; + return kind !== "inactive" && kind !== "ignored" && kind !== "unhandled"; + }); - expect(intersection(routed, ignored)).toEqual([]); - expect([...new Set([...routed, ...ignored])].sort()).toEqual(generatedServerNotificationMethods()); + expect(() => { + for (const method of plannedMethods) { + planChatNotification(state, notificationFixture(method), (prefix) => `${prefix}-1`); + } + }).not.toThrow(); }); it("routes turn-scoped app-server messages for the active scope", () => { @@ -442,19 +445,6 @@ function turnStartedNotification(): ServerNotification { }; } -function sortedMethods(methodsByRouteKind: Record): Record { - return Object.fromEntries(Object.entries(methodsByRouteKind).map(([kind, methods]) => [kind, [...methods].sort()])); -} - -function flattenedMethods(methodsByRouteKind: Record): string[] { - return Object.values(methodsByRouteKind).flat().sort(); -} - -function intersection(left: readonly string[], right: readonly string[]): string[] { - const rightSet = new Set(right); - return left.filter((method) => rightSet.has(method)).sort(); -} - function generatedServerNotificationMethods(): string[] { const generated = readFileSync(path.join(process.cwd(), "src/generated/app-server/ServerNotification.ts"), "utf8"); return [...generated.matchAll(/"method": "([^"]+)"/g)] @@ -466,6 +456,95 @@ function generatedServerNotificationMethods(): string[] { .sort(); } +function notificationFixture(method: string): ServerNotification { + return { + method, + params: { + threadId: "thread-active", + turnId: "turn-active", + thread: threadSnapshot("thread-active"), + turn: { + id: "turn-active", + status: "completed", + error: null, + startedAt: null, + completedAt: null, + durationMs: null, + itemsView: "full", + items: [], + }, + item: { type: "agentMessage", id: "item", text: "hello" }, + itemId: "item", + requestId: 1, + delta: "delta", + diff: "", + changes: [], + explanation: null, + plan: [], + run: { + id: "run", + eventName: "userPromptSubmit", + status: "completed", + statusMessage: null, + startedAt: 1, + durationMs: null, + entries: [], + }, + name: "github", + status: "ready", + error: null, + message: "notice", + success: true, + tokenUsage: { + total: tokenBreakdownFixture(), + last: tokenBreakdownFixture(), + modelContextWindow: null, + }, + threadSettings: { + cwd: "/vault", + model: "gpt-5.5", + effort: "medium", + collaborationMode: { mode: "default" }, + serviceTier: null, + approvalsReviewer: "user", + }, + goal: { + threadId: "thread-active", + objective: "Finish", + status: "active", + tokenBudget: null, + tokensUsed: 0, + timeUsedSeconds: 0, + createdAt: 1, + updatedAt: 1, + }, + startedAtMs: 1, + reviewId: "review", + targetItemId: null, + review: { status: "approved", riskLevel: null, userAuthorization: null, rationale: null }, + action: { type: "command", source: "user", command: "npm test", cwd: "/vault" }, + completedAtMs: 2, + decisionSource: "auto", + }, + } as unknown as ServerNotification; +} + +function tokenBreakdownFixture(): { + totalTokens: number; + inputTokens: number; + cachedInputTokens: number; + outputTokens: number; + reasoningOutputTokens: number; +} { + return { + totalTokens: 0, + inputTokens: 0, + cachedInputTokens: 0, + outputTokens: 0, + reasoningOutputTokens: 0, + }; +} + function threadArchivedNotification(threadId = "thread-active"): ServerNotification { return { method: "thread/archived",