@get-bb/plugin-sdk 0.4.40 → 0.4.45

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.
@@ -280,6 +280,42 @@ var RPC_METHOD_PATTERN = /^[a-zA-Z0-9_-]+(?:\.[a-zA-Z0-9_-]+)*$/;
280
280
  var BACKGROUND_NAME_PATTERN = /^[a-zA-Z0-9_-]+$/;
281
281
  var CLI_COMMAND_NAME_PATTERN = /^[a-z0-9-]+$/;
282
282
  var AGENT_TOOL_NAME_PATTERN = /^[a-zA-Z0-9_-]+$/;
283
+ var PLUGIN_PROVIDER_ENV_NAME_PATTERN = /^[A-Z_][A-Z0-9_]*$/;
284
+ var PLUGIN_PROVIDER_ENV_MAX_ENTRIES = 32;
285
+ var pluginProviderEnvEntrySchema = z3.object({
286
+ name: z3.string().regex(PLUGIN_PROVIDER_ENV_NAME_PATTERN),
287
+ value: z3.union([
288
+ z3.string(),
289
+ z3.object({ serverPath: z3.string().startsWith("/") }).strict()
290
+ ]),
291
+ reason: z3.string(),
292
+ secret: z3.boolean()
293
+ }).strict();
294
+ var pluginProviderEnvEntriesSchema = z3.array(pluginProviderEnvEntrySchema).max(PLUGIN_PROVIDER_ENV_MAX_ENTRIES).superRefine((entries, context) => {
295
+ const names = /* @__PURE__ */ new Set();
296
+ for (let index = 0; index < entries.length; index += 1) {
297
+ const name = entries[index]?.name;
298
+ if (name !== void 0 && names.has(name)) {
299
+ context.addIssue({
300
+ code: "custom",
301
+ path: [index, "name"],
302
+ message: "must be unique within one resolver"
303
+ });
304
+ }
305
+ if (name !== void 0) names.add(name);
306
+ }
307
+ });
308
+ function validatePluginProviderEnvEntries(value) {
309
+ const parsed = pluginProviderEnvEntriesSchema.safeParse(value);
310
+ if (!parsed.success) {
311
+ const issue = parsed.error.issues[0];
312
+ const path = issue?.path.length ? `[${issue.path.join(".")}] ` : "";
313
+ throw new Error(
314
+ `provider environment contribution ${path}${issue?.message ?? "is invalid"}`
315
+ );
316
+ }
317
+ return parsed.data;
318
+ }
283
319
  var PLUGIN_AGENT_STATIC_INSTRUCTIONS_MAX_CHARS = 4096;
284
320
  var PLUGIN_AGENT_STATUS_LABEL_MAX_CHARS = 80;
285
321
  var PLUGIN_AGENT_SELECTION_MAX_IDS = 256;
