@factory/droid-sdk 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +214 -82
  2. package/dist/index.cjs +734 -611
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +1649 -206
  5. package/dist/index.d.ts +1649 -206
  6. package/dist/index.js +729 -624
  7. package/dist/index.js.map +1 -1
  8. package/docs/sdk-usage-guide.md +678 -0
  9. package/examples/abort-session-stream.ts +19 -55
  10. package/examples/droid-dev-structured-output.ts +4 -5
  11. package/examples/fork-session.ts +25 -6
  12. package/examples/hook-execution.ts +62 -0
  13. package/examples/init-metadata.ts +9 -66
  14. package/examples/interrupt-session.ts +19 -54
  15. package/examples/list-sessions.ts +9 -55
  16. package/examples/multi-turn-session.ts +21 -53
  17. package/examples/permission-handler.ts +26 -84
  18. package/examples/readme-structured-output.ts +25 -0
  19. package/examples/result-metadata.ts +1 -1
  20. package/examples/run.ts +1 -1
  21. package/examples/sdk-mcp-tool.ts +11 -7
  22. package/examples/session-stream.ts +54 -0
  23. package/examples/spec-mode-new-session.ts +38 -99
  24. package/examples/spec-mode-same-session.ts +49 -111
  25. package/examples/structured-output.ts +16 -10
  26. package/examples/test-compact.ts +5 -3
  27. package/examples/test-rewind.ts +49 -117
  28. package/examples/tool-controls.ts +22 -55
  29. package/package.json +1 -1
  30. package/docs/examples/init-metadata.md +0 -79
  31. package/docs/examples/list-sessions.md +0 -64
  32. package/docs/examples/multi-turn-session.md +0 -77
  33. package/docs/examples/one-shot-query.md +0 -73
  34. package/docs/examples/permission-handler.md +0 -102
  35. package/docs/examples/run.md +0 -52
  36. package/docs/examples/spec-mode.md +0 -101
  37. package/docs/examples/tool-controls.md +0 -90
  38. package/docs/typescript-sdk-reference.md +0 -372
  39. package/examples/simple-query.ts +0 -53
