@burdenoff/fe-libs 2026.906.2 → 2026.906.3

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.
@@ -42,6 +42,18 @@ export interface AssistantMessageMetadata {
42
42
  * voice the moment the user switches, even with the right voice installed.
43
43
  */
44
44
  lang?: string;
45
+ /**
46
+ * On a "continued from a voice conversation" note: how many spoken turns the
47
+ * conversation held when it was written.
48
+ *
49
+ * ★★ The marker lives on the MESSAGE, not in component state, and that is the
50
+ * whole point. Tracked in state it reset every time `PanelContainer`
51
+ * unmounted the panel — minimise and reopen and the same note could be
52
+ * appended again — and it could not say WHICH turns were already carried
53
+ * over, so a later note repeated questions the thread already showed. A
54
+ * message persists with the conversation and answers both.
55
+ */
56
+ continuedVoiceTurns?: number;
45
57
  /**
46
58
  * This turn happened inside a live VOICE session, not in the chat panel.
47
59
  *
@@ -1 +1 @@
1
- {"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/conversation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAC;AAIhE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,MAAM,MAAM,sBAAsB,GAC9B,MAAM,GACN,cAAc,GACd,SAAS,GACT,UAAU,GACV,OAAO,CAAC;AAEZ,MAAM,MAAM,2BAA2B,GACnC,MAAM,GACN,cAAc,GACd,YAAY,GACZ,WAAW,GACX,UAAU,GACV,OAAO,CAAC;AAEZ;;;;;;;;;GASG;AACH,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,wBAAwB;IACvC,SAAS,CAAC,EAAE,sBAAsB,EAAE,CAAC;IACrC,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,WAAW,CAAC,EAAE,0BAA0B,EAAE,CAAC;IAC3C;;;;;;;;;OASG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;;;;;;;;;;OAcG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,QAAQ,CAAC,EAAE,wBAAwB,CAAC;CACrC;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,aAAa,CAAC;IACpB;;;;;;;;;;;;;;;;;;OAkBG;IACH,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,+CAA+C;IAC/C,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,sBAAsB,CAAC;CAChC;AAED,MAAM,WAAW,+BAA+B;IAC9C,MAAM,EAAE,2BAA2B,CAAC;IACpC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,aAAa,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,wEAAwE;IACxE,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kFAAkF;IAClF,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB"}
1
+ {"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/conversation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAC;AAIhE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,MAAM,MAAM,sBAAsB,GAC9B,MAAM,GACN,cAAc,GACd,SAAS,GACT,UAAU,GACV,OAAO,CAAC;AAEZ,MAAM,MAAM,2BAA2B,GACnC,MAAM,GACN,cAAc,GACd,YAAY,GACZ,WAAW,GACX,UAAU,GACV,OAAO,CAAC;AAEZ;;;;;;;;;GASG;AACH,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,wBAAwB;IACvC,SAAS,CAAC,EAAE,sBAAsB,EAAE,CAAC;IACrC,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,WAAW,CAAC,EAAE,0BAA0B,EAAE,CAAC;IAC3C;;;;;;;;;OASG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;;;;;;OAUG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;;;;;;;;;;;OAcG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,QAAQ,CAAC,EAAE,wBAAwB,CAAC;CACrC;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,aAAa,CAAC;IACpB;;;;;;;;;;;;;;;;;;OAkBG;IACH,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,+CAA+C;IAC/C,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,sBAAsB,CAAC;CAChC;AAED,MAAM,WAAW,+BAA+B;IAC9C,MAAM,EAAE,2BAA2B,CAAC;IACpC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,aAAa,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,wEAAwE;IACxE,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kFAAkF;IAClF,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB"}
@@ -1 +1 @@
1
- {"version":3,"file":"AssistantChatArea.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/ui/AssistantChatArea.tsx"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,EAAE,EACR,MAAM,OAAO,CAAC;AAkEf,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAoLvE;;;;;GAKG;AACH,MAAM,WAAW,sBAAsB;IACrC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;;;;;;;;OAYG;IACH,WAAW,CAAC,EAAE,oBAAoB,CAAC;CACpC;AAED,eAAO,MAAM,iBAAiB,EAAE,EAAE,CAAC,sBAAsB,CAkgDxD,CAAC"}
1
+ {"version":3,"file":"AssistantChatArea.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/ui/AssistantChatArea.tsx"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,EAAE,EACR,MAAM,OAAO,CAAC;AAkEf,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAoLvE;;;;;GAKG;AACH,MAAM,WAAW,sBAAsB;IACrC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;;;;;;;;OAYG;IACH,WAAW,CAAC,EAAE,oBAAoB,CAAC;CACpC;AAED,eAAO,MAAM,iBAAiB,EAAE,EAAE,CAAC,sBAAsB,CA2mDxD,CAAC"}
@@ -46,25 +46,25 @@ var Ie = {
46
46
  function Be() {
47
47
  return `${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
48
48
  }
49
- function O(e) {
49
+ function Ve(e) {
50
50
  return e.info?.time?.created ?? 0;
51
51
  }
52
- function k(e) {
52
+ function O(e) {
53
53
  return (e ?? []).filter((e) => e.type === "text" && typeof e.text == "string").map((e) => e.text?.trim() ?? "").filter(Boolean).join("\n");
54
54
  }
55
- function A(e) {
55
+ function k(e) {
56
56
  return (e ?? []).filter((e) => e.type === "tool" && e.tool).map((e) => {
57
57
  let t = e.state?.status ?? "running", n = e.tool ?? "tool";
58
58
  return t === "completed" ? `Completed: ${n}` : t === "failed" ? `Failed: ${n}` : `Running: ${n}`;
59
59
  });
60
60
  }
61
- function Ve(e, t) {
62
- let n = e.filter((e) => e.info?.role === "assistant" && O(e) > t).sort((e, t) => O(e) - O(t));
61
+ function He(e, t) {
62
+ let n = e.filter((e) => e.info?.role === "assistant" && Ve(e) > t).sort((e, t) => Ve(e) - Ve(t));
63
63
  if (n.length === 0) return {
64
64
  content: "Thinking...",
65
65
  done: !1
66
66
  };
67
- let r = n[n.length - 1], i = k(r.parts), a = p(r.parts), o = A(r.parts), s = x(r.parts), c = [
67
+ let r = n[n.length - 1], i = O(r.parts), a = p(r.parts), o = k(r.parts), s = x(r.parts), c = [
68
68
  i,
69
69
  ...a,
70
70
  ...o
@@ -78,7 +78,7 @@ function Ve(e, t) {
78
78
  ...s ? { pendingWrite: s } : {}
79
79
  };
80
80
  }
81
- function He(e) {
81
+ function Ue(e) {
82
82
  switch (e) {
83
83
  case "provisioning": return "Starting assistant environment...";
84
84
  case "connecting": return "Connecting to assistant...";
@@ -86,40 +86,40 @@ function He(e) {
86
86
  default: return "";
87
87
  }
88
88
  }
89
- var j = ({ visible: p = !0, writeAccess: x = "unknown" }) => {
90
- let k = ae(), { product: A, modes: j, gatherPageContext: Ue, buildPrompt: We, reportTokenUsage: Ge } = ie(), { getAccessToken: Ke, getWorkspaceToken: qe, userId: Je } = t(), { locale: Ye } = e(), Xe = S((e) => e.assistantLanguage), Ze = S((e) => e.replyLanguage), Qe = T(() => re(Xe, Ze, Ye), [
89
+ var A = ({ visible: p = !0, writeAccess: x = "unknown" }) => {
90
+ let O = ae(), { product: k, modes: A, gatherPageContext: We, buildPrompt: Ge, reportTokenUsage: Ke } = ie(), { getAccessToken: j, getWorkspaceToken: qe, userId: Je } = t(), { locale: Ye } = e(), Xe = S((e) => e.assistantLanguage), Ze = S((e) => e.replyLanguage), Qe = T(() => re(Xe, Ze, Ye), [
91
91
  Xe,
92
92
  Ze,
93
93
  Ye
94
- ]), $e = Qe.reply.english, et = Qe.replyIsExplicit, tt = Qe.reply.code, { conversations: nt, activeConversationId: M, mode: N, processingByConversationId: rt, setMode: P, setConversationMode: it, setActiveConversation: at, createConversation: F, addMessage: I, updateMessage: ot, patchMessage: L, mergeMessageMetadata: st, setConversationProcessing: R, setBackendSessionId: ct, clearBackendSessionId: lt, setSandbox: z, clearSandbox: ut, acknowledgeApiCalls: dt } = S(), B = Te(nt.find((e) => e.id === M)), ft = B.all, V = M ? rt[M] : void 0, H = fe(V?.status), pt = H ? V?.messageId ?? null : null, mt = V?.status === "error" ? V.messageId : null, { canUseApiCalls: U, loading: ht } = we(he()), gt = T(() => j.filter((e) => !e.requiresAdmin || U), [j, U]), [_t, vt] = Pe(null), [yt, bt] = Pe(!1), xt = E({}), W = E(_e()), St = E(/* @__PURE__ */ new Set()), G = T(() => j.find((e) => e.id === N), [j, N]);
94
+ ]), $e = Qe.reply.english, et = Qe.replyIsExplicit, tt = Qe.reply.code, { conversations: nt, activeConversationId: M, mode: N, processingByConversationId: rt, setMode: it, setConversationMode: at, setActiveConversation: ot, createConversation: P, addMessage: F, updateMessage: st, patchMessage: I, mergeMessageMetadata: ct, setConversationProcessing: L, setBackendSessionId: lt, clearBackendSessionId: R, setSandbox: z, clearSandbox: ut, acknowledgeApiCalls: dt } = S(), ft = nt.find((e) => e.id === M), B = Te(ft), V = B.all, H = M ? rt[M] : void 0, U = fe(H?.status), pt = U ? H?.messageId ?? null : null, mt = H?.status === "error" ? H.messageId : null, { canUseApiCalls: W, loading: ht } = we(he()), gt = T(() => A.filter((e) => !e.requiresAdmin || W), [A, W]), [_t, vt] = Pe(null), [yt, G] = Pe(!1), bt = E({}), K = E(_e()), xt = E(/* @__PURE__ */ new Set()), St = T(() => A.find((e) => e.id === N), [A, N]);
95
95
  w(() => {
96
- ht || (!G || G.requiresAdmin && !U) && N !== "assistant" && P("assistant");
96
+ ht || (!St || St.requiresAdmin && !W) && N !== "assistant" && it("assistant");
97
97
  }, [
98
98
  N,
99
- G,
100
- U,
99
+ St,
100
+ W,
101
101
  ht,
102
- P
102
+ it
103
103
  ]);
