@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.
- package/dist/chrome/ContextSwitcher.d.ts.map +1 -1
- package/dist/chrome/ContextSwitcher.js +73 -50
- package/dist/chrome/GlobalSearch.d.ts.map +1 -1
- package/dist/chrome/GlobalSearch.js +76 -72
- package/dist/chrome/LanguageSwitcher.d.ts.map +1 -1
- package/dist/chrome/LanguageSwitcher.js +61 -40
- package/dist/chrome/NotificationCenter.d.ts.map +1 -1
- package/dist/chrome/NotificationCenter.js +71 -68
- package/dist/chrome/ProfileSwitcher.d.ts.map +1 -1
- package/dist/chrome/ProfileSwitcher.js +87 -81
- package/dist/chrome/SideNavigation.d.ts.map +1 -1
- package/dist/chrome/SideNavigation.js +120 -76
- package/dist/shared/assistant/appControls/copy.d.ts +12 -0
- package/dist/shared/assistant/appControls/copy.d.ts.map +1 -0
- package/dist/shared/assistant/appControls/copy.js +98 -0
- package/dist/shared/assistant/appControls/grammar.d.ts +102 -0
- package/dist/shared/assistant/appControls/grammar.d.ts.map +1 -0
- package/dist/shared/assistant/appControls/grammar.js +236 -0
- package/dist/shared/assistant/appControls/languages.d.ts +6 -0
- package/dist/shared/assistant/appControls/languages.d.ts.map +1 -0
- package/dist/shared/assistant/appControls/languages.js +52 -0
- package/dist/shared/assistant/appControls/names.d.ts +22 -0
- package/dist/shared/assistant/appControls/names.d.ts.map +1 -0
- package/dist/shared/assistant/appControls/names.js +29 -0
- package/dist/shared/assistant/appControls/pageAdapters.d.ts +59 -0
- package/dist/shared/assistant/appControls/pageAdapters.d.ts.map +1 -0
- package/dist/shared/assistant/appControls/pageAdapters.js +87 -0
- package/dist/shared/assistant/appControls/plan.d.ts +148 -0
- package/dist/shared/assistant/appControls/plan.d.ts.map +1 -0
- package/dist/shared/assistant/appControls/plan.js +511 -0
- package/dist/shared/assistant/appControls/registry.d.ts +9 -0
- package/dist/shared/assistant/appControls/registry.d.ts.map +1 -0
- package/dist/shared/assistant/appControls/registry.js +38 -0
- package/dist/shared/assistant/appControls/snapshot.d.ts +42 -0
- package/dist/shared/assistant/appControls/snapshot.d.ts.map +1 -0
- package/dist/shared/assistant/appControls/snapshot.js +40 -0
- package/dist/shared/assistant/appControls/text.d.ts +7 -0
- package/dist/shared/assistant/appControls/text.d.ts.map +1 -0
- package/dist/shared/assistant/appControls/text.js +6 -0
- package/dist/shared/assistant/appControls/types.d.ts +183 -0
- package/dist/shared/assistant/appControls/types.d.ts.map +1 -0
- package/dist/shared/assistant/appControls/types.js +25 -0
- package/dist/shared/assistant/appControls/useAssistantControl.d.ts +24 -0
- package/dist/shared/assistant/appControls/useAssistantControl.d.ts.map +1 -0
- package/dist/shared/assistant/appControls/useAssistantControl.js +13 -0
- package/dist/shared/assistant/conversation.d.ts +12 -1
- package/dist/shared/assistant/conversation.d.ts.map +1 -1
- package/dist/shared/assistant/history/historyMapping.d.ts.map +1 -1
- package/dist/shared/assistant/history/historyMapping.js +130 -114
- package/dist/shared/assistant/i18nManifest.d.ts +74 -0
- package/dist/shared/assistant/i18nManifest.d.ts.map +1 -1
- package/dist/shared/assistant/i18nManifest.js +86 -12
- package/dist/shared/assistant/index.d.ts +16 -0
- package/dist/shared/assistant/index.d.ts.map +1 -1
- package/dist/shared/assistant/localUiCommandCopy.d.ts +7 -0
- package/dist/shared/assistant/localUiCommandCopy.d.ts.map +1 -1
- package/dist/shared/assistant/localUiCommandCopy.js +1 -1
- package/dist/shared/assistant/localUiCommands.d.ts +16 -0
- package/dist/shared/assistant/localUiCommands.d.ts.map +1 -1
- package/dist/shared/assistant/localUiCommands.js +92 -84
- package/dist/shared/assistant/store.d.ts +10 -0
- package/dist/shared/assistant/store.d.ts.map +1 -1
- package/dist/shared/assistant/store.js +52 -44
- package/dist/shared/assistant/ui/AIAssistantPanel.d.ts.map +1 -1
- package/dist/shared/assistant/ui/AIAssistantPanel.js +57 -49
- package/dist/shared/assistant/ui/AssistantChatArea.d.ts.map +1 -1
- package/dist/shared/assistant/ui/AssistantChatArea.js +1085 -1016
- package/dist/shared/assistant/ui/AssistantControlConfirmDialog.d.ts +38 -0
- package/dist/shared/assistant/ui/AssistantControlConfirmDialog.d.ts.map +1 -0
- package/dist/shared/assistant/ui/AssistantControlConfirmDialog.js +65 -0
- package/dist/shared/assistant/ui/AssistantMoreMenu.d.ts.map +1 -1
- package/dist/shared/assistant/ui/AssistantMoreMenu.js +58 -56
- package/dist/shared/assistant/ui/AssistantSpeechProvider.d.ts.map +1 -1
- package/dist/shared/assistant/ui/AssistantSpeechProvider.js +106 -105
- package/dist/shared/assistant/ui/composer/AssistantVoiceGraceSelector.d.ts +20 -0
- package/dist/shared/assistant/ui/composer/AssistantVoiceGraceSelector.d.ts.map +1 -0
- package/dist/shared/assistant/ui/composer/AssistantVoiceGraceSelector.js +39 -0
- package/dist/shared/assistant/ui/controlConfirmDialog.d.ts +30 -0
- package/dist/shared/assistant/ui/controlConfirmDialog.d.ts.map +1 -0
- package/dist/shared/assistant/ui/controlConfirmDialog.js +46 -0
- package/dist/shared/assistant/ui/useVoiceSession.d.ts +35 -2
- package/dist/shared/assistant/ui/useVoiceSession.d.ts.map +1 -1
- package/dist/shared/assistant/ui/useVoiceSession.js +232 -171
- package/dist/shared/assistant/ui/voice/AssistantVoiceSession.d.ts +15 -1
- package/dist/shared/assistant/ui/voice/AssistantVoiceSession.d.ts.map +1 -1
- package/dist/shared/assistant/ui/voice/AssistantVoiceSession.js +173 -150
- package/dist/shared/assistant/voice/handsFree.d.ts +160 -0
- package/dist/shared/assistant/voice/handsFree.d.ts.map +1 -0
- package/dist/shared/assistant/voice/handsFree.js +104 -0
- package/dist/shared/assistant/voice/supersededTurns.d.ts +29 -0
- package/dist/shared/assistant/voice/supersededTurns.d.ts.map +1 -0
- package/dist/shared/assistant/voice/supersededTurns.js +17 -0
- package/dist/shared/assistant/voice/useVoiceInput.d.ts +7 -0
- package/dist/shared/assistant/voice/useVoiceInput.d.ts.map +1 -1
- package/dist/shared/assistant/voice/useVoiceInput.js +13 -10
- package/dist/shared/assistant/voice/voiceSession.d.ts +64 -20
- package/dist/shared/assistant/voice/voiceSession.d.ts.map +1 -1
- package/dist/shared/assistant/voice/voiceSession.js +120 -67
- package/dist/shared/components/KeyboardHelpDialogWrapper.d.ts.map +1 -1
- package/dist/shared/components/KeyboardHelpDialogWrapper.js +11 -9
- package/dist/shared/providers/shell/GlobalUiProvider.d.ts +2 -0
- package/dist/shared/providers/shell/GlobalUiProvider.d.ts.map +1 -1
- package/dist/shared/providers/shell/GlobalUiProvider.js +4 -1
- package/dist/shared-assistant.js +219 -203
- 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
|
|
7
|
-
import { speechFeed as
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
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
|
|
20
|
-
import { jsx as
|
|
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
|
|
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
|
-
},
|
|
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
|
|
55
|
-
return _(
|
|
55
|
+
function be() {
|
|
56
|
+
return _(ye);
|
|
56
57
|
}
|
|
57
|
-
var
|
|
58
|
-
let
|
|
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 [
|
|
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),
|
|
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
|
|
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) =>
|
|
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
|
-
]),
|
|
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]),
|
|
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([
|
|
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
|
-
]),
|
|
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
|
-
|
|
117
|
+
Se(!0);
|
|
117
118
|
return;
|
|
118
119
|
}
|
|
119
|
-
O(i),
|
|
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),
|
|
132
|
-
if (
|
|
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 (
|
|
138
|
-
|
|
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
|
|
147
|
-
j.current =
|
|
147
|
+
let f = j.current + 1;
|
|
148
|
+
j.current = f, E({
|
|
148
149
|
type: "start",
|
|
149
150
|
messageId: e,
|
|
150
|
-
requestId:
|
|
151
|
-
}), M.current = i ?
|
|
152
|
-
let
|
|
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:
|
|
155
|
-
chunks:
|
|
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 ===
|
|
159
|
-
},
|
|
160
|
-
let
|
|
161
|
-
j.current ===
|
|
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:
|
|
164
|
+
requestId: f
|
|
164
165
|
});
|
|
165
166
|
};
|
|
166
167
|
try {
|
|
167
|
-
S.speak(
|
|
168
|
+
S.speak(p, {
|
|
168
169
|
voice: o(u, d, U[r]),
|
|
169
170
|
lang: d,
|
|
170
|
-
rate:
|
|
171
|
+
rate: Me(r)
|
|
171
172
|
}, {
|
|
172
173
|
onStart: () => {
|
|
173
|
-
j.current ===
|
|
174
|
+
j.current === f && M.current === f && h(e, "firstAudio");
|
|
174
175
|
},
|
|
175
176
|
onChunkStart: (e) => {
|
|
176
|
-
j.current ===
|
|
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 ===
|
|
180
|
-
requestId:
|
|
181
|
-
chunks:
|
|
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 ===
|
|
187
|
+
j.current === f && M.current === f && h(e, "audioEnded"), E({
|
|
187
188
|
type: "finished",
|
|
188
|
-
requestId:
|
|
189
|
+
requestId: f
|
|
189
190
|
});
|
|
190
191
|
},
|
|
191
192
|
onError: () => E({
|
|
192
193
|
type: "failed",
|
|
193
|
-
requestId:
|
|
194
|
+
requestId: f
|
|
194
195
|
})
|
|
195
196
|
});
|
|
196
197
|
} catch {
|
|
197
|
-
|
|
198
|
+
m();
|
|
198
199
|
}
|
|
199
200
|
}, [
|
|
200
201
|
L,
|
|
201
202
|
S,
|
|
202
203
|
w,
|
|
203
204
|
U,
|
|
204
|
-
|
|
205
|
+
Me,
|
|
205
206
|
K,
|
|
206
207
|
C,
|
|
207
208
|
k,
|
|
208
|
-
|
|
209
|
+
Ie
|
|
209
210
|
]);
|
|
210
211
|
v(() => {
|
|
211
|
-
|
|
212
|
+
Te.current = Y;
|
|
212
213
|
}, [Y]);
|
|
213
214
|
let X = g((e, t, n, r) => {
|
|
214
215
|
if (!H) return;
|
|
215
|
-
let i =
|
|
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
|
-
|
|
220
|
+
Ne,
|
|
220
221
|
G,
|
|
221
222
|
Y,
|
|
222
223
|
D
|
|
223
|
-
]),
|
|
224
|
-
if (
|
|
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
|
|
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
|
-
|
|
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),
|
|
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
|
|
285
|
+
let Ve = b(X);
|
|
285
286
|
v(() => {
|
|
286
|
-
|
|
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 } =
|
|
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
|
-
|
|
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 =
|
|
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" || !
|
|
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
|
|
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 =
|
|
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 } =
|
|
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
|
-
|
|
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(() =>
|
|
355
|
-
let
|
|
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
|
-
]),
|
|
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:
|
|
366
|
-
voiceChoices:
|
|
367
|
-
spokenChunks:
|
|
368
|
-
activeVoiceName:
|
|
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) =>
|
|
371
|
+
setVoice: (e) => je(G, e),
|
|
371
372
|
speakingMessageId: T.status === "speaking" ? T.messageId : null,
|
|
372
|
-
isSpeaking: (e) =>
|
|
373
|
-
toggle:
|
|
373
|
+
isSpeaking: (e) => ce(T, e),
|
|
374
|
+
toggle: Le,
|
|
374
375
|
stop: J,
|
|
375
376
|
autoSpeakEnabled: R,
|
|
376
|
-
setAutoSpeak:
|
|
377
|
+
setAutoSpeak: Ee,
|
|
377
378
|
sessionSpeaking: z,
|
|
378
|
-
setSessionSpeaking:
|
|
379
|
-
setSessionMicOpen:
|
|
379
|
+
setSessionSpeaking: De,
|
|
380
|
+
setSessionMicOpen: Oe,
|
|
380
381
|
speakFinishedReply: $,
|
|
381
|
-
previewVoice:
|
|
382
|
+
previewVoice: Pe
|
|
382
383
|
}), [
|
|
383
384
|
H,
|
|
384
385
|
q,
|
|
385
|
-
|
|
386
|
-
He,
|
|
386
|
+
Fe,
|
|
387
387
|
Ue,
|
|
388
|
+
We,
|
|
388
389
|
U,
|
|
389
|
-
|
|
390
|
+
je,
|
|
390
391
|
G,
|
|
391
392
|
T,
|
|
392
|
-
|
|
393
|
+
Le,
|
|
393
394
|
J,
|
|
394
395
|
R,
|
|
395
|
-
|
|
396
|
+
Ee,
|
|
396
397
|
z,
|
|
397
|
-
|
|
398
|
+
Oe,
|
|
398
399
|
$,
|
|
399
|
-
|
|
400
|
+
Pe,
|
|
400
401
|
C,
|
|
401
|
-
|
|
402
|
+
we
|
|
402
403
|
]);
|
|
403
|
-
return /* @__PURE__ */
|
|
404
|
-
value:
|
|
405
|
-
children:
|
|
404
|
+
return /* @__PURE__ */ ge(ye.Provider, {
|
|
405
|
+
value: Ge,
|
|
406
|
+
children: pe
|
|
406
407
|
});
|
|
407
408
|
};
|
|
408
409
|
//#endregion
|
|
409
|
-
export {
|
|
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
|
|
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
|
/**
|