@burdenoff/fe-libs 2026.1024.3 → 2026.1026.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/live/LiveAvatarMinutes.d.ts +24 -0
- package/dist/shared/assistant/avatar/live/LiveAvatarMinutes.js +161 -0
- package/dist/shared/assistant/avatar/live/LiveAvatarStage.js +95 -74
- package/dist/shared/assistant/avatar/live/LiveAvatarTabView.d.ts +6 -0
- package/dist/shared/assistant/avatar/live/LiveAvatarTabView.js +195 -172
- package/dist/shared/assistant/avatar/live/avatarPorts.d.ts +9 -0
- package/dist/shared/assistant/avatar/live/avatarSessionClient.d.ts +77 -1
- package/dist/shared/assistant/avatar/live/avatarSessionClient.js +193 -72
- package/dist/shared/assistant/avatar/live/avatarTransport.d.ts +25 -3
- package/dist/shared/assistant/avatar/live/avatarTransport.js +29 -2
- package/dist/shared/assistant/avatar/live/createLiveAvatarSeam.d.ts +35 -4
- package/dist/shared/assistant/avatar/live/createLiveAvatarSeam.js +136 -79
- package/dist/shared/assistant/avatar/live/liveAvatarController.d.ts +79 -3
- package/dist/shared/assistant/avatar/live/liveAvatarController.js +424 -245
- package/dist/shared/assistant/avatar/live/liveAvatarMinutesView.d.ts +127 -0
- package/dist/shared/assistant/avatar/live/liveAvatarMinutesView.js +168 -0
- package/dist/shared/assistant/avatar/live/liveAvatarStatus.d.ts +3 -0
- package/dist/shared/assistant/avatar/live/liveAvatarStatus.js +11 -7
- package/dist/shared/assistant/avatar/live/liveKitAvatarRoom.js +6 -1
- package/dist/shared/assistant/avatar/useAvatarCopy.d.ts +127 -2
- package/dist/shared/assistant/avatar/useAvatarCopy.js +116 -7
- package/dist/shared/assistant/i18nManifest.d.ts +32 -1
- package/dist/shared/assistant/i18nManifest.js +55 -24
- package/dist/shared/assistant/index.d.ts +2 -0
- package/dist/shared/assistant/ui/AssistantChatArea.js +17 -17
- package/dist/shared/assistant/ui/AssistantMarkdownRenderer.d.ts +5 -2
- package/dist/shared/assistant/ui/assistantLiveAvatarSeam.d.ts +11 -3
- package/dist/shared/assistant/ui/avatar/AssistantAvatarTab.js +78 -76
- package/dist/shared/assistant/ui/avatar/avatarAskGate.d.ts +2 -0
- package/dist/shared/assistant/ui/avatar/avatarAskGate.js +1 -0
- package/dist/shared/events/index.d.ts +2 -1
- package/dist/shared-assistant.js +227 -225
- package/package.json +1 -1
|
@@ -4,23 +4,121 @@ import { VOICE_THINKING_LABEL as n } from "../voice/voiceStatus.js";
|
|
|
4
4
|
import { useMemo as r } from "react";
|
|
5
5
|
//#region src/shared/assistant/avatar/useAvatarCopy.ts
|
|
6
6
|
var i = {
|
|
7
|
+
title: {
|
|
8
|
+
key: "avatar.minutes.howCounted.title",
|
|
9
|
+
fallback: "How avatar credits are counted"
|
|
10
|
+
},
|
|
11
|
+
unit: {
|
|
12
|
+
key: "avatar.minutes.howCounted.unit",
|
|
13
|
+
fallback: "1 credit = 1 minute of avatar time."
|
|
14
|
+
},
|
|
15
|
+
start: {
|
|
16
|
+
key: "avatar.minutes.howCounted.start",
|
|
17
|
+
fallback: "Counting starts once you and the avatar are both connected. Waiting for the avatar and starts that fail are free."
|
|
18
|
+
},
|
|
19
|
+
rounding: {
|
|
20
|
+
key: "avatar.minutes.howCounted.rounding",
|
|
21
|
+
fallback: "Each started minute uses one avatar credit. For example, a 2-minute-10-second session uses 3 credits."
|
|
22
|
+
},
|
|
23
|
+
drops: {
|
|
24
|
+
key: "avatar.minutes.howCounted.drops",
|
|
25
|
+
fallback: "Short connection drops that don't end the session count as part of it, like a phone call."
|
|
26
|
+
},
|
|
27
|
+
lost: {
|
|
28
|
+
key: "avatar.minutes.howCounted.lost",
|
|
29
|
+
fallback: "If the connection is lost, counting stops at the last moment we saw you both connected, minus a {{seconds}}-second safety margin."
|
|
30
|
+
},
|
|
31
|
+
lostNoFigure: {
|
|
32
|
+
key: "avatar.minutes.howCounted.lostNoFigure",
|
|
33
|
+
fallback: "If the connection is lost, counting stops at the last moment we saw you both connected, minus a safety margin."
|
|
34
|
+
},
|
|
35
|
+
ourEnd: {
|
|
36
|
+
key: "avatar.minutes.howCounted.ourEnd",
|
|
37
|
+
fallback: "If we stop the session because of a problem or maintenance on our side, or the avatar fails, the unfinished minute is free."
|
|
38
|
+
},
|
|
39
|
+
support: {
|
|
40
|
+
key: "avatar.minutes.howCounted.support",
|
|
41
|
+
fallback: "If something looks wrong, contact support: we credit the whole session back."
|
|
42
|
+
}
|
|
43
|
+
}, a = {
|
|
7
44
|
hour: "numeric",
|
|
8
45
|
minute: "2-digit"
|
|
9
|
-
},
|
|
46
|
+
}, o = {
|
|
10
47
|
month: "short",
|
|
11
48
|
day: "numeric",
|
|
12
49
|
hour: "numeric",
|
|
13
50
|
minute: "2-digit"
|
|
14
51
|
};
|
|
15
|
-
function
|
|
16
|
-
let r = new Date(e).toDateString() === new Date(t).toDateString() ?
|
|
52
|
+
function s(e, t, n) {
|
|
53
|
+
let r = new Date(e).toDateString() === new Date(t).toDateString() ? a : o;
|
|
17
54
|
try {
|
|
18
55
|
return new Intl.DateTimeFormat(n, r).format(e);
|
|
19
56
|
} catch {
|
|
20
57
|
return new Intl.DateTimeFormat("en", r).format(e);
|
|
21
58
|
}
|
|
22
59
|
}
|
|
23
|
-
|
|
60
|
+
var c = {
|
|
61
|
+
timeZone: "UTC",
|
|
62
|
+
day: "numeric",
|
|
63
|
+
month: "short"
|
|
64
|
+
}, l = /* @__PURE__ */ new Map(), u = /* @__PURE__ */ new Map();
|
|
65
|
+
function d(e, t) {
|
|
66
|
+
let n = t ?? "", r = l.get(n);
|
|
67
|
+
if (r === void 0) {
|
|
68
|
+
try {
|
|
69
|
+
r = new Intl.DateTimeFormat(t, c);
|
|
70
|
+
} catch {
|
|
71
|
+
r = new Intl.DateTimeFormat("en", c);
|
|
72
|
+
}
|
|
73
|
+
l.set(n, r);
|
|
74
|
+
}
|
|
75
|
+
return r.format(e);
|
|
76
|
+
}
|
|
77
|
+
function f(e, t) {
|
|
78
|
+
let n = t ?? "", r = u.get(n);
|
|
79
|
+
if (r === void 0) {
|
|
80
|
+
try {
|
|
81
|
+
r = new Intl.NumberFormat(t, { maximumFractionDigits: 0 });
|
|
82
|
+
} catch {
|
|
83
|
+
r = new Intl.NumberFormat("en", { maximumFractionDigits: 0 });
|
|
84
|
+
}
|
|
85
|
+
u.set(n, r);
|
|
86
|
+
}
|
|
87
|
+
return r.format(e);
|
|
88
|
+
}
|
|
89
|
+
function p(e, t) {
|
|
90
|
+
let n = (e) => f(e, t), r = (e) => d(e, t), a = (t, n) => e(t.key, t.fallback, n), o = i;
|
|
91
|
+
return {
|
|
92
|
+
left: (t) => e("avatar.minutes.left", "Avatar credits left: {{count}}", { count: n(t) }),
|
|
93
|
+
shared: e("avatar.minutes.shared", "Everyone in this workspace shares these credits."),
|
|
94
|
+
freePerMonth: (t) => e("avatar.minutes.freePerMonth", "Free avatar credits each month: {{count}}", { count: n(t) }),
|
|
95
|
+
noFree: e("avatar.minutes.noFree", "No free avatar credits are included."),
|
|
96
|
+
planPerMonth: (t) => e("avatar.minutes.planPerMonth", "Avatar credits from paid plans each month: {{count}}", { count: n(t) }),
|
|
97
|
+
resetsOn: (t) => e("avatar.minutes.resetsOn", "Avatar credits reset on {{date}} (UTC).", { date: r(t) }),
|
|
98
|
+
freePerPerson: (t) => e("avatar.minutes.freePerPerson", "Free avatar credits per person each month: {{count}}", { count: n(t) }),
|
|
99
|
+
low: e("avatar.minutes.low", "Avatar credits are running low. The avatar stops when they run out."),
|
|
100
|
+
sessionLeft: (t) => e("avatar.minutes.sessionLeft", "Minutes left in this session: about {{count}}", { count: n(t) }),
|
|
101
|
+
seePlans: e("avatar.minutes.seePlans", "See plans"),
|
|
102
|
+
askAdmin: e("avatar.minutes.askAdmin", "Ask your billing administrator about a plan with more avatar credits."),
|
|
103
|
+
checkAgain: e("avatar.minutes.checkAgain", "Check again"),
|
|
104
|
+
checking: e("avatar.minutes.checking", "Checking…"),
|
|
105
|
+
checkingPlan: e("avatar.minutes.checkingPlan", "Checking your plan…"),
|
|
106
|
+
assignPlan: e("avatar.minutes.assignPlan", "Assign your new plan to this workspace in Billing to use its credits."),
|
|
107
|
+
ended: e("avatar.minutes.ended", "The avatar stopped because this workspace’s avatar credits ran out. Continuing with voice only."),
|
|
108
|
+
endedNoVoice: e("avatar.minutes.endedNoVoice", "The avatar stopped because this workspace’s avatar credits ran out."),
|
|
109
|
+
howCountedTitle: a(o.title),
|
|
110
|
+
howCounted: (e) => [
|
|
111
|
+
a(o.unit),
|
|
112
|
+
a(o.start),
|
|
113
|
+
a(o.rounding),
|
|
114
|
+
a(o.drops),
|
|
115
|
+
e === null ? a(o.lostNoFigure) : a(o.lost, { seconds: n(e) }),
|
|
116
|
+
a(o.ourEnd),
|
|
117
|
+
a(o.support)
|
|
118
|
+
]
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function m() {
|
|
24
122
|
let i = t(), { locale: a } = e();
|
|
25
123
|
return r(() => ({
|
|
26
124
|
toggle: i("avatar.toggle", "Live avatar"),
|
|
@@ -58,7 +156,7 @@ function s() {
|
|
|
58
156
|
chooserLocked: i("avatar.chooserLocked", "Turn off the avatar to change it."),
|
|
59
157
|
tabLeaveHint: i("avatar.tabLeaveHint", "Leaving the Avatar tab turns the avatar off."),
|
|
60
158
|
availableAgain: (e) => i("avatar.availableAgain", "You can start it again at {{time}}.", { time: e }),
|
|
61
|
-
retryTime: (e, t) =>
|
|
159
|
+
retryTime: (e, t) => s(e, t, a),
|
|
62
160
|
stateTimeLimitNoVoice: i("avatar.stateTimeLimitNoVoice", "The avatar reached its time limit."),
|
|
63
161
|
stateVoiceOnlyNoVoice: i("avatar.stateVoiceOnlyNoVoice", "The avatar is unavailable right now."),
|
|
64
162
|
turnOnStarting: i("avatar.turnOnStarting", "Starting the avatar…"),
|
|
@@ -89,6 +187,7 @@ function s() {
|
|
|
89
187
|
case "mode-escalated": return i("avatar.askMode", "This conversation can make changes, so typed questions to the avatar aren't available here. Start a new conversation to ask one.");
|
|
90
188
|
case "avatar-off": return i("avatar.askNeedsAvatar", "Turn on the avatar to send your question. You can type it now.");
|
|
91
189
|
case "avatar-again": return i("avatar.askAgain", "You can send your question when the avatar is on again.");
|
|
190
|
+
case "avatar-minutes": return i("avatar.askNoMinutes", "You can send your question when avatar credits are available.");
|
|
92
191
|
case "sound": return i("avatar.askSound", "Turn on the avatar's sound first.");
|
|
93
192
|
case "starting": return i("avatar.askStarting", "You can send your question when the avatar is ready.");
|
|
94
193
|
case "busy": return i("avatar.askBusy", "You can send your question when the assistant is ready.");
|
|
@@ -135,9 +234,19 @@ function s() {
|
|
|
135
234
|
case "needs-hosted-voice": return i("avatar.problemNeedsHostedVoice", "The avatar needs one of the assistant’s own voices. Choose one in the voice settings.");
|
|
136
235
|
case "unsupported-browser": return i("avatar.problemUnsupportedBrowser", "This browser can’t show the avatar.");
|
|
137
236
|
case "playback-blocked": return i("avatar.problemPlaybackBlocked", "The browser blocked the avatar’s sound. Tap the avatar to turn it on.");
|
|
237
|
+
case "minutes-exhausted": switch (t.minutesReason) {
|
|
238
|
+
case "FREE_CEILING": return i("avatar.problemMinutesFreeCeiling", "You’ve used your free avatar credits for this month.");
|
|
239
|
+
case "NOT_INCLUDED": return i("avatar.problemMinutesNotIncluded", "Avatar credits aren’t included for this workspace.");
|
|
240
|
+
case "ZERO_SESSION_LIMIT": return i("avatar.problemMinutesZeroSessionLimit", "You’ve started too many short avatar sessions today.");
|
|
241
|
+
default: return t.minutesResetsAt === void 0 || t.minutesResetsAt === null ? i("avatar.problemMinutesExhausted", "No avatar credits left in this workspace.") : i("avatar.problemMinutesExhaustedUntil", "No avatar credits left in this workspace. They come back on {{date}} (UTC).", { date: d(t.minutesResetsAt, a) });
|
|
242
|
+
}
|
|
243
|
+
case "minutes-in-use": return r ? i("avatar.problemMinutesInUseTimed", "Avatar credits are in use in another session.") : i("avatar.problemMinutesInUse", "Avatar credits are in use in another session. Try again when it ends.");
|
|
244
|
+
case "minutes-in-use-self": return r ? i("avatar.problemMinutesInUseSelfTimed", "Your avatar is still running on another device. End it there.") : i("avatar.problemMinutesInUseSelf", "Your avatar is still running on another device. End it there, or try again when it ends.");
|
|
245
|
+
case "minutes-unavailable": return r ? i("avatar.problemMinutesUnavailableTimed", "Avatar credits can’t be checked right now.") : i("avatar.problemMinutesUnavailable", "Avatar credits can’t be checked right now. Try again in a moment.");
|
|
138
246
|
}
|
|
139
|
-
}
|
|
247
|
+
},
|
|
248
|
+
minutes: p(i, a)
|
|
140
249
|
}), [i, a]);
|
|
141
250
|
}
|
|
142
251
|
//#endregion
|
|
143
|
-
export {
|
|
252
|
+
export { i as AVATAR_MINUTES_HOW_COUNTED, f as formatAvatarCount, d as formatAvatarMinutesDate, s as formatAvatarRetryTime, m as useAvatarCopy };
|
|
@@ -100,7 +100,9 @@ import { AssistantModeConfig } from './conversation';
|
|
|
100
100
|
* runtime graph is a handful of modules: data tables and the pure mode-id and
|
|
101
101
|
* mode-capability checks, plus `i18n.tsx` for
|
|
102
102
|
* `assistantTranslationKey` and the I18n and product providers that module
|
|
103
|
-
* brings
|
|
103
|
+
* brings, and `avatar/useAvatarCopy.ts` for the one table of "How avatar
|
|
104
|
+
* credits are counted" (BOFF-9446), which needs nothing more. Its one package
|
|
105
|
+
* is `react`, which every app already has, and it
|
|
104
106
|
* loads under plain `bun`; the test walks the graph so no UI module or other
|
|
105
107
|
* package joins it unnoticed.
|
|
106
108
|
*
|
|
@@ -235,6 +237,7 @@ export declare const ASSISTANT_I18N_LITERAL_COPY: {
|
|
|
235
237
|
readonly 'avatar.askNeedsAvatar': "Turn on the avatar to send your question. You can type it now.";
|
|
236
238
|
readonly 'avatar.askNeedsVoice': "You can still turn the avatar on, but you ask it questions in a voice conversation.";
|
|
237
239
|
readonly 'avatar.askNoFiles': "To attach files, use Chat.";
|
|
240
|
+
readonly 'avatar.askNoMinutes': "You can send your question when avatar credits are available.";
|
|
238
241
|
readonly 'avatar.askNotHeard': "This answer wasn't read aloud: the avatar may still have been finishing the last answer.";
|
|
239
242
|
readonly 'avatar.askNotSpoken': "The avatar wasn't available, so this answer wasn't read aloud.";
|
|
240
243
|
readonly 'avatar.askNothing': "You can't ask the avatar anything in this conversation.";
|
|
@@ -259,6 +262,23 @@ export declare const ASSISTANT_I18N_LITERAL_COPY: {
|
|
|
259
262
|
readonly 'avatar.consentCancel': "Not now";
|
|
260
263
|
readonly 'avatar.consentConfirm': "Turn on the avatar";
|
|
261
264
|
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.";
|
|
265
|
+
readonly 'avatar.minutes.askAdmin': "Ask your billing administrator about a plan with more avatar credits.";
|
|
266
|
+
readonly 'avatar.minutes.assignPlan': "Assign your new plan to this workspace in Billing to use its credits.";
|
|
267
|
+
readonly 'avatar.minutes.checkAgain': "Check again";
|
|
268
|
+
readonly 'avatar.minutes.checking': "Checking…";
|
|
269
|
+
readonly 'avatar.minutes.checkingPlan': "Checking your plan…";
|
|
270
|
+
readonly 'avatar.minutes.ended': "The avatar stopped because this workspace’s avatar credits ran out. Continuing with voice only.";
|
|
271
|
+
readonly 'avatar.minutes.endedNoVoice': "The avatar stopped because this workspace’s avatar credits ran out.";
|
|
272
|
+
readonly 'avatar.minutes.freePerMonth': "Free avatar credits each month: {{count}}";
|
|
273
|
+
readonly 'avatar.minutes.freePerPerson': "Free avatar credits per person each month: {{count}}";
|
|
274
|
+
readonly 'avatar.minutes.left': "Avatar credits left: {{count}}";
|
|
275
|
+
readonly 'avatar.minutes.low': "Avatar credits are running low. The avatar stops when they run out.";
|
|
276
|
+
readonly 'avatar.minutes.noFree': "No free avatar credits are included.";
|
|
277
|
+
readonly 'avatar.minutes.planPerMonth': "Avatar credits from paid plans each month: {{count}}";
|
|
278
|
+
readonly 'avatar.minutes.resetsOn': "Avatar credits reset on {{date}} (UTC).";
|
|
279
|
+
readonly 'avatar.minutes.seePlans': "See plans";
|
|
280
|
+
readonly 'avatar.minutes.sessionLeft': "Minutes left in this session: about {{count}}";
|
|
281
|
+
readonly 'avatar.minutes.shared': "Everyone in this workspace shares these credits.";
|
|
262
282
|
readonly 'avatar.problemAlreadyRunning': "An avatar is already running for you.";
|
|
263
283
|
readonly 'avatar.problemBudgetExhausted': "Avatar time is used up for now.";
|
|
264
284
|
readonly 'avatar.problemBudgetExhaustedEveryone': "Avatar time is used up for everyone for now.";
|
|
@@ -267,6 +287,17 @@ export declare const ASSISTANT_I18N_LITERAL_COPY: {
|
|
|
267
287
|
readonly 'avatar.problemCapacity': "Avatars are busy right now. Try again in a moment.";
|
|
268
288
|
readonly 'avatar.problemCapacityTimed': "Avatars are busy right now.";
|
|
269
289
|
readonly 'avatar.problemConnection': "The connection to the avatar was lost.";
|
|
290
|
+
readonly 'avatar.problemMinutesExhausted': "No avatar credits left in this workspace.";
|
|
291
|
+
readonly 'avatar.problemMinutesExhaustedUntil': "No avatar credits left in this workspace. They come back on {{date}} (UTC).";
|
|
292
|
+
readonly 'avatar.problemMinutesFreeCeiling': "You’ve used your free avatar credits for this month.";
|
|
293
|
+
readonly 'avatar.problemMinutesInUse': "Avatar credits are in use in another session. Try again when it ends.";
|
|
294
|
+
readonly 'avatar.problemMinutesInUseSelf': "Your avatar is still running on another device. End it there, or try again when it ends.";
|
|
295
|
+
readonly 'avatar.problemMinutesInUseSelfTimed': "Your avatar is still running on another device. End it there.";
|
|
296
|
+
readonly 'avatar.problemMinutesInUseTimed': "Avatar credits are in use in another session.";
|
|
297
|
+
readonly 'avatar.problemMinutesNotIncluded': "Avatar credits aren’t included for this workspace.";
|
|
298
|
+
readonly 'avatar.problemMinutesUnavailable': "Avatar credits can’t be checked right now. Try again in a moment.";
|
|
299
|
+
readonly 'avatar.problemMinutesUnavailableTimed': "Avatar credits can’t be checked right now.";
|
|
300
|
+
readonly 'avatar.problemMinutesZeroSessionLimit': "You’ve started too many short avatar sessions today.";
|
|
270
301
|
readonly 'avatar.problemNeedsHostedVoice': "The avatar needs one of the assistant’s own voices. Choose one in the voice settings.";
|
|
271
302
|
readonly 'avatar.problemNotReady': "This avatar isn’t ready yet. Try another one.";
|
|
272
303
|
readonly 'avatar.problemPaused': "Avatars are paused for now.";
|
|
@@ -7,11 +7,12 @@ import { INCOMPLETE_TURN_NOTICES as a } from "./streamBudget.js";
|
|
|
7
7
|
import { STAGE_COPY as o, THINKING_PHRASES as s } from "./stageCopy.js";
|
|
8
8
|
import { VOICE_MUTED_LABEL as c, VOICE_THINKING_LABEL as l } from "./voice/voiceStatus.js";
|
|
9
9
|
import { ATTACHMENT_SOURCES as u } from "./attachmentSources.js";
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
10
|
+
import { AVATAR_MINUTES_HOW_COUNTED as d } from "./avatar/useAvatarCopy.js";
|
|
11
|
+
import { assistantProductCopyEntries as f } from "./productCopy.js";
|
|
12
|
+
import { WRITE_PROPOSAL_ERROR_COPY as p } from "./writeProposalErrorCopy.js";
|
|
13
|
+
import { WRITE_PROPOSAL_VOICE_COPY as m } from "./writeProposalVoice.js";
|
|
13
14
|
//#region src/shared/assistant/i18nManifest.ts
|
|
14
|
-
var
|
|
15
|
+
var h = {
|
|
15
16
|
"apiCalls.consentBody": "In Take action mode the assistant can read AND change your data — creating records, logging activity, updating details, and more, on your behalf.",
|
|
16
17
|
"apiCalls.consentBody2": "It will describe what it is about to do and ask you to confirm before making a change. Only continue if you want the assistant to take actions for you.",
|
|
17
18
|
"apiCalls.consentCancel": "Stay in Ask",
|
|
@@ -129,6 +130,7 @@ var m = {
|
|
|
129
130
|
"avatar.askNeedsAvatar": "Turn on the avatar to send your question. You can type it now.",
|
|
130
131
|
"avatar.askNeedsVoice": "You can still turn the avatar on, but you ask it questions in a voice conversation.",
|
|
131
132
|
"avatar.askNoFiles": "To attach files, use Chat.",
|
|
133
|
+
"avatar.askNoMinutes": "You can send your question when avatar credits are available.",
|
|
132
134
|
"avatar.askNotHeard": "This answer wasn't read aloud: the avatar may still have been finishing the last answer.",
|
|
133
135
|
"avatar.askNotSpoken": "The avatar wasn't available, so this answer wasn't read aloud.",
|
|
134
136
|
"avatar.askNothing": "You can't ask the avatar anything in this conversation.",
|
|
@@ -153,6 +155,23 @@ var m = {
|
|
|
153
155
|
"avatar.consentCancel": "Not now",
|
|
154
156
|
"avatar.consentConfirm": "Turn on the avatar",
|
|
155
157
|
"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.",
|
|
158
|
+
"avatar.minutes.askAdmin": "Ask your billing administrator about a plan with more avatar credits.",
|
|
159
|
+
"avatar.minutes.assignPlan": "Assign your new plan to this workspace in Billing to use its credits.",
|
|
160
|
+
"avatar.minutes.checkAgain": "Check again",
|
|
161
|
+
"avatar.minutes.checking": "Checking…",
|
|
162
|
+
"avatar.minutes.checkingPlan": "Checking your plan…",
|
|
163
|
+
"avatar.minutes.ended": "The avatar stopped because this workspace’s avatar credits ran out. Continuing with voice only.",
|
|
164
|
+
"avatar.minutes.endedNoVoice": "The avatar stopped because this workspace’s avatar credits ran out.",
|
|
165
|
+
"avatar.minutes.freePerMonth": "Free avatar credits each month: {{count}}",
|
|
166
|
+
"avatar.minutes.freePerPerson": "Free avatar credits per person each month: {{count}}",
|
|
167
|
+
"avatar.minutes.left": "Avatar credits left: {{count}}",
|
|
168
|
+
"avatar.minutes.low": "Avatar credits are running low. The avatar stops when they run out.",
|
|
169
|
+
"avatar.minutes.noFree": "No free avatar credits are included.",
|
|
170
|
+
"avatar.minutes.planPerMonth": "Avatar credits from paid plans each month: {{count}}",
|
|
171
|
+
"avatar.minutes.resetsOn": "Avatar credits reset on {{date}} (UTC).",
|
|
172
|
+
"avatar.minutes.seePlans": "See plans",
|
|
173
|
+
"avatar.minutes.sessionLeft": "Minutes left in this session: about {{count}}",
|
|
174
|
+
"avatar.minutes.shared": "Everyone in this workspace shares these credits.",
|
|
156
175
|
"avatar.problemAlreadyRunning": "An avatar is already running for you.",
|
|
157
176
|
"avatar.problemBudgetExhausted": "Avatar time is used up for now.",
|
|
158
177
|
"avatar.problemBudgetExhaustedEveryone": "Avatar time is used up for everyone for now.",
|
|
@@ -161,6 +180,17 @@ var m = {
|
|
|
161
180
|
"avatar.problemCapacity": "Avatars are busy right now. Try again in a moment.",
|
|
162
181
|
"avatar.problemCapacityTimed": "Avatars are busy right now.",
|
|
163
182
|
"avatar.problemConnection": "The connection to the avatar was lost.",
|
|
183
|
+
"avatar.problemMinutesExhausted": "No avatar credits left in this workspace.",
|
|
184
|
+
"avatar.problemMinutesExhaustedUntil": "No avatar credits left in this workspace. They come back on {{date}} (UTC).",
|
|
185
|
+
"avatar.problemMinutesFreeCeiling": "You’ve used your free avatar credits for this month.",
|
|
186
|
+
"avatar.problemMinutesInUse": "Avatar credits are in use in another session. Try again when it ends.",
|
|
187
|
+
"avatar.problemMinutesInUseSelf": "Your avatar is still running on another device. End it there, or try again when it ends.",
|
|
188
|
+
"avatar.problemMinutesInUseSelfTimed": "Your avatar is still running on another device. End it there.",
|
|
189
|
+
"avatar.problemMinutesInUseTimed": "Avatar credits are in use in another session.",
|
|
190
|
+
"avatar.problemMinutesNotIncluded": "Avatar credits aren’t included for this workspace.",
|
|
191
|
+
"avatar.problemMinutesUnavailable": "Avatar credits can’t be checked right now. Try again in a moment.",
|
|
192
|
+
"avatar.problemMinutesUnavailableTimed": "Avatar credits can’t be checked right now.",
|
|
193
|
+
"avatar.problemMinutesZeroSessionLimit": "You’ve started too many short avatar sessions today.",
|
|
164
194
|
"avatar.problemNeedsHostedVoice": "The avatar needs one of the assistant’s own voices. Choose one in the voice settings.",
|
|
165
195
|
"avatar.problemNotReady": "This avatar isn’t ready yet. Try another one.",
|
|
166
196
|
"avatar.problemPaused": "Avatars are paused for now.",
|
|
@@ -542,34 +572,35 @@ var m = {
|
|
|
542
572
|
"writeProposal.values": "Values",
|
|
543
573
|
"writeProposal.variablesOmitted": "{{count}} more values not shown",
|
|
544
574
|
"writeProposal.waitForTurn": "You can confirm once the assistant finishes replying."
|
|
545
|
-
},
|
|
546
|
-
...
|
|
547
|
-
...
|
|
548
|
-
...
|
|
549
|
-
...
|
|
550
|
-
...
|
|
551
|
-
...
|
|
552
|
-
...
|
|
553
|
-
...
|
|
575
|
+
}, g = (e) => Object.fromEntries(e.map((e) => [e.key, e.fallback])), _ = Object.freeze({
|
|
576
|
+
...g(Object.values(o)),
|
|
577
|
+
...g(s),
|
|
578
|
+
...g([l, c]),
|
|
579
|
+
...g(a),
|
|
580
|
+
...g(Object.values(i)),
|
|
581
|
+
...g(Object.values(r)),
|
|
582
|
+
...g(Object.values(p)),
|
|
583
|
+
...g(Object.values(m)),
|
|
584
|
+
...g(Object.values(d)),
|
|
554
585
|
...Object.fromEntries(u.map((e) => [e.labelKey, e.labelFallback]))
|
|
555
|
-
}),
|
|
586
|
+
}), v = Object.freeze({
|
|
556
587
|
"attachments.retrying": "Retrying {{attempt}} of {{max}}",
|
|
557
588
|
"attachments.waking": "File service is starting up — retry {{attempt}} of {{max}}",
|
|
558
589
|
"outcome.usageDailyLimitReachedNoTime": "You've reached today's AI assistant limit. Try again tomorrow."
|
|
559
|
-
}),
|
|
560
|
-
...
|
|
561
|
-
...
|
|
562
|
-
...
|
|
590
|
+
}), y = Object.freeze({
|
|
591
|
+
...h,
|
|
592
|
+
..._,
|
|
593
|
+
...v
|
|
563
594
|
});
|
|
564
|
-
function
|
|
595
|
+
function b(e) {
|
|
565
596
|
let r = e.map((e) => e.id).filter((e) => !n(e));
|
|
566
597
|
if (r.length > 0) throw Error(`assistantModeI18nCopy: malformed mode id ${r.map((e) => JSON.stringify(e)).join(", ")}. Declare product modes with declareAssistantMode().`);
|
|
567
598
|
return Object.fromEntries(e.map((e) => [`mode.${e.id}`, e.label || t(e)]));
|
|
568
599
|
}
|
|
569
|
-
function
|
|
600
|
+
function x(t) {
|
|
570
601
|
let n = {
|
|
571
|
-
...
|
|
572
|
-
...
|
|
602
|
+
...y,
|
|
603
|
+
...b(t.modes)
|
|
573
604
|
}, r = Object.entries(t.overrides ?? {}), i = r.filter(([e]) => !Object.hasOwn(n, e)).map(([e]) => e);
|
|
574
605
|
if (i.length > 0) throw Error(`assistantI18nSeedCopy: no shared assistant key ${i.join(", ")} to override. Check the spelling, or that the key is a mode this product offers; a key fe-libs no longer requests belongs with the product's own keys.`);
|
|
575
606
|
let a = r.filter(([, e]) => e.trim() === "").map(([e]) => e);
|
|
@@ -577,7 +608,7 @@ function b(t) {
|
|
|
577
608
|
let o = {
|
|
578
609
|
...n,
|
|
579
610
|
...Object.fromEntries(r),
|
|
580
|
-
...
|
|
611
|
+
...f({
|
|
581
612
|
modes: t.modes,
|
|
582
613
|
pageLabels: t.pageLabels
|
|
583
614
|
})
|
|
@@ -585,4 +616,4 @@ function b(t) {
|
|
|
585
616
|
return Object.fromEntries(Object.entries(o).map(([n, r]) => [e(t.namespace, n), r]));
|
|
586
617
|
}
|
|
587
618
|
//#endregion
|
|
588
|
-
export {
|
|
619
|
+
export { _ as ASSISTANT_I18N_COMPUTED_COPY, h as ASSISTANT_I18N_LITERAL_COPY, y as ASSISTANT_I18N_MANIFEST, v as ASSISTANT_I18N_SEED_COMPAT_COPY, x as assistantI18nSeedCopy, b as assistantModeI18nCopy };
|
|
@@ -345,6 +345,8 @@ export * from './avatar/live/LiveAvatarTabView';
|
|
|
345
345
|
export * from './avatar/live/avatarFaces';
|
|
346
346
|
export * from './avatar/live/AvatarFace';
|
|
347
347
|
export * from './avatar/live/liveAvatarStatus';
|
|
348
|
+
export * from './avatar/live/liveAvatarMinutesView';
|
|
349
|
+
export * from './avatar/live/LiveAvatarMinutes';
|
|
348
350
|
export * from './avatar/live/createLiveAvatarSeam';
|
|
349
351
|
export * from './avatar/live/avatarVoice';
|
|
350
352
|
export * from './promptDelivery';
|
|
@@ -31,10 +31,10 @@ import { resolveAssistantLanguage as $e } from "../voice/languages.js";
|
|
|
31
31
|
import { resolveLanguagePair as et } from "../voice/languagePair.js";
|
|
32
32
|
import { INITIAL_TRANSCRIPT_AUTO_OPEN as tt, isAwaitingOwnConversation as nt, maySendSpokenTurn as C, planTranscriptAutoOpen as rt, planVoiceSessionBinding as it, planVoiceSessionStart as at, planVoiceSpokenEntry as ot, voiceBindingAtStart as st, voiceBindingConversationId as ct } from "../voice/voiceReopen.js";
|
|
33
33
|
import { countInlineImageCandidates as lt, countInlinedImageParts as ut, largestInlineCharsPerFile as dt, resolveAssistantInlineLimits as ft, toMessageAttachment as pt } from "../attachments.js";
|
|
34
|
-
import {
|
|
35
|
-
import {
|
|
36
|
-
import {
|
|
37
|
-
import {
|
|
34
|
+
import { useAvatarCopy as mt } from "../avatar/useAvatarCopy.js";
|
|
35
|
+
import { WRITE_PROPOSAL_VOICE_COPY as ht, isVoiceProposalBound as gt, voiceProposalChip as _t, voiceProposalChipText as vt, voiceReadbacksDue as yt, voiceWaitingProposals as bt, writeProposalVoiceLine as xt, writeProposalVoiceReadback as St } from "../writeProposalVoice.js";
|
|
36
|
+
import { createAdminModeAccessGate as Ct, resolveAssistantSendModeAfterAccess as wt } from "../adminModeSendGate.js";
|
|
37
|
+
import { buildBoundedAttachmentTurn as Tt } from "../attachmentTurn.js";
|
|
38
38
|
import { attachmentUrlIsStale as Et, refreshStaleAttachmentUrls as Dt } from "../attachmentCommit.js";
|
|
39
39
|
import { VOICE_COMMIT_BUDGET_MS as Ot, settleAndCommitSpokenTurn as kt } from "../voiceCommit.js";
|
|
40
40
|
import { getOrganizationId as At, getWorkspaceId as w } from "../context.js";
|
|
@@ -126,7 +126,7 @@ function M() {
|
|
|
126
126
|
var Ei = () => () => {}, Di = () => "off", Oi = ({ visible: Oi = !0, writeAccess: ki = "unknown" }) => {
|
|
127
127
|
let N = a(), { product: P, modes: F, gatherPageContext: Ai, buildPrompt: ji, reportTurnTimings: Mi, reportTokenUsage: Ni, localUiCommands: Pi } = i(), I = De(i().writeApproval), Fi = E((e, t) => {
|
|
128
128
|
let n = _.getState(), r = t ?? n.sandboxesByMode[e]?.sandboxId ?? null;
|
|
129
|
-
return
|
|
129
|
+
return gt({
|
|
130
130
|
mode: e,
|
|
131
131
|
productWriteApproval: I,
|
|
132
132
|
capabilities: r ? n.sandboxWriteCapabilities[r] : null
|
|
@@ -158,7 +158,7 @@ var Ei = () => () => {}, Di = () => "off", Oi = ({ visible: Oi = !0, writeAccess
|
|
|
158
158
|
let e = window.setTimeout(() => Ma(Na), Ci);
|
|
159
159
|
return () => window.clearTimeout(e);
|
|
160
160
|
}, [Na]);
|
|
161
|
-
let { canUseApiCalls: Pa, loading: Fa } = _r(w(), R), Ia = k(
|
|
161
|
+
let { canUseApiCalls: Pa, loading: Fa } = _r(w(), R), Ia = k(Ct({
|
|
162
162
|
loading: Fa,
|
|
163
163
|
canUseAdminModes: Pa
|
|
164
164
|
})).current, La = k(F);
|
|
@@ -223,7 +223,7 @@ var Ei = () => () => {}, Di = () => "off", Oi = ({ visible: Oi = !0, writeAccess
|
|
|
223
223
|
}, [W]), fo = k({}), q = k(Sn()), J = k(new wr()), po = k(/* @__PURE__ */ new Set()), mo = O(() => F.find((e) => e.id === V), [F, V]), ho = _((e) => {
|
|
224
224
|
let t = e.sandboxesByMode[V]?.sandboxId;
|
|
225
225
|
return t ? e.sandboxWriteCapabilities[t] : void 0;
|
|
226
|
-
}), go = mo !== void 0 &&
|
|
226
|
+
}), go = mo !== void 0 && gt({
|
|
227
227
|
mode: V,
|
|
228
228
|
productWriteApproval: I,
|
|
229
229
|
capabilities: ho
|
|
@@ -1601,7 +1601,7 @@ var Ei = () => () => {}, Di = () => "off", Oi = ({ visible: Oi = !0, writeAccess
|
|
|
1601
1601
|
conversationId: v,
|
|
1602
1602
|
writeReply: ce === "proposal-v1" ? n.writeReplyBound?.writeReply ?? null : null,
|
|
1603
1603
|
...ue ? { uiCatalogue: ue } : {}
|
|
1604
|
-
}, { prompt: me, parts: he } =
|
|
1604
|
+
}, { prompt: me, parts: he } = Tt({
|
|
1605
1605
|
content: ie ? `${ie}${ae}` : ae,
|
|
1606
1606
|
attachments: t,
|
|
1607
1607
|
limits: ft(le),
|
|
@@ -1756,7 +1756,7 @@ var Ei = () => () => {}, Di = () => "off", Oi = ({ visible: Oi = !0, writeAccess
|
|
|
1756
1756
|
code: "UNAUTHENTICATED",
|
|
1757
1757
|
authFailure: "WORKSPACE_CONTEXT_MISSING"
|
|
1758
1758
|
} });
|
|
1759
|
-
let e = await
|
|
1759
|
+
let e = await wt(g, () => La.current.find((e) => e.id === g), Ia);
|
|
1760
1760
|
le = e.config, fe = e.capabilities;
|
|
1761
1761
|
let t = le, n = Ae();
|
|
1762
1762
|
if (n.abandon) {
|
|
@@ -2052,7 +2052,7 @@ var Ei = () => () => {}, Di = () => "off", Oi = ({ visible: Oi = !0, writeAccess
|
|
|
2052
2052
|
D(() => {
|
|
2053
2053
|
ws.current = rc;
|
|
2054
2054
|
}, [rc]);
|
|
2055
|
-
let ic = $.active, ac = O(() =>
|
|
2055
|
+
let ic = $.active, ac = O(() => bt(Object.values(xa), B, Sa), [
|
|
2056
2056
|
xa,
|
|
2057
2057
|
B,
|
|
2058
2058
|
Sa
|
|
@@ -2073,7 +2073,7 @@ var Ei = () => () => {}, Di = () => "off", Oi = ({ visible: Oi = !0, writeAccess
|
|
|
2073
2073
|
ac,
|
|
2074
2074
|
ba,
|
|
2075
2075
|
cc
|
|
2076
|
-
]), uc = ic ?
|
|
2076
|
+
]), uc = ic ? _t(ac) : null, dc = oc ? xa[oc] : void 0, fc = ic && dc && dc.session.conversationId === B ? {
|
|
2077
2077
|
content: /* @__PURE__ */ j(kn, {
|
|
2078
2078
|
refs: [{
|
|
2079
2079
|
proposalId: dc.view.proposalId,
|
|
@@ -2089,7 +2089,7 @@ var Ei = () => () => {}, Di = () => "off", Oi = ({ visible: Oi = !0, writeAccess
|
|
|
2089
2089
|
onReview: cc,
|
|
2090
2090
|
retiredSandboxes: Sa
|
|
2091
2091
|
}),
|
|
2092
|
-
closeLabel:
|
|
2092
|
+
closeLabel: xt(N, ht.trayClose),
|
|
2093
2093
|
onClose: () => sc(null)
|
|
2094
2094
|
} : null, pc = Ca.asking, mc = xs?.asking === !0, hc = Ss?.asking === !0, gc = er(), _c = $.holdListening;
|
|
2095
2095
|
r("assistant.transcript", O(() => ic || K ? null : { run: () => to ? { status: "already" } : (ao(!0), { status: "done" }) }, [
|
|
@@ -2121,15 +2121,15 @@ var Ei = () => () => {}, Di = () => "off", Oi = ({ visible: Oi = !0, writeAccess
|
|
|
2121
2121
|
vc.current = new Set(Object.keys(xa));
|
|
2122
2122
|
return;
|
|
2123
2123
|
}
|
|
2124
|
-
for (let { view: t, session: n } of
|
|
2124
|
+
for (let { view: t, session: n } of yt(ac, e)) {
|
|
2125
2125
|
e.add(t.proposalId);
|
|
2126
2126
|
let r = ba[n.sandboxId];
|
|
2127
|
-
if (!
|
|
2127
|
+
if (!gt({
|
|
2128
2128
|
mode: "api-calls",
|
|
2129
2129
|
productWriteApproval: I,
|
|
2130
2130
|
capabilities: r
|
|
2131
2131
|
})) continue;
|
|
2132
|
-
let i =
|
|
2132
|
+
let i = St(t, Tn(t, r).offerConfirm, N), a = t.proposalId;
|
|
2133
2133
|
yc({
|
|
2134
2134
|
id: `write-readback:${a}`,
|
|
2135
2135
|
text: i.text,
|
|
@@ -2221,7 +2221,7 @@ var Ei = () => () => {}, Di = () => "off", Oi = ({ visible: Oi = !0, writeAccess
|
|
|
2221
2221
|
busy: _a || Co !== null || Oa || Qo,
|
|
2222
2222
|
committing: kc.committing,
|
|
2223
2223
|
dictating: kc.dictating
|
|
2224
|
-
}), Mc =
|
|
2224
|
+
}), Mc = mt(), [Nc, Pc] = A(null);
|
|
2225
2225
|
D(() => {
|
|
2226
2226
|
Nc !== null && (!K || Nc.conversationId !== B) && Pc(null);
|
|
2227
2227
|
}, [
|
|
@@ -2587,7 +2587,7 @@ var Ei = () => () => {}, Di = () => "off", Oi = ({ visible: Oi = !0, writeAccess
|
|
|
2587
2587
|
onToggleMute: $.toggleMute,
|
|
2588
2588
|
onEnd: Oc,
|
|
2589
2589
|
proposalChip: uc ? {
|
|
2590
|
-
label:
|
|
2590
|
+
label: vt(uc, N),
|
|
2591
2591
|
onOpen: lc
|
|
2592
2592
|
} : null,
|
|
2593
2593
|
proposalTray: fc,
|
|
@@ -46,8 +46,11 @@ export type AssistantNavigateResult =
|
|
|
46
46
|
* navigator that does not say is treated as the assistant's.
|
|
47
47
|
*/
|
|
48
48
|
export type AssistantNavigateInitiator = NavigationInitiator;
|
|
49
|
-
/**
|
|
50
|
-
|
|
49
|
+
/**
|
|
50
|
+
* Which assistant surface the person tapped; only ever used for counting. `avatar-minutes` (★ BOFF-9446): the Avatar tab's "See plans",
|
|
51
|
+
* for avatar credits.
|
|
52
|
+
*/
|
|
53
|
+
export type AssistantNavigateSurface = 'offer' | 'reply-link' | 'connect-source' | 'avatar-minutes';
|
|
51
54
|
export interface AssistantNavigateContext {
|
|
52
55
|
surface?: AssistantNavigateSurface;
|
|
53
56
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ComponentType, FC, ReactNode, RefObject } from 'react';
|
|
2
2
|
import { SpeechEngine } from '../speech/types';
|
|
3
|
+
import { AssistantNavigate } from './AssistantMarkdownRenderer';
|
|
3
4
|
import { VoiceView } from './voice/AssistantVoiceSession';
|
|
4
5
|
export interface LiveAvatarStageProps {
|
|
5
6
|
/** Full-screen (true) or the in-panel stage (false). */
|
|
@@ -33,15 +34,16 @@ export interface AssistantLiveAvatarSeam {
|
|
|
33
34
|
/** Whether the Avatar tab may be offered, as a store read with `useSyncExternalStore`. STABLE. */
|
|
34
35
|
export interface LiveAvatarTabOfferedStore {
|
|
35
36
|
subscribe: (onChange: () => void) => () => void;
|
|
36
|
-
/** This browser can show the avatar (
|
|
37
|
+
/** This browser can show the avatar (any browser or phone with what it needs), and it was not refused on this page. */
|
|
37
38
|
getSnapshot: () => boolean;
|
|
38
39
|
}
|
|
39
40
|
/**
|
|
40
41
|
* ★ BOFF-9360: whether the avatar can take the answer to a typed question now (`liveAvatarAskState` maps the
|
|
41
42
|
* controller's snapshot): `ready`; `sound-blocked` (on, its sound blocked until a tap); `ending` (stopping, or near its
|
|
42
|
-
* time limit); `starting`; `locked` (off until the time a refusal named); `off
|
|
43
|
+
* time limit); `starting`; `locked` (off until the time a refusal named); `no-minutes` (★ BOFF-9446: off, and Turn on
|
|
44
|
+
* cannot start it for avatar credits: none left for this person); `off`.
|
|
43
45
|
*/
|
|
44
|
-
export type LiveAvatarAskState = 'off' | 'locked' | 'starting' | 'ready' | 'sound-blocked' | 'ending';
|
|
46
|
+
export type LiveAvatarAskState = 'off' | 'locked' | 'no-minutes' | 'starting' | 'ready' | 'sound-blocked' | 'ending';
|
|
45
47
|
/** `LiveAvatarAskState` as a store read with `useSyncExternalStore`. STABLE. */
|
|
46
48
|
export interface LiveAvatarAskStore {
|
|
47
49
|
subscribe: (onChange: () => void) => () => void;
|
|
@@ -118,6 +120,12 @@ export interface LiveAvatarTabProps {
|
|
|
118
120
|
* `voice.impossible` alone ("…you ask it questions in a voice conversation").
|
|
119
121
|
*/
|
|
120
122
|
readonly askLine?: LiveAvatarTabAskLine;
|
|
123
|
+
/**
|
|
124
|
+
* ★ BOFF-9446: the panel's navigator (the host's `onNavigate`, behind the leave-page guard): the tab's "See plans" opens the app's
|
|
125
|
+
* plans page with it, as the person's own navigation, and never changes the page's location itself. Absent or null: no navigation,
|
|
126
|
+
* so nothing offers to open billing.
|
|
127
|
+
*/
|
|
128
|
+
readonly navigate?: AssistantNavigate | null;
|
|
121
129
|
}
|
|
122
130
|
/** The ids the tab row and the two tab panels share (`AIAssistantPanel` makes them). */
|
|
123
131
|
export interface LiveAvatarTabIds {
|