@burdenoff/fe-libs 2026.1004.4 → 2026.1004.6

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 (105) hide show
  1. package/dist/chrome/ContextSwitcher.d.ts.map +1 -1
  2. package/dist/chrome/ContextSwitcher.js +73 -50
  3. package/dist/chrome/GlobalSearch.d.ts.map +1 -1
  4. package/dist/chrome/GlobalSearch.js +76 -72
  5. package/dist/chrome/LanguageSwitcher.d.ts.map +1 -1
  6. package/dist/chrome/LanguageSwitcher.js +61 -40
  7. package/dist/chrome/NotificationCenter.d.ts.map +1 -1
  8. package/dist/chrome/NotificationCenter.js +71 -68
  9. package/dist/chrome/ProfileSwitcher.d.ts.map +1 -1
  10. package/dist/chrome/ProfileSwitcher.js +87 -81
  11. package/dist/chrome/SideNavigation.d.ts.map +1 -1
  12. package/dist/chrome/SideNavigation.js +120 -76
  13. package/dist/shared/assistant/appControls/copy.d.ts +12 -0
  14. package/dist/shared/assistant/appControls/copy.d.ts.map +1 -0
  15. package/dist/shared/assistant/appControls/copy.js +98 -0
  16. package/dist/shared/assistant/appControls/grammar.d.ts +102 -0
  17. package/dist/shared/assistant/appControls/grammar.d.ts.map +1 -0
  18. package/dist/shared/assistant/appControls/grammar.js +236 -0
  19. package/dist/shared/assistant/appControls/languages.d.ts +6 -0
  20. package/dist/shared/assistant/appControls/languages.d.ts.map +1 -0
  21. package/dist/shared/assistant/appControls/languages.js +52 -0
  22. package/dist/shared/assistant/appControls/names.d.ts +22 -0
  23. package/dist/shared/assistant/appControls/names.d.ts.map +1 -0
  24. package/dist/shared/assistant/appControls/names.js +29 -0
  25. package/dist/shared/assistant/appControls/pageAdapters.d.ts +59 -0
  26. package/dist/shared/assistant/appControls/pageAdapters.d.ts.map +1 -0
  27. package/dist/shared/assistant/appControls/pageAdapters.js +87 -0
  28. package/dist/shared/assistant/appControls/plan.d.ts +148 -0
  29. package/dist/shared/assistant/appControls/plan.d.ts.map +1 -0
  30. package/dist/shared/assistant/appControls/plan.js +511 -0
  31. package/dist/shared/assistant/appControls/registry.d.ts +9 -0
  32. package/dist/shared/assistant/appControls/registry.d.ts.map +1 -0
  33. package/dist/shared/assistant/appControls/registry.js +38 -0
  34. package/dist/shared/assistant/appControls/snapshot.d.ts +42 -0
  35. package/dist/shared/assistant/appControls/snapshot.d.ts.map +1 -0
  36. package/dist/shared/assistant/appControls/snapshot.js +40 -0
  37. package/dist/shared/assistant/appControls/text.d.ts +7 -0
  38. package/dist/shared/assistant/appControls/text.d.ts.map +1 -0
  39. package/dist/shared/assistant/appControls/text.js +6 -0
  40. package/dist/shared/assistant/appControls/types.d.ts +183 -0
  41. package/dist/shared/assistant/appControls/types.d.ts.map +1 -0
  42. package/dist/shared/assistant/appControls/types.js +25 -0
  43. package/dist/shared/assistant/appControls/useAssistantControl.d.ts +24 -0
  44. package/dist/shared/assistant/appControls/useAssistantControl.d.ts.map +1 -0
  45. package/dist/shared/assistant/appControls/useAssistantControl.js +13 -0
  46. package/dist/shared/assistant/conversation.d.ts +12 -1
  47. package/dist/shared/assistant/conversation.d.ts.map +1 -1
  48. package/dist/shared/assistant/history/historyMapping.d.ts.map +1 -1
  49. package/dist/shared/assistant/history/historyMapping.js +130 -114
  50. package/dist/shared/assistant/i18nManifest.d.ts +74 -0
  51. package/dist/shared/assistant/i18nManifest.d.ts.map +1 -1
  52. package/dist/shared/assistant/i18nManifest.js +86 -12
  53. package/dist/shared/assistant/index.d.ts +16 -0
  54. package/dist/shared/assistant/index.d.ts.map +1 -1
  55. package/dist/shared/assistant/localUiCommandCopy.d.ts +7 -0
  56. package/dist/shared/assistant/localUiCommandCopy.d.ts.map +1 -1
  57. package/dist/shared/assistant/localUiCommandCopy.js +1 -1
  58. package/dist/shared/assistant/localUiCommands.d.ts +16 -0
  59. package/dist/shared/assistant/localUiCommands.d.ts.map +1 -1
  60. package/dist/shared/assistant/localUiCommands.js +92 -84
  61. package/dist/shared/assistant/store.d.ts +10 -0
  62. package/dist/shared/assistant/store.d.ts.map +1 -1
  63. package/dist/shared/assistant/store.js +52 -44
  64. package/dist/shared/assistant/ui/AIAssistantPanel.d.ts.map +1 -1
  65. package/dist/shared/assistant/ui/AIAssistantPanel.js +57 -49
  66. package/dist/shared/assistant/ui/AssistantChatArea.d.ts.map +1 -1
  67. package/dist/shared/assistant/ui/AssistantChatArea.js +1085 -1016
  68. package/dist/shared/assistant/ui/AssistantControlConfirmDialog.d.ts +38 -0
  69. package/dist/shared/assistant/ui/AssistantControlConfirmDialog.d.ts.map +1 -0
  70. package/dist/shared/assistant/ui/AssistantControlConfirmDialog.js +65 -0
  71. package/dist/shared/assistant/ui/AssistantMoreMenu.d.ts.map +1 -1
  72. package/dist/shared/assistant/ui/AssistantMoreMenu.js +58 -56
  73. package/dist/shared/assistant/ui/AssistantSpeechProvider.d.ts.map +1 -1
  74. package/dist/shared/assistant/ui/AssistantSpeechProvider.js +106 -105
  75. package/dist/shared/assistant/ui/composer/AssistantVoiceGraceSelector.d.ts +20 -0
  76. package/dist/shared/assistant/ui/composer/AssistantVoiceGraceSelector.d.ts.map +1 -0
  77. package/dist/shared/assistant/ui/composer/AssistantVoiceGraceSelector.js +39 -0
  78. package/dist/shared/assistant/ui/controlConfirmDialog.d.ts +30 -0
  79. package/dist/shared/assistant/ui/controlConfirmDialog.d.ts.map +1 -0
  80. package/dist/shared/assistant/ui/controlConfirmDialog.js +46 -0
  81. package/dist/shared/assistant/ui/useVoiceSession.d.ts +35 -2
  82. package/dist/shared/assistant/ui/useVoiceSession.d.ts.map +1 -1
  83. package/dist/shared/assistant/ui/useVoiceSession.js +232 -171
  84. package/dist/shared/assistant/ui/voice/AssistantVoiceSession.d.ts +15 -1
  85. package/dist/shared/assistant/ui/voice/AssistantVoiceSession.d.ts.map +1 -1
  86. package/dist/shared/assistant/ui/voice/AssistantVoiceSession.js +173 -150
  87. package/dist/shared/assistant/voice/handsFree.d.ts +160 -0
  88. package/dist/shared/assistant/voice/handsFree.d.ts.map +1 -0
  89. package/dist/shared/assistant/voice/handsFree.js +104 -0
  90. package/dist/shared/assistant/voice/supersededTurns.d.ts +29 -0
  91. package/dist/shared/assistant/voice/supersededTurns.d.ts.map +1 -0
  92. package/dist/shared/assistant/voice/supersededTurns.js +17 -0
  93. package/dist/shared/assistant/voice/useVoiceInput.d.ts +7 -0
  94. package/dist/shared/assistant/voice/useVoiceInput.d.ts.map +1 -1
  95. package/dist/shared/assistant/voice/useVoiceInput.js +13 -10
  96. package/dist/shared/assistant/voice/voiceSession.d.ts +64 -20
  97. package/dist/shared/assistant/voice/voiceSession.d.ts.map +1 -1
  98. package/dist/shared/assistant/voice/voiceSession.js +120 -67
  99. package/dist/shared/components/KeyboardHelpDialogWrapper.d.ts.map +1 -1
  100. package/dist/shared/components/KeyboardHelpDialogWrapper.js +11 -9
  101. package/dist/shared/providers/shell/GlobalUiProvider.d.ts +2 -0
  102. package/dist/shared/providers/shell/GlobalUiProvider.d.ts.map +1 -1
  103. package/dist/shared/providers/shell/GlobalUiProvider.js +4 -1
  104. package/dist/shared-assistant.js +219 -203
  105. package/package.json +1 -1
