@get-bb/plugin-sdk 0.4.40 → 0.4.47

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
  };
@@ -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) => ({
@@ -684,13 +686,21 @@ var threadEventItemPresentationTintSchema = z6.object({
684
686
  light: z6.string().min(1),
685
687
  dark: z6.string().min(1)
686
688
  });
689
+ var THREAD_EVENT_ITEM_PRESENTATION_BADGE_LABEL_MAX_LENGTH = 80;
690
+ var threadEventItemPresentationBadgeSchema = z6.object({
691
+ glyph: z6.string().min(1),
692
+ label: z6.string().min(1).max(THREAD_EVENT_ITEM_PRESENTATION_BADGE_LABEL_MAX_LENGTH),
693
+ hint: z6.string().min(1).max(THREAD_EVENT_ITEM_PRESENTATION_BADGE_LABEL_MAX_LENGTH),
694
+ tone: z6.enum(["neutral", "destructive"])
695
+ });
687
696
  var threadEventItemPresentationSchema = z6.object({
688
697
  label: threadEventItemPresentationLabelSchema,
689
698
  icon: threadEventItemPresentationIconSchema,
690
699
  title: z6.string().optional(),
691
700
  detail: z6.string().max(THREAD_EVENT_ITEM_PRESENTATION_DETAIL_MAX_LENGTH).optional(),
692
701
  suppress: z6.boolean().optional(),
693
- tint: threadEventItemPresentationTintSchema.optional()
702
+ tint: threadEventItemPresentationTintSchema.optional(),
703
+ badge: threadEventItemPresentationBadgeSchema.optional()
694
704
  });
695
705
 
696
706
  // ../domain/src/provider-extension-kind.ts
@@ -1409,6 +1419,10 @@ var threadEventScopeDefinitionByType = {
1409
1419
  policy: "thread",
1410
1420
  rationale: "Subscription usage is account-scoped state that can affect multiple turns and threads."
1411
1421
  },
1422
+ "provider.env-resolved": {
1423
+ policy: "thread",
1424
+ rationale: "Resolved provider environment is session state and can change between turns."
1425
+ },
1412
1426
  "thread/extensionState/updated": {
1413
1427
  policy: "thread",
1414
1428
  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 +2066,25 @@ var unscopedProviderEventSchema = z14.discriminatedUnion("type", [
2052
2066
  providerThreadId: z14.string(),
2053
2067
  rateLimits: providerRateLimitStateSchema
2054
2068
  }),
2069
+ z14.object({
2070
+ type: z14.literal("provider.env-resolved"),
2071
+ threadId: z14.string(),
2072
+ providerThreadId: z14.string(),
2073
+ entries: z14.array(
2074
+ z14.object({
2075
+ name: z14.string(),
2076
+ source: z14.union([
2077
+ z14.literal("shell"),
2078
+ z14.object({ plugin: z14.string() }).strict()
2079
+ ]),
2080
+ value: z14.union([
2081
+ z14.string(),
2082
+ z14.object({ masked: z14.literal(true) }).strict()
2083
+ ]),
2084
+ reason: z14.string().optional()
2085
+ }).strict()
2086
+ )
2087
+ }),
2055
2088
  z14.object({
2056
2089
  type: z14.literal("thread/extensionState/updated"),
2057
2090
  threadId: z14.string(),
@@ -2705,7 +2738,8 @@ var sessionReplacedNotificationSchema = z23.object({
2705
2738
  threadId: z23.string().min(1),
2706
2739
  providerThreadId: z23.string().min(1).nullable(),
2707
2740
  reason: z23.string().min(1),
2708
- contextLost: z23.boolean().default(false)
2741
+ contextLost: z23.boolean().default(false),
2742
+ showRuntimeNote: z23.boolean().default(false)
2709
2743
  }).passthrough();
2710
2744
  var providerRawNotificationSchema = z23.object({
2711
2745
  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(),
@@ -6372,15 +6404,6 @@ function isRequest(message) {
6372
6404
  function isResponse(message) {
6373
6405
  return message.id !== void 0 && message.method === void 0;
6374
6406
  }
6375
- function countTurnBoundaries(events) {
6376
- let started = 0;
6377
- let completed = 0;
6378
- for (const event of events) {
6379
- if (event.type === "turn/started") started += 1;
6380
- if (event.type === "turn/completed") completed += 1;
6381
- }
6382
- return { started, completed };
6383
- }
6384
6407
  function planRuntimeSteps(recording, assembler) {
6385
6408
  const steps = [];
6386
6409
  const assembled = [];
@@ -6401,7 +6424,7 @@ function planRuntimeSteps(recording, assembler) {
6401
6424
  steps.push({
6402
6425
  entry,
6403
6426
  message: parseWire(entry.line),
6404
- gate: countTurnBoundaries(assembled),
6427
+ gate: countTurns(assembled),
6405
6428
  eventsBefore: assembled.length
6406
6429
  });
6407
6430
  }
@@ -6650,7 +6673,7 @@ async function replayRecording(options) {
6650
6673
  await waitFor(
6651
6674
  `${step.gate.started} turn/started and ${step.gate.completed} turn/completed before ${method}`,
6652
6675
  () => {
6653
- const live = countTurnBoundaries(events);
6676
+ const live = countTurns(events);
6654
6677
  return live.started >= step.gate.started && live.completed >= step.gate.completed;
6655
6678
  }
6656
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) => ({
@@ -1980,13 +1982,21 @@ var threadEventItemPresentationTintSchema = z10.object({
1980
1982
  light: z10.string().min(1),
1981
1983
  dark: z10.string().min(1)
1982
1984
  });
1985
+ var THREAD_EVENT_ITEM_PRESENTATION_BADGE_LABEL_MAX_LENGTH = 80;
1986
+ var threadEventItemPresentationBadgeSchema = z10.object({
1987
+ glyph: z10.string().min(1),
1988
+ label: z10.string().min(1).max(THREAD_EVENT_ITEM_PRESENTATION_BADGE_LABEL_MAX_LENGTH),
1989
+ hint: z10.string().min(1).max(THREAD_EVENT_ITEM_PRESENTATION_BADGE_LABEL_MAX_LENGTH),
1990
+ tone: z10.enum(["neutral", "destructive"])
1991
+ });
1983
1992
  var threadEventItemPresentationSchema = z10.object({
1984
1993
  label: threadEventItemPresentationLabelSchema,
1985
1994
  icon: threadEventItemPresentationIconSchema,
1986
1995
  title: z10.string().optional(),
1987
1996
  detail: z10.string().max(THREAD_EVENT_ITEM_PRESENTATION_DETAIL_MAX_LENGTH).optional(),
1988
1997
  suppress: z10.boolean().optional(),
1989
- tint: threadEventItemPresentationTintSchema.optional()
1998
+ tint: threadEventItemPresentationTintSchema.optional(),
1999
+ badge: threadEventItemPresentationBadgeSchema.optional()
1990
2000
  });
1991
2001
 
1992
2002
  // ../domain/src/provider-extension-kind.ts
@@ -2714,6 +2724,10 @@ var threadEventScopeDefinitionByType = {
2714
2724
  policy: "thread",
2715
2725
  rationale: "Subscription usage is account-scoped state that can affect multiple turns and threads."
2716
2726
  },
2727
+ "provider.env-resolved": {
2728
+ policy: "thread",
2729
+ rationale: "Resolved provider environment is session state and can change between turns."
2730
+ },
2717
2731
  "thread/extensionState/updated": {
2718
2732
  policy: "thread",
2719
2733
  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 +3371,25 @@ var unscopedProviderEventSchema = z18.discriminatedUnion("type", [
3357
3371
  providerThreadId: z18.string(),
3358
3372
  rateLimits: providerRateLimitStateSchema
3359
3373
  }),
3374
+ z18.object({
3375
+ type: z18.literal("provider.env-resolved"),
3376
+ threadId: z18.string(),
3377
+ providerThreadId: z18.string(),
3378
+ entries: z18.array(
3379
+ z18.object({
3380
+ name: z18.string(),
3381
+ source: z18.union([
3382
+ z18.literal("shell"),
3383
+ z18.object({ plugin: z18.string() }).strict()
3384
+ ]),
3385
+ value: z18.union([
3386
+ z18.string(),
3387
+ z18.object({ masked: z18.literal(true) }).strict()
3388
+ ]),
3389
+ reason: z18.string().optional()
3390
+ }).strict()
3391
+ )
3392
+ }),
3360
3393
  z18.object({
3361
3394
  type: z18.literal("thread/extensionState/updated"),
3362
3395
  threadId: z18.string(),
@@ -4280,7 +4313,8 @@ var sessionReplacedNotificationSchema = z29.object({
4280
4313
  threadId: z29.string().min(1),
4281
4314
  providerThreadId: z29.string().min(1).nullable(),
4282
4315
  reason: z29.string().min(1),
4283
- contextLost: z29.boolean().default(false)
4316
+ contextLost: z29.boolean().default(false),
4317
+ showRuntimeNote: z29.boolean().default(false)
4284
4318
  }).passthrough();
4285
4319
  var providerRawNotificationSchema = z29.object({
4286
4320
  threadId: z29.string().min(1).optional(),