Dropstone Docs

SDK do Dropstone

Cliente JS com tipagem segura para o runtime do agente Dropstone. As sessões do SDK herdam a memória entre superfícies do Dropstone (Continuity) — uma memória persistente compartilhada com a CLI, o chat e o SDK.

O SDK JS/TS do Dropstone fornece um cliente com tipagem segura para interagir com o runtime do agente Dropstone. Ele inicia o dropstone serve como um subprocesso e fornece um cliente HTTP tipado apontando para ele. Como ele executa o mesmo agente local que a CLI usa, cada sessão do SDK herda a memória da sua conta — ensine uma vez na CLI, no chat ou no SDK e todas as superfícies já saberão (veja Memória (Continuity)).

Precisa de acesso headless à API em CI?:

Para uso puramente programático (pipelines de CI, automação, serverless), prefira a API HTTP com uma DROPSTONE_API_KEY. O SDK desta página é destinado a incorporar o agente interativo em um processo Node onde o binário da CLI está instalado junto.

Veja a página do Servidor para entender como a API HTTP subjacente funciona.


Instalação

Instale o SDK a partir do npm:

npm install @blankline/dropstone-sdk

Cliente headless de API

Para pipelines de CI, automação e serverless, você não precisa da CLI. Use o cliente headless, que fala diretamente com a API HTTP do Dropstone usando uma chave de API:

import { createDropstoneApi } from "@blankline/dropstone-sdk"

// Lê DROPSTONE_API_KEY do ambiente automaticamente.
const dropstone = createDropstoneApi()

const resp = await dropstone.chat.completions.create({
  model: "dropstone-fast", // ou "dropstone-pro" / "dropstone-heavy"
  messages: [{ role: "user", content: "Escreva um haicai sobre depuração." }],
})

console.log(resp.choices[0].message.content)
console.log("Custo: $" + resp.usage?.cost) // valor cobrado, em USD

Obter uma chave de API

  1. Entre em dropstone.io/dashboard.
  2. Abra Configurações → API em dropstone.io/dashboard/settings e crie uma chave — ela se parece com dsk_live_<43 caracteres>.
  3. Defina-a como uma variável de ambiente (ou passe apiKey para createDropstoneApi):
export DROPSTONE_API_KEY=dsk_live_...

Note:

Trate sua chave de API como uma senha. Nunca a envie para o git nem a incorpore em um bundle de frontend. As solicitações com chave de API são cobradas conforme o uso a partir do seu saldo de crédito pré-pago — as franquias do plano não se aplicam. Veja Uso e limites.

O streaming funciona da mesma forma, e o cliente é compatível com OpenAI — você pode apontar o SDK da OpenAI para a URL base do Dropstone:

const stream = await dropstone.chat.completions.create({
  model: "dropstone-fast",
  stream: true,
  messages: [{ role: "user", content: "Conte até 5." }],
})

for await (const chunk of stream) {
  process.stdout.write(chunk.choices?.[0]?.delta?.content ?? "")
}

Veja a página da API HTTP para a referência completa.


Criar cliente

Crie uma instância do dropstone:

import { createDropstone } from "@blankline/dropstone-sdk"

const { client } = await createDropstone()

Isso inicia tanto um servidor quanto um cliente. Cada método do SDK retorna { data, request, response }, então acesse o payload via .data.

Opções

OpçãoTipoDescriçãoPadrão
hostnamestringHostname do servidor127.0.0.1
portnumberPorta do servidor4096
signalAbortSignalSinal de abortamento para cancelamentoundefined
timeoutnumberTempo limite em ms para iniciar o servidor5000
configConfigObjeto de configuração{}

Configuração

Você pode passar um objeto de configuração para personalizar o comportamento. A instância ainda capta o seu dropstone.json, mas você pode substituir ou adicionar configuração inline:

import { createDropstone } from "@blankline/dropstone-sdk"

