@burdenoff/fe-libs 2026.1004.7 → 2026.1005.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.
Files changed (43) hide show
  1. package/dist/shared/assistant/api.d.ts +18 -0
  2. package/dist/shared/assistant/api.d.ts.map +1 -1
  3. package/dist/shared/assistant/api.js +169 -147
  4. package/dist/shared/assistant/capabilities.d.ts +21 -0
  5. package/dist/shared/assistant/capabilities.d.ts.map +1 -1
  6. package/dist/shared/assistant/capabilities.js +11 -1
  7. package/dist/shared/assistant/index.d.ts +5 -0
  8. package/dist/shared/assistant/index.d.ts.map +1 -1
  9. package/dist/shared/assistant/liveDeltas.d.ts +76 -0
  10. package/dist/shared/assistant/liveDeltas.d.ts.map +1 -0
  11. package/dist/shared/assistant/liveDeltas.js +196 -0
  12. package/dist/shared/assistant/liveOverlay.d.ts +62 -0
  13. package/dist/shared/assistant/liveOverlay.d.ts.map +1 -0
  14. package/dist/shared/assistant/liveOverlay.js +64 -0
  15. package/dist/shared/assistant/snapshotPoller.d.ts +48 -0
  16. package/dist/shared/assistant/snapshotPoller.d.ts.map +1 -0
  17. package/dist/shared/assistant/snapshotPoller.js +58 -0
  18. package/dist/shared/assistant/turnStream.d.ts +71 -0
  19. package/dist/shared/assistant/turnStream.d.ts.map +1 -0
  20. package/dist/shared/assistant/turnStream.js +266 -0
  21. package/dist/shared/assistant/turnTimeline.d.ts +27 -2
  22. package/dist/shared/assistant/turnTimeline.d.ts.map +1 -1
  23. package/dist/shared/assistant/turnTimeline.js +17 -28
  24. package/dist/shared/assistant/types.d.ts +10 -0
  25. package/dist/shared/assistant/types.d.ts.map +1 -1
  26. package/dist/shared/assistant/ui/AssistantChatArea.d.ts.map +1 -1
  27. package/dist/shared/assistant/ui/AssistantChatArea.js +1049 -1008
  28. package/dist/shared/assistant/ui/AssistantMessageList.d.ts +2 -0
  29. package/dist/shared/assistant/ui/AssistantMessageList.d.ts.map +1 -1
  30. package/dist/shared/assistant/ui/AssistantMessageList.js +48 -32
  31. package/dist/shared/assistant/ui/useVoiceSession.d.ts.map +1 -1
  32. package/dist/shared/assistant/ui/useVoiceSession.js +96 -93
  33. package/dist/shared/assistant/voice/affirmations.d.ts +44 -0
  34. package/dist/shared/assistant/voice/affirmations.d.ts.map +1 -0
  35. package/dist/shared/assistant/voice/affirmations.js +238 -0
  36. package/dist/shared/assistant/voice/handsFree.d.ts +16 -3
  37. package/dist/shared/assistant/voice/handsFree.d.ts.map +1 -1
  38. package/dist/shared/assistant/voice/handsFree.js +43 -37
  39. package/dist/shared/assistant/voice/voiceSession.d.ts +2 -0
  40. package/dist/shared/assistant/voice/voiceSession.d.ts.map +1 -1
  41. package/dist/shared/assistant/voice/voiceSession.js +3 -1
  42. package/dist/shared-assistant.js +208 -203
  43. package/package.json +1 -1
@@ -49,6 +49,8 @@ interface Props {
49
49
  */
50
50
  hidesLegacyWriteCard?: (message: Message) => boolean;
51
51
  }
52
+ /** At most one auto-scroll per this long while a reply is streaming in live. */
53
+ export declare const LIVE_SCROLL_GAP_MS = 250;
52
54
  export declare const AssistantMessageList: FC<Props>;
53
55
  export {};
54
56
  //# sourceMappingURL=AssistantMessageList.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AssistantMessageList.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/ui/AssistantMessageList.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,EAAE,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAGnE,OAAO,KAAK,EAAE,+BAA+B,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAQhF,UAAU,KAAK;IACb;;;OAGG;IACH,qBAAqB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC;;;;;;OAMG;IACH,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB;;;;OAIG;IACH,UAAU,CAAC,EAAE,+BAA+B,GAAG,IAAI,CAAC;IACpD,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,mEAAmE;IACnE,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,SAAS,CAAC;IACvD;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC;CACtD;AAED,eAAO,MAAM,oBAAoB,EAAE,EAAE,CAAC,KAAK,CA6G1C,CAAC"}