@@ -3,23 +3,24 @@ import { useAssistantTr as t } from "../i18n.js";
3
3
  import { useAssistantStore as n } from "../store.js";
4
4
  import { isVoiceTurn as r } from "../voice/turnVisibility.js";
5
5
  import { VOICE_LIST_TIMEOUT_MS as i, languageDisplayName as a, selectVoiceForLocale as o, speechGate as s, speechLangForLocale as c, voiceAvailability as l, voicesForLocale as u } from "../voice/speechVoices.js";
6
- import { getSpeechEngine as d, subscribeSpeechEngine as f } from "../speech/createSpeechEngine.js";
7
- import { speechFeed as p } from "../speech/speechFeed.js";
8
- import { chunkForSpeech as ee, toSpeakableText as m } from "../voice/speakableText.js";
9
- import { voicePreviewText as te } from "../voice/voicePreview.js";
10
- import { findAssistantLanguage as ne } from "../voice/languages.js";
11
- import { resolveLanguagePair as re } from "../voice/languagePair.js";
12
- import { speechLabelsFor as ie } from "../voice/speechLabels.js";
13
- import { resolveSpeechLocale as ae } from "../voice/replyLanguage.js";
14
- import { IDLE_PLAYBACK as oe, isSpeakingMessage as se, publishedChunks as ce, speechPlaybackReducer as le } from "../voice/speechPlayback.js";
15
- import { isTurnInFlight as ue } from "../turnState.js";
16
- import { parseToolActivity as de } from "./AssistantToolActivity.js";
6
+ import { getSpeechEngine as d, subscribeSpeechEngine as ee } from "../speech/createSpeechEngine.js";
7
+ import { speechFeed as f } from "../speech/speechFeed.js";
8
+ import { isTurnSuperseded as p } from "../voice/supersededTurns.js";
9
+ import { chunkForSpeech as te, toSpeakableText as m } from "../voice/speakableText.js";
10
+ import { voicePreviewText as ne } from "../voice/voicePreview.js";
11
+ import { findAssistantLanguage as re } from "../voice/languages.js";
12
+ import { resolveLanguagePair as ie } from "../voice/languagePair.js";
13
+ import { speechLabelsFor as ae } from "../voice/speechLabels.js";
14
+ import { resolveSpeechLocale as oe } from "../voice/replyLanguage.js";
15
+ import { IDLE_PLAYBACK as se, isSpeakingMessage as ce, publishedChunks as le, speechPlaybackReducer as ue } from "../voice/speechPlayback.js";
16
+ import { isTurnInFlight as de } from "../turnState.js";
17
+ import { parseToolActivity as fe } from "./AssistantToolActivity.js";
17
18
  import "../speech/index.js";