const dropstone = await createDropstone({
  hostname: "127.0.0.1",
  port: 4096,
  config: {
    model: "dropstone/dropstone-pro",
  },
})

console.log(`Servidor rodando em ${dropstone.server.url}`)

dropstone.server.close()

Memória (Continuity)

O Dropstone mantém uma memória persistente por conta. Chamamos isso de Continuity — uma memória entre superfícies compartilhada pela CLI, chat, VS Code e SDK. Ensine uma vez em qualquer lugar e todas as superfícies já saberão.

As sessões que você executa pelo SDK usam a mesma memória de conta da CLI. O que você ensina à CLI já é conhecido pelas sessões do SDK, e o que uma sessão do SDK registra fica disponível de volta na CLI e no chat. A cada turno, o agente recupera automaticamente a memória relevante antes de responder, para não reaprender o que já sabe.

O agente do SDK também pode ler e escrever memória diretamente, com as mesmas ferramentas da CLI:

FerramentaFinalidade
memory_recallRecuperar as lições mais relevantes para a tarefa atual
record_lessonSalvar uma lição durável (uma regra ou um fato)
list_lessonsMostrar tudo o que ele aprendeu sobre você
forget_lessonRemover uma lição

Note:

A memória exige que você esteja conectado ao Dropstone. O servidor do SDK lê o mesmo auth.json que a CLI, então entre uma vez com dropstone e as sessões do SDK herdarão a mesma memória de conta. Nada é armazenado se você não estiver conectado.

Exemplo

Declare uma preferência a partir do código e ela será registrada da mesma forma que seria na CLI — visível na CLI e no chat depois:

const { client } = await createDropstone()

const session = await client.session.create({ body: { title: "Ensinar memória" } })

await client.session.prompt({
  path: { id: session.data.id },
  body: {
    parts: [{ type: "text", text: "Lembre-se disso como uma regra permanente: use sempre bun, não npm." }],
  },
})

Continuity vs AGENTS.md

O AGENTS.md é um arquivo de projeto que você envia para o Git para convenções de equipe — estável, com escopo no repositório e compartilhado com qualquer pessoa que o clone. Continuity é a sua memória privada de conta: o que você ensina na CLI, no chat ou no SDK acompanha sua conta entre superfícies e projetos. Eles resolvem problemas diferentes e funcionam melhor juntos — regras de projeto no AGENTS.md, memória pessoal entre superfícies no Continuity. Veja Regras e Memória.

O que é lembrado

A memória armazena apenas as regras e os fatos que você ensina explicitamente — preferências, convenções e correções que valem a pena carregar entre sessões. Ela é distinta do contexto efêmero de uma única sessão, que não é mantido após o término da sessão.

Veja a página Memória para saber como o Dropstone decide o que manter.


Somente cliente

Se você já tem uma instância do dropstone em execução, pode criar uma instância de cliente para se conectar a ela:

import { createDropstoneClient } from "@blankline/dropstone-sdk"

const client = createDropstoneClient({
  baseUrl: "http://localhost:4096",
})

Opções

OpçãoTipoDescriçãoPadrão
baseUrlstringURL do servidorhttp://localhost:4096
fetchfunctionImplementação de fetch personalizadaglobalThis.fetch
parseAsstringMétodo de análise da respostaauto
responseStylestringEstilo de retorno: data ou fieldsfields
throwOnErrorbooleanLançar erros em vez de retornarfalse

Tipos

O SDK inclui definições TypeScript para todos os tipos de API. Importe-os diretamente:

import type { Session, Message, Part } from "@blankline/dropstone-sdk"

Todos os tipos são gerados a partir da especificação OpenAPI do servidor, então os nomes que você vê no TypeScript correspondem um a um às formas de solicitação e resposta do servidor.


Erros

O SDK pode lançar erros que você pode capturar e tratar:

try {
  await client.session.get({ path: { id: "invalid-id" } })
} catch (error) {
  console.error("Falha ao obter a sessão:", (error as Error).message)
}