1
+ {"version":3,"file":"AssistantMessageList.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/ui/AssistantMessageList.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,EAAE,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAGnE,OAAO,KAAK,EAAE,+BAA+B,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAShF,UAAU,KAAK;IACb;;;OAGG;IACH,qBAAqB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC;;;;;;OAMG;IACH,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB;;;;OAIG;IACH,UAAU,CAAC,EAAE,+BAA+B,GAAG,IAAI,CAAC;IACpD,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,mEAAmE;IACnE,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,SAAS,CAAC;IACvD;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC;CACtD;AAED,gFAAgF;AAChF,eAAO,MAAM,kBAAkB,MAAM,CAAC;AAEtC,eAAO,MAAM,oBAAoB,EAAE,EAAE,CAAC,KAAK,CAyJ1C,CAAC"}
@@ -2,50 +2,66 @@ import { useAssistantTr as e } from "../i18n.js";
2
2
  import { approvalFollowUpReplyIds as t, approvedPendingWriteIds as n, goAheadSentReplyIds as r } from "../liveTurns.js";
3
3
  import { readReducedMotion as i } from "./usePrefersReducedMotion.js";
4
4
  import { AssistantMessageItem as a } from "./AssistantMessageItem.js";
5
- import { useEffect as o, useRef as s } from "react";
6
- import { jsx as c, jsxs as l } from "react/jsx-runtime";
5
+ import { useLiveOverlay as o } from "../liveOverlay.js";
6
+ import { useEffect as s, useRef as c } from "react";
7
+ import { jsx as l, jsxs as u } from "react/jsx-runtime";
7
8
  //#region src/shared/assistant/ui/AssistantMessageList.tsx
