@get-bb/plugin-sdk 0.4.45 → 0.4.48

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.
@@ -213,6 +213,127 @@ function collectComposerCustomization(registration, seenIds, onRejected) {
213
213
  }
214
214
 
215
215
  // src/internal/plugin-app-collector.ts
216
+ var sidebarFooterCommandSequence = 0;
217
+ var SIDEBAR_FOOTER_ACTION_KEYS = /* @__PURE__ */ new Set([
218
+ "id",
219
+ "label",
220
+ "icon",
221
+ "kind",
222
+ "onActivate"
223
+ ]);
224
+ var SIDEBAR_FOOTER_DISCLOSURE_KEYS = /* @__PURE__ */ new Set([
225
+ "id",
226
+ "label",
227
+ "icon",
228
+ "kind",
229
+ "component"
230
+ ]);
231
+ var SidebarFooterItemRuntime = class {
232
+ listeners = /* @__PURE__ */ new Set();
233
+ snapshot = {
234
+ command: null
235
+ };
236
+ subscribe = (listener) => {
237
+ this.listeners.add(listener);
238
+ return () => this.listeners.delete(listener);
239
+ };
240
+ getSnapshot = () => this.snapshot;
241
+ acknowledgeCommand = (sequence) => {
242
+ if (this.snapshot.command?.sequence !== sequence) return;
243
+ this.snapshot = { ...this.snapshot, command: null };
244
+ this.emit();
245
+ };
246
+ createDisclosureController() {
247
+ return Object.freeze({
248
+ open: () => this.request("open"),
249
+ close: () => this.request("close"),
250
+ toggle: () => this.request("toggle")
251
+ });
252
+ }
253
+ request(kind) {
254
+ sidebarFooterCommandSequence += 1;
255
+ this.snapshot = {
256
+ ...this.snapshot,
257
+ command: { sequence: sidebarFooterCommandSequence, kind }
258
+ };
259
+ this.emit();
260
+ }
261
+ emit() {
262
+ for (const listener of this.listeners) listener();
263
+ }
264
+ };
265
+ function adaptSidebarFooterAction(registration) {
266
+ return {
267
+ source: "sidebarFooterAction",
268
+ id: registration.id,
269
+ label: registration.title,
270
+ icon: registration.icon,
271
+ kind: "action",
272
+ onActivate: ({ openPluginDetails }) => registration.run({ openSettings: openPluginDetails }),
273
+ runtime: new SidebarFooterItemRuntime()
274
+ };
275
+ }
276
+ var SidebarFooterCollector = class {
277
+ constructor(collected, allCollected, seenIds) {
278
+ this.collected = collected;
279
+ this.allCollected = allCollected;
280
+ this.seenIds = seenIds;
281
+ }
282
+ collected;
283
+ allCollected;
284
+ seenIds;
285
+ register(registration) {
286
+ const kind = "experimental_sidebarFooter.register";
287
+ const id = requireSlotId(kind, registration?.id);
288
+ requireUniqueId(kind, this.seenIds, id);
289
+ const label = requireNonEmptyString(kind, "label", registration.label);
290
+ const icon = requireNonEmptyString(kind, "icon", registration.icon);
291
+ const runtime = new SidebarFooterItemRuntime();
292
+ if (registration.kind === "action") {
293
+ this.rejectUnknownKeys(kind, registration, SIDEBAR_FOOTER_ACTION_KEYS);
294
+ if (typeof registration.onActivate !== "function") {
295
+ throw new Error(`${kind}: "onActivate" must be a function`);
296
+ }
297
+ const item = {
298
+ id,
299
+ label,
300
+ icon,
301
+ kind: "action",
302
+ onActivate: registration.onActivate,
303
+ source: "experimental_sidebarFooter",
304
+ runtime
305
+ };
306
+ this.collected.push(item);
307
+ this.allCollected.push(item);
308
+ return;
309
+ }
310
+ if (registration.kind === "disclosure") {
311
+ this.rejectUnknownKeys(
312
+ kind,
313
+ registration,
314
+ SIDEBAR_FOOTER_DISCLOSURE_KEYS
315
+ );
316
+ const item = {
317
+ id,
318
+ label,
319
+ icon,
320
+ kind: "disclosure",
321
+ component: requireComponent(kind, registration.component),
322
+ source: "experimental_sidebarFooter",
323
+ runtime
324
+ };
325
+ this.collected.push(item);
326
+ this.allCollected.push(item);
327
+ return runtime.createDisclosureController();
328
+ }
329
+ throw new Error(`${kind}: "kind" must be "action" or "disclosure"`);
330
+ }
331
+ rejectUnknownKeys(kind, registration, allowed) {
332
+ for (const key of Object.keys(registration)) {
333
+ if (!allowed.has(key)) throw new Error(`${kind}: unknown field "${key}"`);
334
+ }
335
+ }
336
+ };
216
337
  var NAV_PANEL_REGISTRATION_KEYS = new Set(
217
338
  Object.keys({
218
339
  id: true,
@@ -242,7 +363,12 @@ function rejectStaleNavPanelKeys(kind, registration) {
242
363
  }
243
364
  }
244
365
  }
366
+ var sidebarFooterItemsByRegistrationSet = /* @__PURE__ */ new WeakMap();
367
+ function getCollectedSidebarFooterItems(registrations) {
368
+ return sidebarFooterItemsByRegistrationSet.get(registrations) ?? null;
369
+ }
245
370
  function collectPluginAppRegistrations(definition, onComposerCustomizationRejected = (reason) => console.warn(reason)) {
371
+ const sidebarFooterItems = [];
246
372
  const collected = {
247
373
  homepageSections: [],
248
374
  settingsSections: [],
@@ -253,6 +379,7 @@ function collectPluginAppRegistrations(definition, onComposerCustomizationReject
253
379
  composerCustomizations: [],
254
380
  pendingInteractions: [],
255
381
  sidebarFooterActions: [],
382
+ experimentalSidebarFooterItems: [],
256
383
  experimentalSidebarNavigations: [],
257
384
  threadLists: [],
258
385
  threadHeaderActions: [],
@@ -266,6 +393,7 @@ function collectPluginAppRegistrations(definition, onComposerCustomizationReject
266
393
  timelineRenderers: [],
267
394
  contentScripts: []
268
395
  };
396
+ sidebarFooterItemsByRegistrationSet.set(collected, sidebarFooterItems);
269
397
  const seenIds = {
270
398
  homepageSection: /* @__PURE__ */ new Set(),
271
399
  settingsSection: /* @__PURE__ */ new Set(),
@@ -275,7 +403,7 @@ function collectPluginAppRegistrations(definition, onComposerCustomizationReject
275
403
  newThreadPanelAction: /* @__PURE__ */ new Set(),
276
404
  composerCustomization: /* @__PURE__ */ new Set(),
277
405
  pendingInteraction: /* @__PURE__ */ new Set(),
278
- sidebarFooterAction: /* @__PURE__ */ new Set(),
406
+ sidebarFooterItem: /* @__PURE__ */ new Set(),
279
407
  sidebarNavigation: /* @__PURE__ */ new Set(),
280
408
  threadList: /* @__PURE__ */ new Set(),
281
409
  threadHeaderAction: /* @__PURE__ */ new Set(),
@@ -466,16 +594,18 @@ function collectPluginAppRegistrations(definition, onComposerCustomizationReject
466
594
  sidebarFooterAction(registration) {
467
595
  const kind = "slots.sidebarFooterAction";
468
596
  const id = requireSlotId(kind, registration?.id);
469
- requireUniqueId(kind, seenIds.sidebarFooterAction, id);
597
+ requireUniqueId(kind, seenIds.sidebarFooterItem, id);
470
598
  if (typeof registration.run !== "function") {
471
599
  throw new Error(`${kind}: "run" must be a function`);
472
600
  }
473
- collected.sidebarFooterActions.push({
601
+ const legacyRegistration = {
474
602
  id,
475
603
  title: requireNonEmptyString(kind, "title", registration.title),
476
604
  icon: requireNonEmptyString(kind, "icon", registration.icon),
477
605
  run: registration.run
478
- });
606
+ };
607
+ collected.sidebarFooterActions.push(legacyRegistration);
608
+ sidebarFooterItems.push(adaptSidebarFooterAction(legacyRegistration));
479
609
  },
480
610
  experimental_sidebarNavigation(registration) {
481
611
  const kind = "slots.experimental_sidebarNavigation";
@@ -637,6 +767,11 @@ function collectPluginAppRegistrations(definition, onComposerCustomizationReject
637
767
  });
638
768
  }
639
769
  },
770
+ experimental_sidebarFooter: new SidebarFooterCollector(
771
+ collected.experimentalSidebarFooterItems,
772
+ sidebarFooterItems,
773
+ seenIds.sidebarFooterItem
774
+ ),
640
775
  composer: {
641
776
  customize(registration) {
642
777
  const customization = collectComposerCustomization(
@@ -664,5 +799,7 @@ function collectPluginAppRegistrations(definition, onComposerCustomizationReject
664
799
  return collected;
665
800
  }
666
801
  export {
667
- collectPluginAppRegistrations
802
+ adaptSidebarFooterAction,
803
+ collectPluginAppRegistrations,
804
+ getCollectedSidebarFooterItems
668
805
  };
@@ -189,11 +189,11 @@ var promptInputSchema = z2.discriminatedUnion("type", [
189
189
  function isSelectedPromptCommandMention(mention, selector) {
190
190
  return mention.resource.kind === "command" && mention.resource.trigger === selector.trigger && mention.resource.name === selector.name;
191
191
  }
192
- var BUILTIN_COMPACT_COMMAND = { trigger: "/", name: "compact" };
193
- function isStandaloneBuiltinCompactCommand(input) {
192
+ function isStandaloneBuiltinCommand(input, name) {
193
+ const selector = { trigger: "/", name };
194
194
  const selected = input.flatMap(
195
195
  (item) => item.type === "text" ? item.mentions.filter(
196
- (mention2) => isSelectedPromptCommandMention(mention2, BUILTIN_COMPACT_COMMAND)
196
+ (mention2) => isSelectedPromptCommandMention(mention2, selector)
197
197
  ).map((mention2) => ({ mention: mention2, text: item.text })) : []
198
198
  );
199
199
  const standalone = selected[0];
@@ -201,13 +201,15 @@ function isStandaloneBuiltinCompactCommand(input) {
201
201
  return false;
202
202
  }
203
203
  const { mention, text } = standalone;
204
- if (mention.resource.kind !== "command" || mention.resource.source !== "command" || mention.resource.origin !== "builtin" || text.slice(mention.start, mention.end) !== "/compact") {
204
+ if (mention.resource.kind !== "command" || mention.resource.source !== "command" || mention.resource.origin !== "builtin" || text.slice(mention.start, mention.end) !== `/${name}`) {
205
205
  return false;
206
206
  }
207
- return removeCommandMentionsFromPromptInput(
208
- input,
209
- BUILTIN_COMPACT_COMMAND
210
- ).every((item) => item.type === "text" && item.text.trim() === "");
207
+ return removeCommandMentionsFromPromptInput(input, selector).every(
208
+ (item) => item.type === "text" && item.text.trim() === ""
209
+ );
210
+ }
211
+ function isStandaloneBuiltinCompactCommand(input) {
212
+ return isStandaloneBuiltinCommand(input, "compact");
211
213
  }
212
214
  function commandRemovalRanges(input, selector) {
213
215
  return input.mentions.filter((mention) => isSelectedPromptCommandMention(mention, selector)).map((mention) => ({
@@ -6404,15 +6404,6 @@ function isRequest(message) {
6404
6404
  function isResponse(message) {
6405
6405
  return message.id !== void 0 && message.method === void 0;
6406
6406
  }
6407
- function countTurnBoundaries(events) {
6408
- let started = 0;
6409
- let completed = 0;
6410
- for (const event of events) {
6411
- if (event.type === "turn/started") started += 1;
6412
- if (event.type === "turn/completed") completed += 1;
6413
- }
6414
- return { started, completed };
6415
- }
6416
6407
  function planRuntimeSteps(recording, assembler) {
6417
6408
  const steps = [];
6418
6409
  const assembled = [];
@@ -6433,7 +6424,7 @@ function planRuntimeSteps(recording, assembler) {
6433
6424
  steps.push({
6434
6425
  entry,
6435
6426
  message: parseWire(entry.line),
6436
- gate: countTurnBoundaries(assembled),
6427
+ gate: countTurns(assembled),
6437
6428
  eventsBefore: assembled.length
6438
6429
  });
6439
6430
  }
@@ -6682,7 +6673,7 @@ async function replayRecording(options) {
6682
6673
  await waitFor(
6683
6674
  `${step.gate.started} turn/started and ${step.gate.completed} turn/completed before ${method}`,
6684
6675
  () => {
6685
- const live = countTurnBoundaries(events);
6676
+ const live = countTurns(events);
6686
6677
  return live.started >= step.gate.started && live.completed >= step.gate.completed;
6687
6678
  }
6688
6679
  );
@@ -1460,11 +1460,11 @@ var promptInputSchema = z6.discriminatedUnion("type", [
1460
1460
  function isSelectedPromptCommandMention(mention, selector) {
1461
1461
  return mention.resource.kind === "command" && mention.resource.trigger === selector.trigger && mention.resource.name === selector.name;
1462
1462
  }
1463
- var BUILTIN_COMPACT_COMMAND = { trigger: "/", name: "compact" };
1464
- function isStandaloneBuiltinCompactCommand(input) {
1463
+ function isStandaloneBuiltinCommand(input, name) {
1464
+ const selector = { trigger: "/", name };
1465
1465
  const selected = input.flatMap(
1466
1466
  (item) => item.type === "text" ? item.mentions.filter(
1467
- (mention2) => isSelectedPromptCommandMention(mention2, BUILTIN_COMPACT_COMMAND)
1467
+ (mention2) => isSelectedPromptCommandMention(mention2, selector)
1468
1468
  ).map((mention2) => ({ mention: mention2, text: item.text })) : []
1469
1469
  );
1470
1470
  const standalone = selected[0];
@@ -1472,13 +1472,15 @@ function isStandaloneBuiltinCompactCommand(input) {
1472
1472
  return false;
1473
1473
  }
1474
1474
  const { mention, text } = standalone;
1475
- if (mention.resource.kind !== "command" || mention.resource.source !== "command" || mention.resource.origin !== "builtin" || text.slice(mention.start, mention.end) !== "/compact") {
1475
+ if (mention.resource.kind !== "command" || mention.resource.source !== "command" || mention.resource.origin !== "builtin" || text.slice(mention.start, mention.end) !== `/${name}`) {
1476
1476
  return false;
1477
1477
  }
1478
- return removeCommandMentionsFromPromptInput(
1479
- input,
1480
- BUILTIN_COMPACT_COMMAND
1481
- ).every((item) => item.type === "text" && item.text.trim() === "");
1478
+ return removeCommandMentionsFromPromptInput(input, selector).every(
1479
+ (item) => item.type === "text" && item.text.trim() === ""
1480
+ );
1481
+ }
1482
+ function isStandaloneBuiltinCompactCommand(input) {
1483
+ return isStandaloneBuiltinCommand(input, "compact");
1482
1484
  }
1483
1485
  function commandRemovalRanges(input, selector) {
1484
1486
  return input.mentions.filter((mention) => isSelectedPromptCommandMention(mention, selector)).map((mention) => ({
@@ -392,6 +392,127 @@ function normalizeExperimentalFileOpenOptions(value) {
392
392
  }
393
393
 
394
394
  // src/internal/plugin-app-collector.ts
395
+ var sidebarFooterCommandSequence = 0;
396
+ var SIDEBAR_FOOTER_ACTION_KEYS = /* @__PURE__ */ new Set([
397
+ "id",
398
+ "label",
399
+ "icon",
400
+ "kind",
401
+ "onActivate"
402
+ ]);
403
+ var SIDEBAR_FOOTER_DISCLOSURE_KEYS = /* @__PURE__ */ new Set([
404
+ "id",
405
+ "label",
406
+ "icon",
407
+ "kind",
408
+ "component"
409
+ ]);
410
+ var SidebarFooterItemRuntime = class {
411
+ listeners = /* @__PURE__ */ new Set();
412
+ snapshot = {
413
+ command: null
414
+ };
415
+ subscribe = (listener) => {
416
+ this.listeners.add(listener);
417
+ return () => this.listeners.delete(listener);
418
+ };
419
+ getSnapshot = () => this.snapshot;
420
+ acknowledgeCommand = (sequence) => {
421
+ if (this.snapshot.command?.sequence !== sequence) return;
422
+ this.snapshot = { ...this.snapshot, command: null };
423
+ this.emit();
424
+ };
425
+ createDisclosureController() {
426
+ return Object.freeze({
427
+ open: () => this.request("open"),
428
+ close: () => this.request("close"),
429
+ toggle: () => this.request("toggle")
430
+ });
431
+ }
432
+ request(kind) {
433
+ sidebarFooterCommandSequence += 1;
434
+ this.snapshot = {
435
+ ...this.snapshot,
436
+ command: { sequence: sidebarFooterCommandSequence, kind }
437
+ };
438
+ this.emit();
439
+ }
440
+ emit() {
441
+ for (const listener of this.listeners) listener();
442
+ }
443
+ };
444
+ function adaptSidebarFooterAction(registration) {
445
+ return {
446
+ source: "sidebarFooterAction",
447
+ id: registration.id,
448
+ label: registration.title,
449
+ icon: registration.icon,
450
+ kind: "action",
451
+ onActivate: ({ openPluginDetails }) => registration.run({ openSettings: openPluginDetails }),
452
+ runtime: new SidebarFooterItemRuntime()
453
+ };
454
+ }
455
+ var SidebarFooterCollector = class {
456
+ constructor(collected, allCollected, seenIds) {
457
+ this.collected = collected;
458
+ this.allCollected = allCollected;
459
+ this.seenIds = seenIds;
460
+ }
461
+ collected;
462
+ allCollected;
463
+ seenIds;
464
+ register(registration) {
465
+ const kind = "experimental_sidebarFooter.register";
466
+ const id = requireSlotId(kind, registration?.id);
467
+ requireUniqueId(kind, this.seenIds, id);
468
+ const label = requireNonEmptyString(kind, "label", registration.label);
469
+ const icon = requireNonEmptyString(kind, "icon", registration.icon);
470
+ const runtime = new SidebarFooterItemRuntime();
471
+ if (registration.kind === "action") {
472
+ this.rejectUnknownKeys(kind, registration, SIDEBAR_FOOTER_ACTION_KEYS);
473
+ if (typeof registration.onActivate !== "function") {
474
+ throw new Error(`${kind}: "onActivate" must be a function`);
475
+ }
476
+ const item = {
477
+ id,
478
+ label,
479
+ icon,
480
+ kind: "action",
481
+ onActivate: registration.onActivate,
482
+ source: "experimental_sidebarFooter",
483
+ runtime
484
+ };
485
+ this.collected.push(item);
486
+ this.allCollected.push(item);
487
+ return;
488
+ }
489
+ if (registration.kind === "disclosure") {
490
+ this.rejectUnknownKeys(
491
+ kind,
492
+ registration,
493
+ SIDEBAR_FOOTER_DISCLOSURE_KEYS
494
+ );
495
+ const item = {
496
+ id,
497
+ label,
498
+ icon,
499
+ kind: "disclosure",
500
+ component: requireComponent(kind, registration.component),
501
+ source: "experimental_sidebarFooter",
502
+ runtime
503
+ };
504
+ this.collected.push(item);
505
+ this.allCollected.push(item);
506
+ return runtime.createDisclosureController();
507
+ }
508
+ throw new Error(`${kind}: "kind" must be "action" or "disclosure"`);
509
+ }
510
+ rejectUnknownKeys(kind, registration, allowed) {
511
+ for (const key of Object.keys(registration)) {
512
+ if (!allowed.has(key)) throw new Error(`${kind}: unknown field "${key}"`);
513
+ }
514
+ }
515
+ };
395
516
  var NAV_PANEL_REGISTRATION_KEYS = new Set(
396
517
  Object.keys({
397
518
  id: true,
@@ -421,7 +542,9 @@ function rejectStaleNavPanelKeys(kind, registration) {
421
542
  }
422
543
  }
423
544
  }
545
+ var sidebarFooterItemsByRegistrationSet = /* @__PURE__ */ new WeakMap();
424
546
  function collectPluginAppRegistrations(definition, onComposerCustomizationRejected = (reason) => console.warn(reason)) {
547
+ const sidebarFooterItems = [];
425
548
  const collected = {
426
549
  homepageSections: [],
427
550
  settingsSections: [],
@@ -432,6 +555,7 @@ function collectPluginAppRegistrations(definition, onComposerCustomizationReject
432
555
  composerCustomizations: [],
433
556
  pendingInteractions: [],
434
557
  sidebarFooterActions: [],
558
+ experimentalSidebarFooterItems: [],
435
559
  experimentalSidebarNavigations: [],
436
560
  threadLists: [],
437
561
  threadHeaderActions: [],
@@ -445,6 +569,7 @@ function collectPluginAppRegistrations(definition, onComposerCustomizationReject
445
569
  timelineRenderers: [],
446
570
  contentScripts: []
447
571
  };
572
+ sidebarFooterItemsByRegistrationSet.set(collected, sidebarFooterItems);
448
573
  const seenIds = {
449
574
  homepageSection: /* @__PURE__ */ new Set(),
450
575
  settingsSection: /* @__PURE__ */ new Set(),
@@ -454,7 +579,7 @@ function collectPluginAppRegistrations(definition, onComposerCustomizationReject
454
579
  newThreadPanelAction: /* @__PURE__ */ new Set(),
455
580
  composerCustomization: /* @__PURE__ */ new Set(),
456
581
  pendingInteraction: /* @__PURE__ */ new Set(),
457
- sidebarFooterAction: /* @__PURE__ */ new Set(),
582
+ sidebarFooterItem: /* @__PURE__ */ new Set(),
458
583
  sidebarNavigation: /* @__PURE__ */ new Set(),
459
584
  threadList: /* @__PURE__ */ new Set(),
460
585
  threadHeaderAction: /* @__PURE__ */ new Set(),
@@ -645,16 +770,18 @@ function collectPluginAppRegistrations(definition, onComposerCustomizationReject
645
770
  sidebarFooterAction(registration) {
646
771
  const kind = "slots.sidebarFooterAction";
647
772
  const id = requireSlotId(kind, registration?.id);
648
- requireUniqueId(kind, seenIds.sidebarFooterAction, id);
773
+ requireUniqueId(kind, seenIds.sidebarFooterItem, id);
649
774
  if (typeof registration.run !== "function") {
650
775
  throw new Error(`${kind}: "run" must be a function`);
651
776
  }
652
- collected.sidebarFooterActions.push({
777
+ const legacyRegistration = {
653
778
  id,
654
779
  title: requireNonEmptyString(kind, "title", registration.title),
655
780
  icon: requireNonEmptyString(kind, "icon", registration.icon),
656
781
  run: registration.run
657
- });
782
+ };
783
+ collected.sidebarFooterActions.push(legacyRegistration);
784
+ sidebarFooterItems.push(adaptSidebarFooterAction(legacyRegistration));
658
785
  },
659
786
  experimental_sidebarNavigation(registration) {
660
787
  const kind = "slots.experimental_sidebarNavigation";
@@ -816,6 +943,11 @@ function collectPluginAppRegistrations(definition, onComposerCustomizationReject
816
943
  });
817
944
  }
818
945
  },
946
+ experimental_sidebarFooter: new SidebarFooterCollector(
947
+ collected.experimentalSidebarFooterItems,
948
+ sidebarFooterItems,
949
+ seenIds.sidebarFooterItem
950
+ ),
819
951
  composer: {
820
952
  customize(registration) {
821
953
  const customization = collectComposerCustomization(