@burdenoff/fe-libs 2026.1029.5 → 2026.1029.7
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.
- package/dist/shared/assistant/attachmentAccessCopy.js +1 -1
- package/dist/shared/assistant/index.d.ts +5 -0
- package/dist/shared/assistant/liveDeltas.d.ts +3 -0
- package/dist/shared/assistant/liveDeltas.js +17 -1
- package/dist/shared/assistant/liveOverlay.d.ts +4 -0
- package/dist/shared/assistant/liveOverlay.js +10 -1
- package/dist/shared/assistant/speech/appendSpeechQueue.d.ts +13 -0
- package/dist/shared/assistant/speech/appendSpeechQueue.js +75 -0
- package/dist/shared/assistant/speech/browserSpeechEngine.js +93 -46
- package/dist/shared/assistant/speech/hostedTtsSpeechEngine.js +173 -109
- package/dist/shared/assistant/speech/index.d.ts +1 -1
- package/dist/shared/assistant/speech/notifyCancellationSpeechEngine.js +53 -0
- package/dist/shared/assistant/speech/routingSpeechEngine.js +107 -23
- package/dist/shared/assistant/speech/speechFeed.d.ts +17 -2
- package/dist/shared/assistant/speech/speechFeed.js +35 -12
- package/dist/shared/assistant/speech/types.d.ts +20 -1
- package/dist/shared/assistant/turnTimeline.d.ts +3 -0
- package/dist/shared/assistant/turnTimeline.js +4 -1
- package/dist/shared/assistant/ui/AssistantChatArea.js +1410 -1393
- package/dist/shared/assistant/ui/AssistantSpeechProvider.js +351 -291
- package/dist/shared/assistant/ui/useVoiceSession.js +323 -288
- package/dist/shared/assistant/useAttachmentCommitter.js +46 -45
- package/dist/shared/assistant/voice/livePhraseSpeech.d.ts +14 -0
- package/dist/shared/assistant/voice/livePhraseSpeech.js +72 -0
- package/dist/shared/assistant/voice/phraseGate.d.ts +11 -0
- package/dist/shared/assistant/voice/phraseGate.js +74 -0
- package/dist/shared/assistant/voice/phrasePlayback.d.ts +9 -0
- package/dist/shared/assistant/voice/phrasePlayback.js +78 -0
- package/dist/shared/assistant/voice/phraseSpeechConfig.d.ts +5 -0
- package/dist/shared/assistant/voice/phraseSpeechConfig.js +10 -0
- package/dist/shared/assistant/voice/speakableText.d.ts +1 -0
- package/dist/shared/assistant/voice/speakableText.js +1 -1
- package/dist/shared/assistant/voice/voiceSession.d.ts +5 -0
- package/dist/shared/assistant/voice/voiceSession.js +17 -1
- package/dist/shared/providers/shell/AuthProvider.d.ts +2 -0
- package/dist/shared/providers/shell/AuthProvider.js +34 -31
- package/dist/shared-assistant.js +293 -288
- package/package.json +1 -1
|
@@ -365,5 +365,10 @@ export * from './avatar/live/LiveAvatarMinutes';
|
|
|
365
365
|
export * from './avatar/live/createLiveAvatarSeam';
|
|
366
366
|
export * from './avatar/live/avatarVoice';
|
|
367
367
|
export * from './promptDelivery';
|
|
368
|
+
export * from './speech/appendSpeechQueue';
|
|
369
|
+
export * from './voice/phraseSpeechConfig';
|
|
370
|
+
export * from './voice/phraseGate';
|
|
371
|
+
export * from './voice/livePhraseSpeech';
|
|
372
|
+
export * from './voice/phrasePlayback';
|
|
368
373
|
export * from './attachmentAccess';
|
|
369
374
|
export * from './attachmentAccessCopy';
|
|
@@ -19,6 +19,8 @@ export interface LivePartState {
|
|
|
19
19
|
readonly gapped: boolean;
|
|
20
20
|
/** A new generation began while the part was being written. */
|
|
21
21
|
readonly frozen: boolean;
|
|
22
|
+
/** S7: a tool began after this text part; it is no longer live narration. */
|
|
23
|
+
readonly toolAfter?: boolean;
|
|
22
24
|
}
|
|
23
25
|
export interface LiveMessageState {
|
|
24
26
|
readonly created?: number;
|
|
@@ -27,6 +29,7 @@ export interface LiveMessageState {
|
|
|
27
29
|
export interface LiveDeltaState {
|
|
28
30
|
/** +1 for every re-mint. */
|
|
29
31
|
readonly generation: number;
|
|
32
|
+
readonly toolIds?: ReadonlySet<string>;
|
|
30
33
|
readonly parts: ReadonlyMap<string, LivePartState>;
|
|
31
34
|
readonly messages: ReadonlyMap<string, LiveMessageState>;
|
|
32
35
|
}
|
|
@@ -109,7 +109,23 @@ function p(e, t) {
|
|
|
109
109
|
if (!n) return e;
|
|
110
110
|
switch (t.event) {
|
|
111
111
|
case "message.updated": return u(e, n);
|
|
112
|
-
case "message.part.updated":
|
|
112
|
+
case "message.part.updated": {
|
|
113
|
+
if (n.type === "text") return d(e, n);
|
|
114
|
+
if (n.type !== "tool") return e;
|
|
115
|
+
let t = a(n.id), r = a(n.messageID);
|
|
116
|
+
if (!t || !r || e.toolIds?.has(t)) return e;
|
|
117
|
+
if ((e.toolIds?.size ?? 0) >= 256) return c(e);
|
|
118
|
+
let i = new Map(e.parts);
|
|
119
|
+
for (let [e, t] of i) t.messageId === r && i.set(e, {
|
|
120
|
+
...t,
|
|
121
|
+
toolAfter: !0
|
|
122
|
+
});
|
|
123
|
+
return {
|
|
124
|
+
...e,
|
|
125
|
+
parts: i,
|
|
126
|
+
toolIds: new Set([...e.toolIds ?? [], t])
|
|
127
|
+
};
|
|
128
|
+
}
|
|
113
129
|
case "message.part.delta": return n.partType === "text" || n.partType === void 0 ? f(e, n) : e;
|
|
114
130
|
default: return e;
|
|
115
131
|
}
|
|
@@ -34,6 +34,10 @@ export interface LiveRenderOptions {
|
|
|
34
34
|
onFirstDelta?: () => void;
|
|
35
35
|
/** Called once, when the overlay first shows text. */
|
|
36
36
|
onFirstVisible?: () => void;
|
|
37
|
+
/** S7 reads validated live parts only AFTER this overlay write, never the poll text. */
|
|
38
|
+
/** Safety notifications precede throttling: a tool must cancel a hold timer now. */
|
|
39
|
+
onLiveState?: (live: LiveDeltaState, floor: number) => void;
|
|
40
|
+
onRendered?: (content: string, live: LiveDeltaState, floor: number) => void;
|
|
37
41
|
/** Minimum gap between live renders. Leading edge, with a trailing call. */
|
|
38
42
|
throttleMs?: number;
|
|
39
43
|
now?: () => number;
|
|
@@ -31,9 +31,18 @@ function o(n) {
|
|
|
31
31
|
}, y = () => {
|
|
32
32
|
if (f = null, d || l === null) return;
|
|
33
33
|
let e = _();
|
|
34
|
-
e
|
|
34
|
+
if (e !== "") {
|
|
35
|
+
e !== m && (p = i(), m = e, s.setLive(n.messageId, n.conversationId, e));
|
|
36
|
+
try {
|
|
37
|
+
n.onRendered?.(e, n.stream.live, l);
|
|
38
|
+
} catch {}
|
|
39
|
+
g || (g = !0, n.onFirstVisible?.());
|
|
40
|
+
}
|
|
35
41
|
}, b = n.stream.onLive(() => {
|
|
36
42
|
if (d || l === null) return;
|
|
43
|
+
try {
|
|
44
|
+
n.onLiveState?.(n.stream.live, l);
|
|
45
|
+
} catch {}
|
|
37
46
|
v();
|
|
38
47
|
let e = p + c - i();
|
|
39
48
|
if (e <= 0) {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { SpeechErrorReason, SpeechQueue, SpeechSpeakHandlers } from './types';
|
|
2
|
+
export declare const SPEECH_QUEUE_CAPACITY = 32;
|
|
3
|
+
export declare const SPEECH_QUEUE_TEXT_LIMIT = 16384;
|
|
4
|
+
export interface AppendSpeechPort<T> {
|
|
5
|
+
prepare(text: string, signal: AbortSignal): Promise<T>;
|
|
6
|
+
play(value: T, index: number, began: () => void): Promise<void>;
|
|
7
|
+
drain(): Promise<void>;
|
|
8
|
+
retract(fromIndex: number): void;
|
|
9
|
+
cancel(): void;
|
|
10
|
+
failed(cause: unknown): SpeechErrorReason;
|
|
11
|
+
}
|
|
12
|
+
/** Bounded reply queue: one playing/preparing piece and at most one prefetched. */
|
|
13
|
+
export declare function createAppendSpeechQueue<T>(port: AppendSpeechPort<T>, handlers?: SpeechSpeakHandlers): SpeechQueue;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
//#region src/shared/assistant/speech/appendSpeechQueue.ts
|
|
2
|
+
var e = 32, t = 16384;
|
|
3
|
+
function n(e, t = {}) {
|
|
4
|
+
let n = [], r = null, i = 0, a = !1, o = !1, s = !1, c = !1, l = !1, u = (t) => (t.ready || (t.ready = Promise.resolve().then(() => {
|
|
5
|
+
if (o || t.controller.signal.aborted) throw Error("speech cancelled");
|
|
6
|
+
return e.prepare(t.text, t.controller.signal);
|
|
7
|
+
}), t.ready.catch(() => {})), t.ready), d = () => {
|
|
8
|
+
r?.started && n[0] && u(n[0]);
|
|
9
|
+
}, f = (e) => {
|
|
10
|
+
e.withdrawn = !0, e.controller.abort();
|
|
11
|
+
}, p = () => {
|
|
12
|
+
o || (o = !0, r && f(r), n.forEach(f), n = [], e.cancel());
|
|
13
|
+
}, m = async () => {
|
|
14
|
+
if (!(s || o)) {
|
|
15
|
+
s = !0;
|
|
16
|
+
try {
|
|
17
|
+
for (; !o;) {
|
|
18
|
+
if (r = n.shift() ?? null, !r) {
|
|
19
|
+
if (await e.drain(), o) return;
|
|
20
|
+
if (n.length) continue;
|
|
21
|
+
a ? (o = !0, t.onEnd?.()) : l || (l = !0, t.onPause?.());
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
l = !1;
|
|
25
|
+
let i = r, s;
|
|
26
|
+
try {
|
|
27
|
+
s = await u(i);
|
|
28
|
+
} catch (e) {
|
|
29
|
+
if (i.withdrawn) continue;
|
|
30
|
+
throw e;
|
|
31
|
+
}
|
|
32
|
+
if (o) return;
|
|
33
|
+
if (!i.withdrawn) {
|
|
34
|
+
if (n[0] && u(n[0]), await e.play(s, i.index, () => {
|
|
35
|
+
o || i.withdrawn || i.started || (i.started = !0, c || (c = !0, t.onStart?.()), t.onChunkStart?.(i.index), d());
|
|
36
|
+
}), o || (await e.drain(), o)) return;
|
|
37
|
+
r = null, i.withdrawn || t.onChunkEnd?.(i.index);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
} catch (n) {
|
|
41
|
+
o || (p(), t.onError?.(e.failed(n)));
|
|
42
|
+
} finally {
|
|
43
|
+
s = !1;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
return {
|
|
48
|
+
append(e) {
|
|
49
|
+
if (o || a) return !1;
|
|
50
|
+
let t = e.filter((e) => e.trim().length > 0), s = [...n, ...r ? [r] : []];
|
|
51
|
+
if (s.length + t.length > 32 || s.reduce((e, t) => e + t.text.length, 0) + t.join("").length > 16384) return !1;
|
|
52
|
+
for (let e of t) n.push({
|
|
53
|
+
index: i++,
|
|
54
|
+
text: e,
|
|
55
|
+
controller: new AbortController(),
|
|
56
|
+
started: !1,
|
|
57
|
+
withdrawn: !1
|
|
58
|
+
});
|
|
59
|
+
return d(), m(), !0;
|
|
60
|
+
},
|
|
61
|
+
end() {
|
|
62
|
+
o || (a = !0, m());
|
|
63
|
+
},
|
|
64
|
+
retract() {
|
|
65
|
+
if (o) return;
|
|
66
|
+
let i = n;
|
|
67
|
+
n = [];
|
|
68
|
+
let a = r && !r.started ? r.index : i[0]?.index;
|
|
69
|
+
a !== void 0 && e.retract(a), r && !r.started && i.push(r), i.forEach(f), i.length && t.onRetract?.(i.map((e) => e.index));
|
|
70
|
+
},
|
|
71
|
+
cancel: p
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
//#endregion
|
|
75
|
+
export { e as SPEECH_QUEUE_CAPACITY, t as SPEECH_QUEUE_TEXT_LIMIT, n as createAppendSpeechQueue };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createAppendSpeechQueue as e } from "./appendSpeechQueue.js";
|
|
2
|
+
import { setDeviceVoice as t } from "../voice/handsfree/playbackReference.js";
|
|
2
3
|
//#region src/shared/assistant/speech/browserSpeechEngine.ts
|
|
3
|
-
function
|
|
4
|
+
function n() {
|
|
4
5
|
if (typeof window > "u") return null;
|
|
5
6
|
try {
|
|
6
7
|
return window.speechSynthesis ?? null;
|
|
@@ -8,10 +9,10 @@ function t() {
|
|
|
8
9
|
return null;
|
|
9
10
|
}
|
|
10
11
|
}
|
|
11
|
-
function
|
|
12
|
+
function r() {
|
|
12
13
|
return typeof window < "u" && typeof window.SpeechSynthesisUtterance == "function";
|
|
13
14
|
}
|
|
14
|
-
function
|
|
15
|
+
function i(e) {
|
|
15
16
|
switch (e) {
|
|
16
17
|
case "canceled":
|
|
17
18
|
case "cancelled":
|
|
@@ -23,7 +24,7 @@ function r(e) {
|
|
|
23
24
|
default: return "unknown";
|
|
24
25
|
}
|
|
25
26
|
}
|
|
26
|
-
function
|
|
27
|
+
function a(e, t) {
|
|
27
28
|
if (!t) return null;
|
|
28
29
|
let n;
|
|
29
30
|
try {
|
|
@@ -33,85 +34,131 @@ function i(e, t) {
|
|
|
33
34
|
}
|
|
34
35
|
return n.find((e) => e === t) ?? n.find((e) => e.name === t.name && e.lang === t.lang) ?? null;
|
|
35
36
|
}
|
|
36
|
-
var
|
|
37
|
+
var o = 0, s = null, c = {
|
|
37
38
|
id: "browser-speech-synthesis",
|
|
38
39
|
isSupported() {
|
|
39
|
-
return
|
|
40
|
+
return n() !== null && r();
|
|
40
41
|
},
|
|
41
42
|
listVoices() {
|
|
42
43
|
try {
|
|
43
|
-
return
|
|
44
|
+
return n()?.getVoices() ?? [];
|
|
44
45
|
} catch {
|
|
45
46
|
return [];
|
|
46
47
|
}
|
|
47
48
|
},
|
|
48
49
|
subscribeVoices(e) {
|
|
49
|
-
let
|
|
50
|
-
if (!
|
|
50
|
+
let t = n();
|
|
51
|
+
if (!t?.addEventListener) return () => {};
|
|
51
52
|
let r = () => e();
|
|
52
|
-
return
|
|
53
|
+
return t.addEventListener("voiceschanged", r), () => t.removeEventListener("voiceschanged", r);
|
|
53
54
|
},
|
|
54
|
-
speak(
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
speak(e, c, l = {}) {
|
|
56
|
+
s?.cancel(), s = null;
|
|
57
|
+
let u = n();
|
|
58
|
+
if (!u || !r()) {
|
|
59
|
+
l.onError?.("unsupported");
|
|
58
60
|
return;
|
|
59
61
|
}
|
|
60
|
-
let
|
|
61
|
-
if (
|
|
62
|
-
|
|
62
|
+
let d = e.filter((e) => e.trim().length > 0);
|
|
63
|
+
if (d.length === 0) {
|
|
64
|
+
l.onEnd?.();
|
|
63
65
|
return;
|
|
64
66
|
}
|
|
65
|
-
|
|
66
|
-
let
|
|
67
|
+
o += 1;
|
|
68
|
+
let f = o;
|
|
67
69
|
try {
|
|
68
|
-
|
|
70
|
+
u.cancel();
|
|
69
71
|
} catch {}
|
|
70
|
-
let
|
|
71
|
-
|
|
72
|
-
if (
|
|
73
|
-
let
|
|
72
|
+
let p = a(u, c.voice);
|
|
73
|
+
t(!0), d.forEach((e, n) => {
|
|
74
|
+
if (f !== o) return;
|
|
75
|
+
let r;
|
|
74
76
|
try {
|
|
75
|
-
|
|
77
|
+
r = new window.SpeechSynthesisUtterance(e), r.lang = c.lang, p && (r.voice = p), c.rate !== void 0 && (r.rate = c.rate);
|
|
76
78
|
} catch {
|
|
77
|
-
|
|
79
|
+
o += 1;
|
|
78
80
|
try {
|
|
79
|
-
|
|
81
|
+
u.cancel();
|
|
80
82
|
} catch {}
|
|
81
|
-
|
|
83
|
+
l.onError?.("unknown");
|
|
82
84
|
return;
|
|
83
85
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
},
|
|
87
|
-
if (
|
|
88
|
-
|
|
86
|
+
r.onstart = () => {
|
|
87
|
+
f === o && (n === 0 && l.onStart?.(), l.onChunkStart?.(n));
|
|
88
|
+
}, r.onerror = (e) => {
|
|
89
|
+
if (f === o) {
|
|
90
|
+
t(!1), o += 1;
|
|
89
91
|
try {
|
|
90
|
-
|
|
92
|
+
u.cancel();
|
|
91
93
|
} catch {}
|
|
92
|
-
|
|
94
|
+
l.onError?.(i(e.error));
|
|
93
95
|
}
|
|
94
|
-
}, n ===
|
|
95
|
-
|
|
96
|
+
}, n === d.length - 1 && (r.onend = () => {
|
|
97
|
+
f === o && (t(!1), l.onEnd?.());
|
|
96
98
|
});
|
|
97
99
|
try {
|
|
98
|
-
|
|
100
|
+
u.speak(r);
|
|
99
101
|
} catch {
|
|
100
|
-
if (
|
|
101
|
-
|
|
102
|
+
if (f !== o) return;
|
|
103
|
+
o += 1, t(!1);
|
|
102
104
|
try {
|
|
103
|
-
|
|
105
|
+
u.cancel();
|
|
104
106
|
} catch {}
|
|
105
|
-
|
|
107
|
+
l.onError?.("unknown");
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
},
|
|
111
|
+
open(o, l = {}) {
|
|
112
|
+
c.cancel();
|
|
113
|
+
let u = n(), d = -1, f = null, p = () => {
|
|
114
|
+
f?.(), f = null, t(!1);
|
|
115
|
+
try {
|
|
116
|
+
u?.cancel();
|
|
117
|
+
} catch {}
|
|
118
|
+
}, m = e({
|
|
119
|
+
prepare: async (e) => e,
|
|
120
|
+
play: (e, n, s) => new Promise((c, l) => {
|
|
121
|
+
if (!u || !r()) {
|
|
122
|
+
l({ reason: "unsupported" });
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
d = n;
|
|
126
|
+
let p = !1, m = (e) => {
|
|
127
|
+
p || (p = !0, t(!1), e ? l({ reason: e }) : c());
|
|
128
|
+
};
|
|
129
|
+
f = () => m();
|
|
130
|
+
try {
|
|
131
|
+
let n = new window.SpeechSynthesisUtterance(e);
|
|
132
|
+
n.lang = o.lang;
|
|
133
|
+
let r = a(u, o.voice);
|
|
134
|
+
r && (n.voice = r), o.rate !== void 0 && (n.rate = o.rate), n.onstart = () => {
|
|
135
|
+
p || s();
|
|
136
|
+
}, n.onend = () => m(), n.onerror = (e) => m(i(e.error)), t(!0), u.speak(n);
|
|
137
|
+
} catch {
|
|
138
|
+
m("unknown");
|
|
139
|
+
}
|
|
140
|
+
}),
|
|
141
|
+
drain: async () => {},
|
|
142
|
+
retract: (e) => {
|
|
143
|
+
d >= e && p();
|
|
144
|
+
},
|
|
145
|
+
cancel: p,
|
|
146
|
+
failed: (e) => e?.reason ?? "unknown"
|
|
147
|
+
}, {
|
|
148
|
+
...l,
|
|
149
|
+
onEnd: () => {
|
|
150
|
+
s === m && (s = null), l.onEnd?.();
|
|
106
151
|
}
|
|
107
152
|
});
|
|
153
|
+
return s = m, m;
|
|
108
154
|
},
|
|
109
155
|
cancel() {
|
|
110
|
-
|
|
156
|
+
let e = s;
|
|
157
|
+
s = null, e?.cancel(), o += 1, t(!1);
|
|
111
158
|
try {
|
|
112
|
-
|
|
159
|
+
n()?.cancel();
|
|
113
160
|
} catch {}
|
|
114
161
|
}
|
|
115
162
|
};
|
|
116
163
|
//#endregion
|
|
117
|
-
export {
|
|
164
|
+
export { c as browserSpeechEngine };
|