@get-bb/plugin-sdk 0.4.47 → 0.4.50

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.
@@ -12,7 +12,7 @@ var PLUGIN_INTERACTION_MAX_TITLE_LENGTH = 160;
12
12
  var PLUGIN_INTERACTION_MAX_PAYLOAD_BYTES = 64 * 1024;
13
13
 
14
14
  // src/internal/host-policy.ts
15
- import { z as z3 } from "zod";
15
+ import { z as z4 } from "zod";
16
16
 
17
17
  // ../domain/src/plugin-icon.ts
18
18
  function isPluginOwnedIconPath(icon) {
@@ -36,6 +36,7 @@ function parseNamespacedGlyph(glyph) {
36
36
 
37
37
  // ../domain/src/plugin-cli.ts
38
38
  var RESERVED_BB_CLI_COMMANDS = [
39
+ "browser",
39
40
  "environment",
40
41
  "file",
41
42
  "guide",
@@ -82,37 +83,54 @@ function isRelativeProviderSkillRootPath(value) {
82
83
  return !normalized.startsWith("/") && !/^[a-zA-Z]:\//u.test(normalized) && normalized.split("/").every((segment) => segment !== "" && segment !== "." && segment !== "..");
83
84
  }
84
85
 
85
- // ../domain/src/native-roots.ts
86
+ // ../domain/src/json-value.ts
86
87
  import { z as z2 } from "zod";
88
+ var jsonValueSchema = z2.lazy(
89
+ () => z2.union([
90
+ z2.string(),
91
+ z2.number(),
92
+ z2.boolean(),
93
+ z2.null(),
94
+ z2.array(jsonValueSchema),
95
+ z2.record(z2.string(), jsonValueSchema)
96
+ ])
97
+ );
98
+ var jsonObjectSchema = z2.record(
99
+ z2.string(),
100
+ jsonValueSchema
101
+ );
102
+
103
+ // ../domain/src/native-roots.ts
104
+ import { z as z3 } from "zod";
87
105
  var PROVIDER_NATIVE_ROOTS_MAX = 32;
88
106
  var PROVIDER_NATIVE_ROOT_NAME_PREFIX_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,62}:$/u;
89
- var nativeRootNamePrefixSchema = z2.string().refine(
107
+ var nativeRootNamePrefixSchema = z3.string().refine(
90
108
  (value) => value === "" || PROVIDER_NATIVE_ROOT_NAME_PREFIX_PATTERN.test(value),
91
109
  "A root name prefix is a plugin-name-like token ending in ':'"
92
110
  );
93
- var nativeRootManifestPathSchema = z2.string().min(1).refine(
111
+ var nativeRootManifestPathSchema = z3.string().min(1).refine(
94
112
  isRelativeProviderSkillRootPath,
95
113
  "A manifest marker is a relative path without dot segments"
96
114
  );
97
- var relativeNativeRootPathSchema = z2.string().min(1).refine(
115
+ var relativeNativeRootPathSchema = z3.string().min(1).refine(
98
116
  isRelativeProviderSkillRootPath,
99
117
  "Roots must be relative paths without dot segments"
100
118
  );
101
- var absoluteNativeRootPathSchema = z2.string().min(1).refine(
119
+ var absoluteNativeRootPathSchema = z3.string().min(1).refine(
102
120
  isAbsoluteProviderSkillRootPath,
103
121
  "Absolute roots must be absolute paths without dot segments"
104
122
  );
105
- var providerNativeRootInputSchema = z2.union([
106
- z2.string().min(1),
107
- z2.object({
108
- path: z2.string().min(1),
123
+ var providerNativeRootInputSchema = z3.union([
124
+ z3.string().min(1),
125
+ z3.object({
126
+ path: z3.string().min(1),
109
127
  /** Skills nest in subdirectories (the agent scans recursively). */
110
- recursive: z2.boolean().optional(),
128
+ recursive: z3.boolean().optional(),
111
129
  /**
112
130
  * Scan the same relative directory in every ancestor of the workspace
113
131
  * up to the repository root (`project` roots only).
114
132
  */
115
- ancestors: z2.boolean().optional(),
133
+ ancestors: z3.boolean().optional(),
116
134
  /**
117
135
  * Prepended to every name under the root, a vendor plugin's
118
136
  * `plugin-name:`; a prefixed root is listed as a plugin root.
@@ -127,14 +145,14 @@ var providerNativeRootInputSchema = z2.union([
127
145
  skipIfManifest: nativeRootManifestPathSchema.optional()
128
146
  }).strict()
129
147
  ]);
130
- var providerNativeRootsInputSchema = z2.object({
131
- user: z2.array(providerNativeRootInputSchema).optional(),
132
- project: z2.array(providerNativeRootInputSchema).optional()
148
+ var providerNativeRootsInputSchema = z3.object({
149
+ user: z3.array(providerNativeRootInputSchema).optional(),
150
+ project: z3.array(providerNativeRootInputSchema).optional()
133
151
  }).strict();
134
- var providerNativeRootSchema = z2.object({
135
- path: z2.string().min(1),
136
- recursive: z2.boolean(),
137
- ancestors: z2.boolean(),
152
+ var providerNativeRootSchema = z3.object({
153
+ path: z3.string().min(1),
154
+ recursive: z3.boolean(),
155
+ ancestors: z3.boolean(),
138
156
  namePrefix: nativeRootNamePrefixSchema,
139
157
  /** Absent: every skill-shaped directory under the root is a skill. */
140
158
  skipIfManifest: nativeRootManifestPathSchema.optional()
@@ -143,7 +161,7 @@ function uniqueByPath(roots) {
143
161
  return new Set(roots.map((root) => root.path)).size === roots.length;
144
162
  }
145
163
  function nativeRootSideSchema(side) {
146
- return z2.array(
164
+ return z3.array(
147
165
  providerNativeRootSchema.extend({ path: relativeNativeRootPathSchema }).superRefine((root, context) => {
148
166
  if (root.ancestors && side !== "project") {
149
167
  context.addIssue({
@@ -154,7 +172,7 @@ function nativeRootSideSchema(side) {
154
172
  })
155
173
  ).max(PROVIDER_NATIVE_ROOTS_MAX).refine(uniqueByPath, "Roots must not repeat a path");
156
174
  }
157
- var providerNativeRootsSchema = z2.object({
175
+ var providerNativeRootsSchema = z3.object({
158
176
  user: nativeRootSideSchema("user"),
159
177
  project: nativeRootSideSchema("project")
160
178
  }).strict();
@@ -180,19 +198,19 @@ function normalizeProviderNativeRoots(roots) {
180
198
  project: (roots?.project ?? []).map(normalizeProviderNativeRoot)
181
199
  };
182
200
  }
183
- var providerResolvedNativeRootShapeSchema = z2.enum([
201
+ var providerResolvedNativeRootShapeSchema = z3.enum([
184
202
  "skills",
185
203
  "skill",
186
204
  "skill-file",
187
205
  "commands",
188
206
  "command-file"
189
207
  ]);
190
- var resolvedNativeRootFieldsSchema = z2.object({
208
+ var resolvedNativeRootFieldsSchema = z3.object({
191
209
  path: absoluteNativeRootPathSchema,
192
- origin: z2.enum(["user", "project"]),
193
- recursive: z2.boolean(),
210
+ origin: z3.enum(["user", "project"]),
211
+ recursive: z3.boolean(),
194
212
  /** Only with origin `project`, for a path inside the workspace. */
195
- ancestors: z2.boolean(),
213
+ ancestors: z3.boolean(),
196
214
  namePrefix: nativeRootNamePrefixSchema,
197
215
  shape: providerResolvedNativeRootShapeSchema,
198
216
  /**
@@ -200,7 +218,7 @@ var resolvedNativeRootFieldsSchema = z2.object({
200
218
  * none. A vendor plugin's root SKILL.md takes the plugin's name; absent
201
219
  * means the parent directory's name.
202
220
  */
203
- fallbackName: z2.string().min(1).optional(),
221
+ fallbackName: z3.string().min(1).optional(),
204
222
  /**
205
223
  * `skills` only: a file, relative to a skill directory under this root,
206
224
  * that marks the directory as a vendor plugin rather than a skill; the
@@ -244,14 +262,14 @@ var resolvedCommandShapes = /* @__PURE__ */ new Set([
244
262
  "command-file"
245
263
  ]);
246
264
  var PROVIDER_RESOLVED_NATIVE_ROOTS_MAX = 256;
247
- var providerResolvedNativeRootsSchema = z2.object({
248
- skills: z2.array(
265
+ var providerResolvedNativeRootsSchema = z3.object({
266
+ skills: z3.array(
249
267
  providerResolvedNativeRootSchema.refine(
250
268
  (root) => resolvedSkillShapes.has(root.shape),
251
269
  "A skills root needs a skill shape"
252
270
  )
253
271
  ).max(PROVIDER_RESOLVED_NATIVE_ROOTS_MAX),
254
- commands: z2.array(
272
+ commands: z3.array(
255
273
  providerResolvedNativeRootSchema.refine(
256
274
  (root) => resolvedCommandShapes.has(root.shape),
257
275
  "A commands root needs a command shape"
@@ -262,7 +280,7 @@ var EMPTY_PROVIDER_RESOLVED_NATIVE_ROOTS = Object.freeze({
262
280
  skills: Object.freeze([]),
263
281
  commands: Object.freeze([])
264
282
  });
265
- var providerNativeRootSetSchema = z2.object({
283
+ var providerNativeRootSetSchema = z3.object({
266
284
  skills: providerNativeRootsSchema,
267
285
  commands: providerNativeRootsSchema,
268
286
  resolved: providerResolvedNativeRootsSchema
@@ -295,16 +313,16 @@ var CLI_COMMAND_NAME_PATTERN = /^[a-z0-9-]+$/;
295
313
  var AGENT_TOOL_NAME_PATTERN = /^[a-zA-Z0-9_-]+$/;
296
314
  var PLUGIN_PROVIDER_ENV_NAME_PATTERN = /^[A-Z_][A-Z0-9_]*$/;
297
315
  var PLUGIN_PROVIDER_ENV_MAX_ENTRIES = 32;
298
- var pluginProviderEnvEntrySchema = z3.object({
299
- name: z3.string().regex(PLUGIN_PROVIDER_ENV_NAME_PATTERN),
300
- value: z3.union([
301
- z3.string(),
302
- z3.object({ serverPath: z3.string().startsWith("/") }).strict()
316
+ var pluginProviderEnvEntrySchema = z4.object({
317
+ name: z4.string().regex(PLUGIN_PROVIDER_ENV_NAME_PATTERN),
318
+ value: z4.union([
319
+ z4.string(),
320
+ z4.object({ serverPath: z4.string().startsWith("/") }).strict()
303
321
  ]),
304
- reason: z3.string(),
305
- secret: z3.boolean()
322
+ reason: z4.string(),
323
+ secret: z4.boolean()
306
324
  }).strict();
307
- var pluginProviderEnvEntriesSchema = z3.array(pluginProviderEnvEntrySchema).max(PLUGIN_PROVIDER_ENV_MAX_ENTRIES).superRefine((entries, context) => {
325
+ var pluginProviderEnvEntriesSchema = z4.array(pluginProviderEnvEntrySchema).max(PLUGIN_PROVIDER_ENV_MAX_ENTRIES).superRefine((entries, context) => {
308
326
  const names = /* @__PURE__ */ new Set();
309
327
  for (let index = 0; index < entries.length; index += 1) {
310
328
  const name = entries[index]?.name;
@@ -339,26 +357,26 @@ var PROVIDER_ID_PATTERN = /^[a-z0-9][a-z0-9-]{1,63}$/;
339
357
  var PLUGIN_PROVIDER_BRIDGE_OPTIONS_MAX_BYTES = 64 * 1024;
340
358
  var SETTING_KEY_PATTERN = /^[a-zA-Z0-9_-]+$/;
341
359
  var settingsBaseFields = {
342
- label: z3.string().min(1),
343
- description: z3.string().min(1).optional()
360
+ label: z4.string().min(1),
361
+ description: z4.string().min(1).optional()
344
362
  };
345
- var stringSettingSchemaSchema = z3.custom(
363
+ var stringSettingSchemaSchema = z4.custom(
346
364
  (value) => isStandardSchema(value)
347
365
  );
348
- var booleanSettingSchemaSchema = z3.custom(
366
+ var booleanSettingSchemaSchema = z4.custom(
349
367
  (value) => isStandardSchema(value)
350
368
  );
351
- var numberSettingSchemaSchema = z3.custom(
369
+ var numberSettingSchemaSchema = z4.custom(
352
370
  (value) => isStandardSchema(value)
353
371
  );
354
- var settingDescriptorSchema = z3.discriminatedUnion("type", [
355
- z3.object({
356
- type: z3.literal("string"),
372
+ var settingDescriptorSchema = z4.discriminatedUnion("type", [
373
+ z4.object({
374
+ type: z4.literal("string"),
357
375
  ...settingsBaseFields,
358
- secret: z3.literal(true).optional(),
359
- experimental_multiline: z3.boolean().optional(),
376
+ secret: z4.literal(true).optional(),
377
+ experimental_multiline: z4.boolean().optional(),
360
378
  experimental_schema: stringSettingSchemaSchema.optional(),
361
- default: z3.string().optional()
379
+ default: z4.string().optional()
362
380
  }).strict().refine(
363
381
  (descriptor) => !(descriptor.secret === true && descriptor.experimental_multiline === true),
364
382
  {
@@ -366,30 +384,30 @@ var settingDescriptorSchema = z3.discriminatedUnion("type", [
366
384
  path: ["experimental_multiline"]
367
385
  }
368
386
  ),
369
- z3.object({
370
- type: z3.literal("boolean"),
387
+ z4.object({
388
+ type: z4.literal("boolean"),
371
389
  ...settingsBaseFields,
372
390
  experimental_schema: booleanSettingSchemaSchema.optional(),
373
- default: z3.boolean().optional()
391
+ default: z4.boolean().optional()
374
392
  }).strict(),
375
- z3.object({
376
- type: z3.literal("number"),
393
+ z4.object({
394
+ type: z4.literal("number"),
377
395
  ...settingsBaseFields,
378
396
  experimental_schema: numberSettingSchemaSchema.optional(),
379
- default: z3.number().finite().optional()
397
+ default: z4.number().finite().optional()
380
398
  }).strict(),
381
- z3.object({
382
- type: z3.literal("select"),
399
+ z4.object({
400
+ type: z4.literal("select"),
383
401
  ...settingsBaseFields,
384
- options: z3.array(z3.string().min(1)).min(1),
402
+ options: z4.array(z4.string().min(1)).min(1),
385
403
  experimental_schema: stringSettingSchemaSchema.optional(),
386
- default: z3.string().optional()
404
+ default: z4.string().optional()
387
405
  }).strict(),
388
- z3.object({
389
- type: z3.literal("project"),
406
+ z4.object({
407
+ type: z4.literal("project"),
390
408
  ...settingsBaseFields,
391
409
  experimental_schema: stringSettingSchemaSchema.optional(),
392
- default: z3.string().optional()
410
+ default: z4.string().optional()
393
411
  }).strict()
394
412
  ]);
395
413
  function registerSettingDescriptors(target, added) {
@@ -1409,11 +1427,21 @@ function readRpcMethodContract(method, value) {
1409
1427
  function isZodSchemaLike(value) {
1410
1428
  return typeof value === "object" && value !== null && typeof value.safeParse === "function";
1411
1429
  }
1430
+ function standardSchemaToJsonSchema(schema) {
1431
+ if (isZodSchemaLike(schema)) {
1432
+ return zodSchemaToJsonSchema(schema);
1433
+ }
1434
+ const convertible = schema;
1435
+ if (typeof convertible.toJSONSchema === "function") {
1436
+ return convertible.toJSONSchema();
1437
+ }
1438
+ throw new Error("the validator exposes no JSON Schema conversion");
1439
+ }
1412
1440
  function zodSchemaToJsonSchema(schema) {
1413
1441
  if (typeof schema.toJSONSchema === "function") {
1414
1442
  return schema.toJSONSchema({ io: "input" });
1415
1443
  }
1416
- return z3.toJSONSchema(schema, { io: "input" });
1444
+ return z4.toJSONSchema(schema, { io: "input" });
1417
1445
  }
1418
1446
  var SINGLE_SCHEMA_KEYWORDS = [
1419
1447
  "additionalItems",
@@ -1739,6 +1767,130 @@ function storePluginHook(records, hook, handler) {
1739
1767
  function pluginHookAlreadyRegisteredMessage(hook) {
1740
1768
  return `a "${hook}" hook handler is already registered by this plugin`;
1741
1769
  }
1770
+ var ENVIRONMENT_PROVIDER_ID_PATTERN = /^[a-z0-9][a-z0-9-]{1,63}$/;
1771
+ var ENVIRONMENT_PROVIDER_DISPLAY_NAME_MAX_CHARS = 80;
1772
+ var ENVIRONMENT_PROVIDER_REQUIREMENT_NAMES = [
1773
+ "projectCheckout",
1774
+ "gitCheckout",
1775
+ "gitRemote",
1776
+ "projectless"
1777
+ ];
1778
+ function validatePluginEnvironmentProviderDeclaration(declaration) {
1779
+ if (typeof declaration !== "object" || declaration === null) {
1780
+ throw new Error("environment provider declaration must be an object");
1781
+ }
1782
+ const id = declaration.id;
1783
+ if (typeof id !== "string" || !ENVIRONMENT_PROVIDER_ID_PATTERN.test(id)) {
1784
+ throw new Error(
1785
+ `invalid environment provider id ${JSON.stringify(id)} \u2014 use 2-64 lowercase letters, digits, or "-", starting with a letter or digit`
1786
+ );
1787
+ }
1788
+ const displayName = typeof declaration.displayName === "string" ? declaration.displayName.trim() : "";
1789
+ if (displayName.length === 0 || displayName.length > ENVIRONMENT_PROVIDER_DISPLAY_NAME_MAX_CHARS) {
1790
+ throw new Error(
1791
+ `environment provider "${id}" needs a displayName of 1-${ENVIRONMENT_PROVIDER_DISPLAY_NAME_MAX_CHARS} characters`
1792
+ );
1793
+ }
1794
+ const icon = declaration.icon === void 0 ? null : z4.string().min(1).parse(declaration.icon).trim();
1795
+ if (icon !== null) {
1796
+ if (isPluginOwnedIconPath(icon))
1797
+ validateProviderRelativePath(icon, `"${id}" icon`);
1798
+ else if (!isNamespacedGlyph(icon) && /[/\\]/u.test(icon))
1799
+ throw new Error(
1800
+ `environment provider "${id}" icon must be a glyph, declared icon, or plugin-relative path`
1801
+ );
1802
+ }
1803
+ if (icon !== null && icon.length === 0) {
1804
+ throw new Error(`environment provider "${id}" declares an empty icon`);
1805
+ }
1806
+ const requires = normalizeEnvironmentProviderRequirements(id, declaration);
1807
+ const inputs = normalizeEnvironmentProviderInputs(id, declaration);
1808
+ if (typeof declaration.create !== "function" || typeof declaration.remove !== "function") {
1809
+ throw new Error(
1810
+ `environment provider "${id}" must declare create and remove functions`
1811
+ );
1812
+ }
1813
+ if (declaration.validate !== void 0 && typeof declaration.validate !== "function") {
1814
+ throw new Error(
1815
+ `environment provider "${id}" declares a validate that is not a function`
1816
+ );
1817
+ }
1818
+ if (declaration.availability !== void 0 && typeof declaration.availability !== "function") {
1819
+ throw new Error(
1820
+ `environment provider "${id}" declares availability that is not a function`
1821
+ );
1822
+ }
1823
+ return {
1824
+ id,
1825
+ displayName,
1826
+ icon,
1827
+ requires,
1828
+ inputs: inputs === null ? null : inputs.schema,
1829
+ inputsJsonSchema: inputs === null ? null : inputs.jsonSchema,
1830
+ availability: declaration.availability ?? null,
1831
+ validate: declaration.validate ?? null,
1832
+ create: declaration.create,
1833
+ remove: declaration.remove,
1834
+ policy: environmentProviderPolicySchema.parse(declaration.policy ?? {})
1835
+ };
1836
+ }
1837
+ function normalizeEnvironmentProviderInputs(id, declaration) {
1838
+ const inputs = declaration.inputs;
1839
+ if (inputs === void 0) {
1840
+ return null;
1841
+ }
1842
+ if (!isStandardSchema(inputs)) {
1843
+ throw new Error(
1844
+ `environment provider "${id}" declares an inputs that is not a Standard Schema v1 validator`
1845
+ );
1846
+ }
1847
+ let converted;
1848
+ try {
1849
+ converted = JSON.parse(JSON.stringify(standardSchemaToJsonSchema(inputs)));
1850
+ } catch (error) {
1851
+ throw new Error(
1852
+ `environment 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()`
1853
+ );
1854
+ }
1855
+ const jsonSchema = jsonValueSchema.safeParse(converted);
1856
+ if (!jsonSchema.success) {
1857
+ throw new Error(
1858
+ `environment provider "${id}" declares an inputs schema whose JSON Schema is not JSON-serializable`
1859
+ );
1860
+ }
1861
+ return { schema: inputs, jsonSchema: jsonSchema.data };
1862
+ }
1863
+ function normalizeEnvironmentProviderRequirements(id, declaration) {
1864
+ const requires = declaration.requires ?? {};
1865
+ if (typeof requires !== "object" || requires === null || Array.isArray(requires)) {
1866
+ throw new Error(
1867
+ `environment provider "${id}" declares a requires that is not an object`
1868
+ );
1869
+ }
1870
+ const normalized = {};
1871
+ for (const name of ENVIRONMENT_PROVIDER_REQUIREMENT_NAMES) {
1872
+ const value = requires[name];
1873
+ if (value !== void 0 && typeof value !== "boolean") {
1874
+ throw new Error(
1875
+ `environment provider "${id}" declares a requires.${name} that is not a boolean`
1876
+ );
1877
+ }
1878
+ normalized[name] = value === true;
1879
+ }
1880
+ if (normalized.gitCheckout) {
1881
+ normalized.projectCheckout = true;
1882
+ }
1883
+ if (normalized.projectless && (normalized.projectCheckout || normalized.gitRemote)) {
1884
+ throw new Error(
1885
+ `environment provider "${id}" declares requires.projectless together with a project requirement \u2014 a projectless thread has no checkout or remote`
1886
+ );
1887
+ }
1888
+ return normalized;
1889
+ }
1890
+ var environmentProviderPolicySchema = z4.object({
1891
+ retireGraceMs: z4.number().int().nonnegative().nullable().default(3e5),
1892
+ pathKeys: z4.enum(["per-thread", "per-attempt"]).default("per-thread")
1893
+ }).strict();
1742
1894
 
1743
1895
  // src/testing/fake-sdk.ts
1744
1896
  function withSpawnAttribution(pluginId, args) {
@@ -2777,11 +2929,14 @@ function createFakePluginHostInternal(options, sharedState) {
2777
2929
  "interaction.pending": [],
2778
2930
  "message.queued": [],
2779
2931
  "message.dispatched": [],
2780
- "turn.failed": []
2932
+ "turn.failed": [],
2933
+ "message.cancelled": [],
2934
+ "thread.unarchived": []
2781
2935
  };
2782
2936
  const hooks = {
2783
2937
  "message.dispatch": null
2784
2938
  };
2939
+ const environmentProviders = /* @__PURE__ */ new Map();
2785
2940
  const disposeHooks = [];
2786
2941
  const serviceControllers = [];
2787
2942
  let nextInteractionId = 1;
@@ -3048,6 +3203,20 @@ function createFakePluginHostInternal(options, sharedState) {
3048
3203
  requestedDrains += 1;
3049
3204
  }
3050
3205
  };
3206
+ const experimental_environments = {
3207
+ register(declaration) {
3208
+ assertLive();
3209
+ const target = validatePluginEnvironmentProviderDeclaration(declaration);
3210
+ const problem = target.icon === null ? null : undeclaredIconProblem(pluginId, declaredIconNames, target.icon);
3211
+ if (problem !== null)
3212
+ throw new Error(providerIconRefusalMessage(target.id, problem));
3213
+ environmentProviders.set(target.id, target);
3214
+ },
3215
+ async recheck() {
3216
+ assertLive();
3217
+ requestedDrains += 1;
3218
+ }
3219
+ };
3051
3220
  const bb = {
3052
3221
  pluginId,
3053
3222
  log,
@@ -3063,6 +3232,7 @@ function createFakePluginHostInternal(options, sharedState) {
3063
3232
  ui,
3064
3233
  events,
3065
3234
  experimental_hooks,
3235
+ experimental_environments,
3066
3236
  status,
3067
3237
  server,
3068
3238
  hosts,
@@ -3159,12 +3329,17 @@ function createFakePluginHostInternal(options, sharedState) {
3159
3329
  "interaction.pending": threadEventHandlers["interaction.pending"].length,
3160
3330
  "message.queued": threadEventHandlers["message.queued"].length,
3161
3331
  "message.dispatched": threadEventHandlers["message.dispatched"].length,
3162
- "turn.failed": threadEventHandlers["turn.failed"].length
3332
+ "turn.failed": threadEventHandlers["turn.failed"].length,
3333
+ "message.cancelled": threadEventHandlers["message.cancelled"].length,
3334
+ "thread.unarchived": threadEventHandlers["thread.unarchived"].length
3163
3335
  };
3164
3336
  },
3165
3337
  get hooks() {
3166
3338
  return { ...hooks };
3167
3339
  },
3340
+ get environmentProviders() {
3341
+ return new Map(environmentProviders);
3342
+ },
3168
3343
  mentionProviders,
3169
3344
  providerRegistrations,
3170
3345
  providerEnvResolvers,
@@ -3633,8 +3808,8 @@ function makePluginAgentConfigurationContext(overrides = {}) {
3633
3808
  id: "environment-test",
3634
3809
  name: null,
3635
3810
  path: "/tmp/test",
3636
- workspaceProvisionType: "unmanaged",
3637
- branchName: null
3811
+ branchName: null,
3812
+ workspaceProvisionType: null
3638
3813
  },
3639
3814
  host: { id: "host-test", name: "Test host" },
3640
3815
  provider: {
@@ -3693,7 +3868,8 @@ function makeMessageDispatchHookContext(overrides = {}) {
3693
3868
  origin: null,
3694
3869
  originPluginId: null,
3695
3870
  startedOnBehalfOf: null,
3696
- parentThreadId: null
3871
+ parentThreadId: null,
3872
+ environmentIntent: null
3697
3873
  };
3698
3874
  const environmentDefaults = {
3699
3875
  id: "environment-1",
@@ -3701,14 +3877,18 @@ function makeMessageDispatchHookContext(overrides = {}) {
3701
3877
  projectId: "project-1",
3702
3878
  hostId: "host-1",
3703
3879
  path: "/tmp/test",
3704
- managed: true,
3705
3880
  isGitRepo: true,
3706
3881
  isWorktree: false,
3707
- workspaceProvisionType: "unmanaged",
3708
3882
  branchName: "main",
3709
3883
  baseBranch: null,
3710
3884
  defaultBranch: "main",
3711
3885
  mergeBaseBranch: null,
3886
+ environmentProviderId: null,
3887
+ environmentProviderSelection: null,
3888
+ environmentProviderInstanceKey: null,
3889
+ lifecycle: { phase: "active", retireAt: null, teardown: null },
3890
+ managed: false,
3891
+ workspaceProvisionType: null,
3712
3892
  status: "ready",
3713
3893
  createdAt: 0,
3714
3894
  updatedAt: 0
@@ -3716,8 +3896,8 @@ function makeMessageDispatchHookContext(overrides = {}) {
3716
3896
  const hostDefaults = {
3717
3897
  id: "host-1",
3718
3898
  name: "Test host",
3719
- type: "persistent",
3720
3899
  status: "connected",
3900
+ type: "persistent",
3721
3901
  maxPermissionMode: "full",
3722
3902
  lastSeenAt: null,
3723
3903
  lastRejectedProtocolVersion: null,
@@ -3763,6 +3943,8 @@ function makeMessageDispatchHookContext(overrides = {}) {
3763
3943
  function makeQueueEntry(overrides = {}) {
3764
3944
  return {
3765
3945
  id: "queued_1",
3946
+ initiator: "user",
3947
+ senderThreadId: null,
3766
3948
  threadId: "thread-1",
3767
3949
  content: [{ type: "text", text: "Queued turn", mentions: [] }],
3768
3950
  model: "test-model",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@get-bb/plugin-sdk",
3
- "version": "0.4.47",
3
+ "version": "0.4.50",
4
4
  "homepage": "https://github.com/get-bb/bb#readme",
5
5
  "bugs": {
6
6
  "url": "https://github.com/get-bb/bb/issues"
@@ -50,6 +50,12 @@
50
50
  "import": "./dist/provider-bridge-acp.js",
51
51
  "default": "./dist/provider-bridge-acp.js"
52
52
  },
53
+ "./environment-provider": {
54
+ "source": "./src/environment-provider.ts",
55
+ "types": "./bundled-types/bb-plugin-sdk-environment-provider.d.ts",
56
+ "import": "./dist/environment-provider.js",
57
+ "default": "./dist/environment-provider.js"
58
+ },
53
59
  "./app": {
54
60
  "source": "./src/app.ts",
55
61
  "types": "./bundled-types/bb-plugin-sdk-app.d.ts",