@burdenoff/fe-libs 2026.928.2 → 2026.929.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 (142) hide show
  1. package/dist/shared/assistant/adminModeSendGate.d.ts +6 -5
  2. package/dist/shared/assistant/adminModeSendGate.d.ts.map +1 -1
  3. package/dist/shared/assistant/adminModeSendGate.js +11 -11
  4. package/dist/shared/assistant/api.d.ts +291 -28
  5. package/dist/shared/assistant/api.d.ts.map +1 -1
  6. package/dist/shared/assistant/api.js +351 -147
  7. package/dist/shared/assistant/autoRouting.d.ts +11 -3
  8. package/dist/shared/assistant/autoRouting.d.ts.map +1 -1
  9. package/dist/shared/assistant/autoRouting.js +7 -7
  10. package/dist/shared/assistant/capabilities.d.ts +28 -0
  11. package/dist/shared/assistant/capabilities.d.ts.map +1 -1
  12. package/dist/shared/assistant/capabilities.js +19 -10
  13. package/dist/shared/assistant/conversation.d.ts +24 -2
  14. package/dist/shared/assistant/conversation.d.ts.map +1 -1
  15. package/dist/shared/assistant/createSandboxAssistantTransport.d.ts.map +1 -1
  16. package/dist/shared/assistant/createSandboxAssistantTransport.js +67 -54
  17. package/dist/shared/assistant/history/historyList.js +1 -1
  18. package/dist/shared/assistant/history/historyMapping.d.ts.map +1 -1
  19. package/dist/shared/assistant/history/historyMapping.js +5 -1
  20. package/dist/shared/assistant/history/historyResume.js +7 -7
  21. package/dist/shared/assistant/i18nManifest.d.ts +53 -0
  22. package/dist/shared/assistant/i18nManifest.d.ts.map +1 -1
  23. package/dist/shared/assistant/i18nManifest.js +75 -16
  24. package/dist/shared/assistant/index.d.ts +15 -0
  25. package/dist/shared/assistant/index.d.ts.map +1 -1
  26. package/dist/shared/assistant/modeCapabilities.js +1 -1
  27. package/dist/shared/assistant/operations.d.ts +22 -0
  28. package/dist/shared/assistant/operations.d.ts.map +1 -1
  29. package/dist/shared/assistant/operations.js +2 -2
  30. package/dist/shared/assistant/prewarm.d.ts +7 -0
  31. package/dist/shared/assistant/prewarm.d.ts.map +1 -1
  32. package/dist/shared/assistant/prewarm.js +1 -1
  33. package/dist/shared/assistant/product.d.ts +80 -2
  34. package/dist/shared/assistant/product.d.ts.map +1 -1
  35. package/dist/shared/assistant/product.js +10 -6
  36. package/dist/shared/assistant/proposalWriteRules.d.ts +40 -0
  37. package/dist/shared/assistant/proposalWriteRules.d.ts.map +1 -0
  38. package/dist/shared/assistant/proposalWriteRules.js +14 -0
  39. package/dist/shared/assistant/store.d.ts +17 -0
  40. package/dist/shared/assistant/store.d.ts.map +1 -1
  41. package/dist/shared/assistant/store.js +50 -43
  42. package/dist/shared/assistant/turnOutcome.d.ts +34 -2
  43. package/dist/shared/assistant/turnOutcome.d.ts.map +1 -1
  44. package/dist/shared/assistant/turnOutcome.js +28 -17
  45. package/dist/shared/assistant/turnOutcomeCopy.d.ts +29 -7
  46. package/dist/shared/assistant/turnOutcomeCopy.d.ts.map +1 -1
  47. package/dist/shared/assistant/turnOutcomeCopy.js +18 -6
  48. package/dist/shared/assistant/types.d.ts +5 -1
  49. package/dist/shared/assistant/types.d.ts.map +1 -1
  50. package/dist/shared/assistant/ui/AssistantApiCallsConsentDialog.js +4 -4
  51. package/dist/shared/assistant/ui/AssistantChatArea.d.ts.map +1 -1
  52. package/dist/shared/assistant/ui/AssistantChatArea.js +989 -718
  53. package/dist/shared/assistant/ui/AssistantConversationList.js +6 -6
  54. package/dist/shared/assistant/ui/AssistantLanguageMenu.js +6 -6
  55. package/dist/shared/assistant/ui/AssistantMessageItem.d.ts +8 -1
  56. package/dist/shared/assistant/ui/AssistantMessageItem.d.ts.map +1 -1
  57. package/dist/shared/assistant/ui/AssistantMessageItem.js +77 -76
  58. package/dist/shared/assistant/ui/AssistantMessageList.d.ts +13 -1
  59. package/dist/shared/assistant/ui/AssistantMessageList.d.ts.map +1 -1
  60. package/dist/shared/assistant/ui/AssistantMessageList.js +15 -13
  61. package/dist/shared/assistant/ui/AssistantReplyLanguageSelector.js +5 -5
  62. package/dist/shared/assistant/ui/AssistantSpeechProvider.js +209 -209
  63. package/dist/shared/assistant/ui/AssistantWriteConfirmDialog.d.ts +62 -0
  64. package/dist/shared/assistant/ui/AssistantWriteConfirmDialog.d.ts.map +1 -0
  65. package/dist/shared/assistant/ui/AssistantWriteConfirmDialog.js +253 -0
  66. package/dist/shared/assistant/ui/AssistantWriteProposalCard.d.ts +72 -0
  67. package/dist/shared/assistant/ui/AssistantWriteProposalCard.d.ts.map +1 -0
  68. package/dist/shared/assistant/ui/AssistantWriteProposalCard.js +439 -0
  69. package/dist/shared/assistant/ui/AssistantWriteProposalSlot.d.ts +40 -0
  70. package/dist/shared/assistant/ui/AssistantWriteProposalSlot.d.ts.map +1 -0
  71. package/dist/shared/assistant/ui/AssistantWriteProposalSlot.js +35 -0
  72. package/dist/shared/assistant/ui/composer/AssistantComposer.js +8 -8
  73. package/dist/shared/assistant/ui/useVoiceSession.d.ts +28 -0
  74. package/dist/shared/assistant/ui/useVoiceSession.d.ts.map +1 -1
  75. package/dist/shared/assistant/ui/useVoiceSession.js +159 -110
  76. package/dist/shared/assistant/ui/useWriteProposalConfirm.d.ts +61 -0
  77. package/dist/shared/assistant/ui/useWriteProposalConfirm.d.ts.map +1 -0
  78. package/dist/shared/assistant/ui/useWriteProposalConfirm.js +109 -0
  79. package/dist/shared/assistant/ui/useWriteProposals.d.ts +102 -0
  80. package/dist/shared/assistant/ui/useWriteProposals.d.ts.map +1 -0
  81. package/dist/shared/assistant/ui/useWriteProposals.js +230 -0
  82. package/dist/shared/assistant/ui/voice/AssistantVoiceSession.d.ts +17 -1
  83. package/dist/shared/assistant/ui/voice/AssistantVoiceSession.d.ts.map +1 -1
  84. package/dist/shared/assistant/ui/voice/AssistantVoiceSession.js +141 -109
  85. package/dist/shared/assistant/ui/writeProposalPresentation.d.ts +76 -0
  86. package/dist/shared/assistant/ui/writeProposalPresentation.d.ts.map +1 -0
  87. package/dist/shared/assistant/ui/writeProposalPresentation.js +110 -0
  88. package/dist/shared/assistant/usageReporting.d.ts +108 -0
  89. package/dist/shared/assistant/usageReporting.d.ts.map +1 -0
  90. package/dist/shared/assistant/usageReporting.js +155 -0
  91. package/dist/shared/assistant/useAssistantApiAccess.d.ts +49 -14
  92. package/dist/shared/assistant/useAssistantApiAccess.d.ts.map +1 -1
  93. package/dist/shared/assistant/useAssistantApiAccess.js +43 -25
  94. package/dist/shared/assistant/useAssistantHeartbeat.d.ts.map +1 -1
  95. package/dist/shared/assistant/useAssistantHeartbeat.js +5 -5
  96. package/dist/shared/assistant/useWorkspaceWriteAccess.d.ts +5 -6
  97. package/dist/shared/assistant/useWorkspaceWriteAccess.d.ts.map +1 -1
  98. package/dist/shared/assistant/voice/voiceSession.d.ts +46 -0
  99. package/dist/shared/assistant/voice/voiceSession.d.ts.map +1 -1
  100. package/dist/shared/assistant/voice/voiceSession.js +35 -2
  101. package/dist/shared/assistant/writeConfirmSeam.d.ts +32 -0
  102. package/dist/shared/assistant/writeConfirmSeam.d.ts.map +1 -0
  103. package/dist/shared/assistant/writeConfirmSeam.js +23 -0
  104. package/dist/shared/assistant/writeModeConsent.d.ts +16 -8
  105. package/dist/shared/assistant/writeModeConsent.d.ts.map +1 -1
  106. package/dist/shared/assistant/writeModeConsent.js +2 -2
  107. package/dist/shared/assistant/writeProposalDiscovery.d.ts +123 -0
  108. package/dist/shared/assistant/writeProposalDiscovery.d.ts.map +1 -0
  109. package/dist/shared/assistant/writeProposalDiscovery.js +210 -0
  110. package/dist/shared/assistant/writeProposalErrorCopy.d.ts +135 -0
  111. package/dist/shared/assistant/writeProposalErrorCopy.d.ts.map +1 -0
  112. package/dist/shared/assistant/writeProposalErrorCopy.js +135 -0
  113. package/dist/shared/assistant/writeProposalVoice.d.ts +133 -0
  114. package/dist/shared/assistant/writeProposalVoice.d.ts.map +1 -0
  115. package/dist/shared/assistant/writeProposalVoice.js +66 -0
  116. package/dist/shared/assistant/writeProposals.d.ts +268 -0
  117. package/dist/shared/assistant/writeProposals.d.ts.map +1 -0
  118. package/dist/shared/assistant/writeProposals.js +445 -0
  119. package/dist/shared/assistant/writeReplyBinder.d.ts +166 -0
  120. package/dist/shared/assistant/writeReplyBinder.d.ts.map +1 -0
  121. package/dist/shared/assistant/writeReplyBinder.js +233 -0
  122. package/dist/shared/assistant/writeReplySend.d.ts +110 -0
  123. package/dist/shared/assistant/writeReplySend.d.ts.map +1 -0
  124. package/dist/shared/assistant/writeReplySend.js +93 -0
  125. package/dist/shared/graphql/fetch.d.ts +12 -1
  126. package/dist/shared/graphql/fetch.d.ts.map +1 -1
  127. package/dist/shared/graphql/fetch.js +101 -80
  128. package/dist/shared/providers/shell/ActiveContextProvider.d.ts.map +1 -1
  129. package/dist/shared/providers/shell/ActiveContextProvider.js +28 -26
  130. package/dist/shared/providers/shell/PersonaSurfaceProvider.d.ts.map +1 -1
  131. package/dist/shared/providers/shell/PersonaSurfaceProvider.js +165 -193
  132. package/dist/shared/providers/shell/personaSurfaceRemote.d.ts +8 -2
  133. package/dist/shared/providers/shell/personaSurfaceRemote.d.ts.map +1 -1
  134. package/dist/shared/providers/shell/personaSurfaceRemote.js +37 -15
  135. package/dist/shared/providers/shell/useRemoteNavPreferences.d.ts +30 -0
  136. package/dist/shared/providers/shell/useRemoteNavPreferences.d.ts.map +1 -0
  137. package/dist/shared/providers/shell/useRemoteNavPreferences.js +43 -0
  138. package/dist/shared-assistant.js +167 -152
  139. package/dist/ui/modal-shell.d.ts +14 -1
  140. package/dist/ui/modal-shell.d.ts.map +1 -1
  141. package/dist/ui/modal-shell.js +8 -6
  142. package/package.json +2 -2