18
19
  import { markTurn as h } from "../turnTimeline.js";
19
- import { createContext as fe, useCallback as g, useContext as _, useEffect as v, useMemo as y, useReducer as pe, useRef as b, useState as x, useSyncExternalStore as me } from "react";
20
- import { jsx as he } from "react/jsx-runtime";
20
+ import { createContext as pe, useCallback as g, useContext as _, useEffect as v, useMemo as y, useReducer as me, useRef as b, useState as x, useSyncExternalStore as he } from "react";
21
+ import { jsx as ge } from "react/jsx-runtime";
21
22
  //#region src/shared/assistant/ui/AssistantSpeechProvider.tsx
22
- var ge = {
23
+ var _e = {
23
24
  codeBlock: "",
24
25
  image: "",
25
26
  link: "",
@@ -28,7 +29,7 @@ var ge = {
28
29
  emailAt: "at",
29
30
  emailDot: "dot",
30
31
  nestedItem: ""
31
- }, _e = 4e3, ve = fe({
32
+ }, ve = 4e3, ye = pe({
32
33
  isSupported: !1,
33
34
  availability: "unsupported",
34
35
  isBlocked: !0,
@@ -51,17 +52,17 @@ var ge = {
51
52
  speakFinishedReply: () => {},
52
53
  previewVoice: () => {}
53
54
  });
54
- function ye() {
55
- return _(ve);
55
+ function be() {
56
+ return _(ye);
56
57
  }
57
- var be = ({ children: fe, visible: _ = !0, engine: ye }) => {
58
- let be = me(f, d, d), S = ye ?? be, C = t(), { locale: w } = e(), [T, E] = pe(le, oe), [D, O] = x(() => S.listVoices()), [k, xe] = x(!1), [Se, A] = x(() => /* @__PURE__ */ new Map()), j = b(0), M = b(null), N = b(null), P = b(null);
58
+ var xe = ({ children: pe, visible: _ = !0, engine: be }) => {
59
+ let xe = he(ee, d, d), S = be ?? xe, C = t(), { locale: w } = e(), [T, E] = me(ue, se), [D, O] = x(() => S.listVoices()), [k, Se] = x(!1), [Ce, A] = x(() => /* @__PURE__ */ new Map()), j = b(0), M = b(null), N = b(null), P = b(null);
59
60
  v(() => () => {
60
61
  P.current !== null && clearTimeout(P.current);
61
62
  }, []);
62
- let [Ce, F] = x(null), I = b(null), we = b(() => {}), L = g(() => {
63
+ let [we, F] = x(null), I = b(null), Te = b(() => {}), L = g(() => {
63
64
  I.current?.(), I.current = null;
64
- }, []), R = n((e) => e.autoSpeakEnabled), Te = n((e) => e.setAutoSpeak), [z, Ee] = x(!1), B = b(!1), De = g((e) => {
65
+ }, []), R = n((e) => e.autoSpeakEnabled), Ee = n((e) => e.setAutoSpeak), [z, De] = x(!1), B = b(!1), Oe = g((e) => {
65
66
  B.current = e;
66
67
  }, []), V = n((e) => e.activeConversationId), H = y(() => S.isSupported(), [S]);
67
68
  v(() => {
@@ -71,16 +72,16 @@ var be = ({ children: fe, visible: _ = !0, engine: ye }) => {
71
72
  };
72
73
  return e(), S.subscribeVoices(e);
73
74
  }, [S, H]);
74
- let Oe = n((e) => e.assistantLanguage), ke = n((e) => e.replyLanguage), U = n((e) => e.preferredVoices), Ae = n((e) => e.setPreferredVoice), W = y(() => re(Oe, ke, w).reply, [
75
- Oe,
75
+ let ke = n((e) => e.assistantLanguage), Ae = n((e) => e.replyLanguage), U = n((e) => e.preferredVoices), je = n((e) => e.setPreferredVoice), W = y(() => ie(ke, Ae, w).reply, [
76
76
  ke,
77
+ Ae,
77
78
  w
78
- ]), G = W.code, K = g((e) => ne(e)?.tag ?? c(e), []), je = g((e) => ne(e)?.rate ?? .9, []), q = y(() => l(H, D, W.tag, k), [
79
+ ]), G = W.code, K = g((e) => re(e)?.tag ?? c(e), []), Me = g((e) => re(e)?.rate ?? .9, []), q = y(() => l(H, D, W.tag, k), [
79
80
  H,
80
81
  D,
81
82
  W,
82
83
  k
83
- ]), Me = y(() => ({
84
+ ]), Ne = y(() => ({
84
85
  codeBlock: C("speech.codeBlock", "Code block"),
85
86
  image: C("speech.image", "image"),
86
87
  link: C("speech.link", "link"),
@@ -91,12 +92,12 @@ var be = ({ children: fe, visible: _ = !0, engine: ye }) => {
91
92
  emailDot: C("speech.emailDot", "dot")
92
93
  }), [C]), J = g(() => {
93
94
  L(), M.current = null, S.cancel(), E({ type: "stop" });
94
- }, [L, S]), Ne = g((e) => {
95
+ }, [L, S]), Pe = g((e) => {
95
96
  let t = S.listVoices().find((t) => t.name === e) ?? null;
96
97
  if (t) {
97
98
  J();
98
99
  try {
99
- S.speak([te(G)], {
100
+ S.speak([ne(G)], {
100
101
  voice: t,
101
102
  lang: K(G),
102
103
  fallback: !1
@@ -108,15 +109,15 @@ var be = ({ children: fe, visible: _ = !0, engine: ye }) => {
108
109
  G,
109
110
  J,
110
111
  K
111
- ]), Pe = g((e) => Se.get(e) ?? null, [Se]), Fe = g((e, t, n, r, a) => {
112
+ ]), Fe = g((e) => Ce.get(e) ?? null, [Ce]), Ie = g((e, t, n, r, a) => {
112
113
  L();
113
114
  let o = !1, s = () => {}, c = (i) => {
114
115
  if (!o) {
115
116
  if (o = !0, I.current = null, clearTimeout(l), s(), i.length === 0) {
116
- xe(!0);
117
+ Se(!0);
117
118
  return;
118
119
  }
119
- O(i), we.current(e, t, i, n, r, a);
120
+ O(i), Te.current(e, t, i, n, r, a);
120
121
  }
121
122
  }, l = setTimeout(() => c(S.listVoices()), i);
122
123
  s = S.subscribeVoices(() => c(S.listVoices())), I.current = () => {
@@ -128,14 +129,14 @@ var be = ({ children: fe, visible: _ = !0, engine: ye }) => {
128
129
  let e = S.listVoices();
129
130
  e.length > 0 && (u = e, O(e));
130
131
  }
131
- let d = K(r), f = s(l(!0, u, r, k));
132
- if (f === "block") {
132
+ let d = K(r), ee = s(l(!0, u, r, k));
133
+ if (ee === "block") {
133
134
  let t = C("speech.noVoiceForReply", "This reply is in {{language}}, and no {{language}} voice is installed on this device.", { language: a(d, w) });
134
135
  A((n) => new Map(n).set(e, t));
135
136
  return;
136
137
  }
137
- if (f === "wait-for-voices") {
138
- Fe(e, t, r, i, c);
138
+ if (ee === "wait-for-voices") {
139
+ Ie(e, t, r, i, c);
139
140
  return;
140
141
  }
141
142
  A((t) => {
@@ -143,85 +144,85 @@ var be = ({ children: fe, visible: _ = !0, engine: ye }) => {
143
144
  let n = new Map(t);
144
145
  return n.delete(e), n;
145
146
  }), L();
146
- let p = j.current + 1;
147
- j.current = p, E({
147
+ let f = j.current + 1;
148
+ j.current = f, E({
148
149
  type: "start",
149
150
  messageId: e,
150
- requestId: p
151
- }), M.current = i ? p : null, i && h(e, "ttsStarted");
152
- let m = c === void 0 ? ee(t) : ee(t, void 0, void 0, { firstChunkMaxChars: c });
151
+ requestId: f
152
+ }), M.current = i ? f : null, i && h(e, "ttsStarted");
153
+ let p = c === void 0 ? te(t) : te(t, void 0, void 0, { firstChunkMaxChars: c });
153
154
  F({
154
- requestId: p,
155
- chunks: m,
155
+ requestId: f,
156
+ chunks: p,
156
157
  index: -1
157
158
  }), P.current !== null && clearTimeout(P.current), P.current = setTimeout(() => {
158
- F((e) => e?.requestId === p && e.index < 0 ? null : e);
159
- }, _e);
160
- let te = () => {
161
- j.current === p && P.current !== null && (clearTimeout(P.current), P.current = null), E({
159
+ F((e) => e?.requestId === f && e.index < 0 ? null : e);
160
+ }, ve);
161
+ let m = () => {
162
+ j.current === f && P.current !== null && (clearTimeout(P.current), P.current = null), E({
162
163
  type: "failed",
163
- requestId: p
164
+ requestId: f
164
165
  });
165
166
  };
166
167
  try {
167
- S.speak(m, {
168
+ S.speak(p, {
168
169
  voice: o(u, d, U[r]),
169
170
  lang: d,
170
- rate: je(r)
171
+ rate: Me(r)
171
172
  }, {
172
173
  onStart: () => {
173
- j.current === p && M.current === p && h(e, "firstAudio");
174
+ j.current === f && M.current === f && h(e, "firstAudio");
174
175
  },
175
176
  onChunkStart: (e) => {
176
- j.current === p && P.current !== null && (clearTimeout(P.current), P.current = null), F((t) => t?.requestId === p ? {
177
+ j.current === f && P.current !== null && (clearTimeout(P.current), P.current = null), F((t) => t?.requestId === f ? {
177
178
  ...t,
178
179
  index: e
179
- } : j.current === p ? {
180
- requestId: p,
181
- chunks: m,
180
+ } : j.current === f ? {
181
+ requestId: f,
182
+ chunks: p,
182
183
  index: e
183
184
  } : t);
184
185
  },
185
186
  onEnd: () => {
186
- j.current === p && M.current === p && h(e, "audioEnded"), E({
187
+ j.current === f && M.current === f && h(e, "audioEnded"), E({
187
188
  type: "finished",
188
- requestId: p
189
+ requestId: f
189
190
  });
190
191
  },
191
192
  onError: () => E({
192
193
  type: "failed",
193
- requestId: p
194
+ requestId: f
194
195
  })
195
196
  });
196
197
  } catch {
197
- te();
198
+ m();
198
199
  }
199
200
  }, [
200
201
  L,
201
202
  S,
202
203
  w,
203
204
  U,
204
- je,
205
+ Me,
205
206
  K,
206
207
  C,
207
208
  k,
208
- Fe
209
+ Ie
209
210
  ]);
210
211
  v(() => {
211
- we.current = Y;
212
+ Te.current = Y;
212
213
  }, [Y]);
213
214
  let X = g((e, t, n, r) => {
214
215
  if (!H) return;
215
- let i = ae(m(t, { labels: ge }), n ?? G), a = m(t, { labels: ie(i, Me) });
216
+ let i = oe(m(t, { labels: _e }), n ?? G), a = m(t, { labels: ae(i, Ne) });
216
217
  a && Y(e, a, D, i, r?.auto === !0, r?.firstChunkMaxChars);
217
218
  }, [
218
219
  H,
219
- Me,
220
+ Ne,
220
221
  G,
221
222
  Y,
222
223
  D
223
- ]), Ie = g((e, t, n) => {
224
- if (se(T, e)) {
224
+ ]), Le = g((e, t, n) => {
225
+ if (ce(T, e)) {
225
226
  J();
226
227
  return;
227
228
  }
@@ -234,14 +235,14 @@ var be = ({ children: fe, visible: _ = !0, engine: ye }) => {
234
235
  v(() => {
235
236
  _ || J();
236
237
  }, [_, J]);
237
- let Le = b({
238
+ let Z = b({
238
239
  autoSpeakEnabled: R,
239
240
  sessionSpeaking: z,
240
241
  visible: _,
241
242
  isSupported: H
242
243
  });
243
244
  v(() => {
244
- Le.current = {
245
+ Z.current = {
245
246
  autoSpeakEnabled: R,
246
247
  sessionSpeaking: z,
247
248
  visible: _,
@@ -271,7 +272,7 @@ var be = ({ children: fe, visible: _ = !0, engine: ye }) => {
271
272
  let e = () => {
272
273
  if (document.visibilityState !== "visible") return;
273
274
  let e = S.listVoices();
274
- e.length > 0 && L(), O(e), xe(!1), A((e) => e.size === 0 ? e : /* @__PURE__ */ new Map());
275
+ e.length > 0 && L(), O(e), Se(!1), A((e) => e.size === 0 ? e : /* @__PURE__ */ new Map());
275
276
  };
276
277
  return document.addEventListener("visibilitychange", e), window.addEventListener("focus", e), () => {
277
278
  document.removeEventListener("visibilitychange", e), window.removeEventListener("focus", e);
@@ -281,15 +282,15 @@ var be = ({ children: fe, visible: _ = !0, engine: ye }) => {
281
282
  S,
282
283
  H
283
284
  ]);
284
- let Z = b(X);
285
+ let Ve = b(X);
285
286
  v(() => {
286
- Z.current = X;
287
+ Ve.current = X;
287
288
  }, [X]);
288
289
  let Q = g((e, t) => {
289
- if (r(e) !== t || N.current?.messageId === e.id || B.current) return;
290
- let { text: n } = de(e.content);
290
+ if (r(e) !== t || p(e.id) || N.current?.messageId === e.id || B.current) return;
291
+ let { text: n } = fe(e.content);
291
292
  if (n.trim()) try {
292
- Z.current(e.id, n, e.metadata?.lang, { auto: !0 });
293
+ Ve.current(e.id, n, e.metadata?.lang, { auto: !0 });
293
294
  } catch {}
294
295
  }, []), $ = g((e, t) => {
295
296
  if (e !== Re.current) {
@@ -299,7 +300,7 @@ var be = ({ children: fe, visible: _ = !0, engine: ye }) => {
299
300
  });
300
301
  return;
301
302
  }
302
- let r = Le.current;
303
+ let r = Z.current;
303
304
  if (!r.autoSpeakEnabled && !r.sessionSpeaking || !r.visible || !r.isSupported) return;
304
305
  let i = n.getState();
305
306
  if (i.activeConversationId !== e) return;
@@ -313,7 +314,7 @@ var be = ({ children: fe, visible: _ = !0, engine: ye }) => {
313
314
  let n = e.activeConversationId;
314
315
  if (!n || n !== t.activeConversationId) return;
315
316
  let r = e.processingByConversationId[n], i = t.processingByConversationId[n];
316
- if (r?.status !== "complete" || !ue(i?.status)) return;
317
+ if (r?.status !== "complete" || !de(i?.status)) return;
317
318
  let a = r.messageId ?? i?.messageId ?? null;
318
319
  if (!a) return;
319
320
  let o = e.conversations.find((e) => e.id === n)?.messages.find((e) => e.id === a);
@@ -326,20 +327,20 @@ var be = ({ children: fe, visible: _ = !0, engine: ye }) => {
326
327
  _,
327
328
  Q
328
329
  ]);
329
- let Ve = g((e) => {
330
+ let He = g((e) => {
330
331
  if (e.type === "abort") {
331
332
  let t = N.current;
332
333
  if (!t || t.messageId !== e.messageId) return;
333
334
  N.current = null, (t.requestId === null ? t.waiting && I.current !== null : j.current === t.requestId) && J();
334
335
  return;
335
336
  }
336
- let { messageId: t, item: r } = e, i = Le.current;
337
- if (!i.autoSpeakEnabled && !i.sessionSpeaking || !i.visible || !i.isSupported || r.channel === "voice" !== i.sessionSpeaking || B.current || N.current?.messageId === t || n.getState().activeConversationId !== r.conversationId || Re.current !== r.conversationId) return;
338
- let { text: a } = de(r.text);
337
+ let { messageId: t, item: r } = e, i = Z.current;
338
+ if (!i.autoSpeakEnabled && !i.sessionSpeaking || !i.visible || !i.isSupported || r.channel === "voice" !== i.sessionSpeaking || p(t) || B.current || N.current?.messageId === t || n.getState().activeConversationId !== r.conversationId || Re.current !== r.conversationId) return;
339
+ let { text: a } = fe(r.text);
339
340
  if (!a.trim()) return;
340
341
  let o = j.current;
341
342
  try {
342
- Z.current(t, a, r.lang, {
343
+ Ve.current(t, a, r.lang, {
343
344
  auto: !0,
344
345
  firstChunkMaxChars: 110
345
346
  });
@@ -351,59 +352,59 @@ var be = ({ children: fe, visible: _ = !0, engine: ye }) => {
351
352
  waiting: !s && I.current !== null
352
353
  };
353
354
  }, [J]);
354
- v(() => p.subscribe(Ve), [Ve]);
355
- let He = y(() => u(D, W.tag), [D, W]), Ue = y(() => o(D, W.tag, U[G]), [
355
+ v(() => f.subscribe(He), [He]);
356
+ let Ue = y(() => u(D, W.tag), [D, W]), We = y(() => o(D, W.tag, U[G]), [
356
357
  D,
357
358
  W,
358
359
  U,
359
360
  G
360
- ]), We = y(() => ({
361
+ ]), Ge = y(() => ({
361
362
  isSupported: H,
362
363
  availability: q,
363
364
  isBlocked: q === "no-voices",
364
365
  disabledReason: q === "no-voices" ? C("speech.noVoicesOnDevice", "This device has no speech voices installed. Add one in your device speech or accessibility settings.") : null,
365
- blockedFor: Pe,
366
- voiceChoices: He,
367
- spokenChunks: ce(T, Ce),
368
- activeVoiceName: Ue?.name ?? null,
366
+ blockedFor: Fe,
367
+ voiceChoices: Ue,
368
+ spokenChunks: le(T, we),
369
+ activeVoiceName: We?.name ?? null,
369
370
  preferredVoiceName: U[G] ?? null,
370
- setVoice: (e) => Ae(G, e),
371
+ setVoice: (e) => je(G, e),
371
372
  speakingMessageId: T.status === "speaking" ? T.messageId : null,
372
- isSpeaking: (e) => se(T, e),
373
- toggle: Ie,
373
+ isSpeaking: (e) => ce(T, e),
374
+ toggle: Le,
374
375
  stop: J,
375
376
  autoSpeakEnabled: R,
376
- setAutoSpeak: Te,
377
+ setAutoSpeak: Ee,
377
378
  sessionSpeaking: z,
378
- setSessionSpeaking: Ee,
379
- setSessionMicOpen: De,
379
+ setSessionSpeaking: De,
380
+ setSessionMicOpen: Oe,
380
381
  speakFinishedReply: $,
381
- previewVoice: Ne
382
+ previewVoice: Pe
382
383
  }), [
383
384
  H,
384
385
  q,
385
- Pe,
386
- He,
386
+ Fe,
387
387
  Ue,
388
+ We,
388
389
  U,
389
- Ae,
390
+ je,
390
391
  G,
391
392
  T,
392
- Ie,
393
+ Le,
393
394
  J,
394
395
  R,
395
- Te,
396
+ Ee,
396
397
  z,
397
- De,
398
+ Oe,
398
399
  $,
399
- Ne,
400
+ Pe,
400
401
  C,
401
- Ce
402
+ we
402
403
  ]);
403
- return /* @__PURE__ */ he(ve.Provider, {
404
- value: We,
405
- children: fe
404
+ return /* @__PURE__ */ ge(ye.Provider, {
405
+ value: Ge,
406
+ children: pe
406
407
  });
407
408
  };
408
409
  //#endregion
409
- export { be as AssistantSpeechProvider, ye as useAssistantSpeech };
410
+ export { xe as AssistantSpeechProvider, be as useAssistantSpeech };
@@ -0,0 +1,20 @@
1
+ import { FC } from 'react';
2
+ /**
3
+ * How long a voice conversation waits, in silence, before it sends what you
4
+ * said (H1): 2 seconds by default, or 3 or 5 for people who pause to think.
5
+ *
6
+ * The preference is persisted per profile and is the ONE value the voice
7
+ * session's submit timer waits (`planSubmitTimer`). Resuming to speak inside
8
+ * the wait cancels the send and carries on with the same turn, and "Let me
9
+ * finish" in the session holds it entirely — this is only the default patience.
10
+ *
11
+ * Renders nothing where there is no speech recognition: a setting for a
12
+ * microphone that cannot exist is a control that cannot do anything.
13
+ *
14
+ * A native `<select>`, like the voice and language pickers: on a phone it opens
15
+ * the OS picker, which already scrolls, localises itself and is reachable by
16
+ * speech-control users. Wrapped in its `<label>`, so the visible words are the
17
+ * accessible name (WCAG 2.5.3).
18
+ */
19
+ export declare const AssistantVoiceGraceSelector: FC;
20
+ //# sourceMappingURL=AssistantVoiceGraceSelector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AssistantVoiceGraceSelector.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/ui/composer/AssistantVoiceGraceSelector.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAWhC;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,2BAA2B,EAAE,EA8CzC,CAAC"}
@@ -0,0 +1,39 @@
1
+ import { isSpeechRecognitionSupported as e } from "../../voice/useVoiceInput.js";
2
+ import { useAssistantTr as t } from "../../i18n.js";
3
+ import { VOICE_GRACE_CHOICES_MS as n, resolveVoiceGraceMs as r } from "../../voice/handsFree.js";
4
+ import { useAssistantStore as i } from "../../store.js";
5
+ import { Timer as a } from "lucide-react";
6
+ import { jsx as o, jsxs as s } from "react/jsx-runtime";
7
+ //#region src/shared/assistant/ui/composer/AssistantVoiceGraceSelector.tsx
8
+ var c = () => {
9
+ let c = t(), l = i((e) => e.voiceGraceMs), u = i((e) => e.setVoiceGraceMs);
10
+ if (!e()) return null;
11
+ let d = r(l), f = (e) => e / 1e3;
12
+ return /* @__PURE__ */ s("label", {
13
+ className: "flex items-center gap-2.5 px-3 py-2 text-xs text-text-primary focus-within:ring-2 focus-within:ring-inset focus-within:ring-border-strong",
14
+ title: c("voice.graceHint", "How long the assistant waits in silence before it sends what you said. Start talking again and it carries on with the same message."),
15
+ "data-testid": "assistant-voice-grace",
16
+ children: [
17
+ /* @__PURE__ */ o(a, {
18
+ className: "size-3.5 flex-shrink-0 text-text-secondary",
19
+ "aria-hidden": "true"
20
+ }),
21
+ /* @__PURE__ */ o("span", {
22
+ className: "flex-1",
23
+ children: c("voice.graceLabel", "Wait after I stop talking")
24
+ }),
25
+ /* @__PURE__ */ o("select", {
26
+ value: d,
27
+ onChange: (e) => u(Number(e.target.value)),
28
+ className: "rounded-md border border-border-default bg-bg-surface px-1.5 py-1 text-xs text-text-primary focus:outline-none scheme-normal dark:scheme-dark [&_option]:bg-bg-surface [&_option]:text-text-primary",
29
+ "data-testid": "assistant-voice-grace-select",
30
+ children: n.map((e) => /* @__PURE__ */ o("option", {
31
+ value: e,
32
+ children: e === 2e3 ? c("voice.graceOptionDefault", "{{seconds}} seconds (default)", { seconds: f(e) }) : c("voice.graceOption", "{{seconds}} seconds", { seconds: f(e) })
33
+ }, e))
34
+ })
35
+ ]
36
+ });
37
+ };
38
+ //#endregion
39
+ export { c as AssistantVoiceGraceSelector };
@@ -0,0 +1,30 @@
1
+ import { FC, ReactNode } from 'react';
2
+ import { ConfirmPrompt } from '../appControls/plan';
3
+ /**
4
+ * The panel's one STRONGER confirmation (BOFF-8060): workspace switch and
5
+ * logout. `request` only OPENS it; `onConfirm` runs from a trusted press on the
6
+ * dialog's button and from nowhere else.
7
+ */
8
+ export interface ControlConfirmRequest {
9
+ prompt: ConfirmPrompt;
10
+ /** Runs once, on the trusted press. Never called on Cancel, Esc or dismissal. */
11
+ onConfirm: () => void;
12
+ }
13
+ export interface ControlConfirmDialogController {
14
+ request: (request: ControlConfirmRequest) => void;
15
+ /**
16
+ * The confirmation is open. A live voice session holds its listening
17
+ * meanwhile, so nothing said is heard or sent.
18
+ */
19
+ asking: boolean;
20
+ }
21
+ /**
22
+ * The panel's confirmation, or null outside a panel that provides one
23
+ * (`AIAssistantPanel` does). With none, a control that needs it is not offered:
24
+ * the sentence goes to the model, as it did before the control existed.
25
+ */
26
+ export declare function useControlConfirmDialog(): ControlConfirmDialogController | null;
27
+ export declare const AssistantControlConfirmProvider: FC<{
28
+ children: ReactNode;
29
+ }>;
30
+ //# sourceMappingURL=controlConfirmDialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"controlConfirmDialog.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/ui/controlConfirmDialog.tsx"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,EAAE,EACP,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAGf,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAIzD;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,aAAa,CAAC;IACtB,iFAAiF;IACjF,SAAS,EAAE,MAAM,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,8BAA8B;IAC7C,OAAO,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,IAAI,CAAC;IAClD;;;OAGG;IACH,MAAM,EAAE,OAAO,CAAC;CACjB;AAID;;;;GAIG;AACH,wBAAgB,uBAAuB,IAAI,8BAA8B,GAAG,IAAI,CAE/E;AASD,eAAO,MAAM,+BAA+B,EAAE,EAAE,CAAC;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,CAuCvE,CAAC"}
@@ -0,0 +1,46 @@
1
+ import { useAssistantTr as e } from "../i18n.js";
2
+ import { AssistantControlConfirmDialog as t } from "./AssistantControlConfirmDialog.js";
3
+ import { confirmDialogCopy as n } from "../appControls/copy.js";
4
+ import { createContext as r, useCallback as i, useContext as a, useMemo as o, useState as s } from "react";
5
+ import { jsx as c, jsxs as l } from "react/jsx-runtime";
6
+ //#region src/shared/assistant/ui/controlConfirmDialog.tsx
7
+ var u = r(null);
8
+ function d() {
9
+ return a(u);
10
+ }
11
+ var f = ({ children: r }) => {
12
+ let a = e(), [d, f] = s({
13
+ request: null,
14
+ open: !1,
15
+ opening: 0
16
+ }), p = i((e) => {
17
+ f((t) => ({
18
+ request: e,
19
+ open: !0,
20
+ opening: t.opening + 1
21
+ }));
22
+ }, []), m = i(() => {
23
+ f((e) => e.open ? {
24
+ ...e,
25
+ open: !1
26
+ } : e);
27
+ }, []), h = i(() => {
28
+ let { request: e, open: t } = d;
29
+ !t || !e || (m(), e.onConfirm());
30
+ }, [d, m]), g = o(() => ({
31
+ request: p,
32
+ asking: d.open
33
+ }), [p, d.open]);
34
+ return /* @__PURE__ */ l(u.Provider, {
35
+ value: g,
36
+ children: [r, d.request ? /* @__PURE__ */ c(t, {
37
+ open: d.open,
38
+ copy: n(a, d.request.prompt),
39
+ tr: a,
40
+ onConfirm: h,
41
+ onDismiss: m
42
+ }, d.opening) : null]
43
+ });
44
+ };
45
+ //#endregion
46
+ export { f as AssistantControlConfirmProvider, d as useControlConfirmDialog };
@@ -1,4 +1,5 @@
1
1
  import { VoiceTurnTiming } from '../turnTimeline';
2
+ import { VoiceGraceMs } from '../voice/handsFree';
2
3
  import { VoiceSessionSnapshot } from '../voice/voiceSession';
3
4
  /**
4
5
  * A problem worth TELLING the user about that does not warrant killing the
@@ -46,7 +47,14 @@ interface Options {
46
47
  * When the speech that was submitted ended and when its correction grace
47
48
  * ran out (BOFF-7801) — taken here because the turn has no id yet.
48
49
  */
49
- timing: VoiceTurnTiming) => void;
50
+ timing: VoiceTurnTiming,
51
+ /**
52
+ * H2: facts about THIS turn the sender needs. `correction` is true when it
53
+ * is what the person said to correct a turn still being prepared: the
54
+ * sender must send it as the next message of the same conversation even
55
+ * though the superseded turn may not have let go yet.
56
+ */
57
+ meta: VoiceSubmitMeta) => void;
50
58
  /**
51
59
  * Id + text of the newest assistant reply. A CHANGE of id is what advances
52
60
  * the session out of `thinking` — the text alone is not enough, because two
@@ -58,6 +66,23 @@ interface Options {
58
66
  } | null;
59
67
  /** Language the user is speaking, so the recogniser is pointed correctly. */
60
68
  language: string;
69
+ /**
70
+ * H1: the end-of-speech grace — 2 s (the default), 3 s or 5 s. The ONE value
71
+ * the submit timer waits (`planSubmitTimer`); anything else is the default.
72
+ */
73
+ graceMs?: VoiceGraceMs | number;
74
+ /**
75
+ * H2: a correction was heard while a turn was still being prepared. Cancel
76
+ * that turn — abort it on the sandbox, record it as superseded
77
+ * (`markTurnSuperseded`), withdraw the proposals it made outdated. Called
78
+ * once per supersession, from an effect (never during a reduction).
79
+ */
80
+ onSupersede?: () => void;
81
+ }
82
+ /** What `onSubmit` is told about the turn beyond its words (H2). */
83
+ export interface VoiceSubmitMeta {
84
+ /** The words are a correction of a turn that was superseded. */
85
+ correction: boolean;
61
86
  }
62
87
  /**
63
88
  * Drives a live voice conversation (BOFF-7120).
@@ -73,7 +98,7 @@ interface Options {
73
98
  * microphone's lifetime, and turning "auto-speak is currently on" back off again
74
99
  * when the session ends.
75
100
  */
76
- export declare function useVoiceSession({ onSubmit, latestReply, language }: Options): {
101
+ export declare function useVoiceSession({ onSubmit, latestReply, language, graceMs: graceChoice, onSupersede, }: Options): {
77
102
  session: Readonly<VoiceSessionSnapshot>;
78
103
  /** A recoverable problem worth showing, or null when all is well. */
79
104
  notice: VoiceSessionNotice | null;
@@ -101,6 +126,10 @@ export declare function useVoiceSession({ onSubmit, latestReply, language }: Opt
101
126
  interrupting: boolean;
102
127
  /** Quiet has fallen and the correction window is running. */
103
128
  awaitingEndpoint: boolean;
129
+ /** H1: "Let me finish" is on — nothing is sent until `imDone`. */
130
+ holding: boolean;
131
+ /** H2: what is being collected corrects a turn that was superseded. */
132
+ correcting: boolean;
104
133
  /** Can a session be offered at all on this device? */
105
134
  available: boolean;
106
135
  start: () => void;
@@ -108,6 +137,10 @@ export declare function useVoiceSession({ onSubmit, latestReply, language }: Opt
108
137
  isCurrentSession: (voiceSessionId: string) => boolean;
109
138
  toggleMute: () => void;
110
139
  interrupt: () => void;
140
+ /** H1: hold auto-submit until the person is done. */
141
+ letMeFinish: () => void;
142
+ /** H1: the person is done — send what was said now. */
143
+ imDone: () => void;
111
144
  /** Say a line of the panel's own (BOFF-7803 FE9, `VoiceAnnouncement`). */
112
145
  announce: (item: VoiceAnnouncement) => void;
113
146
  /**