From 255ac27d5200b01c50acef105ab0ec8bb6ab8345 Mon Sep 17 00:00:00 2001 From: Theo Browne Date: Mon, 5 Oct 2026 21:28:36 -0700 Subject: [PATCH] fix(server): Claude limits load again for users with large transcript histories (#16358) The Claude capabilities probe now asks for usage with skipBehaviors, so it no longer scans every local transcript and misses its 4 s deadline. Takes over #14456. Co-authored-by: Ashkaan --- .../provider/ClaudeCapabilitiesProbe.test.ts | 22 +++++++++++++++++++ apps/server/src/provider/ClaudeProvider.ts | 4 +++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/apps/server/src/provider/ClaudeCapabilitiesProbe.test.ts b/apps/server/src/provider/ClaudeCapabilitiesProbe.test.ts index 27b503a3c2168001af5b4a3909e87544f2072820..8147a43b05a54219e83b6122562272c694a5727d 100644 --- a/apps/server/src/provider/ClaudeCapabilitiesProbe.test.ts +++ b/apps/server/src/provider/ClaudeCapabilitiesProbe.test.ts @@ -353,3 +353,25 @@ it.effect("preserves initialized capabilities when optional usage times out", () assert.equal(abortSignal?.aborted, true); }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)), ); + +it.effect("asks for usage without the local transcript scan", () => + Effect.gen(function* () { + let usageOptions: unknown; + const query = vi.spyOn(ClaudeSdk, "query").mockImplementation( + () => + ({ + initializationResult: async () => ({ + account: { email: "dev@example.com", subscriptionType: "max", tokenSource: "oauth" }, + commands: [], + }), + usage_EXPERIMENTAL_MAY_CHANGE_DO_NOT_RELY_ON_THIS_API_YET: async (options?: unknown) => { + usageOptions = options; + return { rate_limits_available: true, rate_limits: null }; + }, + }) as unknown as ReturnType, + ); + yield* Effect.addFinalizer(() => Effect.sync(() => query.mockRestore())); + yield* probeClaudeCapabilities(decodeClaudeSettings({ binaryPath: "claude" })); + assert.deepEqual(usageOptions, { skipBehaviors: true }); + }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)), +); diff --git a/apps/server/src/provider/ClaudeProvider.ts b/apps/server/src/provider/ClaudeProvider.ts index 560982f974f1d925d1ed3c127a9155d7855938c9..37945bbb79af746a53828f62876fbb40cf486a60 100644 --- a/apps/server/src/provider/ClaudeProvider.ts +++ b/apps/server/src/provider/ClaudeProvider.ts @@ -367,9 +367,11 @@ const probeClaudeCapabilities = ( Effect.flatMap(({ q, init }) => Effect.gen(function* () { // Usage has its own deadline so a slow optional request cannot discard initialization. + // Only the rate limits are read, so skip the local transcript scan that fills + // `behaviors`: with a few GB of transcripts it outlasts the deadline. const usageResult = includeUsage ? yield* Effect.tryPromise(() => - q.usage_EXPERIMENTAL_MAY_CHANGE_DO_NOT_RELY_ON_THIS_API_YET(), + q.usage_EXPERIMENTAL_MAY_CHANGE_DO_NOT_RELY_ON_THIS_API_YET({ skipBehaviors: true }), ).pipe(Effect.timeout(DEFAULT_TIMEOUT_MS), Effect.result) : undefined; const usage = -- 2.54.0