@agentuity/core 2.0.11 → 2.0.12

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 (96) hide show
  1. package/dist/services/api.d.ts +1 -1
  2. package/dist/services/api.d.ts.map +1 -1
  3. package/dist/services/api.js +4 -6
  4. package/dist/services/api.js.map +1 -1
  5. package/dist/services/coder/agents.d.ts +6 -4
  6. package/dist/services/coder/agents.d.ts.map +1 -1
  7. package/dist/services/coder/api-reference.d.ts.map +1 -1
  8. package/dist/services/coder/api-reference.js +78 -10
  9. package/dist/services/coder/api-reference.js.map +1 -1
  10. package/dist/services/coder/client.d.ts +5 -1
  11. package/dist/services/coder/client.d.ts.map +1 -1
  12. package/dist/services/coder/client.js +8 -1
  13. package/dist/services/coder/client.js.map +1 -1
  14. package/dist/services/coder/index.d.ts +2 -2
  15. package/dist/services/coder/index.d.ts.map +1 -1
  16. package/dist/services/coder/index.js +1 -1
  17. package/dist/services/coder/index.js.map +1 -1
  18. package/dist/services/coder/protocol.d.ts +385 -15
  19. package/dist/services/coder/protocol.d.ts.map +1 -1
  20. package/dist/services/coder/protocol.js +148 -2
  21. package/dist/services/coder/protocol.js.map +1 -1
  22. package/dist/services/coder/sessions.d.ts +24 -2
  23. package/dist/services/coder/sessions.d.ts.map +1 -1
  24. package/dist/services/coder/sessions.js +10 -1
  25. package/dist/services/coder/sessions.js.map +1 -1
  26. package/dist/services/coder/sse.d.ts +2 -2
  27. package/dist/services/coder/sse.d.ts.map +1 -1
  28. package/dist/services/coder/sse.js +290 -178
  29. package/dist/services/coder/sse.js.map +1 -1
  30. package/dist/services/coder/types.d.ts +607 -42
  31. package/dist/services/coder/types.d.ts.map +1 -1
  32. package/dist/services/coder/types.js +202 -40
  33. package/dist/services/coder/types.js.map +1 -1
  34. package/dist/services/coder/websocket.d.ts +13 -1
  35. package/dist/services/coder/websocket.d.ts.map +1 -1
  36. package/dist/services/coder/websocket.js +91 -19
  37. package/dist/services/coder/websocket.js.map +1 -1
  38. package/dist/services/sandbox/api-reference.js +7 -7
  39. package/dist/services/sandbox/api-reference.js.map +1 -1
  40. package/dist/services/sandbox/client.d.ts +3 -2
  41. package/dist/services/sandbox/client.d.ts.map +1 -1
  42. package/dist/services/sandbox/client.js.map +1 -1
  43. package/dist/services/sandbox/create.d.ts +5 -0
  44. package/dist/services/sandbox/create.d.ts.map +1 -1
  45. package/dist/services/sandbox/create.js +8 -0
  46. package/dist/services/sandbox/create.js.map +1 -1
  47. package/dist/services/sandbox/get.d.ts +8 -4
  48. package/dist/services/sandbox/get.d.ts.map +1 -1
  49. package/dist/services/sandbox/get.js +28 -3
  50. package/dist/services/sandbox/get.js.map +1 -1
  51. package/dist/services/sandbox/getStatus.d.ts +2 -0
  52. package/dist/services/sandbox/getStatus.d.ts.map +1 -1
  53. package/dist/services/sandbox/getStatus.js +17 -1
  54. package/dist/services/sandbox/getStatus.js.map +1 -1
  55. package/dist/services/sandbox/index.d.ts +1 -1
  56. package/dist/services/sandbox/index.d.ts.map +1 -1
  57. package/dist/services/sandbox/list.d.ts +3 -0
  58. package/dist/services/sandbox/list.d.ts.map +1 -1
  59. package/dist/services/sandbox/list.js +5 -0
  60. package/dist/services/sandbox/list.js.map +1 -1
  61. package/dist/services/sandbox/pause.d.ts +17 -1
  62. package/dist/services/sandbox/pause.d.ts.map +1 -1
  63. package/dist/services/sandbox/pause.js +21 -3
  64. package/dist/services/sandbox/pause.js.map +1 -1
  65. package/dist/services/sandbox/run.d.ts +1 -0
  66. package/dist/services/sandbox/run.d.ts.map +1 -1
  67. package/dist/services/sandbox/run.js +145 -85
  68. package/dist/services/sandbox/run.js.map +1 -1
  69. package/dist/services/sandbox/types.d.ts +8 -2
  70. package/dist/services/sandbox/types.d.ts.map +1 -1
  71. package/dist/services/sandbox/types.js +10 -0
  72. package/dist/services/sandbox/types.js.map +1 -1
  73. package/dist/services/stream/namespaces.d.ts +2 -2
  74. package/dist/services/stream/namespaces.js +2 -2
  75. package/dist/services/stream/namespaces.js.map +1 -1
  76. package/package.json +2 -2
  77. package/src/services/api.ts +6 -7
  78. package/src/services/coder/api-reference.ts +79 -9
  79. package/src/services/coder/client.ts +12 -0
  80. package/src/services/coder/index.ts +3 -0
  81. package/src/services/coder/protocol.ts +166 -2
  82. package/src/services/coder/sessions.ts +26 -0
  83. package/src/services/coder/sse.ts +343 -184
  84. package/src/services/coder/types.ts +257 -44
  85. package/src/services/coder/websocket.ts +120 -21
  86. package/src/services/sandbox/api-reference.ts +7 -7
  87. package/src/services/sandbox/client.ts +4 -4
  88. package/src/services/sandbox/create.ts +10 -0
  89. package/src/services/sandbox/get.ts +32 -3
  90. package/src/services/sandbox/getStatus.ts +20 -1
  91. package/src/services/sandbox/index.ts +1 -1
  92. package/src/services/sandbox/list.ts +5 -0
  93. package/src/services/sandbox/pause.ts +38 -4
  94. package/src/services/sandbox/run.ts +202 -108
  95. package/src/services/sandbox/types.ts +15 -2
  96. package/src/services/stream/namespaces.ts +2 -2
