@burdenoff/fe-libs 2026.1004.8 → 2026.1005.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 (32) hide show
  1. package/dist/shared/assistant/api.d.ts +18 -0
  2. package/dist/shared/assistant/api.d.ts.map +1 -1
  3. package/dist/shared/assistant/api.js +169 -147
  4. package/dist/shared/assistant/capabilities.d.ts +21 -0
  5. package/dist/shared/assistant/capabilities.d.ts.map +1 -1
  6. package/dist/shared/assistant/capabilities.js +11 -1
  7. package/dist/shared/assistant/index.d.ts +4 -0
  8. package/dist/shared/assistant/index.d.ts.map +1 -1
  9. package/dist/shared/assistant/liveDeltas.d.ts +76 -0
  10. package/dist/shared/assistant/liveDeltas.d.ts.map +1 -0
  11. package/dist/shared/assistant/liveDeltas.js +196 -0
  12. package/dist/shared/assistant/liveOverlay.d.ts +62 -0
  13. package/dist/shared/assistant/liveOverlay.d.ts.map +1 -0
  14. package/dist/shared/assistant/liveOverlay.js +64 -0
  15. package/dist/shared/assistant/snapshotPoller.d.ts +48 -0
  16. package/dist/shared/assistant/snapshotPoller.d.ts.map +1 -0
  17. package/dist/shared/assistant/snapshotPoller.js +58 -0
  18. package/dist/shared/assistant/turnStream.d.ts +71 -0
  19. package/dist/shared/assistant/turnStream.d.ts.map +1 -0
  20. package/dist/shared/assistant/turnStream.js +266 -0
  21. package/dist/shared/assistant/turnTimeline.d.ts +27 -2
  22. package/dist/shared/assistant/turnTimeline.d.ts.map +1 -1
  23. package/dist/shared/assistant/turnTimeline.js +17 -28
  24. package/dist/shared/assistant/types.d.ts +10 -0
  25. package/dist/shared/assistant/types.d.ts.map +1 -1
  26. package/dist/shared/assistant/ui/AssistantChatArea.d.ts.map +1 -1
  27. package/dist/shared/assistant/ui/AssistantChatArea.js +1049 -1008
  28. package/dist/shared/assistant/ui/AssistantMessageList.d.ts +2 -0
  29. package/dist/shared/assistant/ui/AssistantMessageList.d.ts.map +1 -1
  30. package/dist/shared/assistant/ui/AssistantMessageList.js +48 -32
  31. package/dist/shared-assistant.js +208 -204
  32. package/package.json +1 -1
@@ -50,5 +50,26 @@ export declare function isUnknownFieldError(error: unknown): boolean;
50
50
  * found" and "404" are deliberately not matched here.
51
51
  */
52
52
  export declare function isMissingGatewayFieldError(error: unknown, field: string, typeNames?: readonly string[]): boolean;
53
+ /**
54
+ * ★★ BOFF-7914 (speed S3): the turn stream's OWN mint backoff, separate from the
55
+ * `sse` capability above. `getAssistantStreamAccess` (the widget transport's
56
+ * mint) latches `sse: unsupported` for the page on any failure; this one must
57
+ * not: a mint that answered 404 because the relay is off in prod, or failed
58
+ * once on a bad network, is retried after a pause, and never disables the
59
+ * stream for the rest of the page (design rule 6).
60
+ *
61
+ * - a 404 (relay off, product not allowlisted, bridge without the projection)
62
+ * backs off 5 minutes: it is a deployment answer, not a blip;
63
+ * - any other failure backs off 60 seconds;
64
+ * - a success clears it.
65
+ *
66
+ * Per page load, like every capability here. It only ever LENGTHENS a backoff.
67
+ */
68
+ export declare const STREAM_MINT_BACKOFF_UNAVAILABLE_MS: number;
69
+ export declare const STREAM_MINT_BACKOFF_ERROR_MS = 60000;
70
+ /** Is a mint inside its backoff window? */
71
+ export declare function streamMintBackedOff(now?: number): boolean;
72
+ export declare function backOffStreamMint(ms: number, now?: number): void;
73
+ export declare function clearStreamMintBackoff(): void;
53
74
  export {};
