From 137dd28877fb72d6075b0b4dc38ace16f54a8bf7 Mon Sep 17 00:00:00 2001 From: Xin Wang Date: Wed, 3 Dec 2025 17:19:08 +0800 Subject: [PATCH] add tool for getLocation and changeColorTheme --- src/components/playground/Playground.tsx | 62 +++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/src/components/playground/Playground.tsx b/src/components/playground/Playground.tsx index 77d3cc2..683aaba 100644 --- a/src/components/playground/Playground.tsx +++ b/src/components/playground/Playground.tsx @@ -26,7 +26,7 @@ import { useRoomContext, useParticipantAttributes, } from "@livekit/components-react"; -import { ConnectionState, LocalParticipant, Track } from "livekit-client"; +import { ConnectionState, LocalParticipant, Track, RpcError, RpcInvocationData } from "livekit-client"; import { QRCodeSVG } from "qrcode.react"; import { ReactNode, useCallback, useEffect, useMemo, useState } from "react"; import tailwindTheme from "../../lib/tailwindTheme.preval"; @@ -74,6 +74,66 @@ export default function Playground({ } }, [config, localParticipant, roomState]); + useEffect(() => { + if (!localParticipant || roomState !== ConnectionState.Connected) { + return; + } + + localParticipant.registerRpcMethod( + 'getUserLocation', + async (data: RpcInvocationData) => { + try { + let params = JSON.parse(data.payload); + const position: GeolocationPosition = await new Promise((resolve, reject) => { + navigator.geolocation.getCurrentPosition(resolve, reject, { + enableHighAccuracy: params.highAccuracy ?? false, + timeout: data.responseTimeout, + }); + }); + return JSON.stringify({ + latitude: position.coords.latitude, + longitude: position.coords.longitude, + }); + } catch (error) { + throw new RpcError(1, "Could not retrieve user location"); + } + } + ); + }, [localParticipant, roomState]); + + useEffect(() => { + if (!localParticipant || roomState !== ConnectionState.Connected) { + return; + } + + localParticipant.registerRpcMethod( + 'setThemeColor', + async (data: RpcInvocationData) => { + try { + const params = JSON.parse(data.payload); + const color = params.color; + + // 验证颜色是否在允许的列表中 + if (!themeColors.includes(color)) { + throw new RpcError(2, `Invalid color. Must be one of: ${themeColors.join(', ')}`); + } + + // 更新主题颜色 + const userSettings = { ...config.settings }; + userSettings.theme_color = color; + setUserSettings(userSettings); + + return JSON.stringify({ success: true, color }); + } catch (error) { + if (error instanceof RpcError) { + throw error; + } + throw new RpcError(1, `Could not set theme color: ${error instanceof Error ? error.message : String(error)}`); + } + } + ); + }, [localParticipant, roomState, config.settings, themeColors, setUserSettings]); + const agentVideoTrack = tracks.find( (trackRef) => trackRef.publication.kind === Track.Kind.Video &&