TypeScript SDK for the Factory Droid CLI. Provides a high-level API for interacting with Droid as a subprocess, with streaming message support, multi-turn sessions, and tool permission handling.
- Node.js 18+
- The
droidCLI installed and available on your PATH
npm install @factory/droid-sdkSend a one-shot prompt and stream the response:
import { query } from "@factory/droid-sdk";
const stream = query({
prompt: "What files are in the current directory?",
cwd: "/my/project",
});
for await (const msg of stream) {
if (msg.type === "assistant_text_delta") {
process.stdout.write(msg.text);
}
if (msg.type === "turn_complete") {
console.log("\nDone!");
}
}Use createSession() for persistent conversations with multiple turns:
import { createSession } from "@factory/droid-sdk";
const session = await createSession({ cwd: "/my/project" });
// Streaming turn
for await (const msg of session.stream("List all TypeScript files")) {
if (msg.type === "assistant_text_delta") {
process.stdout.write(msg.text);
}
}
// Non-streaming turn
const result = await session.send("Summarize the project");
console.log(result.text);
await session.close();Resume an existing session by ID:
import { resumeSession } from "@factory/droid-sdk";
const session = await resumeSession("session-id-here");
const result = await session.send("Continue where we left off");
console.log(result.text);
await session.close();Handle tool confirmation requests with a custom permission handler:
import { query, ToolConfirmationOutcome } from "@factory/droid-sdk";
const stream = query({
prompt: "Create a hello.txt file",
cwd: "/my/project",
permissionHandler(params) {
console.log("Tool permission requested:", params);
return ToolConfirmationOutcome.ProceedOnce;
},
});
for await (const msg of stream) {
if (msg.type === "assistant_text_delta") {
process.stdout.write(msg.text);
}
}| Function | Description |
|---|---|
query(options) |
One-shot prompt → async generator of DroidMessage events |
createSession(options?) |
Create a new multi-turn session → DroidSession |
resumeSession(id, options?) |
Resume an existing session → DroidSession |
Returns an async generator that yields DroidMessage events. The returned DroidQuery object also exposes:
interrupt()— gracefully interrupt the agent's current turnabort()— forcefully kill the subprocesssessionId— the session ID (available after initialization)
Returned by createSession() and resumeSession(). Key methods:
stream(text, options?)— send a message, returns async generator ofDroidMessagesend(text, options?)— send a message, returns aggregatedDroidResultinterrupt()— interrupt the current turnclose()— close the session and release resourcesupdateSettings(params)— update model, autonomy level, etc.addMcpServer(params)/removeMcpServer(params)— manage MCP serverssessionId— the session ID
Returned by session.send():
text— concatenated assistant response textmessages— allDroidMessageobjects from the turntokenUsage— final token usage, ornull
All messages have a discriminated type field:
| Type | Description |
|---|---|
assistant_text_delta |
Streaming text token from the assistant |
thinking_text_delta |
Streaming reasoning/thinking token |
tool_use |
Tool invocation by the assistant |
tool_result |
Result from a tool execution |
tool_progress |
Progress update during tool execution |
working_state_changed |
Agent working state transition |
token_usage_update |
Updated token usage counters |
create_message |
Full assistant message created |
turn_complete |
Sentinel: agent turn finished |
error |
Error event from the process |
QueryOptions and CreateSessionOptions accept:
prompt— the user prompt (query only)cwd— working directory for the sessionmodelId— LLM model identifierautonomyLevel—AutonomyLevelenum valuereasoningEffort—ReasoningEffortenum valuepermissionHandler— callback for tool confirmationsaskUserHandler— callback for interactive questionsexecPath— path todroidexecutable (default:"droid")transport— provide a custom transport instead of spawning a process
Low-level JSON-RPC client for advanced use. Provides typed methods for all 19 protocol operations. Most users should prefer query() and createSession().
| Error | Description |
|---|---|
ConnectionError |
Failed to connect to the droid process |
ProtocolError |
JSON-RPC protocol error |
SessionError |
Base session error |
SessionNotFoundError |
Session ID not found |
TimeoutError |
Request timed out |
ProcessExitError |
Droid subprocess exited unexpectedly |
See the examples/ directory for runnable examples:
simple-query.ts— one-shot query with streaming outputmulti-turn-session.ts— multi-turn session lifecyclepermission-handler.ts— custom permission handling
Apache 2.0