oh-my-pi 加载 Gemini CLI 的 gemini-extension.json:发现目录、JSON 有效性与遮蔽优先级 📅 发布时间:2026/9/12 21:13:23 👁 浏览次数: oh-my-pi 加载 Gemini CLI 的 gemini-extension.json发现目录、JSON 有效性与遮蔽优先级【免费下载链接】oh-my-pi⌥ Coding agent with the IDE wired in项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-pi如果你已经在用 Gemini CLI仓库或用户目录下存在.gemini/extensions/name/gemini-extension.json这类清单又想让 oh-my-pi 的 coding-agent 识别这些扩展这篇文章说明 oh-my-pi 是怎么发现、校验和去重这些清单的。oh-my-pi 内置的 Gemini providerid: geminipriority60注册了一个extensionsloader扫描两个固定根目录并把清单解析为extensionscapability 条目但清单本身只是可发现的元数据出现在.gemini/extensions下不会自动执行任何代码这一点在文末单独说明。发现目录两个根目录、只扫一层Gemini provider 的extensions发现只扫描两个根用户级~/.gemini/extensions项目级cwd/.gemini/extensions两条路径由ctx.home和ctx.cwd直接解析getUserPath()/getProjectPath()。项目级查找是cwd-only的不会向上遍历父目录所以在子目录里启动时只有该子目录自己的.gemini/extensions生效。对每个根目录扫描规则是读取根目录条目只保留直接的子目录entry.isDirectory()对每个子目录name按精确文件名读取root/name/gemini-extension.json。由此得到几条实际影响行为的边界清单放在比一层更深的嵌套里不会被发现没有递归以点开头的隐藏子目录不会被过滤只要里面有一份gemini-extension.json就会被考虑根目录不存在属于正常状态静默跳过不产生警告文件名必须恰好是gemini-extension.json其他名字的文件不参与发现。实现入口在 packages/coding-agent/src/discovery/gemini.ts 的loadExtensionsFromDir()完整规则见 docs/gemini-manifest-extensions.md。JSON 有效性唯一硬门槛是解析后为 truthy能力类型定义的清单形状是interface ExtensionManifest { name?: string; description?: string; mcpServers?: Recordstring, OmitMCPServer, name | _source; tools?: unknown[]; context?: unknown; }发现阶段的检查故意宽松。唯一的硬门槛是文件非空且tryParseJson()返回 truthy 值。通过这道门之后不对字段类型或内容做任何运行时 schema 校验解析结果整体存为 capability 条目的manifest字段注册表级别对extensions的校验只检查name和path是否存在。什么会触发警告以下情况走同一条警告路径格式为Invalid JSON in manifestPath其中manifestPath是清单文件的绝对路径由createSourceMeta()规范化。会触发这条警告的包括JSON 语法错误语法合法但值为 falsy 的 JSON 字面量null、false、0、。也就是说一个内容恰好是null或0的清单文件和写坏 JSON 的效果一样——被跳过并告警。什么会被静默跳过以下情况不产生任何警告extensions根目录缺失子目录里没有gemini-extension.json清单文件不可读或为空清单 JSON 是 truthy 但语义上不完整、不合理例如空对象{}也是 truthy会通过这道门。语义有效性不被强制警告门就是tryParseJson()的真值判断而不是一个ExtensionManifest运行时校验器。name 的归一化capability 条目的name取值规则manifest.name非null/undefined时用它否则回退为扩展目录名。这里不做字符串类型检查。因此清单里省略name或name为null时条目名就是目录名。遮蔽优先级同名单条谁胜出extensionscapability 由能力注册表跨 provider 聚合去重键是ext.nameextensionCapability.key ext ext.name。当前参与该 capability 的相关 providernativepackages/coding-agent/src/discovery/builtin.tspriority100geminipriority60。跨 provider高优先级胜出重名时高优先级 provider 胜出。文档给出的例子如果native和gemini都产出扩展名foo保留的是 native 条目低优先级的重复项只保留在result.all中并带_shadowed true标记。一个容易踩中的具体情形native provider 也会从.omp目录读取extensions/name/gemini-extension.json见 docs/config-usage.md 的 native provider 小节。如果你的项目同时存在.omp/extensions/foo/gemini-extension.json和.gemini/extensions/foo/gemini-extension.json且name相同生效的是.omp侧的 native 条目Gemini 侧的被遮蔽。Gemini provider 内部user 先于 project去重是first seen wins所以 provider 内部的条目顺序有影响。Gemini loader 追加顺序是user 根在前、project 根在后loadExtensions()先处理~/.gemini/extensions再处理cwd/.gemini/extensions。因此同名的 user 条目会胜出遮蔽 project 条目。对照native provider 内部构造配置目录的顺序是 project 在前、user 在后方向恰好相反。汇总成四格冲突双方保留条目被遮蔽条目的去向native (100) vs gemini (60) 同名nativegemini 条目留在result.all_shadowed truegemini user 根 vs gemini project 根 同名userproject 条目被遮蔽native 自身 project vs user 同名project与 gemini 方向相反user 条目被遮蔽不同名都保留不涉及边界清单不是可执行入口gemini-extension.json的发现只供给extensions元数据 capability它不标识一个可运行的 TS/JS 入口。Gemini provider 会另外扫描同样的两个扩展根目录来填充extension-modulecapability直接.ts/.js文件、name/index.ts/index.js、以及package.json的omp/pi扩展条目这些模块记录与gemini-extension.json相互独立。但环境启动路径discoverExtensionPaths()目前只请求nativeprovider所以 Gemini 发现的模块记录不会在那里被自动执行显式配置的扩展路径仍然可以被加载。实际含义一份 Gemini 清单只是可发现的元数据清单本身和同目录下的模块都不会仅因为出现在.gemini/extensions下就自动执行。如果你需要真正运行代码走显式配置路径CLI 的-e/--extension或设置里的extensions数组机制见 docs/extension-loading.md--no-extensions只关闭环境发现显式-e路径仍会加载。结果判断按警告与静默清单核对没有独立命令输出这份清单时判断依据是文档定义的警告语义本身看到Invalid JSON in manifestPath对应路径的清单是语法错误 JSON或内容是null/false/0/这类 falsy 字面量。修好 JSON 后该条目才会进入发现结果没有任何警告且条目未生效先核对是否落入静默跳过清单——目录嵌套超过一层、文件名不是gemini-extension.json、文件为空或不可读、启动目录不是你以为的cwd项目根不向上遍历条目存在但内容不对确认你看到的条目来自哪个 provider。同名下 native 遮蔽 gemini、user 遮蔽 project被遮蔽的 Gemini 条目仍带_shadowed true留在result.all中。相关文档Gemini Manifest Extensions、Extension Loading、config-usage.md 的 provider 优先级与去重语义。【免费下载链接】oh-my-pi⌥ Coding agent with the IDE wired in项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-pi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考