@burdenoff/fe-libs 2026.913.2 → 2026.914.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/dist/shared/assistant/conversation.d.ts +29 -0
  2. package/dist/shared/assistant/conversation.d.ts.map +1 -1
  3. package/dist/shared/assistant/displayContent.d.ts +57 -0
  4. package/dist/shared/assistant/displayContent.d.ts.map +1 -0
  5. package/dist/shared/assistant/displayContent.js +26 -0
  6. package/dist/shared/assistant/exportConversation.d.ts +12 -2
  7. package/dist/shared/assistant/exportConversation.d.ts.map +1 -1
  8. package/dist/shared/assistant/exportConversation.js +24 -22
  9. package/dist/shared/assistant/index.d.ts +7 -0
  10. package/dist/shared/assistant/index.d.ts.map +1 -1
  11. package/dist/shared/assistant/legacyFiller.d.ts +60 -0
  12. package/dist/shared/assistant/legacyFiller.d.ts.map +1 -0
  13. package/dist/shared/assistant/legacyFiller.js +35 -0
  14. package/dist/shared/assistant/preview/previewTransitions.d.ts +15 -1
  15. package/dist/shared/assistant/preview/previewTransitions.d.ts.map +1 -1
  16. package/dist/shared/assistant/preview/previewTransitions.js +5 -2
  17. package/dist/shared/assistant/preview/useAssistantPreviewBridge.d.ts.map +1 -1
  18. package/dist/shared/assistant/preview/useAssistantPreviewBridge.js +51 -52
  19. package/dist/shared/assistant/spokenTurns.d.ts +25 -0
  20. package/dist/shared/assistant/spokenTurns.d.ts.map +1 -0
  21. package/dist/shared/assistant/spokenTurns.js +12 -0
  22. package/dist/shared/assistant/stageCopy.d.ts +23 -34
  23. package/dist/shared/assistant/stageCopy.d.ts.map +1 -1
  24. package/dist/shared/assistant/stageCopy.js +7 -16
  25. package/dist/shared/assistant/store.d.ts +10 -2
  26. package/dist/shared/assistant/store.d.ts.map +1 -1
  27. package/dist/shared/assistant/store.js +16 -9
  28. package/dist/shared/assistant/turnActivity.d.ts +70 -0
  29. package/dist/shared/assistant/turnActivity.d.ts.map +1 -0
  30. package/dist/shared/assistant/turnActivity.js +41 -0
  31. package/dist/shared/assistant/turnProgress.d.ts +51 -0
  32. package/dist/shared/assistant/turnProgress.d.ts.map +1 -0
  33. package/dist/shared/assistant/turnProgress.js +27 -0
  34. package/dist/shared/assistant/ui/AssistantChatArea.d.ts.map +1 -1
  35. package/dist/shared/assistant/ui/AssistantChatArea.js +285 -302
  36. package/dist/shared/assistant/ui/AssistantConversationList.d.ts.map +1 -1
  37. package/dist/shared/assistant/ui/AssistantConversationList.js +81 -80
  38. package/dist/shared/assistant/ui/AssistantMessageItem.d.ts +12 -1
  39. package/dist/shared/assistant/ui/AssistantMessageItem.d.ts.map +1 -1
  40. package/dist/shared/assistant/ui/AssistantMessageItem.js +103 -83
  41. package/dist/shared/assistant/ui/AssistantMessageList.d.ts +7 -1
  42. package/dist/shared/assistant/ui/AssistantMessageList.d.ts.map +1 -1
  43. package/dist/shared/assistant/ui/AssistantMessageList.js +28 -26
  44. package/dist/shared/assistant/ui/AssistantMoreMenu.d.ts.map +1 -1
  45. package/dist/shared/assistant/ui/AssistantMoreMenu.js +23 -20
  46. package/dist/shared/assistant/ui/AssistantTurnActivity.d.ts +40 -0
  47. package/dist/shared/assistant/ui/AssistantTurnActivity.d.ts.map +1 -0
  48. package/dist/shared/assistant/ui/AssistantTurnActivity.js +33 -0
  49. package/dist/shared/assistant/ui/usePrefersReducedMotion.d.ts +55 -0
  50. package/dist/shared/assistant/ui/usePrefersReducedMotion.d.ts.map +1 -0
  51. package/dist/shared/assistant/ui/usePrefersReducedMotion.js +28 -0
  52. package/dist/shared/assistant/ui/voice/VoiceMiniController.d.ts +4 -2
  53. package/dist/shared/assistant/ui/voice/VoiceMiniController.d.ts.map +1 -1
  54. package/dist/shared/assistant/ui/voice/VoiceStage.d.ts +4 -2
  55. package/dist/shared/assistant/ui/voice/VoiceStage.d.ts.map +1 -1
  56. package/dist/shared/assistant/ui/voice/VoiceStatusText.d.ts +12 -1
  57. package/dist/shared/assistant/ui/voice/VoiceStatusText.d.ts.map +1 -1
  58. package/dist/shared/assistant/ui/voice/VoiceStatusText.js +19 -18
  59. package/dist/shared/assistant/voice/voiceStatus.d.ts +8 -2
  60. package/dist/shared/assistant/voice/voiceStatus.d.ts.map +1 -1
  61. package/dist/shared-assistant.js +74 -67
  62. package/package.json +1 -1
