diff --git a/apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.test.ts b/apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.test.ts index cfd6c526b2726..01f5c9396f732 100644 --- a/apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.test.ts +++ b/apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.test.ts @@ -395,6 +395,23 @@ describe("ClaudeAdapterV2 runtime query policy", () => { }); }); + it("makes Auto-compact after beat CLAUDE_CODE_AUTO_COMPACT_WINDOW from settings env", () => { + const options = ClaudeAdapterV2.makeClaudeQueryOptions({ + modelSelection: CLAUDE_TEST_MODEL_SELECTION, + nativeThreadId: "native-auto-compact-env", + resume: false, + cwd: "/workspace", + settings: AUTO_COMPACT_CLAUDE_SETTINGS, + sdkSettings: { env: { CLAUDE_CODE_AUTO_COMPACT_WINDOW: "1000000", OTHER: "kept" } }, + }); + const settings = options.settings as { + autoCompactWindow?: number; + env?: Record; + }; + assert.equal(settings.autoCompactWindow, 300_000); + assert.deepEqual(settings.env, { CLAUDE_CODE_AUTO_COMPACT_WINDOW: "300000", OTHER: "kept" }); + }); + it("sends a custom model named like a Claude Code alias to the API unchanged", () => { const options = ClaudeAdapterV2.makeClaudeQueryOptions({ modelSelection: { instanceId: CLAUDE_TEST_MODEL_SELECTION.instanceId, model: "opus" }, diff --git a/apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts b/apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts index a58f91124f16d..814baac2d499c 100644 --- a/apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts +++ b/apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts @@ -2009,12 +2009,16 @@ export function makeClaudeQueryOptions(input: { : typeof input.sdkSettings === "object" && input.sdkSettings !== null ? ({ ...input.sdkSettings, ...selectionSettings } as ClaudeSdkSettings) : selectionSettings; - const compactQuerySettings = + const autoCompactWindow = input.settings?.autoCompactWindow === undefined || input.settings.autoCompactWindow.length === 0 + ? undefined + : input.settings.autoCompactWindow; + const compactQuerySettings = + autoCompactWindow === undefined ? querySettings : ({ ...(typeof querySettings === "object" && querySettings !== null ? querySettings : {}), - autoCompactWindow: Number(input.settings.autoCompactWindow), + autoCompactWindow: Number(autoCompactWindow), } as ClaudeSdkSettings); // Claude Code expands a bare alias to its own model, so a custom model with an alias's name // pins the alias to itself. @@ -2024,9 +2028,17 @@ export function makeClaudeQueryOptions(input: { compiledSelection.apiModelId, } : undefined; + // Claude Code prefers CLAUDE_CODE_AUTO_COMPACT_WINDOW from any settings env over + // autoCompactWindow, and flag settings env beats the settings files. + const autoCompactEnv = + autoCompactWindow === undefined + ? undefined + : { CLAUDE_CODE_AUTO_COMPACT_WINDOW: autoCompactWindow }; // A settings file path cannot take extra keys, so it goes through unchanged. const effectiveQuerySettings = - (input.toolSearchOverride === undefined && aliasOverrideEnv === undefined) || + (input.toolSearchOverride === undefined && + aliasOverrideEnv === undefined && + autoCompactEnv === undefined) || typeof compactQuerySettings === "string" ? compactQuerySettings : ({ @@ -2034,6 +2046,7 @@ export function makeClaudeQueryOptions(input: { env: { ...compactQuerySettings?.env, ...aliasOverrideEnv, + ...autoCompactEnv, ...(input.toolSearchOverride === undefined ? {} : { ENABLE_TOOL_SEARCH: input.toolSearchOverride }),