@burdenoff/fe-libs 2026.909.1 → 2026.909.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.
@@ -27,19 +27,20 @@ export declare function isTurnInFlight(status: AssistantConversationStatus | und
27
27
  * cancelled, leaving the live turn's own completion landing on an entry that no
28
28
  * longer describes it. Silently: there is no error on either side.
29
29
  *
30
- * ★ Scope, stated honestly. This does NOT fire in the voice correction flow:
31
- * the orb is `disabled` while the phase is `thinking`
32
- * (`ui/voice/AssistantVoiceOrb.tsx`), and `micIsInterrupt` is true only for
33
- * `speaking` which is reachable only once the turn is already complete. So no
34
- * voice turn can be aborted mid-generation today. Where this earns its place is
35
- * the host-page `pendingPrompt` route, which starts turns past the voice
36
- * overlay and CAN be aborted while running.
30
+ * ★ Scope. This now fires in the VOICE flow: the orb is pressable during
31
+ * `thinking` and `micIsInterrupt` covers it, so a user can cut off an answer
32
+ * while it is still being generated. It also covers the host-page
33
+ * `pendingPrompt` route, which starts turns past the voice overlay.
37
34
  *
38
- * ★★ It is therefore NOT what delivers stale-output rejection. Old TEXT
39
- * reaching a new caption is a separate defect with a separate fix see
40
- * `publishedChunks` in `voice/speechPlayback.ts`. Do not conflate them; an
41
- * earlier version of this comment claimed this guard stopped the cancelled
42
- * answer being read aloud, and that was never reachable.
35
+ * Two earlier versions of this comment were wrong in opposite directions, which
36
+ * is why the scope is now stated rather than assumed. The first claimed this
37
+ * guard stopped the cancelled answer being read aloud — it never could. The
38
+ * second said it could not fire from voice at all — true only while the orb was
39
+ * inert during `thinking`, which was the very thing this work removed.
40
+ *
41
+ * ★★ It is still NOT what delivers stale-output rejection. Old TEXT reaching a
42
+ * new caption is a separate defect with a separate fix — see `publishedChunks`
43
+ * in `voice/speechPlayback.ts`. Do not conflate them.
43
44
  *
44
45
  * ★ `clearProcessing` is addressed the same way `planTurnAbort` is. An
45
46
  * abandoned turn may clear the shared entry only while that entry is still its
@@ -1 +1 @@
1
- {"version":3,"file":"turnState.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/turnState.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,gBAAgB,CAAC;AAElE;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,2BAA2B,GAAG,SAAS,GAC9C,OAAO,CAMT;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IACtC,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,gDAAgD;IAChD,cAAc,EAAE,OAAO,CAAC;IACxB,gEAAgE;IAChE,YAAY,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;CACzC,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,eAAe,EAAE,OAAO,CAAA;CAAE,CAGjD;AAED,kFAAkF;AAClF,MAAM,MAAM,eAAe,GACvB,MAAM,GACN,iBAAiB,GACjB,YAAY,GACZ,mBAAmB,CAAC;AAExB;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE;IAClC,yCAAyC;IACzC,iBAAiB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC7C,iEAAiE;IACjE,YAAY,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACxC,yDAAyD;IACzD,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,eAAe,CAAA;CAAE,CAkB7C"}
1
+ {"version":3,"file":"turnState.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/turnState.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,gBAAgB,CAAC;AAElE;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,2BAA2B,GAAG,SAAS,GAC9C,OAAO,CAMT;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IACtC,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,gDAAgD;IAChD,cAAc,EAAE,OAAO,CAAC;IACxB,gEAAgE;IAChE,YAAY,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;CACzC,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,eAAe,EAAE,OAAO,CAAA;CAAE,CAGjD;AAED,kFAAkF;AAClF,MAAM,MAAM,eAAe,GACvB,MAAM,GACN,iBAAiB,GACjB,YAAY,GACZ,mBAAmB,CAAC;AAExB;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE;IAClC,yCAAyC;IACzC,iBAAiB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC7C,iEAAiE;IACjE,YAAY,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACxC,yDAAyD;IACzD,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,eAAe,CAAA;CAAE,CAkB7C"}
@@ -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;AAyEf,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,CAm0DxD,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;AAyEf,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,CAi6DxD,CAAC"}
@@ -18,53 +18,53 @@ import { useAssistantStore as x } from "../store.js";
18
18
  import { isTurnInFlight as ge, planAbandonedTurn as _e, planTurnAbort as ve } from "../turnState.js";
19
19
  import { parseToolActivity as ye } from "./AssistantToolActivity.js";
20
20
  import { useVoiceSession as be } from "./useVoiceSession.js";
21
- import { getOrganizationId as xe, getWorkspaceId as Se } from "../context.js";
22
- import { createReadinessTracker as Ce } from "../sandboxReadiness.js";
23
- import { AssistantSpokenTurnsNotice as we } from "./AssistantSpokenTurnsNotice.js";
24
- import { VoiceTranscriptDrawer as Te } from "./voice/VoiceTranscriptDrawer.js";
25
- import { downloadFile as Ee } from "../exportConversation.js";
26
- import { AssistantEmptyState as De } from "./AssistantEmptyState.js";
27
- import { AssistantMessageList as Oe } from "./AssistantMessageList.js";
28
- import { AssistantVoiceSession as ke } from "./voice/AssistantVoiceSession.js";
29
- import { useAssistantApiAccess as Ae } from "../useAssistantApiAccess.js";
30
- import { useConversationTurns as je } from "../useConversationTurns.js";
31
- import { isMultimodalBodyRejection as Me, isRecoverableAssistantError as Ne } from "../transportErrors.js";
32
- import { dispatchAssistantQuotaExhausted as Pe, notifyAiCreditsUpdated as Fe } from "../aiCredits.js";
33
- import { useAssistantAttachments as Ie } from "../useAssistantAttachments.js";
34
- import { AssistantComposer as Le } from "./composer/AssistantComposer.js";
35
- import { isProdRuntime as Re } from "../env.js";
36
- import { AssistantApiCallsConsentDialog as ze } from "./AssistantApiCallsConsentDialog.js";
37
- import { useCallback as S, useEffect as C, useMemo as w, useRef as T, useState as Be } from "react";
38
- import { jsx as E, jsxs as Ve } from "react/jsx-runtime";
21
+ import { getOrganizationId as S, getWorkspaceId as xe } from "../context.js";
22
+ import { createReadinessTracker as Se } from "../sandboxReadiness.js";
23
+ import { AssistantSpokenTurnsNotice as Ce } from "./AssistantSpokenTurnsNotice.js";
24
+ import { VoiceTranscriptDrawer as we } from "./voice/VoiceTranscriptDrawer.js";
25
+ import { downloadFile as Te } from "../exportConversation.js";
26
+ import { AssistantEmptyState as Ee } from "./AssistantEmptyState.js";
27
+ import { AssistantMessageList as De } from "./AssistantMessageList.js";
28
+ import { AssistantVoiceSession as Oe } from "./voice/AssistantVoiceSession.js";
29
+ import { useAssistantApiAccess as ke } from "../useAssistantApiAccess.js";
30
+ import { useConversationTurns as Ae } from "../useConversationTurns.js";
31
+ import { isMultimodalBodyRejection as je, isRecoverableAssistantError as Me } from "../transportErrors.js";
32
+ import { dispatchAssistantQuotaExhausted as Ne, notifyAiCreditsUpdated as Pe } from "../aiCredits.js";
33
+ import { useAssistantAttachments as Fe } from "../useAssistantAttachments.js";
34
+ import { AssistantComposer as Ie } from "./composer/AssistantComposer.js";
35
+ import { isProdRuntime as Le } from "../env.js";
36
+ import { AssistantApiCallsConsentDialog as Re } from "./AssistantApiCallsConsentDialog.js";
37
+ import { useCallback as C, useEffect as w, useMemo as T, useRef as E, useState as ze } from "react";
38
+ import { jsx as D, jsxs as Be } from "react/jsx-runtime";
39
39
  //#region src/shared/assistant/ui/AssistantChatArea.tsx
40
- var He = {
40
+ var Ve = {
41
41
  general: 18e4,
42
42
  assistant: 18e4,
43
43
  "api-calls": 18e4,
44
44
  "vibe-plugins": 6e5
45
- }, Ue = 18e4, We = 600, Ge = 2e4;
46
- function D() {
45
+ }, He = 18e4, Ue = 600, We = 2e4;
46
+ function O() {
47
47
  return `${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
48
48
  }
49
- function O(e) {
49
+ function k(e) {
50
50
  return e.info?.time?.created ?? 0;
51
51
  }
52
- function k(e) {
52
+ function A(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 j(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 Ke(e, t) {
62
- let n = e.filter((e) => e.info?.role === "assistant" && O(e) > t).sort((e, t) => O(e) - O(t));
61
+ function Ge(e, t) {
62
+ let n = e.filter((e) => e.info?.role === "assistant" && k(e) > t).sort((e, t) => k(e) - k(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 = h(r.parts), o = A(r.parts), s = se(r.parts), c = [
67
+ let r = n[n.length - 1], i = A(r.parts), a = h(r.parts), o = j(r.parts), s = se(r.parts), c = [
68
68
  i,
69
69
  ...a,
70
70
  ...o
@@ -78,7 +78,7 @@ function Ke(e, t) {
78
78
  ...s ? { pendingWrite: s } : {}
79
79
  };
80
80
  }
81
- function qe(e) {
81
+ function Ke(e) {
82
82
  switch (e) {
83
83
  case "provisioning": return "Starting assistant environment...";
84
84
  case "connecting": return "Connecting to assistant...";
@@ -86,24 +86,24 @@ function qe(e) {
86
86
  default: return "";
87
87
  }
88
88
  }
89
- var j = ({ visible: h = !0, writeAccess: se = "unknown" }) => {
90
- let k = le(), { product: A, modes: j, gatherPageContext: Je, buildPrompt: Ye, reportTokenUsage: Xe } = ce(), { getAccessToken: M, getWorkspaceToken: N, userId: P } = t(), { locale: Ze } = e(), Qe = x((e) => e.assistantLanguage), $e = x((e) => e.replyLanguage), et = w(() => oe(Qe, $e, Ze), [
89
+ var M = ({ visible: h = !0, writeAccess: se = "unknown" }) => {
90
+ let A = le(), { product: j, modes: M, gatherPageContext: qe, buildPrompt: Je, reportTokenUsage: Ye } = ce(), { getAccessToken: N, getWorkspaceToken: P, userId: F } = t(), { locale: Xe } = e(), Ze = x((e) => e.assistantLanguage), Qe = x((e) => e.replyLanguage), $e = T(() => oe(Ze, Qe, Xe), [
91
+ Ze,
91
92
  Qe,
92
- $e,
93
- Ze
94
- ]), tt = et.reply.english, nt = et.replyIsExplicit, rt = et.reply.code, { conversations: it, activeConversationId: F, mode: I, processingByConversationId: at, setMode: L, setConversationMode: R, setActiveConversation: ot, createConversation: z, addMessage: B, updateMessage: st, patchMessage: V, mergeMessageMetadata: ct, setConversationProcessing: H, clearConversationProcessing: lt, setBackendSessionId: ut, clearBackendSessionId: U, setSandbox: W, clearSandbox: dt, acknowledgeApiCalls: ft } = x(), pt = it.find((e) => e.id === F), G = je(pt), mt = G.all, ht = F ? at[F] : void 0, gt = ge(ht?.status), _t = gt ? ht?.messageId ?? null : null, vt = ht?.status === "error" ? ht.messageId : null, { canUseApiCalls: yt, loading: bt } = Ae(xe()), xt = w(() => j.filter((e) => !e.requiresAdmin || yt), [j, yt]), [St, Ct] = Be(null), [wt, Tt] = Be(!1), Et = T({}), Dt = T(Ce()), Ot = T(/* @__PURE__ */ new Set()), kt = w(() => j.find((e) => e.id === I), [j, I]);
95
- C(() => {
96
- bt || (!kt || kt.requiresAdmin && !yt) && I !== "assistant" && L("assistant");
93
+ Xe
94
+ ]), et = $e.reply.english, tt = $e.replyIsExplicit, nt = $e.reply.code, { conversations: rt, activeConversationId: I, mode: L, processingByConversationId: it, setMode: R, setConversationMode: z, setActiveConversation: at, createConversation: B, addMessage: V, updateMessage: ot, patchMessage: H, mergeMessageMetadata: st, setConversationProcessing: U, clearConversationProcessing: ct, setBackendSessionId: lt, clearBackendSessionId: ut, setSandbox: W, clearSandbox: dt, acknowledgeApiCalls: ft } = x(), pt = rt.find((e) => e.id === I), G = Ae(pt), mt = G.all, ht = I ? it[I] : void 0, gt = ge(ht?.status), _t = gt ? ht?.messageId ?? null : null, vt = ht?.status === "error" ? ht.messageId : null, { canUseApiCalls: yt, loading: bt } = ke(S()), xt = T(() => M.filter((e) => !e.requiresAdmin || yt), [M, yt]), [St, Ct] = ze(null), [wt, Tt] = ze(!1), Et = E({}), Dt = E(Se()), Ot = E(/* @__PURE__ */ new Set()), kt = T(() => M.find((e) => e.id === L), [M, L]);
95
+ w(() => {
96
+ bt || (!kt || kt.requiresAdmin && !yt) && L !== "assistant" && R("assistant");
97
97
  }, [
98
- I,
98
+ L,
99
99
  kt,
100
100
  yt,
101
101
  bt,
102
- L
102
+ R
103
103
  ]);
104
- let K = S((e, t, n, r) => {
105
- H(e, n, t, null), r ? st(e, t, r) : st(e, t, qe(n));
106
- }, [H, st]), At = S(async (e, t, n, r, i) => {
104
+ let K = C((e, t, n, r) => {
105
+ U(e, n, t, null), r ? ot(e, t, r) : ot(e, t, Ke(n));
106
+ }, [U, ot]), At = C(async (e, t, n, r, i) => {
107
107
  let s = x.getState().sandboxesByMode[n]?.sandboxId ?? null, l = async (e) => {
108
108
  if (Dt.current.isFresh(e)) return !0;
109
109
  try {
@@ -114,12 +114,12 @@ var j = ({ visible: h = !0, writeAccess: se = "unknown" }) => {
114
114
  };
115
115
  if (s && (W(n, s, "provisioning"), K(e, t, "provisioning", "Reusing assistant environment..."), await l(s) || (W(n, null, "provisioning"), s = null)), !s) {
116
116
  K(e, t, "provisioning", "Looking for existing environment...");
117
- let a = await c(r, A, n, Re(), i);
117
+ let a = await c(r, j, n, Le(), i);
118
118
  a && (W(n, a, "provisioning"), K(e, t, "provisioning", "Reusing assistant environment..."), await l(a) ? s = a : W(n, null, "provisioning"));
119
119
  }
120
120
  if (!s) {
121
- if (n === "api-calls" && !M()) throw Error("API Calls mode requires an authenticated session. Please sign in again.");
122
- K(e, t, "provisioning", "Starting assistant environment..."), W(n, null, "provisioning"), await f(r, A, n, Re(), i), s = await a(A, n, r, Re(), We, i), W(n, s, "provisioning"), await m(s, r, i, 3e5), await p(s, r, i, 9e4);
121
+ if (n === "api-calls" && !N()) throw Error("API Calls mode requires an authenticated session. Please sign in again.");
122
+ K(e, t, "provisioning", "Starting assistant environment..."), W(n, null, "provisioning"), await f(r, j, n, Le(), i), s = await a(j, n, r, Le(), Ue, i), W(n, s, "provisioning"), await m(s, r, i, 3e5), await p(s, r, i, 9e4);
123
123
  }
124
124
  W(n, s, "running");
125
125
  let u = x.getState().conversations.find((t) => t.id === e)?.backendSessionId ?? null;
@@ -127,78 +127,91 @@ var j = ({ visible: h = !0, writeAccess: se = "unknown" }) => {
127
127
  let e = await d(s, r, u, i);
128
128
  if (e.mode !== n) throw Error(`Session mode mismatch: expected ${n}, received ${e.mode}`);
129
129
  } catch {
130
- U(e), u = null;
130
+ ut(e), u = null;
131
131
  }
132
- return u || (K(e, t, "connecting", "Preparing session..."), u = (await o(s, r, n, i)).sessionId, ut(e, u)), {
132
+ return u || (K(e, t, "connecting", "Preparing session..."), u = (await o(s, r, n, i)).sessionId, lt(e, u)), {
133
133
  sandboxId: s,
134
134
  sessionId: u
135
135
  };
136
136
  }, [
137
- U,
138
- M,
139
- A,
140
137
  ut,
138
+ N,
139
+ j,
140
+ lt,
141
141
  W,
142
142
  K
143
- ]), [jt, Mt] = Be(null), Nt = T(/* @__PURE__ */ new Set()), Pt = S(() => {
143
+ ]), [jt, Mt] = ze(null), q = E(/* @__PURE__ */ new Set()), Nt = E(null), Pt = C(() => {
144
144
  let e = x.getState(), t = e.activeConversationId;
145
145
  if (!t) return;
146
146
  let n = e.processingByConversationId[t], i = ge(n?.status) ? n?.messageId ?? null : null;
147
147
  if (!ve({
148
148
  interruptedTurnId: i,
149
149
  activeTurnId: i,
150
- alreadyRequested: i ? Nt.current.has(i) : !1
150
+ alreadyRequested: i ? q.current.has(i) : !1
151
151
  }).send || !i) return;
152
- let a = e.sandboxesByMode[e.mode]?.sandboxId, o = Se(), s = e.conversations.find((e) => e.id === t)?.backendSessionId;
153
- !a || !o || !s || (Nt.current.add(i), r(a, o, s, {
154
- accessToken: M(),
155
- workspaceToken: N(),
156
- userId: P,
157
- organizationId: xe()
158
- }));
152
+ q.current.add(i);
153
+ let a = e.sandboxesByMode[e.mode]?.sandboxId, o = xe(), s = e.conversations.find((e) => e.id === t)?.backendSessionId;
154
+ !a || !o || !s || r(a, o, s, {
155
+ accessToken: N(),
156
+ workspaceToken: P(),
157
+ userId: F,
158
+ organizationId: S()
159
+ });
159
160
  }, [
160
- P,
161
- M,
162
- N
163
- ]), Ft = S(async (e) => {
164
- let t = x.getState(), n = t.sandboxesByMode[t.mode]?.sandboxId, r = Se(), a = t.activeConversationId;
161
+ F,
162
+ N,
163
+ P
164
+ ]), Ft = C(async (e) => {
165
+ let t = x.getState(), n = t.sandboxesByMode[t.mode]?.sandboxId, r = xe(), a = t.activeConversationId;
165
166
  if (!(!n || !r || !a)) {
166
167
  Mt(e);
167
168
  try {
168
169
  await i(n, r, e, {
169
- accessToken: M(),
170
- workspaceToken: N(),
171
- userId: P,
172
- organizationId: xe()
170
+ accessToken: N(),
171
+ workspaceToken: P(),
172
+ userId: F,
173
+ organizationId: S()
173
174
  });
174
175
  } catch (e) {
175
- Mt(null), B(a, {
176
- id: D(),
176
+ Mt(null), V(a, {
177
+ id: O(),
177
178
  role: "system",
178
179
  content: e instanceof Error ? e.message : "The change could not be approved.",
179
180
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
180
181
  });
181
182
  return;
182
183
  }
183
- Mt(null), J.current(k("pendingWrite.approvedPrompt", "I approved that change — go ahead."));
184
+ Mt(null), Y.current(A("pendingWrite.approvedPrompt", "I approved that change — go ahead."));
184
185
  }
185
186
  }, [
186
- P,
187
- B,
188
- k
189
- ]), q = S(async (e, t = [], r = {}) => {
190
- let i = r.voiceSessionId !== void 0, a = x.getState(), o = a.activeConversationId ?? F;
191
- if (o && (ge(a.processingByConversationId[o]?.status) || Ot.current.has(o))) return;
192
- let c = a.mode, d = F, f = d ? x.getState().conversations.find((e) => e.id === d) : void 0;
193
- if (d ? f && f.mode !== c && (f.messages.length > 0 || f.backendSessionId) ? d = z(void 0, c) : f && f.mode !== c && R(d, c) : d = z(void 0, c), !d) return;
187
+ F,
188
+ V,
189
+ A
190
+ ]), J = C(async (e, t = [], r = {}) => {
191
+ let i = r.voiceSessionId !== void 0, a = x.getState(), o = a.activeConversationId ?? I;
192
+ if (o) {
193
+ if (ge(a.processingByConversationId[o]?.status)) {
194
+ let n = a.processingByConversationId[o]?.messageId ?? null;
195
+ n && q.current.has(n) && (Nt.current = {
196
+ conversationId: o,
197
+ content: e,
198
+ attachments: t,
199
+ options: r
200
+ });
201
+ return;
202
+ }
203
+ if (Ot.current.has(o)) return;
204
+ }
205
+ let c = a.mode, d = I, f = d ? x.getState().conversations.find((e) => e.id === d) : void 0;
206
+ if (d ? f && f.mode !== c && (f.messages.length > 0 || f.backendSessionId) ? d = B(void 0, c) : f && f.mode !== c && z(d, c) : d = B(void 0, c), !d) return;
194
207
  Et.current[d] = t;
195
- let p = Se(), m = {
196
- accessToken: M(),
197
- workspaceToken: N(),
198
- userId: P,
199
- organizationId: xe()
208
+ let p = xe(), m = {
209
+ accessToken: N(),
210
+ workspaceToken: P(),
211
+ userId: F,
212
+ organizationId: S()
200
213
  }, h = {
201
- id: D(),
214
+ id: O(),
202
215
  role: "user",
203
216
  content: e,
204
217
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
@@ -207,20 +220,20 @@ var j = ({ visible: h = !0, writeAccess: se = "unknown" }) => {
207
220
  ..._(r.voiceSessionId)
208
221
  }
209
222
  };
210
- B(d, h);
211
- let g = D();
212
- B(d, {
223
+ V(d, h);
224
+ let g = O();
225
+ V(d, {
213
226
  id: g,
214
227
  role: "assistant",
215
228
  content: "",
216
229
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
217
230
  metadata: {
218
- lang: rt,
231
+ lang: nt,
219
232
  ..._(r.voiceSessionId)
220
233
  }
221
- }), H(d, "provisioning", g, null);
222
- let ne = (e, t, n, i, a = rt) => {
223
- V(d, g, { content: te(e) }), ct(d, g, {
234
+ }), U(d, "provisioning", g, null);
235
+ let ne = (e, t, n, i, a = nt) => {
236
+ H(d, g, { content: te(e) }), st(d, g, {
224
237
  lang: a,
225
238
  ...t?.length ? { artifacts: t } : {},
226
239
  ...t?.length || n || i ? { mode: c } : {},
@@ -231,31 +244,31 @@ var j = ({ visible: h = !0, writeAccess: se = "unknown" }) => {
231
244
  }, v = async (n = 1) => {
232
245
  let r = !1;
233
246
  try {
234
- let { sandboxId: n, sessionId: a } = await At(d, g, c, p, m), o = (await u(n, p, a, m, { limit: 50 }).catch(() => [])).reduce((e, t) => Math.max(e, O(t)), 0);
247
+ let { sandboxId: n, sessionId: a } = await At(d, g, c, p, m), o = (await u(n, p, a, m, { limit: 50 }).catch(() => [])).reduce((e, t) => Math.max(e, k(t)), 0);
235
248
  K(d, g, "streaming", "Thinking...");
236
- let f = de(e, t), h = Ye?.(c, f, tt, nt, i) ?? f, _ = ue(h, t), v = pe(_), y = v > 0, re = Je?.();
249
+ let f = de(e, t), h = Je?.(c, f, et, tt, i) ?? f, _ = ue(h, t), v = pe(_), y = v > 0, re = qe?.();
237
250
  r = fe(t) > v;
238
251
  try {
239
252
  await ee(n, p, a, h, c, re, m, _?.length ? { parts: _ } : void 0);
240
253
  } catch (e) {
241
- if (!_ || !Me(e)) throw e;
254
+ if (!_ || !je(e)) throw e;
242
255
  await ee(n, p, a, h, c, re, m, void 0), r ||= y;
243
256
  }
244
- let b = Ke([], o), ae = Date.now() + (He[c] ?? Ue), oe = Date.now(), se = Date.now(), ce = () => _e({
257
+ let b = Ge([], o), ae = Date.now() + (Ve[c] ?? He), oe = Date.now(), se = Date.now(), ce = () => _e({
245
258
  turnId: g,
246
- abortRequested: Nt.current.has(g),
259
+ abortRequested: q.current.has(g),
247
260
  activeTurnId: x.getState().processingByConversationId[d]?.messageId ?? null
248
261
  });
249
262
  for (; Date.now() < ae;) {
250
263
  let e = ce();
251
264
  if (e.abandon) {
252
- e.clearProcessing && lt(d);
265
+ e.clearProcessing && ct(d);
253
266
  return;
254
267
  }
255
- if (b = Ke(await u(n, p, a, m, {
268
+ if (b = Ge(await u(n, p, a, m, {
256
269
  limit: 50,
257
270
  sinceMs: o
258
- }), o), V(d, g, { content: te(b.content) }), b.pendingWrite && ct(d, g, { pendingWrite: b.pendingWrite }), b.done) break;
271
+ }), o), H(d, g, { content: te(b.content) }), b.pendingWrite && st(d, g, { pendingWrite: b.pendingWrite }), b.done) break;
259
272
  Date.now() - oe > 3e4 && (await s(n, p, 600, m).catch(() => void 0), oe = Date.now()), await new Promise((e) => setTimeout(e, ie(Date.now() - se)));
260
273
  }
261
274
  if (!b.done && c !== "vibe-plugins") throw Error("Assistant response timed out while streaming progress");
@@ -265,27 +278,27 @@ var j = ({ visible: h = !0, writeAccess: se = "unknown" }) => {
265
278
  content: `${b.content}\n\n_Still building in the background — any artifacts below will finish shortly. Re-open this conversation to pick up the completed plugin._`
266
279
  }), r && (b = {
267
280
  ...b,
268
- content: `${b.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._")}`
281
+ content: `${b.content}\n\n${A("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._")}`
269
282
  }), ne(b.content, le, a, n), b.tokens) {
270
- V(d, g, { tokens: b.tokens });
283
+ H(d, g, { tokens: b.tokens });
271
284
  try {
272
- await Xe?.({
285
+ await Ye?.({
273
286
  workspaceId: p,
274
287
  sessionId: a,
275
288
  messageId: b.messageId,
276
289
  model: b.model,
277
290
  tokens: b.tokens
278
- }), Fe(A);
291
+ }), Pe(j);
279
292
  } catch {}
280
293
  }
281
294
  let me = ce();
282
295
  if (me.abandon) {
283
- me.clearProcessing && lt(d);
296
+ me.clearProcessing && ct(d);
284
297
  return;
285
298
  }
286
- H(d, "complete", g, null);
299
+ U(d, "complete", g, null);
287
300
  } catch (e) {
288
- if (n === 1 && Ne(e)) return U(d), dt(c), v(2);
301
+ if (n === 1 && Me(e)) return ut(d), dt(c), v(2);
289
302
  throw e;
290
303
  }
