@burdenoff/fe-libs 2026.1014.5 → 2026.1015.2
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/shared/assistant/avatar/avatarPreferences.d.ts +61 -14
- package/dist/shared/assistant/avatar/avatarPreferences.js +54 -21
- package/dist/shared/assistant/avatar/live/LiveAvatarTabView.d.ts +33 -0
- package/dist/shared/assistant/avatar/live/LiveAvatarTabView.js +278 -0
- package/dist/shared/assistant/avatar/live/avatarSessionClient.d.ts +5 -0
- package/dist/shared/assistant/avatar/live/avatarSessionClient.js +25 -6
- package/dist/shared/assistant/avatar/live/avatarVoice.d.ts +43 -0
- package/dist/shared/assistant/avatar/live/avatarVoice.js +45 -0
- package/dist/shared/assistant/avatar/live/createLiveAvatarSeam.d.ts +21 -1
- package/dist/shared/assistant/avatar/live/createLiveAvatarSeam.js +74 -24
- package/dist/shared/assistant/avatar/live/liveAvatarController.d.ts +47 -8
- package/dist/shared/assistant/avatar/live/liveAvatarController.js +244 -161
- package/dist/shared/assistant/avatar/live/liveAvatarStatus.d.ts +2 -2
- package/dist/shared/assistant/avatar/live/liveAvatarStatus.js +11 -4
- package/dist/shared/assistant/avatar/useAvatarCopy.d.ts +50 -21
- package/dist/shared/assistant/avatar/useAvatarCopy.js +93 -49
- package/dist/shared/assistant/i18nManifest.d.ts +23 -2
- package/dist/shared/assistant/i18nManifest.js +23 -2
- package/dist/shared/assistant/index.d.ts +6 -0
- package/dist/shared/assistant/speech/hostedVoiceCatalogue.d.ts +19 -0
- package/dist/shared/assistant/speech/hostedVoiceCatalogue.js +25 -18
- package/dist/shared/assistant/ui/AIAssistantPanel.js +134 -101
- package/dist/shared/assistant/ui/AssistantAvatarTabs.d.ts +10 -0
- package/dist/shared/assistant/ui/AssistantAvatarTabs.js +48 -0
- package/dist/shared/assistant/ui/AssistantChatArea.js +1261 -1202
- package/dist/shared/assistant/ui/assistantLiveAvatarSeam.d.ts +137 -5
- package/dist/shared/assistant/ui/assistantLiveAvatarSeam.js +114 -55
- package/dist/shared/assistant/ui/avatar/AssistantAvatarTab.d.ts +13 -0
- package/dist/shared/assistant/ui/avatar/AssistantAvatarTab.js +70 -0
- package/dist/shared/assistant/ui/composer/AssistantComposer.d.ts +18 -0
- package/dist/shared/assistant/ui/composer/AssistantComposer.js +121 -102
- package/dist/shared/assistant/ui/panelOverlays.d.ts +24 -3
- package/dist/shared/assistant/ui/panelOverlays.js +11 -10
- package/dist/shared/assistant/ui/useVoiceSession.d.ts +20 -5
- package/dist/shared/assistant/ui/useVoiceSession.js +11 -4
- package/dist/shared/assistant/ui/voice/AssistantVoiceSession.d.ts +8 -2
- package/dist/shared/assistant/ui/voice/AssistantVoiceSession.js +172 -160
- package/dist/shared/assistant/ui/voice/voiceStartGate.d.ts +57 -0
- package/dist/shared/assistant/ui/voice/voiceStartGate.js +9 -0
- package/dist/shared/assistant/voice/voiceReply.d.ts +23 -0
- package/dist/shared/assistant/voice/voiceReply.js +13 -0
- package/dist/shared/assistant/voice/voiceSession.d.ts +10 -0
- package/dist/shared/assistant/voice/voiceSession.js +7 -0
- package/dist/shared-assistant.js +260 -254
- package/package.json +1 -1
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
//#region src/shared/assistant/avatar/live/liveAvatarStatus.ts
|
|
2
|
-
function e(e, t) {
|
|
2
|
+
function e(e, t, n = Date.now()) {
|
|
3
3
|
if (e.problem === "playback-blocked" && e.audioBlocked) return null;
|
|
4
|
-
|
|
4
|
+
let r = e.voiceLive;
|
|
5
|
+
if (e.problem !== null) {
|
|
6
|
+
let i = e.retryAt, a = i !== null && i > n, o = t.problem(e.problem, {
|
|
7
|
+
voiceLive: r,
|
|
8
|
+
timed: a
|
|
9
|
+
});
|
|
10
|
+
return a ? `${o} ${t.availableAgain(t.retryTime(i, n))}` : o;
|
|
11
|
+
}
|
|
5
12
|
if (e.phase === "checking") return t.chooserLoading;
|
|
6
13
|
switch (e.notice) {
|
|
7
14
|
case "interrupted": return t.stateInterrupted;
|
|
8
|
-
case "voice-only": return t.stateVoiceOnly;
|
|
9
|
-
case "time-limit": return t.stateTimeLimit;
|
|
15
|
+
case "voice-only": return r ? t.stateVoiceOnly : t.stateVoiceOnlyNoVoice;
|
|
16
|
+
case "time-limit": return r ? t.stateTimeLimit : t.stateTimeLimitNoVoice;
|
|
10
17
|
default: return null;
|
|
11
18
|
}
|
|
12
19
|
}
|
|
@@ -1,23 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
* Every user-visible word of the optional live avatar, in one place (BOFF-8822).
|
|
3
|
-
*
|
|
4
|
-
* ★★ ONE MODULE, LITERAL KEYS. `i18nManifest.test.ts` parses every module under
|
|
5
|
-
* `shared/assistant` for `tr("<key>", "<English>")` calls and fails on a key the
|
|
6
|
-
* manifest lacks, a default that differs, or a manifest entry no call requests.
|
|
7
|
-
* Keeping every call here means the avatar UI imports words and cannot add a
|
|
8
|
-
* string the manifest does not know — and the manifest entries and these calls
|
|
9
|
-
* are one change.
|
|
10
|
-
*
|
|
11
|
-
* ★ The English names no product of ours (`noProductNames.test.ts`). The consent
|
|
12
|
-
* is the one place that names the services the reply audio goes to: the
|
|
13
|
-
* disclosure decided on 2026-10-08, which must stay true to the data flow —
|
|
14
|
-
* only the assistant's reply audio is sent, as data to the avatar; the person's
|
|
15
|
-
* microphone audio never is. It says nothing of credits (2026-10-09): avatar
|
|
16
|
-
* time is billed to the company, and "credits" read as the person's own. Pinned
|
|
17
|
-
* word for word by `avatarConsentCopy.test.ts`.
|
|
18
|
-
*/
|
|
1
|
+
import { VoiceStartBlocker } from '../ui/voice/voiceStartGate';
|
|
19
2
|
/** What the person can be told went wrong; the adapter maps server codes onto these. */
|
|
20
|
-
export type AvatarProblem = 'unavailable' | 'not-ready' | 'already-running' | 'capacity' | 'rate-limited' | 'paused'
|
|
3
|
+
export type AvatarProblem = 'unavailable' | 'not-ready' | 'already-running' | 'capacity' | 'rate-limited' | 'paused'
|
|
4
|
+
/** The avatar time allowed for now (the daily credits) is used up; the server says when it comes back. */
|
|
5
|
+
| 'budget-exhausted' | 'start-timeout' | 'provider' | 'connection' | 'needs-hosted-voice' | 'unsupported-browser' | 'playback-blocked';
|
|
21
6
|
export interface AvatarCopy {
|
|
22
7
|
toggle: string;
|
|
23
8
|
toggleHint: string;
|
|
@@ -45,11 +30,55 @@ export interface AvatarCopy {
|
|
|
45
30
|
chooserOption: (name: string) => string;
|
|
46
31
|
chooserSelected: (name: string) => string;
|
|
47
32
|
voiceModeLabel: string;
|
|
48
|
-
|
|
33
|
+
/** The avatar voice the host configured for this avatar (`avatarVoices`), naming that speaker; offered only when there is one. */
|
|
34
|
+
voiceModeDefaultNamed: (name: string) => string;
|
|
49
35
|
voiceModeMine: string;
|
|
36
|
+
/** "Keep my current voice", naming the voice the assistant resolves to now. */
|
|
37
|
+
voiceModeMineNamed: (name: string) => string;
|
|
50
38
|
voiceModeHint: string;
|
|
39
|
+
/** The Avatar tab (BOFF-9341): the tablist's accessible name, and its two tabs. */
|
|
40
|
+
tabsLabel: string;
|
|
41
|
+
tabChat: string;
|
|
42
|
+
tabAvatar: string;
|
|
43
|
+
/** While the avatar is on, the chooser is read-only: switching avatars is Turn off, pick, Turn on (a new session). */
|
|
44
|
+
chooserLocked: string;
|
|
45
|
+
/** Leaving the Avatar tab turns its avatar off. */
|
|
46
|
+
tabLeaveHint: string;
|
|
47
|
+
/** After a "not now" refusal that said when: `{{time}}` is `retryTime(...)`. */
|
|
48
|
+
availableAgain: (time: string) => string;
|
|
49
|
+
/** The time a refused start may be tried again, in the interface's locale: the date is added when it is not today. */
|
|
50
|
+
retryTime: (at: number, now: number) => string;
|
|
51
|
+
/** The time-limit notice when no voice conversation is live (nothing continues "with voice only"). */
|
|
52
|
+
stateTimeLimitNoVoice: string;
|
|
53
|
+
/** The voice-only notice when no voice conversation is live. */
|
|
54
|
+
stateVoiceOnlyNoVoice: string;
|
|
55
|
+
/** The Avatar tab's Turn on while its start is under way: aria-disabled, so a second click starts nothing (critic #2). */
|
|
56
|
+
turnOnStarting: string;
|
|
57
|
+
/** The Avatar tab's way into the voice conversation: the composer's own words (`voiceSession.start`). */
|
|
58
|
+
startVoice: string;
|
|
59
|
+
/** Plays the chosen avatar voice on the speakers: the voice settings' own words (`voice.preview`). */
|
|
60
|
+
hearVoice: string;
|
|
61
|
+
/** Why the Avatar tab cannot start a voice conversation now (critic #6): the composer's own check says no. */
|
|
62
|
+
voiceStartBlocked: (blocker: VoiceStartBlocker) => string;
|
|
63
|
+
/** Said with a lasting reason: the avatar can be turned on, but it is asked by voice only. */
|
|
64
|
+
askNeedsVoice: string;
|
|
51
65
|
/** Why hands-free interrupt is off while the avatar is on (the pilot rule), and that it stays off after: the session's notice, and its control's reason. */
|
|
52
66
|
handsFreeOff: string;
|
|
53
|
-
|
|
67
|
+
/**
|
|
68
|
+
* What went wrong. `voiceLive` false: no voice conversation is live, so nothing is said to "continue" (BOFF-9341). `timed`: the next
|
|
69
|
+
* sentence says when it can start again, so the wording does not also say "in a moment".
|
|
70
|
+
*/
|
|
71
|
+
problem: (problem: AvatarProblem, options?: AvatarProblemOptions) => string;
|
|
72
|
+
}
|
|
73
|
+
export interface AvatarProblemOptions {
|
|
74
|
+
/** A voice conversation is live (the default: the voice stage is shown only during one). */
|
|
75
|
+
readonly voiceLive?: boolean;
|
|
76
|
+
/** A "You can start it again at …" sentence follows. */
|
|
77
|
+
readonly timed?: boolean;
|
|
54
78
|
}
|
|
79
|
+
/**
|
|
80
|
+
* `at` as the reader's locale writes a time, with the date when `at` is not on `now`'s day (a daily limit comes back tomorrow).
|
|
81
|
+
* ★ An unknown or malformed locale tag makes `Intl.DateTimeFormat` throw a RangeError: English stands in rather than losing the line.
|
|
82
|
+
*/
|
|
83
|
+
export declare function formatAvatarRetryTime(at: number, now: number, locale: string | undefined): string;
|
|
55
84
|
export declare function useAvatarCopy(): AvatarCopy;
|
|
@@ -1,55 +1,99 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { useI18n as e } from "../../providers/shell/I18nProvider.js";
|
|
2
|
+
import { useAssistantTr as t } from "../i18n.js";
|
|
3
|
+
import { useMemo as n } from "react";
|
|
3
4
|
//#region src/shared/assistant/avatar/useAvatarCopy.ts
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
5
|
+
var r = {
|
|
6
|
+
hour: "numeric",
|
|
7
|
+
minute: "2-digit"
|
|
8
|
+
}, i = {
|
|
9
|
+
month: "short",
|
|
10
|
+
day: "numeric",
|
|
11
|
+
hour: "numeric",
|
|
12
|
+
minute: "2-digit"
|
|
13
|
+
};
|
|
14
|
+
function a(e, t, n) {
|
|
15
|
+
let a = new Date(e).toDateString() === new Date(t).toDateString() ? r : i;
|
|
16
|
+
try {
|
|
17
|
+
return new Intl.DateTimeFormat(n, a).format(e);
|
|
18
|
+
} catch {
|
|
19
|
+
return new Intl.DateTimeFormat("en", a).format(e);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function o() {
|
|
23
|
+
let r = t(), { locale: i } = e();
|
|
24
|
+
return n(() => ({
|
|
25
|
+
toggle: r("avatar.toggle", "Live avatar"),
|
|
26
|
+
toggleHint: r("avatar.toggleHint", "Show the assistant as a speaking avatar during voice conversations."),
|
|
27
|
+
stop: r("avatar.stop", "Turn off the avatar"),
|
|
28
|
+
consent: r("avatar.consent", "Turning on Avatar shares the assistant's reply audio with LiveKit and Protoface to animate the avatar. This feature does not send your microphone audio to Protoface."),
|
|
29
|
+
consentConfirm: r("avatar.consentConfirm", "Turn on the avatar"),
|
|
30
|
+
consentCancel: r("avatar.consentCancel", "Not now"),
|
|
31
|
+
stateOff: r("avatar.stateOff", "Avatar off"),
|
|
32
|
+
stateOn: r("avatar.stateOn", "Avatar on"),
|
|
33
|
+
stateStarting: r("avatar.stateStarting", "Starting the avatar…"),
|
|
34
|
+
stateReady: r("avatar.stateReady", "Avatar ready"),
|
|
35
|
+
stateEnding: r("avatar.stateEnding", "Stopping the avatar…"),
|
|
36
|
+
stateInterrupted: r("avatar.stateInterrupted", "The avatar was interrupted. You can keep talking."),
|
|
37
|
+
stateVoiceOnly: r("avatar.stateVoiceOnly", "The avatar is unavailable right now. Continuing with voice only."),
|
|
38
|
+
stateTimeLimit: r("avatar.stateTimeLimit", "The avatar reached its time limit. Continuing with voice only."),
|
|
39
|
+
stageLabel: r("avatar.stageLabel", "Live avatar"),
|
|
40
|
+
stageWaiting: r("avatar.stageWaiting", "Waiting for the avatar…"),
|
|
41
|
+
chooserTitle: r("avatar.chooserTitle", "Choose an avatar"),
|
|
42
|
+
chooserLabel: r("avatar.chooserLabel", "Avatar"),
|
|
43
|
+
chooserNone: r("avatar.chooserNone", "No avatar chosen"),
|
|
44
|
+
chooserLoading: r("avatar.chooserLoading", "Loading avatars…"),
|
|
45
|
+
chooserEmpty: r("avatar.chooserEmpty", "No avatars are available."),
|
|
46
|
+
chooserRetry: r("avatar.chooserRetry", "Try again"),
|
|
47
|
+
chooserOption: (e) => r("avatar.chooserOption", "Use {{name}}", { name: e }),
|
|
48
|
+
chooserSelected: (e) => r("avatar.chooserSelected", "{{name}} (selected)", { name: e }),
|
|
49
|
+
voiceModeLabel: r("avatar.voiceModeLabel", "Avatar voice"),
|
|
50
|
+
voiceModeDefaultNamed: (e) => r("avatar.voiceModeDefaultNamed", "Default for this avatar ({{name}})", { name: e }),
|
|
51
|
+
voiceModeMine: r("avatar.voiceModeMine", "Keep my current voice"),
|
|
52
|
+
voiceModeMineNamed: (e) => r("avatar.voiceModeMineNamed", "Keep my current voice ({{name}})", { name: e }),
|
|
53
|
+
voiceModeHint: r("avatar.voiceModeNextReplyHint", "Used from the avatar's next reply. The assistant's own voice doesn't change."),
|
|
54
|
+
tabsLabel: r("avatar.tabsLabel", "Assistant views"),
|
|
55
|
+
tabChat: r("avatar.tabChat", "Chat"),
|
|
56
|
+
tabAvatar: r("avatar.tabAvatar", "Avatar"),
|
|
57
|
+
chooserLocked: r("avatar.chooserLocked", "Turn off the avatar to change it."),
|
|
58
|
+
tabLeaveHint: r("avatar.tabLeaveHint", "Leaving the Avatar tab turns the avatar off."),
|
|
59
|
+
availableAgain: (e) => r("avatar.availableAgain", "You can start it again at {{time}}.", { time: e }),
|
|
60
|
+
retryTime: (e, t) => a(e, t, i),
|
|
61
|
+
stateTimeLimitNoVoice: r("avatar.stateTimeLimitNoVoice", "The avatar reached its time limit."),
|
|
62
|
+
stateVoiceOnlyNoVoice: r("avatar.stateVoiceOnlyNoVoice", "The avatar is unavailable right now."),
|
|
63
|
+
turnOnStarting: r("avatar.turnOnStarting", "Starting the avatar…"),
|
|
64
|
+
startVoice: r("voiceSession.start", "Start a voice conversation"),
|
|
65
|
+
hearVoice: r("voice.preview", "Hear this voice"),
|
|
66
|
+
voiceStartBlocked: (e) => {
|
|
67
|
+
switch (e) {
|
|
68
|
+
case "unavailable": return r("avatar.voiceStartUnavailable", "Voice conversations aren’t available here.");
|
|
69
|
+
case "mode": return r("avatar.voiceStartMode", "Voice conversations aren’t available in this mode.");
|
|
70
|
+
case "read-only": return r("avatar.voiceStartReadOnly", "This conversation can’t take new questions. Start a new conversation to ask by voice.");
|
|
71
|
+
case "busy": return r("avatar.voiceStartBusy", "You can start a voice conversation when the assistant is ready.");
|
|
72
|
+
case "committing": return r("avatar.voiceStartCommitting", "You can start a voice conversation once your attachments are saved.");
|
|
73
|
+
case "dictating": return r("avatar.voiceStartDictating", "Stop dictating to start a voice conversation.");
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
askNeedsVoice: r("avatar.askNeedsVoice", "You can still turn the avatar on, but you ask it questions in a voice conversation."),
|
|
77
|
+
handsFreeOff: r("avatar.handsFreeOff", "Hands-free interrupt is off, so the avatar's voice can't interrupt itself. It stays off after you turn the avatar off; turn it back on in More options. You can still tap to interrupt."),
|
|
78
|
+
problem: (e, t = {}) => {
|
|
79
|
+
let n = t.voiceLive !== !1, i = t.timed === !0;
|
|
37
80
|
switch (e) {
|
|
38
|
-
case "unavailable": return
|
|
39
|
-
case "not-ready": return
|
|
40
|
-
case "already-running": return
|
|
41
|
-
case "capacity": return
|
|
42
|
-
case "rate-limited": return
|
|
43
|
-
case "paused": return
|
|
44
|
-
case "
|
|
45
|
-
case "
|
|
46
|
-
case "
|
|
47
|
-
case "
|
|
48
|
-
case "
|
|
49
|
-
case "
|
|
81
|
+
case "unavailable": return r("avatar.problemUnavailable", "The avatar isn’t available here.");
|
|
82
|
+
case "not-ready": return r("avatar.problemNotReady", "This avatar isn’t ready yet. Try another one.");
|
|
83
|
+
case "already-running": return r("avatar.problemAlreadyRunning", "An avatar is already running for you.");
|
|
84
|
+
case "capacity": return i ? r("avatar.problemCapacityTimed", "Avatars are busy right now.") : r("avatar.problemCapacity", "Avatars are busy right now. Try again in a moment.");
|
|
85
|
+
case "rate-limited": return i ? r("avatar.problemRateLimitedTimed", "You started avatars too quickly.") : r("avatar.problemRateLimited", "You started avatars too quickly. Wait a minute and try again.");
|
|
86
|
+
case "paused": return r("avatar.problemPaused", "Avatars are paused for now.");
|
|
87
|
+
case "budget-exhausted": return r("avatar.problemBudgetExhausted", "Avatar time is used up for now.");
|
|
88
|
+
case "start-timeout": return r("avatar.problemStartTimeout", "The avatar took too long to start. Try again in a moment.");
|
|
89
|
+
case "provider": return n ? r("avatar.problemProvider", "The avatar had a problem. Voice continues without it.") : r("avatar.problemProviderNoVoice", "The avatar had a problem.");
|
|
90
|
+
case "connection": return r("avatar.problemConnection", "The connection to the avatar was lost.");
|
|
91
|
+
case "needs-hosted-voice": return r("avatar.problemNeedsHostedVoice", "The avatar needs one of the assistant’s own voices. Choose one in the voice settings.");
|
|
92
|
+
case "unsupported-browser": return r("avatar.problemUnsupportedBrowser", "This browser can’t show the avatar.");
|
|
93
|
+
case "playback-blocked": return r("avatar.problemPlaybackBlocked", "The browser blocked the avatar’s sound. Tap the avatar to turn it on.");
|
|
50
94
|
}
|
|
51
95
|
}
|
|
52
|
-
}), [
|
|
96
|
+
}), [r, i]);
|
|
53
97
|
}
|
|
54
98
|
//#endregion
|
|
55
|
-
export {
|
|
99
|
+
export { a as formatAvatarRetryTime, o as useAvatarCopy };
|
|
@@ -216,9 +216,12 @@ export declare const ASSISTANT_I18N_LITERAL_COPY: {
|
|
|
216
216
|
readonly "attachments.unsupportedImage": "This device can't read that image format, so it can't be resized to send. Save it as JPEG and try again.";
|
|
217
217
|
readonly "attachments.uploading": "Uploading…";
|
|
218
218
|
readonly "attachments.voiceDropped": "{{count}} attachment(s) couldn't be saved and weren't sent.";
|
|
219
|
+
readonly "avatar.askNeedsVoice": "You can still turn the avatar on, but you ask it questions in a voice conversation.";
|
|
220
|
+
readonly "avatar.availableAgain": "You can start it again at {{time}}.";
|
|
219
221
|
readonly "avatar.chooserEmpty": "No avatars are available.";
|
|
220
222
|
readonly "avatar.chooserLabel": "Avatar";
|
|
221
223
|
readonly "avatar.chooserLoading": "Loading avatars…";
|
|
224
|
+
readonly "avatar.chooserLocked": "Turn off the avatar to change it.";
|
|
222
225
|
readonly "avatar.chooserNone": "No avatar chosen";
|
|
223
226
|
readonly "avatar.chooserOption": "Use {{name}}";
|
|
224
227
|
readonly "avatar.chooserRetry": "Try again";
|
|
@@ -229,14 +232,18 @@ export declare const ASSISTANT_I18N_LITERAL_COPY: {
|
|
|
229
232
|
readonly "avatar.consentConfirm": "Turn on the avatar";
|
|
230
233
|
readonly "avatar.handsFreeOff": "Hands-free interrupt is off, so the avatar's voice can't interrupt itself. It stays off after you turn the avatar off; turn it back on in More options. You can still tap to interrupt.";
|
|
231
234
|
readonly "avatar.problemAlreadyRunning": "An avatar is already running for you.";
|
|
235
|
+
readonly "avatar.problemBudgetExhausted": "Avatar time is used up for now.";
|
|
232
236
|
readonly "avatar.problemCapacity": "Avatars are busy right now. Try again in a moment.";
|
|
237
|
+
readonly "avatar.problemCapacityTimed": "Avatars are busy right now.";
|
|
233
238
|
readonly "avatar.problemConnection": "The connection to the avatar was lost.";
|
|
234
239
|
readonly "avatar.problemNeedsHostedVoice": "The avatar needs one of the assistant’s own voices. Choose one in the voice settings.";
|
|
235
240
|
readonly "avatar.problemNotReady": "This avatar isn’t ready yet. Try another one.";
|
|
236
241
|
readonly "avatar.problemPaused": "Avatars are paused for now.";
|
|
237
242
|
readonly "avatar.problemPlaybackBlocked": "The browser blocked the avatar’s sound. Tap the avatar to turn it on.";
|
|
238
243
|
readonly "avatar.problemProvider": "The avatar had a problem. Voice continues without it.";
|
|
244
|
+
readonly "avatar.problemProviderNoVoice": "The avatar had a problem.";
|
|
239
245
|
readonly "avatar.problemRateLimited": "You started avatars too quickly. Wait a minute and try again.";
|
|
246
|
+
readonly "avatar.problemRateLimitedTimed": "You started avatars too quickly.";
|
|
240
247
|
readonly "avatar.problemStartTimeout": "The avatar took too long to start. Try again in a moment.";
|
|
241
248
|
readonly "avatar.problemUnavailable": "The avatar isn’t available here.";
|
|
242
249
|
readonly "avatar.problemUnsupportedBrowser": "This browser can’t show the avatar.";
|
|
@@ -249,14 +256,28 @@ export declare const ASSISTANT_I18N_LITERAL_COPY: {
|
|
|
249
256
|
readonly "avatar.stateReady": "Avatar ready";
|
|
250
257
|
readonly "avatar.stateStarting": "Starting the avatar…";
|
|
251
258
|
readonly "avatar.stateTimeLimit": "The avatar reached its time limit. Continuing with voice only.";
|
|
259
|
+
readonly "avatar.stateTimeLimitNoVoice": "The avatar reached its time limit.";
|
|
252
260
|
readonly "avatar.stateVoiceOnly": "The avatar is unavailable right now. Continuing with voice only.";
|
|
261
|
+
readonly "avatar.stateVoiceOnlyNoVoice": "The avatar is unavailable right now.";
|
|
253
262
|
readonly "avatar.stop": "Turn off the avatar";
|
|
263
|
+
readonly "avatar.tabAvatar": "Avatar";
|
|
264
|
+
readonly "avatar.tabChat": "Chat";
|
|
265
|
+
readonly "avatar.tabLeaveHint": "Leaving the Avatar tab turns the avatar off.";
|
|
266
|
+
readonly "avatar.tabsLabel": "Assistant views";
|
|
254
267
|
readonly "avatar.toggle": "Live avatar";
|
|
255
268
|
readonly "avatar.toggleHint": "Show the assistant as a speaking avatar during voice conversations.";
|
|
256
|
-
readonly "avatar.
|
|
269
|
+
readonly "avatar.turnOnStarting": "Starting the avatar…";
|
|
270
|
+
readonly "avatar.voiceModeDefaultNamed": "Default for this avatar ({{name}})";
|
|
257
271
|
readonly "avatar.voiceModeLabel": "Avatar voice";
|
|
258
272
|
readonly "avatar.voiceModeMine": "Keep my current voice";
|
|
259
|
-
readonly "avatar.
|
|
273
|
+
readonly "avatar.voiceModeMineNamed": "Keep my current voice ({{name}})";
|
|
274
|
+
readonly "avatar.voiceModeNextReplyHint": "Used from the avatar's next reply. The assistant's own voice doesn't change.";
|
|
275
|
+
readonly "avatar.voiceStartBusy": "You can start a voice conversation when the assistant is ready.";
|
|
276
|
+
readonly "avatar.voiceStartCommitting": "You can start a voice conversation once your attachments are saved.";
|
|
277
|
+
readonly "avatar.voiceStartDictating": "Stop dictating to start a voice conversation.";
|
|
278
|
+
readonly "avatar.voiceStartMode": "Voice conversations aren’t available in this mode.";
|
|
279
|
+
readonly "avatar.voiceStartReadOnly": "This conversation can’t take new questions. Start a new conversation to ask by voice.";
|
|
280
|
+
readonly "avatar.voiceStartUnavailable": "Voice conversations aren’t available here.";
|
|
260
281
|
readonly "chatArea.placeholderActions": "What would you like me to do?";
|
|
261
282
|
readonly "chatArea.placeholderGeneral": "Ask me anything…";
|
|
262
283
|
readonly "chatInput.ariaLabel": "Message input";
|
|
@@ -110,9 +110,12 @@ var m = {
|
|
|
110
110
|
"attachments.unsupportedImage": "This device can't read that image format, so it can't be resized to send. Save it as JPEG and try again.",
|
|
111
111
|
"attachments.uploading": "Uploading…",
|
|
112
112
|
"attachments.voiceDropped": "{{count}} attachment(s) couldn't be saved and weren't sent.",
|
|
113
|
+
"avatar.askNeedsVoice": "You can still turn the avatar on, but you ask it questions in a voice conversation.",
|
|
114
|
+
"avatar.availableAgain": "You can start it again at {{time}}.",
|
|
113
115
|
"avatar.chooserEmpty": "No avatars are available.",
|
|
114
116
|
"avatar.chooserLabel": "Avatar",
|
|
115
117
|
"avatar.chooserLoading": "Loading avatars…",
|
|
118
|
+
"avatar.chooserLocked": "Turn off the avatar to change it.",
|
|
116
119
|
"avatar.chooserNone": "No avatar chosen",
|
|
117
120
|
"avatar.chooserOption": "Use {{name}}",
|
|
118
121
|
"avatar.chooserRetry": "Try again",
|
|
@@ -123,14 +126,18 @@ var m = {
|
|
|
123
126
|
"avatar.consentConfirm": "Turn on the avatar",
|
|
124
127
|
"avatar.handsFreeOff": "Hands-free interrupt is off, so the avatar's voice can't interrupt itself. It stays off after you turn the avatar off; turn it back on in More options. You can still tap to interrupt.",
|
|
125
128
|
"avatar.problemAlreadyRunning": "An avatar is already running for you.",
|
|
129
|
+
"avatar.problemBudgetExhausted": "Avatar time is used up for now.",
|
|
126
130
|
"avatar.problemCapacity": "Avatars are busy right now. Try again in a moment.",
|
|
131
|
+
"avatar.problemCapacityTimed": "Avatars are busy right now.",
|
|
127
132
|
"avatar.problemConnection": "The connection to the avatar was lost.",
|
|
128
133
|
"avatar.problemNeedsHostedVoice": "The avatar needs one of the assistant’s own voices. Choose one in the voice settings.",
|
|
129
134
|
"avatar.problemNotReady": "This avatar isn’t ready yet. Try another one.",
|
|
130
135
|
"avatar.problemPaused": "Avatars are paused for now.",
|
|
131
136
|
"avatar.problemPlaybackBlocked": "The browser blocked the avatar’s sound. Tap the avatar to turn it on.",
|
|
132
137
|
"avatar.problemProvider": "The avatar had a problem. Voice continues without it.",
|
|
138
|
+
"avatar.problemProviderNoVoice": "The avatar had a problem.",
|
|
133
139
|
"avatar.problemRateLimited": "You started avatars too quickly. Wait a minute and try again.",
|
|
140
|
+
"avatar.problemRateLimitedTimed": "You started avatars too quickly.",
|
|
134
141
|
"avatar.problemStartTimeout": "The avatar took too long to start. Try again in a moment.",
|
|
135
142
|
"avatar.problemUnavailable": "The avatar isn’t available here.",
|
|
136
143
|
"avatar.problemUnsupportedBrowser": "This browser can’t show the avatar.",
|
|
@@ -143,14 +150,28 @@ var m = {
|
|
|
143
150
|
"avatar.stateReady": "Avatar ready",
|
|
144
151
|
"avatar.stateStarting": "Starting the avatar…",
|
|
145
152
|
"avatar.stateTimeLimit": "The avatar reached its time limit. Continuing with voice only.",
|
|
153
|
+
"avatar.stateTimeLimitNoVoice": "The avatar reached its time limit.",
|
|
146
154
|
"avatar.stateVoiceOnly": "The avatar is unavailable right now. Continuing with voice only.",
|
|
155
|
+
"avatar.stateVoiceOnlyNoVoice": "The avatar is unavailable right now.",
|
|
147
156
|
"avatar.stop": "Turn off the avatar",
|
|
157
|
+
"avatar.tabAvatar": "Avatar",
|
|
158
|
+
"avatar.tabChat": "Chat",
|
|
159
|
+
"avatar.tabLeaveHint": "Leaving the Avatar tab turns the avatar off.",
|
|
160
|
+
"avatar.tabsLabel": "Assistant views",
|
|
148
161
|
"avatar.toggle": "Live avatar",
|
|
149
162
|
"avatar.toggleHint": "Show the assistant as a speaking avatar during voice conversations.",
|
|
150
|
-
"avatar.
|
|
163
|
+
"avatar.turnOnStarting": "Starting the avatar…",
|
|
164
|
+
"avatar.voiceModeDefaultNamed": "Default for this avatar ({{name}})",
|
|
151
165
|
"avatar.voiceModeLabel": "Avatar voice",
|
|
152
166
|
"avatar.voiceModeMine": "Keep my current voice",
|
|
153
|
-
"avatar.
|
|
167
|
+
"avatar.voiceModeMineNamed": "Keep my current voice ({{name}})",
|
|
168
|
+
"avatar.voiceModeNextReplyHint": "Used from the avatar's next reply. The assistant's own voice doesn't change.",
|
|
169
|
+
"avatar.voiceStartBusy": "You can start a voice conversation when the assistant is ready.",
|
|
170
|
+
"avatar.voiceStartCommitting": "You can start a voice conversation once your attachments are saved.",
|
|
171
|
+
"avatar.voiceStartDictating": "Stop dictating to start a voice conversation.",
|
|
172
|
+
"avatar.voiceStartMode": "Voice conversations aren’t available in this mode.",
|
|
173
|
+
"avatar.voiceStartReadOnly": "This conversation can’t take new questions. Start a new conversation to ask by voice.",
|
|
174
|
+
"avatar.voiceStartUnavailable": "Voice conversations aren’t available here.",
|
|
154
175
|
"chatArea.placeholderActions": "What would you like me to do?",
|
|
155
176
|
"chatArea.placeholderGeneral": "Ask me anything…",
|
|
156
177
|
"chatInput.ariaLabel": "Message input",
|
|
@@ -51,6 +51,7 @@ export * from './voice/voiceStageState';
|
|
|
51
51
|
export * from './voice/voiceStatus';
|
|
52
52
|
export * from './voice/rotationClock';
|
|
53
53
|
export * from './voice/voiceSession';
|
|
54
|
+
export * from './voice/voiceReply';
|
|
54
55
|
export * from './voice/handsFree';
|
|
55
56
|
export * from './voice/handsfree/audioTrackTransport';
|
|
56
57
|
export * from './voice/handsfree/backendStreamTransport';
|
|
@@ -223,6 +224,9 @@ export * from './ui/AssistantTurnActivity';
|
|
|
223
224
|
export * from './ui/voice/AssistantVoiceSession';
|
|
224
225
|
export * from './ui/voice/HandsFreePrivacyNotice';
|
|
225
226
|
export * from './ui/assistantLiveAvatarSeam';
|
|
227
|
+
export * from './ui/AssistantAvatarTabs';
|
|
228
|
+
export * from './ui/avatar/AssistantAvatarTab';
|
|
229
|
+
export * from './ui/voice/voiceStartGate';
|
|
226
230
|
export * from './useAssistantApiAccess';
|
|
227
231
|
export * from './useConversationTurns';
|
|
228
232
|
export * from './transportErrors';
|
|
@@ -329,5 +333,7 @@ export * from './avatar/live/avatarSessionClient';
|
|
|
329
333
|
export * from './avatar/live/liveAvatarController';
|
|
330
334
|
export * from './avatar/live/liveKitAvatarRoom';
|
|
331
335
|
export * from './avatar/live/LiveAvatarStage';
|
|
336
|
+
export * from './avatar/live/LiveAvatarTabView';
|
|
332
337
|
export * from './avatar/live/liveAvatarStatus';
|
|
333
338
|
export * from './avatar/live/createLiveAvatarSeam';
|
|
339
|
+
export * from './avatar/live/avatarVoice';
|
|
@@ -1,6 +1,25 @@
|
|
|
1
1
|
import { SpeechVoiceLike } from '../voice/speechVoices';
|
|
2
2
|
/** Vendor tier this catalogue describes; sent to the backend with each request. */
|
|
3
3
|
export declare const HOSTED_TTS_TIER = "chirp3-hd";
|
|
4
|
+
/**
|
|
5
|
+
* Speaker names are shared across locales in this tier — the same speaker id is
|
|
6
|
+
* offered in every supported locale, so the catalogue is a cross product rather
|
|
7
|
+
* than a hand-written list per language.
|
|
8
|
+
*
|
|
9
|
+
* Exported for the live avatar's own voice (BOFF-9341): a person picks a SPEAKER
|
|
10
|
+
* for the avatar, once, and each reply speaks it in that reply's language
|
|
11
|
+
* (`hostedVoiceName`). A stored speaker is checked against this list.
|
|
12
|
+
*/
|
|
13
|
+
export declare const HOSTED_SPEAKERS: readonly ["Achernar", "Algenib", "Charon", "Kore", "Puck", "Zephyr"];
|
|
14
|
+
export type HostedSpeaker = (typeof HOSTED_SPEAKERS)[number];
|
|
15
|
+
/** Whether a value (stored, or from a host's config) is one of this tier's speakers. */
|
|
16
|
+
export declare function isHostedSpeaker(value: unknown): value is HostedSpeaker;
|
|
17
|
+
/**
|
|
18
|
+
* The vendor's voice id for one speaker in one VENDOR locale (`hostedLocaleFor`
|
|
19
|
+
* gives it for an app tag), e.g. `ta-IN-Chirp3-HD-Kore`: the one spelling every
|
|
20
|
+
* entry below uses, and the name a voice is looked up by.
|
|
21
|
+
*/
|
|
22
|
+
export declare function hostedVoiceName(vendorLocale: string, speaker: HostedSpeaker): string;
|
|
4
23
|
/**
|
|
5
24
|
* Every hosted voice, as `SpeechVoiceLike` so it is interchangeable with a
|
|
6
25
|
* device voice everywhere downstream.
|
|
@@ -6,7 +6,11 @@ var e = "chirp3-hd", t = [
|
|
|
6
6
|
"Kore",
|
|
7
7
|
"Puck",
|
|
8
8
|
"Zephyr"
|
|
9
|
-
]
|
|
9
|
+
];
|
|
10
|
+
function n(e) {
|
|
11
|
+
return typeof e == "string" && t.includes(e);
|
|
12
|
+
}
|
|
13
|
+
var r = [
|
|
10
14
|
"en-US",
|
|
11
15
|
"en-GB",
|
|
12
16
|
"en-IN",
|
|
@@ -26,32 +30,35 @@ var e = "chirp3-hd", t = [
|
|
|
26
30
|
"ja-JP",
|
|
27
31
|
"fr-FR",
|
|
28
32
|
"de-DE"
|
|
29
|
-
],
|
|
30
|
-
function
|
|
31
|
-
return
|
|
33
|
+
], i = { "cmn-CN": "zh-CN" };
|
|
34
|
+
function a(e) {
|
|
35
|
+
return i[e] ?? e;
|
|
36
|
+
}
|
|
37
|
+
function o(e, t) {
|
|
38
|
+
return `${e}-Chirp3-HD-${t}`;
|
|
32
39
|
}
|
|
33
|
-
var
|
|
34
|
-
name:
|
|
35
|
-
lang:
|
|
40
|
+
var s = r.flatMap((e) => t.map((t) => ({
|
|
41
|
+
name: o(e, t),
|
|
42
|
+
lang: a(e),
|
|
36
43
|
localService: !1,
|
|
37
44
|
source: "hosted"
|
|
38
|
-
}))),
|
|
39
|
-
for (let e of
|
|
45
|
+
}))), c = /* @__PURE__ */ new Map();
|
|
46
|
+
for (let e of r) for (let t of new Set([a(e), e])) {
|
|
40
47
|
let n = t.toLowerCase().split("-")[0];
|
|
41
|
-
|
|
48
|
+
c.has(n) || c.set(n, e);
|
|
42
49
|
}
|
|
43
|
-
var
|
|
44
|
-
for (let e of
|
|
45
|
-
function
|
|
50
|
+
var l = /* @__PURE__ */ new Map();
|
|
51
|
+
for (let e of r) l.set(e.toLowerCase(), e), l.set(a(e).toLowerCase(), e);
|
|
52
|
+
function u(e) {
|
|
46
53
|
let t = e.trim().replace("_", "-");
|
|
47
54
|
if (!t) return null;
|
|
48
|
-
let n =
|
|
55
|
+
let n = l.get(t.toLowerCase());
|
|
49
56
|
if (n) return n;
|
|
50
57
|
let r = t.toLowerCase().split("-")[0];
|
|
51
|
-
return
|
|
58
|
+
return c.get(r) ?? null;
|
|
52
59
|
}
|
|
53
|
-
function
|
|
54
|
-
return
|
|
60
|
+
function d(e) {
|
|
61
|
+
return u(e) !== null;
|
|
55
62
|
}
|
|
56
63
|
//#endregion
|
|
57
|
-
export { e as HOSTED_TTS_TIER,
|
|
64
|
+
export { t as HOSTED_SPEAKERS, e as HOSTED_TTS_TIER, s as HOSTED_VOICES, u as hostedLocaleFor, d as hostedSupportsLanguage, o as hostedVoiceName, n as isHostedSpeaker };
|