@keyframelabs/elements 0.0.3 → 0.0.5
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 +114 -33
- package/dist/ApiError.d.ts +20 -0
- package/dist/PersonaEmbed.d.ts +3 -11
- package/dist/PersonaView.d.ts +67 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.js +791 -1
- package/dist/types.d.ts +20 -0
- package/package.json +16 -8
- package/dist/index.mjs +0 -636
package/README.md
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
# @keyframelabs/elements
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Framework-agnostic primitives for Keyframe Labs.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**Which package should I use?**
|
|
6
|
+
- **@keyframelabs/sdk** (high control)
|
|
7
|
+
- You implement the UI, state management, and agent/llm binding yourself
|
|
8
|
+
- **@keyframelabs/elements** (custom UI)
|
|
9
|
+
- You implement the UI; we handle the state and agent/llm binding (framework-agnostic)
|
|
10
|
+
- **@keyframelabs/react**: (drop-in)
|
|
11
|
+
- We handle the UI, state, and agent/llm binding
|
|
6
12
|
|
|
7
13
|
## Install
|
|
8
14
|
|
|
@@ -12,13 +18,21 @@ pnpm add @keyframelabs/elements
|
|
|
12
18
|
|
|
13
19
|
## Usage
|
|
14
20
|
|
|
21
|
+
This package provides two primary classes depending on your integration strategy:
|
|
22
|
+
1. **`PersonaEmbed`**: Fully managed. Uses a publishable key. Best for rapid frontend integration.
|
|
23
|
+
2. **`PersonaView`**: Bring your own backend. Uses session tokens generated by your server.
|
|
24
|
+
|
|
25
|
+
### Option A: PersonaEmbed (managed)
|
|
26
|
+
|
|
27
|
+
Use this if you have configured an embed in the Keyframe platform dashboard.
|
|
28
|
+
|
|
15
29
|
```ts
|
|
16
30
|
import { PersonaEmbed } from '@keyframelabs/elements';
|
|
17
31
|
|
|
18
32
|
const embed = new PersonaEmbed({
|
|
19
|
-
container: document.getElementById('
|
|
33
|
+
container: document.getElementById('persona-container'),
|
|
20
34
|
publishableKey: 'kfl_pk_live_...',
|
|
21
|
-
videoFit: '
|
|
35
|
+
videoFit: 'cover',
|
|
22
36
|
onStateChange: (status) => console.log('Status:', status),
|
|
23
37
|
onAgentStateChange: (state) => console.log('Agent:', state),
|
|
24
38
|
onDisconnect: () => console.log('Disconnected'),
|
|
@@ -28,49 +42,116 @@ const embed = new PersonaEmbed({
|
|
|
28
42
|
await embed.connect();
|
|
29
43
|
|
|
30
44
|
// Later...
|
|
31
|
-
embed.toggleMute();
|
|
32
45
|
embed.disconnect();
|
|
33
46
|
```
|
|
34
47
|
|
|
35
|
-
|
|
48
|
+
### Option B: PersonaView (bring your own backend)
|
|
49
|
+
|
|
50
|
+
Use this when you want to manage authentication through your own backend.
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
import { PersonaView } from '@keyframelabs/elements';
|
|
54
|
+
|
|
55
|
+
const view = new PersonaView({
|
|
56
|
+
container: document.getElementById('persona-container')!,
|
|
57
|
+
sessionDetails,
|
|
58
|
+
voiceAgentDetails,
|
|
59
|
+
videoFit: 'contain',
|
|
60
|
+
onStateChange: (status) => console.log('Status:', status),
|
|
61
|
+
onAgentStateChange: (state) => console.log('Agent:', state),
|
|
62
|
+
onDisconnect: () => console.log('Disconnected'),
|
|
63
|
+
onError: (err) => console.error(err),
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
await view.connect();
|
|
36
67
|
|
|
37
|
-
|
|
68
|
+
// Later...
|
|
69
|
+
view.disconnect();
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Supported agents and real-time LLMs
|
|
73
|
+
|
|
74
|
+
Supports ElevenLabs Agents, Cartesia Line, and Gemini Live.
|
|
75
|
+
|
|
76
|
+
For `PersonaEmbed`, this is determined by the values you set in the Keyframe platform dashboard.
|
|
77
|
+
|
|
78
|
+
For `PersonaView`, this is determined by `voiceAgentDetails`.
|
|
79
|
+
|
|
80
|
+
## API
|
|
38
81
|
|
|
39
82
|
### `PersonaEmbed`
|
|
40
83
|
|
|
41
|
-
####
|
|
84
|
+
#### Options
|
|
42
85
|
|
|
43
|
-
| Option
|
|
44
|
-
|
|
45
|
-
| `container`
|
|
46
|
-
| `publishableKey`
|
|
47
|
-
| `apiBaseUrl`
|
|
48
|
-
| `videoFit`
|
|
49
|
-
| `onStateChange`
|
|
50
|
-
| `onAgentStateChange` | `(state: AgentState) => void` |
|
|
51
|
-
| `onDisconnect`
|
|
52
|
-
| `onError`
|
|
86
|
+
| Option | Type | Default | Description |
|
|
87
|
+
| -------------------- | ------------------------------- | -------------------------------- | ---------------------------------------------- |
|
|
88
|
+
| `container` | `HTMLElement` | Required | Target container for video and audio elements. |
|
|
89
|
+
| `publishableKey` | `string` | Required | Your publishable embed key. |
|
|
90
|
+
| `apiBaseUrl` | `string` | `'https://api.keyframelabs.com'` | Base URL for the Keyframe API. |
|
|
91
|
+
| `videoFit` | `'cover' \| 'contain'` | `'cover'` | Video scaling mode (`object-fit`). |
|
|
92
|
+
| `onStateChange` | `(status: EmbedStatus) => void` | — | Fired when connection status changes. |
|
|
93
|
+
| `onAgentStateChange` | `(state: AgentState) => void` | — | Fired when agent state changes. |
|
|
94
|
+
| `onDisconnect` | `() => void` | — | Fired when the session disconnects. |
|
|
95
|
+
| `onError` | `(err: Error) => void` | — | Fired on fatal errors. |
|
|
96
|
+
|
|
97
|
+
#### Methods
|
|
98
|
+
|
|
99
|
+
| Method | Signature | Description |
|
|
100
|
+
| ------------ | --------------------- | -------------------------------------------------- |
|
|
101
|
+
| `connect` | `() => Promise<void>` | Starts the session and establishes the connection. |
|
|
102
|
+
| `disconnect` | `() => void` | Disconnects the session and cleans up resources. |
|
|
103
|
+
| `toggleMute` | `() => void` | Toggles the user's microphone mute state. |
|
|
53
104
|
|
|
54
105
|
#### Properties
|
|
55
106
|
|
|
56
|
-
| Property
|
|
57
|
-
|
|
58
|
-
| `status`
|
|
59
|
-
| `agentState`
|
|
60
|
-
| `isMuted`
|
|
61
|
-
| `videoElement` | `HTMLVideoElement` | The video element |
|
|
62
|
-
| `audioElement` | `HTMLAudioElement` | The audio element |
|
|
107
|
+
| Property | Type | Description |
|
|
108
|
+
| -------------- | ------------------ | -------------------------------------------------------------------------------------- |
|
|
109
|
+
| `status` | `EmbedStatus` | Current connection status: `'connecting' \| 'connected' \| 'disconnected' \| 'error'`. |
|
|
110
|
+
| `agentState` | `AgentState` | Current agent state: `'idle' \| 'listening' \| 'thinking' \| 'speaking'`. |
|
|
111
|
+
| `isMuted` | `boolean` | Whether the microphone is currently muted. |
|
|
112
|
+
| `videoElement` | `HTMLVideoElement` | The underlying video element used for rendering. |
|
|
113
|
+
| `audioElement` | `HTMLAudioElement` | The underlying audio element used for playback. |
|
|
114
|
+
|
|
115
|
+
### `PersonaView`
|
|
116
|
+
|
|
117
|
+
#### Options
|
|
118
|
+
|
|
119
|
+
| Option | Type | Default | Description |
|
|
120
|
+
| -------------------- | ------------------------------- | --------- | ---------------------------------------------- |
|
|
121
|
+
| `container` | `HTMLElement` | Required | Target container for video and audio elements. |
|
|
122
|
+
| `sessionDetails` | `SessionDetails` | Required | Session configuration from your backend. |
|
|
123
|
+
| `voiceAgentDetails` | `VoiceAgentDetails` | Required | Voice agent configuration from your backend. |
|
|
124
|
+
| `videoFit` | `'cover' \| 'contain'` | `'cover'` | Video scaling mode (`object-fit`). |
|
|
125
|
+
| `onStateChange` | `(status: EmbedStatus) => void` | — | Fired when connection status changes. |
|
|
126
|
+
| `onAgentStateChange` | `(state: AgentState) => void` | — | Fired when agent state changes. |
|
|
127
|
+
| `onDisconnect` | `() => void` | — | Fired when the session disconnects. |
|
|
128
|
+
| `onError` | `(err: Error) => void` | — | Fired on fatal errors. |
|
|
63
129
|
|
|
64
130
|
#### Methods
|
|
65
131
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
132
|
+
Same as `PersonaEmbed`.
|
|
133
|
+
|
|
134
|
+
#### Properties
|
|
135
|
+
|
|
136
|
+
Same as `PersonaEmbed`.
|
|
71
137
|
|
|
72
|
-
|
|
138
|
+
#### Types
|
|
139
|
+
|
|
140
|
+
```ts
|
|
141
|
+
type SessionDetails = {
|
|
142
|
+
server_url: string;
|
|
143
|
+
participant_token: string;
|
|
144
|
+
agent_identity: string;
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
type VoiceAgentDetails = {
|
|
148
|
+
type: 'gemini' | 'elevenlabs' | 'cartesia';
|
|
149
|
+
token?: string; // For gemini, cartesia
|
|
150
|
+
agent_id?: string; // For elevenlabs, cartesia
|
|
151
|
+
signed_url?: string; // For elevenlabs
|
|
152
|
+
};
|
|
153
|
+
```
|
|
73
154
|
|
|
74
|
-
|
|
155
|
+
## License
|
|
75
156
|
|
|
76
|
-
|
|
157
|
+
MIT
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type ApiErrorPayload = {
|
|
2
|
+
code?: string;
|
|
3
|
+
message?: string;
|
|
4
|
+
details?: unknown;
|
|
5
|
+
};
|
|
6
|
+
export declare class ApiError extends Error {
|
|
7
|
+
status: number;
|
|
8
|
+
payload?: ApiErrorPayload;
|
|
9
|
+
url?: string;
|
|
10
|
+
constructor(opts: {
|
|
11
|
+
message: string;
|
|
12
|
+
status: number;
|
|
13
|
+
payload?: ApiErrorPayload;
|
|
14
|
+
url?: string;
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
export type ApiErrorResponse = {
|
|
18
|
+
detail?: ApiErrorPayload | string;
|
|
19
|
+
};
|
|
20
|
+
export declare function normalizeFastApiPayload(x: ApiErrorResponse | null): ApiErrorPayload | undefined;
|
package/dist/PersonaEmbed.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AgentState } from './agents';
|
|
2
|
-
|
|
3
|
-
export type VideoFit
|
|
4
|
-
export interface PersonaEmbedOptions {
|
|
2
|
+
import { EmbedStatus, VideoFit, BaseCallbacks } from './types';
|
|
3
|
+
export type { EmbedStatus, VideoFit } from './types';
|
|
4
|
+
export interface PersonaEmbedOptions extends BaseCallbacks {
|
|
5
5
|
/** Target container element */
|
|
6
6
|
container: HTMLElement;
|
|
7
7
|
/** Publishable key from your embed config */
|
|
@@ -10,14 +10,6 @@ export interface PersonaEmbedOptions {
|
|
|
10
10
|
apiBaseUrl?: string;
|
|
11
11
|
/** Video fit mode. 'cover' fills container (may crop), 'contain' shows full video (may have black bars). Default: 'cover' */
|
|
12
12
|
videoFit?: VideoFit;
|
|
13
|
-
/** Called when session disconnects */
|
|
14
|
-
onDisconnect?: () => void;
|
|
15
|
-
/** Called on error */
|
|
16
|
-
onError?: (err: Error) => void;
|
|
17
|
-
/** Called when status changes */
|
|
18
|
-
onStateChange?: (status: EmbedStatus) => void;
|
|
19
|
-
/** Called when agent state changes */
|
|
20
|
-
onAgentStateChange?: (state: AgentState) => void;
|
|
21
13
|
}
|
|
22
14
|
/**
|
|
23
15
|
* Headless Persona avatar with voice agent integration.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { AgentState } from './agents';
|
|
2
|
+
import { EmbedStatus, VideoFit, VoiceAgentDetails, SessionDetails, BaseCallbacks } from './types';
|
|
3
|
+
export interface PersonaViewOptions extends BaseCallbacks {
|
|
4
|
+
/** Target container element */
|
|
5
|
+
container: HTMLElement;
|
|
6
|
+
/** Voice agent configuration from your backend */
|
|
7
|
+
voiceAgentDetails: VoiceAgentDetails;
|
|
8
|
+
/** Session configuration from your backend */
|
|
9
|
+
sessionDetails: SessionDetails;
|
|
10
|
+
/** Video fit mode. 'cover' fills container (may crop), 'contain' shows full video (may have black bars). Default: 'cover' */
|
|
11
|
+
videoFit?: VideoFit;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Headless Persona avatar with voice agent integration (BYOB mode).
|
|
15
|
+
*
|
|
16
|
+
* Creates video/audio elements and handles all wiring.
|
|
17
|
+
* UI (overlays, controls, status) is the consumer's responsibility.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* // Fetch session details from your own backend
|
|
22
|
+
* const { sessionDetails, voiceAgentDetails } = await myBackend.createSession();
|
|
23
|
+
*
|
|
24
|
+
* const view = new PersonaView({
|
|
25
|
+
* container: document.getElementById('avatar'),
|
|
26
|
+
* sessionDetails,
|
|
27
|
+
* voiceAgentDetails,
|
|
28
|
+
* onStateChange: (status) => updateUI(status),
|
|
29
|
+
* });
|
|
30
|
+
* await view.connect();
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export declare class PersonaView {
|
|
34
|
+
private readonly voiceAgentDetails;
|
|
35
|
+
private readonly sessionDetails;
|
|
36
|
+
private readonly callbacks;
|
|
37
|
+
private readonly connectionId;
|
|
38
|
+
private readonly _video;
|
|
39
|
+
private readonly _audio;
|
|
40
|
+
private session;
|
|
41
|
+
private agent;
|
|
42
|
+
private audioContext;
|
|
43
|
+
private processor;
|
|
44
|
+
private stream;
|
|
45
|
+
private _status;
|
|
46
|
+
private _agentState;
|
|
47
|
+
private _isMuted;
|
|
48
|
+
private mounted;
|
|
49
|
+
constructor(options: PersonaViewOptions);
|
|
50
|
+
get status(): EmbedStatus;
|
|
51
|
+
get agentState(): AgentState;
|
|
52
|
+
get isMuted(): boolean;
|
|
53
|
+
get videoElement(): HTMLVideoElement;
|
|
54
|
+
get audioElement(): HTMLAudioElement;
|
|
55
|
+
/** Connect to the session */
|
|
56
|
+
connect(): Promise<void>;
|
|
57
|
+
/** Disconnect and cleanup */
|
|
58
|
+
disconnect(): void;
|
|
59
|
+
/** Toggle microphone mute */
|
|
60
|
+
toggleMute(): void;
|
|
61
|
+
private setStatus;
|
|
62
|
+
private setAgentState;
|
|
63
|
+
private initSession;
|
|
64
|
+
private initMicrophone;
|
|
65
|
+
private connectAgent;
|
|
66
|
+
private cleanup;
|
|
67
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
export { PersonaEmbed } from './PersonaEmbed';
|
|
2
|
-
export type { PersonaEmbedOptions
|
|
2
|
+
export type { PersonaEmbedOptions } from './PersonaEmbed';
|
|
3
|
+
export { PersonaView } from './PersonaView';
|
|
4
|
+
export type { PersonaViewOptions } from './PersonaView';
|
|
5
|
+
export type { EmbedStatus, VideoFit, VoiceAgentDetails, SessionDetails, BaseCallbacks, } from './types';
|
|
3
6
|
export { createAgent, GeminiLiveAgent, ElevenLabsAgent, CartesiaAgent, BaseAgent, AGENT_REGISTRY, getAgentInfo, } from './agents';
|
|
4
7
|
export type { AgentType, AgentState, AgentConfig, AgentEventMap, Agent, AnyAgent, AgentTypeInfo, GeminiLiveConfig, ElevenLabsConfig, CartesiaConfig, } from './agents';
|
|
5
8
|
export { floatTo16BitPCM, resamplePcm, base64ToBytes, bytesToBase64, SAMPLE_RATE, createEventEmitter, } from './agents';
|
|
9
|
+
export { ApiError as KeyframeApiError } from './ApiError';
|
|
10
|
+
export type { ApiErrorPayload as KeyframeApiErrorPayload } from './ApiError';
|