@keyframelabs/elements 0.0.3 → 0.0.4

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 CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Headless vanilla TypeScript library for embedding Persona avatars. Handles video/audio elements, session wiring, microphone input, and voice agent connections.
4
4
 
5
- No UI included — that's your job (or use `@keyframelabs/components-react`).
5
+ No UI included — see `@keyframelabs/components-react` for a React example.
6
6
 
7
7
  ## Install
8
8
 
@@ -12,6 +12,13 @@ pnpm add @keyframelabs/elements
12
12
 
13
13
  ## Usage
14
14
 
15
+ Two classes are available depending on your integration:
16
+
17
+ - **`PersonaEmbed`** — Fully managed KFL embed workflow. Uses a publishable key to handle authentication and session creation automatically.
18
+ - **`PersonaView`** — Bring Your Own Backend (BYOB). Accepts pre-fetched session/agent details from your own backend.
19
+
20
+ ### PersonaEmbed (Publishable Key)
21
+
15
22
  ```ts
16
23
  import { PersonaEmbed } from '@keyframelabs/elements';
17
24
 
@@ -32,11 +39,45 @@ embed.toggleMute();
32
39
  embed.disconnect();
33
40
  ```
34
41
 
42
+ ### PersonaView (Bring Your Own Backend)
43
+
44
+ Use this when you want to manage authentication through your own backend.
45
+
46
+ First, fetch session details from your backend:
47
+
48
+ ```ts
49
+ const response = await fetch('/api/persona/session', { method: 'POST' });
50
+ const { sessionDetails, voiceAgentDetails } = await response.json();
51
+ ```
52
+
53
+ Then pass them to PersonaView:
54
+
55
+ ```ts
56
+ import { PersonaView } from '@keyframelabs/elements';
57
+
58
+ const view = new PersonaView({
59
+ container: document.getElementById('avatar')!,
60
+ sessionDetails,
61
+ voiceAgentDetails,
62
+ videoFit: 'contain',
63
+ onStateChange: (status) => console.log('Status:', status),
64
+ onAgentStateChange: (state) => console.log('Agent:', state),
65
+ onDisconnect: () => console.log('Disconnected'),
66
+ onError: (err) => console.error(err),
67
+ });
68
+
69
+ await view.connect();
70
+
71
+ // Later...
72
+ view.toggleMute();
73
+ view.disconnect();
74
+ ```
75
+
35
76
  ## API
36
77
 
37
- Create your embed config at platform.keyframelabs.com to get a publishable key.
78
+ ### `PersonaEmbed` (Fully Managed)
38
79
 
39
- ### `PersonaEmbed`
80
+ Create your embed config at platform.keyframelabs.com to get a publishable key. KFL handles session creation, authentication, and agent configuration.
40
81
 
41
82
  #### Constructor Options
42
83
 
@@ -69,8 +110,46 @@ Create your embed config at platform.keyframelabs.com to get a publishable key.
69
110
  | `disconnect()` | Disconnect and cleanup |
70
111
  | `toggleMute()` | Toggle microphone mute |
71
112
 
113
+ ### `PersonaView` (BYOB)
114
+
115
+ For self-hosted backends that manage their own session creation and authentication.
116
+
117
+ #### Constructor Options
118
+
119
+ | Option | Type | Default | Description |
120
+ |--------|------|---------|-------------|
121
+ | `container` | `HTMLElement` | required | Target container for video/audio elements |
122
+ | `sessionDetails` | `SessionDetails` | required | Session config from your backend |
123
+ | `voiceAgentDetails` | `VoiceAgentDetails` | required | Voice agent config from your backend |
124
+ | `videoFit` | `'cover' \| 'contain'` | `'cover'` | Video scaling mode |
125
+ | `onStateChange` | `(status: EmbedStatus) => void` | - | Status callback |
126
+ | `onAgentStateChange` | `(state: AgentState) => void` | - | Agent state callback |
127
+ | `onDisconnect` | `() => void` | - | Disconnect callback |
128
+ | `onError` | `(err: Error) => void` | - | Error callback |
129
+
130
+ #### Types
131
+
132
+ ```ts
133
+ type SessionDetails = {
134
+ server_url: string;
135
+ participant_token: string;
136
+ agent_identity: string;
137
+ };
138
+
139
+ type VoiceAgentDetails = {
140
+ type: 'gemini' | 'elevenlabs' | 'cartesia';
141
+ token?: string; // For gemini, cartesia
142
+ agent_id?: string; // For elevenlabs, cartesia
143
+ signed_url?: string; // For elevenlabs
144
+ };
145
+ ```
146
+
147
+ #### Properties & Methods
148
+
149
+ Same as `PersonaEmbed` (see above).
150
+
72
151
  ## Voice Agents
73
152
 
74
- Supports Gemini Live, ElevenLabs, and Cartesia agents. The agent type is determined by your embed config.
153
+ Supports Gemini Live, ElevenLabs, and Cartesia agents. The agent type is determined by your embed config or `voiceAgentDetails.type`.
75
154
 
76
155
  If you need support for new voice agent platforms built in, drop us a line at support@keyframelabs.com
@@ -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;
@@ -1,7 +1,7 @@
1
1
  import { AgentState } from './agents';
2
- export type EmbedStatus = 'connecting' | 'connected' | 'error' | 'disconnected';
3
- export type VideoFit = 'cover' | 'contain';
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, EmbedStatus, VideoFit } from './PersonaEmbed';
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';