104
- let K = C((e, t, n, r) => {
105
- R(e, n, t, null), r ? ot(e, t, r) : ot(e, t, He(n));
106
- }, [R, ot]), Ct = C(async (e, t, n, a, s) => {
104
+ let q = C((e, t, n, r) => {
105
+ L(e, n, t, null), r ? st(e, t, r) : st(e, t, Ue(n));
106
+ }, [L, st]), Ct = C(async (e, t, n, a, s) => {
107
107
  let c = S.getState().sandboxesByMode[n]?.sandboxId ?? null, u = async (e) => {
108
- if (W.current.isFresh(e)) return !0;
108
+ if (K.current.isFresh(e)) return !0;
109
109
  try {
110
- return await f(e, a, s, 3e5), await d(e, a, s, 9e4), W.current.markVerified(e), !0;
110
+ return await f(e, a, s, 3e5), await d(e, a, s, 9e4), K.current.markVerified(e), !0;
111
111
  } catch {
112
- return W.current.invalidate(e), !1;
112
+ return K.current.invalidate(e), !1;
113
113
  }
114
114
  };
115
- if (c && (z(n, c, "provisioning"), K(e, t, "provisioning", "Reusing assistant environment..."), await u(c) || (z(n, null, "provisioning"), c = null)), !c) {
116
- K(e, t, "provisioning", "Looking for existing environment...");
117
- let r = await o(a, A, n, Me(), s);
118
- r && (z(n, r, "provisioning"), K(e, t, "provisioning", "Reusing assistant environment..."), await u(r) ? c = r : z(n, null, "provisioning"));
115
+ if (c && (z(n, c, "provisioning"), q(e, t, "provisioning", "Reusing assistant environment..."), await u(c) || (z(n, null, "provisioning"), c = null)), !c) {
116
+ q(e, t, "provisioning", "Looking for existing environment...");
117
+ let r = await o(a, k, n, Me(), s);
118
+ r && (z(n, r, "provisioning"), q(e, t, "provisioning", "Reusing assistant environment..."), await u(r) ? c = r : z(n, null, "provisioning"));
119
119
  }
120
120
  if (!c) {
121
- if (n === "api-calls" && !Ke()) throw Error("API Calls mode requires an authenticated session. Please sign in again.");
122
- K(e, t, "provisioning", "Starting assistant environment..."), z(n, null, "provisioning"), c = await r(A, n, a, Me(), Re, s), z(n, c, "provisioning"), await f(c, a, s, 3e5), await d(c, a, s, 9e4);
121
+ if (n === "api-calls" && !j()) throw Error("API Calls mode requires an authenticated session. Please sign in again.");
122
+ q(e, t, "provisioning", "Starting assistant environment..."), z(n, null, "provisioning"), c = await r(k, n, a, Me(), Re, s), z(n, c, "provisioning"), await f(c, a, s, 3e5), await d(c, a, s, 9e4);
123
123
  }
124
124
  z(n, c, "running");
125
125
  let p = S.getState().conversations.find((t) => t.id === e)?.backendSessionId ?? null;
@@ -127,27 +127,27 @@ var j = ({ visible: p = !0, writeAccess: x = "unknown" }) => {
127
127
  let e = await l(c, a, p, s);
128
128
  if (e.mode !== n) throw Error(`Session mode mismatch: expected ${n}, received ${e.mode}`);
129
129
  } catch {
130
- lt(e), p = null;
130
+ R(e), p = null;
131
131
  }
132
- return p || (K(e, t, "connecting", "Preparing session..."), p = (await i(c, a, n, s)).sessionId, ct(e, p)), {
132
+ return p || (q(e, t, "connecting", "Preparing session..."), p = (await i(c, a, n, s)).sessionId, lt(e, p)), {
133
133
  sandboxId: c,
134
134
  sessionId: p
135
135
  };
136
136
  }, [
137
+ R,
138
+ j,
139
+ k,
137
140
  lt,
138
- Ke,
139
- A,
140
- ct,
141
141
  z,
142
- K
143
- ]), q = C(async (e, t = [], r = {}) => {
142
+ q
143
+ ]), J = C(async (e, t = [], r = {}) => {
144
144
  let i = r.voiceSessionId !== void 0, o = S.getState(), l = o.activeConversationId ?? M;
145
- if (l && (fe(o.processingByConversationId[l]?.status) || St.current.has(l))) return;
145
+ if (l && (fe(o.processingByConversationId[l]?.status) || xt.current.has(l))) return;
146
146
  let d = o.mode, f = M, p = f ? S.getState().conversations.find((e) => e.id === f) : void 0;
147
- if (f ? p && p.mode !== d && (p.messages.length > 0 || p.backendSessionId) ? f = F(void 0, d) : p && p.mode !== d && it(f, d) : f = F(void 0, d), !f) return;
148
- xt.current[f] = t;
147
+ if (f ? p && p.mode !== d && (p.messages.length > 0 || p.backendSessionId) ? f = P(void 0, d) : p && p.mode !== d && at(f, d) : f = P(void 0, d), !f) return;
148
+ bt.current[f] = t;
149
149
  let m = ge(), g = {
150
- accessToken: Ke(),
150
+ accessToken: j(),
151
151
  workspaceToken: qe(),
152
152
  userId: Je,
153
153
  organizationId: he()
@@ -161,9 +161,9 @@ var j = ({ visible: p = !0, writeAccess: x = "unknown" }) => {
161
161
  ...h(r.voiceSessionId)
162
162
  }
163
163
  };
164
- I(f, _);
164
+ F(f, _);
165
165
  let v = Be();
166
- I(f, {
166
+ F(f, {
167
167
  id: v,
168
168
  role: "assistant",
169
169
  content: "",
@@ -172,9 +172,9 @@ var j = ({ visible: p = !0, writeAccess: x = "unknown" }) => {
172
172
  lang: tt,
173
173
  ...h(r.voiceSessionId)
174
174
  }
175
- }), R(f, "provisioning", v, null);
175
+ }), L(f, "provisioning", v, null);
176
176
  let te = (e, t, n, i, a = tt) => {
177
- L(f, v, { content: ee(e) }), st(f, v, {
177
+ I(f, v, { content: ee(e) }), ct(f, v, {
178
178
  lang: a,
179
179
  ...t?.length ? { artifacts: t } : {},
180
180
  ...t?.length || n || i ? { mode: d } : {},
@@ -185,9 +185,9 @@ var j = ({ visible: p = !0, writeAccess: x = "unknown" }) => {
185
185
  }, y = async (n = 1) => {
186
186
  let r = !1;
187
187
  try {
188
- let { sandboxId: n, sessionId: o } = await Ct(f, v, d, m, g), l = (await c(n, m, o, g, { limit: 50 }).catch(() => [])).reduce((e, t) => Math.max(e, O(t)), 0);
189
- K(f, v, "streaming", "Thinking...");
190
- let p = se(e, t), h = We?.(d, p, $e, et, i) ?? p, _ = oe(h, t), y = le(_), b = y > 0, re = Ue?.();
188
+ let { sandboxId: n, sessionId: o } = await Ct(f, v, d, m, g), l = (await c(n, m, o, g, { limit: 50 }).catch(() => [])).reduce((e, t) => Math.max(e, Ve(t)), 0);
189
+ q(f, v, "streaming", "Thinking...");
190
+ let p = se(e, t), h = Ge?.(d, p, $e, et, i) ?? p, _ = oe(h, t), y = le(_), b = y > 0, re = We?.();
191
191
  r = ce(t) > y;
192
192
  try {
193
193
  await u(n, m, o, h, d, re, g, _?.length ? { parts: _ } : void 0);
@@ -195,11 +195,11 @@ var j = ({ visible: p = !0, writeAccess: x = "unknown" }) => {
195
195
  if (!_ || !Ee(e)) throw e;
196
196
  await u(n, m, o, h, d, re, g, void 0), r ||= b;
197
197
  }
198
- let x = Ve([], l), ie = Date.now() + (Ie[d] ?? Le), ae = Date.now(), ue = Date.now();
199
- for (; Date.now() < ie && (x = Ve(await c(n, m, o, g, {
198
+ let x = He([], l), ie = Date.now() + (Ie[d] ?? Le), ae = Date.now(), ue = Date.now();
199
+ for (; Date.now() < ie && (x = He(await c(n, m, o, g, {
200
200
  limit: 50,
201
201
  sinceMs: l
202
- }), l), L(f, v, { content: ee(x.content) }), x.pendingWrite && st(f, v, { pendingWrite: x.pendingWrite }), !x.done);) Date.now() - ae > 3e4 && (await a(n, m, 600, g).catch(() => void 0), ae = Date.now()), await new Promise((e) => setTimeout(e, ne(Date.now() - ue)));
202
+ }), l), I(f, v, { content: ee(x.content) }), x.pendingWrite && ct(f, v, { pendingWrite: x.pendingWrite }), !x.done);) Date.now() - ae > 3e4 && (await a(n, m, 600, g).catch(() => void 0), ae = Date.now()), await new Promise((e) => setTimeout(e, ne(Date.now() - ue)));
203
203
  if (!x.done && d !== "vibe-plugins") throw Error("Assistant response timed out while streaming progress");
204
204
  let de = d === "vibe-plugins" ? await s(n, m, o, g).then((e) => e).catch(() => []) : void 0;
205
205
  if (x.done || (x = {
@@ -207,83 +207,83 @@ var j = ({ visible: p = !0, writeAccess: x = "unknown" }) => {
207
207
  content: `${x.content}\n\n_Still building in the background — any artifacts below will finish shortly. Re-open this conversation to pick up the completed plugin._`
208
208
  }), r && (x = {
209
209
  ...x,
210
- content: `${x.content}\n\n${k("attachments.imagesNotSent", "_Your photo was too large to include with this message, so the answer above is from the text and the file link only. Try a smaller or more tightly cropped photo._")}`
210
+ content: `${x.content}\n\n${O("attachments.imagesNotSent", "_Your photo was too large to include with this message, so the answer above is from the text and the file link only. Try a smaller or more tightly cropped photo._")}`
211
211
  }), te(x.content, de, o, n), x.tokens) {
212
- L(f, v, { tokens: x.tokens });
212
+ I(f, v, { tokens: x.tokens });
213
213
  try {
214
- await Ge?.({
214
+ await Ke?.({
215
215
  workspaceId: m,
216
216
  sessionId: o,
217
217
  messageId: x.messageId,
218
218
  model: x.model,
219
219
  tokens: x.tokens
220
- }), ke(A);
220
+ }), ke(k);
221
221
  } catch {}
222
222
  }
223
- R(f, "complete", v, null);
223
+ L(f, "complete", v, null);
224
224
  } catch (e) {
225
- if (n === 1 && De(e)) return lt(f), ut(d), y(2);
225
+ if (n === 1 && De(e)) return R(f), ut(d), y(2);
226
226
  throw e;
227
227
  }
228
228
  }, b = f;
229
- St.current.add(b);
229
+ xt.current.add(b);
230
230
  try {
231
231
  if (!m) throw Error("Assistant backend is unavailable without an active workspace context.");
232
232
  await y();
233
233
  } catch (e) {
234
- if (W.current.invalidate(S.getState().sandboxesByMode[d]?.sandboxId ?? null), n(e)) {
235
- Oe(A, "sandbox"), te("You've reached your sandbox limit on the current plan. Upgrade to start the AI assistant.", void 0, void 0, void 0, "en"), R(f, "error", v, null);
234
+ if (K.current.invalidate(S.getState().sandboxesByMode[d]?.sandboxId ?? null), n(e)) {
235
+ Oe(k, "sandbox"), te("You've reached your sandbox limit on the current plan. Upgrade to start the AI assistant.", void 0, void 0, void 0, "en"), L(f, "error", v, null);
236
236
  return;
237
237
  }
238
238
  let t = e instanceof Error ? e.message : "Something went wrong";
239
- R(f, "error", v, t), L(f, v, { content: `Sorry, an error occurred: ${t}. Please try again.` }), st(f, v, {
239
+ L(f, "error", v, t), I(f, v, { content: `Sorry, an error occurred: ${t}. Please try again.` }), ct(f, v, {
240
240
  lang: "en",
241
241
  ...h(r.voiceSessionId)
242
242
  });
243
243
  } finally {
244
- St.current.delete(b);
244
+ xt.current.delete(b);
245
245
  }
246
246
  }, [
247
247
  M,
248
- I,
249
- We,
250
- lt,
248
+ F,
249
+ Ge,
250
+ R,
251
251
  ut,
252
252
  nt,
253
- F,
253
+ P,
254
254
  Ct,
255
- Ue,
256
- Ke,
255
+ We,
256
+ j,
257
257
  qe,
258
- L,
259
- A,
260
- Ge,
258
+ I,
259
+ k,
260
+ Ke,
261
261
  et,
262
262
  tt,
263
263
  $e,
264
- ct,
265
- it,
266
- R,
267
- k,
268
- K,
264
+ lt,
265
+ at,
266
+ L,
267
+ O,
268
+ q,
269
269
  Je
270
270
  ]), wt = C((e) => {
271
- q(e);
272
- }, [q]), Tt = C(() => {
273
- let e = [...B.chat].reverse().find((e) => e.role === "user"), t = M ? xt.current[M] ?? [] : [];
274
- e && q(e.content, t);
271
+ J(e);
272
+ }, [J]), Tt = C(() => {
273
+ let e = [...B.chat].reverse().find((e) => e.role === "user"), t = M ? bt.current[M] ?? [] : [];
274
+ e && J(e.content, t);
275
275
  }, [
276
- ft,
277
- q,
276
+ V,
277
+ J,
278
278
  M
279
- ]), J = E(q);
279
+ ]), Y = E(J);
280
280
  w(() => {
281
- J.current = q;
282
- }, [q]);
283
- let Y = T(() => {
284
- if (H) return null;
285
- for (let e = ft.length - 1; e >= 0; --e) {
286
- let t = ft[e];
281
+ Y.current = J;
282
+ }, [J]);
283
+ let Et = T(() => {
284
+ if (U) return null;
285
+ for (let e = V.length - 1; e >= 0; --e) {
286
+ let t = V[e];
287
287
  if (t?.role !== "assistant" || !m(t)) continue;
288
288
  let n = pe(t.content).text.trim();
289
289
  return n ? {
@@ -292,34 +292,34 @@ var j = ({ visible: p = !0, writeAccess: x = "unknown" }) => {
292
292
  } : null;
293
293
  }
294
294
  return null;
295
- }, [ft, H]), Et = T(() => Y ? y(Y.text) : null, [Y]), Dt = B.chat, X = T(() => B.voice.filter((e) => e.role === "user" || e.role === "assistant").map((e) => ({
295
+ }, [V, U]), Dt = T(() => Et ? y(Et.text) : null, [Et]), Ot = B.chat, X = T(() => B.voice.filter((e) => e.role === "user" || e.role === "assistant").map((e) => ({
296
296
  id: e.id,
297
297
  role: e.role,
298
298
  text: pe(e.content).text.trim(),
299
299
  sessionId: g(e),
300
300
  timestamp: e.timestamp
301
- })).filter((e) => e.text.length > 0), [B.voice]), Ot = C(() => {
301
+ })).filter((e) => e.text.length > 0), [B.voice]), kt = C(() => {
302
302
  if (X.length === 0) return;
303
303
  let e = /* @__PURE__ */ new Date();
304
304
  be(v(X, {
305
- title: k("voiceSession.transcript", "Voice conversation"),
306
- savedAt: k("voiceSession.savedAt", "Saved"),
307
- session: k("voiceSession.sessionLabel", "Session"),
308
- earlier: k("voiceSession.earlierLabel", "Earlier"),
309
- you: k("voiceSession.speakerYou", "You"),
310
- assistant: k("voiceSession.speakerAssistant", "Assistant")
311
- }, e), te(A, e), "text/markdown");
305
+ title: O("voiceSession.transcript", "Voice conversation"),
306
+ savedAt: O("voiceSession.savedAt", "Saved"),
307
+ session: O("voiceSession.sessionLabel", "Session"),
308
+ earlier: O("voiceSession.earlierLabel", "Earlier"),
309
+ you: O("voiceSession.speakerYou", "You"),
310
+ assistant: O("voiceSession.speakerAssistant", "Assistant")
311
+ }, e), te(k, e), "text/markdown");
312
312
  }, [
313
- A,
313
+ k,
314
314
  X,
315
- k
315
+ O
316
316
  ]), Z = Ae(), Q = E(Z);
317
317
  Q.current = Z;
318
318
  let $ = me({
319
319
  onSubmit: C((e, t) => {
320
320
  let n = () => {
321
321
  let n = Q.current, r = ue(n.attachments);
322
- J.current(e, r, { voiceSessionId: t }), n.clear();
322
+ Y.current(e, r, { voiceSessionId: t }), n.clear();
323
323
  };
324
324
  if (!Q.current.isBusy) {
325
325
  n();
@@ -329,67 +329,77 @@ var j = ({ visible: p = !0, writeAccess: x = "unknown" }) => {
329
329
  Q.current.isBusy && Date.now() - r < ze || (window.clearInterval(i), n());
330
330
  }, 200);
331
331
  }, []),
332
- latestReply: Y,
332
+ latestReply: Et,
333
333
  language: b(Xe, Ye).tag
334
- }), kt = C(() => {
334
+ }), At = T(() => (ft?.messages ?? []).reduce((e, t) => Math.max(e, t.metadata?.continuedVoiceTurns ?? 0), 0), [ft?.messages]), jt = X.length > At, Mt = C(() => {
335
335
  let e = S.getState().activeConversationId;
336
- !e || X.length === 0 || (I(e, {
336
+ !e || X.length === 0 || (F(e, {
337
337
  id: Be(),
338
338
  role: "system",
339
- content: _(X, {
340
- intro: k("voiceSession.continuedIntro", "Continued from a voice conversation. You asked about:"),
341
- nothing: k("voiceSession.continuedNothing", "Continued from a voice conversation."),
342
- more: (e) => k("voiceSession.continuedMore", "…and {{count}} more", { count: e })
339
+ content: _(X.slice(At), {
340
+ intro: O("voiceSession.continuedIntro", "Continued from a voice conversation. You asked about:"),
341
+ nothing: O("voiceSession.continuedNothing", "Continued from a voice conversation."),
342
+ more: (e) => O("voiceSession.continuedMore", "…and {{count}} more", { count: e })
343
343
  }),
344
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
345
- }), bt(!1), $.end());
344
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
345
+ metadata: { continuedVoiceTurns: X.length }
346
+ }), G(!1), $.end());
346
347
  }, [
347
348
  X,
348
- I,
349
- k
350
- ]);
349
+ At,
350
+ F,
351
+ O,
352
+ $
353
+ ]), Nt = E(0);
354
+ w(() => {
355
+ $.active && (Nt.current = X.length);
356
+ }, [$.active]);
357
+ let Pt = C(() => {
358
+ let e = X.length > Nt.current;
359
+ $.end(), e && G(!0);
360
+ }, [X, $]);
351
361
  w(() => {
352
362
  !p && $.active && $.end();
353
363
  }, [p, $]), w(() => {
354
364
  $.active || Q.current.clear();
355
365
  }, [$.active]), w(() => {
356
366
  let e = S.getState().consumePendingPrompt();
357
- return e && J.current(e), S.subscribe((e, t) => {
367
+ return e && Y.current(e), S.subscribe((e, t) => {
358
368
  if (e.pendingPrompt && e.pendingPrompt !== t.pendingPrompt) {
359
369
  let e = S.getState().consumePendingPrompt();
360
- e && J.current(e);
370
+ e && Y.current(e);
361
371
  }
362
372
  });
363
373
  }, []);
364
- let At = C((e) => {
374
+ let Ft = C((e) => {
365
375
  let t = M ? S.getState().conversations.find((e) => e.id === M) : void 0;
366
376
  if (t && (t.messages.length > 0 || t.backendSessionId)) {
367
377
  if (t.mode !== e) {
368
378
  let t = S.getState().conversations.find((t) => t.mode === e && t.messages.length === 0 && !t.backendSessionId && !S.getState().processingByConversationId[t.id]);
369
- t ? at(t.id) : F(void 0, e);
379
+ t ? ot(t.id) : P(void 0, e);
370
380
  }
371
- } else M && it(M, e);
372
- P(e);
381
+ } else M && at(M, e);
382
+ it(e);
373
383
  }, [
374
384
  M,
375
- F,
385
+ P,
386
+ ot,
376
387
  at,
377
- it,
378
- P
379
- ]), jt = C((e) => {
380
- if (j.find((t) => t.id === e)?.writeCapable && !S.getState().apiCallsAcknowledged) {
388
+ it
389
+ ]), It = C((e) => {
390
+ if (A.find((t) => t.id === e)?.writeCapable && !S.getState().apiCallsAcknowledged) {
381
391
  vt(e);
382
392
  return;
383
393
  }
384
- At(e);
385
- }, [At, j]), Mt = C(() => {
394
+ Ft(e);
395
+ }, [Ft, A]), Lt = C(() => {
386
396
  let e = _t;
387
- vt(null), dt(), e && At(e);
397
+ vt(null), dt(), e && Ft(e);
388
398
  }, [
389
399
  _t,
390
400
  dt,
391
- At
392
- ]), Nt = C(() => {
401
+ Ft
402
+ ]), Rt = C(() => {
393
403
  vt(null);
394
404
  }, []);
395
405
  return /* @__PURE__ */ Fe("div", {
@@ -401,15 +411,15 @@ var j = ({ visible: p = !0, writeAccess: x = "unknown" }) => {
401
411
  children: [
402
412
  X.length > 0 && !$.active ? /* @__PURE__ */ D(ve, {
403
413
  count: X.length,
404
- onOpenTranscript: () => bt(!0)
414
+ onOpenTranscript: () => G(!0)
405
415
  }) : null,
406
- Dt.length === 0 ? /* @__PURE__ */ D(xe, {
416
+ Ot.length === 0 ? /* @__PURE__ */ D(xe, {
407
417
  mode: N,
408
418
  onSuggestionClick: wt
409
419
  }) : /* @__PURE__ */ D("div", {
410
420
  className: "flex min-h-0 flex-1 flex-col",
411
421
  children: /* @__PURE__ */ D(Se, {
412
- messages: Dt,
422
+ messages: Ot,
413
423
  streamingMessageId: pt,
414
424
  failedMessageId: mt,
415
425
  onRetry: Tt
@@ -417,20 +427,22 @@ var j = ({ visible: p = !0, writeAccess: x = "unknown" }) => {
417
427
  }),
418
428
  /* @__PURE__ */ D(je, {
419
429
  onStartVoiceSession: $.available && N !== "api-calls" ? $.start : void 0,
420
- onSend: (e, t) => void q(e, t),
421
- disabled: H,
422
- placeholder: N === "api-calls" ? k("chatArea.placeholderActions", "What would you like me to do?") : k("chatArea.placeholderGeneral", "Ask me anything…"),
430
+ onSend: (e, t) => void J(e, t),
431
+ disabled: U,
432
+ placeholder: N === "api-calls" ? O("chatArea.placeholderActions", "What would you like me to do?") : O("chatArea.placeholderGeneral", "Ask me anything…"),
423
433
  mode: N,
424
- writeAccessDenied: x === "denied" && !!G?.writeCapable,
434
+ writeAccessDenied: x === "denied" && !!St?.writeCapable,
425
435
  availableModes: gt,
426
- onModeChange: jt
436
+ onModeChange: It
427
437
  })
428
438
  ]
429
439
  }),
430
440
  yt && !$.active ? /* @__PURE__ */ D(ye, {
431
441
  turns: X,
432
- onClose: () => bt(!1),
433
- onSave: Ot
442
+ onClose: () => G(!1),
443
+ onSave: kt,
444
+ onContinueInChat: jt ? Mt : void 0,
445
+ closeOnEscape: !0
434
446
  }) : null,
435
447
  $.active && /* @__PURE__ */ D(Ce, {
436
448
  session: $.session,
@@ -446,20 +458,20 @@ var j = ({ visible: p = !0, writeAccess: x = "unknown" }) => {
446
458
  onRetryAttachment: Z.retry,
447
459
  canAttachMore: Z.canAddMore,
448
460
  preparingAttachments: Z.preparingCount,
449
- onSaveTranscript: Ot,
450
- onContinueInChat: kt,
461
+ onSaveTranscript: kt,
462
+ onContinueInChat: Mt,
451
463
  onInterrupt: $.interrupt,
452
- spoken: Et,
464
+ spoken: Dt,
453
465
  onToggleMute: $.toggleMute,
454
- onEnd: $.end
466
+ onEnd: Pt
455
467
  }),
456
468
  /* @__PURE__ */ D(Ne, {
457
469
  open: _t !== null,
458
- onConfirm: Mt,
459
- onCancel: Nt
470
+ onConfirm: Lt,
471
+ onCancel: Rt
460
472
  })
461
473
  ]
462
474
  });
463
475
  };
464
476
  //#endregion
465
- export { j as AssistantChatArea };
477
+ export { A as AssistantChatArea };
@@ -1 +1 @@
1
- {"version":3,"file":"AssistantVoiceSession.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/ui/voice/AssistantVoiceSession.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA4C,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AAI1E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAO7D,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEtE,gFAAgF;AAChF,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAElD,UAAU,KAAK;IACb,OAAO,EAAE,oBAAoB,CAAC;IAC9B,iEAAiE;IACjE,KAAK,CAAC,EAAE,aAAa,CAAC,mBAAmB,CAAC,CAAC;IAC3C,wCAAwC;IACxC,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,6EAA6E;IAC7E,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,6EAA6E;IAC7E,MAAM,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACnC,gEAAgE;IAChE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACpC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,KAAK,IAAI,CAAC;IACjD,kBAAkB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,iBAAiB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,0EAA0E;IAC1E,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,4DAA4D;IAC5D,YAAY,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC1D,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,mFAAmF;IACnF,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,0EAA0E;IAC1E,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,wEAAwE;IACxE,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,qBAAqB,EAAE,EAAE,CAAC,KAAK,CAuiB3C,CAAC"}
1
+ {"version":3,"file":"AssistantVoiceSession.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/ui/voice/AssistantVoiceSession.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA4C,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AAI1E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAO7D,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEtE,gFAAgF;AAChF,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAElD,UAAU,KAAK;IACb,OAAO,EAAE,oBAAoB,CAAC;IAC9B,iEAAiE;IACjE,KAAK,CAAC,EAAE,aAAa,CAAC,mBAAmB,CAAC,CAAC;IAC3C,wCAAwC;IACxC,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,6EAA6E;IAC7E,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,6EAA6E;IAC7E,MAAM,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACnC,gEAAgE;IAChE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACpC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,KAAK,IAAI,CAAC;IACjD,kBAAkB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,iBAAiB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,0EAA0E;IAC1E,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,4DAA4D;IAC5D,YAAY,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC1D,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,mFAAmF;IACnF,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,0EAA0E;IAC1E,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,wEAAwE;IACxE,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,qBAAqB,EAAE,EAAE,CAAC,KAAK,CAkkB3C,CAAC"}
@@ -2,31 +2,31 @@ import { micIsInterrupt as e, voiceStageState as t } from "../../voice/voiceStag
2
2
  import { spokenSoFar as n } from "../../voice/voiceSession.js";
3
3
  import { useAssistantTr as r } from "../../i18n.js";
4
4
  import { AssistantAttachmentButton as i } from "../composer/AssistantAttachmentButton.js";
5
- import { AssistantAttachmentChips as ee } from "../composer/AssistantAttachmentChips.js";
6
- import { AssistantVoiceOrb as a } from "./AssistantVoiceOrb.js";
7
- import { VoiceMiniController as te } from "./VoiceMiniController.js";
8
- import { VoiceStage as ne } from "./VoiceStage.js";
9
- import { VoiceTranscriptDrawer as o } from "./VoiceTranscriptDrawer.js";
10
- import { useCallback as re, useEffect as s, useRef as c, useState as l } from "react";
11
- import { Maximize2 as u, Minimize2 as d, ScrollText as f, X as p } from "lucide-react";
12
- import { jsx as m, jsxs as h } from "react/jsx-runtime";
5
+ import { AssistantAttachmentChips as a } from "../composer/AssistantAttachmentChips.js";
6
+ import { AssistantVoiceOrb as o } from "./AssistantVoiceOrb.js";
7
+ import { VoiceMiniController as s } from "./VoiceMiniController.js";
8
+ import { VoiceStage as c } from "./VoiceStage.js";
9
+ import { VoiceTranscriptDrawer as ee } from "./VoiceTranscriptDrawer.js";
10
+ import { useCallback as te, useEffect as l, useRef as u, useState as d } from "react";
11
+ import { Maximize2 as f, Minimize2 as p, ScrollText as m, X as h } from "lucide-react";
12
+ import { jsx as g, jsxs as _ } from "react/jsx-runtime";
13
13
  //#region src/shared/assistant/ui/voice/AssistantVoiceSession.tsx
14
- var g = ({ session: g, turns: y = [], onSaveTranscript: b, onContinueInChat: x, notice: S = null, spoken: C, onInterrupt: w, onToggleMute: T, attachments: E = [], onAttachFiles: D, onRemoveAttachment: O, onRetryAttachment: k, canAttachMore: ie = !0, preparingAttachments: A = 0, spokenChunks: j = null, onEnd: M, capturing: ae = !0, interrupting: N = !1, awaitingEndpoint: P = !1 }) => {
15
- let F = r(), { muted: I, error: L } = g, R = c(null), z = c(null), [B, V] = l("mini"), H = B === "full", U = B === "mini", W = B === "mini" ? "panel" : B === "panel" ? "full" : "mini", [G, K] = l(!1), q = c(!1), J = c(T);
16
- J.current = T;
17
- let oe = re(() => {
18
- I || q.current || n(g) || (q.current = !0, J.current());
19
- }, [I, g]);
20
- s(() => {
14
+ var v = ({ session: v, turns: b = [], onSaveTranscript: x, onContinueInChat: S, notice: C = null, spoken: w, onInterrupt: T, onToggleMute: E, attachments: D = [], onAttachFiles: O, onRemoveAttachment: k, onRetryAttachment: re, canAttachMore: ie = !0, preparingAttachments: A = 0, spokenChunks: j = null, onEnd: M, capturing: ae = !0, interrupting: N = !1, awaitingEndpoint: P = !1 }) => {
15
+ let F = r(), { muted: I, error: L } = v, R = u(null), z = u(null), [B, V] = d("mini"), H = B === "full", U = B === "mini", W = B === "mini" ? "panel" : B === "panel" ? "full" : "mini", [G, K] = d(!1), q = u(!1), J = u(E);
16
+ J.current = E;
17
+ let oe = te(() => {
18
+ I || q.current || n(v) || (q.current = !0, J.current());
19
+ }, [I, v]);
20
+ l(() => {
21
21
  let e = () => {
22
22
  q.current && (q.current = !1, J.current());
23
23
  };
24
24
  return window.addEventListener("focus", e), () => {
25
25
  window.removeEventListener("focus", e), q.current = !1;
26
26
  };
27
- }, []), s(() => {
27
+ }, []), l(() => {
28
28
  R.current?.focus();
29
- }, []), s(() => {
29
+ }, []), l(() => {
30
30
  let e = (e) => {
31
31
  if (e.key === "Escape") {
32
32
  if (G) {
@@ -48,8 +48,8 @@ var g = ({ session: g, turns: y = [], onSaveTranscript: b, onContinueInChat: x,
48
48
  H,
49
49
  G
50
50
  ]);
51
- let Y = S !== null && L === null, X = n(g), Z = t({
52
- snapshot: g,
51
+ let Y = C !== null && L === null, X = n(v), Z = t({
52
+ snapshot: v,
53
53
  capturing: ae,
54
54
  interrupting: N,
55
55
  awaitingEndpoint: P
@@ -66,7 +66,7 @@ var g = ({ session: g, turns: y = [], onSaveTranscript: b, onContinueInChat: x,
66
66
  default: return Z;
67
67
  }
68
68
  })(), $ = I && Z !== "listening" && Q !== "" ? `${Q} · ${F("voiceSession.muted", "Microphone off")}` : Q;
69
- return /* @__PURE__ */ h("div", {
69
+ return /* @__PURE__ */ _("div", {
70
70
  ref: z,
71
71
  className: `flex flex-col items-center justify-between bg-bg-sunken ${B === "full" ? "fixed inset-x-0 bottom-0 top-14 z-[60] px-6 py-8" : B === "panel" ? "absolute inset-0 z-20 px-4 py-6" : "absolute inset-x-0 bottom-0 z-20 h-[11.25rem] border-t border-border-subtle px-3 py-3 shadow-lg"}`,
72
72
  role: "dialog",
@@ -74,103 +74,103 @@ var g = ({ session: g, turns: y = [], onSaveTranscript: b, onContinueInChat: x,
74
74
  "aria-label": F("voiceSession.title", "Voice conversation"),
75
75
  "data-testid": "assistant-voice-session",
76
76
  children: [
77
- /* @__PURE__ */ h("button", {
77
+ /* @__PURE__ */ _("button", {
78
78
  ref: R,
79
79
  type: "button",
80
80
  onClick: M,
81
- className: `absolute ${H ? "right-6 top-6 h-14 gap-2 px-5 text-base" : U ? "right-2 top-2 size-8" : "right-3 top-3 h-11 gap-2 px-4 text-sm"} flex items-center justify-center rounded-full border border-border-default bg-bg-elevated text-text-secondary hover:bg-bg-sunken transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong`,
82
- "aria-label": U ? F("voiceSession.end", "End the voice conversation") : void 0,
81
+ className: `absolute ${H ? "right-6 top-6 h-14 gap-2 px-5 text-base" : U ? "right-12 top-2 h-8 gap-1.5 px-2.5 text-xs" : "right-3 top-3 h-11 gap-2 px-4 text-sm"} flex items-center justify-center rounded-full border border-border-default bg-bg-elevated text-text-secondary hover:bg-bg-sunken transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong`,
82
+ title: F("voiceSession.end", "End the voice conversation"),
83
83
  "data-testid": "assistant-voice-end",
84
- children: [/* @__PURE__ */ m(p, {
84
+ children: [/* @__PURE__ */ g(h, {
85
85
  className: H ? "size-6" : U ? "size-4" : "size-5",
86
86
  "aria-hidden": "true"
87
- }), U ? null : /* @__PURE__ */ m("span", {
88
- className: "max-w-[7rem] truncate whitespace-nowrap font-medium",
87
+ }), /* @__PURE__ */ g("span", {
88
+ className: `truncate whitespace-nowrap font-medium ${U ? "max-w-[3.5rem] text-xs" : "max-w-[7rem]"}`,
89
89
  children: F("voiceSession.endShort", "End")
90
90
  })]
91
91
  }),
92
- /* @__PURE__ */ m("div", {
92
+ /* @__PURE__ */ g("div", {
93
93
  className: `flex flex-col items-center ${U ? "px-3" : `min-h-[1.5rem] ${Y ? H ? "pt-14" : "pt-10" : ""}`}`,
94
- children: Y ? /* @__PURE__ */ m("p", {
94
+ children: Y ? /* @__PURE__ */ g("p", {
95
95
  className: "max-w-xs text-center text-xs text-status-warning",
96
96
  "data-testid": "assistant-voice-notice",
97
- children: _(S, F)
97
+ children: ne(C, F)
98
98
  }) : null
99
99
  }),
100
100
  (() => {
101
- let t = /* @__PURE__ */ m(a, {
102
- session: g,
101
+ let t = /* @__PURE__ */ g(o, {
102
+ session: v,
103
103
  compact: U,
104
104
  connecting: Z === "connecting",
105
- onPress: e(Z) ? w : T,
105
+ onPress: e(Z) ? T : E,
106
106
  label: e(Z) ? F("voiceSession.interrupt", "Stop the assistant and speak") : I ? F("voiceSession.unmute", "Turn the microphone on") : F("voiceSession.mute", "Turn the microphone off")
107
- }), n = e(Z) ? C : X || null, r = L === null ? null : v(L, F);
108
- return U ? /* @__PURE__ */ m(te, {
107
+ }), n = e(Z) ? w : X || null, r = L === null ? null : y(L, F);
108
+ return U ? /* @__PURE__ */ g(s, {
109
109
  spokenChunks: j,
110
110
  state: Z,
111
111
  caption: n,
112
112
  statusText: $,
113
113
  errorText: r,
114
114
  control: t
115
- }) : /* @__PURE__ */ m(ne, {
115
+ }) : /* @__PURE__ */ g(c, {
116
116
  state: Z,
117
117
  userCaption: X || null,
118
118
  spokenChunks: j,
119
- assistantCaption: C,
119
+ assistantCaption: w,
120
120
  expanded: H,
121
121
  statusText: $,
122
122
  errorText: r,
123
123
  control: t
124
124
  });
125
125
  })(),
126
- G ? /* @__PURE__ */ m(o, {
127
- turns: y,
126
+ G ? /* @__PURE__ */ g(ee, {
127
+ turns: b,
128
128
  onClose: () => K(!1),
129
- onSave: b,
130
- onContinueInChat: x
129
+ onSave: x,
130
+ onContinueInChat: S
131
131
  }) : null,
132
- D ? /* @__PURE__ */ m("div", {
132
+ O ? /* @__PURE__ */ g("div", {
133
133
  className: `absolute ${H ? "left-6 top-6" : U ? "left-11 top-2" : "left-3 top-3"}`,
134
- children: /* @__PURE__ */ m(i, {
134
+ children: /* @__PURE__ */ g(i, {
135
135
  onFiles: (e) => {
136
- D(e), V((e) => e === "mini" ? "panel" : e);
136
+ O(e), V((e) => e === "mini" ? "panel" : e);
137
137
  },
138
138
  onPickerOpen: oe,
139
139
  direction: "down",
140
140
  canAddMore: ie
141
141
  })
142
142
  }) : null,
143
- (E.length > 0 || A > 0) && !U ? /* @__PURE__ */ m("div", {
143
+ (D.length > 0 || A > 0) && !U ? /* @__PURE__ */ g("div", {
144
144
  className: `absolute ${H ? "bottom-24 left-24 right-24" : "bottom-16 left-16 right-16"}`,
145
145
  "data-testid": "assistant-voice-attachments",
146
- children: /* @__PURE__ */ m(ee, {
147
- attachments: E,
148
- onRemove: O ?? (() => void 0),
149
- onRetry: k ?? (() => void 0),
146
+ children: /* @__PURE__ */ g(a, {
147
+ attachments: D,
148
+ onRemove: k ?? (() => void 0),
149
+ onRetry: re ?? (() => void 0),
150
150
  preparingCount: A
151
151
  })
152
152
  }) : null,
153
- /* @__PURE__ */ m("button", {
153
+ /* @__PURE__ */ g("button", {
154
154
  type: "button",
155
155
  onClick: () => K((e) => !e),
156
- className: `absolute ${H ? "bottom-6 right-6 size-14" : U ? "right-11 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`,
156
+ className: `absolute ${H ? "bottom-6 right-6 size-14" : U ? "right-2 top-2 size-8" : "bottom-3 right-3 size-11"} flex items-center justify-center rounded-full bg-bg-elevated text-text-secondary transition-colors hover:bg-bg-raised hover:text-text-primary focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong`,
157
157
  "aria-pressed": G,
158
158
  "aria-label": F("voiceSession.transcript", "Voice transcript"),
159
159
  "data-testid": "assistant-voice-transcript-toggle",
160
- children: /* @__PURE__ */ m(f, { className: H ? "size-6" : U ? "size-4" : "size-5" })
160
+ children: /* @__PURE__ */ g(m, { className: H ? "size-6" : U ? "size-4" : "size-5" })
161
161
  }),
162
- /* @__PURE__ */ m("button", {
162
+ /* @__PURE__ */ g("button", {
163
163
  type: "button",
164
164
  onClick: () => V(W),
165
165
  className: `absolute ${H ? "bottom-6 left-6 size-14" : U ? "left-2 top-2 size-8" : "bottom-3 left-3 size-11"} flex items-center justify-center rounded-full bg-bg-elevated text-text-secondary transition-colors hover:bg-bg-raised hover:text-text-primary focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong`,
166
166
  "aria-label": W === "panel" ? F("voiceSession.expandPanel", "Show the conversation in the panel") : W === "full" ? F("voiceSession.expand", "Expand the conversation to full screen") : F("voiceSession.collapse", "Shrink to the compact controller"),
167
167
  "data-testid": "assistant-voice-expand",
168
- children: H ? /* @__PURE__ */ m(d, { className: "size-5" }) : /* @__PURE__ */ m(u, { className: U ? "size-4" : "size-5" })
168
+ children: H ? /* @__PURE__ */ g(p, { className: "size-5" }) : /* @__PURE__ */ g(f, { className: U ? "size-4" : "size-5" })
169
169
  })
170
170
  ]
171
171
  });
172
172
  };
173
- function _(e, t) {
173
+ function ne(e, t) {
174
174
  switch (e) {
175
175
  case "network": return t("voiceSession.noticeNetwork", "Speech recognition lost its connection. Check your network — it will retry.");
176
176
  case "not-capturing": return t("voiceSession.noticeNotCapturing", "The microphone did not start. Check that this site is allowed to use it, then try again.");
@@ -179,7 +179,7 @@ function _(e, t) {
179
179
  default: return e;
180
180
  }
181
181
  }
182
- function v(e, t) {
182
+ function y(e, t) {
183
183
  switch (e) {
184
184
  case "mic-denied": return t("voiceSession.micDenied", "Microphone access is blocked. Allow it in your browser settings to talk.");
185
185
  case "no-speech-support": return t("voiceSession.noSpeechSupport", "This browser cannot listen. Try a different browser, or type instead.");
@@ -188,4 +188,4 @@ function v(e, t) {
188
188
  }
189
189
  }
190
190
  //#endregion
191
- export { g as AssistantVoiceSession };
191
+ export { v as AssistantVoiceSession };
@@ -1 +1 @@
1
- {"version":3,"file":"VoiceCaption.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/ui/voice/VoiceCaption.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAEhC;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,UAAU,KAAK;IACb,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,mDAAmD;IACnD,QAAQ,EAAE,OAAO,CAAC;IAClB;;;;;;;;;;;;;OAaG;IACH,YAAY,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,YAAY,EAAE,EAAE,CAAC,KAAK,CA0ElC,CAAC"}
1
+ {"version":3,"file":"VoiceCaption.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/ui/voice/VoiceCaption.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAEhC;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,UAAU,KAAK;IACb,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,mDAAmD;IACnD,QAAQ,EAAE,OAAO,CAAC;IAClB;;;;;;;;;;;;;OAaG;IACH,YAAY,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,YAAY,EAAE,EAAE,CAAC,KAAK,CAsFlC,CAAC"}
@@ -9,7 +9,7 @@ var n = ({ text: n, role: r, expanded: i, spokenChunks: a = null, testId: o }) =
9
9
  "w-full whitespace-pre-wrap break-words text-left",
10
10
  i ? "max-w-[45rem]" : "max-w-md",
11
11
  s ? "font-semibold text-text-primary" : "font-medium text-text-secondary",
12
- i ? s ? "text-[clamp(1.625rem,2.5vw,2.25rem)] leading-[1.5]" : "text-[clamp(1.125rem,1.8vw,1.375rem)] leading-[1.5]" : s ? "text-lg leading-relaxed" : "text-base leading-relaxed"
12
+ s ? i ? "text-[clamp(1.625rem,2.5vw,2.25rem)] leading-[1.5]" : "text-[clamp(1.625rem,2vw,2rem)] leading-[1.5]" : i ? "text-[clamp(1.125rem,1.8vw,1.375rem)] leading-[1.5]" : "text-base leading-relaxed"
13
13
  ].join(" "),
14
14
  role: "status",
15
15
  "aria-live": "polite",
@@ -27,12 +27,26 @@ interface Props {
27
27
  /**
28
28
  * Leave a note of this exchange in the typed thread and carry on there.
29
29
  *
30
- * Supplied only DURING a live session, where "continue in chat" is a move
31
- * the user is making. Opened from the chat panel afterwards they are already
32
- * in chat, and a button offering to take them there would be a no-op with a
33
- * confident label.
30
+ * ★★ Offered on BOTH mounts. This said "only DURING a live session opened
31
+ * from the chat panel the user is already in chat, so the button would be a
32
+ * no-op with a confident label". That reads it as navigation; it is not. It
33
+ * WRITES the note summarising what was asked aloud, and ending the session is
34
+ * the side effect. Withheld here, the trace was obtainable only while the
35
+ * session was still live.
36
+ *
37
+ * ★ Undefined once every turn has already been carried over, so the note
38
+ * cannot be appended twice from a drawer the user can reopen.
34
39
  */
35
40
  onContinueInChat?: () => void;
41
+ /**
42
+ * ★★ Close on Escape. Set on the POST-SESSION mount only.
43
+ *
44
+ * During a live session `AssistantVoiceSession` owns Escape and closes this
45
+ * drawer itself; two handlers would race for one key. But ending a session
46
+ * with Escape hands back this drawer with that component unmounted, so
47
+ * nothing was listening and the gesture that opened it could not close it.
48
+ */
49
+ closeOnEscape?: boolean;
36
50
  }
37
51
  export declare const VoiceTranscriptDrawer: FC<Props>;
38
52
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"VoiceTranscriptDrawer.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/ui/voice/VoiceTranscriptDrawer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAIhC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEtE;;;;;;;;;;;;;;;;;;GAkBG;AAEH,UAAU,KAAK;IACb,KAAK,EAAE,aAAa,CAAC,mBAAmB,CAAC,CAAC;IAC1C,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB;;;;;;;OAOG;IACH,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;CAC/B;AAED,eAAO,MAAM,qBAAqB,EAAE,EAAE,CAAC,KAAK,CAsF3C,CAAC"}
1
+ {"version":3,"file":"VoiceTranscriptDrawer.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/ui/voice/VoiceTranscriptDrawer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AAInD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEtE;;;;;;;;;;;;;;;;;;GAkBG;AAEH,UAAU,KAAK;IACb,KAAK,EAAE,aAAa,CAAC,mBAAmB,CAAC,CAAC;IAC1C,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB;;;;;;;;;;;;OAYG;IACH,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,eAAO,MAAM,qBAAqB,EAAE,EAAE,CAAC,KAAK,CAqI3C,CAAC"}
@@ -1,54 +1,64 @@
1
1
  import { useAssistantTr as e } from "../../i18n.js";
2
2
  import { VoiceConversationView as t } from "./VoiceConversationView.js";
3
- import { ArrowRight as n, Download as r, X as i } from "lucide-react";
4
- import { jsx as a, jsxs as o } from "react/jsx-runtime";
3
+ import { useEffect as n, useRef as r } from "react";
4
+ import { ArrowRight as i, Download as a, X as o } from "lucide-react";
5
+ import { jsx as s, jsxs as c } from "react/jsx-runtime";
5
6
  //#region src/shared/assistant/ui/voice/VoiceTranscriptDrawer.tsx
6
- var s = ({ turns: s, onClose: c, onSave: l, onContinueInChat: u }) => {
7
- let d = e();
8
- return /* @__PURE__ */ o("div", {
7
+ var l = ({ turns: l, onClose: u, onSave: d, onContinueInChat: f, closeOnEscape: p = !1 }) => {
8
+ let m = e(), h = r(null);
9
+ return n(() => {
10
+ if (!p) return;
11
+ let e = (e) => {
12
+ if (e.key !== "Escape" || document.querySelector("[role=\"alertdialog\"]")) return;
13
+ let t = h.current?.closest("[data-testid=\"ai-assistant-panel\"]"), n = document.activeElement;
14
+ !t || !n || !t.contains(n) || (e.preventDefault(), e.stopPropagation(), u());
15
+ };
16
+ return document.addEventListener("keydown", e, !0), () => document.removeEventListener("keydown", e, !0);
17
+ }, [p, u]), /* @__PURE__ */ c("div", {
18
+ ref: h,
9
19
  className: "absolute inset-0 z-30 flex flex-col bg-bg-sunken/95 backdrop-blur-sm",
10
20
  role: "dialog",
11
- "aria-label": d("voiceSession.transcriptTitle", "Voice transcript"),
21
+ "aria-label": m("voiceSession.transcriptTitle", "Voice transcript"),
12
22
  "data-testid": "assistant-voice-transcript",
13
23
  children: [
14
- /* @__PURE__ */ o("div", {
24
+ /* @__PURE__ */ c("div", {
15
25
  className: "flex items-center justify-between border-b border-border-subtle px-4 py-3",
16
- children: [/* @__PURE__ */ o("div", {
26
+ children: [/* @__PURE__ */ c("div", {
17
27
  className: "min-w-0",
18
- children: [/* @__PURE__ */ a("h2", {
28
+ children: [/* @__PURE__ */ s("h2", {
19
29
  className: "text-sm font-semibold text-text-primary",
20
- children: d("voiceSession.transcript", "Voice conversation")
21
- }), /* @__PURE__ */ a("p", {
30
+ children: m("voiceSession.transcript", "Voice conversation")
31
+ }), /* @__PURE__ */ s("p", {
22
32
  className: "truncate text-xs text-text-muted",
23
- children: d("voiceSession.transcriptHint", "Spoken turns in this conversation — kept out of your typed chat.")
33
+ children: m("voiceSession.transcriptHint", "Spoken turns in this conversation — kept out of your typed chat.")
24
34
  })]
25
- }), /* @__PURE__ */ a("button", {
35
+ }), /* @__PURE__ */ s("button", {
26
36
  type: "button",
27
- onClick: c,
37
+ onClick: u,
28
38
  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",
29
- "aria-label": d("voiceSession.transcriptClose", "Close the transcript"),
39
+ "aria-label": m("voiceSession.transcriptClose", "Close the transcript"),
30
40
  "data-testid": "assistant-voice-transcript-close",
31
- children: /* @__PURE__ */ a(i, { className: "size-4" })
41
+ children: /* @__PURE__ */ s(o, { className: "size-4" })
32
42
  })]
33
43
  }),
34
- /* @__PURE__ */ a(t, { turns: s }),
35
- (l || u) && s.length > 0 ? /* @__PURE__ */ o("div", {
44
+ /* @__PURE__ */ s(t, { turns: l }),
45
+ (d || f) && l.length > 0 ? /* @__PURE__ */ c("div", {
36
46
  className: "flex items-center justify-end gap-2 border-t border-border-subtle px-4 py-3",
37
- children: [l ? /* @__PURE__ */ o("button", {
47
+ children: [d ? /* @__PURE__ */ c("button", {
38
48
  type: "button",
39
- onClick: l,
49
+ onClick: d,
40
50
  className: "flex items-center gap-1.5 rounded-lg border border-border-default px-3 py-1.5 text-xs text-text-secondary transition-colors hover:bg-bg-elevated hover:text-text-primary focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong",
41
51
  "data-testid": "assistant-voice-save-transcript",
42
- children: [/* @__PURE__ */ a(r, {
52
+ children: [/* @__PURE__ */ s(a, {
43
53
  className: "size-3.5",
44
54
  "aria-hidden": "true"
45
- }), d("voiceSession.save", "Save transcript")]
46
- }) : null, u ? /* @__PURE__ */ o("button", {
55
+ }), m("voiceSession.save", "Save transcript")]
56
+ }) : null, f ? /* @__PURE__ */ c("button", {
47
57
  type: "button",
48
- onClick: u,
58
+ onClick: f,
49
59
  className: "flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-3 py-1.5 text-xs font-medium text-action-primary-fg transition-opacity hover:opacity-90 focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong",
50
60
  "data-testid": "assistant-voice-continue-in-chat",
51
- children: [d("voiceSession.continueInChat", "Continue in chat"), /* @__PURE__ */ a(n, {
61
+ children: [m("voiceSession.continueInChat", "Continue in chat"), /* @__PURE__ */ s(i, {
52
62
  className: "size-3.5",
53
63
  "aria-hidden": "true"
54
64
  })]
@@ -58,4 +68,4 @@ var s = ({ turns: s, onClose: c, onSave: l, onContinueInChat: u }) => {
58
68
  });
59
69
  };
60
70
  //#endregion
61
- export { s as VoiceTranscriptDrawer };
71
+ export { l as VoiceTranscriptDrawer };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/fe-libs",
3
- "version": "2026.906.2",
3
+ "version": "2026.906.3",
4
4
  "description": "Burdenoff frontend primitives and domain libraries",
5
5
  "type": "module",
6
6
  "bin": {