DirectProject 客户端 Skill 自然语言触发能力缺口 #236

Open
opened 2026-09-01 13:47:19 +08:00 by lhk229 · 1 comment
Owner

DirectProject 客户端 Skill 自然语言触发能力缺口

1. 问题摘要

AGC 已经可以把用户导入的 Skill 安装到客户端,并在下一次 DirectProject 启动时注入真实 Codex app-server。使用 Codex 原生的 $skill-name 形式时,导入的 Skill 可以被读取并执行。

目前缺少的是:用户在普通自然语言中直接提到 Skill 名称时,AGC 没有把这次请求确定性地绑定为 Codex 的 Skill 输入项。结果是模型可能只看到用户提到了一个名称,并把“调用 Skill”误解成调用一个工具,返回“没有可调用接口”,而不是读取 SKILL.md

这不是 Skill 导入失败,也不是需要把 Skill 改造成 MCP 工具;是 AGC 客户端没有复用 Codex 官方客户端的 Skill 输入适配层。

2. 当前 AGC 如何使用 Skill

2.1 客户端导入

用户在客户端设置的“扩展”页面导入文件、目录或 zip。目录或 zip 中发现的每个 SKILL.md 会成为独立的 Skill 扩展项,可以单独启用、禁用、重命名和删除。

已识别的 Skill 导入后默认启用。扩展内容保存于 AGC 客户端扩展仓库,不直接写入用户全局 CODEX_HOME

2.2 DirectProject 启动时注入

创建或复用 DirectProject 的 Codex app-server 时,AGC 会:

  1. 读取客户端扩展索引中 enabled=true 的 Skill;
  2. 在本次隔离运行的临时 HOME 下创建客户端 Skill root;
  3. 将每个 Skill 的运行时副本复制到该目录;
  4. 对手动重命名的 Skill,只在运行时副本的 frontmatter 中使用当前名称;
  5. 调用 Codex app-server 的 skills/extraRoots/set
  6. 调用 skills/list 重新发现 Skill。

AGC 侧的运行时目录准备位于 client_extensions.rsprepare_enabled_client_skill_root,app-server 的 Skill root 注册位于 codex_app_server.rs

Skill 配置从下一次 DirectProject 启动生效,当前已经运行的 Codex 会话不热更新。首页的 DirectHome 不作为客户端 Skill 的运行时入口。

2.3 当前可用的触发方式

Codex 原生显式触发方式是:

$import-smoke-skill 请只回复一行结果。

这个方式已经在 AGC 中验证成功,测试 Skill 返回:

SKILL_IMPORT_OK

这证明导入、启用、运行时 Skill root 注入、Codex 发现和 Skill 正文执行链路已经打通。

3. 当前缺少的能力

3.1 普通自然语言名称没有确定性绑定

以下输入目前不能稳定触发导入的 Skill:

请调用 import-smoke-skill skill。
请明确使用 import-smoke-skill。

实际结果是模型报告“当前没有可调用该 Skill 的工具接口”。这句话在“Skill 不是工具”这一点上没有错,但没有完成 Skill 指令的读取和应用。

3.2 AGC 没有发送结构化 Skill 输入项

Codex 官方 TUI 在识别 $skill-name 或用户从 Skill 提及菜单选择后,会向 turn/start 输入中追加类似内容:

{
  "type": "skill",
  "name": "import-smoke-skill",
  "path": ".../SKILL.md"
}

对应实现见 Codex 仓库中的 codex-rs/tui/src/chatwidget/input_submission.rs。随后 Codex core 会根据结构化输入加载 Skill 正文。

AGC 当前的 codex_app_server_turn_input 只把用户消息整理成普通文本和图片输入,没有追加 type: "skill" 项。

3.3 “能发现”与“本轮已使用”没有明确的客户端绑定

AGC 启动时会设置 skills/extraRoots 并调用 skills/list,这只能证明 Skill 在当前 app-server 进程的发现范围内。它不等于本轮已经选中了某个 Skill,也不等于模型一定会读取该 Skill 的正文。

