CodeCompanion.nvim 工具 API 升级指南:从 v18 位置参数到 v19 结构化 meta 表的全面迁移
2026/9/17 21:28:35 网站建设 项目流程

CodeCompanion.nvim 工具 API 升级指南:从 v18 位置参数到 v19 结构化 meta 表的全面迁移

【免费下载链接】codecompanion.nvim✨ AI Coding, Vim Style项目地址: https://gitcode.com/GitHub_Trending/co/codecompanion.nvim

导读

CodeCompanion.nvim 在 v19 版本中对自定义工具(Tools)的 API 做了系统性重构:所有工具函数与回调的位置参数被替换为结构化 tableopts/meta)。本指南以仓库内置升级提示词 tools.md 为主体,结合 orchestrator.lua、runner.lua、cmd_tool.lua 等源码实现,带你逐项完成cmdsoutputhandlers三类函数签名的迁移。读完本文,你将能把任何基于 v18 签名编写的自定义工具平滑升级到 v19 API,且不改变任何业务逻辑。

一、升级背景与核心原则

该文档是 CodeCompanion.nvim 内置提示词库(prompt library)中的一个升级提示词(Upgrade Tools),定位是让 LLM 帮助用户把自定义工具从 v18 迁移到 v19。其 frontmatter 定义了关键元数据:

--- name: Upgrade Tools interaction: chat description: Upgrade Tools from v18 to v19 opts: is_slash_cmd: false stop_context_insertion: true ---

从 markdown.lua 的解析逻辑可知,interaction: chat表示它作为聊天交互提示词加载,description会展示在提示词库选择器中,opts.stop_context_insertion: true则指示在插入该提示词时不自动注入额外的编辑器上下文。当前仓库版本号为 version.txt 中的19.22.0,正好落在 v19 系列。

迁移的核心原则只有一句话:位置参数被结构化 table 取代。

  • 凡是原来通过第 3、4 个位置参数传递的inputcbtoolscmdstdoutstderropts,现在都收纳进optsmeta表;
  • 迁移时只改函数签名与参数访问方式,不改动任何业务逻辑
  • 原来写tools.chat的地方,一律改为meta.tools.chat

二、cmds函数签名迁移

cmds表中的每一项可以是命令数组(基于vim.system的异步命令),也可以是函数型工具。函数型工具在执行时由 runner.lua 统一以tool_cmd(self, args, opts)的形式调用,其中opts由 Runner 注入三个字段:

{ input = args.input, -- 上一个命令/函数传递下来的输出 output_cb = output_handler, -- 异步回调,提交结果给 Orchestrator register_job = function(job) end, -- 注册 vim.SystemObj 以便取消 }

2.1 同步工具(签名变化仅属"美观")

同步工具直接return一个结果表,v19 中签名的第三个参数从input改为opts。对于不使用inputoutput_cb的同步工具,这只是参数重命名:

-- OLD: function(self, args, input) -- NEW(同步工具保持不变): function(self, args, opts) -- opts 包含: { input = any, output_cb = fun(msg: table) } -- 返回: { status = "success"|"error", data = string }

例如 doc/extending/tools.md 中的计算器工具,同步函数体完全不变,只是参数名从input换成opts

cmds = { function(self, args, opts) local num1 = tonumber(args.num1) local num2 = tonumber(args.num2) -- ... 校验与计算逻辑不变 ... return { status = "success", data = result } end, },

