@get-bb/plugin-sdk 0.4.10 → 0.4.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.
@@ -181,6 +181,80 @@ declare const promptInputSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
181
181
  }, z.core.$strip>], "type">;
182
182
  type PromptInput = z.infer<typeof promptInputSchema>;
183
183
 
184
+ declare const providerInfoSchema: z.ZodObject<{
185
+ available: z.ZodBoolean;
186
+ capabilities: z.ZodObject<{
187
+ permissionModes: z.ZodArray<z.ZodEnum<{
188
+ "accept-edits": "accept-edits";
189
+ auto: "auto";
190
+ full: "full";
191
+ }>>;
192
+ supportsFork: z.ZodBoolean;
193
+ supportsNativeUserQuestion: z.ZodBoolean;
194
+ supportsServiceTier: z.ZodBoolean;
195
+ supportsSessionRewind: z.ZodBoolean;
196
+ supportsThreadArchive: z.ZodBoolean;
197
+ supportsThreadRename: z.ZodBoolean;
198
+ }, z.core.$strip>;
199
+ composerActions: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
200
+ kind: z.ZodLiteral<"skills">;
201
+ trigger: z.ZodEnum<{
202
+ "/": "/";
203
+ }>;
204
+ }, z.core.$strip>, z.ZodObject<{
205
+ command: z.ZodObject<{
206
+ name: z.ZodString;
207
+ trailingText: z.ZodString;
208
+ trigger: z.ZodEnum<{
209
+ "/": "/";
210
+ }>;
211
+ }, z.core.$strip>;
212
+ kind: z.ZodLiteral<"plan">;
213
+ }, z.core.$strip>, z.ZodObject<{
214
+ command: z.ZodObject<{
215
+ name: z.ZodString;
216
+ trailingText: z.ZodString;
217
+ trigger: z.ZodEnum<{
218
+ "/": "/";
219
+ }>;
220
+ }, z.core.$strip>;
221
+ kind: z.ZodLiteral<"goal">;
222
+ }, z.core.$strip>], "kind">>;
223
+ displayName: z.ZodString;
224
+ experimental_providerHealth: z.ZodBoolean;
225
+ experimental_providerInstallation: z.ZodBoolean;
226
+ experimental_providerUsage: z.ZodBoolean;
227
+ extensionKinds: z.ZodOptional<z.ZodRecord<z.ZodString & z.ZodType<`${string}/${string}`, string, z.core.$ZodTypeInternals<`${string}/${string}`, string>>, z.ZodObject<{
228
+ item: z.ZodBoolean;
229
+ state: z.ZodBoolean;
230
+ }, z.core.$strip>>>;
231
+ family: z.ZodOptional<z.ZodString>;
232
+ id: z.ZodString;
233
+ logoUrl: z.ZodNullable<z.ZodString>;
234
+ reasoningLevels: z.ZodOptional<z.ZodArray<z.ZodObject<{
235
+ description: z.ZodOptional<z.ZodString>;
236
+ id: z.ZodString;
237
+ label: z.ZodString;
238
+ }, z.core.$strip>>>;
239
+ serviceTiers: z.ZodOptional<z.ZodArray<z.ZodObject<{
240
+ description: z.ZodOptional<z.ZodString>;
241
+ id: z.ZodString;
242
+ label: z.ZodString;
243
+ }, z.core.$strip>>>;
244
+ strings: z.ZodOptional<z.ZodObject<{
245
+ brandPrefix: z.ZodOptional<z.ZodString>;
246
+ expiredHint: z.ZodString;
247
+ iconTint: z.ZodOptional<z.ZodObject<{
248
+ dark: z.ZodString;
249
+ light: z.ZodString;
250
+ }, z.core.$strip>>;
251
+ installUrl: z.ZodString;
252
+ planModeCopy: z.ZodOptional<z.ZodString>;
253
+ signInHint: z.ZodString;
254
+ }, z.core.$strip>>;
255
+ }, z.core.$strip>;
256
+ type ProviderInfo = z.infer<typeof providerInfoSchema>;
257
+
184
258
  declare const createThreadEnvironmentArgsSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
185
259
  environmentId: z.ZodString;
186
260
  type: z.ZodLiteral<"reuse">;
@@ -405,6 +479,18 @@ interface SourceCodeLineRange {
405
479
  start: number;
406
480
  end: number;
407
481
  }
