advanced60 minLição 1 de 5

Desenvolvimento de Plugins do Zero

Crie plugins personalizados do OpenCode do zero. Aprenda a arquitetura de plugins, eventos de ciclo de vida, API surface e como criar plugins que estendem as capacidades do OpenCode.

Desenvolvimento de Plugins do Zero

Arquitetura de Plugins

Plugins são pacotes Node.js que estendem a funcionalidade do OpenCode:

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

Ciclo de Vida do Plugin

100%
FaseDescrição
LoadO plugin é descoberto e carregado
InitializeO plugin configura recursos
RegisterOs handlers de eventos são registrados
ActiveO plugin escuta eventos
ShutdownLimpeza e liberação de recursos

Criando um Plugin

Passo 1: Inicializar o Pacote

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

Passo 2: Criar o Entry do Plugin

Crie 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("Code Metrics plugin initialized"); } async onFileWrite(filePath: string, content: string) { const lines = content.split("\n").length; const bytes = Buffer.byteLength(content); console.log(`File written: ${filePath}`); console.log(` Lines: ${lines}`); console.log(` Bytes: ${bytes}`); return { lines, bytes }; } async onToolExecute(tool: string, args: any, result: any) { // Log tool usage metrics return { tool, timestamp: Date.now(), success: !result.error }; } async shutdown() { console.log("Code Metrics plugin shutting down"); } }

Passo 3: Registrar o Plugin

Adicione ao opencode.json:

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

API Surface do Plugin

Eventos Disponíveis

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 do Context

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;

Exemplo: Plugin de Scanner de Segurança

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(`Potentially dangerous pattern: ${pattern.source}`); } } if (warnings.length > 0) { console.warn(`Security warnings for ${path}:`); warnings.forEach(w => console.warn(` - ${w}`)); } return { warnings }; } }

Testando Plugins

Testes Unitários

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

Testes de Integração

bash
npm test

Melhores Práticas

PráticaMotivo
Responsabilidade únicaUm plugin, um propósito
Tratamento de errosDegradation graciosa
PerformanceNão bloquear a thread principal
LoggingInformações úteis de debug
ConfiguraçãoTornar o comportamento ajustável

Practice Questions

Practice Question

Qual é a primeira fase no ciclo de vida do plugin?

Practice Question

Qual evento dispara antes de um arquivo ser escrito?

Practice Question

Onde os plugins devem ser registrados?

Practice Question

O que um plugin deve fazer durante o shutdown?

Practice Question

Como os plugins acessam a configuração?


Success

Key Takeaways

  • Plugins são pacotes Node.js que estendem a funcionalidade do OpenCode
  • O ciclo de vida inclui as fases Load, Initialize, Register, Active e Shutdown
  • Use o evento file.write para validar ou transformar o conteúdo antes de salvar
  • Registre plugins no opencode.json sob a chave plugins
  • Siga o princípio de responsabilidade única para o design de plugins
  • Sempre limpe recursos durante o shutdown
  • Teste plugins com testes unitários e de integração
Progresso20%