@burdenoff/fe-libs 2026.912.6 → 2026.913.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/shared/assistant/index.d.ts +4 -0
  2. package/dist/shared/assistant/index.d.ts.map +1 -1
  3. package/dist/shared/assistant/preview/useAssistantPreviewBridge.js +8 -8
  4. package/dist/shared/assistant/ui/AssistantAvatar.d.ts +26 -0
  5. package/dist/shared/assistant/ui/AssistantAvatar.d.ts.map +1 -0
  6. package/dist/shared/assistant/ui/AssistantAvatar.js +12 -0
  7. package/dist/shared/assistant/ui/AssistantChatArea.js +298 -298
  8. package/dist/shared/assistant/ui/AssistantMessageItem.d.ts.map +1 -1
  9. package/dist/shared/assistant/ui/AssistantMessageItem.js +19 -21
  10. package/dist/shared/assistant/ui/AssistantToolActivity.js +1 -1
  11. package/dist/shared/assistant/ui/composer/AssistantAttachmentChips.d.ts.map +1 -1
  12. package/dist/shared/assistant/ui/composer/AssistantAttachmentChips.js +2 -2
  13. package/dist/shared/assistant/ui/composer/AssistantComposer.js +1 -1
  14. package/dist/shared/assistant/ui/voice/AssistantVoiceSession.d.ts.map +1 -1
  15. package/dist/shared/assistant/ui/voice/AssistantVoiceSession.js +112 -102
  16. package/dist/shared/assistant/ui/voice/VoiceMiniController.d.ts +10 -0
  17. package/dist/shared/assistant/ui/voice/VoiceMiniController.d.ts.map +1 -1
  18. package/dist/shared/assistant/ui/voice/VoiceMiniController.js +29 -28
  19. package/dist/shared/assistant/ui/voice/VoiceStage.d.ts +10 -0
  20. package/dist/shared/assistant/ui/voice/VoiceStage.d.ts.map +1 -1
  21. package/dist/shared/assistant/ui/voice/VoiceStage.js +35 -34
  22. package/dist/shared/assistant/ui/voice/VoiceStatusText.d.ts +51 -0
  23. package/dist/shared/assistant/ui/voice/VoiceStatusText.d.ts.map +1 -0
  24. package/dist/shared/assistant/ui/voice/VoiceStatusText.js +42 -0
  25. package/dist/shared/assistant/ui/voice/VoiceWaveform.js +1 -1
  26. package/dist/shared/assistant/voice/rotationClock.d.ts +31 -0
  27. package/dist/shared/assistant/voice/rotationClock.d.ts.map +1 -0
  28. package/dist/shared/assistant/voice/rotationClock.js +27 -0
  29. package/dist/shared/assistant/voice/voiceStatus.d.ts +81 -0
  30. package/dist/shared/assistant/voice/voiceStatus.d.ts.map +1 -0
  31. package/dist/shared/assistant/voice/voiceStatus.js +33 -0
  32. package/dist/shared-assistant.js +88 -84
  33. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"AssistantMessageItem.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/ui/AssistantMessageItem.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AAqBnD,OAAO,KAAK,EAGV,OAAO,EACR,MAAM,iBAAiB,CAAC;AAIzB,UAAU,KAAK;IACb,mEAAmE;IACnE,qBAAqB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,6EAA6E;IAC7E,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAyCD,eAAO,MAAM,oBAAoB,EAAE,EAAE,CAAC,KAAK,CAqS1C,CAAC"}
1
+ {"version":3,"file":"AssistantMessageItem.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/ui/AssistantMessageItem.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AAsBnD,OAAO,KAAK,EAGV,OAAO,EACR,MAAM,iBAAiB,CAAC;AAIzB,UAAU,KAAK;IACb,mEAAmE;IACnE,qBAAqB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,6EAA6E;IAC7E,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAyCD,eAAO,MAAM,oBAAoB,EAAE,EAAE,CAAC,KAAK,CAmS1C,CAAC"}
@@ -5,15 +5,16 @@ import { useAssistantTr as n } from "../i18n.js";
5
5
  import { copyToClipboard as r } from "../clipboard.js";
