@burdenoff/fe-libs 2026.1029.2 → 2026.1029.4

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.
Files changed (31) hide show
  1. package/dist/shared/assistant/conversation.d.ts +10 -0
  2. package/dist/shared/assistant/i18nManifest.d.ts +15 -2
  3. package/dist/shared/assistant/i18nManifest.js +12 -0
  4. package/dist/shared/assistant/index.d.ts +4 -0
  5. package/dist/shared/assistant/productCopy.d.ts +8 -0
  6. package/dist/shared/assistant/productCopy.js +8 -5
  7. package/dist/shared/assistant/turnTimeline.js +1 -1
  8. package/dist/shared/assistant/turnTimingReporter.d.ts +11 -0
  9. package/dist/shared/assistant/turnTimingReporter.js +73 -56
  10. package/dist/shared/assistant/ui/AIAssistantPanel.d.ts +9 -0
  11. package/dist/shared/assistant/ui/AIAssistantPanel.js +70 -69
  12. package/dist/shared/assistant/ui/AssistantApiCallsConsentDialog.d.ts +23 -0
  13. package/dist/shared/assistant/ui/AssistantApiCallsConsentDialog.js +72 -18
  14. package/dist/shared/assistant/ui/AssistantChatArea.d.ts +6 -0
  15. package/dist/shared/assistant/ui/AssistantChatArea.js +1206 -1095
  16. package/dist/shared/assistant/ui/AssistantSpeechProvider.js +134 -129
  17. package/dist/shared/assistant/ui/composer/AssistantComposer.d.ts +27 -0
  18. package/dist/shared/assistant/ui/composer/AssistantComposer.js +350 -206
  19. package/dist/shared/assistant/ui/composer/AssistantModeMenu.d.ts +51 -0
  20. package/dist/shared/assistant/ui/composer/AssistantModeMenu.js +188 -0
  21. package/dist/shared/assistant/ui/composer/imeEnter.d.ts +44 -0
  22. package/dist/shared/assistant/ui/composer/imeEnter.js +11 -0
  23. package/dist/shared/assistant/ui/composer/modeMenuKeys.d.ts +76 -0
  24. package/dist/shared/assistant/ui/composer/modeMenuKeys.js +61 -0
  25. package/dist/shared/assistant/ui/composer/modeSwitchPlan.d.ts +73 -0
  26. package/dist/shared/assistant/ui/composer/modeSwitchPlan.js +25 -0
  27. package/dist/shared/assistant/ui/useVoiceSession.js +201 -177
  28. package/dist/shared/assistant/voice/voiceSession.d.ts +7 -0
  29. package/dist/shared/assistant/voice/voiceSession.js +10 -1
  30. package/dist/shared-assistant.js +241 -237
  31. package/package.json +1 -1
