@burdenoff/fe-libs 2026.1007.6 → 2026.1008.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/shared/assistant/attachmentCommit.d.ts +175 -0
  2. package/dist/shared/assistant/attachmentCommit.d.ts.map +1 -0
  3. package/dist/shared/assistant/attachmentCommit.js +638 -0
  4. package/dist/shared/assistant/attachments.d.ts +39 -19
  5. package/dist/shared/assistant/attachments.d.ts.map +1 -1
  6. package/dist/shared/assistant/history/historyEngine.js +280 -280
  7. package/dist/shared/assistant/i18nManifest.d.ts +14 -2
  8. package/dist/shared/assistant/i18nManifest.d.ts.map +1 -1
  9. package/dist/shared/assistant/i18nManifest.js +17 -3
  10. package/dist/shared/assistant/index.d.ts +3 -0
  11. package/dist/shared/assistant/index.d.ts.map +1 -1
  12. package/dist/shared/assistant/ui/AssistantChatArea.d.ts.map +1 -1
  13. package/dist/shared/assistant/ui/AssistantChatArea.js +1390 -1371
  14. package/dist/shared/assistant/ui/composer/AssistantAttachmentChips.d.ts +8 -5
  15. package/dist/shared/assistant/ui/composer/AssistantAttachmentChips.d.ts.map +1 -1
  16. package/dist/shared/assistant/ui/composer/AssistantAttachmentChips.js +26 -9
  17. package/dist/shared/assistant/ui/composer/AssistantComposer.d.ts +3 -2
  18. package/dist/shared/assistant/ui/composer/AssistantComposer.d.ts.map +1 -1
  19. package/dist/shared/assistant/ui/composer/AssistantComposer.js +214 -125
  20. package/dist/shared/assistant/ui/voice/AssistantVoiceSession.d.ts +10 -0
  21. package/dist/shared/assistant/ui/voice/AssistantVoiceSession.d.ts.map +1 -1
  22. package/dist/shared/assistant/ui/voice/AssistantVoiceSession.js +124 -116
  23. package/dist/shared/assistant/useAssistantAttachments.d.ts +20 -2
  24. package/dist/shared/assistant/useAssistantAttachments.d.ts.map +1 -1
  25. package/dist/shared/assistant/useAssistantAttachments.js +146 -202
  26. package/dist/shared/assistant/useAttachmentCommitter.d.ts +17 -0
  27. package/dist/shared/assistant/useAttachmentCommitter.d.ts.map +1 -0
  28. package/dist/shared/assistant/useAttachmentCommitter.js +41 -0
  29. package/dist/shared/assistant/voiceCommit.d.ts +36 -0
  30. package/dist/shared/assistant/voiceCommit.d.ts.map +1 -0
  31. package/dist/shared/assistant/voiceCommit.js +24 -0
  32. package/dist/shared-assistant.js +161 -158
  33. package/dist/storage/filesPort.d.ts +120 -0
  34. package/dist/storage/filesPort.d.ts.map +1 -0
  35. package/dist/storage/filesPort.js +269 -0
  36. package/dist/storage/index.d.ts +2 -0
  37. package/dist/storage/index.d.ts.map +1 -1
  38. package/dist/storage/index.js +9 -8
  39. package/package.json +1 -1
