mirror of
https://github.com/moltbot/moltbot.git
synced 2026-03-21 16:41:56 +00:00
fix: cap context window resolution (#6187) (thanks @iamEvanYT)
This commit is contained in:
@@ -77,7 +77,7 @@ describe("context-window-guard", () => {
|
||||
cfg,
|
||||
provider: "openrouter",
|
||||
modelId: "tiny",
|
||||
modelContextWindow: undefined,
|
||||
modelContextWindow: 64_000,
|
||||
defaultTokens: 200_000,
|
||||
});
|
||||
const guard = evaluateContextWindowGuard({ info });
|
||||
@@ -85,7 +85,7 @@ describe("context-window-guard", () => {
|
||||
expect(guard.shouldBlock).toBe(true);
|
||||
});
|
||||
|
||||
it("falls back to agents.defaults.contextTokens", () => {
|
||||
it("caps with agents.defaults.contextTokens", () => {
|
||||
const cfg = {
|
||||
agents: { defaults: { contextTokens: 20_000 } },
|
||||
} satisfies OpenClawConfig;
|
||||
@@ -93,7 +93,7 @@ describe("context-window-guard", () => {
|
||||
cfg,
|
||||
provider: "anthropic",
|
||||
modelId: "whatever",
|
||||
modelContextWindow: undefined,
|
||||
modelContextWindow: 200_000,
|
||||
defaultTokens: 200_000,
|
||||
});
|
||||
const guard = evaluateContextWindowGuard({ info });
|
||||
@@ -102,6 +102,21 @@ describe("context-window-guard", () => {
|
||||
expect(guard.shouldBlock).toBe(false);
|
||||
});
|
||||
|
||||
it("does not override when cap exceeds base window", () => {
|
||||
const cfg = {
|
||||
agents: { defaults: { contextTokens: 128_000 } },
|
||||
} satisfies OpenClawConfig;
|
||||
const info = resolveContextWindowInfo({
|
||||
cfg,
|
||||
provider: "anthropic",
|
||||
modelId: "whatever",
|
||||
modelContextWindow: 64_000,
|
||||
defaultTokens: 200_000,
|
||||
});
|
||||
expect(info.source).toBe("model");
|
||||
expect(info.tokens).toBe(64_000);
|
||||
});
|
||||
|
||||
it("uses default when nothing else is available", () => {
|
||||
const info = resolveContextWindowInfo({
|
||||
cfg: undefined,
|
||||
|
||||
@@ -11,9 +11,7 @@ export type ContextWindowInfo = {
|
||||
};
|
||||
|
||||
function normalizePositiveInt(value: unknown): number | null {
|
||||
if (typeof value !== "number" || !Number.isFinite(value)) {
|
||||
return null;
|
||||
}
|
||||
if (typeof value !== "number" || !Number.isFinite(value)) return null;
|
||||
const int = Math.floor(value);
|
||||
return int > 0 ? int : null;
|
||||
}
|
||||
@@ -25,11 +23,6 @@ export function resolveContextWindowInfo(params: {
|
||||
modelContextWindow?: number;
|
||||
defaultTokens: number;
|
||||
}): ContextWindowInfo {
|
||||
const fromModel = normalizePositiveInt(params.modelContextWindow);
|
||||
if (fromModel) {
|
||||
return { tokens: fromModel, source: "model" };
|
||||
}
|
||||
|
||||
const fromModelsConfig = (() => {
|
||||
const providers = params.cfg?.models?.providers as
|
||||
| Record<string, { models?: Array<{ id?: string; contextWindow?: number }> }>
|
||||
@@ -39,16 +32,19 @@ export function resolveContextWindowInfo(params: {
|
||||
const match = models.find((m) => m?.id === params.modelId);
|
||||
return normalizePositiveInt(match?.contextWindow);
|
||||
})();
|
||||
if (fromModelsConfig) {
|
||||
return { tokens: fromModelsConfig, source: "modelsConfig" };
|
||||
const fromModel = normalizePositiveInt(params.modelContextWindow);
|
||||
const baseInfo = fromModelsConfig
|
||||
? { tokens: fromModelsConfig, source: "modelsConfig" as const }
|
||||
: fromModel
|
||||
? { tokens: fromModel, source: "model" as const }
|
||||
: { tokens: Math.floor(params.defaultTokens), source: "default" as const };
|
||||
|
||||
const capTokens = normalizePositiveInt(params.cfg?.agents?.defaults?.contextTokens);
|
||||
if (capTokens && capTokens < baseInfo.tokens) {
|
||||
return { tokens: capTokens, source: "agentContextTokens" };
|
||||
}
|
||||
|
||||
const fromAgentConfig = normalizePositiveInt(params.cfg?.agents?.defaults?.contextTokens);
|
||||
if (fromAgentConfig) {
|
||||
return { tokens: fromAgentConfig, source: "agentContextTokens" };
|
||||
}
|
||||
|
||||
return { tokens: Math.floor(params.defaultTokens), source: "default" };
|
||||
return baseInfo;
|
||||
}
|
||||
|
||||
export type ContextWindowGuardResult = ContextWindowInfo & {
|
||||
|
||||
@@ -197,10 +197,7 @@ export default function compactionSafeguardExtension(api: ExtensionAPI): void {
|
||||
try {
|
||||
const runtime = getCompactionSafeguardRuntime(ctx.sessionManager);
|
||||
const modelContextWindow = resolveContextWindowTokens(model);
|
||||
const contextWindowTokens = Math.min(
|
||||
runtime?.contextWindowTokens ?? modelContextWindow,
|
||||
modelContextWindow,
|
||||
);
|
||||
const contextWindowTokens = runtime?.contextWindowTokens ?? modelContextWindow;
|
||||
const turnPrefixMessages = preparation.turnPrefixMessages ?? [];
|
||||
let messagesToSummarize = preparation.messagesToSummarize;
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ export function registerStatusHealthSessionsCommands(program: Command) {
|
||||
["openclaw sessions --json", "Machine-readable output."],
|
||||
["openclaw sessions --store ./tmp/sessions.json", "Use a specific session store."],
|
||||
])}\n\n${theme.muted(
|
||||
"Shows token usage per session when the agent reports it; set agents.defaults.contextTokens to see % of your model window.",
|
||||
"Shows token usage per session when the agent reports it; set agents.defaults.contextTokens to cap the window and show %.",
|
||||
)}`,
|
||||
)
|
||||
.addHelpText(
|
||||
|
||||
@@ -122,7 +122,7 @@ export type AgentDefaultsConfig = {
|
||||
* Include elapsed time in message envelopes ("on" | "off", default: "on").
|
||||
*/
|
||||
envelopeElapsed?: "on" | "off";
|
||||
/** Optional display-only context window override (used for % in status UIs). */
|
||||
/** Optional context window cap (used for runtime estimates + status %). */
|
||||
contextTokens?: number;
|
||||
/** Optional CLI backends for text-only fallback (claude-cli, etc.). */
|
||||
cliBackends?: Record<string, CliBackendConfig>;
|
||||
|
||||
Reference in New Issue
Block a user