Dropstone Docs

Ferramentas Personalizadas

Crie ferramentas que o LLM pode chamar no dropstone.

Ferramentas personalizadas são funções que você cria e que o LLM pode chamar durante conversas. Elas funcionam junto com as ferramentas integradas do Dropstone, como read, write e bash.


Criando uma ferramenta

As ferramentas são definidas como arquivos TypeScript ou JavaScript. A definição da ferramenta em si é TS/JS, mas o trabalho que ela realiza pode ser implementado em qualquer linguagem: scripts shell, Python, Go, qualquer coisa que você possa executar com os auxiliares de shell do Bun.


Localização

Elas podem ser definidas:

  • Localmente, colocando-as no diretório .dropstone/tools/ do seu projeto.
  • Ou globalmente, colocando-as em ~/.config/dropstone/tools/.

Estrutura

A forma mais fácil de criar ferramentas é usando o auxiliar tool(), que fornece segurança de tipo e validação.

import { tool } from "@blankline/dropstone-plugin"

export default tool({
  description: "Query the project database",
  args: {
    query: tool.schema.string().describe("SQL query to execute"),
  },
  async execute(args) {
    // Your database logic here
    return `Executed query: ${args.query}`
  },
})

O nome do arquivo se torna o nome da ferramenta. O acima cria uma ferramenta database.


Múltiplas ferramentas por arquivo

Você também pode exportar múltiplas ferramentas de um único arquivo. Cada exportação se torna uma ferramenta separada com o nome <filename>_<exportname>:

import { tool } from "@blankline/dropstone-plugin"

export const add = tool({
  description: "Add two numbers",
  args: {
    a: tool.schema.number().describe("First number"),
    b: tool.schema.number().describe("Second number"),
  },
  async execute(args) {
    return args.a + args.b
  },
})

export const multiply = tool({
  description: "Multiply two numbers",
  args: {
    a: tool.schema.number().describe("First number"),
    b: tool.schema.number().describe("Second number"),
  },
  async execute(args) {
    return args.a * args.b
  },
})

Isso cria duas ferramentas: math_add e math_multiply.


Colisões de nomes com ferramentas integradas

Ferramentas personalizadas são identificadas pelo nome da ferramenta. Se uma ferramenta personalizada usar o mesmo nome de uma ferramenta integrada, a ferramenta personalizada tem precedência.

Por exemplo, este arquivo substitui a ferramenta bash integrada:

import { tool } from "@blankline/dropstone-plugin"

export default tool({
  description: "Restricted bash wrapper",
  args: {
    command: tool.schema.string(),
  },
  async execute(args) {
    return `blocked: ${args.command}`
  },
})

Note:

Prefira nomes únicos, a menos que você queira intencionalmente substituir uma ferramenta integrada. Se você quiser desabilitar uma ferramenta integrada mas não substituí-la, use permissions.


Argumentos

Você pode usar tool.schema, que é apenas Zod, para definir tipos de argumentos.

args: {
  query: tool.schema.string().describe("SQL query to execute")
}

Você também pode importar Zod diretamente e retornar um objeto simples:

import { z } from "zod"

export default {
  description: "Tool description",
  args: {
    param: z.string().describe("Parameter description"),
  },
  async execute(args, context) {
    // Tool implementation
    return "result"
  },
}

Contexto

As ferramentas recebem contexto sobre a sessão atual:

import { tool } from "@blankline/dropstone-plugin"

export default tool({
  description: "Get project information",
  args: {},
  async execute(args, context) {
    // Access context information
    const { agent, sessionID, messageID, directory, worktree } = context
    return `Agent: ${agent}, Session: ${sessionID}, Message: ${messageID}, Directory: ${directory}, Worktree: ${worktree}`
  },
})

Use context.directory para o diretório de trabalho da sessão. Use context.worktree para a raiz do git worktree.


Exemplos

Escrever uma ferramenta em Python

Você pode escrever suas ferramentas em qualquer linguagem que desejar. Aqui está um exemplo que adiciona dois números usando Python.

Primeiro, crie a ferramenta como um script Python:

import sys

a = int(sys.argv[1])
b = int(sys.argv[2])
print(a + b)

Depois crie a definição da ferramenta que a invoca:

import { tool } from "@blankline/dropstone-plugin"
import path from "path"

export default tool({
  description: "Add two numbers using Python",
  args: {
    a: tool.schema.number().describe("First number"),
    b: tool.schema.number().describe("Second number"),
  },
  async execute(args, context) {
    const script = path.join(context.worktree, ".dropstone/tools/add.py")
    const result = await Bun.$`python3 ${script} ${args.a} ${args.b}`.text()
    return result.trim()
  },
})

Aqui estamos usando o utilitário Bun.$ para executar o script Python.

Ctrl+I