fix(agents): apply contextTokens cap for compaction threshold (#39099)

Land #39099 by @MumuTW.

Co-authored-by: MumuTW <clothl47364@gmail.com>
This commit is contained in:
Peter Steinberger
2026-03-07 19:18:48 +00:00
parent e27bbe4982
commit 537c97cce9
4 changed files with 25 additions and 3 deletions

View File

@@ -254,6 +254,7 @@ Docs: https://docs.openclaw.ai
- Models/default provider fallback: when the hardcoded default provider is removed from `models.providers`, resolve defaults from configured providers instead of reporting stale removed-provider defaults in status output. (#38947) Thanks @davidemanuelDEV.
- Agents/cache-trace stability: guard stable stringify against circular references in trace payloads so near-limit payloads no longer crash with `Maximum call stack size exceeded`; adds regression coverage. (#38935) Thanks @MumuTW.
- Extensions/diffs CI stability: add `headers` to the `localReq` test helper in `extensions/diffs/index.test.ts` so forwarding-hint checks no longer crash with `req.headers` undefined. (supersedes #39063) Thanks @Shennng.
- Agents/compaction thresholding: apply `agents.defaults.contextTokens` cap to the model passed into embedded run and `/compact` session creation so auto-compaction thresholds use the effective context window, not native model max context. (#39099) Thanks @MumuTW.
## 2026.3.2

View File

@@ -173,6 +173,7 @@ vi.mock("../date-time.js", () => ({
vi.mock("../defaults.js", () => ({
DEFAULT_MODEL: "fake-model",
DEFAULT_PROVIDER: "openai",
DEFAULT_CONTEXT_TOKENS: 128_000,
}));
vi.mock("../utils.js", () => ({

View File

@@ -376,6 +376,20 @@ export async function compactEmbeddedPiSessionDirect(
sessionId: params.sessionId,
warn: makeBootstrapWarn({ sessionLabel, warn: (message) => log.warn(message) }),
});
// Apply contextTokens cap to model so pi-coding-agent's auto-compaction
// threshold uses the effective limit, not the native context window.
const ctxInfo = resolveContextWindowInfo({
cfg: params.config,
provider,
modelId,
modelContextWindow: model.contextWindow,
defaultTokens: DEFAULT_CONTEXT_TOKENS,
});
const effectiveModel =
ctxInfo.tokens < (model.contextWindow ?? Infinity)
? { ...model, contextWindow: ctxInfo.tokens }
: model;
const runAbortController = new AbortController();
const toolsRaw = createOpenClawCodingTools({
exec: {
@@ -398,7 +412,7 @@ export async function compactEmbeddedPiSessionDirect(
abortSignal: runAbortController.signal,
modelProvider: model.provider,
modelId,
modelContextWindowTokens: model.contextWindow,
modelContextWindowTokens: ctxInfo.tokens,
modelAuthMode: resolveModelAuthMode(model.provider, params.config),
});
const tools = sanitizeToolsForGoogle({
@@ -594,7 +608,7 @@ export async function compactEmbeddedPiSessionDirect(
agentDir,
authStorage,
modelRegistry,
model,
model: effectiveModel,
thinkingLevel: mapThinkingLevel(params.thinkLevel),
tools: builtInTools,
customTools,

View File

@@ -375,6 +375,12 @@ export async function runEmbeddedPiAgent(
modelContextWindow: model.contextWindow,
defaultTokens: DEFAULT_CONTEXT_TOKENS,
});
// Apply contextTokens cap to model so pi-coding-agent's auto-compaction
// threshold uses the effective limit, not the native context window.
const effectiveModel =
ctxInfo.tokens < (model.contextWindow ?? Infinity)
? { ...model, contextWindow: ctxInfo.tokens }
: model;
const ctxGuard = evaluateContextWindowGuard({
info: ctxInfo,
warnBelowTokens: CONTEXT_WINDOW_WARN_BELOW_TOKENS,
@@ -866,7 +872,7 @@ export async function runEmbeddedPiAgent(
disableTools: params.disableTools,
provider,
modelId,
model,
model: effectiveModel,
authProfileId: lastProfileId,
authProfileIdSource: lockedProfileId ? "user" : "auto",
authStorage,