@burdenoff/fe-libs 2026.926.2 → 2026.926.4

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 (64) hide show
  1. package/dist/shared/assistant/autoRouting.d.ts +1 -0
  2. package/dist/shared/assistant/autoRouting.d.ts.map +1 -1
  3. package/dist/shared/assistant/autoRouting.js +1 -1
  4. package/dist/shared/assistant/capabilities.d.ts +5 -0
  5. package/dist/shared/assistant/capabilities.d.ts.map +1 -1
  6. package/dist/shared/assistant/capabilities.js +2 -1
  7. package/dist/shared/assistant/conversation.d.ts +29 -0
  8. package/dist/shared/assistant/conversation.d.ts.map +1 -1
  9. package/dist/shared/assistant/guardedStorage.d.ts +32 -0
  10. package/dist/shared/assistant/guardedStorage.d.ts.map +1 -0
  11. package/dist/shared/assistant/guardedStorage.js +36 -0
  12. package/dist/shared/assistant/i18nManifest.d.ts +7 -0
  13. package/dist/shared/assistant/i18nManifest.d.ts.map +1 -1
  14. package/dist/shared/assistant/i18nManifest.js +7 -0
  15. package/dist/shared/assistant/index.d.ts +5 -0
  16. package/dist/shared/assistant/index.d.ts.map +1 -1
  17. package/dist/shared/assistant/liveTurns.d.ts +145 -0
  18. package/dist/shared/assistant/liveTurns.d.ts.map +1 -0
  19. package/dist/shared/assistant/liveTurns.js +99 -0
  20. package/dist/shared/assistant/operations.d.ts +7 -0
  21. package/dist/shared/assistant/operations.d.ts.map +1 -1
  22. package/dist/shared/assistant/operations.js +2 -2
  23. package/dist/shared/assistant/prewarm.d.ts +32 -4
  24. package/dist/shared/assistant/prewarm.d.ts.map +1 -1
  25. package/dist/shared/assistant/prewarm.js +35 -15
  26. package/dist/shared/assistant/product.d.ts +11 -1
  27. package/dist/shared/assistant/product.d.ts.map +1 -1
  28. package/dist/shared/assistant/product.js +8 -6
  29. package/dist/shared/assistant/store.d.ts.map +1 -1
  30. package/dist/shared/assistant/store.js +11 -10
  31. package/dist/shared/assistant/turnState.d.ts +12 -0
  32. package/dist/shared/assistant/turnState.d.ts.map +1 -1
  33. package/dist/shared/assistant/turnState.js +4 -1
  34. package/dist/shared/assistant/turnTimeline.d.ts +37 -3
  35. package/dist/shared/assistant/turnTimeline.d.ts.map +1 -1
  36. package/dist/shared/assistant/turnTimeline.js +45 -33
  37. package/dist/shared/assistant/turnTimingReport.d.ts +86 -0
  38. package/dist/shared/assistant/turnTimingReport.d.ts.map +1 -0
  39. package/dist/shared/assistant/turnTimingReport.js +123 -0
  40. package/dist/shared/assistant/turnTimingReporter.d.ts +146 -0
  41. package/dist/shared/assistant/turnTimingReporter.d.ts.map +1 -0
  42. package/dist/shared/assistant/turnTimingReporter.js +321 -0
  43. package/dist/shared/assistant/ui/AssistantChatArea.d.ts.map +1 -1
  44. package/dist/shared/assistant/ui/AssistantChatArea.js +703 -544
  45. package/dist/shared/assistant/ui/AssistantMessageItem.d.ts +19 -0
  46. package/dist/shared/assistant/ui/AssistantMessageItem.d.ts.map +1 -1
  47. package/dist/shared/assistant/ui/AssistantMessageItem.js +92 -88
  48. package/dist/shared/assistant/ui/AssistantMessageList.d.ts +22 -2
  49. package/dist/shared/assistant/ui/AssistantMessageList.d.ts.map +1 -1
  50. package/dist/shared/assistant/ui/AssistantMessageList.js +37 -36
  51. package/dist/shared/assistant/ui/AssistantPendingWriteCard.d.ts +34 -0
  52. package/dist/shared/assistant/ui/AssistantPendingWriteCard.d.ts.map +1 -1
  53. package/dist/shared/assistant/ui/AssistantPendingWriteCard.js +31 -28
  54. package/dist/shared/assistant/ui/useVoiceSession.d.ts +1 -0
  55. package/dist/shared/assistant/ui/useVoiceSession.d.ts.map +1 -1
  56. package/dist/shared/assistant/ui/useVoiceSession.js +119 -117
  57. package/dist/shared/assistant/voice/voiceReopen.d.ts +117 -0
  58. package/dist/shared/assistant/voice/voiceReopen.d.ts.map +1 -0
  59. package/dist/shared/assistant/voice/voiceReopen.js +49 -0
  60. package/dist/shared/graphql/fetch.d.ts +10 -0
  61. package/dist/shared/graphql/fetch.d.ts.map +1 -1
  62. package/dist/shared/graphql/fetch.js +64 -62
  63. package/dist/shared-assistant.js +136 -131
  64. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"useVoiceSession.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/ui/useVoiceSession.ts"],"names":[],"mappings":"AASA,OAAO,EAAe,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEpE,OAAO,EAcL,KAAK,oBAAoB,EAE1B,MAAM,uBAAuB,CAAC;AAsC/B;;;;;;;;GAQG;AACH,MAAM,MAAM,kBAAkB,GAC5B,SAAS,GAAG,eAAe,GAAG,eAAe,GAAG,oBAAoB,CAAC;AAMvE,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,KACpB,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;CAClB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,OAAO;;IA0kBtE,qEAAqE;;IAErE;;;;;;;OAOG;;;;;IAEH,+DAA+D;;IAE/D;;;;;;;OAOG;;IAIH,0EAA0E;;IAE1E,6DAA6D;;IAE7D,sDAAsD;;;;;;EA4B3D"}