6
6
  import { AssistantMarkdownRenderer as i } from "./AssistantMarkdownRenderer.js";
7
7
  import { downloadAssistantArtifact as a } from "../api.js";
8
- import { AssistantToolActivity as o, parseToolActivity as s } from "./AssistantToolActivity.js";
9
- import { useAssistantSpeech as c } from "./AssistantSpeechProvider.js";
10
- import { AssistantMessageAttachments as l } from "./AssistantMessageAttachments.js";
11
- import { AssistantPendingWriteCard as u } from "./AssistantPendingWriteCard.js";
12
- import { AssistantSpeakButton as d } from "./AssistantSpeakButton.js";
13
- import { SaveToFilesButton as f } from "../../../storage/SaveToFilesButton.js";
8
+ import { AssistantAvatar as o } from "./AssistantAvatar.js";
9
+ import { AssistantToolActivity as s, parseToolActivity as c } from "./AssistantToolActivity.js";
10
+ import { useAssistantSpeech as l } from "./AssistantSpeechProvider.js";
11
+ import { AssistantMessageAttachments as u } from "./AssistantMessageAttachments.js";
12
+ import { AssistantPendingWriteCard as d } from "./AssistantPendingWriteCard.js";
13
+ import { AssistantSpeakButton as f } from "./AssistantSpeakButton.js";
14
+ import { SaveToFilesButton as p } from "../../../storage/SaveToFilesButton.js";
14
15
  import "../../../storage/index.js";
15
- import { useMemo as p, useState as m } from "react";
16
- import { Check as h, Copy as g, RotateCcw as _, Sparkles as v } from "lucide-react";
16
+ import { useMemo as m, useState as h } from "react";
17
+ import { Check as g, Copy as _, RotateCcw as v } from "lucide-react";
17
18
  import { Fragment as y, jsx as b, jsxs as x } from "react/jsx-runtime";
18
19
  //#region src/shared/assistant/ui/AssistantMessageItem.tsx