@@ -146,11 +146,40 @@ export interface AssistantSandboxRuntime {
146
146
  sandboxId: string;
147
147
  status: AssistantSandboxStatus;
148
148
  }
149
+ /**
150
+ * Which step an in-flight turn is on, so the bubble can say what is happening.
151
+ *
152
+ * ★★ TRANSIENT BY CONSTRUCTION. It lives on `AssistantConversationProcessing`,
153
+ * which the store never persists. This copy used to be WRITTEN into the
154
+ * assistant message's `content` (BOFF-7277), and every consumer of content —
155
+ * the transcript, the history preview, Copy, Export, the preview, speech — then
156
+ * had to guess whether it was holding an answer or our own loading copy. A
157
+ * reload mid-turn froze it there as a permanent "answer".
158
+ *
159
+ * ★ Status alone cannot carry this: `provisioning` spans three different
160
+ * environment steps, and `connecting` is only ever shown as "Preparing
161
+ * session...". The names are `STAGE_COPY`'s keys, which `stageCopy.ts` enforces.
162
+ */
163
+ export type AssistantTurnStage = "reusingEnvironment" | "lookingForEnvironment" | "startingEnvironment" | "preparingSession" | "connecting" | "thinking";
149
164
  export interface AssistantConversationProcessing {
150
165
  status: AssistantConversationStatus;
151
166
  messageId: string | null;
152
167
  error?: string | null;
153
168
  updatedAt: string;
169
+ /**
170
+ * The step an in-flight turn is on. Absent when the runtime has not said yet
171
+ * (the synchronous `provisioning` write before any await) and on every settled
172
+ * status.
173
+ */
174
+ stage?: AssistantTurnStage;
175
+ /**
176
+ * Epoch ms the current `stage` began: the rotation origin while `thinking`.
177
+ *
178
+ * ★ Stored, not taken from a component clock. The panel is unmounted when the
179
+ * host closes or minimises it, and a mount-relative clock would restart the
180
+ * phrases from the top on every reopen of a turn that was still running.
181
+ */
182
+ stageStartedAt?: number;
154
183
  }