1
+ {"version":3,"file":"useVoiceSession.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/ui/useVoiceSession.ts"],"names":[],"mappings":"AASA,OAAO,EAAe,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEpE,OAAO,EAcL,KAAK,oBAAoB,EAE1B,MAAM,uBAAuB,CAAC;AAsC/B;;;;;;;;GAQG;AACH,MAAM,MAAM,kBAAkB,GAC5B,SAAS,GAAG,eAAe,GAAG,eAAe,GAAG,oBAAoB,CAAC;AAMvE,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,KACpB,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;CAClB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,OAAO;;IAqlBtE,qEAAqE;;IAErE;;;;;;;OAOG;;;;;IAEH,+DAA+D;;IAE/D;;;;;;;OAOG;;IAIH,0EAA0E;;IAE1E,6DAA6D;;IAE7D,sDAAsD;;;;uCAzDvC,MAAM;;;EAuF1B"}
@@ -1,117 +1,117 @@
1
1
  import { useVoiceInput as e } from "../voice/useVoiceInput.js";
2
- import { INITIAL_SESSION as t, INTERRUPT_MAX_MS as n, NOTHING_HEARD as r, SILENCE_SUBMIT_MS as i, advanceHeardClock as a, isCapturing as o, isSubmittable as s, planReplyConsumption as c, spokenSoFar as l, voiceSessionReducer as ee } from "../voice/voiceSession.js";
3
- import { turnClockMs as u } from "../turnTimeline.js";
4
- import { useAssistantSpeech as d } from "./AssistantSpeechProvider.js";
5
- import { useCallback as f, useEffect as p, useMemo as m, useReducer as h, useRef as g, useState as _ } from "react";
2
+ import { INITIAL_SESSION as t, INTERRUPT_MAX_MS as n, NOTHING_HEARD as r, SILENCE_SUBMIT_MS as i, advanceHeardClock as a, isCapturing as o, isSubmittable as ee, planReplyConsumption as te, spokenSoFar as s, voiceSessionReducer as c } from "../voice/voiceSession.js";
3
+ import { turnClockMs as l } from "../turnTimeline.js";
4
+ import { useAssistantSpeech as ne } from "./AssistantSpeechProvider.js";
5
+ import { useCallback as u, useEffect as d, useMemo as f, useReducer as p, useRef as m, useState as h } from "react";
6
6
  //#region src/shared/assistant/ui/useVoiceSession.ts