@@ -0,0 +1,678 @@
1
+ # SDK Usage Guide
2
+
3
+ ## Getting Started
4
+
5
+ ```bash
6
+ npm install @factory/droid-sdk
7
+ ```
8
+
9
+ Requires Node.js 18+ and the `droid` CLI on your PATH.
10
+
11
+ ```ts
12
+ import { run } from '@factory/droid-sdk';
13
+
14
+ const result = await run('What files are in this directory?', {
15
+ cwd: process.cwd(),
16
+ });
17
+ console.log(result.text);
18
+ ```
19
+
20
+ ---
21
+
22
+ ## One-shot Run
23
+
24
+ Send a prompt, get a result, done. The session is created and closed automatically.
25
+
26
+ ```ts
27
+ import { run } from '@factory/droid-sdk';
28
+
29
+ const result = await run('What is 2 + 2?', { cwd: process.cwd() });
30
+ console.log(result.text);
31
+ ```
32
+
33
+ ## Structured Output
34
+
35
+ Force the response to match a JSON schema. The validated object is available on `result.structuredOutput`.
36
+
37
+ ```ts
38
+ import { OutputFormatType, run } from '@factory/droid-sdk';
39
+
40
+ const result = await run('Pick a number between 1 and 42.', {
41
+ cwd: process.cwd(),
42
+ outputFormat: {
43
+ type: OutputFormatType.JsonSchema,
44
+ schema: {
45
+ type: 'object',
46
+ properties: { number: { type: 'number' } },
47
+ required: ['number'],
48
+ },
49
+ },
50
+ });
51
+
52
+ console.log((result.structuredOutput as { number: number }).number);
53
+ ```
54
+
55
+ ## Multi-turn Session
56
+
57
+ Create a session once, then call `stream()` multiple times. Context is preserved across turns.
58
+
59
+ ```ts
60
+ import { createSession } from '@factory/droid-sdk';
61
+
62
+ const session = await createSession({ cwd: process.cwd() });
63
+
64
+ for await (const msg of session.stream('Remember the word "mango".')) {
65
+ // consume first turn
66
+ }
67
+
68
+ for await (const msg of session.stream('What word did I say?')) {
69
+ if (msg.type === 'assistant') console.log(msg.text);
70
+ }
71
+
72
+ await session.close();
73
+ ```
74
+
75
+ ## Resume Session
76
+
77
+ Reconnect to a previously created session by its ID.
78
+
79
+ ```ts
80
+ import { resumeSession } from '@factory/droid-sdk';
81
+
82
+ const session = await resumeSession('existing-session-id');
83
+
84
+ for await (const msg of session.stream('Continue where we left off.')) {
85
+ if (msg.type === 'assistant') console.log(msg.text);
86
+ }
87
+
88
+ await session.close();
89
+ ```
90
+
91
+ ## Full Message Streaming
92
+
93
+ `stream()` yields complete messages: assistant text, tool calls, tool results, hooks, errors, and the final result.
94
+
95
+ ```ts
96
+ import { createSession, DroidMessageType } from '@factory/droid-sdk';
97
+
98
+ const session = await createSession({ cwd: process.cwd() });
99
+
100
+ for await (const msg of session.stream(
101
+ 'List files in the current directory.'
102
+ )) {
103
+ switch (msg.type) {
104
+ case DroidMessageType.Assistant:
105
+ console.log(msg.text);
106
+ break;
107
+ case DroidMessageType.ToolCall:
108
+ console.log(`[Tool] ${msg.toolUse.name}`);
109
+ break;
110
+ case DroidMessageType.ToolResult:
111
+ console.log(`[Result] ${msg.isError ? 'Error' : 'OK'}`);
112
+ break;
113
+ case DroidMessageType.Result:
114
+ console.log(`Done in ${msg.durationMs}ms`);
115
+ break;
116
+ }
117
+ }
118
+
119
+ await session.close();
120
+ ```
121
+
122
+ ## Partial Message Streaming
123
+
124
+ Enable `includePartialMessages` to get token-by-token deltas, thinking blocks, and tool progress as they arrive.
125
+
126
+ ```ts
127
+ import { createSession, DroidMessageType } from '@factory/droid-sdk';
128
+
129
+ const session = await createSession({ cwd: process.cwd() });
130
+
131
+ for await (const msg of session.stream('Explain recursion.', {
132
+ includePartialMessages: true,
133
+ })) {
134
+ if (msg.type === DroidMessageType.AssistantTextDelta) {
135
+ process.stdout.write(msg.text);
136
+ }
137
+ }
138
+
139
+ await session.close();
140
+ ```
141
+
142
+ ## Interrupt or Cancel Running Work
143
+
144
+ Use `session.interrupt()` to stop the current turn server-side, or pass an `AbortSignal` to cancel from the client.
145
+
146
+ ```ts
147
+ import { createSession } from '@factory/droid-sdk';
148
+
149
+ // Interrupt after receiving some output
150
+ const session = await createSession({ cwd: process.cwd() });
151
+ for await (const msg of session.stream('Write a long essay.')) {
152
+ if (msg.type === 'assistant') {
153
+ await session.interrupt();
154
+ }
155
+ }
156
+ await session.close();
157
+
158
+ // Or cancel with AbortSignal
159
+ const session2 = await createSession({ cwd: process.cwd() });
160
+ const controller = new AbortController();
161
+ setTimeout(() => controller.abort(), 2000);
162
+
163
+ try {
164
+ for await (const msg of session2.stream('Write a long essay.', {
165
+ abortSignal: controller.signal,
166
+ })) {
167
+ }
168
+ } catch {
169
+ console.log('Aborted');
170
+ }
171
+ await session2.close();
172
+ ```
173
+
174
+ ## SDK-backed MCP Tools
175
+
176
+ Define custom tools that Droid can call during a session. Tools are served via a local MCP server that the SDK manages automatically.
177
+
178
+ ```ts
179
+ import {
180
+ createSession,
181
+ createSdkMcpServer,
182
+ tool,
183
+ ToolConfirmationOutcome,
184
+ } from '@factory/droid-sdk';
185
+ import { z } from 'zod';
186
+
187
+ const server = createSdkMcpServer({
188
+ name: 'my-tools',
189
+ tools: [
190
+ tool(
191
+ 'lookup',
192
+ 'Look up a user by name',
193
+ { name: z.string() },
194
+ ({ name }) => {
195
+ return `${name} is user #42.`;
196
+ }
197
+ ),
198
+ ],
199
+ });
200
+
201
+ const session = await createSession({
202
+ cwd: process.cwd(),
203
+ mcpServers: [server],
204
+ permissionHandler: () => ToolConfirmationOutcome.ProceedOnce,
205
+ });
206
+
207
+ for await (const msg of session.stream('Look up Alice.')) {
208
+ if (msg.type === 'assistant') console.log(msg.text);
209
+ }
210
+
211
+ await session.close();
212
+ ```
213
+
214
+ ## Autonomy Levels
215
+
216
+ Control what Droid can do without asking for permission. Set at session creation or change mid-session.
217
+
218
+ ```ts
219
+ import { createSession, AutonomyLevel } from '@factory/droid-sdk';
220
+
221
+ const session = await createSession({
222
+ cwd: process.cwd(),
223
+ autonomyLevel: AutonomyLevel.High, // Off | Low | Medium | High
224
+ });
225
+
226
+ // Change mid-session
227
+ await session.updateSettings({ autonomyLevel: AutonomyLevel.Low });
228
+ await session.close();
229
+ ```
230
+
231
+ ## Enabled/Disabled Tools
232
+
233
+ Restrict which tools Droid can use. Accepts tool IDs like `'Read'`, `'Execute'`, `'Grep'`.
234
+
235
+ ```ts
236
+ import { createSession } from '@factory/droid-sdk';
237
+
238
+ const session = await createSession({
239
+ cwd: process.cwd(),
240
+ enabledToolIds: ['Read', 'Grep'],
241
+ disabledToolIds: ['Execute'],
242
+ });
243
+
244
+ // Change mid-session
245
+ await session.updateSettings({ disabledToolIds: ['Read', 'Execute'] });
246
+ await session.close();
247
+ ```
248
+
249
+ ## Permission Handler
250
+
251
+ Programmatically approve or reject tool calls instead of prompting a human. Receives full tool details including file paths and commands.
252
+
253
+ ```ts
254
+ import {
255
+ run,
256
+ ToolConfirmationOutcome,
257
+ ToolConfirmationType,
258
+ } from '@factory/droid-sdk';
259
+
260
+ await run('Create hello.txt with "Hello, World!"', {
261
+ cwd: process.cwd(),
262
+ permissionHandler(params) {
263
+ const safe = params.toolUses.every(
264
+ (item) => item.details.type === ToolConfirmationType.Create
265
+ );
266
+ return safe
267
+ ? ToolConfirmationOutcome.ProceedOnce
268
+ : ToolConfirmationOutcome.Cancel;
269
+ },
270
+ });
271
+ ```
272
+
273
+ ## Spec Mode
274
+
275
+ Start Droid in read-only planning mode. It will research and produce a plan, then request to exit spec mode for implementation.
276
+
277
+ ```ts
278
+ import {
279
+ createSession,
280
+ DroidInteractionMode,
281
+ ToolConfirmationOutcome,
282
+ ToolConfirmationType,
283
+ } from '@factory/droid-sdk';
284
+
285
+ const session = await createSession({
286
+ cwd: process.cwd(),
287
+ interactionMode: DroidInteractionMode.Spec,
288
+ permissionHandler(params) {
289
+ const exitsSpec = params.toolUses.some(
290
+ (t) => t.details.type === ToolConfirmationType.ExitSpecMode
291
+ );
292
+ return exitsSpec
293
+ ? ToolConfirmationOutcome.ProceedOnce
294
+ : ToolConfirmationOutcome.Cancel;
295
+ },
296
+ });
297
+
298
+ for await (const msg of session.stream('Plan a refactor of src/utils.ts')) {
299
+ }
300
+ await session.close();
301
+ ```
302
+
303
+ ## Multimodal Input
304
+
305
+ Send images or documents alongside your prompt. Images must be base64-encoded.
306
+
307
+ ```ts
308
+ import { readFileSync } from 'node:fs';
309
+ import { createSession } from '@factory/droid-sdk';
310
+
311
+ const session = await createSession({ cwd: process.cwd() });
312
+
313
+ for await (const msg of session.stream('Describe this image.', {
314
+ images: [
315
+ {
316
+ type: 'base64',
317
+ data: readFileSync('screenshot.png').toString('base64'),
318
+ mediaType: 'image/png',
319
+ },
320
+ ],
321
+ })) {
322
+ if (msg.type === 'assistant') console.log(msg.text);
323
+ }
324
+
325
+ await session.close();
326
+ ```
327
+
328
+ ## Fork Session
329
+
330
+ Create a copy of the current session with all context preserved. Useful for branching a conversation.
331
+
332
+ ```ts
333
+ import { createSession, resumeSession } from '@factory/droid-sdk';
334
+
335
+ const session = await createSession({ cwd: process.cwd() });
336
+ for await (const msg of session.stream('Remember: the password is "banana".')) {
337
+ }
338
+
339
+ const { newSessionId } = await session.forkSession();
340
+ const fork = await resumeSession(newSessionId);
341
+
342
+ for await (const msg of fork.stream('What is the password?')) {
343
+ if (msg.type === 'assistant') console.log(msg.text);
344
+ }
345
+
346
+ await fork.close();
347
+ await session.close();
348
+ ```
349
+
350
+ ## Compact Session
351
+
352
+ Summarize and remove old messages to free up context window space.
353
+
354
+ ```ts
355
+ import { createSession } from '@factory/droid-sdk';
356
+
357
+ const session = await createSession({ cwd: process.cwd() });
358
+
359
+ // ... after many turns ...
360
+ const result = await session.compactSession();
361
+ console.log(
362
+ `New session: ${result.newSessionId}, removed: ${result.removedCount} messages`
363
+ );
364
+
365
+ await session.close();
366
+ ```
367
+
368
+ ## Rewind
369
+
370
+ Undo to a specific message and optionally restore files to their state at that point.
371
+
372
+ ```ts
373
+ import {
374
+ DroidClient,
375
+ ProcessTransport,
376
+ AutonomyLevel,
377
+ } from '@factory/droid-sdk';
378
+
379
+ const transport = new ProcessTransport({ cwd: process.cwd() });
380
+ await transport.connect();
381
+ const client = new DroidClient({ transport });
382
+
383
+ await client.initializeSession({
384
+ machineId: 'default',
385
+ cwd: process.cwd(),
386
+ autonomyLevel: AutonomyLevel.High,
387
+ });
388
+
389
+ const messageId = 'target-message-id';
390
+ const info = await client.getRewindInfo({ messageId });
391
+ console.log(`Files available to restore: ${info.availableFiles.length}`);
392
+
393
+ const result = await client.executeRewind({
394
+ messageId,
395
+ filesToRestore: info.availableFiles,
396
+ filesToDelete: [],
397
+ forkTitle: 'Rewind checkpoint',
398
+ });
399
+ console.log(`Rewound into session: ${result.newSessionId}`);
400
+
401
+ await client.close();
402
+ ```
403
+
404
+ ## List Sessions
405
+
406
+ Discover saved sessions on disk. Filters to the current project by default.
407
+
408
+ ```ts
409
+ import { listSessions } from '@factory/droid-sdk';
410
+
411
+ const sessions = await listSessions({ numSessions: 10 });
412
+
413
+ for (const s of sessions) {
414
+ console.log(`${s.id}: ${s.sessionTitle ?? '(untitled)'}`);
415
+ }
416
+ ```
417
+
418
+ ## Model and Reasoning Effort
419
+
420
+ Choose which model to use and how much reasoning effort to apply. Configurable at creation or mid-session.
421
+
422
+ ```ts
423
+ import { createSession, ReasoningEffort } from '@factory/droid-sdk';
424
+
425
+ const session = await createSession({
426
+ cwd: process.cwd(),
427
+ modelId: 'claude-sonnet-4-20250514',
428
+ reasoningEffort: ReasoningEffort.High,
429
+ });
430
+
431
+ // Change mid-session
432
+ await session.updateSettings({
433
+ reasoningEffort: ReasoningEffort.Low,
434
+ });
435
+
436
+ await session.close();
437
+ ```
438
+
439
+ ## Hook Execution Monitoring
440
+
441
+ Observe file hooks (pre/post tool execution hooks) as they run during a session.
442
+
443
+ ```ts
444
+ import { createSession, DroidMessageType } from '@factory/droid-sdk';
445
+
446
+ const session = await createSession({ cwd: process.cwd() });
447
+
448
+ for await (const msg of session.stream('Create a new file.')) {
449
+ if (msg.type === DroidMessageType.Hook) {
450
+ if (msg.status === 'started') {
451
+ console.log(`[Hook] ${msg.command}`);
452
+ } else {
453
+ console.log(`[Hook ${msg.status}] exit=${msg.exitCode}`);
454
+ }
455
+ }
456
+ }
457
+
458
+ await session.close();
459
+ ```
460
+
461
+ ## Ask-User Handler
462
+
463
+ Programmatically answer questions that Droid asks the user during execution.
464
+
465
+ ```ts
466
+ import { createSession } from '@factory/droid-sdk';
467
+
468
+ const session = await createSession({
469
+ cwd: process.cwd(),
470
+ askUserHandler(params) {
471
+ return {
472
+ cancelled: false,
473
+ answers: params.questions.map((q) => ({
474
+ index: q.index,
475
+ question: q.question,
476
+ answer: q.options[0] ?? 'yes',
477
+ })),
478
+ };
479
+ },
480
+ });
481
+
482
+ for await (const msg of session.stream('Help me set up this project.')) {
483
+ if (msg.type === 'assistant') console.log(msg.text);
484
+ }
485
+
486
+ await session.close();
487
+ ```
488
+
489
+ ## MCP Server Management
490
+
491
+ Add, remove, toggle, and list MCP servers at runtime within an active session.
492
+
493
+ ```ts
494
+ import { createSession, McpServerType } from '@factory/droid-sdk';
495
+
496
+ const session = await createSession({ cwd: process.cwd() });
497
+
498
+ await session.addMcpServer({
499
+ name: 'my-server',
500
+ type: McpServerType.Http,
501
+ url: 'https://mcp.example.com/mcp',
502
+ });
503
+
504
+ const { servers, summary } = await session.listMcpServers();
505
+ console.log(`MCP status: ${summary.status}, servers: ${servers.length}`);
506
+
507
+ await session.close();
508
+ ```
509
+
510
+ ## Context Stats
511
+
512
+ Query current context window usage to understand how much capacity remains.
513
+
514
+ ```ts
515
+ import { createSession } from '@factory/droid-sdk';
516
+
517
+ const session = await createSession({ cwd: process.cwd() });
518
+ for await (const msg of session.stream('Hello')) {
519
+ }
520
+
521
+ const stats = await session.getContextStats();
522
+ console.log(
523
+ `Used: ${stats.used}, Remaining: ${stats.remaining}, Limit: ${stats.limit}`
524
+ );
525
+
526
+ await session.close();
527
+ ```
528
+
529
+ ## Token Usage Tracking
530
+
531
+ Monitor token consumption in real-time via stream events, or read the final totals from the result.
532
+
533
+ ```ts
534
+ import { createSession, DroidMessageType } from '@factory/droid-sdk';
535
+
536
+ const session = await createSession({ cwd: process.cwd() });
537
+
538
+ for await (const msg of session.stream('Summarize this project.', {
539
+ includePartialMessages: true,
540
+ })) {
541
+ if (msg.type === DroidMessageType.TokenUsageUpdate) {
542
+ console.log(`Tokens — in: ${msg.inputTokens}, out: ${msg.outputTokens}`);
543
+ }
544
+ if (msg.type === DroidMessageType.Result && msg.tokenUsage) {
545
+ console.log(
546
+ `Final — in: ${msg.tokenUsage.inputTokens}, out: ${msg.tokenUsage.outputTokens}`
547
+ );
548
+ }
549
+ }
550
+
551
+ await session.close();
552
+ ```
553
+
554
+ ## List Skills
555
+
556
+ List all available skills in the current session.
557
+
558
+ ```ts
559
+ import { createSession } from '@factory/droid-sdk';
560
+
561
+ const session = await createSession({ cwd: process.cwd() });
562
+ const { skills } = await session.listSkills();
563
+
564
+ for (const skill of skills) {
565
+ console.log(`${skill.name} (${skill.location}): ${skill.description ?? ''}`);
566
+ }
567
+
568
+ await session.close();
569
+ ```
570
+
571
+ ## Raw Notification Subscription
572
+
573
+ Subscribe to raw protocol notifications for custom event handling beyond the stream API.
574
+
575
+ ```ts
576
+ import { createSession, SessionNotificationType } from '@factory/droid-sdk';
577
+
578
+ const session = await createSession({ cwd: process.cwd() });
579
+
580
+ const unsubscribe = session.onNotification(
581
+ (notification) => {
582
+ console.log('Notification:', notification);
583
+ },
584
+ { type: SessionNotificationType.ERROR }
585
+ );
586
+
587
+ // ... use the session ...
588
+
589
+ unsubscribe();
590
+ await session.close();
591
+ ```
592
+
593
+ ## Error Handling
594
+
595
+ The SDK throws typed errors with structured context. Catch specific error classes to handle different failure modes.
596
+
597
+ ```ts
598
+ import {
599
+ resumeSession,
600
+ ConnectionError,
601
+ TimeoutError,
602
+ SessionNotFoundError,
603
+ ProtocolError,
604
+ } from '@factory/droid-sdk';
605
+
606
+ try {
607
+ const session = await resumeSession('nonexistent-id');
608
+ } catch (error) {
609
+ if (error instanceof SessionNotFoundError) {
610
+ console.log(`Session not found: ${error.sessionId}`);
611
+ } else if (error instanceof TimeoutError) {
612
+ console.log('Request timed out');
613
+ } else if (error instanceof ConnectionError) {
614
+ console.log(`Connection failed: ${error.message}`);
615
+ } else if (error instanceof ProtocolError) {
616
+ console.log(`Protocol error ${error.code}: ${error.message}`);
617
+ }
618
+ }
619
+ ```
620
+
621
+ ## Low-level APIs
622
+
623
+ Most users should use `run()` and `DroidSession`. For direct RPC access, the SDK also exports `ProcessTransport`, `ProtocolEngine`, and `DroidClient`.
624
+
625
+ `DroidClient` exposes additional methods not on `DroidSession`: `killWorkerSession()`, `cancelMcpAuth()`, `clearMcpAuth()`, `submitMcpAuthCode()`, `listMcpRegistry()`, `toggleMcpTool()`, and `submitBugReport()`.
626
+
627
+ The package also exports its full Zod schema surface from `src/schemas/index.ts` for runtime validation of protocol payloads.
628
+
629
+ ---
630
+
631
+ ## Configuration Reference
632
+
633
+ ### `CreateSessionOptions`
634
+
635
+ | Field | Type | Description |
636
+ | :------------------------ | :----------------------- | :---------------------------------------------------------- |
637
+ | `cwd` | `string` | Working directory for the session |
638
+ | `machineId` | `string` | Machine identifier for initialization |
639
+ | `modelId` | `string` | LLM model identifier |
640
+ | `autonomyLevel` | `AutonomyLevel` | `Off` \| `Low` \| `Medium` \| `High` |
641
+ | `interactionMode` | `DroidInteractionMode` | `Auto` \| `Spec` \| `AGI` |
642
+ | `reasoningEffort` | `ReasoningEffort` | `None` \| `Low` \| `Medium` \| `High` \| `Max` (and others) |
643
+ | `specModeModelId` | `string` | Override model for spec mode |
644
+ | `specModeReasoningEffort` | `ReasoningEffort` | Override reasoning effort for spec mode |
645
+ | `mcpServers` | `DroidMcpServerConfig[]` | Initial MCP server configurations |
646
+ | `enabledToolIds` | `string[]` | Tool allowlist |
647
+ | `disabledToolIds` | `string[]` | Tool denylist |
648
+ | `tags` | `SessionTag[]` | Session tags for categorization |
649
+ | `permissionHandler` | `PermissionHandler` | Tool confirmation callback |
650
+ | `askUserHandler` | `AskUserHandler` | Structured user-input callback |
651
+ | `execPath` | `string` | Path to `droid` executable (default: `"droid"`) |
652
+ | `execArgs` | `string[]` | Extra CLI arguments for the subprocess |
653
+ | `env` | `Record<string, string>` | Environment variables for the subprocess |
654
+ | `transport` | `DroidClientTransport` | Custom transport (skips subprocess spawn) |
655
+ | `abortSignal` | `AbortSignal` | Cancellation signal |
656
+
657
+ ### `MessageOptions`
658
+
659
+ Accepted by `session.stream()` and `run()`:
660
+
661
+ | Field | Type | Description |
662
+ | :----------------------- | :-------------------- | :------------------------------------------- |
663
+ | `images` | `Base64ImageSource[]` | Base64-encoded image attachments |
664
+ | `files` | `DocumentSource[]` | Document/file attachments |
665
+ | `outputFormat` | `OutputFormat` | Structured output JSON schema request |
666
+ | `includePartialMessages` | `boolean` | Yield token-level deltas and progress events |
667
+ | `abortSignal` | `AbortSignal` | Cancellation signal for this turn |
668
+
669
+ ### Error Types
670
+
671
+ | Error | Description |
672
+ | :--------------------- | :---------------------------------------- |
673
+ | `ConnectionError` | Failed to connect to the droid subprocess |
674
+ | `ProtocolError` | JSON-RPC or protocol-level failure |
675
+ | `SessionError` | Base session error |
676
+ | `SessionNotFoundError` | Requested session does not exist |
677
+ | `TimeoutError` | RPC timed out |
678
+ | `ProcessExitError` | Subprocess exited unexpectedly |