Skip to content

Commit dfce38d

Browse files
feat: integrate agent-session-view block (#321)
1 parent f7cb24b commit dfce38d

19 files changed

Lines changed: 624 additions & 370 deletions

app-config.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@ export interface AppConfig {
1717
audioVisualizerType?: 'bar' | 'wave' | 'grid' | 'radial' | 'aura';
1818
audioVisualizerColor?: `#${string}`;
1919
audioVisualizerColorDark?: `#${string}`;
20+
audioVisualizerColorShift?: number;
2021
audioVisualizerBarCount?: number;
2122
audioVisualizerGridRowCount?: number;
2223
audioVisualizerGridColumnCount?: number;
2324
audioVisualizerRadialBarCount?: number;
2425
audioVisualizerRadialRadius?: number;
25-
audioVisualizerAuraColorShift?: number;
2626
audioVisualizerWaveLineWidth?: number;
2727

2828
// agent dispatch configuration
@@ -49,9 +49,10 @@ export const APP_CONFIG_DEFAULTS: AppConfig = {
4949
startButtonText: 'Start call',
5050

5151
// optional: audio visualization configuration
52+
// audioVisualizerType: 'bar',
5253
// audioVisualizerColor: '#002cf2',
5354
// audioVisualizerColorDark: '#1fd5f9',
54-
// audioVisualizerType: 'bar',
55+
// audioVisualizerColorShift: 0.3,
5556
// audioVisualizerBarCount: 5,
5657
// audioVisualizerType: 'radial',
5758
// audioVisualizerRadialBarCount: 24,
@@ -62,7 +63,6 @@ export const APP_CONFIG_DEFAULTS: AppConfig = {
6263
// audioVisualizerType: 'wave',
6364
// audioVisualizerWaveLineWidth: 3,
6465
// audioVisualizerType: 'aura',
65-
// audioVisualizerAuraColorShift: 0.3,
6666

6767
// agent dispatch configuration
6868
agentName: process.env.AGENT_NAME ?? undefined,
Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ const LIVEKIT_URL = process.env.LIVEKIT_URL;
1818
export const revalidate = 0;
1919

2020
export async function POST(req: Request) {
21+
if (process.env.NODE_ENV !== 'development') {
22+
throw new Error(
23+
'THIS API ROUTE IS INSECURE. DO NOT USE THIS ROUTE IN PRODUCTION WITHOUT AN AUTHENTICATION LAYER.'
24+
);
25+
}
26+
2127
try {
2228
if (LIVEKIT_URL === undefined) {
2329
throw new Error('LIVEKIT_URL is not defined');
@@ -29,9 +35,10 @@ export async function POST(req: Request) {
2935
throw new Error('LIVEKIT_API_SECRET is not defined');
3036
}
3137

32-
// Parse agent configuration from request body
38+
// Parse room config from request body.
3339
const body = await req.json();
34-
const agentName: string = body?.room_config?.agents?.[0]?.agent_name;
40+
// Recreate the RoomConfiguration object from JSON object.
41+
const roomConfig = RoomConfiguration.fromJson(body?.room_config, { ignoreUnknownFields: true });
3542

3643
// Generate participant token
3744
const participantName = 'user';
@@ -41,15 +48,15 @@ export async function POST(req: Request) {
4148
const participantToken = await createParticipantToken(
4249
{ identity: participantIdentity, name: participantName },
4350
roomName,
44-
agentName
51+
roomConfig
4552
);
4653

4754
// Return connection details
4855
const data: ConnectionDetails = {
4956
serverUrl: LIVEKIT_URL,
5057
roomName,
51-
participantToken: participantToken,
5258
participantName,
59+
participantToken,
5360
};
5461
const headers = new Headers({
5562
'Cache-Control': 'no-store',
@@ -66,7 +73,7 @@ export async function POST(req: Request) {
6673
function createParticipantToken(
6774
userInfo: AccessTokenOptions,
6875
roomName: string,
69-
agentName?: string
76+
roomConfig: RoomConfiguration
7077
): Promise<string> {
7178
const at = new AccessToken(API_KEY, API_SECRET, {
7279
...userInfo,
@@ -81,10 +88,8 @@ function createParticipantToken(
8188
};
8289
at.addGrant(grant);
8390

84-
if (agentName) {
85-
at.roomConfig = new RoomConfiguration({
86-
agents: [{ agentName }],
87-
});
91+
if (roomConfig) {
92+
at.roomConfig = roomConfig;
8893
}
8994

9095
return at.toJwt();

components/agents-ui/agent-audio-visualizer-aura.tsx

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,18 @@ import { ReactShaderToy } from '@/components/agents-ui/react-shader-toy';
88
import { useAgentAudioVisualizerAura } from '@/hooks/agents-ui/use-agent-audio-visualizer-aura';
99
import { cn } from '@/lib/shadcn/utils';
1010

11+
/**
12+
* @license
13+
*
14+
* Originally developed for Unicorn Studio
15+
* https://unicorn.studio
16+
*
17+
* Licensed under the Polyform Non-Resale License 1.0.0
18+
* https://polyformproject.org/licenses/non-resale/1.0.0/
19+
*
20+
* © 2026 UNCRN LLC
21+
*/
22+
1123
const DEFAULT_COLOR = '#1FD5F9';
1224

1325
function hexToRgb(hexColor: string) {
@@ -236,10 +248,10 @@ interface AuraShaderProps {
236248
blur?: number;
237249

238250
/**
239-
* Color of the aura
251+
* Color of the aura in hexidecimal format.
240252
* @default '#1FD5F9'
241253
*/
242-
color?: string;
254+
color?: `#${string}`;
243255

244256
/**
245257
* Color variation across layers (0-1)
@@ -361,10 +373,10 @@ export interface AgentAudioVisualizerAuraProps {
361373
*/
362374
state?: AgentState;
363375
/**
364-
* The color of the aura in hex format.
376+
* The color of the aura in hexidecimal format.
365377
* @defaultValue '#1FD5F9'
366378
*/
367-
color?: string;
379+
color?: `#${string}`;
368380
/**
369381
* The color shift of the aura.
370382
* @defaultValue 0.05
@@ -428,11 +440,7 @@ export function AgentAudioVisualizerAura({
428440
amplitude={amplitude}
429441
frequency={frequency}
430442
brightness={brightness}
431-
className={cn(
432-
AgentAudioVisualizerAuraVariants({ size }),
433-
'overflow-hidden rounded-full',
434-
className
435-
)}
443+
className={cn(AgentAudioVisualizerAuraVariants({ size }), className)}
436444
{...props}
437445
/>
438446
);

components/agents-ui/agent-audio-visualizer-bar.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ function cloneSingleChild(
4646
export const AgentAudioVisualizerBarElementVariants = cva(
4747
[
4848
'rounded-full transition-colors duration-250 ease-linear',
49-
'bg-transparent data-[lk-highlighted=true]:bg-current',
49+
'bg-current/10 data-[lk-highlighted=true]:bg-current',
5050
],
5151
{
5252
variants: {
@@ -93,6 +93,10 @@ export interface AgentAudioVisualizerBarProps {
9393
* @defaultValue 'connecting'
9494
*/
9595
state?: AgentState;
96+
/**
97+
* The color of the bars in hexidecimal format.
98+
*/
99+
color?: `#${string}`;
96100
/**
97101
* The number of bars to display in the visualizer.
98102
* If not provided, defaults based on size: 3 for 'icon'/'sm', 5 for others.
@@ -132,10 +136,12 @@ export interface AgentAudioVisualizerBarProps {
132136
export function AgentAudioVisualizerBar({
133137
size = 'md',
134138
state = 'connecting',
139+
color,
135140
barCount,
136141
audioTrack,
137142
className,
138143
children,
144+
style,
139145
...props
140146
}: AgentAudioVisualizerBarProps &
141147
VariantProps<typeof AgentAudioVisualizerBarVariants> &
@@ -192,6 +198,7 @@ export function AgentAudioVisualizerBar({
192198
return (
193199
<div
194200
data-lk-state={state}
201+
style={{ ...style, color } as CSSProperties}
195202
className={cn(AgentAudioVisualizerBarVariants({ size }), className)}
196203
{...props}
197204
>

components/agents-ui/agent-audio-visualizer-grid.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,10 @@ export type AgentAudioVisualizerGridProps = GridOptions & {
198198
* @defaultValue 'connecting'
199199
*/
200200
state?: AgentState;
201+
/**
202+
* The color of the grid cells in hexidecimal format.
203+
*/
204+
color?: `#${string}`;
201205
/**
202206
* The audio track to visualize. Can be a local/remote audio track or a track reference.
203207
*/
@@ -235,6 +239,7 @@ export function AgentAudioVisualizerGrid({
235239
size = 'md',
236240
state = 'connecting',
237241
radius,
242+
color,
238243
rowCount: _rowCount = 5,
239244
columnCount: _columnCount = 5,
240245
interval = 100,
@@ -266,7 +271,9 @@ export function AgentAudioVisualizerGrid({
266271
<div
267272
data-lk-state={state}
268273
className={cn(AgentAudioVisualizerGridVariants({ size }), className)}
269-
style={{ ...style, gridTemplateColumns: `repeat(${columnCount}, 1fr)` }}
274+
style={
275+
{ ...style, gridTemplateColumns: `repeat(${columnCount}, 1fr)`, color } as CSSProperties
276+
}
270277
{...props}
271278
>
272279
{items.map((idx) => (

components/agents-ui/agent-audio-visualizer-radial.tsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client';
22

3-
import { type ComponentProps, useMemo } from 'react';
3+
import { type CSSProperties, type ComponentProps, useMemo } from 'react';
44
import { type VariantProps, cva } from 'class-variance-authority';
55
import { type LocalAudioTrack, type RemoteAudioTrack } from 'livekit-client';
66
import {
@@ -19,7 +19,7 @@ export const AgentAudioVisualizerRadialVariants = cva(
1919
'**:data-lk-index:rounded-full **:data-lk-index:transition-colors **:data-lk-index:duration-150 **:data-lk-index:ease-linear **:data-lk-index:data-[lk-highlighted=true]:bg-current',
2020
'has-data-[lk-state=connecting]:**:data-lk-index:duration-300',
2121
'has-data-[lk-state=initializing]:**:data-lk-index:duration-300',
22-
'has-data-[lk-state=listening]:**:data-lk-index:duration-300 has-data-[lk-state=listening]:**:data-lk-index:duration-300',
22+
'has-data-[lk-state=listening]:**:data-lk-index:duration-300',
2323
'has-data-[lk-state=thinking]:animate-spin has-data-[lk-state=thinking]:[animation-duration:5s] has-data-[lk-state=thinking]:**:data-lk-index:bg-current',
2424
],
2525
{
@@ -52,6 +52,10 @@ export interface AgentAudioVisualizerRadialProps {
5252
* @defaultValue 'connecting'
5353
*/
5454
state?: AgentState;
55+
/**
56+
* The color of the radial bars in hexidecimal format.
57+
*/
58+
color?: `#${string}`;
5559
/**
5660
* The radius (distance from center) for the radial bars.
5761
* If not provided, defaults based on size.
@@ -93,10 +97,12 @@ export interface AgentAudioVisualizerRadialProps {
9397
export function AgentAudioVisualizerRadial({
9498
size = 'md',
9599
state = 'connecting',
100+
color,
96101
radius,
97102
barCount,
98103
audioTrack,
99104
className,
105+
style,
100106
...props
101107
}: AgentAudioVisualizerRadialProps &
102108
ComponentProps<'div'> &
@@ -175,6 +181,7 @@ export function AgentAudioVisualizerRadial({
175181
<div
176182
data-lk-state={state}
177183
className={cn(AgentAudioVisualizerRadialVariants({ size }), 'relative', className)}
184+
style={{ ...style, color } as CSSProperties}
178185
{...props}
179186
>
180187
{bands.map((band, idx) => {

0 commit comments

Comments
 (0)