@get-bb/plugin-sdk 0.4.30 → 0.4.34

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.
@@ -211,6 +211,7 @@ declare const changedMessageSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{
211
211
  active: "active";
212
212
  error: "error";
213
213
  idle: "idle";
214
+ pending: "pending";
214
215
  provisioning: "provisioning";
215
216
  starting: "starting";
216
217
  stopping: "stopping";
@@ -221,6 +222,7 @@ declare const changedMessageSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{
221
222
  active: "active";
222
223
  error: "error";
223
224
  idle: "idle";
225
+ pending: "pending";
224
226
  starting: "starting";
225
227
  stopping: "stopping";
226
228
  }>;
@@ -639,6 +641,67 @@ declare const pluginPendingInteractionSchema: z$1.ZodObject<{
639
641
  type PluginPendingInteraction = z$1.infer<typeof pluginPendingInteractionSchema>;
640
642
  type PendingInteraction = ProviderPendingInteraction | PluginPendingInteraction;
641
643
 
644
+ declare const providerErrorInfoSchema: z$1.ZodObject<{
645
+ category: z$1.ZodEnum<{
646
+ "active-turn-not-steerable": "active-turn-not-steerable";
647
+ "bad-request": "bad-request";
648
+ "budget-exceeded": "budget-exceeded";
649
+ "connection-failed": "connection-failed";
650
+ "context-window-exceeded": "context-window-exceeded";
651
+ "max-output-tokens": "max-output-tokens";
652
+ "max-turns": "max-turns";
653
+ "rate-limit": "rate-limit";
654
+ "stream-disconnected": "stream-disconnected";
655
+ "structured-output-retries": "structured-output-retries";
656
+ "thread-rollback-failed": "thread-rollback-failed";
657
+ "too-many-failed-attempts": "too-many-failed-attempts";
658
+ billing: "billing";
659
+ internal: "internal";
660
+ overloaded: "overloaded";
661
+ policy: "policy";
662
+ sandbox: "sandbox";
663
+ unauthorized: "unauthorized";
664
+ unknown: "unknown";
665
+ }>;
666
+ httpStatusCode: z$1.ZodNullable<z$1.ZodNumber>;
667
+ providerCode: z$1.ZodNullable<z$1.ZodString>;
668
+ }, z$1.core.$strip>;
669
+ type ProviderErrorInfo = z$1.infer<typeof providerErrorInfoSchema>;
670
+ declare const providerRateLimitStateSchema: z$1.ZodObject<{
671
+ kind: z$1.ZodEnum<{
672
+ "spend-control": "spend-control";
673
+ "subscription-window": "subscription-window";
674
+ credits: "credits";
675
+ unknown: "unknown";
676
+ }>;
677
+ overageReason: z$1.ZodNullable<z$1.ZodString>;
678
+ overageStatus: z$1.ZodNullable<z$1.ZodEnum<{
679
+ allowed: "allowed";
680
+ rejected: "rejected";
681
+ unavailable: "unavailable";
682
+ warning: "warning";
683
+ }>>;
684
+ providerId: z$1.ZodString;
685
+ reachedReason: z$1.ZodNullable<z$1.ZodString>;
686
+ status: z$1.ZodEnum<{
687
+ allowed: "allowed";
688
+ blocked: "blocked";
689
+ unknown: "unknown";
690
+ warning: "warning";
691
+ }>;
692
+ windows: z$1.ZodArray<z$1.ZodObject<{
693
+ label: z$1.ZodNullable<z$1.ZodString>;
694
+ providerKey: z$1.ZodNullable<z$1.ZodString>;
695
+ resetsAtMs: z$1.ZodNullable<z$1.ZodNumber>;
696
+ status: z$1.ZodEnum<{
697
+ allowed: "allowed";
698
+ blocked: "blocked";
699
+ unknown: "unknown";
700
+ warning: "warning";
701
+ }>;
702
+ }, z$1.core.$strip>>;
703
+ }, z$1.core.$strip>;
704
+ type ProviderRateLimitState = z$1.infer<typeof providerRateLimitStateSchema>;
642
705
  declare const threadEventSchema: z$1.ZodPipe<z$1.ZodUnknown, z$1.ZodUnion<readonly [z$1.ZodIntersection<z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{
643
706
  threadId: z$1.ZodString;
644
707
  type: z$1.ZodLiteral<"thread/started">;
@@ -2322,7 +2385,6 @@ declare const threadEventSchema: z$1.ZodPipe<z$1.ZodUnknown, z$1.ZodUnion<readon
2322
2385
  threadId: z$1.ZodString;
2323
2386
  type: z$1.ZodLiteral<"client/thread/start">;
2324
2387
  }, z$1.core.$strip>, z$1.ZodObject<{
2325
- continuationOfRequestId: z$1.ZodOptional<z$1.ZodString>;
2326
2388
  direction: z$1.ZodLiteral<"outbound">;
2327
2389
  execution: z$1.ZodObject<{
2328
2390
  model: z$1.ZodString;
@@ -2529,6 +2591,8 @@ declare const threadEventSchema: z$1.ZodPipe<z$1.ZodUnknown, z$1.ZodUnion<readon
2529
2591
  params: z$1.ZodRecord<z$1.ZodString, z$1.ZodUnknown>;
2530
2592
  }, z$1.core.$strip>;
2531
2593
  requestId: z$1.ZodString;
2594
+ retryAttempt: z$1.ZodOptional<z$1.ZodNumber>;
2595
+ retryOfRequestId: z$1.ZodOptional<z$1.ZodString>;
2532
2596
  senderThreadId: z$1.ZodNullable<z$1.ZodString>;
2533
2597
  source: z$1.ZodEnum<{
2534
2598
  spawn: "spawn";
@@ -2969,6 +3033,18 @@ declare const threadEventSchema: z$1.ZodPipe<z$1.ZodUnknown, z$1.ZodUnion<readon
2969
3033
  type ThreadEvent = z$1.infer<typeof threadEventSchema>;
2970
3034
  type ThreadEventType = ThreadEvent["type"];
2971
3035
 
3036
+ declare const projectSchema: z$1.ZodObject<{
3037
+ createdAt: z$1.ZodNumber;
3038
+ gitRemoteUrl: z$1.ZodNullable<z$1.ZodString>;
3039
+ id: z$1.ZodString;
3040
+ kind: z$1.ZodEnum<{
3041
+ personal: "personal";
3042
+ standard: "standard";
3043
+ }>;
3044
+ name: z$1.ZodString;
3045
+ updatedAt: z$1.ZodNumber;
3046
+ }, z$1.core.$strip>;
3047
+ type Project = z$1.infer<typeof projectSchema>;
2972
3048
  declare const projectSourceSchema: z$1.ZodObject<{
2973
3049
  createdAt: z$1.ZodNumber;
2974
3050
  hostId: z$1.ZodString;
@@ -3085,6 +3161,11 @@ declare const promptInputSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{
3085
3161
  }>>;
3086
3162
  }, z$1.core.$strip>], "type">;
3087
3163
  type PromptInput = z$1.infer<typeof promptInputSchema>;
3164
+ declare const callerExecutionInputSourceSchema: z$1.ZodEnum<{
3165
+ "client-preference": "client-preference";
3166
+ explicit: "explicit";
3167
+ }>;
3168
+ type CallerExecutionInputSource = z$1.infer<typeof callerExecutionInputSourceSchema>;
3088
3169
  declare const resolvedThreadExecutionOptionsSchema: z$1.ZodObject<{
3089
3170
  model: z$1.ZodString;
3090
3171
  permissionMode: z$1.ZodEnum<{
@@ -3139,6 +3220,18 @@ declare const projectExecutionDefaultsSchema: z$1.ZodObject<{
3139
3220
  }, z$1.core.$strip>;
3140
3221
  type ProjectExecutionDefaults = z$1.infer<typeof projectExecutionDefaultsSchema>;
3141
3222
 
3223
+ /**
3224
+ * Who owns a wait, as the denormalized `waitHolder` column stores it.
3225
+ *
3226
+ * This exists only because the orphan sweep and the per-plugin release both
3227
+ * need an indexed equality lookup ("every row this plugin is holding"), which
3228
+ * a JSON `waitingOn` cannot serve. It is written by the same single writer
3229
+ * that writes `waitingOn`, derived from it — never set independently — so the
3230
+ * two cannot drift. Core waits have no holder.
3231
+ */
3232
+ declare const queuedMessageWaitHolderSchema: z$1.ZodTemplateLiteral<`plugin:${string}`>;
3233
+ type QueuedMessageWaitHolder = z$1.infer<typeof queuedMessageWaitHolderSchema>;
3234
+
3142
3235
  declare const PROVIDER_FORK_VALUES: readonly ["none", "tip", "checkpoint"];
3143
3236
  type ProviderFork = (typeof PROVIDER_FORK_VALUES)[number];
3144
3237
 
@@ -3261,6 +3354,7 @@ declare const threadStatusSchema: z$1.ZodEnum<{
3261
3354
  active: "active";
3262
3355
  error: "error";
3263
3356
  idle: "idle";
3357
+ pending: "pending";
3264
3358
  starting: "starting";
3265
3359
  stopping: "stopping";
3266
3360
  }>;
@@ -3364,9 +3458,19 @@ declare const threadQueuedMessageSchema: z$1.ZodObject<{
3364
3458
  }>>;
3365
3459
  }, z$1.core.$strip>], "type">>;
3366
3460
  createdAt: z$1.ZodNumber;
3461
+ editable: z$1.ZodBoolean;
3462
+ failureReason: z$1.ZodNullable<z$1.ZodString>;
3367
3463
  groupWithNext: z$1.ZodBoolean;
3368
3464
  id: z$1.ZodString;
3369
3465
  model: z$1.ZodString;
3466
+ payload: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{
3467
+ kind: z$1.ZodLiteral<"inline">;
3468
+ }, z$1.core.$strip>, z$1.ZodObject<{
3469
+ attempt: z$1.ZodNumber;
3470
+ kind: z$1.ZodLiteral<"retry">;
3471
+ reason: z$1.ZodString;
3472
+ retryOfTurnRequestId: z$1.ZodString;
3473
+ }, z$1.core.$strip>], "kind">;
3370
3474
  permissionMode: z$1.ZodEnum<{
3371
3475
  "accept-edits": "accept-edits";
3372
3476
  auto: "auto";
@@ -3382,11 +3486,31 @@ declare const threadQueuedMessageSchema: z$1.ZodObject<{
3382
3486
  ultracode: "ultracode";
3383
3487
  xhigh: "xhigh";
3384
3488
  }>;
3489
+ sendAt: z$1.ZodNullable<z$1.ZodNumber>;
3385
3490
  serviceTier: z$1.ZodEnum<{
3386
3491
  default: "default";
3387
3492
  fast: "fast";
3388
3493
  }>;
3494
+ threadId: z$1.ZodString;
3389
3495
  updatedAt: z$1.ZodNumber;
3496
+ waitingOn: z$1.ZodNullable<z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{
3497
+ kind: z$1.ZodLiteral<"time">;
3498
+ }, z$1.core.$strip>, z$1.ZodObject<{
3499
+ kind: z$1.ZodLiteral<"thread-busy">;
3500
+ }, z$1.core.$strip>, z$1.ZodObject<{
3501
+ kind: z$1.ZodLiteral<"turn-starting">;
3502
+ }, z$1.core.$strip>, z$1.ZodObject<{
3503
+ kind: z$1.ZodLiteral<"provisioning">;
3504
+ }, z$1.core.$strip>, z$1.ZodObject<{
3505
+ hostName: z$1.ZodString;
3506
+ kind: z$1.ZodLiteral<"host-offline">;
3507
+ }, z$1.core.$strip>, z$1.ZodObject<{
3508
+ kind: z$1.ZodLiteral<"interaction">;
3509
+ }, z$1.core.$strip>, z$1.ZodObject<{
3510
+ kind: z$1.ZodLiteral<"plugin">;
3511
+ pluginId: z$1.ZodString;
3512
+ reason: z$1.ZodString;
3513
+ }, z$1.core.$strip>], "kind">>;
3390
3514
  }, z$1.core.$strip>;
3391
3515
  type ThreadQueuedMessage = z$1.infer<typeof threadQueuedMessageSchema>;
3392
3516
 
@@ -3851,6 +3975,11 @@ declare const projectWithThreadsResponseSchema: z$1.ZodObject<{
3851
3975
  pinnedAt: z$1.ZodNullable<z$1.ZodNumber>;
3852
3976
  projectId: z$1.ZodString;
3853
3977
  providerId: z$1.ZodString;
3978
+ queuedWork: z$1.ZodEnum<{
3979
+ failed: "failed";
3980
+ none: "none";
3981
+ waiting: "waiting";
3982
+ }>;
3854
3983
  runtime: z$1.ZodObject<{
3855
3984
  displayStatus: z$1.ZodEnum<{
3856
3985
  "host-reconnecting": "host-reconnecting";
@@ -3858,6 +3987,7 @@ declare const projectWithThreadsResponseSchema: z$1.ZodObject<{
3858
3987
  active: "active";
3859
3988
  error: "error";
3860
3989
  idle: "idle";
3990
+ pending: "pending";
3861
3991
  provisioning: "provisioning";
3862
3992
  starting: "starting";
3863
3993
  stopping: "stopping";
@@ -3870,6 +4000,7 @@ declare const projectWithThreadsResponseSchema: z$1.ZodObject<{
3870
4000
  active: "active";
3871
4001
  error: "error";
3872
4002
  idle: "idle";
4003
+ pending: "pending";
3873
4004
  starting: "starting";
3874
4005
  stopping: "stopping";
3875
4006
  }>;
@@ -3960,6 +4091,11 @@ declare const sidebarBootstrapResponseSchema: z$1.ZodObject<{
3960
4091
  pinnedAt: z$1.ZodNullable<z$1.ZodNumber>;
3961
4092
  projectId: z$1.ZodString;
3962
4093
  providerId: z$1.ZodString;
4094
+ queuedWork: z$1.ZodEnum<{
4095
+ failed: "failed";
4096
+ none: "none";
4097
+ waiting: "waiting";
4098
+ }>;
3963
4099
  runtime: z$1.ZodObject<{
3964
4100
  displayStatus: z$1.ZodEnum<{
3965
4101
  "host-reconnecting": "host-reconnecting";
@@ -3967,6 +4103,7 @@ declare const sidebarBootstrapResponseSchema: z$1.ZodObject<{
3967
4103
  active: "active";
3968
4104
  error: "error";
3969
4105
  idle: "idle";
4106
+ pending: "pending";
3970
4107
  provisioning: "provisioning";
3971
4108
  starting: "starting";
3972
4109
  stopping: "stopping";
@@ -3979,6 +4116,7 @@ declare const sidebarBootstrapResponseSchema: z$1.ZodObject<{
3979
4116
  active: "active";
3980
4117
  error: "error";
3981
4118
  idle: "idle";
4119
+ pending: "pending";
3982
4120
  starting: "starting";
3983
4121
  stopping: "stopping";
3984
4122
  }>;
@@ -4067,6 +4205,11 @@ declare const sidebarBootstrapResponseSchema: z$1.ZodObject<{
4067
4205
  pinnedAt: z$1.ZodNullable<z$1.ZodNumber>;
4068
4206
  projectId: z$1.ZodString;
4069
4207
  providerId: z$1.ZodString;
4208
+ queuedWork: z$1.ZodEnum<{
4209
+ failed: "failed";
4210
+ none: "none";
4211
+ waiting: "waiting";
4212
+ }>;
4070
4213
  runtime: z$1.ZodObject<{
4071
4214
  displayStatus: z$1.ZodEnum<{
4072
4215
  "host-reconnecting": "host-reconnecting";
@@ -4074,6 +4217,7 @@ declare const sidebarBootstrapResponseSchema: z$1.ZodObject<{
4074
4217
  active: "active";
4075
4218
  error: "error";
4076
4219
  idle: "idle";
4220
+ pending: "pending";
4077
4221
  provisioning: "provisioning";
4078
4222
  starting: "starting";
4079
4223
  stopping: "stopping";
@@ -4086,6 +4230,7 @@ declare const sidebarBootstrapResponseSchema: z$1.ZodObject<{
4086
4230
  active: "active";
4087
4231
  error: "error";
4088
4232
  idle: "idle";
4233
+ pending: "pending";
4089
4234
  starting: "starting";
4090
4235
  stopping: "stopping";
4091
4236
  }>;
@@ -9573,6 +9718,14 @@ interface TimelineTurnRow extends TimelineRowBase {
9573
9718
  type TimelineSourceRow = TimelineConversationRow | TimelineWorkRow | TimelineSystemRow;
9574
9719
  type TimelineRow = TimelineSourceRow | TimelineTurnRow;
9575
9720
 
9721
+ declare const threadCreateOriginSchema: z$1.ZodEnum<{
9722
+ app: "app";
9723
+ cli: "cli";
9724
+ plugin: "plugin";
9725
+ sdk: "sdk";
9726
+ }>;
9727
+ type ThreadCreateOrigin = z$1.infer<typeof threadCreateOriginSchema>;
9728
+ type ExecutionInputFieldSource = CallerExecutionInputSource;
9576
9729
  declare const createExecutionInputSourcesSchema: z$1.ZodObject<{
9577
9730
  model: z$1.ZodOptional<z$1.ZodEnum<{
9578
9731
  "client-preference": "client-preference";
@@ -9596,6 +9749,14 @@ declare const createExecutionInputSourcesSchema: z$1.ZodObject<{
9596
9749
  }>>;
9597
9750
  }, z$1.core.$strict>;
9598
9751
  type CreateExecutionInputSources = z$1.infer<typeof createExecutionInputSourcesSchema>;
9752
+ declare const startedOnBehalfOfSchema: z$1.ZodObject<{
9753
+ initiator: z$1.ZodEnum<{
9754
+ agent: "agent";
9755
+ system: "system";
9756
+ }>;
9757
+ senderThreadId: z$1.ZodString;
9758
+ }, z$1.core.$strip>;
9759
+ type StartedOnBehalfOf = z$1.infer<typeof startedOnBehalfOfSchema>;
9599
9760
  declare const createThreadRequestSchema: z$1.ZodObject<{
9600
9761
  environment: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{
9601
9762
  environmentId: z$1.ZodString;
@@ -9760,6 +9921,7 @@ declare const createThreadRequestSchema: z$1.ZodObject<{
9760
9921
  xhigh: "xhigh";
9761
9922
  }>>;
9762
9923
  sectionId: z$1.ZodOptional<z$1.ZodNullable<z$1.ZodString>>;
9924
+ sendAt: z$1.ZodOptional<z$1.ZodNumber>;
9763
9925
  serviceTier: z$1.ZodOptional<z$1.ZodEnum<{
9764
9926
  default: "default";
9765
9927
  fast: "fast";
@@ -10093,6 +10255,7 @@ declare const sendMessageRequestSchema: z$1.ZodObject<{
10093
10255
  ultracode: "ultracode";
10094
10256
  xhigh: "xhigh";
10095
10257
  }>>;
10258
+ sendAt: z$1.ZodOptional<z$1.ZodNumber>;
10096
10259
  senderThreadId: z$1.ZodOptional<z$1.ZodString>;
10097
10260
  serviceTier: z$1.ZodOptional<z$1.ZodEnum<{
10098
10261
  default: "default";
@@ -10100,14 +10263,38 @@ declare const sendMessageRequestSchema: z$1.ZodObject<{
10100
10263
  }>>;
10101
10264
  }, z$1.core.$strip>;
10102
10265
  type SendMessageRequest = z$1.infer<typeof sendMessageRequestSchema>;
10103
- declare const sendMessageResponseSchema: z$1.ZodObject<{
10104
- delivery: z$1.ZodEnum<{
10105
- deferred: "deferred";
10106
- queued: "queued";
10107
- sent: "sent";
10108
- }>;
10266
+ /**
10267
+ * A discriminated union rather than a flat record with nullable extras: a
10268
+ * `sent` message has no queued row and no wait, and modelling those as "null
10269
+ * for now" would invite every caller to check fields that cannot exist.
10270
+ */
10271
+ declare const sendMessageResponseSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{
10272
+ delivery: z$1.ZodLiteral<"sent">;
10109
10273
  ok: z$1.ZodLiteral<true>;
10110
- }, z$1.core.$strip>;
10274
+ }, z$1.core.$strip>, z$1.ZodObject<{
10275
+ delivery: z$1.ZodLiteral<"queued">;
10276
+ ok: z$1.ZodLiteral<true>;
10277
+ queuedMessageId: z$1.ZodString;
10278
+ sendAt: z$1.ZodNullable<z$1.ZodNumber>;
10279
+ waitingOn: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{
10280
+ kind: z$1.ZodLiteral<"time">;
10281
+ }, z$1.core.$strip>, z$1.ZodObject<{
10282
+ kind: z$1.ZodLiteral<"thread-busy">;
10283
+ }, z$1.core.$strip>, z$1.ZodObject<{
10284
+ kind: z$1.ZodLiteral<"turn-starting">;
10285
+ }, z$1.core.$strip>, z$1.ZodObject<{
10286
+ kind: z$1.ZodLiteral<"provisioning">;
10287
+ }, z$1.core.$strip>, z$1.ZodObject<{
10288
+ hostName: z$1.ZodString;
10289
+ kind: z$1.ZodLiteral<"host-offline">;
10290
+ }, z$1.core.$strip>, z$1.ZodObject<{
10291
+ kind: z$1.ZodLiteral<"interaction">;
10292
+ }, z$1.core.$strip>, z$1.ZodObject<{
10293
+ kind: z$1.ZodLiteral<"plugin">;
10294
+ pluginId: z$1.ZodString;
10295
+ reason: z$1.ZodString;
10296
+ }, z$1.core.$strip>], "kind">;
10297
+ }, z$1.core.$strip>], "delivery">;
10111
10298
  type SendMessageResponse = z$1.infer<typeof sendMessageResponseSchema>;
10112
10299
  declare const editMessageRequestSchema: z$1.ZodObject<{
10113
10300
  executionInputSources: z$1.ZodOptional<z$1.ZodObject<{
@@ -10240,6 +10427,45 @@ declare const editMessageResponseSchema: z$1.ZodObject<{
10240
10427
  requestSequence: z$1.ZodNumber;
10241
10428
  }, z$1.core.$strict>;
10242
10429
  type EditMessageResponse = z$1.infer<typeof editMessageResponseSchema>;
10430
+ /**
10431
+ * What a retry did, mirroring `sendMessageResponseSchema`: a retry is a
10432
+ * dispatch of a turn that already exists, so it is delivered or queued on
10433
+ * exactly the same terms as a send. The two retry-specific facts ride along,
10434
+ * because a caller that let the server pick the turn has no other way to learn
10435
+ * which one it picked.
10436
+ */
10437
+ declare const retryTurnResponseSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{
10438
+ attempt: z$1.ZodNumber;
10439
+ delivery: z$1.ZodLiteral<"sent">;
10440
+ ok: z$1.ZodLiteral<true>;
10441
+ turnRequestId: z$1.ZodString;
10442
+ }, z$1.core.$strip>, z$1.ZodObject<{
10443
+ attempt: z$1.ZodNumber;
10444
+ delivery: z$1.ZodLiteral<"queued">;
10445
+ ok: z$1.ZodLiteral<true>;
10446
+ queuedMessageId: z$1.ZodString;
10447
+ sendAt: z$1.ZodNullable<z$1.ZodNumber>;
10448
+ turnRequestId: z$1.ZodString;
10449
+ waitingOn: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{
10450
+ kind: z$1.ZodLiteral<"time">;
10451
+ }, z$1.core.$strip>, z$1.ZodObject<{
10452
+ kind: z$1.ZodLiteral<"thread-busy">;
10453
+ }, z$1.core.$strip>, z$1.ZodObject<{
10454
+ kind: z$1.ZodLiteral<"turn-starting">;
10455
+ }, z$1.core.$strip>, z$1.ZodObject<{
10456
+ kind: z$1.ZodLiteral<"provisioning">;
10457
+ }, z$1.core.$strip>, z$1.ZodObject<{
10458
+ hostName: z$1.ZodString;
10459
+ kind: z$1.ZodLiteral<"host-offline">;
10460
+ }, z$1.core.$strip>, z$1.ZodObject<{
10461
+ kind: z$1.ZodLiteral<"interaction">;
10462
+ }, z$1.core.$strip>, z$1.ZodObject<{
10463
+ kind: z$1.ZodLiteral<"plugin">;
10464
+ pluginId: z$1.ZodString;
10465
+ reason: z$1.ZodString;
10466
+ }, z$1.core.$strip>], "kind">;
10467
+ }, z$1.core.$strip>], "delivery">;
10468
+ type RetryTurnResponse = z$1.infer<typeof retryTurnResponseSchema>;
10243
10469
  declare const createQueuedMessageRequestSchema: z$1.ZodObject<{
10244
10470
  executionInputSources: z$1.ZodOptional<z$1.ZodObject<{
10245
10471
  model: z$1.ZodOptional<z$1.ZodEnum<{
@@ -10551,9 +10777,19 @@ declare const sendQueuedMessageResponseSchema: z$1.ZodObject<{
10551
10777
  }>>;
10552
10778
  }, z$1.core.$strip>], "type">>;
10553
10779
  createdAt: z$1.ZodNumber;
10780
+ editable: z$1.ZodBoolean;
10781
+ failureReason: z$1.ZodNullable<z$1.ZodString>;
10554
10782
  groupWithNext: z$1.ZodBoolean;
10555
10783
  id: z$1.ZodString;
10556
10784
  model: z$1.ZodString;
10785
+ payload: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{
10786
+ kind: z$1.ZodLiteral<"inline">;
10787
+ }, z$1.core.$strip>, z$1.ZodObject<{
10788
+ attempt: z$1.ZodNumber;
10789
+ kind: z$1.ZodLiteral<"retry">;
10790
+ reason: z$1.ZodString;
10791
+ retryOfTurnRequestId: z$1.ZodString;
10792
+ }, z$1.core.$strip>], "kind">;
10557
10793
  permissionMode: z$1.ZodEnum<{
10558
10794
  "accept-edits": "accept-edits";
10559
10795
  auto: "auto";
@@ -10569,11 +10805,31 @@ declare const sendQueuedMessageResponseSchema: z$1.ZodObject<{
10569
10805
  ultracode: "ultracode";
10570
10806
  xhigh: "xhigh";
10571
10807
  }>;
10808
+ sendAt: z$1.ZodNullable<z$1.ZodNumber>;
10572
10809
  serviceTier: z$1.ZodEnum<{
10573
10810
  default: "default";
10574
10811
  fast: "fast";
10575
10812
  }>;
10813
+ threadId: z$1.ZodString;
10576
10814
  updatedAt: z$1.ZodNumber;
10815
+ waitingOn: z$1.ZodNullable<z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{
10816
+ kind: z$1.ZodLiteral<"time">;
10817
+ }, z$1.core.$strip>, z$1.ZodObject<{
10818
+ kind: z$1.ZodLiteral<"thread-busy">;
10819
+ }, z$1.core.$strip>, z$1.ZodObject<{
10820
+ kind: z$1.ZodLiteral<"turn-starting">;
10821
+ }, z$1.core.$strip>, z$1.ZodObject<{
10822
+ kind: z$1.ZodLiteral<"provisioning">;
10823
+ }, z$1.core.$strip>, z$1.ZodObject<{
10824
+ hostName: z$1.ZodString;
10825
+ kind: z$1.ZodLiteral<"host-offline">;
10826
+ }, z$1.core.$strip>, z$1.ZodObject<{
10827
+ kind: z$1.ZodLiteral<"interaction">;
10828
+ }, z$1.core.$strip>, z$1.ZodObject<{
10829
+ kind: z$1.ZodLiteral<"plugin">;
10830
+ pluginId: z$1.ZodString;
10831
+ reason: z$1.ZodString;
10832
+ }, z$1.core.$strip>], "kind">>;
10577
10833
  }, z$1.core.$strip>;
10578
10834
  }, z$1.core.$strip>;
10579
10835
  type SendQueuedMessageResponse = z$1.infer<typeof sendQueuedMessageResponseSchema>;
@@ -10610,6 +10866,11 @@ declare const threadListResponseSchema: z$1.ZodArray<z$1.ZodObject<{
10610
10866
  pinnedAt: z$1.ZodNullable<z$1.ZodNumber>;
10611
10867
  projectId: z$1.ZodString;
10612
10868
  providerId: z$1.ZodString;
10869
+ queuedWork: z$1.ZodEnum<{
10870
+ failed: "failed";
10871
+ none: "none";
10872
+ waiting: "waiting";
10873
+ }>;
10613
10874
  runtime: z$1.ZodObject<{
10614
10875
  displayStatus: z$1.ZodEnum<{
10615
10876
  "host-reconnecting": "host-reconnecting";
@@ -10617,6 +10878,7 @@ declare const threadListResponseSchema: z$1.ZodArray<z$1.ZodObject<{
10617
10878
  active: "active";
10618
10879
  error: "error";
10619
10880
  idle: "idle";
10881
+ pending: "pending";
10620
10882
  provisioning: "provisioning";
10621
10883
  starting: "starting";
10622
10884
  stopping: "stopping";
@@ -10629,6 +10891,7 @@ declare const threadListResponseSchema: z$1.ZodArray<z$1.ZodObject<{
10629
10891
  active: "active";
10630
10892
  error: "error";
10631
10893
  idle: "idle";
10894
+ pending: "pending";
10632
10895
  starting: "starting";
10633
10896
  stopping: "stopping";
10634
10897
  }>;
@@ -10702,6 +10965,11 @@ declare const threadSearchResponseSchema: z$1.ZodObject<{
10702
10965
  pinnedAt: z$1.ZodNullable<z$1.ZodNumber>;
10703
10966
  projectId: z$1.ZodString;
10704
10967
  providerId: z$1.ZodString;
10968
+ queuedWork: z$1.ZodEnum<{
10969
+ failed: "failed";
10970
+ none: "none";
10971
+ waiting: "waiting";
10972
+ }>;
10705
10973
  runtime: z$1.ZodObject<{
10706
10974
  displayStatus: z$1.ZodEnum<{
10707
10975
  "host-reconnecting": "host-reconnecting";
@@ -10709,6 +10977,7 @@ declare const threadSearchResponseSchema: z$1.ZodObject<{
10709
10977
  active: "active";
10710
10978
  error: "error";
10711
10979
  idle: "idle";
10980
+ pending: "pending";
10712
10981
  provisioning: "provisioning";
10713
10982
  starting: "starting";
10714
10983
  stopping: "stopping";
@@ -10721,6 +10990,7 @@ declare const threadSearchResponseSchema: z$1.ZodObject<{
10721
10990
  active: "active";
10722
10991
  error: "error";
10723
10992
  idle: "idle";
10993
+ pending: "pending";
10724
10994
  starting: "starting";
10725
10995
  stopping: "stopping";
10726
10996
  }>;
@@ -10785,6 +11055,11 @@ declare const threadSearchResponseSchema: z$1.ZodObject<{
10785
11055
  pinnedAt: z$1.ZodNullable<z$1.ZodNumber>;
10786
11056
  projectId: z$1.ZodString;
10787
11057
  providerId: z$1.ZodString;
11058
+ queuedWork: z$1.ZodEnum<{
11059
+ failed: "failed";
11060
+ none: "none";
11061
+ waiting: "waiting";
11062
+ }>;
10788
11063
  runtime: z$1.ZodObject<{
10789
11064
  displayStatus: z$1.ZodEnum<{
10790
11065
  "host-reconnecting": "host-reconnecting";
@@ -10792,6 +11067,7 @@ declare const threadSearchResponseSchema: z$1.ZodObject<{
10792
11067
  active: "active";
10793
11068
  error: "error";
10794
11069
  idle: "idle";
11070
+ pending: "pending";
10795
11071
  provisioning: "provisioning";
10796
11072
  starting: "starting";
10797
11073
  stopping: "stopping";
@@ -10804,6 +11080,7 @@ declare const threadSearchResponseSchema: z$1.ZodObject<{
10804
11080
  active: "active";
10805
11081
  error: "error";
10806
11082
  idle: "idle";
11083
+ pending: "pending";
10807
11084
  starting: "starting";
10808
11085
  stopping: "stopping";
10809
11086
  }>;
@@ -10838,6 +11115,7 @@ declare const threadResponseSchema: z$1.ZodObject<{
10838
11115
  pinnedAt: z$1.ZodNullable<z$1.ZodNumber>;
10839
11116
  projectId: z$1.ZodString;
10840
11117
  providerId: z$1.ZodString;
11118
+ queuedMessageCount: z$1.ZodNumber;
10841
11119
  runtime: z$1.ZodObject<{
10842
11120
  displayStatus: z$1.ZodEnum<{
10843
11121
  "host-reconnecting": "host-reconnecting";
@@ -10845,6 +11123,7 @@ declare const threadResponseSchema: z$1.ZodObject<{
10845
11123
  active: "active";
10846
11124
  error: "error";
10847
11125
  idle: "idle";
11126
+ pending: "pending";
10848
11127
  provisioning: "provisioning";
10849
11128
  starting: "starting";
10850
11129
  stopping: "stopping";
@@ -10857,6 +11136,7 @@ declare const threadResponseSchema: z$1.ZodObject<{
10857
11136
  active: "active";
10858
11137
  error: "error";
10859
11138
  idle: "idle";
11139
+ pending: "pending";
10860
11140
  starting: "starting";
10861
11141
  stopping: "stopping";
10862
11142
  }>;
@@ -10940,6 +11220,7 @@ declare const threadWithIncludesResponseSchema: z$1.ZodObject<{
10940
11220
  pinnedAt: z$1.ZodNullable<z$1.ZodNumber>;
10941
11221
  projectId: z$1.ZodString;
10942
11222
  providerId: z$1.ZodString;
11223
+ queuedMessageCount: z$1.ZodNumber;
10943
11224
  runtime: z$1.ZodObject<{
10944
11225
  displayStatus: z$1.ZodEnum<{
10945
11226
  "host-reconnecting": "host-reconnecting";
@@ -10947,6 +11228,7 @@ declare const threadWithIncludesResponseSchema: z$1.ZodObject<{
10947
11228
  active: "active";
10948
11229
  error: "error";
10949
11230
  idle: "idle";
11231
+ pending: "pending";
10950
11232
  provisioning: "provisioning";
10951
11233
  starting: "starting";
10952
11234
  stopping: "stopping";
@@ -10959,6 +11241,7 @@ declare const threadWithIncludesResponseSchema: z$1.ZodObject<{
10959
11241
  active: "active";
10960
11242
  error: "error";
10961
11243
  idle: "idle";
11244
+ pending: "pending";
10962
11245
  starting: "starting";
10963
11246
  stopping: "stopping";
10964
11247
  }>;
@@ -11301,9 +11584,19 @@ declare const threadQueuedMessageListResponseSchema: z$1.ZodArray<z$1.ZodObject<
11301
11584
  }>>;
11302
11585
  }, z$1.core.$strip>], "type">>;
11303
11586
  createdAt: z$1.ZodNumber;
11587
+ editable: z$1.ZodBoolean;
11588
+ failureReason: z$1.ZodNullable<z$1.ZodString>;
11304
11589
  groupWithNext: z$1.ZodBoolean;
11305
11590
  id: z$1.ZodString;
11306
11591
  model: z$1.ZodString;
11592
+ payload: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{
11593
+ kind: z$1.ZodLiteral<"inline">;
11594
+ }, z$1.core.$strip>, z$1.ZodObject<{
11595
+ attempt: z$1.ZodNumber;
11596
+ kind: z$1.ZodLiteral<"retry">;
11597
+ reason: z$1.ZodString;
11598
+ retryOfTurnRequestId: z$1.ZodString;
11599
+ }, z$1.core.$strip>], "kind">;
11307
11600
  permissionMode: z$1.ZodEnum<{
11308
11601
  "accept-edits": "accept-edits";
11309
11602
  auto: "auto";
@@ -11319,11 +11612,31 @@ declare const threadQueuedMessageListResponseSchema: z$1.ZodArray<z$1.ZodObject<
11319
11612
  ultracode: "ultracode";
11320
11613
  xhigh: "xhigh";
11321
11614
  }>;
11615
+ sendAt: z$1.ZodNullable<z$1.ZodNumber>;
11322
11616
  serviceTier: z$1.ZodEnum<{
11323
11617
  default: "default";
11324
11618
  fast: "fast";
11325
11619
  }>;
11620
+ threadId: z$1.ZodString;
11326
11621
  updatedAt: z$1.ZodNumber;
11622
+ waitingOn: z$1.ZodNullable<z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{
11623
+ kind: z$1.ZodLiteral<"time">;
11624
+ }, z$1.core.$strip>, z$1.ZodObject<{
11625
+ kind: z$1.ZodLiteral<"thread-busy">;
11626
+ }, z$1.core.$strip>, z$1.ZodObject<{
11627
+ kind: z$1.ZodLiteral<"turn-starting">;
11628
+ }, z$1.core.$strip>, z$1.ZodObject<{
11629
+ kind: z$1.ZodLiteral<"provisioning">;
11630
+ }, z$1.core.$strip>, z$1.ZodObject<{
11631
+ hostName: z$1.ZodString;
11632
+ kind: z$1.ZodLiteral<"host-offline">;
11633
+ }, z$1.core.$strip>, z$1.ZodObject<{
11634
+ kind: z$1.ZodLiteral<"interaction">;
11635
+ }, z$1.core.$strip>, z$1.ZodObject<{
11636
+ kind: z$1.ZodLiteral<"plugin">;
11637
+ pluginId: z$1.ZodString;
11638
+ reason: z$1.ZodString;
11639
+ }, z$1.core.$strip>], "kind">>;
11327
11640
  }, z$1.core.$strip>>;
11328
11641
  type ThreadQueuedMessageListResponse = z$1.infer<typeof threadQueuedMessageListResponseSchema>;
11329
11642
  declare const threadChildSummaryResponseSchema: z$1.ZodObject<{
@@ -11427,6 +11740,35 @@ declare const threadListQuerySchema: z$1.ZodObject<{
11427
11740
  }>>;
11428
11741
  }, z$1.core.$strip>;
11429
11742
  type ThreadListQuery = z$1.infer<typeof threadListQuerySchema>;
11743
+ /**
11744
+ * Grouping for `GET /threads/count`. Omitted, the route answers one total.
11745
+ * `host` groups by the host the thread's environment lives on; a thread with
11746
+ * no environment yet counts under the `null` key.
11747
+ */
11748
+ declare const threadCountGroupBySchema: z$1.ZodEnum<{
11749
+ host: "host";
11750
+ project: "project";
11751
+ provider: "provider";
11752
+ }>;
11753
+ type ThreadCountGroupBy = z$1.infer<typeof threadCountGroupBySchema>;
11754
+ /**
11755
+ * `total` is always the count of every matching thread. `groups` is present
11756
+ * exactly when `groupBy` was requested — an ungrouped count has no group list,
11757
+ * rather than one anonymous group.
11758
+ */
11759
+ declare const threadCountResponseSchema: z$1.ZodObject<{
11760
+ groups: z$1.ZodOptional<z$1.ZodArray<z$1.ZodObject<{
11761
+ count: z$1.ZodNumber;
11762
+ key: z$1.ZodNullable<z$1.ZodString>;
11763
+ }, z$1.core.$strip>>>;
11764
+ total: z$1.ZodNumber;
11765
+ }, z$1.core.$strip>;
11766
+ type ThreadCountResponse = z$1.infer<typeof threadCountResponseSchema>;
11767
+ declare const threadRunningResponseSchema: z$1.ZodArray<z$1.ZodObject<{
11768
+ hostId: z$1.ZodNullable<z$1.ZodString>;
11769
+ id: z$1.ZodString;
11770
+ }, z$1.core.$strip>>;
11771
+ type ThreadRunningResponse = z$1.infer<typeof threadRunningResponseSchema>;
11430
11772
  declare const threadSearchQuerySchema: z$1.ZodObject<{
11431
11773
  limitPerGroup: z$1.ZodOptional<z$1.ZodString>;
11432
11774
  query: z$1.ZodString;
@@ -12196,6 +12538,56 @@ interface PluginPendingInteractionProps {
12196
12538
  */
12197
12539
  interface PluginSidebarFooterActionProps {
12198
12540
  }
12541
+ /** Display and accessibility metadata for a host-owned sidebar shortcut. */
12542
+ interface ExperimentalSidebarNavigationShortcut {
12543
+ label: string;
12544
+ ariaKeyShortcuts: string;
12545
+ }
12546
+ /** Host-owned behavior represented by one sidebar navigation item. */
12547
+ type ExperimentalSidebarNavigationAction = {
12548
+ kind: "new-thread";
12549
+ } | {
12550
+ kind: "search-threads";
12551
+ } | {
12552
+ kind: "open-extensions";
12553
+ } | {
12554
+ kind: "open-plugin-panel";
12555
+ pluginId: string;
12556
+ panelId: string;
12557
+ };
12558
+ /** Semantic icon identity for one sidebar navigation item. */
12559
+ type ExperimentalSidebarNavigationIcon = {
12560
+ kind: "host";
12561
+ name: "extensions" | "new-thread" | "search";
12562
+ } | {
12563
+ kind: "plugin";
12564
+ pluginId: string;
12565
+ icon: string | null;
12566
+ };
12567
+ /** One host-owned destination or action a plugin may arrange. */
12568
+ interface ExperimentalSidebarNavigationItem {
12569
+ id: string;
12570
+ label: string;
12571
+ icon: ExperimentalSidebarNavigationIcon;
12572
+ action: ExperimentalSidebarNavigationAction;
12573
+ isDisabled: boolean;
12574
+ shortcut: ExperimentalSidebarNavigationShortcut | null;
12575
+ experimental_splitProps: {
12576
+ onPointerDown?: (event: react.PointerEvent<HTMLElement>) => void;
12577
+ };
12578
+ }
12579
+ /** How the host should activate a sidebar navigation item. */
12580
+ interface ExperimentalSidebarNavigationActivationOptions {
12581
+ openInSplit: boolean;
12582
+ }
12583
+ /** Props passed to an `experimental_sidebarNavigation` component. */
12584
+ interface ExperimentalSidebarNavigationProps {
12585
+ items: readonly ExperimentalSidebarNavigationItem[];
12586
+ activeItemId: string | null;
12587
+ isCompactViewport: boolean;
12588
+ experimental_activate(itemId: string, options: ExperimentalSidebarNavigationActivationOptions): void;
12589
+ experimental_Original: ComponentType;
12590
+ }
12199
12591
  /**
12200
12592
  * Props passed to an `experimental_threadList` component — the sidebar's
12201
12593
  * scrolling thread area, replaced wholesale by one plugin.
@@ -12973,6 +13365,16 @@ interface PluginThreadListRegistration {
12973
13365
  description?: string;
12974
13366
  component: ComponentType<PluginThreadListProps>;
12975
13367
  }
13368
+ /** Replace the bounded navigation controls above the sidebar thread list. */
13369
+ interface ExperimentalSidebarNavigationRegistration {
13370
+ /** Unique within the plugin; letters, digits, `-`, `_`. */
13371
+ id: string;
13372
+ /** Label shown in Settings → Appearance and capability details. */
13373
+ title: string;
13374
+ /** Optional one-line description shown with the provider choice. */
13375
+ description?: string;
13376
+ component: ComponentType<ExperimentalSidebarNavigationProps>;
13377
+ }
12976
13378
  /**
12977
13379
  * Register this plugin as a viewer/editor for file extensions. By default,
12978
13380
  * matching files render the first applicable opener in deterministic slot
@@ -13274,6 +13676,8 @@ interface PluginAppSlots {
13274
13676
  experimental_newThreadPanelAction(registration: PluginNewThreadPanelActionRegistration): void;
13275
13677
  pendingInteraction(registration: PluginPendingInteractionRegistration): void;
13276
13678
  sidebarFooterAction(registration: PluginSidebarFooterActionRegistration): void;
13679
+ /** Replace the bounded sidebar navigation controls. */
13680
+ experimental_sidebarNavigation(registration: ExperimentalSidebarNavigationRegistration): void;
13277
13681
  /**
13278
13682
  * Replace the sidebar's thread list (see
13279
13683
  * {@link PluginThreadListRegistration}). Experimental: see
@@ -13570,6 +13974,51 @@ interface PluginComposerApi {
13570
13974
  insertMention(mention: PluginComposerMention): void;
13571
13975
  /** Focus the composer caret at the end of the draft. */
13572
13976
  focus(): void;
13977
+ /**
13978
+ * Submit this composer's draft through the composer's OWN submit pipeline,
13979
+ * queued until `sendAt` instead of dispatched now.
13980
+ *
13981
+ * This is a real submission, not a plugin-issued send: the host builds the
13982
+ * request exactly as pressing Enter would, so the draft's attachments and
13983
+ * @-mentions, and — in the new-thread composer — the provider, model,
13984
+ * reasoning level, service tier, permission mode and environment the user
13985
+ * has selected on screen, all travel with it. A plugin cannot assemble that
13986
+ * tuple itself, which is why sending from the backend instead would silently
13987
+ * run the message with different settings than the ones in front of the user.
13988
+ *
13989
+ * In a thread composer the message is queued as a row instead of being
13990
+ * sent or queued for the next idle moment. In the new-thread composer the
13991
+ * thread is created `pending` and its first message becomes the queued row.
13992
+ * Either way the resulting row is core's: the queued card above the
13993
+ * composer, the countdown, Send now and Delete all work with no further
13994
+ * plugin involvement.
13995
+ *
13996
+ * Resolves once the host has accepted the submission and cleared the draft.
13997
+ * Rejects when the composer refused to submit — a scope with no submit
13998
+ * pipeline (a queued-message editor, a side chat), an empty draft, or a
13999
+ * composer that is not ready (still loading its execution defaults, missing
14000
+ * an environment). The rejection's message is safe to show to the user.
14001
+ * Failures of the underlying request are reported by bb's own submit error
14002
+ * handling and restore the draft, exactly as an interactive failure does.
14003
+ *
14004
+ * Experimental: see docs/api_to_audit.md.
14005
+ */
14006
+ experimental_submit(options: ExperimentalComposerSubmitOptions): Promise<void>;
14007
+ }
14008
+ /**
14009
+ * What `experimental_submit` does differently from pressing Enter.
14010
+ *
14011
+ * There is deliberately no zero-argument overload and no "submit now" arm: a
14012
+ * plugin that wants a draft sent immediately is asking for the affordance the
14013
+ * user already has, and handing plugins an unconditional "send this draft"
14014
+ * button is a much larger surface than scheduling needs.
14015
+ */
14016
+ interface ExperimentalComposerSubmitOptions {
14017
+ /**
14018
+ * Epoch ms the submission should dispatch at. Must be in the future; the
14019
+ * host does not second-guess how far ahead it is.
14020
+ */
14021
+ sendAt: number;
13573
14022
  }
13574
14023
  /**
13575
14024
  * A consumer-supplied action on the messages of one `ThreadChat` instance,
@@ -13637,7 +14086,13 @@ interface ThreadChatProps {
13637
14086
  */
13638
14087
  messageActions?: readonly ThreadChatMessageAction[];
13639
14088
  }
13640
- /** The controlled execution selection resolved by the picker. */
14089
+ /**
14090
+ * The controlled execution selection resolved by the picker.
14091
+ *
14092
+ * Deliberately a single concrete shape, not a union: this value exists to be
14093
+ * forwarded verbatim to `bb.sdk.threads.spawn`, so it must name a real
14094
+ * provider and model.
14095
+ */
13641
14096
  interface ExperimentalProviderModelPickerValue {
13642
14097
  providerId: string;
13643
14098
  model: string;
@@ -13724,6 +14179,14 @@ interface NewThreadRequest {
13724
14179
  executionInputSources: CreateExecutionInputSources;
13725
14180
  environment: CreateThreadEnvironmentArgs;
13726
14181
  input: PromptInput[];
14182
+ /**
14183
+ * Epoch ms the first turn should dispatch at. Present only when the
14184
+ * submission came from `useComposer().experimental_submit` — a scheduled
14185
+ * create — and absent otherwise, which is what makes an ordinary submission
14186
+ * start work at once. Forward it to `threads.spawn` unchanged: the thread is
14187
+ * created `pending` and its first message is queued as a row until then.
14188
+ */
14189
+ sendAt?: number;
13727
14190
  }
13728
14191
  /**
13729
14192
  * Props of the host-owned `experimental_NewThreadComposer` component — bb's
@@ -14974,6 +15437,26 @@ interface ThreadListArgs {
14974
15437
  interface ThreadSearchArgs extends ThreadSearchQuery {
14975
15438
  signal?: AbortSignal;
14976
15439
  }
15440
+ /**
15441
+ * Counting is a server-side `SELECT count(*)`: a caller that only needs "how
15442
+ * many threads are running on this host" must never page rows through
15443
+ * `threads.list`, which would both cost memory and miscount past its limit.
15444
+ *
15445
+ * Every filter is genuinely absent by default. `parentThreadId` is
15446
+ * three-valued: omitted does not filter on parentage at all, the
15447
+ * `THREAD_COUNT_ROOT_PARENT` sentinel (`"none"`) counts root threads only, and
15448
+ * any other value counts that parent's children. Archived and deleted threads
15449
+ * are excluded by the route.
15450
+ */
15451
+ interface ThreadCountArgs {
15452
+ groupBy?: ThreadCountGroupBy;
15453
+ hostId?: string;
15454
+ parentThreadId?: string;
15455
+ projectId?: string;
15456
+ providerId?: string;
15457
+ signal?: AbortSignal;
15458
+ status?: ThreadStatus;
15459
+ }
14977
15460
  interface ThreadResolveMentionsArgs extends ResolveThreadMentionsRequest {
14978
15461
  signal?: AbortSignal;
14979
15462
  }
@@ -14983,6 +15466,30 @@ interface ThreadGetArgs {
14983
15466
  threadId: string;
14984
15467
  }
14985
15468
  type ThreadGetResult = ThreadResponse | ThreadWithIncludesResponse;
15469
+ type ThreadCountResult = ThreadCountResponse;
15470
+ /**
15471
+ * The threads occupying capacity right now — canonical status `starting` or
15472
+ * `active`, archived and deleted excluded, hidden included (a hidden thread
15473
+ * burns a real slot). Each row is just `id` and `hostId` — the machine whose
15474
+ * pool the thread occupies, from its environment or, before one is attached,
15475
+ * from the start intent it was admitted with; null only when neither names
15476
+ * one. Anything else a policy needs it fetches by id.
15477
+ *
15478
+ * **Exact inside the `message.dispatch` hook, a snapshot everywhere else.**
15479
+ * Hook passes are serialized under one server-wide lock and a cleared first
15480
+ * attempt commits its `pending -> starting` flip before that lock releases, so
15481
+ * a handler reading this sees every admission granted ahead of it in the same
15482
+ * burst — which is what makes "five quick creates against a limit of two" hold
15483
+ * three of them instead of admitting all five. Read from a background service,
15484
+ * a timer or a `turn.failed` listener it is an ordinary query racing with every
15485
+ * concurrent dispatch, exactly like {@link ThreadsArea.count}.
15486
+ *
15487
+ * One boundary: a warm follow-up admitted on an already-live `idle` thread
15488
+ * flips `idle -> active` inside the send transaction, just AFTER the lock
15489
+ * releases. First-dispatch admissions are exact; a burst of follow-ups to
15490
+ * distinct idle threads can momentarily under-report.
15491
+ */
15492
+ type ThreadRunningResult = ThreadRunningResponse;
14986
15493
  type ThreadListResult = ThreadListResponse;
14987
15494
  type ThreadSearchResult = ThreadSearchResponse;
14988
15495
  type ThreadResolveMentionsResult = ResolveThreadMentionsResponse;
@@ -15007,6 +15514,7 @@ type ThreadDeleteResult = {
15007
15514
  ok: true;
15008
15515
  };
15009
15516
  type ThreadSendResult = SendMessageResponse;
15517
+ type ThreadRetryResult = RetryTurnResponse;
15010
15518
  type ThreadEditMessageResult = EditMessageResponse;
15011
15519
  type ThreadStopResult = {
15012
15520
  ok: true;
@@ -15033,6 +15541,7 @@ type ThreadQueuedMessageDeleteResult = {
15033
15541
  type ThreadQueuedMessageReorderResult = ThreadQueuedMessageListResponse;
15034
15542
  type ThreadQueuedMessageSendResult = SendQueuedMessageResponse;
15035
15543
  type ThreadQueuedMessageGroupBoundaryResult = ThreadQueuedMessageListResponse;
15544
+ type ThreadQueueListResult = ThreadQueuedMessageListResponse;
15036
15545
  type ThreadTabsResult = ThreadTabsResponse;
15037
15546
  type ThreadTabsUpdateResult = ThreadTabsResponse;
15038
15547
  type ThreadStorageFilesResult = ThreadStorageFileListResponse;
@@ -15071,6 +15580,22 @@ interface ThreadSendArgs extends SendMessageRequest {
15071
15580
  interface ThreadEditMessageArgs extends EditMessageRequest {
15072
15581
  threadId: string;
15073
15582
  }
15583
+ interface ThreadRetryArgs {
15584
+ threadId: string;
15585
+ /**
15586
+ * The failed turn to re-submit. Omitted means the thread's most recent turn,
15587
+ * which is the one whose failure put it in `error`; naming one asserts which
15588
+ * failure you decided on and fails if the thread has moved on since.
15589
+ */
15590
+ turnRequestId?: string;
15591
+ /**
15592
+ * Epoch ms to retry at. Omitted attempts the retry now — it may still queue
15593
+ * behind a busy thread or a plugin wait, like any other dispatch.
15594
+ */
15595
+ sendAt?: number;
15596
+ /** Why the turn is being retried, shown verbatim on the queued row. */
15597
+ reason?: string;
15598
+ }
15074
15599
  interface ThreadActionArgs {
15075
15600
  threadId: string;
15076
15601
  }
@@ -15104,6 +15629,17 @@ interface ThreadQueuedMessageReorderArgs extends ThreadQueuedMessageTargetArgs,
15104
15629
  interface ThreadQueuedMessageGroupBoundaryArgs extends SetQueuedMessageGroupBoundaryRequest {
15105
15630
  threadId: string;
15106
15631
  }
15632
+ /**
15633
+ * Both filters are genuinely absent by default: no filter lists every live
15634
+ * queued row in the workspace, which is what `bb thread queue list` with no
15635
+ * thread and a limiter plugin's own bookkeeping ask for.
15636
+ */
15637
+ interface ThreadQueueListArgs {
15638
+ /** `plugin:<id>` — every row that plugin is holding the wait on. */
15639
+ waitHolder?: QueuedMessageWaitHolder;
15640
+ signal?: AbortSignal;
15641
+ threadId?: string;
15642
+ }
15107
15643
  interface ThreadStorageFilesArgs extends ThreadStorageFilesQuery {
15108
15644
  signal?: AbortSignal;
15109
15645
  threadId: string;
@@ -15223,6 +15759,18 @@ interface ThreadTabsArea {
15223
15759
  get(args: ThreadStatusArgs): Promise<ThreadTabsResult>;
15224
15760
  update(args: ThreadTabsUpdateArgs): Promise<ThreadTabsUpdateResult>;
15225
15761
  }
15762
+ /**
15763
+ * Queued rows across every thread.
15764
+ *
15765
+ * The per-thread list, send-now, edit, reorder and delete all live on
15766
+ * `queuedMessages`, which is where a row's own operations belong. This area
15767
+ * exists for the one question a thread-scoped list cannot answer: "what is
15768
+ * queued right now, anywhere" — a workspace-wide pending view, or a plugin
15769
+ * recovering the rows it is holding after a restart.
15770
+ */
15771
+ interface ThreadQueueArea {
15772
+ list(args?: ThreadQueueListArgs): Promise<ThreadQueueListResult>;
15773
+ }
15226
15774
  interface ThreadsArea {
15227
15775
  archive(args: ThreadActionArgs): Promise<ThreadArchiveResult>;
15228
15776
  archiveAll(args: ThreadActionArgs): Promise<ThreadArchiveAllResult>;
@@ -15231,14 +15779,19 @@ interface ThreadsArea {
15231
15779
  cancelPlan(args: ThreadActionArgs): Promise<ThreadBannerActionResult>;
15232
15780
  clearGoal(args: ThreadActionArgs): Promise<ThreadBannerActionResult>;
15233
15781
  conversationOutline(args: ThreadStatusArgs): Promise<ThreadConversationOutlineResult>;
15782
+ count(args?: ThreadCountArgs): Promise<ThreadCountResult>;
15234
15783
  defaultExecutionOptions(args: ThreadStatusArgs): Promise<ThreadDefaultExecutionOptionsResult>;
15235
15784
  delete(args: ThreadDeleteArgs): Promise<ThreadDeleteResult>;
15236
15785
  editMessage(args: ThreadEditMessageArgs): Promise<ThreadEditMessageResult>;
15237
15786
  events: ThreadEventsArea;
15238
15787
  fork(args: ThreadForkArgs): Promise<ThreadForkResult>;
15239
15788
  get(args: ThreadGetArgs): Promise<ThreadGetResult>;
15789
+ queue: ThreadQueueArea;
15240
15790
  interactions: ThreadInteractionsArea;
15241
15791
  list(args?: ThreadListArgs): Promise<ThreadListResult>;
15792
+ listRunning(args?: {
15793
+ signal?: AbortSignal;
15794
+ }): Promise<ThreadRunningResult>;
15242
15795
  markRead(args: ThreadActionArgs): Promise<ThreadReadStateResult>;
15243
15796
  markUnread(args: ThreadActionArgs): Promise<ThreadReadStateResult>;
15244
15797
  open(args: ThreadOpenArgs): Promise<ThreadOpenResult>;
@@ -15249,6 +15802,12 @@ interface ThreadsArea {
15249
15802
  queuedMessages: ThreadQueuedMessagesArea;
15250
15803
  reorderPinned(args: ThreadPinOrderArgs): Promise<ThreadPinOrderResult>;
15251
15804
  resolveMentions(args: ThreadResolveMentionsArgs): Promise<ThreadResolveMentionsResult>;
15805
+ /**
15806
+ * Re-submit a failed turn. The retry is an ordinary dispatch attempt, so a
15807
+ * `sendAt` in the future queues it on the clock and a `message.dispatch` hook
15808
+ * can still hold it; the response says which of the two happened.
15809
+ */
15810
+ retry(args: ThreadRetryArgs): Promise<ThreadRetryResult>;
15252
15811
  search(args: ThreadSearchArgs): Promise<ThreadSearchResult>;
15253
15812
  send(args: ThreadSendArgs): Promise<ThreadSendResult>;
15254
15813
  spawn(args: ThreadSpawnArgs): Promise<ThreadSpawnResult>;
@@ -15499,9 +16058,66 @@ interface PluginStorage {
15499
16058
  migrate(db: Database.Database, statements: string[]): void;
15500
16059
  }
15501
16060
  /**
15502
- * Thread lifecycle events a plugin can observe (design §4.5). Observe-only:
15503
- * handlers run fire-and-forget after the transition is applied and can never
15504
- * block or veto it. `thread` is the same public DTO GET /threads/:id serves.
16061
+ * Why a turn failed, assembled by core from the failed turn's own records so a
16062
+ * listener never has to replay the event log to find out.
16063
+ *
16064
+ * Ids and failure facts only. There is no thread DTO and no copy of the
16065
+ * message that failed: a retry re-submits the turn BY REFERENCE
16066
+ * (`bb.sdk.threads.retry`), so the id is the whole of what a policy needs, and
16067
+ * anything else about the thread is one `bb.sdk.threads.get` away and fresher
16068
+ * for being read when it is used.
16069
+ */
16070
+ interface PluginTurnFailedEvent {
16071
+ /** The thread the failed turn ran on. */
16072
+ threadId: string;
16073
+ /**
16074
+ * The failed turn's `client/turn/requested` id — what
16075
+ * `bb.sdk.threads.retry` takes as `turnRequestId`. On a retry's failure this
16076
+ * is the RETRY's id; core walks back to the request the chain started from
16077
+ * when it queues the next attempt.
16078
+ */
16079
+ requestId: string;
16080
+ /** The provider turn, when the failure happened inside one. */
16081
+ turnId: string | null;
16082
+ /**
16083
+ * The failure's structured classification: the provider's own report when
16084
+ * the failure happened inside a turn, or the typed rejection code (a rate
16085
+ * limit, an auth failure) when the provider refused the request at the
16086
+ * door. Null when neither carried one, so a retry policy must handle null
16087
+ * rather than assume.
16088
+ */
16089
+ errorInfo: ProviderErrorInfo | null;
16090
+ /**
16091
+ * Whether the provider accepted the turn's input before failing. True is a
16092
+ * mid-stream failure — the input is already part of the provider's
16093
+ * conversation, so core's retry continues it instead of re-sending the
16094
+ * blocks. False is a request the provider never took, which a retry
16095
+ * re-sends verbatim.
16096
+ */
16097
+ inputAccepted: boolean;
16098
+ /**
16099
+ * The most recent rate-limit snapshot this thread's provider reported, or
16100
+ * null when the provider reports no windows.
16101
+ */
16102
+ rateLimits: ProviderRateLimitState | null;
16103
+ /**
16104
+ * Which attempt just failed: 1 is the original dispatch, 2 the first retry.
16105
+ * A policy caps its own retries by comparing against this.
16106
+ */
16107
+ attemptNumber: number;
16108
+ }
16109
+ /**
16110
+ * Lifecycle events a plugin can observe with `bb.events.on` (design §4.5).
16111
+ *
16112
+ * **Events are announcements core makes.** Something already happened; a
16113
+ * handler is told about it and whatever it returns is IGNORED. Handlers run
16114
+ * fire-and-forget after the change is applied and can never block or veto it.
16115
+ * The surface that *can* is `bb.experimental_hooks`, where core asks a
16116
+ * question and acts on the answer — the same split git draws between its
16117
+ * post-commit and pre-commit hooks.
16118
+ *
16119
+ * `thread` is the same public DTO GET /threads/:id serves and `entry` is the
16120
+ * queued row GET /threads/:id/queued-messages serves.
15505
16121
  */
15506
16122
  interface PluginThreadEventPayloads {
15507
16123
  /** Fired after a thread row is created. */
@@ -15532,9 +16148,252 @@ interface PluginThreadEventPayloads {
15532
16148
  "thread.deleted": {
15533
16149
  thread: ThreadResponse;
15534
16150
  };
16151
+ /**
16152
+ * Fired after a dispatch attempt is queued as a row — by a `message.dispatch`
16153
+ * hook's `wait` decision, by a `sendAt` in the future, or by a core wait (the
16154
+ * thread is busy, its turn is still starting, provisioning, or awaiting an
16155
+ * interaction).
16156
+ *
16157
+ * Every listener sees every queued row, not just the ones it is holding: an
16158
+ * observer that only wants its own filters on
16159
+ * `entry.waitingOn?.kind === "plugin" && entry.waitingOn.pluginId === bb.pluginId`.
16160
+ *
16161
+ * A re-queue fires this again with the new wait, because a row that moved
16162
+ * from one wait to another is news to whoever was waiting on the old one.
16163
+ */
16164
+ "message.queued": {
16165
+ entry: ThreadQueuedMessage;
16166
+ };
16167
+ /**
16168
+ * Fired after a queued row's waits all cleared and it dispatched. The turn
16169
+ * it carried runs after this, so a handler must not assume it has started.
16170
+ */
16171
+ "message.dispatched": {
16172
+ entry: ThreadQueuedMessage;
16173
+ };
16174
+ /**
16175
+ * Fired after a turn failed and the thread has already landed in `error`.
16176
+ *
16177
+ * An announcement, not a question: the failure stands exactly as core
16178
+ * applied it, and a listener that wants another attempt asks for one with
16179
+ * `bb.sdk.threads.retry({ threadId, turnRequestId, sendAt })`. That retry is
16180
+ * an ordinary dispatch attempt, so it still passes the `message.dispatch`
16181
+ * hook — a retry coming back after a rate-limit window respects a limiter
16182
+ * that is at capacity instead of jumping the queue.
16183
+ */
16184
+ "turn.failed": PluginTurnFailedEvent;
15535
16185
  }
15536
16186
  type PluginThreadEventName = keyof PluginThreadEventPayloads;
15537
16187
  type PluginThreadEventHandler<E extends PluginThreadEventName> = (payload: PluginThreadEventPayloads[E]) => void | Promise<void>;
16188
+ /**
16189
+ * What a `message.dispatch` hook answers.
16190
+ *
16191
+ * `proceed` lets the attempt continue. `wait` QUEUES the message as a row
16192
+ * whose `waitingOn` names this plugin and carries `reason` verbatim; the
16193
+ * row stays queued until `sendAt` comes due, capacity frees, the user sends
16194
+ * it now, or the orphan sweep clears it because this plugin is no longer
16195
+ * running. `sendAt` (epoch ms) sets the row's own `sendAt`, so core's due sweep
16196
+ * re-attempts at that instant without the plugin holding a timer of its own —
16197
+ * which is what a rate-limit window wants. `reject` refuses the attempt
16198
+ * outright: `message` is shown to the user verbatim.
16199
+ *
16200
+ * There is deliberately no "handled it myself" answer and no amendment arm —
16201
+ * a hook is a decision, never an owner or an author of the work.
16202
+ */
16203
+ type MessageDispatchHookDecision = {
16204
+ action: "proceed";
16205
+ } | {
16206
+ action: "wait";
16207
+ reason: string;
16208
+ sendAt?: number | null;
16209
+ } | {
16210
+ action: "reject";
16211
+ message: string;
16212
+ };
16213
+ /**
16214
+ * The execution tuple as core resolved it before this hook ran. `model` and
16215
+ * the three option fields are null only when no default has been resolved for
16216
+ * them yet; `providerId` is always resolved.
16217
+ */
16218
+ interface PluginDispatchExecution {
16219
+ providerId: string;
16220
+ model: string | null;
16221
+ reasoningLevel: ReasoningLevel | null;
16222
+ serviceTier: ServiceTier | null;
16223
+ permissionMode: PermissionMode | null;
16224
+ }
16225
+ /**
16226
+ * Where each execution value came from. `explicit` is a user choice,
16227
+ * `client-preference` a remembered client default, and null means core
16228
+ * resolved it from project/provider defaults. A hook that must not act against
16229
+ * a deliberate choice checks for `explicit` here.
16230
+ */
16231
+ interface PluginDispatchExecutionSources {
16232
+ providerId: ExecutionInputFieldSource | null;
16233
+ model: ExecutionInputFieldSource | null;
16234
+ reasoningLevel: ExecutionInputFieldSource | null;
16235
+ serviceTier: ExecutionInputFieldSource | null;
16236
+ permissionMode: ExecutionInputFieldSource | null;
16237
+ }
16238
+ /**
16239
+ * The prompt this dispatch carries. `blocks` is the message itself; `text` is
16240
+ * the concatenated text of its text blocks, which is what a rules-based hook
16241
+ * actually wants to match on.
16242
+ */
16243
+ interface PluginDispatchInput {
16244
+ blocks: readonly PromptInput[];
16245
+ text: string;
16246
+ }
16247
+ /**
16248
+ * How this attempt would reach the provider.
16249
+ *
16250
+ * `start-turn` is a dispatch that begins a turn: a thread's first message, a
16251
+ * plain send to an idle or `pending` thread, or a steer-mode message that
16252
+ * found no running turn to join. `join-turn` is an injection into a turn that
16253
+ * is already executing.
16254
+ *
16255
+ * Decision powers are identical for both — a steer is hooked exactly like a
16256
+ * send, uniformly. A hook that limits concurrency proceeds on `join-turn`: the
16257
+ * thread already holds its slot, so joining it asks for nothing new.
16258
+ */
16259
+ type PluginDispatchAttemptKind = "join-turn" | "start-turn";
16260
+ /**
16261
+ * What core hands a `message.dispatch` hook: the one checkpoint, run before a
16262
+ * message reaches a provider. The exception is a user's explicit Send-now on a
16263
+ * queued row, which bypasses the pass by design — it is the user overriding
16264
+ * policy, and a policy that could veto its own override would not be one.
16265
+ *
16266
+ * It runs identically whether the attempt is inline (someone just sent) or
16267
+ * from a drain (a queued row became eligible again), and whether the message
16268
+ * is a thread's first, a follow-up, a steer, or a retry of a failed turn. A
16269
+ * handler must therefore be idempotent for one logical dispatch: passes re-run
16270
+ * on every drain, on restart, and on retry.
16271
+ */
16272
+ interface MessageDispatchHookContext {
16273
+ /**
16274
+ * The target thread. Never null: thread creation is unhooked — it is a cheap
16275
+ * row — so by the time the first message is decided about, the thread exists
16276
+ * in `pending`, with its provider resolved and nothing provisioned.
16277
+ */
16278
+ thread: ThreadResponse;
16279
+ project: Project;
16280
+ /** Null until an environment is chosen (a queued or not-yet-provisioned thread). */
16281
+ environment: Environment | null;
16282
+ /**
16283
+ * The machine the work will run on. Resolved from the environment when one
16284
+ * is attached, and before that from the start intent the thread was created
16285
+ * with — so a per-host policy counts a cold start against the pool it is
16286
+ * about to occupy. Null only when neither names a machine.
16287
+ */
16288
+ host: Host | null;
16289
+ input: PluginDispatchInput;
16290
+ requestedExecution: PluginDispatchExecution;
16291
+ /** Where each execution value came from. */
16292
+ executionSources: PluginDispatchExecutionSources;
16293
+ /** Whether this attempt starts a turn or joins a running one. */
16294
+ attempt: PluginDispatchAttemptKind;
16295
+ /**
16296
+ * The queued row this attempt is re-trying, or null when the attempt is
16297
+ * inline and no row has ever existed for it.
16298
+ *
16299
+ * This is how a hook tells a fresh send from a re-attempt of something it
16300
+ * already decided about — the replacement for the old
16301
+ * `isReleaseReevaluation`/`hold` pair. A hook that counts in-flight work
16302
+ * should treat the two identically; a hook that logs should not
16303
+ * double-count.
16304
+ */
16305
+ queuedMessage: ThreadQueuedMessage | null;
16306
+ /** How the dispatch was requested; null for internal/core-driven sends. */
16307
+ origin: ThreadCreateOrigin | null;
16308
+ originPluginId: string | null;
16309
+ startedOnBehalfOf: StartedOnBehalfOf | null;
16310
+ parentThreadId: string | null;
16311
+ }
16312
+ /**
16313
+ * The hooks a plugin can answer, each mapping its key to the context core
16314
+ * hands the handler and the decision core acts on. `on()` and the handler type
16315
+ * derive from this map — and so does the server's hook registry — so a
16316
+ * half-added hook does not compile.
16317
+ *
16318
+ * One hook today: `message.dispatch`, THE admission checkpoint, run identically
16319
+ * for a thread's first message, a follow-up, a steer, a retry, and every
16320
+ * re-attempt a drain makes. It replaced the earlier `thread.create` +
16321
+ * `turn.submit` pair, whose split was an accident of where the code happened to
16322
+ * branch rather than a difference a plugin needed to see — the attempt's own
16323
+ * `attempt` kind carries what actually differs.
16324
+ */
16325
+ interface PluginHookSignatures {
16326
+ "message.dispatch": {
16327
+ context: MessageDispatchHookContext;
16328
+ decision: MessageDispatchHookDecision;
16329
+ };
16330
+ }
16331
+ type PluginHookName = keyof PluginHookSignatures;
16332
+ type PluginHookHandler<K extends PluginHookName> = (context: PluginHookSignatures[K]["context"]) => PluginHookSignatures[K]["decision"] | Promise<PluginHookSignatures[K]["decision"]>;
16333
+ interface PluginHooks {
16334
+ /**
16335
+ * Answer a hook.
16336
+ *
16337
+ * **Hooks are questions core asks.** Core stops at a checkpoint, hands the
16338
+ * handler a context, and ACTS ON what it returns — the opposite of
16339
+ * `bb.events`, whose handlers are told what already happened and whose
16340
+ * return value is ignored. It is the same split git draws between its
16341
+ * pre-commit and post-commit hooks, and the reason the two live in separate
16342
+ * namespaces rather than behind one `on`.
16343
+ *
16344
+ * Handlers for a hook run as a deterministic chain in plugin install order,
16345
+ * a `reject` short-circuits the pass, and `wait` decisions are COLLECTED
16346
+ * across the whole pass rather than short-circuiting. The attempt proceeds
16347
+ * only when a pass yields no waits. When several plugins wait, the FIRST owns
16348
+ * the row's `waitingOn` and the rest have their reasons appended to it, so
16349
+ * one decision produces one card rather than one per plugin; each of them
16350
+ * answers again on the next attempt, so nothing is lost by not owning the
16351
+ * row.
16352
+ *
16353
+ * Fail-closed: a handler that throws or exceeds the 10 second decision box
16354
+ * FAILS THE ATTEMPT with this plugin named. Decide in milliseconds — if the
16355
+ * answer needs real work, return `wait` with a `sendAt` and answer again on
16356
+ * the re-attempt.
16357
+ *
16358
+ * The whole pass runs under one server-wide lock, so a counting handler never
16359
+ * races another attempt. It also means a handler that blocks delays every
16360
+ * other attempt, up to the box.
16361
+ *
16362
+ * Passes re-run on every drain, on restart and on retry. A handler must be
16363
+ * idempotent for one logical dispatch.
16364
+ *
16365
+ * At most one handler per hook per plugin; registering a second replaces
16366
+ * nothing and throws.
16367
+ */
16368
+ on<K extends PluginHookName>(hook: K, handler: PluginHookHandler<K>): void;
16369
+ /**
16370
+ * Ask core to re-attempt the messages queued behind plugin waits.
16371
+ *
16372
+ * **The pair to `on`.** `on` answers the question core asks; `recheck`
16373
+ * asks core to ask it again. Core owns the re-draining and the clock — the
16374
+ * `sendAt` due sweep is still core's — and a plugin owns every other
16375
+ * condition its own waits depend on. When that condition changes, say so
16376
+ * here and answer the hook again on the re-attempt; there is no way to
16377
+ * release a specific row, and there does not need to be.
16378
+ *
16379
+ * The walk re-attempts every plugin-queued row IN QUEUE ORDER, each one
16380
+ * claimed exactly once, running the full `message.dispatch` pass over it —
16381
+ * every plugin's handler, not just the caller's. A row that is still blocked
16382
+ * simply re-queues, which is what makes an unwarranted request safe: nobody
16383
+ * has to work out whether their own condition was the last one the message
16384
+ * was waiting on. The existing per-thread re-queue pacing bounds the churn,
16385
+ * so a plugin that stays full is not re-asked in a loop.
16386
+ *
16387
+ * Bursts coalesce: several calls before the walk starts produce one walk.
16388
+ *
16389
+ * **Resolves when the walk is SCHEDULED, not when it finishes.** The walk is
16390
+ * a background pass with no caller to report to — its failures land on the
16391
+ * rows, exactly as the due sweep's do. Awaiting completion would also mean
16392
+ * awaiting a full hook pass from inside whatever called this, which for a
16393
+ * handler holding the evaluation lock could not complete. Fire and forget.
16394
+ */
16395
+ recheck(hook: PluginHookName): Promise<void>;
16396
+ }
15538
16397
  type PluginHttpAuthMode = "local" | "none" | "token";
15539
16398
  type PluginHttpHandler = (context: Context) => Response | Promise<Response>;
15540
16399
  interface PluginHttp {
@@ -16438,8 +17297,18 @@ interface BbPluginApi {
16438
17297
  readonly providers: PluginProviders;
16439
17298
  /** Host-rendered UI contributions (design §4.9). */
16440
17299
  readonly ui: PluginUi;
16441
- /** Additive plugin lifecycle listeners (design §4.5). */
17300
+ /**
17301
+ * Additive plugin lifecycle listeners (design §4.5). Announcements core
17302
+ * makes: a handler's return value is ignored.
17303
+ */
16442
17304
  readonly events: PluginEvents;
17305
+ /**
17306
+ * Questions core asks and acts on the answer to. Today: the dispatch
17307
+ * checkpoint messages pass through on their way to a provider (a user's
17308
+ * Send-now bypasses it by design), which a handler may let go, queue with a
17309
+ * reason, or refuse.
17310
+ */
17311
+ readonly experimental_hooks: PluginHooks;
16443
17312
  /** Plugin-reported status (needs-configuration). */
16444
17313
  readonly status: PluginStatusApi;
16445
17314
  /** Read-only facts about the running server (loopback base URL). */
@@ -16469,4 +17338,4 @@ interface BbPluginApi {
16469
17338
  }
16470
17339
 
16471
17340
  export { PLUGIN_CLI_OUTPUT_MAX_BYTES, defineRpcContract, experimental_defineHostEntry };
16472
- export type { BbContext, BbNavigate, BbPluginApi, CodeOverflowMode, ComposerCustomization, ComposerPlusMenuItem, ComposerRichTextSpec, ComposerStructuredDraft, ComposerView, DiffProps, DiffViewMode, ExperimentalAppPanel, ExperimentalAppPanelSurface, ExperimentalDiffFileContent, ExperimentalDiffFullFileContents, ExperimentalFileLinkProps, ExperimentalFileLocation, ExperimentalFileOpenOptions, ExperimentalFixedTabTargetContract, ExperimentalFixedTabTargetState, ExperimentalHostCallOptions, ExperimentalHostClient, ExperimentalHostEntry, ExperimentalHostPaths, ExperimentalHostRpcContext, ExperimentalHostRpcHandlers, ExperimentalHostSignalContract, ExperimentalHostSignalEvent, ExperimentalHostSignals, ExperimentalHostWatchChange, ExperimentalHostWatchChangeType, ExperimentalHostWatchEvent, ExperimentalHostWatchListener, ExperimentalHostWatchOptions, ExperimentalHostWatchSubscription, ExperimentalHostWorkerLease, ExperimentalLiveFileTarget, ExperimentalOpenFixedTabOptions, ExperimentalPermissionModePickerProps, ExperimentalPluginFixedTabReference, ExperimentalProviderModelPickerProps, ExperimentalProviderModelPickerRouting, ExperimentalProviderModelPickerValue, JsonValue, MarkdownProps, NewThreadComposerProps, NewThreadRequest, PluginAgentConfiguration, PluginAgentConfigurationContext, PluginAgentToolContentPart, PluginAgentToolContext, PluginAgentToolLabels, PluginAgentToolPresentation, PluginAgentToolRegistrationBase, PluginAgentToolResult, PluginAgentToolSelection, PluginAgents, PluginAiServiceDeclaration, PluginAiServiceKind, PluginAiServices, PluginAppBuilder, PluginAppComposer, PluginAppContentScripts, PluginAppDefinition, PluginAppSetup, PluginAppSlots, PluginBackground, PluginCli, PluginCliCommandInfo, PluginCliContext, PluginCliExecutionResult, PluginCliOutputLimitError, PluginCliRegistration, PluginCliResult, PluginCodeThemeData, PluginCodeThemeState, PluginCodeThemeTokenRule, PluginCommandPaletteActionContext, PluginCommandPaletteActionRegistration, PluginComposerApi, PluginComposerMention, PluginComposerScope, PluginComposerTextEffect, PluginComposerThreadRowStatus, PluginContentScriptContext, PluginContentScriptDisposer, PluginContentScriptRegistration, PluginDiffRendererProps, PluginDiffRendererRegistration, PluginEvents, PluginFileOpenerProps, PluginFileOpenerRegistration, PluginFileOpenerSource, PluginFixedTabDeclaration, PluginFixedTabRegistration, PluginHomepageSectionProps, PluginHomepageSectionRegistration, PluginHosts, PluginHttp, PluginHttpAuthMode, PluginHttpHandler, PluginInteractionCancelReason, PluginInteractionRequest, PluginInteractionResult, PluginKvStorage, PluginLogger, PluginMentionItem, PluginMentionProviderRegistration, PluginMentionSearchContext, PluginMentionTrigger, PluginMessageActionContext, PluginMessageActionRegistration, PluginMessageDirectiveMessage, PluginMessageDirectiveOpenWorkspaceFile, PluginMessageDirectiveProps, PluginMessageDirectiveRegistration, PluginNavPanelProps, PluginNavPanelRegistration, PluginNewThreadPanelActionContext, PluginNewThreadPanelActionRegistration, PluginNewThreadPanelProps, PluginPanelActionOpenOptions, PluginPendingInteractionProps, PluginPendingInteractionRegistration, PluginPendingInteractionView, PluginProviderCapabilities, PluginProviderComposerAction, PluginProviderDeclaration, PluginProviderExtensionKindDeclaration, PluginProviderFallbackModel, PluginProviderIconRegistration, PluginProviderMaintenance, PluginProviderModelCatalogScope, PluginProviderNativeRootEntry, PluginProviderNativeRoots, PluginProviderOptionDescriptor, PluginProviderOptionsContext, PluginProviderPermissionMode, PluginProviderReasoningLevel, PluginProviderStrings, PluginProviders, PluginProvidersState, PluginRealtime, PluginRealtimeConnectionState, PluginRpc, PluginRpcCallArgs, PluginRpcClient, PluginRpcContract, PluginRpcError, PluginRpcErrorCode, PluginRpcHandlers, PluginRpcIssuePathSegment, PluginRpcMethodContract, PluginRpcResult, PluginRpcValidationIssue, PluginSdkApp, PluginServerApi, PluginSettingDescriptor, PluginSettingDescriptors, PluginSettingValue, PluginSettings, PluginSettingsHandle, PluginSettingsSectionProps, PluginSettingsSectionRegistration, PluginSettingsState, PluginSettingsValues, PluginSharedPortTunnelIdentity, PluginSidebarFooterActionContext, PluginSidebarFooterActionProps, PluginSidebarFooterActionRegistration, PluginSidebarProject, PluginSidebarPullRequest, PluginSidebarSplitPane, PluginSidebarThread, PluginSidebarThreadActions, PluginSidebarThreadActivity, PluginSidebarThreadIndicator, PluginSidebarThreadPullRequestState, PluginSidebarThreadSplit, PluginSidebarThreadsState, PluginSidebarWorkspaceKind, PluginSourceCodeRendererProps, PluginSourceCodeRendererRegistration, PluginStatusApi, PluginStorage, PluginTargetedPanelActionOpenOptions, PluginThreadEventHandler, PluginThreadEventName, PluginThreadEventPayloads, PluginThreadHeaderActionProps, PluginThreadHeaderActionRegistration, PluginThreadListProps, PluginThreadListRegistration, PluginThreadPanelActionContext, PluginThreadPanelActionRegistration, PluginThreadPanelProps, PluginTimelineRendererProps, PluginTimelineRendererRegistration, PluginTimelineRendererRow, PluginTimelineRowPresentation, PluginTimelineRowStatus, PluginUi, SourceCodeLineRange, SourceCodeProps, StandardSchemaV1, StandardSchemaV1InferInput, StandardSchemaV1InferOutput, StandardSchemaV1Issue, StandardSchemaV1Result, ThreadChatMessageAction, ThreadChatMessageReference, ThreadChatProps, UrlLinkProps };
17341
+ export type { BbContext, BbNavigate, BbPluginApi, CodeOverflowMode, ComposerCustomization, ComposerPlusMenuItem, ComposerRichTextSpec, ComposerStructuredDraft, ComposerView, DiffProps, DiffViewMode, ExperimentalAppPanel, ExperimentalAppPanelSurface, ExperimentalComposerSubmitOptions, ExperimentalDiffFileContent, ExperimentalDiffFullFileContents, ExperimentalFileLinkProps, ExperimentalFileLocation, ExperimentalFileOpenOptions, ExperimentalFixedTabTargetContract, ExperimentalFixedTabTargetState, ExperimentalHostCallOptions, ExperimentalHostClient, ExperimentalHostEntry, ExperimentalHostPaths, ExperimentalHostRpcContext, ExperimentalHostRpcHandlers, ExperimentalHostSignalContract, ExperimentalHostSignalEvent, ExperimentalHostSignals, ExperimentalHostWatchChange, ExperimentalHostWatchChangeType, ExperimentalHostWatchEvent, ExperimentalHostWatchListener, ExperimentalHostWatchOptions, ExperimentalHostWatchSubscription, ExperimentalHostWorkerLease, ExperimentalLiveFileTarget, ExperimentalOpenFixedTabOptions, ExperimentalPermissionModePickerProps, ExperimentalPluginFixedTabReference, ExperimentalProviderModelPickerProps, ExperimentalProviderModelPickerRouting, ExperimentalProviderModelPickerValue, ExperimentalSidebarNavigationAction, ExperimentalSidebarNavigationActivationOptions, ExperimentalSidebarNavigationIcon, ExperimentalSidebarNavigationItem, ExperimentalSidebarNavigationProps, ExperimentalSidebarNavigationRegistration, ExperimentalSidebarNavigationShortcut, JsonValue, MarkdownProps, MessageDispatchHookContext, MessageDispatchHookDecision, NewThreadComposerProps, NewThreadRequest, PluginAgentConfiguration, PluginAgentConfigurationContext, PluginAgentToolContentPart, PluginAgentToolContext, PluginAgentToolLabels, PluginAgentToolPresentation, PluginAgentToolRegistrationBase, PluginAgentToolResult, PluginAgentToolSelection, PluginAgents, PluginAiServiceDeclaration, PluginAiServiceKind, PluginAiServices, PluginAppBuilder, PluginAppComposer, PluginAppContentScripts, PluginAppDefinition, PluginAppSetup, PluginAppSlots, PluginBackground, PluginCli, PluginCliCommandInfo, PluginCliContext, PluginCliExecutionResult, PluginCliOutputLimitError, PluginCliRegistration, PluginCliResult, PluginCodeThemeData, PluginCodeThemeState, PluginCodeThemeTokenRule, PluginCommandPaletteActionContext, PluginCommandPaletteActionRegistration, PluginComposerApi, PluginComposerMention, PluginComposerScope, PluginComposerTextEffect, PluginComposerThreadRowStatus, PluginContentScriptContext, PluginContentScriptDisposer, PluginContentScriptRegistration, PluginDiffRendererProps, PluginDiffRendererRegistration, PluginDispatchAttemptKind, PluginDispatchExecution, PluginDispatchExecutionSources, PluginDispatchInput, PluginEvents, PluginFileOpenerProps, PluginFileOpenerRegistration, PluginFileOpenerSource, PluginFixedTabDeclaration, PluginFixedTabRegistration, PluginHomepageSectionProps, PluginHomepageSectionRegistration, PluginHookHandler, PluginHookName, PluginHookSignatures, PluginHooks, PluginHosts, PluginHttp, PluginHttpAuthMode, PluginHttpHandler, PluginInteractionCancelReason, PluginInteractionRequest, PluginInteractionResult, PluginKvStorage, PluginLogger, PluginMentionItem, PluginMentionProviderRegistration, PluginMentionSearchContext, PluginMentionTrigger, PluginMessageActionContext, PluginMessageActionRegistration, PluginMessageDirectiveMessage, PluginMessageDirectiveOpenWorkspaceFile, PluginMessageDirectiveProps, PluginMessageDirectiveRegistration, PluginNavPanelProps, PluginNavPanelRegistration, PluginNewThreadPanelActionContext, PluginNewThreadPanelActionRegistration, PluginNewThreadPanelProps, PluginPanelActionOpenOptions, PluginPendingInteractionProps, PluginPendingInteractionRegistration, PluginPendingInteractionView, PluginProviderCapabilities, PluginProviderComposerAction, PluginProviderDeclaration, PluginProviderExtensionKindDeclaration, PluginProviderFallbackModel, PluginProviderIconRegistration, PluginProviderMaintenance, PluginProviderModelCatalogScope, PluginProviderNativeRootEntry, PluginProviderNativeRoots, PluginProviderOptionDescriptor, PluginProviderOptionsContext, PluginProviderPermissionMode, PluginProviderReasoningLevel, PluginProviderStrings, PluginProviders, PluginProvidersState, PluginRealtime, PluginRealtimeConnectionState, PluginRpc, PluginRpcCallArgs, PluginRpcClient, PluginRpcContract, PluginRpcError, PluginRpcErrorCode, PluginRpcHandlers, PluginRpcIssuePathSegment, PluginRpcMethodContract, PluginRpcResult, PluginRpcValidationIssue, PluginSdkApp, PluginServerApi, PluginSettingDescriptor, PluginSettingDescriptors, PluginSettingValue, PluginSettings, PluginSettingsHandle, PluginSettingsSectionProps, PluginSettingsSectionRegistration, PluginSettingsState, PluginSettingsValues, PluginSharedPortTunnelIdentity, PluginSidebarFooterActionContext, PluginSidebarFooterActionProps, PluginSidebarFooterActionRegistration, PluginSidebarProject, PluginSidebarPullRequest, PluginSidebarSplitPane, PluginSidebarThread, PluginSidebarThreadActions, PluginSidebarThreadActivity, PluginSidebarThreadIndicator, PluginSidebarThreadPullRequestState, PluginSidebarThreadSplit, PluginSidebarThreadsState, PluginSidebarWorkspaceKind, PluginSourceCodeRendererProps, PluginSourceCodeRendererRegistration, PluginStatusApi, PluginStorage, PluginTargetedPanelActionOpenOptions, PluginThreadEventHandler, PluginThreadEventName, PluginThreadEventPayloads, PluginThreadHeaderActionProps, PluginThreadHeaderActionRegistration, PluginThreadListProps, PluginThreadListRegistration, PluginThreadPanelActionContext, PluginThreadPanelActionRegistration, PluginThreadPanelProps, PluginTimelineRendererProps, PluginTimelineRendererRegistration, PluginTimelineRendererRow, PluginTimelineRowPresentation, PluginTimelineRowStatus, PluginTurnFailedEvent, PluginUi, SourceCodeLineRange, SourceCodeProps, StandardSchemaV1, StandardSchemaV1InferInput, StandardSchemaV1InferOutput, StandardSchemaV1Issue, StandardSchemaV1Result, ThreadChatMessageAction, ThreadChatMessageReference, ThreadChatProps, UrlLinkProps };