外掛程式
編寫自己的外掛程式以擴展 Dropstone。
外掛程式允許您透過掛接各種事件並自訂行為來擴展 Dropstone。您可以建立外掛程式以新增功能、與外部服務整合,或修改 Dropstone 的預設行為。
使用外掛程式
有兩種方式可以載入外掛程式。
從本機檔案
將 JavaScript 或 TypeScript 檔案放在外掛程式目錄中。
.dropstone/plugins/- 專案層級外掛程式~/.config/dropstone/plugins/- 全域外掛程式
這些目錄中的檔案會在啟動時自動載入。
從 npm
在設定檔中指定 npm 套件。
{
"$schema": "https://dropstone.io/schema/config.json",
"plugin": ["@my-org/internal-plugin", "dropstone-notify-on-idle"]
}
支援一般和範圍內的 npm 套件。
外掛程式如何安裝
npm 外掛程式在啟動時使用 Bun 自動安裝。套件及其相依性會快取在 ~/.cache/dropstone/node_modules/ 中。
本機外掛程式直接從外掛程式目錄載入。若要使用外部套件,您必須在設定目錄中建立 package.json(請參閱相依性),或將外掛程式發佈到 npm 並將其新增到您的設定。
載入順序
外掛程式從所有來源載入,所有掛接按順序執行。載入順序為:
- 全域設定(
~/.config/dropstone/dropstone.json) - 專案設定(
dropstone.json) - 全域外掛程式目錄(
~/.config/dropstone/plugins/) - 專案外掛程式目錄(
.dropstone/plugins/)
具有相同名稱和版本的重複 npm 套件只會載入一次。但是,本機外掛程式和具有相似名稱的 npm 外掛程式會分別載入。
建立外掛程式
外掛程式是一個 JavaScript/TypeScript 模組,可匯出一個或多個外掛程式函數。每個函數接收一個上下文物件並傳回一個掛接物件。
相依性
本機外掛程式和自訂工具可以使用外部 npm 套件。將 package.json 新增到您的設定目錄,其中包含您需要的相依性。
{
"dependencies": {
"shescape": "^2.1.0"
}
}
Dropstone 在啟動時執行 bun install 以安裝這些。您的外掛程式和工具可以匯入它們。
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)
}
},
}
}
基本結構
export const MyPlugin = async ({ project, client, $, directory, worktree }) => {
console.log("Plugin initialized!")
return {
// Hook implementations go here
}
}
外掛程式函數接收:
project:目前的專案資訊。directory:目前的工作目錄。worktree:git worktree 路徑。client:用於與代理互動的 Dropstone SDK 用戶端。$:Bun 的殼層 API,用於執行命令。
TypeScript 支援
對於 TypeScript 外掛程式,您可以從外掛程式套件匯入類型:
import type { Plugin } from "@blankline/dropstone-plugin"
export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree }) => {
return {
// Type-safe hook implementations
}
}
事件
外掛程式可以訂閱事件,如下面的範例部分所示。以下是可用的不同事件清單。
命令事件
command.executed
檔案事件
file.editedfile.watcher.updated
安裝事件
installation.updated
LSP 事件
lsp.client.diagnosticslsp.updated
訊息事件
message.part.removedmessage.part.updatedmessage.removedmessage.updated
權限事件
permission.askedpermission.replied
伺服器事件
server.connected
工作階段事件
session.createdsession.compactedsession.deletedsession.diffsession.errorsession.idlesession.statussession.updated
待辦事項事件
todo.updated
殼層事件
shell.env
工具事件
tool.execute.aftertool.execute.before
範例
以下是一些外掛程式範例,您可以使用它們來擴展 dropstone。
傳送通知
在某些事件發生時傳送通知:
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"'`
}
},
}
}
我們使用 osascript 在 macOS 上執行 AppleScript。在這裡我們使用它來傳送通知。
.env 保護
防止 dropstone 讀取 .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")
}
},
}
}
注入環境變數
將環境變數注入所有殼層執行(AI 工具和使用者終端):
export const InjectEnvPlugin = async () => {
return {
"shell.env": async (input, output) => {
output.env.MY_API_KEY = "secret"
output.env.PROJECT_ROOT = input.cwd
},
}
}
自訂工具
外掛程式也可以將自訂工具新增到 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})`
},
}),
},
}
}
tool 輔助程式建立一個 dropstone 可以呼叫的自訂工具。它採用 Zod 結構描述函數並傳回具有以下內容的工具定義:
description:工具的功能args:工具引數的 Zod 結構描述execute:呼叫工具時執行的函數
您的自訂工具將與內建工具一起提供給 dropstone。
Note:
如果外掛程式工具使用與內建工具相同的名稱,外掛程式工具優先。
記錄
使用 client.app.log() 而不是 console.log 進行結構化記錄:
export const MyPlugin = async ({ client }) => {
await client.app.log({
body: {
service: "my-plugin",
level: "info",
message: "Plugin initialized",
extra: { foo: "bar" },
},
})
}
層級:debug、info、warn、error。詳見 SDK 參考。
壓縮掛接
自訂工作階段壓縮時包含的上下文:
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
`)
},
}
}
experimental.session.compacting 掛接在 LLM 產生延續摘要之前觸發。使用它來注入預設壓縮提示會遺漏的特定領域上下文。
您也可以透過設定 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.
`
},
}
}
設定 output.prompt 時,它會完全取代預設壓縮提示。在此情況下,output.context 陣列會被忽略。