UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

110 lines (109 loc) 6.21 kB
import { n as findNormalizedProviderValue } from "./provider-id-Dq06Bcx6.js"; import { n as resolveProviderEndpoint } from "./provider-attribution-GEHCfopl.js"; //#region src/agents/context-window-guard.ts /** * Resolves effective model context windows and formats guard warnings/blocks. * * Configured model values can cap provider metadata, and local endpoints get * more actionable remediation text. */ const CONTEXT_WINDOW_HARD_MIN_TOKENS = 4e3; const CONTEXT_WINDOW_WARN_BELOW_TOKENS = 8e3; const CONTEXT_WINDOW_HARD_MIN_RATIO = .1; const CONTEXT_WINDOW_WARN_BELOW_RATIO = .2; function normalizePositiveInt(value) { if (typeof value !== "number" || !Number.isFinite(value)) return null; const int = Math.floor(value); return int > 0 ? int : null; } function modelIdMatchesProviderScope(params) { const configuredId = params.configuredId?.trim(); if (!configuredId) return false; if (configuredId === params.modelId) return true; const providerPrefix = params.provider ? `${params.provider}/` : ""; if (!providerPrefix) return false; const stripProvider = (id) => id.startsWith(providerPrefix) ? id.slice(providerPrefix.length) : id; return stripProvider(configuredId) === stripProvider(params.modelId); } /** Resolve the effective context window and source for one provider/model. */ function resolveContextWindowInfo(params) { const fromModelsConfig = (() => { const providers = params.cfg?.models?.providers; const providerEntry = findNormalizedProviderValue(providers, params.provider); const match = (Array.isArray(providerEntry?.models) ? providerEntry.models : []).find((model) => modelIdMatchesProviderScope({ configuredId: model?.id, provider: params.provider, modelId: params.modelId })); return normalizePositiveInt(match?.contextTokens) ?? normalizePositiveInt(match?.contextWindow); })(); const fromModel = normalizePositiveInt(params.modelContextTokens) ?? normalizePositiveInt(params.modelContextWindow); const defaultTokens = normalizePositiveInt(params.defaultTokens) ?? 8e3; const baseInfo = fromModelsConfig ? { tokens: fromModelsConfig, source: "modelsConfig" } : fromModel ? { tokens: fromModel, source: "model" } : { tokens: defaultTokens, source: "default" }; const capTokens = normalizePositiveInt(params.cfg?.agents?.defaults?.contextTokens); if (capTokens && capTokens < baseInfo.tokens) return { tokens: capTokens, referenceTokens: baseInfo.tokens, source: "agentContextTokens" }; return baseInfo; } function resolveContextWindowGuardHint(params) { const endpoint = resolveProviderEndpoint(params.runtimeBaseUrl ?? void 0); return { endpointClass: endpoint.endpointClass, likelySelfHosted: endpoint.endpointClass === "local" }; } /** Derive warning/block floors from the resolved model context window. */ function resolveContextWindowGuardThresholds(contextWindowTokens) { const tokens = normalizePositiveInt(contextWindowTokens) ?? 0; return { hardMinTokens: Math.max(CONTEXT_WINDOW_HARD_MIN_TOKENS, Math.floor(tokens * CONTEXT_WINDOW_HARD_MIN_RATIO)), warnBelowTokens: Math.max(CONTEXT_WINDOW_WARN_BELOW_TOKENS, Math.floor(tokens * CONTEXT_WINDOW_WARN_BELOW_RATIO)) }; } /** Format a non-blocking low-context warning message. */ function formatContextWindowWarningMessage(params) { const base = `low context window: ${params.provider}/${params.modelId} ctx=${params.guard.tokens} (warn<${params.guard.warnBelowTokens}) source=${params.guard.source}`; if (!resolveContextWindowGuardHint({ runtimeBaseUrl: params.runtimeBaseUrl }).likelySelfHosted) return base; if (params.guard.source === "agentContextTokens") return `${base}; OpenClaw is capped by agents.defaults.contextTokens, so raise that cap if you want to use more of the model context window`; if (params.guard.source === "modelsConfig") return `${base}; OpenClaw is using the configured model context limit for this model, so raise contextWindow/contextTokens if it is set too low`; return `${base}; local/self-hosted runs work best at ${params.guard.warnBelowTokens}+ tokens and may show weaker tool use or more compaction until the server/model context limit is raised`; } /** Format a blocking context-window guard message. */ function formatContextWindowBlockMessage(params) { const base = `Model context window too small (${params.guard.tokens} tokens; source=${params.guard.source}). Minimum is ${params.guard.hardMinTokens}.`; if (!resolveContextWindowGuardHint({ runtimeBaseUrl: params.runtimeBaseUrl }).likelySelfHosted) return base; if (params.guard.source === "agentContextTokens") return `${base} OpenClaw is capped by agents.defaults.contextTokens. Raise that cap.`; if (params.guard.source === "modelsConfig") return `${base} OpenClaw is using the configured model context limit for this model. Raise contextWindow/contextTokens or choose a larger model.`; return `${base} This looks like a local model endpoint. Raise the server/model context limit or choose a larger model. OpenClaw local/self-hosted runs work best at ${params.guard.warnBelowTokens}+ tokens.`; } /** Evaluate whether the resolved context window should warn or block. */ function evaluateContextWindowGuard(params) { const normalizedTokens = normalizePositiveInt(params.info.tokens); const tokens = normalizedTokens ?? 0; const resolvedThresholds = resolveContextWindowGuardThresholds(normalizePositiveInt(params.info.referenceTokens) ?? tokens); const warnBelow = Math.max(1, Math.floor(params.warnBelowTokens ?? resolvedThresholds.warnBelowTokens)); const defaultHardMin = Math.min(resolvedThresholds.hardMinTokens, Math.max(tokens, CONTEXT_WINDOW_HARD_MIN_TOKENS)); const hardMin = Math.max(1, Math.floor(params.hardMinTokens ?? defaultHardMin)); return { ...params.info, tokens, hardMinTokens: hardMin, warnBelowTokens: warnBelow, shouldWarn: !normalizedTokens || tokens < warnBelow, shouldBlock: !normalizedTokens || tokens < hardMin }; } //#endregion export { formatContextWindowWarningMessage as a, formatContextWindowBlockMessage as i, CONTEXT_WINDOW_WARN_BELOW_TOKENS as n, resolveContextWindowGuardThresholds as o, evaluateContextWindowGuard as r, resolveContextWindowInfo as s, CONTEXT_WINDOW_HARD_MIN_TOKENS as t };