Codex Light 插件安装器源码解析:oh-my-openagent 如何把 omo 一键装进 ~/.codex
2026/9/20 20:43:29 网站建设 项目流程
  • 人工智能
  • AI Agent
  • 代码智能体
  • 多智能体
  • MCP Clients
  • Agent 编排

【免费下载链接】oh-my-openagent

OmO: Just type "mass ulw" keyword with your prompt. Now you are the master of graph engineering.

项目地址:https://gitcode.com/gh_mirrors/oh/oh-my-openagent
点击查看免费下载

install-codex是 oh-my-openagent(OmO)项目中专用于 Codex CLI Light 版的插件安装器:它负责把omo插件及其捆绑的 Agent、MCP 清单、Hook 信任哈希与 CLI 入口完整写入用户的~/.codex/目录,并同步改写~/.codex/config.toml。本文以仓库中的 packages/omo-opencode/src/cli/install-codex/AGENTS.md 为主线,结合其底层实现(位于 packages/omo-codex/src/install/)逐阶段拆解安装流程、产物布局与设计约束,读完即可理解该安装器的全部内部机制,也能独立排查安装产物与卸载残留问题。

一、定位:一个指向规范实现的 OpenCode CLI 适配垫片

文档开篇即点明这个目录的本质——它不再是独立的安装器实现,而是一个 OpenCode CLI adapter shim(适配垫片)。真正的安装器源码被收敛到packages/omo-codex/src/install/,而packages/omo-opencode/src/cli/install-codex/下的同名文件只做一件事:从@oh-my-opencode/omo-codex/install/install-codex@oh-my-opencode/omo-codex/install/types重新导出,例如 packages/omo-opencode/src/cli/install-codex/install-codex.ts 全文只有一行export * from "@oh-my-opencode/omo-codex/install/install-codex",types.ts 同理。这种"垫片 + 规范实现"的双层结构让 OpenCode CLI 侧只保留命令路由入口,所有安装逻辑单点维护,避免双实现漂移。

安装的触发方式有两种等价命令(文档明确给出):

  • bunx oh-my-openagent install --platform=codex
  • 别名形式:npx lazycodex-ai install

入口函数是runCodexInstaller(),它接收一个可选的CodexInstallOptions参数并返回CodexInstallResult,这两个类型定义在 packages/omo-codex/src/install/types.ts。

二、目录结构与关键文件

install-codex目录内共 39 个文件,文档以表格形式给出了最核心的 8 个文件及其职责,这是理解整个安装器的最小清单:

