@factory/droid-sdk 0.1.4 → 0.2.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 (36) hide show
  1. package/README.md +239 -47
  2. package/dist/index.cjs +1869 -1296
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +6734 -4444
  5. package/dist/index.d.ts +6734 -4444
  6. package/dist/index.js +1815 -1298
  7. package/dist/index.js.map +1 -1
  8. package/docs/examples/init-metadata.md +79 -0
  9. package/docs/examples/list-sessions.md +64 -0
  10. package/docs/examples/multi-turn-session.md +77 -0
  11. package/docs/examples/one-shot-query.md +73 -0
  12. package/docs/examples/permission-handler.md +102 -0
  13. package/docs/examples/run.md +52 -0
  14. package/docs/examples/spec-mode.md +101 -0
  15. package/docs/examples/tool-controls.md +90 -0
  16. package/docs/typescript-sdk-reference.md +372 -0
  17. package/examples/.gitkeep +1 -0
  18. package/examples/abort-session-stream.ts +67 -0
  19. package/examples/droid-dev-structured-output.ts +44 -0
  20. package/examples/fork-session.ts +42 -0
  21. package/examples/init-metadata.ts +76 -0
  22. package/examples/interrupt-session.ts +67 -0
  23. package/examples/list-sessions.ts +65 -0
  24. package/examples/multi-turn-session.ts +67 -0
  25. package/examples/permission-handler.ts +98 -0
  26. package/examples/result-metadata.ts +62 -0
  27. package/examples/run.ts +38 -0
  28. package/examples/sdk-mcp-tool.ts +38 -0
  29. package/examples/simple-query.ts +53 -0
  30. package/examples/spec-mode-new-session.ts +121 -0
  31. package/examples/spec-mode-same-session.ts +133 -0
  32. package/examples/structured-output.ts +53 -0
  33. package/examples/test-compact.ts +60 -0
  34. package/examples/test-rewind.ts +155 -0
  35. package/examples/tool-controls.ts +69 -0
  36. package/package.json +26 -4
package/dist/index.js CHANGED
@@ -14,11 +14,18 @@ var DroidServerMethod = /* @__PURE__ */ ((DroidServerMethod2) => {
14
14
  DroidServerMethod2["REMOVE_MCP_SERVER"] = "droid.remove_mcp_server";
15
15
  DroidServerMethod2["LIST_MCP_REGISTRY"] = "droid.list_mcp_registry";
16
16
  DroidServerMethod2["LIST_MCP_TOOLS"] = "droid.list_mcp_tools";
17
+ DroidServerMethod2["LIST_TOOLS"] = "droid.list_tools";
17
18
  DroidServerMethod2["LIST_MCP_SERVERS"] = "droid.list_mcp_servers";
18
19
  DroidServerMethod2["TOGGLE_MCP_TOOL"] = "droid.toggle_mcp_tool";
19
20
  DroidServerMethod2["SUBMIT_MCP_AUTH_CODE"] = "droid.submit_mcp_auth_code";
20
21
  DroidServerMethod2["LIST_SKILLS"] = "droid.list_skills";
21
22
  DroidServerMethod2["SUBMIT_BUG_REPORT"] = "droid.submit_bug_report";
23
+ DroidServerMethod2["GET_REWIND_INFO"] = "droid.get_rewind_info";
24
+ DroidServerMethod2["EXECUTE_REWIND"] = "droid.execute_rewind";
25
+ DroidServerMethod2["COMPACT_SESSION"] = "droid.compact_session";
26
+ DroidServerMethod2["FORK_SESSION"] = "droid.fork_session";
27
+ DroidServerMethod2["RENAME_SESSION"] = "droid.rename_session";
28
+ DroidServerMethod2["GET_CONTEXT_STATS"] = "droid.get_context_stats";
22
29
  return DroidServerMethod2;
23
30
  })(DroidServerMethod || {});