155
184
  export interface AssistantModeConfig {
156
185
  id: AssistantMode;
@@ -1 +1 @@
1
- {"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/conversation.ts"],"names":[],"mappings":"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"}
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;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,kBAAkB,GAC1B,oBAAoB,GACpB,uBAAuB,GACvB,qBAAqB,GACrB,kBAAkB,GAClB,YAAY,GACZ,UAAU,CAAC;AAEf,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;IAClB;;;;OAIG;IACH,KAAK,CAAC,EAAE,kBAAkB,CAAC;IAC3B;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;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"}
@@ -0,0 +1,57 @@
1
+ import { AssistantConversationProcessing, Message } from './conversation';
2
+ import { AssistantTr } from './i18n';
3
+ /**
4
+ * What a message IS, for anything that shows it to a person.
5
+ *
6
+ * - `output`: text the model produced, or a genuine settled outcome (an error,
7
+ * a quota refusal, the incomplete-turn note). `text` may be empty only when
8
+ * the message carries completion evidence without prose — its cards still
9
+ * render.
10
+ * - `working`: a live turn with nothing to show yet. Loading copy is drawn from
11
+ * the processing state, never from here, so `text` is empty.
12
+ * - `stopped`: a turn that ended without producing anything, shown as "Stopped".
13
+ *
14
+ * ★ A status label is not an answer, so consumers act on `kind`, not on whether
15
+ * `text` is non-empty: Copy and Listen are for `output` only, and the voice
16
+ * session never advances on anything else.
17
+ */
18
+ export type AssistantDisplayContent = {
19
+ readonly kind: "output";
20
+ readonly text: string;
21
+ } | {
22
+ readonly kind: "working";
23
+ readonly text: "";
24
+ } | {
25
+ readonly kind: "stopped";
26
+ readonly text: string;
27
+ };
28
+ /**
29
+ * The one projection from a stored message to what is shown for it.
30
+ *
31
+ * Used by every surface that shows a message to a person — the bubble, the
32
+ * history preview, Copy, Listen, Export, the voice transcript — so no two of
33
+ * them can disagree about whether a bubble holds an answer.
34
+ *
35
+ * ★★ PURE, and never written back. See `legacyFiller.ts` for why storage is not
36
+ * rewritten.
37
+ *
38
+ * `processing` is the entry for the message's OWN conversation. Passing another
39
+ * conversation's entry (or none, for a conversation with a live turn) would show
40
+ * that live turn as Stopped.
41
+ *
42
+ * The rule for `stopped` is deliberately conservative — ALL of:
43
+ * 1. an assistant message;
44
+ * 2. no turn in flight for it;
45
+ * 3. no completion evidence (see `hasCompletionEvidence`);
46
+ * 4. content that is empty, EXACTLY loading copy an older build stored, or
47
+ * EXACTLY the "Stopped" a BOFF-7229 build stored.
48
+ * A reply that happens to read "Thinking..." carries evidence and is left alone.
49
+ *
50
+ * ★ Known limit, accepted: liveness is per TAB, because processing is never
51
+ * persisted. A second tab opened on the same profile while the first is mid-turn
52
+ * shows that turn as "Stopped" until the first tab's answer is reloaded — the
53
+ * same message a real orphan shows, and nothing distinguishes the two. Older
54
+ * builds showed frozen loading copy there instead.
55
+ */
56
+ export declare function getAssistantDisplayContent(message: Message, processing: AssistantConversationProcessing | null | undefined, tr: AssistantTr): AssistantDisplayContent;
57
+ //# sourceMappingURL=displayContent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"displayContent.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/displayContent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,+BAA+B,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC/E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAS1C;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,uBAAuB,GAC/B;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAClD;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAA;CAAE,GAC/C;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAgExD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,+BAA+B,GAAG,IAAI,GAAG,SAAS,EAC9D,EAAE,EAAE,WAAW,GACd,uBAAuB,CAkBzB"}
@@ -0,0 +1,26 @@
1
+ import { STAGE_COPY as e, stageText as t } from "./stageCopy.js";
2
+ import { isTurnInFlight as n } from "./turnState.js";
3
+ import { isLegacyFiller as r, isLegacyStopped as i, stripLegacyFillerPrefix as a } from "./legacyFiller.js";
4
+ //#region src/shared/assistant/displayContent.ts
5
+ var o = {
6
+ kind: "working",
7
+ text: ""
8
+ }, s = (e) => ({
9
+ kind: "output",
10
+ text: e
11
+ }), c = (e) => typeof e == "string" && e.length > 0, l = (e) => Array.isArray(e) && e.length > 0, u = (e, t) => t?.messageId === e.id && n(t.status);
12
+ function d(e, t) {
13
+ if (t?.messageId === e.id && (t.status === "complete" || t.status === "error") || e.tokens) return !0;
14
+ let n = e.metadata;
15
+ return n ? c(n.sessionId) || c(n.sandboxId) || n.mode !== void 0 || l(n.artifacts) || l(n.attachments) || !!n.pendingWrite : !1;
16
+ }
17
+ function f(n, c, l) {
18
+ if (n.role !== "assistant") return s(n.content);
19
+ let f = n.content, p = f.trim() === "";
20
+ return u(n, c) ? p ? o : s(f) : !p && !r(l, f) && !i(l, f) ? s(a(l, f) ?? f) : d(n, c) ? s(f) : {
21
+ kind: "stopped",
22
+ text: t(l, e.stopped)
23
+ };
24
+ }
25
+ //#endregion
26
+ export { f as getAssistantDisplayContent };
@@ -1,5 +1,15 @@
1
- import { Conversation } from './conversation';
2
- export declare function exportConversation(conversation: Conversation, format: "json" | "markdown"): {
1
+ import { AssistantConversationProcessing, Conversation } from './conversation';
2
+ import { AssistantTr } from './i18n';
3
+ export interface ExportConversationOptions {
4
+ /**
5
+ * The conversation's processing entry. Without it a turn still running is
6
+ * exported as "Stopped", because nothing else says it is live.
7
+ */
8
+ processing?: AssistantConversationProcessing | null;
9
+ /** The product's translator, for "Stopped". English when omitted. */
10
+ tr?: AssistantTr;
11
+ }
12
+ export declare function exportConversation(conversation: Conversation, format: "json" | "markdown", options?: ExportConversationOptions): {
3
13
  content: string;
4
14
  filename: string;
5
15
  mimeType: string;
@@ -1 +1 @@
1
- {"version":3,"file":"exportConversation.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/exportConversation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD,wBAAgB,kBAAkB,CAChC,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,MAAM,GAAG,UAAU,GAC1B;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAuEzD;AAED,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,IAAI,CAUN"}
1
+ {"version":3,"file":"exportConversation.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/exportConversation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,+BAA+B,EAC/B,YAAY,EACb,MAAM,gBAAgB,CAAC;AAExB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAE1C,MAAM,WAAW,yBAAyB;IACxC;;;OAGG;IACH,UAAU,CAAC,EAAE,+BAA+B,GAAG,IAAI,CAAC;IACpD,qEAAqE;IACrE,EAAE,CAAC,EAAE,WAAW,CAAC;CAClB;AAID,wBAAgB,kBAAkB,CAChC,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,MAAM,GAAG,UAAU,EAC3B,OAAO,GAAE,yBAA8B,GACtC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CA6EzD;AAED,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,IAAI,CAUN"}
@@ -1,47 +1,49 @@
1
1
  import { isVoiceTurn as e } from "./voice/turnVisibility.js";
2
+ import { getAssistantDisplayContent as t } from "./displayContent.js";
2
3
  //#region src/shared/assistant/exportConversation.ts
3
- function t(t, n) {
4
- let r = t.title.replace(/[^a-zA-Z0-9]+/g, "-").replace(/^-|-$/g, "").toLowerCase(), i = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
5
- if (n === "json") {
6
- let n = {
7
- id: t.id,
8
- title: t.title,
9
- mode: t.mode,
4
+ var n = (e, t) => t;
5
+ function r(r, i, a = {}) {
6
+ let o = a.tr ?? n, s = (e) => t(e, a.processing, o).text, c = r.title.replace(/[^a-zA-Z0-9]+/g, "-").replace(/^-|-$/g, "").toLowerCase(), l = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
7
+ if (i === "json") {
8
+ let t = {
9
+ id: r.id,
10
+ title: r.title,
11
+ mode: r.mode,
10
12
  exportedAt: (/* @__PURE__ */ new Date()).toISOString(),
11
- backendSessionId: t.backendSessionId ?? null,
12
- messages: t.messages.map((t) => ({
13
+ backendSessionId: r.backendSessionId ?? null,
14
+ messages: r.messages.map((t) => ({
13
15
  role: t.role,
14
16
  channel: e(t) ? "voice" : "chat",
15
- content: t.content,
17
+ content: s(t),
16
18
  timestamp: t.timestamp,
17
19
  tokens: t.tokens
18
20
  }))
19
21
  };
20
22
  return {
21
- content: JSON.stringify(n, null, 2),
22
- filename: `${r}-${i}.json`,
23
+ content: JSON.stringify(t, null, 2),
24
+ filename: `${c}-${l}.json`,
23
25
  mimeType: "application/json"
24
26
  };
25
27
  }
26
- let a = [
27
- `# ${t.title}`,
28
+ let u = [
29
+ `# ${r.title}`,
28
30
  "",
29
- `> Mode: ${t.mode} | Exported: ${(/* @__PURE__ */ new Date()).toLocaleString()}`,
31
+ `> Mode: ${r.mode} | Exported: ${(/* @__PURE__ */ new Date()).toLocaleString()}`,
30
32
  ""
31
33
  ];
32
- for (let n of t.messages) {
33
- let t = n.role === "system" ? "Note" : n.role === "user" ? "You" : "Assistant";
34
- a.push(`## ${t}${e(n) ? " (spoken)" : ""}`), a.push(""), a.push(n.content), a.push("");
34
+ for (let t of r.messages) {
35
+ let n = t.role === "system" ? "Note" : t.role === "user" ? "You" : "Assistant";
36
+ u.push(`## ${n}${e(t) ? " (spoken)" : ""}`), u.push(""), u.push(s(t)), u.push("");
35
37
  }
36
38
  return {
37
- content: a.join("\n"),
38
- filename: `${r}-${i}.md`,
39
+ content: u.join("\n"),
40
+ filename: `${c}-${l}.md`,
39
41
  mimeType: "text/markdown"
40
42
  };
41
43
  }
42
- function n(e, t, n) {
44
+ function i(e, t, n) {
43
45
  let r = new Blob([e], { type: n }), i = URL.createObjectURL(r), a = document.createElement("a");
44
46
  a.href = i, a.download = t, document.body.appendChild(a), a.click(), document.body.removeChild(a), URL.revokeObjectURL(i);
45
47
  }
46
48
  //#endregion
47
- export { n as downloadFile, t as exportConversation };
49
+ export { i as downloadFile, r as exportConversation };
@@ -72,6 +72,11 @@ export * from './attachments';
72
72
  export * from './store';
73
73
  export * from './turnState';
74
74
  export * from './stageCopy';
75
+ export * from './legacyFiller';
76
+ export * from './displayContent';
77
+ export * from './turnActivity';
78
+ export * from './turnProgress';
79
+ export * from './spokenTurns';
75
80
  export * from './gatewayLimits';
76
81
  export * from './documentText';
77
82
  export * from './ui/AssistantAvatar';
@@ -106,6 +111,7 @@ export * from './preview/entity/AssistantEntityPreview';
106
111
  export * from './ui/panelOverlays';
107
112
  export * from './ui/useDropdownEscape';
108
113
  export * from './ui/useOverlayFocus';
114
+ export * from './ui/usePrefersReducedMotion';
109
115
  export * from './preview/useAssistantPreviewBridge';
110
116
  export * from './preview/AssistantPreviewOverlay';
111
117
  export * from './ui/composer/AssistantLanguageSelector';
@@ -129,6 +135,7 @@ export * from './ui/AssistantEmptyState';
129
135
  export * from './exportConversation';
130
136
  export * from './ui/AssistantMessageItem';
131
137
  export * from './ui/AssistantMessageList';
138
+ export * from './ui/AssistantTurnActivity';
132
139
  export * from './ui/voice/AssistantVoiceSession';
133
140
  export * from './useAssistantApiAccess';
134
141
  export * from './useConversationTurns';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ import { AssistantTr } from './i18n';
2
+ /**
3
+ * Is this EXACTLY loading copy an older build stored — and nothing else?
4
+ *
5
+ * ★ Exact whole-string match, trimmed. "I am thinking..." and "Thinking about
6
+ * your irrigation schedule" are answers. Empty is NOT filler here: an empty
7
+ * bubble is a question for the display projection, which knows whether a turn
8
+ * is live.
9
+ *
10
+ * ★★ Compared against the CURRENT translation and the English fallback. That
11
+ * covers copy written in English and read in any locale (the fallback), and
12
+ * copy written and read in the same locale, including a key that is published
13
+ * but not ACTIVE and so resolved to its fallback — which is how ~9,000
14
+ * assistant keys behaved in prod. It does NOT cover copy written translated and
15
+ * read after switching to another locale, English included: that stored text
16
+ * matches neither. The write-time locale is not recorded, so this is a false
17
+ * negative — the filler is shown as it was stored — which is the direction this
18
+ * is meant to err in. Reach is small: loading copy was only translated from
19
+ * 2026-09-10.
20
+ */
21
+ export declare function isLegacyFiller(tr: AssistantTr, content: string | null | undefined): boolean;
22
+ /**
23
+ * Is this EXACTLY the "Stopped" a BOFF-7229 build wrote into content?
24
+ *
25
+ * ★ Those builds (2026-09-10 to BOFF-7277) replaced the filler of a turn the
26
+ * user cut off with the word itself. The display projection shows a turn that
27
+ * ended with nothing as a muted "Stopped" with no Copy or Listen; recognising
28
+ * the stored word lets those older turns look — and behave — the same.
29
+ *
30
+ * Deliberately a separate predicate from `isLegacyFiller`: "Stopped" is a
31
+ * settled outcome, not loading copy, and the projection only treats it as one
32
+ * when the message carries no completion evidence. A reply that says "Stopped
33
+ * the pump at 4pm." never matches, and a completed reply that is exactly
34
+ * "Stopped" carries evidence.
35
+ */
36
+ export declare function isLegacyStopped(tr: AssistantTr, content: string | null | undefined): boolean;
37
+ /**
38
+ * The older predicate: empty OR exactly legacy filler.
39
+ *
40
+ * @deprecated Kept for the public API only. It answered "is this bubble still
41
+ * loading?" by reading content, which is the question BOFF-7277 moved to live
42
+ * processing state. Use `getAssistantDisplayContent` to decide what to show.
43
+ */
44
+ export declare function isStageCopy(tr: AssistantTr, content: string | null | undefined): boolean;
45
+ /**
46
+ * Strip the "Thinking..." an older build left IN FRONT OF its own timeout note.
47
+ *
48
+ * ★★ The shape, exactly: the progress sentinel, a blank line, then one of the
49
+ * incomplete-turn notices (translated or English) and whatever followed it. A
50
+ * turn whose stream budget elapsed before any output passed the sentinel into
51
+ * `withIncompleteTurnNotice`, which keeps any non-blank body — so the stored
52
+ * reply read "Thinking...\n\n_This turn stopped before an answer arrived..._".
53
+ * That is a genuine settled outcome with our filler glued to it; the note is
54
+ * kept and the filler is not.
55
+ *
56
+ * Returns the text without the prefix, or `null` when the content is anything
57
+ * other than that shape — a model reply is never touched.
58
+ */
59
+ export declare function stripLegacyFillerPrefix(tr: AssistantTr, content: string): string | null;
60
+ //# sourceMappingURL=legacyFiller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"legacyFiller.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/legacyFiller.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AA0C1C;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,cAAc,CAC5B,EAAE,EAAE,WAAW,EACf,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACjC,OAAO,CAIT;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAC7B,EAAE,EAAE,WAAW,EACf,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACjC,OAAO,CAGT;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,EAAE,EAAE,WAAW,EACf,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACjC,OAAO,CAET;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,uBAAuB,CACrC,EAAE,EAAE,WAAW,EACf,OAAO,EAAE,MAAM,GACd,MAAM,GAAG,IAAI,CAkBf"}
@@ -0,0 +1,35 @@
1
+ import { incompleteTurnNotice as e } from "./streamBudget.js";
2
+ import { STAGE_COPY as t, THINKING_PHRASES as n, stageText as r } from "./stageCopy.js";
3
+ //#region src/shared/assistant/legacyFiller.ts
4
+ var i = [
5
+ t.reusingEnvironment,
6
+ t.lookingForEnvironment,
7
+ t.startingEnvironment,
8
+ t.preparingSession,
9
+ t.connecting,
10
+ ...n
11
+ ], a = (e, t, n) => r(e, t) === n || t.fallback === n;
12
+ function o(e, t) {
13
+ let n = (t ?? "").trim();
14
+ return n ? i.some((t) => a(e, t, n)) : !1;
15
+ }
16
+ function s(e, n) {
17
+ let r = (n ?? "").trim();
18
+ return r !== "" && a(e, t.stopped, r);
19
+ }
20
+ function c(e, t) {
21
+ return !(t ?? "").trim() || o(e, t);
22
+ }
23
+ function l(n, r) {
24
+ let i = r.indexOf("\n\n");
25
+ if (i < 0) return null;
26
+ let o = r.slice(0, i).trim();
27
+ if (!a(n, t.thinking, o)) return null;
28
+ let s = r.slice(i + 2);
29
+ return [e("assistant"), e("vibe-plugins")].some((e) => {
30
+ let t = n(e.key, e.fallback);
31
+ return s.startsWith(e.fallback) || t !== "" && s.startsWith(t);
32
+ }) ? s : null;
33
+ }
34
+ //#endregion
35
+ export { o as isLegacyFiller, s as isLegacyStopped, c as isStageCopy, l as stripLegacyFillerPrefix };
@@ -80,9 +80,23 @@ export interface PreviewInput {
80
80
  */
81
81
  readonly steps: readonly AssistantToolStep[];
82
82
  readonly error?: string | null;
83
- /** `isStageCopy`, injected so this stays pure and testable without i18n. */
83
+ /**
84
+ * Whether prose is not model output, injected so this stays pure. The bridge
85
+ * passes a blank check: since BOFF-7277 a live turn's content is output or
86
+ * nothing. Kept as a parameter so the rule is still applied in exactly one
87
+ * place and swept by the exhaustive tests.
88
+ */
84
89
  readonly isFiller: (content: string) => boolean;
85
90
  }
91
+ /**
92
+ * The filler predicate the bridge injects: blank prose is not model output.
93
+ *
94
+ * ★ Since BOFF-7277 a live turn's content is the model's output or nothing, so
95
+ * blank is the ONLY thing that is not an answer. Exported so the bridge and the
96
+ * release-blocking lifecycle test use the same function rather than two copies
97
+ * of it.
98
+ */
99
+ export declare function isBlankProse(value: string): boolean;
86
100
  export declare function nextPreviewEvents(state: PreviewBridgeState, input: PreviewInput): {
87
101
  events: AssistantPreviewEvent[];
88
102
  state: PreviewBridgeState;
@@ -1 +1 @@
1
- {"version":3,"file":"previewTransitions.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/preview/previewTransitions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,KAAK,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAC1E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AASrE;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,2BAA2B,GAAG,OAAO,CAE5E;AAED,MAAM,WAAW,kBAAkB;IACjC;;;;;;;;;;;;;;;;;;;OAmBG;IACH,QAAQ,CAAC,sBAAsB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/C;;;;;;;;OAQG;IACH,QAAQ,CAAC,UAAU,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAChD;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,wEAAwE;IACxE,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CACtC;AAED,eAAO,MAAM,kBAAkB,EAAE,kBAKhC,CAAC;AAEF,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,QAAQ,CAAC,GAAG,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACzC;;;;;;;;OAQG;IACH,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE,2BAA2B,CAAC;IAC7C,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC7C,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,4EAA4E;IAC5E,QAAQ,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;CACjD;AAkDD,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,kBAAkB,EACzB,KAAK,EAAE,YAAY,GAClB;IAAE,MAAM,EAAE,qBAAqB,EAAE,CAAC;IAAC,KAAK,EAAE,kBAAkB,CAAA;CAAE,CAwJhE"}
1
+ {"version":3,"file":"previewTransitions.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/preview/previewTransitions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,KAAK,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAC1E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AASrE;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,2BAA2B,GAAG,OAAO,CAE5E;AAED,MAAM,WAAW,kBAAkB;IACjC;;;;;;;;;;;;;;;;;;;OAmBG;IACH,QAAQ,CAAC,sBAAsB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/C;;;;;;;;OAQG;IACH,QAAQ,CAAC,UAAU,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAChD;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,wEAAwE;IACxE,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CACtC;AAED,eAAO,MAAM,kBAAkB,EAAE,kBAKhC,CAAC;AAEF,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,QAAQ,CAAC,GAAG,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACzC;;;;;;;;OAQG;IACH,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE,2BAA2B,CAAC;IAC7C,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC7C,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;CACjD;AAkDD;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,kBAAkB,EACzB,KAAK,EAAE,YAAY,GAClB;IAAE,MAAM,EAAE,qBAAqB,EAAE,CAAC;IAAC,KAAK,EAAE,kBAAkB,CAAA;CAAE,CAwJhE"}
@@ -30,7 +30,10 @@ function i(e, t, n, i, a) {
30
30
  signature: s
31
31
  };
32
32
  }
33
- function a(t, n) {
33
+ function a(e) {
34
+ return e.trim() === "";
35
+ }
36
+ function o(t, n) {
34
37
  let r = [], a = n.run?.runId ?? null, o = n.conversationId ?? n.run?.conversationId ?? null, s = o !== null && t.observedConversationId === o, c = {
35
38
  ...t,
36
39
  observedConversationId: o ?? t.observedConversationId
@@ -106,4 +109,4 @@ function a(t, n) {
106
109
  };
107
110
  }
108
111
  //#endregion
109
- export { n as IDLE_PREVIEW_STATE, t as isRunningStatus, a as nextPreviewEvents };
112
+ export { n as IDLE_PREVIEW_STATE, a as isBlankProse, t as isRunningStatus, o as nextPreviewEvents };
@@ -1 +1 @@
1
- {"version":3,"file":"useAssistantPreviewBridge.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/preview/useAssistantPreviewBridge.ts"],"names":[],"mappings":"AA0CA,OAAO,KAAK,EAAE,0BAA0B,EAAyB,MAAM,SAAS,CAAC;AA2CjF,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,0BAA0B,GAAG,IAAI,GAC5C,IAAI,CA0MN"}
1
+ {"version":3,"file":"useAssistantPreviewBridge.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/preview/useAssistantPreviewBridge.ts"],"names":[],"mappings":"AA4CA,OAAO,KAAK,EAAE,0BAA0B,EAAyB,MAAM,SAAS,CAAC;AA2CjF,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,0BAA0B,GAAG,IAAI,GAC5C,IAAI,CAyMN"}
@@ -1,13 +1,11 @@
1
- import { useAssistantTr as e } from "../i18n.js";
2
- import { isStageCopy as t } from "../stageCopy.js";
3
- import { useAssistantStore as n } from "../store.js";
4
- import { parseToolActivity as r } from "../ui/AssistantToolActivity.js";
5
- import { IDLE_PREVIEW_STATE as i, isRunningStatus as a, nextPreviewEvents as o } from "./previewTransitions.js";
6
- import { NO_OWNER as s } from "./surfaceState.js";
7
- import { runIdentities as c } from "./runIdentity.js";
8
- import { useEffect as l, useRef as u } from "react";
1
+ import { useAssistantStore as e } from "../store.js";
2
+ import { parseToolActivity as t } from "../ui/AssistantToolActivity.js";
3
+ import { IDLE_PREVIEW_STATE as n, isBlankProse as r, isRunningStatus as i, nextPreviewEvents as a } from "./previewTransitions.js";
4
+ import { NO_OWNER as o } from "./surfaceState.js";
5
+ import { runIdentities as s } from "./runIdentity.js";
6
+ import { useEffect as c, useRef as l } from "react";
9
7
  //#region src/shared/assistant/preview/useAssistantPreviewBridge.ts
10
- function d(e, t) {
8
+ function u(e, t) {
11
9
  try {
12
10
  let n = e?.onEvent?.(t);
13
11
  n && typeof n.then == "function" && Promise.resolve(n).catch((e) => {
@@ -17,15 +15,15 @@ function d(e, t) {
17
15
  console.error("[assistant] preview observer threw", e);
18
16
  }
19
17
  }
20
- function f(f) {
21
- let p = e(), m = n((e) => e.activeConversationId), h = n((e) => e.activeConversationId ? e.processingByConversationId[e.activeConversationId] : void 0), g = n((e) => {
18
+ function d(d) {
19
+ let f = e((e) => e.activeConversationId), p = e((e) => e.activeConversationId ? e.processingByConversationId[e.activeConversationId] : void 0), m = e((e) => {
22
20
  let t = e.activeConversationId, n = t ? e.processingByConversationId[t]?.messageId : null;
23
21
  return !t || !n ? null : e.conversations.find((e) => e.id === t)?.messages.find((e) => e.id === n)?.content ?? null;
24
- }), _ = u(i), v = u(null), y = u(null);
25
- l(() => {
26
- v.current = f;
27
- }, [f]), l(() => () => {
28
- let { events: e, state: t } = o(_.current, {
22
+ }), h = l(n), g = l(null);
23
+ c(() => {
24
+ g.current = d;
25
+ }, [d]), c(() => () => {
26
+ let { events: e, state: t } = a(h.current, {
29
27
  run: null,
30
28
  conversationId: null,
31
29
  status: "idle",
@@ -33,47 +31,48 @@ function f(f) {
33
31
  steps: [],
34
32
  isFiller: () => !1
35
33
  });
36
- _.current = t;
37
- for (let t of e) d(v.current, t);
38
- }, []), l(() => {
39
- let e = f?.onEvent, n = h?.messageId ?? null, l = m && n ? `${m}:${n}` : null, u = h?.status ?? "idle", v = l ? a(u) ? c.ownerFor(l) : c.ownerForSettled(l) : s;
34
+ h.current = t;
35
+ for (let t of e) u(g.current, t);
36
+ }, []), c(() => {
37
+ let e = d?.onEvent, c = p?.messageId ?? null, l = f && c ? `${f}:${c}` : null, g = p?.status ?? "idle", _ = l ? i(g) ? s.ownerFor(l) : s.ownerForSettled(l) : o;
40
38
  if (!e) {
41
- _.current = i;
39
+ h.current = n;
42
40
  return;
43
41
  }
44
- let b = (e) => {
45
- d(f, e);
46
- }, x = m && n ? {
47
- runId: `${m}:${n}`,
48
- conversationId: m,
49
- messageId: n,
50
- ...v
51
- } : null;
52
- x && y.current?.runId !== x.runId && (y.current = {
53
- runId: x.runId,
54
- tr: p
55
- });
56
- let S = x ? y.current?.tr ?? p : p, { steps: C, text: w } = g ? r(g) : {
57
- steps: [],
58
- text: ""
59
- }, { events: T, state: E } = o(_.current, {
60
- run: x,
61
- conversationId: m,
62
- status: u,
63
- content: w,
64
- steps: C,
65
- error: h?.error ?? null,
66
- isFiller: (e) => t(S, e)
67
- });
68
- _.current = E;
69
- for (let e of T) b(e);
42
+ let v = (e) => {
43
+ u(d, e);
44
+ }, y = f && c ? {
45
+ runId: `${f}:${c}`,
46
+ conversationId: f,
47
+ messageId: c,
48
+ ..._
49
+ } : null, b;
50
+ try {
51
+ let { steps: e, text: n } = m ? t(m) : {
52
+ steps: [],
53
+ text: ""
54
+ };
55
+ b = a(h.current, {
56
+ run: y,
57
+ conversationId: f,
58
+ status: g,
59
+ content: n,
60
+ steps: e,
61
+ error: p?.error ?? null,
62
+ isFiller: r
63
+ });
64
+ } catch (e) {
65
+ console.error("[assistant] preview bridge could not read the turn", e);
66
+ return;
67
+ }
68
+ h.current = b.state;
69
+ for (let e of b.events) v(e);
70
70
  }, [
71
+ d,
71
72
  f,
72
- m,
73
- h,
74
- g,
75
- p
73
+ p,
74
+ m
76
75
  ]);
77
76
  }
78
77
  //#endregion
79
- export { f as useAssistantPreviewBridge };
78
+ export { d as useAssistantPreviewBridge };
@@ -0,0 +1,25 @@
1
+ import { AssistantConversationProcessing, Message } from './conversation';
2
+ import { AssistantTr } from './i18n';
3
+ /**
4
+ * The text a spoken turn shows in the voice transcript, the saved transcript
5
+ * and the live session — through the same projection as the typed thread, so no
6
+ * surface shows loading copy and a turn that ended with nothing reads "Stopped"
7
+ * everywhere. Tool-activity markup is stripped, as it is for the caption.
8
+ */
9
+ export declare function spokenTurnText(message: Message, processing: AssistantConversationProcessing | null | undefined, tr: AssistantTr): string;
10
+ /**
11
+ * How many spoken turns there are, for the "Continue in chat" watermark and the
12
+ * session baseline.
13
+ *
14
+ * ★★ The turn in flight COUNTS from its first moment, although the transcript
15
+ * lists it only once it has prose. The watermark is persisted on the note (`continuedVoiceTurns`),
16
+ * and before BOFF-7277 that turn was counted because it held loading copy.
17
+ * Leaving it out would record a watermark one short when "Continue in chat" is
18
+ * pressed mid-turn; the reply then lands, the count moves past it, and the
19
+ * action is offered again — appending a second note with nothing new in it.
20
+ *
21
+ * Only the newest turn can be live, so the transcript's indices and this count
22
+ * agree for every turn that is listed.
23
+ */
24
+ export declare function countSpokenTurns(voiceMessages: readonly Message[], processing: AssistantConversationProcessing | null | undefined, tr: AssistantTr): number;
25
+ //# sourceMappingURL=spokenTurns.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spokenTurns.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/spokenTurns.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,+BAA+B,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAE/E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAI1C;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,+BAA+B,GAAG,IAAI,GAAG,SAAS,EAC9D,EAAE,EAAE,WAAW,GACd,MAAM,CAIR;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAC9B,aAAa,EAAE,SAAS,OAAO,EAAE,EACjC,UAAU,EAAE,+BAA+B,GAAG,IAAI,GAAG,SAAS,EAC9D,EAAE,EAAE,WAAW,GACd,MAAM,CAOR"}
@@ -0,0 +1,12 @@
1
+ import { isTurnInFlight as e } from "./turnState.js";
2
+ import { getAssistantDisplayContent as t } from "./displayContent.js";
3
+ import { parseToolActivity as n } from "./ui/AssistantToolActivity.js";
4
+ //#region src/shared/assistant/spokenTurns.ts
5
+ function r(e, r, i) {
6
+ return n(t(e, r, i).text).text.trim();
7
+ }
8
+ function i(t, n, i) {
9
+ return t.filter((t) => t.role !== "user" && t.role !== "assistant" ? !1 : n?.messageId === t.id && e(n.status) || r(t, n, i).length > 0).length;
10
+ }
11
+ //#endregion
12
+ export { i as countSpokenTurns, r as spokenTurnText };