@@ -407,6 +407,16 @@ export interface AssistantModeConfig {
407
407
  id: AssistantMode;
408
408
  label: string;
409
409
  description: string;
410
+ /**
411
+ * One line under the mode's name in the COMPACT presentation's Mode menu
412
+ * (BOFF-10055): what the mode does, in the product's confirmed wording.
413
+ * Translated at display time under `modeShortDescription.<id>`
414
+ * (`productCopy.ts`), which `assistantI18nSeedCopy` emits.
415
+ *
416
+ * ★ Not `description`: that is the long description, already seeded under
417
+ * `modeDescription.<id>` with a different meaning. Absent: no line.
418
+ */
419
+ shortDescription?: string;
410
420
  suggestions: readonly string[];
411
421
  /** Only offered to a workspace admin, `sandbox:admin` here (see useAssistantApiAccess). */
412
422
  requiresAdmin?: boolean;
@@ -41,7 +41,8 @@ import { AssistantModeConfig } from './conversation';
41
41
  * - A mode's `description` and `suggestions`, and the page label from
42
42
  * `describeCurrentPage()`, are the product's words too. Since BOFF-8060 (F5)
43
43
  * they are translated AT DISPLAY TIME under keys derived from their English
44
- * (`suggestion.<mode>.<slug>`, `modeDescription.<mode>`, `page.<slug>`; see
44
+ * (`suggestion.<mode>.<slug>`, `modeDescription.<mode>`,
45
+ * `modeShortDescription.<mode>`, `page.<slug>`; see
45
46
  * `productCopy.ts`). They stay out of the shared manifest, and
46
47
  * `assistantI18nSeedCopy` emits them from the product's own modes and the
47
48
  * `pageLabels` it passes — so a product passes its ENGLISH, never a
@@ -352,6 +353,8 @@ export declare const ASSISTANT_I18N_LITERAL_COPY: {
352
353
  readonly 'composer.dropHere': "Drop files to attach";
353
354
  readonly 'composer.hint': "Enter to send · Shift+Enter for newline · drag or paste files to attach";
354
355
  readonly 'composer.placeholder': "Ask me anything…";
356
+ readonly 'composer.stop': "Stop the reply";
357
+ readonly 'composer.stopped': "Reply stopped.";
355
358
  readonly 'composer.voiceStart': "Dictate a message";
356
359
  readonly 'composer.voiceStarting': "Starting the microphone — tap to cancel";
357
360
  readonly 'composer.voiceStop': "Stop dictation";
@@ -500,9 +503,19 @@ export declare const ASSISTANT_I18N_LITERAL_COPY: {
500
503
  readonly 'message.stopSpeaking': "Stop reading aloud";
501
504
  readonly 'message.stopSpeakingShort': "Stop";
502
505
  readonly 'messageList.ariaLabel': "Conversation messages";
506
+ readonly 'modeMenu.disabledBusy': "Mode can't change right now.";
507
+ readonly 'modeMenu.disabledReplying': "Mode can't change while the assistant is replying. Stop the reply to change it.";
508
+ readonly 'modeMenu.staticLabel': "Mode: {{mode}}";
509
+ readonly 'modeMenu.trigger': "Assistant mode: {{mode}}";
503
510
  readonly 'modeSelector.ariaLabel': "Select assistant mode";
504
511
  readonly 'modeSelector.auto': "Auto";
505
512
  readonly 'modeSelector.autoHint': "Answers your questions, and proposes changes for you to approve";
513
+ readonly 'modeSwitch.confirm': "Switch to {{mode}}";
514
+ readonly 'modeSwitch.draftKept': "What you typed stays in the message box.";
515
+ readonly 'modeSwitch.intro': "If you switch now:";
516
+ readonly 'modeSwitch.newConversation': "{{mode}} continues in a new conversation. This one stays in History.";
517
+ readonly 'modeSwitch.title': "Switch to {{mode}}?";
518
+ readonly 'modeSwitch.withdrawn': "{{count}} change(s) waiting for your approval will be withdrawn.";
506
519
  readonly 'offer.announce': "Suggested page: {{page}}";
507
520
  readonly 'offer.expired': "That suggestion has expired. Ask again, or use the menu.";
508
521
  readonly 'offer.hintLink': "Tap, or say “take me there”.";
@@ -708,7 +721,7 @@ export declare const ASSISTANT_I18N_MANIFEST: Readonly<Record<string, string>>;
708
721
  * The part of a mode that decides its keys and English: the pill, plus (when
709
722
  * given) its description and suggestion chips (BOFF-8060, F5).
710
723
  */
711
- export type AssistantModeCopySource = Pick<AssistantModeConfig, 'id' | 'label' | 'producesArtifacts'> & Partial<Pick<AssistantModeConfig, 'description' | 'suggestions'>>;
724
+ export type AssistantModeCopySource = Pick<AssistantModeConfig, 'id' | 'label' | 'producesArtifacts'> & Partial<Pick<AssistantModeConfig, 'description' | 'shortDescription' | 'suggestions'>>;
712
725
  /**
713
726
  * `mode.<id>` for each mode a product offers, in the product's own words.
714
727
  *
@@ -246,6 +246,8 @@ var g = {
246
246
  "composer.dropHere": "Drop files to attach",
247
247
  "composer.hint": "Enter to send · Shift+Enter for newline · drag or paste files to attach",
248
248
  "composer.placeholder": "Ask me anything…",
249
+ "composer.stop": "Stop the reply",
250
+ "composer.stopped": "Reply stopped.",
249
251
  "composer.voiceStart": "Dictate a message",
250
252
  "composer.voiceStarting": "Starting the microphone — tap to cancel",
251
253
  "composer.voiceStop": "Stop dictation",
@@ -394,9 +396,19 @@ var g = {
394
396
  "message.stopSpeaking": "Stop reading aloud",
395
397
  "message.stopSpeakingShort": "Stop",
396
398
  "messageList.ariaLabel": "Conversation messages",
399
+ "modeMenu.disabledBusy": "Mode can't change right now.",
400
+ "modeMenu.disabledReplying": "Mode can't change while the assistant is replying. Stop the reply to change it.",
401
+ "modeMenu.staticLabel": "Mode: {{mode}}",
402
+ "modeMenu.trigger": "Assistant mode: {{mode}}",
397
403
  "modeSelector.ariaLabel": "Select assistant mode",
398
404
  "modeSelector.auto": "Auto",
399
405
  "modeSelector.autoHint": "Answers your questions, and proposes changes for you to approve",
406
+ "modeSwitch.confirm": "Switch to {{mode}}",
407
+ "modeSwitch.draftKept": "What you typed stays in the message box.",
408
+ "modeSwitch.intro": "If you switch now:",
409
+ "modeSwitch.newConversation": "{{mode}} continues in a new conversation. This one stays in History.",
410
+ "modeSwitch.title": "Switch to {{mode}}?",
411
+ "modeSwitch.withdrawn": "{{count}} change(s) waiting for your approval will be withdrawn.",
400
412
  "offer.announce": "Suggested page: {{page}}",
401
413
  "offer.expired": "That suggestion has expired. Ask again, or use the menu.",
402
414
  "offer.hintLink": "Tap, or say “take me there”.",
@@ -168,6 +168,10 @@ export * from './preview/bridgeHostContext';
168
168
  export * from './preview/AssistantPreviewOverlay';
169
169
  export * from './ui/composer/AssistantLanguageSelector';
170
170
  export * from './ui/composer/AssistantModeSelector';
171
+ export * from './ui/composer/AssistantModeMenu';
172
+ export * from './ui/composer/modeMenuKeys';
173
+ export * from './ui/composer/modeSwitchPlan';
174
+ export * from './ui/composer/imeEnter';
171
175
  export * from './ui/composer/AssistantVoiceButton';
172
176
  export * from './ui/composer/AssistantVoiceSelector';
173
177
  export * from './ui/composer/AssistantVoiceGraceSelector';
@@ -13,6 +13,7 @@
13
13
  *
14
14
  * suggestion.<modeId>.<slug(english)> a suggestion chip
15
15
  * modeDescription.<modeId> a mode's description
16
+ * modeShortDescription.<modeId> a mode's one-line Mode-menu text
16
17
  * page.<slug(english)> a page label
17
18
  *
18
19
  * `slug` is the lower-camel ASCII of the English ("Show overdue tasks" ->
@@ -62,6 +63,12 @@ export declare function assistantCopySlug(english: string): string | null;
62
63
  export declare function assistantSuggestionKey(modeId: string, english: string): string | null;
63
64
  /** `modeDescription.<modeId>`. */
64
65
  export declare function assistantModeDescriptionKey(modeId: string): string;
66
+ /**
67
+ * `modeShortDescription.<modeId>`: the one line under a mode in the compact
68
+ * Mode menu (BOFF-10055). A separate family from `modeDescription.<modeId>`,
69
+ * which holds the long description and is already seeded with that meaning.
70
+ */
71
+ export declare function assistantModeShortDescriptionKey(modeId: string): string;
65
72
  /** `page.<slug>`, or null for a label that cannot be keyed. */
66
73
  export declare function assistantPageLabelKey(english: string): string | null;
67
74
  /** Translate one piece of product copy, or return it unchanged when unkeyable. */
@@ -71,6 +78,7 @@ export declare function assistantProductCopyEntries(args: {
71
78
  modes: readonly {
72
79
  id: string;
73
80
  description?: string;
81
+ shortDescription?: string;
74
82
  suggestions?: readonly string[];
75
83
  }[];
76
84
  pageLabels?: readonly string[];
@@ -21,13 +21,16 @@ function o(e) {
21
21
  return `modeDescription.${e}`;
22
22
  }
23
23
  function s(e) {
24
+ return `modeShortDescription.${e}`;
25
+ }
26
+ function c(e) {
24
27
  let t = i(e);
25
28
  return t === null ? null : `page.${t}`;
26
29
  }
27
- function c(e, t, n) {
30
+ function l(e, t, n) {
28
31
  return t === null ? n : e(t, n);
29
32
  }
30
- function l(e) {
33
+ function u(e) {
31
34
  let t = {}, n = (e, n) => {
32
35
  if (e === null) return;
33
36
  let r = t[e];
@@ -35,11 +38,11 @@ function l(e) {
35
38
  t[e] = n;
36
39
  };
37
40
  for (let t of e.modes) {
38
- t.description && t.description.trim() !== "" && n(o(t.id), t.description);
41
+ t.description && t.description.trim() !== "" && n(o(t.id), t.description), t.shortDescription && t.shortDescription.trim() !== "" && n(s(t.id), t.shortDescription);
39
42
  for (let e of t.suggestions ?? []) n(a(t.id, e), e);
40
43
  }
41
- for (let t of e.pageLabels ?? []) n(s(t), t);
44
+ for (let t of e.pageLabels ?? []) n(c(t), t);
42
45
  return t;
43
46
  }
44
47
  //#endregion
45
- export { e as MAX_COPY_SLUG_LENGTH, i as assistantCopySlug, o as assistantModeDescriptionKey, s as assistantPageLabelKey, l as assistantProductCopyEntries, a as assistantSuggestionKey, c as translateProductCopy };
48
+ export { e as MAX_COPY_SLUG_LENGTH, i as assistantCopySlug, o as assistantModeDescriptionKey, s as assistantModeShortDescriptionKey, c as assistantPageLabelKey, u as assistantProductCopyEntries, a as assistantSuggestionKey, l as translateProductCopy };
@@ -107,7 +107,7 @@ function _() {
107
107
  return [...i.values()].map(u);
108
108
  }
109
109
  function v() {
110
- i.clear();
110
+ i.clear(), a = 0;
111
111
  }
112
112
  var y = [
113
113
  {
@@ -131,6 +131,17 @@ export interface TurnTimingReportingOptions {
131
131
  /** How this panel sends a batch — reading workspace and credentials when it does. */
132
132
  send: TurnTimingSender;
133
133
  }
134
+ /**
135
+ * Register timing-only cleanup for a turn stopped on pagehide. The callback
136
+ * finishes its timeline and returns its id; the reporter reads that snapshot
137
+ * synchronously before flushing, regardless of Window listener order. Also
138
+ * call the returned `settle` before clearing the owner's id in its own exit
139
+ * handler. Normal notifications remain asynchronous. Unregister on unmount.
140
+ */
141
+ export declare function registerTurnTimingPageExit(finish: () => string | undefined): {
142
+ settle: () => void;
143
+ unregister: () => void;
144
+ };
134
145
  /**
135
146
  * Report this page's finished turns. The first call starts the page-wide
136
147
  * reporter, which runs for the page load (see the header); each panel lends it
@@ -2,10 +2,10 @@ import { graphqlFetch as e } from "../graphql/fetch.js";
2
2
  import "../../shared-graphql.js";
3
3
  import { REPORT_MY_ASSISTANT_TURN_TIMINGS as t } from "./operations.js";
4
4
  import { getCapability as n, isUnknownFieldError as r, markSupported as i, markUnsupported as a } from "./capabilities.js";
5
- import { subscribeTurnTimelines as o, turnClockMs as s } from "./turnTimeline.js";
6
- import { buildAbandonedTurnReport as c, buildTurnTimingReport as l, isFinishedTurn as u } from "./turnTimingReport.js";
5
+ import { subscribeTurnTimelines as o, turnClockMs as s, turnTimeline as c } from "./turnTimeline.js";
6
+ import { buildAbandonedTurnReport as l, buildTurnTimingReport as u, isFinishedTurn as d } from "./turnTimingReport.js";
7
7
  //#region src/shared/assistant/turnTimingReporter.ts
8
- var d = {
8
+ var f = {
9
9
  flushAt: 5,
10
10
  flushAfterMs: 15e3,
11
11
  maxQueued: 50,
@@ -15,7 +15,7 @@ var d = {
15
15
  rememberedTurns: 200,
16
16
  maxRunningTurns: 20
17
17
  };
18
- function f() {
18
+ function p() {
19
19
  try {
20
20
  let e = globalThis.crypto === void 0 ? null : globalThis.crypto;
21
21
  if (!e) return null;
@@ -29,22 +29,22 @@ function f() {
29
29
  return null;
30
30
  }
31
31
  }
32
- var p = (e, t) => {
32
+ var m = (e, t) => {
33
33
  let n = setTimeout(e, t);
34
34
  return () => clearTimeout(n);
35
35
  };
36
- function m(e) {
37
- let t = d, n = e.schedule ?? p, r = e.now ?? Date.now, i = e.turnClock ?? s, a = e.nonce ?? f, o = () => {
36
+ function h(e) {
37
+ let t = f, n = e.schedule ?? m, r = e.now ?? Date.now, i = e.turnClock ?? s, a = e.nonce ?? p, o = () => {
38
38
  try {
39
39
  return e.isPageHidden?.() === !0;
40
40
  } catch {
41
41
  return !1;
42
42
  }
43
- }, m = /* @__PURE__ */ new Set(), h = /* @__PURE__ */ new Map(), g = /* @__PURE__ */ new Map(), _ = [], v = null, y = !1, b = !1, x = 0, S = !1, C = !1, w = !1, T = (e) => {
44
- for (m.add(e); m.size > t.rememberedTurns;) {
45
- let e = m.values().next().value;
43
+ }, c = /* @__PURE__ */ new Set(), h = /* @__PURE__ */ new Map(), g = /* @__PURE__ */ new Map(), _ = [], v = null, y = !1, b = !1, x = 0, S = !1, C = !1, w = !1, T = (e) => {
44
+ for (c.add(e); c.size > t.rememberedTurns;) {
45
+ let e = c.values().next().value;
46
46
  if (e === void 0) break;
47
- m.delete(e);
47
+ c.delete(e);
48
48
  }
49
49
  }, E = () => {
50
50
  let e = v;
@@ -102,7 +102,7 @@ function m(e) {
102
102
  let e = i();
103
103
  for (let [t, n] of [...g]) {
104
104
  g.delete(t), T(t);
105
- let r = c(n, e);
105
+ let r = l(n, e);
106
106
  r && _.push(r);
107
107
  }
108
108
  _.length > t.maxQueued && _.splice(0, _.length - t.maxQueued);
@@ -134,7 +134,7 @@ function m(e) {
134
134
  }
135
135
  function F(e, n, r) {
136
136
  T(e);
137
- let i = l(n);
137
+ let i = u(n);
138
138
  i && (_.push(i), _.length > t.maxQueued && _.splice(0, _.length - t.maxQueued), r && (o() ? P({
139
139
  final: !0,
140
140
  keepalive: !0,
@@ -155,8 +155,8 @@ function m(e) {
155
155
  return {
156
156
  observe: (e) => {
157
157
  try {
158
- if (S || m.has(e.turnId)) return;
159
- if (!u(e)) {
158
+ if (S || c.has(e.turnId)) return;
159
+ if (!d(e)) {
160
160
  L(e);
161
161
  return;
162
162
  }
@@ -194,23 +194,23 @@ function m(e) {
194
194
  })
195
195
  };
196
196
  }
197
- var h = new Set([
197
+ var g = new Set([
198
198
  "GRAPHQL_VALIDATION_FAILED",
199
199
  "BAD_USER_INPUT",
200
200
  "FORBIDDEN"
201
201
  ]);
202
- function g(e) {
202
+ function _(e) {
203
203
  if (typeof e.message == "string" && r(e.message)) return !0;
204
204
  let t = e.extensions?.code;
205
- return typeof t == "string" && h.has(t);
205
+ return typeof t == "string" && g.has(t);
206
206
  }
207
- function _(e) {
207
+ function v(e) {
208
208
  return typeof e == "object" && !!e && !Array.isArray(e);
209
209
  }
210
- function v(e) {
211
- if (!_(e)) return null;
210
+ function y(e) {
211
+ if (!v(e)) return null;
212
212
  let t = e.reportMyAssistantTurnTimings;
213
- if (!_(t)) return null;
213
+ if (!v(t)) return null;
214
214
  let { enabled: n, accepted: r, rejected: i, duplicate: a, rateLimited: o } = t;
215
215
  return typeof n != "boolean" || typeof r != "number" || typeof i != "number" || typeof a != "boolean" || typeof o != "boolean" ? null : {
216
216
  enabled: n,
@@ -220,12 +220,12 @@ function v(e) {
220
220
  rateLimited: o
221
221
  };
222
222
  }
223
- function y(e) {
224
- return !_(e) || !Array.isArray(e.errors) ? [] : e.errors.filter(_);
223
+ function b(e) {
224
+ return !v(e) || !Array.isArray(e.errors) ? [] : e.errors.filter(v);
225
225
  }
226
- var b = { kind: "dropped" }, x = { kind: "unsupported" };
227
- async function S(n, i, a = e) {
228
- if (!i.workspaceId) return b;
226
+ var x = { kind: "dropped" }, S = { kind: "unsupported" };
227
+ async function C(n, i, a = e) {
228
+ if (!i.workspaceId) return x;
229
229
  try {
230
230
  let e = await a({
231
231
  gateway: "workspace",
@@ -244,78 +244,95 @@ async function S(n, i, a = e) {
244
244
  extraHeaders: { "x-request-id": `bf-assistant-${n.nonce}` },
245
245
  ...n.keepalive ? { keepalive: !0 } : {}
246
246
  });
247
- if (y(e).some(g)) return x;
248
- let r = v(e.data);
247
+ if (b(e).some(_)) return S;
248
+ let r = y(e.data);
249
249
  return r ? {
250
250
  kind: "receipt",
251
251
  receipt: r
252
- } : b;
252
+ } : x;
253
253
  } catch (e) {
254
- return r(e) || y(e).some(g) ? x : b;
254
+ return r(e) || b(e).some(_) ? S : x;
255
255
  }
256
256
  }
257
- var C = [], w = null, T = null;
258
- function E() {
257
+ var w = [], T = null, E = null, D = /* @__PURE__ */ new Set();
258
+ function O(e) {
259
+ let t = () => {
260
+ try {
261
+ let t = e(), n = t ? c(t) : void 0;
262
+ n && d(n) && E?.reporter.observe(n);
263
+ } catch {}
264
+ };
265
+ return D.add(t), {
266
+ settle: t,
267
+ unregister: () => {
268
+ D.delete(t);
269
+ }
270
+ };
271
+ }
272
+ function k() {
259
273
  return typeof document < "u" && document?.visibilityState === "hidden";
260
274
  }
261
- function D(e) {
275
+ function A(e) {
262
276
  let t = typeof window > "u" ? null : window, n = typeof document > "u" ? null : document, r = () => e.flush({
263
277
  final: !0,
264
278
  keepalive: !0,
265
279
  abandonRunning: !0
266
280
  }), i = () => {
281
+ for (let e of [...D]) e();
282
+ r();
283
+ }, a = () => {
267
284
  n?.visibilityState === "hidden" && e.flush({
268
285
  final: !0,
269
286
  keepalive: !0,
270
287
  keepAwaitingAudio: !0
271
288
  });
272
289
  };
273
- return t?.addEventListener?.("pagehide", r), n?.addEventListener?.("freeze", r), n?.addEventListener?.("visibilitychange", i), () => {
274
- t?.removeEventListener?.("pagehide", r), n?.removeEventListener?.("freeze", r), n?.removeEventListener?.("visibilitychange", i);
290
+ return t?.addEventListener?.("pagehide", i), n?.addEventListener?.("freeze", r), n?.addEventListener?.("visibilitychange", a), () => {
291
+ t?.removeEventListener?.("pagehide", i), n?.removeEventListener?.("freeze", r), n?.removeEventListener?.("visibilitychange", a);
275
292
  };
276
293
  }
277
- function O() {
278
- return C[C.length - 1]?.send ?? w;
294
+ function j() {
295
+ return w[w.length - 1]?.send ?? T;
279
296
  }
280
- function k() {
297
+ function M() {
281
298
  let e = () => void 0, t = () => void 0, n = !1, r = {
282
- reporter: m({
299
+ reporter: h({
283
300
  send: (e) => {
284
- let t = O();
285
- return t ? t(e) : Promise.resolve(b);
301
+ let t = j();
302
+ return t ? t(e) : Promise.resolve(x);
286
303
  },
287
304
  onSupported: () => i("turnTimings"),
288
- isPageHidden: E,
305
+ isPageHidden: k,
289
306
  onUnsupported: () => {
290
- a("turnTimings"), T === r && (T = null), r.release();
307
+ a("turnTimings"), E === r && (E = null), r.release();
291
308
  }
292
309
  }),
293
310
  release: () => {
294
311
  n || (n = !0, e(), t());
295
312
  }
296
313
  };
297
- return e = o((e) => r.reporter.observe(e)), t = D(r.reporter), r;
314
+ return e = o((e) => r.reporter.observe(e)), t = A(r.reporter), r;
298
315
  }
299
- var A = () => void 0;
300
- function j(e) {
316
+ var N = () => void 0;
317
+ function P(e) {
301
318
  try {
302
- if (n("turnTimings") === "unsupported") return A;
319
+ if (n("turnTimings") === "unsupported") return N;
303
320
  let t = { send: e.send };
304
- C.push(t), T ||= k();
321
+ w.push(t), E ||= M();
305
322
  let r = !1;
306
323
  return () => {
307
324
  if (r) return;
308
325
  r = !0;
309
- let e = C.indexOf(t);
310
- e >= 0 && C.splice(e, 1), w = t.send;
326
+ let e = w.indexOf(t);
327
+ e >= 0 && w.splice(e, 1), T = t.send;
311
328
  };
312
329
  } catch {
313
- return A;
330
+ return N;
314
331
  }
315
332
  }
316
- function M() {
317
- let e = T;
318
- T = null, C.length = 0, w = null, e && (e.release(), e.reporter.dispose());
333
+ function F() {
334
+ let e = E;
335
+ E = null, w.length = 0, T = null, e && (e.release(), e.reporter.dispose());
319
336
  }
320
337
  //#endregion
321
- export { d as TURN_TIMING_REPORTING, f as createTurnTimingNonce, m as createTurnTimingReporter, M as resetTurnTimingReporting, S as sendAssistantTurnTimings, j as startTurnTimingReporting };
338
+ export { f as TURN_TIMING_REPORTING, p as createTurnTimingNonce, h as createTurnTimingReporter, O as registerTurnTimingPageExit, F as resetTurnTimingReporting, C as sendAssistantTurnTimings, P as startTurnTimingReporting };
@@ -4,6 +4,7 @@ import { WorkspaceWriteAccess } from '../useWorkspaceWriteAccess';
4
4
  import { AssistantNavigate } from './AssistantMarkdownRenderer';
5
5
  import { AssistantLiveAvatarSeam } from './assistantLiveAvatarSeam';
6
6
  import { AssistantPreviewController } from '../preview/types';
7
+ import { AssistantPresentation } from './composer/AssistantComposer';
7
8
  export type AIAssistantPanelProps = PanelProps & {
8
9
  /** When provided, renders a dock/float toggle in the header. */
9
10
  docked?: boolean;
@@ -104,6 +105,14 @@ export type AIAssistantPanelProps = PanelProps & {
104
105
  * a prop chain. See `assistantLiveAvatarSeam`.
105
106
  */
106
107
  liveAvatar?: AssistantLiveAvatarSeam;
108
+ /**
109
+ * BOFF-10055: how the assistant is presented. Absent or `classic`: exactly the
110
+ * panel of before. `compact` opts this product into the redesigned composer
111
+ * (Slice 1: the card, the Mode menu, Stop, IME-safe Enter and the mode-switch
112
+ * confirmation). A product passes it through `AssistantOverlay`'s
113
+ * `panelProps`, behind its own flag.
114
+ */
115
+ presentation?: AssistantPresentation;
107
116
  };
108
117
  /**
109
118
  * The panel.