@@ -115,11 +115,11 @@ export const CoderWorkspaceDetailSchema = z
115
115
  repoCount: z.number().describe('Number of repositories'),
116
116
  savedSkillIds: z.array(z.string()).describe('Saved skill IDs in workspace'),
117
117
  skillBucketIds: z.array(z.string()).describe('Skill bucket IDs in workspace'),
118
- agentSlugs: z
118
+ enabledAgents: z
119
119
  .array(z.string())
120
120
  .optional()
121
121
  .default([])
122
- .describe('Published custom agent slugs in workspace'),
122
+ .describe('Effective agent roster stored on the workspace'),
123
123
  selectionCount: z.number().describe('Total number of selections'),
124
124
  createdAt: z.string().describe('Creation timestamp (ISO-8601)'),
125
125
  updatedAt: z.string().describe('Last update timestamp (ISO-8601)'),
@@ -133,7 +133,7 @@ export const CoderCustomAgentThinkingLevelSchema = z
133
133
  .describe('Thinking level override for a custom agent');
134
134
  export type CoderCustomAgentThinkingLevel = z.infer<typeof CoderCustomAgentThinkingLevelSchema>;
135
135
 
136
- export const CODER_CUSTOM_AGENT_PI_TOOLS = [
136
+ export const CODER_CUSTOM_AGENT_TOOLS = [
137
137
  'read',
138
138
  'ls',
139
139
  'find',
@@ -143,17 +143,17 @@ export const CODER_CUSTOM_AGENT_PI_TOOLS = [
143
143
  'edit',
144
144
  ] as const;
145
145
 
146
- export const CoderCustomAgentPiToolSchema = z
147
- .enum(CODER_CUSTOM_AGENT_PI_TOOLS)
146
+ export const CoderCustomAgentToolSchema = z
147
+ .enum(CODER_CUSTOM_AGENT_TOOLS)
148
148
  .describe('Workspace tool available to a standalone custom agent');
149
- export type CoderCustomAgentPiTool = z.infer<typeof CoderCustomAgentPiToolSchema>;
149
+ export type CoderCustomAgentTool = z.infer<typeof CoderCustomAgentToolSchema>;
150
150
 
151
- export const CoderCustomAgentPiToolResponseSchema = z
152
- .union([CoderCustomAgentPiToolSchema, z.string()])
153
- .describe('Pi workspace tool granted to a standalone custom agent');
154
- export type CoderCustomAgentPiToolResponse = z.infer<typeof CoderCustomAgentPiToolResponseSchema>;
151
+ export const CoderCustomAgentToolResponseSchema = z
152
+ .union([CoderCustomAgentToolSchema, z.string()])
153
+ .describe('Workspace tool granted to a standalone custom agent');
154
+ export type CoderCustomAgentToolResponse = z.infer<typeof CoderCustomAgentToolResponseSchema>;
155
155
 
156
- export const CODER_CUSTOM_AGENT_HUB_TOOLS = [
156
+ export const CODER_CUSTOM_AGENT_SERVICE_TOOLS = [
157
157
  'session_dashboard',
158
158
  'memory_service_search',
159
159
  'memory_service_store',
@@ -198,15 +198,17 @@ export const CODER_CUSTOM_AGENT_HUB_TOOLS = [
198
198
  'coord_spawn_workers',
199
199
  ] as const;
200
200
 
201
- export const CoderCustomAgentHubToolSchema = z
202
- .enum(CODER_CUSTOM_AGENT_HUB_TOOLS)
203
- .describe('Hub-managed tool available to a standalone custom agent');
204
- export type CoderCustomAgentHubTool = z.infer<typeof CoderCustomAgentHubToolSchema>;
201
+ export const CoderCustomAgentServiceToolSchema = z
202
+ .enum(CODER_CUSTOM_AGENT_SERVICE_TOOLS)
203
+ .describe('Service tool available to a standalone custom agent');
204
+ export type CoderCustomAgentServiceTool = z.infer<typeof CoderCustomAgentServiceToolSchema>;
205
205
 
206
- export const CoderCustomAgentHubToolResponseSchema = z
207
- .union([CoderCustomAgentHubToolSchema, z.string()])
208
- .describe('Hub-managed tool granted to a standalone custom agent');
209
- export type CoderCustomAgentHubToolResponse = z.infer<typeof CoderCustomAgentHubToolResponseSchema>;
206
+ export const CoderCustomAgentServiceToolResponseSchema = z
207
+ .union([CoderCustomAgentServiceToolSchema, z.string()])
208
+ .describe('Service tool granted to a standalone custom agent');
209
+ export type CoderCustomAgentServiceToolResponse = z.infer<
210
+ typeof CoderCustomAgentServiceToolResponseSchema
211
+ >;
210
212
 
211
213
  export const CoderCustomAgentSnapshotSchema = z
212
214
  .object({
@@ -221,15 +223,19 @@ export const CoderCustomAgentSnapshotSchema = z
221
223
  headlessCompatible: z
222
224
  .boolean()
223
225
  .describe('Whether the custom agent is safe for non-interactive callers'),
224
- piTools: z
225
- .array(CoderCustomAgentPiToolResponseSchema)
226
- .describe('Pi workspace tools granted to the custom agent'),
227
- hubToolNames: z
228
- .array(CoderCustomAgentHubToolResponseSchema)
229
- .describe('Hub-managed tools granted to the custom agent'),
226
+ tools: z
227
+ .array(CoderCustomAgentToolResponseSchema)
228
+ .describe('Workspace tools granted to the custom agent'),
229
+ serviceTools: z
230
+ .array(CoderCustomAgentServiceToolResponseSchema)
231
+ .describe('Service tools granted to the custom agent'),
230
232
  savedSkills: z
231
233
  .array(CoderSkillRefSchema)
232
234
  .describe('Frozen saved-skill refs attached to the custom agent snapshot'),
235
+ companionAgents: z
236
+ .array(z.string())
237
+ .default([])
238
+ .describe('Companion agents auto-included alongside this custom agent'),
233
239
  })
234
240
  .passthrough()
235
241
  .describe('Custom agent snapshot returned by coder hub');
@@ -316,6 +322,20 @@ export const CoderWorkspaceListResponseSchema = z
316
322
  .describe('Response payload for listing workspaces');
317
323
  export type CoderWorkspaceListResponse = z.infer<typeof CoderWorkspaceListResponseSchema>;
318
324
 
325
+ function hasWorkspaceSelections(input: {
326
+ repos?: unknown[];
327
+ savedSkillIds?: unknown[];
328
+ skillBucketIds?: unknown[];
329
+ enabledAgents?: unknown[];
330
+ }): boolean {
331
+ return (
332
+ (input.repos?.length ?? 0) > 0 ||
333
+ (input.savedSkillIds?.length ?? 0) > 0 ||
334
+ (input.skillBucketIds?.length ?? 0) > 0 ||
335
+ (input.enabledAgents?.length ?? 0) > 0
336
+ );
337
+ }
338
+
319
339
  export const CoderCreateWorkspaceRequestSchema = z
320
340
  .object({
321
341
  name: z.string().describe('Workspace name'),
@@ -324,7 +344,13 @@ export const CoderCreateWorkspaceRequestSchema = z
324
344
  repos: z.array(CoderSessionRepositoryRefSchema).optional().describe('Repositories'),
325
345
  savedSkillIds: z.array(z.string()).optional().describe('Saved skill IDs'),
326
346
  skillBucketIds: z.array(z.string()).optional().describe('Skill bucket IDs'),
327
- agentSlugs: z.array(z.string()).optional().describe('Published custom agent slugs'),
347
+ enabledAgents: z
348
+ .array(z.string())
349
+ .optional()
350
+ .describe('Effective agent roster to store on the workspace'),
351
+ })
352
+ .refine(hasWorkspaceSelections, {
353
+ message: 'A workspace needs at least one repo, saved skill, skill bucket, or agent',
328
354
  })
329
355
  .describe('Request body for creating a workspace');
330
356
  export type CoderCreateWorkspaceRequest = z.infer<typeof CoderCreateWorkspaceRequestSchema>;
@@ -343,18 +369,22 @@ export const CoderCreateCustomAgentRequestSchema = z
343
369
  .boolean()
344
370
  .optional()
345
371
  .describe('Whether the custom agent is safe for non-interactive callers'),
346
- piTools: z
347
- .array(CoderCustomAgentPiToolSchema)
372
+ tools: z
373
+ .array(CoderCustomAgentToolSchema)
348
374
  .optional()
349
- .describe('Pi workspace tools to grant to the custom agent'),
350
- hubToolNames: z
351
- .array(CoderCustomAgentHubToolSchema)
375
+ .describe('Workspace tools to grant to the custom agent'),
376
+ serviceTools: z
377
+ .array(CoderCustomAgentServiceToolSchema)
352
378
  .optional()
353
- .describe('Hub-managed tools to grant to the custom agent'),
379
+ .describe('Service tools to grant to the custom agent'),
354
380
  savedSkillIds: z
355
381
  .array(z.string())
356
382
  .optional()
357
383
  .describe('Saved skill row ids to snapshot onto the custom agent'),
384
+ companionAgents: z
385
+ .array(z.string())
386
+ .optional()
387
+ .describe('Agent names to auto-include alongside this custom agent'),
358
388
  })
359
389
  .describe('Request body for creating a custom agent draft');
360
390
  export type CoderCreateCustomAgentRequest = z.infer<typeof CoderCreateCustomAgentRequestSchema>;
@@ -373,18 +403,22 @@ export const CoderUpdateCustomAgentRequestSchema = z
373
403
  .boolean()
374
404
  .optional()
375
405
  .describe('Whether the custom agent is safe for non-interactive callers'),
376
- piTools: z
377
- .array(CoderCustomAgentPiToolSchema)
406
+ tools: z
407
+ .array(CoderCustomAgentToolSchema)
378
408
  .optional()
379
- .describe('Pi workspace tools to grant to the custom agent'),
380
- hubToolNames: z
381
- .array(CoderCustomAgentHubToolSchema)
409
+ .describe('Workspace tools to grant to the custom agent'),
410
+ serviceTools: z
411
+ .array(CoderCustomAgentServiceToolSchema)
382
412
  .optional()
383
- .describe('Hub-managed tools to grant to the custom agent'),
413
+ .describe('Service tools to grant to the custom agent'),
384
414
  savedSkillIds: z
385
415
  .array(z.string())
386
416
  .optional()
387
417
  .describe('Saved skill row ids to snapshot onto the custom agent'),
418
+ companionAgents: z
419
+ .array(z.string())
420
+ .optional()
421
+ .describe('Agent names to auto-include alongside this custom agent'),
388
422
  })
