@get-bb/plugin-sdk 0.4.9 → 0.4.10

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.
package/README.md CHANGED
@@ -21,6 +21,42 @@ Any mounted plugin component can use
21
21
  same plugin's registered thread-panel actions; it returns false when the
22
22
  current surface has no thread side panel.
23
23
 
24
+ Use `experimental_UrlLink` for a real anchor that applies BB's current
25
+ in-app/external-browser preference on ordinary HTTP(S) activation, or
26
+ `useBbNavigate().experimental_openUrl(url)` for a button or menu. Internal app
27
+ routes, modifier clicks, explicit anchor targets, and unsupported schemes stay
28
+ browser-owned. A `_blank` or named target preserves supplied `rel` tokens but
29
+ adds `noopener noreferrer` unless `rel` explicitly contains `opener`, so a
30
+ newly opened page cannot control BB by accident. The frontend harness records
31
+ both forms in `navigateCalls` and accepts an `openUrl` behavior option.
32
+
33
+ Use `experimental_FileLink` for an explicit live workspace, host, or
34
+ thread-storage file. Ordinary activation opens the shared BB preview and its
35
+ context menu exposes built-in/plugin viewers, preferred external opening, and
36
+ copy actions. Valid targets expose an encoded, scheme-safe anchor href so
37
+ modifier clicks, downloads, and copied links cannot reinterpret a file name as
38
+ an external URL scheme. Malformed runtime targets—including traversal paths
39
+ and ill-formed Unicode—have no active href and cannot record a preview in the
40
+ frontend harness. Buttons and menus can call
41
+ `experimental_openFilePreview({ target, location })` or
42
+ `experimental_openFileExternally({ target, location })`; both return whether
43
+ the current host accepted the intent. Targets never infer an ambient workspace.
44
+ The frontend harness records both methods and accepts `openFilePreview` and
45
+ `openFileExternally` behavior options.
46
+
47
+ A nav panel's `experimental_fixedTabs` entries must include the containing nav
48
+ panel's `id` as `panelId`; each entry is also a stable reference to that
49
+ plugin's own tab. Give a targeted tab an `experimental_target.validate` type guard, call
50
+ `experimental_useAppPanel().openFixedTab({ surface: { kind:
51
+ "current" }, tab, target })`, and read the in-memory state inside the tab with
52
+ `experimental_useFixedTabTarget(tab)`. The target survives tab, panel, and
53
+ route remounts for the current app session; call `clear()` when the tab returns
54
+ to its untargeted state. The host validates JSON before the owner's type guard,
55
+ persists only selection, and returns false for an unavailable tab or invalid
56
+ target. The frontend harness records accepted requests in
57
+ `experimental_fixedTabOpenCalls`, accepts an `experimental_openFixedTab`
58
+ behavior, and can seed `experimental_fixedTabTarget` state.
59
+
24
60
  Every panel-open entry point reports the same way: `openThreadPanel` and the
25
61
  `openPanel` handed to `threadPanelAction`, `experimental_newThreadPanelAction`,
26
62
  and `messageAction` `run` callbacks all return `boolean` — true when the host
@@ -45,8 +81,13 @@ reload, disable, removal, failed replacement, and app-window teardown. The old
45
81
  generation is disposed before candidate mounts, so generations never overlap.
46
82
  Content scripts are trusted same-origin page code, not a sandbox.
47
83
 
48
- Static styles should stay in the normal imported `app.css`; scripts may own
49
- dynamic DOM/style nodes when their disposer removes them. See the
84
+ Static styles should stay in the normal imported `app.css`. The host keeps
85
+ that stylesheet active while the plugin has rendered slot, panel-header, or
86
+ portal UI, and for the full lifetime of any active content-script generation;
87
+ it is not an app-wide stylesheet hook. Use manifest `bb.themes` entries for
88
+ app-wide selectable palette CSS. Styling or decorating existing app-shell DOM
89
+ belongs in a content script, and scripts may own dynamic DOM/style nodes only
90
+ when their disposer removes them. See the
50
91
  [`content-script` reference plugin](../../examples/plugins/content-script/README.md)