文件职责
install-codex.ts主编排器runCodexInstaller()——解析路径、遍历 marketplace 插件、驱动 cache/install/config 各阶段
types.tsCodexInstallOptionsCodexInstallResultMarketplaceManifestPluginManifestInstalledPlugin等类型
codex-marketplace.ts读取packages/omo-codex/marketplace.json与各插件的.codex-plugin/plugin.json,校验路径段
codex-cache-install.ts构建源码、拷贝到临时缓存目录、执行npm ci --omit=dev、改写 MCP 清单、原子提升到~/.codex/plugins/cache/{marketplace}/{name}/{version}/
codex-cache-bins.ts发现package.jsonbin条目,把组件 CLI 链接进 bin 目录;写入omo运行时包装器(POSIX shell / Windows.cmd
link-cached-plugin-agents.ts发现components/*/agents/下捆绑的 Agent TOML,拷贝到~/.codex/agents/,保留既有model_reasoning_effortservice_tier,写.installed-agents.json清单
codex-marketplace-snapshot.ts把本地 marketplace 快照写入~/.codex/.tmp/marketplaces/{marketplace}/
codex-config-toml.ts改写~/.codex/config.toml:启用特性、写入 marketplace/plugin/agent/hook-trust 块、可选的自主任权限
codex-cleanup.ts卸载编排器:移除 cache、agents、config 块与项目本地残留

需要提醒的是:上表中的文件路径在规范实现仓库中全部位于 packages/omo-codex/src/install/ 下(如 codex-cache-install.ts、codex-config-toml.ts、codex-cleanup.ts 等),OpenCode 垫片目录里只有转发的薄壳,阅读源码时应以omo-codex包为准。

三、安装入口与配置项:CodexInstallOptions 全解

runCodexInstaller的默认路径解析逻辑集中在 install-codex.ts:

const repoRoot = resolve(options.repoRoot ?? findRepoRoot({ importerDir: import.meta.dir, env })) const codexHome = resolve(options.codexHome ?? env.CODEX_HOME ?? join(homedir(), ".codex")) const projectDirectory = resolve(options.projectDirectory ?? env.OMO_CODEX_PROJECT ?? process.cwd()) const binDir = resolveCodexInstallerBinDir({ binDir: options.binDir, codexHome, env }) const versionOverride = env.LAZYCODEX_DEV_VERSION?.trim() || undefined

从这段代码可以看出四个关键路径的优先级:显式参数 > 环境变量 > 默认值

  • repoRoot:安装器的工作根目录,通过findRepoRoot向上最多探测 7 层父目录,寻找同时满足packages/omo-codex/plugin/.codex-plugin/plugin.json存在的目录(见findRepoRootFromImporterisRepoRootWithCodexPlugin,install-codex.ts);也支持用OMO_WRAPPER_PACKAGE_ROOT环境变量直接指定包装包根目录。
  • codexHome:默认为~/.codex,可被CODEX_HOME覆盖,所有安装产物都落在该目录内。
  • projectDirectory:项目目录,默认取OMO_CODEX_PROJECT或当前工作目录,用于后续"项目本地 Codex 产物修复"阶段。
  • binDir:由resolveCodexInstallerBinDir解析(涉及CODEX_LOCAL_BIN_DIR等环境变量),是组件 CLI 与omo运行时包装器的落盘位置。
  • versionOverride:开发期可用LAZYCODEX_DEV_VERSION强制覆盖插件版本号。

CodexInstallOptions的完整字段(types.ts)如下:

选项类型含义
codexHomestringCodex 主目录,默认~/.codex
binDirstringCLI 链接目录,默认由resolveCodexInstallerBinDir决定
repoRootstring仓库/包装包根目录
projectDirectorystring项目目录,用于项目本地清理
platformCodexInstallPlatform目标平台,默认process.platform
env{ [key: string]: string \| undefined }环境变量快照
gitBashResolverGitBashResolverWindows 下 Git Bash 解析器(仅 win32 使用)
autonomousPermissionsboolean是否写入 Codex 自主任权限块,默认true(非 false)
reasoningstring统一的 omo 配置推理等级,覆盖捆绑目录中的model_reasoning_effortoff映射为none
astGrepInstallerRunAstGrepSkillInstallast-grep 安装器(供 LSP 类技能使用)
runCommandRunCommand命令执行器,默认为defaultRunCommand
log(message: string) => void日志回调,默认空操作

runCodexInstaller返回CodexInstallResult(types.ts):marketplaceNameinstalledInstalledPlugin[])、configPathcodexHomegitBashPathprojectCleanup

四、安装主流程:九阶段编排逐层拆解

文档给出了安装流程的完整示意,runCodexInstaller()的 9 个阶段与源码一一对应(install-codex.ts):

runCodexInstaller() 1. resolve repoRoot / codexHome / binDir / projectDirectory 2. git-bash.ts: Windows Git Bash preflight(仅探测发现,不自动 winget/system 安装) 3. codex-marketplace.ts: 读取 marketplace.json + 插件清单 4. lazycodex-version-stamp.ts: 从发行清单解析插件版本 5. 对每个 marketplace 插件: a. codex-cache-install.ts: 构建、拷贝、npm ci、改写 MCP 清单、提升到 cache b. codex-cache-bins.ts: 链接组件 CLI + omo 运行时包装器 c. link-cached-plugin-agents.ts: 拷贝 Agent TOML 到 ~/.codex/agents/ 6. codex-cache-prune.ts: 清理过期插件 + 旧 marketplace 缓存 7. codex-config-toml.ts: 改写 ~/.codex/config.toml 8. codex-project-local-cleanup-best-effort.ts: 修复项目本地 .codex/config.toml 冲突 9. Telemetry: 记录 install_completed

4.1 阶段 1-2:路径解析与 Windows Git Bash 预检

路径解析见上文第三节。Git Bash 预检只针对win32平台调用prepareGitBashForInstall(install-codex.ts),如果gitBashResolution.foundfalse,安装会直接抛出带installHint的错误。值得注意的设计是:预检是"发现优先"(discovery-first)GitBashResolutionsource字段标注了发现途径(not-required/env/program-files/program-files-x86/path),安装器只探测并报告,不会自动执行 winget 或系统级安装——这是文档明确强调的边界。

4.2 阶段 3:读取 marketplace 与插件清单

readMarketplace读取 packages/omo-codex/marketplace.json,其真实内容为:

{ "name": "sisyphuslabs", "interface": { "displayName": "Sisyphus Labs" }, "plugins": [ { "name": "omo", "source": "./plugins/omo", "category": "Developer Tools", "policy": { "installation": "AVAILABLE", "authentication": "ON_INSTALL" } } ] }

校验逻辑在 codex-marketplace.ts:name必须是非空字符串,plugins必须是数组;每个插件的source支持字符串路径或{ source: "local", path }对象,且本地路径必须以./开头、不得包含..路径穿越段(validateLocalSourcePath)。validatePathSegment则用正则^[A-Za-z0-9._+-]+$校验 marketplace 名、插件名与版本号,并拒绝...——这套校验直接作用于后续缓存目录的路径拼接,是防止路径注入的关键一环。

随后readPluginManifest读取每个插件根目录下.codex-plugin/plugin.jsonname、可选version、可选hooks),并在安装器内强制校验manifest.name === entry.name,不一致即抛错。

4.3 阶段 4:版本解析与发行清单打戳

resolveLazyCodexPluginVersion综合manifestVersionmarketplaceNamepluginName、发行清单(distribution manifest)与LAZYCODEX_DEV_VERSION覆盖值,确定最终安装版本;随后validatePathSegment(version, "plugin version")再次校验。对sisyphuslabsmarketplace 的omo插件,安装完成后还会执行stampLazyCodexPluginVersionwriteLazyCodexInstallSnapshot(install-codex.ts),并在插件根记录 binDir 位置writeInstalledCodexBinDir——源码注释解释了原因:CODEX_LOCAL_BIN_DIR常是一次性覆盖(one-shot override),卸载时无法从环境变量重新计算该位置,因此必须在安装期落盘存档。

4.4 阶段 5a:缓存安装——构建、拷贝、npm ci、改写 MCP 清单、原子提升

这是安装器的核心阶段,实现于installCachedPlugin(codex-cache-install.ts):

  1. 构建:默认先对源插件执行npm installnpm run buildmaybeRunNpmInstall/maybeRunNpmBuild,均以package.json存在为前提;buildSource: false时跳过构建并改为后续执行npm run sync:skills)。
  2. 拷贝到临时目录:目标路径为{codexHome}/plugins/cache/{marketplace}/{name}/{version},临时目录是它的兄弟目录.tmp-{basename}-{pid}-{Date.now()}。拷贝时过滤掉.gitnode_modules,并且绝不拷贝嵌套组件里的.mcp.json——因为 Codex 只从插件根目录的.mcp.json加载 MCP 服务器,嵌套清单里的相对 daemon 路径在拍平后的缓存布局中会悬空(isNestedComponentMcpManifest)。
  3. 改写本地依赖与运行时rewriteCachedPackageLocalFileDependenciesfile:本地依赖改写为缓存内路径;copyBundledMcpRuntimeDists/copyRootRuntimeDists把仓库dist/clidist/cli-node等运行时拷入;copyCanonicalPromptSourcespackages/prompts-core/prompts/ultrawork/codex.md等规范提示词固化到插件根,避免sync-skills在缓存布局下解析不到仓库相对路径。
  4. npm ci 依赖安装:改写本地依赖会令package.jsonpackage-lock.json漂移,npm ci会以 EUSAGE 中止(源码注释引用 lazycodex#137,方案归功于 oh-my-openagent#6202 的社区修复),因此:
    • 改写过依赖 → 用npm install --omit=dev --no-audit --no-fund让 npm 自行调和 lock;
    • 未改写 → 走确定性更快的npm ci --omit=dev。 同时sanitizeNpmInstallEnv会过滤掉npm_config_allow_scripts,防止脚本执行策略被意外放宽。
  5. 校验与清单改写rewriteCachedMcpManifest重写 MCP 清单、rewriteCachedManifestRoot把根路径改写为最终缓存路径;assertHookCommandTargets校验 Hook 命令目标不越界;assertNoRemovedSparkshellPromptReferences还会在.codex-pluginagentsbundled-ruleshooksskills等提示面目录中扫描已移除的 sparkshell 引用,发现即中止安装。
  6. 原子提升promoteDirectory采用"先拷临时兄弟目录 →rename()提升 → 失败恢复备份"的原子策略:已有目标先改名为.backup-*,提升失败则回滚备份,成功才删除备份(codex-cache-install.ts)。

4.5 阶段 5b:CLI 链接与 omo 运行时包装器

linkCachedPluginBins(codex-cache-bins.ts)递归扫描插件根目录下所有package.jsonbin字段(跳过node_modules.gitdist),生成链接:

  • POSIX:创建符号链接(symlink);
  • Windows:写入带COMMAND_SHIM_MARKER标记的.cmdshim(windowsCommandShim)。

其中有一组保留名RESERVED_NESTED_BIN_NAMESomoomo-agent-toolkitlazycodexlazycodex-aioh-my-opencodeoh-my-openagent——嵌套包(非插件根)声明的这些 bin 名会被跳过,避免子组件抢占顶层命令名。此外 bin 目标必须解析在包根内(resolvePackageBinTarget拒绝..越界与\0),assertSafeCommandName则拒绝空名、...、路径分隔符等非法命令名。

omo插件,还会额外执行linkRootRuntimeBin(codex-cache-bins.ts)生成omo-agent-toolkit运行时包装器:POSIX 下写 shell 包装并chmod 0o755,Windows 下写.cmd;包装器内容带RUNTIME_WRAPPER_MARKER标记,旧版omo遗留包装器会被安全移除。若仓库缺少dist/cli/index.js,安装器仅记录 warning 而不会失败。

4.6 阶段 5c:Agent 配置落盘与设置保留

linkCachedPluginAgents(link-cached-plugin-agents.ts)扫描插件根components/*/agents/下的全部*.toml,逐个拷贝到~/.codex/agents/(以拷贝而非符号链接的方式落盘),并执行两个关键的用户设置保留动作:

  • restorePreservedReasoning:安装前先用capturePreservedAgentReasoning记录用户已有的model_reasoning_effort,拷贝后写回;
  • restorePreservedServiceTier:同理保留service_tier

这是"升级不丢用户偏好"的核心机制。若存在lazycodex-worker-medium.toml,还会调用installDefaultAgentRole安装默认角色。最终把已安装 Agent 路径写入.installed-agents.json清单,供卸载阶段精确回收。文档还提示当前受管(managed)的 Codex Agent 名单为explorerlibrarianmetismomusplan

4.7 阶段 6:缓存剪枝与旧 marketplace 清理

pruneMarketplaceCache删除当前 marketplace 下不再被引用的插件版本;legacyCacheMarketplaces(install-codex.ts)在安装sisyphuslabs时会额外清理旧 marketplacelazycodexcode-yeongyu-codex-plugins的缓存。同时reapLspDaemons会尽力回收遗留的 Codex LSP daemon,失败仅记录 warning 不阻断安装。

4.8 阶段 7:config.toml 改写

updateCodexConfig(codex-config-toml.ts)是字符串级 TOML 改写(通过toml-section-editor.ts逐段编辑,不引入 TOML 解析器依赖),按顺序完成:

  1. 先移除旧 marketplace(lazycodex等)遗留的 marketplace 块、插件块与 hook 状态块,以及当前 marketplace 中过期插件的块;
  2. 移除不再受管的 Agent 配置块(removeStaleManagedAgentBlocks);
  3. 依次确保开启pluginsplugin_hooksmulti_agent特性(ensureFeatureEnabled);
  4. 移除不支持的旧版 multi-agent mode 配置,写入基于模型目录(readCodexModelCatalog)的 reasoning 配置,支持options.reasoning覆盖(offnone);
  5. 写入 multi-agent v2 配置(ensureCodexMultiAgentV2Config);
  6. autonomousPermissions !== false时写入自主任权限块(ensureAutonomousPermissions);
  7. 写入 marketplace 块(本地源,sourceType: "local",指向缓存根);
  8. 逐个启用插件({plugin}@{marketplace})与内置 MCP 策略(ensureOmoBuiltinMcpPolicies);
  9. 写入每个可信 Hook 状态的哈希(ensureHookTrusted);
  10. 写入每个 Agent 的config_file = ./agents/xxx.toml引用。

最终通过writeFileAtomic原子落盘(config.trimEnd() + "\n"),配置不存在时从空串开始构建。

4.9 阶段 8-9:项目本地修复与遥测

repairProjectLocalCodexArtifactsBestEffortprojectDirectory向上扫描,修复项目本地.codex/config.toml与全局配置的冲突——只做"尽力而为",发现遗留项目产物只记录不删除。最后trackCodexInstallTelemetry记录install_completed事件,并返回完整的CodexInstallResult

五、安装产物:WHAT IT WRITES 全表

安装完成后~/.codex/(或自定义CODEX_HOME)下的布局如下:

路径内容
~/.codex/plugins/cache/{marketplace}/{plugin}/{version}/构建完成的插件缓存(已 npm 安装、MCP 清单已改写、原子提升)
~/.codex/.tmp/marketplaces/{marketplace}/本地 marketplace 快照(插件源码拷贝 +marketplace.json
~/.codex/agents/*.toml从捆绑组件拷贝的 Agent 配置
~/.codex/config.toml被改写:marketplace 块、插件启用、特性开关、Agent 配置、hook 信任哈希、MCP 策略
~/.local/bin/(自定义 home 时为~/.codex/bin组件 CLI 的符号链接或.cmdshim +omo包装器

值得注意的是~/.local/bin/是默认 binDir(由resolveCodexInstallerBinDir决定),只有自定义 home 时才回退到~/.codex/bin

六、设计约定与反模式

文档归纳了三条必须遵守的设计约定(CONVENTIONS):

  • TOML 改写一律基于字符串:经由toml-section-editor.ts做文本级操作,刻意不引入 TOML 解析器依赖ANTI-PATTERNS第一条:Never use a real TOML parser);
  • 原子目录提升:先拷贝到临时兄弟目录再rename(),失败时恢复备份,绝不允许直接写活缓存ANTI-PATTERNS第二条:Never skip the temp-and-rename promotion);
  • 平台差异:Windows 用.cmdshim,POSIX 用符号链接。

第三条例外约束同样重要:新增受管 Agent 时,必须同步更新MANAGED_CODEX_AGENT_NAMES(同时存在于codex-config-agents.tscodex-cleanup-config.ts),否则卸载时无法精确回收对应 Agent 文件(ANTI-PATTERNS第三条:Never hardcode new agent names)。此外,文档还强调兼容性负担:保留的 legacy purge 代码仍在追踪已退役的 reviewer agent,用于清理旧版本安装残留的陈旧配置与 Agent 文件。

七、卸载:与安装严格对称的清理编排

虽然文档正文聚焦安装,其产物与约定同样定义了卸载语义。cleanupCodexLight(codex-cleanup.ts)是卸载编排器,与安装形成镜像:

  1. 先读后删:在删除任何受管目录前,先读取.installed-agents.json与安装期记录的 binDir(readInstalledCodexBinDir)——因为清单文件本身就位于将被删除的受管树内;
  2. Agent 回收:结合MANAGED_CODEX_AGENT_NAMES与清单路径(.tmp/marketplaces/sisyphuslabs/plugins/omo/.installed-agents.json及各缓存版本下的清单)收集 Agent 路径,逐条安全校验(必须在~/.codex/agents/内、文件名必须匹配受管名单)后移除;
  3. 受管状态目录:删除plugins/cache/sisyphuslabs.tmp/marketplaces/sisyphuslabsruntime/ast-grepruntime/nodeplugins/data/omo-sisyphuslabs/bootstrap,并以 glob 兜底(深度 ≤ 5)清理布局漂移的 bootstrap 目录;源码注释明确安全不变量——只删受管子树,绝不整体删除runtime/
  4. 安全校验validateManagedCleanupTarget会拒绝指向文件系统根或越界的清理目标(codex-cleanup-safety.ts),bin 链接清理同理;
  5. 项目本地修复:复用与安装相同的repairProjectLocalCodexArtifactsBestEffort
  6. 重试语义removeManagedPathBestEffort采用"单次重试"策略——正在运行的 bootstrap worker 可能在首次删除后重建状态,若重试后仍存在,命令依然以 0 退出,再次执行lazycodex-ai uninstall即可清干净。

结语

install-codex安装器的设计可以概括为三个关键词:原子性(temp-and-rename 提升与原子 config 写入)、可逆性.installed-agents.json清单 + 安装期记录的 binDir,让卸载能精确还原)、兼容性(保留旧 marketplace 清理、旧 Agent 追踪与 sparkshell 引用扫描,平滑迁移历史安装)。如果你要在自己的 Codex 环境里排查插件问题,建议按本文第三节的路径优先级检查CODEX_HOMECODEX_LOCAL_BIN_DIROMO_CODEX_PROJECT等环境变量,再对照第五节的产品表核对每个目录是否存在;若需彻底重装,则走npx lazycodex-ai uninstall,它会依据清单精确回收全部受管产物。

  • 人工智能
  • AI Agent
  • 代码智能体
  • 多智能体
  • MCP Clients
  • Agent 编排

【免费下载链接】oh-my-openagent

OmO: Just type "mass ulw" keyword with your prompt. Now you are the master of graph engineering.

项目地址:https://gitcode.com/gh_mirrors/oh/oh-my-openagent
点击查看免费下载

相关推荐

上一篇:CC Switch ccswitch:// 协议:把配置打包成一条链接,同事点一下就导入
下一篇:ClaraVerse革命性AI平台:一站式解决8大AI工具集成难题

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询