SDK Dropstone
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 tanpa antarmuka 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 tanpa antarmuka
Untuk pipeline CI, otomatisasi, dan serverless, Anda tidak memerlukan CLI sama sekali. Gunakan klien tanpa antarmuka, yang berbicara langsung ke HTTP API Dropstone dengan kunci API:
import { createDropstoneApi } from "@blankline/dropstone-sdk"
// Membaca DROPSTONE_API_KEY dari lingkungan 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 Pengaturan → API di dropstone.io/dashboard/settings dan buat kunci — bentuknya seperti
dsk_live_<43 karakter>. - Atur sebagai variabel lingkungan (atau teruskan
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 sesuai pemakaian dari saldo kredit prabayar Anda — tunjangan paket tidak berlaku. Lihat Penggunaan & batas.
Streaming bekerja dengan cara yang sama, dan klien ini kompatibel dengan OpenAI — Anda dapat mengarahkan OpenAI SDK ke URL dasar 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 teruskan 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 diperlukan. Kunci API ditolak di /v1, dan agen build default bertanya sebelum setiap panggilan alat, jadi tanpa daftar izin, proses 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 | Tipe | Deskripsi | Default |
|---|---|---|---|
hostname | string | Nama host server | 127.0.0.1 |
port | number | Port server | 4096 |
signal | AbortSignal | Sinyal pembatalan untuk pembatalan | undefined |
timeout | number | Waktu tunggu dalam ms untuk mulai server | 5000 |
config | Config | Objek konfigurasi | {} |
Konfigurasi
Anda dapat meneruskan objek konfigurasi untuk menyesuaikan perilaku. Instance tetap mengambil 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) |
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 repositori, 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 berbagai permukaan dan proyek. Keduanya memecahkan masalah yang berbeda dan bekerja paling baik bersama — aturan proyek di AGENTS.md, memori pribadi lintas-permukaan 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 | Tipe | Deskripsi | Default |
|---|---|---|---|
baseUrl | string | URL server | http://localhost:4096 |
fetch | function | Implementasi fetch kustom | globalThis.fetch |
parseAs | string | Metode penguraian respons | auto |
responseStyle | string | Gaya pengembalian: data atau fields | fields |
throwOnError | boolean | Lempar kesalahan 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, jadi nama yang Anda lihat di TypeScript dipetakan satu-ke-satu ke bentuk permintaan dan respons server.
Kesalahan
SDK dapat melempar kesalahan 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"] }
Tipe Format Output
| Tipe | 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:
| Bidang | Tipe | 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 Kesalahan
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 yang 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()
Proyek
| 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()
Konfigurasi
| Metode | Deskripsi | Respons |
|---|---|---|
config.get() | Dapatkan info konfigurasi | Config |
Contoh
const config = await client.config.get()
Sesi
| 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 }) | Kembalikan pesan | Mengembalikan Session |
session.unrevert({ path }) | Pulihkan pesan yang dikembalikan | 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." }],
},
})
File
| 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 ruang kerja | 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 akar 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" },
})
Peristiwa
| Metode | Deskripsi | Respons |
|---|---|---|
event.subscribe() | Aliran peristiwa yang dikirim server | Aliran peristiwa yang dikirim server |
Contoh
// Dengarkan peristiwa waktu nyata
const events = await client.event.subscribe()
for await (const event of events.stream) {
console.log("Peristiwa:", event.type, event.properties)
}
API v2
SDK menyediakan 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. Titik akhir baru hanya tersedia di v2.