From 0389f86f9308e6d4f7d6af29e482acad52bfc529 Mon Sep 17 00:00:00 2001 From: murashit Date: Thu, 4 Jun 2026 12:07:04 +0900 Subject: [PATCH] Merge sparse rate limit updates --- src/features/chat/chat-controller.ts | 4 ++++ src/features/chat/chat-notification-plan.ts | 5 +++-- src/features/chat/chat-view-controller-assembly.ts | 3 +++ tests/features/chat/chat-controller.test.ts | 14 ++++++-------- .../requests/pending-request-controller.test.ts | 1 + 5 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/features/chat/chat-controller.ts b/src/features/chat/chat-controller.ts index 580d7780..a5a0ecda 100644 --- a/src/features/chat/chat-controller.ts +++ b/src/features/chat/chat-controller.ts @@ -14,6 +14,7 @@ import { planChatNotification, type ChatNotificationEffect } from "./chat-notifi export interface ChatControllerActions { refreshThreads: () => void; + refreshRateLimits: () => void; refreshSkills: (forceReload?: boolean) => void; publishAppServerMetadata: () => void; maybeNameThread: (threadId: string, turn: Turn) => void; @@ -151,6 +152,9 @@ export class ChatController { case "refresh-threads": this.actions.refreshThreads(); return; + case "refresh-rate-limits": + this.actions.refreshRateLimits(); + return; case "refresh-skills": this.actions.refreshSkills(effect.forceReload); return; diff --git a/src/features/chat/chat-notification-plan.ts b/src/features/chat/chat-notification-plan.ts index d42e36f2..5caf396e 100644 --- a/src/features/chat/chat-notification-plan.ts +++ b/src/features/chat/chat-notification-plan.ts @@ -29,6 +29,7 @@ import { routeServerNotification } from "./inbound-routing"; export type ChatNotificationEffect = | { type: "refresh-threads" } + | { type: "refresh-rate-limits" } | { type: "refresh-skills"; forceReload: boolean } | { type: "publish-app-server-metadata" } | { type: "maybe-name-thread"; threadId: string; turn: Turn } @@ -255,8 +256,8 @@ function planDiagnosticStatus(notification: ServerNotification): ChatNotificatio } if (method === "account/rateLimits/updated") { return { - actions: [{ type: "thread/list-applied", rateLimit: params.rateLimits }], - effects: [{ type: "publish-app-server-metadata" }], + actions: [], + effects: [{ type: "refresh-rate-limits" }], }; } if (method === "skills/changed") { diff --git a/src/features/chat/chat-view-controller-assembly.ts b/src/features/chat/chat-view-controller-assembly.ts index df1a582e..7c6c460b 100644 --- a/src/features/chat/chat-view-controller-assembly.ts +++ b/src/features/chat/chat-view-controller-assembly.ts @@ -354,6 +354,9 @@ export function createChatViewControllerAssembly(host: ChatViewControllerAssembl refreshThreads: () => { void host.refreshThreads(); }, + refreshRateLimits: () => { + void appServer.refreshRateLimits(); + }, refreshSkills: (forceReload) => void host.refreshSkills(forceReload), publishAppServerMetadata: host.publishAppServerMetadataSnapshot, maybeNameThread: (threadId, turn) => { diff --git a/tests/features/chat/chat-controller.test.ts b/tests/features/chat/chat-controller.test.ts index bc843fec..f7985a1e 100644 --- a/tests/features/chat/chat-controller.test.ts +++ b/tests/features/chat/chat-controller.test.ts @@ -23,6 +23,7 @@ function controllerForState( ): ChatController { return new ChatController(testStoreForState(state), { refreshThreads: vi.fn(), + refreshRateLimits: vi.fn(), refreshSkills: vi.fn(), publishAppServerMetadata: vi.fn(), maybeNameThread: vi.fn(), @@ -641,10 +642,10 @@ describe("ChatController", () => { expect(refreshThreads).not.toHaveBeenCalled(); }); - it("stores account rate limit updates outside thread scope", () => { + it("refreshes account rate limits after sparse update notifications", () => { const state = createChatState(); - const publishAppServerMetadata = vi.fn(); - const controller = controllerForState(state, { publishAppServerMetadata }); + const refreshRateLimits = vi.fn(); + const controller = controllerForState(state, { refreshRateLimits }); controller.handleNotification({ method: "account/rateLimits/updated", @@ -662,11 +663,8 @@ describe("ChatController", () => { }, } satisfies Extract); - expect(state.rateLimit).toMatchObject({ - limitId: "codex", - primary: { usedPercent: 64 }, - }); - expect(publishAppServerMetadata).toHaveBeenCalledOnce(); + expect(state.rateLimit).toBeNull(); + expect(refreshRateLimits).toHaveBeenCalledOnce(); }); it("records MCP startup status for diagnostics without a chat system message", () => { diff --git a/tests/features/chat/controllers/requests/pending-request-controller.test.ts b/tests/features/chat/controllers/requests/pending-request-controller.test.ts index ce20db55..fd712330 100644 --- a/tests/features/chat/controllers/requests/pending-request-controller.test.ts +++ b/tests/features/chat/controllers/requests/pending-request-controller.test.ts @@ -20,6 +20,7 @@ describe("PendingRequestController", () => { const render = vi.fn(); const controller = new ChatController(stateStore, { refreshThreads: vi.fn(), + refreshRateLimits: vi.fn(), refreshSkills: vi.fn(), publishAppServerMetadata: vi.fn(), maybeNameThread: vi.fn(),