跳到正文
FunCoding

搜索

搜索文档、Skill 和 MCP

编写扩展工具与命令

用 joinSession 注册工具、斜杠命令与事件监听,理解权限和内存状态。

joinSession 把运行中的 JavaScript 进程连接到 CLI 会话,并注册扩展提供的能力。工具由模型选择调用,斜杠命令由用户主动执行;事件监听则让进程在两次调用之间保留累计状态。

一个累计工具次数的命令

在项目 .github/extensions/tool-counter/extension.mjs 写入以下示例。它根据官方的 joinSession、commands、session.log 和工具事件接口组合,只统计扩展运行期间收到的完成事件:

import { joinSession } from "@github/copilot-sdk/extension";

let completedCalls = 0;
const session = await joinSession({
  commands: [
    {
      name: "toolcount",
      description: "Show completed tool calls observed by this extension.",
      handler: async () => {
        await session.log(`Observed ${completedCalls} completed tool calls.`, {
          level: "info",
        });
      },
    },
  ],
});

session.on("tool.execution_complete", () => {
  completedCalls += 1;
});

启用 experimental 并从项目启动会话,确认扩展 running,让 Copilot 执行一些工具后运行 /toolcount。这个计数不是历史账单,也不会恢复重启前的值。

注册斜杠命令

commands 条目包含 name、description 和异步 handler。name 不带斜杠;handler 的 ctx.args 是命令名后面的原始文本,例如 /tokencount start 的参数为 start。

用 session.log(message, { level: "info" }) 把结果写到会话时间线。模块级变量在扩展进程存活期间保留,重载或 /clear 后重置。

注册模型工具

tools 条目使用 name、description、parameters 和 handler。parameters 是描述输入的 JSON Schema;handler 返回的字符串成为工具结果,供模型读取。

可选字段效果
defer: "never"即使工具搜索启用,也始终展示工具描述
skipPermission: true请求扩展级批准后,工具不再每次单独确认

defer 不会强迫模型调用工具。描述应说明能力和何时有用,尤其是模型无法从其他来源获得的信息。

skipPermission 不是安装后无条件跳过权限。官方 tool-time 示例首次请求允许 user:tool-time 跳过逐次批准;对应精确预批准模式为 extension-permission-access(user:tool-time)。只应为已审阅且适合此权限范围的扩展采用它。

对齐事件

tool.execution_start 包含 toolName,完成事件包含 success,两者通过 toolCallId 关联。计时扩展应按 ID 保存开始时间,完成时计算差值;计算时可能包含等待用户批准的时间,因此是扩展观察到的墙钟时间。

assistant.usage 提供 inputTokens 和 outputTokens,可用来累计会话 token 用量。它不是价格计算公式;若要统计某段时间,从当前累计值建立基线,再显示差值。

验证结果

先确认 /extensions manage 中状态,再分别测试命令入口、工具调用和事件更新。模型回答正确不必然说明调用了新工具,应检查回复前显示的工具名称。重载后重新检查内存计数,避免把重置误判为事件丢失。