19
20
  function S(e) {
@@ -32,10 +33,10 @@ function T(e, t, n) {
32
33
  s.href = o, s.download = t, document.body.appendChild(s), s.click(), document.body.removeChild(s), URL.revokeObjectURL(o);
33
34
  }
34
35
  var E = ({ onApprovePendingWrite: w, approvingWriteRef: E = null, message: D, isStreaming: O, isFailed: k, isLastAssistant: A, onRetry: j }) => {
35
- let M = n(), N = t(), { getAccessToken: P, getWorkspaceToken: F } = e(), I = c(), [L, R] = m(null), [z, B] = m(!1), V = D.role === "user", H = p(() => S(D), [D]), U = p(() => C(H), [H]), { steps: W, text: G } = p(() => V ? {
36
+ let M = n(), N = t(), { getAccessToken: P, getWorkspaceToken: F } = e(), I = l(), [L, R] = h(null), [z, B] = h(!1), V = D.role === "user", H = m(() => S(D), [D]), U = m(() => C(H), [H]), { steps: W, text: G } = m(() => V ? {
36
37
  steps: [],
37
38
  text: D.content
38
- } : s(D.content), [V, D.content]), K = () => {
39
+ } : c(D.content), [V, D.content]), K = () => {
39
40
  r(G || D.content).then((e) => {
40
41
  e && (B(!0), setTimeout(() => B(!1), 2e3));
41
42
  });
@@ -81,7 +82,7 @@ var E = ({ onApprovePendingWrite: w, approvingWriteRef: E = null, message: D, is
81
82
  children: D.content
82
83
  })
83
84
  }),
84
- /* @__PURE__ */ b(l, { attachments: e }),
85
+ /* @__PURE__ */ b(u, { attachments: e }),
85
86
  /* @__PURE__ */ b("div", {
86
87
  className: "mt-1 pr-1 text-right text-[10px] text-text-muted",
87
88
  children: J
@@ -93,14 +94,11 @@ var E = ({ onApprovePendingWrite: w, approvingWriteRef: E = null, message: D, is
93
94
  return /* @__PURE__ */ x("div", {
94
95
  className: "flex gap-2.5",
95
96
  "data-testid": "assistant-message-assistant",
96
- children: [/* @__PURE__ */ b("div", {
97
- className: "mt-0.5 flex size-6 flex-shrink-0 items-center justify-center rounded-full bg-gradient-to-br from-action-primary-bg/25 to-action-primary-bg/5 text-action-primary-bg",
98
- children: /* @__PURE__ */ b(v, { className: "size-3.5" })
99
- }), /* @__PURE__ */ x("div", {
97
+ children: [/* @__PURE__ */ b(o, { active: O }), /* @__PURE__ */ x("div", {
100
98
  className: "min-w-0 flex-1",
101
99
  children: [
102
- W.length > 0 && /* @__PURE__ */ b(o, { steps: W }),
103
- H?.pendingWrite ? /* @__PURE__ */ b(u, {
100
+ W.length > 0 && /* @__PURE__ */ b(s, { steps: W }),
101
+ H?.pendingWrite ? /* @__PURE__ */ b(d, {
104
102
  pendingWrite: H.pendingWrite,
105
103
  onApprove: w,
106
104
  approving: E !== null && E === H.pendingWrite.reference
@@ -122,7 +120,7 @@ var E = ({ onApprovePendingWrite: w, approvingWriteRef: E = null, message: D, is
122
120
  className: "flex flex-wrap gap-2",
123
121
  children: U.map((e) => {
124
122
  let t = `${e.name}${e.type === "directory" ? ".tar.gz" : ""}`;
125
- return /* @__PURE__ */ b(f, {
123
+ return /* @__PURE__ */ b(p, {
126
124
  label: t,
127
125
  disabled: L === e.path,
128
126
  testId: `assistant-artifact-${e.name}`,
@@ -148,11 +146,11 @@ var E = ({ onApprovePendingWrite: w, approvingWriteRef: E = null, message: D, is
148
146
  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",
149
147
  "aria-label": M("message.copy", "Copy message"),
150
148
  "data-testid": "assistant-message-copy",
151
- children: z ? /* @__PURE__ */ x(y, { children: [/* @__PURE__ */ b(h, { className: "size-3 text-status-success-text" }), /* @__PURE__ */ b("span", { children: M("message.copied", "Copied") })] }) : /* @__PURE__ */ x(y, { children: [/* @__PURE__ */ b(g, { className: "size-3" }), /* @__PURE__ */ b("span", { children: M("message.copy", "Copy") })] })
149
+ children: z ? /* @__PURE__ */ x(y, { children: [/* @__PURE__ */ b(g, { className: "size-3 text-status-success-text" }), /* @__PURE__ */ b("span", { children: M("message.copied", "Copied") })] }) : /* @__PURE__ */ x(y, { children: [/* @__PURE__ */ b(_, { className: "size-3" }), /* @__PURE__ */ b("span", { children: M("message.copy", "Copy") })] })
152
150
  }),
153
151
  G && I.isSupported && (() => {
154
152
  let e = I.blockedFor(D.id) ?? I.disabledReason, t = !!e && !!A, n = t ? `speak-reason-${D.id}` : void 0;
155
- return /* @__PURE__ */ x(y, { children: [/* @__PURE__ */ b(d, {
153
+ return /* @__PURE__ */ x(y, { children: [/* @__PURE__ */ b(f, {
156
154
  isSpeaking: I.isSpeaking(D.id),
157
155
  disabled: e !== null,
158
156
  disabledReason: e,
@@ -171,7 +169,7 @@ var E = ({ onApprovePendingWrite: w, approvingWriteRef: E = null, message: D, is
171
169
  className: `flex items-center gap-1 rounded-md px-1.5 py-1 text-[11px] transition-colors hover:bg-bg-elevated ${k ? "text-status-error-text" : "text-text-muted hover:text-text-secondary"}`,
172
170
  "aria-label": M("message.retry", "Retry"),
173
171
  "data-testid": "assistant-message-retry",
174
- children: [/* @__PURE__ */ b(_, { className: "size-3" }), /* @__PURE__ */ b("span", { children: M("message.retry", "Retry") })]
172
+ children: [/* @__PURE__ */ b(v, { className: "size-3" }), /* @__PURE__ */ b("span", { children: M("message.retry", "Retry") })]
175
173
  })
176
174
  ]
177
175
  }),
@@ -44,7 +44,7 @@ function f({ status: e }) {
44
44
  "aria-hidden": "true"
45
45
  });
46
46
  case "running": return /* @__PURE__ */ o(r, {
47
- className: "size-3.5 animate-spin text-action-primary-bg",
47
+ className: "size-3.5 motion-safe:animate-spin text-action-primary-bg",
48
48
  "aria-hidden": "true"
49
49
  });
50
50
  default: return /* @__PURE__ */ o(n, {
@@ -1 +1 @@
1
- {"version":3,"file":"AssistantAttachmentChips.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/ui/composer/AssistantAttachmentChips.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAUhC,OAAO,EAAe,KAAK,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAE1E,UAAU,KAAK;IACb,WAAW,EAAE,mBAAmB,EAAE,CAAC;IACnC,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,qEAAqE;IACrE,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,wBAAwB,EAAE,EAAE,CAAC,KAAK,CAwH9C,CAAC"}
1
+ {"version":3,"file":"AssistantAttachmentChips.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/ui/composer/AssistantAttachmentChips.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAUhC,OAAO,EAAe,KAAK,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAE1E,UAAU,KAAK;IACb,WAAW,EAAE,mBAAmB,EAAE,CAAC;IACnC,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,qEAAqE;IACrE,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,wBAAwB,EAAE,EAAE,CAAC,KAAK,CA2H9C,CAAC"}
@@ -43,7 +43,7 @@ var u = ({ attachments: u, onRemove: d, onRetry: f, preparingCount: p = 0, disab
43
43
  children: /* @__PURE__ */ c(o, { className: "size-3" })
44
44
  }),
45
45
  u ? /* @__PURE__ */ c(i, {
46
- className: "size-3.5 flex-shrink-0 animate-spin text-text-muted",
46
+ className: "size-3.5 flex-shrink-0 motion-safe:animate-spin text-text-muted",
47
47
  "aria-label": h("attachments.uploading", "Uploading…")
48
48
  }) : /* @__PURE__ */ c("button", {
49
49
  type: "button",
@@ -60,7 +60,7 @@ var u = ({ attachments: u, onRemove: d, onRetry: f, preparingCount: p = 0, disab
60
60
  className: "flex items-center gap-1.5 rounded-lg border border-border-subtle bg-bg-sunken px-2 py-1 text-xs text-text-muted",
61
61
  "data-testid": "assistant-attachment-preparing",
62
62
  children: [/* @__PURE__ */ c(i, {
63
- className: "size-3 animate-spin",
63
+ className: "size-3 motion-safe:animate-spin",
64
64
  "aria-hidden": "true"
65
65
  }), h("attachments.preparing", "Reading file…")]
66
66
  }, `preparing-${t}`))]
@@ -121,7 +121,7 @@ var _ = 200, v = ({ writeAccessDenied: v = !1, onSend: y, disabled: b = !1, plac
121
121
  className: `flex size-9 flex-shrink-0 items-center justify-center rounded-full shadow-sm transition-all focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong ${X ? "bg-action-primary-bg text-action-primary-text hover:scale-105 hover:bg-action-primary-bg-hover" : "bg-bg-elevated text-text-muted"}`,
122
122
  "aria-label": T("chatInput.send", "Send message"),
123
123
  "data-testid": "assistant-send",
124
- children: b || P ? /* @__PURE__ */ h(m, { className: "size-4 animate-spin" }) : /* @__PURE__ */ h(p, { className: "size-4" })
124
+ children: b || P ? /* @__PURE__ */ h(m, { className: "size-4 motion-safe:animate-spin" }) : /* @__PURE__ */ h(p, { className: "size-4" })
125
125
  })
126
126
  ]
127
127
  }),
@@ -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;AAW7D,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,CAukB3C,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 { spokenSoFar as i } from "../../voice/voiceSession.js";
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 a } from "../composer/AssistantAttachmentChips.js";
6
- import { AssistantVoiceOrb as o } from "./AssistantVoiceOrb.js";
7
- import { VoiceMiniController as s } from "./VoiceMiniController.js";
8
- import { VoiceStage as c } from "./VoiceStage.js";
9
- import { VoiceTranscriptDrawer as te } from "./VoiceTranscriptDrawer.js";
10
- import { useCallback as ne, useEffect as l, useRef as u, useState as d } from "react";
11
- import { Maximize2 as f, Minimize2 as p, ScrollText as m, X as re } from "lucide-react";
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: b = [], onSaveTranscript: x, onContinueInChat: S, notice: C = null, spoken: w, onInterrupt: T, onToggleMute: E, attachments: D = [], onAttachFiles: O, onRemoveAttachment: k, onRetryAttachment: ie, canAttachMore: ae = !0, preparingAttachments: A = 0, spokenChunks: j = null, onEnd: M, capturing: oe = !0, interrupting: N = !1, awaitingEndpoint: P = !1 }) => {
15
- let F = e(), { muted: I, error: L } = _, R = u(null), z = u(null), [B, V] = d("mini"), H = B === "full", U = B === "mini", W = B === "mini" ? "panel" : B === "panel" ? "full" : "mini", [G, K] = d(!1), q = u(!1), J = u(E);
16
- J.current = E;
17
- let se = ne(() => {
18
- I || q.current || i(_) || (q.current = !0, J.current());
19
- }, [I, _]);
20
- l(() => {
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
- q.current && (q.current = !1, J.current());
23
+ G.current && (G.current = !1, K.current());
23
24
  };
24
25
  return window.addEventListener("focus", e), () => {
25
- window.removeEventListener("focus", e), q.current = !1;
26
+ window.removeEventListener("focus", e), G.current = !1;
26
27
  };
27
- }, []), l(() => {
28
- R.current?.focus();
29
- }, []), l(() => {
28
+ }, []), f(() => {
29
+ I.current?.focus();
30
+ }, []), f(() => {
30
31
  let e = (e) => {
31
32
  if (e.key === "Escape") {
32
- if (G) {
33
- K(!1);
33
+ if (U) {
34
+ W(!1);
34
35
  return;
35
36
  }
36
- M();
37
+ A();
37
38
  return;
38
39
  }
39
- if (e.key !== "Tab" || !H) return;
40
- let t = (G ? z.current?.querySelector("[data-testid=\"assistant-voice-transcript\"]") : z.current)?.querySelectorAll("button:not([disabled])");
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
- M,
48
- H,
49
- G
48
+ A,
49
+ B,
50
+ U
50
51
  ]);
51
- let Y = C !== null && L === null, X = i(_), Z = r({
52
+ let q = S !== null && F === null, J = s(_), Y = r({
52
53
  snapshot: _,
53
- capturing: oe,
54
- interrupting: N,
55
- awaitingEndpoint: P
56
- }), Q = (() => {
57
- switch (Z) {
58
- case "connecting": return F("voiceSession.connecting", "Starting the microphone…");
59
- case "endpoint-grace": return F("voiceSession.endpointGrace", "Still listening — take your time");
60
- case "interrupting": return F("voiceSession.interrupting", "Stopped — go ahead");
61
- case "thinking": return F("voiceSession.thinking", "Thinking…");
62
- case "speaking": return F("voiceSession.speaking", "Speaking — tap to stop");
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 I ? F("voiceSession.muted", "Microphone off") : F("voiceSession.listening", "Listening…");
66
- default: return Z;
66
+ case "listening": return P ? N("voiceSession.muted", "Microphone off") : N("voiceSession.listening", "Listening…");
67
+ default: return Y;
67
68
  }
68
- })(), $ = I && Z !== "listening" && Q !== "" ? `${Q} · ${F("voiceSession.muted", "Microphone off")}` : Q;
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: z,
71
- className: `flex flex-col items-center justify-between bg-bg-sunken ${B === "full" ? "fixed inset-x-0 bottom-0 top-14 z-[60] px-6 py-8" : B === "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"}`,
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": H || void 0,
74
- "aria-label": F("voiceSession.title", "Voice conversation"),
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: R,
84
+ ref: I,
79
85
  type: "button",
80
- onClick: M,
81
- className: `absolute ${H ? "right-6 top-6 h-14 gap-2 px-5 text-base" : U ? "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`,
82
- title: F("voiceSession.end", "End the voice conversation"),
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(re, {
85
- className: H ? "size-6" : U ? "size-4" : "size-5",
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 ${U ? "max-w-[3.5rem] text-xs" : "max-w-[7rem]"}`,
89
- children: F("voiceSession.endShort", "End")
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 ${U ? "px-3" : `min-h-[1.5rem] ${Y ? H ? "pt-14" : "pt-10" : ""}`}`,
94
- children: Y ? /* @__PURE__ */ h("p", {
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: v(C, F)
103
+ children: se(S, N)
98
104
  }) : null
99
105
  }),
100
106
  (() => {
101
- let e = /* @__PURE__ */ h(o, {
107
+ let e = /* @__PURE__ */ h(ne, {
102
108
  session: _,
103
- compact: U,
104
- connecting: Z === "connecting",
105
- onPress: t(Z) ? T : E,
106
- label: t(Z) ? F("voiceSession.interrupt", "Stop the assistant and speak") : I ? F("voiceSession.unmute", "Turn the microphone on") : F("voiceSession.mute", "Turn the microphone off")
107
- }), r = n(Z) ? w : X || null, i = L === null ? null : y(L, F);
108
- return U ? /* @__PURE__ */ h(s, {
109
- spokenChunks: j,
110
- state: Z,
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(c, {
116
- state: Z,
117
- userCaption: X || null,
118
- spokenChunks: j,
119
- assistantCaption: w,
120
- expanded: H,
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
- G ? /* @__PURE__ */ h(te, {
127
- turns: b,
128
- onClose: () => K(!1),
129
- onSave: x,
130
- onContinueInChat: S
136
+ U ? /* @__PURE__ */ h(u, {
137
+ turns: y,
138
+ onClose: () => W(!1),
139
+ onSave: b,
140
+ onContinueInChat: x
131
141
  }) : null,
132
- O ? /* @__PURE__ */ h("div", {
133
- className: `absolute ${H ? "left-6 top-6" : U ? "left-11 top-2" : "left-3 top-3"}`,
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
- O(e), V((e) => e === "mini" ? "panel" : e);
146
+ E(e), z((e) => e === "mini" ? "panel" : e);
137
147
  },
138
- onPickerOpen: se,
148
+ onPickerOpen: fe,
139
149
  direction: "down",
140
- canAddMore: ae
150
+ canAddMore: ue
141
151
  })
142
152
  }) : null,
143
- (D.length > 0 || A > 0) && !U ? /* @__PURE__ */ h("div", {
144
- className: `absolute ${H ? "bottom-24 left-24 right-24" : "bottom-16 left-16 right-16"}`,
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(a, {
147
- attachments: D,
148
- onRemove: k ?? (() => void 0),
149
- onRetry: ie ?? (() => void 0),
150
- preparingCount: A
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: () => K((e) => !e),
156
- className: `absolute ${H ? "bottom-6 right-6 size-14" : U ? "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`,
157
- "aria-pressed": G,
158
- "aria-label": F("voiceSession.transcript", "Voice transcript"),
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(m, { className: H ? "size-6" : U ? "size-4" : "size-5" })
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: () => V(W),
165
- className: `absolute ${H ? "bottom-6 left-6 size-14" : U ? "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`,
166
- "aria-label": W === "panel" ? F("voiceSession.expandPanel", "Show the conversation in the panel") : W === "full" ? F("voiceSession.expand", "Expand the conversation to full screen") : F("voiceSession.collapse", "Shrink to the compact controller"),
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: H ? /* @__PURE__ */ h(p, { className: "size-5" }) : /* @__PURE__ */ h(f, { className: U ? "size-4" : "size-5" })
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 v(e, t) {
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 y(e, t) {
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;AAG3C,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,mEAAmE;IACnE,OAAO,EAAE,SAAS,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,eAAO,MAAM,mBAAmB,EAAE,EAAE,CAAC,KAAK,CAgHzC,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"}
@@ -1,55 +1,56 @@
1
1
  import { showsAssistantCaption as e, waveformIsActive as t, waveformIsSettled as n } from "../../voice/voiceStageState.js";
2
2
  import { showPreviousChunk as r } from "../../voice/miniCaptionBudget.js";
3
3
  import { VoiceWaveform as i } from "./VoiceWaveform.js";
4
- import { Fragment as a, jsx as o, jsxs as s } from "react/jsx-runtime";
4
+ import { VoiceStatusText as a } from "./VoiceStatusText.js";
5
+ import { Fragment as o, jsx as s, jsxs as c } from "react/jsx-runtime";
5
6
  //#region src/shared/assistant/ui/voice/VoiceMiniController.tsx
6
- var c = ({ state: c, caption: l, spokenChunks: u = null, statusText: d, control: f, errorText: p = null }) => {
7
- let m = e(c), h = m && u && u.index >= 0 ? u : null;
8
- return /* @__PURE__ */ s("div", {
7
+ var l = ({ state: l, caption: u, spokenChunks: d = null, statusText: f, statusSuffix: p, rotateStatus: m, control: h, errorText: g = null }) => {
8
+ let _ = e(l), v = _ && d && d.index >= 0 ? d : null;
9
+ return /* @__PURE__ */ c("div", {
9
10
  className: "flex min-h-0 w-full flex-1 items-center gap-3 px-4",
10
11
  "data-testid": "assistant-voice-mini",
11
- "data-state": c,
12
- children: [/* @__PURE__ */ s("div", {
12
+ "data-state": l,
13
+ children: [/* @__PURE__ */ c("div", {
13
14
  className: "flex min-w-0 flex-1 flex-col gap-1.5",
14
- children: [/* @__PURE__ */ s("div", {
15
+ children: [/* @__PURE__ */ c("div", {
15
16
  className: "flex items-center gap-2",
16
- children: [/* @__PURE__ */ o(i, {
17
- active: t(c),
18
- settled: n(c),
19
- tone: c === "speaking" ? "speaking" : "listening"
20
- }), /* @__PURE__ */ o("p", {
17
+ children: [/* @__PURE__ */ s(i, {
18
+ active: t(l),
19
+ settled: n(l),
20
+ tone: l === "speaking" ? "speaking" : "listening"
21
+ }), /* @__PURE__ */ s(a, {
21
22
  className: "truncate text-xs text-text-muted",
22
- "aria-live": "polite",
23
- "data-testid": "assistant-voice-status",
24
- children: d
23
+ status: f,
24
+ suffix: p,
25
+ rotating: m
25
26
  })]
26
- }), c === "mic-error" ? /* @__PURE__ */ o("p", {
27
+ }), l === "mic-error" ? /* @__PURE__ */ s("p", {
27
28
  className: "line-clamp-2 text-xs text-status-warning",
28
29
  role: "alert",
29
30
  "data-testid": "assistant-voice-mini-error",
30
- children: p
31
- }) : l ? /* @__PURE__ */ o("p", {
32
- className: ["line-clamp-3 break-words text-left text-sm leading-snug", m ? "font-semibold text-text-primary" : "font-medium text-text-secondary"].join(" "),
31
+ children: g
32
+ }) : u ? /* @__PURE__ */ s("p", {
33
+ className: ["line-clamp-3 break-words text-left text-sm leading-snug", _ ? "font-semibold text-text-primary" : "font-medium text-text-secondary"].join(" "),
33
34
  role: "status",
34
35
  "aria-live": "polite",
35
36
  "data-testid": "assistant-voice-caption",
36
- children: h ? /* @__PURE__ */ s(a, { children: [r(h) ? /* @__PURE__ */ s("span", {
37
+ children: v ? /* @__PURE__ */ c(o, { children: [r(v) ? /* @__PURE__ */ c("span", {
37
38
  className: "text-text-muted transition-colors duration-300",
38
- children: [h.chunks[h.index - 1], " "]
39
- }) : null, /* @__PURE__ */ o("span", {
39
+ children: [v.chunks[v.index - 1], " "]
40
+ }) : null, /* @__PURE__ */ s("span", {
40
41
  className: "text-text-primary",
41
42
  "data-testid": "assistant-voice-caption-current",
42
- children: h.chunks[h.index]
43
- })] }) : l
44
- }) : /* @__PURE__ */ o("div", {
43
+ children: v.chunks[v.index]
44
+ })] }) : u
45
+ }) : /* @__PURE__ */ s("div", {
45
46
  className: "h-9",
46
47
  "aria-hidden": "true"
47
48
  })]
48
- }), /* @__PURE__ */ o("div", {
49
+ }), /* @__PURE__ */ s("div", {
49
50
  className: "shrink-0",
50
- children: f
51
+ children: h
51
52
  })]
52
53
  });
53
54
  };
54
55
  //#endregion
55
- export { c as VoiceMiniController };
56
+ export { l as VoiceMiniController };
@@ -27,6 +27,16 @@ interface Props {
27
27
  expanded: boolean;
28
28
  /** Status words — already localised by the caller. */
29
29
  statusText: string;
30
+ /**
31
+ * Visible alongside a rotating status, e.g. "Microphone off". Only meaningful
32
+ * with `rotateStatus`; `statusText` already carries it for the announcement.
33
+ */
34
+ statusSuffix?: string | null;
35
+ /**
36
+ * Rotate the SHOWN status through the thinking phrases while the assistant
37
+ * thinks. What is ANNOUNCED is always `statusText` — see `VoiceStatusText`.
38
+ */
39
+ rotateStatus?: boolean;
30
40
  /** The microphone / interrupt control. */
31
41
  control: ReactNode;
32
42
  /** Shown in the mic-error state instead of a caption. */
@@ -1 +1 @@
1
- {"version":3,"file":"VoiceStage.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/ui/voice/VoiceStage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAG3C,OAAO,EAKL,KAAK,eAAe,EACrB,MAAM,6BAA6B,CAAC;AAErC;;;;;;;;;;;;;;;;;GAiBG;AAEH,UAAU,KAAK;IACb,KAAK,EAAE,eAAe,CAAC;IACvB,mDAAmD;IACnD,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,oCAAoC;IACpC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,EAAE,OAAO,CAAC;IAClB,sDAAsD;IACtD,UAAU,EAAE,MAAM,CAAC;IACnB,0CAA0C;IAC1C,OAAO,EAAE,SAAS,CAAC;IACnB,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,+EAA+E;IAC/E,YAAY,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAC3D;AAED,eAAO,MAAM,UAAU,EAAE,EAAE,CAAC,KAAK,CAiIhC,CAAC"}
1
+ {"version":3,"file":"VoiceStage.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/ui/voice/VoiceStage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAI3C,OAAO,EAKL,KAAK,eAAe,EACrB,MAAM,6BAA6B,CAAC;AAErC;;;;;;;;;;;;;;;;;GAiBG;AAEH,UAAU,KAAK;IACb,KAAK,EAAE,eAAe,CAAC;IACvB,mDAAmD;IACnD,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,oCAAoC;IACpC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,EAAE,OAAO,CAAC;IAClB,sDAAsD;IACtD,UAAU,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,0CAA0C;IAC1C,OAAO,EAAE,SAAS,CAAC;IACnB,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,+EAA+E;IAC/E,YAAY,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAC3D;AAED,eAAO,MAAM,UAAU,EAAE,EAAE,CAAC,KAAK,CAmIhC,CAAC"}