Dropstone SDK
Klien JS yang aman terhadap tipe untuk runtime agen Dropstone. Sesi SDK mewarisi memori lintas-permukaan Dropstone (Continuity) — satu memori persisten yang dibagikan dengan CLI, chat, dan SDK.
SDK JS/TS Dropstone menyediakan klien yang aman terhadap tipe untuk berinteraksi dengan runtime agen Dropstone. SDK ini menjalankan dropstone serve sebagai subproses dan memberi Anda klien HTTP bertipe yang mengarah ke sana. Karena SDK menjalankan agen lokal yang sama dengan yang digunakan CLI, setiap sesi SDK mewarisi memori akun Anda — ajari sekali di CLI, chat, atau SDK dan setiap permukaan sudah mengetahuinya (lihat Memori (Continuity)).
Butuh akses API headless di CI?
Untuk penggunaan programatik murni (pipeline CI, otomatisasi, serverless), gunakan HTTP API dengan DROPSTONE_API_KEY. SDK di halaman ini ditujukan untuk menyematkan agen interaktif dalam proses Node tempat biner CLI terpasang di sampingnya.
Lihat halaman Server untuk cara kerja HTTP API yang mendasarinya.
Instalasi
Instal SDK dari npm:
npm install @blankline/dropstone-sdk
Klien API headless
Untuk pipeline CI, otomatisasi, dan serverless, Anda tidak memerlukan CLI sama sekali. Gunakan klien headless, yang berbicara langsung ke HTTP API Dropstone dengan kunci API:
import { createDropstoneApi } from "@blankline/dropstone-sdk"
// Membaca DROPSTONE_API_KEY dari environment secara otomatis.
const dropstone = createDropstoneApi()
const resp = await dropstone.chat.completions.create({
model: "dropstone-fast", // atau "dropstone-pro" / "dropstone-heavy"
messages: [{ role: "user", content: "Tulis haiku tentang debugging." }],
})
console.log(resp.choices[0].message.content)
console.log("Biaya: $" + resp.usage?.cost) // jumlah yang ditagih, dalam USD
Dapatkan kunci API
- Masuk di dropstone.io/dashboard.
- Buka Settings → API di dropstone.io/dashboard/settings dan buat kunci — bentuknya seperti
dsk_live_<43 karakter>. - Atur sebagai variabel environment (atau berikan
apiKeykecreateDropstoneApi):
export DROPSTONE_API_KEY=dsk_live_...
Note
Perlakukan kunci API Anda seperti kata sandi. Jangan pernah mengirimkannya ke git atau menyematkannya dalam bundel frontend. Permintaan dengan kunci API ditagih pay-per-use dari saldo kredit prabayar Anda — tunjangan paket tidak berlaku. Lihat Penggunaan & batas.
Streaming bekerja dengan cara yang sama, dan kliennya kompatibel dengan OpenAI — Anda dapat mengarahkan OpenAI SDK ke base URL Dropstone sebagai gantinya:
const stream = await dropstone.chat.completions.create({
model: "dropstone-fast",
stream: true,
messages: [{ role: "user", content: "Hitung sampai 5." }],
})
for await (const chunk of stream) {
process.stdout.write(chunk.choices?.[0]?.delta?.content ?? "")
}
Lihat halaman HTTP API untuk referensi lengkap.
Buat klien
Buat instance dropstone:
import { createDropstone } from "@blankline/dropstone-sdk"
const { client } = await createDropstone()
Ini memulai server dan klien sekaligus. Setiap metode SDK mengembalikan { data, request, response }, jadi akses payload melalui .data.
Secara default, server masuk sebagai siapa pun yang menjalankan dropstone auth login di mesin tersebut. Di host tanpa pengawasan tidak ada akun seperti itu, jadi berikan kunci API dan daftar izin eksplisit melalui config:
const { client } = await createDropstone({
config: {
provider: {
dropstone: {
options: {
apiKey: process.env.DROPSTONE_API_KEY,
baseURL: "https://api.dropstone.io/api/v1",
},
},
},
permission: { "*": "deny", read: "allow", edit: "allow", glob: "allow", grep: "allow", bash: "allow" },
},
})
Kedua bagian tersebut wajib. Kunci API ditolak di /v1, dan agen build default bertanya sebelum setiap panggilan alat, jadi tanpa daftar izin, proses akan menunggu persetujuan yang tidak bisa diberikan siapa pun dan menggantung alih-alih gagal. Mengirim "agent": "accept all" pada prompt adalah alternatif untuk daftar izin. Lihat Server dan Izin.
Opsi
| Opsi | Jenis | Deskripsi | Default |
|---|---|---|---|
hostname | string | Hostname server | 127.0.0.1 |
port | number | Port server | 4096 |
signal | AbortSignal | Sinyal pembatalan untuk pembatalan | undefined |
timeout | number | Timeout dalam ms untuk mulai server | 5000 |
config | Config | Objek konfigurasi | {} |
Konfigurasi
Anda dapat memberikan objek konfigurasi untuk menyesuaikan perilaku. Instance tetap membaca dropstone.json Anda, tetapi Anda dapat menimpa atau menambahkan konfigurasi secara 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(`Server berjalan di ${dropstone.server.url}`)
dropstone.server.close()
Memori (Continuity)
Dropstone menyimpan satu memori persisten per akun. Kami menyebutnya Continuity — memori lintas-permukaan yang dibagikan oleh CLI, chat, VS Code, dan SDK. Ajari sekali di mana saja dan setiap permukaan sudah mengetahuinya.
Sesi yang Anda jalankan melalui SDK menggunakan memori akun yang sama dengan CLI. Apa yang Anda ajarkan ke CLI sudah diketahui oleh sesi SDK, dan apa yang dicatat sesi SDK tersedia kembali di CLI dan chat. Pada setiap giliran, agen secara otomatis mengingat kembali memori yang relevan sebelum menjawab, sehingga tidak perlu mempelajari ulang apa yang sudah diketahuinya.
Agen SDK juga dapat membaca dan menulis memori secara langsung, dengan alat yang sama seperti CLI:
| Alat | Tujuan |
|---|---|
memory_recall | Mengingat kembali pelajaran yang paling relevan untuk tugas saat ini |
record_lesson | Menyimpan pelajaran yang tahan lama (aturan atau fakta) |
edit_lesson | Menulis ulang pelajaran yang tersimpan di tempatnya jika sudah usang atau kata-katanya buruk |
list_lessons | Menampilkan semua yang telah dipelajari tentang Anda |
forget_lesson | Menghapus pelajaran |
Note
Memori memerlukan masuk ke Dropstone. Server SDK membaca auth.json yang sama dengan CLI, jadi masuk sekali dengan dropstone dan sesi SDK mewarisi memori akun yang sama. Tidak ada yang disimpan jika Anda tidak masuk.
Contoh
Nyatakan preferensi dari kode dan itu dicatat dengan cara yang sama seperti di CLI — terlihat di CLI dan chat setelahnya:
const { client } = await createDropstone()
const session = await client.session.create({ body: { title: "Ajari memori" } })
await client.session.prompt({
path: { id: session.data.id },
body: {
parts: [{ type: "text", text: "Ingat ini sebagai aturan tetap: selalu gunakan bun, bukan npm." }],
},
})
Continuity vs AGENTS.md
AGENTS.md adalah file proyek yang Anda kirim ke Git untuk konvensi tim — stabil, terbatas pada repo, dan dibagikan dengan siapa pun yang mengkloningnya. Continuity adalah memori akun pribadi Anda: apa yang Anda ajarkan di CLI, chat, atau SDK mengikuti akun Anda di seluruh permukaan dan proyek. Keduanya memecahkan masalah yang berbeda dan bekerja paling baik bersama — aturan proyek di AGENTS.md, memori lintas-permukaan pribadi di Continuity. Lihat Aturan dan Memori.
Apa yang diingat
Memori hanya menyimpan aturan dan fakta yang secara eksplisit Anda ajarkan — preferensi, konvensi, dan koreksi yang layak dibawa antar sesi. Ini berbeda dari konteks sementara satu sesi, yang tidak disimpan setelah sesi berakhir.
Lihat halaman Memori untuk cara Dropstone memutuskan apa yang disimpan.
Klien saja
Jika Anda sudah memiliki instance dropstone yang berjalan, Anda dapat membuat instance klien untuk terhubung ke sana:
import { createDropstoneClient } from "@blankline/dropstone-sdk"
const client = createDropstoneClient({
baseUrl: "http://localhost:4096",
})
Opsi
| Opsi | Jenis | Deskripsi | Default |
|---|---|---|---|
baseUrl | string | URL server | http://localhost:4096 |
fetch | function | Implementasi fetch kustom | globalThis.fetch |
parseAs | string | Metode parsing respons | auto |
responseStyle | string | Gaya pengembalian: data atau fields | fields |
throwOnError | boolean | Lempar error alih-alih mengembalikan | false |
Tipe
SDK menyertakan definisi TypeScript untuk semua tipe API. Impor langsung:
import type { Session, Message, Part } from "@blankline/dropstone-sdk"
Semua tipe dihasilkan dari spesifikasi OpenAPI server, sehingga nama yang Anda lihat di TypeScript memetakan satu-ke-satu ke bentuk permintaan dan respons server.
Error
SDK dapat melempar error yang dapat Anda tangkap dan tangani:
try {
await client.session.get({ path: { id: "invalid-id" } })
} catch (error) {
console.error("Gagal mendapatkan sesi:", (error as Error).message)
}
Output Terstruktur
Anda dapat meminta output JSON terstruktur dari model dengan menentukan format dengan skema JSON. Model akan menggunakan alat StructuredOutput untuk mengembalikan JSON tervalidasi yang cocok dengan skema Anda.
Penggunaan Dasar
const result = await client.session.prompt({
path: { id: sessionId },
body: {
parts: [{ type: "text", text: "Riset Dropstone dan berikan info perusahaan" }],
format: {
type: "json_schema",
schema: {
type: "object",
properties: {
company: { type: "string", description: "Nama perusahaan" },
founded: { type: "number", description: "Tahun didirikan" },
products: {
type: "array",
items: { type: "string" },
description: "Produk utama",
},
},
required: ["company", "founded"],
},
},
},
})
// Akses output terstruktur
console.log(result.data.info.structured_output)
// { company: "Dropstone", founded: 2024, products: ["Dropstone CLI"] }
Jenis Format Output
| Jenis | Deskripsi |
|---|---|
text | Default. Respons teks standar (tanpa output terstruktur) |
json_schema | Mengembalikan JSON tervalidasi yang cocok dengan skema yang diberikan |
Format Skema JSON
Saat menggunakan type: 'json_schema', berikan:
| Field | Jenis | Deskripsi |
|---|---|---|
type | 'json_schema' | Wajib. Menentukan mode skema JSON |
schema | object | Wajib. Objek Skema JSON yang mendefinisikan struktur output |
retryCount | number | Opsional. Jumlah percobaan validasi (default: 2) |
Penanganan Error
Jika model gagal menghasilkan output terstruktur yang valid setelah semua percobaan, respons akan menyertakan StructuredOutputError:
if (result.data.info.error?.name === "StructuredOutputError") {
console.error("Gagal menghasilkan output terstruktur:", result.data.info.error.message)
console.error("Percobaan:", result.data.info.error.retries)
}
Praktik Terbaik
- Berikan deskripsi yang jelas di properti skema Anda untuk membantu model memahami data apa yang harus diekstrak
- Gunakan
requireduntuk menentukan bidang mana yang harus ada - Jaga skema tetap fokus - skema bersarang yang kompleks mungkin lebih sulit diisi dengan benar oleh model
- Atur
retryCountyang sesuai - tingkatkan untuk skema kompleks, kurangi untuk skema sederhana
API
SDK mengekspos semua API server melalui klien yang aman terhadap tipe.
Global
| Metode | Deskripsi | Respons |
|---|---|---|
global.health() | Periksa kesehatan dan versi server | { healthy: true, version: string } |
Contoh
const health = await client.global.health()
console.log(health.data.version)
App
| Metode | Deskripsi | Respons |
|---|---|---|
app.log() | Tulis entri log | boolean |
app.agents() | Daftar semua agen yang tersedia | Agent[] |
Contoh
// Tulis entri log
await client.app.log({
body: {
service: "my-app",
level: "info",
message: "Operasi selesai",
},
})
// Daftar agen yang tersedia
const agents = await client.app.agents()
Project
| Metode | Deskripsi | Respons |
|---|---|---|
project.list() | Daftar semua proyek | Project[] |
project.current() | Dapatkan proyek saat ini | Project |
Contoh
// Daftar semua proyek
const projects = await client.project.list()
// Dapatkan proyek saat ini
const currentProject = await client.project.current()
Path
| Metode | Deskripsi | Respons |
|---|---|---|
path.get() | Dapatkan path saat ini | Path |
Contoh
// Dapatkan informasi path saat ini
const pathInfo = await client.path.get()
Config
| Metode | Deskripsi | Respons |
|---|---|---|
config.get() | Dapatkan info konfigurasi | Config |
Contoh
const config = await client.config.get()
Sessions
| Metode | Deskripsi | Catatan |
|---|---|---|
session.list() | Daftar sesi | Mengembalikan Session[] |
session.get({ path }) | Dapatkan sesi | Mengembalikan Session |
session.children({ path }) | Daftar sesi anak | Mengembalikan Session[] |
session.create({ body }) | Buat sesi | Mengembalikan Session |
session.delete({ path }) | Hapus sesi | Mengembalikan boolean |
session.update({ path, body }) | Perbarui properti sesi | Mengembalikan Session |
session.init({ path, body }) | Analisis aplikasi dan buat AGENTS.md | Mengembalikan boolean |
session.abort({ path }) | Batalkan sesi yang berjalan | Mengembalikan boolean |
session.summarize({ path, body }) | Ringkas sesi | Mengembalikan boolean |
session.messages({ path }) | Daftar pesan dalam sesi | Mengembalikan { info: Message, parts: Part[]}[] |
session.message({ path }) | Dapatkan detail pesan | Mengembalikan { info: Message, parts: Part[]} |
session.prompt({ path, body }) | Kirim pesan prompt | body.noReply: true mengembalikan UserMessage (hanya konteks). Default mengembalikan AssistantMessage dengan respons AI. Mendukung body.outputFormat untuk output terstruktur |
session.command({ path, body }) | Kirim perintah ke sesi | Mengembalikan { info: AssistantMessage, parts: Part[]} |
session.shell({ path, body }) | Jalankan perintah shell | Mengembalikan AssistantMessage |
session.revert({ path, body }) | Batalkan pesan | Mengembalikan Session |
session.unrevert({ path }) | Pulihkan pesan yang dibatalkan | Mengembalikan Session |
postSessionByIdPermissionsByPermissionId({ path, body }) | Tanggapi permintaan izin | Mengembalikan boolean |
Contoh
// Buat dan kelola sesi
const session = await client.session.create({
body: { title: "Sesi saya" },
})
const sessions = await client.session.list()
// Kirim pesan prompt
const result = await client.session.prompt({
path: { id: session.data.id },
body: {
model: { providerID: "dropstone", modelID: "dropstone-pro" },
parts: [{ type: "text", text: "Halo!" }],
},
})
// Suntikkan konteks tanpa memicu respons AI (berguna untuk plugin)
await client.session.prompt({
path: { id: session.data.id },
body: {
noReply: true,
parts: [{ type: "text", text: "Anda adalah asisten yang membantu." }],
},
})
Files
| Metode | Deskripsi | Respons |
|---|---|---|
find.text({ query }) | Cari teks dalam file | Array objek kecocokan dengan path, lines, line_number, absolute_offset, submatches |
find.files({ query }) | Temukan file dan direktori berdasarkan nama | string[] (path) |
find.symbols({ query }) | Temukan simbol workspace | Symbol[] |
file.read({ query }) | Baca file | { type: "raw" | "patch", content: string } |
file.status({ query? }) | Dapatkan status untuk file yang dilacak | File[] |
find.files mendukung beberapa bidang kueri opsional:
type:"file"atau"directory"directory: timpa root proyek untuk pencarianlimit: hasil maksimal (1–200)
Contoh
// Cari dan baca file
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" },
})
Auth
| Metode | Deskripsi | Respons |
|---|---|---|
auth.set({ ... }) | Atur kredensial autentikasi | boolean |
Contoh
await client.auth.set({
path: { id: "dropstone" },
body: { type: "api", key: "kunci-api-dropstone-anda" },
})
Events
| Metode | Deskripsi | Respons |
|---|---|---|
event.subscribe() | Aliran event yang dikirim server | Aliran event yang dikirim server |
Contoh
// Dengarkan event real-time
const events = await client.event.subscribe()
for await (const event of events.stream) {
console.log("Event:", event.type, event.properties)
}
API v2
SDK menyertakan permukaan v1 yang stabil (digunakan dalam contoh di atas) dan permukaan v2 yang mencerminkan kontrak Effect HttpApi yang lebih baru. Pilih v2 untuk integrasi baru:
import { createDropstone } from "@blankline/dropstone-sdk/v2"
const { client, server } = await createDropstone()
// v2 mengekspos hierarki sumber daya yang lebih kaya: workspace, worktree, file, find, dll.
const files = await client.file.list({ path: "src" })
Permukaan v1 dipertahankan untuk kompatibilitas mundur. Endpoint baru hanya mendarat di v2.