389
423
  .describe('Request body for updating a custom agent draft');
390
424
  export type CoderUpdateCustomAgentRequest = z.infer<typeof CoderUpdateCustomAgentRequestSchema>;
@@ -447,10 +481,10 @@ export const CoderCreateSessionRequestSchema = z
447
481
  workflowMode: CoderWorkflowModeSchema.optional().describe('Workflow execution mode'),
448
482
  loop: CoderSessionLoopConfigSchema.optional().describe('Loop mode settings for the session'),
449
483
  tags: z.array(z.string()).optional().describe('Tags applied to the session for filtering'),
450
- agentSlugs: z
484
+ enabledAgents: z
451
485
  .array(z.string())
452
486
  .optional()
453
- .describe('Published custom agent slugs to include in the session'),
487
+ .describe('Enabled agent roster to include in the session'),
454
488
  savedSkillIds: z
455
489
  .array(z.string())
456
490
  .optional()
@@ -486,6 +520,59 @@ export const CoderCreateSessionRequestSchema = z
486
520
  .describe('Request body for creating a coder session');
487
521
  export type CoderCreateSessionRequest = z.infer<typeof CoderCreateSessionRequestSchema>;
488
522
 
523
+ function inferCoderAgentBuilderSessionMode(input: {
524
+ mode?: 'new' | 'edit' | 'from_session';
525
+ sourceSessionId?: string;
526
+ targetAgentId?: string;
527
+ targetAgentSlug?: string;
528
+ }): 'new' | 'edit' | 'from_session' {
529
+ if (input.mode) return input.mode;
530
+ if (input.sourceSessionId) return 'from_session';
531
+ if (input.targetAgentId || input.targetAgentSlug) return 'edit';
532
+ return 'new';
533
+ }
534
+
535
+ export const CoderCreateAgentBuilderSessionRequestSchema = z
536
+ .object({
537
+ label: z.string().optional().describe('Builder session label override'),
538
+ prompt: z.string().optional().describe('Optional user focus for the builder session kickoff'),
539
+ mode: z
540
+ .enum(['new', 'edit', 'from_session'])
541
+ .optional()
542
+ .describe('Builder launch mode override'),
543
+ visibility: CoderSessionVisibilitySchema.optional().describe('Builder session visibility'),
544
+ sourceSessionId: z
545
+ .string()
546
+ .optional()
547
+ .describe('Source session identifier for build-from-session launches'),
548
+ targetAgentId: z
549
+ .string()
550
+ .optional()
551
+ .describe('Target custom-agent identifier for edit launches'),
552
+ targetAgentSlug: z.string().optional().describe('Target custom-agent slug for edit launches'),
553
+ })
554
+ .superRefine((value, ctx) => {
555
+ const mode = inferCoderAgentBuilderSessionMode(value);
556
+ if (mode === 'from_session' && !value.sourceSessionId?.trim()) {
557
+ ctx.addIssue({
558
+ code: z.ZodIssueCode.custom,
559
+ path: ['sourceSessionId'],
560
+ message: 'sourceSessionId is required for from-session builder launches.',
561
+ });
562
+ }
563
+ if (mode === 'edit' && !value.targetAgentId?.trim() && !value.targetAgentSlug?.trim()) {
564
+ ctx.addIssue({
565
+ code: z.ZodIssueCode.custom,
566
+ path: ['targetAgentId'],
567
+ message: 'targetAgentId or targetAgentSlug is required for edit launches.',
568
+ });
569
+ }
570
+ })
571
+ .describe('Request body for creating an agent-builder session');
572
+ export type CoderCreateAgentBuilderSessionRequest = z.infer<
573
+ typeof CoderCreateAgentBuilderSessionRequestSchema
574
+ >;
575
+
489
576
  export const CoderUpdateSessionRequestSchema = z