@@ -1716,6 +1752,8 @@ export {
1716
1752
  PLUGIN_PROVIDER_BRIDGE_OPTIONS_MAX_BYTES,
1717
1753
  PLUGIN_PROVIDER_COMPOSER_ACTION_VALUES,
1718
1754
  PLUGIN_PROVIDER_DISPLAY_NAME_MAX_CHARS,
1755
+ PLUGIN_PROVIDER_ENV_MAX_ENTRIES,
1756
+ PLUGIN_PROVIDER_ENV_NAME_PATTERN,
1719
1757
  PLUGIN_PROVIDER_PERMISSION_MODE_VALUES,
1720
1758
  PLUGIN_PROVIDER_REASONING_LEVEL_VALUES,
1721
1759
  PROVIDER_ID_PATTERN,
@@ -1749,6 +1787,7 @@ export {
1749
1787
  undeclaredIconProblem,
1750
1788
  validatePluginAiServiceDeclaration,
1751
1789
  validatePluginProviderDeclaration,
1790
+ validatePluginProviderEnvEntries,
1752
1791
  validateSettingsUpdate,
1753
1792
  zodSchemaToJsonSchema
1754
1793
  };
@@ -684,13 +684,21 @@ var threadEventItemPresentationTintSchema = z6.object({
684
684
  light: z6.string().min(1),
685
685
  dark: z6.string().min(1)
686
686
  });
687
+ var THREAD_EVENT_ITEM_PRESENTATION_BADGE_LABEL_MAX_LENGTH = 80;
688
+ var threadEventItemPresentationBadgeSchema = z6.object({
689
+ glyph: z6.string().min(1),
690
+ label: z6.string().min(1).max(THREAD_EVENT_ITEM_PRESENTATION_BADGE_LABEL_MAX_LENGTH),
691
+ hint: z6.string().min(1).max(THREAD_EVENT_ITEM_PRESENTATION_BADGE_LABEL_MAX_LENGTH),
692
+ tone: z6.enum(["neutral", "destructive"])
693
+ });
687
694
  var threadEventItemPresentationSchema = z6.object({
688
695
  label: threadEventItemPresentationLabelSchema,
689
696
  icon: threadEventItemPresentationIconSchema,
690
697
  title: z6.string().optional(),
691
698
  detail: z6.string().max(THREAD_EVENT_ITEM_PRESENTATION_DETAIL_MAX_LENGTH).optional(),
692
699
  suppress: z6.boolean().optional(),
693
- tint: threadEventItemPresentationTintSchema.optional()
700
+ tint: threadEventItemPresentationTintSchema.optional(),
701
+ badge: threadEventItemPresentationBadgeSchema.optional()
694
702
  });
695
703
 
696
704
  // ../domain/src/provider-extension-kind.ts
@@ -1409,6 +1417,10 @@ var threadEventScopeDefinitionByType = {
1409
1417
  policy: "thread",
1410
1418
  rationale: "Subscription usage is account-scoped state that can affect multiple turns and threads."
1411
1419
  },
1420
+ "provider.env-resolved": {
1421
+ policy: "thread",
1422
+ rationale: "Resolved provider environment is session state and can change between turns."
1423
+ },
1412
1424
  "thread/extensionState/updated": {
1413
1425
  policy: "thread",
1414
1426
  rationale: "Plugin-declared thread state is current thread metadata (like goals), not part of a specific turn transcript; latest snapshot per kind wins."
@@ -2052,6 +2064,25 @@ var unscopedProviderEventSchema = z14.discriminatedUnion("type", [
2052
2064
  providerThreadId: z14.string(),
2053
2065
  rateLimits: providerRateLimitStateSchema
2054
2066
  }),
2067
+ z14.object({
2068
+ type: z14.literal("provider.env-resolved"),
2069
+ threadId: z14.string(),
2070
+ providerThreadId: z14.string(),
2071
+ entries: z14.array(
2072
+ z14.object({
2073
+ name: z14.string(),
2074
+ source: z14.union([
2075
+ z14.literal("shell"),
2076
+ z14.object({ plugin: z14.string() }).strict()
2077
+ ]),
2078
+ value: z14.union([
2079
+ z14.string(),
2080
+ z14.object({ masked: z14.literal(true) }).strict()
2081
+ ]),
2082
+ reason: z14.string().optional()
2083
+ }).strict()
2084
+ )
2085
+ }),
2055
2086
  z14.object({
2056
2087
  type: z14.literal("thread/extensionState/updated"),
2057
2088
  threadId: z14.string(),
@@ -2705,7 +2736,8 @@ var sessionReplacedNotificationSchema = z23.object({
2705
2736
  threadId: z23.string().min(1),
2706
2737
  providerThreadId: z23.string().min(1).nullable(),
2707
2738
  reason: z23.string().min(1),
2708
- contextLost: z23.boolean().default(false)
2739
+ contextLost: z23.boolean().default(false),
2740
+ showRuntimeNote: z23.boolean().default(false)
2709
2741
  }).passthrough();
2710
2742
  var providerRawNotificationSchema = z23.object({
2711
2743
  threadId: z23.string().min(1).optional(),
@@ -322,13 +322,21 @@ var threadEventItemPresentationTintSchema = z4.object({
322
322
  light: z4.string().min(1),
323
323
  dark: z4.string().min(1)
324
324
  });
325
+ var THREAD_EVENT_ITEM_PRESENTATION_BADGE_LABEL_MAX_LENGTH = 80;
326
+ var threadEventItemPresentationBadgeSchema = z4.object({
327
+ glyph: z4.string().min(1),
328
+ label: z4.string().min(1).max(THREAD_EVENT_ITEM_PRESENTATION_BADGE_LABEL_MAX_LENGTH),
329
+ hint: z4.string().min(1).max(THREAD_EVENT_ITEM_PRESENTATION_BADGE_LABEL_MAX_LENGTH),
330
+ tone: z4.enum(["neutral", "destructive"])
331
+ });
325
332
  var threadEventItemPresentationSchema = z4.object({
326
333
  label: threadEventItemPresentationLabelSchema,
327
334
  icon: threadEventItemPresentationIconSchema,
328
335
  title: z4.string().optional(),
329
336
  detail: z4.string().max(THREAD_EVENT_ITEM_PRESENTATION_DETAIL_MAX_LENGTH).optional(),
330
337
  suppress: z4.boolean().optional(),
331
- tint: threadEventItemPresentationTintSchema.optional()
338
+ tint: threadEventItemPresentationTintSchema.optional(),
339
+ badge: threadEventItemPresentationBadgeSchema.optional()
332
340
  });
333
341
 
334
342
  // ../domain/src/provider-extension-kind.ts
@@ -1041,6 +1049,10 @@ var threadEventScopeDefinitionByType = {
1041
1049
  policy: "thread",
1042
1050
  rationale: "Subscription usage is account-scoped state that can affect multiple turns and threads."
1043
1051
  },
1052
+ "provider.env-resolved": {
1053
+ policy: "thread",
1054
+ rationale: "Resolved provider environment is session state and can change between turns."
1055
+ },
1044
1056
  "thread/extensionState/updated": {
1045
1057
  policy: "thread",
1046
1058
  rationale: "Plugin-declared thread state is current thread metadata (like goals), not part of a specific turn transcript; latest snapshot per kind wins."
@@ -1693,6 +1705,25 @@ var unscopedProviderEventSchema = z12.discriminatedUnion("type", [
1693
1705
  providerThreadId: z12.string(),
1694
1706
  rateLimits: providerRateLimitStateSchema
1695
1707
  }),
1708
+ z12.object({
1709
+ type: z12.literal("provider.env-resolved"),
1710
+ threadId: z12.string(),
1711
+ providerThreadId: z12.string(),
1712
+ entries: z12.array(
1713
+ z12.object({
1714
+ name: z12.string(),
1715
+ source: z12.union([
1716
+ z12.literal("shell"),
1717
+ z12.object({ plugin: z12.string() }).strict()
1718
+ ]),
1719
+ value: z12.union([
1720
+ z12.string(),
1721
+ z12.object({ masked: z12.literal(true) }).strict()
1722
+ ]),
1723
+ reason: z12.string().optional()
1724
+ }).strict()
1725
+ )
1726
+ }),
1696
1727
  z12.object({
1697
1728
  type: z12.literal("thread/extensionState/updated"),
1698
1729
  threadId: z12.string(),
@@ -4564,7 +4595,8 @@ var sessionReplacedNotificationSchema = z24.object({
4564
4595
  threadId: z24.string().min(1),
4565
4596
  providerThreadId: z24.string().min(1).nullable(),
4566
4597
  reason: z24.string().min(1),
4567
- contextLost: z24.boolean().default(false)
4598
+ contextLost: z24.boolean().default(false),
4599
+ showRuntimeNote: z24.boolean().default(false)
4568
4600
  }).passthrough();
4569
4601
  var providerRawNotificationSchema = z24.object({
4570
4602
  threadId: z24.string().min(1).optional(),
@@ -1980,13 +1980,21 @@ var threadEventItemPresentationTintSchema = z10.object({
1980
1980
  light: z10.string().min(1),
1981
1981
  dark: z10.string().min(1)
1982
1982
  });
1983
+ var THREAD_EVENT_ITEM_PRESENTATION_BADGE_LABEL_MAX_LENGTH = 80;
1984
+ var threadEventItemPresentationBadgeSchema = z10.object({
1985
+ glyph: z10.string().min(1),
1986
+ label: z10.string().min(1).max(THREAD_EVENT_ITEM_PRESENTATION_BADGE_LABEL_MAX_LENGTH),
1987
+ hint: z10.string().min(1).max(THREAD_EVENT_ITEM_PRESENTATION_BADGE_LABEL_MAX_LENGTH),
1988
+ tone: z10.enum(["neutral", "destructive"])
1989
+ });
1983
1990
  var threadEventItemPresentationSchema = z10.object({
1984
1991
  label: threadEventItemPresentationLabelSchema,
1985
1992
  icon: threadEventItemPresentationIconSchema,
1986
1993
  title: z10.string().optional(),
1987
1994
  detail: z10.string().max(THREAD_EVENT_ITEM_PRESENTATION_DETAIL_MAX_LENGTH).optional(),
1988
1995
  suppress: z10.boolean().optional(),
1989
- tint: threadEventItemPresentationTintSchema.optional()
1996
+ tint: threadEventItemPresentationTintSchema.optional(),
1997
+ badge: threadEventItemPresentationBadgeSchema.optional()
1990
1998
  });
1991
1999
 
1992
2000
  // ../domain/src/provider-extension-kind.ts
@@ -2714,6 +2722,10 @@ var threadEventScopeDefinitionByType = {
2714
2722
  policy: "thread",
2715
2723
  rationale: "Subscription usage is account-scoped state that can affect multiple turns and threads."
2716
2724
  },
2725
+ "provider.env-resolved": {
2726
+ policy: "thread",
2727
+ rationale: "Resolved provider environment is session state and can change between turns."
2728
+ },
2717
2729
  "thread/extensionState/updated": {
2718
2730
  policy: "thread",
2719
2731
  rationale: "Plugin-declared thread state is current thread metadata (like goals), not part of a specific turn transcript; latest snapshot per kind wins."
@@ -3357,6 +3369,25 @@ var unscopedProviderEventSchema = z18.discriminatedUnion("type", [
3357
3369
  providerThreadId: z18.string(),
3358
3370
  rateLimits: providerRateLimitStateSchema
3359
3371
  }),
3372
+ z18.object({
3373
+ type: z18.literal("provider.env-resolved"),
3374
+ threadId: z18.string(),
3375
+ providerThreadId: z18.string(),
3376
+ entries: z18.array(
3377
+ z18.object({
3378
+ name: z18.string(),
3379
+ source: z18.union([
3380
+ z18.literal("shell"),
3381
+ z18.object({ plugin: z18.string() }).strict()
3382
+ ]),
3383
+ value: z18.union([
3384
+ z18.string(),
3385
+ z18.object({ masked: z18.literal(true) }).strict()
3386
+ ]),
3387
+ reason: z18.string().optional()
3388
+ }).strict()
3389
+ )
3390
+ }),
3360
3391
  z18.object({
3361
3392
  type: z18.literal("thread/extensionState/updated"),
3362
3393
  threadId: z18.string(),
@@ -4280,7 +4311,8 @@ var sessionReplacedNotificationSchema = z29.object({
4280
4311
  threadId: z29.string().min(1),
4281
4312
  providerThreadId: z29.string().min(1).nullable(),
4282
4313
  reason: z29.string().min(1),
4283
- contextLost: z29.boolean().default(false)
4314
+ contextLost: z29.boolean().default(false),
4315
+ showRuntimeNote: z29.boolean().default(false)
4284
4316
  }).passthrough();
4285
4317
  var providerRawNotificationSchema = z29.object({
4286
4318
  threadId: z29.string().min(1).optional(),
@@ -293,6 +293,42 @@ var RPC_METHOD_PATTERN = /^[a-zA-Z0-9_-]+(?:\.[a-zA-Z0-9_-]+)*$/;
293
293
  var BACKGROUND_NAME_PATTERN = /^[a-zA-Z0-9_-]+$/;
294
294
  var CLI_COMMAND_NAME_PATTERN = /^[a-z0-9-]+$/;
295
295
  var AGENT_TOOL_NAME_PATTERN = /^[a-zA-Z0-9_-]+$/;
296
+ var PLUGIN_PROVIDER_ENV_NAME_PATTERN = /^[A-Z_][A-Z0-9_]*$/;
297
+ 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()
303
+ ]),
304
+ reason: z3.string(),
305
+ secret: z3.boolean()
306
+ }).strict();
307
+ var pluginProviderEnvEntriesSchema = z3.array(pluginProviderEnvEntrySchema).max(PLUGIN_PROVIDER_ENV_MAX_ENTRIES).superRefine((entries, context) => {
308
+ const names = /* @__PURE__ */ new Set();
309
+ for (let index = 0; index < entries.length; index += 1) {
310
+ const name = entries[index]?.name;
311
+ if (name !== void 0 && names.has(name)) {
312
+ context.addIssue({
313
+ code: "custom",
314
+ path: [index, "name"],
315
+ message: "must be unique within one resolver"
316
+ });
317
+ }
318
+ if (name !== void 0) names.add(name);
319
+ }
320
+ });
321
+ function validatePluginProviderEnvEntries(value) {
322
+ const parsed = pluginProviderEnvEntriesSchema.safeParse(value);
323
+ if (!parsed.success) {
324
+ const issue = parsed.error.issues[0];
325
+ const path = issue?.path.length ? `[${issue.path.join(".")}] ` : "";
326
+ throw new Error(
327
+ `provider environment contribution ${path}${issue?.message ?? "is invalid"}`
328
+ );
329
+ }
330
+ return parsed.data;
331
+ }
296
332
  var PLUGIN_AGENT_STATIC_INSTRUCTIONS_MAX_CHARS = 4096;
297
333
  var PLUGIN_AGENT_STATUS_LABEL_MAX_CHARS = 80;
298
334
  var PLUGIN_AGENT_SELECTION_MAX_IDS = 256;
@@ -2174,7 +2210,9 @@ function createFakePluginHostInternal(options, sharedState) {
2174
2210
  "ALTER TABLE _bb_migrations ADD COLUMN statement_hash TEXT"
2175
2211
  );
2176
2212
  }
2177
- const rows = database.prepare("SELECT id, statement_hash FROM _bb_migrations ORDER BY id").all();
2213
+ const rows = database.prepare(
2214
+ "SELECT id, statement_hash FROM _bb_migrations ORDER BY id"
2215
+ ).all();
2178
2216
  const applied = /* @__PURE__ */ new Map();
2179
2217
  for (const row of rows) applied.set(row.id, row.statement_hash);
2180
2218
  const statementHashes = statements.map(migrationStatementHash);
@@ -2466,6 +2504,8 @@ function createFakePluginHostInternal(options, sharedState) {
2466
2504
  };
2467
2505
  const agentTools = [];
2468
2506
  const providerRegistrations = [];
2507
+ const providerEnvResolvers = /* @__PURE__ */ new Map();
2508
+ const providerEnvHealthResolvers = /* @__PURE__ */ new Map();
2469
2509
  let agentConfigurationProvider = null;
2470
2510
  let instructionProvider = null;
2471
2511
  function registerProviderDeclaration(declaration) {
@@ -2931,6 +2971,44 @@ function createFakePluginHostInternal(options, sharedState) {
2931
2971
  const providers = {
2932
2972
  register(declaration) {
2933
2973
  return registerProviderDeclaration(declaration);
2974
+ },
2975
+ experimental_contributeEnv(providerId, resolve2) {
2976
+ assertLive();
2977
+ if (typeof providerId !== "string" || providerId.trim().length === 0) {
2978
+ throw new Error(
2979
+ "provider environment contribution requires a provider id"
2980
+ );
2981
+ }
2982
+ if (providerEnvResolvers.has(providerId)) {
2983
+ throw new Error(
2984
+ `provider environment contribution for "${providerId}" is already registered`
2985
+ );
2986
+ }
2987
+ if (typeof resolve2 !== "function") {
2988
+ throw new Error(
2989
+ "provider environment contribution requires a resolver function"
2990
+ );
2991
+ }
2992
+ providerEnvResolvers.set(providerId, resolve2);
2993
+ },
2994
+ experimental_contributeEnvHealth(providerId, resolve2) {
2995
+ assertLive();
2996
+ if (typeof providerId !== "string" || providerId.trim().length === 0) {
2997
+ throw new Error(
2998
+ "provider environment health contribution requires a provider id"
2999
+ );
3000
+ }
3001
+ if (providerEnvHealthResolvers.has(providerId)) {
3002
+ throw new Error(
3003
+ `provider environment health contribution for "${providerId}" is already registered`
3004
+ );
3005
+ }
3006
+ if (typeof resolve2 !== "function") {
3007
+ throw new Error(
3008
+ "provider environment health contribution requires a resolver function"
3009
+ );
3010
+ }
3011
+ providerEnvHealthResolvers.set(providerId, resolve2);
2934
3012
  }
2935
3013
  };
2936
3014
  const experimental_hooks = {
@@ -3060,6 +3138,8 @@ function createFakePluginHostInternal(options, sharedState) {
3060
3138
  },
3061
3139
  mentionProviders,
3062
3140
  providerRegistrations,
3141
+ providerEnvResolvers,
3142
+ providerEnvHealthResolvers,
3063
3143
  aiServiceRegistrations
3064
3144
  },
3065
3145
  get pendingInteractions() {
@@ -3077,6 +3157,43 @@ function createFakePluginHostInternal(options, sharedState) {
3077
3157
  await handler({ hostId });
3078
3158
  }
3079
3159
  },
3160
+ async resolveProviderEnv(providerId, context) {
3161
+ assertLive();
3162
+ const resolve2 = providerEnvResolvers.get(providerId);
3163
+ if (resolve2 === void 0) return [];
3164
+ try {
3165
+ return validatePluginProviderEnvEntries(await resolve2(context));
3166
+ } catch (error) {
3167
+ emitLog(
3168
+ "warn",
3169
+ `provider environment contribution failed: ${error instanceof Error ? error.message : String(error)}`
3170
+ );
3171
+ return [];
3172
+ }
3173
+ },
3174
+ async resolveProviderEnvHealth(providerId, context) {
3175
+ assertLive();
3176
+ if (!providerEnvResolvers.has(providerId)) return null;
3177
+ const resolve2 = providerEnvHealthResolvers.get(providerId);
3178
+ if (resolve2 === void 0) return null;
3179
+ try {
3180
+ const value = await resolve2(context);
3181
+ if (value === null) return null;
3182
+ if (value.label.trim().length === 0) {
3183
+ throw new Error("label must not be empty");
3184
+ }
3185
+ if (value.statusMessage.trim().length === 0) {
3186
+ throw new Error("statusMessage must not be empty");
3187
+ }
3188
+ return value;
3189
+ } catch (error) {
3190
+ emitLog(
3191
+ "warn",
3192
+ `provider environment health contribution failed: ${error instanceof Error ? error.message : String(error)}`
3193
+ );
3194
+ return null;
3195
+ }
3196
+ },
3080
3197
  async experimental_emitHostSignal(hostId, signal, payload) {
3081
3198
  assertLive();
3082
3199
  if (hostId.trim().length === 0) {
@@ -3348,6 +3465,151 @@ function makeThreadResponse(overrides = {}) {
3348
3465
  ...overrides
3349
3466
  };
3350
3467
  }
3468
+ function makePluginAgentConfigurationContext(overrides = {}) {
3469
+ const context = {
3470
+ thread: {
3471
+ id: "thread-test",
3472
+ title: null,
3473
+ parentThreadId: null,
3474
+ sourceThreadId: null
3475
+ },
3476
+ project: {
3477
+ id: "project-test",
3478
+ kind: "standard",
3479
+ name: "Test project",
3480
+ gitRemoteUrl: null
3481
+ },
3482
+ environment: {
3483
+ id: "environment-test",
3484
+ name: null,
3485
+ path: "/tmp/test",
3486
+ workspaceProvisionType: "unmanaged",
3487
+ branchName: null
3488
+ },
3489
+ host: { id: "host-test", name: "Test host" },
3490
+ provider: {
3491
+ id: "test-provider",
3492
+ model: "test-model",
3493
+ capabilities: { supportsNativeUserQuestion: false }
3494
+ },
3495
+ origin: { kind: null, pluginId: null }
3496
+ };
3497
+ return {
3498
+ thread: { ...context.thread, ...overrides.thread },
3499
+ project: { ...context.project, ...overrides.project },
3500
+ environment: { ...context.environment, ...overrides.environment },
3501
+ host: { ...context.host, ...overrides.host },
3502
+ provider: {
3503
+ ...context.provider,
3504
+ ...overrides.provider,
3505
+ capabilities: {
3506
+ ...context.provider.capabilities,
3507
+ ...overrides.provider?.capabilities
3508
+ }
3509
+ },
3510
+ origin: { ...context.origin, ...overrides.origin }
3511
+ };
3512
+ }
3513
+ function makeMessageDispatchHookContext(overrides = {}) {
3514
+ const context = {
3515
+ thread: makeThreadResponse({ status: "pending" }),
3516
+ project: {
3517
+ id: "project-1",
3518
+ kind: "standard",
3519
+ name: "Test project",
3520
+ gitRemoteUrl: null,
3521
+ createdAt: 0,
3522
+ updatedAt: 0
3523
+ },
3524
+ environment: null,
3525
+ host: null,
3526
+ input: { blocks: [], text: "Test message" },
3527
+ requestedExecution: {
3528
+ providerId: "test-provider",
3529
+ model: null,
3530
+ reasoningLevel: null,
3531
+ serviceTier: null,
3532
+ permissionMode: null
3533
+ },
3534
+ executionSources: {
3535
+ providerId: null,
3536
+ model: null,
3537
+ reasoningLevel: null,
3538
+ serviceTier: null,
3539
+ permissionMode: null
3540
+ },
3541
+ attempt: "start-turn",
3542
+ queuedMessage: null,
3543
+ origin: null,
3544
+ originPluginId: null,
3545
+ startedOnBehalfOf: null,
3546
+ parentThreadId: null
3547
+ };
3548
+ const environmentDefaults = {
3549
+ id: "environment-1",
3550
+ name: null,
3551
+ projectId: "project-1",
3552
+ hostId: "host-1",
3553
+ path: "/tmp/test",
3554
+ managed: true,
3555
+ isGitRepo: true,
3556
+ isWorktree: false,
3557
+ workspaceProvisionType: "unmanaged",
3558
+ branchName: "main",
3559
+ baseBranch: null,
3560
+ defaultBranch: "main",
3561
+ mergeBaseBranch: null,
3562
+ status: "ready",
3563
+ createdAt: 0,
3564
+ updatedAt: 0
3565
+ };
3566
+ const hostDefaults = {
3567
+ id: "host-1",
3568
+ name: "Test host",
3569
+ type: "persistent",
3570
+ status: "connected",
3571
+ maxPermissionMode: "full",
3572
+ lastSeenAt: null,
3573
+ lastRejectedProtocolVersion: null,
3574
+ createdAt: 0,
3575
+ updatedAt: 0
3576
+ };
3577
+ const project = { ...context.project, ...overrides.project };
3578
+ const host = overrides.host === void 0 ? context.host : overrides.host === null ? null : { ...hostDefaults, ...overrides.host };
3579
+ const environment = overrides.environment === void 0 ? context.environment : overrides.environment === null ? null : {
3580
+ ...environmentDefaults,
3581
+ projectId: project.id,
3582
+ hostId: host?.id ?? environmentDefaults.hostId,
3583
+ ...overrides.environment
3584
+ };
3585
+ const thread = {
3586
+ ...context.thread,
3587
+ projectId: project.id,
3588
+ environmentId: environment?.id ?? null,
3589
+ ...overrides.thread
3590
+ };
3591
+ return {
3592
+ ...context,
3593
+ ...overrides,
3594
+ thread,
3595
+ project,
3596
+ environment,
3597
+ host,
3598
+ input: { ...context.input, ...overrides.input },
3599
+ requestedExecution: {
3600
+ ...context.requestedExecution,
3601
+ ...overrides.requestedExecution
3602
+ },
3603
+ executionSources: {
3604
+ ...context.executionSources,
3605
+ ...overrides.executionSources
3606
+ },
3607
+ queuedMessage: overrides.queuedMessage === void 0 ? context.queuedMessage : overrides.queuedMessage === null ? null : makeQueueEntry({
3608
+ threadId: thread.id,
3609
+ ...overrides.queuedMessage
3610
+ })
3611
+ };
3612
+ }
3351
3613
  function makeQueueEntry(overrides = {}) {
3352
3614
  return {
3353
3615
  id: "queued_1",
@@ -3485,6 +3747,8 @@ export {
3485
3747
  createFakePluginHost,
3486
3748
  createFakeSdk,
3487
3749
  scanPublicSdkOnly as experimental_scanPublicSdkOnly,
3750
+ makeMessageDispatchHookContext,
3751
+ makePluginAgentConfigurationContext,
3488
3752
  makeQueueEntry,
3489
3753
  makeThreadResponse,
3490
3754
  makeTurnFailedEvent
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@get-bb/plugin-sdk",
3
- "version": "0.4.40",
3
+ "version": "0.4.45",
4
4
  "homepage": "https://github.com/get-bb/bb#readme",
5
5
  "bugs": {
6
6
  "url": "https://github.com/get-bb/bb/issues"