482
+ /** One complete text side of a diff, resolved by the caller. */
483
+ interface ExperimentalDiffFileContent {
484
+ /** File path for this side. May differ between `old` and `new` for a rename. */
485
+ path: string;
486
+ /** Complete UTF-8 file contents, including unchanged lines outside the patch. */
487
+ content: string;
488
+ }
489
+ /** Complete text contents for both sides of a diff. */
490
+ interface ExperimentalDiffFullFileContents {
491
+ old: ExperimentalDiffFileContent;
492
+ new: ExperimentalDiffFileContent;
493
+ }
408
494
  /**
409
495
  * Props of the host-owned `experimental_SourceCode` component — BB's source
410
496
  * viewer. The host owns syntax highlighting, gutters, wrapping, line-selection
@@ -430,8 +516,9 @@ interface SourceCodeProps {
430
516
  * Props of the host-owned `experimental_Diff` component — BB's diff viewer.
431
517
  * The host owns patch normalization (a patch without a `diff --git` header is
432
518
  * completed from `path`), syntax highlighting, unified/split presentation,
433
- * gutters, line-selection presentation, and the live BB code theme. Content
434
- * that cannot be parsed as a patch degrades to plain monospace text.
519
+ * gutters, line-selection presentation, optional full-file context expansion,
520
+ * and the live BB code theme. Content that cannot be parsed as a patch
521
+ * degrades to plain monospace text.
435
522
  */
