@get-bb/plugin-sdk 0.4.56 → 0.4.84

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/dist/app.js CHANGED
@@ -1,5 +1,7 @@
1
1
  // src/app.ts
2
2
  var runtime = globalThis.__bbPluginRuntime?.pluginSdkApp ?? {};
3
+ var experimental_Icon = runtime.experimental_Icon;
4
+ var experimental_ProviderIcon = runtime.experimental_ProviderIcon;
3
5
  var definePluginApp = runtime.definePluginApp;
4
6
  var ThreadChat = runtime.ThreadChat;
5
7
  var Markdown = runtime.Markdown;
@@ -37,8 +39,10 @@ export {
37
39
  experimental_BranchPicker,
38
40
  experimental_Diff,
39
41
  experimental_FileLink,
42
+ experimental_Icon,
40
43
  experimental_NewThreadComposer,
41
44
  experimental_PermissionModePicker,
45
+ experimental_ProviderIcon,
42
46
  experimental_ProviderModelPicker,
43
47
  experimental_SourceCode,
44
48
  experimental_useAppPanel,
@@ -306,8 +306,7 @@ var pluginProviderEnvEntrySchema = z4.object({
306
306
  z4.string(),
307
307
  z4.object({ serverPath: z4.string().startsWith("/") }).strict()
308
308
  ]),
309
- reason: z4.string(),
310
- secret: z4.boolean()
309
+ reason: z4.string()
311
310
  }).strict();
