@get-bb/plugin-sdk 0.4.48 → 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) {
@@ -83,37 +83,54 @@ function isRelativeProviderSkillRootPath(value) {
83
83
  return !normalized.startsWith("/") && !/^[a-zA-Z]:\//u.test(normalized) && normalized.split("/").every((segment) => segment !== "" && segment !== "." && segment !== "..");
84
84
  }
85
85
 
86
- // ../domain/src/native-roots.ts
86
+ // ../domain/src/json-value.ts
87
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";
88
105
  var PROVIDER_NATIVE_ROOTS_MAX = 32;
89
106
  var PROVIDER_NATIVE_ROOT_NAME_PREFIX_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,62}:$/u;
90
- var nativeRootNamePrefixSchema = z2.string().refine(
107
+ var nativeRootNamePrefixSchema = z3.string().refine(
91
108
  (value) => value === "" || PROVIDER_NATIVE_ROOT_NAME_PREFIX_PATTERN.test(value),
92
109
  "A root name prefix is a plugin-name-like token ending in ':'"
93
110
  );
94
- var nativeRootManifestPathSchema = z2.string().min(1).refine(
111
+ var nativeRootManifestPathSchema = z3.string().min(1).refine(
95
112
  isRelativeProviderSkillRootPath,
96
113
  "A manifest marker is a relative path without dot segments"
97
114
  );
98
- var relativeNativeRootPathSchema = z2.string().min(1).refine(
115
+ var relativeNativeRootPathSchema = z3.string().min(1).refine(
99
116
  isRelativeProviderSkillRootPath,
100
117
  "Roots must be relative paths without dot segments"
101
118
  );
102
- var absoluteNativeRootPathSchema = z2.string().min(1).refine(
119
+ var absoluteNativeRootPathSchema = z3.string().min(1).refine(
103
120
  isAbsoluteProviderSkillRootPath,
104
121
  "Absolute roots must be absolute paths without dot segments"
105
122
  );
106
- var providerNativeRootInputSchema = z2.union([
107
- z2.string().min(1),
108
- z2.object({
109
- path: z2.string().min(1),
123
+ var providerNativeRootInputSchema = z3.union([
124
+ z3.string().min(1),
125
+ z3.object({
126
+ path: z3.string().min(1),
110
127
  /** Skills nest in subdirectories (the agent scans recursively). */
111
- recursive: z2.boolean().optional(),
128
+ recursive: z3.boolean().optional(),
112
129
  /**
113
130
  * Scan the same relative directory in every ancestor of the workspace
114
131
  * up to the repository root (`project` roots only).
115
132
  */
116
- ancestors: z2.boolean().optional(),
133
+ ancestors: z3.boolean().optional(),
117
134
  /**
118
135
  * Prepended to every name under the root, a vendor plugin's
119
136
  * `plugin-name:`; a prefixed root is listed as a plugin root.
@@ -128,14 +145,14 @@ var providerNativeRootInputSchema = z2.union([
128
145
  skipIfManifest: nativeRootManifestPathSchema.optional()
129
146
  }).strict()
130
147
  ]);
131
- var providerNativeRootsInputSchema = z2.object({
132
- user: z2.array(providerNativeRootInputSchema).optional(),
133
- project: z2.array(providerNativeRootInputSchema).optional()
148
+ var providerNativeRootsInputSchema = z3.object({
149
+ user: z3.array(providerNativeRootInputSchema).optional(),
150
+ project: z3.array(providerNativeRootInputSchema).optional()
134
151
  }).strict();
135
- var providerNativeRootSchema = z2.object({
136
- path: z2.string().min(1),
137
- recursive: z2.boolean(),
138
- ancestors: z2.boolean(),
152
+ var providerNativeRootSchema = z3.object({
153
+ path: z3.string().min(1),
154
+ recursive: z3.boolean(),
155
+ ancestors: z3.boolean(),
139
156
  namePrefix: nativeRootNamePrefixSchema,
140
157
  /** Absent: every skill-shaped directory under the root is a skill. */
141
158
  skipIfManifest: nativeRootManifestPathSchema.optional()
@@ -144,7 +161,7 @@ function uniqueByPath(roots) {
144
161
  return new Set(roots.map((root) => root.path)).size === roots.length;
145
162
  }
146
163
  function nativeRootSideSchema(side) {
147
- return z2.array(
164
+ return z3.array(
148
165
  providerNativeRootSchema.extend({ path: relativeNativeRootPathSchema }).superRefine((root, context) => {
149
166
  if (root.ancestors && side !== "project") {
150
167
  context.addIssue({
@@ -155,7 +172,7 @@ function nativeRootSideSchema(side) {
155
172
  })
156
173
  ).max(PROVIDER_NATIVE_ROOTS_MAX).refine(uniqueByPath, "Roots must not repeat a path");
157
174
  }
158
- var providerNativeRootsSchema = z2.object({
175
+ var providerNativeRootsSchema = z3.object({
159
176
  user: nativeRootSideSchema("user"),
160
177
  project: nativeRootSideSchema("project")
161
178
  }).strict();
@@ -181,19 +198,19 @@ function normalizeProviderNativeRoots(roots) {
181
198
  project: (roots?.project ?? []).map(normalizeProviderNativeRoot)
182
199
  };
183
200
  }
184
- var providerResolvedNativeRootShapeSchema = z2.enum([
201
+ var providerResolvedNativeRootShapeSchema = z3.enum([
185
202
  "skills",
186
203
  "skill",
187
204
  "skill-file",
188
205
  "commands",
189
206
  "command-file"
190
207
  ]);
191
- var resolvedNativeRootFieldsSchema = z2.object({
208
+ var resolvedNativeRootFieldsSchema = z3.object({
192
209
  path: absoluteNativeRootPathSchema,
193
- origin: z2.enum(["user", "project"]),
194
- recursive: z2.boolean(),
210
+ origin: z3.enum(["user", "project"]),
211
+ recursive: z3.boolean(),
195
212
  /** Only with origin `project`, for a path inside the workspace. */
196
- ancestors: z2.boolean(),
213
+ ancestors: z3.boolean(),
197
214
  namePrefix: nativeRootNamePrefixSchema,
198
215
  shape: providerResolvedNativeRootShapeSchema,
199
216
  /**
@@ -201,7 +218,7 @@ var resolvedNativeRootFieldsSchema = z2.object({
201
218
  * none. A vendor plugin's root SKILL.md takes the plugin's name; absent
202
219
  * means the parent directory's name.
203
220
  */
204
- fallbackName: z2.string().min(1).optional(),
221
+ fallbackName: z3.string().min(1).optional(),
205
222
  /**
206
223
  * `skills` only: a file, relative to a skill directory under this root,
207
224
  * that marks the directory as a vendor plugin rather than a skill; the
@@ -245,14 +262,14 @@ var resolvedCommandShapes = /* @__PURE__ */ new Set([
245
262
  "command-file"
246
263
  ]);
247
264
  var PROVIDER_RESOLVED_NATIVE_ROOTS_MAX = 256;
248
- var providerResolvedNativeRootsSchema = z2.object({
249
- skills: z2.array(
265
+ var providerResolvedNativeRootsSchema = z3.object({
266
+ skills: z3.array(
250
267
  providerResolvedNativeRootSchema.refine(
251
268
  (root) => resolvedSkillShapes.has(root.shape),
252
269
  "A skills root needs a skill shape"
253
270
  )
254
271
  ).max(PROVIDER_RESOLVED_NATIVE_ROOTS_MAX),
255
- commands: z2.array(
272
+ commands: z3.array(
256
273
  providerResolvedNativeRootSchema.refine(
257
274
  (root) => resolvedCommandShapes.has(root.shape),
258
275
  "A commands root needs a command shape"
@@ -263,7 +280,7 @@ var EMPTY_PROVIDER_RESOLVED_NATIVE_ROOTS = Object.freeze({
263
280
  skills: Object.freeze([]),
264
281
  commands: Object.freeze([])
265
282
  });
266
- var providerNativeRootSetSchema = z2.object({
283
+ var providerNativeRootSetSchema = z3.object({
267
284
  skills: providerNativeRootsSchema,
268
285
  commands: providerNativeRootsSchema,
269
286
  resolved: providerResolvedNativeRootsSchema
@@ -296,16 +313,16 @@ var CLI_COMMAND_NAME_PATTERN = /^[a-z0-9-]+$/;
296
313
  var AGENT_TOOL_NAME_PATTERN = /^[a-zA-Z0-9_-]+$/;
297
314
  var PLUGIN_PROVIDER_ENV_NAME_PATTERN = /^[A-Z_][A-Z0-9_]*$/;
298
315
  var PLUGIN_PROVIDER_ENV_MAX_ENTRIES = 32;
299
- var pluginProviderEnvEntrySchema = z3.object({
300
- name: z3.string().regex(PLUGIN_PROVIDER_ENV_NAME_PATTERN),
301
- value: z3.union([
302
- z3.string(),
303
- 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()
304
321
  ]),
305
- reason: z3.string(),
306
- secret: z3.boolean()
322
+ reason: z4.string(),
323
+ secret: z4.boolean()
307
324
  }).strict();
308
- 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) => {
309
326
  const names = /* @__PURE__ */ new Set();
310
327
  for (let index = 0; index < entries.length; index += 1) {
311
328
  const name = entries[index]?.name;
@@ -340,26 +357,26 @@ var PROVIDER_ID_PATTERN = /^[a-z0-9][a-z0-9-]{1,63}$/;
340
357
  var PLUGIN_PROVIDER_BRIDGE_OPTIONS_MAX_BYTES = 64 * 1024;
341
358
  var SETTING_KEY_PATTERN = /^[a-zA-Z0-9_-]+$/;
342
359
  var settingsBaseFields = {
343
- label: z3.string().min(1),
344
- description: z3.string().min(1).optional()
360
+ label: z4.string().min(1),
361
+ description: z4.string().min(1).optional()
345
362
  };
346
- var stringSettingSchemaSchema = z3.custom(
363
+ var stringSettingSchemaSchema = z4.custom(
347
364
  (value) => isStandardSchema(value)
348
365
  );
349
- var booleanSettingSchemaSchema = z3.custom(
366
+ var booleanSettingSchemaSchema = z4.custom(
350
367
  (value) => isStandardSchema(value)
351
368
  );
352
- var numberSettingSchemaSchema = z3.custom(
369
+ var numberSettingSchemaSchema = z4.custom(
353
370
  (value) => isStandardSchema(value)
354
371
  );
355
- var settingDescriptorSchema = z3.discriminatedUnion("type", [
356
- z3.object({
357
- type: z3.literal("string"),
372
+ var settingDescriptorSchema = z4.discriminatedUnion("type", [
373
+ z4.object({
374
+ type: z4.literal("string"),
358
375
  ...settingsBaseFields,
359
- secret: z3.literal(true).optional(),
360
- experimental_multiline: z3.boolean().optional(),
376
+ secret: z4.literal(true).optional(),
377
+ experimental_multiline: z4.boolean().optional(),
361
378
  experimental_schema: stringSettingSchemaSchema.optional(),
362
- default: z3.string().optional()
379
+ default: z4.string().optional()
363
380
  }).strict().refine(
364
381
  (descriptor) => !(descriptor.secret === true && descriptor.experimental_multiline === true),
365
382
  {
@@ -367,30 +384,30 @@ var settingDescriptorSchema = z3.discriminatedUnion("type", [
367
384
  path: ["experimental_multiline"]
368
385
  }
369
386
  ),
370
- z3.object({
371
- type: z3.literal("boolean"),
387
+ z4.object({
388
+ type: z4.literal("boolean"),
372
389
  ...settingsBaseFields,
373
390
  experimental_schema: booleanSettingSchemaSchema.optional(),
374
- default: z3.boolean().optional()
391
+ default: z4.boolean().optional()
375
392
  }).strict(),
376
- z3.object({
377
- type: z3.literal("number"),
393
+ z4.object({
394
+ type: z4.literal("number"),
378
395
  ...settingsBaseFields,
379
396
  experimental_schema: numberSettingSchemaSchema.optional(),
380
- default: z3.number().finite().optional()
397
+ default: z4.number().finite().optional()
381
398
  }).strict(),
382
- z3.object({
383
- type: z3.literal("select"),
399
+ z4.object({
400
+ type: z4.literal("select"),
384
401
  ...settingsBaseFields,
385
- options: z3.array(z3.string().min(1)).min(1),
402
+ options: z4.array(z4.string().min(1)).min(1),
386
403
  experimental_schema: stringSettingSchemaSchema.optional(),
387
- default: z3.string().optional()
404
+ default: z4.string().optional()
388
405
  }).strict(),
389
- z3.object({
390
- type: z3.literal("project"),
406
+ z4.object({
407
+ type: z4.literal("project"),
391
408
  ...settingsBaseFields,
392
409
  experimental_schema: stringSettingSchemaSchema.optional(),
393
- default: z3.string().optional()
410
+ default: z4.string().optional()
394
411
  }).strict()
395
412
  ]);
396
413
  function registerSettingDescriptors(target, added) {
@@ -1410,11 +1427,21 @@ function readRpcMethodContract(method, value) {
1410
1427
  function isZodSchemaLike(value) {
1411
1428
  return typeof value === "object" && value !== null && typeof value.safeParse === "function";
1412
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
+ }
1413
1440
  function zodSchemaToJsonSchema(schema) {
1414
1441
  if (typeof schema.toJSONSchema === "function") {
1415
1442
  return schema.toJSONSchema({ io: "input" });
1416
1443
  }
1417
- return z3.toJSONSchema(schema, { io: "input" });
1444
+ return z4.toJSONSchema(schema, { io: "input" });
1418
1445
  }
1419
1446
  var SINGLE_SCHEMA_KEYWORDS = [
1420
1447
  "additionalItems",
@@ -1740,6 +1767,130 @@ function storePluginHook(records, hook, handler) {
1740
1767
  function pluginHookAlreadyRegisteredMessage(hook) {
1741
1768
  return `a "${hook}" hook handler is already registered by this plugin`;
1742
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();
1743
1894
 
1744
1895
  // src/testing/fake-sdk.ts
1745
1896
  function withSpawnAttribution(pluginId, args) {
@@ -2778,11 +2929,14 @@ function createFakePluginHostInternal(options, sharedState) {
2778
2929
  "interaction.pending": [],
2779
2930
  "message.queued": [],
2780
2931
  "message.dispatched": [],
2781
- "turn.failed": []
2932
+ "turn.failed": [],
2933
+ "message.cancelled": [],
2934
+ "thread.unarchived": []
2782
2935
  };
2783
2936
  const hooks = {
2784
2937
  "message.dispatch": null
2785
2938
  };
2939
+ const environmentProviders = /* @__PURE__ */ new Map();
2786
2940
  const disposeHooks = [];
2787
2941
  const serviceControllers = [];
2788
2942
  let nextInteractionId = 1;
@@ -3049,6 +3203,20 @@ function createFakePluginHostInternal(options, sharedState) {
3049
3203
  requestedDrains += 1;
3050
3204
  }
3051
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
+ };
3052
3220
  const bb = {
3053
3221
  pluginId,
3054
3222
  log,
@@ -3064,6 +3232,7 @@ function createFakePluginHostInternal(options, sharedState) {
3064
3232
  ui,
3065
3233
  events,
3066
3234
  experimental_hooks,
3235
+ experimental_environments,
3067
3236
  status,
3068
3237
  server,
3069
3238
  hosts,
@@ -3160,12 +3329,17 @@ function createFakePluginHostInternal(options, sharedState) {
3160
3329
  "interaction.pending": threadEventHandlers["interaction.pending"].length,
3161
3330
  "message.queued": threadEventHandlers["message.queued"].length,
3162
3331
  "message.dispatched": threadEventHandlers["message.dispatched"].length,
3163
- "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
3164
3335
  };
3165
3336
  },
3166
3337
  get hooks() {
3167
3338
  return { ...hooks };
3168
3339
  },
3340
+ get environmentProviders() {
3341
+ return new Map(environmentProviders);
3342
+ },
3169
3343
  mentionProviders,
3170
3344
  providerRegistrations,
3171
3345
  providerEnvResolvers,
@@ -3634,8 +3808,8 @@ function makePluginAgentConfigurationContext(overrides = {}) {
3634
3808
  id: "environment-test",
3635
3809
  name: null,
3636
3810
  path: "/tmp/test",
3637
- workspaceProvisionType: "unmanaged",
3638
- branchName: null
3811
+ branchName: null,
3812
+ workspaceProvisionType: null
3639
3813
  },
3640
3814
  host: { id: "host-test", name: "Test host" },
3641
3815
  provider: {
@@ -3694,7 +3868,8 @@ function makeMessageDispatchHookContext(overrides = {}) {
3694
3868
  origin: null,
3695
3869
  originPluginId: null,
3696
3870
  startedOnBehalfOf: null,
3697
- parentThreadId: null
3871
+ parentThreadId: null,
3872
+ environmentIntent: null
3698
3873
  };
3699
3874
  const environmentDefaults = {
3700
3875
  id: "environment-1",
@@ -3702,14 +3877,18 @@ function makeMessageDispatchHookContext(overrides = {}) {
3702
3877
  projectId: "project-1",
3703
3878
  hostId: "host-1",
3704
3879
  path: "/tmp/test",
3705
- managed: true,
3706
3880
  isGitRepo: true,
3707
3881
  isWorktree: false,
3708
- workspaceProvisionType: "unmanaged",
3709
3882
  branchName: "main",
3710
3883
  baseBranch: null,
3711
3884
  defaultBranch: "main",
3712
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,
3713
3892
  status: "ready",
3714
3893
  createdAt: 0,
3715
3894
  updatedAt: 0
@@ -3717,8 +3896,8 @@ function makeMessageDispatchHookContext(overrides = {}) {
3717
3896
  const hostDefaults = {
3718
3897
  id: "host-1",
3719
3898
  name: "Test host",
3720
- type: "persistent",
3721
3899
  status: "connected",
3900
+ type: "persistent",
3722
3901
  maxPermissionMode: "full",
3723
3902
  lastSeenAt: null,
3724
3903
  lastRejectedProtocolVersion: null,
@@ -3764,6 +3943,8 @@ function makeMessageDispatchHookContext(overrides = {}) {
3764
3943
  function makeQueueEntry(overrides = {}) {
3765
3944
  return {
3766
3945
  id: "queued_1",
3946
+ initiator: "user",
3947
+ senderThreadId: null,
3767
3948
  threadId: "thread-1",
3768
3949
  content: [{ type: "text", text: "Queued turn", mentions: [] }],
3769
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.48",
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",