@burdenoff/fe-libs 2026.913.1 → 2026.914.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) 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 +9 -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 +66 -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 +362 -379
  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 +16 -15
  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 +37 -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/voice/AssistantVoiceSession.d.ts.map +1 -1
  50. package/dist/shared/assistant/ui/voice/AssistantVoiceSession.js +112 -102
  51. package/dist/shared/assistant/ui/voice/VoiceMiniController.d.ts +10 -0
  52. package/dist/shared/assistant/ui/voice/VoiceMiniController.d.ts.map +1 -1
  53. package/dist/shared/assistant/ui/voice/VoiceMiniController.js +29 -28
  54. package/dist/shared/assistant/ui/voice/VoiceStage.d.ts +10 -0
  55. package/dist/shared/assistant/ui/voice/VoiceStage.d.ts.map +1 -1
  56. package/dist/shared/assistant/ui/voice/VoiceStage.js +35 -34
  57. package/dist/shared/assistant/ui/voice/VoiceStatusText.d.ts +51 -0
  58. package/dist/shared/assistant/ui/voice/VoiceStatusText.d.ts.map +1 -0
  59. package/dist/shared/assistant/ui/voice/VoiceStatusText.js +42 -0
  60. package/dist/shared/assistant/voice/rotationClock.d.ts +31 -0
  61. package/dist/shared/assistant/voice/rotationClock.d.ts.map +1 -0
  62. package/dist/shared/assistant/voice/rotationClock.js +27 -0
  63. package/dist/shared/assistant/voice/voiceStatus.d.ts +81 -0
  64. package/dist/shared/assistant/voice/voiceStatus.d.ts.map +1 -0
  65. package/dist/shared/assistant/voice/voiceStatus.js +33 -0
  66. package/dist/shared-assistant.js +94 -85
  67. package/package.json +1 -1
@@ -1,21 +1,17 @@
1
1
  import { AssistantConversationStatus } from './conversation';
2
2
  import { AssistantTr } from './i18n';
3
3
  /**
4
- * Every string the assistant shows in its own bubble while a turn is still
5
- * working — and the one predicate that recognises them.
4
+ * Every string the assistant shows while a turn is still working.
6
5
  *
7
- * ★★ THE REASON THIS IS ONE MODULE. Two features depend on the same set and
8
- * they fail in opposite directions if it drifts:
6
+ * ★★ RENDERED, NEVER STORED (BOFF-7277). This copy is drawn from the turn's
7
+ * live processing state (`AssistantConversationProcessing.stage`) by
8
+ * `AssistantTurnActivity`; a message's `content` holds only what the model
9
+ * produced or a genuine settled outcome. It used to be written into content,
10
+ * which is how filler reached the history preview, Copy, Export and the preview
11
+ * — and how a reload mid-turn left "Thinking..." standing as an answer forever.
9
12
  *
10
- * - the bubble rotates filler while the model thinks, so the set GROWS;
11
- * - an interrupted turn must have its filler replaced, so the set must be
12
- * RECOGNISED exhaustively.
13
- *
14
- * Add a phrase to the rotation without teaching the predicate about it and an
15
- * interrupt during that phrase strands it in the transcript forever — which is
16
- * precisely the defect this module exists to fix (BOFF-7229), reintroduced one
17
- * word at a time. Keeping both sides here makes that impossible: the predicate
18
- * is derived from the same tables the writers use, and a test asserts it.
13
+ * ★ Recognising the copy that OLDER builds stored is a separate concern, kept
14
+ * in `legacyFiller.ts` so nothing that runs a turn can reach for it.
19
15
  */