7
- var v = 4e3, te = 2500, ne = 5e3, y = 12e3, b = "data:audio/wav;base64,UklGRiQAAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQAAAAA=";
8
- function x({ onSubmit: x, latestReply: S, language: C }) {
9
- let w = g(null), [T, E] = h(f((e, t) => ee(e, t, w.current), []), t), D = d(), { setSessionSpeaking: O, setSessionMicOpen: k, speakingMessageId: A, stop: j } = D, M = g(null), N = g({}), P = g(r), F = g(null), I = g(!1), [L, R] = _(null), [z, B] = _(!1), [V, H] = _(!1), U = g(T);
10
- U.current = T;
11
- let W = g(S);
12
- W.current = S, p(() => {
13
- if (T.phase === "speaking") {
14
- w.current = S?.text ?? null;
7
+ var g = 4e3, _ = 2500, re = 5e3, v = 12e3, y = "data:audio/wav;base64,UklGRiQAAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQAAAAA=";
8
+ function b({ onSubmit: b, latestReply: x, language: S }) {
9
+ let C = m(null), [w, T] = p(u((e, t) => c(e, t, C.current), []), t), E = ne(), { setSessionSpeaking: D, setSessionMicOpen: O, speakingMessageId: k, stop: A } = E, j = m(null), M = m({}), N = m(r), P = m(null), F = m(!1), [I, L] = h(null), [R, z] = h(!1), [B, V] = h(!1), H = m(w);
10
+ H.current = w;
11
+ let U = m(x);
12
+ U.current = x, d(() => {
13
+ if (w.phase === "speaking") {
14
+ C.current = x?.text ?? null;
15
15
  return;
16
16
  }
17
- if (w.current === null) return;
17
+ if (C.current === null) return;
18
18
  let e = setTimeout(() => {
19
- w.current = null;
20
- }, te);
19
+ C.current = null;
20
+ }, _);
21
21
  return () => clearTimeout(e);
22
- }, [T.phase, S]);
23
- let G = f((e, t) => {
24
- E({
22
+ }, [w.phase, x]);
23
+ let W = u((e, t) => {
24
+ T({
25
25
  type: "speech",
26
26
  transcript: e,
27
27
  final: t
28
28
  });
29
- }, []), K = g(0), q = f(() => {
30
- j(), K.current = Date.now(), B(!0), E({ type: "interrupt" });
31
- }, [j]), J = e({
32
- onFinalize: f((e) => G(e, !0), [G]),
33
- language: C
29
+ }, []), G = m(0), K = u(() => {
30
+ A(), G.current = Date.now(), z(!0), T({ type: "interrupt" });
31
+ }, [A]), q = e({
32
+ onFinalize: u((e) => W(e, !0), [W]),
33
+ language: S
34
34
  });
35
- p(() => {
36
- J.interim && G(J.interim, !1);
37
- }, [J.interim, G]), p(() => {
38
- if (M.current && clearTimeout(M.current), H(!1), P.current = a(P.current, T, u()), T.phase !== "listening" || T.muted || !s(l(T))) return;
39
- let e = setTimeout(() => H(!0), 800), t = u();
40
- return M.current = setTimeout(() => {
41
- N.current = {
42
- speechEnded: P.current.at ?? t,
35
+ d(() => {
36
+ q.interim && W(q.interim, !1);
37
+ }, [q.interim, W]), d(() => {
38
+ if (j.current && clearTimeout(j.current), V(!1), N.current = a(N.current, w, l()), w.phase !== "listening" || w.muted || !ee(s(w))) return;
39
+ let e = setTimeout(() => V(!0), 800), t = l();
40
+ return j.current = setTimeout(() => {
41
+ M.current = {
42
+ speechEnded: N.current.at ?? t,
43
43
  graceStarted: t,
44
- graceEnded: u()
45
- }, E({ type: "silence" });
44
+ graceEnded: l()
45
+ }, T({ type: "silence" });
46
46
  }, i), () => {
47
- clearTimeout(e), M.current && clearTimeout(M.current);
47
+ clearTimeout(e), j.current && clearTimeout(j.current);
48
48
  };
49
- }, [T]), p(() => {
50
- if (!z) return;
51
- let e = Date.now() - K.current, t = J.isListening ? Math.max(0, 500 - e) : Math.max(0, n - e), r = setTimeout(() => B(!1), t);
49
+ }, [w]), d(() => {
50
+ if (!R) return;
51
+ let e = Date.now() - G.current, t = q.isListening ? Math.max(0, 500 - e) : Math.max(0, n - e), r = setTimeout(() => z(!1), t);
52
52
  return () => clearTimeout(r);
53
- }, [z, J.isListening]);
54
- let Y = g("");
55
- T.phase === "listening" && (Y.current = l(T)), p(() => {
56
- if (T.phase !== "thinking") return;
57
- k(!1);
58
- let e = Y.current.trim();
59
- e && x(e, X.current ?? `vs-orphan-${Date.now().toString(36)}`, N.current), N.current = {}, P.current = r;
60
- }, [T.phase]), p(() => {
61
- let e = c(S?.id, T.phase, F.current);
62
- e.claim && (F.current = S?.id ?? null, e.advance && S && E({
53
+ }, [R, q.isListening]);
54
+ let J = m("");
55
+ w.phase === "listening" && (J.current = s(w)), d(() => {
56
+ if (w.phase !== "thinking") return;
57
+ O(!1);
58
+ let e = J.current.trim();
59
+ e && b(e, Y.current ?? `vs-orphan-${Date.now().toString(36)}`, M.current), M.current = {}, N.current = r;
60
+ }, [w.phase]), d(() => {
61
+ let e = te(x?.id, w.phase, P.current);
62
+ e.claim && (P.current = x?.id ?? null, e.advance && x && T({
63
63
  type: "reply",
64
- text: S.text
64
+ text: x.text
65
65
  }));
66
- }, [S, T.phase]), p(() => {
67
- let e = A !== null;
68
- I.current && !e && E({ type: "speech-ended" }), I.current = e;
69
- }, [A]), p(() => {
70
- T.phase !== "listening" && R((e) => e === "nothing-heard" ? null : e);
71
- }, [T.phase]), p(() => {
72
- if (T.phase !== "speaking" || A !== null) return;
66
+ }, [x, w.phase]), d(() => {
67
+ let e = k !== null;
68
+ F.current && !e && T({ type: "speech-ended" }), F.current = e;
69
+ }, [k]), d(() => {
70
+ w.phase !== "listening" && L((e) => e === "nothing-heard" ? null : e);
71
+ }, [w.phase]), d(() => {
72
+ if (w.phase !== "speaking" || k !== null) return;
73
73
  let e = setTimeout(() => {
74
- I.current || E({ type: "speech-ended" });
75
- }, v);
74
+ F.current || T({ type: "speech-ended" });
75
+ }, g);
76
76
  return () => clearTimeout(e);
77
- }, [T.phase, A]), p(() => {
78
- let e = o(T);
79
- k(e), e ? J.isActive || J.start("auto") : J.isActive && J.stop();
77
+ }, [w.phase, k]), d(() => {
78
+ let e = o(w);
79
+ O(e), e ? q.isActive || q.start("auto") : q.isActive && q.stop();
80
80
  }, [
81
- T,
82
- J,
83
- k
84
- ]), p(() => {
85
- J.error === "not-allowed" || J.error === "audio-capture" ? E({
81
+ w,
82
+ q,
83
+ O
84
+ ]), d(() => {
85
+ q.error === "not-allowed" || q.error === "audio-capture" ? T({
86
86
  type: "fail",
87
87
  error: "mic-denied"
88
- }) : J.error === "language-not-supported" ? E({
88
+ }) : q.error === "language-not-supported" ? T({
89
89
  type: "fail",
90
90
  error: "no-speech-support"
91
- }) : J.error === "network" ? R("network") : J.error === "unknown" && R("recognition-failed");
92
- }, [J.error]), p(() => {
93
- J.error !== null || !J.isListening || R((e) => e === "network" || e === "recognition-failed" ? null : e);
94
- }, [J.error, J.isListening]), p(() => {
95
- if (J.isListening && R((e) => e === "not-capturing" ? null : e), !o(T) || J.isListening) return;
96
- let e = setTimeout(() => R("not-capturing"), ne);
91
+ }) : q.error === "network" ? L("network") : q.error === "unknown" && L("recognition-failed");
92
+ }, [q.error]), d(() => {
93
+ q.error !== null || !q.isListening || L((e) => e === "network" || e === "recognition-failed" ? null : e);
94
+ }, [q.error, q.isListening]), d(() => {
95
+ if (q.isListening && L((e) => e === "not-capturing" ? null : e), !o(w) || q.isListening) return;
96
+ let e = setTimeout(() => L("not-capturing"), re);
97
97
  return () => clearTimeout(e);
98
- }, [T, J.isListening]), p(() => {
99
- if (T.phase !== "listening" || T.muted || !J.isListening || l(T) !== "") return;
100
- let e = setTimeout(() => R("nothing-heard"), y);
98
+ }, [w, q.isListening]), d(() => {
99
+ if (w.phase !== "listening" || w.muted || !q.isListening || s(w) !== "") return;
100
+ let e = setTimeout(() => L("nothing-heard"), v);
101
101
  return () => clearTimeout(e);
102
- }, [T, J.isListening]), p(() => {
103
- l(T) !== "" && R(null);
104
- }, [T]);
105
- let X = g(null), Z = f(() => {
106
- if (B(!1), H(!1), !J.isSupported) {
107
- E({
102
+ }, [w, q.isListening]), d(() => {
103
+ s(w) !== "" && L(null);
104
+ }, [w]);
105
+ let Y = m(null), X = u(() => {
106
+ if (z(!1), V(!1), !q.isSupported) {
107
+ T({
108
108
  type: "fail",
109
109
  error: "no-speech-support"
110
110
  });
111
111
  return;
112
112
  }
113
- if (D.isBlocked) {
114
- E({
113
+ if (E.isBlocked) {
114
+ T({
115
115
  type: "fail",
116
116
  error: "no-voice-support"
117
117
  });
@@ -126,52 +126,54 @@ function x({ onSubmit: x, latestReply: S, language: C }) {
126
126
  } catch {}
127
127
  try {
128
128
  if (typeof window < "u" && typeof window.Audio == "function") {
129
- let e = new window.Audio(b);
129
+ let e = new window.Audio(y);
130
130
  e.volume = 0, e.play().catch(() => {});
131
131
  }
132
132
  } catch {}
133
- O(!0), R(null), F.current = W.current?.id ?? null, X.current = `vs-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`, E({ type: "start" });
133
+ D(!0), L(null), P.current = U.current?.id ?? null, Y.current = `vs-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`, T({ type: "start" });
134
134
  }, [
135
- J.isSupported,
136
- D.isBlocked,
137
- O
138
- ]), Q = f(() => {
139
- B(!1), H(!1), X.current = null, E({ type: "end" }), j(), O(!1);
140
- }, [j, O]), $ = f(() => {
141
- E({
135
+ q.isSupported,
136
+ E.isBlocked,
137
+ D
138
+ ]), Z = u(() => {
139
+ z(!1), V(!1), Y.current = null, T({ type: "end" }), A(), D(!1);
140
+ }, [A, D]), Q = u((e) => Y.current === e, []), $ = u(() => {
141
+ T({
142
142
  type: "mute",
143
- muted: !U.current.muted
143
+ muted: !H.current.muted
144
144
  });
145
145
  }, []);
146
- return p(() => () => {
147
- O(!1), k(!1);
148
- }, [O, k]), m(() => ({
149
- session: T,
150
- notice: L,
151
- spokenChunks: D.spokenChunks,
152
- capturing: J.isListening,
153
- active: T.phase !== "idle" && (T.phase !== "ended" || T.error !== null),
154
- interrupting: z,
155
- awaitingEndpoint: V,
156
- available: J.isSupported && !D.isBlocked,
157
- start: Z,
158
- end: Q,
146
+ return d(() => () => {
147
+ D(!1), O(!1);
148
+ }, [D, O]), f(() => ({
149
+ session: w,
150
+ notice: I,
151
+ spokenChunks: E.spokenChunks,
152
+ capturing: q.isListening,
153
+ active: w.phase !== "idle" && (w.phase !== "ended" || w.error !== null),
154
+ interrupting: R,
155
+ awaitingEndpoint: B,
156
+ available: q.isSupported && !E.isBlocked,
157
+ start: X,
158
+ end: Z,
159
+ isCurrentSession: Q,
159
160
  toggleMute: $,
160
- interrupt: q
161
+ interrupt: K
161
162
  }), [
162
- T,
163
- L,
164
- z,
165
- V,
166
- J.isListening,
167
- J.isSupported,
168
- D.isBlocked,
169
- D.spokenChunks,
163
+ w,
164
+ I,
165
+ R,
166
+ B,
167
+ q.isListening,
168
+ q.isSupported,
169
+ E.isBlocked,
170
+ E.spokenChunks,
171
+ X,
170
172
  Z,
171
173
  Q,
172
174
  $,
173
- q
175
+ K
174
176
  ]);
175
177
  }
176
178
  //#endregion
177
- export { x as useVoiceSession };
179
+ export { b as useVoiceSession };
@@ -0,0 +1,117 @@
1
+ /**
2
+ * What a reopened conversation does with its spoken turns, and which
3
+ * conversation a live voice session speaks into (BOFF-7335).
4
+ *
5
+ * ★★ Pure, and deliberately free of any voice machinery. Reopening a
6
+ * conversation must SHOW what was said and never start the microphone or play
7
+ * anything; the only effects these planners can produce are "open the
8
+ * read-only transcript", "end the session" and "drop a spoken turn". None can
9
+ * start one.
10
+ */
11
+ /**
12
+ * The conversation a live voice session belongs to.
13
+ *
14
+ * `undefined`: no session is live. `null`: a session is live but has not
15
+ * spoken into any conversation yet — its first turn creates one.
16
+ */
17
+ export type VoiceSessionBinding = string | null | undefined;
18
+ /**
19
+ * Keep a live voice session in the conversation it started in.
20
+ *
21
+ * ★★ The session is bound to a conversation, and the send path is not: every
22
+ * spoken turn goes to whatever conversation is ACTIVE when it is submitted. So
23
+ * opening another conversation from History mid-session, or deleting this one
24
+ * (which opens the next), sent the rest of the spoken exchange — and read the
25
+ * answers aloud — into a conversation the person was no longer talking to. The
26
+ * session now ends instead; nothing is moved.
27
+ *
28
+ * A session that started with no conversation adopts the first one that
29
+ * becomes active — the one its own first turn creates. A conversation the
30
+ * session's own turn starts (the send path records it as the new binding
31
+ * first) is not a switch — provided the caller passes where the store is NOW:
32
+ * the send moves the store and the binding together, after the render the
33
+ * caller's effect belongs to.
34
+ */
35
+ export declare function planVoiceSessionBinding(args: {
36
+ sessionLive: boolean;
37
+ bound: VoiceSessionBinding;
38
+ activeConversationId: string | null;
39
+ /** The bound conversation is still in the store. */
40
+ boundConversationExists: boolean;
41
+ }): {
42
+ bound: VoiceSessionBinding;
43
+ end: boolean;
44
+ };
45
+ /**
46
+ * May a spoken turn still be sent — now, as opposed to when it was asked?
47
+ *
48
+ * ★★ A spoken question with a file still being prepared or uploaded waits for
49
+ * it (up to 20s; a cold files service is slower). Meanwhile the person can
50
+ * open another conversation or delete this one, which ends the session
51
+ * (`planVoiceSessionBinding`) — and the turn, sent once its file settled, went
52
+ * to whatever conversation was open by then: into another thread, or, when
53
+ * the deleted one had been the only conversation, into a NEW conversation
54
+ * started for it. A turn belongs to the exchange that produced it, so it is
55
+ * sent only while that session is still the live one and still speaking into
56
+ * the conversation it was asked in; otherwise it goes nowhere.
57
+ *
58
+ * A session that had not yet spoken into any conversation (`boundAtSubmit`
59
+ * null) has nowhere else it belongs: its turn goes where its session goes.
60
+ */
61
+ export declare function maySendSpokenTurn(args: {
62
+ /** The session that produced the turn is still the live one. */
63
+ sessionLive: boolean;
64
+ /** The session's conversation when the turn was asked. */
65
+ boundAtSubmit: VoiceSessionBinding;
66
+ activeConversationId: string | null;
67
+ /** `boundAtSubmit` is still in the store. */
68
+ boundConversationExists: boolean;
69
+ }): boolean;
70
+ /**
71
+ * Where the automatic transcript opening stands for the conversation now
72
+ * active: decided (`settled`), or still waiting for its messages.
73
+ */
74
+ export interface TranscriptAutoOpenState {
75
+ conversationId: string | null;
76
+ settled: boolean;
77
+ }
78
+ export declare const INITIAL_TRANSCRIPT_AUTO_OPEN: TranscriptAutoOpenState;
79
+ /**
80
+ * Open the read-only transcript when a SPOKEN-ONLY conversation is opened.
81
+ *
82
+ * ★ Spoken turns never enter the typed thread, so a conversation that was only
83
+ * ever spoken reopened as an empty chat with a one-line notice — the whole
84
+ * exchange a click away and easy to miss. It now opens on its transcript, once
85
+ * per opening: closing it is respected until the conversation is opened again.
86
+ *
87
+ * ★★ Only a conversation being REOPENED. One in use right now — a live voice
88
+ * session speaking into it, or a turn in flight — settles without opening:
89
+ * there the person is already on the voice surface, or about to be answered in
90
+ * the thread, and a drawer appearing over either would be an interruption. The
91
+ * drawer offers only Save and Continue in chat, and both need a click.
92
+ *
93
+ * ★ A live session bound to ANOTHER conversation does not make this one in
94
+ * use. Opening this one is what ends that session (`planVoiceSessionBinding`),
95
+ * in the very effect flush this runs in — so reading "a session is live" as
96
+ * "in use" settled the opening shut, and a spoken-only conversation opened
97
+ * mid-session showed an empty chat instead of its transcript.
98
+ *
99
+ * Waits, rather than deciding "not spoken-only", while the conversation holds
100
+ * no messages yet: they may still be loading.
101
+ */
102
+ export declare function planTranscriptAutoOpen(previous: TranscriptAutoOpenState, now: {
103
+ activeConversationId: string | null;
104
+ chatTurnCount: number;
105
+ voiceTurnCount: number;
106
+ sessionLive: boolean;
107
+ /**
108
+ * The conversation the live session speaks into, AFTER this flush's
109
+ * binding decision — see `VoiceSessionBinding`.
110
+ */
111
+ sessionBoundTo: VoiceSessionBinding;
112
+ turnInFlight: boolean;
113
+ }): {
114
+ state: TranscriptAutoOpenState;
115
+ open: boolean;
116
+ };
117
+ //# sourceMappingURL=voiceReopen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voiceReopen.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/voice/voiceReopen.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;;;;GAKG;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;AAE5D;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE;IAC5C,WAAW,EAAE,OAAO,CAAC;IACrB,KAAK,EAAE,mBAAmB,CAAC;IAC3B,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,oDAAoD;IACpD,uBAAuB,EAAE,OAAO,CAAC;CAClC,GAAG;IAAE,KAAK,EAAE,mBAAmB,CAAC;IAAC,GAAG,EAAE,OAAO,CAAA;CAAE,CAY/C;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IACtC,gEAAgE;IAChE,WAAW,EAAE,OAAO,CAAC;IACrB,0DAA0D;IAC1D,aAAa,EAAE,mBAAmB,CAAC;IACnC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,6CAA6C;IAC7C,uBAAuB,EAAE,OAAO,CAAC;CAClC,GAAG,OAAO,CAOV;AAED;;;GAGG;AACH,MAAM,WAAW,uBAAuB;IACtC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,eAAO,MAAM,4BAA4B,EAAE,uBAG1C,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,uBAAuB,EACjC,GAAG,EAAE;IACH,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,cAAc,EAAE,mBAAmB,CAAC;IACpC,YAAY,EAAE,OAAO,CAAC;CACvB,GACA;IAAE,KAAK,EAAE,uBAAuB,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAqBnD"}
@@ -0,0 +1,49 @@
1
+ //#region src/shared/assistant/voice/voiceReopen.ts
2
+ function e(e) {
3
+ return e.sessionLive ? e.bound === void 0 || e.bound === null ? {
4
+ bound: e.activeConversationId,
5
+ end: !1
6
+ } : e.activeConversationId !== e.bound || !e.boundConversationExists ? {
7
+ bound: e.bound,
8
+ end: !0
9
+ } : {
10
+ bound: e.bound,
11
+ end: !1
12
+ } : {
13
+ bound: void 0,
14
+ end: !1
15
+ };
16
+ }
17
+ function t(e) {
18
+ return e.sessionLive ? typeof e.boundAtSubmit == "string" ? e.activeConversationId === e.boundAtSubmit && e.boundConversationExists : !0 : !1;
19
+ }
20
+ var n = {
21
+ conversationId: null,
22
+ settled: !0
23
+ };
24
+ function r(e, t) {
25
+ let n = e.conversationId === t.activeConversationId ? e : {
26
+ conversationId: t.activeConversationId,
27
+ settled: t.activeConversationId === null
28
+ };
29
+ if (n.settled) return {
30
+ state: n,
31
+ open: !1
32
+ };
33
+ let r = {
34
+ ...n,
35
+ settled: !0
36
+ };
37
+ return t.sessionLive && (t.sessionBoundTo === void 0 || t.sessionBoundTo === null || t.sessionBoundTo === t.activeConversationId) || t.turnInFlight || t.chatTurnCount > 0 ? {
38
+ state: r,
39
+ open: !1
40
+ } : t.voiceTurnCount === 0 ? {
41
+ state: n,
42
+ open: !1
43
+ } : {
44
+ state: r,
45
+ open: !0
46
+ };
47
+ }
48
+ //#endregion
49
+ export { n as INITIAL_TRANSCRIPT_AUTO_OPEN, t as maySendSpokenTurn, r as planTranscriptAutoOpen, e as planVoiceSessionBinding };
@@ -46,6 +46,14 @@ export interface GraphQLFetchOptions {
46
46
  extraHeaders?: Record<string, string>;
47
47
  /** AbortSignal for cancellation */
48
48
  signal?: AbortSignal;
49
+ /**
50
+ * Send with fetch `keepalive`, so the request outlives the page — for a
51
+ * last report on `pagehide` / `visibilitychange`. Such a request skips the
52
+ * batching queue: a queued request waits for a timer that an unloading page
53
+ * never runs. Keep the body small; browsers cap in-flight keepalive bodies
54
+ * (64 KiB in total).
55
+ */
56
+ keepalive?: boolean;
49
57
  /**
50
58
  * Skip the global backend-error event (the "[Burdenoff backend error]"
51
59
  * console log + the user-facing error toast/banner) for this call. Use for
@@ -135,6 +143,8 @@ export declare function resolveGatewayUrl(gateway: Gateway, baseUrl?: string): s
135
143
  export interface EnqueueGraphQLFetchOptions {
136
144
  batchMax?: number;
137
145
  batchInterval?: number;
146
+ /** Dispatch at once, outside any batch, with fetch `keepalive`. */
147
+ keepalive?: boolean;
138
148
  }
139
149
  /**
140
150
  * Drop the short-lived GraphQL read caches so the next read of any operation
@@ -1 +1 @@
1
- {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../../src/shared/graphql/fetch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../../src/shared/graphql/fetch.ts"],"names":[],"mappings":"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"}