Desarrollo de Plugins desde Cero
Avanzado⏱60 min📖2 min de lecturaLección 1 de 5

Desarrollo de Plugins desde Cero

Construye plugins personalizados de OpenCode desde cero. Aprende la arquitectura de plugins, eventos del ciclo de vida, superficie de API y cómo crear plugins que extiendan las capacidades de OpenCode.

Arquitectura de Plugins

Los plugins son paquetes de Node.js que extienden la funcionalidad de OpenCode:

.opencode/plugins/my-plugin/ ├── package.json ├── src/ │ └── index.ts ├── assets/ ├── examples/ ├── references/ └── scripts/

Ciclo de Vida del Plugin

100%
Fase
Descripción
Carga
El plugin es descubierto y cargado
Inicializar
El plugin configura recursos
Registrar
Los handlers de eventos son registrados
Activo
El plugin escucha eventos
Apagado
Limpieza y liberación de recursos

Creando un Plugin

Paso 1: Inicializar Paquete

bash
mkdir -p .opencode/plugins/code-metrics cd .opencode/plugins/code-metrics npm init -y

Paso 2: Crear Entrada del Plugin

Crear src/index.ts:

typescript
import { Plugin, PluginContext } from "opencode"; export default class CodeMetricsPlugin implements Plugin { name = "code-metrics"; version = "1.0.0"; async initialize(context: PluginContext) { console.log("Plugin de Métricas de Código inicializado"); } async onFileWrite(filePath: string, content: string) { const lines = content.split("\n").length; const bytes = Buffer.byteLength(content); console.log(`Archivo escrito: ${filePath}`); console.log(` Líneas: ${lines}`); console.log(` Bytes: ${bytes}`); return { lines, bytes }; } async onToolExecute(tool: string, args: any, result: any) { // Registrar métricas de uso de herramientas return { tool, timestamp: Date.now(), success: !result.error }; } async shutdown() { console.log("Plugin de Métricas de Código apagándose"); } }

Paso 3: Registrar Plugin

Agregar a opencode.json:

json
{ "plugins": { "code-metrics": { "path": ".opencode/plugins/code-metrics", "enabled": true } } }

Superficie de API del Plugin

Eventos Disponibles

Evento
Parámetros
Retorno
session.start
sessionId
void
session.end
sessionId
void
file.read
path, content
content
file.write
path, content
content
file.edit
path, old, new
new
tool.execute.before
tool, args
args
tool.execute.after
tool, args, result
result
agent.route
request, agent
agent

Métodos de Contexto

typescript
context.log(message: string, level: "info" | "warn" | "error"); context.getConfig(key: string): any; context.setConfig(key: string, value: any): void; context.getMemory(key: string): any; context.setMemory(key: string, value: any): void;

Ejemplo: Plugin de Escáner de Seguridad

typescript
import { Plugin, PluginContext } from "opencode"; const DANGEROUS_PATTERNS = [ /eval\s*\(/, /new\s+Function\s*\(/, /process\.exit/, /require\s*\(\s*['"]child_process['"]\s*\)/, ]; export default class SecurityScannerPlugin implements Plugin { name = "security-scanner"; version = "1.0.0"; async onFileWrite(path: string, content: string) { const warnings: string[] = []; for (const pattern of DANGEROUS_PATTERNS) { if (pattern.test(content)) { warnings.push(`Patrón potencialmente peligroso: ${pattern.source}`); } } if (warnings.length > 0) { console.warn(`Advertencias de seguridad para ${path}:`); warnings.forEach(w => console.warn(` - ${w}`)); } return { warnings }; } }

Probando Plugins

Pruebas Unitarias

typescript
import CodeMetricsPlugin from "../src/index"; describe("CodeMetricsPlugin", () => { let plugin: CodeMetricsPlugin; beforeEach(() => { plugin = new CodeMetricsPlugin(); }); it("debería contar líneas correctamente", async () => { const result = await plugin.onFileWrite("test.ts", "line1\nline2\nline3"); expect(result.lines).toBe(3); }); it("debería contar bytes correctamente", async () => { const result = await plugin.onFileWrite("test.ts", "hello"); expect(result.bytes).toBe(5); }); });

Pruebas de Integración

bash
npm test

Mejores Prácticas

Práctica
Razón
Responsabilidad única
Un plugin, un propósito
Manejo de errores
Degradación elegante
Rendimiento
No bloquear el hilo principal
Registro
Información de depuración útil
Configuración
Hacer el comportamiento ajustable

Preguntas de Práctica (Practice Questions)

Pregunta de Práctica
Cómo responder

Pregunta de opción múltiple con 4 opciones. Selecciona una opción y elige Comprobar respuesta.

¿Cuál es la primera fase en el ciclo de vida del plugin?

Pregunta de Práctica
Cómo responder

Pregunta de opción múltiple con 4 opciones. Selecciona una opción y elige Comprobar respuesta.

¿Qué evento se dispara antes de que se escriba un archivo?

Pregunta de Práctica
Cómo responder

Pregunta de opción múltiple con 4 opciones. Selecciona una opción y elige Comprobar respuesta.

¿Dónde se deben registrar los plugins?

Pregunta de Práctica
Cómo responder

Pregunta de opción múltiple con 4 opciones. Selecciona una opción y elige Comprobar respuesta.

¿Qué debe hacer un plugin durante el apagado?

Pregunta de Práctica
Cómo responder

Pregunta de opción múltiple con 4 opciones. Selecciona una opción y elige Comprobar respuesta.

¿Cómo acceden los plugins a la configuración?


✅Éxito

Key Takeaways

  • Los plugins son paquetes de Node.js que extienden la funcionalidad de OpenCode
  • El ciclo de vida incluye fases de Carga, Inicializar, Registrar, Activo y Apagado
  • Usa el evento file.write para validar o transformar contenido antes de guardar
  • Registra plugins en opencode.json bajo la clave plugins
  • Sigue el principio de responsabilidad única para el diseño de plugins
  • Siempre limpia recursos durante el apagado
  • Prueba plugins con pruebas unitarias y de integración
Progreso20%