@absolutejs/voice 0.0.22-beta.494 → 0.0.22-beta.496
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/agent.d.ts +12 -0
- package/dist/angular/index.d.ts +2 -0
- package/dist/angular/index.js +2992 -2813
- package/dist/angular/voice-widget.service.d.ts +18 -0
- package/dist/client/voiceWidgetView.d.ts +50 -0
- package/dist/index.js +42 -1
- package/dist/react/VoiceWidget.d.ts +4 -24
- package/dist/react/index.js +143 -84
- package/dist/svelte/createVoiceWidget.d.ts +19 -0
- package/dist/svelte/index.d.ts +2 -0
- package/dist/svelte/index.js +5341 -5182
- package/dist/testing/index.js +6 -0
- package/dist/types.d.ts +2 -0
- package/dist/vue/VoiceWidget.d.ts +77 -0
- package/dist/vue/index.d.ts +2 -0
- package/dist/vue/index.js +216 -0
- package/package.json +1 -1
package/dist/testing/index.js
CHANGED
|
@@ -5670,6 +5670,7 @@ var createVoiceSession = (options) => {
|
|
|
5670
5670
|
let activeAdapterGeneration = 0;
|
|
5671
5671
|
let activeTTSTurnId;
|
|
5672
5672
|
const currentTurnAudio = [];
|
|
5673
|
+
const pendingUserAttachments = [];
|
|
5673
5674
|
let fallbackAttemptsForCurrentTurn = 0;
|
|
5674
5675
|
let fallbackReplayAudioMsForCurrentTurn = 0;
|
|
5675
5676
|
const amdDetector = options.amd;
|
|
@@ -7194,7 +7195,9 @@ var createVoiceSession = (options) => {
|
|
|
7194
7195
|
audioMs: costEstimate.totalBillableAudioMs
|
|
7195
7196
|
});
|
|
7196
7197
|
}
|
|
7198
|
+
const drainedAttachments = pendingUserAttachments.length > 0 ? pendingUserAttachments.splice(0, pendingUserAttachments.length) : undefined;
|
|
7197
7199
|
const turn = {
|
|
7200
|
+
attachments: drainedAttachments,
|
|
7198
7201
|
committedAt: Date.now(),
|
|
7199
7202
|
id: createId(),
|
|
7200
7203
|
text: finalText,
|
|
@@ -7488,6 +7491,9 @@ var createVoiceSession = (options) => {
|
|
|
7488
7491
|
};
|
|
7489
7492
|
const api = {
|
|
7490
7493
|
id: options.id,
|
|
7494
|
+
attachUserMedia: async (attachment) => {
|
|
7495
|
+
pendingUserAttachments.push(attachment);
|
|
7496
|
+
},
|
|
7491
7497
|
close: async (reason) => {
|
|
7492
7498
|
await runSerial("api.close", async () => {
|
|
7493
7499
|
const disposition = reason === "silence-timeout" ? "silence-timeout" : "closed";
|
package/dist/types.d.ts
CHANGED
|
@@ -220,6 +220,7 @@ export type VoiceTurnRecord<TResult = unknown> = {
|
|
|
220
220
|
quality?: VoiceTranscriptQuality;
|
|
221
221
|
transcripts: Transcript[];
|
|
222
222
|
assistantText?: string;
|
|
223
|
+
attachments?: import("./agent").VoiceAgentMessageAttachment[];
|
|
223
224
|
committedAt: number;
|
|
224
225
|
result?: TResult;
|
|
225
226
|
};
|
|
@@ -436,6 +437,7 @@ export type VoiceSessionHandle<TContext = unknown, TSession extends VoiceSession
|
|
|
436
437
|
id: string;
|
|
437
438
|
connect: (socket: VoiceSocket) => Promise<void>;
|
|
438
439
|
receiveAudio: (audio: AudioChunk) => Promise<void>;
|
|
440
|
+
attachUserMedia: (attachment: import("./agent").VoiceAgentMessageAttachment) => Promise<void>;
|
|
439
441
|
commitTurn: (reason?: VoiceEndOfTurnEvent["reason"]) => Promise<void>;
|
|
440
442
|
disconnect: (event?: VoiceCloseEvent) => Promise<void>;
|
|
441
443
|
complete: (result?: TResult) => Promise<void>;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { type PropType } from "vue";
|
|
2
|
+
import type { VoiceControllerOptions } from "../types";
|
|
3
|
+
export type VoiceWidgetTheme = {
|
|
4
|
+
accent?: string;
|
|
5
|
+
background?: string;
|
|
6
|
+
errorAccent?: string;
|
|
7
|
+
fontFamily?: string;
|
|
8
|
+
foreground?: string;
|
|
9
|
+
radius?: number | string;
|
|
10
|
+
};
|
|
11
|
+
export type VoiceWidgetLabels = {
|
|
12
|
+
callEnded?: string;
|
|
13
|
+
connecting?: string;
|
|
14
|
+
endCall?: string;
|
|
15
|
+
idle?: string;
|
|
16
|
+
listening?: string;
|
|
17
|
+
mute?: string;
|
|
18
|
+
speaking?: string;
|
|
19
|
+
startCall?: string;
|
|
20
|
+
thinking?: string;
|
|
21
|
+
unmute?: string;
|
|
22
|
+
};
|
|
23
|
+
export declare const VoiceWidget: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
24
|
+
controllerOptions: {
|
|
25
|
+
default: () => {};
|
|
26
|
+
type: PropType<VoiceControllerOptions>;
|
|
27
|
+
};
|
|
28
|
+
labels: {
|
|
29
|
+
default: () => {};
|
|
30
|
+
type: PropType<VoiceWidgetLabels>;
|
|
31
|
+
};
|
|
32
|
+
path: {
|
|
33
|
+
default: string;
|
|
34
|
+
type: StringConstructor;
|
|
35
|
+
};
|
|
36
|
+
theme: {
|
|
37
|
+
default: () => {};
|
|
38
|
+
type: PropType<VoiceWidgetTheme>;
|
|
39
|
+
};
|
|
40
|
+
title: {
|
|
41
|
+
default: string;
|
|
42
|
+
type: StringConstructor;
|
|
43
|
+
};
|
|
44
|
+
}>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
45
|
+
[key: string]: any;
|
|
46
|
+
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
47
|
+
error: (_message: string) => true;
|
|
48
|
+
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
49
|
+
controllerOptions: {
|
|
50
|
+
default: () => {};
|
|
51
|
+
type: PropType<VoiceControllerOptions>;
|
|
52
|
+
};
|
|
53
|
+
labels: {
|
|
54
|
+
default: () => {};
|
|
55
|
+
type: PropType<VoiceWidgetLabels>;
|
|
56
|
+
};
|
|
57
|
+
path: {
|
|
58
|
+
default: string;
|
|
59
|
+
type: StringConstructor;
|
|
60
|
+
};
|
|
61
|
+
theme: {
|
|
62
|
+
default: () => {};
|
|
63
|
+
type: PropType<VoiceWidgetTheme>;
|
|
64
|
+
};
|
|
65
|
+
title: {
|
|
66
|
+
default: string;
|
|
67
|
+
type: StringConstructor;
|
|
68
|
+
};
|
|
69
|
+
}>> & Readonly<{
|
|
70
|
+
onError?: ((_message: string) => any) | undefined;
|
|
71
|
+
}>, {
|
|
72
|
+
title: string;
|
|
73
|
+
path: string;
|
|
74
|
+
theme: VoiceWidgetTheme;
|
|
75
|
+
controllerOptions: VoiceControllerOptions;
|
|
76
|
+
labels: VoiceWidgetLabels;
|
|
77
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
package/dist/vue/index.d.ts
CHANGED
|
@@ -31,6 +31,8 @@ export { useVoiceDeliveryRuntime } from "./useVoiceDeliveryRuntime";
|
|
|
31
31
|
export { useVoiceCampaignDialerProof } from "./useVoiceCampaignDialerProof";
|
|
32
32
|
export { useVoiceStream } from "./useVoiceStream";
|
|
33
33
|
export { useVoiceController } from "./useVoiceController";
|
|
34
|
+
export { VoiceWidget } from "./VoiceWidget";
|
|
35
|
+
export type { VoiceWidgetLabels, VoiceWidgetTheme, } from "./VoiceWidget";
|
|
34
36
|
export { useVoiceProviderStatus } from "./useVoiceProviderStatus";
|
|
35
37
|
export { useVoiceProviderCapabilities } from "./useVoiceProviderCapabilities";
|
|
36
38
|
export { useVoiceProviderContracts } from "./useVoiceProviderContracts";
|
package/dist/vue/index.js
CHANGED
|
@@ -11867,6 +11867,221 @@ function useVoiceController(path, options = {}) {
|
|
|
11867
11867
|
turns
|
|
11868
11868
|
};
|
|
11869
11869
|
}
|
|
11870
|
+
// src/vue/VoiceWidget.ts
|
|
11871
|
+
import { computed as computed10, defineComponent as defineComponent18, h as h18 } from "vue";
|
|
11872
|
+
|
|
11873
|
+
// src/agentState.ts
|
|
11874
|
+
var deriveVoiceAgentUIState = (input) => {
|
|
11875
|
+
if (!input.isConnected) {
|
|
11876
|
+
return "idle";
|
|
11877
|
+
}
|
|
11878
|
+
if (input.isPlaying) {
|
|
11879
|
+
return "speaking";
|
|
11880
|
+
}
|
|
11881
|
+
if (input.isRecording && input.hasActivePartial) {
|
|
11882
|
+
return "listening";
|
|
11883
|
+
}
|
|
11884
|
+
if (input.isRecording) {
|
|
11885
|
+
return "listening";
|
|
11886
|
+
}
|
|
11887
|
+
if (input.lastTranscriptAt && !input.lastAssistantAt) {
|
|
11888
|
+
return "thinking";
|
|
11889
|
+
}
|
|
11890
|
+
if (input.lastTranscriptAt && input.lastAssistantAt && input.lastTranscriptAt > input.lastAssistantAt) {
|
|
11891
|
+
return "thinking";
|
|
11892
|
+
}
|
|
11893
|
+
return "idle";
|
|
11894
|
+
};
|
|
11895
|
+
var describeVoiceAgentUIState = (state) => {
|
|
11896
|
+
switch (state) {
|
|
11897
|
+
case "idle":
|
|
11898
|
+
return "Idle";
|
|
11899
|
+
case "listening":
|
|
11900
|
+
return "Listening";
|
|
11901
|
+
case "speaking":
|
|
11902
|
+
return "Speaking";
|
|
11903
|
+
case "thinking":
|
|
11904
|
+
return "Thinking";
|
|
11905
|
+
}
|
|
11906
|
+
};
|
|
11907
|
+
var voiceAgentUIStateOrder = [
|
|
11908
|
+
"idle",
|
|
11909
|
+
"listening",
|
|
11910
|
+
"thinking",
|
|
11911
|
+
"speaking"
|
|
11912
|
+
];
|
|
11913
|
+
|
|
11914
|
+
// src/vue/VoiceWidget.ts
|
|
11915
|
+
var DEFAULT_THEME = {
|
|
11916
|
+
accent: "#3b82f6",
|
|
11917
|
+
background: "#0f172a",
|
|
11918
|
+
errorAccent: "#ef4444",
|
|
11919
|
+
fontFamily: 'ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
|
|
11920
|
+
foreground: "#f8fafc",
|
|
11921
|
+
radius: 16
|
|
11922
|
+
};
|
|
11923
|
+
var DEFAULT_LABELS = {
|
|
11924
|
+
callEnded: "Call ended",
|
|
11925
|
+
connecting: "Connecting\u2026",
|
|
11926
|
+
endCall: "End call",
|
|
11927
|
+
idle: "Idle",
|
|
11928
|
+
listening: "Listening",
|
|
11929
|
+
mute: "Mute",
|
|
11930
|
+
speaking: "Speaking",
|
|
11931
|
+
startCall: "Start call",
|
|
11932
|
+
thinking: "Thinking",
|
|
11933
|
+
unmute: "Unmute"
|
|
11934
|
+
};
|
|
11935
|
+
var resolveRadius = (radius) => typeof radius === "number" ? `${radius}px` : radius;
|
|
11936
|
+
var VoiceWidget = defineComponent18({
|
|
11937
|
+
name: "VoiceWidget",
|
|
11938
|
+
props: {
|
|
11939
|
+
controllerOptions: {
|
|
11940
|
+
default: () => ({}),
|
|
11941
|
+
type: Object
|
|
11942
|
+
},
|
|
11943
|
+
labels: {
|
|
11944
|
+
default: () => ({}),
|
|
11945
|
+
type: Object
|
|
11946
|
+
},
|
|
11947
|
+
path: { default: "/voice", type: String },
|
|
11948
|
+
theme: {
|
|
11949
|
+
default: () => ({}),
|
|
11950
|
+
type: Object
|
|
11951
|
+
},
|
|
11952
|
+
title: { default: "Voice", type: String }
|
|
11953
|
+
},
|
|
11954
|
+
emits: { error: (_message) => true },
|
|
11955
|
+
setup(props, { emit }) {
|
|
11956
|
+
const controller = useVoiceController(props.path, props.controllerOptions);
|
|
11957
|
+
const theme = computed10(() => ({ ...DEFAULT_THEME, ...props.theme }));
|
|
11958
|
+
const labels = computed10(() => ({ ...DEFAULT_LABELS, ...props.labels }));
|
|
11959
|
+
const agentState = computed10(() => {
|
|
11960
|
+
const lastAssistantAt = controller.assistantAudio.value.at(-1)?.receivedAt;
|
|
11961
|
+
const lastTranscriptAt = controller.turns.value.at(-1)?.committedAt;
|
|
11962
|
+
return deriveVoiceAgentUIState({
|
|
11963
|
+
hasActivePartial: controller.partial.value.length > 0,
|
|
11964
|
+
isConnected: controller.isConnected.value,
|
|
11965
|
+
isPlaying: false,
|
|
11966
|
+
isRecording: controller.isRecording.value,
|
|
11967
|
+
lastAssistantAt,
|
|
11968
|
+
lastTranscriptAt
|
|
11969
|
+
});
|
|
11970
|
+
});
|
|
11971
|
+
return () => {
|
|
11972
|
+
const t = theme.value;
|
|
11973
|
+
const l = labels.value;
|
|
11974
|
+
if (controller.error.value) {
|
|
11975
|
+
emit("error", controller.error.value);
|
|
11976
|
+
}
|
|
11977
|
+
const stateLabel = controller.error.value ? "Error" : !controller.isConnected.value && controller.status.value !== "idle" ? l.connecting : controller.status.value === "completed" ? l.callEnded : agentState.value === "listening" ? l.listening : agentState.value === "speaking" ? l.speaking : agentState.value === "thinking" ? l.thinking : l.idle;
|
|
11978
|
+
const showStart = !controller.isRecording.value && controller.status.value !== "completed";
|
|
11979
|
+
return h18("div", {
|
|
11980
|
+
"aria-live": "polite",
|
|
11981
|
+
"data-agent-state": agentState.value,
|
|
11982
|
+
role: "region",
|
|
11983
|
+
style: {
|
|
11984
|
+
background: t.background,
|
|
11985
|
+
borderRadius: resolveRadius(t.radius),
|
|
11986
|
+
color: t.foreground,
|
|
11987
|
+
fontFamily: t.fontFamily,
|
|
11988
|
+
minWidth: "240px",
|
|
11989
|
+
padding: "20px 22px"
|
|
11990
|
+
}
|
|
11991
|
+
}, [
|
|
11992
|
+
h18("div", {
|
|
11993
|
+
style: {
|
|
11994
|
+
alignItems: "center",
|
|
11995
|
+
display: "flex",
|
|
11996
|
+
gap: "10px",
|
|
11997
|
+
marginBottom: "12px"
|
|
11998
|
+
}
|
|
11999
|
+
}, [
|
|
12000
|
+
h18("span", {
|
|
12001
|
+
"aria-hidden": "true",
|
|
12002
|
+
style: {
|
|
12003
|
+
background: controller.error.value ? t.errorAccent : agentState.value === "idle" ? "rgba(148,163,184,0.6)" : t.accent,
|
|
12004
|
+
borderRadius: "50%",
|
|
12005
|
+
height: "10px",
|
|
12006
|
+
width: "10px"
|
|
12007
|
+
}
|
|
12008
|
+
}),
|
|
12009
|
+
h18("strong", { style: { fontSize: "15px" } }, props.title),
|
|
12010
|
+
h18("span", {
|
|
12011
|
+
style: {
|
|
12012
|
+
fontSize: "13px",
|
|
12013
|
+
marginLeft: "auto",
|
|
12014
|
+
opacity: "0.7"
|
|
12015
|
+
}
|
|
12016
|
+
}, stateLabel)
|
|
12017
|
+
]),
|
|
12018
|
+
controller.partial.value ? h18("p", {
|
|
12019
|
+
style: {
|
|
12020
|
+
fontSize: "13px",
|
|
12021
|
+
margin: "8px 0 12px",
|
|
12022
|
+
opacity: "0.85",
|
|
12023
|
+
wordBreak: "break-word"
|
|
12024
|
+
}
|
|
12025
|
+
}, `\u201C${controller.partial.value}\u201D`) : null,
|
|
12026
|
+
h18("div", { style: { display: "flex", gap: "10px" } }, [
|
|
12027
|
+
showStart ? h18("button", {
|
|
12028
|
+
onClick: () => {
|
|
12029
|
+
controller.startRecording();
|
|
12030
|
+
},
|
|
12031
|
+
style: {
|
|
12032
|
+
background: t.accent,
|
|
12033
|
+
border: "none",
|
|
12034
|
+
borderRadius: "12px",
|
|
12035
|
+
color: t.foreground,
|
|
12036
|
+
cursor: "pointer",
|
|
12037
|
+
fontSize: "14px",
|
|
12038
|
+
fontWeight: "500",
|
|
12039
|
+
padding: "10px 14px"
|
|
12040
|
+
},
|
|
12041
|
+
type: "button"
|
|
12042
|
+
}, l.startCall) : null,
|
|
12043
|
+
controller.isRecording.value ? h18("button", {
|
|
12044
|
+
onClick: () => controller.stopRecording(),
|
|
12045
|
+
style: {
|
|
12046
|
+
background: "transparent",
|
|
12047
|
+
border: "1px solid rgba(255,255,255,0.18)",
|
|
12048
|
+
borderRadius: "12px",
|
|
12049
|
+
color: t.foreground,
|
|
12050
|
+
cursor: "pointer",
|
|
12051
|
+
fontSize: "14px",
|
|
12052
|
+
fontWeight: "500",
|
|
12053
|
+
padding: "10px 14px"
|
|
12054
|
+
},
|
|
12055
|
+
type: "button"
|
|
12056
|
+
}, l.mute) : null,
|
|
12057
|
+
controller.isConnected.value ? h18("button", {
|
|
12058
|
+
onClick: () => {
|
|
12059
|
+
controller.close();
|
|
12060
|
+
},
|
|
12061
|
+
style: {
|
|
12062
|
+
background: t.errorAccent,
|
|
12063
|
+
border: "none",
|
|
12064
|
+
borderRadius: "12px",
|
|
12065
|
+
color: t.foreground,
|
|
12066
|
+
cursor: "pointer",
|
|
12067
|
+
fontSize: "14px",
|
|
12068
|
+
fontWeight: "500",
|
|
12069
|
+
padding: "10px 14px"
|
|
12070
|
+
},
|
|
12071
|
+
type: "button"
|
|
12072
|
+
}, l.endCall) : null
|
|
12073
|
+
]),
|
|
12074
|
+
controller.error.value ? h18("p", {
|
|
12075
|
+
style: {
|
|
12076
|
+
color: t.errorAccent,
|
|
12077
|
+
fontSize: "12px",
|
|
12078
|
+
marginTop: "12px"
|
|
12079
|
+
}
|
|
12080
|
+
}, controller.error.value) : null
|
|
12081
|
+
]);
|
|
12082
|
+
};
|
|
12083
|
+
}
|
|
12084
|
+
});
|
|
11870
12085
|
// src/vue/useVoiceTraceTimeline.ts
|
|
11871
12086
|
import { onUnmounted as onUnmounted23, ref as ref18, shallowRef as shallowRef22 } from "vue";
|
|
11872
12087
|
function useVoiceTraceTimeline(path = "/api/voice-traces", options = {}) {
|
|
@@ -12036,6 +12251,7 @@ export {
|
|
|
12036
12251
|
useVoiceCampaignDialerProof,
|
|
12037
12252
|
useVoiceCallDebugger,
|
|
12038
12253
|
useVoiceAgentSquadStatus,
|
|
12254
|
+
VoiceWidget,
|
|
12039
12255
|
VoiceTurnQuality,
|
|
12040
12256
|
VoiceTurnLatency,
|
|
12041
12257
|
VoiceSessionSnapshot,
|