Plugin
Scrivi i tuoi plugin per estendere Dropstone.
I plugin ti permettono di estendere Dropstone collegandoti a vari eventi e personalizzando il comportamento. Puoi creare plugin per aggiungere nuove funzionalità, integrare servizi esterni o modificare il comportamento predefinito di Dropstone.
Usare un plugin
Ci sono due modi per caricare i plugin.
Da file locali
Posiziona file JavaScript o TypeScript nella directory dei plugin.
.dropstone/plugins/- Plugin a livello di progetto~/.config/dropstone/plugins/- Plugin globali
I file in queste directory vengono caricati automaticamente all'avvio.
Da npm
Specifica i pacchetti npm nel tuo file di configurazione.
{
"$schema": "https://dropstone.io/schema/config.json",
"plugin": ["@my-org/internal-plugin", "dropstone-notify-on-idle"]
}
Sono supportati sia i pacchetti npm regolari che quelli con scope.
Come vengono installati i plugin
I plugin npm vengono installati automaticamente usando Bun all'avvio. I pacchetti e le loro dipendenze vengono memorizzati nella cache in ~/.cache/dropstone/node_modules/.
I plugin locali vengono caricati direttamente dalla directory dei plugin. Per utilizzare pacchetti esterni, devi creare un package.json nella tua directory di configurazione (vedi Dipendenze), oppure pubblicare il plugin su npm e aggiungerlo alla tua configurazione.
Ordine di caricamento
I plugin vengono caricati da tutte le fonti e tutti gli hook vengono eseguiti in sequenza. L'ordine di caricamento è:
- Configurazione globale (
~/.config/dropstone/dropstone.json) - Configurazione del progetto (
dropstone.json) - Directory dei plugin globali (
~/.config/dropstone/plugins/) - Directory dei plugin del progetto (
.dropstone/plugins/)
I pacchetti npm duplicati con lo stesso nome e versione vengono caricati una sola volta. Tuttavia, un plugin locale e un plugin npm con nomi simili vengono entrambi caricati separatamente.
Creare un plugin
Un plugin è un modulo JavaScript/TypeScript che esporta una o più funzioni plugin. Ogni funzione riceve un oggetto di contesto e restituisce un oggetto di hook.
Dipendenze
I plugin locali e gli strumenti personalizzati possono utilizzare pacchetti npm esterni. Aggiungi un package.json alla tua directory di configurazione con le dipendenze di cui hai bisogno.
{
"dependencies": {
"shescape": "^2.1.0"
}
}
Dropstone esegue bun install all'avvio per installare queste dipendenze. I tuoi plugin e strumenti possono quindi importarle.
import { escape } from "shescape"
export const MyPlugin = async (ctx) => {
return {
"tool.execute.before": async (input, output) => {
if (input.tool === "bash") {
output.args.command = escape(output.args.command)
}
},
}
}
Struttura di base
export const MyPlugin = async ({ project, client, $, directory, worktree }) => {
console.log("Plugin initialized!")
return {
// Hook implementations go here
}
}
La funzione del plugin riceve:
project: Le informazioni del progetto corrente.directory: La directory di lavoro corrente.worktree: Il percorso del worktree git.client: Un client SDK di Dropstone per interagire con l'agente.$: L'API shell di Bun per eseguire comandi.
Supporto TypeScript
Per i plugin TypeScript, puoi importare i tipi dal pacchetto plugin:
import type { Plugin } from "@blankline/dropstone-plugin"
export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree }) => {
return {
// Type-safe hook implementations
}
}
Eventi
I plugin possono sottoscriversi agli eventi come visto di seguito nella sezione Esempi. Ecco un elenco dei diversi eventi disponibili.
Eventi di comando
command.executed
Eventi di file
file.editedfile.watcher.updated
Eventi di installazione
installation.updated
Eventi LSP
lsp.client.diagnosticslsp.updated
Eventi di messaggio
message.part.removedmessage.part.updatedmessage.removedmessage.updated
Eventi di permesso
permission.askedpermission.replied
Eventi del server
server.connected
Eventi di sessione
session.createdsession.compactedsession.deletedsession.diffsession.errorsession.idlesession.statussession.updated
Eventi Todo
todo.updated
Eventi Shell
shell.env
Eventi Tool
tool.execute.aftertool.execute.before
Esempi
Ecco alcuni esempi di plugin che puoi utilizzare per estendere dropstone.
Inviare notifiche
Invia notifiche quando si verificano determinati eventi:
export const NotificationPlugin = async ({ project, client, $, directory, worktree }) => {
return {
event: async ({ event }) => {
// Send notification on session completion
if (event.type === "session.idle") {
await $`osascript -e 'display notification "Session completed!" with title "dropstone"'`
}
},
}
}
Stiamo usando osascript per eseguire AppleScript su macOS. Qui lo stiamo usando per inviare notifiche.
Protezione .env
Impedisci a dropstone di leggere i file .env:
export const EnvProtection = async ({ project, client, $, directory, worktree }) => {
return {
"tool.execute.before": async (input, output) => {
if (input.tool === "read" && output.args.filePath.includes(".env")) {
throw new Error("Do not read .env files")
}
},
}
}
Iniettare variabili di ambiente
Inietta variabili di ambiente in tutte le esecuzioni shell (strumenti AI e terminali utente):
export const InjectEnvPlugin = async () => {
return {
"shell.env": async (input, output) => {
output.env.MY_API_KEY = "secret"
output.env.PROJECT_ROOT = input.cwd
},
}
}
Strumenti personalizzati
I plugin possono anche aggiungere strumenti personalizzati a dropstone:
import { type Plugin, tool } from "@blankline/dropstone-plugin"
export const CustomToolsPlugin: Plugin = async (ctx) => {
return {
tool: {
mytool: tool({
description: "This is a custom tool",
args: {
foo: tool.schema.string(),
},
async execute(args, context) {
const { directory, worktree } = context
return `Hello ${args.foo} from ${directory} (worktree: ${worktree})`
},
}),
},
}
}
L'helper tool crea uno strumento personalizzato che dropstone può chiamare. Accetta una funzione di schema Zod e restituisce una definizione di strumento con:
description: Cosa fa lo strumentoargs: Schema Zod per gli argomenti dello strumentoexecute: Funzione che viene eseguita quando lo strumento viene chiamato
I tuoi strumenti personalizzati saranno disponibili a dropstone insieme agli strumenti integrati.
Note:
Se uno strumento plugin utilizza lo stesso nome di uno strumento integrato, lo strumento plugin ha la precedenza.
Logging
Usa client.app.log() invece di console.log per il logging strutturato:
export const MyPlugin = async ({ client }) => {
await client.app.log({
body: {
service: "my-plugin",
level: "info",
message: "Plugin initialized",
extra: { foo: "bar" },
},
})
}
Livelli: debug, info, warn, error. Vedi il riferimento SDK per i dettagli.
Hook di compattazione
Personalizza il contesto incluso quando una sessione viene compattata:
import type { Plugin } from "@blankline/dropstone-plugin"
export const CompactionPlugin: Plugin = async (ctx) => {
return {
"experimental.session.compacting": async (input, output) => {
// Inject additional context into the compaction prompt
output.context.push(`
## Custom Context
Include any state that should persist across compaction:
- Current task status
- Important decisions made
- Files being actively worked on
`)
},
}
}
L'hook experimental.session.compacting si attiva prima che l'LLM generi un riepilogo di continuazione. Usalo per iniettare contesto specifico del dominio che il prompt di compattazione predefinito potrebbe perdere.
Puoi anche sostituire completamente il prompt di compattazione impostando output.prompt:
import type { Plugin } from "@blankline/dropstone-plugin"
export const CustomCompactionPlugin: Plugin = async (ctx) => {
return {
"experimental.session.compacting": async (input, output) => {
// Replace the entire compaction prompt
output.prompt = `
You are generating a continuation prompt for a long-running coding session.
Summarize:
1. The current task and its status
2. Which files are being modified
3. Any blockers or open questions
4. The next steps to complete the work
Format as a structured prompt the next session can use to resume work.
`
},
}
}
Quando output.prompt è impostato, sostituisce completamente il prompt di compattazione predefinito. L'array output.context viene ignorato in questo caso.