@elevenlabs/react 0.14.3 → 1.0.0-rc.0
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/README.md +33 -1085
- package/dist/conversation/ConversationClientTools.d.ts +39 -0
- package/dist/conversation/ConversationClientTools.d.ts.map +1 -0
- package/dist/conversation/ConversationClientTools.js +87 -0
- package/dist/conversation/ConversationClientTools.js.map +1 -0
- package/dist/conversation/ConversationContext.d.ts +47 -0
- package/dist/conversation/ConversationContext.d.ts.map +1 -0
- package/dist/conversation/ConversationContext.js +61 -0
- package/dist/conversation/ConversationContext.js.map +1 -0
- package/dist/conversation/ConversationControls.d.ts +34 -0
- package/dist/conversation/ConversationControls.d.ts.map +1 -0
- package/dist/conversation/ConversationControls.js +113 -0
- package/dist/conversation/ConversationControls.js.map +1 -0
- package/dist/conversation/ConversationFeedback.d.ts +19 -0
- package/dist/conversation/ConversationFeedback.d.ts.map +1 -0
- package/dist/conversation/ConversationFeedback.js +44 -0
- package/dist/conversation/ConversationFeedback.js.map +1 -0
- package/dist/conversation/ConversationInput.d.ts +18 -0
- package/dist/conversation/ConversationInput.d.ts.map +1 -0
- package/dist/conversation/ConversationInput.js +40 -0
- package/dist/conversation/ConversationInput.js.map +1 -0
- package/dist/conversation/ConversationMode.d.ts +19 -0
- package/dist/conversation/ConversationMode.d.ts.map +1 -0
- package/dist/conversation/ConversationMode.js +40 -0
- package/dist/conversation/ConversationMode.js.map +1 -0
- package/dist/conversation/ConversationProvider.d.ts +4 -0
- package/dist/conversation/ConversationProvider.d.ts.map +1 -0
- package/dist/conversation/ConversationProvider.js +127 -0
- package/dist/conversation/ConversationProvider.js.map +1 -0
- package/dist/conversation/ConversationStatus.d.ts +19 -0
- package/dist/conversation/ConversationStatus.d.ts.map +1 -0
- package/dist/conversation/ConversationStatus.js +44 -0
- package/dist/conversation/ConversationStatus.js.map +1 -0
- package/dist/conversation/ListenerMap.d.ts +29 -0
- package/dist/conversation/ListenerMap.d.ts.map +1 -0
- package/dist/conversation/ListenerMap.js +63 -0
- package/dist/conversation/ListenerMap.js.map +1 -0
- package/dist/conversation/ListenerSet.d.ts +7 -0
- package/dist/conversation/ListenerSet.d.ts.map +1 -0
- package/dist/conversation/ListenerSet.js +17 -0
- package/dist/conversation/ListenerSet.js.map +1 -0
- package/dist/conversation/types.d.ts +9 -0
- package/dist/conversation/types.d.ts.map +1 -0
- package/dist/conversation/types.js +2 -0
- package/dist/conversation/types.js.map +1 -0
- package/dist/conversation/useConversation.d.ts +45 -0
- package/dist/conversation/useConversation.d.ts.map +1 -0
- package/dist/conversation/useConversation.js +76 -0
- package/dist/conversation/useConversation.js.map +1 -0
- package/dist/conversation/useStableCallbacks.d.ts +13 -0
- package/dist/conversation/useStableCallbacks.d.ts.map +1 -0
- package/dist/conversation/useStableCallbacks.js +33 -0
- package/dist/conversation/useStableCallbacks.js.map +1 -0
- package/dist/index.d.ts +19 -51
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/lib.iife.js +984 -0
- package/dist/lib.iife.js.map +1 -0
- package/dist/scribe.d.ts +1 -0
- package/dist/scribe.d.ts.map +1 -0
- package/dist/scribe.js +307 -0
- package/dist/scribe.js.map +1 -0
- package/dist/version.d.ts +2 -1
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +3 -0
- package/dist/version.js.map +1 -0
- package/package.json +25 -20
- package/.turbo/turbo-build.log +0 -29
- package/.turbo/turbo-check-types.log +0 -4
- package/.turbo/turbo-generate-version.log +0 -4
- package/.turbo/turbo-lint$colon$es.log +0 -6
- package/.turbo/turbo-lint$colon$prettier.log +0 -6
- package/CHANGELOG.md +0 -53
- package/dist/lib.cjs +0 -2
- package/dist/lib.cjs.map +0 -1
- package/dist/lib.modern.js +0 -2
- package/dist/lib.modern.js.map +0 -1
- package/dist/lib.module.js +0 -2
- package/dist/lib.module.js.map +0 -1
- package/dist/lib.umd.js +0 -2
- package/dist/lib.umd.js.map +0 -1
- package/jest.config.cjs +0 -23
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, } from "react";
|
|
3
|
+
import { Conversation } from "@elevenlabs/client";
|
|
4
|
+
import { CALLBACK_KEYS, mergeOptions, parseLocation, getOriginForLocation, getLivekitUrlForLocation, } from "@elevenlabs/client/internal";
|
|
5
|
+
import { ConversationContext, } from "./ConversationContext";
|
|
6
|
+
import { ConversationControlsProvider } from "./ConversationControls";
|
|
7
|
+
import { ConversationStatusProvider } from "./ConversationStatus";
|
|
8
|
+
import { ConversationInputProvider } from "./ConversationInput";
|
|
9
|
+
import { ConversationModeProvider } from "./ConversationMode";
|
|
10
|
+
import { ConversationFeedbackProvider } from "./ConversationFeedback";
|
|
11
|
+
import { ConversationClientToolsProvider, buildClientTools, } from "./ConversationClientTools";
|
|
12
|
+
import { ListenerMap } from "./ListenerMap";
|
|
13
|
+
import { useStableCallbacks } from "./useStableCallbacks";
|
|
14
|
+
const SUB_PROVIDERS = [
|
|
15
|
+
ConversationControlsProvider,
|
|
16
|
+
ConversationStatusProvider,
|
|
17
|
+
ConversationInputProvider,
|
|
18
|
+
ConversationModeProvider,
|
|
19
|
+
ConversationFeedbackProvider,
|
|
20
|
+
ConversationClientToolsProvider,
|
|
21
|
+
];
|
|
22
|
+
export function ConversationProvider({ children, ...defaultOptions }) {
|
|
23
|
+
/** The active conversation instance, if any. */
|
|
24
|
+
const conversationRef = useRef(null);
|
|
25
|
+
/** In-flight startSession promise, used to prevent duplicate connections. */
|
|
26
|
+
const lockRef = useRef(null);
|
|
27
|
+
/** Signals that endSession was called while a connection was still pending. */
|
|
28
|
+
const shouldEndRef = useRef(false);
|
|
29
|
+
/** Registry of hook-registered client tools. Survives across sessions. */
|
|
30
|
+
const [clientToolsRegistry] = useState(() => new Map());
|
|
31
|
+
/** Ref to the live clientTools object currently held by BaseConversation. */
|
|
32
|
+
const clientToolsRef = useRef({});
|
|
33
|
+
/** Always holds the latest provider props, avoiding stale closures in callbacks. */
|
|
34
|
+
const defaultOptionsRef = useRef(defaultOptions);
|
|
35
|
+
// eslint-disable-next-line react-hooks/refs -- intentional sync during render for latest-ref pattern
|
|
36
|
+
defaultOptionsRef.current = defaultOptions;
|
|
37
|
+
/** Callback registry for sub-providers (status, mode, feedback, etc.). */
|
|
38
|
+
const [listenerMap] = useState(() => new ListenerMap(CALLBACK_KEYS));
|
|
39
|
+
/** Reactive mirror of conversationRef, triggers re-renders for context consumers. */
|
|
40
|
+
const [conversation, setConversation] = useState(null);
|
|
41
|
+
const stableCallbacks = useStableCallbacks(defaultOptions);
|
|
42
|
+
const registerCallbacks = useCallback((callbacks) => listenerMap.register(callbacks), [listenerMap]);
|
|
43
|
+
// Sync provider state when session ends externally (agent disconnect,
|
|
44
|
+
// raw instance endSession(), etc.). Uses the listener map so it composes
|
|
45
|
+
// with user-provided onDisconnect callbacks.
|
|
46
|
+
useLayoutEffect(() => {
|
|
47
|
+
return listenerMap.register({
|
|
48
|
+
onDisconnect: () => {
|
|
49
|
+
conversationRef.current = null;
|
|
50
|
+
setConversation(null);
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
}, [listenerMap]);
|
|
54
|
+
const startSession = useCallback((options) => {
|
|
55
|
+
if (conversationRef.current) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (lockRef.current) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
shouldEndRef.current = false;
|
|
62
|
+
const defaults = defaultOptionsRef.current;
|
|
63
|
+
const resolvedServerLocation = parseLocation(options?.serverLocation || defaults?.serverLocation);
|
|
64
|
+
const origin = getOriginForLocation(resolvedServerLocation);
|
|
65
|
+
const calculatedLivekitUrl = getLivekitUrlForLocation(resolvedServerLocation);
|
|
66
|
+
// Strip raw callbacks from defaults — stableCallbacks provides
|
|
67
|
+
// ref-backed versions that won't go stale across renders.
|
|
68
|
+
const defaultConfig = { ...defaults };
|
|
69
|
+
for (const key of CALLBACK_KEYS) {
|
|
70
|
+
delete defaultConfig[key];
|
|
71
|
+
}
|
|
72
|
+
const sessionOptions = mergeOptions({ livekitUrl: calculatedLivekitUrl }, defaultConfig, stableCallbacks, listenerMap.compose(), options ?? {}, { origin });
|
|
73
|
+
const clientTools = buildClientTools(sessionOptions.clientTools, clientToolsRegistry);
|
|
74
|
+
clientToolsRef.current = clientTools;
|
|
75
|
+
sessionOptions.clientTools = clientTools;
|
|
76
|
+
lockRef.current = Conversation.startSession(sessionOptions);
|
|
77
|
+
lockRef.current.then(conv => {
|
|
78
|
+
if (shouldEndRef.current) {
|
|
79
|
+
conv.endSession();
|
|
80
|
+
lockRef.current = null;
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
conversationRef.current = conv;
|
|
84
|
+
setConversation(conv);
|
|
85
|
+
lockRef.current = null;
|
|
86
|
+
}, () => {
|
|
87
|
+
lockRef.current = null;
|
|
88
|
+
});
|
|
89
|
+
}, [stableCallbacks, listenerMap, clientToolsRegistry, clientToolsRef]);
|
|
90
|
+
const endSession = useCallback(() => {
|
|
91
|
+
shouldEndRef.current = true;
|
|
92
|
+
const pendingConnection = lockRef.current;
|
|
93
|
+
const conv = conversationRef.current;
|
|
94
|
+
conversationRef.current = null;
|
|
95
|
+
setConversation(null);
|
|
96
|
+
if (pendingConnection) {
|
|
97
|
+
pendingConnection.then(c => c.endSession());
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
conv?.endSession();
|
|
101
|
+
}
|
|
102
|
+
}, []);
|
|
103
|
+
// Cleanup on unmount
|
|
104
|
+
useEffect(() => {
|
|
105
|
+
return () => {
|
|
106
|
+
shouldEndRef.current = true;
|
|
107
|
+
if (lockRef.current) {
|
|
108
|
+
lockRef.current.then(conv => conv.endSession());
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
conversationRef.current?.endSession();
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
}, []);
|
|
115
|
+
const contextValue = useMemo(() => ({
|
|
116
|
+
conversation,
|
|
117
|
+
conversationRef,
|
|
118
|
+
startSession,
|
|
119
|
+
endSession,
|
|
120
|
+
registerCallbacks,
|
|
121
|
+
clientToolsRegistry,
|
|
122
|
+
clientToolsRef,
|
|
123
|
+
}), [conversation, conversationRef, startSession, endSession, registerCallbacks, clientToolsRegistry, clientToolsRef]);
|
|
124
|
+
const wrappedChildren = SUB_PROVIDERS.reduceRight((nested, Provider) => _jsx(Provider, { children: nested }), children);
|
|
125
|
+
return (_jsx(ConversationContext.Provider, { value: contextValue, children: wrappedChildren }));
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=ConversationProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConversationProvider.js","sourceRoot":"","sources":["../../src/conversation/ConversationProvider.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export type ConversationStatus = "disconnected" | "connecting" | "connected" | "error";
|
|
2
|
+
export type ConversationStatusValue = {
|
|
3
|
+
status: ConversationStatus;
|
|
4
|
+
message?: string;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Reads from `ConversationContext` and registers `onStatusChange` + `onError`
|
|
8
|
+
* callbacks. Manages its own `status`/`message` state and provides it through
|
|
9
|
+
* `ConversationStatusContext`. Must be rendered inside a `ConversationProvider`.
|
|
10
|
+
*/
|
|
11
|
+
export declare function ConversationStatusProvider({ children, }: React.PropsWithChildren): import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
/**
|
|
13
|
+
* Returns the current conversation status and any error message.
|
|
14
|
+
* Re-renders when the connection status or error message changes.
|
|
15
|
+
*
|
|
16
|
+
* Must be used within a `ConversationProvider`.
|
|
17
|
+
*/
|
|
18
|
+
export declare function useConversationStatus(): ConversationStatusValue;
|
|
19
|
+
//# sourceMappingURL=ConversationStatus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConversationStatus.d.ts","sourceRoot":"","sources":["../../src/conversation/ConversationStatus.tsx"],"names":[],"mappings":"AAGA,MAAM,MAAM,kBAAkB,GAC1B,cAAc,GACd,YAAY,GACZ,WAAW,GACX,OAAO,CAAC;AAEZ,MAAM,MAAM,uBAAuB,GAAG;IACpC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAMF;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,EACzC,QAAQ,GACT,EAAE,KAAK,CAAC,iBAAiB,2CA+BzB;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,IAAI,uBAAuB,CAQ/D"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useContext, useMemo, useState } from "react";
|
|
3
|
+
import { useRegisterCallbacks } from "./ConversationContext";
|
|
4
|
+
const ConversationStatusContext = createContext(null);
|
|
5
|
+
/**
|
|
6
|
+
* Reads from `ConversationContext` and registers `onStatusChange` + `onError`
|
|
7
|
+
* callbacks. Manages its own `status`/`message` state and provides it through
|
|
8
|
+
* `ConversationStatusContext`. Must be rendered inside a `ConversationProvider`.
|
|
9
|
+
*/
|
|
10
|
+
export function ConversationStatusProvider({ children, }) {
|
|
11
|
+
const [status, setStatus] = useState("disconnected");
|
|
12
|
+
const [message, setMessage] = useState(undefined);
|
|
13
|
+
useRegisterCallbacks({
|
|
14
|
+
onStatusChange({ status: newStatus }) {
|
|
15
|
+
if (newStatus === "disconnecting") {
|
|
16
|
+
// Transient state — keep current status
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
setStatus(newStatus);
|
|
20
|
+
// Clear error message when transitioning to a non-error state
|
|
21
|
+
setMessage(undefined);
|
|
22
|
+
},
|
|
23
|
+
onError(errorMessage) {
|
|
24
|
+
setStatus("error");
|
|
25
|
+
setMessage(errorMessage);
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
const value = useMemo(() => ({ status, message }), [status, message]);
|
|
29
|
+
return (_jsx(ConversationStatusContext.Provider, { value: value, children: children }));
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Returns the current conversation status and any error message.
|
|
33
|
+
* Re-renders when the connection status or error message changes.
|
|
34
|
+
*
|
|
35
|
+
* Must be used within a `ConversationProvider`.
|
|
36
|
+
*/
|
|
37
|
+
export function useConversationStatus() {
|
|
38
|
+
const ctx = useContext(ConversationStatusContext);
|
|
39
|
+
if (!ctx) {
|
|
40
|
+
throw new Error("useConversationStatus must be used within a ConversationProvider");
|
|
41
|
+
}
|
|
42
|
+
return ctx;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=ConversationStatus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConversationStatus.js","sourceRoot":"","sources":["../../src/conversation/ConversationStatus.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAa7D,MAAM,yBAAyB,GAAG,aAAa,CAC7C,IAAI,CACL,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,0BAA0B,CAAC,EACzC,QAAQ,GACgB;IACxB,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GACvB,QAAQ,CAAoC,cAAc,CAAC,CAAC;IAC9D,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAqB,SAAS,CAAC,CAAC;IAEtE,oBAAoB,CAAC;QACnB,cAAc,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE;YAClC,IAAI,SAAS,KAAK,eAAe,EAAE,CAAC;gBAClC,wCAAwC;gBACxC,OAAO;YACT,CAAC;YACD,SAAS,CAAC,SAAS,CAAC,CAAC;YACrB,8DAA8D;YAC9D,UAAU,CAAC,SAAS,CAAC,CAAC;QACxB,CAAC;QACD,OAAO,CAAC,YAAY;YAClB,SAAS,CAAC,OAAO,CAAC,CAAC;YACnB,UAAU,CAAC,YAAY,CAAC,CAAC;QAC3B,CAAC;KACF,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,OAAO,CACnB,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAC3B,CAAC,MAAM,EAAE,OAAO,CAAC,CAClB,CAAC;IAEF,OAAO,CACL,KAAC,yBAAyB,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YAC7C,QAAQ,GAC0B,CACtC,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB;IACnC,MAAM,GAAG,GAAG,UAAU,CAAC,yBAAyB,CAAC,CAAC;IAClD,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CACb,kEAAkE,CACnE,CAAC;IACJ,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A map of named listener sets. Each key maps to a `ListenerSet` that can have
|
|
3
|
+
* multiple listeners registered. Typed through `T` so that `register` and
|
|
4
|
+
* `compose` preserve per-key callback signatures.
|
|
5
|
+
*
|
|
6
|
+
* All keys are pre-initialized in the constructor so `register` can validate
|
|
7
|
+
* keys. `compose()` only includes keys with at least one registered listener,
|
|
8
|
+
* preserving callback-presence semantics used by the client as feature guards.
|
|
9
|
+
* For included keys, composed functions delegate to the live listener set, so
|
|
10
|
+
* listeners added/removed after `compose()` still take effect. Keys with no
|
|
11
|
+
* listeners at compose time are omitted entirely; call `compose()` again after
|
|
12
|
+
* registering listeners to pick up newly populated keys.
|
|
13
|
+
*/
|
|
14
|
+
export declare class ListenerMap<T extends Record<string, ((...args: never[]) => void) | undefined>> {
|
|
15
|
+
private sets;
|
|
16
|
+
constructor(keys: readonly (keyof T & string)[]);
|
|
17
|
+
/**
|
|
18
|
+
* Register listeners for one or more keys. Returns a function that removes
|
|
19
|
+
* all listeners added by this call.
|
|
20
|
+
*/
|
|
21
|
+
register(callbacks: Partial<T>): () => void;
|
|
22
|
+
/**
|
|
23
|
+
* Compose all registered listeners into a single callbacks object. Each
|
|
24
|
+
* composed function delegates to the live listener set, so listeners
|
|
25
|
+
* added/removed after this call still take effect.
|
|
26
|
+
*/
|
|
27
|
+
compose(): Partial<T>;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=ListenerMap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ListenerMap.d.ts","sourceRoot":"","sources":["../../src/conversation/ListenerMap.ts"],"names":[],"mappings":"AAWA;;;;;;;;;;;;GAYG;AACH,qBAAa,WAAW,CACtB,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAElE,OAAO,CAAC,IAAI,CAA6C;gBAE7C,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,EAAE;IAM/C;;;OAGG;IACH,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI;IAgB3C;;;;OAIG;IACH,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC;CAYtB"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { ListenerSet } from "./ListenerSet";
|
|
2
|
+
function assertFunction(value, key) {
|
|
3
|
+
if (typeof value !== "function") {
|
|
4
|
+
throw new Error(`Expected function for key "${key}", got ${typeof value}`);
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* A map of named listener sets. Each key maps to a `ListenerSet` that can have
|
|
9
|
+
* multiple listeners registered. Typed through `T` so that `register` and
|
|
10
|
+
* `compose` preserve per-key callback signatures.
|
|
11
|
+
*
|
|
12
|
+
* All keys are pre-initialized in the constructor so `register` can validate
|
|
13
|
+
* keys. `compose()` only includes keys with at least one registered listener,
|
|
14
|
+
* preserving callback-presence semantics used by the client as feature guards.
|
|
15
|
+
* For included keys, composed functions delegate to the live listener set, so
|
|
16
|
+
* listeners added/removed after `compose()` still take effect. Keys with no
|
|
17
|
+
* listeners at compose time are omitted entirely; call `compose()` again after
|
|
18
|
+
* registering listeners to pick up newly populated keys.
|
|
19
|
+
*/
|
|
20
|
+
export class ListenerMap {
|
|
21
|
+
sets = new Map();
|
|
22
|
+
constructor(keys) {
|
|
23
|
+
for (const key of keys) {
|
|
24
|
+
this.sets.set(key, new ListenerSet());
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Register listeners for one or more keys. Returns a function that removes
|
|
29
|
+
* all listeners added by this call.
|
|
30
|
+
*/
|
|
31
|
+
register(callbacks) {
|
|
32
|
+
const removers = Object.entries(callbacks)
|
|
33
|
+
.filter(([, fn]) => fn !== undefined)
|
|
34
|
+
.map(([key, fn]) => {
|
|
35
|
+
assertFunction(fn, key);
|
|
36
|
+
const set = this.sets.get(key);
|
|
37
|
+
if (!set) {
|
|
38
|
+
throw new Error(`Unknown callback key "${key}"`);
|
|
39
|
+
}
|
|
40
|
+
return set.add(fn);
|
|
41
|
+
});
|
|
42
|
+
return () => {
|
|
43
|
+
for (const remove of removers)
|
|
44
|
+
remove();
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Compose all registered listeners into a single callbacks object. Each
|
|
49
|
+
* composed function delegates to the live listener set, so listeners
|
|
50
|
+
* added/removed after this call still take effect.
|
|
51
|
+
*/
|
|
52
|
+
compose() {
|
|
53
|
+
return Object.fromEntries(Array.from(this.sets.entries())
|
|
54
|
+
.filter(([, set]) => set.size > 0)
|
|
55
|
+
.map(([key, set]) => [
|
|
56
|
+
key,
|
|
57
|
+
(...args) => {
|
|
58
|
+
set.invoke(...args);
|
|
59
|
+
},
|
|
60
|
+
]));
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=ListenerMap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ListenerMap.js","sourceRoot":"","sources":["../../src/conversation/ListenerMap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,SAAS,cAAc,CACrB,KAAc,EACd,GAAW;IAEX,IAAI,OAAO,KAAK,KAAK,UAAU,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,8BAA8B,GAAG,UAAU,OAAO,KAAK,EAAE,CAAC,CAAC;IAC7E,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,WAAW;IAGd,IAAI,GAAG,IAAI,GAAG,EAAkC,CAAC;IAEzD,YAAY,IAAmC;QAC7C,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,WAAW,EAAa,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,QAAQ,CAAC,SAAqB;QAC5B,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC;aACvC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,KAAK,SAAS,CAAC;aACpC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE;YACjB,cAAc,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YACxB,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC/B,IAAI,CAAC,GAAG,EAAE,CAAC;gBACT,MAAM,IAAI,KAAK,CAAC,yBAAyB,GAAG,GAAG,CAAC,CAAC;YACnD,CAAC;YACD,OAAO,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACrB,CAAC,CAAC,CAAC;QACL,OAAO,GAAG,EAAE;YACV,KAAK,MAAM,MAAM,IAAI,QAAQ;gBAAE,MAAM,EAAE,CAAC;QAC1C,CAAC,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACH,OAAO;QACL,OAAO,MAAM,CAAC,WAAW,CACvB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;aAC5B,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC;aACjC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC;YACnB,GAAG;YACH,CAAC,GAAG,IAAa,EAAE,EAAE;gBACnB,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;YACtB,CAAC;SACF,CAAC,CACS,CAAC;IAClB,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ListenerSet.d.ts","sourceRoot":"","sources":["../../src/conversation/ListenerSet.ts"],"names":[],"mappings":"AAAA,qBAAa,WAAW,CAAC,IAAI,SAAS,OAAO,EAAE;IAC7C,OAAO,CAAC,SAAS,CAAsC;IAEvD,GAAG,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,IAAI,GAAG,MAAM,IAAI;IAO5C,MAAM,CAAC,GAAG,IAAI,EAAE,IAAI,GAAG,IAAI;IAI3B,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export class ListenerSet {
|
|
2
|
+
listeners = new Set();
|
|
3
|
+
add(fn) {
|
|
4
|
+
this.listeners.add(fn);
|
|
5
|
+
return () => {
|
|
6
|
+
this.listeners.delete(fn);
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
invoke(...args) {
|
|
10
|
+
for (const fn of this.listeners)
|
|
11
|
+
fn(...args);
|
|
12
|
+
}
|
|
13
|
+
get size() {
|
|
14
|
+
return this.listeners.size;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=ListenerSet.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ListenerSet.js","sourceRoot":"","sources":["../../src/conversation/ListenerSet.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,WAAW;IACd,SAAS,GAAG,IAAI,GAAG,EAA2B,CAAC;IAEvD,GAAG,CAAC,EAA2B;QAC7B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACvB,OAAO,GAAG,EAAE;YACV,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC5B,CAAC,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,GAAG,IAAU;QAClB,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,SAAS;YAAE,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;IAC/C,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;IAC7B,CAAC;CACF"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { SessionConfig, ClientToolsConfig, InputConfig, AudioWorkletConfig, OutputConfig, FormatConfig, Callbacks, Location } from "@elevenlabs/client";
|
|
2
|
+
export type ClientToolResult = string | number | void;
|
|
3
|
+
export type ClientTool<Parameters extends Record<string, unknown> = Record<string, unknown>, Result extends ClientToolResult = ClientToolResult> = (parameters: Parameters) => Promise<Result> | Result;
|
|
4
|
+
export type ClientTools = Record<string, ClientTool>;
|
|
5
|
+
export type HookCallbacks = Pick<Callbacks, "onConnect" | "onDisconnect" | "onError" | "onMessage" | "onAudio" | "onModeChange" | "onStatusChange" | "onCanSendFeedbackChange" | "onDebug" | "onUnhandledClientToolCall" | "onVadScore" | "onInterruption" | "onAgentToolResponse" | "onAgentToolRequest" | "onConversationMetadata" | "onMCPToolCall" | "onMCPConnectionStatus" | "onAsrInitiationMetadata" | "onAgentChatResponsePart" | "onAudioAlignment">;
|
|
6
|
+
export type HookOptions = Partial<SessionConfig & HookCallbacks & ClientToolsConfig & InputConfig & OutputConfig & AudioWorkletConfig & FormatConfig & {
|
|
7
|
+
serverLocation?: Location | string;
|
|
8
|
+
}>;
|
|
9
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/conversation/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,iBAAiB,EACjB,WAAW,EACX,kBAAkB,EAClB,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,QAAQ,EACT,MAAM,oBAAoB,CAAC;AAE5B,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;AAEtD,MAAM,MAAM,UAAU,CACpB,UAAU,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpE,MAAM,SAAS,gBAAgB,GAAG,gBAAgB,IAChD,CAAC,UAAU,EAAE,UAAU,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;AAEzD,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAErD,MAAM,MAAM,aAAa,GAAG,IAAI,CAC9B,SAAS,EACP,WAAW,GACX,cAAc,GACd,SAAS,GACT,WAAW,GACX,SAAS,GACT,cAAc,GACd,gBAAgB,GAChB,yBAAyB,GACzB,SAAS,GACT,2BAA2B,GAC3B,YAAY,GACZ,gBAAgB,GAChB,qBAAqB,GACrB,oBAAoB,GACpB,wBAAwB,GACxB,eAAe,GACf,uBAAuB,GACvB,yBAAyB,GACzB,yBAAyB,GACzB,kBAAkB,CACrB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG,OAAO,CAC/B,aAAa,GACX,aAAa,GACb,iBAAiB,GACjB,WAAW,GACX,YAAY,GACZ,kBAAkB,GAClB,YAAY,GAAG;IACb,cAAc,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;CACpC,CACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/conversation/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { HookOptions } from "./types";
|
|
2
|
+
export type UseConversationOptions = HookOptions & {
|
|
3
|
+
micMuted?: boolean;
|
|
4
|
+
volume?: number;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Convenience hook that combines all granular conversation hooks into a single
|
|
8
|
+
* return value. Less performant than using individual hooks because any state
|
|
9
|
+
* change in any sub-context triggers a re-render of the consuming component.
|
|
10
|
+
*
|
|
11
|
+
* Accepts optional `micMuted`, `volume`, session config, and callback props.
|
|
12
|
+
* Session config and callbacks passed here are used as defaults when calling
|
|
13
|
+
* `startSession()` without arguments. Callbacks are also registered with the
|
|
14
|
+
* provider so they stay up-to-date across re-renders.
|
|
15
|
+
*
|
|
16
|
+
* Must be used within a `ConversationProvider`.
|
|
17
|
+
*/
|
|
18
|
+
export declare function useConversation(props?: UseConversationOptions): {
|
|
19
|
+
startSession: (options?: HookOptions) => void;
|
|
20
|
+
status: import("./ConversationStatus").ConversationStatus;
|
|
21
|
+
message: string | undefined;
|
|
22
|
+
isMuted: boolean;
|
|
23
|
+
setMuted: (isMuted: boolean) => void;
|
|
24
|
+
mode: "speaking" | "listening";
|
|
25
|
+
isSpeaking: boolean;
|
|
26
|
+
isListening: boolean;
|
|
27
|
+
canSendFeedback: boolean;
|
|
28
|
+
sendFeedback: (like: boolean) => void;
|
|
29
|
+
endSession: () => void;
|
|
30
|
+
sendUserMessage: (text: string) => void;
|
|
31
|
+
sendContextualUpdate: (text: string) => void;
|
|
32
|
+
sendUserActivity: () => void;
|
|
33
|
+
sendMCPToolApprovalResult: (toolCallId: string, isApproved: boolean) => void;
|
|
34
|
+
setVolume: (options: {
|
|
35
|
+
volume: number;
|
|
36
|
+
}) => void;
|
|
37
|
+
changeInputDevice: (config: import("@elevenlabs/client").FormatConfig & import("@elevenlabs/client").InputDeviceConfig) => Promise<void>;
|
|
38
|
+
changeOutputDevice: (config: import("@elevenlabs/client").FormatConfig & import("@elevenlabs/client").OutputConfig) => Promise<void>;
|
|
39
|
+
getInputByteFrequencyData: () => Uint8Array;
|
|
40
|
+
getOutputByteFrequencyData: () => Uint8Array;
|
|
41
|
+
getInputVolume: () => number;
|
|
42
|
+
getOutputVolume: () => number;
|
|
43
|
+
getId: () => string;
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=useConversation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useConversation.d.ts","sourceRoot":"","sources":["../../src/conversation/useConversation.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C,MAAM,MAAM,sBAAsB,GAAG,WAAW,GAAG;IACjD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,KAAK,GAAE,sBAA2B;6BAiBnD,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;EA+CzB"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef } from "react";
|
|
2
|
+
import { CALLBACK_KEYS } from "@elevenlabs/client/internal";
|
|
3
|
+
import { useConversationControls } from "./ConversationControls";
|
|
4
|
+
import { useConversationStatus } from "./ConversationStatus";
|
|
5
|
+
import { useConversationInput } from "./ConversationInput";
|
|
6
|
+
import { useConversationMode } from "./ConversationMode";
|
|
7
|
+
import { useConversationFeedback } from "./ConversationFeedback";
|
|
8
|
+
import { useRawConversation, useRegisterCallbacks, } from "./ConversationContext";
|
|
9
|
+
import { useStableCallbacks } from "./useStableCallbacks";
|
|
10
|
+
/**
|
|
11
|
+
* Convenience hook that combines all granular conversation hooks into a single
|
|
12
|
+
* return value. Less performant than using individual hooks because any state
|
|
13
|
+
* change in any sub-context triggers a re-render of the consuming component.
|
|
14
|
+
*
|
|
15
|
+
* Accepts optional `micMuted`, `volume`, session config, and callback props.
|
|
16
|
+
* Session config and callbacks passed here are used as defaults when calling
|
|
17
|
+
* `startSession()` without arguments. Callbacks are also registered with the
|
|
18
|
+
* provider so they stay up-to-date across re-renders.
|
|
19
|
+
*
|
|
20
|
+
* Must be used within a `ConversationProvider`.
|
|
21
|
+
*/
|
|
22
|
+
export function useConversation(props = {}) {
|
|
23
|
+
const { micMuted, volume, ...hookOptions } = props;
|
|
24
|
+
const stableCallbacks = useStableCallbacks(hookOptions);
|
|
25
|
+
useRegisterCallbacks(stableCallbacks);
|
|
26
|
+
const hookOptionsRef = useRef(hookOptions);
|
|
27
|
+
// eslint-disable-next-line react-hooks/refs -- intentional sync during render for latest-ref pattern
|
|
28
|
+
hookOptionsRef.current = hookOptions;
|
|
29
|
+
const controls = useConversationControls();
|
|
30
|
+
const { status, message } = useConversationStatus();
|
|
31
|
+
const { isMuted, setMuted } = useConversationInput();
|
|
32
|
+
const { mode, isSpeaking, isListening } = useConversationMode();
|
|
33
|
+
const { canSendFeedback, sendFeedback } = useConversationFeedback();
|
|
34
|
+
const startSession = useCallback((options) => {
|
|
35
|
+
// Strip callbacks from the hook-level defaults: those are registered via
|
|
36
|
+
// useRegisterCallbacks and kept ref-stable across renders.
|
|
37
|
+
// NOTE: We intentionally do NOT strip callbacks from the `options` parameter
|
|
38
|
+
// here. Callbacks passed directly to startSession() are treated as one-shot
|
|
39
|
+
// per-session overrides, and may capture render-local state. This asymmetry
|
|
40
|
+
// (hook callbacks are ref-stable; startSession callbacks are one-shot) is
|
|
41
|
+
// intentional and relied on by the public API.
|
|
42
|
+
const sessionConfig = { ...hookOptionsRef.current };
|
|
43
|
+
for (const key of CALLBACK_KEYS) {
|
|
44
|
+
delete sessionConfig[key];
|
|
45
|
+
}
|
|
46
|
+
controls.startSession({
|
|
47
|
+
...sessionConfig,
|
|
48
|
+
...options,
|
|
49
|
+
});
|
|
50
|
+
}, [controls, hookOptionsRef]);
|
|
51
|
+
const conversation = useRawConversation();
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
if (micMuted !== undefined && conversation) {
|
|
54
|
+
setMuted(micMuted);
|
|
55
|
+
}
|
|
56
|
+
}, [micMuted, conversation, setMuted]);
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
if (volume !== undefined && conversation) {
|
|
59
|
+
conversation.setVolume({ volume });
|
|
60
|
+
}
|
|
61
|
+
}, [volume, conversation]);
|
|
62
|
+
return {
|
|
63
|
+
...controls,
|
|
64
|
+
startSession,
|
|
65
|
+
status,
|
|
66
|
+
message,
|
|
67
|
+
isMuted: micMuted ?? isMuted,
|
|
68
|
+
setMuted,
|
|
69
|
+
mode,
|
|
70
|
+
isSpeaking,
|
|
71
|
+
isListening,
|
|
72
|
+
canSendFeedback,
|
|
73
|
+
sendFeedback,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=useConversation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useConversation.js","sourceRoot":"","sources":["../../src/conversation/useConversation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAE5D,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EACL,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAQ1D;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,eAAe,CAAC,QAAgC,EAAE;IAChE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,WAAW,EAAE,GAAG,KAAK,CAAC;IAEnD,MAAM,eAAe,GAAG,kBAAkB,CAAC,WAAW,CAAC,CAAC;IACxD,oBAAoB,CAAC,eAAe,CAAC,CAAC;IAEtC,MAAM,cAAc,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;IAC3C,qGAAqG;IACrG,cAAc,CAAC,OAAO,GAAG,WAAW,CAAC;IAErC,MAAM,QAAQ,GAAG,uBAAuB,EAAE,CAAC;IAC3C,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,qBAAqB,EAAE,CAAC;IACpD,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,oBAAoB,EAAE,CAAC;IACrD,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,GAAG,mBAAmB,EAAE,CAAC;IAChE,MAAM,EAAE,eAAe,EAAE,YAAY,EAAE,GAAG,uBAAuB,EAAE,CAAC;IAEpE,MAAM,YAAY,GAAG,WAAW,CAC9B,CAAC,OAAqB,EAAE,EAAE;QACxB,yEAAyE;QACzE,2DAA2D;QAC3D,6EAA6E;QAC7E,4EAA4E;QAC5E,4EAA4E;QAC5E,0EAA0E;QAC1E,+CAA+C;QAC/C,MAAM,aAAa,GAAG,EAAE,GAAG,cAAc,CAAC,OAAO,EAAE,CAAC;QACpD,KAAK,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;YAChC,OAAQ,aAAyC,CAAC,GAAG,CAAC,CAAC;QACzD,CAAC;QACD,QAAQ,CAAC,YAAY,CAAC;YACpB,GAAG,aAAa;YAChB,GAAG,OAAO;SACI,CAAC,CAAC;IACpB,CAAC,EACD,CAAC,QAAQ,EAAE,cAAc,CAAC,CAC3B,CAAC;IAEF,MAAM,YAAY,GAAG,kBAAkB,EAAE,CAAC;IAE1C,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,QAAQ,KAAK,SAAS,IAAI,YAAY,EAAE,CAAC;YAC3C,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACrB,CAAC;IACH,CAAC,EAAE,CAAC,QAAQ,EAAE,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC;IAEvC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,MAAM,KAAK,SAAS,IAAI,YAAY,EAAE,CAAC;YACzC,YAAY,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;QACrC,CAAC;IACH,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;IAE3B,OAAO;QACL,GAAG,QAAQ;QACX,YAAY;QACZ,MAAM;QACN,OAAO;QACP,OAAO,EAAE,QAAQ,IAAI,OAAO;QAC5B,QAAQ;QACR,IAAI;QACJ,UAAU;QACV,WAAW;QACX,eAAe;QACf,YAAY;KACb,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Callbacks } from "@elevenlabs/client";
|
|
2
|
+
import type { HookOptions } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* Wraps user-provided callback props in stable ref-backed functions,
|
|
5
|
+
* preventing stale closure bugs when the session outlives renders.
|
|
6
|
+
*
|
|
7
|
+
* Returns a `Partial<Callbacks>` containing only the keys the caller
|
|
8
|
+
* actually provided. Function references are stable per key across
|
|
9
|
+
* renders, but always invoke the latest prop value. The returned object
|
|
10
|
+
* reference is stable as long as the set of provided keys doesn't change.
|
|
11
|
+
*/
|
|
12
|
+
export declare function useStableCallbacks(props: HookOptions): Partial<Callbacks>;
|
|
13
|
+
//# sourceMappingURL=useStableCallbacks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useStableCallbacks.d.ts","sourceRoot":"","sources":["../../src/conversation/useStableCallbacks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,CA6BzE"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { useMemo, useRef } from "react";
|
|
2
|
+
import { CALLBACK_KEYS } from "@elevenlabs/client/internal";
|
|
3
|
+
/**
|
|
4
|
+
* Wraps user-provided callback props in stable ref-backed functions,
|
|
5
|
+
* preventing stale closure bugs when the session outlives renders.
|
|
6
|
+
*
|
|
7
|
+
* Returns a `Partial<Callbacks>` containing only the keys the caller
|
|
8
|
+
* actually provided. Function references are stable per key across
|
|
9
|
+
* renders, but always invoke the latest prop value. The returned object
|
|
10
|
+
* reference is stable as long as the set of provided keys doesn't change.
|
|
11
|
+
*/
|
|
12
|
+
export function useStableCallbacks(props) {
|
|
13
|
+
// Store the latest prop value for each callback in a ref.
|
|
14
|
+
// Uses Record<string, unknown> to avoid TypeScript's union-to-intersection
|
|
15
|
+
// issue when indexing Callbacks with a union of all its keys.
|
|
16
|
+
const callbackRefs = useRef({});
|
|
17
|
+
for (const key of CALLBACK_KEYS) {
|
|
18
|
+
callbackRefs.current[key] = props[key];
|
|
19
|
+
}
|
|
20
|
+
// Compute a stable scalar from the set of provided keys so we can
|
|
21
|
+
// memoize the result object.
|
|
22
|
+
const activeKeys = CALLBACK_KEYS.filter(key => props[key] !== undefined);
|
|
23
|
+
return useMemo(() => Object.fromEntries(activeKeys.map(key => [
|
|
24
|
+
key,
|
|
25
|
+
(...args) => {
|
|
26
|
+
const fn = callbackRefs.current[key];
|
|
27
|
+
fn?.(...args);
|
|
28
|
+
},
|
|
29
|
+
])),
|
|
30
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps -- joined string is a stable scalar derived from activeKeys
|
|
31
|
+
[activeKeys.join("|")]);
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=useStableCallbacks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useStableCallbacks.js","sourceRoot":"","sources":["../../src/conversation/useStableCallbacks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAExC,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAG5D;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAkB;IACnD,0DAA0D;IAC1D,2EAA2E;IAC3E,8DAA8D;IAC9D,MAAM,YAAY,GAAG,MAAM,CAA0B,EAAE,CAAC,CAAC;IACzD,KAAK,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;QAChC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;IACzC,CAAC;IAED,kEAAkE;IAClE,6BAA6B;IAC7B,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,SAAS,CAAC,CAAC;IAEzE,OAAO,OAAO,CACZ,GAAG,EAAE,CACH,MAAM,CAAC,WAAW,CAChB,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;QACpB,GAAG;QACH,CAAC,GAAG,IAAe,EAAE,EAAE;YACrB,MAAM,EAAE,GAAG,YAAY,CAAC,OAAO,CAAC,GAAG,CAEtB,CAAC;YACd,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;QAChB,CAAC;KACF,CAAC,CACmB;IACzB,mHAAmH;IACnH,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CACvB,CAAC;AACJ,CAAC"}
|