@pagelines/sdk 1.0.822 → 1.0.824
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/AgentWrap.js +136 -96
- package/dist/AgentWrap.js.map +1 -1
- package/dist/agent/voice/provider.d.ts +14 -1
- package/dist/agent/voice/providers/livekit/provider.d.ts +7 -2
- package/dist/agent/voice/voice-session-client.d.ts +12 -6
- package/dist/agent.js +74 -53
- package/dist/agent.js.map +1 -1
- package/dist/contract.js +1 -0
- package/dist/contract.js.map +1 -1
- package/dist/provider.js +4 -1
- package/dist/provider.js.map +1 -1
- package/dist/provider2.js +1 -1
- package/dist/provider3.js +29 -14
- package/dist/provider3.js.map +1 -1
- package/dist/sdk.css +1 -1
- package/package.json +1 -1
|
@@ -6,19 +6,32 @@ export interface VoiceLevelEvent {
|
|
|
6
6
|
/** Speech-spectrum energies, low pitch first. */
|
|
7
7
|
bands?: readonly number[];
|
|
8
8
|
}
|
|
9
|
+
/** One speech/noise boundary shared by audible UI state and work-cue ducking. */
|
|
10
|
+
export declare function isVoiceAudible(level: number): boolean;
|
|
9
11
|
export interface VoiceSessionError {
|
|
10
12
|
code: string;
|
|
11
13
|
message: string;
|
|
12
14
|
}
|
|
13
15
|
export type VoiceDisconnectCause = 'agent' | 'error' | 'network' | 'unknown';
|
|
16
|
+
/**
|
|
17
|
+
* Who the transport says is talking. Raw energy is not a speech signal — room
|
|
18
|
+
* tone and the speaker's own playback both read as audible — so ducking,
|
|
19
|
+
* tone, and which meter the surface follows come from here.
|
|
20
|
+
*/
|
|
21
|
+
export interface VoiceSpeakingState {
|
|
22
|
+
user: boolean;
|
|
23
|
+
agent: boolean;
|
|
24
|
+
}
|
|
14
25
|
export interface VoiceProviderClient {
|
|
15
26
|
connect: (handlers: {
|
|
16
27
|
onDisconnected: (cause: VoiceDisconnectCause) => void;
|
|
17
28
|
onError: (error: VoiceSessionError) => void;
|
|
18
29
|
onThinkingChange?: (thinking: boolean) => void;
|
|
30
|
+
onSpeakingChange?: (state: VoiceSpeakingState) => void;
|
|
19
31
|
}) => Promise<void>;
|
|
20
32
|
disconnect: () => Promise<void>;
|
|
21
|
-
|
|
33
|
+
/** Loudest source by default; `prefer` pins a meter while someone is known to be speaking. */
|
|
34
|
+
sampleLevel: (prefer?: VoiceLevelEvent['source']) => VoiceLevelEvent | undefined;
|
|
22
35
|
/** Self-mute without ending the live session. */
|
|
23
36
|
setMuted?: (muted: boolean) => Promise<void>;
|
|
24
37
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { VoiceSessionMint } from '@pagelines/core';
|
|
2
|
-
import { VoiceProviderClient } from '../../provider';
|
|
2
|
+
import { VoiceLevelEvent, VoiceProviderClient } from '../../provider';
|
|
3
3
|
type LiveKitMint = Extract<VoiceSessionMint, {
|
|
4
4
|
provider: 'livekit';
|
|
5
5
|
}>;
|
|
@@ -40,6 +40,10 @@ export declare class LiveKitVoiceProvider implements VoiceProviderClient {
|
|
|
40
40
|
private levelSources;
|
|
41
41
|
private attachedElements;
|
|
42
42
|
private closing;
|
|
43
|
+
private userSpeaking;
|
|
44
|
+
private agentActiveSpeaker;
|
|
45
|
+
private agentStateSpeaking;
|
|
46
|
+
private lastSpeaking?;
|
|
43
47
|
constructor(mint: LiveKitMint, deps?: {
|
|
44
48
|
createRoom?: () => VoiceRoom;
|
|
45
49
|
createAnalyser?: (track: unknown) => VoiceLevelAnalyser;
|
|
@@ -47,7 +51,8 @@ export declare class LiveKitVoiceProvider implements VoiceProviderClient {
|
|
|
47
51
|
connect(handlers: Parameters<VoiceProviderClient['connect']>[0]): Promise<void>;
|
|
48
52
|
disconnect(): Promise<void>;
|
|
49
53
|
setMuted(muted: boolean): Promise<void>;
|
|
50
|
-
sampleLevel(): ReturnType<VoiceProviderClient['sampleLevel']>;
|
|
54
|
+
sampleLevel(prefer?: VoiceLevelEvent['source']): ReturnType<VoiceProviderClient['sampleLevel']>;
|
|
55
|
+
private publishSpeaking;
|
|
51
56
|
private waitForAgentReady;
|
|
52
57
|
private analyserFor;
|
|
53
58
|
private watchMicLevel;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Ref } from 'vue';
|
|
2
|
-
import { CreateVoiceProviderClient, VoiceLevelEvent, VoiceSessionError } from './provider';
|
|
2
|
+
import { CreateVoiceProviderClient, VoiceLevelEvent, VoiceSessionError, VoiceSpeakingState } from './provider';
|
|
3
3
|
import { SettingsObject } from '@pagelines/core';
|
|
4
|
-
export type { VoiceLevelEvent, VoiceSessionError } from './provider';
|
|
5
|
-
export { VOICE_SPECTRUM_BANDS, voiceSpectrum } from './provider';
|
|
4
|
+
export type { VoiceLevelEvent, VoiceSessionError, VoiceSpeakingState } from './provider';
|
|
5
|
+
export { isVoiceAudible, VOICE_SPECTRUM_BANDS, voiceSpectrum } from './provider';
|
|
6
6
|
export type VoiceSessionClientState = 'idle' | 'minting' | 'connecting' | 'live' | 'ended';
|
|
7
7
|
export type VoiceChimeKind = 'start' | 'end';
|
|
8
8
|
export interface VoiceWorkStatus {
|
|
@@ -20,6 +20,7 @@ export interface VoiceClientHandlers {
|
|
|
20
20
|
onLevel?: (event: VoiceLevelEvent) => void;
|
|
21
21
|
onError?: (error: VoiceSessionError) => void;
|
|
22
22
|
onThinkingChange?: (thinking: boolean) => void;
|
|
23
|
+
onSpeakingChange?: (state: VoiceSpeakingState) => void;
|
|
23
24
|
/** Fire-and-forget latency phases for product observability. */
|
|
24
25
|
onMetric?: (metric: VoiceMetric) => void;
|
|
25
26
|
onWorkChange?: (work: VoiceWorkStatus) => void;
|
|
@@ -28,6 +29,8 @@ export interface VoiceSessionClientSettings extends VoiceClientHandlers, Record<
|
|
|
28
29
|
agentId: string;
|
|
29
30
|
orgId: string;
|
|
30
31
|
conversationId?: string;
|
|
32
|
+
/** Last message already loaded by the host; the work stream starts after it. */
|
|
33
|
+
latestSequence?: string;
|
|
31
34
|
apiBase?: string;
|
|
32
35
|
isDev?: boolean;
|
|
33
36
|
token?: string;
|
|
@@ -48,8 +51,8 @@ export declare class VoiceSessionClient extends SettingsObject<VoiceSessionClien
|
|
|
48
51
|
readonly state: Ref<VoiceSessionClientState>;
|
|
49
52
|
readonly isMuted: Ref<boolean>;
|
|
50
53
|
private provider?;
|
|
51
|
-
private
|
|
52
|
-
private
|
|
54
|
+
private chime?;
|
|
55
|
+
private workCue?;
|
|
53
56
|
private generation;
|
|
54
57
|
private levelTimer;
|
|
55
58
|
private startAtMs;
|
|
@@ -60,7 +63,7 @@ export declare class VoiceSessionClient extends SettingsObject<VoiceSessionClien
|
|
|
60
63
|
private workAbort?;
|
|
61
64
|
private workState;
|
|
62
65
|
private workCuePlaying;
|
|
63
|
-
private
|
|
66
|
+
private speaking;
|
|
64
67
|
constructor(settings: VoiceSessionClientSettings);
|
|
65
68
|
start(): Promise<void>;
|
|
66
69
|
end(): Promise<void>;
|
|
@@ -77,8 +80,11 @@ export declare class VoiceSessionClient extends SettingsObject<VoiceSessionClien
|
|
|
77
80
|
private startLevelTimer;
|
|
78
81
|
private authHeaders;
|
|
79
82
|
private startWorkStream;
|
|
83
|
+
private setSpeaking;
|
|
84
|
+
/** Duck on speech, not on energy: room tone kept the loop from ever starting. */
|
|
80
85
|
private updateWorkCue;
|
|
81
86
|
private setWorkCue;
|
|
87
|
+
private playChime;
|
|
82
88
|
private post;
|
|
83
89
|
private mintSession;
|
|
84
90
|
private toSessionError;
|
package/dist/agent.js
CHANGED
|
@@ -2,17 +2,17 @@ import "./rolldown-runtime.js";
|
|
|
2
2
|
import { c as e, s as t } from "./sdkClient.js";
|
|
3
3
|
import { a as n, h as r, m as i, n as a, p as o, r as s, t as c } from "./AgentWrap.js";
|
|
4
4
|
import { n as l, t as u } from "./AgentProvider.js";
|
|
5
|
-
import {
|
|
6
|
-
import { SettingsObject as
|
|
7
|
-
import { Fragment as
|
|
5
|
+
import { n as d, t as f } from "./provider.js";
|
|
6
|
+
import { SettingsObject as p, readChatEventStream as m, zVoiceSessionMint as h } from "@pagelines/core";
|
|
7
|
+
import { Fragment as g, createBlock as _, createCommentVNode as v, createElementBlock as y, createElementVNode as b, createVNode as x, defineComponent as S, nextTick as C, normalizeClass as w, normalizeStyle as T, openBlock as E, ref as D, renderList as O, watch as k, withCtx as A } from "vue";
|
|
8
8
|
//#region agent/ui/AgentWidget.vue?vue&type=script&setup=true&lang.ts
|
|
9
|
-
var
|
|
9
|
+
var j = {
|
|
10
10
|
key: 0,
|
|
11
11
|
class: "relative h-full w-full"
|
|
12
|
-
},
|
|
12
|
+
}, M = { class: "group relative h-full w-full rounded-3xl overflow-hidden shadow-lg transition-all duration-300 ease-[cubic-bezier(0.25,1,0.33,1)] hover:shadow-2xl hover:translate-y-[-1px] hover:brightness-110 active:scale-[1.06] active:-translate-y-0.5 active:duration-100" }, N = ["src", "alt"], P = {
|
|
13
13
|
key: 0,
|
|
14
14
|
class: "absolute top-0.5 right-0.5"
|
|
15
|
-
},
|
|
15
|
+
}, F = /* @__PURE__ */ S({
|
|
16
16
|
__name: "AgentWidget",
|
|
17
17
|
props: {
|
|
18
18
|
sdk: {},
|
|
@@ -22,12 +22,12 @@ var A = {
|
|
|
22
22
|
position: {}
|
|
23
23
|
},
|
|
24
24
|
setup(e, { expose: t }) {
|
|
25
|
-
let n = e, r =
|
|
25
|
+
let n = e, r = D(!1), i = D(!1);
|
|
26
26
|
function toggle() {
|
|
27
27
|
r.value = !r.value;
|
|
28
28
|
}
|
|
29
|
-
|
|
30
|
-
e ? (await
|
|
29
|
+
k(r, async (e) => {
|
|
30
|
+
e ? (await C(), setTimeout(() => {
|
|
31
31
|
i.value = !0;
|
|
32
32
|
}, 400)) : i.value = !1;
|
|
33
33
|
});
|
|
@@ -44,29 +44,29 @@ var A = {
|
|
|
44
44
|
toggle,
|
|
45
45
|
open,
|
|
46
46
|
close
|
|
47
|
-
}), (t, a) => (
|
|
47
|
+
}), (t, a) => (E(), _(c, {
|
|
48
48
|
sdk: e.sdk,
|
|
49
49
|
handle: e.handle,
|
|
50
50
|
context: e.context,
|
|
51
51
|
"first-message": e.firstMessage
|
|
52
52
|
}, {
|
|
53
|
-
default:
|
|
53
|
+
default: A(({ agent: t, sdk: o }) => [t ? (E(), y("div", {
|
|
54
54
|
key: 0,
|
|
55
|
-
class:
|
|
56
|
-
}, [
|
|
57
|
-
class:
|
|
58
|
-
style:
|
|
55
|
+
class: w(["fixed z-[999999] pointer-events-auto", [n.position === "bottom-left" ? "bottom-6 left-6" : n.position === "top-right" ? "top-6 right-6" : n.position === "top-left" ? "top-6 left-6" : "bottom-6 right-6"]])
|
|
56
|
+
}, [b("div", {
|
|
57
|
+
class: w(["transition-all duration-500 ease-[cubic-bezier(0.25,1,0.33,1)] transform-gpu", [r.value ? "widget-expanded w-96 h-[600px] max-w-[calc(100vw-48px)] max-h-[calc(100vh-48px)] rounded-3xl opacity-100 scale-100" : "widget-button w-[80px] h-[80px] opacity-100 scale-100 flex items-center justify-center cursor-pointer"]]),
|
|
58
|
+
style: T({ "transform-origin": n.position === "bottom-left" ? "bottom left" : n.position === "top-right" ? "top right" : n.position === "top-left" ? "top left" : "bottom right" }),
|
|
59
59
|
onClick: a[0] || (a[0] = (e) => r.value ? void 0 : toggle())
|
|
60
|
-
}, [r.value ?
|
|
60
|
+
}, [r.value ? v("", !0) : (E(), y("div", j, [b("div", M, [b("img", {
|
|
61
61
|
src: t.avatarUrl.value,
|
|
62
62
|
alt: `${t.displayName.value} assistant`,
|
|
63
63
|
class: "h-full w-full object-cover pointer-events-none",
|
|
64
64
|
width: "80",
|
|
65
65
|
height: "80"
|
|
66
|
-
}, null, 8,
|
|
66
|
+
}, null, 8, N), a[1] || (a[1] = b("div", { class: "absolute inset-0 pointer-events-none bg-gradient-to-br from-transparent via-black/10 to-black/40 opacity-60 transition-opacity duration-300 group-hover:opacity-40" }, null, -1))]), t.state.value.lifecycle === "running" ? (E(), y("div", P, [...a[2] || (a[2] = [b("div", {
|
|
67
67
|
class: "size-3 bg-green-500 rounded-full ring-2 ring-white absolute animate-ping",
|
|
68
68
|
style: { "animation-duration": "3s" }
|
|
69
|
-
}, null, -1),
|
|
69
|
+
}, null, -1), b("div", { class: "size-3 bg-green-500 rounded-full ring-2 ring-white" }, null, -1)])])) : v("", !0)])), r.value && t ? (E(), _(l, {
|
|
70
70
|
key: 1,
|
|
71
71
|
class: "rounded-3xl shadow-2xl border border-white/10",
|
|
72
72
|
sdk: o,
|
|
@@ -82,7 +82,7 @@ var A = {
|
|
|
82
82
|
"context",
|
|
83
83
|
"first-message",
|
|
84
84
|
"is-active"
|
|
85
|
-
])) :
|
|
85
|
+
])) : v("", !0)], 6)], 2)) : v("", !0)]),
|
|
86
86
|
_: 1
|
|
87
87
|
}, 8, [
|
|
88
88
|
"sdk",
|
|
@@ -91,25 +91,25 @@ var A = {
|
|
|
91
91
|
"first-message"
|
|
92
92
|
]));
|
|
93
93
|
}
|
|
94
|
-
}),
|
|
94
|
+
}), I = ["data-sender"], L = /* @__PURE__ */ S({
|
|
95
95
|
__name: "ElAgentChatPreview",
|
|
96
96
|
props: {
|
|
97
97
|
messages: {},
|
|
98
98
|
variant: {}
|
|
99
99
|
},
|
|
100
100
|
setup(e) {
|
|
101
|
-
return (t, r) => (
|
|
102
|
-
class:
|
|
101
|
+
return (t, r) => (E(), y("div", {
|
|
102
|
+
class: w(["@container/chat-preview flex flex-col gap-3", e.variant === "dark" ? "text-white" : "text-slate-950"]),
|
|
103
103
|
"data-test": "agent-chat-preview"
|
|
104
|
-
}, [(
|
|
104
|
+
}, [(E(!0), y(g, null, O(e.messages, (t, r) => (E(), y("div", {
|
|
105
105
|
key: `${t.sender}-${r}`,
|
|
106
|
-
class:
|
|
106
|
+
class: w(["flex", t.sender === "user" ? "justify-end" : "justify-start"]),
|
|
107
107
|
"data-test": "agent-chat-preview-message",
|
|
108
108
|
"data-sender": t.sender
|
|
109
|
-
}, [
|
|
109
|
+
}, [b("div", { class: w(["max-w-[88%] rounded-2xl px-4 py-3 text-sm shadow-sm @sm/chat-preview:max-w-[78%]", t.sender === "user" ? "bg-slate-950 text-white" : e.variant === "dark" ? "border border-white/10 bg-white/10 text-white" : "border border-slate-200 bg-white text-slate-950"]) }, [x(n, {
|
|
110
110
|
text: t.text,
|
|
111
111
|
inverted: t.sender === "user" || e.variant === "dark"
|
|
112
|
-
}, null, 8, ["text", "inverted"])], 2)], 10,
|
|
112
|
+
}, null, 8, ["text", "inverted"])], 2)], 10, I))), 128))], 2));
|
|
113
113
|
}
|
|
114
114
|
});
|
|
115
115
|
//#endregion
|
|
@@ -151,14 +151,14 @@ function reduceVoiceWorkEvent(e, t) {
|
|
|
151
151
|
}
|
|
152
152
|
//#endregion
|
|
153
153
|
//#region agent/voice/voice-session-client.ts
|
|
154
|
-
var
|
|
154
|
+
var R = {
|
|
155
155
|
start: "/audio/start-call.mp3",
|
|
156
156
|
end: "/audio/end-call.mp3"
|
|
157
|
-
},
|
|
157
|
+
}, z = .7, B = 50, V = 15e3;
|
|
158
158
|
function createBrowserVoiceChimePlayer(e) {
|
|
159
|
-
let t = Object.fromEntries(Object.entries(
|
|
159
|
+
let t = Object.fromEntries(Object.entries(R).map(([t, n]) => {
|
|
160
160
|
let r = new Audio(`${e}${n}`);
|
|
161
|
-
return r.preload = "auto", r.volume =
|
|
161
|
+
return r.preload = "auto", r.volume = z, [t, r];
|
|
162
162
|
}));
|
|
163
163
|
return (e) => {
|
|
164
164
|
t[e].currentTime = 0, t[e].play().catch(() => {});
|
|
@@ -174,9 +174,12 @@ function createBrowserVoiceWorkCue(e) {
|
|
|
174
174
|
t.pause(), t.currentTime = 0;
|
|
175
175
|
};
|
|
176
176
|
}
|
|
177
|
-
var
|
|
178
|
-
constructor(
|
|
179
|
-
super("VoiceSessionClient",
|
|
177
|
+
var VoiceSessionClient = class extends p {
|
|
178
|
+
constructor(e) {
|
|
179
|
+
super("VoiceSessionClient", e), t(this, "state", D("idle")), t(this, "isMuted", D(!1)), t(this, "provider", void 0), t(this, "chime", void 0), t(this, "workCue", void 0), t(this, "generation", 0), t(this, "levelTimer", void 0), t(this, "startAtMs", 0), t(this, "liveAtMs", 0), t(this, "firstPlaybackEmitted", !1), t(this, "mutePending", !1), t(this, "conversationId", void 0), t(this, "workAbort", void 0), t(this, "workState", createVoiceWorkState()), t(this, "workCuePlaying", !1), t(this, "speaking", {
|
|
180
|
+
user: !1,
|
|
181
|
+
agent: !1
|
|
182
|
+
}), this.chime = e.playChime, this.workCue = e.setWorkCue;
|
|
180
183
|
}
|
|
181
184
|
async start() {
|
|
182
185
|
if (this.state.value !== "idle") return;
|
|
@@ -197,10 +200,10 @@ var V = .08, H = .08, VoiceSessionClient = class extends f {
|
|
|
197
200
|
async end() {
|
|
198
201
|
if (this.state.value === "idle" || this.state.value === "ended") return;
|
|
199
202
|
let e = this.state.value === "live";
|
|
200
|
-
this.generation++, e && this.
|
|
203
|
+
this.generation++, e && this.playChime("end"), this.setState("ended"), await this.teardown();
|
|
201
204
|
}
|
|
202
205
|
async connect(e) {
|
|
203
|
-
let { mint: t, generation: n } = e, r = await (this.settings.createProvider ??
|
|
206
|
+
let { mint: t, generation: n } = e, r = await (this.settings.createProvider ?? f)(t);
|
|
204
207
|
if (n !== this.generation) {
|
|
205
208
|
await r.disconnect().catch(() => {});
|
|
206
209
|
return;
|
|
@@ -210,7 +213,7 @@ var V = .08, H = .08, VoiceSessionClient = class extends f {
|
|
|
210
213
|
onDisconnected: (e) => {
|
|
211
214
|
if (!(n !== this.generation || this.provider !== r)) {
|
|
212
215
|
if (this.state.value === "live" && e === "agent") {
|
|
213
|
-
this.generation++, this.
|
|
216
|
+
this.generation++, this.playChime("end"), this.setState("ended"), this.teardown();
|
|
214
217
|
return;
|
|
215
218
|
}
|
|
216
219
|
this.fail({
|
|
@@ -224,11 +227,14 @@ var V = .08, H = .08, VoiceSessionClient = class extends f {
|
|
|
224
227
|
},
|
|
225
228
|
onThinkingChange: (e) => {
|
|
226
229
|
n === this.generation && this.provider === r && this.settings.onThinkingChange?.(e);
|
|
230
|
+
},
|
|
231
|
+
onSpeakingChange: (e) => {
|
|
232
|
+
n === this.generation && this.provider === r && this.setSpeaking(e);
|
|
227
233
|
}
|
|
228
234
|
}), a;
|
|
229
235
|
try {
|
|
230
236
|
await Promise.race([i, new Promise((e, t) => {
|
|
231
|
-
a = setTimeout(() => t(Object.assign(/* @__PURE__ */ Error("Voice connection timed out."), { code: "VOICE_CONNECT_TIMEOUT" })),
|
|
237
|
+
a = setTimeout(() => t(Object.assign(/* @__PURE__ */ Error("Voice connection timed out."), { code: "VOICE_CONNECT_TIMEOUT" })), V);
|
|
232
238
|
})]);
|
|
233
239
|
} catch (e) {
|
|
234
240
|
if (i.then(() => r.disconnect()).catch(() => {}), n !== this.generation || this.provider !== r) return;
|
|
@@ -237,7 +243,7 @@ var V = .08, H = .08, VoiceSessionClient = class extends f {
|
|
|
237
243
|
} finally {
|
|
238
244
|
a && clearTimeout(a);
|
|
239
245
|
}
|
|
240
|
-
n !== this.generation || this.provider !== r || (this.startLevelTimer(r, n), this.liveAtMs = Date.now(), this.setState("live"), this.updateWorkCue(), this.emitMetric("voice.ready", this.liveAtMs - this.startAtMs), this.
|
|
246
|
+
n !== this.generation || this.provider !== r || (this.startLevelTimer(r, n), this.liveAtMs = Date.now(), this.setState("live"), this.updateWorkCue(), this.emitMetric("voice.ready", this.liveAtMs - this.startAtMs), this.playChime("start"));
|
|
241
247
|
}
|
|
242
248
|
get canSendUserMessage() {
|
|
243
249
|
return this.state.value === "live" && !!this.provider?.sendUserMessage;
|
|
@@ -252,7 +258,10 @@ var V = .08, H = .08, VoiceSessionClient = class extends f {
|
|
|
252
258
|
let t = this.generation, n = !this.isMuted.value;
|
|
253
259
|
this.mutePending = !0;
|
|
254
260
|
try {
|
|
255
|
-
return await e.setMuted(n), t !== this.generation || this.provider !== e || this.state.value !== "live" ? void 0 : (this.isMuted.value = n, n
|
|
261
|
+
return await e.setMuted(n), t !== this.generation || this.provider !== e || this.state.value !== "live" ? void 0 : (this.isMuted.value = n, n && this.speaking.user && this.setSpeaking({
|
|
262
|
+
...this.speaking,
|
|
263
|
+
user: !1
|
|
264
|
+
}), n);
|
|
256
265
|
} catch {
|
|
257
266
|
return;
|
|
258
267
|
} finally {
|
|
@@ -270,12 +279,15 @@ var V = .08, H = .08, VoiceSessionClient = class extends f {
|
|
|
270
279
|
}
|
|
271
280
|
fail(e) {
|
|
272
281
|
let t = this.state.value === "live";
|
|
273
|
-
this.generation++, t && this.
|
|
282
|
+
this.generation++, t && this.playChime("end"), this.settings.onError?.(e), this.setState("ended"), this.teardown();
|
|
274
283
|
}
|
|
275
284
|
async teardown() {
|
|
276
285
|
this.workAbort?.abort(), this.workAbort = void 0;
|
|
277
286
|
let e = !!this.workState.activeTurnId;
|
|
278
|
-
this.workState = createVoiceWorkState(), e && this.settings.onWorkChange?.({ active: !1 }), this.
|
|
287
|
+
this.workState = createVoiceWorkState(), e && this.settings.onWorkChange?.({ active: !1 }), this.setSpeaking({
|
|
288
|
+
user: !1,
|
|
289
|
+
agent: !1
|
|
290
|
+
}), this.settings.onThinkingChange?.(!1), this.setWorkCue(!1), this.levelTimer !== void 0 && (clearInterval(this.levelTimer), this.levelTimer = void 0);
|
|
279
291
|
let t = this.provider;
|
|
280
292
|
this.provider = void 0, this.isMuted.value = !1, this.settings.onLevel?.({
|
|
281
293
|
source: "playback",
|
|
@@ -285,21 +297,20 @@ var V = .08, H = .08, VoiceSessionClient = class extends f {
|
|
|
285
297
|
startLevelTimer(e, t) {
|
|
286
298
|
this.levelTimer === void 0 && (this.levelTimer = setInterval(() => {
|
|
287
299
|
if (t !== this.generation || this.provider !== e) return;
|
|
288
|
-
let n = e.sampleLevel();
|
|
289
|
-
n && (this.settings.onLevel?.(n),
|
|
290
|
-
},
|
|
300
|
+
let n = e.sampleLevel(this.speaking.agent ? "playback" : this.speaking.user ? "mic" : void 0);
|
|
301
|
+
n && (this.settings.onLevel?.(n), !this.firstPlaybackEmitted && n.source === "playback" && d(n.level) && this.liveAtMs > 0 && (this.firstPlaybackEmitted = !0, this.emitMetric("voice.first_playback", Date.now() - this.liveAtMs)));
|
|
302
|
+
}, B));
|
|
291
303
|
}
|
|
292
304
|
authHeaders() {
|
|
293
305
|
return this.settings.token ? { Authorization: `Bearer ${this.settings.token}` } : {};
|
|
294
306
|
}
|
|
295
307
|
startWorkStream(t, n) {
|
|
296
|
-
if (!this.settings.onWorkChange) return;
|
|
297
308
|
this.workAbort?.abort();
|
|
298
309
|
let r = new AbortController();
|
|
299
310
|
this.workAbort = r;
|
|
300
|
-
let i = e(this.settings.apiBase, this.settings.isDev), a = this.settings.fetchFn ?? fetch
|
|
311
|
+
let i = e(this.settings.apiBase, this.settings.isDev), a = this.settings.fetchFn ?? fetch, o = this.settings.latestSequence ? `${i}/api/conversations/${encodeURIComponent(t)}/stream?since=${encodeURIComponent(this.settings.latestSequence)}` : `${i}/api/conversations/${encodeURIComponent(t)}/stream`;
|
|
301
312
|
(async () => {
|
|
302
|
-
let e = await a(
|
|
313
|
+
let e = await a(o, {
|
|
303
314
|
headers: {
|
|
304
315
|
Accept: "text/event-stream",
|
|
305
316
|
...this.authHeaders()
|
|
@@ -307,7 +318,7 @@ var V = .08, H = .08, VoiceSessionClient = class extends f {
|
|
|
307
318
|
credentials: "include",
|
|
308
319
|
signal: r.signal
|
|
309
320
|
});
|
|
310
|
-
if (!(!e.ok || !e.body)) for await (let t of
|
|
321
|
+
if (!(!e.ok || !e.body)) for await (let t of m(e.body.getReader())) {
|
|
311
322
|
if (r.signal.aborted || n !== this.generation) return;
|
|
312
323
|
let e = this.workState, i = reduceVoiceWorkEvent(e, t);
|
|
313
324
|
i !== e && (this.workState = i, (i.activeTurnId !== e.activeTurnId || i.description !== e.description) && (this.settings.onWorkChange?.({
|
|
@@ -317,11 +328,21 @@ var V = .08, H = .08, VoiceSessionClient = class extends f {
|
|
|
317
328
|
}
|
|
318
329
|
})().catch(() => {});
|
|
319
330
|
}
|
|
331
|
+
setSpeaking(e) {
|
|
332
|
+
let t = {
|
|
333
|
+
user: e.user && !this.isMuted.value,
|
|
334
|
+
agent: e.agent
|
|
335
|
+
};
|
|
336
|
+
t.user === this.speaking.user && t.agent === this.speaking.agent || (this.speaking = t, this.settings.onSpeakingChange?.(t), this.updateWorkCue());
|
|
337
|
+
}
|
|
320
338
|
updateWorkCue() {
|
|
321
|
-
this.setWorkCue(this.state.value === "live" && !!this.workState.activeTurnId && !this.
|
|
339
|
+
this.setWorkCue(this.state.value === "live" && !!this.workState.activeTurnId && !this.speaking.user && !this.speaking.agent);
|
|
340
|
+
}
|
|
341
|
+
setWorkCue(t) {
|
|
342
|
+
this.workCuePlaying !== t && (this.workCuePlaying = t, this.workCue ?? (this.workCue = createBrowserVoiceWorkCue(e(this.settings.apiBase, this.settings.isDev))), this.workCue(t));
|
|
322
343
|
}
|
|
323
|
-
|
|
324
|
-
this.
|
|
344
|
+
playChime(t) {
|
|
345
|
+
this.chime ?? (this.chime = createBrowserVoiceChimePlayer(e(this.settings.apiBase, this.settings.isDev))), this.chime(t);
|
|
325
346
|
}
|
|
326
347
|
async post(t) {
|
|
327
348
|
let n = e(this.settings.apiBase, this.settings.isDev), r = await (this.settings.fetchFn ?? fetch)(`${n}${t.path}`, {
|
|
@@ -356,7 +377,7 @@ var V = .08, H = .08, VoiceSessionClient = class extends f {
|
|
|
356
377
|
body: { conversationId: t }
|
|
357
378
|
});
|
|
358
379
|
if (e !== this.generation) return null;
|
|
359
|
-
let r =
|
|
380
|
+
let r = h.safeParse(n);
|
|
360
381
|
if (!r.success) throw Object.assign(/* @__PURE__ */ Error("Voice session mint returned an unexpected shape."), { code: "VOICE_MINT_INVALID" });
|
|
361
382
|
return this.conversationId = t, r.data;
|
|
362
383
|
}
|
|
@@ -371,6 +392,6 @@ var V = .08, H = .08, VoiceSessionClient = class extends f {
|
|
|
371
392
|
}
|
|
372
393
|
};
|
|
373
394
|
//#endregion
|
|
374
|
-
export { i as AGENT_MODES, r as Agent, l as AgentChat, o as AgentChatController, o as AgentController, u as AgentProvider,
|
|
395
|
+
export { i as AGENT_MODES, r as Agent, l as AgentChat, o as AgentChatController, o as AgentController, u as AgentProvider, F as AgentWidget, c as AgentWrap, a as ElAgentChat, L as ElAgentChatPreview, s as VoiceMode, VoiceSessionClient };
|
|
375
396
|
|
|
376
397
|
//# sourceMappingURL=agent.js.map
|