Skip to main content
扩展能力

Plugins

options.plugins 用来把本地 plugin 目录加载进当前会话。SDK 会为每个本地 plugin 转成一个 --plugin-dir <path> 启动参数;插件里包含的 commands、agents、skills 和 MCP servers 都会参与本次会话的能力发现。

加载本地 plugin

import { query } from '@qodercn-ai/qodercn-agent-sdk';

const q = query({
  prompt: 'List the commands and agents contributed by the current plugins',
  options: {
    plugins: [
      { type: 'local', path: '/path/to/my-plugin' },
    ],
  },
});

const init = await q.initializationResult();
console.log(init.commands);
console.log(init.agents);
console.log(init.skills);

const plugins = await q.listPlugins();
console.log(plugins);
可以同时传多个本地 plugin,会按顺序写出多次 --plugin-dir
const q = query({
  options: {
    plugins: [
      { type: 'local', path: '/path/to/plugin-a' },
      { type: 'local', path: '/path/to/plugin-b' },
    ],
  },
});
💡 Python 中 query() 是一次性的消息流,无法在握手后查询 init 响应。要读取插件贡献的命令 / agent / skill,请用 QoderSDKClient 并在 connect() 之后调用 get_server_info(),或在消息流里捕获 SystemMessage(subtype='init') 自行读取 message.data。要读取完整 plugin inventory,请调用 client.list_plugins()

插件目录布局

一个本地 plugin 通常可以包含:
my-plugin/
  .qoder-plugin/plugin.json
  commands/
  agents/
  skills/
  .mcp.json
.qoder-plugin/plugin.json 用来声明插件名、版本、描述。其余目录按文件类型自动被 CLI 扫描。 SDK 不会校验路径是否存在 / 是否合法:
  • 不存在的 --plugin-dir 路径在 SDK 模式里会被静默忽略,会话仍正常初始化。
  • 损坏的 frontmatter / .mcp.json 不阻断 init,损坏的命令不会出现在 init 响应中。
  • 想显式诊断 plugin 加载失败,目前只能依赖 reload 后的 error_count 兜底。

插件贡献 slash commands

插件里的 commands/*.md 会出现在初始化结果中,名称以 <plugin>:<cmd> 限定名形式出现:
const commands = await q.supportedCommands();
console.log(commands.map((cmd) => cmd.name));

插件贡献 agents

插件里的 agents/*.md 会出现在初始化结果中,SDK 提供便捷方法直接拿到这份列表:
const agents = await q.supportedAgents();
console.log(agents.map((agent) => agent.name));

插件贡献 skills

插件里的 skills/<name>/SKILL.md 会以插件限定名(plugin:skill)注册。可通过 options.skills 控制它在主会话中的上下文可见性与调用策略:传插件限定名启用指定 skill,传 'all' 启用全部已发现 skills;不传则使用 CLI 默认策略。见 Skills 文档

插件贡献 MCP servers

插件里的 .mcp.json 会由 CLI 启动并纳入 MCP 状态:
const servers = await q.mcpServerStatus();
console.log(servers);

临时覆盖已安装同名插件

通过 options.plugins 加载的本地 plugin 是 session-scoped。当前会话中,如果它和已安装插件同名,本地 plugin 会优先参与本次会话能力发现。这个能力适合做 plugin 开发、调试和灰度验证。
const q = query({
  options: {
    // The local version only takes effect for this query session and does not
    // touch the user's global install state.
    plugins: [{ type: 'local', path: './my-plugin-dev' }],
  },
});

运行中重新加载 Plugins

如果 plugin 目录发生变化,可以在同一个会话里调用 reloadPlugins() / reload_plugins(),让 CLI 重新扫描 plugin 资源。
const refreshed = await q.reloadPlugins();

console.log(refreshed.commands);
console.log(refreshed.agents);
console.log(refreshed.plugins);
console.log(refreshed.mcpServers);
console.log(refreshed.error_count);
典型用途:
  • 开发 plugin 时新增或删除 commands/*.md 后刷新。
  • 安装或更新本地 plugin 后,不重启宿主应用。
  • 宿主 UI 需要展示 reload 后的 commands、agents、plugins 和 MCP 状态。
注意:Python 中 reload_plugins() 只在 QoderSDKClient(streaming)模式下有意义;一次性的 query() 流没有运行时控制 channel。

Options 速查

字段(TypeScript / Python)说明
plugins / plugins加载本地 plugin 目录,目前常用 { type: 'local', path }
settings / settings透传给 CLI 的 settings,可以包含 enabledPluginspluginConfigs 等字段
settingSources / setting_sources控制 CLI 读取哪些 settings 来源
使用 settings.enabledPlugins 控制插件启用状态,使用 settings.pluginConfigs 为插件提供 MCP server 替换等配置。

返回值参考

初始化结果

initializationResult()(TypeScript)/ client.get_server_info()(Python)返回当前会话发现到的 commands、agents、skills 等初始化资源。它不包含稳定的 plugin inventory 字段;完整返回类型见 SDK References
{
    "commands": [
        {"name": "plugin-a:greet", "description": "...", "argumentHint": "..."},
        ...
    ],
    "agents": [
        {"name": "plugin-a:helper", "description": "...", "model": "sonnet"},
        ...
    ],
    "skills": [
        {"name": "plugin-a:echo", "description": "...", "source": "plugin"},
        ...
    ],
    # Also includes models / account / output_style and other fields
}

列出插件

listPlugins(): Promise<PluginDetails[]>;
读取当前 CLI 的 plugin 清单和每个 plugin 的资源摘要。宿主 UI 要展示 plugin inventory 时应使用这个方法,而不是读取初始化结果里的 plugins 字段。 每一项是 PluginDetails,包含 idnamesourcepathversionscopeenabledcanDisable,以及按 skillsagentsmcpServerscommandshooks 分类的 resources

重新加载插件

reloadPlugins() / reload_plugins() 返回:
type SDKControlReloadPluginsResponse = {
  commands: Array<{ name: string; description?: string; argumentHint?: string }>;
  agents: Array<{ name: string; description?: string }>;
  plugins: Array<{ name: string; path: string; source?: string }>;
  mcpServers: Array<Record<string, unknown>>;
  error_count: number;  // Number of plugins that failed to load in this reload
};

最佳实践

  • 区分初始化资源和 plugin 清单:使用初始化结果展示已发现 commands、agents、skills;使用 listPlugins() / list_plugins() 展示 plugin inventory。其中初始化结果里的 skills 是发现清单,不代表主会话当前全部可调用。
  • 开发 plugin 时使用 options.plugins:它只影响当前会话,不需要修改用户全局安装状态。
  • reload 之前先准备好用户提示:reload 会触发 CLI 重新扫描磁盘,可能短暂改变可用资源列表,UI 上最好同步更新。
  • 错误诊断看 error_count:reload 后 error_count > 0 表示有 plugin 资源加载失败,应该把它的来源展示给用户。

当前限制

  • 部分 qoderclicn 版本下,本地 plugin 的 commands、agents、MCP 可以正常出现在初始化结果中,但 plugin skills 可能没有出现在发现清单里,这属于 CLI 侧发现链路问题。
  • 当前 qoderclicn 实现下,不存在的 --plugin-dir 路径在 SDK 模式里会被静默忽略;如果需要显式诊断 plugin 加载失败,目前只能通过 reload 后的 error_count 兜底。
  • reload 是 SDK 暴露的运行时控制 API;如果当前 CLI 版本返回 this._plugins 相关内部错误,需要升级到修复后的 qoderclicn。