24
31
  var DroidClientMethod = /* @__PURE__ */ ((DroidClientMethod2) => {
@@ -57,6 +64,10 @@ var ToolConfirmationOutcome = /* @__PURE__ */ ((ToolConfirmationOutcome3) => {
57
64
  ToolConfirmationOutcome3["ProceedAutoRunLow"] = "proceed_auto_run_low";
58
65
  ToolConfirmationOutcome3["ProceedAutoRunMedium"] = "proceed_auto_run_medium";
59
66
  ToolConfirmationOutcome3["ProceedAutoRunHigh"] = "proceed_auto_run_high";
67
+ ToolConfirmationOutcome3["ProceedNewSession"] = "proceed_new_session";
68
+ ToolConfirmationOutcome3["ProceedNewSessionLow"] = "proceed_new_session_low";
69
+ ToolConfirmationOutcome3["ProceedNewSessionMedium"] = "proceed_new_session_medium";
70
+ ToolConfirmationOutcome3["ProceedNewSessionHigh"] = "proceed_new_session_high";
60
71
  ToolConfirmationOutcome3["ProceedEdit"] = "proceed_edit";
61
72
  ToolConfirmationOutcome3["Cancel"] = "cancel";
62
73
  return ToolConfirmationOutcome3;
@@ -81,6 +92,11 @@ var DroidWorkingState = /* @__PURE__ */ ((DroidWorkingState2) => {
81
92
  DroidWorkingState2["CompactingConversation"] = "compacting_conversation";
82
93
  return DroidWorkingState2;
83
94
  })(DroidWorkingState || {});
95
+ var ContextStatsAccuracy = /* @__PURE__ */ ((ContextStatsAccuracy2) => {
96
+ ContextStatsAccuracy2["Exact"] = "exact";
97
+ ContextStatsAccuracy2["Estimated"] = "estimated";
98
+ return ContextStatsAccuracy2;
99
+ })(ContextStatsAccuracy || {});
84
100
  var DroidErrorType = /* @__PURE__ */ ((DroidErrorType2) => {
85
101
  DroidErrorType2["CONNECTION_ERROR"] = "ConnectionError";
86
102
  DroidErrorType2["PROTOCOL_ERROR"] = "ProtocolError";
@@ -252,19 +268,39 @@ var SkillLocation = /* @__PURE__ */ ((SkillLocation2) => {
252
268
  // src/schemas/constants.ts
253
269
  var JSONRPC_VERSION = "2.0";
254
270
  var LEGACY_FACTORY_API_VERSION = "1.0.0";
255
- var FACTORY_PROTOCOL_VERSION = "1.2.0";
271
+ var FACTORY_PROTOCOL_VERSION = "1.3.0";
256
272
  var FACTORY_CLIENT_HEADER = "X-Factory-Client";
257
273
  var FACTORY_CLIENT_VERSION = "X-Client-Version";
258
274
  var DEFAULT_REQUEST_TIMEOUT = 3e4;
259
275
  var SESSION_INIT_TIMEOUT = 6e4;
260
276
  var MCP_AUTH_TIMEOUT = 3e5;
277
+ var COMPACTION_TIMEOUT = 24e4;
278
+ var REWIND_TIMEOUT = 6e4;
261
279
 
262
280
  // src/schemas/shared.ts
263
281
  import { z } from "zod";
282
+ var JsonValueSchema = z.lazy(
283
+ () => z.union([
284
+ z.string(),
285
+ z.number(),
286
+ z.boolean(),
287
+ z.null(),
288
+ z.array(JsonValueSchema),
289
+ z.record(JsonValueSchema)
290
+ ])
291
+ );
292
+ var JsonObjectSchema = z.record(JsonValueSchema);
293
+ var JsonArraySchema = z.array(JsonValueSchema);
264
294
  var TraceContextMetaSchema = z.object({
265
295
  traceparent: z.string().optional(),
266
296
  tracestate: z.string().optional()
267
297
  });
298
+ var ToolSelectionOverridesSchema = z.object({
299
+ enabledToolIds: z.array(z.string()).optional(),
300
+ disabledToolIds: z.array(z.string()).optional()
301
+ });
302
+ var EmptyResultSchema = z.object({}).passthrough();
303
+ var SuccessResultSchema = z.object({ success: z.boolean() }).passthrough();
268
304
  var JsonRpcEnvelopeSchema = z.object({
269
305
  jsonrpc: z.literal(JSONRPC_VERSION),
270
306
  factoryApiVersion: z.literal(LEGACY_FACTORY_API_VERSION),
@@ -274,18 +310,18 @@ var JsonRpcEnvelopeSchema = z.object({
274
310
  var JsonRpcErrorSchema = z.object({
275
311
  code: z.nativeEnum(JsonRpcErrorCode),
276
312
  message: z.string(),
277
- data: z.unknown().optional()
313
+ data: JsonValueSchema.optional()
278
314
  });
279
315
  var BaseRequestSchema = z.object({
280
316
  type: z.literal("request"),
281
317
  id: z.string(),
282
318
  method: z.string(),
283
- params: z.unknown().optional()
319
+ params: JsonValueSchema.optional()
284
320
  });
285
321
  var BaseResponseSuccessSchema = z.object({
286
322
  type: z.literal("response"),
287
323
  id: z.string(),
288
- result: z.unknown()
324
+ result: JsonValueSchema
289
325
  });
290
326
  var BaseResponseFailureSchema = z.object({
291
327
  type: z.literal("response"),
@@ -295,7 +331,7 @@ var BaseResponseFailureSchema = z.object({
295
331
  var BaseNotificationSchema = z.object({
296
332
  type: z.literal("notification"),
297
333
  method: z.string(),
298
- params: z.unknown().optional()
334
+ params: JsonValueSchema.optional()
299
335
  });
300
336
  var JsonRpcRequestSchema = JsonRpcEnvelopeSchema.extend(
301
337
  BaseRequestSchema.shape
@@ -318,61 +354,128 @@ var JsonRpcMessageSchema = z.discriminatedUnion("type", [
318
354
  JsonRpcEnvelopeSchema.extend({
319
355
  type: z.literal("response"),
320
356
  id: z.string().nullable(),
321
- result: z.unknown().optional(),
357
+ result: JsonValueSchema.optional(),
322
358
  error: JsonRpcErrorSchema.optional()
323
359
  }),
324
360
  JsonRpcNotificationSchema
325
361
  ]);
326
362
 
327
- // src/schemas/messages.ts
363
+ // src/schemas/session-metadata.ts
364
+ import { z as z6 } from "zod";
365
+
366
+ // src/schemas/client.ts
367
+ import { z as z5 } from "zod";
368
+
369
+ // src/schemas/mcp.ts
328
370
  import { z as z2 } from "zod";
329
- var TextBlockSchema = z2.object({
330
- type: z2.literal("text"),
331
- text: z2.string(),
332
- id: z2.string().optional()
333
- }).passthrough();
334
- var Base64ImageSourceSchema = z2.object({
335
- type: z2.literal("base64"),
336
- data: z2.string(),
337
- mediaType: z2.enum(["image/jpeg", "image/png", "image/gif", "image/webp"])
338
- }).passthrough();
339
- var ImageBlockSchema = z2.object({
340
- type: z2.literal("image"),
341
- source: Base64ImageSourceSchema,
342
- id: z2.string().optional()
343
- }).passthrough();
344
- var ThinkingBlockSchema = z2.object({
345
- type: z2.literal("thinking"),
346
- signature: z2.string(),
347
- thinking: z2.string(),
348
- id: z2.string().optional(),
349
- signatureProvider: z2.string().optional()
350
- }).passthrough();
351
- var RedactedThinkingBlockSchema = z2.object({
352
- type: z2.literal("redacted_thinking"),
353
- data: z2.string(),
354
- id: z2.string().optional()
355
- }).passthrough();
356
- var ToolUseBlockSchema = z2.object({
357
- type: z2.literal("tool_use"),
358
- id: z2.string(),
359
- input: z2.record(z2.unknown()),
371
+ var McpStdioServerConfigFieldsSchema = z2.object({
372
+ command: z2.string().optional(),
373
+ args: z2.array(z2.string()).optional()
374
+ });
375
+ var McpHttpServerConfigFieldsSchema = z2.object({
376
+ url: z2.string().optional()
377
+ });
378
+ var McpSseServerConfigFieldsSchema = z2.object({
379
+ url: z2.string(),
380
+ headers: z2.record(z2.string()).optional()
381
+ });
382
+ var McpServerStatusInfoSchema = z2.object({
383
+ name: z2.string(),
384
+ status: z2.nativeEnum(McpServerStatus),
385
+ source: z2.nativeEnum(SettingsLevel),
386
+ isManaged: z2.boolean(),
387
+ error: z2.string().optional(),
388
+ toolCount: z2.number().optional(),
389
+ serverType: z2.nativeEnum(McpServerType).optional(),
390
+ hasAuthTokens: z2.boolean().optional()
391
+ }).passthrough();
392
+ var McpStatusSummarySchema = z2.object({
393
+ total: z2.number(),
394
+ connected: z2.number(),
395
+ connecting: z2.number(),
396
+ failed: z2.number(),
397
+ disabled: z2.number().optional()
398
+ }).passthrough();
399
+ var McpRegistryServerSchema = z2.object({
400
+ name: z2.string(),
401
+ description: z2.string(),
402
+ type: z2.nativeEnum(McpServerType),
403
+ // Stdio config fields
404
+ command: z2.string().optional(),
405
+ args: z2.array(z2.string()).optional(),
406
+ // HTTP config fields
407
+ url: z2.string().optional(),
408
+ // Additional metadata
409
+ note: z2.string().optional(),
410
+ logoUrl: z2.string().optional()
411
+ }).passthrough();
412
+ var McpToolInputSchemaSchema = z2.object({
413
+ type: z2.string().optional(),
414
+ properties: JsonObjectSchema.optional(),
415
+ required: z2.array(z2.string()).optional()
416
+ }).passthrough();
417
+ var McpToolInfoSchema = z2.object({
418
+ serverName: z2.string(),
360
419
  name: z2.string(),
361
- thoughtSignature: z2.string().optional()
420
+ description: z2.string().optional(),
421
+ isEnabled: z2.boolean(),
422
+ isReadOnly: z2.boolean().optional(),
423
+ inputSchema: McpToolInputSchemaSchema.optional()
424
+ }).passthrough();
425
+ var ToolConfirmationListItemSchema = z2.object({
426
+ label: z2.string(),
427
+ value: z2.nativeEnum(ToolConfirmationOutcome)
428
+ }).passthrough();
429
+
430
+ // src/schemas/messages.ts
431
+ import { z as z3 } from "zod";
432
+ var TextBlockSchema = z3.object({
433
+ type: z3.literal("text"),
434
+ text: z3.string(),
435
+ id: z3.string().optional()
436
+ }).passthrough();
437
+ var Base64ImageSourceSchema = z3.object({
438
+ type: z3.literal("base64"),
439
+ data: z3.string(),
440
+ mediaType: z3.enum(["image/jpeg", "image/png", "image/gif", "image/webp"])
441
+ }).passthrough();
442
+ var ImageBlockSchema = z3.object({
443
+ type: z3.literal("image"),
444
+ source: Base64ImageSourceSchema,
445
+ id: z3.string().optional()
446
+ }).passthrough();
447
+ var ThinkingBlockSchema = z3.object({
448
+ type: z3.literal("thinking"),
449
+ signature: z3.string(),
450
+ thinking: z3.string(),
451
+ id: z3.string().optional(),
452
+ signatureProvider: z3.string().optional()
453
+ }).passthrough();
454
+ var RedactedThinkingBlockSchema = z3.object({
455
+ type: z3.literal("redacted_thinking"),
456
+ data: z3.string(),
457
+ id: z3.string().optional()
458
+ }).passthrough();
459
+ var ToolUseBlockSchema = z3.object({
460
+ type: z3.literal("tool_use"),
461
+ id: z3.string(),
462
+ input: JsonObjectSchema,
463
+ name: z3.string(),
464
+ thoughtSignature: z3.string().optional()
362
465
  }).passthrough();
363
- var ToolResultBlockSchema = z2.object({
364
- type: z2.literal("tool_result"),
365
- toolUseId: z2.string(),
366
- content: z2.union([z2.string(), z2.array(z2.unknown())]).optional(),
367
- isError: z2.boolean().optional(),
368
- id: z2.string().optional()
466
+ var ToolResultBlockSchema = z3.object({
467
+ type: z3.literal("tool_result"),
468
+ toolUseId: z3.string(),
469
+ content: z3.union([z3.string(), z3.array(JsonValueSchema)]).optional(),
470
+ isError: z3.boolean().optional(),
471
+ id: z3.string().optional()
369
472
  }).passthrough();
370
- var DocumentBlockSchema = z2.object({
371
- type: z2.literal("document"),
372
- source: z2.record(z2.unknown()),
373
- id: z2.string().optional()
473
+ var DocumentBlockSchema = z3.object({
474
+ type: z3.literal("document"),
475
+ source: JsonObjectSchema,
476
+ id: z3.string().optional()
374
477
  }).passthrough();
375
- var ContentBlockSchema = z2.discriminatedUnion("type", [
478
+ var ContentBlockSchema = z3.discriminatedUnion("type", [
376
479
  TextBlockSchema,
377
480
  ImageBlockSchema,
378
481
  ThinkingBlockSchema,
@@ -381,83 +484,33 @@ var ContentBlockSchema = z2.discriminatedUnion("type", [
381
484
  ToolResultBlockSchema,
382
485
  DocumentBlockSchema
383
486
  ]);
384
- var FactoryDroidMessageSchema = z2.object({
385
- id: z2.string(),
386
- role: z2.enum(["user", "assistant", "tool", "system"]),
387
- content: z2.array(ContentBlockSchema),
388
- createdAt: z2.number(),
389
- updatedAt: z2.number(),
390
- parentId: z2.string().optional(),
391
- visibility: z2.enum(["both", "llm_only", "user_only"]).optional(),
392
- isError: z2.boolean().optional()
393
- }).passthrough();
394
- var DocumentSourceSchema = z2.object({
395
- type: z2.string(),
396
- mediaType: z2.string(),
397
- data: z2.string(),
398
- name: z2.string().optional(),
399
- mime: z2.string().optional()
400
- }).strict();
401
-
402
- // src/schemas/mcp.ts
403
- import { z as z3 } from "zod";
404
- var McpStdioServerConfigFieldsSchema = z3.object({
405
- command: z3.string().optional(),
406
- args: z3.array(z3.string()).optional()
407
- });
408
- var McpHttpServerConfigFieldsSchema = z3.object({
409
- url: z3.string().optional()
410
- });
411
- var McpSseServerConfigFieldsSchema = z3.object({
412
- url: z3.string(),
413
- headers: z3.record(z3.string()).optional()
414
- });
415
- var McpServerStatusInfoSchema = z3.object({
416
- name: z3.string(),
417
- status: z3.nativeEnum(McpServerStatus),
418
- source: z3.nativeEnum(SettingsLevel),
419
- isManaged: z3.boolean(),
420
- error: z3.string().optional(),
421
- toolCount: z3.number().optional(),
422
- serverType: z3.nativeEnum(McpServerType).optional(),
423
- hasAuthTokens: z3.boolean().optional()
424
- }).passthrough();
425
- var McpStatusSummarySchema = z3.object({
426
- total: z3.number(),
427
- connected: z3.number(),
428
- connecting: z3.number(),
429
- failed: z3.number(),
430
- disabled: z3.number().optional()
431
- }).passthrough();
432
- var McpRegistryServerSchema = z3.object({
433
- name: z3.string(),
434
- description: z3.string(),
435
- type: z3.nativeEnum(McpServerType),
436
- // Stdio config fields
437
- command: z3.string().optional(),
438
- args: z3.array(z3.string()).optional(),
439
- // HTTP config fields
440
- url: z3.string().optional(),
441
- // Additional metadata
442
- note: z3.string().optional(),
443
- logoUrl: z3.string().optional()
444
- }).passthrough();
445
- var McpToolInputSchemaSchema = z3.object({
446
- type: z3.string().optional(),
447
- properties: z3.record(z3.unknown()).optional(),
448
- required: z3.array(z3.string()).optional()
449
- }).passthrough();
450
- var McpToolInfoSchema = z3.object({
451
- serverName: z3.string(),
452
- name: z3.string(),
453
- description: z3.string().optional(),
454
- isEnabled: z3.boolean(),
455
- isReadOnly: z3.boolean().optional(),
456
- inputSchema: McpToolInputSchemaSchema.optional()
457
- }).passthrough();
458
- var ToolConfirmationListItemSchema = z3.object({
459
- label: z3.string(),
460
- value: z3.nativeEnum(ToolConfirmationOutcome)
487
+ var FactoryDroidMessageRole = {
488
+ User: "user",
489
+ Assistant: "assistant",
490
+ Tool: "tool",
491
+ System: "system"
492
+ };
493
+ var FactoryDroidMessageSchema = z3.object({
494
+ id: z3.string(),
495
+ role: z3.enum([
496
+ FactoryDroidMessageRole.User,
497
+ FactoryDroidMessageRole.Assistant,
498
+ FactoryDroidMessageRole.Tool,
499
+ FactoryDroidMessageRole.System
500
+ ]),
501
+ content: z3.array(ContentBlockSchema),
502
+ createdAt: z3.number(),
503
+ updatedAt: z3.number(),
504
+ parentId: z3.string().optional(),
505
+ visibility: z3.enum(["both", "llm_only", "user_only"]).optional(),
506
+ isError: z3.boolean().optional()
507
+ }).passthrough();
508
+ var DocumentSourceSchema = z3.object({
509
+ type: z3.string(),
510
+ mediaType: z3.string(),
511
+ data: z3.string(),
512
+ name: z3.string().optional(),
513
+ mime: z3.string().optional()
461
514
  }).passthrough();
462
515
 
463
516
  // src/schemas/mission.ts
@@ -608,7 +661,12 @@ var ProgressLogEntrySchema = z4.discriminatedUnion("type", [
608
661
  ]);
609
662
 
610
663
  // src/schemas/client.ts
611
- import { z as z5 } from "zod";
664
+ var SessionModeRequestFieldsShape = {
665
+ modelId: z5.string().optional(),
666
+ autonomyMode: z5.nativeEnum(AutonomyMode).optional(),
667
+ interactionMode: z5.nativeEnum(DroidInteractionMode).optional(),
668
+ autonomyLevel: z5.nativeEnum(AutonomyLevel).optional()
669
+ };
612
670
  var SessionTagSchema = z5.object({
613
671
  name: z5.string(),
614
672
  metadata: z5.record(z5.string()).optional()
@@ -650,7 +708,8 @@ var SessionSettingsSchema = z5.object({
650
708
  interactionMode: z5.nativeEnum(DroidInteractionMode).optional().catch(void 0),
651
709
  autonomyLevel: z5.nativeEnum(AutonomyLevel).optional().catch(void 0),
652
710
  specModeModelId: z5.string().optional(),
653
- specModeReasoningEffort: z5.nativeEnum(ReasoningEffort).optional()
711
+ specModeReasoningEffort: z5.nativeEnum(ReasoningEffort).optional(),
712
+ ...ToolSelectionOverridesSchema.shape
654
713
  }).passthrough();
655
714
  var GitRepoInfoSchema = z5.object({
656
715
  owner: z5.string().optional(),
@@ -670,7 +729,7 @@ var AvailableModelConfigSchema = z5.object({
670
729
  tier: z5.string().optional(),
671
730
  tokenMultiplier: z5.number().optional(),
672
731
  promoLabel: z5.string().optional(),
673
- featureFlag: z5.record(z5.unknown()).optional(),
732
+ featureFlag: JsonObjectSchema.optional(),
674
733
  usesUSBasedInference: z5.boolean().optional()
675
734
  }).passthrough();
676
735
  var TokenUsageSchema = z5.object({
@@ -680,6 +739,13 @@ var TokenUsageSchema = z5.object({
680
739
  cacheReadTokens: z5.number(),
681
740
  thinkingTokens: z5.number()
682
741
  }).passthrough();
742
+ var ContextStatsSchema = z5.object({
743
+ used: z5.number(),
744
+ remaining: z5.number(),
745
+ limit: z5.number(),
746
+ accuracy: z5.nativeEnum(ContextStatsAccuracy),
747
+ updatedAt: z5.string()
748
+ }).passthrough();
683
749
  var WorkerStateInfoSchema = z5.object({
684
750
  startedAt: z5.string(),
685
751
  completedAt: z5.string().optional(),
@@ -707,17 +773,14 @@ var InitializeSessionRequestParamsSchema = z5.object({
707
773
  workspaceId: z5.string().optional(),
708
774
  sessionId: z5.string().optional(),
709
775
  mcpServers: z5.array(McpServerConfigSchema).optional(),
710
- autonomyMode: z5.nativeEnum(AutonomyMode).optional(),
711
- interactionMode: z5.nativeEnum(DroidInteractionMode).optional().catch(void 0),
712
- autonomyLevel: z5.nativeEnum(AutonomyLevel).optional().catch(void 0),
713
- modelId: z5.string().optional(),
776
+ ...SessionModeRequestFieldsShape,
714
777
  reasoningEffort: z5.nativeEnum(ReasoningEffort).optional(),
715
778
  specModeModelId: z5.string().optional(),
716
779
  specModeReasoningEffort: z5.nativeEnum(ReasoningEffort).optional(),
717
780
  decompSessionType: z5.nativeEnum(DecompSessionType).optional(),
718
781
  decompMissionId: z5.string().optional(),
719
782
  skipPermissionsUnsafe: z5.boolean().optional(),
720
- enabledToolIds: z5.array(z5.string()).optional(),
783
+ ...ToolSelectionOverridesSchema.shape,
721
784
  sessionLocation: z5.string().optional(),
722
785
  sessionSource: SessionSourceSchema.optional(),
723
786
  tags: z5.array(SessionTagSchema).optional(),
@@ -728,24 +791,30 @@ var LoadSessionRequestParamsSchema = z5.object({
728
791
  mcpServers: z5.array(McpServerConfigSchema).optional(),
729
792
  mcpOAuthCallbackUri: z5.string().optional()
730
793
  }).strict();
794
+ var OutputFormatType = {
795
+ JsonSchema: "json_schema"
796
+ };
797
+ var OutputFormatSchema = z5.object({
798
+ type: z5.literal(OutputFormatType.JsonSchema),
799
+ schema: JsonObjectSchema
800
+ }).strict();
731
801
  var AddUserMessageRequestParamsSchema = z5.object({
732
802
  messageId: z5.string().optional(),
733
803
  text: z5.string(),
734
804
  images: z5.array(Base64ImageSourceSchema).optional(),
735
- files: z5.array(DocumentSourceSchema).optional()
805
+ files: z5.array(DocumentSourceSchema).optional(),
806
+ outputFormat: OutputFormatSchema.optional()
736
807
  }).strict();
737
808
  var InterruptSessionRequestParamsSchema = z5.object({}).strict();
738
809
  var KillWorkerSessionRequestParamsSchema = z5.object({
739
810
  workerSessionId: z5.string()
740
811
  }).strict();
741
812
  var UpdateSessionSettingsRequestParamsSchema = z5.object({
742
- modelId: z5.string().optional(),
813
+ ...SessionModeRequestFieldsShape,
743
814
  reasoningEffort: z5.nativeEnum(ReasoningEffort).optional(),
744
- autonomyMode: z5.nativeEnum(AutonomyMode).optional(),
745
- interactionMode: z5.nativeEnum(DroidInteractionMode).optional().catch(void 0),
746
- autonomyLevel: z5.nativeEnum(AutonomyLevel).optional().catch(void 0),
747
815
  specModeModelId: z5.string().nullable().optional(),
748
- specModeReasoningEffort: z5.nativeEnum(ReasoningEffort).nullable().optional()
816
+ specModeReasoningEffort: z5.nativeEnum(ReasoningEffort).nullable().optional(),
817
+ ...ToolSelectionOverridesSchema.shape
749
818
  }).strict();
750
819
  var ToggleMcpServerRequestParamsSchema = z5.object({
751
820
  serverName: z5.string(),
@@ -781,6 +850,22 @@ var RemoveMcpServerRequestParamsSchema = z5.object({
781
850
  }).strict();
782
851
  var ListMcpRegistryRequestParamsSchema = z5.object({}).strict();
783
852
  var ListMcpToolsRequestParamsSchema = z5.object({}).strict();
853
+ var ExecToolInfoSchema = z5.object({
854
+ id: z5.string(),
855
+ llmId: z5.string(),
856
+ displayName: z5.string(),
857
+ description: z5.string(),
858
+ category: z5.enum(["read", "edit", "execute", "other"]),
859
+ defaultAllowed: z5.boolean(),
860
+ currentlyAllowed: z5.boolean()
861
+ }).passthrough();
862
+ var ListToolsRequestParamsSchema = z5.object({
863
+ ...SessionModeRequestFieldsShape,
864
+ specModeModelId: z5.string().nullable().optional(),
865
+ skipPermissionsUnsafe: z5.boolean().optional(),
866
+ ...ToolSelectionOverridesSchema.shape,
867
+ depth: z5.number().int().min(0).optional()
868
+ }).strict();
784
869
  var ListMcpServersRequestParamsSchema = z5.object({}).strict();
785
870
  var ToggleMcpToolRequestParamsSchema = z5.object({
786
871
  serverName: z5.string(),
@@ -792,6 +877,35 @@ var SubmitBugReportRequestParamsSchema = z5.object({
792
877
  userComment: z5.string(),
793
878
  clientLogs: z5.string().optional()
794
879
  }).strict();
880
+ var RewindFileSnapshotSchema = z5.object({
881
+ filePath: z5.string(),
882
+ contentHash: z5.string(),
883
+ size: z5.number()
884
+ }).passthrough();
885
+ var RewindFileCreationSchema = z5.object({
886
+ filePath: z5.string()
887
+ }).passthrough();
888
+ var RewindEvictedFileSchema = z5.object({
889
+ filePath: z5.string(),
890
+ reason: z5.string()
891
+ }).passthrough();
892
+ var GetRewindInfoRequestParamsSchema = z5.object({
893
+ messageId: z5.string()
894
+ }).passthrough();
895
+ var ExecuteRewindRequestParamsSchema = z5.object({
896
+ messageId: z5.string(),
897
+ filesToRestore: z5.array(RewindFileSnapshotSchema),
898
+ filesToDelete: z5.array(RewindFileCreationSchema),
899
+ forkTitle: z5.string()
900
+ }).passthrough();
901
+ var CompactSessionRequestParamsSchema = z5.object({
902
+ customInstructions: z5.string().optional()
903
+ }).passthrough();
904
+ var RenameSessionRequestParamsSchema = z5.object({
905
+ title: z5.string()
906
+ }).passthrough();
907
+ var ForkSessionRequestParamsSchema = z5.object({}).passthrough();
908
+ var GetContextStatsRequestParamsSchema = z5.object({}).passthrough();
795
909
  var InitializeSessionRequestSchema = JsonRpcRequestSchema.extend({
796
910
  method: z5.literal("droid.initialize_session" /* INITIALIZE_SESSION */),
797
911
  params: InitializeSessionRequestParamsSchema
@@ -852,6 +966,10 @@ var ListMcpToolsRequestSchema = JsonRpcRequestSchema.extend({
852
966
  method: z5.literal("droid.list_mcp_tools" /* LIST_MCP_TOOLS */),
853
967
  params: ListMcpToolsRequestParamsSchema
854
968
  });
969
+ var ListToolsRequestSchema = JsonRpcRequestSchema.extend({
970
+ method: z5.literal("droid.list_tools" /* LIST_TOOLS */),
971
+ params: ListToolsRequestParamsSchema
972
+ });
855
973
  var ListMcpServersRequestSchema = JsonRpcRequestSchema.extend({
856
974
  method: z5.literal("droid.list_mcp_servers" /* LIST_MCP_SERVERS */),
857
975
  params: ListMcpServersRequestParamsSchema
@@ -868,6 +986,30 @@ var SubmitBugReportRequestSchema = JsonRpcRequestSchema.extend({
868
986
  method: z5.literal("droid.submit_bug_report" /* SUBMIT_BUG_REPORT */),
869
987
  params: SubmitBugReportRequestParamsSchema
870
988
  });
989
+ var GetRewindInfoRequestSchema = JsonRpcRequestSchema.extend({
990
+ method: z5.literal("droid.get_rewind_info" /* GET_REWIND_INFO */),
991
+ params: GetRewindInfoRequestParamsSchema
992
+ });
993
+ var ExecuteRewindRequestSchema = JsonRpcRequestSchema.extend({
994
+ method: z5.literal("droid.execute_rewind" /* EXECUTE_REWIND */),
995
+ params: ExecuteRewindRequestParamsSchema
996
+ });
997
+ var CompactSessionRequestSchema = JsonRpcRequestSchema.extend({
998
+ method: z5.literal("droid.compact_session" /* COMPACT_SESSION */),
999
+ params: CompactSessionRequestParamsSchema
1000
+ });
1001
+ var ForkSessionRequestSchema = JsonRpcRequestSchema.extend({
1002
+ method: z5.literal("droid.fork_session" /* FORK_SESSION */),
1003
+ params: ForkSessionRequestParamsSchema
1004
+ });
1005
+ var GetContextStatsRequestSchema = JsonRpcRequestSchema.extend({
1006
+ method: z5.literal("droid.get_context_stats" /* GET_CONTEXT_STATS */),
1007
+ params: GetContextStatsRequestParamsSchema
1008
+ });
1009
+ var RenameSessionRequestSchema = JsonRpcRequestSchema.extend({
1010
+ method: z5.literal("droid.rename_session" /* RENAME_SESSION */),
1011
+ params: RenameSessionRequestParamsSchema
1012
+ });
871
1013
  var ClientRequestSchema = z5.discriminatedUnion("method", [
872
1014
  InitializeSessionRequestSchema,
873
1015
  LoadSessionRequestSchema,
@@ -884,10 +1026,17 @@ var ClientRequestSchema = z5.discriminatedUnion("method", [
884
1026
  RemoveMcpServerRequestSchema,
885
1027
  ListMcpRegistryRequestSchema,
886
1028
  ListMcpToolsRequestSchema,
1029
+ ListToolsRequestSchema,
887
1030
  ListMcpServersRequestSchema,
888
1031
  ToggleMcpToolRequestSchema,
889
1032
  ListSkillsRequestSchema,
890
- SubmitBugReportRequestSchema
1033
+ SubmitBugReportRequestSchema,
1034
+ GetRewindInfoRequestSchema,
1035
+ ExecuteRewindRequestSchema,
1036
+ CompactSessionRequestSchema,
1037
+ ForkSessionRequestSchema,
1038
+ GetContextStatsRequestSchema,
1039
+ RenameSessionRequestSchema
891
1040
  ]);
892
1041
  var MissionSnapshotSchema = z5.object({
893
1042
  state: z5.nativeEnum(MissionState),
@@ -900,20 +1049,20 @@ var MissionSnapshotSchema = z5.object({
900
1049
  }).passthrough();
901
1050
  var InitializeSessionResultSchema = z5.object({
902
1051
  sessionId: z5.string(),
903
- session: z5.record(z5.unknown()),
1052
+ session: JsonObjectSchema,
904
1053
  mcpServers: z5.array(McpServerConfigSchema).optional(),
905
1054
  settings: SessionSettingsSchema,
906
1055
  gitRepo: GitRepoInfoSchema.optional(),
907
1056
  availableModels: z5.array(AvailableModelConfigSchema).optional()
908
1057
  }).passthrough();
909
1058
  var LoadSessionResultSchema = z5.object({
910
- session: z5.record(z5.unknown()),
1059
+ session: JsonObjectSchema,
911
1060
  mcpServers: z5.array(McpServerConfigSchema).optional(),
912
- pendingPermissions: z5.array(z5.record(z5.unknown())).optional(),
913
- pendingAskUserRequests: z5.array(z5.record(z5.unknown())).optional(),
1061
+ pendingPermissions: z5.array(JsonObjectSchema).optional(),
1062
+ pendingAskUserRequests: z5.array(JsonObjectSchema).optional(),
914
1063
  settings: SessionSettingsSchema,
915
1064
  isAgentLoopInProgress: z5.boolean().optional(),
916
- queuedMessages: z5.array(z5.record(z5.unknown())).optional(),
1065
+ queuedMessages: z5.array(JsonObjectSchema).optional(),
917
1066
  gitRepo: GitRepoInfoSchema.optional(),
918
1067
  cwd: z5.string().optional(),
919
1068
  callingSessionId: z5.string().optional(),
@@ -923,26 +1072,48 @@ var LoadSessionResultSchema = z5.object({
923
1072
  mission: MissionSnapshotSchema.optional(),
924
1073
  decompSessionType: z5.nativeEnum(DecompSessionType).optional()
925
1074
  }).passthrough();
926
- var AddUserMessageResultSchema = z5.object({}).passthrough();
927
- var InterruptSessionResultSchema = z5.object({}).passthrough();
928
- var KillWorkerSessionResultSchema = z5.object({}).passthrough();
929
- var UpdateSessionSettingsResultSchema = z5.object({}).passthrough();
930
- var ToggleMcpServerResultSchema = z5.object({ success: z5.boolean() }).passthrough();
931
- var AuthenticateMcpServerResultSchema = z5.object({ success: z5.boolean() }).passthrough();
932
- var CancelMcpAuthResultSchema = z5.object({ success: z5.boolean() }).passthrough();
933
- var ClearMcpAuthResultSchema = z5.object({ success: z5.boolean() }).passthrough();
934
- var SubmitMcpAuthCodeResultSchema = z5.object({ success: z5.boolean() }).passthrough();
935
- var AddMcpServerResultSchema = z5.object({ success: z5.boolean() }).passthrough();
936
- var RemoveMcpServerResultSchema = z5.object({ success: z5.boolean() }).passthrough();
1075
+ var AddUserMessageResultSchema = EmptyResultSchema;
1076
+ var InterruptSessionResultSchema = EmptyResultSchema;
1077
+ var KillWorkerSessionResultSchema = EmptyResultSchema;
1078
+ var UpdateSessionSettingsResultSchema = EmptyResultSchema;
1079
+ var ToggleMcpServerResultSchema = SuccessResultSchema;
1080
+ var AuthenticateMcpServerResultSchema = SuccessResultSchema;
1081
+ var CancelMcpAuthResultSchema = SuccessResultSchema;
1082
+ var ClearMcpAuthResultSchema = SuccessResultSchema;
1083
+ var SubmitMcpAuthCodeResultSchema = SuccessResultSchema;
1084
+ var AddMcpServerResultSchema = SuccessResultSchema;
1085
+ var RemoveMcpServerResultSchema = SuccessResultSchema;
937
1086
  var ListMcpRegistryResultSchema = z5.object({ servers: z5.array(McpRegistryServerSchema) }).passthrough();
938
1087
  var ListMcpToolsResultSchema = z5.object({ tools: z5.array(McpToolInfoSchema) }).passthrough();
1088
+ var ListToolsResultSchema = z5.object({ tools: z5.array(ExecToolInfoSchema) }).passthrough();
939
1089
  var ListMcpServersResultSchema = z5.object({
940
1090
  servers: z5.array(McpServerStatusInfoSchema),
941
1091
  summary: McpStatusSummarySchema
942
1092
  }).passthrough();
943
- var ToggleMcpToolResultSchema = z5.object({ success: z5.boolean() }).passthrough();
1093
+ var ToggleMcpToolResultSchema = SuccessResultSchema;
944
1094
  var ListSkillsResultSchema = z5.object({ skills: z5.array(SkillInfoSchema) }).passthrough();
945
1095
  var SubmitBugReportResultSchema = z5.object({ bugReportId: z5.string() }).passthrough();
1096
+ var GetRewindInfoResultSchema = z5.object({
1097
+ availableFiles: z5.array(RewindFileSnapshotSchema),
1098
+ createdFiles: z5.array(RewindFileCreationSchema),
1099
+ evictedFiles: z5.array(RewindEvictedFileSchema)
1100
+ }).passthrough();
1101
+ var ExecuteRewindResultSchema = z5.object({
1102
+ newSessionId: z5.string(),
1103
+ restoredCount: z5.number(),
1104
+ deletedCount: z5.number(),
1105
+ failedRestoreCount: z5.number(),
1106
+ failedDeleteCount: z5.number()
1107
+ }).passthrough();
1108
+ var CompactSessionResultSchema = z5.object({
1109
+ newSessionId: z5.string(),
1110
+ removedCount: z5.number()
1111
+ }).passthrough();
1112
+ var ForkSessionResultSchema = z5.object({
1113
+ newSessionId: z5.string()
1114
+ }).passthrough();
1115
+ var GetContextStatsResultSchema = ContextStatsSchema;
1116
+ var RenameSessionResultSchema = SuccessResultSchema;
946
1117
  var InitializeSessionResponseSchema = z5.union([
947
1118
  JsonRpcResponseSuccessSchema.extend({
948
1119
  result: InitializeSessionResultSchema
@@ -1020,6 +1191,10 @@ var ListMcpToolsResponseSchema = z5.union([
1020
1191
  JsonRpcResponseSuccessSchema.extend({ result: ListMcpToolsResultSchema }),
1021
1192
  JsonRpcResponseFailureSchema
1022
1193
  ]);
1194
+ var ListToolsResponseSchema = z5.union([
1195
+ JsonRpcResponseSuccessSchema.extend({ result: ListToolsResultSchema }),
1196
+ JsonRpcResponseFailureSchema
1197
+ ]);
1023
1198
  var ListMcpServersResponseSchema = z5.union([
1024
1199
  JsonRpcResponseSuccessSchema.extend({ result: ListMcpServersResultSchema }),
1025
1200
  JsonRpcResponseFailureSchema
@@ -1036,145 +1211,194 @@ var SubmitBugReportResponseSchema = z5.union([
1036
1211
  JsonRpcResponseSuccessSchema.extend({ result: SubmitBugReportResultSchema }),
1037
1212
  JsonRpcResponseFailureSchema
1038
1213
  ]);
1214
+ var GetRewindInfoResponseSchema = z5.union([
1215
+ JsonRpcResponseSuccessSchema.extend({ result: GetRewindInfoResultSchema }),
1216
+ JsonRpcResponseFailureSchema
1217
+ ]);
1218
+ var ExecuteRewindResponseSchema = z5.union([
1219
+ JsonRpcResponseSuccessSchema.extend({ result: ExecuteRewindResultSchema }),
1220
+ JsonRpcResponseFailureSchema
1221
+ ]);
1222
+ var CompactSessionResponseSchema = z5.union([
1223
+ JsonRpcResponseSuccessSchema.extend({ result: CompactSessionResultSchema }),
1224
+ JsonRpcResponseFailureSchema
1225
+ ]);
1226
+ var ForkSessionResponseSchema = z5.union([
1227
+ JsonRpcResponseSuccessSchema.extend({ result: ForkSessionResultSchema }),
1228
+ JsonRpcResponseFailureSchema
1229
+ ]);
1230
+ var GetContextStatsResponseSchema = z5.union([
1231
+ JsonRpcResponseSuccessSchema.extend({ result: GetContextStatsResultSchema }),
1232
+ JsonRpcResponseFailureSchema
1233
+ ]);
1234
+ var RenameSessionResponseSchema = z5.union([
1235
+ JsonRpcResponseSuccessSchema.extend({ result: RenameSessionResultSchema }),
1236
+ JsonRpcResponseFailureSchema
1237
+ ]);
1039
1238
 
1040
- // src/schemas/server.ts
1041
- import { z as z6 } from "zod";
1042
- var ToolUseSchema = z6.object({
1043
- type: z6.literal("tool_use"),
1239
+ // src/schemas/session-metadata.ts
1240
+ var SessionMetadataSchema = z6.object({
1044
1241
  id: z6.string(),
1045
- input: z6.record(z6.unknown()),
1046
- name: z6.string(),
1047
- thoughtSignature: z6.string().optional()
1048
- }).passthrough();
1049
- var ErrorDetailSchema = z6.object({
1050
- name: z6.string(),
1051
- message: z6.string()
1052
- }).passthrough();
1053
- var ToolProgressUpdateSchema = z6.object({
1054
- type: z6.enum(["tool_call", "tool_result", "error", "status", "message"]),
1055
- toolName: z6.string().optional(),
1056
- status: z6.string().optional(),
1057
- details: z6.string().optional(),
1058
- text: z6.string().optional(),
1059
- error: z6.string().optional(),
1060
- timestamp: z6.number().optional(),
1061
- parameters: z6.record(z6.unknown()).optional(),
1062
- valueSnippet: z6.string().optional(),
1063
- subagentSessionId: z6.string().optional()
1064
- }).passthrough();
1065
- var SettingsUpdatedPayloadSchema = z6.object({
1066
- autonomyMode: z6.nativeEnum(AutonomyMode).optional(),
1067
- interactionMode: z6.nativeEnum(DroidInteractionMode).optional().catch(void 0),
1068
- autonomyLevel: z6.nativeEnum(AutonomyLevel).optional().catch(void 0),
1069
- modelId: z6.string().optional(),
1070
- reasoningEffort: z6.nativeEnum(ReasoningEffort).optional(),
1071
- specModeModelId: z6.string().optional(),
1072
- specModeReasoningEffort: z6.nativeEnum(ReasoningEffort).optional()
1073
- }).passthrough();
1074
- var ToolResultNotificationSchema = z6.object({
1075
- type: z6.literal("tool_result" /* TOOL_RESULT */),
1076
- messageId: z6.string(),
1077
- toolUseId: z6.string(),
1078
- content: z6.unknown().optional(),
1079
- isError: z6.boolean().optional(),
1080
- id: z6.string().optional()
1081
- }).passthrough();
1082
- var ToolProgressUpdateNotificationSchema = z6.object({
1083
- type: z6.literal("tool_progress_update" /* TOOL_PROGRESS_UPDATE */),
1084
- toolUseId: z6.string(),
1085
- toolName: z6.string(),
1242
+ title: z6.string(),
1243
+ sessionTitle: z6.string().optional(),
1244
+ owner: z6.string(),
1245
+ messageCount: z6.number(),
1246
+ modifiedTime: z6.date(),
1247
+ createdTime: z6.date(),
1248
+ isFavorite: z6.boolean().optional(),
1249
+ cwd: z6.string().optional(),
1250
+ decompSessionType: z6.nativeEnum(DecompSessionType).optional(),
1251
+ decompMissionId: z6.string().optional()
1252
+ }).passthrough();
1253
+ var SessionStartEventSchema = z6.object({
1254
+ type: z6.literal("session_start"),
1255
+ sessionId: z6.string().optional(),
1256
+ title: z6.string().optional(),
1257
+ sessionTitle: z6.string().optional(),
1258
+ owner: z6.string().optional(),
1259
+ cwd: z6.string().optional(),
1260
+ decompSessionType: z6.nativeEnum(DecompSessionType).optional().catch(void 0),
1261
+ decompMissionId: z6.string().optional()
1262
+ }).passthrough();
1263
+ var SessionSettingsFileSchema = z6.object({
1264
+ archivedAt: z6.string().optional(),
1265
+ tags: z6.array(SessionTagSchema).optional()
1266
+ }).passthrough();
1267
+
1268
+ // src/schemas/server.ts
1269
+ import { z as z7 } from "zod";
1270
+ var ToolUseBlockSchema2 = ToolUseBlockSchema;
1271
+ var ToolUseSchema = ToolUseBlockSchema2;
1272
+ var ErrorDetailSchema = z7.object({
1273
+ name: z7.string(),
1274
+ message: z7.string()
1275
+ }).passthrough();
1276
+ var ToolProgressUpdateSchema = z7.object({
1277
+ type: z7.enum(["tool_call", "tool_result", "error", "status", "message"]),
1278
+ toolName: z7.string().optional(),
1279
+ status: z7.string().optional(),
1280
+ details: z7.string().optional(),
1281
+ text: z7.string().optional(),
1282
+ error: z7.string().optional(),
1283
+ timestamp: z7.number().optional(),
1284
+ parameters: JsonObjectSchema.optional(),
1285
+ valueSnippet: z7.string().optional(),
1286
+ subagentSessionId: z7.string().optional()
1287
+ }).passthrough();
1288
+ var SettingsUpdatedPayloadSchema = z7.object({
1289
+ autonomyMode: z7.nativeEnum(AutonomyMode).optional(),
1290
+ interactionMode: z7.nativeEnum(DroidInteractionMode).optional().catch(void 0),
1291
+ autonomyLevel: z7.nativeEnum(AutonomyLevel).optional().catch(void 0),
1292
+ modelId: z7.string().optional(),
1293
+ reasoningEffort: z7.nativeEnum(ReasoningEffort).optional(),
1294
+ specModeModelId: z7.string().optional(),
1295
+ specModeReasoningEffort: z7.nativeEnum(ReasoningEffort).optional(),
1296
+ ...ToolSelectionOverridesSchema.shape
1297
+ }).passthrough();
1298
+ var ToolResultNotificationSchema = z7.object({
1299
+ type: z7.literal("tool_result" /* TOOL_RESULT */),
1300
+ messageId: z7.string(),
1301
+ toolUseId: z7.string(),
1302
+ content: JsonValueSchema.optional(),
1303
+ isError: z7.boolean().optional(),
1304
+ id: z7.string().optional()
1305
+ }).passthrough();
1306
+ var ToolProgressUpdateNotificationSchema = z7.object({
1307
+ type: z7.literal("tool_progress_update" /* TOOL_PROGRESS_UPDATE */),
1308
+ toolUseId: z7.string(),
1309
+ toolName: z7.string(),
1086
1310
  update: ToolProgressUpdateSchema
1087
1311
  }).passthrough();
1088
- var CreateMessageNotificationSchema = z6.object({
1089
- type: z6.literal("create_message" /* CREATE_MESSAGE */),
1312
+ var CreateMessageNotificationSchema = z7.object({
1313
+ type: z7.literal("create_message" /* CREATE_MESSAGE */),
1090
1314
  message: FactoryDroidMessageSchema,
1091
- parentId: z6.string().optional(),
1092
- requestId: z6.string().optional()
1093
- }).passthrough();
1094
- var ErrorNotificationSchema = z6.object({
1095
- type: z6.literal("error" /* ERROR */),
1096
- message: z6.string(),
1097
- errorType: z6.nativeEnum(DroidErrorType),
1098
- timestamp: z6.string(),
1315
+ parentId: z7.string().optional(),
1316
+ requestId: z7.string().optional()
1317
+ }).passthrough();
1318
+ var ErrorNotificationSchema = z7.object({
1319
+ type: z7.literal("error" /* ERROR */),
1320
+ message: z7.string(),
1321
+ errorType: z7.nativeEnum(DroidErrorType),
1322
+ timestamp: z7.string(),
1099
1323
  error: ErrorDetailSchema.optional()
1100
1324
  }).passthrough();
1101
- var DroidWorkingStateChangedNotificationSchema = z6.object({
1102
- type: z6.literal("droid_working_state_changed" /* DROID_WORKING_STATE_CHANGED */),
1103
- newState: z6.nativeEnum(DroidWorkingState)
1325
+ var DroidWorkingStateChangedNotificationSchema = z7.object({
1326
+ type: z7.literal("droid_working_state_changed" /* DROID_WORKING_STATE_CHANGED */),
1327
+ newState: z7.nativeEnum(DroidWorkingState)
1104
1328
  }).passthrough();
1105
- var PermissionResolvedNotificationSchema = z6.object({
1106
- type: z6.literal("permission_resolved" /* PERMISSION_RESOLVED */),
1107
- requestId: z6.string(),
1108
- toolUseIds: z6.array(z6.string()),
1109
- selectedOption: z6.nativeEnum(ToolConfirmationOutcome)
1329
+ var PermissionResolvedNotificationSchema = z7.object({
1330
+ type: z7.literal("permission_resolved" /* PERMISSION_RESOLVED */),
1331
+ requestId: z7.string(),
1332
+ toolUseIds: z7.array(z7.string()),
1333
+ selectedOption: z7.nativeEnum(ToolConfirmationOutcome)
1110
1334
  }).passthrough();
1111
- var SettingsUpdatedNotificationSchema = z6.object({
1112
- type: z6.literal("settings_updated" /* SETTINGS_UPDATED */),
1335
+ var SettingsUpdatedNotificationSchema = z7.object({
1336
+ type: z7.literal("settings_updated" /* SETTINGS_UPDATED */),
1113
1337
  settings: SettingsUpdatedPayloadSchema
1114
1338
  }).passthrough();
1115
- var SessionTitleUpdatedNotificationSchema = z6.object({
1116
- type: z6.literal("session_title_updated" /* SESSION_TITLE_UPDATED */),
1117
- title: z6.string()
1339
+ var SessionTitleUpdatedNotificationSchema = z7.object({
1340
+ type: z7.literal("session_title_updated" /* SESSION_TITLE_UPDATED */),
1341
+ title: z7.string()
1118
1342
  }).passthrough();
1119
- var McpStatusChangedNotificationSchema = z6.object({
1120
- type: z6.literal("mcp_status_changed" /* MCP_STATUS_CHANGED */),
1121
- servers: z6.array(McpServerStatusInfoSchema),
1343
+ var McpStatusChangedNotificationSchema = z7.object({
1344
+ type: z7.literal("mcp_status_changed" /* MCP_STATUS_CHANGED */),
1345
+ servers: z7.array(McpServerStatusInfoSchema),
1122
1346
  summary: McpStatusSummarySchema
1123
1347
  }).passthrough();
1124
- var AssistantTextDeltaNotificationSchema = z6.object({
1125
- type: z6.literal("assistant_text_delta" /* ASSISTANT_TEXT_DELTA */),
1126
- messageId: z6.string(),
1127
- blockIndex: z6.number(),
1128
- textDelta: z6.string()
1129
- }).passthrough();
1130
- var ThinkingTextDeltaNotificationSchema = z6.object({
1131
- type: z6.literal("thinking_text_delta" /* THINKING_TEXT_DELTA */),
1132
- messageId: z6.string(),
1133
- blockIndex: z6.number(),
1134
- textDelta: z6.string()
1135
- }).passthrough();
1136
- var SessionTokenUsageChangedNotificationSchema = z6.object({
1137
- type: z6.literal("session_token_usage_changed" /* SESSION_TOKEN_USAGE_CHANGED */),
1138
- sessionId: z6.string(),
1348
+ var AssistantTextDeltaNotificationSchema = z7.object({
1349
+ type: z7.literal("assistant_text_delta" /* ASSISTANT_TEXT_DELTA */),
1350
+ messageId: z7.string(),
1351
+ blockIndex: z7.number(),
1352
+ textDelta: z7.string()
1353
+ }).passthrough();
1354
+ var ThinkingTextDeltaNotificationSchema = z7.object({
1355
+ type: z7.literal("thinking_text_delta" /* THINKING_TEXT_DELTA */),
1356
+ messageId: z7.string(),
1357
+ blockIndex: z7.number(),
1358
+ textDelta: z7.string()
1359
+ }).passthrough();
1360
+ var SessionTokenUsageChangedNotificationSchema = z7.object({
1361
+ type: z7.literal("session_token_usage_changed" /* SESSION_TOKEN_USAGE_CHANGED */),
1362
+ sessionId: z7.string(),
1139
1363
  tokenUsage: TokenUsageSchema
1140
1364
  }).passthrough();
1141
- var MissionStateChangedNotificationSchema = z6.object({
1142
- type: z6.literal("mission_state_changed" /* MISSION_STATE_CHANGED */),
1143
- state: z6.nativeEnum(MissionState)
1365
+ var MissionStateChangedNotificationSchema = z7.object({
1366
+ type: z7.literal("mission_state_changed" /* MISSION_STATE_CHANGED */),
1367
+ state: z7.nativeEnum(MissionState)
1144
1368
  }).passthrough();
1145
- var MissionFeaturesChangedNotificationSchema = z6.object({
1146
- type: z6.literal("mission_features_changed" /* MISSION_FEATURES_CHANGED */),
1147
- features: z6.array(MissionFeatureSchema)
1369
+ var MissionFeaturesChangedNotificationSchema = z7.object({
1370
+ type: z7.literal("mission_features_changed" /* MISSION_FEATURES_CHANGED */),
1371
+ features: z7.array(MissionFeatureSchema)
1148
1372
  }).passthrough();
1149
- var MissionProgressEntryNotificationSchema = z6.object({
1150
- type: z6.literal("mission_progress_entry" /* MISSION_PROGRESS_ENTRY */),
1151
- progressLog: z6.array(ProgressLogEntrySchema)
1373
+ var MissionProgressEntryNotificationSchema = z7.object({
1374
+ type: z7.literal("mission_progress_entry" /* MISSION_PROGRESS_ENTRY */),
1375
+ progressLog: z7.array(ProgressLogEntrySchema)
1152
1376
  }).passthrough();
1153
- var MissionHeartbeatNotificationSchema = z6.object({
1154
- type: z6.literal("mission_heartbeat" /* MISSION_HEARTBEAT */),
1155
- timestamp: z6.string()
1377
+ var MissionHeartbeatNotificationSchema = z7.object({
1378
+ type: z7.literal("mission_heartbeat" /* MISSION_HEARTBEAT */),
1379
+ timestamp: z7.string()
1156
1380
  }).passthrough();
1157
- var MissionWorkerStartedNotificationSchema = z6.object({
1158
- type: z6.literal("mission_worker_started" /* MISSION_WORKER_STARTED */),
1159
- workerSessionId: z6.string()
1381
+ var MissionWorkerStartedNotificationSchema = z7.object({
1382
+ type: z7.literal("mission_worker_started" /* MISSION_WORKER_STARTED */),
1383
+ workerSessionId: z7.string()
1160
1384
  }).passthrough();
1161
- var MissionWorkerCompletedNotificationSchema = z6.object({
1162
- type: z6.literal("mission_worker_completed" /* MISSION_WORKER_COMPLETED */),
1163
- workerSessionId: z6.string(),
1164
- exitCode: z6.number()
1385
+ var MissionWorkerCompletedNotificationSchema = z7.object({
1386
+ type: z7.literal("mission_worker_completed" /* MISSION_WORKER_COMPLETED */),
1387
+ workerSessionId: z7.string(),
1388
+ exitCode: z7.number()
1165
1389
  }).passthrough();
1166
- var McpAuthRequiredNotificationSchema = z6.object({
1167
- type: z6.literal("mcp_auth_required" /* MCP_AUTH_REQUIRED */),
1168
- serverName: z6.string(),
1169
- authUrl: z6.string(),
1170
- message: z6.string(),
1171
- state: z6.string()
1390
+ var McpAuthRequiredNotificationSchema = z7.object({
1391
+ type: z7.literal("mcp_auth_required" /* MCP_AUTH_REQUIRED */),
1392
+ serverName: z7.string(),
1393
+ authUrl: z7.string(),
1394
+ message: z7.string(),
1395
+ state: z7.string()
1172
1396
  }).passthrough();
1173
- var McpAuthCompletedNotificationSchema = z6.object({
1174
- type: z6.literal("mcp_auth_completed" /* MCP_AUTH_COMPLETED */),
1175
- serverName: z6.string(),
1176
- outcome: z6.nativeEnum(McpAuthOutcome),
1177
- message: z6.string()
1397
+ var McpAuthCompletedNotificationSchema = z7.object({
1398
+ type: z7.literal("mcp_auth_completed" /* MCP_AUTH_COMPLETED */),
1399
+ serverName: z7.string(),
1400
+ outcome: z7.nativeEnum(McpAuthOutcome),
1401
+ message: z7.string()
1178
1402
  }).passthrough();
1179
1403
  var SessionNotificationSchemaList = [
1180
1404
  ToolResultNotificationSchema,
@@ -1198,84 +1422,86 @@ var SessionNotificationSchemaList = [
1198
1422
  McpAuthRequiredNotificationSchema,
1199
1423
  McpAuthCompletedNotificationSchema
1200
1424
  ];
1201
- var SessionNotificationPayloadSchema = z6.discriminatedUnion(
1425
+ var SessionNotificationPayloadSchema = z7.discriminatedUnion(
1202
1426
  "type",
1203
1427
  SessionNotificationSchemaList
1204
1428
  );
1205
- var SessionNotificationParamsSchema = z6.object({
1429
+ var _SessionNotificationParamsSchema = z7.object({
1206
1430
  notification: SessionNotificationPayloadSchema
1207
1431
  }).passthrough();
1208
- var SessionNotificationSchema = JsonRpcNotificationSchema.extend({
1209
- method: z6.literal("droid.session_notification" /* SESSION_NOTIFICATION */),
1432
+ var SessionNotificationParamsSchema = _SessionNotificationParamsSchema;
1433
+ var _SessionNotificationSchema = JsonRpcNotificationSchema.extend({
1434
+ method: z7.literal("droid.session_notification" /* SESSION_NOTIFICATION */),
1210
1435
  params: SessionNotificationParamsSchema
1211
1436
  });
1212
- var EditToolConfirmationDetailsSchema = z6.object({
1213
- type: z6.literal("edit" /* Edit */),
1214
- filePath: z6.string(),
1215
- fileName: z6.string(),
1216
- oldContent: z6.string().optional(),
1217
- newContent: z6.string().optional()
1218
- }).passthrough();
1219
- var ExecuteToolConfirmationDetailsSchema = z6.object({
1220
- type: z6.literal("exec" /* Execute */),
1221
- fullCommand: z6.string(),
1222
- command: z6.string(),
1223
- extractedCommands: z6.array(z6.string()).optional(),
1224
- impactLevel: z6.string().optional()
1225
- }).passthrough();
1226
- var CreateToolConfirmationDetailsSchema = z6.object({
1227
- type: z6.literal("create" /* Create */),
1228
- filePath: z6.string(),
1229
- fileName: z6.string(),
1230
- content: z6.string()
1231
- }).passthrough();
1232
- var AskUserQuestionSchema = z6.object({
1233
- index: z6.number(),
1234
- topic: z6.string(),
1235
- question: z6.string(),
1236
- options: z6.array(z6.string())
1237
- }).passthrough();
1238
- var AskUserConfirmationDetailsSchema = z6.object({
1239
- type: z6.literal("ask_user" /* AskUser */),
1240
- questionnaire: z6.string(),
1241
- parsed: z6.object({
1242
- questions: z6.array(AskUserQuestionSchema)
1437
+ var SessionNotificationSchema = _SessionNotificationSchema;
1438
+ var EditToolConfirmationDetailsSchema = z7.object({
1439
+ type: z7.literal("edit" /* Edit */),
1440
+ filePath: z7.string(),
1441
+ fileName: z7.string(),
1442
+ oldContent: z7.string().optional(),
1443
+ newContent: z7.string().optional()
1444
+ }).passthrough();
1445
+ var ExecuteToolConfirmationDetailsSchema = z7.object({
1446
+ type: z7.literal("exec" /* Execute */),
1447
+ fullCommand: z7.string(),
1448
+ command: z7.string(),
1449
+ extractedCommands: z7.array(z7.string()).optional(),
1450
+ impactLevel: z7.string().optional()
1451
+ }).passthrough();
1452
+ var CreateToolConfirmationDetailsSchema = z7.object({
1453
+ type: z7.literal("create" /* Create */),
1454
+ filePath: z7.string(),
1455
+ fileName: z7.string(),
1456
+ content: z7.string()
1457
+ }).passthrough();
1458
+ var AskUserQuestionSchema = z7.object({
1459
+ index: z7.number(),
1460
+ topic: z7.string(),
1461
+ question: z7.string(),
1462
+ options: z7.array(z7.string())
1463
+ }).passthrough();
1464
+ var AskUserConfirmationDetailsSchema = z7.object({
1465
+ type: z7.literal("ask_user" /* AskUser */),
1466
+ questionnaire: z7.string(),
1467
+ parsed: z7.object({
1468
+ questions: z7.array(AskUserQuestionSchema)
1243
1469
  }).optional(),
1244
- parseError: z6.object({
1245
- message: z6.string(),
1246
- line: z6.number().optional()
1470
+ parseError: z7.object({
1471
+ message: z7.string(),
1472
+ line: z7.number().optional()
1247
1473
  }).optional()
1248
1474
  }).passthrough();
1249
- var ExitSpecModeConfirmationDetailsSchema = z6.object({
1250
- type: z6.literal("exit_spec_mode" /* ExitSpecMode */),
1251
- plan: z6.string(),
1252
- title: z6.string().optional(),
1253
- optionNames: z6.array(z6.string()).optional()
1254
- }).passthrough();
1255
- var ProposeMissionConfirmationDetailsSchema = z6.object({
1256
- type: z6.literal("propose_mission" /* ProposeMission */),
1257
- proposal: z6.string(),
1258
- title: z6.string().optional()
1259
- }).passthrough();
1260
- var StartMissionRunConfirmationDetailsSchema = z6.object({
1261
- type: z6.literal("start_mission_run" /* StartMissionRun */),
1262
- runningMissionCount: z6.number(),
1263
- runningMissionSessionIds: z6.array(z6.string())
1264
- }).passthrough();
1265
- var ApplyPatchToolConfirmationDetailsSchema = z6.object({
1266
- type: z6.literal("apply_patch" /* ApplyPatch */),
1267
- filePath: z6.string(),
1268
- fileName: z6.string(),
1269
- patchContent: z6.string(),
1270
- oldContent: z6.string().optional(),
1271
- newContent: z6.string().optional()
1272
- }).passthrough();
1273
- var McpToolConfirmationDetailsSchema = z6.object({
1274
- type: z6.literal("mcp_tool" /* McpTool */),
1275
- toolName: z6.string(),
1276
- impactLevel: z6.string()
1277
- }).passthrough();
1278
- var ToolConfirmationDetailsSchema = z6.discriminatedUnion("type", [
1475
+ var ExitSpecModeConfirmationDetailsSchema = z7.object({
1476
+ type: z7.literal("exit_spec_mode" /* ExitSpecMode */),
1477
+ plan: z7.string(),
1478
+ title: z7.string().optional(),
1479
+ optionNames: z7.array(z7.string()).optional()
1480
+ }).passthrough();
1481
+ var ProposeMissionConfirmationDetailsSchema = z7.object({
1482
+ type: z7.literal("propose_mission" /* ProposeMission */),
1483
+ proposal: z7.string(),
1484
+ title: z7.string().optional()
1485
+ }).passthrough();
1486
+ var StartMissionRunConfirmationDetailsSchema = z7.object({
1487
+ type: z7.literal("start_mission_run" /* StartMissionRun */),
1488
+ runningMissionCount: z7.number(),
1489
+ runningMissionSessionIds: z7.array(z7.string())
1490
+ }).passthrough();
1491
+ var ApplyPatchToolConfirmationDetailsSchema = z7.object({
1492
+ type: z7.literal("apply_patch" /* ApplyPatch */),
1493
+ filePath: z7.string(),
1494
+ fileName: z7.string(),
1495
+ patchContent: z7.string(),
1496
+ oldContent: z7.string().optional(),
1497
+ newContent: z7.string().optional()
1498
+ }).passthrough();
1499
+ var McpToolConfirmationDetailsSchema = z7.object({
1500
+ type: z7.literal("mcp_tool" /* McpTool */),
1501
+ toolName: z7.string(),
1502
+ impactLevel: z7.string()
1503
+ }).passthrough();
1504
+ var ToolConfirmationDetailsSchema = z7.discriminatedUnion("type", [
1279
1505
  EditToolConfirmationDetailsSchema,
1280
1506
  ExecuteToolConfirmationDetailsSchema,
1281
1507
  CreateToolConfirmationDetailsSchema,
@@ -1286,60 +1512,67 @@ var ToolConfirmationDetailsSchema = z6.discriminatedUnion("type", [
1286
1512
  ApplyPatchToolConfirmationDetailsSchema,
1287
1513
  McpToolConfirmationDetailsSchema
1288
1514
  ]);
1289
- var ToolConfirmationInfoSchema = z6.object({
1515
+ var ToolConfirmationInfoSchema = z7.object({
1290
1516
  toolUse: ToolUseSchema,
1291
- confirmationType: z6.nativeEnum(ToolConfirmationType),
1517
+ confirmationType: z7.nativeEnum(ToolConfirmationType),
1292
1518
  details: ToolConfirmationDetailsSchema
1293
1519
  }).passthrough();
1294
- var RequestPermissionRequestParamsSchema = z6.object({
1295
- toolUses: z6.array(ToolConfirmationInfoSchema),
1296
- options: z6.array(ToolConfirmationListItemSchema)
1520
+ var RequestPermissionRequestParamsSchema = z7.object({
1521
+ toolUses: z7.array(ToolConfirmationInfoSchema),
1522
+ options: z7.array(ToolConfirmationListItemSchema)
1297
1523
  }).passthrough();
1298
1524
  var RequestPermissionRequestSchema = JsonRpcRequestSchema.extend({
1299
- method: z6.literal("droid.request_permission" /* REQUEST_PERMISSION */),
1525
+ method: z7.literal("droid.request_permission" /* REQUEST_PERMISSION */),
1300
1526
  params: RequestPermissionRequestParamsSchema
1301
1527
  });
1302
- var RequestPermissionResultSchema = z6.object({
1303
- selectedOption: z6.nativeEnum(ToolConfirmationOutcome)
1528
+ var RequestPermissionResultSchema = z7.object({
1529
+ selectedOption: z7.nativeEnum(ToolConfirmationOutcome),
1530
+ comment: z7.string().optional()
1304
1531
  }).strict();
1305
- var RequestPermissionResponseSchema = z6.union([
1532
+ var RequestPermissionResponseSchema = z7.union([
1306
1533
  JsonRpcResponseSuccessSchema.extend({
1307
1534
  result: RequestPermissionResultSchema
1308
1535
  }),
1309
1536
  JsonRpcResponseFailureSchema
1310
1537
  ]);
1311
- var AskUserRequestParamsSchema = z6.object({
1312
- toolCallId: z6.string(),
1313
- questions: z6.array(AskUserQuestionSchema)
1538
+ var AskUserRequestParamsSchema = z7.object({
1539
+ toolCallId: z7.string(),
1540
+ questions: z7.array(AskUserQuestionSchema)
1314
1541
  }).passthrough();
1315
1542
  var AskUserRequestSchema = JsonRpcRequestSchema.extend({
1316
- method: z6.literal("droid.ask_user" /* ASK_USER */),
1543
+ method: z7.literal("droid.ask_user" /* ASK_USER */),
1317
1544
  params: AskUserRequestParamsSchema
1318
1545
  });
1319
- var AskUserCollectedAnswerSchema = z6.object({
1320
- index: z6.number(),
1321
- question: z6.string(),
1322
- answer: z6.string()
1546
+ var AskUserCollectedAnswerSchema = z7.object({
1547
+ index: z7.number(),
1548
+ question: z7.string(),
1549
+ answer: z7.string()
1323
1550
  }).strict();
1324
- var AskUserResultSchema = z6.object({
1325
- cancelled: z6.boolean().optional(),
1326
- answers: z6.array(AskUserCollectedAnswerSchema)
1551
+ var AskUserResultSchema = z7.object({
1552
+ cancelled: z7.boolean().optional(),
1553
+ answers: z7.array(AskUserCollectedAnswerSchema)
1327
1554
  }).strict();
1328
- var AskUserResponseSchema = z6.union([
1555
+ var AskUserResponseSchema = z7.union([
1329
1556
  JsonRpcResponseSuccessSchema.extend({ result: AskUserResultSchema }),
1330
1557
  JsonRpcResponseFailureSchema
1331
1558
  ]);
1332
- var CliRequestOrNotificationSchema = z6.union([
1559
+ var _CliRequestOrNotificationSchema = z7.union([
1333
1560
  SessionNotificationSchema,
1334
1561
  RequestPermissionRequestSchema,
1335
1562
  AskUserRequestSchema
1336
1563
  ]);
1564
+ var CliRequestOrNotificationSchema = _CliRequestOrNotificationSchema;
1565
+
1566
+ // src/constants.ts
1567
+ var SDK_VERSION = "0.2.0";
1568
+ var SDK_TAG = {
1569
+ name: "sdk",
1570
+ metadata: { language: "typescript", version: SDK_VERSION }
1571
+ };
1337
1572
 
1338
1573
  // src/errors.ts
1339
1574
  var ConnectionError = class _ConnectionError extends Error {
1340
- /** The working directory used when spawning the process. */
1341
1575
  cwd;
1342
- /** The executable path used when spawning the process. */
1343
1576
  execPath;
1344
1577
  constructor(message, options) {
1345
1578
  super(message);
@@ -1350,9 +1583,7 @@ var ConnectionError = class _ConnectionError extends Error {
1350
1583
  }
1351
1584
  };
1352
1585
  var ProtocolError = class _ProtocolError extends Error {
1353
- /** The JSON-RPC error code, if available. */
1354
1586
  code;
1355
- /** Additional error data from the JSON-RPC response. */
1356
1587
  data;
1357
1588
  constructor(message, options) {
1358
1589
  super(message);
@@ -1370,7 +1601,6 @@ var SessionError = class _SessionError extends Error {
1370
1601
  }
1371
1602
  };
1372
1603
  var SessionNotFoundError = class _SessionNotFoundError extends SessionError {
1373
- /** The ID of the session that was not found. */
1374
1604
  sessionId;
1375
1605
  constructor(sessionId) {
1376
1606
  super(`Session not found: ${sessionId}`);
@@ -1387,9 +1617,7 @@ var TimeoutError = class _TimeoutError extends Error {
1387
1617
  }
1388
1618
  };
1389
1619
  var ProcessExitError = class _ProcessExitError extends Error {
1390
- /** The exit code of the process, or null if terminated by signal. */
1391
1620
  exitCode;
1392
- /** The signal that terminated the process, or null if exited normally. */
1393
1621
  signal;
1394
1622
  constructor(message, options) {
1395
1623
  super(message);
@@ -1403,6 +1631,13 @@ var ProcessExitError = class _ProcessExitError extends Error {
1403
1631
  // src/transport.ts
1404
1632
  import { spawn } from "child_process";
1405
1633
  import * as readline from "readline";
1634
+
1635
+ // src/utils.ts
1636
+ function isRecord(value) {
1637
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1638
+ }
1639
+
1640
+ // src/transport.ts
1406
1641
  var DEFAULT_EXEC_ARGS = [
1407
1642
  "exec",
1408
1643
  "--input-format",
@@ -1421,12 +1656,9 @@ var ProcessTransport = class {
1421
1656
  readlineInterface = null;
1422
1657
  messageHandler = null;
1423
1658
  errorHandler = null;
1424
- /**
1425
- * Sticky error from a process error or unexpected exit. Once set,
1426
- * all subsequent `send()` calls throw immediately.
1427
- */
1659
+ /** Once set, all subsequent `send()` calls throw immediately. */
1428
1660
  processError = null;
1429
- /** Promise-chain serializer for stdin writes. */
1661
+ /** Serializes stdin writes to prevent interleaving. */
1430
1662
  writeChain = Promise.resolve();
1431
1663
  _isConnected = false;
1432
1664
  isClosing = false;
@@ -1437,9 +1669,6 @@ var ProcessTransport = class {
1437
1669
  this.env = options.env;
1438
1670
  this.gracePeriodMs = (options.gracePeriod ?? DEFAULT_GRACE_PERIOD_MS / 1e3) * 1e3;
1439
1671
  }
1440
- // -----------------------------------------------------------------------
1441
- // DroidClientTransport interface
1442
- // -----------------------------------------------------------------------
1443
1672
  get isConnected() {
1444
1673
  return this._isConnected;
1445
1674
  }
@@ -1491,7 +1720,7 @@ var ProcessTransport = class {
1491
1720
  if (this.processError) {
1492
1721
  throw this.processError;
1493
1722
  }
1494
- await new Promise((resolve, reject) => {
1723
+ await new Promise((resolve2, reject) => {
1495
1724
  if (!this.childProcess || !this.childProcess.stdin) {
1496
1725
  reject(
1497
1726
  new ConnectionError("Process stdin unavailable", {
@@ -1527,7 +1756,7 @@ var ProcessTransport = class {
1527
1756
  );
1528
1757
  }
1529
1758
  } else {
1530
- resolve();
1759
+ resolve2();
1531
1760
  }
1532
1761
  });
1533
1762
  });
@@ -1552,7 +1781,7 @@ var ProcessTransport = class {
1552
1781
  this.readlineInterface = null;
1553
1782
  }
1554
1783
  if (proc && proc.exitCode === null && !proc.killed) {
1555
- await new Promise((resolve) => {
1784
+ await new Promise((resolve2) => {
1556
1785
  const timeout = setTimeout(() => {
1557
1786
  if (proc.exitCode === null && !proc.killed) {
1558
1787
  try {
@@ -1563,7 +1792,7 @@ var ProcessTransport = class {
1563
1792
  }, this.gracePeriodMs);
1564
1793
  proc.once("exit", () => {
1565
1794
  clearTimeout(timeout);
1566
- resolve();
1795
+ resolve2();
1567
1796
  });
1568
1797
  if (proc.stdin) {
1569
1798
  try {
@@ -1575,15 +1804,12 @@ var ProcessTransport = class {
1575
1804
  proc.kill("SIGTERM");
1576
1805
  } catch {
1577
1806
  clearTimeout(timeout);
1578
- resolve();
1807
+ resolve2();
1579
1808
  }
1580
1809
  });
1581
1810
  }
1582
1811
  this.isClosing = false;
1583
1812
  }
1584
- // -----------------------------------------------------------------------
1585
- // Private helpers
1586
- // -----------------------------------------------------------------------
1587
1813
  setupHandlers() {
1588
1814
  const proc = this.childProcess;
1589
1815
  if (!proc || !proc.stdout) {
@@ -1598,10 +1824,10 @@ var ProcessTransport = class {
1598
1824
  if (!trimmed) {
1599
1825
  return;
1600
1826
  }
1601
- if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
1827
+ if (trimmed.startsWith("{")) {
1602
1828
  try {
1603
1829
  const parsed = JSON.parse(trimmed);
1604
- if (this.messageHandler && typeof parsed === "object" && parsed !== null) {
1830
+ if (this.messageHandler && isRecord(parsed)) {
1605
1831
  this.messageHandler(parsed);
1606
1832
  }
1607
1833
  } catch {
@@ -1657,23 +1883,12 @@ import { v4 as uuidv4 } from "uuid";
1657
1883
  var ProtocolEngine = class {
1658
1884
  _transport;
1659
1885
  _defaultTimeout;
1660
- /** Pending requests keyed by UUID string. */
1661
1886
  _pendingRequests = /* @__PURE__ */ new Map();
1662
- /** Notification listener registry. */
1663
1887
  _notificationListeners = /* @__PURE__ */ new Set();
1664
- /** Server→client request handlers. */
1665
1888
  _permissionHandler = null;
1666
1889
  _askUserHandler = null;
1667
- /** Sticky transport error — once set, all requests fail immediately. */
1668
1890
  _transportError = null;
1669
- /** Closed flag — once true, new requests are rejected. */
1670
1891
  _closed = false;
1671
- /**
1672
- * Create a new ProtocolEngine.
1673
- *
1674
- * @param options.transport - A connected DroidClientTransport implementation.
1675
- * @param options.defaultTimeout - Default timeout in ms for sendRequest (default 30 000).
1676
- */
1677
1892
  constructor(options) {
1678
1893
  this._transport = options.transport;
1679
1894
  this._defaultTimeout = options.defaultTimeout ?? DEFAULT_REQUEST_TIMEOUT;
@@ -1684,25 +1899,6 @@ var ProtocolEngine = class {
1684
1899
  this._handleTransportError(error);
1685
1900
  });
1686
1901
  }
1687
- // ------------------------------------------------------------------
1688
- // Public API: Sending requests
1689
- // ------------------------------------------------------------------
1690
- /**
1691
- * Send a JSON-RPC request and wait for the response.
1692
- *
1693
- * Constructs the full envelope, registers a pending promise, sends
1694
- * via transport, and returns the parsed response `result` field.
1695
- *
1696
- * @param method - The RPC method name (e.g. `"droid.list_skills"`).
1697
- * @param params - Method parameters object.
1698
- * @param timeout - Timeout in ms. Defaults to `defaultTimeout`.
1699
- * @returns The `result` field from the JSON-RPC success response.
1700
- * @throws {ConnectionError} If the engine is closed.
1701
- * @throws {ConnectionError} If the transport has a sticky error.
1702
- * @throws {TimeoutError} If no response arrives within the timeout.
1703
- * @throws {ProtocolError} If the response contains a protocol error.
1704
- * @throws {SessionNotFoundError} If error code is ENTITY_NOT_FOUND.
1705
- */
1706
1902
  async sendRequest(method, params, timeout) {
1707
1903
  if (this._closed) {
1708
1904
  throw new ConnectionError("Protocol engine is closed");
@@ -1718,12 +1914,12 @@ var ProtocolEngine = class {
1718
1914
  jsonrpc: JSONRPC_VERSION,
1719
1915
  factoryApiVersion: LEGACY_FACTORY_API_VERSION,
1720
1916
  factoryProtocolVersion: FACTORY_PROTOCOL_VERSION,
1721
- type: "request",
1917
+ type: "request" /* Request */,
1722
1918
  id: requestId,
1723
1919
  method,
1724
1920
  params
1725
1921
  };
1726
- return new Promise((resolve, reject) => {
1922
+ return new Promise((resolve2, reject) => {
1727
1923
  const timer = setTimeout(() => {
1728
1924
  this._pendingRequests.delete(requestId);
1729
1925
  reject(
@@ -1736,7 +1932,7 @@ var ProtocolEngine = class {
1736
1932
  method,
1737
1933
  requestId,
1738
1934
  params,
1739
- resolve,
1935
+ resolve: resolve2,
1740
1936
  reject,
1741
1937
  timer
1742
1938
  };
@@ -1756,19 +1952,6 @@ var ProtocolEngine = class {
1756
1952
  }
1757
1953
  });
1758
1954
  }
1759
- // ------------------------------------------------------------------
1760
- // Public API: Notification listeners
1761
- // ------------------------------------------------------------------
1762
- /**
1763
- * Register a callback for incoming notification messages.
1764
- *
1765
- * Multiple listeners can be registered. Each receives the full
1766
- * parsed notification object.
1767
- *
1768
- * @param callback - Invoked with the notification object.
1769
- * @param filter - Optional filter to only receive specific notification types.
1770
- * @returns An unsubscribe function. Calling it again is safe (no-op).
1771
- */
1772
1955
  onNotification(callback, filter) {
1773
1956
  const listener = { callback, filter };
1774
1957
  this._notificationListeners.add(listener);
@@ -1780,23 +1963,9 @@ var ProtocolEngine = class {
1780
1963
  }
1781
1964
  };
1782
1965
  }
1783
- // ------------------------------------------------------------------
1784
- // Public API: Server→client request handlers
1785
- // ------------------------------------------------------------------
1786
- /**
1787
- * Register a handler for server→client permission requests.
1788
- *
1789
- * The handler receives the request params and should return a
1790
- * ToolConfirmationOutcome string value.
1791
- *
1792
- * Replaces any previously registered handler.
1793
- */
1794
1966
  setPermissionHandler(handler) {
1795
1967
  this._permissionHandler = handler;
1796
1968
  }
1797
- /**
1798
- * Remove the permission request handler (restores default Cancel).
1799
- */
1800
1969
  clearPermissionHandler() {
1801
1970
  this._permissionHandler = null;
1802
1971
  }
@@ -1811,31 +1980,12 @@ var ProtocolEngine = class {
1811
1980
  setAskUserHandler(handler) {
1812
1981
  this._askUserHandler = handler;
1813
1982
  }
1814
- /**
1815
- * Remove the ask-user request handler (restores default cancelled=true).
1816
- */
1817
1983
  clearAskUserHandler() {
1818
1984
  this._askUserHandler = null;
1819
1985
  }
1820
- // ------------------------------------------------------------------
1821
- // Public API: Health check
1822
- // ------------------------------------------------------------------
1823
- /**
1824
- * Whether the engine is in a healthy state — not closed and no
1825
- * sticky transport error.
1826
- */
1827
1986
  get isHealthy() {
1828
1987
  return !this._closed && this._transportError === null;
1829
1988
  }
1830
- // ------------------------------------------------------------------
1831
- // Public API: Close
1832
- // ------------------------------------------------------------------
1833
- /**
1834
- * Close the protocol engine.
1835
- *
1836
- * Rejects all pending requests, closes the transport, and prevents
1837
- * new requests. Idempotent — safe to call multiple times.
1838
- */
1839
1989
  async close() {
1840
1990
  if (this._closed) {
1841
1991
  return;
@@ -1850,38 +2000,25 @@ var ProtocolEngine = class {
1850
2000
  this._notificationListeners.clear();
1851
2001
  await this._transport.close();
1852
2002
  }
1853
- // ------------------------------------------------------------------
1854
- // Internal: Message handling
1855
- // ------------------------------------------------------------------
1856
- /**
1857
- * Handle an incoming parsed message from the transport.
1858
- * Dispatches to response handler, notification handler, or
1859
- * server→client request handler based on message type.
1860
- */
1861
- _handleMessage(parsed) {
1862
- const msgType = parsed["type"];
1863
- if (msgType === "response") {
1864
- this._handleResponse(parsed);
1865
- } else if (msgType === "notification") {
1866
- this._handleNotification(parsed);
1867
- } else if (msgType === "request") {
1868
- void this._handleServerRequest(parsed);
1869
- } else {
1870
- if ("result" in parsed || "error" in parsed) {
1871
- this._handleResponse(parsed);
1872
- } else if ("method" in parsed && !("id" in parsed)) {
1873
- this._handleNotification(parsed);
1874
- } else if ("method" in parsed && "id" in parsed) {
1875
- void this._handleServerRequest(parsed);
1876
- }
2003
+ _handleMessage(raw) {
2004
+ const parsed = JsonRpcMessageSchema.safeParse(raw);
2005
+ if (!parsed.success) {
2006
+ return;
2007
+ }
2008
+ const msg = parsed.data;
2009
+ switch (msg.type) {
2010
+ case "response" /* Response */:
2011
+ this._handleResponse(msg.id, msg.result, msg.error);
2012
+ break;
2013
+ case "notification" /* Notification */:
2014
+ this._handleNotification(msg);
2015
+ break;
2016
+ case "request" /* Request */:
2017
+ void this._handleServerRequest(msg.method, msg.id, msg.params);
2018
+ break;
1877
2019
  }
1878
2020
  }
1879
- /**
1880
- * Handle an incoming response message.
1881
- * Matches by ID to resolve the correct pending Promise.
1882
- */
1883
- _handleResponse(response) {
1884
- const responseId = response["id"];
2021
+ _handleResponse(responseId, result, error) {
1885
2022
  if (responseId == null) {
1886
2023
  return;
1887
2024
  }
@@ -1891,32 +2028,29 @@ var ProtocolEngine = class {
1891
2028
  }
1892
2029
  this._pendingRequests.delete(responseId);
1893
2030
  clearTimeout(pending.timer);
1894
- const errorObj = response["error"];
1895
- if (errorObj != null && typeof errorObj === "object") {
1896
- const error = errorObj;
1897
- const code = error["code"];
1898
- const message = error["message"] ?? "Unknown error";
1899
- const data = error["data"];
1900
- if (code === -32004 /* ENTITY_NOT_FOUND */) {
2031
+ if (error != null) {
2032
+ if (error.code === -32004 /* ENTITY_NOT_FOUND */) {
1901
2033
  const sessionId = String(
1902
2034
  pending.params["sessionId"] ?? pending.requestId
1903
2035
  );
1904
2036
  pending.reject(new SessionNotFoundError(sessionId));
1905
2037
  return;
1906
2038
  }
1907
- pending.reject(new ProtocolError(message, { code, data }));
2039
+ pending.reject(
2040
+ new ProtocolError(error.message, { code: error.code, data: error.data })
2041
+ );
1908
2042
  return;
1909
2043
  }
1910
- pending.resolve(response);
2044
+ pending.resolve(result);
1911
2045
  }
1912
- /**
1913
- * Handle an incoming notification message.
1914
- * Dispatches to all registered notification listeners that match.
1915
- */
1916
2046
  _handleNotification(notification) {
1917
- const params = notification["params"];
1918
- const innerNotification = params?.["notification"];
1919
- const notificationType = innerNotification?.["type"];
2047
+ let notificationType;
2048
+ const parsed = SessionNotificationParamsSchema.safeParse(
2049
+ notification["params"]
2050
+ );
2051
+ if (parsed.success) {
2052
+ notificationType = parsed.data.notification.type;
2053
+ }
1920
2054
  for (const listener of this._notificationListeners) {
1921
2055
  if (listener.filter?.type != null && listener.filter.type !== notificationType) {
1922
2056
  continue;
@@ -1927,32 +2061,32 @@ var ProtocolEngine = class {
1927
2061
  }
1928
2062
  }
1929
2063
  }
1930
- /**
1931
- * Handle an incoming server→client request.
1932
- * Dispatches to the appropriate handler based on the method field.
1933
- */
1934
- async _handleServerRequest(request) {
1935
- const method = request["method"];
1936
- const requestId = request["id"];
1937
- const params = request["params"] ?? {};
2064
+ async _handleServerRequest(method, requestId, params) {
1938
2065
  if (method === "droid.request_permission" /* REQUEST_PERMISSION */) {
1939
2066
  await this._handlePermissionRequest(requestId, params);
1940
2067
  } else if (method === "droid.ask_user" /* ASK_USER */) {
1941
2068
  await this._handleAskUserRequest(requestId, params);
1942
2069
  }
1943
2070
  }
1944
- /**
1945
- * Handle droid.request_permission server→client request.
1946
- */
1947
2071
  async _handlePermissionRequest(requestId, params) {
1948
2072
  const handler = this._permissionHandler;
1949
2073
  if (handler == null) {
1950
- this._sendResponse(requestId, { selectedOption: "cancel" });
2074
+ this._sendResponse(
2075
+ requestId,
2076
+ RequestPermissionResultSchema.parse({
2077
+ selectedOption: "cancel" /* Cancel */
2078
+ })
2079
+ );
1951
2080
  return;
1952
2081
  }
1953
2082
  try {
1954
- const selectedOption = await Promise.resolve(handler(params));
1955
- this._sendResponse(requestId, { selectedOption });
2083
+ const parsedParams = RequestPermissionRequestParamsSchema.parse(params);
2084
+ const selection = await Promise.resolve(handler(parsedParams));
2085
+ const result = typeof selection === "string" ? { selectedOption: selection } : selection;
2086
+ this._sendResponse(
2087
+ requestId,
2088
+ RequestPermissionResultSchema.parse(result)
2089
+ );
1956
2090
  } catch (exc) {
1957
2091
  const errorMessage = exc instanceof Error ? exc.message : String(exc);
1958
2092
  this._sendErrorResponse(
@@ -1963,18 +2097,19 @@ var ProtocolEngine = class {
1963
2097
  );
1964
2098
  }
1965
2099
  }
1966
- /**
1967
- * Handle droid.ask_user server→client request.
1968
- */
1969
2100
  async _handleAskUserRequest(requestId, params) {
1970
2101
  const handler = this._askUserHandler;
1971
2102
  if (handler == null) {
1972
- this._sendResponse(requestId, { cancelled: true, answers: [] });
2103
+ this._sendResponse(
2104
+ requestId,
2105
+ AskUserResultSchema.parse({ cancelled: true, answers: [] })
2106
+ );
1973
2107
  return;
1974
2108
  }
1975
2109
  try {
1976
- const result = await Promise.resolve(handler(params));
1977
- this._sendResponse(requestId, result);
2110
+ const parsedParams = AskUserRequestParamsSchema.parse(params);
2111
+ const result = await Promise.resolve(handler(parsedParams));
2112
+ this._sendResponse(requestId, AskUserResultSchema.parse(result));
1978
2113
  } catch (exc) {
1979
2114
  const errorMessage = exc instanceof Error ? exc.message : String(exc);
1980
2115
  this._sendErrorResponse(
@@ -1985,9 +2120,6 @@ var ProtocolEngine = class {
1985
2120
  );
1986
2121
  }
1987
2122
  }
1988
- // ------------------------------------------------------------------
1989
- // Internal: Transport error handling
1990
- // ------------------------------------------------------------------
1991
2123
  /**
1992
2124
  * Handle a transport error.
1993
2125
  * Sets the sticky transport error and rejects all pending requests.
@@ -2001,29 +2133,17 @@ var ProtocolEngine = class {
2001
2133
  connectionError.cause = error;
2002
2134
  this._rejectAllPending(connectionError);
2003
2135
  }
2004
- // ------------------------------------------------------------------
2005
- // Internal: Response helpers
2006
- // ------------------------------------------------------------------
2007
- /**
2008
- * Send a JSON-RPC success response back to the server.
2009
- */
2010
2136
  _sendResponse(requestId, result) {
2011
2137
  const response = {
2012
2138
  jsonrpc: JSONRPC_VERSION,
2013
2139
  factoryApiVersion: LEGACY_FACTORY_API_VERSION,
2014
2140
  factoryProtocolVersion: FACTORY_PROTOCOL_VERSION,
2015
- type: "response",
2141
+ type: "response" /* Response */,
2016
2142
  id: requestId,
2017
2143
  result
2018
2144
  };
2019
- try {
2020
- this._transport.send(response);
2021
- } catch {
2022
- }
2145
+ this._sendBestEffort(response);
2023
2146
  }
2024
- /**
2025
- * Send a JSON-RPC error response back to the server.
2026
- */
2027
2147
  _sendErrorResponse(requestId, code, message, data) {
2028
2148
  const errorObj = { code, message };
2029
2149
  if (data !== void 0) {
@@ -2033,18 +2153,18 @@ var ProtocolEngine = class {
2033
2153
  jsonrpc: JSONRPC_VERSION,
2034
2154
  factoryApiVersion: LEGACY_FACTORY_API_VERSION,
2035
2155
  factoryProtocolVersion: FACTORY_PROTOCOL_VERSION,
2036
- type: "response",
2156
+ type: "response" /* Response */,
2037
2157
  id: requestId,
2038
2158
  error: errorObj
2039
2159
  };
2160
+ this._sendBestEffort(response);
2161
+ }
2162
+ _sendBestEffort(message) {
2040
2163
  try {
2041
- this._transport.send(response);
2164
+ this._transport.send(message);
2042
2165
  } catch {
2043
2166
  }
2044
2167
  }
2045
- /**
2046
- * Reject all pending requests with the given error.
2047
- */
2048
2168
  _rejectAllPending(error) {
2049
2169
  const pending = new Map(this._pendingRequests);
2050
2170
  this._pendingRequests.clear();
@@ -2062,7 +2182,7 @@ var DroidClient = class {
2062
2182
  _closed = false;
2063
2183
  /**
2064
2184
  * Client-level notification listeners.
2065
- * Each entry is [callback, optional type filter string].
2185
+ * Each entry is [callback, optional notification filter].
2066
2186
  */
2067
2187
  _notificationListeners = [];
2068
2188
  /** Client-level permission handler. */
@@ -2084,329 +2204,212 @@ var DroidClient = class {
2084
2204
  (params) => this._dispatchAskUserRequest(params)
2085
2205
  );
2086
2206
  }
2087
- // ------------------------------------------------------------------
2088
- // Properties
2089
- // ------------------------------------------------------------------
2090
- /**
2091
- * Current session ID, or `null` if no session is active.
2092
- */
2207
+ async _rpc(method, params, schema, timeout) {
2208
+ const raw = await this._engine.sendRequest(method, params, timeout);
2209
+ return schema.parse(raw);
2210
+ }
2211
+ async _sessionRpc(method, params, schema, timeout) {
2212
+ this._ensureNotClosed();
2213
+ this._ensureSession();
2214
+ return this._rpc(method, params, schema, timeout);
2215
+ }
2216
+ async _sessionRpcWithoutParams(method, schema, timeout) {
2217
+ return this._sessionRpc(method, {}, schema, timeout);
2218
+ }
2093
2219
  get sessionId() {
2094
2220
  return this._sessionId;
2095
2221
  }
2096
- /**
2097
- * Whether the client is in a healthy state — not closed and no
2098
- * transport errors have occurred. Returns false after transport
2099
- * disconnect/error.
2100
- */
2101
2222
  get isConnected() {
2102
2223
  return !this._closed && this._engine.isHealthy;
2103
2224
  }
2104
- // ------------------------------------------------------------------
2105
- // Session lifecycle methods
2106
- // ------------------------------------------------------------------
2107
- /**
2108
- * Initialize a new session.
2109
- *
2110
- * Sends `droid.initialize_session` with extended timeout. On success,
2111
- * stores the session ID internally and returns the typed result.
2112
- */
2113
2225
  async initializeSession(params) {
2114
2226
  this._ensureNotClosed();
2115
- const response = await this._engine.sendRequest(
2227
+ const result = await this._rpc(
2116
2228
  "droid.initialize_session" /* INITIALIZE_SESSION */,
2117
2229
  params,
2230
+ InitializeSessionResultSchema,
2118
2231
  SESSION_INIT_TIMEOUT
2119
2232
  );
2120
- const result = response["result"];
2121
- if (result) {
2122
- this._sessionId = result.sessionId;
2123
- return result;
2124
- }
2125
- if ("sessionId" in response) {
2126
- this._sessionId = response["sessionId"];
2127
- return response;
2128
- }
2129
- return response;
2233
+ this._sessionId = result.sessionId;
2234
+ return result;
2130
2235
  }
2131
- /**
2132
- * Load an existing session.
2133
- *
2134
- * Sends `droid.load_session`. SessionNotFoundError is thrown for
2135
- * non-existent sessions (mapped from ENTITY_NOT_FOUND by the protocol engine).
2136
- */
2137
2236
  async loadSession(params) {
2138
2237
  this._ensureNotClosed();
2139
- const response = await this._engine.sendRequest(
2238
+ const result = await this._rpc(
2140
2239
  "droid.load_session" /* LOAD_SESSION */,
2141
2240
  params,
2241
+ LoadSessionResultSchema,
2142
2242
  SESSION_INIT_TIMEOUT
2143
2243
  );
2144
- const result = response["result"];
2145
- if (result) {
2146
- this._sessionId = params.sessionId;
2147
- return result;
2148
- }
2149
2244
  this._sessionId = params.sessionId;
2150
- return response;
2245
+ return result;
2151
2246
  }
2152
- /**
2153
- * Add a user message to the active session.
2154
- *
2155
- * Sends `droid.add_user_message` with text and optional images/files.
2156
- */
2157
2247
  async addUserMessage(params) {
2158
- this._ensureNotClosed();
2159
- this._ensureSession();
2160
- const response = await this._engine.sendRequest(
2248
+ return this._sessionRpc(
2161
2249
  "droid.add_user_message" /* ADD_USER_MESSAGE */,
2162
- params
2250
+ params,
2251
+ AddUserMessageResultSchema
2163
2252
  );
2164
- const result = response["result"];
2165
- return result ?? response;
2166
2253
  }
2167
- /**
2168
- * Interrupt the current session.
2169
- *
2170
- * Sends `droid.interrupt_session` with empty params.
2171
- */
2172
2254
  async interruptSession() {
2173
- this._ensureNotClosed();
2174
- this._ensureSession();
2175
- const response = await this._engine.sendRequest(
2255
+ return this._sessionRpcWithoutParams(
2176
2256
  "droid.interrupt_session" /* INTERRUPT_SESSION */,
2177
- {}
2257
+ InterruptSessionResultSchema
2178
2258
  );
2179
- const result = response["result"];
2180
- return result ?? response;
2181
2259
  }
2182
- /**
2183
- * Kill a worker session.
2184
- *
2185
- * Sends `droid.kill_worker_session`.
2186
- */
2187
2260
  async killWorkerSession(params) {
2188
- this._ensureNotClosed();
2189
- this._ensureSession();
2190
- const response = await this._engine.sendRequest(
2261
+ return this._sessionRpc(
2191
2262
  "droid.kill_worker_session" /* KILL_WORKER_SESSION */,
2192
- params
2263
+ params,
2264
+ KillWorkerSessionResultSchema
2193
2265
  );
2194
- const result = response["result"];
2195
- return result ?? response;
2196
2266
  }
2197
- /**
2198
- * Update session settings.
2199
- *
2200
- * Sends `droid.update_session_settings` with the provided partial settings.
2201
- */
2202
2267
  async updateSessionSettings(params) {
2203
- this._ensureNotClosed();
2204
- this._ensureSession();
2205
- const response = await this._engine.sendRequest(
2268
+ return this._sessionRpc(
2206
2269
  "droid.update_session_settings" /* UPDATE_SESSION_SETTINGS */,
2207
- params
2270
+ params,
2271
+ UpdateSessionSettingsResultSchema
2208
2272
  );
2209
- const result = response["result"];
2210
- return result ?? response;
2211
2273
  }
2212
- // ------------------------------------------------------------------
2213
- // MCP methods
2214
- // ------------------------------------------------------------------
2215
- /**
2216
- * Toggle an MCP server on or off.
2217
- */
2218
2274
  async toggleMcpServer(params) {
2219
- this._ensureNotClosed();
2220
- this._ensureSession();
2221
- const response = await this._engine.sendRequest(
2275
+ return this._sessionRpc(
2222
2276
  "droid.toggle_mcp_server" /* TOGGLE_MCP_SERVER */,
2223
- params
2277
+ params,
2278
+ ToggleMcpServerResultSchema
2224
2279
  );
2225
- const result = response["result"];
2226
- return result ?? response;
2227
2280
  }
2228
- /**
2229
- * Authenticate an MCP server (OAuth flow).
2230
- * Uses extended timeout (300s) since OAuth requires user interaction.
2231
- */
2232
2281
  async authenticateMcpServer(params) {
2233
- this._ensureNotClosed();
2234
- this._ensureSession();
2235
- const response = await this._engine.sendRequest(
2282
+ return this._sessionRpc(
2236
2283
  "droid.authenticate_mcp_server" /* AUTHENTICATE_MCP_SERVER */,
2237
2284
  params,
2285
+ AuthenticateMcpServerResultSchema,
2238
2286
  MCP_AUTH_TIMEOUT
2239
2287
  );
2240
- const result = response["result"];
2241
- return result ?? response;
2242
2288
  }
2243
- /**
2244
- * Cancel an in-progress MCP authentication.
2245
- */
2246
2289
  async cancelMcpAuth(params) {
2247
- this._ensureNotClosed();
2248
- this._ensureSession();
2249
- const response = await this._engine.sendRequest(
2290
+ return this._sessionRpc(
2250
2291
  "droid.cancel_mcp_auth" /* CANCEL_MCP_AUTH */,
2251
- params
2292
+ params,
2293
+ CancelMcpAuthResultSchema
2252
2294
  );
2253
- const result = response["result"];
2254
- return result ?? response;
2255
2295
  }
2256
- /**
2257
- * Clear stored MCP authentication tokens.
2258
- */
2259
2296
  async clearMcpAuth(params) {
2260
- this._ensureNotClosed();
2261
- this._ensureSession();
2262
- const response = await this._engine.sendRequest(
2297
+ return this._sessionRpc(
2263
2298
  "droid.clear_mcp_auth" /* CLEAR_MCP_AUTH */,
2264
- params
2299
+ params,
2300
+ ClearMcpAuthResultSchema
2265
2301
  );
2266
- const result = response["result"];
2267
- return result ?? response;
2268
2302
  }
2269
- /**
2270
- * Submit an MCP authentication code (OAuth callback).
2271
- */
2272
2303
  async submitMcpAuthCode(params) {
2273
- this._ensureNotClosed();
2274
- this._ensureSession();
2275
- const response = await this._engine.sendRequest(
2304
+ return this._sessionRpc(
2276
2305
  "droid.submit_mcp_auth_code" /* SUBMIT_MCP_AUTH_CODE */,
2277
- params
2306
+ params,
2307
+ SubmitMcpAuthCodeResultSchema
2278
2308
  );
2279
- const result = response["result"];
2280
- return result ?? response;
2281
2309
  }
2282
- /**
2283
- * Add an MCP server.
2284
- */
2285
2310
  async addMcpServer(params) {
2286
- this._ensureNotClosed();
2287
- this._ensureSession();
2288
- const response = await this._engine.sendRequest(
2311
+ return this._sessionRpc(
2289
2312
  "droid.add_mcp_server" /* ADD_MCP_SERVER */,
2290
- params
2313
+ params,
2314
+ AddMcpServerResultSchema
2291
2315
  );
2292
- const result = response["result"];
2293
- return result ?? response;
2294
2316
  }
2295
- /**
2296
- * Remove an MCP server.
2297
- */
2298
2317
  async removeMcpServer(params) {
2299
- this._ensureNotClosed();
2300
- this._ensureSession();
2301
- const response = await this._engine.sendRequest(
2318
+ return this._sessionRpc(
2302
2319
  "droid.remove_mcp_server" /* REMOVE_MCP_SERVER */,
2303
- params
2320
+ params,
2321
+ RemoveMcpServerResultSchema
2304
2322
  );
2305
- const result = response["result"];
2306
- return result ?? response;
2307
2323
  }
2308
- /**
2309
- * List available MCP registry servers.
2310
- */
2311
2324
  async listMcpRegistry() {
2312
- this._ensureNotClosed();
2313
- this._ensureSession();
2314
- const response = await this._engine.sendRequest(
2325
+ return this._sessionRpcWithoutParams(
2315
2326
  "droid.list_mcp_registry" /* LIST_MCP_REGISTRY */,
2316
- {}
2327
+ ListMcpRegistryResultSchema
2317
2328
  );
2318
- const result = response["result"];
2319
- return result ?? response;
2320
2329
  }
2321
- /**
2322
- * List available MCP tools.
2323
- */
2324
2330
  async listMcpTools() {
2325
- this._ensureNotClosed();
2326
- this._ensureSession();
2327
- const response = await this._engine.sendRequest(
2331
+ return this._sessionRpcWithoutParams(
2328
2332
  "droid.list_mcp_tools" /* LIST_MCP_TOOLS */,
2329
- {}
2333
+ ListMcpToolsResultSchema
2334
+ );
2335
+ }
2336
+ async listTools(params = {}) {
2337
+ return this._sessionRpc(
2338
+ "droid.list_tools" /* LIST_TOOLS */,
2339
+ params,
2340
+ ListToolsResultSchema
2330
2341
  );
2331
- const result = response["result"];
2332
- return result ?? response;
2333
2342
  }
2334
- /**
2335
- * List MCP servers with status and summary.
2336
- */
2337
2343
  async listMcpServers() {
2338
- this._ensureNotClosed();
2339
- this._ensureSession();
2340
- const response = await this._engine.sendRequest(
2344
+ return this._sessionRpcWithoutParams(
2341
2345
  "droid.list_mcp_servers" /* LIST_MCP_SERVERS */,
2342
- {}
2346
+ ListMcpServersResultSchema
2343
2347
  );
2344
- const result = response["result"];
2345
- return result ?? response;
2346
2348
  }
2347
- /**
2348
- * Toggle an MCP tool on or off.
2349
- */
2350
2349
  async toggleMcpTool(params) {
2351
- this._ensureNotClosed();
2352
- this._ensureSession();
2353
- const response = await this._engine.sendRequest(
2350
+ return this._sessionRpc(
2354
2351
  "droid.toggle_mcp_tool" /* TOGGLE_MCP_TOOL */,
2355
- params
2352
+ params,
2353
+ ToggleMcpToolResultSchema
2356
2354
  );
2357
- const result = response["result"];
2358
- return result ?? response;
2359
2355
  }
2360
- // ------------------------------------------------------------------
2361
- // Skills and bug report methods
2362
- // ------------------------------------------------------------------
2363
- /**
2364
- * List available skills.
2365
- */
2366
2356
  async listSkills() {
2367
- this._ensureNotClosed();
2368
- this._ensureSession();
2369
- const response = await this._engine.sendRequest(
2357
+ return this._sessionRpcWithoutParams(
2370
2358
  "droid.list_skills" /* LIST_SKILLS */,
2371
- {}
2359
+ ListSkillsResultSchema
2372
2360
  );
2373
- const result = response["result"];
2374
- return result ?? response;
2375
2361
  }
2376
- /**
2377
- * Submit a bug report.
2378
- */
2379
2362
  async submitBugReport(params) {
2380
- this._ensureNotClosed();
2381
- this._ensureSession();
2382
- const response = await this._engine.sendRequest(
2363
+ return this._sessionRpc(
2383
2364
  "droid.submit_bug_report" /* SUBMIT_BUG_REPORT */,
2384
- params
2365
+ params,
2366
+ SubmitBugReportResultSchema
2367
+ );
2368
+ }
2369
+ async getRewindInfo(params) {
2370
+ return this._sessionRpc(
2371
+ "droid.get_rewind_info" /* GET_REWIND_INFO */,
2372
+ params,
2373
+ GetRewindInfoResultSchema
2374
+ );
2375
+ }
2376
+ async executeRewind(params) {
2377
+ return this._sessionRpc(
2378
+ "droid.execute_rewind" /* EXECUTE_REWIND */,
2379
+ params,
2380
+ ExecuteRewindResultSchema,
2381
+ REWIND_TIMEOUT
2382
+ );
2383
+ }
2384
+ async compactSession(params) {
2385
+ return this._sessionRpc(
2386
+ "droid.compact_session" /* COMPACT_SESSION */,
2387
+ params,
2388
+ CompactSessionResultSchema,
2389
+ COMPACTION_TIMEOUT
2390
+ );
2391
+ }
2392
+ async forkSession() {
2393
+ return this._sessionRpcWithoutParams(
2394
+ "droid.fork_session" /* FORK_SESSION */,
2395
+ ForkSessionResultSchema
2396
+ );
2397
+ }
2398
+ async getContextStats() {
2399
+ return this._sessionRpcWithoutParams(
2400
+ "droid.get_context_stats" /* GET_CONTEXT_STATS */,
2401
+ GetContextStatsResultSchema
2402
+ );
2403
+ }
2404
+ async renameSession(params) {
2405
+ return this._sessionRpc(
2406
+ "droid.rename_session" /* RENAME_SESSION */,
2407
+ params,
2408
+ RenameSessionResultSchema
2385
2409
  );
2386
- const result = response["result"];
2387
- return result ?? response;
2388
2410
  }
2389
- // ------------------------------------------------------------------
2390
- // Notification subscription
2391
- // ------------------------------------------------------------------
2392
- /**
2393
- * Register a callback for incoming notification messages.
2394
- *
2395
- * Multiple listeners can be registered. Each receives the full parsed
2396
- * notification object. Optionally filter by notification type.
2397
- *
2398
- * Listener exceptions are isolated — if one raises, others still receive
2399
- * the event and the engine continues.
2400
- *
2401
- * @param callback - Invoked with the notification object.
2402
- * @param filter - Optional filter to only receive specific notification types.
2403
- * @returns An unsubscribe function. Calling it again is safe (no-op).
2404
- */
2405
2411
  onNotification(callback, filter) {
2406
- const entry = {
2407
- callback,
2408
- typeFilter: filter?.type
2409
- };
2412
+ const entry = { callback, filter };
2410
2413
  this._notificationListeners.push(entry);
2411
2414
  let unsubscribed = false;
2412
2415
  return () => {
@@ -2419,54 +2422,18 @@ var DroidClient = class {
2419
2422
  }
2420
2423
  };
2421
2424
  }
2422
- // ------------------------------------------------------------------
2423
- // Permission/ask-user handler registration
2424
- // ------------------------------------------------------------------
2425
- /**
2426
- * Register a handler for server→client permission requests.
2427
- *
2428
- * The handler receives the request params and should return a
2429
- * ToolConfirmationOutcome string value. Async handlers are awaited.
2430
- * Replaces any previously registered handler.
2431
- */
2432
2425
  setPermissionHandler(handler) {
2433
2426
  this._permissionHandler = handler;
2434
2427
  }
2435
- /**
2436
- * Remove the permission request handler.
2437
- * Restores default behavior: return "cancel".
2438
- */
2439
2428
  clearPermissionHandler() {
2440
2429
  this._permissionHandler = null;
2441
2430
  }
2442
- /**
2443
- * Register a handler for server→client ask-user requests.
2444
- *
2445
- * The handler receives the request params and should return a result
2446
- * object with `cancelled` and `answers` keys. Async handlers are awaited.
2447
- * Replaces any previously registered handler.
2448
- */
2449
2431
  setAskUserHandler(handler) {
2450
2432
  this._askUserHandler = handler;
2451
2433
  }
2452
- /**
2453
- * Remove the ask-user request handler.
2454
- * Restores default behavior: return `{ cancelled: true, answers: [] }`.
2455
- */
2456
2434
  clearAskUserHandler() {
2457
2435
  this._askUserHandler = null;
2458
2436
  }
2459
- // ------------------------------------------------------------------
2460
- // Lifecycle
2461
- // ------------------------------------------------------------------
2462
- /**
2463
- * Close the client and release all resources.
2464
- *
2465
- * Rejects pending requests, clears handlers and listeners, and closes
2466
- * the protocol engine. Idempotent — safe to call multiple times.
2467
- *
2468
- * After close, all method calls throw ConnectionError immediately.
2469
- */
2470
2437
  async close() {
2471
2438
  if (this._closed) {
2472
2439
  return;
@@ -2477,21 +2444,17 @@ var DroidClient = class {
2477
2444
  this._askUserHandler = null;
2478
2445
  await this._engine.close();
2479
2446
  }
2480
- // ------------------------------------------------------------------
2481
- // Internal: dispatch methods
2482
- // ------------------------------------------------------------------
2483
- /**
2484
- * Dispatch a notification to all registered client-level listeners.
2485
- * Filters by notification type if a type filter is set.
2486
- * Exception in one listener does not affect others.
2487
- */
2488
2447
  _dispatchNotification(notification) {
2489
- const params = notification["params"];
2490
- const innerNotification = params?.["notification"];
2491
- const notificationType = innerNotification?.["type"];
2448
+ let notificationType;
2449
+ const parsed = SessionNotificationParamsSchema.safeParse(
2450
+ notification["params"]
2451
+ );
2452
+ if (parsed.success) {
2453
+ notificationType = parsed.data.notification.type;
2454
+ }
2492
2455
  const listeners = [...this._notificationListeners];
2493
2456
  for (const listener of listeners) {
2494
- if (listener.typeFilter != null && listener.typeFilter !== notificationType) {
2457
+ if (listener.filter?.type != null && listener.filter.type !== notificationType) {
2495
2458
  continue;
2496
2459
  }
2497
2460
  try {
@@ -2500,25 +2463,13 @@ var DroidClient = class {
2500
2463
  }
2501
2464
  }
2502
2465
  }
2503
- /**
2504
- * Dispatch to the client-level permission handler.
2505
- * If no handler is set, returns the default "cancel" outcome.
2506
- * If handler throws, the error propagates to the protocol engine
2507
- * which sends an error response.
2508
- */
2509
2466
  _dispatchPermissionRequest(params) {
2510
2467
  const handler = this._permissionHandler;
2511
2468
  if (handler == null) {
2512
- return "cancel";
2469
+ return "cancel" /* Cancel */;
2513
2470
  }
2514
2471
  return handler(params);
2515
2472
  }
2516
- /**
2517
- * Dispatch to the client-level ask-user handler.
2518
- * If no handler is set, returns the default cancelled response.
2519
- * If handler throws, the error propagates to the protocol engine
2520
- * which sends an error response.
2521
- */
2522
2473
  _dispatchAskUserRequest(params) {
2523
2474
  const handler = this._askUserHandler;
2524
2475
  if (handler == null) {
@@ -2526,12 +2477,6 @@ var DroidClient = class {
2526
2477
  }
2527
2478
  return handler(params);
2528
2479
  }
2529
- // ------------------------------------------------------------------
2530
- // Internal: guards
2531
- // ------------------------------------------------------------------
2532
- /**
2533
- * Throw ConnectionError if the client has been closed.
2534
- */
2535
2480
  _ensureNotClosed() {
2536
2481
  if (this._closed) {
2537
2482
  throw new ConnectionError(
@@ -2539,9 +2484,6 @@ var DroidClient = class {
2539
2484
  );
2540
2485
  }
2541
2486
  }
2542
- /**
2543
- * Throw SessionError if no active session.
2544
- */
2545
2487
  _ensureSession() {
2546
2488
  if (this._sessionId == null) {
2547
2489
  throw new SessionError(
@@ -2552,26 +2494,56 @@ var DroidClient = class {
2552
2494
  };
2553
2495
 
2554
2496
  // src/stream.ts
2555
- function convertNotificationToStreamMessage(notification) {
2497
+ var DroidMessageType = {
2498
+ AssistantTextDelta: "assistant_text_delta",
2499
+ ThinkingTextDelta: "thinking_text_delta",
2500
+ ToolUse: "tool_use",
2501
+ ToolResult: "tool_result",
2502
+ ToolProgress: "tool_progress",
2503
+ WorkingStateChanged: "working_state_changed",
2504
+ TokenUsageUpdate: "token_usage_update",
2505
+ CreateMessage: "create_message",
2506
+ PermissionResolved: "permission_resolved",
2507
+ SettingsUpdated: "settings_updated",
2508
+ SessionTitleUpdated: "session_title_updated",
2509
+ McpStatusChanged: "mcp_status_changed",
2510
+ MissionStateChanged: "mission_state_changed",
2511
+ MissionFeaturesChanged: "mission_features_changed",
2512
+ MissionProgressEntry: "mission_progress_entry",
2513
+ MissionHeartbeat: "mission_heartbeat",
2514
+ MissionWorkerStarted: "mission_worker_started",
2515
+ MissionWorkerCompleted: "mission_worker_completed",
2516
+ McpAuthRequired: "mcp_auth_required",
2517
+ McpAuthCompleted: "mcp_auth_completed",
2518
+ Error: "error",
2519
+ TurnComplete: "turn_complete"
2520
+ };
2521
+ function convertNotificationToStreamMessage(raw) {
2522
+ const parsed = SessionNotificationPayloadSchema.safeParse(raw);
2523
+ if (!parsed.success) {
2524
+ return null;
2525
+ }
2526
+ const notification = parsed.data;
2556
2527
  switch (notification.type) {
2557
2528
  case "assistant_text_delta" /* ASSISTANT_TEXT_DELTA */:
2558
2529
  return {
2559
- type: "assistant_text_delta",
2530
+ type: DroidMessageType.AssistantTextDelta,
2560
2531
  messageId: notification.messageId,
2561
2532
  blockIndex: notification.blockIndex,
2562
2533
  text: notification.textDelta
2563
2534
  };
2564
2535
  case "thinking_text_delta" /* THINKING_TEXT_DELTA */:
2565
2536
  return {
2566
- type: "thinking_text_delta",
2537
+ type: DroidMessageType.ThinkingTextDelta,
2567
2538
  messageId: notification.messageId,
2568
2539
  blockIndex: notification.blockIndex,
2569
2540
  text: notification.textDelta
2570
2541
  };
2571
2542
  case "tool_result" /* TOOL_RESULT */:
2572
2543
  return {
2573
- type: "tool_result",
2544
+ type: DroidMessageType.ToolResult,
2574
2545
  toolUseId: notification.toolUseId,
2546
+ toolName: "",
2575
2547
  content: normalizeToolResultContent(notification.content),
2576
2548
  isError: Boolean(notification.isError)
2577
2549
  };
@@ -2579,7 +2551,7 @@ function convertNotificationToStreamMessage(notification) {
2579
2551
  const update = notification.update;
2580
2552
  const text = update?.text ?? update?.status ?? update?.details ?? "";
2581
2553
  return {
2582
- type: "tool_progress",
2554
+ type: DroidMessageType.ToolProgress,
2583
2555
  toolUseId: notification.toolUseId,
2584
2556
  toolName: notification.toolName,
2585
2557
  content: text,
@@ -2588,108 +2560,106 @@ function convertNotificationToStreamMessage(notification) {
2588
2560
  }
2589
2561
  case "droid_working_state_changed" /* DROID_WORKING_STATE_CHANGED */:
2590
2562
  return {
2591
- type: "working_state_changed",
2563
+ type: DroidMessageType.WorkingStateChanged,
2592
2564
  state: notification.newState
2593
2565
  };
2594
2566
  case "session_token_usage_changed" /* SESSION_TOKEN_USAGE_CHANGED */: {
2595
2567
  const tu = notification.tokenUsage;
2596
2568
  return {
2597
- type: "token_usage_update",
2569
+ type: DroidMessageType.TokenUsageUpdate,
2598
2570
  inputTokens: tu.inputTokens,
2599
2571
  outputTokens: tu.outputTokens,
2600
2572
  cacheReadTokens: tu.cacheReadTokens,
2601
- cacheWriteTokens: tu.cacheCreationTokens,
2573
+ cacheCreationTokens: tu.cacheCreationTokens,
2602
2574
  thinkingTokens: tu.thinkingTokens
2603
2575
  };
2604
2576
  }
2605
2577
  case "create_message" /* CREATE_MESSAGE */: {
2606
2578
  const msg = notification.message;
2607
2579
  const messages = [];
2608
- if (msg.content && Array.isArray(msg.content)) {
2609
- for (const block of msg.content) {
2610
- if (block.type === "tool_use") {
2611
- messages.push({
2612
- type: "tool_use",
2613
- toolName: block.name,
2614
- toolInput: block.input ?? {},
2615
- toolUseId: block.id
2616
- });
2617
- }
2580
+ for (const block of msg.content) {
2581
+ if (block.type === DroidMessageType.ToolUse) {
2582
+ messages.push({
2583
+ type: DroidMessageType.ToolUse,
2584
+ toolName: block.name,
2585
+ toolInput: block.input,
2586
+ toolUseId: block.id
2587
+ });
2618
2588
  }
2619
2589
  }
2620
2590
  messages.push({
2621
- type: "create_message",
2591
+ type: DroidMessageType.CreateMessage,
2622
2592
  messageId: msg.id,
2623
2593
  role: msg.role,
2624
- content: msg.content ?? [],
2594
+ content: msg.content,
2625
2595
  parentId: notification.parentId
2626
2596
  });
2627
2597
  return messages;
2628
2598
  }
2629
2599
  case "error" /* ERROR */:
2630
2600
  return {
2631
- type: "error",
2601
+ type: DroidMessageType.Error,
2632
2602
  message: notification.message,
2633
2603
  errorType: notification.errorType,
2634
2604
  timestamp: notification.timestamp
2635
2605
  };
2636
2606
  case "permission_resolved" /* PERMISSION_RESOLVED */:
2637
2607
  return {
2638
- type: "permission_resolved",
2608
+ type: DroidMessageType.PermissionResolved,
2639
2609
  requestId: notification.requestId,
2640
2610
  toolUseIds: notification.toolUseIds,
2641
2611
  selectedOption: notification.selectedOption
2642
2612
  };
2643
2613
  case "settings_updated" /* SETTINGS_UPDATED */:
2644
2614
  return {
2645
- type: "settings_updated",
2615
+ type: DroidMessageType.SettingsUpdated,
2646
2616
  settings: notification.settings
2647
2617
  };
2648
2618
  case "session_title_updated" /* SESSION_TITLE_UPDATED */:
2649
2619
  return {
2650
- type: "session_title_updated",
2620
+ type: DroidMessageType.SessionTitleUpdated,
2651
2621
  title: notification.title
2652
2622
  };
2653
2623
  case "mcp_status_changed" /* MCP_STATUS_CHANGED */:
2654
2624
  return {
2655
- type: "mcp_status_changed",
2625
+ type: DroidMessageType.McpStatusChanged,
2656
2626
  servers: notification.servers,
2657
2627
  summary: notification.summary
2658
2628
  };
2659
2629
  case "mission_state_changed" /* MISSION_STATE_CHANGED */:
2660
2630
  return {
2661
- type: "mission_state_changed",
2631
+ type: DroidMessageType.MissionStateChanged,
2662
2632
  state: notification.state
2663
2633
  };
2664
2634
  case "mission_features_changed" /* MISSION_FEATURES_CHANGED */:
2665
2635
  return {
2666
- type: "mission_features_changed",
2636
+ type: DroidMessageType.MissionFeaturesChanged,
2667
2637
  features: notification.features
2668
2638
  };
2669
2639
  case "mission_progress_entry" /* MISSION_PROGRESS_ENTRY */:
2670
2640
  return {
2671
- type: "mission_progress_entry",
2641
+ type: DroidMessageType.MissionProgressEntry,
2672
2642
  progressLog: notification.progressLog
2673
2643
  };
2674
2644
  case "mission_heartbeat" /* MISSION_HEARTBEAT */:
2675
2645
  return {
2676
- type: "mission_heartbeat",
2646
+ type: DroidMessageType.MissionHeartbeat,
2677
2647
  timestamp: notification.timestamp
2678
2648
  };
2679
2649
  case "mission_worker_started" /* MISSION_WORKER_STARTED */:
2680
2650
  return {
2681
- type: "mission_worker_started",
2651
+ type: DroidMessageType.MissionWorkerStarted,
2682
2652
  workerSessionId: notification.workerSessionId
2683
2653
  };
2684
2654
  case "mission_worker_completed" /* MISSION_WORKER_COMPLETED */:
2685
2655
  return {
2686
- type: "mission_worker_completed",
2656
+ type: DroidMessageType.MissionWorkerCompleted,
2687
2657
  workerSessionId: notification.workerSessionId,
2688
2658
  exitCode: notification.exitCode
2689
2659
  };
2690
2660
  case "mcp_auth_required" /* MCP_AUTH_REQUIRED */:
2691
2661
  return {
2692
- type: "mcp_auth_required",
2662
+ type: DroidMessageType.McpAuthRequired,
2693
2663
  serverName: notification.serverName,
2694
2664
  authUrl: notification.authUrl,
2695
2665
  message: notification.message,
@@ -2697,54 +2667,45 @@ function convertNotificationToStreamMessage(notification) {
2697
2667
  };
2698
2668
  case "mcp_auth_completed" /* MCP_AUTH_COMPLETED */:
2699
2669
  return {
2700
- type: "mcp_auth_completed",
2670
+ type: DroidMessageType.McpAuthCompleted,
2701
2671
  serverName: notification.serverName,
2702
2672
  outcome: notification.outcome,
2703
2673
  message: notification.message
2704
2674
  };
2705
2675
  default:
2706
- console.warn(
2707
- `[droid-sdk] Unknown notification type: ${String(notification.type)}`
2708
- );
2709
2676
  return null;
2710
2677
  }
2711
2678
  }
2712
2679
  var StreamStateTracker = class {
2713
- /** Whether we have ever seen a non-idle state. */
2714
2680
  hasBeenNonIdle = false;
2715
- /** Last-seen token usage update (to attach to TurnComplete). */
2716
2681
  lastTokenUsage = null;
2717
- /**
2718
- * Process a DroidMessage and return any additional messages that should be
2719
- * emitted (e.g. TurnComplete sentinel).
2720
- *
2721
- * @param message - The DroidMessage to process.
2722
- * @returns An array of additional messages to emit (may be empty).
2723
- */
2682
+ toolNameMap = /* @__PURE__ */ new Map();
2683
+ getToolName(toolUseId) {
2684
+ return this.toolNameMap.get(toolUseId) ?? "";
2685
+ }
2724
2686
  processMessage(message) {
2725
2687
  const additional = [];
2726
- if (message.type === "token_usage_update") {
2688
+ if (message.type === DroidMessageType.ToolUse) {
2689
+ this.toolNameMap.set(message.toolUseId, message.toolName);
2690
+ }
2691
+ if (message.type === DroidMessageType.ToolResult) {
2692
+ message = { ...message, toolName: this.getToolName(message.toolUseId) };
2693
+ }
2694
+ if (message.type === DroidMessageType.TokenUsageUpdate) {
2727
2695
  this.lastTokenUsage = message;
2728
2696
  }
2729
- if (message.type === "working_state_changed") {
2697
+ if (message.type === DroidMessageType.WorkingStateChanged) {
2730
2698
  if (message.state !== "idle" /* Idle */) {
2731
2699
  this.hasBeenNonIdle = true;
2732
2700
  } else if (this.hasBeenNonIdle) {
2733
2701
  additional.push({
2734
- type: "turn_complete",
2702
+ type: DroidMessageType.TurnComplete,
2735
2703
  tokenUsage: this.lastTokenUsage
2736
2704
  });
2737
2705
  this.hasBeenNonIdle = false;
2738
2706
  }
2739
2707
  }
2740
- return additional;
2741
- }
2742
- /**
2743
- * Reset the tracker for a new turn/stream call.
2744
- */
2745
- reset() {
2746
- this.hasBeenNonIdle = false;
2747
- this.lastTokenUsage = null;
2708
+ return { message, additional };
2748
2709
  }
2749
2710
  };
2750
2711
  function normalizeToolResultContent(content) {
@@ -2760,124 +2721,469 @@ function normalizeToolResultContent(content) {
2760
2721
  return String(content);
2761
2722
  }
2762
2723
 
2763
- // src/query.ts
2764
- function query(options) {
2765
- let transport = null;
2766
- let client = null;
2767
- let sessionId = null;
2768
- let aborted = false;
2769
- const messageQueue = [];
2770
- let resolveWaiting = null;
2771
- let streamDone = false;
2772
- function enqueueMessage(msg) {
2773
- messageQueue.push(msg);
2774
- if (resolveWaiting) {
2775
- const resolve = resolveWaiting;
2776
- resolveWaiting = null;
2777
- resolve();
2778
- }
2724
+ // src/helpers.ts
2725
+ function wireAbortSignal(signal, onAbort) {
2726
+ if (!signal) return () => {
2727
+ };
2728
+ if (signal.aborted) {
2729
+ onAbort();
2730
+ return () => {
2731
+ };
2732
+ } else {
2733
+ const listener = () => onAbort();
2734
+ signal.addEventListener("abort", listener, { once: true });
2735
+ return () => signal.removeEventListener("abort", listener);
2779
2736
  }
2780
- function signalDone() {
2781
- streamDone = true;
2782
- if (resolveWaiting) {
2783
- const resolve = resolveWaiting;
2784
- resolveWaiting = null;
2785
- resolve();
2737
+ }
2738
+ function extractInnerNotification(notification) {
2739
+ const parsed = SessionNotificationSchema.safeParse(notification);
2740
+ return parsed.success ? parsed.data.params.notification : null;
2741
+ }
2742
+ var MessageBridge = class {
2743
+ _queue = [];
2744
+ _resolveWaiting = null;
2745
+ _done = false;
2746
+ _stateTracker = new StreamStateTracker();
2747
+ notificationHandler = (notification) => {
2748
+ const inner = extractInnerNotification(notification);
2749
+ if (!inner) return;
2750
+ const converted = convertNotificationToStreamMessage(inner);
2751
+ if (converted === null) return;
2752
+ const messages = Array.isArray(converted) ? converted : [converted];
2753
+ for (const msg of messages) {
2754
+ const { message, additional } = this._stateTracker.processMessage(msg);
2755
+ this._enqueue(message);
2756
+ for (const extra of additional) {
2757
+ this._enqueue(extra);
2758
+ if (extra.type === DroidMessageType.TurnComplete) {
2759
+ this._signalDone();
2760
+ }
2761
+ }
2786
2762
  }
2787
- }
2788
- async function* generateMessages() {
2789
- if (options.transport) {
2790
- transport = options.transport;
2791
- } else {
2792
- const transportOptions = {
2793
- execPath: options.execPath,
2794
- execArgs: options.execArgs,
2795
- cwd: options.cwd,
2796
- env: options.env
2797
- };
2798
- const processTransport = new ProcessTransport(transportOptions);
2799
- await processTransport.connect();
2800
- transport = processTransport;
2801
- }
2802
- client = new DroidClient({ transport });
2803
- if (options.permissionHandler) {
2804
- client.setPermissionHandler(options.permissionHandler);
2805
- }
2806
- if (options.askUserHandler) {
2807
- client.setAskUserHandler(options.askUserHandler);
2808
- }
2809
- const stateTracker = new StreamStateTracker();
2810
- client.onNotification((notification) => {
2811
- const params = notification["params"];
2812
- const innerNotification = params?.["notification"];
2813
- if (!innerNotification) {
2814
- return;
2763
+ };
2764
+ signalDone() {
2765
+ this._signalDone();
2766
+ }
2767
+ async *messages() {
2768
+ while (true) {
2769
+ while (this._queue.length > 0) {
2770
+ const msg = this._queue.shift();
2771
+ yield msg;
2772
+ if (msg.type === DroidMessageType.TurnComplete) {
2773
+ return;
2774
+ }
2815
2775
  }
2816
- const converted = convertNotificationToStreamMessage(
2817
- innerNotification
2818
- );
2819
- if (converted === null) {
2776
+ if (this._done && this._queue.length === 0) {
2820
2777
  return;
2821
2778
  }
2822
- const messages = Array.isArray(converted) ? converted : [converted];
2823
- for (const msg of messages) {
2824
- enqueueMessage(msg);
2825
- const additional = stateTracker.processMessage(msg);
2826
- for (const extra of additional) {
2827
- enqueueMessage(extra);
2828
- if (extra.type === "turn_complete") {
2829
- signalDone();
2830
- }
2831
- }
2832
- }
2833
- });
2834
- const initParams = {
2835
- machineId: options.machineId ?? "default",
2836
- cwd: options.cwd ?? "."
2779
+ await new Promise((resolve2) => {
2780
+ this._resolveWaiting = resolve2;
2781
+ });
2782
+ }
2783
+ }
2784
+ _enqueue(msg) {
2785
+ this._queue.push(msg);
2786
+ if (this._resolveWaiting) {
2787
+ const resolve2 = this._resolveWaiting;
2788
+ this._resolveWaiting = null;
2789
+ resolve2();
2790
+ }
2791
+ }
2792
+ _signalDone() {
2793
+ this._done = true;
2794
+ if (this._resolveWaiting) {
2795
+ const resolve2 = this._resolveWaiting;
2796
+ this._resolveWaiting = null;
2797
+ resolve2();
2798
+ }
2799
+ }
2800
+ };
2801
+ async function createTransport(options) {
2802
+ if (options.transport) {
2803
+ return options.transport;
2804
+ }
2805
+ const transportOptions = {
2806
+ execPath: options.execPath,
2807
+ execArgs: options.execArgs,
2808
+ cwd: options.cwd,
2809
+ env: options.env
2810
+ };
2811
+ const processTransport = new ProcessTransport(transportOptions);
2812
+ await processTransport.connect();
2813
+ return processTransport;
2814
+ }
2815
+ function setupClientHandlers(client, options) {
2816
+ if (options.permissionHandler) {
2817
+ client.setPermissionHandler(options.permissionHandler);
2818
+ }
2819
+ if (options.askUserHandler) {
2820
+ client.setAskUserHandler(options.askUserHandler);
2821
+ }
2822
+ }
2823
+ async function createConfiguredClient(options) {
2824
+ const transport = await createTransport(options);
2825
+ const client = new DroidClient({ transport });
2826
+ setupClientHandlers(client, options);
2827
+ return { transport, client };
2828
+ }
2829
+ async function closeQuietly(resource) {
2830
+ if (!resource) {
2831
+ return;
2832
+ }
2833
+ try {
2834
+ await resource.close();
2835
+ } catch {
2836
+ }
2837
+ }
2838
+ function buildInitParams(options) {
2839
+ return {
2840
+ machineId: options.machineId ?? "default",
2841
+ cwd: options.cwd ?? ".",
2842
+ ...options.modelId !== void 0 && { modelId: options.modelId },
2843
+ ...options.autonomyLevel !== void 0 && {
2844
+ autonomyLevel: options.autonomyLevel
2845
+ },
2846
+ ...options.interactionMode !== void 0 && {
2847
+ interactionMode: options.interactionMode
2848
+ },
2849
+ ...options.reasoningEffort !== void 0 && {
2850
+ reasoningEffort: options.reasoningEffort
2851
+ },
2852
+ ...options.specModeModelId !== void 0 && {
2853
+ specModeModelId: options.specModeModelId
2854
+ },
2855
+ ...options.specModeReasoningEffort !== void 0 && {
2856
+ specModeReasoningEffort: options.specModeReasoningEffort
2857
+ },
2858
+ ...options.mcpServers !== void 0 && {
2859
+ mcpServers: options.mcpServers
2860
+ },
2861
+ ...options.enabledToolIds !== void 0 && {
2862
+ enabledToolIds: options.enabledToolIds
2863
+ },
2864
+ ...options.disabledToolIds !== void 0 && {
2865
+ disabledToolIds: options.disabledToolIds
2866
+ },
2867
+ tags: [...options.tags ?? [], SDK_TAG]
2868
+ };
2869
+ }
2870
+
2871
+ // src/mcp.ts
2872
+ import { once } from "events";
2873
+ import http from "http";
2874
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2875
+ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
2876
+ import { z as z8 } from "zod";
2877
+ function tool(name, description, inputSchemaOrHandler, handler) {
2878
+ if (typeof inputSchemaOrHandler === "function") {
2879
+ const actualHandler = inputSchemaOrHandler;
2880
+ return {
2881
+ name,
2882
+ description,
2883
+ handler: (input) => actualHandler(input)
2837
2884
  };
2838
- if (options.modelId !== void 0) {
2839
- initParams.modelId = options.modelId;
2885
+ }
2886
+ if (!handler) {
2887
+ throw new Error(`Missing handler for SDK MCP tool "${name}"`);
2888
+ }
2889
+ const inputObjectSchema = z8.object(inputSchemaOrHandler);
2890
+ return {
2891
+ name,
2892
+ description,
2893
+ inputSchema: inputSchemaOrHandler,
2894
+ handler: (input) => handler(inputObjectSchema.parse(input))
2895
+ };
2896
+ }
2897
+ function isSdkMcpServer(server) {
2898
+ return server instanceof SdkMcpServer;
2899
+ }
2900
+ function toCallToolResult(result) {
2901
+ if (typeof result === "string") {
2902
+ return {
2903
+ content: [{ type: "text", text: result }]
2904
+ };
2905
+ }
2906
+ return result;
2907
+ }
2908
+ async function readJsonBody(req) {
2909
+ const chunks = [];
2910
+ for await (const chunk of req) {
2911
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
2912
+ }
2913
+ if (chunks.length === 0) {
2914
+ return void 0;
2915
+ }
2916
+ return JSON.parse(Buffer.concat(chunks).toString("utf8"));
2917
+ }
2918
+ function writeJsonError(res, statusCode, message) {
2919
+ if (res.headersSent) {
2920
+ return;
2921
+ }
2922
+ res.writeHead(statusCode, { "content-type": "application/json" });
2923
+ res.end(
2924
+ JSON.stringify({
2925
+ jsonrpc: JSONRPC_VERSION,
2926
+ error: { code: -32603 /* INTERNAL_ERROR */, message },
2927
+ id: null
2928
+ })
2929
+ );
2930
+ }
2931
+ var SdkMcpServer = class {
2932
+ name;
2933
+ version;
2934
+ tools;
2935
+ _httpServer = null;
2936
+ _url = null;
2937
+ constructor(options) {
2938
+ this.name = options.name;
2939
+ this.version = options.version ?? "1.0.0";
2940
+ this.tools = options.tools;
2941
+ }
2942
+ get config() {
2943
+ if (!this._url) {
2944
+ return null;
2840
2945
  }
2841
- if (options.autonomyLevel !== void 0) {
2842
- initParams.autonomyLevel = options.autonomyLevel;
2946
+ return {
2947
+ type: "http" /* Http */,
2948
+ name: this.name,
2949
+ url: this._url,
2950
+ headers: []
2951
+ };
2952
+ }
2953
+ async start() {
2954
+ if (this.config) {
2955
+ return this.config;
2843
2956
  }
2844
- if (options.interactionMode !== void 0) {
2845
- initParams.interactionMode = options.interactionMode;
2957
+ this._httpServer = http.createServer((req, res) => {
2958
+ void this.handleRequest(req, res);
2959
+ });
2960
+ this._httpServer.listen(0, "127.0.0.1");
2961
+ await once(this._httpServer, "listening");
2962
+ const address = this._httpServer.address();
2963
+ if (!address || typeof address === "string") {
2964
+ throw new Error("Unable to determine SDK MCP server address");
2846
2965
  }
2847
- if (options.reasoningEffort !== void 0) {
2848
- initParams.reasoningEffort = options.reasoningEffort;
2966
+ this._url = `http://127.0.0.1:${address.port}/mcp`;
2967
+ const config = this.config;
2968
+ if (!config) {
2969
+ throw new Error("Unable to start SDK MCP server");
2849
2970
  }
2850
- if (options.mcpServers !== void 0) {
2851
- initParams.mcpServers = options.mcpServers;
2971
+ return config;
2972
+ }
2973
+ async close() {
2974
+ const server = this._httpServer;
2975
+ this._httpServer = null;
2976
+ this._url = null;
2977
+ if (!server) {
2978
+ return;
2852
2979
  }
2853
- if (options.enabledToolIds !== void 0) {
2854
- initParams.enabledToolIds = options.enabledToolIds;
2980
+ server.closeAllConnections?.();
2981
+ server.close();
2982
+ await once(server, "close");
2983
+ }
2984
+ createMcpServer() {
2985
+ const server = new McpServer({
2986
+ name: this.name,
2987
+ version: this.version
2988
+ });
2989
+ for (const sdkTool of this.tools) {
2990
+ server.registerTool(
2991
+ sdkTool.name,
2992
+ {
2993
+ description: sdkTool.description,
2994
+ ...sdkTool.inputSchema && {
2995
+ inputSchema: sdkTool.inputSchema
2996
+ }
2997
+ },
2998
+ async (input) => toCallToolResult(await sdkTool.handler(input))
2999
+ );
2855
3000
  }
2856
- const initResult = await client.initializeSession(
2857
- initParams
2858
- );
2859
- sessionId = initResult.sessionId;
2860
- await client.addUserMessage({ text: options.prompt });
3001
+ return server;
3002
+ }
3003
+ async handleRequest(req, res) {
3004
+ if (req.url !== "/mcp") {
3005
+ res.writeHead(404).end();
3006
+ return;
3007
+ }
3008
+ if (req.method !== "POST") {
3009
+ res.writeHead(405).end();
3010
+ return;
3011
+ }
3012
+ const server = this.createMcpServer();
3013
+ const transport = new StreamableHTTPServerTransport({
3014
+ sessionIdGenerator: void 0
3015
+ });
3016
+ res.on("close", () => {
3017
+ void transport.close();
3018
+ void server.close();
3019
+ });
2861
3020
  try {
2862
- while (true) {
3021
+ const body = await readJsonBody(req);
3022
+ await server.connect(transport);
3023
+ await transport.handleRequest(req, res, body);
3024
+ } catch (error) {
3025
+ writeJsonError(
3026
+ res,
3027
+ 500,
3028
+ error instanceof Error ? error.message : "Internal server error"
3029
+ );
3030
+ await transport.close();
3031
+ await server.close();
3032
+ }
3033
+ }
3034
+ };
3035
+ function createSdkMcpServer(options) {
3036
+ return new SdkMcpServer(options);
3037
+ }
3038
+ async function startSdkMcpServers(servers) {
3039
+ if (!servers) {
3040
+ return { cleanup: async () => {
3041
+ } };
3042
+ }
3043
+ const startedServers = [];
3044
+ const mcpServers = [];
3045
+ try {
3046
+ for (const server of servers) {
3047
+ if (isSdkMcpServer(server)) {
3048
+ mcpServers.push(await server.start());
3049
+ startedServers.push(server);
3050
+ } else {
3051
+ mcpServers.push(server);
3052
+ }
3053
+ }
3054
+ } catch (error) {
3055
+ await Promise.all(startedServers.map((server) => server.close()));
3056
+ throw error;
3057
+ }
3058
+ return {
3059
+ mcpServers,
3060
+ cleanup: async () => {
3061
+ await Promise.all(startedServers.map((server) => server.close()));
3062
+ }
3063
+ };
3064
+ }
3065
+
3066
+ // src/query.ts
3067
+ var DroidQueryImpl = class {
3068
+ _generator;
3069
+ _getSessionId;
3070
+ _getInitResult;
3071
+ _getInitialized;
3072
+ _interruptFn;
3073
+ _abortFn;
3074
+ constructor(generator, getSessionId, getInitResult, getInitialized, interruptFn, abortFn) {
3075
+ this._generator = generator;
3076
+ this._getSessionId = getSessionId;
3077
+ this._getInitResult = getInitResult;
3078
+ this._getInitialized = getInitialized;
3079
+ this._interruptFn = interruptFn;
3080
+ this._abortFn = abortFn;
3081
+ }
3082
+ get sessionId() {
3083
+ return this._getSessionId();
3084
+ }
3085
+ get initResult() {
3086
+ return this._getInitResult();
3087
+ }
3088
+ get initialized() {
3089
+ return this._getInitialized();
3090
+ }
3091
+ async interrupt() {
3092
+ return this._interruptFn();
3093
+ }
3094
+ abort() {
3095
+ this._abortFn();
3096
+ }
3097
+ next(...args) {
3098
+ return this._generator.next(...args);
3099
+ }
3100
+ return(value) {
3101
+ return this._generator.return(value);
3102
+ }
3103
+ throw(e) {
3104
+ return this._generator.throw(e);
3105
+ }
3106
+ [Symbol.asyncIterator]() {
3107
+ return this;
3108
+ }
3109
+ };
3110
+ function query(options) {
3111
+ let transport = null;
3112
+ let client = null;
3113
+ let sessionId = null;
3114
+ let initResult = null;
3115
+ let aborted = false;
3116
+ let initializationPromise = null;
3117
+ let promptPromise = null;
3118
+ let cleanupAbortSignal = () => {
3119
+ };
3120
+ let cleanupSdkMcpServers = null;
3121
+ const bridge = new MessageBridge();
3122
+ const closeActiveResources = async () => {
3123
+ const closer = client ?? transport;
3124
+ const cleanupMcp = cleanupSdkMcpServers;
3125
+ client = null;
3126
+ transport = null;
3127
+ cleanupSdkMcpServers = null;
3128
+ await Promise.all([closeQuietly(closer), cleanupMcp?.()]);
3129
+ };
3130
+ const ensureInitialized = () => {
3131
+ if (initResult) {
3132
+ return Promise.resolve(initResult);
3133
+ }
3134
+ if (initializationPromise) {
3135
+ return initializationPromise;
3136
+ }
3137
+ initializationPromise = (async () => {
3138
+ try {
2863
3139
  if (aborted) {
2864
- return;
2865
- }
2866
- while (messageQueue.length > 0) {
2867
- const msg = messageQueue.shift();
2868
- yield msg;
2869
- if (msg.type === "turn_complete") {
2870
- return;
2871
- }
3140
+ throw new Error("Query aborted before initialization");
2872
3141
  }
2873
- if (streamDone && messageQueue.length === 0) {
2874
- return;
3142
+ const configuredClient = await createConfiguredClient(options);
3143
+ transport = configuredClient.transport;
3144
+ client = configuredClient.client;
3145
+ client.onNotification(bridge.notificationHandler);
3146
+ if (aborted) {
3147
+ throw new Error("Query aborted before initialization");
2875
3148
  }
2876
- await new Promise((resolve) => {
2877
- resolveWaiting = resolve;
2878
- });
3149
+ const sdkMcpServers = await startSdkMcpServers(options.mcpServers);
3150
+ cleanupSdkMcpServers = sdkMcpServers.cleanup;
3151
+ const result = await client.initializeSession(
3152
+ buildInitParams({
3153
+ ...options,
3154
+ mcpServers: sdkMcpServers.mcpServers
3155
+ })
3156
+ );
3157
+ sessionId = result.sessionId;
3158
+ initResult = result;
3159
+ return result;
3160
+ } catch (error) {
3161
+ await closeActiveResources();
3162
+ throw error;
2879
3163
  }
2880
- } finally {
3164
+ })();
3165
+ return initializationPromise;
3166
+ };
3167
+ const ensurePromptSent = () => {
3168
+ if (promptPromise) {
3169
+ return promptPromise;
3170
+ }
3171
+ promptPromise = (async () => {
3172
+ await ensureInitialized();
3173
+ if (aborted || client === null) {
3174
+ return;
3175
+ }
3176
+ await client.addUserMessage({ text: options.prompt });
3177
+ })();
3178
+ return promptPromise;
3179
+ };
3180
+ async function* generateMessages() {
3181
+ if (aborted) return;
3182
+ await ensurePromptSent();
3183
+ if (aborted) return;
3184
+ for await (const msg of bridge.messages()) {
3185
+ if (aborted) return;
3186
+ yield msg;
2881
3187
  }
2882
3188
  }
2883
3189
  const generator = generateMessages();
@@ -2885,310 +3191,273 @@ function query(options) {
2885
3191
  try {
2886
3192
  yield* generator;
2887
3193
  } finally {
2888
- if (client) {
2889
- try {
2890
- await client.close();
2891
- } catch {
2892
- }
2893
- client = null;
2894
- } else if (transport) {
2895
- try {
2896
- await transport.close();
2897
- } catch {
2898
- }
2899
- }
2900
- transport = null;
3194
+ cleanupAbortSignal();
3195
+ await closeActiveResources();
2901
3196
  }
2902
3197
  }
2903
- const wrapped = wrappedGenerator();
2904
- const droidQuery = wrapped;
2905
- Object.defineProperties(droidQuery, {
2906
- interrupt: {
2907
- value: async function interrupt() {
2908
- if (client && !aborted) {
2909
- await client.interruptSession();
2910
- }
2911
- },
2912
- writable: false,
2913
- enumerable: true
2914
- },
2915
- abort: {
2916
- value: function abort() {
2917
- aborted = true;
2918
- signalDone();
2919
- if (client) {
2920
- void client.close().catch(() => {
2921
- });
2922
- client = null;
2923
- } else if (transport) {
2924
- void transport.close().catch(() => {
2925
- });
2926
- }
2927
- transport = null;
2928
- },
2929
- writable: false,
2930
- enumerable: true
3198
+ const droidQuery = new DroidQueryImpl(
3199
+ wrappedGenerator(),
3200
+ () => sessionId,
3201
+ () => initResult,
3202
+ () => ensureInitialized(),
3203
+ async () => {
3204
+ if (client && !aborted) {
3205
+ await client.interruptSession();
3206
+ }
2931
3207
  },
2932
- sessionId: {
2933
- get() {
2934
- return sessionId;
2935
- },
2936
- enumerable: true
3208
+ () => {
3209
+ aborted = true;
3210
+ bridge.signalDone();
3211
+ cleanupAbortSignal();
3212
+ void closeActiveResources();
2937
3213
  }
2938
- });
3214
+ );
3215
+ cleanupAbortSignal = wireAbortSignal(
3216
+ options.abortSignal,
3217
+ () => droidQuery.abort()
3218
+ );
2939
3219
  return droidQuery;
2940
3220
  }
2941
3221
 
2942
3222
  // src/session.ts
3223
+ function getAbortError(signal) {
3224
+ if (signal.reason instanceof Error) {
3225
+ return signal.reason;
3226
+ }
3227
+ return new Error(
3228
+ typeof signal.reason === "string" ? signal.reason : "Operation aborted"
3229
+ );
3230
+ }
3231
+ function throwIfAborted(signal) {
3232
+ if (signal?.aborted) {
3233
+ throw getAbortError(signal);
3234
+ }
3235
+ }
3236
+ function parseJsonObject(text) {
3237
+ try {
3238
+ const parsed = JSON.parse(text);
3239
+ const result = JsonObjectSchema.safeParse(parsed);
3240
+ return result.success ? result.data : null;
3241
+ } catch {
3242
+ return null;
3243
+ }
3244
+ }
3245
+ function extractAssistantText(message) {
3246
+ if (message.type !== DroidMessageType.CreateMessage) {
3247
+ return "";
3248
+ }
3249
+ if (message.role !== FactoryDroidMessageRole.Assistant) {
3250
+ return "";
3251
+ }
3252
+ return message.content.filter((block) => block.type === "text").map((block) => block.text).join("");
3253
+ }
2943
3254
  var DroidSession = class {
2944
3255
  _client;
2945
3256
  _sessionId;
2946
3257
  _initResult;
2947
3258
  _closed = false;
3259
+ _cleanupAbortSignal = null;
3260
+ _cleanupCallbacks = [];
2948
3261
  /** @internal */
2949
3262
  constructor(client, sessionId, initResult) {
2950
3263
  this._client = client;
2951
3264
  this._sessionId = sessionId;
2952
3265
  this._initResult = initResult;
2953
3266
  }
2954
- // ------------------------------------------------------------------
2955
- // Properties
2956
- // ------------------------------------------------------------------
2957
- /** The session ID. */
2958
3267
  get sessionId() {
2959
3268
  return this._sessionId;
2960
3269
  }
2961
- /** The result from session initialization or loading. */
2962
3270
  get initResult() {
2963
3271
  return this._initResult;
2964
3272
  }
2965
- // ------------------------------------------------------------------
2966
- // Messaging
2967
- // ------------------------------------------------------------------
2968
- /**
2969
- * Send a message and return a streaming async generator of DroidMessage events.
2970
- *
2971
- * The generator yields messages until a TurnComplete event is received,
2972
- * signaling the end of the agent's turn.
2973
- *
2974
- * @param text - The user message text.
2975
- * @param options - Optional images/files to include.
2976
- * @returns An async generator yielding DroidMessage events.
2977
- */
3273
+ /** @internal */
3274
+ setAbortSignalCleanup(cleanup) {
3275
+ this._cleanupAbortSignal = cleanup;
3276
+ }
3277
+ /** @internal */
3278
+ addCleanup(cleanup) {
3279
+ this._cleanupCallbacks.push(cleanup);
3280
+ }
3281
+ /** Yields {@link DroidMessage} events until `turn_complete`. */
2978
3282
  async *stream(text, options) {
2979
3283
  this._ensureNotClosed();
2980
- const messageQueue = [];
2981
- let resolveWaiting = null;
2982
- let streamDone = false;
2983
- function enqueueMessage(msg) {
2984
- messageQueue.push(msg);
2985
- if (resolveWaiting) {
2986
- const resolve = resolveWaiting;
2987
- resolveWaiting = null;
2988
- resolve();
2989
- }
2990
- }
2991
- function signalDone() {
2992
- streamDone = true;
2993
- if (resolveWaiting) {
2994
- const resolve = resolveWaiting;
2995
- resolveWaiting = null;
2996
- resolve();
2997
- }
2998
- }
2999
- const stateTracker = new StreamStateTracker();
3000
- const unsubscribe = this._client.onNotification((notification) => {
3001
- const params = notification["params"];
3002
- const innerNotification = params?.["notification"];
3003
- if (!innerNotification) {
3004
- return;
3005
- }
3006
- const converted = convertNotificationToStreamMessage(
3007
- innerNotification
3008
- );
3009
- if (converted === null) {
3010
- return;
3011
- }
3012
- const messages = Array.isArray(converted) ? converted : [converted];
3013
- for (const msg of messages) {
3014
- enqueueMessage(msg);
3015
- const additional = stateTracker.processMessage(msg);
3016
- for (const extra of additional) {
3017
- enqueueMessage(extra);
3018
- if (extra.type === "turn_complete") {
3019
- signalDone();
3020
- }
3021
- }
3022
- }
3284
+ throwIfAborted(options?.abortSignal);
3285
+ const bridge = new MessageBridge();
3286
+ const unsubscribe = this._client.onNotification(bridge.notificationHandler);
3287
+ let resolveAbort = () => {
3288
+ };
3289
+ const abortPromise = new Promise((resolve2) => {
3290
+ resolveAbort = resolve2;
3023
3291
  });
3024
- try {
3025
- await this._client.addUserMessage({
3026
- text,
3027
- images: options?.images,
3028
- files: options?.files
3292
+ const cleanupAbortSignal = wireAbortSignal(options?.abortSignal, () => {
3293
+ bridge.signalDone();
3294
+ resolveAbort();
3295
+ void this._client.interruptSession().catch(() => {
3029
3296
  });
3030
- while (true) {
3031
- while (messageQueue.length > 0) {
3032
- const msg = messageQueue.shift();
3033
- yield msg;
3034
- if (msg.type === "turn_complete") {
3035
- return;
3036
- }
3037
- }
3038
- if (streamDone && messageQueue.length === 0) {
3039
- return;
3040
- }
3041
- await new Promise((resolve) => {
3042
- resolveWaiting = resolve;
3043
- });
3297
+ });
3298
+ try {
3299
+ await Promise.race([
3300
+ this._client.addUserMessage({
3301
+ text,
3302
+ images: options?.images,
3303
+ files: options?.files,
3304
+ outputFormat: options?.outputFormat
3305
+ }),
3306
+ abortPromise
3307
+ ]);
3308
+ throwIfAborted(options?.abortSignal);
3309
+ for await (const msg of bridge.messages()) {
3310
+ throwIfAborted(options?.abortSignal);
3311
+ yield msg;
3044
3312
  }
3313
+ throwIfAborted(options?.abortSignal);
3045
3314
  } finally {
3315
+ cleanupAbortSignal();
3046
3316
  unsubscribe();
3047
3317
  }
3048
3318
  }
3049
- /**
3050
- * Send a message and collect the complete response (non-streaming).
3051
- *
3052
- * Internally consumes all stream messages and returns an aggregated
3053
- * {@link DroidResult} with the concatenated text, all messages, and
3054
- * final token usage.
3055
- *
3056
- * @param text - The user message text.
3057
- * @param options - Optional images/files to include.
3058
- * @returns Aggregated result with text, messages, and token usage.
3059
- */
3319
+ /** Consumes the stream and returns an aggregated {@link DroidResult}. */
3060
3320
  async send(text, options) {
3061
3321
  this._ensureNotClosed();
3062
3322
  const messages = [];
3063
3323
  let fullText = "";
3064
3324
  let lastTokenUsage = null;
3325
+ let firstError = null;
3326
+ let structuredOutput = null;
3327
+ let finalAssistantText = "";
3328
+ let turnCount = 0;
3329
+ const startedAt = Date.now();
3065
3330
  for await (const msg of this.stream(text, options)) {
3066
3331
  messages.push(msg);
3067
- if (msg.type === "assistant_text_delta") {
3332
+ if (msg.type === DroidMessageType.AssistantTextDelta) {
3068
3333
  fullText += msg.text;
3069
3334
  }
3070
- if (msg.type === "token_usage_update") {
3335
+ const assistantText = extractAssistantText(msg);
3336
+ if (assistantText) {
3337
+ finalAssistantText = assistantText;
3338
+ if (options?.outputFormat && fullText.length === 0) {
3339
+ fullText = assistantText;
3340
+ }
3341
+ }
3342
+ if (msg.type === DroidMessageType.TokenUsageUpdate) {
3071
3343
  lastTokenUsage = msg;
3072
3344
  }
3073
- if (msg.type === "turn_complete" && msg.tokenUsage) {
3074
- lastTokenUsage = msg.tokenUsage;
3345
+ if (msg.type === DroidMessageType.Error && firstError === null) {
3346
+ firstError = msg;
3347
+ }
3348
+ if (options?.outputFormat && structuredOutput === null) {
3349
+ const textToParse = finalAssistantText || fullText;
3350
+ if (textToParse) {
3351
+ structuredOutput = parseJsonObject(textToParse);
3352
+ }
3353
+ }
3354
+ if (msg.type === DroidMessageType.TurnComplete) {
3355
+ turnCount++;
3356
+ if (msg.tokenUsage) {
3357
+ lastTokenUsage = msg.tokenUsage;
3358
+ }
3075
3359
  }
3076
3360
  }
3077
3361
  return {
3362
+ sessionId: this._sessionId,
3078
3363
  text: fullText,
3079
3364
  messages,
3080
- tokenUsage: lastTokenUsage
3365
+ tokenUsage: lastTokenUsage,
3366
+ durationMs: Date.now() - startedAt,
3367
+ turnCount,
3368
+ error: firstError,
3369
+ structuredOutput,
3370
+ success: firstError === null
3081
3371
  };
3082
3372
  }
3083
- // ------------------------------------------------------------------
3084
- // Session control
3085
- // ------------------------------------------------------------------
3086
- /**
3087
- * Interrupt the current agent turn.
3088
- *
3089
- * Sends an interrupt request. The agent will stop after completing
3090
- * its current operation.
3091
- */
3092
3373
  async interrupt() {
3093
3374
  this._ensureNotClosed();
3094
3375
  await this._client.interruptSession();
3095
3376
  }
3096
- /**
3097
- * Close the session and release all resources.
3098
- *
3099
- * Closes the underlying transport and rejects any pending requests.
3100
- * After close, the session cannot be used.
3101
- */
3102
3377
  async close() {
3103
3378
  if (this._closed) {
3104
3379
  return;
3105
3380
  }
3106
3381
  this._closed = true;
3107
- await this._client.close();
3382
+ this._cleanupAbortSignal?.();
3383
+ this._cleanupAbortSignal = null;
3384
+ try {
3385
+ await this._client.close();
3386
+ } finally {
3387
+ const cleanups = this._cleanupCallbacks.splice(0);
3388
+ await Promise.all(cleanups.map((cleanup) => cleanup()));
3389
+ }
3108
3390
  }
3109
- // ------------------------------------------------------------------
3110
- // Settings
3111
- // ------------------------------------------------------------------
3112
- /**
3113
- * Update session settings (model, reasoning effort, autonomy, etc.).
3114
- *
3115
- * @param params - Partial settings to update.
3116
- */
3117
3391
  async updateSettings(params) {
3118
3392
  this._ensureNotClosed();
3119
3393
  return this._client.updateSessionSettings(params);
3120
3394
  }
3121
- // ------------------------------------------------------------------
3122
- // MCP methods
3123
- // ------------------------------------------------------------------
3124
- /**
3125
- * Add an MCP server to the session.
3126
- */
3395
+ async enterSpecMode(params = {}) {
3396
+ this._ensureNotClosed();
3397
+ return this._client.updateSessionSettings({
3398
+ interactionMode: "spec" /* Spec */,
3399
+ ...params
3400
+ });
3401
+ }
3127
3402
  async addMcpServer(params) {
3128
3403
  this._ensureNotClosed();
3129
3404
  return this._client.addMcpServer(params);
3130
3405
  }
3131
- /**
3132
- * Remove an MCP server from the session.
3133
- */
3134
3406
  async removeMcpServer(params) {
3135
3407
  this._ensureNotClosed();
3136
3408
  return this._client.removeMcpServer(params);
3137
3409
  }
3138
- /**
3139
- * Toggle an MCP server on or off.
3140
- */
3141
3410
  async toggleMcpServer(params) {
3142
3411
  this._ensureNotClosed();
3143
3412
  return this._client.toggleMcpServer(params);
3144
3413
  }
3145
- /**
3146
- * List MCP servers and their status.
3147
- */
3148
3414
  async listMcpServers() {
3149
3415
  this._ensureNotClosed();
3150
3416
  return this._client.listMcpServers();
3151
3417
  }
3152
- /**
3153
- * List available MCP tools.
3154
- */
3155
3418
  async listMcpTools() {
3156
3419
  this._ensureNotClosed();
3157
3420
  return this._client.listMcpTools();
3158
3421
  }
3159
- /**
3160
- * Authenticate an MCP server (OAuth flow).
3161
- */
3422
+ async listTools(params = {}) {
3423
+ this._ensureNotClosed();
3424
+ return this._client.listTools(params);
3425
+ }
3162
3426
  async authenticateMcpServer(params) {
3163
3427
  this._ensureNotClosed();
3164
3428
  return this._client.authenticateMcpServer(params);
3165
3429
  }
3166
- // ------------------------------------------------------------------
3167
- // Skills
3168
- // ------------------------------------------------------------------
3169
- /**
3170
- * List available skills.
3171
- */
3172
3430
  async listSkills() {
3173
3431
  this._ensureNotClosed();
3174
3432
  return this._client.listSkills();
3175
3433
  }
3176
- // ------------------------------------------------------------------
3177
- // Notification subscription
3178
- // ------------------------------------------------------------------
3179
- /**
3180
- * Register a callback for incoming notification messages.
3181
- *
3182
- * @param callback - Invoked with the notification object.
3183
- * @param filter - Optional filter to only receive specific notification types.
3184
- * @returns An unsubscribe function.
3185
- */
3434
+ async getRewindInfo(params) {
3435
+ this._ensureNotClosed();
3436
+ return this._client.getRewindInfo(params);
3437
+ }
3438
+ async executeRewind(params) {
3439
+ this._ensureNotClosed();
3440
+ return this._client.executeRewind(params);
3441
+ }
3442
+ async compactSession(params) {
3443
+ this._ensureNotClosed();
3444
+ return this._client.compactSession(params ?? {});
3445
+ }
3446
+ async forkSession() {
3447
+ this._ensureNotClosed();
3448
+ return this._client.forkSession();
3449
+ }
3450
+ async getContextStats() {
3451
+ this._ensureNotClosed();
3452
+ return this._client.getContextStats();
3453
+ }
3454
+ async renameSession(params) {
3455
+ this._ensureNotClosed();
3456
+ return this._client.renameSession(params);
3457
+ }
3186
3458
  onNotification(callback, filter) {
3187
3459
  return this._client.onNotification(callback, filter);
3188
3460
  }
3189
- // ------------------------------------------------------------------
3190
- // Internal
3191
- // ------------------------------------------------------------------
3192
3461
  _ensureNotClosed() {
3193
3462
  if (this._closed) {
3194
3463
  throw new ConnectionError(
@@ -3198,98 +3467,290 @@ var DroidSession = class {
3198
3467
  }
3199
3468
  };
3200
3469
  async function createSession(options = {}) {
3201
- let transport;
3202
- if (options.transport) {
3203
- transport = options.transport;
3204
- } else {
3205
- const transportOptions = {
3206
- execPath: options.execPath,
3207
- execArgs: options.execArgs,
3208
- cwd: options.cwd,
3209
- env: options.env
3470
+ const { client } = await createConfiguredClient(options);
3471
+ let cleanupInitAbortSignal = options.abortSignal?.aborted ? () => {
3472
+ } : wireAbortSignal(options.abortSignal, () => {
3473
+ void closeQuietly(client);
3474
+ });
3475
+ let sdkMcpServers;
3476
+ try {
3477
+ sdkMcpServers = await startSdkMcpServers(options.mcpServers);
3478
+ const initParams = buildInitParams({
3479
+ ...options,
3480
+ mcpServers: sdkMcpServers.mcpServers
3481
+ });
3482
+ const initResult = await client.initializeSession(initParams);
3483
+ const session = new DroidSession(client, initResult.sessionId, initResult);
3484
+ session.addCleanup(sdkMcpServers.cleanup);
3485
+ cleanupInitAbortSignal();
3486
+ cleanupInitAbortSignal = () => {
3210
3487
  };
3211
- const processTransport = new ProcessTransport(transportOptions);
3212
- await processTransport.connect();
3213
- transport = processTransport;
3214
- }
3215
- const client = new DroidClient({ transport });
3216
- if (options.permissionHandler) {
3217
- client.setPermissionHandler(options.permissionHandler);
3218
- }
3219
- if (options.askUserHandler) {
3220
- client.setAskUserHandler(options.askUserHandler);
3221
- }
3222
- const initParams = {
3223
- machineId: options.machineId ?? "default",
3224
- cwd: options.cwd ?? "."
3225
- };
3226
- if (options.modelId !== void 0) {
3227
- initParams.modelId = options.modelId;
3488
+ session.setAbortSignalCleanup(
3489
+ wireAbortSignal(options.abortSignal, () => void session.close())
3490
+ );
3491
+ return session;
3492
+ } catch (error) {
3493
+ cleanupInitAbortSignal();
3494
+ await sdkMcpServers?.cleanup();
3495
+ await closeQuietly(client);
3496
+ throw error;
3228
3497
  }
3229
- if (options.autonomyLevel !== void 0) {
3230
- initParams.autonomyLevel = options.autonomyLevel;
3498
+ }
3499
+ async function resumeSession(sessionId, options = {}) {
3500
+ const { client } = await createConfiguredClient(options);
3501
+ let sdkMcpServers;
3502
+ try {
3503
+ sdkMcpServers = await startSdkMcpServers(options.mcpServers);
3504
+ const loadParams = {
3505
+ sessionId,
3506
+ mcpServers: sdkMcpServers.mcpServers
3507
+ };
3508
+ const loadResult = await client.loadSession(loadParams);
3509
+ const session = new DroidSession(client, sessionId, loadResult);
3510
+ session.addCleanup(sdkMcpServers.cleanup);
3511
+ session.setAbortSignalCleanup(
3512
+ wireAbortSignal(options.abortSignal, () => void session.close())
3513
+ );
3514
+ return session;
3515
+ } catch (error) {
3516
+ await sdkMcpServers?.cleanup();
3517
+ await closeQuietly(client);
3518
+ throw error;
3231
3519
  }
3232
- if (options.interactionMode !== void 0) {
3233
- initParams.interactionMode = options.interactionMode;
3520
+ }
3521
+
3522
+ // src/run.ts
3523
+ async function run(text, options = {}) {
3524
+ const session = await createSession(options);
3525
+ try {
3526
+ return await session.send(text, options);
3527
+ } finally {
3528
+ await session.close();
3234
3529
  }
3235
- if (options.reasoningEffort !== void 0) {
3236
- initParams.reasoningEffort = options.reasoningEffort;
3530
+ }
3531
+
3532
+ // src/session-discovery.ts
3533
+ import * as fs from "fs";
3534
+ import * as os from "os";
3535
+ import * as path from "path";
3536
+ var FAVORITES_FILE = ".favorites";
3537
+ var SESSION_EXTENSION = ".jsonl";
3538
+ var SETTINGS_SUFFIX = ".settings.json";
3539
+ var MISSION_TAG_PREFIX = "mission:";
3540
+ var MISSION_ID_METADATA_KEY = "missionId";
3541
+ var DECOMP_SESSION_TYPE_TAG = "decompSessionType";
3542
+ var DECOMP_SESSION_TYPE_METADATA_KEY = "value";
3543
+ var LF = 10;
3544
+ var CR = 13;
3545
+ var SPACE = 32;
3546
+ var TAB = 9;
3547
+ var PARSE_OVERSAMPLE = 20;
3548
+ function readFileBuffer(filePath) {
3549
+ try {
3550
+ return fs.readFileSync(filePath);
3551
+ } catch {
3552
+ return null;
3237
3553
  }
3238
- if (options.mcpServers !== void 0) {
3239
- initParams.mcpServers = options.mcpServers;
3554
+ }
3555
+ function parseJsonBuffer(buf) {
3556
+ try {
3557
+ return JSON.parse(buf.toString("utf-8"));
3558
+ } catch {
3559
+ return null;
3240
3560
  }
3241
- if (options.enabledToolIds !== void 0) {
3242
- initParams.enabledToolIds = options.enabledToolIds;
3561
+ }
3562
+ function scanBufferForLines(buf) {
3563
+ let nonEmptyLineCount = 0;
3564
+ let firstLineEnd = -1;
3565
+ let currentLineHasContent = false;
3566
+ for (let i = 0; i < buf.length; i++) {
3567
+ const ch = buf[i];
3568
+ if (ch === LF) {
3569
+ if (currentLineHasContent) nonEmptyLineCount++;
3570
+ if (firstLineEnd === -1) firstLineEnd = i;
3571
+ currentLineHasContent = false;
3572
+ } else if (ch !== CR && ch !== SPACE && ch !== TAB) {
3573
+ currentLineHasContent = true;
3574
+ }
3243
3575
  }
3576
+ if (currentLineHasContent) nonEmptyLineCount++;
3577
+ const end = firstLineEnd === -1 ? buf.length : firstLineEnd > 0 && buf[firstLineEnd - 1] === CR ? firstLineEnd - 1 : firstLineEnd;
3578
+ return {
3579
+ firstLine: buf.subarray(0, end),
3580
+ nonEmptyLineCount
3581
+ };
3582
+ }
3583
+ function loadFavorites(sessionsDir) {
3584
+ const buf = readFileBuffer(path.join(sessionsDir, FAVORITES_FILE));
3585
+ if (!buf) return /* @__PURE__ */ new Set();
3586
+ const parsed = parseJsonBuffer(buf);
3587
+ if (!Array.isArray(parsed)) return /* @__PURE__ */ new Set();
3588
+ return new Set(parsed.filter((id) => typeof id === "string"));
3589
+ }
3590
+ function loadSettingsFile(directory, sessionId) {
3591
+ const buf = readFileBuffer(
3592
+ path.join(directory, `${sessionId}${SETTINGS_SUFFIX}`)
3593
+ );
3594
+ if (!buf) return null;
3595
+ const parsed = parseJsonBuffer(buf);
3596
+ if (parsed === null) return null;
3597
+ const result = SessionSettingsFileSchema.safeParse(parsed);
3598
+ return result.success ? result.data : null;
3599
+ }
3600
+ function getMissionMetadataFromTags(settings) {
3601
+ if (!settings?.tags) return {};
3602
+ const missionTag = settings.tags.find(
3603
+ (tag) => tag.name.startsWith(MISSION_TAG_PREFIX)
3604
+ );
3605
+ const roleTag = settings.tags.find(
3606
+ (tag) => tag.name === DECOMP_SESSION_TYPE_TAG
3607
+ );
3608
+ return {
3609
+ decompMissionId: missionTag?.metadata?.[MISSION_ID_METADATA_KEY],
3610
+ decompSessionType: roleTag?.metadata?.[DECOMP_SESSION_TYPE_METADATA_KEY]
3611
+ };
3612
+ }
3613
+ function parseSessionFile(candidate, ctx) {
3614
+ const buf = readFileBuffer(candidate.sessionPath);
3615
+ if (!buf) return null;
3616
+ const scanned = scanBufferForLines(buf);
3617
+ const firstParsed = parseJsonBuffer(scanned.firstLine);
3618
+ if (firstParsed === null) return null;
3619
+ const firstResult = SessionStartEventSchema.safeParse(firstParsed);
3620
+ if (!firstResult.success) return null;
3621
+ const summary = firstResult.data;
3622
+ if (ctx.requiredCwd !== void 0 && (summary.cwd === void 0 || path.resolve(summary.cwd) !== ctx.requiredCwd)) {
3623
+ return null;
3624
+ }
3625
+ const settingsName = `${candidate.sessionId}${SETTINGS_SUFFIX}`;
3626
+ const settings = candidate.siblingNames.has(settingsName) ? loadSettingsFile(candidate.directory, candidate.sessionId) : null;
3627
+ if (settings?.archivedAt) return null;
3628
+ const tagMeta = getMissionMetadataFromTags(settings);
3629
+ const decompSessionType = summary.decompSessionType ?? SessionStartEventSchema.shape.decompSessionType.safeParse(
3630
+ tagMeta.decompSessionType
3631
+ ).data;
3632
+ const messageCount = Math.max(0, scanned.nonEmptyLineCount - 1);
3633
+ return {
3634
+ id: candidate.sessionId,
3635
+ title: summary.title ?? "",
3636
+ sessionTitle: summary.sessionTitle,
3637
+ owner: summary.owner ?? "",
3638
+ messageCount,
3639
+ modifiedTime: candidate.stats.mtime,
3640
+ createdTime: candidate.stats.birthtime || candidate.stats.ctime,
3641
+ isFavorite: ctx.favorites.has(candidate.sessionId),
3642
+ cwd: summary.cwd,
3643
+ decompSessionType,
3644
+ decompMissionId: tagMeta.decompMissionId ?? summary.decompMissionId
3645
+ };
3646
+ }
3647
+ function readDirEntries(directory) {
3244
3648
  try {
3245
- const initResult = await client.initializeSession(
3246
- initParams
3247
- );
3248
- return new DroidSession(client, initResult.sessionId, initResult);
3249
- } catch (error) {
3649
+ return fs.readdirSync(directory, { withFileTypes: true });
3650
+ } catch {
3651
+ return [];
3652
+ }
3653
+ }
3654
+ function collectCandidates(directory, entries) {
3655
+ const siblingNames = new Set(entries.map((e) => e.name));
3656
+ const candidates = [];
3657
+ for (const entry of entries) {
3658
+ if (entry.isDirectory()) continue;
3659
+ if (!entry.name.endsWith(SESSION_EXTENSION)) continue;
3660
+ const sessionPath = path.join(directory, entry.name);
3661
+ let stats;
3250
3662
  try {
3251
- await client.close();
3663
+ stats = fs.statSync(sessionPath);
3252
3664
  } catch {
3665
+ continue;
3253
3666
  }
3254
- throw error;
3667
+ candidates.push({
3668
+ sessionId: entry.name.slice(0, -SESSION_EXTENSION.length),
3669
+ sessionPath,
3670
+ directory,
3671
+ siblingNames,
3672
+ stats
3673
+ });
3255
3674
  }
3675
+ return candidates;
3256
3676
  }
3257
- async function resumeSession(sessionId, options = {}) {
3258
- let transport;
3259
- if (options.transport) {
3260
- transport = options.transport;
3261
- } else {
3262
- const transportOptions = {
3263
- execPath: options.execPath,
3264
- execArgs: options.execArgs,
3265
- cwd: options.cwd,
3266
- env: options.env
3267
- };
3268
- const processTransport = new ProcessTransport(transportOptions);
3269
- await processTransport.connect();
3270
- transport = processTransport;
3677
+ function parseUpTo(candidates, ctx, limit) {
3678
+ const out = [];
3679
+ for (const candidate of candidates) {
3680
+ if (limit !== void 0 && out.length >= limit) break;
3681
+ const metadata = parseSessionFile(candidate, ctx);
3682
+ if (metadata) out.push(metadata);
3683
+ }
3684
+ return out;
3685
+ }
3686
+ function sanitizePathToDirectoryName(cwd) {
3687
+ let expandedPath = cwd;
3688
+ if (cwd.startsWith("~/") || cwd === "~") {
3689
+ expandedPath = path.join(os.homedir(), cwd.slice(1));
3271
3690
  }
3272
- const client = new DroidClient({ transport });
3273
- if (options.permissionHandler) {
3274
- client.setPermissionHandler(options.permissionHandler);
3691
+ const absolutePath = path.resolve(expandedPath);
3692
+ let canonicalPath = absolutePath;
3693
+ try {
3694
+ canonicalPath = fs.realpathSync(absolutePath);
3695
+ } catch {
3696
+ canonicalPath = absolutePath;
3275
3697
  }
3276
- if (options.askUserHandler) {
3277
- client.setAskUserHandler(options.askUserHandler);
3698
+ const normalized = canonicalPath.replace(/[\\/]+$/, "");
3699
+ if (process.platform === "win32") {
3700
+ return `-${normalized.replace(/^([A-Z]):/i, "$1").replace(/[\\/]+/g, "-")}`;
3278
3701
  }
3279
- const loadParams = {
3280
- sessionId,
3281
- mcpServers: options.mcpServers
3282
- };
3283
- try {
3284
- const loadResult = await client.loadSession(loadParams);
3285
- return new DroidSession(client, sessionId, loadResult);
3286
- } catch (error) {
3287
- try {
3288
- await client.close();
3289
- } catch {
3702
+ return `-${normalized.replace(/^\/+/, "").replace(/\/+/g, "-")}`;
3703
+ }
3704
+ function getDefaultSessionsDir() {
3705
+ return path.join(os.homedir(), ".factory", "sessions");
3706
+ }
3707
+ async function listSessions(options = {}) {
3708
+ const sessionsDir = options.sessionsDir ?? getDefaultSessionsDir();
3709
+ const favorites = loadFavorites(sessionsDir);
3710
+ const rootEntries = readDirEntries(sessionsDir);
3711
+ const legacyCandidates = collectCandidates(sessionsDir, rootEntries);
3712
+ const projectCandidates = [];
3713
+ let requiredCwd;
3714
+ if (options.fetchOutsideCWD) {
3715
+ for (const entry of rootEntries) {
3716
+ if (!entry.isDirectory()) continue;
3717
+ if (!entry.name.startsWith("-")) continue;
3718
+ const dir = path.join(sessionsDir, entry.name);
3719
+ projectCandidates.push(...collectCandidates(dir, readDirEntries(dir)));
3290
3720
  }
3291
- throw error;
3721
+ } else {
3722
+ const normalizedCwd = path.resolve(options.cwd ?? process.cwd());
3723
+ requiredCwd = normalizedCwd;
3724
+ const projectDir = path.join(
3725
+ sessionsDir,
3726
+ sanitizePathToDirectoryName(normalizedCwd)
3727
+ );
3728
+ projectCandidates.push(
3729
+ ...collectCandidates(projectDir, readDirEntries(projectDir))
3730
+ );
3731
+ }
3732
+ const byMtimeDesc = (a, b) => b.stats.mtime.getTime() - a.stats.mtime.getTime();
3733
+ projectCandidates.sort(byMtimeDesc);
3734
+ legacyCandidates.sort(byMtimeDesc);
3735
+ const parseLimit = options.numSessions !== void 0 && options.numSessions >= 0 ? options.numSessions + PARSE_OVERSAMPLE : void 0;
3736
+ const ctx = { favorites };
3737
+ const legacyCtx = requiredCwd !== void 0 ? { favorites, requiredCwd } : ctx;
3738
+ const projectSessions = parseUpTo(projectCandidates, ctx, parseLimit);
3739
+ const legacySessions = parseUpTo(legacyCandidates, legacyCtx, parseLimit);
3740
+ const byId = /* @__PURE__ */ new Map();
3741
+ for (const session of [...projectSessions, ...legacySessions]) {
3742
+ const existing = byId.get(session.id);
3743
+ if (!existing || session.modifiedTime.getTime() > existing.modifiedTime.getTime()) {
3744
+ byId.set(session.id, session);
3745
+ }
3746
+ }
3747
+ const sorted = Array.from(byId.values()).sort(
3748
+ (a, b) => b.modifiedTime.getTime() - a.modifiedTime.getTime()
3749
+ );
3750
+ if (options.numSessions !== void 0 && options.numSessions >= 0) {
3751
+ return sorted.slice(0, options.numSessions);
3292
3752
  }
3753
+ return sorted;
3293
3754
  }
3294
3755
  export {
3295
3756
  AddMcpServerRequestParamsSchema,
@@ -3321,6 +3782,7 @@ export {
3321
3782
  BaseRequestSchema,
3322
3783
  BaseResponseFailureSchema,
3323
3784
  BaseResponseSuccessSchema,
3785
+ COMPACTION_TIMEOUT,
3324
3786
  CancelMcpAuthRequestParamsSchema,
3325
3787
  CancelMcpAuthRequestSchema,
3326
3788
  CancelMcpAuthResponseSchema,
@@ -3331,8 +3793,14 @@ export {
3331
3793
  ClearMcpAuthResultSchema,
3332
3794
  CliRequestOrNotificationSchema,
3333
3795
  ClientRequestSchema,
3796
+ CompactSessionRequestParamsSchema,
3797
+ CompactSessionRequestSchema,
3798
+ CompactSessionResponseSchema,
3799
+ CompactSessionResultSchema,
3334
3800
  ConnectionError,
3335
3801
  ContentBlockSchema,
3802
+ ContextStatsAccuracy,
3803
+ ContextStatsSchema,
3336
3804
  CreateMessageNotificationSchema,
3337
3805
  CreateToolConfirmationDetailsSchema,
3338
3806
  DEFAULT_REQUEST_TIMEOUT,
@@ -3346,22 +3814,42 @@ export {
3346
3814
  DroidClientMethod,
3347
3815
  DroidErrorType,
3348
3816
  DroidInteractionMode,
3817
+ DroidMessageType,
3349
3818
  DroidServerMethod,
3350
3819
  DroidSession,
3351
3820
  DroidWorkingState,
3352
3821
  DroidWorkingStateChangedNotificationSchema,
3353
3822
  EditToolConfirmationDetailsSchema,
3823
+ EmptyResultSchema,
3354
3824
  ErrorDetailSchema,
3355
3825
  ErrorNotificationSchema,
3826
+ ExecToolInfoSchema,
3827
+ ExecuteRewindRequestParamsSchema,
3828
+ ExecuteRewindRequestSchema,
3829
+ ExecuteRewindResponseSchema,
3830
+ ExecuteRewindResultSchema,
3356
3831
  ExecuteToolConfirmationDetailsSchema,
3357
3832
  ExitSpecModeConfirmationDetailsSchema,
3358
3833
  FACTORY_CLIENT_HEADER,
3359
3834
  FACTORY_CLIENT_VERSION,
3360
3835
  FACTORY_PROTOCOL_VERSION,
3836
+ FactoryDroidMessageRole,
3361
3837
  FactoryDroidMessageSchema,
3362
3838
  FeatureStatus,
3363
3839
  FeatureSuccessState,
3364
3840
  FeatureSuccessStateSchema,
3841
+ ForkSessionRequestParamsSchema,
3842
+ ForkSessionRequestSchema,
3843
+ ForkSessionResponseSchema,
3844
+ ForkSessionResultSchema,
3845
+ GetContextStatsRequestParamsSchema,
3846
+ GetContextStatsRequestSchema,
3847
+ GetContextStatsResponseSchema,
3848
+ GetContextStatsResultSchema,
3849
+ GetRewindInfoRequestParamsSchema,
3850
+ GetRewindInfoRequestSchema,
3851
+ GetRewindInfoResponseSchema,
3852
+ GetRewindInfoResultSchema,
3365
3853
  GitRepoInfoSchema,
3366
3854
  HandoffItemsDismissedEntrySchema,
3367
3855
  HandoffSchema,
@@ -3379,6 +3867,8 @@ export {
3379
3867
  InterruptSessionResultSchema,
3380
3868
  IssueSeverity,
3381
3869
  JSONRPC_VERSION,
3870
+ JsonArraySchema,
3871
+ JsonObjectSchema,
3382
3872
  JsonRpcEnvelopeSchema,
3383
3873
  JsonRpcErrorCode,
3384
3874
  JsonRpcErrorSchema,
@@ -3389,6 +3879,7 @@ export {
3389
3879
  JsonRpcResponseFailureSchema,
3390
3880
  JsonRpcResponseSchema,
3391
3881
  JsonRpcResponseSuccessSchema,
3882
+ JsonValueSchema,
3392
3883
  KillWorkerSessionRequestParamsSchema,
3393
3884
  KillWorkerSessionRequestSchema,
3394
3885
  KillWorkerSessionResponseSchema,
@@ -3410,6 +3901,10 @@ export {
3410
3901
  ListSkillsRequestSchema,
3411
3902
  ListSkillsResponseSchema,
3412
3903
  ListSkillsResultSchema,
3904
+ ListToolsRequestParamsSchema,
3905
+ ListToolsRequestSchema,
3906
+ ListToolsResponseSchema,
3907
+ ListToolsResultSchema,
3413
3908
  LoadSessionRequestParamsSchema,
3414
3909
  LoadSessionRequestSchema,
3415
3910
  LoadSessionResponseSchema,
@@ -3447,6 +3942,8 @@ export {
3447
3942
  MissionWorkerCompletedNotificationSchema,
3448
3943
  MissionWorkerStartedNotificationSchema,
3449
3944
  ModelProvider,
3945
+ OutputFormatSchema,
3946
+ OutputFormatType,
3450
3947
  PermissionResolvedNotificationSchema,
3451
3948
  ProcessExitError,
3452
3949
  ProcessTransport,
@@ -3455,26 +3952,40 @@ export {
3455
3952
  ProposeMissionConfirmationDetailsSchema,
3456
3953
  ProtocolEngine,
3457
3954
  ProtocolError,
3955
+ REWIND_TIMEOUT,
3458
3956
  ReasoningEffort,
3459
3957
  RedactedThinkingBlockSchema,
3460
3958
  RemoveMcpServerRequestParamsSchema,
3461
3959
  RemoveMcpServerRequestSchema,
3462
3960
  RemoveMcpServerResponseSchema,
3463
3961
  RemoveMcpServerResultSchema,
3962
+ RenameSessionRequestParamsSchema,
3963
+ RenameSessionRequestSchema,
3964
+ RenameSessionResponseSchema,
3965
+ RenameSessionResultSchema,
3464
3966
  RequestPermissionRequestParamsSchema,
3465
3967
  RequestPermissionRequestSchema,
3466
3968
  RequestPermissionResponseSchema,
3467
3969
  RequestPermissionResultSchema,
3970
+ RewindEvictedFileSchema,
3971
+ RewindFileCreationSchema,
3972
+ RewindFileSnapshotSchema,
3973
+ SDK_TAG,
3974
+ SDK_VERSION,
3468
3975
  SESSION_INIT_TIMEOUT,
3976
+ SdkMcpServer,
3469
3977
  SessionError,
3978
+ SessionMetadataSchema,
3470
3979
  SessionNotFoundError,
3471
3980
  SessionNotificationParamsSchema,
3472
3981
  SessionNotificationPayloadSchema,
3473
3982
  SessionNotificationSchema,
3474
3983
  SessionNotificationSchemaList,
3475
3984
  SessionNotificationType,
3985
+ SessionSettingsFileSchema,
3476
3986
  SessionSettingsSchema,
3477
3987
  SessionSourceSchema,
3988
+ SessionStartEventSchema,
3478
3989
  SessionTagSchema,
3479
3990
  SessionTitleUpdatedNotificationSchema,
3480
3991
  SessionTokenUsageChangedNotificationSchema,
@@ -3498,6 +4009,7 @@ export {
3498
4009
  SubmitMcpAuthCodeRequestSchema,
3499
4010
  SubmitMcpAuthCodeResponseSchema,
3500
4011
  SubmitMcpAuthCodeResultSchema,
4012
+ SuccessResultSchema,
3501
4013
  TestCaseSchema,
3502
4014
  TestFileSchema,
3503
4015
  TestsSchema,
@@ -3523,6 +4035,7 @@ export {
3523
4035
  ToolProgressUpdateSchema,
3524
4036
  ToolResultBlockSchema,
3525
4037
  ToolResultNotificationSchema,
4038
+ ToolSelectionOverridesSchema,
3526
4039
  ToolUseBlockSchema,
3527
4040
  ToolUseSchema,
3528
4041
  TraceContextMetaSchema,
@@ -3539,8 +4052,12 @@ export {
3539
4052
  WorkerStartedEntrySchema,
3540
4053
  WorkerStateInfoSchema,
3541
4054
  convertNotificationToStreamMessage,
4055
+ createSdkMcpServer,
3542
4056
  createSession,
4057
+ listSessions,
3543
4058
  query,
3544
- resumeSession
4059
+ resumeSession,
4060
+ run,
4061
+ tool
3545
4062
  };
3546
4063
  //# sourceMappingURL=index.js.map