DeepSeek Harness limpieza automática y ctx.effect()
Capítulo anteriorDeepSeek Harness: cargar complementos localesImprimir una línea de registro sería todo, pero un complemento real registra oyentes, herramientas y temporizadores.
Este capítulo resuelve una pregunta: cuando el complemento se desinstala, ¿quién limpia estos recursos?
El registro se delega en ctx, y la limpieza también se delega en ctx.
Mecanismo de limpieza automática
Cualquier cosa registrada a través de ctx —oyentes de eventos, herramientas, temporizadores— se limpiará automáticamente al desinstalar el complemento.
No necesitas llamar manualmente a removeListener o clearInterval.
El framework puede limpiar automáticamente porque todos los registros a través de ctx se guardan en el ámbito Fiber del complemento.
Al desinstalar, el framework los revierte en orden inverso al de registro.
¿Qué operaciones se rastrean automáticamente?
Las siguientes operaciones se rastrean y limpian automáticamente.
| Operaciones de registro | Comportamiento al desinstalar |
|---|---|
| ctx.on(event, handler) | Los oyentes de eventos se eliminan automáticamente |
| ctx.tools.register(tool) | El registro de herramientas se revierte automáticamente |
| ctx.llm.registerAdapter(names, adapter) | El registro del adaptador LLM se revierte automáticamente |
| ctx.effect(() => cleanup) | Se ejecuta la función de limpieza disposer devuelta |
ctx.effect(): entregar recursos manuales al framework
Hay recursos que no están en la lista anterior, por ejemplo, una conexión de red.
Usa ctx.effect() para indicar al framework cómo limpiarlo.
ctx.effect recibe un callback; dentro del callback se crea el recurso y se devuelve una función de limpieza (disposer).
Este disposer se ejecutará cuando el complemento se desinstale.
disposerLa función de limpieza es el valor de retorno del callback de ctx.effect.
Describe "cómo destruir el recurso creado en este momento".
Cuando el complemento se desinstale, el framework lo invocará.
A continuación, un ejemplo de un temporizador de heartbeat:
Ejemplo
import type { Context } from '@deepseek-ai/cordis'
export function apply(ctx: Context) {
ctx.effect(() => {
// Crear un temporizador: imprime heartbeat cada 5 segundos
const timer = setInterval(() => {
console.log('heartbeat')
}, 5000)
// La función de limpieza devuelta se ejecuta al desinstalar el complemento
// Equivalente a: no necesitas clearInterval manualmente en la lógica de desinstalación
return () => clearInterval(timer)
})
}
Si no hay nada que hacer al desinstalar, el disposer puede omitirse.
Pero una vez que se crean recursos como temporizadores o conexiones, es obligatorio devolver la función de limpieza correspondiente.

Detalles del orden de ejecución
Al desinstalar el complemento, los disposers se invocan en el orden inverso al de registro.
Varios disposers asíncronos se ejecutan de forma concurrente, sin garantía de que se completen uno a uno.
Los pasos de limpieza con dependencia de orden deben colocarse en el disposer devuelto por el mismo ctx.effect(), y ese disposer es responsable de esperar en serie.
Nota: esta regla implica que lo que se registra primero se limpia después — los recursos registrados más tarde se limpian primero.
Resumen y autoevaluación
Los recursos registrados a través de ctx se limpian automáticamente al desinstalar; para los recursos manuales, usa ctx.effect() para proporcionar un disposer.
Otras extensiones
1. ¿Un temporizador registrado a través de ctx necesita clearInterval manual?
2. ¿Cuándo se ejecuta el disposer de ctx.effect(() => disposer)?
3. ¿Por qué las limpiezas con dependencia de orden deben colocarse en el mismo effect?