54
75
  //# sourceMappingURL=capabilities.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/capabilities.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,WAAW,GAAG,aAAa,CAAC;AAEtE,UAAU,qBAAqB;IAC7B,qBAAqB,EAAE,eAAe,CAAC;IACvC,UAAU,EAAE,eAAe,CAAC;IAC5B,GAAG,EAAE,eAAe,CAAC;IACrB;;;OAGG;IACH,WAAW,EAAE,eAAe,CAAC;IAC7B;;;;OAIG;IACH,yBAAyB,EAAE,eAAe,CAAC;IAC3C,sBAAsB,EAAE,eAAe,CAAC;IACxC,2BAA2B,EAAE,eAAe,CAAC;CAC9C;AAYD,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,qBAAqB,GAAG,eAAe,CAE/E;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,qBAAqB,GAAG,IAAI,CAEpE;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,qBAAqB,GAAG,IAAI,CAEtE;AAED,8EAA8E;AAC9E,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAK3D;AAID;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,MAAM,EACb,SAAS,GAAE,SAAS,MAAM,EAAO,GAChC,OAAO,CAWT"}
1
+ {"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/capabilities.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,WAAW,GAAG,aAAa,CAAC;AAEtE,UAAU,qBAAqB;IAC7B,qBAAqB,EAAE,eAAe,CAAC;IACvC,UAAU,EAAE,eAAe,CAAC;IAC5B,GAAG,EAAE,eAAe,CAAC;IACrB;;;OAGG;IACH,WAAW,EAAE,eAAe,CAAC;IAC7B;;;;OAIG;IACH,yBAAyB,EAAE,eAAe,CAAC;IAC3C,sBAAsB,EAAE,eAAe,CAAC;IACxC,2BAA2B,EAAE,eAAe,CAAC;CAC9C;AAYD,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,qBAAqB,GAAG,eAAe,CAE/E;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,qBAAqB,GAAG,IAAI,CAEpE;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,qBAAqB,GAAG,IAAI,CAEtE;AAED,8EAA8E;AAC9E,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAK3D;AAID;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,MAAM,EACb,SAAS,GAAE,SAAS,MAAM,EAAO,GAChC,OAAO,CAWT;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,kCAAkC,QAAa,CAAC;AAC7D,eAAO,MAAM,4BAA4B,QAAS,CAAC;AAInD,2CAA2C;AAC3C,wBAAgB,mBAAmB,CAAC,GAAG,GAAE,MAAmB,GAAG,OAAO,CAErE;AAED,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,GAAE,MAAmB,GAAG,IAAI,CAE5E;AAED,wBAAgB,sBAAsB,IAAI,IAAI,CAE7C"}
@@ -27,5 +27,15 @@ function s(t, n, r = []) {
27
27
  let i = t instanceof Error ? t.message : String(t), a = (e) => `["'\u201C]${o(e)}["'\u201D]`;
28
28
  return /missing @rbac directive/i.test(i) ? RegExp(`Field ${a(n)}`).test(i) ? !0 : e(t).some((e) => e.code === "FORBIDDEN" && e.field === n) : RegExp(`Cannot query field ${a(n)}`).test(i) ? !0 : r.some((e) => RegExp(`Unknown type ${a(e)}`).test(i));
29
29
  }
30
+ var c = 5 * 6e4, l = 6e4, u = 0;
31
+ function d(e = Date.now()) {
32
+ return e < u;
33
+ }
34
+ function f(e, t = Date.now()) {
35
+ u = Math.max(u, t + e);
36
+ }
37
+ function p() {
38
+ u = 0;
39
+ }
30
40
  //#endregion
31
- export { n as getCapability, s as isMissingGatewayFieldError, a as isUnknownFieldError, r as markSupported, i as markUnsupported };
41
+ export { l as STREAM_MINT_BACKOFF_ERROR_MS, c as STREAM_MINT_BACKOFF_UNAVAILABLE_MS, f as backOffStreamMint, p as clearStreamMintBackoff, n as getCapability, s as isMissingGatewayFieldError, a as isUnknownFieldError, r as markSupported, i as markUnsupported, d as streamMintBackedOff };
@@ -202,6 +202,10 @@ export * from './permissionError';
202
202
  export * from './autoRouting';
203
203
  export * from './turnOutcome';
204
204
  export * from './turnTimeline';
205
+ export * from './turnStream';
206
+ export * from './liveDeltas';
207
+ export * from './liveOverlay';
208
+ export * from './snapshotPoller';
205
209
  export * from './turnTimingReport';
206
210
  export * from './turnTimingReporter';
207
211
  export * from './prewarm';