20
16
  export interface StageCopyEntry {
21
17
  /** Relative i18n key, resolved through `AssistantTr`. */
@@ -58,11 +54,11 @@ export declare const STAGE_COPY: {
58
54
  readonly fallback: "Thinking...";
59
55
  };
60
56
  /**
61
- * What replaces stage copy on a turn the user cut off.
57
+ * What a turn that ended without producing anything is shown as.
62
58
  *
63
- * ★ Deliberately NOT a member of `isStageCopy`: it is a settled outcome, not
64
- * a turn still working. That asymmetry is what makes the replacement
65
- * idempotent — a second pass over an already-stopped turn rewrites nothing.
59
+ * ★ Deliberately NOT legacy filler (`legacyFiller.ts`): it is a settled
60
+ * outcome, not a turn still working, and a model can genuinely answer
61
+ * "Stopped the pump at 4pm."
66
62
  */
67
63
  readonly stopped: {
68
64
  readonly key: "stage.stopped";
@@ -77,8 +73,8 @@ export declare const STAGE_COPY: {
77
73
  * "Thinking..." for the length of a turn reads as a hang; a phrase that moves
78
74
  * reads as work in progress.
79
75
  *
80
- * ★ Every entry here is machine copy by construction, so `isStageCopy` covers
81
- * the whole list rather than a hand-maintained subset.
76
+ * ★ Every entry here is machine copy by construction, so legacy recognition
77
+ * covers the whole list rather than a hand-maintained subset.
82
78
  */
83
79
  export declare const THINKING_PHRASES: readonly StageCopyEntry[];
84
80
  /**
@@ -86,8 +82,8 @@ export declare const THINKING_PHRASES: readonly StageCopyEntry[];
86
82
  *
87
83
  * ★ Not the poll cadence. Polls land every 600-1500ms
88
84
  * (`voice/assistantPollSchedule`), and rotating on every one of them flickers.
89
- * Rotation is driven by ELAPSED TIME so the cadence is independent of how often
90
- * the loop happens to write.
85
+ * Rotation is driven by ELAPSED TIME, from the stage's stored origin, so the
86
+ * cadence is independent of how often anything writes.
91
87
  */
92
88
  export declare const PHRASE_ROTATE_MS = 2500;
93
89
  /** Resolve one entry through the product's translator. */
@@ -99,6 +95,12 @@ export declare function stageText(tr: AssistantTr, entry: StageCopyEntry): strin
99
95
  * exercised by tests without faking timers.
100
96
  */
101
97
  export declare function thinkingPhrase(tr: AssistantTr, elapsedMs: number): string;
98
+ /**
99
+ * The ENTRY behind `thinkingPhrase` — for a caller that needs to know which
100
+ * key is showing, not just its text. Two keys can translate to the same word,
101
+ * so recovering the entry from the text is ambiguous.
102
+ */
103
+ export declare function thinkingPhraseEntry(elapsedMs: number): StageCopyEntry;
102
104
  /**
103
105
  * The copy for a conversation status, when a caller has none of its own.
104
106
  *
@@ -107,17 +109,4 @@ export declare function thinkingPhrase(tr: AssistantTr, elapsedMs: number): stri
107
109
  * for once in the fe-libs shell.
108
110
  */
109
111
  export declare function statusStageCopy(tr: AssistantTr, status: AssistantConversationStatus): string;
110
- /**
111
- * Is this bubble still showing machine copy rather than an answer?
112
- *
113
- * ★★ Both the translation AND the English fallback are compared, for two
114
- * reasons that are easy to miss. A locale can change mid-turn, leaving content
115
- * written under the previous one; and a key that is published but not yet
116
- * ACTIVE resolves to its fallback, which is how ~9,000 assistant keys behaved
117
- * in prod. Matching one form only would leave the bubble stranded in exactly
118
- * the cases this predicate exists to catch.
119
- *
120
- * ★ Empty is machine copy too — a bubble with nothing in it is not an answer.
121
- */
122
- export declare function isStageCopy(tr: AssistantTr, content: string | null | undefined): boolean;
123
112
  //# sourceMappingURL=stageCopy.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"stageCopy.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/stageCopy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAE1C;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,cAAc;IAC7B,yDAAyD;IACzD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;IAyBrB;;;;;;OAMG;;;;;CAK8C,CAAC;AAEpD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gBAAgB,EAAE,SAAS,cAAc,EAWrD,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,OAAO,CAAC;AAErC,0DAA0D;AAC1D,wBAAgB,SAAS,CAAC,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,cAAc,GAAG,MAAM,CAExE;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAKzE;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,EAAE,EAAE,WAAW,EACf,MAAM,EAAE,2BAA2B,GAClC,MAAM,CAcR;AAeD;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CACzB,EAAE,EAAE,WAAW,EACf,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACjC,OAAO,CAOT"}
1
+ {"version":3,"file":"stageCopy.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/stageCopy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,2BAA2B,EAE5B,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAE1C;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,cAAc;IAC7B,yDAAyD;IACzD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;IAyBrB;;;;;;OAMG;;;;;CAKsE,CAAC;AAE5E;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gBAAgB,EAAE,SAAS,cAAc,EAWrD,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,OAAO,CAAC;AAErC,0DAA0D;AAC1D,wBAAgB,SAAS,CAAC,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,cAAc,GAAG,MAAM,CAExE;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAEzE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,CAKrE;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,EAAE,EAAE,WAAW,EACf,MAAM,EAAE,2BAA2B,GAClC,MAAM,CAcR"}
@@ -70,10 +70,13 @@ var e = {
70
70
  function r(e, t) {
71
71
  return e(t.key, t.fallback);
72
72
  }
73
- function i(e, i) {
74
- return r(e, t[Math.floor((Number.isFinite(i) ? Math.max(0, i) : 0) / n) % t.length]);
73
+ function i(e, t) {
74
+ return r(e, a(t));
75
75
  }
76
- function a(t, n) {
76
+ function a(e) {
77
+ return t[Math.floor((Number.isFinite(e) ? Math.max(0, e) : 0) / n) % t.length];
78
+ }
79
+ function o(t, n) {
77
80
  switch (n) {
78
81
  case "provisioning": return r(t, e.startingEnvironment);
79
82
  case "connecting": return r(t, e.connecting);
@@ -81,17 +84,5 @@ function a(t, n) {
81
84
  default: return "";
82
85
  }
83
86
  }
84
- var o = [
85
- e.reusingEnvironment,
86
- e.lookingForEnvironment,
87
- e.startingEnvironment,
88
- e.preparingSession,
89
- e.connecting,
90
- ...t
91
- ];
92
- function s(e, t) {
93
- let n = (t ?? "").trim();
94
- return n ? o.some((t) => e(t.key, t.fallback) === n || t.fallback === n) : !0;
95
- }
96
87
  //#endregion
97
- export { n as PHRASE_ROTATE_MS, e as STAGE_COPY, t as THINKING_PHRASES, s as isStageCopy, r as stageText, a as statusStageCopy, i as thinkingPhrase };
88
+ export { n as PHRASE_ROTATE_MS, e as STAGE_COPY, t as THINKING_PHRASES, r as stageText, o as statusStageCopy, i as thinkingPhrase, a as thinkingPhraseEntry };
@@ -1,4 +1,4 @@
1
- import { AssistantConversationProcessing, AssistantConversationStatus, AssistantMessageMetadata, AssistantSandboxRuntime, AssistantSandboxStatus, Conversation, Message } from './conversation';
1
+ import { AssistantConversationProcessing, AssistantConversationStatus, AssistantMessageMetadata, AssistantSandboxRuntime, AssistantSandboxStatus, AssistantTurnStage, Conversation, Message } from './conversation';
2
2
  import { AssistantMode } from './types';
3
3
  interface AssistantState {
4
4
  conversations: Conversation[];
@@ -73,7 +73,15 @@ interface AssistantState {
73
73
  * takes `lang` and `voice` down with it.
74
74
  */
75
75
  mergeMessageMetadata: (conversationId: string, messageId: string, patch: Partial<AssistantMessageMetadata>) => void;
76
- setConversationProcessing: (conversationId: string, status: AssistantConversationStatus, messageId?: string | null, error?: string | null) => void;
76
+ /**
77
+ * Replace a conversation's processing entry.
78
+ *
79
+ * `stage` is the step an in-flight turn is on (see `AssistantTurnStage`). It
80
+ * lands in the SAME set as the status, so no render can pair a new status with
81
+ * the previous step's copy. Omitting it clears it, which is what every settled
82
+ * status wants.
83
+ */
84
+ setConversationProcessing: (conversationId: string, status: AssistantConversationStatus, messageId?: string | null, error?: string | null, stage?: AssistantTurnStage | null) => void;
77
85
  clearConversationProcessing: (conversationId: string) => void;
78
86
  toggleConversationList: () => void;
79
87
  setConversationListOpen: (open: boolean) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/store.ts"],"names":[],"mappings":"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"}
@@ -95,15 +95,22 @@ var i = t()(n((e, t) => ({
95
95
  } : e),
96
96
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
97
97
  } : e) })),
98
- setConversationProcessing: (t, n, r = null, i = null) => e((e) => ({ processingByConversationId: {
99
- ...e.processingByConversationId,
100
- [t]: {
101
- status: n,
102
- messageId: r,
103
- error: i,
104
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
105
- }
106
- } })),
98
+ setConversationProcessing: (t, n, r = null, i = null, a = null) => e((e) => {
99
+ let o = Date.now(), s = e.processingByConversationId[t], c = a !== null && r !== null && s?.messageId === r && s.stage === a && typeof s.stageStartedAt == "number" ? s.stageStartedAt : o;
100
+ return { processingByConversationId: {
101
+ ...e.processingByConversationId,
102
+ [t]: {
103
+ status: n,
104
+ messageId: r,
105
+ error: i,
106
+ updatedAt: new Date(o).toISOString(),
107
+ ...a === null ? {} : {
108
+ stage: a,
109
+ stageStartedAt: c
110
+ }
111
+ }
112
+ } };
113
+ }),
107
114
  clearConversationProcessing: (t) => e((e) => {
108
115
  let n = { ...e.processingByConversationId };
109
116
  return delete n[t], { processingByConversationId: n };
@@ -0,0 +1,66 @@
1
+ import { AssistantConversationProcessing, AssistantTurnStage } from './conversation';
2
+ import { AssistantTr } from './i18n';
3
+ /**
4
+ * The waiting copy for a live turn, derived from its processing state.
5
+ *
6
+ * ★★ Nothing here reads or writes message content (BOFF-7277). Everything is a
7
+ * pure function of the processing entry and elapsed time; the clock that
8
+ * advances it lives in the leaf that renders it, `AssistantTurnActivity`.
9
+ */
10
+ /**
11
+ * The step to describe, or `null` when there is nothing honest to say.
12
+ *
13
+ * ★ `provisioning` with no stage is the synchronous write before the runtime
14
+ * has looked at anything. Guessing "Starting..." there would flash the wrong
15
+ * word on every reused sandbox a moment before the real step arrives, so it
16
+ * says nothing and the avatar and caret carry the wait.
17
+ */
18
+ export declare function turnActivityStage(processing: AssistantConversationProcessing | null | undefined): AssistantTurnStage | null;
19
+ export interface TurnActivityCopy {
20
+ /** For the eye. Rotates while thinking; otherwise identical to `label`. */
21
+ readonly shown: string;
22
+ /** For assistive tech. Changes only when the step does. */
23
+ readonly label: string;
24
+ /** Whether `shown` moves with elapsed time. */
25
+ readonly rotating: boolean;
26
+ }
27
+ /**
28
+ * What to show for a live turn that has produced nothing yet.
29
+ *
30
+ * ★ Environment steps are informative and hold still. Only `thinking` rotates:
31
+ * a single frozen word for the length of a turn reads as a hang.
32
+ *
33
+ * ★★ A phrase is shown only in the SAME translation state as the thinking
34
+ * label, as on the voice status line. The phrases are separately seeded keys; if
35
+ * the label is translated and a phrase is not, rotating would alternate the
36
+ * user's language with English, so the line holds on the translated label.
37
+ *
38
+ * Pure in `elapsedMs` — the caller owns the clock.
39
+ */
40
+ export declare function turnActivityCopy(tr: AssistantTr, processing: AssistantConversationProcessing | null | undefined, elapsedMs: number): TurnActivityCopy | null;
41
+ /**
42
+ * Time a rotation has run: from the stage's stored `origin` to the last tick.
43
+ *
44
+ * `null` origin — not rotating, or holding still for reduced motion — is 0,
45
+ * which is the stable label. Never negative: `now` lags the real clock, so a
46
+ * stage that began after the last tick reads as just started.
47
+ */
48
+ export declare function elapsedSince(origin: number | null, now: number): number;
49
+ /**
50
+ * Milliseconds until the phrase at `elapsedMs` is replaced by the next one.
51
+ *
52
+ * Always in (0, PHRASE_ROTATE_MS], so a tick scheduled with it lands on the
53
+ * boundary instead of up to a whole phrase late.
54
+ */
55
+ export declare function msUntilNextPhrase(elapsedMs: number): number;
56
+ /**
57
+ * Call `onTick(now)` at each phrase boundary after `startedAt`, until stopped.
58
+ *
59
+ * ★ Boundary-aligned timeouts rather than a fixed interval: the origin is the
60
+ * stage's stored start, which is usually well before this component mounted, so
61
+ * an interval started at mount would change phrase at the wrong moments.
62
+ *
63
+ * Returns the stop function — an effect's cleanup.
64
+ */
65
+ export declare function startPhraseTicker(startedAt: number, onTick: (now: number) => void, clock?: () => number): () => void;
66
+ //# sourceMappingURL=turnActivity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"turnActivity.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/turnActivity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,+BAA+B,EAC/B,kBAAkB,EACnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAU1C;;;;;;GAMG;AAEH;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,+BAA+B,GAAG,IAAI,GAAG,SAAS,GAC7D,kBAAkB,GAAG,IAAI,CAM3B;AAED,MAAM,WAAW,gBAAgB;IAC/B,2EAA2E;IAC3E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,2DAA2D;IAC3D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,+CAA+C;IAC/C,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAKD;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAC9B,EAAE,EAAE,WAAW,EACf,UAAU,EAAE,+BAA+B,GAAG,IAAI,GAAG,SAAS,EAC9D,SAAS,EAAE,MAAM,GAChB,gBAAgB,GAAG,IAAI,CAczB;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAKvE;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAG3D;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,EAC7B,KAAK,GAAE,MAAM,MAAiB,GAC7B,MAAM,IAAI,CAoBZ"}
@@ -0,0 +1,41 @@
1
+ import { PHRASE_ROTATE_MS as e, STAGE_COPY as t, stageText as n, thinkingPhraseEntry as r } from "./stageCopy.js";
2
+ import { isTurnInFlight as i } from "./turnState.js";
3
+ //#region src/shared/assistant/turnActivity.ts
4
+ function a(e) {
5
+ return !e || !i(e.status) ? null : e.stage ? e.stage : e.status === "streaming" ? "thinking" : e.status === "connecting" ? "connecting" : null;
6
+ }
7
+ var o = (e, t) => e(t.key, t.fallback) !== t.fallback;
8
+ function s(e, i, s) {
9
+ let c = a(i);
10
+ if (!c) return null;
11
+ let l = n(e, t[c]);
12
+ if (c !== "thinking") return {
13
+ shown: l,
14
+ label: l,
15
+ rotating: !1
16
+ };
17
+ let u = r(s), d = n(e, u);
18
+ return {
19
+ shown: o(e, u) === o(e, t.thinking) ? d : l,
20
+ label: l,
21
+ rotating: !0
22
+ };
23
+ }
24
+ function c(e, t) {
25
+ return e === null || !Number.isFinite(e) || !Number.isFinite(t) ? 0 : Math.max(0, t - e);
26
+ }
27
+ function l(t) {
28
+ return e - (Number.isFinite(t) ? Math.max(0, t) : 0) % e;
29
+ }
30
+ function u(e, t, n = Date.now) {
31
+ let r = null, i = !1, a = () => {
32
+ r = setTimeout(() => {
33
+ t(n()), i || a();
34
+ }, l(n() - e));
35
+ };
36
+ return a(), () => {
37
+ i = !0, r !== null && clearTimeout(r), r = null;
38
+ };
39
+ }
40
+ //#endregion
41
+ export { c as elapsedSince, l as msUntilNextPhrase, u as startPhraseTicker, s as turnActivityCopy, a as turnActivityStage };
@@ -0,0 +1,51 @@
1
+ import { PendingWrite } from './pendingWrite';
2
+ import { AssistantRawMessage } from './types';
3
+ /** What one poll of the sandbox says this turn has produced so far. */
4
+ export interface AssistantTurnProgress {
5
+ /**
6
+ * The model's output so far — text, media markdown and tool progress lines —
7
+ * and NOTHING else. Empty until something renderable arrives.
8
+ */
9
+ content: string;
10
+ /**
11
+ * ★★ Whether `content` holds anything to show, as an explicit field.
12
+ *
13
+ * This used to be signalled by a SENTINEL: `content` came back as
14
+ * "Thinking..." when nothing had arrived, and callers compared strings to find
15
+ * out. The sentinel then leaked wherever that comparison was skipped — a turn
16
+ * whose stream budget elapsed stored "Thinking..." in front of its timeout
17
+ * note. A boolean cannot be mistaken for output (BOFF-7277).
18
+ */
19
+ hasRenderableOutput: boolean;
20
+ done: boolean;
21
+ tokens?: {
22
+ input: number;
23
+ output: number;
24
+ };
25
+ /**
26
+ * Identity + model of the message these tokens came from, needed to charge the
27
+ * turn: `messageId` is half the server's idempotency hash and `model` selects the
28
+ * per-token prices. Read from the SAME message as `tokens`, never guessed from
29
+ * the tail of `messages` — on a session with trailing history that is a different
30
+ * message, and mis-attributing a charge is worse than missing one.
31
+ */
32
+ messageId?: string;
33
+ model?: string;
34
+ /** A write the sandbox refused pending approval, if this turn produced one. */
35
+ pendingWrite?: PendingWrite;
36
+ }
37
+ /**
38
+ * Reduce one poll's session messages to this turn's progress.
39
+ *
40
+ * `priorNewestCreatedMs` is the `created` timestamp (sandbox clock) of the newest
41
+ * message that already existed in this session BEFORE the prompt was sent. This
42
+ * turn's reply is the assistant message created strictly after it. Crucially this
43
+ * stays WITHIN the sandbox clock domain: an earlier version compared the
44
+ * sandbox-stamped `created` against the browser wall-clock (Date#now), so a reply
45
+ * stamped at prompt-time was silently dropped whenever the sandbox clock lagged
46
+ * the browser — the turn then hung until the stream budget elapsed. A
47
+ * sandbox-domain floor is immune to clock skew and correct for both fresh and
48
+ * reused (per-conversation) sessions, with no message-window gap.
49
+ */
50
+ export declare function buildAssistantProgress(messages: AssistantRawMessage[], priorNewestCreatedMs: number): AssistantTurnProgress;
51
+ //# sourceMappingURL=turnProgress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"turnProgress.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/turnProgress.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAOrE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAEnD,uEAAuE;AACvE,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;;;;OAQG;IACH,mBAAmB,EAAE,OAAO,CAAC;IAC7B,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,mBAAmB,EAAE,EAC/B,oBAAoB,EAAE,MAAM,GAC3B,qBAAqB,CAmDvB"}
@@ -0,0 +1,27 @@
1
+ import { getAssistantMedia as e, getAssistantText as t, getRawMessageCreatedAt as n, getToolProgress as r } from "./progress.js";
2
+ import { findPendingWrite as i } from "./pendingWrite.js";
3
+ //#region src/shared/assistant/turnProgress.ts
4
+ function a(a, o) {
5
+ let s = a.filter((e) => e.info?.role === "assistant" && n(e) > o).sort((e, t) => n(e) - n(t));
6
+ if (s.length === 0) return {
7
+ content: "",
8
+ hasRenderableOutput: !1,
9
+ done: !1
10
+ };
11
+ let c = s[s.length - 1], l = t(c.parts), u = e(c.parts), d = r(c.parts), f = i(c.parts), p = !!l || u.length > 0 || d.length > 0, m = [
12
+ l,
13
+ ...u,
14
+ ...d
15
+ ].filter(Boolean).join("\n\n"), h = c.info?.providerID, g = c.info?.modelID;
16
+ return {
17
+ content: m,
18
+ hasRenderableOutput: p,
19
+ done: !!c.info?.time?.completed && p,
20
+ tokens: c.info?.tokens,
21
+ messageId: c.info?.id,
22
+ ...h && g ? { model: `${h}/${g}` } : {},
23
+ ...f ? { pendingWrite: f } : {}
24
+ };
25
+ }
26
+ //#endregion
27
+ export { a as buildAssistantProgress };
@@ -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;AAqEf,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAoKvE;;;;;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,CAs9DxD,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;AAuEf,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAgDvE;;;;;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,CA2+DxD,CAAC"}