Codex 的 Skill 扩展会把可用 Skill 目录和使用规则放入模型上下文,但普通文本相关性判断主要交给模型;它不是 AGC 客户端已经完成的确定性绑定。

4. Codex 源码中的相关分层

4.1 模型侧使用规则

Codex 仓库中的 codex-rs/ext/skills/src/catalog_prompt.rs 会向模型说明:用户用 $SkillName 或普通文本点名 Skill,或者任务符合 Skill 描述时,应使用该 Skill。

这是一条模型行为指令,不是一个保证命中的 if user_text.contains(...) 路由器。普通自然语言是否命中,仍取决于模型能否看到对应目录、是否理解名称和描述,以及是否调用 skills.read

4.2 显式 Skill 选择

Codex 仓库中的 codex-rs/ext/skills/src/selection.rs 会处理结构化 UserInput::Skill,也会解析文本中的 $skill-name。选中后,core 在回合开始阶段读取并注入 Skill 正文。

4.3 “隐式 Skill”不是普通自然语言路由

源码中的 implicit invocation 主要用于命令或脚本访问某个 Skill 的资源目录时记录/识别对应 Skill,入口在 Codex 仓库的 codex-rs/ext/skills/src/invocation.rs。它不是一个根据任意用户自然语言自动选择 Skill 的通用分类器。

4.4 相关性选择实验不是当前确定性注入

Codex 的 shadow_selection / skill_search 相关实现会对任务和 Skill 描述做词法/相关性排序,但当前是 shadow 观测路径,不直接替当前回合注入 Skill,不能作为 AGC 当前缺口的现成解决方案。

5. 复现步骤

准备一个普通的 Skill 导入目录,目录中放置一个 SKILL.md。例如:

---
name: import-smoke-skill
description: 用于验证客户端导入和加载 Skill 的最小测试 Skill。
---

当用户明确要求使用 `import-smoke-skill` 时,先单独输出一行 `SKILL_IMPORT_OK`,再继续回答用户的问题。

该目录和文件可以由 Issue 提交者在自己的测试环境中临时创建,不依赖仓库外的固定目录或本机产物。

复现:

  1. 在客户端“扩展”中导入包含上述 SKILL.md 的目录;

  2. 确认列表显示 import-smoke-skill、类型为 Skill、状态为“已启用”;

  3. 新开一个 DirectProject 会话;

  4. 依次发送:

    请调用 import-smoke-skill skill,如果找不到这个skill,不要伪造结果。
    
    请明确使用 import-smoke-skill,只回复一行结果。
    
    $import-smoke-skill 请只回复一行结果。
    

预期现象:前两条不会稳定加载 Skill,第三条返回 SKILL_IMPORT_OK

6. 可能的修复方向

以下只是供 Issue 讨论的候选方向,不在本文锁定具体实现。

方向 A:客户端显式绑定用户点名的 Skill

AGC 在发送回合前,根据当前已启用 Skill 列表识别用户明确提到的名称,并把匹配项转换成 Codex 原生的 type: "skill" 输入项,同时保留原始用户文本。

优点是行为确定、与官方 TUI 的协议一致;需要讨论名称边界、重名处理和用户文本中普通单词与 Skill 名称的冲突。

方向 B:增加 Skill 提及选择入口

在聊天输入框提供 Skill 名称补全或选择入口。用户选择后,客户端保存/发送结构化 Skill 绑定,而不是要求用户手写 $

优点是用户不需要了解 Codex 协议标记;需要额外的前端交互设计,且要决定是否在 DirectProject 聊天区增加入口。

方向 C:仅支持 Codex 原生 $skill-name

保持当前实现,只把 $skill-name 作为 Skill 的正式调用方式,并在测试和使用说明中明确这一点。

优点是改动最小;缺点是用户需要知道 Codex 的 Skill 提及语法,普通中文“请使用某 Skill”仍不会得到确定性支持。

方向 D:依赖模型根据 Skill 目录自行判断

让 Skill 目录和描述保持模型可见,由模型在普通任务中自行判断是否需要调用 skills.read

这种方式可以覆盖“任务适合某 Skill”而不仅是精确名称,但结果受模型判断和上下文影响,不适合作为“用户明确点名后必须使用”的唯一保证。

