@burdenoff/fe-libs 2026.913.1 → 2026.914.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/conversation.d.ts +29 -0
- package/dist/shared/assistant/conversation.d.ts.map +1 -1
- package/dist/shared/assistant/displayContent.d.ts +57 -0
- package/dist/shared/assistant/displayContent.d.ts.map +1 -0
- package/dist/shared/assistant/displayContent.js +26 -0
- package/dist/shared/assistant/exportConversation.d.ts +12 -2
- package/dist/shared/assistant/exportConversation.d.ts.map +1 -1
- package/dist/shared/assistant/exportConversation.js +24 -22
- package/dist/shared/assistant/index.d.ts +9 -0
- package/dist/shared/assistant/index.d.ts.map +1 -1
- package/dist/shared/assistant/legacyFiller.d.ts +60 -0
- package/dist/shared/assistant/legacyFiller.d.ts.map +1 -0
- package/dist/shared/assistant/legacyFiller.js +35 -0
- package/dist/shared/assistant/preview/previewTransitions.d.ts +15 -1
- package/dist/shared/assistant/preview/previewTransitions.d.ts.map +1 -1
- package/dist/shared/assistant/preview/previewTransitions.js +5 -2
- package/dist/shared/assistant/preview/useAssistantPreviewBridge.d.ts.map +1 -1
- package/dist/shared/assistant/preview/useAssistantPreviewBridge.js +51 -52
- package/dist/shared/assistant/spokenTurns.d.ts +25 -0
- package/dist/shared/assistant/spokenTurns.d.ts.map +1 -0
- package/dist/shared/assistant/spokenTurns.js +12 -0
- package/dist/shared/assistant/stageCopy.d.ts +23 -34
- package/dist/shared/assistant/stageCopy.d.ts.map +1 -1
- package/dist/shared/assistant/stageCopy.js +7 -16
- package/dist/shared/assistant/store.d.ts +10 -2
- package/dist/shared/assistant/store.d.ts.map +1 -1
- package/dist/shared/assistant/store.js +16 -9
- package/dist/shared/assistant/turnActivity.d.ts +66 -0
- package/dist/shared/assistant/turnActivity.d.ts.map +1 -0
- package/dist/shared/assistant/turnActivity.js +41 -0
- package/dist/shared/assistant/turnProgress.d.ts +51 -0
- package/dist/shared/assistant/turnProgress.d.ts.map +1 -0
- package/dist/shared/assistant/turnProgress.js +27 -0
- package/dist/shared/assistant/ui/AssistantChatArea.d.ts.map +1 -1
- package/dist/shared/assistant/ui/AssistantChatArea.js +362 -379
- package/dist/shared/assistant/ui/AssistantConversationList.d.ts.map +1 -1
- package/dist/shared/assistant/ui/AssistantConversationList.js +81 -80
- package/dist/shared/assistant/ui/AssistantMessageItem.d.ts +12 -1
- package/dist/shared/assistant/ui/AssistantMessageItem.d.ts.map +1 -1
- package/dist/shared/assistant/ui/AssistantMessageItem.js +103 -83
- package/dist/shared/assistant/ui/AssistantMessageList.d.ts +7 -1
- package/dist/shared/assistant/ui/AssistantMessageList.d.ts.map +1 -1
- package/dist/shared/assistant/ui/AssistantMessageList.js +16 -15
- package/dist/shared/assistant/ui/AssistantMoreMenu.d.ts.map +1 -1
- package/dist/shared/assistant/ui/AssistantMoreMenu.js +23 -20
- package/dist/shared/assistant/ui/AssistantTurnActivity.d.ts +37 -0
- package/dist/shared/assistant/ui/AssistantTurnActivity.d.ts.map +1 -0
- package/dist/shared/assistant/ui/AssistantTurnActivity.js +33 -0
- package/dist/shared/assistant/ui/voice/AssistantVoiceSession.d.ts.map +1 -1
- package/dist/shared/assistant/ui/voice/AssistantVoiceSession.js +112 -102
- package/dist/shared/assistant/ui/voice/VoiceMiniController.d.ts +10 -0
- package/dist/shared/assistant/ui/voice/VoiceMiniController.d.ts.map +1 -1
- package/dist/shared/assistant/ui/voice/VoiceMiniController.js +29 -28
- package/dist/shared/assistant/ui/voice/VoiceStage.d.ts +10 -0
- package/dist/shared/assistant/ui/voice/VoiceStage.d.ts.map +1 -1
- package/dist/shared/assistant/ui/voice/VoiceStage.js +35 -34
- package/dist/shared/assistant/ui/voice/VoiceStatusText.d.ts +51 -0
- package/dist/shared/assistant/ui/voice/VoiceStatusText.d.ts.map +1 -0
- package/dist/shared/assistant/ui/voice/VoiceStatusText.js +42 -0
- package/dist/shared/assistant/voice/rotationClock.d.ts +31 -0
- package/dist/shared/assistant/voice/rotationClock.d.ts.map +1 -0
- package/dist/shared/assistant/voice/rotationClock.js +27 -0
- package/dist/shared/assistant/voice/voiceStatus.d.ts +81 -0
- package/dist/shared/assistant/voice/voiceStatus.d.ts.map +1 -0
- package/dist/shared/assistant/voice/voiceStatus.js +33 -0
- package/dist/shared-assistant.js +94 -85
- package/package.json +1 -1
|
@@ -3,36 +3,37 @@ import { AssistantMessageItem as t } from "./AssistantMessageItem.js";
|
|
|
3
3
|
import { useEffect as n, useRef as r } from "react";
|
|
4
4
|
import { jsx as i, jsxs as a } from "react/jsx-runtime";
|
|
5
5
|
//#region src/shared/assistant/ui/AssistantMessageList.tsx
|
|
6
|
-
var o = ({ onApprovePendingWrite: o, approvingWriteRef: s = null, messages: c,
|
|
7
|
-
let
|
|
6
|
+
var o = ({ onApprovePendingWrite: o, approvingWriteRef: s = null, messages: c, processing: l, streamingMessageId: u, failedMessageId: d, onRetry: f }) => {
|
|
7
|
+
let p = e(), m = (() => {
|
|
8
8
|
for (let e = c.length - 1; e >= 0; --e) if (c[e].role === "assistant") return c[e].id;
|
|
9
9
|
return null;
|
|
10
|
-
})(),
|
|
10
|
+
})(), h = r(null), g = r(null);
|
|
11
11
|
return n(() => {
|
|
12
|
-
let e =
|
|
12
|
+
let e = g.current;
|
|
13
13
|
if (e && e.scrollHeight - e.scrollTop - e.clientHeight < 100) {
|
|
14
14
|
let e = typeof window < "u" && window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
|
|
15
|
-
|
|
15
|
+
h.current?.scrollIntoView({ behavior: e ? "auto" : "smooth" });
|
|
16
16
|
}
|
|
17
|
-
}, [c,
|
|
18
|
-
|
|
17
|
+
}, [c, u]), n(() => {
|
|
18
|
+
h.current?.scrollIntoView({ behavior: "instant" });
|
|
19
19
|
}, []), /* @__PURE__ */ a("div", {
|
|
20
|
-
ref:
|
|
20
|
+
ref: g,
|
|
21
21
|
className: "flex-1 space-y-4 overflow-y-auto p-3",
|
|
22
22
|
role: "log",
|
|
23
23
|
"aria-live": "polite",
|
|
24
24
|
"aria-relevant": "additions",
|
|
25
|
-
"aria-busy":
|
|
26
|
-
"aria-label":
|
|
25
|
+
"aria-busy": u !== null,
|
|
26
|
+
"aria-label": p("messageList.ariaLabel", "Conversation messages"),
|
|
27
27
|
children: [c.map((e) => /* @__PURE__ */ i(t, {
|
|
28
28
|
onApprovePendingWrite: o,
|
|
29
29
|
approvingWriteRef: s,
|
|
30
30
|
message: e,
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
processing: l,
|
|
32
|
+
isStreaming: e.id === u,
|
|
33
|
+
isFailed: e.id === d,
|
|
34
|
+
isLastAssistant: e.id === m,
|
|
35
|
+
onRetry: f
|
|
36
|
+
}, e.id)), /* @__PURE__ */ i("div", { ref: h })]
|
|
36
37
|
});
|
|
37
38
|
};
|
|
38
39
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssistantMoreMenu.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/ui/AssistantMoreMenu.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AAiB7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,iBAAiB,EAAE,
|
|
1
|
+
{"version":3,"file":"AssistantMoreMenu.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/ui/AssistantMoreMenu.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AAiB7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,iBAAiB,EAAE,EAqM/B,CAAC"}
|
|
@@ -10,7 +10,7 @@ import { Check as d, FileJson as f, FileText as p, MoreHorizontal as m, Play as
|
|
|
10
10
|
import { Fragment as _, jsx as v, jsxs as y } from "react/jsx-runtime";
|
|
11
11
|
//#region src/shared/assistant/ui/AssistantMoreMenu.tsx
|
|
12
12
|
var b = () => {
|
|
13
|
-
let b = e(), [x, S] = u(!1), C = l(null), w = l(null), { conversations: T, activeConversationId: E } = t(),
|
|
13
|
+
let b = e(), [x, S] = u(!1), C = l(null), w = l(null), { conversations: T, activeConversationId: E, processingByConversationId: D } = t(), O = T.find((e) => e.id === E), k = !!(O && O.messages.length > 0), { isSupported: A, isBlocked: j, disabledReason: M, autoSpeakEnabled: N, setAutoSpeak: P, stop: F, previewVoice: I, activeVoiceName: L } = n(), R = j && !N;
|
|
14
14
|
i(x, C, w, () => S(!1)), c(() => {
|
|
15
15
|
if (!x) return;
|
|
16
16
|
let e = (e) => {
|
|
@@ -21,13 +21,16 @@ var b = () => {
|
|
|
21
21
|
document.removeEventListener("mousedown", e);
|
|
22
22
|
};
|
|
23
23
|
}, [x]);
|
|
24
|
-
let
|
|
25
|
-
if (!
|
|
26
|
-
let { content: t, filename: n, mimeType: r } = s(
|
|
24
|
+
let z = (e) => {
|
|
25
|
+
if (!O) return;
|
|
26
|
+
let { content: t, filename: n, mimeType: r } = s(O, e, {
|
|
27
|
+
processing: D[O.id],
|
|
28
|
+
tr: b
|
|
29
|
+
});
|
|
27
30
|
o(t, n, r), S(!1);
|
|
28
|
-
},
|
|
29
|
-
|
|
30
|
-
},
|
|
31
|
+
}, B = () => {
|
|
32
|
+
N && F(), P(!N);
|
|
33
|
+
}, V = b("header.more", "More options");
|
|
31
34
|
return /* @__PURE__ */ y("div", {
|
|
32
35
|
className: "relative",
|
|
33
36
|
children: [/* @__PURE__ */ v("button", {
|
|
@@ -35,7 +38,7 @@ var b = () => {
|
|
|
35
38
|
type: "button",
|
|
36
39
|
onClick: () => S((e) => !e),
|
|
37
40
|
className: "rounded p-1 transition-colors hover:bg-bg-elevated",
|
|
38
|
-
"aria-label":
|
|
41
|
+
"aria-label": V,
|
|
39
42
|
"aria-haspopup": "menu",
|
|
40
43
|
"aria-expanded": x,
|
|
41
44
|
"data-testid": "assistant-more",
|
|
@@ -43,17 +46,17 @@ var b = () => {
|
|
|
43
46
|
}), x ? /* @__PURE__ */ y("div", {
|
|
44
47
|
ref: C,
|
|
45
48
|
role: "menu",
|
|
46
|
-
"aria-label":
|
|
49
|
+
"aria-label": V,
|
|
47
50
|
className: "absolute right-0 top-full z-50 mt-1 min-w-56 overflow-hidden rounded-xl border border-border-default bg-bg-surface py-1 shadow-lg",
|
|
48
51
|
"data-testid": "assistant-more-menu",
|
|
49
52
|
children: [
|
|
50
|
-
|
|
53
|
+
A ? /* @__PURE__ */ y("button", {
|
|
51
54
|
type: "button",
|
|
52
55
|
role: "menuitemcheckbox",
|
|
53
|
-
"aria-checked":
|
|
54
|
-
onClick:
|
|
55
|
-
disabled:
|
|
56
|
-
title:
|
|
56
|
+
"aria-checked": N,
|
|
57
|
+
onClick: B,
|
|
58
|
+
disabled: R,
|
|
59
|
+
title: R ? M ?? void 0 : void 0,
|
|
57
60
|
className: "flex w-full items-center gap-2.5 px-3 py-2 text-left text-xs text-text-primary transition-colors hover:bg-bg-elevated disabled:cursor-not-allowed disabled:text-text-muted disabled:hover:bg-transparent",
|
|
58
61
|
"data-testid": "assistant-auto-speak",
|
|
59
62
|
children: [
|
|
@@ -65,16 +68,16 @@ var b = () => {
|
|
|
65
68
|
className: "flex-1",
|
|
66
69
|
children: b("header.autoRead", "Auto-read replies")
|
|
67
70
|
}),
|
|
68
|
-
|
|
71
|
+
N ? /* @__PURE__ */ v(d, { className: "size-3.5 flex-shrink-0 text-action-primary-bg" }) : null
|
|
69
72
|
]
|
|
70
73
|
}) : null,
|
|
71
74
|
/* @__PURE__ */ v(r, {}),
|
|
72
75
|
/* @__PURE__ */ y("div", {
|
|
73
76
|
className: "flex items-center gap-1 px-3 py-1.5",
|
|
74
77
|
"data-testid": "assistant-more-voice",
|
|
75
|
-
children: [/* @__PURE__ */ v(a, {}),
|
|
78
|
+
children: [/* @__PURE__ */ v(a, {}), L ? /* @__PURE__ */ y("button", {
|
|
76
79
|
type: "button",
|
|
77
|
-
onClick: () =>
|
|
80
|
+
onClick: () => I(L),
|
|
78
81
|
className: "flex items-center gap-1 rounded-md px-1.5 py-1 text-[11px] text-text-muted transition-colors hover:bg-bg-elevated hover:text-text-secondary focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong",
|
|
79
82
|
"aria-label": b("voice.preview", "Hear this voice"),
|
|
80
83
|
"data-testid": "assistant-voice-preview",
|
|
@@ -84,7 +87,7 @@ var b = () => {
|
|
|
84
87
|
}), b("voice.previewShort", "Preview")]
|
|
85
88
|
}) : null]
|
|
86
89
|
}),
|
|
87
|
-
|
|
90
|
+
k ? /* @__PURE__ */ y(_, { children: [
|
|
88
91
|
/* @__PURE__ */ v("div", {
|
|
89
92
|
className: "my-1 border-t border-border-subtle",
|
|
90
93
|
role: "separator"
|
|
@@ -92,7 +95,7 @@ var b = () => {
|
|
|
92
95
|
/* @__PURE__ */ y("button", {
|
|
93
96
|
type: "button",
|
|
94
97
|
role: "menuitem",
|
|
95
|
-
onClick: () =>
|
|
98
|
+
onClick: () => z("json"),
|
|
96
99
|
className: "flex w-full items-center gap-2.5 px-3 py-2 text-left text-xs text-text-primary transition-colors hover:bg-bg-elevated",
|
|
97
100
|
"data-testid": "export-json",
|
|
98
101
|
children: [/* @__PURE__ */ v(f, {
|
|
@@ -103,7 +106,7 @@ var b = () => {
|
|
|
103
106
|
/* @__PURE__ */ y("button", {
|
|
104
107
|
type: "button",
|
|
105
108
|
role: "menuitem",
|
|
106
|
-
onClick: () =>
|
|
109
|
+
onClick: () => z("markdown"),
|
|
107
110
|
className: "flex w-full items-center gap-2.5 px-3 py-2 text-left text-xs text-text-primary transition-colors hover:bg-bg-elevated",
|
|
108
111
|
"data-testid": "export-markdown",
|
|
109
112
|
children: [/* @__PURE__ */ v(p, {
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
import { AssistantConversationProcessing } from '../conversation';
|
|
3
|
+
/**
|
|
4
|
+
* The waiting line for one turn, as markup.
|
|
5
|
+
*
|
|
6
|
+
* ★ Two spans, like the voice status line: the moving phrase is hidden from
|
|
7
|
+
* assistive tech and the step's label is read instead, so a screen reader
|
|
8
|
+
* browsing the transcript hears "Thinking..." rather than whichever decoration
|
|
9
|
+
* the rotation happened to be on. Neither is a live region — the transcript is
|
|
10
|
+
* `role="log"` and `aria-busy` while a turn runs, which already says so.
|
|
11
|
+
*
|
|
12
|
+
* ★ `relative` contains the `sr-only` span. Without a positioned ancestor its
|
|
13
|
+
* absolute box escapes to the nearest scroll container.
|
|
14
|
+
*
|
|
15
|
+
* Exported separately so the markup can be rendered with different shown and
|
|
16
|
+
* label text; static rendering runs no clock, so the stateful component alone
|
|
17
|
+
* would only ever show the two equal.
|
|
18
|
+
*/
|
|
19
|
+
export declare const TurnActivityLine: FC<{
|
|
20
|
+
shown: string;
|
|
21
|
+
label: string;
|
|
22
|
+
}>;
|
|
23
|
+
/**
|
|
24
|
+
* What a live turn is doing, drawn from its processing state (BOFF-7277).
|
|
25
|
+
*
|
|
26
|
+
* ★★ The clock lives HERE. A tick re-renders only this line, the orchestrator
|
|
27
|
+
* stays free of timers, and nothing is written anywhere — the message's content
|
|
28
|
+
* is untouched while the phrase moves.
|
|
29
|
+
*
|
|
30
|
+
* ★ Under `prefers-reduced-motion` the line holds the step's label instead of
|
|
31
|
+
* rotating: text that changes every few seconds on its own is exactly the kind
|
|
32
|
+
* of movement that preference asks to stop, as the avatar and caret already do.
|
|
33
|
+
*/
|
|
34
|
+
export declare const AssistantTurnActivity: FC<{
|
|
35
|
+
processing: AssistantConversationProcessing | null | undefined;
|
|
36
|
+
}>;
|
|
37
|
+
//# sourceMappingURL=AssistantTurnActivity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AssistantTurnActivity.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/ui/AssistantTurnActivity.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AAGrD,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,iBAAiB,CAAC;AASvE;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,gBAAgB,EAAE,EAAE,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAkBjE,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,qBAAqB,EAAE,EAAE,CAAC;IACrC,UAAU,EAAE,+BAA+B,GAAG,IAAI,GAAG,SAAS,CAAC;CAChE,CAaA,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { useMediaQuery as e } from "../../hooks/useMediaQuery.js";
|
|
2
|
+
import { useAssistantTr as t } from "../i18n.js";
|
|
3
|
+
import { elapsedSince as n, startPhraseTicker as r, turnActivityCopy as i, turnActivityStage as a } from "../turnActivity.js";
|
|
4
|
+
import { useEffect as o, useState as s } from "react";
|
|
5
|
+
import { jsx as c, jsxs as l } from "react/jsx-runtime";
|
|
6
|
+
//#region src/shared/assistant/ui/AssistantTurnActivity.tsx
|
|
7
|
+
var u = ({ shown: e, label: t }) => /* @__PURE__ */ l("p", {
|
|
8
|
+
className: "relative text-[15px] leading-relaxed text-text-secondary",
|
|
9
|
+
"data-testid": "assistant-turn-activity",
|
|
10
|
+
children: [/* @__PURE__ */ c("span", {
|
|
11
|
+
"aria-hidden": "true",
|
|
12
|
+
"data-testid": "assistant-turn-activity-shown",
|
|
13
|
+
children: e
|
|
14
|
+
}), /* @__PURE__ */ c("span", {
|
|
15
|
+
className: "sr-only left-0 top-0",
|
|
16
|
+
"data-testid": "assistant-turn-activity-label",
|
|
17
|
+
children: t
|
|
18
|
+
})]
|
|
19
|
+
}), d = ({ processing: n }) => {
|
|
20
|
+
let r = t(), o = e("(prefers-reduced-motion: reduce)"), s = i(r, n, f(a(n) === "thinking" && !o && typeof n?.stageStartedAt == "number" ? n.stageStartedAt : null));
|
|
21
|
+
return s ? /* @__PURE__ */ c(u, {
|
|
22
|
+
shown: s.shown,
|
|
23
|
+
label: s.label
|
|
24
|
+
}) : null;
|
|
25
|
+
};
|
|
26
|
+
function f(e) {
|
|
27
|
+
let [t, i] = s(() => Date.now());
|
|
28
|
+
return o(() => {
|
|
29
|
+
if (e !== null) return r(e, i);
|
|
30
|
+
}, [e]), n(e, t);
|
|
31
|
+
}
|
|
32
|
+
//#endregion
|
|
33
|
+
export { d as AssistantTurnActivity, u as TurnActivityLine };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssistantVoiceSession.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/ui/voice/AssistantVoiceSession.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA4C,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AAI1E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"AssistantVoiceSession.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/ui/voice/AssistantVoiceSession.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA4C,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AAI1E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAgB7D,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEtE,gFAAgF;AAChF,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAElD,UAAU,KAAK;IACb,OAAO,EAAE,oBAAoB,CAAC;IAC9B,iEAAiE;IACjE,KAAK,CAAC,EAAE,aAAa,CAAC,mBAAmB,CAAC,CAAC;IAC3C,wCAAwC;IACxC,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,6EAA6E;IAC7E,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,6EAA6E;IAC7E,MAAM,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACnC,gEAAgE;IAChE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACpC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,KAAK,IAAI,CAAC;IACjD,kBAAkB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,iBAAiB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,0EAA0E;IAC1E,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,4DAA4D;IAC5D,YAAY,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC1D,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,mFAAmF;IACnF,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,0EAA0E;IAC1E,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,wEAAwE;IACxE,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,qBAAqB,EAAE,EAAE,CAAC,KAAK,CAokB3C,CAAC"}
|
|
@@ -1,176 +1,186 @@
|
|
|
1
1
|
import { useAssistantTr as e } from "../../i18n.js";
|
|
2
2
|
import { micIsInterrupt as t, showsAssistantCaption as n, voiceStageState as r } from "../../voice/voiceStageState.js";
|
|
3
|
-
import {
|
|
3
|
+
import { VOICE_THINKING_LABEL as i, composeVoiceStatus as a, voiceStatusSuffix as o } from "../../voice/voiceStatus.js";
|
|
4
|
+
import { spokenSoFar as s } from "../../voice/voiceSession.js";
|
|
4
5
|
import { AssistantAttachmentButton as ee } from "../composer/AssistantAttachmentButton.js";
|
|
5
|
-
import { AssistantAttachmentChips as
|
|
6
|
-
import { AssistantVoiceOrb as
|
|
7
|
-
import { VoiceMiniController as
|
|
8
|
-
import { VoiceStage as
|
|
9
|
-
import { VoiceTranscriptDrawer as
|
|
10
|
-
import { useCallback as
|
|
11
|
-
import { Maximize2 as
|
|
6
|
+
import { AssistantAttachmentChips as te } from "../composer/AssistantAttachmentChips.js";
|
|
7
|
+
import { AssistantVoiceOrb as ne } from "./AssistantVoiceOrb.js";
|
|
8
|
+
import { VoiceMiniController as c } from "./VoiceMiniController.js";
|
|
9
|
+
import { VoiceStage as l } from "./VoiceStage.js";
|
|
10
|
+
import { VoiceTranscriptDrawer as u } from "./VoiceTranscriptDrawer.js";
|
|
11
|
+
import { useCallback as d, useEffect as f, useRef as p, useState as m } from "react";
|
|
12
|
+
import { Maximize2 as re, Minimize2 as ie, ScrollText as ae, X as oe } from "lucide-react";
|
|
12
13
|
import { jsx as h, jsxs as g } from "react/jsx-runtime";
|
|
13
14
|
//#region src/shared/assistant/ui/voice/AssistantVoiceSession.tsx
|
|
14
|
-
var _ = ({ session: _, turns:
|
|
15
|
-
let
|
|
16
|
-
|
|
17
|
-
let
|
|
18
|
-
|
|
19
|
-
}, [
|
|
20
|
-
|
|
15
|
+
var _ = ({ session: _, turns: y = [], onSaveTranscript: b, onContinueInChat: x, notice: S = null, spoken: C, onInterrupt: ce, onToggleMute: w, attachments: T = [], onAttachFiles: E, onRemoveAttachment: D, onRetryAttachment: le, canAttachMore: ue = !0, preparingAttachments: O = 0, spokenChunks: k = null, onEnd: A, capturing: de = !0, interrupting: j = !1, awaitingEndpoint: M = !1 }) => {
|
|
16
|
+
let N = e(), { muted: P, error: F } = _, I = p(null), L = p(null), [R, z] = m("mini"), B = R === "full", V = R === "mini", H = R === "mini" ? "panel" : R === "panel" ? "full" : "mini", [U, W] = m(!1), G = p(!1), K = p(w);
|
|
17
|
+
K.current = w;
|
|
18
|
+
let fe = d(() => {
|
|
19
|
+
P || G.current || s(_) || (G.current = !0, K.current());
|
|
20
|
+
}, [P, _]);
|
|
21
|
+
f(() => {
|
|
21
22
|
let e = () => {
|
|
22
|
-
|
|
23
|
+
G.current && (G.current = !1, K.current());
|
|
23
24
|
};
|
|
24
25
|
return window.addEventListener("focus", e), () => {
|
|
25
|
-
window.removeEventListener("focus", e),
|
|
26
|
+
window.removeEventListener("focus", e), G.current = !1;
|
|
26
27
|
};
|
|
27
|
-
}, []),
|
|
28
|
-
|
|
29
|
-
}, []),
|
|
28
|
+
}, []), f(() => {
|
|
29
|
+
I.current?.focus();
|
|
30
|
+
}, []), f(() => {
|
|
30
31
|
let e = (e) => {
|
|
31
32
|
if (e.key === "Escape") {
|
|
32
|
-
if (
|
|
33
|
-
|
|
33
|
+
if (U) {
|
|
34
|
+
W(!1);
|
|
34
35
|
return;
|
|
35
36
|
}
|
|
36
|
-
|
|
37
|
+
A();
|
|
37
38
|
return;
|
|
38
39
|
}
|
|
39
|
-
if (e.key !== "Tab" || !
|
|
40
|
-
let t = (
|
|
40
|
+
if (e.key !== "Tab" || !B) return;
|
|
41
|
+
let t = (U ? L.current?.querySelector("[data-testid=\"assistant-voice-transcript\"]") : L.current)?.querySelectorAll("button:not([disabled])");
|
|
41
42
|
if (!t || t.length === 0) return;
|
|
42
43
|
let n = t[0], r = t[t.length - 1];
|
|
43
44
|
!n || !r || (e.shiftKey && document.activeElement === n ? (e.preventDefault(), r.focus()) : !e.shiftKey && document.activeElement === r && (e.preventDefault(), n.focus()));
|
|
44
45
|
};
|
|
45
46
|
return window.addEventListener("keydown", e), () => window.removeEventListener("keydown", e);
|
|
46
47
|
}, [
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
A,
|
|
49
|
+
B,
|
|
50
|
+
U
|
|
50
51
|
]);
|
|
51
|
-
let
|
|
52
|
+
let q = S !== null && F === null, J = s(_), Y = r({
|
|
52
53
|
snapshot: _,
|
|
53
|
-
capturing:
|
|
54
|
-
interrupting:
|
|
55
|
-
awaitingEndpoint:
|
|
56
|
-
}),
|
|
57
|
-
switch (
|
|
58
|
-
case "connecting": return
|
|
59
|
-
case "endpoint-grace": return
|
|
60
|
-
case "interrupting": return
|
|
61
|
-
case "thinking": return
|
|
62
|
-
case "speaking": return
|
|
54
|
+
capturing: de,
|
|
55
|
+
interrupting: j,
|
|
56
|
+
awaitingEndpoint: M
|
|
57
|
+
}), X = (() => {
|
|
58
|
+
switch (Y) {
|
|
59
|
+
case "connecting": return N("voiceSession.connecting", "Starting the microphone…");
|
|
60
|
+
case "endpoint-grace": return N("voiceSession.endpointGrace", "Still listening — take your time");
|
|
61
|
+
case "interrupting": return N("voiceSession.interrupting", "Stopped — go ahead");
|
|
62
|
+
case "thinking": return N(i.key, i.fallback);
|
|
63
|
+
case "speaking": return N("voiceSession.speaking", "Speaking — tap to stop");
|
|
63
64
|
case "mic-error":
|
|
64
65
|
case "ended": return "";
|
|
65
|
-
case "listening": return
|
|
66
|
-
default: return
|
|
66
|
+
case "listening": return P ? N("voiceSession.muted", "Microphone off") : N("voiceSession.listening", "Listening…");
|
|
67
|
+
default: return Y;
|
|
67
68
|
}
|
|
68
|
-
})(),
|
|
69
|
+
})(), Z = o({
|
|
70
|
+
tr: N,
|
|
71
|
+
stage: Y,
|
|
72
|
+
muted: P,
|
|
73
|
+
label: X
|
|
74
|
+
}), Q = a(X, Z), $ = Y === "thinking";
|
|
69
75
|
return /* @__PURE__ */ g("div", {
|
|
70
|
-
ref:
|
|
71
|
-
className: `flex flex-col items-center justify-between bg-bg-sunken ${
|
|
76
|
+
ref: L,
|
|
77
|
+
className: `flex flex-col items-center justify-between bg-bg-sunken ${R === "full" ? "fixed inset-x-0 bottom-0 top-14 z-[60] px-6 py-8" : R === "panel" ? "absolute inset-0 z-20 px-4 py-6" : "absolute inset-x-0 bottom-0 z-20 h-[11.25rem] border-t border-border-subtle px-3 py-3 shadow-lg"}`,
|
|
72
78
|
role: "dialog",
|
|
73
|
-
"aria-modal":
|
|
74
|
-
"aria-label":
|
|
79
|
+
"aria-modal": B || void 0,
|
|
80
|
+
"aria-label": N("voiceSession.title", "Voice conversation"),
|
|
75
81
|
"data-testid": "assistant-voice-session",
|
|
76
82
|
children: [
|
|
77
83
|
/* @__PURE__ */ g("button", {
|
|
78
|
-
ref:
|
|
84
|
+
ref: I,
|
|
79
85
|
type: "button",
|
|
80
|
-
onClick:
|
|
81
|
-
className: `absolute ${
|
|
82
|
-
title:
|
|
86
|
+
onClick: A,
|
|
87
|
+
className: `absolute ${B ? "right-6 top-6 h-14 gap-2 px-5 text-base" : V ? "right-12 top-2 h-8 gap-1.5 px-2.5 text-xs" : "right-3 top-3 h-11 gap-2 px-4 text-sm"} flex items-center justify-center rounded-full border border-border-default bg-bg-elevated text-text-secondary hover:bg-bg-sunken transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong`,
|
|
88
|
+
title: N("voiceSession.end", "End the voice conversation"),
|
|
83
89
|
"data-testid": "assistant-voice-end",
|
|
84
|
-
children: [/* @__PURE__ */ h(
|
|
85
|
-
className:
|
|
90
|
+
children: [/* @__PURE__ */ h(oe, {
|
|
91
|
+
className: B ? "size-6" : V ? "size-4" : "size-5",
|
|
86
92
|
"aria-hidden": "true"
|
|
87
93
|
}), /* @__PURE__ */ h("span", {
|
|
88
|
-
className: `truncate whitespace-nowrap font-medium ${
|
|
89
|
-
children:
|
|
94
|
+
className: `truncate whitespace-nowrap font-medium ${V ? "max-w-[3.5rem] text-xs" : "max-w-[7rem]"}`,
|
|
95
|
+
children: N("voiceSession.endShort", "End")
|
|
90
96
|
})]
|
|
91
97
|
}),
|
|
92
98
|
/* @__PURE__ */ h("div", {
|
|
93
|
-
className: `flex flex-col items-center ${
|
|
94
|
-
children:
|
|
99
|
+
className: `flex flex-col items-center ${V ? "px-3" : `min-h-[1.5rem] ${q ? B ? "pt-14" : "pt-10" : ""}`}`,
|
|
100
|
+
children: q ? /* @__PURE__ */ h("p", {
|
|
95
101
|
className: "max-w-xs text-center text-xs text-status-warning",
|
|
96
102
|
"data-testid": "assistant-voice-notice",
|
|
97
|
-
children:
|
|
103
|
+
children: se(S, N)
|
|
98
104
|
}) : null
|
|
99
105
|
}),
|
|
100
106
|
(() => {
|
|
101
|
-
let e = /* @__PURE__ */ h(
|
|
107
|
+
let e = /* @__PURE__ */ h(ne, {
|
|
102
108
|
session: _,
|
|
103
|
-
compact:
|
|
104
|
-
connecting:
|
|
105
|
-
onPress: t(
|
|
106
|
-
label: t(
|
|
107
|
-
}), r = n(
|
|
108
|
-
return
|
|
109
|
-
spokenChunks:
|
|
110
|
-
state:
|
|
109
|
+
compact: V,
|
|
110
|
+
connecting: Y === "connecting",
|
|
111
|
+
onPress: t(Y) ? ce : w,
|
|
112
|
+
label: t(Y) ? N("voiceSession.interrupt", "Stop the assistant and speak") : P ? N("voiceSession.unmute", "Turn the microphone on") : N("voiceSession.mute", "Turn the microphone off")
|
|
113
|
+
}), r = n(Y) ? C : J || null, i = F === null ? null : v(F, N);
|
|
114
|
+
return V ? /* @__PURE__ */ h(c, {
|
|
115
|
+
spokenChunks: k,
|
|
116
|
+
state: Y,
|
|
111
117
|
caption: r,
|
|
112
|
-
statusText:
|
|
118
|
+
statusText: Q,
|
|
119
|
+
statusSuffix: Z,
|
|
120
|
+
rotateStatus: $,
|
|
113
121
|
errorText: i,
|
|
114
122
|
control: e
|
|
115
|
-
}) : /* @__PURE__ */ h(
|
|
116
|
-
state:
|
|
117
|
-
userCaption:
|
|
118
|
-
spokenChunks:
|
|
119
|
-
assistantCaption:
|
|
120
|
-
expanded:
|
|
121
|
-
statusText:
|
|
123
|
+
}) : /* @__PURE__ */ h(l, {
|
|
124
|
+
state: Y,
|
|
125
|
+
userCaption: J || null,
|
|
126
|
+
spokenChunks: k,
|
|
127
|
+
assistantCaption: C,
|
|
128
|
+
expanded: B,
|
|
129
|
+
statusText: Q,
|
|
130
|
+
statusSuffix: Z,
|
|
131
|
+
rotateStatus: $,
|
|
122
132
|
errorText: i,
|
|
123
133
|
control: e
|
|
124
134
|
});
|
|
125
135
|
})(),
|
|
126
|
-
|
|
127
|
-
turns:
|
|
128
|
-
onClose: () =>
|
|
129
|
-
onSave:
|
|
130
|
-
onContinueInChat:
|
|
136
|
+
U ? /* @__PURE__ */ h(u, {
|
|
137
|
+
turns: y,
|
|
138
|
+
onClose: () => W(!1),
|
|
139
|
+
onSave: b,
|
|
140
|
+
onContinueInChat: x
|
|
131
141
|
}) : null,
|
|
132
|
-
|
|
133
|
-
className: `absolute ${
|
|
142
|
+
E ? /* @__PURE__ */ h("div", {
|
|
143
|
+
className: `absolute ${B ? "left-6 top-6" : V ? "left-11 top-2" : "left-3 top-3"}`,
|
|
134
144
|
children: /* @__PURE__ */ h(ee, {
|
|
135
145
|
onFiles: (e) => {
|
|
136
|
-
|
|
146
|
+
E(e), z((e) => e === "mini" ? "panel" : e);
|
|
137
147
|
},
|
|
138
|
-
onPickerOpen:
|
|
148
|
+
onPickerOpen: fe,
|
|
139
149
|
direction: "down",
|
|
140
|
-
canAddMore:
|
|
150
|
+
canAddMore: ue
|
|
141
151
|
})
|
|
142
152
|
}) : null,
|
|
143
|
-
(
|
|
144
|
-
className: `absolute ${
|
|
153
|
+
(T.length > 0 || O > 0) && !V ? /* @__PURE__ */ h("div", {
|
|
154
|
+
className: `absolute ${B ? "bottom-24 left-24 right-24" : "bottom-16 left-16 right-16"}`,
|
|
145
155
|
"data-testid": "assistant-voice-attachments",
|
|
146
|
-
children: /* @__PURE__ */ h(
|
|
147
|
-
attachments:
|
|
148
|
-
onRemove:
|
|
149
|
-
onRetry:
|
|
150
|
-
preparingCount:
|
|
156
|
+
children: /* @__PURE__ */ h(te, {
|
|
157
|
+
attachments: T,
|
|
158
|
+
onRemove: D ?? (() => void 0),
|
|
159
|
+
onRetry: le ?? (() => void 0),
|
|
160
|
+
preparingCount: O
|
|
151
161
|
})
|
|
152
162
|
}) : null,
|
|
153
163
|
/* @__PURE__ */ h("button", {
|
|
154
164
|
type: "button",
|
|
155
|
-
onClick: () =>
|
|
156
|
-
className: `absolute ${
|
|
157
|
-
"aria-pressed":
|
|
158
|
-
"aria-label":
|
|
165
|
+
onClick: () => W((e) => !e),
|
|
166
|
+
className: `absolute ${B ? "bottom-6 right-6 size-14" : V ? "right-2 top-2 size-8" : "bottom-3 right-3 size-11"} flex items-center justify-center rounded-full bg-bg-elevated text-text-secondary transition-colors hover:bg-bg-raised hover:text-text-primary focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong`,
|
|
167
|
+
"aria-pressed": U,
|
|
168
|
+
"aria-label": N("voiceSession.transcript", "Voice transcript"),
|
|
159
169
|
"data-testid": "assistant-voice-transcript-toggle",
|
|
160
|
-
children: /* @__PURE__ */ h(
|
|
170
|
+
children: /* @__PURE__ */ h(ae, { className: B ? "size-6" : V ? "size-4" : "size-5" })
|
|
161
171
|
}),
|
|
162
172
|
/* @__PURE__ */ h("button", {
|
|
163
173
|
type: "button",
|
|
164
|
-
onClick: () =>
|
|
165
|
-
className: `absolute ${
|
|
166
|
-
"aria-label":
|
|
174
|
+
onClick: () => z(H),
|
|
175
|
+
className: `absolute ${B ? "bottom-6 left-6 size-14" : V ? "left-2 top-2 size-8" : "bottom-3 left-3 size-11"} flex items-center justify-center rounded-full bg-bg-elevated text-text-secondary transition-colors hover:bg-bg-raised hover:text-text-primary focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong`,
|
|
176
|
+
"aria-label": H === "panel" ? N("voiceSession.expandPanel", "Show the conversation in the panel") : H === "full" ? N("voiceSession.expand", "Expand the conversation to full screen") : N("voiceSession.collapse", "Shrink to the compact controller"),
|
|
167
177
|
"data-testid": "assistant-voice-expand",
|
|
168
|
-
children:
|
|
178
|
+
children: B ? /* @__PURE__ */ h(ie, { className: "size-5" }) : /* @__PURE__ */ h(re, { className: V ? "size-4" : "size-5" })
|
|
169
179
|
})
|
|
170
180
|
]
|
|
171
181
|
});
|
|
172
182
|
};
|
|
173
|
-
function
|
|
183
|
+
function se(e, t) {
|
|
174
184
|
switch (e) {
|
|
175
185
|
case "network": return t("voiceSession.noticeNetwork", "Speech recognition lost its connection. Check your network — it will retry.");
|
|
176
186
|
case "not-capturing": return t("voiceSession.noticeNotCapturing", "The microphone did not start. Check that this site is allowed to use it, then try again.");
|
|
@@ -179,7 +189,7 @@ function v(e, t) {
|
|
|
179
189
|
default: return e;
|
|
180
190
|
}
|
|
181
191
|
}
|
|
182
|
-
function
|
|
192
|
+
function v(e, t) {
|
|
183
193
|
switch (e) {
|
|
184
194
|
case "mic-denied": return t("voiceSession.micDenied", "Microphone access is blocked. Allow it in your browser settings to talk.");
|
|
185
195
|
case "no-speech-support": return t("voiceSession.noSpeechSupport", "This browser cannot listen. Try a different browser, or type instead.");
|
|
@@ -37,6 +37,16 @@ interface Props {
|
|
|
37
37
|
index: number;
|
|
38
38
|
} | null;
|
|
39
39
|
statusText: string;
|
|
40
|
+
/**
|
|
41
|
+
* Visible alongside a rotating status, e.g. "Microphone off". Only meaningful
|
|
42
|
+
* with `rotateStatus`; `statusText` already carries it for the announcement.
|
|
43
|
+
*/
|
|
44
|
+
statusSuffix?: string | null;
|
|
45
|
+
/**
|
|
46
|
+
* Rotate the SHOWN status through the thinking phrases while the assistant
|
|
47
|
+
* thinks. What is ANNOUNCED is always `statusText` — see `VoiceStatusText`.
|
|
48
|
+
*/
|
|
49
|
+
rotateStatus?: boolean;
|
|
40
50
|
/** Mic / interrupt control — the same orb, in its compact size. */
|
|
41
51
|
control: ReactNode;
|
|
42
52
|
errorText?: string | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VoiceMiniController.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/ui/voice/VoiceMiniController.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"VoiceMiniController.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/ui/voice/VoiceMiniController.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAI3C,OAAO,EAIL,KAAK,eAAe,EACrB,MAAM,6BAA6B,CAAC;AAErC;;;;;;;;;;;;;;;;;GAiBG;AAEH,UAAU,KAAK;IACb,KAAK,EAAE,eAAe,CAAC;IACvB,uEAAuE;IACvE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC1D,UAAU,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,mEAAmE;IACnE,OAAO,EAAE,SAAS,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,eAAO,MAAM,mBAAmB,EAAE,EAAE,CAAC,KAAK,CAiHzC,CAAC"}
|