@get-bb/plugin-sdk 0.4.34 → 0.4.40

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.
@@ -276,7 +276,7 @@ var PLUGIN_HTTP_METHODS = /* @__PURE__ */ new Set([
276
276
  "HEAD",
277
277
  "OPTIONS"
278
278
  ]);
279
- var RPC_METHOD_PATTERN = /^[a-zA-Z0-9_-]+$/;
279
+ 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_-]+$/;
@@ -293,12 +293,22 @@ var settingsBaseFields = {
293
293
  label: z3.string().min(1),
294
294
  description: z3.string().min(1).optional()
295
295
  };
296
+ var stringSettingSchemaSchema = z3.custom(
297
+ (value) => isStandardSchema(value)
298
+ );
299
+ var booleanSettingSchemaSchema = z3.custom(
300
+ (value) => isStandardSchema(value)
301
+ );
302
+ var numberSettingSchemaSchema = z3.custom(
303
+ (value) => isStandardSchema(value)
304
+ );
296
305
  var settingDescriptorSchema = z3.discriminatedUnion("type", [
297
306
  z3.object({
298
307
  type: z3.literal("string"),
299
308
  ...settingsBaseFields,
300
309
  secret: z3.literal(true).optional(),
301
310
  experimental_multiline: z3.boolean().optional(),
311
+ experimental_schema: stringSettingSchemaSchema.optional(),
302
312
  default: z3.string().optional()
303
313
  }).strict().refine(
304
314
  (descriptor) => !(descriptor.secret === true && descriptor.experimental_multiline === true),
@@ -310,17 +320,26 @@ var settingDescriptorSchema = z3.discriminatedUnion("type", [
310
320
  z3.object({
311
321
  type: z3.literal("boolean"),
312
322
  ...settingsBaseFields,
323
+ experimental_schema: booleanSettingSchemaSchema.optional(),
313
324
  default: z3.boolean().optional()
314
325
  }).strict(),
326
+ z3.object({
327
+ type: z3.literal("number"),
328
+ ...settingsBaseFields,
329
+ experimental_schema: numberSettingSchemaSchema.optional(),
330
+ default: z3.number().finite().optional()
331
+ }).strict(),
315
332
  z3.object({
316
333
  type: z3.literal("select"),
317
334
  ...settingsBaseFields,
318
335
  options: z3.array(z3.string().min(1)).min(1),
336
+ experimental_schema: stringSettingSchemaSchema.optional(),
319
337
  default: z3.string().optional()
320
338
  }).strict(),
321
339
  z3.object({
322
340
  type: z3.literal("project"),
323
341
  ...settingsBaseFields,
342
+ experimental_schema: stringSettingSchemaSchema.optional(),
324
343
  default: z3.string().optional()
325
344
  }).strict()
326
345
  ]);
@@ -349,11 +368,39 @@ function registerSettingDescriptors(target, added) {
349
368
  `default for setting "${key}" must be one of its options`
350
369
  );
351
370
  }
371
+ if (descriptor.default !== void 0) {
372
+ const errors = validateSettingsUpdate(
373
+ { [key]: descriptor },
374
+ { [key]: descriptor.default }
375
+ );
376
+ if (errors.length > 0) {
377
+ throw new Error(`invalid default for setting "${key}": ${errors[0]}`);
378
+ }
379
+ }
352
380
  validated[key] = descriptor;
353
381
  }
354
382
  Object.assign(target, validated);
355
383
  return validated;
356
384
  }