291
304
  }, y = d;
@@ -297,62 +310,64 @@ var j = ({ visible: h = !0, writeAccess: se = "unknown" }) => {
297
310
  Dt.current.invalidate(x.getState().sandboxesByMode[c]?.sandboxId ?? null);
298
311
  let t = n(e);
299
312
  if (t) {
300
- t.refusal === "exhausted" && Pe(A, "sandbox");
313
+ t.refusal === "exhausted" && Ne(j, "sandbox");
301
314
  let e = [t.quotaName, t.traceId ? `reference ${t.traceId}` : null].filter(Boolean).join(" · "), n = t.refusal === "exhausted" ? "You've reached your sandbox limit on the current plan. Upgrade to start the AI assistant." : "This workspace has no sandbox allowance provisioned, so the AI assistant cannot start. Upgrading will not help — ask an administrator to provision it.";
302
- ne(e ? `${n}\n\n${e}` : n, void 0, void 0, void 0, "en"), H(d, "error", g, null);
315
+ ne(e ? `${n}\n\n${e}` : n, void 0, void 0, void 0, "en"), U(d, "error", g, null);
303
316
  return;
304
317
  }
305
318
  let i = e instanceof Error ? e.message : "Something went wrong";
306
- H(d, "error", g, i), V(d, g, { content: `Sorry, an error occurred: ${i}. Please try again.` }), ct(d, g, {
319
+ U(d, "error", g, i), H(d, g, { content: `Sorry, an error occurred: ${i}. Please try again.` }), st(d, g, {
307
320
  lang: "en",
308
321
  ..._(r.voiceSessionId)
309
322
  });
310
323
  } finally {
311
324
  Ot.current.delete(y);
325
+ let e = Nt.current;
326
+ Nt.current = null, e && e.conversationId === y && Y.current(e.content, e.attachments, e.options);
312
327
  }
313
328
  }, [
314
- F,
315
- B,
316
- Ye,
317
- U,
329
+ I,
330
+ V,
331
+ Je,
332
+ ut,
318
333
  dt,
319
- it,
320
- z,
334
+ rt,
335
+ B,
321
336
  At,
322
- Je,
323
- M,
337
+ qe,
324
338
  N,
325
- V,
326
- A,
327
- Xe,
328
- nt,
329
- rt,
330
- tt,
331
- ut,
332
- R,
339
+ P,
333
340
  H,
341
+ j,
342
+ Ye,
343
+ tt,
344
+ nt,
345
+ et,
334
346
  lt,
335
- k,
347
+ z,
348
+ U,
349
+ ct,
350
+ A,
336
351
  K,
337
- P
338
- ]), It = S((e) => {
339
- q(e);
340
- }, [q]), Lt = S(() => {
341
- let e = [...G.chat].reverse().find((e) => e.role === "user"), t = F ? Et.current[F] ?? [] : [];
342
- e && q(e.content, t);
352
+ F
353
+ ]), It = C((e) => {
354
+ J(e);
355
+ }, [J]), Lt = C(() => {
356
+ let e = [...G.chat].reverse().find((e) => e.role === "user"), t = I ? Et.current[I] ?? [] : [];
357
+ e && J(e.content, t);
343
358
  }, [
344
359
  mt,
345
- q,
346
- F
347
- ]), J = T(q);
348
- C(() => {
349
- J.current = q;
350
- }, [q]);
351
- let Rt = w(() => {
360
+ J,
361
+ I
362
+ ]), Y = E(J);
363
+ w(() => {
364
+ Y.current = J;
365
+ }, [J]);
366
+ let Rt = T(() => {
352
367
  if (gt) return null;
353
368
  for (let e = mt.length - 1; e >= 0; --e) {
354
369
  let t = mt[e];
355
- if (t?.role !== "assistant" || !g(t)) continue;
370
+ if (t?.role !== "assistant" || !g(t) || q.current.has(t.id)) continue;
356
371
  let n = ye(t.content).text.trim();
357
372
  return n ? {
358
373
  id: t.id,
@@ -360,133 +375,133 @@ var j = ({ visible: h = !0, writeAccess: se = "unknown" }) => {
360
375
  } : null;
361
376
  }
362
377
  return null;
363
- }, [mt, gt]), zt = w(() => Rt ? b(Rt.text) : null, [Rt]), Bt = G.chat, Y = w(() => G.voice.filter((e) => e.role === "user" || e.role === "assistant").map((e) => ({
378
+ }, [mt, gt]), zt = T(() => Rt ? b(Rt.text) : null, [Rt]), Bt = G.chat, X = T(() => G.voice.filter((e) => e.role === "user" || e.role === "assistant").map((e) => ({
364
379
  id: e.id,
365
380
  role: e.role,
366
381
  text: ye(e.content).text.trim(),
367
382
  sessionId: ne(e),
368
383
  timestamp: e.timestamp
369
- })).filter((e) => e.text.length > 0), [G.voice]), Vt = S(() => {
370
- if (Y.length === 0) return;
384
+ })).filter((e) => e.text.length > 0), [G.voice]), Vt = C(() => {
385
+ if (X.length === 0) return;
371
386
  let e = /* @__PURE__ */ new Date();
372
- Ee(y(Y, {
373
- title: k("voiceSession.transcript", "Voice conversation"),
374
- savedAt: k("voiceSession.savedAt", "Saved"),
375
- session: k("voiceSession.sessionLabel", "Session"),
376
- earlier: k("voiceSession.earlierLabel", "Earlier"),
377
- you: k("voiceSession.speakerYou", "You"),
378
- assistant: k("voiceSession.speakerAssistant", "Assistant")
379
- }, e), re(A, e), "text/markdown");
387
+ Te(y(X, {
388
+ title: A("voiceSession.transcript", "Voice conversation"),
389
+ savedAt: A("voiceSession.savedAt", "Saved"),
390
+ session: A("voiceSession.sessionLabel", "Session"),
391
+ earlier: A("voiceSession.earlierLabel", "Earlier"),
392
+ you: A("voiceSession.speakerYou", "You"),
393
+ assistant: A("voiceSession.speakerAssistant", "Assistant")
394
+ }, e), re(j, e), "text/markdown");
380
395
  }, [
381
- A,
382
- Y,
383
- k
384
- ]), X = Ie(), Z = T(X);
385
- Z.current = X;
386
- let Q = be({
387
- onSubmit: S((e, t) => {
396
+ j,
397
+ X,
398
+ A
399
+ ]), Z = Fe(), Q = E(Z);
400
+ Q.current = Z;
401
+ let $ = be({
402
+ onSubmit: C((e, t) => {
388
403
  let n = () => {
389
- let n = Z.current, r = me(n.attachments);
390
- J.current(e, r, { voiceSessionId: t }), n.clear();
404
+ let n = Q.current, r = me(n.attachments);
405
+ Y.current(e, r, { voiceSessionId: t }), n.clear();
391
406
  };
392
- if (!Z.current.isBusy) {
407
+ if (!Q.current.isBusy) {
393
408
  n();
394
409
  return;
395
410
  }
396
411
  let r = Date.now(), i = window.setInterval(() => {
397
- Z.current.isBusy && Date.now() - r < Ge || (window.clearInterval(i), n());
412
+ Q.current.isBusy && Date.now() - r < We || (window.clearInterval(i), n());
398
413
  }, 200);
399
414
  }, []),
400
415
  latestReply: Rt,
401
- language: ae(Qe, Ze).tag
402
- }), Ht = w(() => (pt?.messages ?? []).reduce((e, t) => Math.max(e, t.metadata?.continuedVoiceTurns ?? 0), 0), [pt?.messages]), Ut = Y.length > Ht, Wt = S(() => {
416
+ language: ae(Ze, Xe).tag
417
+ }), Ht = T(() => (pt?.messages ?? []).reduce((e, t) => Math.max(e, t.metadata?.continuedVoiceTurns ?? 0), 0), [pt?.messages]), Ut = X.length > Ht, Wt = C(() => {
403
418
  let e = x.getState().activeConversationId;
404
- !e || Y.length === 0 || (B(e, {
405
- id: D(),
419
+ !e || X.length === 0 || (V(e, {
420
+ id: O(),
406
421
  role: "system",
407
- content: v(Y.slice(Ht), {
408
- intro: k("voiceSession.continuedIntro", "Continued from a voice conversation. You asked about:"),
409
- nothing: k("voiceSession.continuedNothing", "Continued from a voice conversation."),
410
- more: (e) => k("voiceSession.continuedMore", "…and {{count}} more", { count: e })
422
+ content: v(X.slice(Ht), {
423
+ intro: A("voiceSession.continuedIntro", "Continued from a voice conversation. You asked about:"),
424
+ nothing: A("voiceSession.continuedNothing", "Continued from a voice conversation."),
425
+ more: (e) => A("voiceSession.continuedMore", "…and {{count}} more", { count: e })
411
426
  }),
412
427
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
413
- metadata: { continuedVoiceTurns: Y.length }
414
- }), Tt(!1), Q.end());
428
+ metadata: { continuedVoiceTurns: X.length }
429
+ }), Tt(!1), $.end());
415
430
  }, [
416
- Y,
431
+ X,
417
432
  Ht,
418
- B,
419
- k,
420
- Q
421
- ]), Gt = T(0);
422
- C(() => {
423
- Q.active && (Gt.current = Y.length);
424
- }, [Q.active]);
425
- let Kt = S(() => {
426
- let e = Y.length > Gt.current;
427
- Q.end(), e && Tt(!0);
428
- }, [Y, Q]);
429
- C(() => {
430
- !h && Q.active && Q.end();
431
- }, [h, Q]), C(() => {
432
- Q.active || Z.current.clear();
433
- }, [Q.active]), C(() => {
433
+ V,
434
+ A,
435
+ $
436
+ ]), Gt = E(0);
437
+ w(() => {
438
+ $.active && (Gt.current = X.length);
439
+ }, [$.active]);
440
+ let Kt = C(() => {
441
+ let e = X.length > Gt.current;
442
+ $.end(), e && Tt(!0);
443
+ }, [X, $]);
444
+ w(() => {
445
+ !h && $.active && $.end();
446
+ }, [h, $]), w(() => {
447
+ $.active || (Q.current.clear(), Nt.current = null);
448
+ }, [$.active]), w(() => {
434
449
  let e = x.getState().consumePendingPrompt();
435
- return e && J.current(e), x.subscribe((e, t) => {
450
+ return e && Y.current(e), x.subscribe((e, t) => {
436
451
  if (e.pendingPrompt && e.pendingPrompt !== t.pendingPrompt) {
437
452
  let e = x.getState().consumePendingPrompt();
438
- e && J.current(e);
453
+ e && Y.current(e);
439
454
  }
440
455
  });
441
456
  }, []);
442
- let $ = S((e) => {
443
- let t = F ? x.getState().conversations.find((e) => e.id === F) : void 0;
457
+ let qt = C((e) => {
458
+ let t = I ? x.getState().conversations.find((e) => e.id === I) : void 0;
444
459
  if (t && (t.messages.length > 0 || t.backendSessionId)) {
445
460
  if (t.mode !== e) {
446
461
  let t = x.getState().conversations.find((t) => t.mode === e && t.messages.length === 0 && !t.backendSessionId && !x.getState().processingByConversationId[t.id]);
447
- t ? ot(t.id) : z(void 0, e);
462
+ t ? at(t.id) : B(void 0, e);
448
463
  }
449
- } else F && R(F, e);
450
- L(e);
464
+ } else I && z(I, e);
465
+ R(e);
451
466
  }, [
452
- F,
467
+ I,
468
+ B,
469
+ at,
453
470
  z,
454
- ot,
455
- R,
456
- L
457
- ]), qt = S((e) => {
458
- if (j.find((t) => t.id === e)?.writeCapable && !x.getState().apiCallsAcknowledged) {
471
+ R
472
+ ]), Jt = C((e) => {
473
+ if (M.find((t) => t.id === e)?.writeCapable && !x.getState().apiCallsAcknowledged) {
459
474
  Ct(e);
460
475
  return;
461
476
  }
462
- $(e);
463
- }, [$, j]), Jt = S(() => {
477
+ qt(e);
478
+ }, [qt, M]), Yt = C(() => {
464
479
  let e = St;
465
- Ct(null), ft(), e && $(e);
480
+ Ct(null), ft(), e && qt(e);
466
481
  }, [
467
482
  St,
468
483
  ft,
469
- $
470
- ]), Yt = S(() => {
484
+ qt
485
+ ]), Xt = C(() => {
471
486
  Ct(null);
472
487
  }, []);
473
- return /* @__PURE__ */ Ve("div", {
488
+ return /* @__PURE__ */ Be("div", {
474
489
  className: "relative flex flex-1 flex-col overflow-hidden",
475
490
  children: [
476
- /* @__PURE__ */ Ve("div", {
491
+ /* @__PURE__ */ Be("div", {
477
492
  className: "contents",
478
- inert: Q.active || void 0,
493
+ inert: $.active || void 0,
479
494
  children: [
480
- Y.length > 0 && !Q.active ? /* @__PURE__ */ E(we, {
481
- count: Y.length,
495
+ X.length > 0 && !$.active ? /* @__PURE__ */ D(Ce, {
496
+ count: X.length,
482
497
  onOpenTranscript: () => Tt(!0)
483
498
  }) : null,
484
- Bt.length === 0 ? /* @__PURE__ */ E(De, {
485
- mode: I,
499
+ Bt.length === 0 ? /* @__PURE__ */ D(Ee, {
500
+ mode: L,
486
501
  onSuggestionClick: It
487
- }) : /* @__PURE__ */ E("div", {
502
+ }) : /* @__PURE__ */ D("div", {
488
503
  className: "flex min-h-0 flex-1 flex-col",
489
- children: /* @__PURE__ */ E(Oe, {
504
+ children: /* @__PURE__ */ D(De, {
490
505
  onApprovePendingWrite: Ft,
491
506
  approvingWriteRef: jt,
492
507
  messages: Bt,
@@ -495,55 +510,55 @@ var j = ({ visible: h = !0, writeAccess: se = "unknown" }) => {
495
510
  onRetry: Lt
496
511
  })
497
512
  }),
498
- /* @__PURE__ */ E(Le, {
499
- onStartVoiceSession: Q.available && I !== "api-calls" ? Q.start : void 0,
500
- onSend: (e, t) => void q(e, t),
513
+ /* @__PURE__ */ D(Ie, {
514
+ onStartVoiceSession: $.available && L !== "api-calls" ? $.start : void 0,
515
+ onSend: (e, t) => void J(e, t),
501
516
  disabled: gt,
502
- placeholder: I === "api-calls" ? k("chatArea.placeholderActions", "What would you like me to do?") : k("chatArea.placeholderGeneral", "Ask me anything…"),
503
- mode: I,
517
+ placeholder: L === "api-calls" ? A("chatArea.placeholderActions", "What would you like me to do?") : A("chatArea.placeholderGeneral", "Ask me anything…"),
518
+ mode: L,
504
519
  writeAccessDenied: se === "denied" && !!kt?.writeCapable,
505
520
  availableModes: xt,
506
- onModeChange: qt
521
+ onModeChange: Jt
507
522
  })
508
523
  ]
509
524
  }),
510
- wt && !Q.active ? /* @__PURE__ */ E(Te, {
511
- turns: Y,
525
+ wt && !$.active ? /* @__PURE__ */ D(we, {
526
+ turns: X,
512
527
  onClose: () => Tt(!1),
513
528
  onSave: Vt,
514
529
  onContinueInChat: Ut ? Wt : void 0,
515
530
  closeOnEscape: !0
516
531
  }) : null,
517
- Q.active && /* @__PURE__ */ E(ke, {
518
- session: Q.session,
519
- notice: Q.notice,
520
- capturing: Q.capturing,
521
- interrupting: Q.interrupting,
522
- awaitingEndpoint: Q.awaitingEndpoint,
523
- turns: Y,
524
- spokenChunks: Q.spokenChunks,
525
- attachments: X.attachments,
526
- onAttachFiles: X.addFiles,
527
- onRemoveAttachment: X.remove,
528
- onRetryAttachment: X.retry,
529
- canAttachMore: X.canAddMore,
530
- preparingAttachments: X.preparingCount,
532
+ $.active && /* @__PURE__ */ D(Oe, {
533
+ session: $.session,
534
+ notice: $.notice,
535
+ capturing: $.capturing,
536
+ interrupting: $.interrupting,
537
+ awaitingEndpoint: $.awaitingEndpoint,
538
+ turns: X,
539
+ spokenChunks: $.spokenChunks,
540
+ attachments: Z.attachments,
541
+ onAttachFiles: Z.addFiles,
542
+ onRemoveAttachment: Z.remove,
543
+ onRetryAttachment: Z.retry,
544
+ canAttachMore: Z.canAddMore,
545
+ preparingAttachments: Z.preparingCount,
531
546
  onSaveTranscript: Vt,
532
547
  onContinueInChat: Wt,
533
548
  onInterrupt: () => {
534
- Q.interrupt(), Pt();
549
+ $.interrupt(), Pt();
535
550
  },
536
551
  spoken: zt,
537
- onToggleMute: Q.toggleMute,
552
+ onToggleMute: $.toggleMute,
538
553
  onEnd: Kt
539
554
  }),
540
- /* @__PURE__ */ E(ze, {
555
+ /* @__PURE__ */ D(Re, {
541
556
  open: St !== null,
542
- onConfirm: Jt,
543
- onCancel: Yt
557
+ onConfirm: Yt,
558
+ onCancel: Xt
544
559
  })
545
560
  ]
546
561
  });
547
562
  };
548
563
  //#endregion
549
- export { j as AssistantChatArea };
564
+ export { M as AssistantChatArea };
@@ -13,7 +13,7 @@ import { VoiceSessionSnapshot } from '../../voice/voiceSession';
13
13
  * - listening -> mute (Mic)
14
14
  * - muted -> unmute (MicOff)
15
15
  * - speaking -> interrupt (Square — the stop glyph, not a microphone)
16
- * - thinking -> nothing (disabled; there is nothing to stop or mute yet)
16
+ * - thinking -> interrupt (Square stop the answer being generated)
17
17
  *
18
18
  * Interruption living here is deliberate: it is the biggest target on screen,
19
19
  * and it replaced barge-in when the microphone had to be closed during playback
@@ -1 +1 @@
1
- {"version":3,"file":"AssistantVoiceOrb.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/ui/voice/AssistantVoiceOrb.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAEhC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAGrE;;;;;;;;;;;;;;;;;;GAkBG;AACH,UAAU,KAAK;IACb,OAAO,EAAE,oBAAoB,CAAC;IAC9B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,iEAAiE;IACjE,KAAK,EAAE,MAAM,CAAC;IACd,+EAA+E;IAC/E,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,iBAAiB,EAAE,EAAE,CAAC,KAAK,CA8EvC,CAAC"}
1
+ {"version":3,"file":"AssistantVoiceOrb.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/ui/voice/AssistantVoiceOrb.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAEhC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAGrE;;;;;;;;;;;;;;;;;;GAkBG;AACH,UAAU,KAAK;IACb,OAAO,EAAE,oBAAoB,CAAC;IAC9B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,iEAAiE;IACjE,KAAK,EAAE,MAAM,CAAC;IACd,+EAA+E;IAC/E,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,iBAAiB,EAAE,EAAE,CAAC,KAAK,CAkGvC,CAAC"}
@@ -3,14 +3,14 @@ import { Mic as t, MicOff as n, Square as r } from "lucide-react";
3
3
  import { jsx as i } from "react/jsx-runtime";
4
4
  //#region src/shared/assistant/ui/voice/AssistantVoiceOrb.tsx
5
5
  var a = ({ session: a, compact: o = !1, onPress: s, label: c, connecting: l = !1 }) => {
6
- let u = e(a), { muted: d, phase: f, error: p } = a, m = f === "thinking" || f === "idle" || f === "ended" || p !== null || l, h = d && f !== "speaking" ? "from-bg-elevated to-bg-elevated" : u === "listening" ? "from-action-primary-bg/80 to-action-primary-bg/20" : u === "thinking" ? "from-text-muted/60 to-text-muted/10" : u === "speaking" ? "from-action-primary-bg to-action-primary-bg/40" : "from-bg-elevated to-bg-elevated/40", g = d && f !== "speaking" ? "" : u === "listening" ? "motion-safe:animate-pulse" : u === "thinking" ? "motion-safe:animate-[pulse_1.6s_ease-in-out_infinite]" : u === "speaking" ? "motion-safe:animate-[pulse_0.9s_ease-in-out_infinite]" : "", _ = o ? "h-16 w-40" : "h-24 w-56", v = o ? "size-6" : "size-8", y = f === "speaking" ? r : d ? n : t;
6
+ let u = e(a), { muted: d, phase: f, error: p } = a, m = f === "idle" || f === "ended" || p !== null || l, h = d && f !== "speaking" ? "from-bg-elevated to-bg-elevated" : u === "listening" ? "from-action-primary-bg/80 to-action-primary-bg/20" : u === "thinking" ? "from-action-primary-bg/55 to-action-primary-bg/15" : u === "speaking" ? "from-action-primary-bg to-action-primary-bg/40" : "from-bg-elevated to-bg-elevated/40", g = d && f !== "speaking" ? "" : u === "listening" ? "motion-safe:animate-pulse" : u === "thinking" ? "motion-safe:animate-[pulse_1.6s_ease-in-out_infinite]" : u === "speaking" ? "motion-safe:animate-[pulse_0.9s_ease-in-out_infinite]" : "", _ = o ? "h-16 w-40" : "h-24 w-56", v = o ? "size-6" : "size-8", y = f === "speaking" || f === "thinking" ? r : d ? n : t;
7
7
  return /* @__PURE__ */ i("button", {
8
8
  type: "button",
9
9
  onClick: s,
10
10
  disabled: m || !s,
11
11
  className: `flex ${_} items-center justify-center rounded-full bg-gradient-to-b ${h} ${g} text-text-primary shadow-lg transition-colors duration-300 focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong disabled:cursor-default`,
12
12
  "aria-label": c,
13
- "aria-pressed": f === "speaking" ? void 0 : d,
13
+ "aria-pressed": f === "speaking" || f === "thinking" ? void 0 : d,
14
14
  "data-testid": "assistant-voice-orb",
15
15
  "data-state": u,
16
16
  "data-muted": d || void 0,
@@ -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,CAkkB3C,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;AAW7D,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,CAukB3C,CAAC"}
@@ -1,39 +1,39 @@
1
- import { micIsInterrupt as e, voiceStageState as t } from "../../voice/voiceStageState.js";
2
- import { spokenSoFar as n } from "../../voice/voiceSession.js";
3
- import { useAssistantTr as r } from "../../i18n.js";
4
- import { AssistantAttachmentButton as i } from "../composer/AssistantAttachmentButton.js";
1
+ import { micIsInterrupt as e, showsAssistantCaption as t, voiceStageState as n } from "../../voice/voiceStageState.js";
2
+ import { spokenSoFar as r } from "../../voice/voiceSession.js";
3
+ import { useAssistantTr as i } from "../../i18n.js";
4
+ import { AssistantAttachmentButton as ee } from "../composer/AssistantAttachmentButton.js";
5
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";
6
+ import { AssistantVoiceOrb as te } from "./AssistantVoiceOrb.js";
7
+ import { VoiceMiniController as o } from "./VoiceMiniController.js";
8
+ import { VoiceStage as s } from "./VoiceStage.js";
9
+ import { VoiceTranscriptDrawer as c } from "./VoiceTranscriptDrawer.js";
10
+ import { useCallback as l, useEffect as u, useRef as d, useState as f } from "react";
11
+ import { Maximize2 as ne, Minimize2 as re, ScrollText as p, X as m } from "lucide-react";
12
+ import { jsx as h, jsxs as g } from "react/jsx-runtime";
13
13
  //#region src/shared/assistant/ui/voice/AssistantVoiceSession.tsx
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(() => {
14
+ var _ = ({ session: _, turns: b = [], onSaveTranscript: ie, onContinueInChat: ae, notice: x = null, spoken: S, onInterrupt: oe, onToggleMute: C, attachments: w = [], onAttachFiles: T, onRemoveAttachment: E, onRetryAttachment: D, canAttachMore: O = !0, preparingAttachments: k = 0, spokenChunks: A = null, onEnd: j, capturing: M = !0, interrupting: N = !1, awaitingEndpoint: P = !1 }) => {
15
+ let F = i(), { muted: I, error: L } = _, R = d(null), z = d(null), [B, V] = f("mini"), H = B === "full", U = B === "mini", W = B === "mini" ? "panel" : B === "panel" ? "full" : "mini", [G, K] = f(!1), q = d(!1), J = d(C);
16
+ J.current = C;
17
+ let se = l(() => {
18
+ I || q.current || r(_) || (q.current = !0, J.current());
19
+ }, [I, _]);
20
+ u(() => {
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
- }, []), l(() => {
27
+ }, []), u(() => {
28
28
  R.current?.focus();
29
- }, []), l(() => {
29
+ }, []), u(() => {
30
30
  let e = (e) => {
31
31
  if (e.key === "Escape") {
32
32
  if (G) {
33
33
  K(!1);
34
34
  return;
35
35
  }
36
- M();
36
+ j();
37
37
  return;
38
38
  }
39
39
  if (e.key !== "Tab" || !H) return;
@@ -44,13 +44,13 @@ var v = ({ session: v, turns: b = [], onSaveTranscript: x, onContinueInChat: S,
44
44
  };
45
45
  return window.addEventListener("keydown", e), () => window.removeEventListener("keydown", e);
46
46
  }, [
47
- M,
47
+ j,
48
48
  H,
49
49
  G
50
50
  ]);
51
- let Y = C !== null && L === null, X = n(v), Z = t({
52
- snapshot: v,
53
- capturing: ae,
51
+ let Y = x !== null && L === null, X = r(_), Z = n({
52
+ snapshot: _,
53
+ capturing: M,
54
54
  interrupting: N,
55
55
  awaitingEndpoint: P
56
56
  }), Q = (() => {
@@ -66,7 +66,7 @@ var v = ({ session: v, turns: b = [], onSaveTranscript: x, onContinueInChat: S,
66
66
  default: return Z;
67
67
  }
68
68
  })(), $ = I && Z !== "listening" && Q !== "" ? `${Q} · ${F("voiceSession.muted", "Microphone off")}` : Q;
69
- return /* @__PURE__ */ _("div", {
69
+ return /* @__PURE__ */ g("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 v = ({ session: v, turns: b = [], onSaveTranscript: x, onContinueInChat: S,
74
74
  "aria-label": F("voiceSession.title", "Voice conversation"),
75
75
  "data-testid": "assistant-voice-session",
76
76
  children: [
77
- /* @__PURE__ */ _("button", {
77
+ /* @__PURE__ */ g("button", {
78
78
  ref: R,
79
79
  type: "button",
80
- onClick: M,
80
+ onClick: j,
81
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
82
  title: F("voiceSession.end", "End the voice conversation"),
83
83
  "data-testid": "assistant-voice-end",
84
- children: [/* @__PURE__ */ g(h, {
84
+ children: [/* @__PURE__ */ h(m, {
85
85
  className: H ? "size-6" : U ? "size-4" : "size-5",
86
86
  "aria-hidden": "true"
87
- }), /* @__PURE__ */ g("span", {
87
+ }), /* @__PURE__ */ h("span", {
88
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__ */ g("div", {
92
+ /* @__PURE__ */ h("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__ */ g("p", {
94
+ children: Y ? /* @__PURE__ */ h("p", {
95
95
  className: "max-w-xs text-center text-xs text-status-warning",
96
96
  "data-testid": "assistant-voice-notice",
97
- children: ne(C, F)
97
+ children: v(x, F)
98
98
  }) : null
99
99
  }),
100
100
  (() => {
101
- let t = /* @__PURE__ */ g(o, {
102
- session: v,
101
+ let n = /* @__PURE__ */ h(te, {
102
+ session: _,
103
103
  compact: U,
104
104
  connecting: Z === "connecting",
105
- onPress: e(Z) ? T : E,
105
+ onPress: e(Z) ? oe : C,
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) ? w : X || null, r = L === null ? null : y(L, F);
108
- return U ? /* @__PURE__ */ g(s, {
109
- spokenChunks: j,
107
+ }), r = t(Z) ? S : X || null, i = L === null ? null : y(L, F);
108
+ return U ? /* @__PURE__ */ h(o, {
109
+ spokenChunks: A,
110
110
  state: Z,
111
- caption: n,
111
+ caption: r,
112
112
  statusText: $,
113
- errorText: r,
114
- control: t
115
- }) : /* @__PURE__ */ g(c, {
113
+ errorText: i,
114
+ control: n
115
+ }) : /* @__PURE__ */ h(s, {
116
116
  state: Z,
117
117
  userCaption: X || null,
118
- spokenChunks: j,
119
- assistantCaption: w,
118
+ spokenChunks: A,
119
+ assistantCaption: S,
120
120
  expanded: H,
121
121
  statusText: $,
122
- errorText: r,
123
- control: t
122
+ errorText: i,
123
+ control: n
124
124
  });
125
125
  })(),
126
- G ? /* @__PURE__ */ g(ee, {
126
+ G ? /* @__PURE__ */ h(c, {
127
127
  turns: b,
128
128
  onClose: () => K(!1),
129
- onSave: x,
130
- onContinueInChat: S
129
+ onSave: ie,
130
+ onContinueInChat: ae
131
131
  }) : null,
132
- O ? /* @__PURE__ */ g("div", {
132
+ T ? /* @__PURE__ */ h("div", {
133
133
  className: `absolute ${H ? "left-6 top-6" : U ? "left-11 top-2" : "left-3 top-3"}`,
134
- children: /* @__PURE__ */ g(i, {
134
+ children: /* @__PURE__ */ h(ee, {
135
135
  onFiles: (e) => {
136
- O(e), V((e) => e === "mini" ? "panel" : e);
136
+ T(e), V((e) => e === "mini" ? "panel" : e);
137
137
  },
138
- onPickerOpen: oe,
138
+ onPickerOpen: se,
139
139
  direction: "down",
140
- canAddMore: ie
140
+ canAddMore: O
141
141
  })
142
142
  }) : null,
143
- (D.length > 0 || A > 0) && !U ? /* @__PURE__ */ g("div", {
143
+ (w.length > 0 || k > 0) && !U ? /* @__PURE__ */ h("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__ */ g(a, {
147
- attachments: D,
148
- onRemove: k ?? (() => void 0),
149
- onRetry: re ?? (() => void 0),
150
- preparingCount: A
146
+ children: /* @__PURE__ */ h(a, {
147
+ attachments: w,
148
+ onRemove: E ?? (() => void 0),
149
+ onRetry: D ?? (() => void 0),
150
+ preparingCount: k
151
151
  })
152
152
  }) : null,
153
- /* @__PURE__ */ g("button", {
153
+ /* @__PURE__ */ h("button", {
154
154
  type: "button",
155
155
  onClick: () => K((e) => !e),
156
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__ */ g(m, { className: H ? "size-6" : U ? "size-4" : "size-5" })
160
+ children: /* @__PURE__ */ h(p, { className: H ? "size-6" : U ? "size-4" : "size-5" })
161
161
  }),
162
- /* @__PURE__ */ g("button", {
162
+ /* @__PURE__ */ h("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__ */ g(p, { className: "size-5" }) : /* @__PURE__ */ g(f, { className: U ? "size-4" : "size-5" })
168
+ children: H ? /* @__PURE__ */ h(re, { className: "size-5" }) : /* @__PURE__ */ h(ne, { className: U ? "size-4" : "size-5" })
169
169
  })
170
170
  ]
171
171
  });
172
172
  };
173
- function ne(e, t) {
173
+ function v(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.");
@@ -188,4 +188,4 @@ function y(e, t) {
188
188
  }
189
189
  }
190
190
  //#endregion
191
- export { v as AssistantVoiceSession };
191
+ export { _ as AssistantVoiceSession };
@@ -1 +1 @@
1
- {"version":3,"file":"voiceSession.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/voice/voiceSession.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,8EAA8E;AAC9E,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,WAAW,GAAG,UAAU,GAAG,UAAU,GAAG,OAAO,CAAC;AAEzF,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,iBAAiB,CAAC;IACzB,8DAA8D;IAC9D,KAAK,EAAE,OAAO,CAAC;IACf,oEAAoE;IACpE,OAAO,EAAE,MAAM,CAAC;IAChB,6EAA6E;IAC7E,OAAO,EAAE,MAAM,CAAC;IAChB,2DAA2D;IAC3D,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAAC;CACjC;AAED;;;;;;GAMG;AACH,MAAM,MAAM,iBAAiB,GAAG,mBAAmB,GAAG,kBAAkB,GAAG,YAAY,CAAC;AAExF,MAAM,MAAM,iBAAiB;AAC3B,uEAAuE;AACrE;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE;AACxD,6CAA6C;GAC3C;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE,GACxB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE;AAClC,wEAAwE;GACtE;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,GACrB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,iBAAiB,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC;AAEpB;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,iBAAiB,OAAO,CAAC;AAEtC;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,iBAAiB,MAAM,CAAC;AAErC;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,OAAO,CAAC;AAErC;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,MAAM,CAAC;AAEpC,sEAAsE;AACtE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED,4EAA4E;AAC5E,wBAAgB,WAAW,CAAC,QAAQ,EAAE,oBAAoB,GAAG,MAAM,CAElE;AAqCD,wBAAgB,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAY7E;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAClC,KAAK,EAAE,iBAAiB,EACxB,eAAe,EAAE,MAAM,GAAG,IAAI,GAC7B;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAItC;AAED,eAAO,MAAM,eAAe,EAAE,QAAQ,CAAC,oBAAoB,CAMzD,CAAC;AAEH;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,oBAAoB,EAC9B,KAAK,EAAE,iBAAiB,EACxB,UAAU,GAAE,MAAM,GAAG,IAAW,GAC/B,oBAAoB,CAmFtB;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,oBAAoB,GAAG,OAAO,CAKnE;AAED,gFAAgF;AAChF,wBAAgB,OAAO,CAAC,QAAQ,EAAE,oBAAoB,GAAG,MAAM,GAAG,WAAW,GAAG,UAAU,GAAG,UAAU,CAatG"}
1
+ {"version":3,"file":"voiceSession.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/voice/voiceSession.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,8EAA8E;AAC9E,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,WAAW,GAAG,UAAU,GAAG,UAAU,GAAG,OAAO,CAAC;AAEzF,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,iBAAiB,CAAC;IACzB,8DAA8D;IAC9D,KAAK,EAAE,OAAO,CAAC;IACf,oEAAoE;IACpE,OAAO,EAAE,MAAM,CAAC;IAChB,6EAA6E;IAC7E,OAAO,EAAE,MAAM,CAAC;IAChB,2DAA2D;IAC3D,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAAC;CACjC;AAED;;;;;;GAMG;AACH,MAAM,MAAM,iBAAiB,GAAG,mBAAmB,GAAG,kBAAkB,GAAG,YAAY,CAAC;AAExF,MAAM,MAAM,iBAAiB;AAC3B,uEAAuE;AACrE;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE;AACxD,6CAA6C;GAC3C;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE,GACxB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE;AAClC,wEAAwE;GACtE;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,GACrB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,iBAAiB,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC;AAEpB;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,iBAAiB,OAAO,CAAC;AAEtC;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,iBAAiB,MAAM,CAAC;AAErC;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,OAAO,CAAC;AAErC;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,MAAM,CAAC;AAEpC,sEAAsE;AACtE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED,4EAA4E;AAC5E,wBAAgB,WAAW,CAAC,QAAQ,EAAE,oBAAoB,GAAG,MAAM,CAElE;AAqCD,wBAAgB,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAY7E;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAClC,KAAK,EAAE,iBAAiB,EACxB,eAAe,EAAE,MAAM,GAAG,IAAI,GAC7B;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAItC;AAED,eAAO,MAAM,eAAe,EAAE,QAAQ,CAAC,oBAAoB,CAMzD,CAAC;AAEH;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,oBAAoB,EAC9B,KAAK,EAAE,iBAAiB,EACxB,UAAU,GAAE,MAAM,GAAG,IAAW,GAC/B,oBAAoB,CA6FtB;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,oBAAoB,GAAG,OAAO,CAKnE;AAED,gFAAgF;AAChF,wBAAgB,OAAO,CAAC,QAAQ,EAAE,oBAAoB,GAAG,MAAM,GAAG,WAAW,GAAG,UAAU,GAAG,UAAU,CAatG"}
@@ -60,7 +60,7 @@ function d(e, t, n = null) {
60
60
  interim: ""
61
61
  } : {}
62
62
  };
63
- case "interrupt": return e.phase === "speaking" ? {
63
+ case "interrupt": return e.phase === "speaking" || e.phase === "thinking" ? {
64
64
  ...e,
65
65
  phase: "listening",
66
66
  pending: "",
@@ -25,7 +25,22 @@ export declare function voiceStageState({ snapshot, capturing, interrupting, awa
25
25
  export declare function showsUserCaption(state: VoiceStageState): boolean;
26
26
  /** Does this stage show the assistant's caption? */
27
27
  export declare function showsAssistantCaption(state: VoiceStageState): boolean;
28
- /** Is the microphone control an INTERRUPT rather than a mute toggle? */
28
+ /**
29
+ * Is the microphone control an INTERRUPT rather than a mute toggle?
30
+ *
31
+ * ★★ `thinking` too, as of the cancellation work. It used to be `speaking`
32
+ * only, which meant the orb was inert for the whole time the model was
33
+ * generating — the user could only stop an answer that had already finished,
34
+ * which is not really interrupting. Everything that makes stopping a running
35
+ * turn safe now ships: the sandbox `/abort` route (verified in prod),
36
+ * `planTurnAbort` so a late abort cannot kill a newer turn, `planAbandonedTurn`
37
+ * so the cancelled turn's own loop stops, and `publishedChunks` so its caption
38
+ * cannot survive it. Those guards existed for an action the UI did not allow.
39
+ *
40
+ * ★ This is NOT the same question as "does this stage show the assistant's
41
+ * caption" — use `showsAssistantCaption` for that. The two coincided while both
42
+ * meant `speaking`, and one call site was reading this one to pick a caption.
43
+ */
29
44
  export declare function micIsInterrupt(state: VoiceStageState): boolean;
30
45
  /**
31
46
  * Does this stage show a LIVE waveform?
@@ -1 +1 @@
1
- {"version":3,"file":"voiceStageState.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/voice/voiceStageState.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAE3D,MAAM,MAAM,eAAe,GACzB,YAAY,GAAG,WAAW,GAAG,gBAAgB,GAAG,UAAU,GAAG,UAAU,GAAG,cAAc,GAAG,WAAW,GAAG,OAAO,CAAC;AAEnH,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,kEAAkE;IAClE,SAAS,EAAE,OAAO,CAAC;IACnB,oFAAoF;IACpF,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,SAAS,EACT,YAAoB,EACpB,gBAAwB,GACzB,EAAE,WAAW,GAAG,eAAe,CAwB/B;AAED,6EAA6E;AAC7E,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAKhE;AAED,oDAAoD;AACpD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAErE;AAED,wEAAwE;AACxE,wBAAgB,cAAc,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAE9D;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAEhE;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAEjE"}
1
+ {"version":3,"file":"voiceStageState.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/voice/voiceStageState.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAE3D,MAAM,MAAM,eAAe,GACzB,YAAY,GAAG,WAAW,GAAG,gBAAgB,GAAG,UAAU,GAAG,UAAU,GAAG,cAAc,GAAG,WAAW,GAAG,OAAO,CAAC;AAEnH,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,kEAAkE;IAClE,SAAS,EAAE,OAAO,CAAC;IACnB,oFAAoF;IACpF,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,SAAS,EACT,YAAoB,EACpB,gBAAwB,GACzB,EAAE,WAAW,GAAG,eAAe,CAwB/B;AAED,6EAA6E;AAC7E,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAKhE;AAED,oDAAoD;AACpD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAErE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAE9D;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAEhE;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAEjE"}
@@ -9,7 +9,7 @@ function n(e) {
9
9
  return e === "speaking";
10
10
  }
11
11
  function r(e) {
12
- return e === "speaking";
12
+ return e === "speaking" || e === "thinking";
13
13
  }
14
14
  function i(e) {
15
15
  return e === "listening" || e === "endpoint-grace" || e === "speaking";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/fe-libs",
3
- "version": "2026.909.1",
3
+ "version": "2026.909.3",
4
4
  "description": "Burdenoff frontend primitives and domain libraries",
5
5
  "type": "module",
6
6
  "bin": {