51
92
  for a cleanup-safe editor enhancement.
52
93
 
@@ -6,9 +6,19 @@
6
6
  // and read the real source: https://github.com/get-bb/bb
7
7
 
8
8
  import * as react from 'react';
9
- import { ComponentType, ReactNode } from 'react';
9
+ import { ComponentType, ComponentPropsWithoutRef, ReactNode } from 'react';
10
10
  import { z } from 'zod';
11
11
 
12
+ /**
13
+ * A value that survives a JSON round trip without coercion or data loss.
14
+ *
15
+ * Host boundaries still validate values at runtime because TypeScript cannot
16
+ * exclude non-finite numbers and plugin bundles can bypass static types.
17
+ */
18
+ type JsonValue = string | number | boolean | null | JsonValue[] | {
19
+ [key: string]: JsonValue;
20
+ };
21
+
12
22
  /** A JSON-safe path segment reported by a Standard Schema validation issue. */
13
23
  type PluginRpcIssuePathSegment = string | number;
14
24
  /** Validator-neutral validation detail carried by an RPC error envelope. */
@@ -227,16 +237,6 @@ declare const createExecutionInputSourcesSchema: z.ZodObject<{
227
237
  }, z.core.$strict>;
228
238
  type CreateExecutionInputSources = z.infer<typeof createExecutionInputSourcesSchema>;
229
239
 
230
- /**
231
- * A value that survives a JSON round trip without coercion or data loss.
232
- *
233
- * Host boundaries still validate values at runtime because TypeScript cannot
234
- * exclude non-finite numbers and plugin bundles can bypass static types.
235
- */
236
- type JsonValue = string | number | boolean | null | JsonValue[] | {
237
- [key: string]: JsonValue;
238
- };
239
-
240
240
  /**
241
241
  * The `@get-bb/plugin-sdk/app` contract (plugin design §5.2) — pure types with no
242
242
  * side effects. The BB app imports these to keep its real implementation in
@@ -376,6 +376,13 @@ interface PluginFileOpenerSource {
376
376
  threadId: string | null;
377
377
  environmentId: string | null;
378
378
  projectId: string | null;
379
+ /**
380
+ * Explicit host selected for a project-backed workspace file. Omitted when
381
+ * the source is resolved by its environment/thread or the primary host.
382
+ *
383
+ * @experimental Audit before relying on this as a stable contract.
384
+ */
385
+ experimental_hostId?: string;
379
386
  }
380
387
  /** Props passed to a `fileOpener` component (rendered as a panel file tab). */