8
- var u = ({ onApprovePendingWrite: u, approvingWriteRef: d = null, approvableMessageId: f = null, retryableMessageId: p = null, messages: m, processing: h, streamingMessageId: g, failedMessageId: _, onRetry: v, renderWriteProposals: y, hidesLegacyWriteCard: b }) => {
9
- let x = e(), S = (() => {
10
- for (let e = m.length - 1; e >= 0; --e) if (m[e].role === "assistant") return m[e].id;
9
+ var d = 250, f = ({ onApprovePendingWrite: d, approvingWriteRef: f = null, approvableMessageId: p = null, retryableMessageId: m = null, messages: h, processing: g, streamingMessageId: _, failedMessageId: v, onRetry: y, renderWriteProposals: b, hidesLegacyWriteCard: x }) => {
10
+ let S = e(), C = (() => {
11
+ for (let e = h.length - 1; e >= 0; --e) if (h[e].role === "assistant") return h[e].id;
11
12
  return null;
12
- })(), C = n(m), w = r(m), T = t(m), E = s(null), D = s(null);
13
- return o(() => {
14
- let e = D.current;
13
+ })(), w = n(h), T = r(h), E = t(h), D = c(null), O = c(null);
14
+ s(() => {
15
+ let e = O.current;
15
16
  if (e && e.scrollHeight - e.scrollTop - e.clientHeight < 100) {
16
17
  let e = i();
17
- E.current?.scrollIntoView({ behavior: e ? "auto" : "smooth" });
18
+ D.current?.scrollIntoView({ behavior: e ? "auto" : "smooth" });
18
19
  }
19
- }, [m, g]), o(() => {
20
- E.current?.scrollIntoView({ behavior: "instant" });
21
- }, []), /* @__PURE__ */ l("div", {
22
- ref: D,
20
+ }, [h, _]);
21
+ let k = o((e) => e.byMessageId), A = _ === null ? null : k[_]?.content ?? null, j = c(0), M = c(null);
22
+ return s(() => {
23
+ if (A === null) return;
24
+ let e = () => {
25
+ M.current = null, j.current = Date.now();
26
+ let e = O.current;
27
+ e && e.scrollHeight - e.scrollTop - e.clientHeight < 100 && D.current?.scrollIntoView({ behavior: "auto" });
28
+ }, t = j.current + 250 - Date.now();
29
+ t <= 0 ? e() : M.current === null && (M.current = setTimeout(e, t));
30
+ }, [A]), s(() => () => {
31
+ M.current !== null && clearTimeout(M.current);
32
+ }, []), s(() => {
33
+ D.current?.scrollIntoView({ behavior: "instant" });
34
+ }, []), /* @__PURE__ */ u("div", {
35
+ ref: O,
23
36
  className: "scrollbar-slim flex-1 space-y-4 overflow-y-auto p-3",
24
37
  role: "log",
25
38
  "aria-live": "polite",
26
39
  "aria-relevant": "additions",
27
- "aria-busy": g !== null,
28
- "aria-label": x("messageList.ariaLabel", "Conversation messages"),
29
- children: [m.map((e) => {
30
- let t = C.has(e.id), n = !t && (e.id === f || e.id === g);
31
- return /* @__PURE__ */ c(a, {
32
- onApprovePendingWrite: n ? u : void 0,
33
- approvingWriteRef: d,
40
+ "aria-busy": _ !== null,
41
+ "aria-label": S("messageList.ariaLabel", "Conversation messages"),
42
+ children: [h.map((e) => {
43
+ let t = w.has(e.id), n = !t && (e.id === p || e.id === _);
44
+ return /* @__PURE__ */ l(a, {
45
+ onApprovePendingWrite: n ? d : void 0,
46
+ approvingWriteRef: f,
34
47
  pendingWriteApproved: t,
35
- pendingWriteGoAheadSent: w.has(e.id),
48
+ pendingWriteGoAheadSent: T.has(e.id),
36
49
  pendingWriteExpired: !t && !n,
37
- message: e,
38
- processing: h,
39
- isStreaming: e.id === g,
40
- isFailed: e.id === _,
41
- isLastAssistant: e.id === p,
42
- isNewestAssistant: e.id === S,
43
- onRetry: T.has(e.id) ? void 0 : v,
44
- legacyWriteCardHidden: b?.(e) ?? !1,
45
- writeProposals: y?.(e)
50
+ message: e.id === _ && A !== null ? {
51
+ ...e,
52
+ content: A
53
+ } : e,
54
+ processing: g,
55
+ isStreaming: e.id === _,
56
+ isFailed: e.id === v,
57
+ isLastAssistant: e.id === m,
58
+ isNewestAssistant: e.id === C,
59
+ onRetry: E.has(e.id) ? void 0 : y,
60
+ legacyWriteCardHidden: x?.(e) ?? !1,
61
+ writeProposals: b?.(e)
46
62
  }, e.id);
47
- }), /* @__PURE__ */ c("div", { ref: E })]
63
+ }), /* @__PURE__ */ l("div", { ref: D })]
48
64
  });
49
65
  };
50
66
  //#endregion
51
- export { u as AssistantMessageList };
67
+ export { f as AssistantMessageList, d as LIVE_SCROLL_GAP_MS };
@@ -1 +1 @@
1
- {"version":3,"file":"useVoiceSession.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/ui/useVoiceSession.ts"],"names":[],"mappings":"AAUA,OAAO,EAAe,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAIpE,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAgBL,KAAK,oBAAoB,EAE1B,MAAM,uBAAuB,CAAC;AAsC/B;;;;;;;;GAQG;AACH,MAAM,MAAM,kBAAkB,GAC5B,SAAS,GAAG,eAAe,GAAG,eAAe,GAAG,oBAAoB,CAAC;AAEvE;;;;;;;;GAQG;AACH,MAAM,WAAW,iBAAiB;IAChC,iFAAiF;IACjF,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC;CAC7B;AAMD,UAAU,OAAO;IACf,+EAA+E;IAC/E;;;;;;;OAOG;IACH,QAAQ,EAAE,CACR,IAAI,EAAE,MAAM,EACZ,cAAc,EAAE,MAAM;IACtB;;;OAGG;IACH,MAAM,EAAE,eAAe;IACvB;;;;;OAKG;IACH,IAAI,EAAE,eAAe,KAClB,IAAI,CAAC;IACV;;;;OAIG;IACH,WAAW,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACjD,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,OAAO,CAAC,EAAE,YAAY,GAAG,MAAM,CAAC;IAChC;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;CAC1B;AAED,oEAAoE;AACpE,MAAM,WAAW,eAAe;IAC9B,gEAAgE;IAChE,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,OAAO,EAAE,WAAW,EACpB,WAAW,GACZ,EAAE,OAAO;;IAq4BJ,qEAAqE;;IAErE;;;;;;;OAOG;;IAEH,+DAA+D;;IAE/D;;;;;;;OAOG;;IAIH,0EAA0E;;IAE1E,6DAA6D;;IAE7D,kEAAkE;;IAElE,uEAAuE;;IAEvE,sDAAsD;;;;uCA1GvC,MAAM;;;IAiHrB,qDAAqD;;IAErD,uDAAuD;;IAEvD,0EAA0E;qBA7yB1C,iBAAiB;IA+yBjD;;;OAGG;+BA7zBuC,OAAO;IA+zBjD;;;OAGG;0BA5xBE,iBAAiB;EA2zB3B"}
1
+ {"version":3,"file":"useVoiceSession.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/ui/useVoiceSession.ts"],"names":[],"mappings":"AAUA,OAAO,EAAe,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAIpE,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAgBL,KAAK,oBAAoB,EAE1B,MAAM,uBAAuB,CAAC;AAsC/B;;;;;;;;GAQG;AACH,MAAM,MAAM,kBAAkB,GAC5B,SAAS,GAAG,eAAe,GAAG,eAAe,GAAG,oBAAoB,CAAC;AAEvE;;;;;;;;GAQG;AACH,MAAM,WAAW,iBAAiB;IAChC,iFAAiF;IACjF,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC;CAC7B;AAMD,UAAU,OAAO;IACf,+EAA+E;IAC/E;;;;;;;OAOG;IACH,QAAQ,EAAE,CACR,IAAI,EAAE,MAAM,EACZ,cAAc,EAAE,MAAM;IACtB;;;OAGG;IACH,MAAM,EAAE,eAAe;IACvB;;;;;OAKG;IACH,IAAI,EAAE,eAAe,KAClB,IAAI,CAAC;IACV;;;;OAIG;IACH,WAAW,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACjD,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,OAAO,CAAC,EAAE,YAAY,GAAG,MAAM,CAAC;IAChC;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;CAC1B;AAED,oEAAoE;AACpE,MAAM,WAAW,eAAe;IAC9B,gEAAgE;IAChE,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,OAAO,EAAE,WAAW,EACpB,WAAW,GACZ,EAAE,OAAO;;IAg5BJ,qEAAqE;;IAErE;;;;;;;OAOG;;IAEH,+DAA+D;;IAE/D;;;;;;;OAOG;;IAIH,0EAA0E;;IAE1E,6DAA6D;;IAE7D,kEAAkE;;IAElE,uEAAuE;;IAEvE,sDAAsD;;;;uCA1GvC,MAAM;;;IAiHrB,qDAAqD;;IAErD,uDAAuD;;IAEvD,0EAA0E;qBAxzB1C,iBAAiB;IA0zBjD;;;OAGG;+BAx0BuC,OAAO;IA00BjD;;;OAGG;0BAvyBE,iBAAiB;EAs0B3B"}
@@ -1,24 +1,24 @@
1
1
  import { useVoiceInput as e } from "../voice/useVoiceInput.js";
2
2
  import { planSubmitTimer as t, resolveVoiceGraceMs as n } from "../voice/handsFree.js";
3
3
  import { speechFeed as r } from "../speech/speechFeed.js";
4
- import { INITIAL_SESSION as ee, INTERRUPT_MAX_MS as te, NOTHING_HEARD as i, advanceHeardClock as ne, isCapturing as a, isSubmittable as re, planListeningHold as ie, planReplyConsumption as ae, planVoiceAnnouncement as oe, shouldRecognise as se, spokenSoFar as o, voiceSessionReducer as ce } from "../voice/voiceSession.js";
5
- import { isTurnSuperseded as s } from "../voice/supersededTurns.js";
6
- import { captionChunks as le } from "../voice/speechPlayback.js";
7
- import { turnClockMs as c } from "../turnTimeline.js";
8
- import { useAssistantSpeech as ue } from "./AssistantSpeechProvider.js";
9
- import { useCallback as l, useEffect as u, useLayoutEffect as de, useMemo as fe, useReducer as pe, useRef as d, useState as f } from "react";
4
+ import { INITIAL_SESSION as ee, INTERRUPT_MAX_MS as te, NOTHING_HEARD as i, advanceHeardClock as ne, isCapturing as re, isSubmittable as ie, planListeningHold as ae, planReplyConsumption as oe, planVoiceAnnouncement as se, shouldRecognise as ce, spokenSoFar as a, voiceSessionReducer as le } from "../voice/voiceSession.js";
5
+ import { isTurnSuperseded as o } from "../voice/supersededTurns.js";
6
+ import { captionChunks as ue } from "../voice/speechPlayback.js";
7
+ import { turnClockMs as s } from "../turnTimeline.js";
8
+ import { useAssistantSpeech as de } from "./AssistantSpeechProvider.js";
9
+ import { useCallback as c, useEffect as l, useLayoutEffect as fe, useMemo as pe, useReducer as me, useRef as u, useState as d } from "react";
10
10
  //#region src/shared/assistant/ui/useVoiceSession.ts
11
- var me = 4e3, he = 2500, ge = 5e3, _e = 12e3, ve = "data:audio/wav;base64,UklGRiQAAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQAAAAA=";
12
- function ye({ onSubmit: ye, latestReply: p, language: be, graceMs: xe, onSupersede: m }) {
13
- let h = n(xe), g = d(null), [_, v] = pe(l((e, t) => ce(e, t, g.current), []), ee), y = ue(), { setSessionSpeaking: b, setSessionMicOpen: x, speakingMessageId: S, stop: C } = y, w = d(y.toggle), T = y.toggle;
14
- de(() => {
11
+ var he = 4e3, ge = 2500, _e = 5e3, ve = 12e3, ye = "data:audio/wav;base64,UklGRiQAAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQAAAAA=";
12
+ function f({ onSubmit: f, latestReply: p, language: m, graceMs: be, onSupersede: h }) {
13
+ let xe = n(be), g = u(null), [_, v] = me(c((e, t) => le(e, t, g.current), []), ee), y = de(), { setSessionSpeaking: b, setSessionMicOpen: x, speakingMessageId: S, stop: C } = y, w = u(y.toggle), T = y.toggle;
14
+ fe(() => {
15
15
  w.current = T;
16
16
  }, [T]);
17
- let E = d(null), D = d({}), O = d(i), k = d(null), A = d(!1), j = d(null), [M, N] = f(null), [P, F] = f(!1), [I, L] = f(!1), [R, z] = f(!1), B = d(_);
17
+ let E = u(null), D = u({}), O = u(i), k = u(null), A = u(!1), j = u(null), [M, N] = d(null), [P, F] = d(!1), [I, L] = d(!1), [R, z] = d(!1), B = u(_);
18
18
  B.current = _;
19
- let V = d([]), H = d(null), U = d(!1), W = l(() => {
19
+ let V = u([]), H = u(null), U = u(!1), W = c(() => {
20
20
  V.current = [], H.current = null, U.current = !1;
21
- }, []), G = l(() => {
21
+ }, []), G = c(() => {
22
22
  for (;;) {
23
23
  let e = V.current.shift();
24
24
  if (!e) return !1;
@@ -33,8 +33,8 @@ function ye({ onSubmit: ye, latestReply: p, language: be, graceMs: xe, onSuperse
33
33
  return !0;
34
34
  }
35
35
  }
36
- }, []), K = d(!1), q = l((e) => {
37
- let t = ie({
36
+ }, []), K = u(!1), q = c((e) => {
37
+ let t = ae({
38
38
  requested: e,
39
39
  held: K.current,
40
40
  muted: B.current.muted
@@ -43,17 +43,17 @@ function ye({ onSubmit: ye, latestReply: p, language: be, graceMs: xe, onSuperse
43
43
  type: "mute",
44
44
  muted: t.mute
45
45
  });
46
- }, []), J = l((e) => {
47
- let t = oe(B.current);
46
+ }, []), J = c((e) => {
47
+ let t = se(B.current);
48
48
  t !== "drop" && (H.current?.id === e.id || V.current.some((t) => t.id === e.id) || (V.current.push(e), t === "start" && !U.current && (U.current = !0, v({ type: "announce" }))));
49
- }, []), Se = l((e) => {
49
+ }, []), Se = c((e) => {
50
50
  if (B.current.phase !== "thinking") {
51
51
  J(e);
52
52
  return;
53
53
  }
54
54
  V.current.push(e), U.current = !0, v({ type: "answered-locally" });
55
- }, [J]), Ce = d(p);
56
- Ce.current = p, u(() => {
55
+ }, [J]), Ce = u(p);
56
+ Ce.current = p, l(() => {
57
57
  if (_.phase === "speaking") {
58
58
  let e = j.current;
59
59
  g.current = e && k.current === e.id && p?.id !== e.id ? e.text : p?.text ?? null;
@@ -62,40 +62,43 @@ function ye({ onSubmit: ye, latestReply: p, language: be, graceMs: xe, onSuperse
62
62
  if (g.current === null) return;
63
63
  let e = setTimeout(() => {
64
64
  g.current = null;
65
- }, he);
65
+ }, ge);
66
66
  return () => clearTimeout(e);
67
67
  }, [_.phase, p]);
68
- let Y = l((e, t) => {
68
+ let we = u(m);
69
+ we.current = m;
70
+ let Y = c((e, t) => {
69
71
  v({
70
72
  type: "speech",
71
73
  transcript: e,
72
74
  final: t,
73
- at: Date.now()
75
+ at: Date.now(),
76
+ language: we.current
74
77
  });
75
- }, []), we = d(0), Te = l(() => {
76
- W(), C(), we.current = Date.now(), F(!0), v({ type: "interrupt" });
78
+ }, []), Te = u(0), Ee = c(() => {
79
+ W(), C(), Te.current = Date.now(), F(!0), v({ type: "interrupt" });
77
80
  }, [C, W]), X = e({
78
- onFinalize: l((e) => Y(e, !0), [Y]),
79
- language: be
81
+ onFinalize: c((e) => Y(e, !0), [Y]),
82
+ language: m
80
83
  });
81
- u(() => {
84
+ l(() => {
82
85
  X.interim && Y(X.interim, !1);
83
- }, [X.interim, Y]), u(() => {
84
- E.current && clearTimeout(E.current), L(!1), O.current = ne(O.current, _, c());
86
+ }, [X.interim, Y]), l(() => {
87
+ E.current && clearTimeout(E.current), L(!1), O.current = ne(O.current, _, s());
85
88
  let e = t({
86
89
  phase: _.phase,
87
90
  muted: _.muted,
88
- spoken: o(_),
91
+ spoken: a(_),
89
92
  holding: R,
90
- graceMs: h
93
+ graceMs: xe
91
94
  });
92
95
  if (!e.arm) return;
93
- let n = setTimeout(() => L(!0), Math.min(800, e.delayMs)), r = c();
96
+ let n = setTimeout(() => L(!0), Math.min(800, e.delayMs)), r = s();
94
97
  return E.current = setTimeout(() => {
95
98
  D.current = {
96
99
  speechEnded: O.current.at ?? r,
97
100
  graceStarted: r,
98
- graceEnded: c()
101
+ graceEnded: s()
99
102
  }, v({
100
103
  type: "silence",
101
104
  at: Date.now()
@@ -106,34 +109,34 @@ function ye({ onSubmit: ye, latestReply: p, language: be, graceMs: xe, onSuperse
106
109
  }, [
107
110
  _,
108
111
  R,
109
- h
110
- ]), u(() => {
112
+ xe
113
+ ]), l(() => {
111
114
  (_.phase !== "listening" || _.muted) && z(!1);
112
- }, [_.phase, _.muted]), u(() => {
115
+ }, [_.phase, _.muted]), l(() => {
113
116
  if (!P) return;
114
- let e = Date.now() - we.current, t = X.isListening ? Math.max(0, 500 - e) : Math.max(0, te - e), n = setTimeout(() => F(!1), t);
117
+ let e = Date.now() - Te.current, t = X.isListening ? Math.max(0, 500 - e) : Math.max(0, te - e), n = setTimeout(() => F(!1), t);
115
118
  return () => clearTimeout(n);
116
119
  }, [P, X.isListening]);
117
- let Ee = d("");
118
- _.phase === "listening" && (Ee.current = o(_)), u(() => {
120
+ let De = u("");
121
+ _.phase === "listening" && (De.current = a(_)), l(() => {
119
122
  if (_.phase !== "thinking") return;
120
123
  x(!1), W();
121
- let e = Ee.current.trim();
122
- e && ye(e, Z.current ?? `vs-orphan-${Date.now().toString(36)}`, D.current, { correction: B.current.correcting }), D.current = {}, O.current = i;
123
- }, [_.phase]), u(() => {
124
- let e = ae(p?.id, _.phase, k.current, s(p?.id));
124
+ let e = De.current.trim();
125
+ e && f(e, Q.current ?? `vs-orphan-${Date.now().toString(36)}`, D.current, { correction: B.current.correcting }), D.current = {}, O.current = i;
126
+ }, [_.phase]), l(() => {
127
+ let e = oe(p?.id, _.phase, k.current, o(p?.id));
125
128
  e.claim && (k.current = p?.id ?? null, e.advance && p && v({
126
129
  type: "reply",
127
130
  text: p.text
128
131
  }));
129
- }, [p, _.phase]), u(() => {
132
+ }, [p, _.phase]), l(() => {
130
133
  if (S === null || _.phase !== "thinking" || k.current === S) return;
131
- if (s(S)) {
134
+ if (o(S)) {
132
135
  C();
133
136
  return;
134
137
  }
135
138
  let e = r.peek(S);
136
- !e || e.channel !== "voice" || e.voiceSessionId === void 0 || e.voiceSessionId !== Z.current || (k.current = S, j.current = {
139
+ !e || e.channel !== "voice" || e.voiceSessionId === void 0 || e.voiceSessionId !== Q.current || (k.current = S, j.current = {
137
140
  id: S,
138
141
  text: e.text
139
142
  }, v({
@@ -144,41 +147,41 @@ function ye({ onSubmit: ye, latestReply: p, language: be, graceMs: xe, onSuperse
144
147
  S,
145
148
  _.phase,
146
149
  C
147
- ]), u(() => {
150
+ ]), l(() => {
148
151
  let e = S !== null;
149
152
  A.current && !e && (H.current = null, (B.current.phase !== "speaking" || !G()) && v({ type: "speech-ended" })), A.current = e;
150
- }, [S, G]), u(() => {
153
+ }, [S, G]), l(() => {
151
154
  _.phase !== "listening" && N((e) => e === "nothing-heard" ? null : e);
152
- }, [_.phase]), u(() => {
155
+ }, [_.phase]), l(() => {
153
156
  if (_.phase !== "speaking" || S !== null) return;
154
157
  let e = setTimeout(() => {
155
158
  A.current || (W(), v({ type: "speech-ended" }));
156
- }, me);
159
+ }, he);
157
160
  return () => clearTimeout(e);
158
161
  }, [
159
162
  _.phase,
160
163
  S,
161
164
  W
162
165
  ]);
163
- let De = d(m);
164
- De.current = m;
165
- let Oe = d(0);
166
- u(() => {
166
+ let Oe = u(h);
167
+ Oe.current = h;
168
+ let Z = u(0);
169
+ l(() => {
167
170
  let e = _.superseded;
168
- e !== Oe.current && (Oe.current = e, e !== 0 && (W(), C(), De.current?.()));
171
+ e !== Z.current && (Z.current = e, e !== 0 && (W(), C(), Oe.current?.()));
169
172
  }, [
170
173
  _.superseded,
171
174
  W,
172
175
  C
173
- ]), u(() => {
174
- x(a(_)), se(_) ? X.isActive || X.start("auto") : X.isActive && X.stop();
176
+ ]), l(() => {
177
+ x(re(_)), ce(_) ? X.isActive || X.start("auto") : X.isActive && X.stop();
175
178
  }, [
176
179
  _,
177
180
  X,
178
181
  x
179
- ]), u(() => {
182
+ ]), l(() => {
180
183
  _.phase !== "speaking" || !U.current || (U.current = !1, G() || v({ type: "speech-ended" }));
181
- }, [_.phase, G]), u(() => {
184
+ }, [_.phase, G]), l(() => {
182
185
  X.error === "not-allowed" || X.error === "audio-capture" ? v({
183
186
  type: "fail",
184
187
  error: "mic-denied"
@@ -186,20 +189,20 @@ function ye({ onSubmit: ye, latestReply: p, language: be, graceMs: xe, onSuperse
186
189
  type: "fail",
187
190
  error: "no-speech-support"
188
191
  }) : X.error === "network" ? N("network") : X.error === "unknown" && N("recognition-failed");
189
- }, [X.error]), u(() => {
192
+ }, [X.error]), l(() => {
190
193
  X.error !== null || !X.isListening || N((e) => e === "network" || e === "recognition-failed" ? null : e);
191
- }, [X.error, X.isListening]), u(() => {
192
- if (X.isListening && N((e) => e === "not-capturing" ? null : e), !a(_) || X.isListening) return;
193
- let e = setTimeout(() => N("not-capturing"), ge);
194
+ }, [X.error, X.isListening]), l(() => {
195
+ if (X.isListening && N((e) => e === "not-capturing" ? null : e), !re(_) || X.isListening) return;
196
+ let e = setTimeout(() => N("not-capturing"), _e);
194
197
  return () => clearTimeout(e);
195
- }, [_, X.isListening]), u(() => {
196
- if (_.phase !== "listening" || _.muted || !X.isListening || o(_) !== "") return;
197
- let e = setTimeout(() => N("nothing-heard"), _e);
198
+ }, [_, X.isListening]), l(() => {
199
+ if (_.phase !== "listening" || _.muted || !X.isListening || a(_) !== "") return;
200
+ let e = setTimeout(() => N("nothing-heard"), ve);
198
201
  return () => clearTimeout(e);
199
- }, [_, X.isListening]), u(() => {
200
- o(_) !== "" && N(null);
202
+ }, [_, X.isListening]), l(() => {
203
+ a(_) !== "" && N(null);
201
204
  }, [_]);
202
- let Z = d(null), Q = l(() => {
205
+ let Q = u(null), ke = c(() => {
203
206
  if (F(!1), L(!1), z(!1), W(), K.current = !1, !X.isSupported) {
204
207
  v({
205
208
  type: "fail",
@@ -223,30 +226,30 @@ function ye({ onSubmit: ye, latestReply: p, language: be, graceMs: xe, onSuperse
223
226
  } catch {}
224
227
  try {
225
228
  if (typeof window < "u" && typeof window.Audio == "function") {
226
- let e = new window.Audio(ve);
229
+ let e = new window.Audio(ye);
227
230
  e.volume = 0, e.play().catch(() => {});
228
231
  }
229
232
  } catch {}
230
- b(!0), N(null), k.current = Ce.current?.id ?? null, j.current = null, Z.current = `vs-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`, v({ type: "start" });
233
+ b(!0), N(null), k.current = Ce.current?.id ?? null, j.current = null, Q.current = `vs-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`, v({ type: "start" });
231
234
  }, [
232
235
  X.isSupported,
233
236
  y.isBlocked,
234
237
  b,
235
238
  W
236
- ]), ke = l(() => {
237
- F(!1), L(!1), z(!1), W(), K.current = !1, Z.current = null, v({ type: "end" }), C(), b(!1);
239
+ ]), Ae = c(() => {
240
+ F(!1), L(!1), z(!1), W(), K.current = !1, Q.current = null, v({ type: "end" }), C(), b(!1);
238
241
  }, [
239
242
  C,
240
243
  b,
241
244
  W
242
- ]), Ae = l((e) => Z.current === e, []), je = l(() => {
245
+ ]), je = c((e) => Q.current === e, []), Me = c(() => {
243
246
  let e = B.current;
244
247
  e.phase !== "listening" || e.muted || z(!0);
245
- }, []), Me = l(() => {
248
+ }, []), Ne = c(() => {
246
249
  z(!1);
247
250
  let e = B.current;
248
- if (e.phase !== "listening" || e.muted || !re(o(e))) return;
249
- let t = c();
251
+ if (e.phase !== "listening" || e.muted || !ie(a(e))) return;
252
+ let t = s();
250
253
  D.current = {
251
254
  speechEnded: O.current.at ?? t,
252
255
  graceStarted: t,
@@ -255,17 +258,17 @@ function ye({ onSubmit: ye, latestReply: p, language: be, graceMs: xe, onSuperse
255
258
  type: "silence",
256
259
  at: Date.now()
257
260
  });
258
- }, []), Ne = l(() => {
261
+ }, []), Pe = c(() => {
259
262
  v({
260
263
  type: "mute",
261
264
  muted: !B.current.muted
262
265
  });
263
266
  }, []);
264
- u(() => () => {
267
+ l(() => () => {
265
268
  b(!1), x(!1);
266
269
  }, [b, x]);
267
- let $ = le(y.spokenChunks, _.phase, S);
268
- return fe(() => ({
270
+ let $ = ue(y.spokenChunks, _.phase, S);
271
+ return pe(() => ({
269
272
  session: _,
270
273
  notice: M,
271
274
  spokenChunks: $,
@@ -276,13 +279,13 @@ function ye({ onSubmit: ye, latestReply: p, language: be, graceMs: xe, onSuperse
276
279
  holding: R,
277
280
  correcting: _.correcting,
278
281
  available: X.isSupported && !y.isBlocked,
279
- start: Q,
280
- end: ke,
281
- isCurrentSession: Ae,
282
- toggleMute: Ne,
283
- interrupt: Te,
284
- letMeFinish: je,
285
- imDone: Me,
282
+ start: ke,
283
+ end: Ae,
284
+ isCurrentSession: je,
285
+ toggleMute: Pe,
286
+ interrupt: Ee,
287
+ letMeFinish: Me,
288
+ imDone: Ne,
286
289
  announce: J,
287
290
  holdListening: q,
288
291
  answerLocally: Se
@@ -296,17 +299,17 @@ function ye({ onSubmit: ye, latestReply: p, language: be, graceMs: xe, onSuperse
296
299
  X.isSupported,
297
300
  y.isBlocked,
298
301
  $,
299
- Q,
300
302
  ke,
301
303
  Ae,
302
- Ne,
303
- Te,
304
304
  je,
305
+ Pe,
306
+ Ee,
305
307
  Me,
308
+ Ne,
306
309
  J,
307
310
  q,
308
311
  Se
309
312
  ]);
310
313
  }
311
314
  //#endregion
312
- export { ye as useVoiceSession };
315
+ export { f as useVoiceSession };
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Bare affirmations, per speaking language (BOFF-8613, F1b).
3
+ *
4
+ * `classifyWriteReply` is an ENGLISH classifier: for any other locale it
5
+ * answers "other". `planThinkingSpeech` used to call it with a hard-coded
6
+ * "en", so a Hindi "हाँ", a Tamil "சரி", a Spanish "vale", an Arabic "نعم" or a
7
+ * Chinese "好的" said while an answer was being prepared was not a bare
8
+ * affirmation at all: it aborted the turn and re-sent it as a correction.
9
+ *
10
+ * Nothing here approves or commits anything. This file only answers "is this
11
+ * utterance nothing but a yes?", so that `planThinkingSpeech` can leave the
12
+ * turn alone. The binder, and the card's button, stay the only way a change is
13
+ * confirmed.
14
+ *
15
+ * Pure data in, answer out: no DOM, no timers.
16
+ */
17
+ /** The languages the assistant is offered in (`languages.ts`). */
18
+ export type AffirmationLanguage = "en" | "hi" | "ta" | "es" | "ar" | "zh";
19
+ /**
20
+ * "hi-IN", "ta_IN", "zh-Hant-TW" -> the language this module has a lexicon
21
+ * for. Anything unknown (or absent) is English: that is what the assistant
22
+ * classified with before this module existed, so a new locale degrades to the
23
+ * old behaviour and never to a looser one.
24
+ */
25
+ export declare function resolveAffirmationLanguage(language: string | null | undefined): AffirmationLanguage;
26
+ /**
27
+ * Is this utterance NOTHING but a yes, in the language being spoken?
28
+ *
29
+ * English is the 5a classifier itself, so "yes please thanks" and "ok go
30
+ * ahead" mean here exactly what they mean to the binder. The other languages
31
+ * use the lexicons above. A yes WITH a change ("yes but make it 9", "好的但是
32
+ * 改成九点") is not bare: it is a correction.
33
+ */
34
+ export declare function isBareAffirmation(text: string, language: string | null | undefined): boolean;
35
+ /**
36
+ * Does the utterance hold anything that is not a yes (or part of one)?
37
+ *
38
+ * "ok go" is made only of the tokens of "ok" and "go ahead": it is the START
39
+ * of a yes, and nothing yet to correct. "ok go ahead and plant ragi" has
40
+ * content. `interim` lets the last token be a prefix of a yes token, because a
41
+ * live guess can end mid-word ("ok go ahe").
42
+ */
43
+ export declare function hasContentBeyondAffirmation(text: string, language: string | null | undefined, interim?: boolean): boolean;
44
+ //# sourceMappingURL=affirmations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"affirmations.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/voice/affirmations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,kEAAkE;AAClE,MAAM,MAAM,mBAAmB,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAiL1E;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,mBAAmB,CAYnG;AAoFD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAM5F;AAED;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACnC,OAAO,UAAQ,GACd,OAAO,CAcT"}