opencodex 全局上下文上限:Models 页 Context Cap 值可配置化与 Set-all 批量开关实践

发布时间:2026/9/23 11:57:22
opencodex 全局上下文上限:Models 页 Context Cap 值可配置化与 Set-all 批量开关实践 opencodex 全局上下文上限Models 页 Context Cap 值可配置化与 Set-all 批量开关实践【免费下载链接】opencodexUniversal provider proxy for OpenAI Codex Claude Code — use any LLM (Claude, Gemini, Grok, DeepSeek, Ollama…) with Codex CLI, App, SDK, and Claude Code项目地址: https://gitcode.com/gh_mirrors/ope/opencodexopencodex 的 Models 页面为每个 Provider 提供Cap 350k开关用于把超大上下文模型在 Codex 可见的目录catalog中压到 350k。本篇文章基于 devlog/_fin/260629_provider-context-cap/20_global-cap-and-set-all.md 这一工作阶段文档讲解其后续演进上限值从代码里硬编码的350_000变成用户可全局配置的值100k–950k下拉 Custom数值输入并新增一个Set all开关对所有 Provider 一键批量设置或清除。读完本文你将掌握该功能的前端交互、管理 API 契约、配置持久化与 Codex catalog 应用语义的完整实现脉络。从固定 350k 到用户可控的全局上限在最初的实现里见 00_design.md 与 10_implementation.md每个 Provider 头部都有一个Cap 350k开关但350k是写死在代码常量DEFAULT_PROVIDER_CONTEXT_CAP中的打开开关永远写入350000。本次工作阶段做了两个用户提出的跟进上限值可配置在 Models 页页头与第一个 Provider 块之间新增一行可点击的控件显示当前全局上限值默认350k可通过下拉选择100k–950k每50k一档或选择Custom输入任意正整数原始 token 数。修改全局值后所有已开启上限的 Provider 会被重新指向新值其开关保持视觉上的开。Set all 批量开关同一行提供Set all控制一键为全部 Provider 开启使用当前全局值或关闭上限。关键语义保持不变上限是全局共享的单一值不是 per-provider 的并且上限只负责把已知的模型上下文窗口降低某个 Provider 若没有任何模型超过所选值开启上限是一个安全的 no-op。设计决策D1–D4原文档记录了四个核心决策D1 — 全局值存根配置在配置根部新增contextCapValue?: number默认DEFAULT_PROVIDER_CONTEXT_CAP 350_000。理由是上限是全局的一个值应放在根级而非每个 Provider 下providerContextCaps[provider]继续存解析后的数值 cap因此 catalog/应用路径与既有测试无需改动DEFAULT_PROVIDER_CONTEXT_CAP作为未设置时的兜底保持旧配置的行为不变。D2 — 已开启的 Provider 与全局值保持同步全局值变更时当前存在于providerContextCaps中的每个 Provider 都被改写为新值否则contextCaps[provider] contextCapValue会变成 false导致所有开关在仍存有 cap 的情况下渲染成关。D3 — 下拉选项100_000 ... 950_000按50_000步进生成渲染为100k、150k…950k末尾附带Custom...项选择Custom...后展开正整数数值输入与确认动作当前生效值即使不在50k网格上如默认350k或历史自定义值也始终可被选中。D4 — Set all 语义Set all on把当前全局值写给目录中每个 ProviderSet all off整体清空providerContextCaps复用与 per-provider 开关一致的值契约。配置模型与校验根级contextCapValue实现层面配置类型与 schema 分别在类型定义与 zod 校验中落地src/types/config.ts 在providerContextCaps旁新增根级字段contextCapValue?: number注释明确其为Codex 可见的全局上下文上限值token未设置时回退到DEFAULT_PROVIDER_CONTEXT_CAP。src/config/schema/config-schema.ts 为两个字段都声明了显式校验providerContextCaps: z.record(z.string(), z.number().int().positive()).optional(), contextCapValue: z.number().int().positive().optional(),这样手工编辑的config.json也会被 schema 约束而不是只依赖.passthrough()放行。对应测试 tests/server/config.test.ts 验证了contextCapValue: 500_000可被接受回读、contextCapValue: -5会被拒绝且诊断信息提及contextCapValuetests/config/config-user-edits.test.ts 则验证了用户编辑后contextCapValue: 240_000能正确持久化到磁盘。核心纯函数src/providers/context-cap.ts原文档规划的新模块src/provider-context-cap.ts在仓库重构后位于 src/providers/context-cap.ts全部核心逻辑以纯函数形式集中于此导出DEFAULT_PROVIDER_CONTEXT_CAP在 L4globalContextCapValue(config)L41-L44读取config.contextCapValue仅当它是有限正数时返回并Math.floor否则回退DEFAULT_PROVIDER_CONTEXT_CAP。setGlobalContextCapValue(config, value, applyToAll)L71-L82写入新的全局值applyToAll为 true 时对应 GUI 的应用到全部路由 Provider开关把所有已启用 Provider 重新指向新值并同步providerContextCapValues记忆表。setAllProviderContextCaps(config, providerNames, enabled)L85-L98enabled时以globalContextCapValue(config)为每个 Provider 名写值关闭时删除providerContextCaps键同时保留记忆表。applyProviderContextCap(contextWindow, cap)L25-L29只降不升、不发明值——cap 或窗口非法时原样返回窗口大于 cap 时取 cap否则原样返回。这是整个 catalog 语义的核心保证。resolveUnknownRoutedContextWindow(cap)L35-L38上游未报告窗口时已开启的 cap 就作为实际窗口128_000只是 Codex 解析器的兼容底线不能当作已发现窗口去和 cap 做 min。值得注意的实现演进setProviderContextCap(config, provider, enabled, value?)L51-L64在开启时支持三层取值——显式传入的 per-providervalue 记忆的providerContextCapValues[provider] 全局globalContextCapValue(config)这比原文档中enable 一律写全局值的早期描述更精细另外还提供了forgetProviderContextCap供删除 Provider 时清理 cap 与记忆值见 provider-routes.ts 中删除 Provider 的调用。管理 API 契约GET / PUT /api/provider-context-caps路由实现在 src/server/management/provider-routes.ts并在 route-registry.ts 登记为 GET只读与 PUT可变更。GET 响应return jsonResponse({ cap: DEFAULT_PROVIDER_CONTEXT_CAP, // 350_000向后兼容 / 兜底展示 value: globalContextCapValue(config), // 有效全局值contextCapValue ?? cap caps: providerContextCaps(config), // providerContextCaps 映射 values: selectedProviderContextCaps(config) // 记忆的 per-provider 选择 });即GET返回{ cap, value, caps, values }cap恒为DEFAULT_PROVIDER_CONTEXT_CAP保留用于向后兼容与兜底显示value才是生效的全局上限。PUT 三种请求体分支PUT 会先做请求体形状校验非对象载荷直接400provider/enabled必须成对出现且类型正确并且setAll不得与 provider 更新混用否则400避免静默忽略per-provider 开关{ provider, enabled }可选携带显式value。校验 provider 名isValidProviderName与存在性未知返回404显式value必须为有限数字floor 后仍须 1避免0.5floor 成 0 后静默回退全局默认。开启时按上文三层取值逻辑写 cap。设置全局值{ value }可附加setAll: true。value必须是有限数字floor 后 1拒绝400setAll存在时必须是布尔。setAll: true会把所有已启用 Provider 重新指向新值并逐个清模型缓存否则只改默认值、各 Provider 保留自己的 cap。Set all{ setAll: boolean }。对Object.keys(config.providers)全部写当前全局值或整体清除。任一分支成功后save(config)持久化 →reconcileLiveStateStores()→ 清受影响 Provider 的模型缓存clearModelCache→convergeCodexCatalog()尽力刷新 Codex 目录 → 返回{ ok: true, cap, value, caps, values, catalogRefresh }。无法识别的载荷最终统一400。这一契约被 tests/server/management-provider-validation.test.ts 完整锁定{ value: 500_000 }后旧 Provider 保持 350k、新开启的 Provider 写 500k不再写常量{ value: 600_000, setAll: true }把两个已启用 Provider 都重指向 600k{ setAll: false }清空caps{ setAll: true }全部按当前值开启{ provider, enabled: true, setAll: true }的混合载荷返回400见该文件 L4808。Catalog 应用语义只降低已知上下文窗口cap 的应用点位于 Codex 目录生成链路重构后分散在 src/codex/catalog/ 下的多个模块aggregation、bundled、combo-member、effort、gather-capture、metadata、model-hints 等统一调用applyProviderContextCap对每个模型的已解析上下文窗口contextWindow min(resolvedContextWindow, cap)若模型完全没有上下文元数据cap 不会发明出 350000仍由目录既有的默认逻辑负责——这保留了没有超过上限的模型时开启是 no-op的用户预期cap 应用在既有 provider/model 提示之后因此可以降低任何已知窗口但绝不抬高原文档 10_implementation 的 B 阶段修正也沿用至今jawcode 附加的 catalog 元数据可能在 cap 逻辑之后把 1M 窗口恢复回来因此 jawcode 追加的CatalogModel须在buildCatalogEntries()之前就携带 cap 元数据先应用 provider 提示再做 cap 处理参见 src/codex/catalog/combo-member.ts 与 src/codex/catalog/effort.ts 的applyProviderContextCap调用。GUI 实现顶部一行控件与值感知的开关文案前端集中在 gui/src/pages/Models.tsx共享常量与格式化工具在 gui/src/pages/models-shared.ts下拉选项L155-L156CAP_OPTIONS Array.from({ length: 18 }, (_, i) 100_000 i * 50_000)生成100k…950k共 18 档CUSTOM_OPTION custom作为尾项。原生 Codex 登录组特例L167-L169NATIVE_CAP_OPTIONS刻意只给 272_000 / 372_000 / 922_000 三个值——这是 GPT-5.6 原生族真正有契约的窗口live catalog 报 272k、此前 opencodex 契约 372k、当前广告上限 922k。cap 只降不升列出高于广告窗口的值没有意义其余走Custom。fmtKL182-L189350000 - 350k非 1000 整除的自定义值按千分位展示 1_000_000时渲染为1M这类紧凑格式单位后缀是技术记法而非文案因此不做 i18n。页面顶部行Models.tsx L2098-L2128位于页面头与第一个 Provider 卡之间包含models.contextCapLabel标签、全局值select当前值不在网格上时先插入一项真实可选项再列 18 档与Custom...以及一个Set all开关Switch on{allCapped} ... label{t(models.setAll)} /与提示文案setAllHintbusy 时禁用。每 Provider 的 cap 下拉L1599-L1627开关标签用models.capValue含fmtK后的当前值替代了原来的cap350k字面量被 cap 命中的模型行显示models.contextCappedValue标记L1794同样展示实际生效值而非固定的350k。原文档 Build record 里记录了一个 UI 细化用户最终要求单个Set all开关一个 Switch而非最初设计的Set all on / Set all off两个按钮同时 i18nen/ko/zh新增contextCapLabel、capValue、contextCappedValue、setAll、custom、customApply、customPlaceholder等键旧的cap350k/contextCapped键保留但不再被引用。CLI headless 侧的复用该 API 不只是 GUI 在用CLI 无头场景同样通过/api/provider-context-caps走同一契约。tests/cli/cli-headless-parity.test.ts 验证了 CLI 会发送{ setAll: true }以及{ value: 128_000, setAll: true }这类批量请求说明全局值 set-all 的语义在 CLI 自动化路径与 GUI 完全一致。验证方式与手工配置示例原文档给出的验证命令在仓库根目录执行依然适用bun test tests/config/config-user-edits.test.ts tests/server/config.test.ts tests/server/management-provider-validation.test.ts bun x tsc --noEmit cd gui bun run build对应构建记录显示最终状态101 个测试通过、0 失败、423 次 expecttsc --noEmit退出码 0GUI 的 TypeScript 项目构建与 Vite 生产构建均成功。提交被拆为三个feat(models): global context cap value set-all backend、feat(models): cap value dropdown single set-all toggle UI、test(models): cover global cap value and set-all toggles。若想绕过 GUI 手工配置可直接在config.json根级写入schema 会校验为正整数{ contextCapValue: 500000, providerContextCaps: { anthropic: 500000, openai: 500000 } }contextCapValue是全局默认providerContextCaps是每个 Provider 的实际生效值两者配合即可在重启后维持全局 500k、全部 Provider 已开启的状态同时每次变更都会触发模型缓存清理与 Codex 目录的尽力刷新保证 Codex 侧看到的上下文窗口立即反映最新上限。【免费下载链接】opencodexUniversal provider proxy for OpenAI Codex Claude Code — use any LLM (Claude, Gemini, Grok, DeepSeek, Ollama…) with Codex CLI, App, SDK, and Claude Code项目地址: https://gitcode.com/gh_mirrors/ope/opencodex创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考