Cline 插件开发指南:从 Manifest 能力声明到七钩子运行时,构建可跨 CLI/IDE/SDK 运行的 Agent 扩展
Cline 插件是一个 TypeScript 模块,用于扩展任何构建在 Cline SDK 之上的 agent。同一个插件可以在 Cline CLI、VS Code 与 JetBrains 扩展,以及任何基于 @cline/core 的自定义应用中运行。读完本篇,你将掌握插件的两类形态(单文件插件与插件包)、manifest 能力声明机制、setup(api, ctx) 注册阶段、七个运行时钩子的语义与拦截技巧,以及消息构建器、自动化事件、插件包分发契约与完整测试流程。
心智模型:注册表的四个阶段与两条不变量
当宿主启动会话时,会构建一个插件注册表(registry)并按四个阶段执行:
- resolve — 收集所有插件对象;
- validate — 校验每个插件的
manifest:capabilities 必须非空;声明了 hook 阶段就必须有对应的 handler;若存在hooks属性,则"hooks"必须在capabilities中; - setup — 调用每个插件的
setup(api, ctx)一次,这是你执行registerTool、registerCommand等注册操作的地方; - activate — 注册表冻结,agent 循环开始运行,你的钩子与工具正式生效。
注册表强制执行两条不变量:
- 每一项贡献都需要匹配的能力。若
manifest.capabilities中没有"rules",调用api.registerRule(...)会直接抛出异常; - 能力声明与 handler 必须一致。声明了
"hooks"却没有hooks对象,或反之,都会校验失败。
校验之后,注册是一次性的(one-shot)——会话期间不允许动态注册/注销。
这一流程在源码中可以直接印证:contribution-registry.ts 中注册表用一个 phase 字段在 "resolve" | "validate" | "setup" | "activate" | "run" 之间单向推进;normalizeManifest 在 第 355–401 行 实现了文档中提到的两条校验规则——capabilities 为空数组时抛出 "capabilities must be a non-empty array"(对应源码 第 364 行),定义了 hooks 却没声明 "hooks" 能力时抛出 runtime hooks require the "hooks" capability(对应源码 第 397–401 行)。
另外从源码结构看,注册表在 setup() 阶段支持 tolerateSetupErrors 选项:开启后单个插件 setup 失败会被记录,成功完成的插件仍然会被合并进注册表——这正是 CLI "插件校验/setup 失败时打印清晰错误并继续运行"行为的底层依据。
最小可运行插件
import type { AgentPlugin } from "@cline/core"
import { createTool } from "@cline/core"
const plugin: AgentPlugin = {
name: "hello-plugin",
manifest: {
capabilities: ["tools"],
},
setup(api, ctx) {
api.registerTool(
createTool({
name: "say_hello",
description: "Greet a person by name.",
inputSchema: {
type: "object",
properties: { name: { type: "string" } },
required: ["name"],
},
async execute({ name }: { name: string }) {
return { greeting: `Hello, ${name}!` }
},
}),
)
},
}
export default plugin
agent 会把 say_hello 视为一个可调用工具。
Manifest 与完整能力清单
manifest: {
capabilities: ["tools", "hooks"], // required, non-empty array
paths?: string[], // optional, multi-entry packages
providerIds?: string[], // optional, provider plugins
modelIds?: string[], // optional, model plugins
}
| Capability | 在 api 上解锁的方法 |
|---|---|
"tools" |
api.registerTool() |
"commands" |
api.registerCommand()(聊天界面中的斜杠命令) |
"rules" |
api.registerRule()(注入系统提示词的字符串) |
"messageBuilders" |
api.registerMessageBuilder()(重写发往 provider 的消息) |
"providers" |
api.registerProvider()(自定义模型 provider) |
"automationEvents" |
api.registerAutomationEventType() 与 ctx.automation?.ingestEvent() |
"hooks" |
插件上的运行时 hooks 对象(生命周期回调) |
可以声明任意组合——大多数真实插件只需要 1–3 个能力。
源码中能力枚举定义于 contribution-registry.ts 第 204–214 行。需要说明:当前源码的 ExtensionCapabilityOptions 还包括 "skills" 与 "mcp" 两项,后者可解锁 api.registerMcpServer(),把 MCP 服务器暴露为运行时工具(见 第 142–143 行 与 第 539–553 行);使用这两个新能力时,同样遵循"能力必须预先声明"的规则。
setup(api, ctx):注册阶段
setup() 在每个会话中、agent 循环开始前运行一次。你在这里注册的一切都会冻结到该会话结束。
api 对象
每个 register* 方法都要求 manifest 中声明了匹配的能力:
api.registerTool(tool) // requires "tools"
api.registerCommand({ name, description, handler }) // requires "commands"
api.registerRule({ id, content, source }) // requires "rules"
api.registerMessageBuilder({ name, build }) // requires "messageBuilders"
api.registerProvider({ name, description }) // requires "providers"
api.registerAutomationEventType({ eventType, source }) // requires "automationEvents"
从源码实现看,这些方法在 setup 阶段只是把贡献 push 进一个 pending 暂存区,全部插件的 setup 成功后才合并进全局注册表(见 setup 方法第 500–582 行)。能力检查也并非所有方法都做硬校验——例如 registerRule 缺少 "rules" 能力会抛出 第 519–523 行 的错误;registerAutomationEventType 与 registerMcpServer 也有对应的硬检查。
ctx 对象:宿主提供的会话上下文
第二个参数携带宿主对当前会话所知的一切。所有字段都是可选的,使用前必须做特性探测(feature-detect)——同一个插件必须能在提供较少上下文的宿主(单元测试、沙箱化插件进程)中工作:
ctx.session?.sessionId // string, 稳定的 core session id
ctx.client?.name // 宿主: "cline-cli", "cline-vscode" 等
ctx.user // 认证的用户/组织信息(可用时)
ctx.workspaceInfo // { rootPath, hint, latestGitBranchName,
// latestGitCommitHash, associatedRemoteUrls }
ctx.automation?.ingestEvent // 发出归一化的自动化事件
ctx.logger?.log // 作用于该插件的结构化日志
ctx.telemetry // ITelemetryService,仅进程内存在
这些字段的语义在 PluginSetupContext 接口第 159–202 行 中有完整 JSDoc 说明。其中 telemetry 值得注意:进程内插件直接拿到宿主服务;沙箱化插件拿到的是一个 bridge,转发 capture/recordCounter 等方法到宿主,宿主会把事件命名空间加 plugin. 前缀并打上 plugin_name 标记,用户关闭遥测时直接丢弃。
关于 ctx.workspaceInfo 的两条规则:
- 始终优先使用
ctx.workspaceInfo?.rootPath而非process.cwd()。CLI 可能以--cwd启动而没有调用chdir,而 VS Code 工作区也不存在单一 CWD。workspaceInfo来源于会话配置,始终正确; - 不要用
import.meta.url技巧去找"工作区"。那得到的是插件自身的位置,而不是用户的项目。
跨钩子持久化状态
setup() 先运行,hooks 后触发。共享状态最简单的方式是模块级变量:
let sessionWorkspaceRoot: string | undefined
let sessionBranch: string | undefined
const plugin: AgentPlugin = {
name: "metrics",
manifest: { capabilities: ["hooks"] },
setup(api, ctx) {
sessionWorkspaceRoot = ctx.workspaceInfo?.rootPath
sessionBranch = ctx.workspaceInfo?.latestGitBranchName
},
hooks: {
beforeTool({ toolCall, input }) {
if (sessionBranch === "main" && toolCall.toolName === "run_commands") {
// inspect input, optionally block
}
return undefined
},
},
}
单个 Node 进程可能并发承载多个会话。如果你的插件会运行在多会话宿主中,请按 ctx.session?.sessionId 键控状态:
const stateBySession = new Map<string, MyState>()
setup(api, ctx) {
const id = ctx.session?.sessionId
if (id) stateBySession.set(id, /* ... */)
}
运行时钩子:七个钩点与拦截语义
运行时钩子是同一 hook 层上的类型化进程内回调——运行在 agent 循环内部,拥有完整类型信息,没有 IPC、没有 JSON 序列化开销。在 manifest.capabilities 中声明 "hooks" 后添加 hooks 属性:
const plugin: AgentPlugin = {
name: "metrics",
manifest: { capabilities: ["hooks"] },
hooks: {
beforeRun(ctx) { /* ... */ },
beforeTool({ toolCall, input }) { /* ... */ },
afterTool({ toolCall, result }) { /* ... */ },
afterRun({ result }) { /* ... */ },
onEvent(event) { /* ... */ },
},
}
| 钩子 | 触发时机 | 能停止循环吗 | 常见用途 |
|---|---|---|---|
beforeRun |
运行时循环开始前 | 能 | 问候、日志、附加会话元数据 |
afterRun |
循环结束后(成功、中止或失败) | 不能 | 通知、指标、持久化日志 |
beforeModel |
每次模型请求前 | 能(可变更 req) | 注入上下文、最后一英里提示词编辑 |
afterModel |
每次模型响应后、工具执行前 | 能 | 基于模型输出拦截 |
beforeTool |
每次工具执行前 | 能({ stop }) |
审计、脱敏、拦截危险工具 |
afterTool |
每次工具执行后 | 可替换 result | 后处理、脱敏工具输出中的密钥 |
onEvent |
运行时发出的每个 AgentRuntimeEvent |
不能 | 流式 UI、遥测管道 |
钩子的类型定义在 agent.ts 第 420–449 行的 AgentRuntimeHooks。从源码结构看,各钩子的返回对象还支持一个文档未强调的通用字段 appendContext:例如 AgentAfterToolResult 第 406 行 的 appendContext 会跨钩子收集,并在本轮工具结果之后以 <hook_context> 用户消息追加,使模型在下次请求中能看到——这是向模型"追加旁注"的正式通道。
从钩子中停止循环
多个钩子返回可选的控制对象。最常见模式是 beforeTool 拦截破坏性工具调用:
beforeTool({ toolCall, input }) {
if (toolCall.toolName === "run_commands") {
const { commands } = input as { commands?: string[] }
if (sessionBranch === "main" && commands?.some(c => c.startsWith("git push"))) {
return { stop: true, reason: "Blocked git push on protected branch" }
}
}
return undefined // 显式"继续"
}
返回 undefined(或省略 return)让执行正常继续。
afterRun 语义
afterRun 对所有终态触发——completed、aborted、failed。只想在成功时行动:
afterRun({ result }) {
if (result.status !== "completed") return
// notify, log success metrics, etc.
}
插件钩子 vs 文件钩子
运行时支持两套 hook 系统:
- 文件钩子 —
.cline/hooks/下的外部脚本,以序列化 JSON 调用。适合不随代码分发的用户/工作区特定脚本; - 插件运行时钩子 — 类型化的进程内回调。适合行为属于可复用扩展、且需要类型化访问运行时的场景。
Core 会把文件钩子适配到运行时 hook 层,因此你无需两套都写。如果你在发布插件,请写成运行时钩子。
消息构建器(Message Builders)
消息构建器在模型调用前重写"发往 provider 的消息列表"。它们在运行时消息转换为 SDK 消息块之后、core 内建安全 builder 之前运行。
适用场景:
- 自定义压缩策略(用摘要替换中间历史);
- 在到达 provider 前脱敏 PII 或密钥;
- 针对特定模型的强项重塑上下文。
api.registerMessageBuilder({
name: "summarize-middle-history",
build(messages) {
if (estimateTokens(messages) < THRESHOLD) return messages
return [...prefix, summary, ...recent]
},
})
多个构建器按注册顺序执行,前一个的输出是后一个的输入。
何时改用 beforeModel:只有当你需要运行时快照、或想直接变更请求对象本身时,才使用 beforeModel 钩子。纯粹的消息重写应该放在 builder 里。
自动化事件(Automation Events)
插件可以声明归一化事件类型,并将其发出到 Cline 自动化管线。未启用 automation 的宿主会同时忽略两者——请特性探测 ctx.automation:
manifest: { capabilities: ["automationEvents"] },
setup(api, ctx) {
api.registerAutomationEventType({
eventType: "github.pull_request.opened",
source: "github",
description: "A new GitHub PR was opened",
attributesSchema: { /* JSON Schema for envelope.attributes */ },
})
if (!ctx.automation) return // 宿主没有 automation
ctx.automation.ingestEvent({
eventId: "pr-1234",
eventType: "github.pull_request.opened",
source: "github",
subject: "owner/repo#1234",
occurredAt: new Date().toISOString(),
attributes: { /* ... */ },
})
}
从源码看,事件类型贡献要求 eventType 与 source 非空,否则在 normalizeAutomationEventType 第 409–438 行 抛错;另外注册表在 setup 阶段会对未声明 automationEvents 能力的插件把 ctx.automation 强制置为 undefined(第 555–560 行)——即"没有能力,连入口都拿不到",这比简单的 feature-detect 更严格。
加载插件的三种方式
1. 自动发现(CLI)
CLI 在启动时扫描以下目录:
<workspace>/.cline/plugins/— 项目作用域插件;~/.cline/plugins/— 用户作用域插件。
放入 .ts 或 .js 文件,运行 cline,完成:
mkdir -p .cline/plugins
cp my-plugin.ts .cline/plugins/
cline -i "do the thing my plugin enables"
2. SDK 配置中显式 extensions
当你用 ClineCore 构建自己的宿主时,直接传入插件对象:
import plugin from "./my-plugin"
import { ClineCore } from "@cline/core"
const host = await ClineCore.create({ backendMode: "local" })
await host.start({
config: {
providerId: "anthropic",
modelId: "claude-sonnet-4-6",
apiKey: process.env.ANTHROPIC_API_KEY ?? "",
cwd: process.cwd(),
enableTools: true,
systemPrompt: "You are a helpful assistant.",
extensions: [plugin],
extensionContext: {
workspace: { rootPath: process.cwd(), cwd: process.cwd() },
},
},
prompt: "...",
interactive: false,
})
3. pluginPaths 指向目录型插件
当插件是一个带 package.json 的目录时,把 pluginPaths 指向该目录:
config: {
pluginPaths: ["./path/to/my-plugin-package"],
}
或者用 CLI 安装:
cline plugin install ./path/to/my-plugin-package
cline plugin install @scope/my-cline-plugin # from npm
cline plugin install --git github.com/owner/repo # from git
路径加载的底层实现是 plugin-loader.ts 中的 loadAgentPluginFromPath:它动态 import 模块,优先取 default 导出(否则取名为 plugin 的具名导出),随后经 validatePluginExport 第 83–103 行 校验——导出必须是对象、name 必须是非空字符串、manifest.capabilities 必须是非空字符串数组。值得注意的是 第 122–140 行:loader 会包装你的 setup,把从会话注入的 session/client/user/workspaceInfo/automation/logger/telemetry 合并进 ctx 后再调用原始 setup——这解释了为什么文档强调宿主上下文"始终来源于会话配置"。批量加载时(第 160–213 行),同名插件后者覆盖前者并产生 duplicate_plugin_override 警告,单个插件加载失败只会记入 failures 而不中断整体。
单文件插件模板
保存为 my-plugin.ts,放入 .cline/plugins/:
import { type AgentPlugin, ClineCore, createTool } from "@cline/core"
let sessionRoot: string | undefined
const plugin: AgentPlugin = {
name: "my-plugin",
manifest: {
capabilities: ["tools", "hooks"],
},
setup(api, ctx) {
sessionRoot = ctx.workspaceInfo?.rootPath
api.registerTool(
createTool({
name: "do_thing",
description: "Do the thing this plugin exists for.",
inputSchema: {
type: "object",
properties: { target: { type: "string" } },
required: ["target"],
},
async execute(input) {
const { target } = input as { target: string }
return { ok: true, target, root: sessionRoot }
},
}),
)
},
hooks: {
beforeRun() {
console.log("[my-plugin] run started")
},
afterRun({ result }) {
if (result.status !== "completed") return
console.log(`[my-plugin] done in ${result.iterations} iteration(s)`)
},
},
}
async function runDemo(): Promise<void> {
const host = await ClineCore.create({ backendMode: "local" })
try {
const result = await host.start({
config: {
providerId: "anthropic",
modelId: "claude-sonnet-4-6",
apiKey: process.env.ANTHROPIC_API_KEY ?? "",
cwd: process.cwd(),
enableTools: true,
systemPrompt: "You are a helpful assistant. Use tools when needed.",
extensions: [plugin],
extensionContext: {
workspace: { rootPath: process.cwd(), cwd: process.cwd() },
},
},
prompt: "Use do_thing on the target 'world'.",
interactive: false,
})
console.log(result.result?.text ?? "")
} finally {
await host.dispose()
}
}
if (import.meta.main) {
await runDemo()
}
export { plugin, runDemo }
export default plugin
复制后改个工具名、换入你的逻辑。runDemo() 函数让你可以用 ANTHROPIC_API_KEY=sk-... bun run my-plugin.ts 直接测试。
插件包(Plugin Package)
当需要 npm 依赖、多入口、打包资源或 npm/git 分发时,使用插件包。
目录结构
my-cline-plugin/
+-- package.json
+-- tsconfig.json (optional, for local typechecking)
+-- index.ts (the plugin entry point)
+-- README.md
+-- assets/ (optional, bundled content)
+-- templates/
+-- schemas/
package.json —— 发现契约
{
"name": "my-cline-plugin",
"version": "0.1.0",
"private": true,
"description": "What this plugin does, in one sentence.",
"type": "module",
"exports": {
".": "./index.ts"
},
"cline": {
"plugins": [
{
"paths": ["./index.ts"],
"capabilities": ["tools", "hooks"]
}
]
},
"peerDependencies": {
"@cline/core": "*"
},
"peerDependenciesMeta": {
"@cline/core": { "optional": true }
},
"dependencies": {
"zod": "^4.1.5"
}
}
关键字段:
type: "module"— 必需。Cline 插件是 ES 模块;cline.plugins— 发现契约。数组的每个条目含paths(入口文件)与capabilities(预先声明、import 前校验);- 对
@cline/core的peerDependencies— 宿主已提供它。标记为 optional 让你可以独立做类型检查。
打包资源
用 import.meta.url 而非 process.cwd() 解析资源路径:
import { dirname, join } from "node:path"
import { fileURLToPath } from "node:url"
import { readFileSync, existsSync } from "node:fs"
const MODULE_DIR = dirname(fileURLToPath(import.meta.url))
const TEMPLATES_DIR = join(MODULE_DIR, "assets", "templates")
function loadTemplate(name: string): string | undefined {
const path = join(TEMPLATES_DIR, `${name}.md`)
return existsSync(path) ? readFileSync(path, "utf8") : undefined
}
这是插件中 import.meta.url 的唯一适用场景——定位插件包内部的文件。工作区路径始终用 ctx.workspaceInfo?.rootPath。
覆盖模式(Bundled / Global / Project)
包可以内置默认资源并允许用户覆盖。约定是三层查找,按 name 后者胜出(last write wins):
- bundled — 插件包内文件(随插件分发的默认值);
- global —
~/.cline/data/settings/<kind>/下文件(用户覆盖); - project —
<workspace>/.cline/<kind>/下文件(项目覆盖)。
多插件条目
如果包暴露多个插件,在 cline.plugins 中逐个列出:
"cline": {
"plugins": [
{ "paths": ["./tools-plugin.ts"], "capabilities": ["tools"] },
{ "paths": ["./hooks-plugin.ts"], "capabilities": ["hooks"] }
]
}
每个入口文件应各自 export default 一个插件对象。
测试你的插件
单元测试
插件对象是纯数据。用最小上下文驱动 setup(),直接调用工具:
import plugin from "../my-plugin"
const tools: unknown[] = []
const api = {
registerTool: (t: unknown) => tools.push(t),
registerCommand: () => {},
registerRule: () => {},
registerMessageBuilder: () => {},
registerProvider: () => {},
registerAutomationEventType: () => {},
}
await plugin.setup?.(api as never, {
workspaceInfo: { rootPath: "/tmp/fake-workspace" },
})
// Now `tools` contains the registered tools -- call tool.execute(input, ctx)
端到端:runDemo()
在插件文件中加一个 runDemo()(见上方单文件模板),启动真实的 ClineCore 会话:
ANTHROPIC_API_KEY=sk-... bun run my-plugin.ts
CLI 冒烟测试
mkdir -p .cline/plugins
cp my-plugin.ts .cline/plugins/
cline -i "trigger something that exercises the plugin"
包的形式:
cline plugin install ./my-cline-plugin
cline -i "..."
如果插件校验或 setup 失败,CLI 会打印清晰错误并继续运行(不带该插件)。
常见陷阱清单
- "capabilities must be a non-empty array" — 你漏写了
manifest.capabilities,或它是[]; - "registerRule requires the 'rules' capability" — 能力/handler 漂移。把
"rules"加进 capabilities,或停止调用registerRule; - 工具对模型不可见 — 检查会话配置中
enableTools: true,以及 capabilities 中声明了"tools"; - SDK 测试中
ctx.workspaceInfo为 undefined — 宿主没有传extensionContext.workspace。在 SDK 代码中显式设置(见上面 ClineCore 加载示例); - 状态跨会话泄漏 — 模块级变量在同一进程的多个会话间共享。若宿主并发跑多会话,按
ctx.session?.sessionId键控; afterRun在中止时也触发 — 用if (result.status !== "completed") return守卫;setup()中做重活 —setup()会阻塞会话启动。把昂贵工作推迟到首次工具调用或beforeRun;- 导入宿主内部模块 — 只从
@cline/core导入。伸手进宿主特定包(如 CLI 内部)会在非 CLI 宿主中失效; - 沙箱插件与
telemetry— telemetry 是进程内的。特性探测ctx.telemetry,并预期它在沙箱化插件进程中为 undefined; - 解析打包资源 — 找包内文件用
import.meta.url+fileURLToPath,绝不用process.cwd()。工作区路径反过来:用ctx.workspaceInfo?.rootPath,绝不用import.meta.url; - 插件名冲突 —
name在会话内必须唯一。两个插件同名时校验失败。按包命名空间化(my-org-redactor,而非redactor)。
决策指南:该选哪个扩展点?
| 你想要…… | 使用 |
|---|---|
| 给模型一个新能力 | registerTool |
| 在聊天界面加斜杠命令 | registerCommand |
| 向系统提示词注入文本 | registerRule |
| 在消息到达 provider 前重写 | registerMessageBuilder |
| 添加自定义模型 provider | registerProvider |
| 发出归一化的 cron/webhook 事件 | registerAutomationEventType + ctx.automation |
| 观察或引导 agent 循环 | hooks.* |
| 拦截危险工具调用 | hooks.beforeTool 返回 { stop: true } |
| 完成时通知 | hooks.afterRun(用 status === "completed" 门控) |
| 微调每次模型请求 | hooks.beforeModel |
| 把事件流式送到 UI | hooks.onEvent |
| 随插件分发可复用模板 | 把资源打进 index.ts 旁边,用 import.meta.url 解析 |
| 让用户在全局或项目级覆盖默认值 | 三层查找:bundled / global / project |
发布前检查清单
manifest.capabilities是非空数组;- 每个
api.register*调用都有对应的能力声明; - 若存在
hooks,"hooks"在capabilities中; - 工作区路径使用
ctx.workspaceInfo?.rootPath(不是process.cwd()); - 可选
ctx字段都做了特性探测; - 工具名是 snake_case 动词;description 是写给模型看的;
- 工具输入有带
required的 JSON Schema; - 只关心成功时,
afterRunhandler 用result.status === "completed"门控; - 不能跨并发会话泄漏的状态按
ctx.session?.sessionId键控; - (包)
package.json含type: "module"、cline.plugins,以及把@cline/core声明为 optional peer 依赖; - (包)打包资源用
import.meta.url而非process.cwd()解析; - 冒烟测试:把插件放进
.cline/plugins/(或cline plugin install),跑cline -i "...",亲眼看它工作。
SDK 仓库中的官方插件示例
本仓库 sdk/examples/plugins/ 目录提供了可直接研读的示例:
| 插件 | 说明 |
|---|---|
| weather-metrics.ts | 工具注册 + 生命周期指标,并用 ctx.workspaceInfo 与 ctx.telemetry 演示宿主上下文 |
| mac-notify.ts | macOS 通知中心提醒 |
| custom-compaction.ts | 通过消息构建器实现自定义消息压缩 |
| background-terminal.ts | 脱离式 shell 作业管理 |
| automation-events.ts | 插件发出的自动化事件 |
| gitignore-read-files-guard.ts | 通过 beforeTool 强制文件访问策略 |
| web-search.ts | 基于 Exa API 的网络搜索 |
| typescript-lsp/ | TypeScript 语言服务工具(插件包形态) |
| agents-squad/ | 多 agent 团队编排(插件包形态) |
其中 weather-metrics.ts 与本节描述的"模块级状态 + setup 填充 + 钩子消费"模式逐行对应:它用 sessionWorkspaceRoot/sessionBranch 等模块变量在 setup() 中从 ctx.workspaceInfo 取值,再由 beforeRun/beforeTool/afterTool/afterRun 统计工具调用次数,并通过 ctx.telemetry 把指标推入宿主遥测服务。
相关文档
- 工具创建参考 — Tool creation
- 事件系统参考 — Event system
- Agent 参考 — 在 Agent 中使用插件
- ClineCore 参考 — 在 ClineCore 中使用插件
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00