advanced60 minLecció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.

Desarrollo de Plugins desde Cero

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%
FaseDescripción
CargaEl plugin es descubierto y cargado
InicializarEl plugin configura recursos
RegistrarLos handlers de eventos son registrados
ActivoEl plugin escucha eventos
ApagadoLimpieza 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

EventoParámetrosRetorno
session.startsessionIdvoid
session.endsessionIdvoid
file.readpath, contentcontent
file.writepath, contentcontent
file.editpath, old, newnew
tool.execute.beforetool, argsargs
tool.execute.aftertool, args, resultresult
agent.routerequest, agentagent

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ácticaRazón
Responsabilidad únicaUn plugin, un propósito
Manejo de erroresDegradación elegante
RendimientoNo bloquear el hilo principal
RegistroInformación de depuración útil
ConfiguraciónHacer el comportamiento ajustable

Practice Questions

Practice Question

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

Practice Question

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

Practice Question

¿Dónde se deben registrar los plugins?

Practice Question

¿Qué debe hacer un plugin durante el apagado?

Practice Question

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


Success

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%