7. Issue 建议关注点

提 Issue 时建议先确认产品契约,而不是直接指定实现:

  • “用户普通中文提到已启用 Skill 名称”是否必须确定性生效;
  • 是否接受用户使用 Codex 原生 $skill-name
  • 是否需要聊天输入框提供 Skill 选择/补全;
  • Skill 名称与 MCP Server 名称冲突时,客户端按哪类扩展解析;
  • 没有找到匹配 Skill 时,是否只给出说明并继续普通对话;
  • 是否需要在回合记录或状态 UI 中展示本轮实际注入了哪些 Skill。

本 Issue 不应扩大为:重新设计 Skill/MCP 导入格式、把 Skill 做成 MCP 工具、增加第三方内容安全扫描、增加脚本沙箱,或重做 Codex Plugin Runtime。

# DirectProject 客户端 Skill 自然语言触发能力缺口 ## 1. 问题摘要 AGC 已经可以把用户导入的 Skill 安装到客户端,并在下一次 DirectProject 启动时注入真实 Codex app-server。使用 Codex 原生的 `$skill-name` 形式时,导入的 Skill 可以被读取并执行。 目前缺少的是:用户在普通自然语言中直接提到 Skill 名称时,AGC 没有把这次请求确定性地绑定为 Codex 的 Skill 输入项。结果是模型可能只看到用户提到了一个名称,并把“调用 Skill”误解成调用一个工具,返回“没有可调用接口”,而不是读取 `SKILL.md`。 这不是 Skill 导入失败,也不是需要把 Skill 改造成 MCP 工具;是 AGC 客户端没有复用 Codex 官方客户端的 Skill 输入适配层。 ## 2. 当前 AGC 如何使用 Skill ### 2.1 客户端导入 用户在客户端设置的“扩展”页面导入文件、目录或 zip。目录或 zip 中发现的每个 `SKILL.md` 会成为独立的 Skill 扩展项,可以单独启用、禁用、重命名和删除。 已识别的 Skill 导入后默认启用。扩展内容保存于 AGC 客户端扩展仓库,不直接写入用户全局 `CODEX_HOME`。 ### 2.2 DirectProject 启动时注入 创建或复用 DirectProject 的 Codex app-server 时,AGC 会: 1. 读取客户端扩展索引中 `enabled=true` 的 Skill; 2. 在本次隔离运行的临时 HOME 下创建客户端 Skill root; 3. 将每个 Skill 的运行时副本复制到该目录; 4. 对手动重命名的 Skill,只在运行时副本的 frontmatter 中使用当前名称; 5. 调用 Codex app-server 的 `skills/extraRoots/set`; 6. 调用 `skills/list` 重新发现 Skill。 AGC 侧的运行时目录准备位于 [`client_extensions.rs`](../../apps/ai-game-creator-shell/src-tauri/src/client_extensions.rs) 的 `prepare_enabled_client_skill_root`,app-server 的 Skill root 注册位于 [`codex_app_server.rs`](../../apps/ai-game-creator-shell/src-tauri/src/agent/codex_app_server.rs)。 Skill 配置从下一次 DirectProject 启动生效,当前已经运行的 Codex 会话不热更新。首页的 DirectHome 不作为客户端 Skill 的运行时入口。 ### 2.3 当前可用的触发方式 Codex 原生显式触发方式是: ```text $import-smoke-skill 请只回复一行结果。 ``` 这个方式已经在 AGC 中验证成功,测试 Skill 返回: ```text SKILL_IMPORT_OK ``` 这证明导入、启用、运行时 Skill root 注入、Codex 发现和 Skill 正文执行链路已经打通。 ## 3. 当前缺少的能力 ### 3.1 普通自然语言名称没有确定性绑定 以下输入目前不能稳定触发导入的 Skill: ```text 请调用 import-smoke-skill skill。 ``` ```text 请明确使用 import-smoke-skill。 ``` 实际结果是模型报告“当前没有可调用该 Skill 的工具接口”。这句话在“Skill 不是工具”这一点上没有错,但没有完成 Skill 指令的读取和应用。 ### 3.2 AGC 没有发送结构化 Skill 输入项 Codex 官方 TUI 在识别 `$skill-name` 或用户从 Skill 提及菜单选择后,会向 `turn/start` 输入中追加类似内容: ```json { "type": "skill", "name": "import-smoke-skill", "path": ".../SKILL.md" } ``` 对应实现见 Codex 仓库中的 `codex-rs/tui/src/chatwidget/input_submission.rs`。随后 Codex core 会根据结构化输入加载 Skill 正文。 AGC 当前的 [`codex_app_server_turn_input`](../../apps/ai-game-creator-shell/src-tauri/src/agent/codex_app_server.rs) 只把用户消息整理成普通文本和图片输入,没有追加 `type: "skill"` 项。 ### 3.3 “能发现”与“本轮已使用”没有明确的客户端绑定 AGC 启动时会设置 `skills/extraRoots` 并调用 `skills/list`,这只能证明 Skill 在当前 app-server 进程的发现范围内。它不等于本轮已经选中了某个 Skill,也不等于模型一定会读取该 Skill 的正文。 Codex 的 Skill 扩展会把可用 Skill 目录和使用规则放入模型上下文,但普通文本相关性判断主要交给模型;它不是 AGC 客户端已经完成的确定性绑定。 ## 4. Codex 源码中的相关分层 ### 4.1 模型侧使用规则 Codex 仓库中的 `codex-rs/ext/skills/src/catalog_prompt.rs` 会向模型说明:用户用 `$SkillName` 或普通文本点名 Skill,或者任务符合 Skill 描述时,应使用该 Skill。 这是一条模型行为指令,不是一个保证命中的 `if user_text.contains(...)` 路由器。普通自然语言是否命中,仍取决于模型能否看到对应目录、是否理解名称和描述,以及是否调用 `skills.read`。 ### 4.2 显式 Skill 选择 Codex 仓库中的 `codex-rs/ext/skills/src/selection.rs` 会处理结构化 `UserInput::Skill`,也会解析文本中的 `$skill-name`。选中后,core 在回合开始阶段读取并注入 Skill 正文。 ### 4.3 “隐式 Skill”不是普通自然语言路由 源码中的 `implicit invocation` 主要用于命令或脚本访问某个 Skill 的资源目录时记录/识别对应 Skill,入口在 Codex 仓库的 `codex-rs/ext/skills/src/invocation.rs`。它不是一个根据任意用户自然语言自动选择 Skill 的通用分类器。 ### 4.4 相关性选择实验不是当前确定性注入 Codex 的 `shadow_selection` / `skill_search` 相关实现会对任务和 Skill 描述做词法/相关性排序,但当前是 shadow 观测路径,不直接替当前回合注入 Skill,不能作为 AGC 当前缺口的现成解决方案。 ## 5. 复现步骤 准备一个普通的 Skill 导入目录,目录中放置一个 `SKILL.md`。例如: ```markdown --- name: import-smoke-skill description: 用于验证客户端导入和加载 Skill 的最小测试 Skill。 --- 当用户明确要求使用 `import-smoke-skill` 时,先单独输出一行 `SKILL_IMPORT_OK`,再继续回答用户的问题。 ``` 该目录和文件可以由 Issue 提交者在自己的测试环境中临时创建,不依赖仓库外的固定目录或本机产物。 复现: 1. 在客户端“扩展”中导入包含上述 `SKILL.md` 的目录; 2. 确认列表显示 `import-smoke-skill`、类型为 Skill、状态为“已启用”; 3. 新开一个 DirectProject 会话; 4. 依次发送: ```text 请调用 import-smoke-skill skill,如果找不到这个skill,不要伪造结果。 ``` ```text 请明确使用 import-smoke-skill,只回复一行结果。 ``` ```text $import-smoke-skill 请只回复一行结果。 ``` 预期现象:前两条不会稳定加载 Skill,第三条返回 `SKILL_IMPORT_OK`。 ## 6. 可能的修复方向 以下只是供 Issue 讨论的候选方向,不在本文锁定具体实现。 ### 方向 A:客户端显式绑定用户点名的 Skill AGC 在发送回合前,根据当前已启用 Skill 列表识别用户明确提到的名称,并把匹配项转换成 Codex 原生的 `type: "skill"` 输入项,同时保留原始用户文本。 优点是行为确定、与官方 TUI 的协议一致;需要讨论名称边界、重名处理和用户文本中普通单词与 Skill 名称的冲突。 ### 方向 B:增加 Skill 提及选择入口 在聊天输入框提供 Skill 名称补全或选择入口。用户选择后,客户端保存/发送结构化 Skill 绑定,而不是要求用户手写 `$`。 优点是用户不需要了解 Codex 协议标记;需要额外的前端交互设计,且要决定是否在 DirectProject 聊天区增加入口。 ### 方向 C:仅支持 Codex 原生 `$skill-name` 保持当前实现,只把 `$skill-name` 作为 Skill 的正式调用方式,并在测试和使用说明中明确这一点。 优点是改动最小;缺点是用户需要知道 Codex 的 Skill 提及语法,普通中文“请使用某 Skill”仍不会得到确定性支持。 ### 方向 D:依赖模型根据 Skill 目录自行判断 让 Skill 目录和描述保持模型可见,由模型在普通任务中自行判断是否需要调用 `skills.read`。 这种方式可以覆盖“任务适合某 Skill”而不仅是精确名称,但结果受模型判断和上下文影响,不适合作为“用户明确点名后必须使用”的唯一保证。 ## 7. Issue 建议关注点 提 Issue 时建议先确认产品契约,而不是直接指定实现: - “用户普通中文提到已启用 Skill 名称”是否必须确定性生效; - 是否接受用户使用 Codex 原生 `$skill-name`; - 是否需要聊天输入框提供 Skill 选择/补全; - Skill 名称与 MCP Server 名称冲突时,客户端按哪类扩展解析; - 没有找到匹配 Skill 时,是否只给出说明并继续普通对话; - 是否需要在回合记录或状态 UI 中展示本轮实际注入了哪些 Skill。 本 Issue 不应扩大为:重新设计 Skill/MCP 导入格式、把 Skill 做成 MCP 工具、增加第三方内容安全扫描、增加脚本沙箱,或重做 Codex Plugin Runtime。
kdletters added the Kind/Feature label 2026-09-07 15:27:10 +08:00
Member