@@ -1,117 +1,157 @@
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 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";
2
+ import { INITIAL_SESSION as t, INTERRUPT_MAX_MS as ee, NOTHING_HEARD as n, SILENCE_SUBMIT_MS as te, advanceHeardClock as ne, isCapturing as r, isSubmittable as re, planListeningHold as ie, planReplyConsumption as ae, planVoiceAnnouncement as oe, spokenSoFar as i, voiceSessionReducer as se } from "../voice/voiceSession.js";
3
+ import { turnClockMs as a } from "../turnTimeline.js";
4
+ import { useAssistantSpeech as ce } from "./AssistantSpeechProvider.js";
5
+ import { useCallback as o, useEffect as s, useLayoutEffect as c, useMemo as le, useReducer as ue, useRef as l, useState as u } from "react";
6
6
  //#region src/shared/assistant/ui/useVoiceSession.ts
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;
7
+ var de = 4e3, fe = 2500, pe = 5e3, me = 12e3, he = "data:audio/wav;base64,UklGRiQAAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQAAAAA=";
8
+ function d({ onSubmit: d, latestReply: f, language: ge }) {
9
+ let p = l(null), [m, h] = ue(o((e, t) => se(e, t, p.current), []), t), g = ce(), { setSessionSpeaking: _, setSessionMicOpen: v, speakingMessageId: y, stop: b } = g, x = l(g.toggle), S = g.toggle;
10
+ c(() => {
11
+ x.current = S;
12
+ }, [S]);
13
+ let C = l(null), w = l({}), T = l(n), E = l(null), D = l(!1), [O, k] = u(null), [A, j] = u(!1), [M, N] = u(!1), P = l(m);
14
+ P.current = m;
15
+ let F = l([]), I = l(null), L = l(!1), R = o(() => {
16
+ F.current = [], I.current = null, L.current = !1;
17
+ }, []), z = o(() => {
18
+ for (;;) {
19
+ let e = F.current.shift();
20
+ if (!e) return !1;
21
+ if (!(e.stillWanted && !e.stillWanted())) {
22
+ I.current = e, p.current = p.current ? `${p.current} ${e.text}` : e.text;
23
+ try {
24
+ x.current(e.id, e.text, e.lang);
25
+ } catch {
26
+ I.current = null;
27
+ continue;
28
+ }
29
+ return !0;
30
+ }
31
+ }
32
+ }, []), B = l(!1), V = o((e) => {
33
+ let t = ie({
34
+ requested: e,
35
+ held: B.current,
36
+ muted: P.current.muted
37
+ });
38
+ B.current = t.held, t.mute !== null && h({
39
+ type: "mute",
40
+ muted: t.mute
41
+ });
42
+ }, []), H = o((e) => {
43
+ let t = oe(P.current);
44
+ t !== "drop" && (I.current?.id === e.id || F.current.some((t) => t.id === e.id) || (F.current.push(e), t === "start" && !L.current && (L.current = !0, h({ type: "announce" }))));
45
+ }, []), U = l(f);
46
+ U.current = f, s(() => {
47
+ if (m.phase === "speaking") {
48
+ p.current = f?.text ?? null;
15
49
  return;
16
50
  }
17
- if (C.current === null) return;
51
+ if (p.current === null) return;
18
52
  let e = setTimeout(() => {
19
- C.current = null;
20
- }, _);
53
+ p.current = null;
54
+ }, fe);
21
55
  return () => clearTimeout(e);
22
- }, [w.phase, x]);
23
- let W = u((e, t) => {
24
- T({
56
+ }, [m.phase, f]);
57
+ let W = o((e, t) => {
58
+ h({
25
59
  type: "speech",
26
60
  transcript: e,
27
61
  final: t
28
62
  });
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
63
+ }, []), G = l(0), K = o(() => {
64
+ R(), b(), G.current = Date.now(), j(!0), h({ type: "interrupt" });
65
+ }, [b, R]), q = e({
66
+ onFinalize: o((e) => W(e, !0), [W]),
67
+ language: ge
34
68
  });
35
- d(() => {
69
+ s(() => {
36
70
  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,
71
+ }, [q.interim, W]), s(() => {
72
+ if (C.current && clearTimeout(C.current), N(!1), T.current = ne(T.current, m, a()), m.phase !== "listening" || m.muted || !re(i(m))) return;
73
+ let e = setTimeout(() => N(!0), 800), t = a();
74
+ return C.current = setTimeout(() => {
75
+ w.current = {
76
+ speechEnded: T.current.at ?? t,
43
77
  graceStarted: t,
44
- graceEnded: l()
45
- }, T({ type: "silence" });
46
- }, i), () => {
47
- clearTimeout(e), j.current && clearTimeout(j.current);
78
+ graceEnded: a()
79
+ }, h({ type: "silence" });
80
+ }, te), () => {
81
+ clearTimeout(e), C.current && clearTimeout(C.current);
48
82
  };
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
- return () => clearTimeout(r);
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);
83
+ }, [m]), s(() => {
84
+ if (!A) return;
85
+ let e = Date.now() - G.current, t = q.isListening ? Math.max(0, 500 - e) : Math.max(0, ee - e), n = setTimeout(() => j(!1), t);
86
+ return () => clearTimeout(n);
87
+ }, [A, q.isListening]);
88
+ let J = l("");
89
+ m.phase === "listening" && (J.current = i(m)), s(() => {
90
+ if (m.phase !== "thinking") return;
91
+ v(!1), R();
58
92
  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({
93
+ e && d(e, Y.current ?? `vs-orphan-${Date.now().toString(36)}`, w.current), w.current = {}, T.current = n;
94
+ }, [m.phase]), s(() => {
95
+ let e = ae(f?.id, m.phase, E.current);
96
+ e.claim && (E.current = f?.id ?? null, e.advance && f && h({
63
97
  type: "reply",
64
- text: x.text
98
+ text: f.text
65
99
  }));
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;
100
+ }, [f, m.phase]), s(() => {
101
+ let e = y !== null;
102
+ D.current && !e && (I.current = null, (P.current.phase !== "speaking" || !z()) && h({ type: "speech-ended" })), D.current = e;
103
+ }, [y, z]), s(() => {
104
+ m.phase !== "listening" && k((e) => e === "nothing-heard" ? null : e);
105
+ }, [m.phase]), s(() => {
106
+ if (m.phase !== "speaking" || y !== null) return;
73
107
  let e = setTimeout(() => {
74
- F.current || T({ type: "speech-ended" });
75
- }, g);
108
+ D.current || (R(), h({ type: "speech-ended" }));
109
+ }, de);
76
110
  return () => clearTimeout(e);
77
- }, [w.phase, k]), d(() => {
78
- let e = o(w);
79
- O(e), e ? q.isActive || q.start("auto") : q.isActive && q.stop();
80
111
  }, [
81
- w,
112
+ m.phase,
113
+ y,
114
+ R
115
+ ]), s(() => {
116
+ let e = r(m);
117
+ v(e), e ? q.isActive || q.start("auto") : q.isActive && q.stop();
118
+ }, [
119
+ m,
82
120
  q,
83
- O
84
- ]), d(() => {
85
- q.error === "not-allowed" || q.error === "audio-capture" ? T({
121
+ v
122
+ ]), s(() => {
123
+ m.phase !== "speaking" || !L.current || (L.current = !1, z() || h({ type: "speech-ended" }));
124
+ }, [m.phase, z]), s(() => {
125
+ q.error === "not-allowed" || q.error === "audio-capture" ? h({
86
126
  type: "fail",
87
127
  error: "mic-denied"
88
- }) : q.error === "language-not-supported" ? T({
128
+ }) : q.error === "language-not-supported" ? h({
89
129
  type: "fail",
90
130
  error: "no-speech-support"
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);
131
+ }) : q.error === "network" ? k("network") : q.error === "unknown" && k("recognition-failed");
132
+ }, [q.error]), s(() => {
133
+ q.error !== null || !q.isListening || k((e) => e === "network" || e === "recognition-failed" ? null : e);
134
+ }, [q.error, q.isListening]), s(() => {
135
+ if (q.isListening && k((e) => e === "not-capturing" ? null : e), !r(m) || q.isListening) return;
136
+ let e = setTimeout(() => k("not-capturing"), pe);
97
137
  return () => clearTimeout(e);
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);
138
+ }, [m, q.isListening]), s(() => {
139
+ if (m.phase !== "listening" || m.muted || !q.isListening || i(m) !== "") return;
140
+ let e = setTimeout(() => k("nothing-heard"), me);
101
141
  return () => clearTimeout(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({
142
+ }, [m, q.isListening]), s(() => {
143
+ i(m) !== "" && k(null);
144
+ }, [m]);
145
+ let Y = l(null), X = o(() => {
146
+ if (j(!1), N(!1), R(), B.current = !1, !q.isSupported) {
147
+ h({
108
148
  type: "fail",
109
149
  error: "no-speech-support"
110
150
  });
111
151
  return;
112
152
  }
113
- if (E.isBlocked) {
114
- T({
153
+ if (g.isBlocked) {
154
+ h({
115
155
  type: "fail",
116
156
  error: "no-voice-support"
117
157
  });
@@ -126,54 +166,63 @@ function b({ onSubmit: b, latestReply: x, language: S }) {
126
166
  } catch {}
127
167
  try {
128
168
  if (typeof window < "u" && typeof window.Audio == "function") {
129
- let e = new window.Audio(y);
169
+ let e = new window.Audio(he);
130
170
  e.volume = 0, e.play().catch(() => {});
131
171
  }
132
172
  } catch {}
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" });
173
+ _(!0), k(null), E.current = U.current?.id ?? null, Y.current = `vs-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`, h({ type: "start" });
134
174
  }, [
135
175
  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({
176
+ g.isBlocked,
177
+ _,
178
+ R
179
+ ]), Z = o(() => {
180
+ j(!1), N(!1), R(), B.current = !1, Y.current = null, h({ type: "end" }), b(), _(!1);
181
+ }, [
182
+ b,
183
+ _,
184
+ R
185
+ ]), Q = o((e) => Y.current === e, []), $ = o(() => {
186
+ h({
142
187
  type: "mute",
143
- muted: !H.current.muted
188
+ muted: !P.current.muted
144
189
  });
145
190
  }, []);
146
- return d(() => () => {
147
- D(!1), O(!1);
148
- }, [D, O]), f(() => ({
149
- session: w,
150
- notice: I,
151
- spokenChunks: E.spokenChunks,
191
+ return s(() => () => {
192
+ _(!1), v(!1);
193
+ }, [_, v]), le(() => ({
194
+ session: m,
195
+ notice: O,
196
+ spokenChunks: g.spokenChunks,
152
197
  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,
198
+ active: m.phase !== "idle" && (m.phase !== "ended" || m.error !== null),
199
+ interrupting: A,
200
+ awaitingEndpoint: M,
201
+ available: q.isSupported && !g.isBlocked,
157
202
  start: X,
158
203
  end: Z,
159
204
  isCurrentSession: Q,
160
205
  toggleMute: $,
161
- interrupt: K
206
+ interrupt: K,
207
+ announce: H,
208
+ holdListening: V
162
209
  }), [
163
- w,
164
- I,
165
- R,
166
- B,
210
+ m,
211
+ O,
212
+ A,
213
+ M,
167
214
  q.isListening,
168
215
  q.isSupported,
169
- E.isBlocked,
170
- E.spokenChunks,
216
+ g.isBlocked,
217
+ g.spokenChunks,
171
218
  X,
172
219
  Z,
173
220
  Q,
174
221
  $,
175
- K
222
+ K,
223
+ H,
224
+ V
176
225
  ]);
177
226
  }
178
227
  //#endregion
179
- export { b as useVoiceSession };
228
+ export { d as useVoiceSession };
@@ -0,0 +1,61 @@
1
+ import { WriteProposalView } from '../writeProposals';
2
+ import { AssistantWriteConfirmDialogProps } from './AssistantWriteConfirmDialog';
3
+ /**
4
+ * The HIGH-risk confirmation flow (BOFF-7803 5a, unit FE5; OD-12): the
5
+ * product's own dialog through `confirmWrite` when it has one, fe-libs'
6
+ * `AssistantWriteConfirmDialog` otherwise.
7
+ *
8
+ * ★★ 5a is a safety floor, not the final security boundary. This hook makes
9
+ * the approve and decline calls itself, through the caller's `actions`, and
10
+ * only on a person's decision: an exact `'confirmed'` from the product's
11
+ * dialog (surface `host_modal`) or a press of the default dialog's armed
12
+ * confirm (surface `assistant_modal`). The product seam never gets `actions`.
13
+ * The issuing sandbox and wspace-sandbox-svc decide whether anything runs.
14
+ *
15
+ * ★ Only the dialog kinds reach it: `review` ignores any proposal whose
16
+ * confirmation is the card's single button, and any proposal that is not
17
+ * pending, bound, executable and button-approvable.
18
+ *
19
+ * Usage (the panel):
20
+ *
21
+ * const confirm = useWriteProposalConfirm(actions);
22
+ * <AssistantWriteProposalCard … onReview={() => confirm.review(view)} />
23
+ * <AssistantWriteConfirmDialog {...confirm.dialog} serverNow=… capabilities=…
24
+ * turnInFlight=… tr=… />
25
+ *
26
+ * Call `dismiss()` when the proposal can no longer be confirmed here (it was
27
+ * replaced, the conversation or mode changed): that closes the default dialog
28
+ * and aborts the product's.
29
+ */
30
+ /** Where a HIGH-risk confirmation was made. */
31
+ export type WriteConfirmDecisionSurface = "assistant_modal" | "host_modal";
32
+ /**
33
+ * The calls the flow makes. Each is the caller's, bound to the ISSUING sandbox
34
+ * (`WriteProposalClient`), and handles its own errors: a rejection here only
35
+ * ends the flow.
36
+ */
37
+ export interface WriteProposalConfirmActions {
38
+ /** Approve by button (`method: "button"`), from `surface`. */
39
+ approve: (view: WriteProposalView, surface: WriteConfirmDecisionSurface) => void | Promise<unknown>;
40
+ /** Decline by button, from `surface`. */
41
+ decline: (view: WriteProposalView, reason: "user_declined", surface: WriteConfirmDecisionSurface) => void | Promise<unknown>;
42
+ /** The proposal was shown in a dialog. */
43
+ presented: (view: WriteProposalView, surface: "modal") => void | Promise<unknown>;
44
+ }
45
+ export type WriteProposalConfirmDialogBinding = Pick<AssistantWriteConfirmDialogProps, "open" | "view" | "onApprove" | "onDecline" | "onPresented" | "onDismiss">;
46
+ export interface WriteProposalConfirmController {
47
+ /** The person asked to confirm `view` (the card's "Review & confirm…"). */
48
+ review: (view: WriteProposalView) => void;
49
+ /** Close the default dialog and abort the product's, deciding nothing. */
50
+ dismiss: () => void;
51
+ /** Spread into `AssistantWriteConfirmDialog`. */
52
+ dialog: WriteProposalConfirmDialogBinding;
53
+ /**
54
+ * ★ BOFF-7803 FE9: a confirmation is being asked right now — the default
55
+ * dialog is open, or the product's own is. A live voice conversation pauses
56
+ * listening meanwhile.
57
+ */
58
+ asking: boolean;
59
+ }
60
+ export declare function useWriteProposalConfirm(actions: WriteProposalConfirmActions): WriteProposalConfirmController;
61
+ //# sourceMappingURL=useWriteProposalConfirm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useWriteProposalConfirm.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/ui/useWriteProposalConfirm.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,KAAK,EAAE,gCAAgC,EAAE,MAAM,+BAA+B,CAAC;AAGtF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,+CAA+C;AAC/C,MAAM,MAAM,2BAA2B,GAAG,iBAAiB,GAAG,YAAY,CAAC;AAE3E;;;;GAIG;AACH,MAAM,WAAW,2BAA2B;IAC1C,8DAA8D;IAC9D,OAAO,EAAE,CACP,IAAI,EAAE,iBAAiB,EACvB,OAAO,EAAE,2BAA2B,KACjC,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7B,yCAAyC;IACzC,OAAO,EAAE,CACP,IAAI,EAAE,iBAAiB,EACvB,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,2BAA2B,KACjC,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7B,0CAA0C;IAC1C,SAAS,EAAE,CACT,IAAI,EAAE,iBAAiB,EACvB,OAAO,EAAE,OAAO,KACb,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC9B;AAED,MAAM,MAAM,iCAAiC,GAAG,IAAI,CAClD,gCAAgC,EAChC,MAAM,GAAG,MAAM,GAAG,WAAW,GAAG,WAAW,GAAG,aAAa,GAAG,WAAW,CAC1E,CAAC;AAEF,MAAM,WAAW,8BAA8B;IAC7C,2EAA2E;IAC3E,MAAM,EAAE,CAAC,IAAI,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAC1C,0EAA0E;IAC1E,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,iDAAiD;IACjD,MAAM,EAAE,iCAAiC,CAAC;IAC1C;;;;OAIG;IACH,MAAM,EAAE,OAAO,CAAC;CACjB;AAkCD,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,2BAA2B,GACnC,8BAA8B,CA0IhC"}
@@ -0,0 +1,109 @@
1
+ import { useAssistantProduct as e } from "../product.js";
2
+ import { writeProposalUsesDialog as t } from "./AssistantWriteProposalCard.js";
3
+ import { askProductToConfirmWrite as n } from "../writeConfirmSeam.js";
4
+ import { useCallback as r, useEffect as i, useMemo as a, useRef as o, useState as s } from "react";
5
+ //#region src/shared/assistant/ui/useWriteProposalConfirm.ts
6
+ function c(e) {
7
+ return t(e) && e.status === "pending" && e.approvable && e.execution.enabled === !0 && e.allowedMethods.includes("button");
8
+ }
9
+ async function l(e) {
10
+ try {
11
+ await e();
12
+ } catch {}
13
+ }
14
+ var u = {
15
+ view: null,
16
+ open: !1
17
+ };
18
+ function d(t) {
19
+ let { confirmWrite: d } = e(), f = o(d), p = o(t);
20
+ i(() => {
21
+ f.current = d, p.current = t;
22
+ });
23
+ let [m, h] = s(u), g = o(u), _ = r((e) => {
24
+ g.current = e, h(e);
25
+ }, []), v = o(null), [y, b] = s(!1), x = r((e) => {
26
+ v.current = e, b(e !== null);
27
+ }, []), S = r(() => {
28
+ let e = v.current;
29
+ x(null), e?.controller.abort();
30
+ }, [x]);
31
+ i(() => S, [S]);
32
+ let C = r((e) => {
33
+ let t = g.current;
34
+ t.open && (e !== void 0 && t.view?.proposalId !== e || _({
35
+ view: t.view,
36
+ open: !1
37
+ }));
38
+ }, [_]), w = r((e) => _({
39
+ view: e,
40
+ open: !0
41
+ }), [_]), T = r((e) => {
42
+ if (!c(e)) return;
43
+ let t = e.proposalId;
44
+ if (v.current?.proposalId === t) return;
45
+ let r = g.current;
46
+ if (r.open && r.view?.proposalId === t) return;
47
+ S(), C();
48
+ let i = f.current;
49
+ if (!i) {
50
+ w(e);
51
+ return;
52
+ }
53
+ let a = {
54
+ proposalId: t,
55
+ controller: new AbortController()
56
+ };
57
+ x(a);
58
+ let { signal: o } = a.controller;
59
+ (async () => {
60
+ let t = await n(i, e, o);
61
+ if (!(v.current !== a || o.aborted)) {
62
+ if (t === "aborted") {
63
+ x(null);
64
+ return;
65
+ }
66
+ if (t === "default") {
67
+ x(null), w(e);
68
+ return;
69
+ }
70
+ await l(() => p.current.presented(e, "modal")), !(v.current !== a || o.aborted) && (x(null), t === "approve" ? await l(() => p.current.approve(e, "host_modal")) : await l(() => p.current.decline(e, "user_declined", "host_modal")));
71
+ }
72
+ })();
73
+ }, [
74
+ S,
75
+ C,
76
+ w,
77
+ x
78
+ ]), E = r(() => {
79
+ S(), C();
80
+ }, [S, C]), D = m.view;
81
+ return {
82
+ review: T,
83
+ dismiss: E,
84
+ dialog: a(() => {
85
+ let e = D?.proposalId;
86
+ return {
87
+ open: m.open,
88
+ view: D,
89
+ onApprove: (t) => {
90
+ if (D) return l(() => p.current.approve(D, t)).then(() => C(e));
91
+ },
92
+ onDecline: (t, n) => {
93
+ if (D) return l(() => p.current.decline(D, t, n)).then(() => C(e));
94
+ },
95
+ onPresented: (e) => {
96
+ D && l(() => p.current.presented(D, e));
97
+ },
98
+ onDismiss: () => C(e)
99
+ };
100
+ }, [
101
+ m.open,
102
+ D,
103
+ C
104
+ ]),
105
+ asking: m.open || y
106
+ };
107
+ }
108
+ //#endregion
109
+ export { d as useWriteProposalConfirm };
@@ -0,0 +1,102 @@
1
+ import { AssistantTr } from '../i18n';
2
+ import { WriteProposalMessageRef, WriteProposalSession } from '../writeProposalDiscovery';
3
+ import { WriteProposalApproveSurface, WriteProposalDeclineReason, WriteProposalDecisionSurface, WriteProposalPresentationSurface, WriteProposalView } from '../writeProposals';
4
+ import { WriteReplyDeclineReason } from '../writeReplyBinder';
5
+ import { WriteReplyLiveState, WriteReplyPersonOrigin } from '../writeReplySend';
6
+ /**
7
+ * The panel's write proposals (BOFF-7803 5a, unit FE7): the records the
8
+ * ISSUING sandboxes hold, the references the thread keeps to them, and the
9
+ * calls a person's press makes.
10
+ *
11
+ * ★★ 5a is a safety floor, not the final security boundary. Nothing here
12
+ * authorises a change: the sandbox's store and wspace-sandbox-svc (route
13
+ * policy, live admin re-check, session relay) decide. The panel draws what
14
+ * they answer and carries a press to them.
15
+ *
16
+ * ★★ Discovery (design §3.1 / FE7): `list` on the session of the sandbox that
17
+ * ISSUED the proposals, only when that sandbox's own `/health` said
18
+ * `proposal-v1` —
19
+ * - after every settled turn (`afterTurn`),
20
+ * - when a conversation opens (`openConversation`),
21
+ * - when a card mounts whose record this panel does not hold (`ensureKnown`),
22
+ * - every 2 s while one of the session's proposals is executing, stopping at
23
+ * the terminal state and when the panel unmounts.
24
+ *
25
+ * ★ References, not records, go into the thread: a new live proposal's
26
+ * `{proposalId, sandboxId, sessionId}` is attached to the reply of the turn
27
+ * that raised it (or, found later, the newest reply of its session). The view
28
+ * lives here, in memory, and is replaced by every answer.
29
+ *
30
+ * ★ Every refusal or failure a person should know about becomes a system
31
+ * message through `tr("writeProposal.error.<code>")` (`writeProposalErrorLine`).
32
+ *
33
+ * ★★ BOFF-7803 FE8 — declines the panel makes on the person's behalf, all to
34
+ * the ISSUING sandbox and only ever for PENDING proposals (a change already
35
+ * running is never withdrawn):
36
+ * - a reply that corrects, declines or redirects (`declineForReply`), awaited
37
+ * by the send path BEFORE anything is sent; a failure is told;
38
+ * - the conversation is left or deleted (`conversation_closed`), the mode is
39
+ * switched (`mode_switched`), or its sandbox is replaced by a failover
40
+ * (`sandbox_replaced`, after which its cards are inert). These are
41
+ * best-effort and silent, and each fires ONCE: a proposal the panel has
42
+ * already withdrawn is not withdrawn again by the next event.
43
+ */
44
+ /** Why the panel withdraws a conversation's waiting changes on its own. */
45
+ export type WriteProposalLifecycleReason = Extract<WriteProposalDeclineReason, "conversation_closed" | "mode_switched">;
46
+ /** One proposal as its issuing sandbox last reported it. */
47
+ export interface WriteProposalEntry {
48
+ view: WriteProposalView;
49
+ /** That sandbox's clock at the read the view came from (`list().serverNow`). */
50
+ serverNow: number;
51
+ /** Where the proposal lives: its issuing sandbox, session and conversation. */
52
+ session: WriteProposalSession;
53
+ }
54
+ export type WriteProposalEntries = Readonly<Record<string, WriteProposalEntry>>;
55
+ /** The panel's handle. Stable for the panel's life. */
56
+ export interface WriteProposalPanel {
57
+ /** A turn in `session` settled; new live proposals attach to its reply. */
58
+ afterTurn: (session: WriteProposalSession, turnMessageId: string) => void;
59
+ /** A conversation opened: read every session its cards belong to. */
60
+ openConversation: (conversationId: string) => void;
61
+ /** A card mounted: read its session unless this panel already holds it. */
62
+ ensureKnown: (ref: WriteProposalMessageRef, conversationId: string) => void;
63
+ /** Confirm pressed (the card's single button, or a dialog's). */
64
+ approve: (view: WriteProposalView, surface: WriteProposalApproveSurface) => Promise<void>;
65
+ /** Cancel pressed. */
66
+ decline: (view: WriteProposalView, reason: "user_declined", surface: WriteProposalDecisionSurface) => Promise<void>;
67
+ /** The proposal was shown. */
68
+ presented: (view: WriteProposalView, surface: WriteProposalPresentationSurface) => Promise<void>;
69
+ /** The latest entry for a proposal, read live. */
70
+ entry: (proposalId: string) => WriteProposalEntry | undefined;
71
+ /**
72
+ * The conversation's waiting changes, for the write-reply binder: how many
73
+ * are pending (in sandboxes still in use), and whether any card offers its
74
+ * confirm button.
75
+ */
76
+ liveFor: (conversationId: string | null | undefined) => WriteReplyLiveState;
77
+ /**
78
+ * A person's reply corrected, declined or redirected: decline every pending
79
+ * proposal of the conversation, in each session holding one. Resolves once
80
+ * every sandbox answered (or failed — a failure is told, and the sandbox's
81
+ * sweep on the next prompt is the backstop), or after
82
+ * `WRITE_REPLY_DECLINE_WAIT_MS`, so a sandbox that never answers cannot
83
+ * freeze the panel. Never rejects.
84
+ */
85
+ declineForReply: (conversationId: string, reason: WriteReplyDeclineReason, origin: WriteReplyPersonOrigin) => Promise<void>;
86
+ /** The conversation was left or its mode switched: withdraw, once, best-effort. */
87
+ withdraw: (conversationId: string, reason: WriteProposalLifecycleReason) => void;
88
+ /**
89
+ * A failover replaced this sandbox: withdraw its waiting changes
90
+ * (`sandbox_replaced`, best-effort) and make its cards inert.
91
+ */
92
+ retireSandbox: (sandboxId: string) => void;
93
+ }
94
+ export declare function useWriteProposals(options: {
95
+ tr: AssistantTr;
96
+ }): {
97
+ panel: WriteProposalPanel;
98
+ entries: WriteProposalEntries;
99
+ /** Sandboxes a failover replaced: their cards are inert. */
100
+ retiredSandboxes: ReadonlySet<string>;
101
+ };
102
+ //# sourceMappingURL=useWriteProposals.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useWriteProposals.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/ui/useWriteProposals.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C,OAAO,EAKL,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,EAC1B,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAEL,KAAK,2BAA2B,EAEhC,KAAK,0BAA0B,EAC/B,KAAK,4BAA4B,EACjC,KAAK,gCAAgC,EACrC,KAAK,iBAAiB,EACvB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAIL,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC5B,MAAM,mBAAmB,CAAC;AAG3B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,2EAA2E;AAC3E,MAAM,MAAM,4BAA4B,GAAG,OAAO,CAChD,0BAA0B,EAC1B,qBAAqB,GAAG,eAAe,CACxC,CAAC;AAEF,4DAA4D;AAC5D,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,iBAAiB,CAAC;IACxB,gFAAgF;IAChF,SAAS,EAAE,MAAM,CAAC;IAClB,+EAA+E;IAC/E,OAAO,EAAE,oBAAoB,CAAC;CAC/B;AAED,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC,CAAC;AAEhF,uDAAuD;AACvD,MAAM,WAAW,kBAAkB;IACjC,2EAA2E;IAC3E,SAAS,EAAE,CAAC,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1E,qEAAqE;IACrE,gBAAgB,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,IAAI,CAAC;IACnD,2EAA2E;IAC3E,WAAW,EAAE,CAAC,GAAG,EAAE,uBAAuB,EAAE,cAAc,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5E,iEAAiE;IACjE,OAAO,EAAE,CACP,IAAI,EAAE,iBAAiB,EACvB,OAAO,EAAE,2BAA2B,KACjC,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,sBAAsB;IACtB,OAAO,EAAE,CACP,IAAI,EAAE,iBAAiB,EACvB,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,4BAA4B,KAClC,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,8BAA8B;IAC9B,SAAS,EAAE,CACT,IAAI,EAAE,iBAAiB,EACvB,OAAO,EAAE,gCAAgC,KACtC,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,kDAAkD;IAClD,KAAK,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,kBAAkB,GAAG,SAAS,CAAC;IAC9D;;;;OAIG;IACH,OAAO,EAAE,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,KAAK,mBAAmB,CAAC;IAC5E;;;;;;;OAOG;IACH,eAAe,EAAE,CACf,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,uBAAuB,EAC/B,MAAM,EAAE,sBAAsB,KAC3B,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,mFAAmF;IACnF,QAAQ,EAAE,CACR,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,4BAA4B,KACjC,IAAI,CAAC;IACV;;;OAGG;IACH,aAAa,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5C;AA+ED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE;IAAE,EAAE,EAAE,WAAW,CAAA;CAAE,GAAG;IAC/D,KAAK,EAAE,kBAAkB,CAAC;IAC1B,OAAO,EAAE,oBAAoB,CAAC;IAC9B,4DAA4D;IAC5D,gBAAgB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACvC,CA0VA"}