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 registroComportamiento 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

// Ruta del archivo: scratch-plugin/src/heartbeat.ts
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.

  • 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?

Otras extensiones