@@ -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,76 @@
1
+ import { AssistantRawMessage } from './types';
2
+ /** One frame as the stream hands it over: the SSE event name and its JSON data. */
3
+ export interface LiveFrame {
4
+ readonly event: string;
5
+ readonly data: unknown;
6
+ }
7
+ /** What the reducer holds about one text part. */
8
+ export interface LivePartState {
9
+ readonly messageId: string;
10
+ /** The stream generation that started the part (`LiveDeltaState.generation`). */
11
+ readonly generation: number;
12
+ /** The redacted text so far — or, once `ended`, the final redacted text. */
13
+ readonly text: string;
14
+ /** Began live: this stream saw the part's start frame. `false` is poll-only. */
15
+ readonly live: boolean;
16
+ /** The part's end frame arrived. */
17
+ readonly ended: boolean;
18
+ /** A delta did not continue the text: no later delta is applied. */
19
+ readonly gapped: boolean;
20
+ /** A new generation began while the part was being written. */
21
+ readonly frozen: boolean;
22
+ }
23
+ export interface LiveMessageState {
24
+ readonly created?: number;
25
+ readonly completed?: number;
26
+ }
27
+ export interface LiveDeltaState {
28
+ /** +1 for every re-mint. */
29
+ readonly generation: number;
30
+ readonly parts: ReadonlyMap<string, LivePartState>;
31
+ readonly messages: ReadonlyMap<string, LiveMessageState>;
32
+ }
33
+ /** Bounds on what one turn's stream may make this reducer remember. */
34
+ export declare const LIVE_PART_LIMIT = 256;
35
+ export declare const LIVE_MESSAGE_LIMIT = 256;
36
+ /** The longest live text one part may hold; past it the part is frozen. */
37
+ export declare const LIVE_TEXT_LIMIT: number;
38
+ export declare function createLiveState(): LiveDeltaState;
39
+ /**
40
+ * The stream was lost: whatever arrives next is unknown, so every part still
41
+ * being written is frozen at its text. The generation does not change.
42
+ */
43
+ export declare function freezeLiveParts(state: LiveDeltaState): LiveDeltaState;
44
+ /**
45
+ * A new generation: the stream was replaced (a re-mint). Every part still being
46
+ * written is frozen at its text — the frames between two streams are unknown —
47
+ * and parts the new stream starts belong to the new generation.
48
+ */
49
+ export declare function beginLiveGeneration(state: LiveDeltaState): LiveDeltaState;
50
+ /**
51
+ * Fold one frame into the state. Frames that are not about text (a tool part, a
52
+ * reasoning part, `session.idle`, `stream.end`) change nothing here: they wake
53
+ * the poll loop, and that is `turnStream`'s business.
54
+ */
55
+ export declare function reduceLiveFrame(state: LiveDeltaState, frame: LiveFrame): LiveDeltaState;
56
+ /**
57
+ * The poll's messages with the live text merged in, for DISPLAY ONLY.
58
+ *
59
+ * - Only messages created after `floor` are touched.
60
+ * - A text part the poll already has is rewritten in place (same id); a
61
+ * live-from-start part the poll has not seen yet is appended to its message,
62
+ * or to a synthetic assistant message that is NOT completed.
63
+ * - A part first seen mid-way (`live: false`) is never taken from the stream.
64
+ * - The input is never modified; nothing is removed; nothing but the text of
65
+ * text parts changes.
66
+ */
67
+ export declare function applyLiveDeltas(polled: readonly AssistantRawMessage[], state: LiveDeltaState, floor: number): AssistantRawMessage[];
68
+ /**
69
+ * How much of the turn's text the stream carried: `full` when every text part
70
+ * it saw was live from its start and none was gapped or frozen, `partial` when
71
+ * the stream carried some but not all, `none` when it carried nothing.
72
+ */
73
+ export declare function liveCoverage(state: LiveDeltaState): "full" | "partial" | "none";
74
+ /** Has any live text arrived that could be shown? */
75
+ export declare function hasLiveText(state: LiveDeltaState): boolean;
76
+ //# sourceMappingURL=liveDeltas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"liveDeltas.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/liveDeltas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAA2B,MAAM,SAAS,CAAC;AAE5E,mFAAmF;AACnF,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;CACxB;AAED,kDAAkD;AAClD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,iFAAiF;IACjF,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,4EAA4E;IAC5E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,gFAAgF;IAChF,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,oCAAoC;IACpC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,oEAAoE;IACpE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,cAAc;IAC7B,4BAA4B;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACnD,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;CAC1D;AAED,uEAAuE;AACvE,eAAO,MAAM,eAAe,MAAM,CAAC;AACnC,eAAO,MAAM,kBAAkB,MAAM,CAAC;AACtC,2EAA2E;AAC3E,eAAO,MAAM,eAAe,QAAa,CAAC;AAE1C,wBAAgB,eAAe,IAAI,cAAc,CAEhD;AAqBD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,cAAc,GAAG,cAAc,CASrE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,cAAc,GAAG,cAAc,CAGzE;AA+HD;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,cAAc,EACrB,KAAK,EAAE,SAAS,GACf,cAAc,CAehB;AAoCD;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,SAAS,mBAAmB,EAAE,EACtC,KAAK,EAAE,cAAc,EACrB,KAAK,EAAE,MAAM,GACZ,mBAAmB,EAAE,CAmEvB;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAa/E;AAED,qDAAqD;AACrD,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAK1D"}
@@ -0,0 +1,196 @@
1
+ //#region src/shared/assistant/liveDeltas.ts
2
+ var e = 256, t = 256, n = 512 * 1024;
3
+ function r() {
4
+ return {
5
+ generation: 0,
6
+ parts: /* @__PURE__ */ new Map(),
7
+ messages: /* @__PURE__ */ new Map()
8
+ };
9
+ }
10
+ function i(e) {
11
+ return typeof e == "object" && e && !Array.isArray(e) ? e : void 0;
12
+ }
13
+ var a = (e) => typeof e == "string" && e !== "" ? e : void 0, o = (e) => typeof e == "number" && Number.isFinite(e) ? e : void 0;
14
+ function s(e, t, n) {
15
+ let r = new Map(e);
16
+ return r.set(t, n), r;
17
+ }
18
+ function c(e) {
19
+ let t = null;
20
+ for (let [n, r] of e.parts) r.live && !r.ended && !r.frozen && (t ??= new Map(e.parts), t.set(n, {
21
+ ...r,
22
+ frozen: !0
23
+ }));
24
+ return t ? {
25
+ ...e,
26
+ parts: t
27
+ } : e;
28
+ }
29
+ function l(e) {
30
+ let t = c(e);
31
+ return {
32
+ ...t,
33
+ generation: t.generation + 1
34
+ };
35
+ }
36
+ function u(e, t) {
37
+ let n = i(t.info), r = a(n?.id);
38
+ if (!n || !r || n.role !== "assistant" || !e.messages.has(r) && e.messages.size >= 256) return e;
39
+ let c = i(n.time), l = o(c?.created), u = o(c?.completed), d = e.messages.get(r);
40
+ return {
41
+ ...e,
42
+ messages: s(e.messages, r, {
43
+ ...l === void 0 ? d?.created === void 0 ? {} : { created: d.created } : { created: l },
44
+ ...u === void 0 ? d?.completed === void 0 ? {} : { completed: d.completed } : { completed: u }
45
+ })
46
+ };
47
+ }
48
+ function d(e, t) {
49
+ let r = a(t.id), c = a(t.messageID);
50
+ if (!r || !c) return e;
51
+ let l = o(i(t.time)?.end) !== void 0, u = typeof t.text == "string" ? t.text : void 0, d = e.parts.get(r);
52
+ if (!d) {
53
+ if (e.parts.size >= 256) return e;
54
+ let n = t.live === !0 && u === "" && !l;
55
+ return {
56
+ ...e,
57
+ parts: s(e.parts, r, {
58
+ messageId: c,
59
+ generation: e.generation,
60
+ text: "",
61
+ live: n,
62
+ ended: l,
63
+ gapped: !1,
64
+ frozen: !1
65
+ })
66
+ };
67
+ }
68
+ return d.ended || !l ? e : !d.live || u === void 0 ? {
69
+ ...e,
70
+ parts: s(e.parts, r, {
71
+ ...d,
72
+ ended: !0
73
+ })
74
+ } : {
75
+ ...e,
76
+ parts: s(e.parts, r, {
77
+ ...d,
78
+ text: u.length > 524288 ? u.slice(0, n) : u,
79
+ ended: !0
80
+ })
81
+ };
82
+ }
83
+ function f(e, t) {
84
+ let n = a(t.partID), r = typeof t.delta == "string" ? t.delta : void 0, i = o(t.offset);
85
+ if (!n || r === void 0) return e;
86
+ let c = e.parts.get(n);
87
+ return !c || !c.live || c.ended || c.gapped || c.frozen ? e : c.generation === e.generation ? i !== c.text.length || c.text.length + r.length > 524288 ? {
88
+ ...e,
89
+ parts: s(e.parts, n, {
90
+ ...c,
91
+ gapped: !0
92
+ })
93
+ } : r === "" ? e : {
94
+ ...e,
95
+ parts: s(e.parts, n, {
96
+ ...c,
97
+ text: c.text + r
98
+ })
99
+ } : {
100
+ ...e,
101
+ parts: s(e.parts, n, {
102
+ ...c,
103
+ frozen: !0
104
+ })
105
+ };
106
+ }
107
+ function p(e, t) {
108
+ let n = i(t.data);
109
+ if (!n) return e;
110
+ switch (t.event) {
111
+ case "message.updated": return u(e, n);
112
+ case "message.part.updated": return n.type === "text" ? d(e, n) : e;
113
+ case "message.part.delta": return n.partType === "text" || n.partType === void 0 ? f(e, n) : e;
114
+ default: return e;
115
+ }
116
+ }
117
+ function m(e, t) {
118
+ return e.time?.end !== void 0 || t.info?.time?.completed !== void 0;
119
+ }
120
+ function h(e, t, n) {
121
+ return t !== void 0 && n ? t : t === void 0 ? e.text : t.startsWith(e.text) ? t : e.text.startsWith(t) ? e.text : t;
122
+ }
123
+ function g(e, t, n) {
124
+ if (t.parts.size === 0) return [...e];
125
+ let r = /* @__PURE__ */ new Map();
126
+ for (let e of t.parts) {
127
+ let [, t] = e;
128
+ if (!t.live || t.text === "" && !t.ended) continue;
129
+ let n = r.get(t.messageId);
130
+ n ? n.push(e) : r.set(t.messageId, [e]);
131
+ }
132
+ if (r.size === 0) return [...e];
133
+ let i = [], a = /* @__PURE__ */ new Set();
134
+ for (let t of e) {
135
+ let e = t.info?.id, o = e ? r.get(e) : void 0;
136
+ if (!e || !o) {
137
+ i.push(t);
138
+ continue;
139
+ }
140
+ a.add(e);
141
+ let s = t.info?.time?.created ?? 0;
142
+ if (t.info?.role !== "assistant" || s <= n) {
143
+ i.push(t);
144
+ continue;
145
+ }
146
+ let c = [...t.parts ?? []];
147
+ for (let [e, n] of o) {
148
+ let r = c.findIndex((t) => t.type === "text" && t.id === e);
149
+ if (r < 0) {
150
+ c.push({
151
+ type: "text",
152
+ id: e,
153
+ text: n.text
154
+ });
155
+ continue;
156
+ }
157
+ let i = c[r], a = h(n, typeof i.text == "string" ? i.text : void 0, m(i, t));
158
+ a !== i.text && (c[r] = {
159
+ ...i,
160
+ text: a
161
+ });
162
+ }
163
+ i.push({
164
+ ...t,
165
+ parts: c
166
+ });
167
+ }
168
+ for (let [e, o] of r) {
169
+ if (a.has(e)) continue;
170
+ let r = t.messages.get(e)?.created;
171
+ r === void 0 || r <= n || i.push({
172
+ info: {
173
+ id: e,
174
+ role: "assistant",
175
+ time: { created: r }
176
+ },
177
+ parts: o.map(([e, t]) => ({
178
+ type: "text",
179
+ id: e,
180
+ text: t.text
181
+ }))
182
+ });
183
+ }
184
+ return i;
185
+ }
186
+ function _(e) {
187
+ let t = 0, n = 0;
188
+ for (let r of e.parts.values()) r.live && r.text !== "" ? (t += 1, (r.gapped || r.frozen) && (n += 1)) : r.live || (n += 1);
189
+ return t === 0 ? "none" : n === 0 ? "full" : "partial";
190
+ }
191
+ function v(e) {
192
+ for (let t of e.parts.values()) if (t.live && t.text !== "") return !0;
193
+ return !1;
194
+ }
195
+ //#endregion
196
+ export { t as LIVE_MESSAGE_LIMIT, e as LIVE_PART_LIMIT, n as LIVE_TEXT_LIMIT, g as applyLiveDeltas, l as beginLiveGeneration, r as createLiveState, c as freezeLiveParts, v as hasLiveText, _ as liveCoverage, p as reduceLiveFrame };
@@ -0,0 +1,62 @@
1
+ import { LiveDeltaState } from './liveDeltas';
2
+ import { AssistantRawMessage } from './types';
3
+ export interface LiveOverlayEntry {
4
+ readonly conversationId: string;
5
+ readonly content: string;
6
+ }
7
+ interface LiveOverlayState {
8
+ readonly byMessageId: Readonly<Record<string, LiveOverlayEntry>>;
9
+ setLive: (messageId: string, conversationId: string, content: string) => void;
10
+ clearLive: (messageId: string) => void;
11
+ }
12
+ /** Not persisted, by construction: there is no `persist` in this file. */
13
+ export declare const useLiveOverlay: import('zustand').UseBoundStore<import('zustand').StoreApi<LiveOverlayState>>;
14
+ /** The live text for one message, or null when there is none. */
15
+ export declare function useLiveOverlayContent(messageId: string | null | undefined): string | null;
16
+ /** What the live renderer needs of the stream. `TurnStream` satisfies it. */
17
+ export interface LiveSource {
18
+ readonly live: LiveDeltaState;
19
+ onLive(listener: () => void): () => void;
20
+ endLive(): void;
21
+ }
22
+ export interface LiveRenderOptions {
23
+ stream: LiveSource;
24
+ conversationId: string;
25
+ /** The turn's own assistant message id: the only key this writes. */
26
+ messageId: string;
27
+ /**
28
+ * The bubble's text for these messages — the SAME builder the poll uses
29
+ * (`buildAssistantProgress` + `sanitizeAssistantResponse`), so the live text
30
+ * and the finished answer are made the same way.
31
+ */
32
+ build: (messages: AssistantRawMessage[], floor: number) => string;
33
+ /** Called once, when live text first exists for this turn (after arming). */
34
+ onFirstDelta?: () => void;
35
+ /** Called once, when the overlay first shows text. */
36
+ onFirstVisible?: () => void;
37
+ /** Minimum gap between live renders. Leading edge, with a trailing call. */
38
+ throttleMs?: number;
39
+ now?: () => number;
40
+ setTimer?: (run: () => void, ms: number) => unknown;
41
+ clearTimer?: (timer: unknown) => void;
42
+ /** Tests only: a store other than the shared one. */
43
+ overlay?: Pick<LiveOverlayState, "setLive" | "clearLive">;
44
+ }
45
+ export interface LiveRender {
46
+ /**
47
+ * Allow rendering, once the reply floor is known AND the prompt is sent
48
+ * (design rule 3). Frames that arrived earlier were only kept; they render
49
+ * now, if they are this turn's.
50
+ */
51
+ arm(floor: number): void;
52
+ /** The poll landed: re-merge its messages with the live text, at once. */
53
+ refresh(polled: readonly AssistantRawMessage[]): void;
54
+ /** Synchronous, idempotent. Detaches, cancels the throttle, drops the overlay. */
55
+ end(): void;
56
+ readonly armed: boolean;
57
+ readonly ended: boolean;
58
+ }
59
+ export declare const LIVE_RENDER_THROTTLE_MS = 100;
60
+ export declare function createLiveRender(options: LiveRenderOptions): LiveRender;
61
+ export {};
62
+ //# sourceMappingURL=liveOverlay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"liveOverlay.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/liveOverlay.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAEnD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,UAAU,gBAAgB;IACxB,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC;IACjE,OAAO,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9E,SAAS,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC;AAED,0EAA0E;AAC1E,eAAO,MAAM,cAAc,+EAyBxB,CAAC;AAEJ,iEAAiE;AACjE,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACnC,MAAM,GAAG,IAAI,CAIf;AAED,6EAA6E;AAC7E,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,MAAM,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;IACzC,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,UAAU,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,qEAAqE;IACrE,SAAS,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,KAAK,EAAE,CAAC,QAAQ,EAAE,mBAAmB,EAAE,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAClE,6EAA6E;IAC7E,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,sDAAsD;IACtD,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC;IACpD,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,qDAAqD;IACrD,OAAO,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,SAAS,GAAG,WAAW,CAAC,CAAC;CAC3D;AAED,MAAM,WAAW,UAAU;IACzB;;;;OAIG;IACH,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,0EAA0E;IAC1E,OAAO,CAAC,MAAM,EAAE,SAAS,mBAAmB,EAAE,GAAG,IAAI,CAAC;IACtD,kFAAkF;IAClF,GAAG,IAAI,IAAI,CAAC;IACZ,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AAED,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAE3C,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,GAAG,UAAU,CAkGvE"}
@@ -0,0 +1,64 @@
1
+ import { applyLiveDeltas as e, hasLiveText as t } from "./liveDeltas.js";
2
+ import { create as n } from "zustand";
3
+ //#region src/shared/assistant/liveOverlay.ts
4
+ var r = n()((e) => ({
5
+ byMessageId: {},
6
+ setLive: (t, n, r) => e((e) => {
7
+ let i = e.byMessageId[t];
8
+ return i && i.content === r && i.conversationId === n ? e : { byMessageId: {
9
+ ...e.byMessageId,
10
+ [t]: {
11
+ conversationId: n,
12
+ content: r
13
+ }
14
+ } };
15
+ }),
16
+ clearLive: (t) => e((e) => {
17
+ if (!(t in e.byMessageId)) return e;
18
+ let n = { ...e.byMessageId };
19
+ return delete n[t], { byMessageId: n };
20
+ })
21
+ }));
22
+ function i(e) {
23
+ return r((t) => e ? t.byMessageId[e]?.content ?? null : null);
24
+ }
25
+ var a = 100;
26
+ function o(n) {
27
+ let i = n.now ?? Date.now, a = n.setTimer ?? ((e, t) => setTimeout(e, t)), o = n.clearTimer ?? ((e) => {
28
+ clearTimeout(e);
29
+ }), s = n.overlay ?? r.getState(), c = n.throttleMs ?? 100, l = null, u = [], d = !1, f = null, p = -Infinity, m = "", h = !1, g = !1, _ = () => l === null ? "" : n.build(e(u, n.stream.live, l), l), v = () => {
30
+ h || l === null || t(n.stream.live) && _() !== "" && (h = !0, n.onFirstDelta?.());
31
+ }, y = () => {
32
+ if (f = null, d || l === null) return;
33
+ let e = _();
34
+ e === "" || e === m || (p = i(), m = e, s.setLive(n.messageId, n.conversationId, e), g || (g = !0, n.onFirstVisible?.()));
35
+ }, b = n.stream.onLive(() => {
36
+ if (d || l === null) return;
37
+ v();
38
+ let e = p + c - i();
39
+ if (e <= 0) {
40
+ f !== null && (o(f), f = null), y();
41
+ return;
42
+ }
43
+ f === null && (f = a(y, e));
44
+ });
45
+ return {
46
+ arm(e) {
47
+ d || l !== null || (l = e, v(), y());
48
+ },
49
+ refresh(e) {
50
+ u = e, !(d || l === null) && y();
51
+ },
52
+ end() {
53
+ d || (d = !0, f !== null && (o(f), f = null), b(), s.clearLive(n.messageId), n.stream.endLive());
54
+ },
55
+ get armed() {
56
+ return l !== null;
57
+ },
58
+ get ended() {
59
+ return d;
60
+ }
61
+ };
62
+ }
63
+ //#endregion
64
+ export { a as LIVE_RENDER_THROTTLE_MS, o as createLiveRender, r as useLiveOverlay, i as useLiveOverlayContent };
@@ -0,0 +1,48 @@
1
+ /**
2
+ * ★★ BOFF-7914 (speed S3): the completion fast path.
3
+ *
4
+ * A turn's completion is discovered by a GET of the session's messages — the
5
+ * poll — and only by it. Without a stream the poll is the whole mechanism.
6
+ * With one, the bridge's `session.idle` says the turn is over, and the question
7
+ * becomes how soon after it the poll can SEE that.
8
+ *
9
+ * Take the common case: a GET started just before the idle is still in flight.
10
+ * Its answer was read before the turn settled, so it will probably say "not
11
+ * done", and the loop would then sleep and issue another. Instead, the idle
12
+ * starts ONE extra GET at once, beside the one in flight. Then:
13
+ *
14
+ * - Snapshots are applied in START order. Whichever finishes first is applied;
15
+ * an OLDER snapshot that arrives after a newer one is discarded.
16
+ * - At most one extra request is outstanding, and at most two are started per
17
+ * turn. The cadence of an ordinary poll is unchanged.
18
+ * - A failed request is skipped when a newer one is still pending or has
19
+ * succeeded; it is thrown only when nothing newer can answer.
20
+ * - A snapshot says nothing by itself: the caller applies it exactly as it
21
+ * applies a snapshot without a stream. This module decides nothing about the
22
+ * turn.
23
+ */
24
+ export interface SnapshotPollerOptions {
25
+ /** Extra requests the idle fast path may start per turn. */
26
+ maxExtra?: number;
27
+ }
28
+ export interface SnapshotPoller<T> {
29
+ /**
30
+ * The next snapshot to apply. Starts a request when none is pending; when a
31
+ * newer request than the one that answered is pending, it stays pending for
32
+ * the next call (`hasPending`).
33
+ */
34
+ next(): Promise<T>;
35
+ /**
36
+ * The bridge said the turn is idle. If a request is in flight, start one
37
+ * extra now and return true; otherwise (or past the caps) return false and
38
+ * leave it to the next `next()`.
39
+ */
40
+ startExtra(): boolean;
41
+ /** A started request has not been applied yet: do not sleep before `next()`. */
42
+ hasPending(): boolean;
43
+ /** Requests started in all, for tests and for the timeline. */
44
+ readonly started: number;
45
+ readonly extraStarted: number;
46
+ }
47
+ export declare function createSnapshotPoller<T>(fetch: () => Promise<T>, options?: SnapshotPollerOptions): SnapshotPoller<T>;
48
+ //# sourceMappingURL=snapshotPoller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshotPoller.d.ts","sourceRoot":"","sources":["../../../src/shared/assistant/snapshotPoller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,MAAM,WAAW,qBAAqB;IACpC,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B;;;;OAIG;IACH,IAAI,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC;IACnB;;;;OAIG;IACH,UAAU,IAAI,OAAO,CAAC;IACtB,gFAAgF;IAChF,UAAU,IAAI,OAAO,CAAC;IACtB,+DAA+D;IAC/D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAUD,wBAAgB,oBAAoB,CAAC,CAAC,EACpC,KAAK,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACvB,OAAO,GAAE,qBAA0B,GAClC,cAAc,CAAC,CAAC,CAAC,CAoGnB"}
@@ -0,0 +1,58 @@
1
+ //#region src/shared/assistant/snapshotPoller.ts
2
+ function e(e, t = {}) {
3
+ let n = t.maxExtra ?? 2, r = [], i = 0, a = 0, o = null, s = () => {
4
+ let e = o;
5
+ o = null, e?.();
6
+ }, c = () => {
7
+ let t = {
8
+ seq: i += 1,
9
+ done: !1,
10
+ failed: !1,
11
+ value: void 0,
12
+ error: void 0
13
+ }, n;
14
+ try {
15
+ n = e();
16
+ } catch (e) {
17
+ n = Promise.reject(e);
18
+ }
19
+ return n.then((e) => {
20
+ t.value = e, t.done = !0, s();
21
+ }, (e) => {
22
+ t.failed = !0, t.error = e, t.done = !0, s();
23
+ }), r.push(t), t;
24
+ };
25
+ return {
26
+ async next() {
27
+ for (r.length === 0 && c();;) {
28
+ let e = r.filter((e) => e.done && !e.failed);
29
+ if (e.length > 0) {
30
+ let t = e.reduce((e, t) => t.seq > e.seq ? t : e);
31
+ return r = r.filter((e) => e.seq > t.seq && !(e.done && e.failed)), t.value;
32
+ }
33
+ let t = r.filter((e) => !e.done);
34
+ if (t.length === 0) {
35
+ let e = r.reduce((e, t) => t.seq > e.seq ? t : e);
36
+ throw r = [], e.error;
37
+ }
38
+ r = t, await new Promise((e) => {
39
+ o = e;
40
+ });
41
+ }
42
+ },
43
+ startExtra() {
44
+ return !r.some((e) => !e.done) || r.length >= 2 || a >= n ? !1 : (a += 1, c(), !0);
45
+ },
46
+ hasPending() {
47
+ return r.length > 0;
48
+ },
49
+ get started() {
50
+ return i;
51
+ },
52
+ get extraStarted() {
53
+ return a;
54
+ }
55
+ };
56
+ }
57
+ //#endregion
58
+ export { e as createSnapshotPoller };