490
577
  .object({
491
578
  label: z.string().optional().describe('Updated session label'),
@@ -495,10 +582,10 @@ export const CoderUpdateSessionRequestSchema = z
495
582
  workflowMode: CoderWorkflowModeSchema.optional().describe('Updated workflow mode'),
496
583
  loop: CoderSessionLoopConfigSchema.optional().describe('Updated loop mode configuration'),
497
584
  tags: z.array(z.string()).optional().describe('Updated set of tags for the session'),
498
- agentSlugs: z
585
+ enabledAgents: z
499
586
  .array(z.string())
500
587
  .optional()
501
- .describe('Updated published custom agent slugs included in the session'),
588
+ .describe('Updated enabled agent roster for the session'),
502
589
  skills: z
503
590
  .array(CoderSkillRefSchema)
504
591
  .optional()
@@ -540,6 +627,126 @@ export const CoderSessionWorkspaceSchema = z
540
627
  .describe('Workspace associated with a coder session');
541
628
  export type CoderSessionWorkspace = z.infer<typeof CoderSessionWorkspaceSchema>;
542
629
 
630
+ export const CoderAgentBuilderSessionModeSchema = z
631
+ .enum(['new', 'edit', 'from_session'])
632
+ .describe('Agent-builder launch mode for a builder session');
633
+ export type CoderAgentBuilderSessionMode = z.infer<typeof CoderAgentBuilderSessionModeSchema>;
634
+
635
+ export const CoderAgentBuilderActionKindSchema = z
636
+ .enum(['create_draft', 'update_draft', 'publish'])
637
+ .describe('Durable builder action emitted by an agent-builder session');
638
+ export type CoderAgentBuilderActionKind = z.infer<typeof CoderAgentBuilderActionKindSchema>;
639
+
640
+ export const CoderAgentBuilderSourceSessionSchema = z
641
+ .object({
642
+ sessionId: z.string().describe('Source session identifier linked to the builder session'),
643
+ label: z.string().optional().describe('Source session label when available'),
644
+ })
645
+ .describe('Source session reference used by agent-builder flows');
646
+ export type CoderAgentBuilderSourceSession = z.infer<typeof CoderAgentBuilderSourceSessionSchema>;
647
+
648
+ export const CoderAgentBuilderTargetAgentSchema = z
649
+ .object({
650
+ agentId: z.string().optional().describe('Target custom-agent identifier when editing'),
651
+ slug: z.string().describe('Target custom-agent slug'),
652
+ displayName: z.string().optional().describe('Target custom-agent display name'),
653
+ })
654
+ .describe('Target custom-agent reference for agent-builder edit flows');
655
+ export type CoderAgentBuilderTargetAgent = z.infer<typeof CoderAgentBuilderTargetAgentSchema>;
656
+
657
+ export const CoderAgentBuilderProposalSchema = z
658
+ .object({
659
+ slug: z.string().optional().describe('Proposed custom-agent slug'),
660
+ displayName: z.string().optional().describe('Proposed custom-agent name'),
661
+ description: z.string().optional().describe('Proposed custom-agent description'),
662
+ instructions: z.string().optional().describe('Proposed custom-agent system prompt'),
663
+ model: z.string().optional().describe('Proposed model override'),
664
+ thinkingLevel: CoderCustomAgentThinkingLevelSchema.optional().describe(
665
+ 'Proposed thinking level override'
666
+ ),
667
+ headlessCompatible: z
668
+ .boolean()
669
+ .optional()
670
+ .describe('Whether the proposed agent is safe for non-interactive callers'),
671
+ tools: z
672
+ .array(CoderCustomAgentToolResponseSchema)
673
+ .default([])
674
+ .describe('Proposed workspace tools for the agent'),
675
+ serviceTools: z
676
+ .array(CoderCustomAgentServiceToolResponseSchema)
677
+ .default([])
678
+ .describe('Proposed service tools for the agent'),
679
+ savedSkills: z
680
+ .array(CoderSkillRefSchema)
681
+ .default([])
682
+ .describe('Proposed frozen skill refs to attach'),
683
+ companionAgents: z
684
+ .array(z.string())
685
+ .default([])
686
+ .describe('Proposed companion agents to auto-include'),
687
+ })
688
+ .passthrough()
689
+ .describe('Session-scoped agent-builder proposal state');
690
+ export type CoderAgentBuilderProposal = z.infer<typeof CoderAgentBuilderProposalSchema>;
691
+
692
+ export const CoderAgentBuilderDurableStateSchema = z
693
+ .object({
694
+ draftAgentId: z.string().optional().describe('Linked draft custom-agent identifier'),
695
+ draftAgentSlug: z.string().optional().describe('Linked draft custom-agent slug'),
696
+ lastPublishedVersion: z
697
+ .number()
698
+ .int()
699
+ .optional()
700
+ .describe('Latest published version created through the builder flow'),
701
+ })
702
+ .describe('Durable agent-library state associated with a builder session');
703
+ export type CoderAgentBuilderDurableState = z.infer<typeof CoderAgentBuilderDurableStateSchema>;
704
+
705
+ export const CoderAgentBuilderActionStateSchema = z
706
+ .object({
707
+ kind: CoderAgentBuilderActionKindSchema.describe('Last durable builder action'),
708
+ status: z.enum(['completed', 'failed']).describe('Result of the last durable builder action'),
709
+ occurredAt: z.string().describe('Timestamp of the last durable builder action'),
710
+ message: z.string().optional().describe('Human-readable builder action result summary'),
711
+ agentId: z.string().optional().describe('Affected custom-agent identifier'),
712
+ agentSlug: z.string().optional().describe('Affected custom-agent slug'),
713
+ publishedVersion: z
714
+ .number()
715
+ .int()
716
+ .optional()
717
+ .describe('Published version number when publish succeeded'),
718
+ })
719
+ .describe('Latest durable action emitted by a builder session');
720
+ export type CoderAgentBuilderActionState = z.infer<typeof CoderAgentBuilderActionStateSchema>;
721
+
722
+ export const CoderAgentBuilderSessionSummarySchema = z
723
+ .object({
724
+ mode: CoderAgentBuilderSessionModeSchema.describe('Builder session mode'),
725
+ sourceSession: CoderAgentBuilderSourceSessionSchema.optional().describe(
726
+ 'Linked source session when the builder was launched from an existing session'
727
+ ),
728
+ targetAgent: CoderAgentBuilderTargetAgentSchema.optional().describe(
729
+ 'Target agent baseline when the builder is editing an existing custom agent'
730
+ ),
731
+ durable: CoderAgentBuilderDurableStateSchema.optional().describe(
732
+ 'Linked durable draft/publish state'
733
+ ),
734
+ lastAction: CoderAgentBuilderActionStateSchema.optional().describe(
735
+ 'Most recent durable builder action'
736
+ ),
737
+ })
738
+ .describe('Projected builder-session summary returned in session listings');
739
+ export type CoderAgentBuilderSessionSummary = z.infer<typeof CoderAgentBuilderSessionSummarySchema>;
740
+
741
+ export const CoderAgentBuilderSessionStateSchema = CoderAgentBuilderSessionSummarySchema.extend({
742
+ proposal: CoderAgentBuilderProposalSchema.optional().describe(
743
+ 'Full builder proposal state projected in session detail responses'
744
+ ),
745
+ })
746
+ .passthrough()
747
+ .describe('Full builder-session state returned in session details');
748
+ export type CoderAgentBuilderSessionState = z.infer<typeof CoderAgentBuilderSessionStateSchema>;
749
+
543
750
  export const CoderSessionListItemSchema = z
544
751
  .object({
545
752
  sessionId: z.string().describe('Unique session identifier'),
@@ -580,11 +787,14 @@ export const CoderSessionListItemSchema = z
580
787
  participantCount: z.number().describe('Total number of participants in the session'),
581
788
  tags: z.array(z.string()).describe('Tag values attached to the session'),
582
789
  skills: z.array(CoderSkillRefSchema).describe('Skills attached to the session'),
583
- agentSlugs: z
790
+ enabledAgents: z
584
791
  .array(z.string())
585
792
  .optional()
586
793
  .default([])
587
- .describe('Published custom agent slugs attached to the session'),
794
+ .describe('Enabled agent roster attached to the session'),
795
+ builder: CoderAgentBuilderSessionSummarySchema.optional().describe(
796
+ 'Projected builder-session summary when this session is an agent-builder flow'
797
+ ),
588
798
  defaultAgent: z.string().optional().describe('Default agent assigned to session operations'),
589
799
  bucket: CoderSessionBucketSchema.describe('Derived bucket for session listing'),
590
800
  runtimeAvailable: z.boolean().describe('Whether runtime is currently reachable'),
@@ -616,6 +826,9 @@ export const CoderSessionSchema = CoderSessionListItemSchema.extend({
616
826
  .string()
617
827
  .optional()
618
828
  .describe('Last update timestamp for session metadata (ISO-8601)'),
829
+ builder: CoderAgentBuilderSessionStateSchema.optional().describe(
830
+ 'Full builder-session state when this session is an agent-builder flow'
831
+ ),
619
832
  // These fields are present in list items but may be absent in detail responses
620
833
  lastActivityAt: z.string().optional().describe('Timestamp of most recent activity (ISO-8601)'),
621
834
  taskCount: z.number().optional().describe('Number of tasks associated with the session'),
@@ -70,7 +70,7 @@ import type {
70
70
  ConnectionParams,
71
71
  ServerMessage,
72
72
  } from './protocol.ts';
73
- import { CoderHubInitMessageSchema } from './protocol.ts';
73
+ import { CoderHubInitMessageSchema, parseServerMessage } from './protocol.ts';
74
74
  import { normalizeCoderUrl } from './util.ts';
75
75
 
76
76
  /**
@@ -118,6 +118,11 @@ export const CoderHubWebSocketOptionsSchema = z.object({
118
118
  task: z.string().optional().describe('Initial task for driver mode'),
119
119
  /** Human-readable session label */
120
120
  label: z.string().optional().describe('Session label'),
121
+ /** Observer event filters to request during the initial connection. */
122
+ subscribe: z
123
+ .array(z.string())
124
+ .optional()
125
+ .describe('Observer event filters to request during connection setup'),
121
126
  /** Client origin (web, desktop, tui, sdk) */
122
127
  origin: z.enum(['web', 'desktop', 'tui', 'sdk']).optional().describe('Client origin'),
123
128
  /** Driver mode: 'rpc' for RPC bridge driver */
@@ -198,7 +203,13 @@ export const CoderHubWebSocketError = StructuredError('CoderHubWebSocketError')<
198
203
  | 'response_timeout'
199
204
  | 'invalid_response';
200
205
  sessionId?: string;
206
+ serverCode?: string;
207
+ serverMessage?: string;
208
+ serverMessageType?: 'connection_rejected' | 'protocol_error';
209
+ closeCode?: number;
210
+ closeReason?: string;
201
211
  }>();
212
+ export type CoderHubWebSocketErrorInstance = InstanceType<typeof CoderHubWebSocketError>;
202
213
 
203
214
  interface PendingRequest {
204
215
  resolve: (response: CoderHubResponse) => void;
@@ -270,6 +281,7 @@ export class CoderHubWebSocketClient {
270
281
  parentSessionId: string;
271
282
  task: string;
272
283
  label: string;
284
+ subscribe: string[];
273
285
  origin: 'web' | 'desktop' | 'tui' | 'sdk';
274
286
  driverMode: 'rpc' | undefined;
275
287
  driverInstanceId: string;
@@ -317,6 +329,7 @@ export class CoderHubWebSocketClient {
317
329
  parentSessionId: options.parentSessionId ?? '',
318
330
  task: options.task ?? '',
319
331
  label: options.label ?? '',
332
+ subscribe: options.subscribe ?? [],
320
333
  origin: options.origin ?? 'sdk',
321
334
  driverMode: options.driverMode,
322
335
  driverInstanceId: options.driverInstanceId ?? '',
@@ -522,6 +535,57 @@ export class CoderHubWebSocketClient {
522
535
  return `${Date.now()}-${++this.#messageId}`;
523
536
  }
524
537
 
538
+ #buildHandshakeError(input: {
539
+ code: 'auth_failed' | 'connection_error';
540
+ message: string;
541
+ serverCode?: string;
542
+ serverMessage?: string;
543
+ serverMessageType?: 'connection_rejected' | 'protocol_error';
544
+ closeCode?: number;
545
+ closeReason?: string;
546
+ }): CoderHubWebSocketErrorInstance {
547
+ return new CoderHubWebSocketError({
548
+ code: input.code,
549
+ message: input.message,
550
+ sessionId: this.sessionId,
551
+ serverCode: input.serverCode,
552
+ serverMessage: input.serverMessage,
553
+ serverMessageType: input.serverMessageType,
554
+ closeCode: input.closeCode,
555
+ closeReason: input.closeReason,
556
+ });
557
+ }
558
+
559
+ #markReady(input?: {
560
+ initMessage?: CoderHubInitMessage;
561
+ firstMessage?: ServerMessage;
562
+ sendBootstrapReady?: boolean;
563
+ }): void {
564
+ this.#authenticated = true;
565
+ this.#initMessage = input?.initMessage ?? null;
566
+ this.#sessionId =
567
+ input?.initMessage?.sessionId ??
568
+ (input?.firstMessage && 'sessionId' in input.firstMessage
569
+ ? input.firstMessage.sessionId
570
+ : undefined) ??
571
+ this.#options.sessionId ??
572
+ null;
573
+ this.#reconnectAttempts = 0;
574
+ this.#setState('connected');
575
+ this.#startHeartbeat();
576
+ if (input?.initMessage) {
577
+ this.#options.onInit(input.initMessage);
578
+ }
579
+ if (input?.sendBootstrapReady && this.#ws?.readyState === WebSocket.OPEN) {
580
+ this.#ws.send(JSON.stringify({ type: 'bootstrap_ready' }));
581
+ }
582
+ this.#flushMessageQueue();
583
+ this.#options.onOpen();
584
+ if (input?.firstMessage) {
585
+ this.#options.onMessage(input.firstMessage);
586
+ }
587
+ }
588
+
525
589
  #setState(state: CoderHubWebSocketState): void {
526
590
  if (this.#state !== state) {
527
591
  this.#state = state;
@@ -589,6 +653,8 @@ export class CoderHubWebSocketClient {
589
653
  parent: this.#options.parentSessionId || undefined,
590
654
  task: this.#options.task || undefined,
591
655
  label: this.#options.label || undefined,
656
+ subscribe:
657
+ this.#options.subscribe.length > 0 ? this.#options.subscribe.join(',') : undefined,
592
658
  orgId: this.#options.orgId || undefined,
593
659
  origin: this.#options.origin || undefined,
594
660
  driverMode: this.#options.driverMode || undefined,
@@ -601,6 +667,9 @@ export class CoderHubWebSocketClient {
601
667
  params.set(key, String(value));
602
668
  }
603
669
  }
670
+ if (this.#options.apiKey) {
671
+ params.set('api_key', this.#options.apiKey);
672
+ }
604
673
 
605
674
  const queryString = params.toString();
606
675
  return queryString ? `${wsUrl}?${queryString}` : wsUrl;
@@ -642,12 +711,16 @@ export class CoderHubWebSocketClient {
642
711
  ws.onopen = () => {
643
712
  if (ws !== this.#ws) return;
644
713
  this.#setState('authenticating');
645
- ws.send(
646
- JSON.stringify({
647
- authorization: this.#options.apiKey,
648
- org_id: this.#options.orgId,
649
- })
650
- );
714
+ if (this.#options.apiKey || this.#options.orgId) {
715
+ const bootstrapPayload: { authorization?: string; org_id?: string } = {};
716
+ if (this.#options.apiKey) {
717
+ bootstrapPayload.authorization = this.#options.apiKey;
718
+ }
719
+ if (this.#options.orgId) {
720
+ bootstrapPayload.org_id = this.#options.orgId;
721
+ }
722
+ ws.send(JSON.stringify(bootstrapPayload));
723
+ }
651
724
  };
652
725
 
653
726
  ws.onmessage = (event: MessageEvent) => {
@@ -685,10 +758,12 @@ export class CoderHubWebSocketClient {
685
758
  if (msg.type === 'connection_rejected' || msg.type === 'protocol_error') {
686
759
  this.#setState('closed');
687
760
  this.#options.onError(
688
- new CoderHubWebSocketError({
689
- message: `Connection rejected: ${msg.message ?? msg.code ?? 'Unknown error'}`,
761
+ this.#buildHandshakeError({
690
762
  code: 'auth_failed',
691
- sessionId: this.sessionId,
763
+ message: `Connection rejected: ${msg.message ?? msg.code ?? 'Unknown error'}`,
764
+ serverCode: msg.code,
765
+ serverMessage: msg.message,
766
+ serverMessageType: msg.type,
692
767
  })
693
768
  );
694
769
  this.#intentionallyClosed = true;
@@ -700,15 +775,18 @@ export class CoderHubWebSocketClient {
700
775
  const initResult = CoderHubInitMessageSchema.safeParse(parsed);
701
776
  if (initResult.success) {
702
777
  const initMsg = initResult.data;
703
- this.#authenticated = true;
704
- this.#initMessage = initMsg;
705
- this.#sessionId = initMsg.sessionId ?? this.#options.sessionId ?? null;
706
- this.#reconnectAttempts = 0;
707
- this.#setState('connected');
708
- this.#startHeartbeat();
709
- this.#flushMessageQueue();
710
- this.#options.onInit(initMsg);
711
- this.#options.onOpen();
778
+ this.#markReady({
779
+ initMessage: initMsg,
780
+ sendBootstrapReady: this.#options.role === 'controller',
781
+ });
782
+ return;
783
+ }
784
+
785
+ if (this.#options.role === 'observer') {
786
+ const firstObserverMessage = parseServerMessage(parsed);
787
+ if (firstObserverMessage) {
788
+ this.#markReady({ firstMessage: firstObserverMessage });
789
+ }
712
790
  }
713
791
  return;
714
792
  }
@@ -759,14 +837,31 @@ export class CoderHubWebSocketClient {
759
837
  this.#clearTimers();
760
838
  this.#setState('closed');
761
839
 
840
+ const wasAuthenticated = this.#authenticated;
841
+ const hadTerminalError = this.#intentionallyClosed;
842
+ const terminalClose = isTerminalCloseCode(event.code);
843
+
762
844
  // Clear auth state for clean reconnect
763
845
  this.#authenticated = false;
764
846
  this.#initMessage = null;
765
847
 
766
- if (isTerminalCloseCode(event.code)) {
848
+ if (terminalClose) {
767
849
  this.#intentionallyClosed = true;
768
850
  }
769
851
 
852
+ if (!wasAuthenticated && terminalClose && !hadTerminalError) {
853
+ this.#options.onError(
854
+ this.#buildHandshakeError({
855
+ code: 'connection_error',
856
+ message: `WebSocket closed before connection was ready (code ${event.code})${
857
+ event.reason ? `: ${event.reason}` : ''
858
+ }`,
859
+ closeCode: event.code,
860
+ closeReason: event.reason || undefined,
861
+ })
862
+ );
863
+ }
864
+
770
865
  this.#options.onClose(event.code, event.reason);
771
866
 
772
867
  if (!this.#intentionallyClosed) {
@@ -896,7 +991,11 @@ export async function* subscribeToCoderHub(
896
991
  onError: (error) => {
897
992
  if (
898
993
  error instanceof CoderHubWebSocketError &&
899
- (error.code === 'max_reconnects_exceeded' || error.code === 'auth_failed')
994
+ (error.code === 'max_reconnects_exceeded' ||
995
+ error.code === 'auth_failed' ||
996
+ (error.code === 'connection_error' &&
997
+ typeof error.closeCode === 'number' &&
998
+ isTerminalCloseCode(error.closeCode)))
900
999
  ) {
901
1000
  terminalError = error;
902
1001
  done = true;