拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

opencodex 斜杠模型 ID 编解码:Codex 单斜杠 Slug 契约的完整实现与路由解析

opencodex 斜杠模型 ID 编解码:Codex 单斜杠 Slug 契约的完整实现与路由解析 【免费下载链接】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点击查看免费下载本指南基于devlog/_fin/260718_slash_model_id_codec/记录深入讲解 opencodex 如何为原生 model id 含/的提供商zenmuxmoonshotai/kimi-k3-free、openrouteranthropic/...、nvidiamoonshotai/...等生成 Codex 端单斜杠 slug并在代理层做精确双射解码。读完你将掌握为什么 Codex 的「单斜杠标签查找」会丢失元数据、src/providers/slug-codec.ts的核心契约别名分隔符、解码优先级、冲突处理、路由器与目录的接入点以及如何在ocx sync后验证冷缓存解码与原始全斜杠选择器的兼容性。背景Codex 的单斜杠标签查找Tagging约束opencodex 作为通用提供商代理会把原生 model id 以provider/model-id的「路由 slug」形式写入 Codex 目录catalog使 Codex 模型选择器picker能显示第三方模型。但 Codex 自身对模型元数据推理努力阶梯、上下文窗口、能力标签的解析有严格的单斜杠规则codex-rs 的models-manager中find_model_by_namespaced_suffix对应 模型目录元数据文档对modelId执行split_once(/)若剩余部分仍包含/则直接拒绝本次元数据查找。对于原生 id 自带命名空间的提供商——zenmuxmoonshotai/kimi-k3-free、openrouteranthropic/claude-sonnet-5、nvidiamoonshotai/kimi-k2.6——若原样透传就会生成zenmux/moonshotai/kimi-k3-free这样的双斜杠 slug。Codex 因无法通过标签查找解析它会静默回退到默认元数据努力阶梯、上下文窗口、能力标签全部丢失。该问题在真实缓存中得到了验证~/.codex/opencodex-catalog.json中唯一的双斜杠 slug 就是zenmux/moonshotai/kimi-k3-free。于是产生了一个明确的需求把内层斜杠在 Codex 面对面上改写为别名分隔符同时在代理层无歧义地还原为原生 id。设计决策别名分隔符与单向契约围绕上述约束opencodex 采用了「Codex 兼容性别名仅此而已」的定位并形成四条硬性规则别名分隔符是-连字符由 slug-codec.ts 的SLUG_ALIAS_SEPARATOR -定义。原生 id 往往已含大量下划线连字符在 Codex 应用展示中更易读因此用户方向上从_修订为-。绝不盲目解码-→/解码必须是针对提供商「已知原生 id 集合」的精确双射查找。未知 id 原样透传由上游给出诚实的报错绝不猜测。原生 id 永远是内部规范形式上游请求、日志、用量统计、jawcode 元数据、combo 键、禁用列表全部使用原生 id只有 Codex 面对面的界面目录条目、picker 列表、Codex 侧配置选择才使用编码 slug。向后兼容原始全斜杠选择器用户在配置或请求里直接写zenmux/moonshotai/kimi-k3-free依然有效——精确原生匹配优先于编码匹配。核心编解码函数逐一解析slug-codec.ts 是本次实现的叶子模块只导入类型、不引入循环依赖其导出函数构成了完整的编解码契约1. 编码encodeRoutedModelId与routedSlug/** 原生 model id - Codex 面对面的别名 id。对不含 / 的 id 是 no-op。 */ export function encodeRoutedModelId(id: string): string { return id.includes(/) ? id.replaceAll(/, SLUG_ALIAS_SEPARATOR) : id; } /** Codex 面对面的路由 slug恰好一个 / —— provider/encoded id。 */ export function routedSlug(provider: string, id: string): string { return ${provider}/${encodeRoutedModelId(id)}; }encodeRoutedModelId(moonshotai/kimi-k3-free)→moonshotai-kimi-k3-freeroutedSlug(zenmux, moonshotai/kimi-k3-free)→zenmux/moonshotai-kimi-k3-free恰好一个/配套的encodedModelIdCollides(modelId, knownIds)用于在目录构建期检测两个原生 id 编码后是否撞车例如openai/gpt-5.5与openai-gpt-5.5从而让provider/openai-gpt-5.5能被解码回原生openai-gpt-5.5同时自定义openai/gpt-5.5行仍然可见。2. 解码decodeRoutedModelId的三段优先级export function decodeRoutedModelId(requested: string, knownIds: Iterablestring): string { let aliasMatch: string | undefined; for (const id of knownIds) { if (id requested) return requested; // ① 原生精确匹配原始选择器向后兼容 if (id.includes(/) encodeRoutedModelId(id) requested) { if (aliasMatch ! undefined aliasMatch ! id) return requested; // ② 别名歧义拒绝猜测 aliasMatch id; // ③ 唯一别名匹配 } } return aliasMatch ?? requested; // ③ 未知 id 原样透传 }三段查找按顺序执行原生精确匹配requested本身就是已知原生 id如a/b、a-b→ 原样返回这是原始全斜杠选择器向后兼容的根基唯一别名匹配恰好一个已知原生 id 编码后等于requested→ 返回该原生 id透传既不是原生 id、也没有唯一别名 → 原样返回requested交由上游给出诚实错误。歧义绝不猜测当同一提供商同时存在a/b与a-b且没有原生a-b时decodeRoutedModelId(a-b, ...)保持a-b不变——因为x/y/z与x/y-z会编码成同一个x-y-z盲目替换会把请求路由到错误模型。另有严格变体decodeRoutedModelIdOrThrow它收集所有匹配原生或编码等价到集合中若匹配数 1 直接抛出ambiguous model id ...异常。src/router.ts显式提供商命名空间分支正使用该变体用以在运行期捕获「写入期检查无法覆盖的后来实时缓存冲突」。3. 配置比较的宽容等价slugEquals/slugEquivalenceKey/slugsEquivalentexport function slugEquals(stored: string, provider: string, id: string): boolean { return stored ${provider}/${id} || stored routedSlug(provider, id); } export function slugEquivalenceKey(slug: string): string { const slash slug.indexOf(/); return slash 0 ? JSON.stringify([exact, slug]) : JSON.stringify([routed, slug.slice(0, slash), encodeRoutedModelId(slug.slice(slash 1))]); } export function slugsEquivalent(a: string, b: string): boolean { return a b || slugEquivalenceKey(a) slugEquivalenceKey(b); }slugEquals(zenmux/moonshotai-kimi-k3-free, zenmux, moonshotai/kimi-k3-free)→trueslugEquals(zenmux/moonshotai/kimi-k3-free, zenmux, moonshotai/kimi-k3)→falseid 不同slugsEquivalent(zenmux/moonshotai/kimi-k3-free, zenmux/moonshotai/kimi-k3-free)→true跨原始/编码两种拼写等价slugEquivalenceKey是有意有损的——单斜杠规则强制a/b与a-b归入同一编码形式。目录过滤与持久化同步共享此键因此保持一致但会在提供商同时发布两个拼写时静默超额授权over-grant。slugEquals/slugsEquivalent的存在保证了遗留原始全斜杠配置如disabledModels、subagentModels无论以何种形式存储都能继续生效。4.#2491选择解析器resolveSlugSelectionresolveSlugSelection(provider, selection, knownIds)返回SlugSelectionMatch { matched, exact, ambiguous }把「这个选择到底命中了谁」显式暴露给调用方先决条件若 roster 确实发布了原生 idacme/turbo自我命名空间则字面拼写按原生 id 处理而不是按「provider 限定的turbo」否则一个已发布的acme/turbo会变得不可达而兄弟 idturbo会悄悄吞掉该选择ocx models remove正是从该解析器读取匹配此歧义会指向破坏性命令。两个拼写都存在时报ambiguous: true同时给出exact操作者字面键入的那一行由调用方决定是严格收紧到精确行还是容忍整个撞车类。roster 缺失某个已发布 id 时返回空匹配——绝不发明一个。目录Catalog接入单斜杠 slug 的发射与冲突处理发射规则build-entries.ts 的buildCatalogEntries中路由模型目录条目使用routedSlug(m.provider, m.id)生成 slug、display_name同步采用该编码 slug而base_instructions中的身份文本必须使用原生 model id——即 jawcode 元数据键是原生的openrouteranthropic/...编码别名切片无法命中元数据表。测试 slug-codec.test.ts 断言buildCatalogEntries(..., [{provider: zenmux, id: moonshotai/kimi-k3-free}])产出slug zenmux/moonshotai-kimi-k3-free且slug.split(/)长度恰为 2其base_instructions文本包含moonshotai/kimi-k3-free原生而非moonshotai-kimi-k3-free。jawcode 元数据在原生 id 上解析模板 空模板双分支const meta getModelMetadata(openrouter, anthropic/claude-sonnet-5); // contextWindow 1_000_000input_modalities [text, image]对{ provider: openrouter, id: anthropic/claude-sonnet-5 }无论是否有原生目录模板template 与 null-template 两条分支编码条目openrouter/anthropic-claude-sonnet-5的context_window与input_modalities都必须来自原生 id 的元数据查找——applyJawcodeCatalogMetadata的签名改为(entry, provider, nativeModelId, contextCap)绝不从编码 slug 反推 provider/id。撞车处理警告一次、原生连字符优先当同一提供商的两个原生 id 编码为同一个别名如a/b与a-b目录槽位原生连字符拼写a-b胜出与解码优先级一致失败者a/b被丢弃但依然可通过其原始全斜杠选择器调用警告console.warn每个 provideralias 只触发一次——测试中两次构建buildCatalogEntries后console.warn恰好被调用 1 次重复编码 slug 永不发射。路由器Router接入编码请求还原为原生 idsrc/router.ts 的显式提供商命名空间分支约 L742-L763是代理层解码的核心const known knownModelIdsForProvider(provName, prov, config); // 自我命名空间原生 id如 orcarouter/auto整体路由不做切片 if (known.includes(modelId)) { return routeResult(config, provName, prov, modelId, explicit-provider, explicit-provider-namespace); } // Codex 面对面的别名 idprovider/vendor-model通过精确已知 id 查找解码回原生斜杠 id const requestedModel modelId.slice(slash 1); const decoded decodeRoutedModelIdOrThrow(requestedModel, known); const nativeModel known.includes(decoded) ? decoded : resolveModelAlias(config, prov, known, requestedModel) ?? decoded; return routeResult(config, provName, prov, nativeModel, explicit-provider, explicit-provider-namespace);knownModelIdsForProvider将三类来源合并为「已知原生 id 并集」配置层config.providers[provName].models、defaultModel、customModels仅限该 provider 的行注册表层PROVIDER_REGISTRY条目的静态modelsseed以及 registry 中各类以原生 id 为键的 hint mapmodelWireDefaults、modelDisplayNames、modelContextWindows、modelReasoningEfforts、keyAuthServiceTier.modelSupportsServiceTier等实时缓存层getStaleCached(provName)拉取过的模型列表。另有两条编码回退分支defaultModel与providers[].models中的裸 id如vendor-m-1在走默认模型/模型列表匹配时也通过编码形式比较因此routeModel(config, vendor-m-1)能路由到other提供商的vendor/m-1。实战冷缓存注册表 seed 与实时缓存边界静态 seed冷缓存也能解码zenmux 注册表条目补充了静态models: [moonshotai/kimi-k3-free, moonshotai/kimi-k3]2026-07-18 经 zenmux.ai/api/v1/models 实测验证替换了原先的 FREEZE 注释。这意味着即便没有实时缓存routeModel(config, zenmux/moonshotai-kimi-k3-free)也能解码回moonshotai/kimi-k3-free。nvidia 这类没有静态 models 列表的提供商则依赖 registry 的 model-keyed hint map 作为解码种子routeModel(config, nvidia/moonshotai-kimi-k2.6)同样解码成功且其原始全斜杠形式nvidia/moonshotai/kimi-k2.6继续可达。已知边界诚实行为传输不匹配的提供商不继承解码提示若某提供商配置了与 registry 不一致的 baseUrl/传输其解码提示不生效编码 id 原样透传registry 解码提示本身不发布目录行仅存在于 hint map 的 id 不会因此出现在 catalog 中冷缓存解码依赖原生 id 含斜杠且无静态 seed 的提供商只能靠暖的实时缓存解码否则编码 id 原样透传并触发上游报错运行期撞车被严格拒绝自定义openai/gpt-5.5先被收录后若实时缓存又发现openai-gpt-5.5则routeModel抛ambiguous而不是静默二选一。集成面与 SoT 同步管理 APIsrc/server/management-api.ts/api/models命名空间列表、/api/injection-model可用列表等所有管理 picker 界面发射routedSlug(...)使存储的配置值disabledModels、injectionModel、subagentModels与 Codex 面对面的目录 slug 一致读取端统一slugEquals-宽容。Claude 代理侧src/claude/agents-inject.ts在调用claudeCodeAlias(provider, id)前先用同一 known-ids 并集解码 model-id 段保证原始原生 context-window 映射表context-windows.ts继续命中。上游保持原始形态/v1/modelsOpenAI 形态的命名空间可用列表、combo 目录 slug 等上游面对面的表面保持原始原生键不变不做编码。SoT 文档README 与 docs/codex-app-model-catalog.mdSlash-containing native ids 一节记录了该别名规则作为模型的单一事实来源SoT。验证与激活证据单元测试 slug-codec.test.ts 覆盖编码往返、解码优先级原生 唯一别名 透传、别名歧义拒绝、撞车警告一次、slugEquals/slugsEquivalent/slugEquivalenceKey等价关系、冷缓存 registry seed 解码、registry hint map 独立播种、默认模型与 models 列表编码回退、jawcode 原生元数据模板 空模板、撞车槽位裁决、featured 排名对原始/编码拼写双兼容以及#2491选择解析器的 9 个场景全量回归变更集相对 HEAD 基线失败集合完全一致15 个新绿测试现存 55 个失败均为预存的并行加载波动websocket 超时、oauth token-store 竞争、worktree-only GUI react 运行时解析与本变更无关目录端激活断言slash-id 模型产出的 slug 恰有一个/且编码请求经routeModel解码到原生 id。升级到本分支后的操作步骤从本分支重新安装/重启本地 ocx 服务运行ocx sync或重启应用使~/.codex/opencodex-catalog.json拾取单斜杠 slug下一次同步后陈旧的zenmux/moonshotai/kimi-k3-free条目被替换为新条目zenmux/moonshotai-kimi-k3-free验证Codex 模型选择器中出现zenmux/moonshotai-kimi-k3-free单斜杠其努力阶梯、上下文窗口等标签来自原生 id 元数据同时旧的原始全斜杠选择器zenmux/moonshotai/kimi-k3-free依然可路由。赞分享【免费下载链接】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点击查看免费下载相关推荐Hermes Desktop 斜杠命令执行机制解析从 slash.exec 路由管线到中央命令路由器的完整实现Hermes Desktop 斜杠命令执行机制解析从 slash.exec 路由管线到中央命令路由器的完整实现 导读 本文以 Hermes DesktopHAI 应用交互助手桌面应用Manim v0.17.1 修复解析LaTeX 路径正斜杠兼容与子字幕 Unicode 编码Manim v0.17.1 修复解析LaTeX 路径正斜杠兼容与子字幕 Unicode 编码 导读 ManimCommunity Edition简称 Ma图形学教育上一篇3分钟快速部署WorkshopDL跨平台游戏模组下载终极解决方案下一篇零基础用 Czkawka 快速找出重复文件与相似图片创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表