2.2 异步工具(必须从回调迁移到opts.output_cb

异步工具原来通过第 4 个位置参数拿到回调函数,v19 中回调统一从opts.output_cb获取:

-- OLD: function(self, args, _, cb) cb({ status = "success", data = result }) end -- NEW: function(self, args, opts) local cb = opts.output_cb cb({ status = "success", data = result }) end

从源码看,runner.lua 的output_handler有两条硬性约束,迁移后依然适用:

  1. output_cb只能被调用一次,第二次调用会被tool_finished标记直接丢弃;
  2. 一个工具函数要么同步return结果表,要么调用opts.output_cb,二者不可同时使用——同时使用的结果是未定义的,因为无法保证哪个输出先被处理。

2.3 连续命令(Consecutive cmds)

cmds中多个函数会串行执行,前一个的输出会作为下一个函数的输入。v18 中前一个输出通过第 3 个位置参数传入,v19 中改从opts.input读取:

-- OLD: 第二个函数收到前一个输出作为第 3 个位置参数 function(self, args, input) -- NEW: 前一个输出在 opts.input 中 function(self, args, opts) local input = opts.input end

这条链路在源码中由 Runner 维护:Runner:go_to_next_tool(output)会把上一个函数的输出透传给下一个 Runner 实例的input(见 runner.lua)。

三、output回调签名迁移

output表负责在每次命令/函数执行后格式化并回写结果。Orchestrator 在 orchestrator.lua 中统一包装这些回调,迁移后回调参数结构如下:

回调OLD 签名NEW 签名meta 内容
success(self, tools, cmd, stdout)(self, stdout, meta){ tools, cmd }
error(self, tools, cmd, stderr)(self, stderr, meta){ tools, cmd }
rejected(self, tools, cmd, opts)(self, meta){ tools, cmd, opts }
prompt(self, tools)(self, meta){ tools }
cmd_string(self, tools)(self, meta){ tools }
cancelled(self, tools, cmd)(self, meta){ tools, cmd }

3.1successerror

stdout/stderr从第 4 个位置参数提前到第 2 个参数,原来用于取 chat 引用的tools收敛进meta.tools

-- OLD: success = function(self, tools, cmd, stdout) local chat = tools.chat -- NEW: success = function(self, stdout, meta) local chat = meta.tools.chat -- meta.cmd 在需要时也可用
-- OLD: error = function(self, tools, cmd, stderr) local chat = tools.chat -- NEW: error = function(self, stderr, meta) local chat = meta.tools.chat

注意 Orchestrator 在调用success/error时,若stdout/stderr为空表,会传入nil(见 orchestrator.lua 与#L244-L249),迁移后应保留对空值的防御处理。

3.2rejected(变化最大)

rejected是迁移中差异最明显的回调:v18 需要自行拼装{ tools, message }传给helpers.rejected,v19 中meta已经天然携带{ tools, cmd, opts },只需把自定义message合并进 meta 再转发:

-- OLD: rejected = function(self, tools, cmd, opts) helpers.rejected(self, { tools = tools, message = "..." }) -- NEW: rejected = function(self, meta) -- meta 已经包含 { tools, cmd, opts } local message = "The user rejected ..." meta = vim.tbl_extend("force", { message = message }, meta or {}) helpers.rejected(self, meta) end

这套新写法在仓库内置工厂 cmd_tool.lua 中就是标准实现:

rejected = function(self, meta) local message = fmt("The user rejected the execution of the `%s` tool", spec.name) meta = vim.tbl_extend("force", { message = message }, meta or {}) helpers.rejected(self, meta) end

helpers.rejected本身在 v19 中的签名是(self, opts),其中opts = { tools, message, reason }。Orchestrator 在用户拒绝时会把用户填写的拒绝理由通过opts.reason传入output.rejected(self.tool, { cmd = cmd, tools = self.tools, opts = opts })(见 orchestrator.lua),因此meta.opts.reason可以在迁移后用于携带拒绝理由。

3.3promptcmd_string

这两个回调原来只接收tools一个位置参数,现在统一接收meta = { tools }

-- OLD: prompt = function(self, tools) -- NEW: prompt = function(self, meta) -- meta 包含 { tools }
-- OLD: cmd_string = function(self, tools) -- NEW: cmd_string = function(self, meta) -- meta 包含 { tools }

prompt的返回值用于审批弹窗文案——Orchestrator 在_prompt_for_approval中调用self.output.prompt(),若返回空则回退到默认文案Run the %q tool?(见 orchestrator.lua)。cmd_string则用于审批与 YOLO 模式下的命令展示及命令级审批缓存 key。

3.4cancelled

-- OLD: cancelled = function(self, tools, cmd) local chat = tools.chat -- NEW: cancelled = function(self, meta) local chat = meta.tools.chat -- meta.cmd 也可用 end

该回调在用户取消执行、取消待执行队列(cancel_pending_tools)以及工具被中断时触发(见 orchestrator.lua)。若工具未定义cancelled,Orchestrator 会向 chat 写入默认文案The user cancelled the execution of the %s tool

四、handlers回调签名迁移

handlers表控制工具生命周期:setupcmds/output执行之前调用(常用来动态生成cmds),on_exit之后调用,prompt_condition用于决定是否需要弹出审批。三者统一从(self, tools)迁移为(self, meta)

-- OLD: setup = function(self, tools) -- NEW: setup = function(self, meta) -- meta 包含 { tools }
-- OLD: on_exit = function(self, tools) -- NEW: on_exit = function(self, meta) -- meta 包含 { tools }
-- OLD: prompt_condition = function(self, tools) -- NEW: prompt_condition = function(self, meta) -- meta 包含 { tools }

源码侧,Orchestrator 在_setup_handlers中正是以{ tools = self.tools }作为 meta 调用这三个回调(见 orchestrator.lua)。setupsetup_next_tool中会提前调用,以便run_commandcmd_tool这类工具在真正执行前动态填充cmds——这也是迁移后setup必须能访问meta.tools以读写工具状态的原因。

五、迁移模式速查

升级提示词在结尾给出了完整的模式总结,这是迁移任何工具时可直接对照的清单:

  • cmds函数:(self, args, opts),其中opts = { input, output_cb }
  • output.success/output.error(self, stdout_or_stderr, meta),其中meta = { tools, cmd }
  • output.rejected(self, meta),其中meta = { tools, cmd, opts }
  • output.prompt/output.cmd_string(self, meta),其中meta = { tools }
  • output.cancelled(self, meta),其中meta = { tools, cmd }
  • handlers.setup/handlers.on_exit/handlers.prompt_condition(self, meta),其中meta = { tools }
  • helpers.rejected(self, opts),其中opts = { tools, message, reason }

全局规则:任何原来访问tools.chat的地方,迁移后统一写成meta.tools.chat

六、源码视角:迁移后的调用链长什么样

结合源码可以完整还原 v19 的调用链,帮助你验证迁移是否正确:

  1. 解析与入队:tools/init.lua 的Tools:execute解析 LLM 返回的工具调用,经_resolve_and_prepare_tool深度拷贝工具定义、解析args(字符串参数会经vim.json.decode转为 Lua 表)、合并opts,然后压入 Orchestrator 队列;
  2. 生命周期回调:Orchestrator 依次执行handlers.setup()(可能动态改写cmds)→ 审批流程(output.prompt/cmd_string,必要时rejected/cancelled)→Runner逐条执行cmds
  3. 执行与回写:runner.lua 以(self, args, { input, output_cb, register_job })调用每个函数型cmd,同步return或异步output_cb的结果进入output.success/output.error,最终通过meta.tools.chat:add_tool_output(...)写回聊天缓冲;
  4. 收尾:所有cmds执行完毕后调用handlers.on_exit(),触发ToolFinished/ToolsFinished事件。

仓库内置的 cmd_tool.lua 是一个完全采用 v19 新签名的参考实现:它的handlers.setup(self, meta)在 setup 阶段调用spec.build_cmd(self.args)动态构造命令,output.cmd_string(self, meta)供审批展示,output.rejected(self, meta)采用vim.tbl_extend("force", ...)合并 message 后转发给helpers.rejected。迁移自定义工具时,对照它的写法即可确认签名是否正确。

七、如何使用这份升级提示词

该文件是提示词库的 Markdown 格式,会被 markdown.lua 解析:YAML frontmatter 提供元数据,## user之后的正文作为用户消息注入聊天。其中#{buffer}是运行时占位符,会被替换为当前缓冲区的引用——即提示词所指向的"待升级工具"所在文件。

使用流程(无需手动修改本仓库文件):

  1. 在 CodeCompanion chat buffer 中打开提示词库选择器(<leader>ap调出 Action Palette 后选择 Prompt Library,或通过 prompt-library 文档 描述的方式调用);
  2. 选择Upgrade Tools(v18 → v19)提示词;
  3. 将你的自定义工具代码粘贴进当前缓冲区,或确保#{buffer}指向包含工具定义的文件;
  4. 发送消息,让 LLM 仅修改函数签名与参数访问方式,保持业务逻辑不变;
  5. 对照上文第五节速查表人工复核改动。

八、迁移检查清单

最后,整理一份可直接执行的迁移自检清单:

  • cmds中所有函数第 3 个参数统一为opts;使用异步回调的改为opts.output_cb
  • 连续命令中读取前置输出的位置改为opts.input
  • output.success/output.error改为(self, stdout/stderr, meta),内部改用meta.tools.chat
  • output.rejected改为(self, meta),用vim.tbl_extend("force", { message = ... }, meta or {})合并后调用helpers.rejected
  • output.prompt/output.cmd_string/output.cancelled改为(self, meta)
  • handlers.setup/on_exit/prompt_condition改为(self, meta)
  • 全文搜索tools.chat,确认已全部替换为meta.tools.chat
  • 确认opts.output_cb只调用一次,且不与同步return混用
  • 业务逻辑除参数访问方式外零改动

完成以上检查后,你的自定义工具即可在 v19 系列(当前仓库为 19.22.0)上正常运行;进一步了解工具的结构、schema 与审批机制,可继续阅读 工具扩展指南 与 Agent 与工具使用说明。

【免费下载链接】codecompanion.nvim✨ AI Coding, Vim Style项目地址: https://gitcode.com/GitHub_Trending/co/codecompanion.nvim

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

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

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

立即咨询