项目文件夹

文件
2026-07-13 13:39:38 +08:00

132 行
4.7 KiB
Python

from __future__ import annotations
import asyncio
import datetime
import logging
import os
import sys
import uuid
import aiohttp
import nest_asyncio # type: ignore
from livekit import api
from livekit.rtc.jupyter import display_room
from .cli import cli, proto
from .job import JobExecutorType
from .worker import AgentServer, WorkerOptions
def run_app(server: AgentServer | WorkerOptions, *, jupyter_url: str | None = None) -> None:
nest_asyncio.apply()
if isinstance(server, WorkerOptions):
IN_COLAB = "google.colab" in sys.modules
if IN_COLAB:
from google.colab import userdata # type: ignore
if not jupyter_url:
server.ws_url = userdata.get("LIVEKIT_URL")
server.api_key = userdata.get("LIVEKIT_API_KEY")
server.api_secret = userdata.get("LIVEKIT_API_SECRET")
else:
server.ws_url = server.ws_url or os.environ.get("LIVEKIT_URL", "")
server.api_key = server.api_key or os.environ.get("LIVEKIT_API_KEY", "")
server.api_secret = server.api_secret or os.environ.get("LIVEKIT_API_SECRET", "")
if not jupyter_url and (not server.ws_url or not server.api_key or not server.api_secret):
raise ValueError(
"Failed to get LIVEKIT_URL, LIVEKIT_API_KEY, or LIVEKIT_API_SECRET from environment variables. " # noqa: E501
"Alternatively, you can use `jupyter_url`, which generates and uses join tokens for authentication." # noqa: E501
)
server = AgentServer.from_server_options(server)
server._job_executor_type = JobExecutorType.THREAD
# create user and agent tokens
if jupyter_url:
async def fetch_join_tokens(url: str) -> tuple[str, str, str]:
async with aiohttp.ClientSession() as session:
async with session.post(url) as response:
data = await response.json()
return data["livekit_url"], data["user_token"], data["agent_token"]
try:
ws_url, user_token, agent_token = asyncio.run(fetch_join_tokens(jupyter_url))
claims = api.TokenVerifier().verify(agent_token, verify_signature=False)
if claims.video and claims.video.room:
room_name = claims.video.room
else:
room_name = f"jupyter-room-{uuid.uuid4()}"
except Exception as e:
raise ValueError(
f"Failed to fetch join tokens via jupyter_url. Error: {e}\n"
"You can still use your own LIVEKIT_URL, LIVEKIT_API_KEY, and LIVEKIT_API_SECRET from environment variables instead." # noqa: E501
) from None
else:
ws_url = server._ws_url
api_key = server._api_key
api_secret = server._api_secret
# manually create the user_token and agent_token using the provided api key and secret
room_name = f"jupyter-room-{uuid.uuid4()}"
user_token = (
api.AccessToken(api_key, api_secret)
.with_identity("user-jupyter")
.with_grants(
api.VideoGrants(
can_publish=True, can_subscribe=True, room_join=True, room=room_name
)
)
.with_ttl(datetime.timedelta(minutes=1))
.to_jwt()
)
agent_token = (
api.AccessToken(api_key, api_secret)
.with_identity("agent-jupyter")
.with_kind("agent")
.with_grants(
api.VideoGrants(
agent=True,
can_publish=True,
can_subscribe=True,
room_join=True,
can_update_own_metadata=True,
room=room_name,
)
)
.with_ttl(datetime.timedelta(minutes=1))
.to_jwt()
)
display_room(ws_url, user_token)
root = logging.getLogger()
for handler in root.handlers[:]:
if isinstance(handler, logging.StreamHandler):
root.removeHandler(handler)
@server.once("worker_started")
def _simulate_job() -> None:
async def simulate_job() -> None:
async with api.LiveKitAPI(ws_url, api_key, api_secret) as lk_api:
room_info = await lk_api.room.create_room(api.CreateRoomRequest(name=room_name))
await server.simulate_job(
room_name,
fake_job=False,
room_info=room_info,
token=agent_token,
)
asyncio.run_coroutine_threadsafe(simulate_job(), asyncio.get_event_loop())
args = proto.CliArgs(log_level="DEBUG", url=ws_url, api_key=api_key, api_secret=api_secret)
cli._run_worker(server, args)