Dropstone Docs

Plugin

Tulis plugin Anda sendiri untuk memperluas Dropstone.

Plugin memungkinkan Anda memperluas Dropstone dengan menghubungkan ke berbagai peristiwa dan menyesuaikan perilaku. Anda dapat membuat plugin untuk menambahkan fitur baru, mengintegrasikan dengan layanan eksternal, atau memodifikasi perilaku default Dropstone.


Gunakan plugin

Ada dua cara untuk memuat plugin.


Dari file lokal

Tempatkan file JavaScript atau TypeScript di direktori plugin.

  • .dropstone/plugins/ - Plugin tingkat proyek
  • ~/.config/dropstone/plugins/ - Plugin global

File di direktori ini secara otomatis dimuat saat startup.


Dari npm

Tentukan paket npm di file konfigurasi Anda.

{
  "$schema": "https://dropstone.io/schema/config.json",
  "plugin": ["@my-org/internal-plugin", "dropstone-notify-on-idle"]
}

Paket npm reguler dan scoped didukung.


Cara plugin diinstal

Plugin npm diinstal secara otomatis menggunakan Bun saat startup. Paket dan dependensinya di-cache di ~/.cache/dropstone/node_modules/.

Plugin lokal dimuat langsung dari direktori plugin. Untuk menggunakan paket eksternal, Anda harus membuat package.json dalam direktori konfigurasi Anda (lihat Dependencies), atau publikasikan plugin ke npm dan tambahkan ke konfigurasi Anda.


Urutan pemuatan

Plugin dimuat dari semua sumber dan semua hook berjalan secara berurutan. Urutan pemuatan adalah:

  1. Konfigurasi global (~/.config/dropstone/dropstone.json)
  2. Konfigurasi proyek (dropstone.json)
  3. Direktori plugin global (~/.config/dropstone/plugins/)
  4. Direktori plugin proyek (.dropstone/plugins/)

Paket npm duplikat dengan nama dan versi yang sama dimuat sekali. Namun, plugin lokal dan plugin npm dengan nama serupa keduanya dimuat secara terpisah.


Buat plugin

Plugin adalah modul JavaScript/TypeScript yang mengekspor satu atau lebih fungsi plugin. Setiap fungsi menerima objek konteks dan mengembalikan objek hooks.


Dependencies

Plugin lokal dan alat kustom dapat menggunakan paket npm eksternal. Tambahkan package.json ke direktori konfigurasi Anda dengan dependensi yang Anda butuhkan.

{
  "dependencies": {
    "shescape": "^2.1.0"
  }
}

Dropstone menjalankan bun install saat startup untuk menginstal ini. Plugin dan alat Anda kemudian dapat mengimpornya.

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)
      }
    },
  }
}

Struktur dasar

export const MyPlugin = async ({ project, client, $, directory, worktree }) => {
  console.log("Plugin initialized!")

  return {
    // Hook implementations go here
  }
}

Fungsi plugin menerima:

  • project: Informasi proyek saat ini.
  • directory: Direktori kerja saat ini.
  • worktree: Jalur git worktree.
  • client: Klien Dropstone SDK untuk berinteraksi dengan agen.
  • $: Shell API Bun untuk menjalankan perintah.

Dukungan TypeScript

Untuk plugin TypeScript, Anda dapat mengimpor tipe dari paket plugin:

import type { Plugin } from "@blankline/dropstone-plugin"

export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree }) => {
  return {
    // Type-safe hook implementations
  }
}

Peristiwa

Plugin dapat berlangganan peristiwa seperti yang terlihat di bawah di bagian Contoh. Berikut adalah daftar peristiwa yang berbeda yang tersedia.

Peristiwa Perintah

  • command.executed

Peristiwa File

  • file.edited
  • file.watcher.updated

Peristiwa Instalasi

  • installation.updated

Peristiwa LSP

  • lsp.client.diagnostics
  • lsp.updated

Peristiwa Pesan

  • message.part.removed
  • message.part.updated
  • message.removed
  • message.updated

Peristiwa Izin

  • permission.asked
  • permission.replied

Peristiwa Server

  • server.connected

Peristiwa Sesi

  • session.created
  • session.compacted
  • session.deleted
  • session.diff
  • session.error
  • session.idle
  • session.status
  • session.updated

Peristiwa Todo

  • todo.updated

Peristiwa Shell

  • shell.env

Peristiwa Alat

  • tool.execute.after
  • tool.execute.before

Contoh

Berikut adalah beberapa contoh plugin yang dapat Anda gunakan untuk memperluas dropstone.


Kirim notifikasi

Kirim notifikasi ketika peristiwa tertentu terjadi:

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"'`
      }
    },
  }
}

Kami menggunakan osascript untuk menjalankan AppleScript di macOS. Di sini kami menggunakannya untuk mengirim notifikasi.


Perlindungan .env

Cegah dropstone dari membaca 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")
      }
    },
  }
}

Injeksi variabel lingkungan

Injeksi variabel lingkungan ke semua eksekusi shell (alat AI dan terminal pengguna):

export const InjectEnvPlugin = async () => {
  return {
    "shell.env": async (input, output) => {
      output.env.MY_API_KEY = "secret"
      output.env.PROJECT_ROOT = input.cwd
    },
  }
}

Alat kustom

Plugin juga dapat menambahkan alat kustom ke 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})`
        },
      }),
    },
  }
}

Helper tool membuat alat kustom yang dapat dipanggil dropstone. Ini mengambil fungsi skema Zod dan mengembalikan definisi alat dengan:

  • description: Apa yang dilakukan alat
  • args: Skema Zod untuk argumen alat
  • execute: Fungsi yang berjalan ketika alat dipanggil

Alat kustom Anda akan tersedia untuk dropstone bersama dengan alat bawaan.

Note:

Jika alat plugin menggunakan nama yang sama dengan alat bawaan, alat plugin memiliki prioritas.


Logging

Gunakan client.app.log() alih-alih console.log untuk logging terstruktur:

export const MyPlugin = async ({ client }) => {
  await client.app.log({
    body: {
      service: "my-plugin",
      level: "info",
      message: "Plugin initialized",
      extra: { foo: "bar" },
    },
  })
}

Level: debug, info, warn, error. Lihat referensi SDK untuk detail.


Hook pemadatan

Sesuaikan konteks yang disertakan ketika sesi dipadatkan:

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
`)
    },
  }
}

Hook experimental.session.compacting diaktifkan sebelum LLM menghasilkan ringkasan kelanjutan. Gunakan untuk menyuntikkan konteks khusus domain yang akan dilewatkan oleh prompt pemadatan default.

Anda juga dapat mengganti prompt pemadatan sepenuhnya dengan mengatur 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.
`
    },
  }
}

Ketika output.prompt diatur, itu sepenuhnya menggantikan prompt pemadatan default. Array output.context diabaikan dalam hal ini.

Ctrl+I