312
311
  var pluginProviderEnvEntriesSchema = z4.array(pluginProviderEnvEntrySchema).max(PLUGIN_PROVIDER_ENV_MAX_ENTRIES).superRefine((entries, context) => {
313
312
  const names = /* @__PURE__ */ new Set();
@@ -1776,12 +1775,23 @@ function pluginHookAlreadyRegisteredMessage(hook) {
1776
1775
  }
1777
1776
  var ENVIRONMENT_PROVIDER_ID_PATTERN = /^[a-z0-9][a-z0-9-]{1,63}$/;
1778
1777
  var ENVIRONMENT_PROVIDER_DISPLAY_NAME_MAX_CHARS = 80;
1778
+ var ENVIRONMENT_PROVIDER_DESCRIPTION_MAX_CHARS = 200;
1779
1779
  var ENVIRONMENT_PROVIDER_REQUIREMENT_NAMES = [
1780
1780
  "projectCheckout",
1781
1781
  "gitCheckout",
1782
1782
  "gitRemote",
1783
1783
  "projectless"
1784
1784
  ];
1785
+ var environmentCompositionSchema = z4.object({
1786
+ id: z4.string().regex(ENVIRONMENT_PROVIDER_ID_PATTERN),
1787
+ displayName: z4.string().trim().min(1).max(ENVIRONMENT_PROVIDER_DISPLAY_NAME_MAX_CHARS),
1788
+ description: z4.string().trim().min(1).max(ENVIRONMENT_PROVIDER_DESCRIPTION_MAX_CHARS).optional().transform((value) => value ?? null),
1789
+ icon: z4.string().trim().min(1).transform(
1790
+ (icon) => isPluginOwnedIconPath(icon) ? validateProviderRelativePath(icon, "Composition icon") : icon
1791
+ ).optional().transform((value) => value ?? null),
1792
+ machineProviderId: z4.string().regex(ENVIRONMENT_PROVIDER_ID_PATTERN),
1793
+ environmentProviderId: z4.string().regex(ENVIRONMENT_PROVIDER_ID_PATTERN)
1794
+ }).strict();
1785
1795
  function validatePluginEnvironmentProviderDeclaration(declaration) {
1786
1796
  if (typeof declaration !== "object" || declaration === null) {
1787
1797
  throw new Error("environment provider declaration must be an object");
@@ -1798,17 +1808,14 @@ function validatePluginEnvironmentProviderDeclaration(declaration) {
1798
1808
  `environment provider "${id}" needs a displayName of 1-${ENVIRONMENT_PROVIDER_DISPLAY_NAME_MAX_CHARS} characters`
1799
1809
  );
1800
1810
  }
1801
- const icon = declaration.icon === void 0 ? null : z4.string().min(1).parse(declaration.icon).trim();
1802
- if (icon !== null) {
1803
- if (isPluginOwnedIconPath(icon))
1804
- validateProviderRelativePath(icon, `"${id}" icon`);
1805
- else if (!isNamespacedGlyph(icon) && /[/\\]/u.test(icon))
1806
- throw new Error(
1807
- `environment provider "${id}" icon must be a glyph, declared icon, or plugin-relative path`
1808
- );
1809
- }
1810
- if (icon !== null && icon.length === 0) {
1811
- throw new Error(`environment provider "${id}" declares an empty icon`);
1811
+ const description = z4.string().trim().min(1).max(ENVIRONMENT_PROVIDER_DESCRIPTION_MAX_CHARS).optional().transform((value) => value ?? null).parse(declaration.description);
1812
+ const icon = z4.string().trim().min(1).optional().transform((value) => value ?? null).parse(declaration.icon);
1813
+ if (icon !== null && isPluginOwnedIconPath(icon)) {
1814
+ validateProviderRelativePath(icon, `"${id}" icon`);
1815
+ } else if (icon !== null && !isNamespacedGlyph(icon) && /[/\\]/u.test(icon)) {
1816
+ throw new Error(
1817
+ `environment provider "${id}" icon must be a glyph, declared icon, or plugin-relative path`
1818
+ );
1812
1819
  }
1813
1820
  const requires = normalizeEnvironmentProviderRequirements(id, declaration);
1814
1821
  const inputs = normalizeEnvironmentProviderInputs(id, declaration);
@@ -1830,6 +1837,7 @@ function validatePluginEnvironmentProviderDeclaration(declaration) {
1830
1837
  return {
1831
1838
  id,
1832
1839
  displayName,
1840
+ description,
1833
1841
  icon,
1834
1842
  requires,
1835
1843
  inputs: inputs === null ? null : inputs.schema,
@@ -1898,16 +1906,116 @@ var environmentProviderPolicySchema = z4.object({
1898
1906
  retireGraceMs: z4.number().int().nonnegative().nullable().default(3e5),
1899
1907
  pathKeys: z4.enum(["per-thread", "per-attempt"]).default("per-thread")
1900
1908
  }).strict();
1901
- var MACHINE_PROVIDER_REQUIREMENT_NAMES = ["gitRemote"];
1909
+ var MACHINE_PROVIDER_DESCRIPTION_MAX_CHARS = 200;
1910
+ function validatePluginMachineProviderDeclaration(declaration) {
1911
+ if (typeof declaration !== "object" || declaration === null) {
1912
+ throw new Error("machine provider declaration must be an object");
1913
+ }
1914
+ const id = declaration.id;
1915
+ if (typeof id !== "string" || !ENVIRONMENT_PROVIDER_ID_PATTERN.test(id)) {
1916
+ throw new Error(
1917
+ `invalid machine provider id ${JSON.stringify(id)} \u2014 use 2-64 lowercase letters, digits, or "-", starting with a letter or digit`
1918
+ );
1919
+ }
1920
+ const displayName = typeof declaration.displayName === "string" ? declaration.displayName.trim() : "";
1921
+ if (displayName.length === 0 || displayName.length > ENVIRONMENT_PROVIDER_DISPLAY_NAME_MAX_CHARS) {
1922
+ throw new Error(
1923
+ `machine provider "${id}" needs a displayName of 1-${ENVIRONMENT_PROVIDER_DISPLAY_NAME_MAX_CHARS} characters`
1924
+ );
1925
+ }
1926
+ const description = z4.string().trim().min(1).max(MACHINE_PROVIDER_DESCRIPTION_MAX_CHARS).parse(declaration.description);
1927
+ const icon = z4.string().trim().min(1).parse(declaration.icon);
1928
+ if (isPluginOwnedIconPath(icon)) {
1929
+ validateProviderRelativePath(icon, `"${id}" icon`);
1930
+ } else if (!isNamespacedGlyph(icon) && /[/\\]/u.test(icon)) {
1931
+ throw new Error(
1932
+ `machine provider "${id}" icon must be a glyph, declared icon, or plugin-relative path`
1933
+ );
1934
+ }
1935
+ const ephemeral = z4.boolean().default(false).parse(declaration.ephemeral);
1936
+ const inputs = normalizeMachineProviderInputs(id, declaration);
1937
+ if (typeof declaration.create !== "function" || typeof declaration.reconcileCleanup !== "function" || typeof declaration.remove !== "function") {
1938
+ throw new Error(
1939
+ `machine provider "${id}" must declare create, reconcileCleanup and remove functions`
1940
+ );
1941
+ }
1942
+ const hasSuspend = typeof declaration.suspend === "function";
1943
+ const hasResume = typeof declaration.resume === "function";
1944
+ if (hasSuspend !== hasResume) {
1945
+ throw new Error(
1946
+ `machine provider "${id}" must declare suspend and resume together`
1947
+ );
1948
+ }
1949
+ if (declaration.validate !== void 0 && typeof declaration.validate !== "function") {
1950
+ throw new Error(
1951
+ `machine provider "${id}" declares a validate that is not a function`
1952
+ );
1953
+ }
1954
+ if (declaration.availability !== void 0 && typeof declaration.availability !== "function") {
1955
+ throw new Error(
1956
+ `machine provider "${id}" declares availability that is not a function`
1957
+ );
1958
+ }
1959
+ return {
1960
+ id,
1961
+ displayName,
1962
+ description,
1963
+ icon,
1964
+ ephemeral,
1965
+ inputs: inputs === null ? null : inputs.schema,
1966
+ inputsJsonSchema: inputs === null ? null : inputs.jsonSchema,
1967
+ availability: declaration.availability ?? null,
1968
+ validate: declaration.validate ?? null,
1969
+ reconcileCleanup: declaration.reconcileCleanup,
1970
+ create: declaration.create,
1971
+ suspend: declaration.suspend ?? null,
1972
+ resume: declaration.resume ?? null,
1973
+ remove: declaration.remove
1974
+ };
1975
+ }
1976
+ function normalizeMachineProviderInputs(id, declaration) {
1977
+ const inputs = declaration.inputs;
1978
+ if (inputs === void 0) return null;
1979
+ if (!isStandardSchema(inputs)) {
1980
+ throw new Error(
1981
+ `machine provider "${id}" declares an inputs that is not a Standard Schema v1 validator`
1982
+ );
1983
+ }
1984
+ let converted;
1985
+ try {
1986
+ converted = JSON.parse(JSON.stringify(standardSchemaToJsonSchema(inputs)));
1987
+ } catch (error) {
1988
+ throw new Error(
1989
+ `machine provider "${id}" declares an inputs validator that cannot be published as JSON Schema (${error instanceof Error ? error.message : String(error)}) \u2014 declare it with zod 4 or a validator exposing toJSONSchema()`
1990
+ );
1991
+ }
1992
+ const jsonSchema = jsonValueSchema.safeParse(converted);
1993
+ if (!jsonSchema.success) {
1994
+ throw new Error(
1995
+ `machine provider "${id}" declares an inputs schema whose JSON Schema is not JSON-serializable`
1996
+ );
1997
+ }
1998
+ return { schema: inputs, jsonSchema: jsonSchema.data };
1999
+ }
2000
+ function validateServerAccessProviderDeclaration(declaration) {
2001
+ if (typeof declaration !== "object" || declaration === null)
2002
+ throw new Error("Invalid server access provider declaration");
2003
+ if (typeof declaration.id !== "string" || !/^[a-z][a-z0-9-]*$/u.test(declaration.id) || declaration.id === "direct")
2004
+ throw new Error("Invalid or reserved server access provider id");
2005
+ if (typeof declaration.displayName !== "string" || !declaration.displayName.trim() || typeof declaration.description !== "string" || !declaration.description.trim() || typeof declaration.availability !== "function" || typeof declaration.acquire !== "function" || typeof declaration.release !== "function")
2006
+ throw new Error("Invalid server access provider declaration");
2007
+ return declaration;
2008
+ }
1902
2009
  export {
1903
2010
  AGENT_TOOL_NAME_PATTERN,
1904
2011
  BACKGROUND_NAME_PATTERN,
1905
2012
  CLI_COMMAND_NAME_PATTERN,
2013
+ ENVIRONMENT_PROVIDER_DESCRIPTION_MAX_CHARS,
1906
2014
  ENVIRONMENT_PROVIDER_DISPLAY_NAME_MAX_CHARS,
1907
2015
  ENVIRONMENT_PROVIDER_ID_PATTERN,
1908
2016
  ENVIRONMENT_PROVIDER_REQUIREMENT_NAMES,
1909
2017
  KV_VALUE_MAX_BYTES,
1910
- MACHINE_PROVIDER_REQUIREMENT_NAMES,
2018
+ MACHINE_PROVIDER_DESCRIPTION_MAX_CHARS,
1911
2019
  MENTION_PROVIDER_ID_PATTERN,
1912
2020
  PLUGIN_AGENT_DYNAMIC_INSTRUCTIONS_MAX_CHARS,
1913
2021
  PLUGIN_AGENT_SELECTION_MAX_IDS,
@@ -1936,6 +2044,7 @@ export {
1936
2044
  assertNoRecursiveJsonSchemaReferences,
1937
2045
  deriveValidatedProviderOptions,
1938
2046
  enforcePluginCliOutputLimit,
2047
+ environmentCompositionSchema,
1939
2048
  isPluginMentionTrigger,
1940
2049
  isStandardSchema,
1941
2050
  isZodSchemaLike,
@@ -1955,8 +2064,10 @@ export {
1955
2064
  undeclaredIconProblem,
1956
2065
  validatePluginAiServiceDeclaration,
1957
2066
  validatePluginEnvironmentProviderDeclaration,
2067
+ validatePluginMachineProviderDeclaration,
1958
2068
  validatePluginProviderDeclaration,
1959
2069
  validatePluginProviderEnvEntries,
2070
+ validateServerAccessProviderDeclaration,
1960
2071
  validateSettingsUpdate,
1961
2072
  zodSchemaToJsonSchema
1962
2073
  };
@@ -398,8 +398,10 @@ function collectPluginAppRegistrations(definition, onComposerCustomizationReject
398
398
  messageActions: [],
399
399
  commandPaletteActions: [],
400
400
  providerIcons: [],
401
+ icons: [],
401
402
  timelineRenderers: [],
402
403
  environmentProviderInputs: [],
404
+ machineProviderInputs: [],
403
405
  contentScripts: []
404
406
  };
405
407
  sidebarFooterItemsByRegistrationSet.set(collected, sidebarFooterItems);
@@ -425,6 +427,7 @@ function collectPluginAppRegistrations(definition, onComposerCustomizationReject
425
427
  providerIcon: /* @__PURE__ */ new Set(),
426
428
  timelineRenderer: /* @__PURE__ */ new Set(),
427
429
  environmentProviderInputs: /* @__PURE__ */ new Set(),
430
+ machineProviderInputs: /* @__PURE__ */ new Set(),
428
431
  contentScript: /* @__PURE__ */ new Set()
429
432
  };
430
433
  definition.setup({
@@ -761,8 +764,18 @@ function collectPluginAppRegistrations(definition, onComposerCustomizationReject
761
764
  experimental_providerIcon(registration) {
762
765
  const kind = "slots.experimental_providerIcon";
763
766
  const providerId = requireProviderId(kind, registration?.providerId);
764
- requireUniqueId(kind, seenIds.providerIcon, providerId);
767
+ const declaredKind = registration.providerKind;
768
+ if (declaredKind !== void 0 && declaredKind !== "agent" && declaredKind !== "machine" && declaredKind !== "environment") {
769
+ throw new Error(`${kind}: invalid providerKind`);
770
+ }
771
+ const providerKind = declaredKind ?? "all";
772
+ requireUniqueId(
773
+ kind,
774
+ seenIds.providerIcon,
775
+ `${providerKind}:${providerId}`
776
+ );
765
777
  collected.providerIcons.push({
778
+ providerKind,
766
779
  providerId,
767
780
  icon: requireComponent(kind, registration.icon)
768
781
  });
@@ -791,6 +804,18 @@ function collectPluginAppRegistrations(definition, onComposerCustomizationReject
791
804
  environmentProviderId,
792
805
  component: requireComponent(kind, registration.component)
793
806
  });
807
+ },
808
+ experimental_machineProviderInputs(registration) {
809
+ const kind = "slots.experimental_machineProviderInputs";
810
+ const machineProviderId = requireProviderId(
811
+ kind,
812
+ registration?.machineProviderId
813
+ );
814
+ requireUniqueId(kind, seenIds.machineProviderInputs, machineProviderId);
815
+ collected.machineProviderInputs.push({
816
+ machineProviderId,
817
+ component: requireComponent(kind, registration.component)
818
+ });
794
819
  }
795
820
  },
796
821
  experimental_sidebarFooter: new SidebarFooterCollector(
@@ -810,6 +835,25 @@ function collectPluginAppRegistrations(definition, onComposerCustomizationReject
810
835
  }
811
836
  }
812
837
  },
838
+ experimental_icons: {
839
+ register(registration) {
840
+ const kind = "experimental_icons.register";
841
+ const name = requireNonEmptyString(
842
+ kind,
843
+ "name",
844
+ registration?.name
845
+ ).trim();
846
+ if (name.length === 0)
847
+ throw new Error(`${kind}: "name" must not be blank`);
848
+ if (collected.icons.some((icon) => icon.name === name)) {
849
+ throw new Error(`${kind}: duplicate icon name "${name}"`);
850
+ }
851
+ collected.icons.push({
852
+ name,
853
+ component: requireComponent(kind, registration.component)
854
+ });
855
+ }
856
+ },
813
857
  contentScripts: {
814
858
  register(registration) {
815
859
  const kind = "contentScripts.register";
File without changes
@@ -2089,7 +2089,8 @@ var unscopedProviderEventSchema = z14.discriminatedUnion("type", [
2089
2089
  name: z14.string(),
2090
2090
  source: z14.union([
2091
2091
  z14.literal("shell"),
2092
- z14.object({ plugin: z14.string() }).strict()
2092
+ z14.object({ plugin: z14.string() }).strict(),
2093
+ z14.object({ core: z14.enum(["machine-git", "machine-environment"]) }).strict()
2093
2094
  ]),
2094
2095
  value: z14.union([
2095
2096
  z14.string(),
@@ -1728,7 +1728,8 @@ var unscopedProviderEventSchema = z12.discriminatedUnion("type", [
1728
1728
  name: z12.string(),
1729
1729
  source: z12.union([
1730
1730
  z12.literal("shell"),
1731
- z12.object({ plugin: z12.string() }).strict()
1731
+ z12.object({ plugin: z12.string() }).strict(),
1732
+ z12.object({ core: z12.enum(["machine-git", "machine-environment"]) }).strict()
1732
1733
  ]),
1733
1734
  value: z12.union([
1734
1735
  z12.string(),
@@ -3394,7 +3394,8 @@ var unscopedProviderEventSchema = z18.discriminatedUnion("type", [
3394
3394
  name: z18.string(),
3395
3395
  source: z18.union([
3396
3396
  z18.literal("shell"),
3397
- z18.object({ plugin: z18.string() }).strict()
3397
+ z18.object({ plugin: z18.string() }).strict(),
3398
+ z18.object({ core: z18.enum(["machine-git", "machine-environment"]) }).strict()
3398
3399
  ]),
3399
3400
  value: z18.union([
3400
3401
  z18.string(),
@@ -574,8 +574,10 @@ function collectPluginAppRegistrations(definition, onComposerCustomizationReject
574
574
  messageActions: [],
575
575
  commandPaletteActions: [],
576
576
  providerIcons: [],
577
+ icons: [],
577
578
  timelineRenderers: [],
578
579
  environmentProviderInputs: [],
580
+ machineProviderInputs: [],
579
581
  contentScripts: []
580
582
  };
581
583
  sidebarFooterItemsByRegistrationSet.set(collected, sidebarFooterItems);
@@ -601,6 +603,7 @@ function collectPluginAppRegistrations(definition, onComposerCustomizationReject
601
603
  providerIcon: /* @__PURE__ */ new Set(),
602
604
  timelineRenderer: /* @__PURE__ */ new Set(),
603
605
  environmentProviderInputs: /* @__PURE__ */ new Set(),
606
+ machineProviderInputs: /* @__PURE__ */ new Set(),
604
607
  contentScript: /* @__PURE__ */ new Set()
605
608
  };
606
609
  definition.setup({
@@ -937,8 +940,18 @@ function collectPluginAppRegistrations(definition, onComposerCustomizationReject
937
940
  experimental_providerIcon(registration) {
938
941
  const kind = "slots.experimental_providerIcon";
939
942
  const providerId = requireProviderId(kind, registration?.providerId);
940
- requireUniqueId(kind, seenIds.providerIcon, providerId);
943
+ const declaredKind = registration.providerKind;
944
+ if (declaredKind !== void 0 && declaredKind !== "agent" && declaredKind !== "machine" && declaredKind !== "environment") {
945
+ throw new Error(`${kind}: invalid providerKind`);
946
+ }
947
+ const providerKind = declaredKind ?? "all";
948
+ requireUniqueId(
949
+ kind,
950
+ seenIds.providerIcon,
951
+ `${providerKind}:${providerId}`
952
+ );
941
953
  collected.providerIcons.push({
954
+ providerKind,
942
955
  providerId,
943
956
  icon: requireComponent(kind, registration.icon)
944
957
  });
@@ -967,6 +980,18 @@ function collectPluginAppRegistrations(definition, onComposerCustomizationReject
967
980
  environmentProviderId,
968
981
  component: requireComponent(kind, registration.component)
969
982
  });
983
+ },
984
+ experimental_machineProviderInputs(registration) {
985
+ const kind = "slots.experimental_machineProviderInputs";
986
+ const machineProviderId = requireProviderId(
987
+ kind,
988
+ registration?.machineProviderId
989
+ );
990
+ requireUniqueId(kind, seenIds.machineProviderInputs, machineProviderId);
991
+ collected.machineProviderInputs.push({
992
+ machineProviderId,
993
+ component: requireComponent(kind, registration.component)
994
+ });
970
995
  }
971
996
  },
972
997
  experimental_sidebarFooter: new SidebarFooterCollector(
@@ -986,6 +1011,25 @@ function collectPluginAppRegistrations(definition, onComposerCustomizationReject
986
1011
  }
987
1012
  }
988
1013
  },
1014
+ experimental_icons: {
1015
+ register(registration) {
1016
+ const kind = "experimental_icons.register";
1017
+ const name = requireNonEmptyString(
1018
+ kind,
1019
+ "name",
1020
+ registration?.name
1021
+ ).trim();
1022
+ if (name.length === 0)
1023
+ throw new Error(`${kind}: "name" must not be blank`);
1024
+ if (collected.icons.some((icon) => icon.name === name)) {
1025
+ throw new Error(`${kind}: duplicate icon name "${name}"`);
1026
+ }
1027
+ collected.icons.push({
1028
+ name,
1029
+ component: requireComponent(kind, registration.component)
1030
+ });
1031
+ }
1032
+ },
989
1033
  contentScripts: {
990
1034
  register(registration) {
991
1035
  const kind = "contentScripts.register";
@@ -1499,6 +1543,24 @@ var testPluginSdkApp = {
1499
1543
  ThreadChat: TestThreadChat,
1500
1544
  Markdown: TestMarkdown,
1501
1545
  experimental_FileLink: TestFileLink,
1546
+ experimental_Icon: ({ name, fallback, ...props }) => /* @__PURE__ */ jsx("span", { ...props, "data-icon": name, "data-icon-fallback": fallback }),
1547
+ experimental_ProviderIcon: ({
1548
+ providerKind,
1549
+ provider,
1550
+ fallback,
1551
+ ...props
1552
+ }) => /* @__PURE__ */ jsx(
1553
+ "span",
1554
+ {
1555
+ ...props,
1556
+ "data-provider-kind": providerKind,
1557
+ "data-provider-id": provider.id,
1558
+ "data-provider-logo": provider.logoUrl ?? void 0,
1559
+ "data-provider-glyph": (typeof provider.icon === "string" ? provider.icon : provider.icon?.glyph) ?? void 0,
1560
+ "data-provider-tint": provider.strings?.iconTint == null ? void 0 : JSON.stringify(provider.strings.iconTint),
1561
+ "data-provider-fallback": fallback
1562
+ }
1563
+ ),
1502
1564
  UrlLink: TestUrlLink,
1503
1565
  experimental_NewThreadComposer: TestNewThreadComposer,
1504
1566
  experimental_ProviderModelPicker: TestProviderModelPicker,