DeepSeek Harness 自动清理与 ctx.effect() 菜鸟教程
上一章节 DeepSeek Harness 加载本地插件 打印一行日志就结束了,但真实插件会注册监听、工具、定时器。
本章节解决一个问题:插件卸载时,这些资源谁来清理?
注册交给 ctx,清理也交给 ctx。
自动清理机制
通过 ctx 注册的任何东西——事件监听、工具、定时器——在插件卸载时都会被自动清理。
你不需要手动 removeListener 或 clearInterval。
框架能自动清理,是因为所有通过 ctx 的注册都被记在插件的 Fiber 作用域里。
卸载时,框架按注册顺序的逆序撤销它们。
哪些操作会被自动追踪
下面这些操作都会被自动追踪和清理。
| 注册操作 | 卸载时的行为 |
|---|---|
| ctx.on(event, handler) | 事件监听自动移除 |
| ctx.tools.register(tool) | 工具注册自动撤销 |
| ctx.llm.registerAdapter(names, adapter) | LLM 适配器注册自动撤销 |
| ctx.effect(() => cleanup) | 执行返回的 disposer 清理函数 |
ctx.effect():手动资源交给框架
有些资源不在上面的列表里,比如一个网络连接。
用 ctx.effect() 告诉框架怎么清理它。
ctx.effect 接收一个回调,回调里创建资源并返回一个清理函数(disposer)。
这个 disposer 会在插件卸载时执行。
disposer(清理函数)是 ctx.effect 回调的返回值。
它描述了"如何销毁这次创建的资源"。
插件卸载时,框架会调用它。
下面是一个心跳定时器的例子:
实例
// 文件路径:scratch-plugin/src/heartbeat.ts
import type { Context } from ‘@deepseek-ai/cordis’
export function apply(ctx: Context) {
ctx.effect(() => {
// 创建定时器:每 5 秒打印一次 heartbeat
const timer = setInterval(() => {
console.log(‘heartbeat’)
}, 5000)
// 返回的清理函数在插件卸载时执行
// 等价于:不需要你在卸载逻辑里手动 clearInterval
return () => clearInterval(timer)
})
}
如果卸载时什么都不用做,disposer 可以不写。
但一旦创建了定时器、连接这类资源,就一定要返回对应的清理函数。
执行顺序的细节
插件卸载时,处置器按注册顺序的逆序开始调用。
多个异步处置器会并发执行,不保证逐个完成。
存在顺序依赖的清理步骤,必须放进同一个 ctx.effect() 返回的处置器中,由该处置器负责串行等待。
提示:这条规则意味着先注册后清理——后注册的资源先被清理。
小结与自测
通过 ctx 注册的资源在卸载时自动清理;手动资源用 ctx.effect() 提供 disposer。
1. 通过 ctx 注册的定时器需要手动 clearInterval 吗?
2. ctx.effect(() => disposer) 的 disposer 何时执行?
3. 为什么有顺序依赖的清理要放进同一个 effect?
- 原文作者:知识铺
- 原文链接:https://index.zshipu.com/gpt/post/20260818/DeepSeek-Harness-%E8%87%AA%E5%8A%A8%E6%B8%85%E7%90%86%E4%B8%8E-ctx.effect-%E8%8F%9C%E9%B8%9F%E6%95%99%E7%A8%8B/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。
- 免责声明:本页面内容均来源于站内编辑发布,部分信息来源互联网,并不意味着本站赞同其观点或者证实其内容的真实性,如涉及版权等问题,请立即联系客服进行更改或删除,保证您的合法权益。转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。也可以邮件至 sblig@126.com