436
523
  interface DiffProps {
437
524
  /** Unified patch text for exactly ONE file. */
@@ -448,6 +535,12 @@ interface DiffProps {
448
535
  overflow?: CodeOverflowMode;
449
536
  /** Whether the gutter shows line numbers. Defaults to `true`. */
450
537
  showLineNumbers?: boolean;
538
+ /**
539
+ * Complete text for both file sides. When present and consistent with the
540
+ * patch, BB enables expand-context controls between hunks. The caller owns
541
+ * loading these contents; omit the field to render from the patch alone.
542
+ */
543
+ experimental_fullFileContents?: ExperimentalDiffFullFileContents;
451
544
  /** Applied to the renderer's root element. */
452
545
  className?: string;
453
546
  }
@@ -470,7 +563,8 @@ interface PluginSourceCodeRendererProps {
470
563
  }
471
564
  /**
472
565
  * Props passed to an `experimental_diffRenderer` component. `patch` is always
473
- * a complete single-file unified patch, whatever shape the caller supplied.
566
+ * a complete single-file unified patch, whatever shape the caller supplied,
567
+ * and optional full-file context is resolved to an object or `null`.
474
568
  */
475
569
  interface PluginDiffRendererProps {
476
570
  patch: string;
@@ -478,6 +572,14 @@ interface PluginDiffRendererProps {
478
572
  view: DiffViewMode;
479
573
  overflow: CodeOverflowMode;
480
574
  showLineNumbers: boolean;
575
+ /**
576
+ * Caller-resolved text for both sides, or `null` when the caller supplied
577
+ * only the patch. A replacement can use this to implement context expansion,
578
+ * but must verify that the paths and hunk lines agree with `patch` before
579
+ * treating the contents as complete. BB's original renderer performs that
580
+ * verification when it mounts.
581
+ */
582
+ experimental_fullFileContents: ExperimentalDiffFullFileContents | null;
481
583
  /**
482
584
  * BB's diff renderer, bound to this request. Render it to delegate
483
585
  * conditionally without re-entering plugin replacement resolution.
@@ -787,7 +889,8 @@ interface PluginSidebarThread {
787
889
  originKind: "fork" | null;
788
890
  /** The plugin that spawned it, or null for non-plugin origins. */
789
891
  originPluginId: string | null;
790
- /** The agent provider this thread runs on, e.g. "codex", "claude-code". */
892
+ /** The agent provider this thread runs on; resolve it through
893
+ * {@link PluginSdkApp.experimental_useProviders} for a name and icon. */
791
894
  providerId: string;
792
895
  /** The agent is blocked on the user: an approval or a question. */
793
896
  hasPendingInteraction: boolean;
@@ -857,6 +960,17 @@ interface PluginSidebarThreadsState {
857
960
  threads: readonly PluginSidebarThread[];
858
961
  projects: readonly PluginSidebarProject[];
859
962
  }
963
+ /**
964
+ * The provider directory (see {@link PluginSdkApp.experimental_useProviders}):
965
+ * every registered agent provider in picker order, as the same `ProviderInfo`
966
+ * the host's own pickers read. `logoUrl` is server-relative
967
+ * (`/api/v1/system/providers/<id>/logo`) or null when the provider declared a
968
+ * glyph or no icon; `strings` carries the provider's declared copy.
969
+ */
970
+ interface PluginProvidersState {
971
+ status: "error" | "loading" | "ready";
972
+ providers: readonly ProviderInfo[];
973
+ }
860
974
  /**
861
975
  * Act on threads from a plugin surface. Every method routes to the host's own
862
976
  * flow, so optimistic updates, toasts, dialogs, pane closing, and route repair
@@ -1844,6 +1958,13 @@ interface PluginSdkApp {
1844
1958
  * Experimental: see docs/api_to_audit.md.
1845
1959
  */
1846
1960
  experimental_useSidebarThreadSplit(threadId: string): PluginSidebarThreadSplit;
1961
+ /**
1962
+ * The provider directory (see {@link PluginProvidersState}). Reads the
1963
+ * host's own cached provider roster, so a plugin that shows a thread's
1964
+ * provider never re-vendors provider names, icons, or copy. Experimental:
1965
+ * see docs/api_to_audit.md.
1966
+ */
1967
+ experimental_useProviders(): PluginProvidersState;
1847
1968
  /**
1848
1969
  * The host-owned chat component (see {@link ThreadChatProps}). Together
1849
1970
  * with `Markdown`, the only components the SDK ships — everything else
@@ -1877,8 +1998,9 @@ interface PluginSdkApp {
1877
1998
  experimental_SourceCode: ComponentType<SourceCodeProps>;
1878
1999
  /**
1879
2000
  * The host-owned diff viewer (see {@link DiffProps}). Renders supplied patch
1880
- * content with BB's normalization, syntax highlighting, unified/split
1881
- * presentation, and live code theme, and honours an active
2001
+ * content with BB's normalization, optional full-file context expansion,
2002
+ * syntax highlighting, unified/split presentation, and live code theme, and
2003
+ * honours an active
1882
2004
  * `experimental_diffRenderer` replacement. Experimental: see
1883
2005
  * docs/api_to_audit.md.
1884
2006
  */
@@ -1908,6 +2030,7 @@ declare const experimental_useSidebarThreads: () => PluginSidebarThreadsState;
1908
2030
  declare const experimental_useSidebarThreadActions: () => PluginSidebarThreadActions;
1909
2031
  declare const experimental_useSidebarThreadPullRequest: (threadId: string) => PluginSidebarThreadPullRequestState;
1910
2032
  declare const experimental_useSidebarThreadSplit: (threadId: string) => PluginSidebarThreadSplit;
2033
+ declare const experimental_useProviders: () => PluginProvidersState;
1911
2034
 
1912
- export { Markdown, ThreadChat, definePluginApp, experimental_Diff, experimental_FileLink, experimental_NewThreadComposer, experimental_SourceCode, experimental_UrlLink, experimental_useAppPanel, experimental_useFixedTabTarget, experimental_useSidebarThreadActions, experimental_useSidebarThreadPullRequest, experimental_useSidebarThreadSplit, experimental_useSidebarThreads, useBbContext, useBbNavigate, useComposer, useComposerView, useRealtime, useRealtimeConnectionState, useRpc, useSettings };
1913
- export type { BbContext, BbNavigate, CodeOverflowMode, ComposerCustomization, ComposerPlusMenuItem, ComposerRichTextSpec, ComposerStructuredDraft, ComposerView, DiffProps, DiffViewMode, ExperimentalAppPanel, ExperimentalAppPanelSurface, ExperimentalFileLinkProps, ExperimentalFileLocation, ExperimentalFileOpenOptions, ExperimentalFixedTabTargetContract, ExperimentalFixedTabTargetState, ExperimentalLiveFileTarget, ExperimentalOpenFixedTabOptions, ExperimentalPluginFixedTabDeclaration, ExperimentalPluginFixedTabReference, ExperimentalPluginFixedTabRegistration, ExperimentalUrlLinkProps, JsonValue, MarkdownProps, NewThreadComposerProps, NewThreadRequest, PluginAppBuilder, PluginAppComposer, PluginAppContentScripts, PluginAppDefinition, PluginAppSetup, PluginAppSlots, PluginComposerApi, PluginComposerMention, PluginComposerScope, PluginComposerTextEffect, PluginComposerThreadRowStatus, PluginContentScriptContext, PluginContentScriptDisposer, PluginContentScriptRegistration, PluginDiffRendererProps, PluginDiffRendererRegistration, PluginFileOpenerProps, PluginFileOpenerRegistration, PluginFileOpenerSource, PluginHomepageSectionProps, PluginHomepageSectionRegistration, PluginMessageActionContext, PluginMessageActionRegistration, PluginMessageDirectiveMessage, PluginMessageDirectiveOpenWorkspaceFile, PluginMessageDirectiveProps, PluginMessageDirectiveRegistration, PluginNavPanelProps, PluginNavPanelRegistration, PluginNewThreadPanelActionContext, PluginNewThreadPanelActionRegistration, PluginNewThreadPanelProps, PluginPanelActionOpenOptions, PluginPendingInteractionProps, PluginPendingInteractionRegistration, PluginPendingInteractionView, PluginProviderIconRegistration, PluginRealtimeConnectionState, PluginRpcCallArgs, PluginRpcClient, PluginRpcContract, PluginRpcError, PluginRpcErrorCode, PluginRpcHandlers, PluginRpcIssuePathSegment, PluginRpcMethodContract, PluginRpcResult, PluginRpcValidationIssue, PluginSdkApp, PluginSettingsSectionProps, PluginSettingsSectionRegistration, PluginSettingsState, PluginSidebarFooterActionContext, PluginSidebarFooterActionProps, PluginSidebarFooterActionRegistration, PluginSidebarProject, PluginSidebarPullRequest, PluginSidebarSplitPane, PluginSidebarThread, PluginSidebarThreadActions, PluginSidebarThreadActivity, PluginSidebarThreadIndicator, PluginSidebarThreadPullRequestState, PluginSidebarThreadSplit, PluginSidebarThreadsState, PluginSidebarWorkspaceKind, PluginSourceCodeRendererProps, PluginSourceCodeRendererRegistration, PluginTargetedPanelActionOpenOptions, PluginThreadHeaderActionProps, PluginThreadHeaderActionRegistration, PluginThreadListProps, PluginThreadListRegistration, PluginThreadPanelActionContext, PluginThreadPanelActionRegistration, PluginThreadPanelProps, SourceCodeLineRange, SourceCodeProps, StandardSchemaV1, StandardSchemaV1InferInput, StandardSchemaV1InferOutput, StandardSchemaV1Issue, StandardSchemaV1Result, ThreadChatMessageAction, ThreadChatMessageReference, ThreadChatProps };
2035
+ export { Markdown, ThreadChat, definePluginApp, experimental_Diff, experimental_FileLink, experimental_NewThreadComposer, experimental_SourceCode, experimental_UrlLink, experimental_useAppPanel, experimental_useFixedTabTarget, experimental_useProviders, experimental_useSidebarThreadActions, experimental_useSidebarThreadPullRequest, experimental_useSidebarThreadSplit, experimental_useSidebarThreads, useBbContext, useBbNavigate, useComposer, useComposerView, useRealtime, useRealtimeConnectionState, useRpc, useSettings };
2036
+ export type { BbContext, BbNavigate, CodeOverflowMode, ComposerCustomization, ComposerPlusMenuItem, ComposerRichTextSpec, ComposerStructuredDraft, ComposerView, DiffProps, DiffViewMode, ExperimentalAppPanel, ExperimentalAppPanelSurface, ExperimentalDiffFileContent, ExperimentalDiffFullFileContents, ExperimentalFileLinkProps, ExperimentalFileLocation, ExperimentalFileOpenOptions, ExperimentalFixedTabTargetContract, ExperimentalFixedTabTargetState, ExperimentalLiveFileTarget, ExperimentalOpenFixedTabOptions, ExperimentalPluginFixedTabDeclaration, ExperimentalPluginFixedTabReference, ExperimentalPluginFixedTabRegistration, ExperimentalUrlLinkProps, JsonValue, MarkdownProps, NewThreadComposerProps, NewThreadRequest, PluginAppBuilder, PluginAppComposer, PluginAppContentScripts, PluginAppDefinition, PluginAppSetup, PluginAppSlots, PluginComposerApi, PluginComposerMention, PluginComposerScope, PluginComposerTextEffect, PluginComposerThreadRowStatus, PluginContentScriptContext, PluginContentScriptDisposer, PluginContentScriptRegistration, PluginDiffRendererProps, PluginDiffRendererRegistration, PluginFileOpenerProps, PluginFileOpenerRegistration, PluginFileOpenerSource, PluginHomepageSectionProps, PluginHomepageSectionRegistration, PluginMessageActionContext, PluginMessageActionRegistration, PluginMessageDirectiveMessage, PluginMessageDirectiveOpenWorkspaceFile, PluginMessageDirectiveProps, PluginMessageDirectiveRegistration, PluginNavPanelProps, PluginNavPanelRegistration, PluginNewThreadPanelActionContext, PluginNewThreadPanelActionRegistration, PluginNewThreadPanelProps, PluginPanelActionOpenOptions, PluginPendingInteractionProps, PluginPendingInteractionRegistration, PluginPendingInteractionView, PluginProviderIconRegistration, PluginProvidersState, PluginRealtimeConnectionState, PluginRpcCallArgs, PluginRpcClient, PluginRpcContract, PluginRpcError, PluginRpcErrorCode, PluginRpcHandlers, PluginRpcIssuePathSegment, PluginRpcMethodContract, PluginRpcResult, PluginRpcValidationIssue, PluginSdkApp, PluginSettingsSectionProps, PluginSettingsSectionRegistration, PluginSettingsState, PluginSidebarFooterActionContext, PluginSidebarFooterActionProps, PluginSidebarFooterActionRegistration, PluginSidebarProject, PluginSidebarPullRequest, PluginSidebarSplitPane, PluginSidebarThread, PluginSidebarThreadActions, PluginSidebarThreadActivity, PluginSidebarThreadIndicator, PluginSidebarThreadPullRequestState, PluginSidebarThreadSplit, PluginSidebarThreadsState, PluginSidebarWorkspaceKind, PluginSourceCodeRendererProps, PluginSourceCodeRendererRegistration, PluginTargetedPanelActionOpenOptions, PluginThreadHeaderActionProps, PluginThreadHeaderActionRegistration, PluginThreadListProps, PluginThreadListRegistration, PluginThreadPanelActionContext, PluginThreadPanelActionRegistration, PluginThreadPanelProps, SourceCodeLineRange, SourceCodeProps, StandardSchemaV1, StandardSchemaV1InferInput, StandardSchemaV1InferOutput, StandardSchemaV1Issue, StandardSchemaV1Result, ThreadChatMessageAction, ThreadChatMessageReference, ThreadChatProps };
@@ -19,7 +19,7 @@ declare const RESERVED_BB_CLI_COMMANDS: readonly string[];
19
19
  /**
20
20
  * How completely a provider can clone one of its sessions — the single
21
21
  * vocabulary shared by the provider declaration
22
- * (`bb.agents.experimental_registerProvider`), the server→daemon
22
+ * (`bb.providers.register`), the server→daemon
23
23
  * `bridgeLaunch`, and the bridge's `initialize` handshake.
24
24
  *
25
25
  * - `"none"`: sessions cannot be cloned at all.
@@ -108,6 +108,7 @@ type PluginSettingDescriptor = {
108
108
  default?: string;
109
109
  };
110
110
  type PluginSettingDescriptors = Record<string, PluginSettingDescriptor>;
111
+ type PluginSettingValue = string | boolean;
111
112
  interface PluginCliOutputLimitError {
112
113
  code: "plugin_cli_output_too_large";
113
114
  message: string;
@@ -190,9 +191,6 @@ interface PluginProviderCapabilities {
190
191
  /** The provider stores a thread name of its own, so BB forwards renames to
191
192
  * it. */
192
193
  supportsThreadRename: boolean;
193
- /** The provider can run BB's Workflow tools — gates the workflows opt-in on
194
- * new threads. */
195
- supportsWorkflows: boolean;
196
194
  /** Permission modes the provider can actually run in. Non-empty, no
197
195
  * duplicates. */
198
196
  permissionModes: readonly PluginProviderPermissionMode[];
@@ -200,14 +198,109 @@ interface PluginProviderCapabilities {
200
198
  * {@link PluginProviderReasoningLevel}). Non-empty, no duplicates. */
201
199
  reasoningLevels: readonly PluginProviderReasoningLevel[];
202
200
  }
201
+ /**
202
+ * Provider copy core surfaces render from per-provider tables today (usage
203
+ * banners, sign-in hints, the mobile picker, the agent guide). Declared once
204
+ * here so no core surface keys copy on a provider id. Mirrors
205
+ * `ProviderStrings` in `@bb/domain`, which is the client projection.
206
+ */
207
+ interface PluginProviderStrings {
208
+ /** How to sign in on the host ("Run `claude` on the machine to sign in."). */
209
+ signInHint: string;
210
+ /** Shown when a session's credentials expired. */
211
+ expiredHint: string;
212
+ /** Where to install the agent. */
213
+ installUrl: string;
214
+ /** Brand prefix stripped from model display names ("Claude "). */
215
+ brandPrefix?: string;
216
+ /** Plan-mode banner copy for providers that declare the `plan` action. */
217
+ planModeCopy?: string;
218
+ /** Per-theme tint for the provider icon. */
219
+ iconTint?: {
220
+ light: string;
221
+ dark: string;
222
+ };
223
+ }
224
+ /**
225
+ * One selectable option for a picker — a service tier or a reasoning level.
226
+ * `id` is the wire value the bridge receives; `label` is what the picker
227
+ * shows. Declared lists are the cold-cache fallback; `model/list` is precise
228
+ * per model.
229
+ */
230
+ interface PluginProviderOptionDescriptor {
231
+ id: string;
232
+ label: string;
233
+ description?: string;
234
+ }
235
+ /**
236
+ * Payload schemas for one extension kind this provider emits, keyed by the
237
+ * kind's local name (the server prefixes the plugin id to form the
238
+ * namespaced `"<pluginId>/<name>"`). `item` validates `item.open` payloads
239
+ * with `type: "extension"`, `state` validates `extension.state` payloads;
240
+ * each is optional so a kind can be item-only or state-only. Schemas are
241
+ * Standard Schema v1 validators (zod 4 schemas qualify).
242
+ */
243
+ interface PluginProviderExtensionKindDeclaration {
244
+ item?: StandardSchemaV1;
245
+ state?: StandardSchemaV1;
246
+ }
247
+ /**
248
+ * Per-command context handed to
249
+ * {@link PluginProviderDeclaration.experimental_deriveProviderOptions}. The
250
+ * server builds one for every session and turn command it dispatches on a
251
+ * thread of this provider.
252
+ */
253
+ interface PluginProviderOptionsContext {
254
+ threadId: string;
255
+ projectId: string;
256
+ /** The resolved model id for this command. */
257
+ model: string;
258
+ /** BB's permission mode for this command (already clamped to the host). */
259
+ permissionMode: PluginProviderPermissionMode;
260
+ /**
261
+ * `"plan"` when the prompt entered plan mode through this provider's
262
+ * declared `plan` composer action. Absent for an ordinary prompt — plan
263
+ * mode is a BB prompt mode, so the bridge maps it onto whatever the agent
264
+ * calls it natively.
265
+ */
266
+ promptMode?: "plan";
267
+ /**
268
+ * This plugin's own settings values (`bb.settings.define`), read at call
269
+ * time. Secret settings are omitted — provider options ride the daemon
270
+ * wire and are persisted with the session, so a secret must never be
271
+ * derived into them.
272
+ */
273
+ settings: Readonly<Record<string, PluginSettingValue | undefined>>;
274
+ }
275
+ /**
276
+ * One cold-cache fallback model. The provider's live `model/list` result is
277
+ * the only real model source; this list stands in only while no probe has
278
+ * completed, or when a probe fails transiently, so the picker is not empty.
279
+ * `id` is the wire model id the bridge receives.
280
+ */
281
+ interface PluginProviderFallbackModel {
282
+ id: string;
283
+ /** Picker display name ("Opus 5 (1M)"). */
284
+ displayName: string;
285
+ description: string;
286
+ /** Reasoning levels this model supports, lowest to highest. Non-empty. */
287
+ supportedReasoningEfforts: readonly {
288
+ reasoningEffort: PluginProviderReasoningLevel;
289
+ description: string;
290
+ }[];
291
+ /** Must be one of `supportedReasoningEfforts`. */
292
+ defaultReasoningEffort: PluginProviderReasoningLevel;
293
+ /** Exactly one entry in the list is the default. */
294
+ isDefault: boolean;
295
+ }
203
296
  /**
204
297
  * One provider this plugin contributes to BB's provider registry.
205
298
  *
206
299
  * Ids are stable public identifiers — thread rows and routes reference them —
207
300
  * and are collision-rejected: a declaration whose id matches another plugin's
208
- * live registration, or reserves a first-party provider it does not own, is
209
- * refused. Registrations are replaced wholesale on plugin reload, like every
210
- * other plugin surface.
301
+ * live registration is refused; the first registration wins and no id is
302
+ * reserved ahead of time. Registrations are replaced wholesale on plugin
303
+ * reload, like every other plugin surface.
211
304
  *
212
305
  * A declaration owns the provider's static metadata and bridge options. The
213
306
  * executable implementation is the plugin's own provider bridge, named by
@@ -222,6 +315,12 @@ interface PluginProviderDeclaration {
222
315
  id: string;
223
316
  /** Picker display name: 1–80 characters, non-blank. */
224
317
  displayName: string;
318
+ /**
319
+ * Optional grouping key (same grammar as `id`) for providers that share a
320
+ * family — the ACP agents, for example — so clients can group them without
321
+ * parsing a prefix out of the id. Grouping only: no policy keys on it.
322
+ */
323
+ experimental_family?: string;
225
324
  /**
226
325
  * Optional picker icon, in the same grammar as `bb.branding.icon`: either a
227
326
  * named host glyph (`"Zap"`) or a plugin-relative path starting with `"./"`
@@ -248,6 +347,52 @@ interface PluginProviderDeclaration {
248
347
  /** Composer actions this provider supports. No duplicates; may be empty
249
348
  * (the universal skills typeahead is implicit). */
250
349
  composerActions: readonly PluginProviderComposerAction[];
350
+ /** Provider copy for core surfaces ({@link PluginProviderStrings}). */
351
+ experimental_strings?: PluginProviderStrings;
352
+ /** Service tiers this provider accepts, as picker options. Non-empty when
353
+ * present, unique ids. The coarse `capabilities.supportsServiceTier` stays
354
+ * until WS2a stabilizes. */
355
+ experimental_serviceTiers?: readonly PluginProviderOptionDescriptor[];
356
+ /** Reasoning levels as picker options with labels, beside the coarse
357
+ * `capabilities.reasoningLevels` ladder (ids only). Non-empty when present,
358
+ * unique ids. WS2a merges the two. */
359
+ experimental_reasoningLevels?: readonly PluginProviderOptionDescriptor[];
360
+ /** Extension kinds this provider's bridge may emit, keyed by local name
361
+ * (`[a-z0-9-]+`). The server validates extension payloads against these
362
+ * schemas at ingest and persists a `provider/unhandled` on a miss. */
363
+ experimental_extensionKinds?: Readonly<Record<string, PluginProviderExtensionKindDeclaration>>;
364
+ /**
365
+ * Cold-cache fallback models ({@link PluginProviderFallbackModel}). The
366
+ * server offers them only while a model probe has not completed or failed
367
+ * transiently; the live `model/list` result always replaces them. Ids must
368
+ * be unique and exactly one entry must be the default.
369
+ */
370
+ experimental_models?: {
371
+ fallback: readonly PluginProviderFallbackModel[];
372
+ };
373
+ /**
374
+ * Daemon environment variables this provider's bridge may read. Provider
375
+ * processes are spawned with every inherited `BB_*` variable stripped, so a
376
+ * bridge that honors an operator override (a CLI path, say) names it here
377
+ * and the daemon forwards exactly those variables. Names are
378
+ * `[A-Z_][A-Z0-9_]*`, at most 32.
379
+ */
380
+ experimental_env?: {
381
+ passthrough: readonly string[];
382
+ };
383
+ /**
384
+ * Derive this provider's opaque per-command options. Called synchronously
385
+ * by the server for every session and turn command on a thread of this
386
+ * provider, with the command's {@link PluginProviderOptionsContext}; the
387
+ * returned JSON object reaches this plugin's bridge as
388
+ * `options.providerOptions`, merged over `experimental_bridgeOptions`. Core
389
+ * never interprets its keys — this is where a provider's own knobs (memory,
390
+ * native subagents, a native plan flag) travel instead of on the shared
391
+ * execution contract. A throw fails the command with the plugin named, so
392
+ * a buggy hook cannot silently run a turn with default knobs. Must be fast:
393
+ * it sits on the turn-submit path.
394
+ */
395
+ experimental_deriveProviderOptions?: (context: PluginProviderOptionsContext) => Readonly<Record<string, JsonValue>>;
251
396
  }
252
397
  type PluginMentionTrigger = "!" | "#" | "$" | "@" | "~";
253
398
 
@@ -291,13 +436,24 @@ declare const PLUGIN_PROVIDER_PERMISSION_MODE_VALUES: readonly ["accept-edits",
291
436
  declare const PLUGIN_PROVIDER_REASONING_LEVEL_VALUES: readonly ["none", "low", "medium", "high", "xhigh", "ultracode", "max", "ultra"];
292
437
  declare const PLUGIN_PROVIDER_COMPOSER_ACTION_VALUES: readonly ["plan", "goal"];
293
438
  /**
294
- * Validate one `bb.agents.experimental_registerProvider` declaration. Plugin
439
+ * Validate one `bb.providers.register` declaration. Plugin
295
440
  * sources are untyped at runtime, so every field is checked; the production
296
441
  * host and the fake host both call this, so they accept and reject provider
297
442
  * declarations identically. Throws a descriptive error on the first problem;
298
443
  * returns a normalized, deeply frozen copy carrying only contract fields.
299
444
  */
300
445
  declare function validatePluginProviderDeclaration(declaration: PluginProviderDeclaration): PluginProviderDeclaration;
446
+ /**
447
+ * Run a declaration's `experimental_deriveProviderOptions` hook for one
448
+ * command and validate its result as a bounded, plain-JSON object — the same
449
+ * rules as `experimental_bridgeOptions`, because the result rides the same
450
+ * wire slot. Shared by the real host and the fake so a hook that works in
451
+ * tests works in production.
452
+ */
453
+ declare function deriveValidatedProviderOptions(args: {
454
+ declaration: PluginProviderDeclaration;
455
+ context: Parameters<NonNullable<PluginProviderDeclaration["experimental_deriveProviderOptions"]>>[0];
456
+ }): Readonly<Record<string, JsonValue>>;
301
457
  declare function isStandardSchema(value: unknown): value is StandardSchemaV1;
302
458
  declare function readRpcMethodContract(method: string, value: unknown): PluginRpcMethodContract;
303
459
  /** Duck-typed zod detection: plugin sources may carry their own zod copy,
@@ -327,4 +483,4 @@ declare function enforcePluginCliOutputLimit(result: Omit<PluginCliExecutionResu
327
483
  */
328
484
  declare function adoptHttpRouteResponse(value: unknown): Response;
329
485
 
330
- export { AGENT_TOOL_NAME_PATTERN, BACKGROUND_NAME_PATTERN, CLI_COMMAND_NAME_PATTERN, KV_VALUE_MAX_BYTES, MENTION_PROVIDER_ID_PATTERN, PLUGIN_AGENT_DYNAMIC_INSTRUCTIONS_MAX_CHARS, PLUGIN_AGENT_SELECTION_MAX_IDS, PLUGIN_AGENT_STATIC_INSTRUCTIONS_MAX_CHARS, PLUGIN_AGENT_STATUS_LABEL_MAX_CHARS, PLUGIN_AGENT_TOOL_PARAMETERS_MAX_BYTES, PLUGIN_HTTP_METHODS, PLUGIN_MENTION_TRIGGER_VALUES, PLUGIN_PROVIDER_BRIDGE_OPTIONS_MAX_BYTES, PLUGIN_PROVIDER_COMPOSER_ACTION_VALUES, PLUGIN_PROVIDER_DISPLAY_NAME_MAX_CHARS, PLUGIN_PROVIDER_PERMISSION_MODE_VALUES, PLUGIN_PROVIDER_REASONING_LEVEL_VALUES, PROVIDER_ID_PATTERN, RESERVED_AGENT_TOOL_NAMES, RESERVED_BB_CLI_COMMANDS, RPC_METHOD_PATTERN, SETTING_KEY_PATTERN, adoptHttpRouteResponse, assertNoRecursiveJsonSchemaReferences, enforcePluginCliOutputLimit, isPluginMentionTrigger, isStandardSchema, isZodSchemaLike, normalizeMentionProviderTriggers, readRpcMethodContract, registerSettingDescriptors, summarizeParseIssues, validatePluginProviderDeclaration, validateSettingsUpdate };
486
+ export { AGENT_TOOL_NAME_PATTERN, BACKGROUND_NAME_PATTERN, CLI_COMMAND_NAME_PATTERN, KV_VALUE_MAX_BYTES, MENTION_PROVIDER_ID_PATTERN, PLUGIN_AGENT_DYNAMIC_INSTRUCTIONS_MAX_CHARS, PLUGIN_AGENT_SELECTION_MAX_IDS, PLUGIN_AGENT_STATIC_INSTRUCTIONS_MAX_CHARS, PLUGIN_AGENT_STATUS_LABEL_MAX_CHARS, PLUGIN_AGENT_TOOL_PARAMETERS_MAX_BYTES, PLUGIN_HTTP_METHODS, PLUGIN_MENTION_TRIGGER_VALUES, PLUGIN_PROVIDER_BRIDGE_OPTIONS_MAX_BYTES, PLUGIN_PROVIDER_COMPOSER_ACTION_VALUES, PLUGIN_PROVIDER_DISPLAY_NAME_MAX_CHARS, PLUGIN_PROVIDER_PERMISSION_MODE_VALUES, PLUGIN_PROVIDER_REASONING_LEVEL_VALUES, PROVIDER_ID_PATTERN, RESERVED_AGENT_TOOL_NAMES, RESERVED_BB_CLI_COMMANDS, RPC_METHOD_PATTERN, SETTING_KEY_PATTERN, adoptHttpRouteResponse, assertNoRecursiveJsonSchemaReferences, deriveValidatedProviderOptions, enforcePluginCliOutputLimit, isPluginMentionTrigger, isStandardSchema, isZodSchemaLike, normalizeMentionProviderTriggers, readRpcMethodContract, registerSettingDescriptors, summarizeParseIssues, validatePluginProviderDeclaration, validateSettingsUpdate };