@@ -17,243 +17,251 @@ import { useCallback as s, useEffect as c, useMemo as me, useRef as l, useState
17
17
  import { Maximize2 as he, Minimize2 as ge, ScrollText as _e, X as d } from "lucide-react";
18
18
  import { jsx as f, jsxs as p } from "react/jsx-runtime";
19
19
  //#region src/shared/assistant/ui/voice/AssistantVoiceSession.tsx
20
- var m = ({ session: m, turns: be = [], onSaveTranscript: xe, onContinueInChat: Se, notice: h = null, privacyNotice: g = null, spoken: _, onInterrupt: Ce, onToggleMute: v, attachments: y = [], onAttachFiles: b, onRemoveAttachment: we, onRetryAttachment: Te, canAttachMore: Ee = !0, preparingAttachments: x = 0, spokenChunks: S = null, onEnd: C, capturing: De = !0, interrupting: Oe = !1, awaitingEndpoint: ke = !1, holding: w = !1, correcting: Ae = !1, onLetMeFinish: T, onImDone: E, proposalChip: D = null, proposalTray: O = null, renderAfterTurn: je }) => {
21
- let k = n(), { muted: A, error: j } = m, M = l(null), N = l(null), [P, F] = u("mini"), I = P === "full", L = P === "mini", R = P === "mini" ? "panel" : P === "panel" ? "full" : "mini", [z, B] = u(!1);
22
- t("assistant.transcript", me(() => ({ run: () => z ? { status: "already" } : (B(!0), { status: "done" }) }), [z]));
23
- let V = O !== null && !L, H = l(!1), U = l(v);
24
- U.current = v;
25
- let W = s(() => {
26
- m.phase !== "listening" && m.phase !== "thinking" || A || H.current || o(m) || (H.current = !0, U.current());
27
- }, [A, m]), G = s(() => {
28
- H.current && (H.current = !1, U.current());
29
- }, []), Me = W;
20
+ var m = ({ session: m, turns: be = [], onSaveTranscript: xe, onContinueInChat: Se, notice: h = null, privacyNotice: g = null, spoken: _, onInterrupt: Ce, onToggleMute: v, attachments: y = [], onAttachFiles: b, onRemoveAttachment: we, onRetryAttachment: Te, canAttachMore: Ee = !0, preparingAttachments: x = 0, attachmentsLocked: S = !1, attachmentNotice: C = null, spokenChunks: w = null, onEnd: T, capturing: De = !0, interrupting: Oe = !1, awaitingEndpoint: ke = !1, holding: E = !1, correcting: Ae = !1, onLetMeFinish: D, onImDone: O, proposalChip: k = null, proposalTray: A = null, renderAfterTurn: je }) => {
21
+ let j = n(), { muted: M, error: N } = m, P = l(null), F = l(null), [I, L] = u("mini"), R = I === "full", z = I === "mini", B = I === "mini" ? "panel" : I === "panel" ? "full" : "mini", [V, H] = u(!1);
22
+ t("assistant.transcript", me(() => ({ run: () => V ? { status: "already" } : (H(!0), { status: "done" }) }), [V]));
23
+ let U = A !== null && !z, W = l(!1), G = l(v);
24
+ G.current = v;
25
+ let K = s(() => {
26
+ m.phase !== "listening" && m.phase !== "thinking" || M || W.current || o(m) || (W.current = !0, G.current());
27
+ }, [M, m]), q = s(() => {
28
+ W.current && (W.current = !1, G.current());
29
+ }, []), Me = K;
30
30
  c(() => {
31
31
  let e = () => {
32
- document.visibilityState === "hidden" ? W() : G();
32
+ document.visibilityState === "hidden" ? K() : q();
33
33
  };
34
34
  return document.addEventListener("visibilitychange", e), () => document.removeEventListener("visibilitychange", e);
35
- }, [W, G]), c(() => {
36
- let e = G;
35
+ }, [K, q]), c(() => {
36
+ let e = q;
37
37
  return window.addEventListener("focus", e), () => {
38
- window.removeEventListener("focus", e), H.current = !1;
38
+ window.removeEventListener("focus", e), W.current = !1;
39
39
  };
40
40
  }, []), c(() => {
41
- document.activeElement?.closest("[data-hands-free-notice]") || M.current?.focus();
42
- }, []), e(N, { fallbackSelector: `[${ae}]` }), c(() => {
41
+ document.activeElement?.closest("[data-hands-free-notice]") || P.current?.focus();
42
+ }, []), e(F, { fallbackSelector: `[${ae}]` }), c(() => {
43
43
  let e = (e) => {
44
44
  if (e.key === "Escape") {
45
45
  let t = fe({
46
46
  defaultPrevented: e.defaultPrevented,
47
47
  layerAbove: de({
48
48
  target: e.target,
49
- session: N.current,
49
+ session: F.current,
50
50
  doc: document
51
51
  }),
52
- transcriptOpen: z
52
+ transcriptOpen: V
53
53
  });
54
54
  if (t === "ignore") return;
55
- e.preventDefault(), t === "close-transcript" ? B(!1) : g ? g.decline() : V ? O?.onClose() : C();
55
+ e.preventDefault(), t === "close-transcript" ? H(!1) : g ? g.decline() : U ? A?.onClose() : T();
56
56
  return;
57
57
  }
58
- if (e.key !== "Tab" || !I) return;
59
- let t = (z ? N.current?.querySelector("[data-testid=\"assistant-voice-transcript\"]") : N.current)?.querySelectorAll("button:not([disabled])");
58
+ if (e.key !== "Tab" || !R) return;
59
+ let t = (V ? F.current?.querySelector("[data-testid=\"assistant-voice-transcript\"]") : F.current)?.querySelectorAll("button:not([disabled])");
60
60
  if (!t || t.length === 0) return;
61
61
  let n = t[0], r = t[t.length - 1];
62
62
  !n || !r || (e.shiftKey && document.activeElement === n ? (e.preventDefault(), r.focus()) : !e.shiftKey && document.activeElement === r && (e.preventDefault(), n.focus()));
63
63
  };
64
64
  return window.addEventListener("keydown", e), () => window.removeEventListener("keydown", e);
65
65
  }, [
66
- C,
67
- I,
68
- z,
66
+ T,
67
+ R,
69
68
  V,
70
- O,
69
+ U,
70
+ A,
71
71
  g
72
72
  ]);
73
- let K = h !== null && j === null, q = o(m), J = T && E && m.phase === "listening" && !A && j === null ? {
74
- letMeFinish: T,
75
- imDone: E
76
- } : null, Y = J !== null;
73
+ let J = h !== null && N === null, Y = o(m), X = D && O && m.phase === "listening" && !M && N === null ? {
74
+ letMeFinish: D,
75
+ imDone: O
76
+ } : null, Ne = X !== null;
77
77
  c(() => {
78
- if (Y) return;
78
+ if (Ne) return;
79
79
  let e = document.activeElement;
80
- (!e || e === document.body) && M.current?.focus();
81
- }, [Y]);
82
- let X = i({
80
+ (!e || e === document.body) && P.current?.focus();
81
+ }, [Ne]);
82
+ let Z = i({
83
83
  snapshot: m,
84
84
  capturing: De,
85
85
  interrupting: Oe,
86
86
  awaitingEndpoint: ke
87
- }), Ne = (() => {
88
- switch (X) {
89
- case "connecting": return k("voiceSession.connecting", "Starting the microphone…");
90
- case "endpoint-grace": return k("voiceSession.endpointGrace", "Still listening — take your time");
91
- case "interrupting": return k("voiceSession.interrupting", "Stopped — go ahead");
92
- case "thinking": return k(a.key, a.fallback);
93
- case "speaking": return k("voiceSession.speaking", "Speaking — tap to stop");
87
+ }), Pe = (() => {
88
+ switch (Z) {
89
+ case "connecting": return j("voiceSession.connecting", "Starting the microphone…");
90
+ case "endpoint-grace": return j("voiceSession.endpointGrace", "Still listening — take your time");
91
+ case "interrupting": return j("voiceSession.interrupting", "Stopped — go ahead");
92
+ case "thinking": return j(a.key, a.fallback);
93
+ case "speaking": return j("voiceSession.speaking", "Speaking — tap to stop");
94
94
  case "mic-error":
95
95
  case "ended": return "";
96
- case "listening": return A ? k("voiceSession.muted", "Microphone off") : k("voiceSession.listening", "Listening…");
97
- default: return X;
96
+ case "listening": return M ? j("voiceSession.muted", "Microphone off") : j("voiceSession.listening", "Listening…");
97
+ default: return Z;
98
98
  }
99
- })(), Z = !A && (X === "listening" || X === "endpoint-grace"), Q = Z && w ? k("voiceSession.holding", "Take your time — tap “I’m done” when you finish") : Z && Ae ? k("voiceSession.correcting", "Stopped that answer — listening to your correction") : Ne, $ = ne({
100
- tr: k,
101
- stage: X,
102
- muted: A,
103
- label: Q
104
- }), Pe = te(Q, $), Fe = X === "thinking";
99
+ })(), Fe = !M && (Z === "listening" || Z === "endpoint-grace"), Ie = Fe && E ? j("voiceSession.holding", "Take your time — tap “I’m done” when you finish") : Fe && Ae ? j("voiceSession.correcting", "Stopped that answer — listening to your correction") : Pe, Q = ne({
100
+ tr: j,
101
+ stage: Z,
102
+ muted: M,
103
+ label: Ie
104
+ }), Le = te(Ie, Q), $ = Z === "thinking";
105
105
  return /* @__PURE__ */ p("div", {
106
- ref: N,
107
- className: `flex flex-col items-center justify-between bg-bg-sunken ${P === "full" ? "fixed inset-x-0 bottom-0 top-14 z-[60] px-6 py-8" : P === "panel" ? "absolute inset-0 z-20 px-4 py-6" : "absolute inset-x-0 bottom-0 z-20 h-[11.25rem] border-t border-border-subtle px-3 py-3 shadow-lg"}`,
106
+ ref: F,
107
+ className: `flex flex-col items-center justify-between bg-bg-sunken ${I === "full" ? "fixed inset-x-0 bottom-0 top-14 z-[60] px-6 py-8" : I === "panel" ? "absolute inset-0 z-20 px-4 py-6" : "absolute inset-x-0 bottom-0 z-20 h-[11.25rem] border-t border-border-subtle px-3 py-3 shadow-lg"}`,
108
108
  role: "dialog",
109
- "aria-modal": I || void 0,
110
- "aria-label": k("voiceSession.title", "Voice conversation"),
109
+ "aria-modal": R || void 0,
110
+ "aria-label": j("voiceSession.title", "Voice conversation"),
111
111
  "data-testid": "assistant-voice-session",
112
112
  [oe]: "",
113
113
  children: [
114
114
  /* @__PURE__ */ p("button", {
115
- ref: M,
115
+ ref: P,
116
116
  type: "button",
117
- onClick: C,
118
- className: `absolute ${I ? "right-6 top-6 h-14 gap-2 px-5 text-base" : L ? "right-12 top-2 h-8 gap-1.5 px-2.5 text-xs" : "right-3 top-3 h-11 gap-2 px-4 text-sm"} flex items-center justify-center rounded-full border border-border-default bg-bg-elevated text-text-secondary hover:bg-bg-sunken transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong`,
119
- title: k("voiceSession.end", "End the voice conversation"),
117
+ onClick: T,
118
+ className: `absolute ${R ? "right-6 top-6 h-14 gap-2 px-5 text-base" : z ? "right-12 top-2 h-8 gap-1.5 px-2.5 text-xs" : "right-3 top-3 h-11 gap-2 px-4 text-sm"} flex items-center justify-center rounded-full border border-border-default bg-bg-elevated text-text-secondary hover:bg-bg-sunken transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong`,
119
+ title: j("voiceSession.end", "End the voice conversation"),
120
120
  "data-testid": "assistant-voice-end",
121
121
  children: [/* @__PURE__ */ f(d, {
122
- className: I ? "size-6" : L ? "size-4" : "size-5",
122
+ className: R ? "size-6" : z ? "size-4" : "size-5",
123
123
  "aria-hidden": "true"
124
124
  }), /* @__PURE__ */ f("span", {
125
- className: `truncate whitespace-nowrap font-medium ${L ? "max-w-[3.5rem] text-xs" : "max-w-[7rem]"}`,
126
- children: k("voiceSession.endShort", "End")
125
+ className: `truncate whitespace-nowrap font-medium ${z ? "max-w-[3.5rem] text-xs" : "max-w-[7rem]"}`,
126
+ children: j("voiceSession.endShort", "End")
127
127
  })]
128
128
  }),
129
- /* @__PURE__ */ f("div", {
130
- className: `flex flex-col items-center ${L ? "px-3" : `min-h-[1.5rem] ${K ? I ? "pt-14" : "pt-10" : ""}`}`,
131
- children: K ? /* @__PURE__ */ f("p", {
129
+ /* @__PURE__ */ p("div", {
130
+ className: `flex flex-col items-center ${z ? "px-3" : `min-h-[1.5rem] ${J || C ? R ? "pt-14" : "pt-10" : ""}`}`,
131
+ children: [J ? /* @__PURE__ */ f("p", {
132
132
  className: "max-w-xs text-center text-xs text-status-warning",
133
133
  "data-testid": "assistant-voice-notice",
134
- children: ve(h, k)
135
- }) : null
134
+ children: ve(h, j)
135
+ }) : null, C ? /* @__PURE__ */ f("p", {
136
+ className: "max-w-xs text-center text-xs text-status-warning",
137
+ role: "status",
138
+ "aria-live": "polite",
139
+ "data-testid": "assistant-voice-attachment-notice",
140
+ children: C
141
+ }) : null]
136
142
  }),
137
143
  (() => {
138
144
  let e = /* @__PURE__ */ f(se, {
139
145
  session: m,
140
- compact: L,
141
- connecting: X === "connecting",
142
- onPress: r(X) ? Ce : v,
143
- label: r(X) ? k("voiceSession.interrupt", "Stop the assistant and speak") : A ? k("voiceSession.unmute", "Turn the microphone on") : k("voiceSession.mute", "Turn the microphone off")
144
- }), t = J ? /* @__PURE__ */ f("button", {
146
+ compact: z,
147
+ connecting: Z === "connecting",
148
+ onPress: r(Z) ? Ce : v,
149
+ label: r(Z) ? j("voiceSession.interrupt", "Stop the assistant and speak") : M ? j("voiceSession.unmute", "Turn the microphone on") : j("voiceSession.mute", "Turn the microphone off")
150
+ }), t = X ? /* @__PURE__ */ f("button", {
145
151
  type: "button",
146
- onClick: w ? J.imDone : J.letMeFinish,
147
- className: `flex items-center justify-center rounded-full border font-medium transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong ${L ? "h-7 px-3 text-xs" : I ? "h-11 px-6 text-base" : "h-9 px-4 text-sm"} ${w ? "border-transparent bg-action-primary-bg text-action-primary-text hover:opacity-90" : "border-border-default bg-bg-elevated text-text-secondary hover:bg-bg-sunken"}`,
148
- title: w ? k("voiceSession.imDoneHint", "Send what you said now") : k("voiceSession.letMeFinishHint", "Pause sending until you tap “I’m done”"),
152
+ onClick: E ? X.imDone : X.letMeFinish,
153
+ className: `flex items-center justify-center rounded-full border font-medium transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong ${z ? "h-7 px-3 text-xs" : R ? "h-11 px-6 text-base" : "h-9 px-4 text-sm"} ${E ? "border-transparent bg-action-primary-bg text-action-primary-text hover:opacity-90" : "border-border-default bg-bg-elevated text-text-secondary hover:bg-bg-sunken"}`,
154
+ title: E ? j("voiceSession.imDoneHint", "Send what you said now") : j("voiceSession.letMeFinishHint", "Pause sending until you tap “I’m done”"),
149
155
  "data-testid": "assistant-voice-hold",
150
- "data-holding": w ? "true" : "false",
151
- children: w ? k("voiceSession.imDone", "I’m done") : k("voiceSession.letMeFinish", "Let me finish")
156
+ "data-holding": E ? "true" : "false",
157
+ children: E ? j("voiceSession.imDone", "I’m done") : j("voiceSession.letMeFinish", "Let me finish")
152
158
  }) : null, n = t ? /* @__PURE__ */ p("div", {
153
159
  className: "flex flex-col items-center gap-2",
154
160
  children: [e, t]
155
- }) : e, i = ee(X) ? _ : q || null, a = j === null ? null : ye(j, k);
156
- return L ? /* @__PURE__ */ f(ce, {
157
- spokenChunks: S,
158
- state: X,
161
+ }) : e, i = ee(Z) ? _ : Y || null, a = N === null ? null : ye(N, j);
162
+ return z ? /* @__PURE__ */ f(ce, {
163
+ spokenChunks: w,
164
+ state: Z,
159
165
  caption: i,
160
- statusText: Pe,
161
- statusSuffix: $,
162
- rotateStatus: Fe,
166
+ statusText: Le,
167
+ statusSuffix: Q,
168
+ rotateStatus: $,
163
169
  errorText: a,
164
170
  control: n
165
171
  }) : /* @__PURE__ */ f(le, {
166
- state: X,
167
- userCaption: q || null,
168
- spokenChunks: S,
172
+ state: Z,
173
+ userCaption: Y || null,
174
+ spokenChunks: w,
169
175
  assistantCaption: _,
170
- expanded: I,
171
- statusText: Pe,
172
- statusSuffix: $,
173
- rotateStatus: Fe,
176
+ expanded: R,
177
+ statusText: Le,
178
+ statusSuffix: Q,
179
+ rotateStatus: $,
174
180
  errorText: a,
175
181
  control: n
176
182
  });
177
183
  })(),
178
- D && !V ? /* @__PURE__ */ f("div", {
179
- className: L ? "absolute left-20 right-36 top-2 flex justify-center" : `flex w-full justify-center ${I ? "max-w-[calc(100%-12rem)]" : "max-w-[calc(100%-8rem)]"}`,
184
+ k && !U ? /* @__PURE__ */ f("div", {
185
+ className: z ? "absolute left-20 right-36 top-2 flex justify-center" : `flex w-full justify-center ${R ? "max-w-[calc(100%-12rem)]" : "max-w-[calc(100%-8rem)]"}`,
180
186
  children: /* @__PURE__ */ f("button", {
181
187
  type: "button",
182
188
  onClick: () => {
183
- F("panel"), D.onOpen();
189
+ L("panel"), k.onOpen();
184
190
  },
185
- className: `max-w-full truncate rounded-full border border-border-default bg-bg-elevated font-medium text-text-primary transition-colors hover:bg-bg-raised focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong ${L ? "h-8 px-3 text-xs" : "h-10 px-4 text-sm"}`,
191
+ className: `max-w-full truncate rounded-full border border-border-default bg-bg-elevated font-medium text-text-primary transition-colors hover:bg-bg-raised focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong ${z ? "h-8 px-3 text-xs" : "h-10 px-4 text-sm"}`,
186
192
  "data-testid": "assistant-voice-proposal-chip",
187
- children: D.label
193
+ children: k.label
188
194
  })
189
195
  }) : null,
190
- O && V ? /* @__PURE__ */ p("div", {
191
- className: `absolute z-10 flex flex-col gap-2 overflow-y-auto rounded-lg border border-border-subtle bg-bg-elevated shadow-lg ${I ? "inset-x-6 bottom-24 top-24 mx-auto max-w-xl p-4" : "inset-x-3 bottom-16 top-16 p-3"}`,
196
+ A && U ? /* @__PURE__ */ p("div", {
197
+ className: `absolute z-10 flex flex-col gap-2 overflow-y-auto rounded-lg border border-border-subtle bg-bg-elevated shadow-lg ${R ? "inset-x-6 bottom-24 top-24 mx-auto max-w-xl p-4" : "inset-x-3 bottom-16 top-16 p-3"}`,
192
198
  "data-testid": "assistant-voice-proposal-tray",
193
199
  children: [/* @__PURE__ */ f("div", {
194
200
  className: "flex justify-end",
195
201
  children: /* @__PURE__ */ f("button", {
196
202
  type: "button",
197
- onClick: O.onClose,
203
+ onClick: A.onClose,
198
204
  className: "flex size-8 items-center justify-center rounded-full text-text-secondary transition-colors hover:bg-bg-raised hover:text-text-primary focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong",
199
- "aria-label": O.closeLabel,
205
+ "aria-label": A.closeLabel,
200
206
  "data-testid": "assistant-voice-proposal-tray-close",
201
207
  children: /* @__PURE__ */ f(d, {
202
208
  className: "size-4",
203
209
  "aria-hidden": "true"
204
210
  })
205
211
  })
206
- }), O.content]
212
+ }), A.content]
207
213
  }) : null,
208
214
  g ? /* @__PURE__ */ f(pe, {
209
- view: P,
215
+ view: I,
210
216
  onContinue: g.accept,
211
217
  onNotNow: g.decline
212
218
  }) : null,
213
- z ? /* @__PURE__ */ f(ue, {
219
+ V ? /* @__PURE__ */ f(ue, {
214
220
  turns: be,
215
- onClose: () => B(!1),
221
+ onClose: () => H(!1),
216
222
  onSave: xe,
217
223
  onContinueInChat: Se,
218
224
  renderAfterTurn: je
219
225
  }) : null,
220
226
  b ? /* @__PURE__ */ f("div", {
221
- className: `absolute ${I ? "left-6 top-6" : L ? "left-11 top-2" : "left-3 top-3"}`,
227
+ className: `absolute ${R ? "left-6 top-6" : z ? "left-11 top-2" : "left-3 top-3"}`,
222
228
  children: /* @__PURE__ */ f(re, {
223
229
  onFiles: (e) => {
224
- b(e), F((e) => e === "mini" ? "panel" : e);
230
+ b(e), L((e) => e === "mini" ? "panel" : e);
225
231
  },
226
232
  onPickerOpen: Me,
227
233
  direction: "down",
228
- canAddMore: Ee
234
+ canAddMore: Ee,
235
+ disabled: S
229
236
  })
230
237
  }) : null,
231
- (y.length > 0 || x > 0) && !L ? /* @__PURE__ */ f("div", {
232
- className: `absolute ${I ? "bottom-24 left-24 right-24" : "bottom-16 left-16 right-16"}`,
238
+ (y.length > 0 || x > 0) && !z ? /* @__PURE__ */ f("div", {
239
+ className: `absolute ${R ? "bottom-24 left-24 right-24" : "bottom-16 left-16 right-16"}`,
233
240
  "data-testid": "assistant-voice-attachments",
234
241
  children: /* @__PURE__ */ f(ie, {
235
242
  attachments: y,
236
243
  onRemove: we ?? (() => void 0),
237
244
  onRetry: Te ?? (() => void 0),
238
- preparingCount: x
245
+ preparingCount: x,
246
+ disabled: S
239
247
  })
240
248
  }) : null,
241
249
  /* @__PURE__ */ f("button", {
242
250
  type: "button",
243
- onClick: () => B((e) => !e),
244
- className: `absolute ${I ? "bottom-6 right-6 size-14" : L ? "right-2 top-2 size-8" : "bottom-3 right-3 size-11"} flex items-center justify-center rounded-full bg-bg-elevated text-text-secondary transition-colors hover:bg-bg-raised hover:text-text-primary focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong`,
245
- "aria-pressed": z,
246
- "aria-label": k("voiceSession.transcriptTitle", "Voice transcript"),
251
+ onClick: () => H((e) => !e),
252
+ className: `absolute ${R ? "bottom-6 right-6 size-14" : z ? "right-2 top-2 size-8" : "bottom-3 right-3 size-11"} flex items-center justify-center rounded-full bg-bg-elevated text-text-secondary transition-colors hover:bg-bg-raised hover:text-text-primary focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong`,
253
+ "aria-pressed": V,
254
+ "aria-label": j("voiceSession.transcriptTitle", "Voice transcript"),
247
255
  "data-testid": "assistant-voice-transcript-toggle",
248
- children: /* @__PURE__ */ f(_e, { className: I ? "size-6" : L ? "size-4" : "size-5" })
256
+ children: /* @__PURE__ */ f(_e, { className: R ? "size-6" : z ? "size-4" : "size-5" })
249
257
  }),
250
258
  /* @__PURE__ */ f("button", {
251
259
  type: "button",
252
- onClick: () => F(R),
253
- className: `absolute ${I ? "bottom-6 left-6 size-14" : L ? "left-2 top-2 size-8" : "bottom-3 left-3 size-11"} flex items-center justify-center rounded-full bg-bg-elevated text-text-secondary transition-colors hover:bg-bg-raised hover:text-text-primary focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong`,
254
- "aria-label": R === "panel" ? k("voiceSession.expandPanel", "Show the conversation in the panel") : R === "full" ? k("voiceSession.expand", "Expand the conversation to full screen") : k("voiceSession.collapse", "Shrink to the compact controller"),
260
+ onClick: () => L(B),
261
+ className: `absolute ${R ? "bottom-6 left-6 size-14" : z ? "left-2 top-2 size-8" : "bottom-3 left-3 size-11"} flex items-center justify-center rounded-full bg-bg-elevated text-text-secondary transition-colors hover:bg-bg-raised hover:text-text-primary focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong`,
262
+ "aria-label": B === "panel" ? j("voiceSession.expandPanel", "Show the conversation in the panel") : B === "full" ? j("voiceSession.expand", "Expand the conversation to full screen") : j("voiceSession.collapse", "Shrink to the compact controller"),
255
263
  "data-testid": "assistant-voice-expand",
256
- children: I ? /* @__PURE__ */ f(ge, { className: "size-5" }) : /* @__PURE__ */ f(he, { className: L ? "size-4" : "size-5" })
264
+ children: R ? /* @__PURE__ */ f(ge, { className: "size-5" }) : /* @__PURE__ */ f(he, { className: z ? "size-4" : "size-5" })
257
265
  })
258
266
  ]
259
267
  });
@@ -1,9 +1,10 @@
1
1
  import { AssistantAttachment, AttachmentRejection, AttachmentSendBlocker } from './attachments';
2
+ import { AttachmentCommitResult, CommitOptions } from './attachmentCommit';
2
3
  export interface UseAssistantAttachmentsResult {
3
4
  /** Files being read/downscaled — no chip of their own yet. See below. */
4
5
  preparingCount: number;
5
6
  attachments: AssistantAttachment[];
6
- /** True while any attachment is still being prepared or uploaded. */
7
+ /** True while any attachment is still being prepared or saved (Send's commit). */
7
8
  isBusy: boolean;
8
9
  /**
9
10
  * Why the current attachments block sending, or `null` when they do not.
@@ -15,12 +16,29 @@ export interface UseAssistantAttachmentsResult {
15
16
  /** Most recent rejection, for a transient inline message. */
16
17
  rejection: AttachmentRejection | null;
17
18
  addFiles: (files: FileList | File[] | null | undefined) => void;
19
+ /** Drop a draft attachment. Ignored while Send is saving that very chip. */
18
20
  remove: (id: string) => void;
19
- /** Re-upload a single failed attachment, reusing the bytes already prepared. */
21
+ /** Clear the reason a Send could not save this attachment, ready for the next Send. */
20
22
  retry: (id: string) => void;
23
+ /** Drop the whole draft; a commit in flight is cancelled and rolled back first. */
21
24
  clear: () => void;
22
25
  clearRejection: () => void;
23
26
  canAddMore: boolean;
27
+ /**
28
+ * Save the draft to Files and mint download URLs — the one step that touches the file library.
29
+ * Resolves with the attachments to send (see `AttachmentCommitResult`); on failure or cancel it
30
+ * has undone what it created and the draft is intact. Single flight: a second call while one is
31
+ * running returns the same promise.
32
+ */
33
+ commit: (options?: {
34
+ mode?: CommitOptions['mode'];
35
+ budgetMs?: number;
36
+ signal?: AbortSignal;
37
+ }) => Promise<AttachmentCommitResult>;
38
+ /** Stop the commit in flight (it rolls back and resolves `{ ok: false, cancelled: true }`). */
39
+ cancelCommit: () => void;
40
+ /** True from the moment `commit()` is called until it settles. */
41
+ isCommitting: boolean;
24
42
  }
25
43
  export interface UseAssistantAttachmentsOptions {
26
44
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"useAssistantAttachments.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/useAssistantAttachments.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAOH,OAAO,EAYL,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC3B,MAAM,eAAe,CAAC;AAsJvB,MAAM,WAAW,6BAA6B;IAC5C,yEAAyE;IACzE,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,mBAAmB,EAAE,CAAC;IACnC,qEAAqE;IACrE,MAAM,EAAE,OAAO,CAAC;IAChB;;;;;OAKG;IACH,WAAW,EAAE,qBAAqB,GAAG,IAAI,CAAC;IAC1C,6DAA6D;IAC7D,SAAS,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACtC,QAAQ,EAAE,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,EAAE,GAAG,IAAI,GAAG,SAAS,KAAK,IAAI,CAAC;IAChE,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,gFAAgF;IAChF,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,8BAA8B;IAC7C;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,uBAAuB,CACrC,OAAO,GAAE,8BAAmC,GAC3C,6BAA6B,CAyQ/B"}
1
+ {"version":3,"file":"useAssistantAttachments.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/useAssistantAttachments.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAIH,OAAO,EAYL,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC3B,MAAM,eAAe,CAAC;AAEvB,OAAO,EAEL,KAAK,sBAAsB,EAE3B,KAAK,aAAa,EACnB,MAAM,oBAAoB,CAAC;AAkJ5B,MAAM,WAAW,6BAA6B;IAC5C,yEAAyE;IACzE,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,mBAAmB,EAAE,CAAC;IACnC,kFAAkF;IAClF,MAAM,EAAE,OAAO,CAAC;IAChB;;;;;OAKG;IACH,WAAW,EAAE,qBAAqB,GAAG,IAAI,CAAC;IAC1C,6DAA6D;IAC7D,SAAS,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACtC,QAAQ,EAAE,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,EAAE,GAAG,IAAI,GAAG,SAAS,KAAK,IAAI,CAAC;IAChE,4EAA4E;IAC5E,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,uFAAuF;IACvF,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,mFAAmF;IACnF,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,UAAU,EAAE,OAAO,CAAC;IACpB;;;;;OAKG;IACH,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE;QACjB,IAAI,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;QAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,MAAM,CAAC,EAAE,WAAW,CAAC;KACtB,KAAK,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACtC,+FAA+F;IAC/F,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,kEAAkE;IAClE,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,8BAA8B;IAC7C;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,uBAAuB,CACrC,OAAO,GAAE,8BAAmC,GAC3C,6BAA6B,CAwN/B"}