385
+ function settingSchemaError(key, schema, value) {
386
+ if (schema === void 0) return null;
387
+ try {
388
+ const result = schema["~standard"].validate(value);
389
+ if (result instanceof Promise) {
390
+ return `schema for setting "${key}" must validate synchronously`;
391
+ }
392
+ if (result.issues !== void 0) {
393
+ return result.issues[0]?.message ?? `schema for setting "${key}" rejected the value`;
394
+ }
395
+ if (result.value !== value) {
396
+ return `schema for setting "${key}" must not transform its value`;
397
+ }
398
+ return null;
399
+ } catch (error) {
400
+ const detail = error instanceof Error ? error.message : String(error);
401
+ return `schema for setting "${key}" failed: ${detail}`;
402
+ }
403
+ }
357
404
  function validateSettingsUpdate(descriptors, values) {
358
405
  const errors = [];
359
406
  for (const [key, value] of Object.entries(values)) {
@@ -366,6 +413,30 @@ function validateSettingsUpdate(descriptors, values) {
366
413
  if (descriptor.type === "boolean") {
367
414
  if (typeof value !== "boolean") {
368
415
  errors.push(`setting "${key}" expects a boolean`);
416
+ continue;
417
+ }
418
+ const validationError2 = settingSchemaError(
419
+ key,
420
+ descriptor.experimental_schema,
421
+ value
422
+ );
423
+ if (validationError2 !== null) {
424
+ errors.push(validationError2);
425
+ }
426
+ continue;
427
+ }
428
+ if (descriptor.type === "number") {
429
+ if (typeof value !== "number" || !Number.isFinite(value)) {
430
+ errors.push(`setting "${key}" expects a finite number`);
431
+ continue;
432
+ }
433
+ const validationError2 = settingSchemaError(
434
+ key,
435
+ descriptor.experimental_schema,
436
+ value
437
+ );
438
+ if (validationError2 !== null) {
439
+ errors.push(validationError2);
369
440
  }
370
441
  continue;
371
442
  }
@@ -377,6 +448,15 @@ function validateSettingsUpdate(descriptors, values) {
377
448
  errors.push(
378
449
  `setting "${key}" must be one of: ${descriptor.options.join(", ")}`
379
450
  );
451
+ continue;
452
+ }
453
+ const validationError = settingSchemaError(
454
+ key,
455
+ descriptor.experimental_schema,
456
+ value
457
+ );
458
+ if (validationError !== null) {
459
+ errors.push(validationError);
380
460
  }
381
461
  }
382
462
  return errors;
@@ -1290,6 +1370,12 @@ function readRpcMethodContract(method, value) {
1290
1370
  function isZodSchemaLike(value) {
1291
1371
  return typeof value === "object" && value !== null && typeof value.safeParse === "function";
1292
1372
  }
1373
+ function zodSchemaToJsonSchema(schema) {
1374
+ if (typeof schema.toJSONSchema === "function") {
1375
+ return schema.toJSONSchema({ io: "input" });
1376
+ }
1377
+ return z3.toJSONSchema(schema, { io: "input" });
1378
+ }
1293
1379
  var SINGLE_SCHEMA_KEYWORDS = [
1294
1380
  "additionalItems",
1295
1381
  "additionalProperties",
@@ -1663,5 +1749,6 @@ export {
1663
1749
  undeclaredIconProblem,
1664
1750
  validatePluginAiServiceDeclaration,
1665
1751
  validatePluginProviderDeclaration,
1666
- validateSettingsUpdate
1752
+ validateSettingsUpdate,
1753
+ zodSchemaToJsonSchema
1667
1754
  };
@@ -246,6 +246,7 @@ function collectPluginAppRegistrations(definition, onComposerCustomizationReject
246
246
  const collected = {
247
247
  homepageSections: [],
248
248
  settingsSections: [],
249
+ appOverlays: [],
249
250
  navPanels: [],
250
251
  threadPanelActions: [],
251
252
  newThreadPanelActions: [],
@@ -268,6 +269,7 @@ function collectPluginAppRegistrations(definition, onComposerCustomizationReject
268
269
  const seenIds = {
269
270
  homepageSection: /* @__PURE__ */ new Set(),
270
271
  settingsSection: /* @__PURE__ */ new Set(),
272
+ appOverlay: /* @__PURE__ */ new Set(),
271
273
  navPanel: /* @__PURE__ */ new Set(),
272
274
  threadPanelAction: /* @__PURE__ */ new Set(),
273
275
  newThreadPanelAction: /* @__PURE__ */ new Set(),
@@ -316,6 +318,15 @@ function collectPluginAppRegistrations(definition, onComposerCustomizationReject
316
318
  component: requireComponent(kind, registration.component)
317
319
  });
318
320
  },
321
+ experimental_appOverlay(registration) {
322
+ const kind = "slots.experimental_appOverlay";
323
+ const id = requireSlotId(kind, registration?.id);
324
+ requireUniqueId(kind, seenIds.appOverlay, id);
325
+ collected.appOverlays.push({
326
+ id,
327
+ component: requireComponent(kind, registration.component)
328
+ });
329
+ },
319
330
  navPanel(registration) {
320
331
  const kind = "slots.navPanel";
321
332
  const id = requireSlotId(kind, registration?.id);
@@ -4189,6 +4189,11 @@ var acpCompactionCompletedNotificationParamsSchema = z34.discriminatedUnion("sta
4189
4189
  threadId: z34.string().min(1),
4190
4190
  status: z34.literal("interrupted")
4191
4191
  }).passthrough(),
4192
+ z34.object({
4193
+ threadId: z34.string().min(1),
4194
+ status: z34.literal("skipped"),
4195
+ detail: z34.string().min(1)
4196
+ }).passthrough(),
4192
4197
  z34.object({
4193
4198
  threadId: z34.string().min(1),
4194
4199
  status: z34.literal("failed"),
@@ -4820,6 +4825,18 @@ function ompCommandResult(event) {
4820
4825
  ...output.length === 0 ? {} : { output }
4821
4826
  };
4822
4827
  }
4828
+ var OMP_COMPACTION_FAILURE_PATTERN = /\bcompaction failed\b/i;
4829
+ var OMP_COMPACTION_NOOP_PATTERN = /\b(?:nothing to compact|already compacted)\b/i;
4830
+ function compactionOutcomeForEndTurn(dialect, agentMessage) {
4831
+ if (dialect.id !== "omp") {
4832
+ return { status: "completed" };
4833
+ }
4834
+ const text = agentMessage.trim();
4835
+ if (!OMP_COMPACTION_FAILURE_PATTERN.test(text)) {
4836
+ return { status: "completed" };
4837
+ }
4838
+ return OMP_COMPACTION_NOOP_PATTERN.test(text) ? { status: "skipped", detail: text } : { status: "failed", error: text };
4839
+ }
4823
4840
  var OMP_ACP_DIALECT = {
4824
4841
  id: "omp",
4825
4842
  commandResult: ompCommandResult
@@ -6022,12 +6039,22 @@ function createAcpDeltaTranslator(options = {}) {
6022
6039
  return [];
6023
6040
  }
6024
6041
  const status = params.data.status;
6042
+ const turnStatus = status === "skipped" ? "completed" : status;
6025
6043
  return [
6026
- ...flushOpenTurnWork(context, status),
6044
+ ...flushOpenTurnWork(context, itemStatusForTurnStatus(turnStatus)),
6027
6045
  ...status === "completed" ? [{ kind: "context.compacted" }] : [],
6046
+ ...status === "skipped" ? [
6047
+ {
6048
+ kind: "provider.warning",
6049
+ category: "compaction-skipped",
6050
+ summary: "Context compaction skipped",
6051
+ details: params.data.detail,
6052
+ vouchedTurn: true
6053
+ }
6054
+ ] : [],
6028
6055
  {
6029
6056
  kind: "turn.boundary",
6030
- status,
6057
+ status: turnStatus,
6031
6058
  ...status === "failed" ? { error: { message: params.data.error } } : {}
6032
6059
  }
6033
6060
  ];
@@ -6663,6 +6690,93 @@ function splitPrimaryModels(catalogModels, primaryModels) {
6663
6690
  };
6664
6691
  }
6665
6692
 
6693
+ // ../provider-bridge-acp/src/cursor-model-selection.ts
6694
+ var CURSOR_LEGACY_FAMILY_SELECTIONS = {
6695
+ "claude-4-sonnet": { modelId: "claude-sonnet-4" },
6696
+ "claude-4.5-opus": { modelId: "claude-opus-4-5" },
6697
+ "claude-4.5-sonnet": { modelId: "claude-sonnet-4-5" },
6698
+ "claude-4.6-opus": { modelId: "claude-opus-4-6" },
6699
+ "claude-4.6-sonnet": { modelId: "claude-sonnet-4-6" },
6700
+ "gemini-3.6-flash-minimal": {
6701
+ modelId: "gemini-3.6-flash",
6702
+ reasoningLevel: "low"
6703
+ },
6704
+ "gpt-5.1-codex-max": { modelId: "gpt-5.1" }
6705
+ };
6706
+ function bareCursorFamilyId(model) {
6707
+ const familyId = model === "auto" ? "default" : agentModelFamilyId(model);
6708
+ return familyId.startsWith("cursor-") ? familyId.slice("cursor-".length) : familyId;
6709
+ }
6710
+ function cursorParameterizedSelection(model, reasoningLevel) {
6711
+ const familyId = bareCursorFamilyId(model);
6712
+ const selection = CURSOR_LEGACY_FAMILY_SELECTIONS[familyId] ?? {
6713
+ modelId: familyId
6714
+ };
6715
+ return selection.reasoningLevel !== void 0 || reasoningLevel === void 0 ? selection : { ...selection, reasoningLevel };
6716
+ }
6717
+ function cursorCatalogModel(model) {
6718
+ const selection = cursorParameterizedSelection(
6719
+ model.id,
6720
+ model.defaultReasoningEffort
6721
+ );
6722
+ const efforts = /* @__PURE__ */ new Map();
6723
+ for (const effort of model.supportedReasoningEfforts) {
6724
+ const level = cursorParameterizedSelection(model.id, effort.reasoningEffort).reasoningLevel ?? effort.reasoningEffort;
6725
+ if (!efforts.has(level)) {
6726
+ efforts.set(level, { ...effort, reasoningEffort: level });
6727
+ }
6728
+ }
6729
+ return {
6730
+ model: {
6731
+ ...model,
6732
+ id: selection.modelId,
6733
+ model: selection.modelId,
6734
+ supportedReasoningEfforts: [...efforts.values()].sort(
6735
+ (a, b) => reasoningLevelValues.indexOf(a.reasoningEffort) - reasoningLevelValues.indexOf(b.reasoningEffort)
6736
+ ),
6737
+ defaultReasoningEffort: selection.reasoningLevel ?? model.defaultReasoningEffort
6738
+ },
6739
+ directFamily: bareCursorFamilyId(model.id) === selection.modelId
6740
+ };
6741
+ }
6742
+ function buildCursorParameterizedModelCatalog(models) {
6743
+ const normalized = /* @__PURE__ */ new Map();
6744
+ for (const model of models) {
6745
+ const candidate = cursorCatalogModel(model);
6746
+ const current = normalized.get(candidate.model.id);
6747
+ if (current === void 0) {
6748
+ normalized.set(candidate.model.id, candidate);
6749
+ continue;
6750
+ }
6751
+ const preferred = candidate.directFamily && !current.directFamily ? candidate : current;
6752
+ const efforts = new Map(
6753
+ preferred.model.supportedReasoningEfforts.map((effort) => [
6754
+ effort.reasoningEffort,
6755
+ effort
6756
+ ])
6757
+ );
6758
+ for (const effort of [
6759
+ ...current.model.supportedReasoningEfforts,
6760
+ ...candidate.model.supportedReasoningEfforts
6761
+ ]) {
6762
+ if (!efforts.has(effort.reasoningEffort)) {
6763
+ efforts.set(effort.reasoningEffort, effort);
6764
+ }
6765
+ }
6766
+ normalized.set(candidate.model.id, {
6767
+ model: {
6768
+ ...preferred.model,
6769
+ supportedReasoningEfforts: [...efforts.values()].sort(
6770
+ (a, b) => reasoningLevelValues.indexOf(a.reasoningEffort) - reasoningLevelValues.indexOf(b.reasoningEffort)
6771
+ ),
6772
+ isDefault: current.model.isDefault || candidate.model.isDefault
6773
+ },
6774
+ directFamily: preferred.directFamily
6775
+ });
6776
+ }
6777
+ return [...normalized.values()].map((entry) => entry.model);
6778
+ }
6779
+
6666
6780
  // ../provider-bridge-acp/src/session-params.ts
6667
6781
  function sanitizeAcpSkillDescription(description) {
6668
6782
  const sanitized = description.replace(/[\r\n]+/gu, " ").replace(/\s+/gu, " ").replace(/[<>]/gu, "").trim();
@@ -6751,26 +6865,6 @@ function buildAcpModelListParams(launchSpec, options) {
6751
6865
  ...launchSpec.nativeReasoning !== void 0 ? { nativeReasoning: launchSpec.nativeReasoning } : {}
6752
6866
  };
6753
6867
  }
6754
- var CURSOR_LEGACY_FAMILY_SELECTIONS = {
6755
- "claude-4-sonnet": { modelId: "claude-sonnet-4" },
6756
- "claude-4.5-opus": { modelId: "claude-opus-4-5" },
6757
- "claude-4.5-sonnet": { modelId: "claude-sonnet-4-5" },
6758
- "claude-4.6-opus": { modelId: "claude-opus-4-6" },
6759
- "claude-4.6-sonnet": { modelId: "claude-sonnet-4-6" },
6760
- "gemini-3.6-flash-minimal": {
6761
- modelId: "gemini-3.6-flash",
6762
- reasoningLevel: "low"
6763
- },
6764
- "gpt-5.1-codex-max": { modelId: "gpt-5.1" }
6765
- };
6766
- function cursorParameterizedSelection(model, reasoningLevel) {
6767
- const familyId = model === "auto" ? "default" : agentModelFamilyId(model);
6768
- const bareFamilyId = familyId.startsWith("cursor-") ? familyId.slice("cursor-".length) : familyId;
6769
- const selection = CURSOR_LEGACY_FAMILY_SELECTIONS[bareFamilyId] ?? {
6770
- modelId: bareFamilyId
6771
- };
6772
- return selection.reasoningLevel !== void 0 || reasoningLevel === void 0 ? selection : { ...selection, reasoningLevel };
6773
- }
6774
6868
  function buildAcpModelSelectionParam(launchSpec, options, parameterizedModelPicker, dialectId) {
6775
6869
  const model = options.model;
6776
6870
  const listCommand = buildAcpModelListCommand(launchSpec);
@@ -8636,6 +8730,7 @@ async function startAgentSession(request) {
8636
8730
  },
8637
8731
  pendingInstructions: params.instructions,
8638
8732
  activePromptKind: null,
8733
+ compactionAgentMessage: "",
8639
8734
  queuedInputs: [],
8640
8735
  promptRequestPending: false,
8641
8736
  cancelRequested: false,
@@ -8977,6 +9072,7 @@ function runTurn(session, firstInput) {
8977
9072
  }
8978
9073
  function startCompaction(session, pending) {
8979
9074
  session.activePromptKind = "compaction";
9075
+ session.compactionAgentMessage = "";
8980
9076
  emitForSession(session, ACP_COMPACTION_STARTED_METHOD, {
8981
9077
  threadId: session.bbThreadId
8982
9078
  });
@@ -8994,7 +9090,10 @@ function startCompaction(session, pending) {
8994
9090
  acceptTurnInput(session, pending);
8995
9091
  session.turnSettled = promptResult.then((result) => {
8996
9092
  finish(
8997
- result.stopReason === "end_turn" ? { status: "completed" } : result.stopReason === "cancelled" ? { status: "interrupted" } : {
9093
+ result.stopReason === "end_turn" ? compactionOutcomeForEndTurn(
9094
+ session.dialect,
9095
+ session.compactionAgentMessage
9096
+ ) : result.stopReason === "cancelled" ? { status: "interrupted" } : {
8998
9097
  status: "failed",
8999
9098
  error: `Agent stopped compaction: ${result.stopReason}`
9000
9099
  }
@@ -9080,6 +9179,14 @@ function handleAgentNotification(session, method, params) {
9080
9179
  if (parsed.data.sessionId !== session.providerThreadId) {
9081
9180
  return;
9082
9181
  }
9182
+ if (session.activePromptKind === "compaction") {
9183
+ const chunk = acpAgentMessageChunkUpdateSchema.safeParse(
9184
+ parsed.data.update
9185
+ );
9186
+ if (chunk.success) {
9187
+ session.compactionAgentMessage += extractAcpContentText(chunk.data.content) ?? "";
9188
+ }
9189
+ }
9083
9190
  emitForSession(session, ACP_UPDATE_METHOD, update);
9084
9191
  }
9085
9192
  function decodeAcpBridgeJsonRpcRequest(raw) {
@@ -9113,13 +9220,14 @@ function decodeAcpBridgeJsonRpcRequest(raw) {
9113
9220
  issues: command.error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`).join("; ")
9114
9221
  };
9115
9222
  }
9116
- async function handleModelList(id, params) {
9223
+ async function handleModelList(id, params, dialectId) {
9117
9224
  const catalog = params.listCommand ? await loadAgentModelCatalog(params.listCommand) : null;
9118
9225
  if (catalog) {
9226
+ const catalogModels = params.parameterizedModelPicker && dialectId === "cursor" ? buildCursorParameterizedModelCatalog(catalog.models) : catalog.models;
9119
9227
  sendResult(
9120
9228
  id,
9121
9229
  splitPrimaryModels(
9122
- applyConfiguredReasoningToModels(catalog.models, {
9230
+ applyConfiguredReasoningToModels(catalogModels, {
9123
9231
  reasoningCli: params.reasoningCli,
9124
9232
  nativeReasoning: params.nativeReasoning
9125
9233
  }),
@@ -9221,7 +9329,8 @@ async function handleRequest2(request) {
9221
9329
  buildAcpModelListParams(
9222
9330
  decodeLaunchSpec(request.params.providerOptions),
9223
9331
  modelPicker
9224
- )
9332
+ ),
9333
+ decodeDialectId(request.params.providerOptions)
9225
9334
  );
9226
9335
  return;
9227
9336
  }
@@ -425,6 +425,7 @@ function collectPluginAppRegistrations(definition, onComposerCustomizationReject
425
425
  const collected = {
426
426
  homepageSections: [],
427
427
  settingsSections: [],
428
+ appOverlays: [],
428
429
  navPanels: [],
429
430
  threadPanelActions: [],
430
431
  newThreadPanelActions: [],
@@ -447,6 +448,7 @@ function collectPluginAppRegistrations(definition, onComposerCustomizationReject
447
448
  const seenIds = {
448
449
  homepageSection: /* @__PURE__ */ new Set(),
449
450
  settingsSection: /* @__PURE__ */ new Set(),
451
+ appOverlay: /* @__PURE__ */ new Set(),
450
452
  navPanel: /* @__PURE__ */ new Set(),
451
453
  threadPanelAction: /* @__PURE__ */ new Set(),
452
454
  newThreadPanelAction: /* @__PURE__ */ new Set(),
@@ -495,6 +497,15 @@ function collectPluginAppRegistrations(definition, onComposerCustomizationReject
495
497
  component: requireComponent(kind, registration.component)
496
498
  });
497
499
  },
500
+ experimental_appOverlay(registration) {
501
+ const kind = "slots.experimental_appOverlay";
502
+ const id = requireSlotId(kind, registration?.id);
503
+ requireUniqueId(kind, seenIds.appOverlay, id);
504
+ collected.appOverlays.push({
505
+ id,
506
+ component: requireComponent(kind, registration.component)
507
+ });
508
+ },
498
509
  navPanel(registration) {
499
510
  const kind = "slots.navPanel";
500
511
  const id = requireSlotId(kind, registration?.id);