diff --git a/src/agents/cli-runner/prepare.ts b/src/agents/cli-runner/prepare.ts index 75d950a2f17b..053db331e6e7 100644 --- a/src/agents/cli-runner/prepare.ts +++ b/src/agents/cli-runner/prepare.ts @@ -843,6 +843,7 @@ export async function prepareCliRunContext( provider: params.provider, modelProvider: backendResolved.modelProvider, model: contextModelId, + agentId: sessionAgentId, modelContextWindow: params.modelContextWindow, modelContextTokens: params.modelContextTokens, allowAsyncLoad: false, diff --git a/src/agents/context-resolution.ts b/src/agents/context-resolution.ts index 74a3385233e9..2726ecf16ec6 100644 --- a/src/agents/context-resolution.ts +++ b/src/agents/context-resolution.ts @@ -11,7 +11,7 @@ import { minPositiveContextTokens, providerContextTokenCacheKey, } from "./context-cache.js"; -import { resolveModelExtraParamSources } from "./model-extra-params.js"; +import { resolveModelExtraParamValue } from "./model-extra-params.js"; import { normalizeProviderId } from "./model-selection.js"; type ConfigModelEntry = { id?: string; contextWindow?: number; contextTokens?: number }; @@ -27,6 +27,7 @@ export type ContextTokenResolutionParams = { provider?: string; modelProvider?: string; model?: string; + agentId?: string; fallbackContextTokens?: number; modelContextWindow?: number; modelContextTokens?: number; @@ -211,15 +212,15 @@ export function resolveContextTokensForModelFromCache( params.modelProvider, ref.model, ); - const extraParamSources = resolveModelExtraParamSources({ - config: params.cfg, - provider: ref.provider, - modelId: ref.model, - }); - const effectiveContext1M = - extraParamSources.modelParams && Object.hasOwn(extraParamSources.modelParams, "context1m") - ? extraParamSources.modelParams.context1m - : extraParamSources.defaultParams?.context1m; + const effectiveContext1M = resolveModelExtraParamValue( + { + config: params.cfg, + provider: ref.provider, + modelId: ref.model, + agentId: params.agentId, + }, + "context1m", + ); const fixedContextWindow = resolveAnthropicFixedContextWindow(ref.provider, ref.model, { claudeCli1M: effectiveContext1M === true, }); diff --git a/src/agents/context.test.ts b/src/agents/context.test.ts index 5be8dd318a1b..bf67345c145e 100644 --- a/src/agents/context.test.ts +++ b/src/agents/context.test.ts @@ -393,6 +393,36 @@ describe("resolveContextTokensForModel", () => { expect(result).toBe(ANTHROPIC_CONTEXT_1M_TOKENS); }); + it("honors an agent model context1m override", () => { + const result = resolveContextTokensForModel({ + cfg: { + agents: { + defaults: { + params: { context1m: false }, + models: { + "claude-cli/claude-opus-4-7": { params: { context1m: false } }, + }, + }, + list: [ + { + id: "research", + models: { + "claude-cli/claude-opus-4-7": { params: { context1m: true } }, + }, + }, + ], + }, + }, + provider: "claude-cli", + model: "claude-opus-4-7", + agentId: "research", + fallbackContextTokens: 200_000, + allowAsyncLoad: false, + }); + + expect(result).toBe(ANTHROPIC_CONTEXT_1M_TOKENS); + }); + it("returns 1M context when claude-cli context1m is enabled for a GA 1M model", () => { const result = resolveContextTokensForModel({ cfg: { diff --git a/src/auto-reply/reply/agent-runner-context-recovery.ts b/src/auto-reply/reply/agent-runner-context-recovery.ts index cf4721ed5e13..2c8e43976f5a 100644 --- a/src/auto-reply/reply/agent-runner-context-recovery.ts +++ b/src/auto-reply/reply/agent-runner-context-recovery.ts @@ -76,6 +76,7 @@ function resolveContextWindowForHint(params: { cfg: params.cfg, provider: params.ref.provider, model: params.ref.model, + agentId: params.agentId, allowAsyncLoad: false, }); return modelContextTokens ?? sessionContextTokens; diff --git a/src/auto-reply/reply/agent-runner-memory.ts b/src/auto-reply/reply/agent-runner-memory.ts index 606188e4744e..95518170d7e9 100644 --- a/src/auto-reply/reply/agent-runner-memory.ts +++ b/src/auto-reply/reply/agent-runner-memory.ts @@ -781,6 +781,7 @@ export async function runPreflightCompactionIfNeeded(params: { runtimePolicySessionKey: params.runtimePolicySessionKey, }), modelId: params.followupRun.run.model ?? params.defaultModel, + agentId: compactionAgentId, }); const memoryFlushPlan = resolveMemoryFlushPlan({ cfg: params.cfg }); const reserveTokensFloor = memoryFlushPlan?.reserveTokensFloor ?? 20_000; @@ -1160,6 +1161,7 @@ export async function runMemoryFlushIfNeeded(params: { runtimePolicySessionKey: params.runtimePolicySessionKey, }), modelId: params.followupRun.run.model ?? params.defaultModel, + agentId: params.followupRun.run.agentId, }); const promptTokenEstimate = estimatePromptTokensForMemoryFlush( diff --git a/src/auto-reply/reply/agent-runner-result-accounting.ts b/src/auto-reply/reply/agent-runner-result-accounting.ts index b80b43e49127..321cd764099a 100644 --- a/src/auto-reply/reply/agent-runner-result-accounting.ts +++ b/src/auto-reply/reply/agent-runner-result-accounting.ts @@ -236,6 +236,7 @@ export async function accountAgentTurn(context: AgentTurnAccountingContext) { cfg, provider: providerUsed, model: modelUsed, + agentId: followupRun.run.agentId, allowAsyncLoad: false, }) : undefined; diff --git a/src/auto-reply/reply/commands-compact.ts b/src/auto-reply/reply/commands-compact.ts index 1f5042774250..89719cb4cfdf 100644 --- a/src/auto-reply/reply/commands-compact.ts +++ b/src/auto-reply/reply/commands-compact.ts @@ -130,6 +130,7 @@ function resolveManualCompactContextTokenBudget(params: { contextConfigProvider, model, }), + agentId: params.agentId, allowAsyncLoad: false, }); if (typeof configuredContextTokens === "number" && configuredContextTokens > 0) { diff --git a/src/auto-reply/reply/get-reply-directives-apply.ts b/src/auto-reply/reply/get-reply-directives-apply.ts index 3e907fcceccb..8243340dac0d 100644 --- a/src/auto-reply/reply/get-reply-directives-apply.ts +++ b/src/auto-reply/reply/get-reply-directives-apply.ts @@ -522,6 +522,7 @@ export async function applyInlineDirectiveOverrides(params: { config: cfg, }), model, + agentId: resolveSessionAgentId({ sessionKey, config: cfg }), modelContextWindow: selectedCatalogEntry?.contextWindow, modelContextTokens: selectedCatalogEntry?.contextTokens, }); diff --git a/src/auto-reply/reply/get-reply-directives.ts b/src/auto-reply/reply/get-reply-directives.ts index 0f8a081a8deb..d40de007ce1d 100644 --- a/src/auto-reply/reply/get-reply-directives.ts +++ b/src/auto-reply/reply/get-reply-directives.ts @@ -481,6 +481,7 @@ export async function resolveReplyDirectives(params: { cfg, provider, model, + agentId, modelContextWindow: modelState.modelContextWindow, modelContextTokens: modelState.modelContextTokens, }); diff --git a/src/auto-reply/reply/get-reply-native-slash-fast-path.ts b/src/auto-reply/reply/get-reply-native-slash-fast-path.ts index 55b0b62e7720..9cc05e32a1cd 100644 --- a/src/auto-reply/reply/get-reply-native-slash-fast-path.ts +++ b/src/auto-reply/reply/get-reply-native-slash-fast-path.ts @@ -384,6 +384,7 @@ export async function maybeResolveNativeSlashCommandFastReply(params: { cfg: params.cfg, provider: params.provider, model: params.model, + agentId: params.agentId, }), isGroup: sessionState.isGroup, loadSkillCommands: loadNativeSkillCommands, diff --git a/src/auto-reply/reply/memory-flush.ts b/src/auto-reply/reply/memory-flush.ts index 645668ae1e72..7037c599b9f1 100644 --- a/src/auto-reply/reply/memory-flush.ts +++ b/src/auto-reply/reply/memory-flush.ts @@ -18,12 +18,14 @@ export function resolveMemoryFlushContextWindowTokens(params: { modelId?: string; cfg?: OpenClawConfig; provider?: string; + agentId?: string; }): number { return ( resolveContextTokensForModel({ cfg: params.cfg, provider: params.provider, model: params.modelId, + agentId: params.agentId, allowAsyncLoad: false, }) ?? DEFAULT_CONTEXT_TOKENS ); diff --git a/src/auto-reply/reply/model-selection-context.ts b/src/auto-reply/reply/model-selection-context.ts index f2e099fa0ba5..2d8baf1d74d8 100644 --- a/src/auto-reply/reply/model-selection-context.ts +++ b/src/auto-reply/reply/model-selection-context.ts @@ -7,6 +7,7 @@ export function resolveContextTokens(params: { cfg: OpenClawConfig; provider: string; model: string; + agentId?: string; modelContextWindow?: number; modelContextTokens?: number; }): number { @@ -15,6 +16,7 @@ export function resolveContextTokens(params: { cfg: params.cfg, provider: params.provider, model: params.model, + agentId: params.agentId, modelContextWindow: params.modelContextWindow, modelContextTokens: params.modelContextTokens, allowAsyncLoad: false, diff --git a/src/cron/isolated-agent/run-finalize.ts b/src/cron/isolated-agent/run-finalize.ts index a94d40673062..e6fde792989c 100644 --- a/src/cron/isolated-agent/run-finalize.ts +++ b/src/cron/isolated-agent/run-finalize.ts @@ -107,6 +107,7 @@ export async function finalizeCronRun(params: { cfg: prepared.cfgWithAgentDefaults, provider: providerUsed, model: modelUsed, + agentId: prepared.agentId, allowAsyncLoad: false, }); const agentHarnessId = normalizeOptionalString(finalRunResult.meta?.agentMeta?.agentHarnessId);