381
388
  interface PluginFileOpenerProps {
@@ -529,6 +536,38 @@ interface PluginSettingsSectionRegistration {
529
536
  description?: string;
530
537
  component: ComponentType<PluginSettingsSectionProps>;
531
538
  }
539
+ /**
540
+ * Owner-defined validator for a fixed tab's transient target. The host first
541
+ * verifies that the value is JSON-safe, then calls this validator before
542
+ * selecting the tab or delivering the target.
543
+ */
544
+ interface ExperimentalFixedTabTargetContract<Target extends JsonValue> {
545
+ validate(value: JsonValue): value is Target;
546
+ }
547
+ /** Stable, owner-scoped reference used by the app-panel controller. */
548
+ type ExperimentalPluginFixedTabReference<Target extends JsonValue = never> = {
549
+ /** The owning `navPanel` id; validated against the containing registration. */
550
+ readonly panelId: string;
551
+ /** Unique within the owning nav panel; letters, digits, `-`, `_`. */
552
+ readonly id: string;
553
+ } & ([Target] extends [never] ? {
554
+ /** An untargeted tab cannot be opened with a target. */
555
+ readonly experimental_target?: never;
556
+ } : {
557
+ /** Owner validation required before the host delivers a target. */
558
+ readonly experimental_target: ExperimentalFixedTabTargetContract<Target>;
559
+ });
560
+ /** A fixed tab declared by a plugin nav panel. */
561
+ type ExperimentalPluginFixedTabRegistration<Target extends JsonValue = never> = ExperimentalPluginFixedTabReference<Target> & {
562
+ title: string;
563
+ /** Icon hint (BB icon name); unknown names fall back to a generic icon. */
564
+ icon: string;
565
+ component: ComponentType<PluginNavPanelProps>;
566
+ /** `flush` lets the component own padding and scrolling. */
567
+ layout?: "flush" | "padded";
568
+ };
569
+ /** A fixed tab with either no target or an owner-validated JSON target. */
570
+ type ExperimentalPluginFixedTabDeclaration = ExperimentalPluginFixedTabRegistration | ExperimentalPluginFixedTabRegistration<JsonValue>;
532
571
  interface PluginNavPanelRegistration {
533
572
  /** Unique within the plugin; letters, digits, `-`, `_`. */
534
573
  id: string;
@@ -541,22 +580,14 @@ interface PluginNavPanelRegistration {
541
580
  /**
542
581
  * Ordered, non-closable tabs shown in this page's host-owned right panel.
543
582
  * BB owns selection and persistence and always includes its native Browser
544
- * and Terminal tools beside them. Components mount only while their tab is
545
- * active and the panel is open, and receive the same `subPath` as the page
546
- * component.
583
+ * and Terminal tools beside them. One tab is active in each visible split
584
+ * pane, so multiple fixed-tab components can be mounted concurrently. A
585
+ * component mounts only while its tab is active in a visible pane and the
586
+ * panel is open, and receives the same `subPath` as the page component.
547
587
  *
548
588
  * Experimental: see docs/api_to_audit.md.
549
589
  */
550
- experimental_fixedTabs?: readonly {
551
- /** Unique within this nav panel; letters, digits, `-`, `_`. */
552
- id: string;
553
- title: string;
554
- /** Icon hint (BB icon name); unknown names fall back to a generic icon. */
555
- icon: string;
556
- component: ComponentType<PluginNavPanelProps>;
557
- /** `flush` lets the component own padding and scrolling. */
558
- layout?: "flush" | "padded";
559
- }[];
590
+ experimental_fixedTabs?: readonly ExperimentalPluginFixedTabDeclaration[];
560
591
  /**
561
592
  * Optional presentational component rendered at the trailing edge of this
562
593
  * panel's sidebar row. It receives no props so it can own a narrow live
@@ -1200,7 +1231,10 @@ interface PluginContentScriptRegistration {
1200
1231
  id: string;
1201
1232
  /**
1202
1233
  * Install behavior into the bb app shell. The host awaits a returned
1203
- * promise, contains failures, and calls the returned disposer exactly once.
1234
+ * promise, retains the plugin's imported frontend stylesheet for this
1235
+ * generation, contains failures, and calls the returned disposer exactly
1236
+ * once. Styling or decorating existing app-shell DOM belongs here rather
1237
+ * than in an always-on frontend stylesheet.
1204
1238
  */
1205
1239
  mount(context: PluginContentScriptContext): void | PluginContentScriptDisposer | Promise<void | PluginContentScriptDisposer>;
1206
1240
  }
@@ -1631,6 +1665,78 @@ interface MarkdownProps {
1631
1665
  content: string;
1632
1666
  className?: string;
1633
1667
  }
1668
+ /**
1669
+ * Props for BB's semantic URL link. The host owns ordinary activation while
1670
+ * retaining browser-owned anchor behavior for app routes, modifiers, explicit
1671
+ * targets, copying, and unsupported schemes. New top-level targets preserve
1672
+ * supplied `rel` tokens and receive safe defaults unless `opener` is explicit.
1673
+ * Experimental: see docs/api_to_audit.md.
1674
+ */
1675
+ interface ExperimentalUrlLinkProps extends Omit<ComponentPropsWithoutRef<"a">, "href"> {
1676
+ href: string;
1677
+ }
1678
+ /** A live file whose identity is complete without ambient route context. */
1679
+ type ExperimentalLiveFileTarget = {
1680
+ kind: "workspace";
1681
+ environmentId: string;
1682
+ path: string;
1683
+ } | {
1684
+ kind: "host";
1685
+ hostId: string;
1686
+ path: string;
1687
+ } | {
1688
+ kind: "thread-storage";
1689
+ threadId: string;
1690
+ path: string;
1691
+ };
1692
+ /** One-based location to reveal after a live file opens. */
1693
+ type ExperimentalFileLocation = {
1694
+ kind: "line";
1695
+ line: number;
1696
+ column: number | null;
1697
+ } | {
1698
+ kind: "range";
1699
+ startLine: number;
1700
+ endLine: number;
1701
+ };
1702
+ /** Options shared by BB's preview and preferred-external file intents. */
1703
+ interface ExperimentalFileOpenOptions {
1704
+ target: ExperimentalLiveFileTarget;
1705
+ location: ExperimentalFileLocation | null;
1706
+ }
1707
+ /**
1708
+ * Props for BB's host-rendered semantic file link. Valid targets receive a
1709
+ * scheme-safe anchor href; traversal paths, ill-formed Unicode, and other
1710
+ * malformed runtime targets remain inert.
1711
+ */
1712
+ interface ExperimentalFileLinkProps extends Omit<ComponentPropsWithoutRef<"a">, "href" | "target"> {
1713
+ target: ExperimentalLiveFileTarget;
1714
+ location?: ExperimentalFileLocation | null;
1715
+ }
1716
+ /** The panel surface resolved by the component making the request. */
1717
+ type ExperimentalAppPanelSurface = {
1718
+ kind: "current";
1719
+ };
1720
+ /**
1721
+ * The owning fixed tab's current memory-only target. It survives tab, panel,
1722
+ * and route remounts during the current app session, but is never persisted
1723
+ * across a refresh. Call `clear` when the owner returns to its untargeted state.
1724
+ */
1725
+ interface ExperimentalFixedTabTargetState<Target extends JsonValue> {
1726
+ readonly sequence: number;
1727
+ readonly target: Target;
1728
+ clear(): void;
1729
+ }
1730
+ type ExperimentalOpenFixedTabOptions<Target extends JsonValue> = {
1731
+ surface: ExperimentalAppPanelSurface;
1732
+ tab: ExperimentalPluginFixedTabReference<Target>;
1733
+ /** Omit to select the tab without replacing its current session target. */
1734
+ target?: NoInfer<Target>;
1735
+ };
1736
+ /** Surface-aware controller for selecting owner-scoped fixed tabs. */
1737
+ interface ExperimentalAppPanel {
1738
+ openFixedTab<Target extends JsonValue = never>(options: ExperimentalOpenFixedTabOptions<Target>): boolean;
1739
+ }
1634
1740
  /** Current app selection, derived from the route. */
1635
1741
  interface BbContext {
1636
1742
  projectId: string | null;
@@ -1665,6 +1771,16 @@ interface BbNavigate {
1665
1771
  * the action is unavailable.
1666
1772
  */
1667
1773
  openThreadPanel(options: PluginTargetedPanelActionOpenOptions): boolean;
1774
+ /**
1775
+ * Open an HTTP(S) URL using this client's BB browser preference. Returns
1776
+ * false for schemes the host does not own. Experimental: see
1777
+ * docs/api_to_audit.md.
1778
+ */
1779
+ experimental_openUrl(url: string): boolean;
1780
+ /** Open a live file in this surface's shared BB preview panel. */
1781
+ experimental_openFilePreview(options: ExperimentalFileOpenOptions): boolean;
1782
+ /** Open a live file in this client's preferred external file target. */
1783
+ experimental_openFileExternally(options: ExperimentalFileOpenOptions): boolean;
1668
1784
  }
1669
1785
  /**
1670
1786
  * Everything `@get-bb/plugin-sdk/app` resolves to at runtime. The BB app builds
@@ -1685,6 +1801,10 @@ interface PluginSdkApp {
1685
1801
  useSettings(): PluginSettingsState;
1686
1802
  useBbContext(): BbContext;
1687
1803
  useBbNavigate(): BbNavigate;
1804
+ /** Select one of this plugin's eligible fixed tabs on the current surface. */
1805
+ experimental_useAppPanel(): ExperimentalAppPanel;
1806
+ /** Read or clear the owning tab's validated, session-scoped target. */
1807
+ experimental_useFixedTabTarget<Target extends JsonValue>(tab: ExperimentalPluginFixedTabReference<Target>): ExperimentalFixedTabTargetState<Target> | null;
1688
1808
  useComposer(): PluginComposerApi;
1689
1809
  /**
1690
1810
  * The sidebar's live thread view (see {@link PluginSidebarThreadsState}).
@@ -1735,6 +1855,13 @@ interface PluginSdkApp {
1735
1855
  * {@link MarkdownProps}).
1736
1856
  */
1737
1857
  Markdown: ComponentType<MarkdownProps>;
1858
+ /**
1859
+ * A real anchor whose ordinary HTTP(S) activation uses BB's URL preference.
1860
+ * Experimental: see docs/api_to_audit.md.
1861
+ */
1862
+ experimental_UrlLink: ComponentType<ExperimentalUrlLinkProps>;
1863
+ /** Host-rendered live-file link backed by the shared navigation controller. */
1864
+ experimental_FileLink: ComponentType<ExperimentalFileLinkProps>;
1738
1865
  /**
1739
1866
  * The host-owned new-thread compose surface (see
1740
1867
  * {@link NewThreadComposerProps}). Experimental: see
@@ -1762,6 +1889,8 @@ interface PluginSdkApp {
1762
1889
  declare const definePluginApp: (setup: PluginAppSetup) => PluginAppDefinition;
1763
1890
  declare const ThreadChat: react.ComponentType<ThreadChatProps>;
1764
1891
  declare const Markdown: react.ComponentType<MarkdownProps>;
1892
+ declare const experimental_FileLink: react.ComponentType<ExperimentalFileLinkProps>;
1893
+ declare const experimental_UrlLink: react.ComponentType<ExperimentalUrlLinkProps>;
1765
1894
  declare const experimental_NewThreadComposer: react.ComponentType<NewThreadComposerProps>;
1766
1895
  declare const experimental_SourceCode: react.ComponentType<SourceCodeProps>;
1767
1896
  declare const experimental_Diff: react.ComponentType<DiffProps>;
@@ -1771,6 +1900,8 @@ declare const useRealtimeConnectionState: () => PluginRealtimeConnectionState;
1771
1900
  declare const useSettings: () => PluginSettingsState;
1772
1901
  declare const useBbContext: () => BbContext;
1773
1902
  declare const useBbNavigate: () => BbNavigate;
1903
+ declare const experimental_useAppPanel: () => ExperimentalAppPanel;
1904
+ declare const experimental_useFixedTabTarget: <Target extends JsonValue>(tab: ExperimentalPluginFixedTabReference<Target>) => ExperimentalFixedTabTargetState<Target> | null;
1774
1905
  declare const useComposer: () => PluginComposerApi;
1775
1906
  declare const useComposerView: () => ComposerView;
1776
1907
  declare const experimental_useSidebarThreads: () => PluginSidebarThreadsState;
@@ -1778,5 +1909,5 @@ declare const experimental_useSidebarThreadActions: () => PluginSidebarThreadAct
1778
1909
  declare const experimental_useSidebarThreadPullRequest: (threadId: string) => PluginSidebarThreadPullRequestState;
1779
1910
  declare const experimental_useSidebarThreadSplit: (threadId: string) => PluginSidebarThreadSplit;
1780
1911
 
1781
- export { Markdown, ThreadChat, definePluginApp, experimental_Diff, experimental_NewThreadComposer, experimental_SourceCode, experimental_useSidebarThreadActions, experimental_useSidebarThreadPullRequest, experimental_useSidebarThreadSplit, experimental_useSidebarThreads, useBbContext, useBbNavigate, useComposer, useComposerView, useRealtime, useRealtimeConnectionState, useRpc, useSettings };
1782
- export type { BbContext, BbNavigate, CodeOverflowMode, ComposerCustomization, ComposerPlusMenuItem, ComposerRichTextSpec, ComposerStructuredDraft, ComposerView, DiffProps, DiffViewMode, 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 };
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 };
@@ -0,0 +1,42 @@
1
+ // Portable type declarations for `@get-bb/plugin-sdk`. Unpublished BB
2
+ // workspace contracts are flattened; public subpaths may reuse the
3
+ // package root without requiring any other @bb/* package.
4
+ //
5
+ // Confused by the API, or need a symbol that isn't here? Clone the BB repo
6
+ // and read the real source: https://github.com/get-bb/bb
7
+
8
+ /** A live file whose identity is complete without ambient route context. */
9
+ type ExperimentalLiveFileTarget = {
10
+ kind: "workspace";
11
+ environmentId: string;
12
+ path: string;
13
+ } | {
14
+ kind: "host";
15
+ hostId: string;
16
+ path: string;
17
+ } | {
18
+ kind: "thread-storage";
19
+ threadId: string;
20
+ path: string;
21
+ };
22
+ /** One-based location to reveal after a live file opens. */
23
+ type ExperimentalFileLocation = {
24
+ kind: "line";
25
+ line: number;
26
+ column: number | null;
27
+ } | {
28
+ kind: "range";
29
+ startLine: number;
30
+ endLine: number;
31
+ };
32
+ /** Options shared by BB's preview and preferred-external file intents. */
33
+ interface ExperimentalFileOpenOptions {
34
+ target: ExperimentalLiveFileTarget;
35
+ location: ExperimentalFileLocation | null;
36
+ }
37
+
38
+ declare function normalizeExperimentalLiveFileTarget(value: unknown): ExperimentalLiveFileTarget | null;
39
+ declare function normalizeExperimentalFileLocation(value: unknown): ExperimentalFileLocation | null | undefined;
40
+ declare function normalizeExperimentalFileOpenOptions(value: unknown): ExperimentalFileOpenOptions | null;
41
+
42
+ export { normalizeExperimentalFileLocation, normalizeExperimentalFileOpenOptions, normalizeExperimentalLiveFileTarget };
@@ -35,6 +35,16 @@ declare const RESERVED_BB_CLI_COMMANDS: readonly string[];
35
35
  declare const PROVIDER_FORK_VALUES: readonly ["none", "tip", "checkpoint"];
36
36
  type ProviderFork = (typeof PROVIDER_FORK_VALUES)[number];
37
37
 
38
+ /**
39
+ * A value that survives a JSON round trip without coercion or data loss.
40
+ *
41
+ * Host boundaries still validate values at runtime because TypeScript cannot
42
+ * exclude non-finite numbers and plugin bundles can bypass static types.
43
+ */
44
+ type JsonValue = string | number | boolean | null | JsonValue[] | {
45
+ [key: string]: JsonValue;
46
+ };
47
+
38
48
  /**
39
49
  * The validator-neutral subset of Standard Schema v1 used by plugin RPC.
40
50
  * Zod 4 schemas implement this interface directly; other validators can do
@@ -139,10 +149,23 @@ type PluginProviderComposerAction = "goal" | "plan";
139
149
  * live session (picker rendering, route gating, cross-plugin tool
140
150
  * composition — including with the host offline). Every boolean is a
141
151
  * provider-native fact — the provider implements the feature; the flag only
142
- * tells external consumers it exists. Everything else is a handshake fact the
143
- * bridge reports at `initialize`, where it cannot drift from behavior.
152
+ * tells external consumers it exists. Session-behavior facts remain handshake
153
+ * capabilities reported by the running bridge. Sessionless maintenance
154
+ * methods are declared here so callers can decide whether to probe without
155
+ * starting the bridge first.
144
156
  */
145
157
  interface PluginProviderCapabilities {
158
+ /** The provider bridge implements the sessionless `provider/health`
159
+ * request. This is host-local readiness, not a network health check. */
160
+ experimental_providerHealth: boolean;
161
+ /** The provider exposes subscription usage through the sessionless
162
+ * `provider/usage` request. False means callers skip the request and usage
163
+ * settings omit the provider. A shared bridge that declares true may still
164
+ * report usage unavailable for one provider id or return no windows. */
165
+ experimental_providerUsage: boolean;
166
+ /** The provider bridge implements `provider/installation/status` and
167
+ * `provider/installation/run` for host-local installation management. */
168
+ experimental_providerInstallation: boolean;
146
169
  /** The provider accepts a fast/priority service-tier choice — shows the
147
170
  * service-tier toggle in the picker. */
148
171
  supportsServiceTier: boolean;
@@ -186,11 +209,11 @@ interface PluginProviderCapabilities {
186
209
  * refused. Registrations are replaced wholesale on plugin reload, like every
187
210
  * other plugin surface.
188
211
  *
189
- * A declaration is metadata only. The implementation is the plugin's own
190
- * provider bridge, named by `bb.providerBridge` in the manifest and built into
191
- * the artifact BB ships to hosts declaring a provider without one is
192
- * refused, because the picker entry would exist and no turn on it could ever
193
- * run.
212
+ * A declaration owns the provider's static metadata and bridge options. The
213
+ * executable implementation is the plugin's own provider bridge, named by
214
+ * `bb.providerBridge` in the manifest and built into the artifact BB ships to
215
+ * hosts declaring a provider without one is refused, because the picker
216
+ * entry would exist and no turn on it could ever run.
194
217
  */
195
218
  interface PluginProviderDeclaration {
196
219
  /** Stable provider id: 2–64 characters of lowercase letters, digits, and
@@ -206,6 +229,19 @@ interface PluginProviderDeclaration {
206
229
  * — no leading "/", no ".." segments, no backslashes.
207
230
  */
208
231
  icon?: string;
232
+ /**
233
+ * Provider-owned static options passed opaquely to this plugin's bridge on
234
+ * every sessionless and session request. Core validates that the value is
235
+ * JSON, but does not interpret its keys. This is intended for immutable
236
+ * launch metadata shared by every host (for example an ACP command spec),
237
+ * not user or machine configuration.
238
+ */
239
+ experimental_bridgeOptions?: Readonly<Record<string, JsonValue>>;
240
+ /**
241
+ * Whether the provider is always listed or only listed on hosts where its
242
+ * bridge reports it installed. Defaults to `"always"`.
243
+ */
244
+ experimental_visibility?: "always" | "installed";
209
245
  /** Pre-session capability facts (see the declaration tests on
210
246
  * {@link PluginProviderCapabilities}). */
211
247
  capabilities: PluginProviderCapabilities;
@@ -237,6 +273,7 @@ declare const PLUGIN_AGENT_DYNAMIC_INSTRUCTIONS_MAX_CHARS = 4096;
237
273
  declare const PLUGIN_AGENT_TOOL_PARAMETERS_MAX_BYTES: number;
238
274
  declare const MENTION_PROVIDER_ID_PATTERN: RegExp;
239
275
  declare const PROVIDER_ID_PATTERN: RegExp;
276
+ declare const PLUGIN_PROVIDER_BRIDGE_OPTIONS_MAX_BYTES: number;
240
277
  declare const SETTING_KEY_PATTERN: RegExp;
241
278
  /**
242
279
  * Validate freeform descriptors from plugin code and merge them into the
@@ -290,4 +327,4 @@ declare function enforcePluginCliOutputLimit(result: Omit<PluginCliExecutionResu
290
327
  */
291
328
  declare function adoptHttpRouteResponse(value: unknown): Response;
292
329
 
293
- 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_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 };
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 };