This was generated by AI during triage.

Issue 已经把“发现 Skill”和“本轮确定使用 Skill”区分清楚,建议把方向 A 作为默认产品契约:普通中文明确点名已启用 Skill 时,客户端按启用清单做名称匹配并生成 Codex 原生的结构化 skill 输入,同时保留原始用户文本;单纯依赖模型相关性判断不能作为确定性保证。

实现前请锁定边界:手动重命名后的精确匹配与规范化规则、重名 Skill 的处理、禁用/未找到时的提示和普通对话回退、与 MCP Server 同名时的解析优先级,以及是否在回合记录/UI 展示本轮实际注入的 Skill。回归用例应同时覆盖普通中文点名、原生 $skill-name、名称出现在普通句子但未明确要求使用、找不到 Skill 和重启后新 DirectProject 会话;不要把 Skill 改造成 MCP 工具。

> *This was generated by AI during triage.* Issue 已经把“发现 Skill”和“本轮确定使用 Skill”区分清楚,建议把方向 A 作为默认产品契约:普通中文明确点名已启用 Skill 时,客户端按启用清单做名称匹配并生成 Codex 原生的结构化 skill 输入,同时保留原始用户文本;单纯依赖模型相关性判断不能作为确定性保证。 实现前请锁定边界:手动重命名后的精确匹配与规范化规则、重名 Skill 的处理、禁用/未找到时的提示和普通对话回退、与 MCP Server 同名时的解析优先级,以及是否在回合记录/UI 展示本轮实际注入的 Skill。回归用例应同时覆盖普通中文点名、原生 $skill-name、名称出现在普通句子但未明确要求使用、找不到 Skill 和重启后新 DirectProject 会话;不要把 Skill 改造成 MCP 工具。
Sign in to join this conversation.
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: GenarrativeAI/Genarrative#236