Saída estruturada

Você pode solicitar saída JSON estruturada do modelo especificando um format com um schema JSON. O modelo usará uma ferramenta StructuredOutput para retornar JSON validado que corresponde ao seu schema.

Uso básico

const result = await client.session.prompt({
  path: { id: sessionId },
  body: {
    parts: [{ type: "text", text: "Pesquise o Dropstone e forneça informações da empresa" }],
    format: {
      type: "json_schema",
      schema: {
        type: "object",
        properties: {
          company: { type: "string", description: "Nome da empresa" },
          founded: { type: "number", description: "Ano de fundação" },
          products: {
            type: "array",
            items: { type: "string" },
            description: "Principais produtos",
          },
        },
        required: ["company", "founded"],
      },
    },
  },
})

// Acesse a saída estruturada
console.log(result.data.info.structured_output)
// { company: "Dropstone", founded: 2024, products: ["Dropstone CLI"] }

Tipos de formato de saída

TipoDescrição
textPadrão. Resposta de texto padrão (sem saída estruturada)
json_schemaRetorna JSON validado correspondente ao schema fornecido

Formato do schema JSON

Ao usar type: 'json_schema', forneça:

CampoTipoDescrição
type'json_schema'Obrigatório. Especifica o modo de schema JSON
schemaobjectObrigatório. Objeto de schema JSON que define a estrutura de saída
retryCountnumberOpcional. Número de tentativas de validação (padrão: 2)

Tratamento de erros

Se o modelo falhar ao produzir saída estruturada válida após todas as tentativas, a resposta incluirá um StructuredOutputError:

if (result.data.info.error?.name === "StructuredOutputError") {
  console.error("Falha ao produzir saída estruturada:", result.data.info.error.message)
  console.error("Tentativas:", result.data.info.error.retries)
}

Melhores práticas

  1. Forneça descrições claras nas propriedades do seu schema para ajudar o modelo a entender quais dados extrair
  2. Use required para especificar quais campos devem estar presentes
  3. Mantenha os schemas focados — schemas aninhados complexos podem ser mais difíceis para o modelo preencher corretamente
  4. Defina um retryCount adequado — aumente para schemas complexos, diminua para os simples

APIs

O SDK expõe todas as APIs do servidor por meio de um cliente com tipagem segura.


Global

MétodoDescriçãoResposta
global.health()Verificar saúde e versão do servidor{ healthy: true, version: string }

Exemplos

const health = await client.global.health()
console.log(health.data.version)

App

MétodoDescriçãoResposta
app.log()Escrever uma entrada de logboolean
app.agents()Listar todos os agentes disponíveisAgent[]

Exemplos

// Escrever uma entrada de log
await client.app.log({
  body: {
    service: "my-app",
    level: "info",
    message: "Operação concluída",
  },
})

// Listar agentes disponíveis
const agents = await client.app.agents()

Projeto

MétodoDescriçãoResposta
project.list()Listar todos os projetosProject[]
project.current()Obter o projeto atualProject

Exemplos

// Listar todos os projetos
const projects = await client.project.list()

// Obter o projeto atual
const currentProject = await client.project.current()

Caminho

MétodoDescriçãoResposta
path.get()Obter o caminho atualPath

Exemplos

// Obter informações do caminho atual
const pathInfo = await client.path.get()

Configuração

MétodoDescriçãoResposta
config.get()Obter informações de configuraçãoConfig

Exemplos

const config = await client.config.get()

Sessões

