@burdenoff/fe-libs 2026.1014.4 → 2026.1015.1
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 +52 -21
- package/dist/shared/assistant/avatar/useAvatarCopy.js +93 -48
- package/dist/shared/assistant/i18nManifest.d.ts +24 -2
- package/dist/shared/assistant/i18nManifest.js +24 -2
- package/dist/shared/assistant/index.d.ts +5 -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 +136 -103
- 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 +1260 -1199
- package/dist/shared/assistant/ui/assistantLiveAvatarSeam.d.ts +165 -5
- package/dist/shared/assistant/ui/assistantLiveAvatarSeam.js +141 -59
- 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/composer/AssistantHandsFreeInterruptToggle.d.ts +9 -0
- package/dist/shared/assistant/ui/composer/AssistantHandsFreeInterruptToggle.js +28 -14
- 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.js +234 -233
- package/dist/shared/assistant/ui/voice/AssistantVoiceSession.d.ts +6 -0
- package/dist/shared/assistant/ui/voice/AssistantVoiceSession.js +161 -149
- package/dist/shared/assistant/ui/voice/VoiceMiniController.js +7 -7
- package/dist/shared/assistant/ui/voice/VoiceStage.js +7 -7
- 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/handsfree/handsFreeSetting.d.ts +7 -1
- package/dist/shared/assistant/voice/handsfree/handsFreeSetting.js +2 -2
- package/dist/shared-assistant.js +259 -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,9 +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;
|
|
51
|
-
|
|
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;
|
|
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. */
|
|
66
|
+
handsFreeOff: string;
|
|
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;
|
|
52
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;
|
|
53
84
|
export declare function useAvatarCopy(): AvatarCopy;
|
|
@@ -1,54 +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
|
-
|
|
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;
|
|
36
80
|
switch (e) {
|
|
37
|
-
case "unavailable": return
|
|
38
|
-
case "not-ready": return
|
|
39
|
-
case "already-running": return
|
|
40
|
-
case "capacity": return
|
|
41
|
-
case "rate-limited": return
|
|
42
|
-
case "paused": return
|
|
43
|
-
case "
|
|
44
|
-
case "
|
|
45
|
-
case "
|
|
46
|
-
case "
|
|
47
|
-
case "
|
|
48
|
-
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.");
|
|
49
94
|
}
|
|
50
95
|
}
|
|
51
|
-
}), [
|
|
96
|
+
}), [r, i]);
|
|
52
97
|
}
|
|
53
98
|
//#endregion
|
|
54
|
-
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";
|
|
@@ -227,15 +230,20 @@ export declare const ASSISTANT_I18N_LITERAL_COPY: {
|
|
|
227
230
|
readonly "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.";
|
|
228
231
|
readonly "avatar.consentCancel": "Not now";
|
|
229
232
|
readonly "avatar.consentConfirm": "Turn on the avatar";
|
|
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.";
|
|
230
234
|
readonly "avatar.problemAlreadyRunning": "An avatar is already running for you.";
|
|
235
|
+
readonly "avatar.problemBudgetExhausted": "Avatar time is used up for now.";
|
|
231
236
|
readonly "avatar.problemCapacity": "Avatars are busy right now. Try again in a moment.";
|
|
237
|
+
readonly "avatar.problemCapacityTimed": "Avatars are busy right now.";
|
|
232
238
|
readonly "avatar.problemConnection": "The connection to the avatar was lost.";
|
|
233
239
|
readonly "avatar.problemNeedsHostedVoice": "The avatar needs one of the assistant’s own voices. Choose one in the voice settings.";
|
|
234
240
|
readonly "avatar.problemNotReady": "This avatar isn’t ready yet. Try another one.";
|
|
235
241
|
readonly "avatar.problemPaused": "Avatars are paused for now.";
|
|
236
242
|
readonly "avatar.problemPlaybackBlocked": "The browser blocked the avatar’s sound. Tap the avatar to turn it on.";
|
|
237
243
|
readonly "avatar.problemProvider": "The avatar had a problem. Voice continues without it.";
|
|
244
|
+
readonly "avatar.problemProviderNoVoice": "The avatar had a problem.";
|
|
238
245
|
readonly "avatar.problemRateLimited": "You started avatars too quickly. Wait a minute and try again.";
|
|
246
|
+
readonly "avatar.problemRateLimitedTimed": "You started avatars too quickly.";
|
|
239
247
|
readonly "avatar.problemStartTimeout": "The avatar took too long to start. Try again in a moment.";
|
|
240
248
|
readonly "avatar.problemUnavailable": "The avatar isn’t available here.";
|
|
241
249
|
readonly "avatar.problemUnsupportedBrowser": "This browser can’t show the avatar.";
|
|
@@ -248,14 +256,28 @@ export declare const ASSISTANT_I18N_LITERAL_COPY: {
|
|
|
248
256
|
readonly "avatar.stateReady": "Avatar ready";
|
|
249
257
|
readonly "avatar.stateStarting": "Starting the avatar…";
|
|
250
258
|
readonly "avatar.stateTimeLimit": "The avatar reached its time limit. Continuing with voice only.";
|
|
259
|
+
readonly "avatar.stateTimeLimitNoVoice": "The avatar reached its time limit.";
|
|
251
260
|
readonly "avatar.stateVoiceOnly": "The avatar is unavailable right now. Continuing with voice only.";
|
|
261
|
+
readonly "avatar.stateVoiceOnlyNoVoice": "The avatar is unavailable right now.";
|
|
252
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";
|
|
253
267
|
readonly "avatar.toggle": "Live avatar";
|
|
254
268
|
readonly "avatar.toggleHint": "Show the assistant as a speaking avatar during voice conversations.";
|
|
255
|
-
readonly "avatar.
|
|
269
|
+
readonly "avatar.turnOnStarting": "Starting the avatar…";
|
|
270
|
+
readonly "avatar.voiceModeDefaultNamed": "Default for this avatar ({{name}})";
|
|
256
271
|
readonly "avatar.voiceModeLabel": "Avatar voice";
|
|
257
272
|
readonly "avatar.voiceModeMine": "Keep my current voice";
|
|
258
|
-
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.";
|
|
259
281
|
readonly "chatArea.placeholderActions": "What would you like me to do?";
|
|
260
282
|
readonly "chatArea.placeholderGeneral": "Ask me anything…";
|
|
261
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",
|
|
@@ -121,15 +124,20 @@ var m = {
|
|
|
121
124
|
"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.",
|
|
122
125
|
"avatar.consentCancel": "Not now",
|
|
123
126
|
"avatar.consentConfirm": "Turn on the avatar",
|
|
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.",
|
|
124
128
|
"avatar.problemAlreadyRunning": "An avatar is already running for you.",
|
|
129
|
+
"avatar.problemBudgetExhausted": "Avatar time is used up for now.",
|
|
125
130
|
"avatar.problemCapacity": "Avatars are busy right now. Try again in a moment.",
|
|
131
|
+
"avatar.problemCapacityTimed": "Avatars are busy right now.",
|
|
126
132
|
"avatar.problemConnection": "The connection to the avatar was lost.",
|
|
127
133
|
"avatar.problemNeedsHostedVoice": "The avatar needs one of the assistant’s own voices. Choose one in the voice settings.",
|
|
128
134
|
"avatar.problemNotReady": "This avatar isn’t ready yet. Try another one.",
|
|
129
135
|
"avatar.problemPaused": "Avatars are paused for now.",
|
|
130
136
|
"avatar.problemPlaybackBlocked": "The browser blocked the avatar’s sound. Tap the avatar to turn it on.",
|
|
131
137
|
"avatar.problemProvider": "The avatar had a problem. Voice continues without it.",
|
|
138
|
+
"avatar.problemProviderNoVoice": "The avatar had a problem.",
|
|
132
139
|
"avatar.problemRateLimited": "You started avatars too quickly. Wait a minute and try again.",
|
|
140
|
+
"avatar.problemRateLimitedTimed": "You started avatars too quickly.",
|
|
133
141
|
"avatar.problemStartTimeout": "The avatar took too long to start. Try again in a moment.",
|
|
134
142
|
"avatar.problemUnavailable": "The avatar isn’t available here.",
|
|
135
143
|
"avatar.problemUnsupportedBrowser": "This browser can’t show the avatar.",
|
|
@@ -142,14 +150,28 @@ var m = {
|
|
|
142
150
|
"avatar.stateReady": "Avatar ready",
|
|
143
151
|
"avatar.stateStarting": "Starting the avatar…",
|
|
144
152
|
"avatar.stateTimeLimit": "The avatar reached its time limit. Continuing with voice only.",
|
|
153
|
+
"avatar.stateTimeLimitNoVoice": "The avatar reached its time limit.",
|
|
145
154
|
"avatar.stateVoiceOnly": "The avatar is unavailable right now. Continuing with voice only.",
|
|
155
|
+
"avatar.stateVoiceOnlyNoVoice": "The avatar is unavailable right now.",
|
|
146
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",
|
|
147
161
|
"avatar.toggle": "Live avatar",
|
|
148
162
|
"avatar.toggleHint": "Show the assistant as a speaking avatar during voice conversations.",
|
|
149
|
-
"avatar.
|
|
163
|
+
"avatar.turnOnStarting": "Starting the avatar…",
|
|
164
|
+
"avatar.voiceModeDefaultNamed": "Default for this avatar ({{name}})",
|
|
150
165
|
"avatar.voiceModeLabel": "Avatar voice",
|
|
151
166
|
"avatar.voiceModeMine": "Keep my current voice",
|
|
152
|
-
"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.",
|
|
153
175
|
"chatArea.placeholderActions": "What would you like me to do?",
|
|
154
176
|
"chatArea.placeholderGeneral": "Ask me anything…",
|
|
155
177
|
"chatInput.ariaLabel": "Message input",
|
|
@@ -223,6 +223,9 @@ export * from './ui/AssistantTurnActivity';
|
|
|
223
223
|
export * from './ui/voice/AssistantVoiceSession';
|
|
224
224
|
export * from './ui/voice/HandsFreePrivacyNotice';
|
|
225
225
|
export * from './ui/assistantLiveAvatarSeam';
|
|
226
|
+
export * from './ui/AssistantAvatarTabs';
|
|
227
|
+
export * from './ui/avatar/AssistantAvatarTab';
|
|
228
|
+
export * from './ui/voice/voiceStartGate';
|
|
226
229
|
export * from './useAssistantApiAccess';
|
|
227
230
|
export * from './useConversationTurns';
|
|
228
231
|
export * from './transportErrors';
|
|
@@ -329,5 +332,7 @@ export * from './avatar/live/avatarSessionClient';
|
|
|
329
332
|
export * from './avatar/live/liveAvatarController';
|
|
330
333
|
export * from './avatar/live/liveKitAvatarRoom';
|
|
331
334
|
export * from './avatar/live/LiveAvatarStage';
|
|
335
|
+
export * from './avatar/live/LiveAvatarTabView';
|
|
332
336
|
export * from './avatar/live/liveAvatarStatus';
|
|
333
337
|
export * from './avatar/live/createLiveAvatarSeam';
|
|
338
|
+
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 };
|