MétodoDescriçãoNotas
session.list()Listar sessõesRetorna Session[]
session.get({ path })Obter sessãoRetorna Session
session.children({ path })Listar sessões filhasRetorna Session[]
session.create({ body })Criar sessãoRetorna Session
session.delete({ path })Excluir sessãoRetorna boolean
session.update({ path, body })Atualizar propriedades da sessãoRetorna Session
session.init({ path, body })Analisar o app e criar AGENTS.mdRetorna boolean
session.abort({ path })Abortar uma sessão em execuçãoRetorna boolean
session.summarize({ path, body })Resumir sessãoRetorna boolean
session.messages({ path })Listar mensagens em uma sessãoRetorna { info: Message, parts: Part[]}[]
session.message({ path })Obter detalhes da mensagemRetorna { info: Message, parts: Part[]}
session.prompt({ path, body })Enviar mensagem de promptbody.noReply: true retorna UserMessage (somente contexto). O padrão retorna AssistantMessage com resposta da IA. Suporta body.outputFormat para saída estruturada
session.command({ path, body })Enviar comando para a sessãoRetorna { info: AssistantMessage, parts: Part[]}
session.shell({ path, body })Executar um comando de shellRetorna AssistantMessage
session.revert({ path, body })Reverter uma mensagemRetorna Session
session.unrevert({ path })Restaurar mensagens revertidasRetorna Session
postSessionByIdPermissionsByPermissionId({ path, body })Responder a uma solicitação de permissãoRetorna boolean

Exemplos

// Criar e gerenciar sessões
const session = await client.session.create({
  body: { title: "Minha sessão" },
})

const sessions = await client.session.list()

// Enviar uma mensagem de prompt
const result = await client.session.prompt({
  path: { id: session.data.id },
  body: {
    model: { providerID: "dropstone", modelID: "dropstone-pro" },
    parts: [{ type: "text", text: "Olá!" }],
  },
})

// Injetar contexto sem acionar resposta da IA (útil para plugins)
await client.session.prompt({
  path: { id: session.data.id },
  body: {
    noReply: true,
    parts: [{ type: "text", text: "Você é um assistente útil." }],
  },
})

Arquivos

MétodoDescriçãoResposta
find.text({ query })Buscar texto em arquivosMatriz de objetos de correspondência com path, lines, line_number, absolute_offset, submatches
find.files({ query })Encontrar arquivos e diretórios por nomestring[] (caminhos)
find.symbols({ query })Encontrar símbolos do workspaceSymbol[]
file.read({ query })Ler um arquivo{ type: "raw" | "patch", content: string }
file.status({ query? })Obter status de arquivos rastreadosFile[]

find.files suporta alguns campos de consulta opcionais:

  • type: "file" ou "directory"
  • directory: substituir a raiz do projeto para a busca
  • limit: máximo de resultados (1–200)

Exemplos

// Buscar e ler arquivos
const textResults = await client.find.text({
  query: { pattern: "function.*dropstone" },
})

const files = await client.find.files({
  query: { query: "*.ts", type: "file" },
})

const directories = await client.find.files({
  query: { query: "packages", type: "directory", limit: 20 },
})

const content = await client.file.read({
  query: { path: "src/index.ts" },
})

Autenticação

MétodoDescriçãoResposta
auth.set({ ... })Definir credenciais de autenticaçãoboolean

Exemplos

await client.auth.set({
  path: { id: "dropstone" },
  body: { type: "api", key: "sua-chave-de-api-do-dropstone" },
})

Eventos

MétodoDescriçãoResposta
event.subscribe()Fluxo de eventos enviados pelo servidorFluxo de eventos enviados pelo servidor

Exemplos

// Ouvir eventos em tempo real
const events = await client.event.subscribe()
for await (const event of events.stream) {
  console.log("Evento:", event.type, event.properties)
}

API v2

O SDK inclui uma superfície v1 estável (usada nos exemplos acima) e uma superfície v2 que espelha o contrato mais recente do Effect HttpApi. Prefira v2 para novas integrações:

import { createDropstone } from "@blankline/dropstone-sdk/v2"

const { client, server } = await createDropstone()
// v2 expõe uma hierarquia de recursos mais rica: workspace, worktree, file, find, etc.
const files = await client.file.list({ path: "src" })

A superfície v1 é mantida para compatibilidade com versões anteriores. Novos endpoints só são adicionados na v2.

Ctrl+I