Files
2026-07-13 13:39:38 +08:00

141 lines
4.7 KiB
Python

from __future__ import annotations
import argparse
import importlib
import logging
import pkgutil
import sys
from typing import TYPE_CHECKING
from .plugin import Plugin
if TYPE_CHECKING:
from .worker import AgentServer
logger = logging.getLogger("livekit.agents")
def _discover_and_import_plugins() -> list[str]:
try:
import livekit.plugins as ns
except ImportError:
logger.warning("no livekit.plugins namespace found — nothing to download")
return []
attempted: list[str] = []
for _finder, name, is_pkg in pkgutil.iter_modules(ns.__path__, prefix="livekit.plugins."):
if not is_pkg:
continue
attempted.append(name)
try:
importlib.import_module(name)
except Exception as e:
logger.warning("failed to import %s: %s", name, e)
return attempted
def _download_files() -> int:
attempted = _discover_and_import_plugins()
logger.info(
"discovered %d plugin package(s): %s",
len(attempted),
", ".join(attempted) if attempted else "(none)",
)
exit_code = 0
for plugin in Plugin.registered_plugins:
logger.info("downloading files for %s", plugin.package)
try:
plugin.download_files()
except Exception as e:
logger.error("failed downloading files for %s: %s", plugin.package, e)
exit_code = 1
else:
logger.info("finished downloading files for %s", plugin.package)
return exit_code
def _dispatch(server: AgentServer, args: argparse.Namespace) -> None:
from .cli import proto
from .cli.cli import _run_tcp_console, _run_worker
if args.command == "console":
_run_tcp_console(server=server, connect_addr=args.connect_addr, record=args.record)
elif args.command == "start":
_run_worker(
server=server,
args=proto.CliArgs(
log_level=args.log_level,
url=args.url,
api_key=args.api_key,
api_secret=args.api_secret,
# --cli-addr is the current name; --reload-addr is the legacy
# alias the CLI still passes for backwards compatibility.
cli_addr=args.cli_addr or args.reload_addr,
log_format=args.log_format,
dev=args.dev,
simulation=args.simulation,
),
)
def _discover_server(entrypoint: str | None) -> AgentServer:
"""Import the user's entrypoint and return the AgentServer it defines.
Reuses the discovery in cli.discover (prefers an app, server, or agent global,
else the single AgentServer in the module).
"""
from pathlib import Path
from .cli.discover import get_import_data
import_data = get_import_data(path=Path(entrypoint) if entrypoint else None)
mod = importlib.import_module(import_data.module_data.module_import_str)
return getattr(mod, import_data.app_name) # type: ignore[no-any-return]
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(
prog="python -m livekit.agents",
description="LiveKit Agents utilities.",
)
sub = parser.add_subparsers(dest="command", required=True)
sub.add_parser(
"download-files",
help="Discover installed livekit-plugins-* packages and run their download_files step.",
)
start_p = sub.add_parser("start")
start_p.add_argument("entrypoint", nargs="?")
start_p.add_argument("--log-level", default="INFO")
start_p.add_argument("--log-format", choices=["json", "colored"], default="json")
start_p.add_argument("--url")
start_p.add_argument("--api-key")
start_p.add_argument("--api-secret")
start_p.add_argument("--dev", action="store_true", default=False)
# address of the driving `lk` CLI's dev channel. --reload-addr is the legacy
# name, kept for backwards compatibility with older CLIs.
start_p.add_argument("--cli-addr")
start_p.add_argument("--reload-addr")
# set by `lk simulate`: disables the worker load limit so simulation runs
# can saturate the agent
start_p.add_argument("--simulation", action="store_true", default=False)
console_p = sub.add_parser("console")
console_p.add_argument("entrypoint", nargs="?")
console_p.add_argument("--connect-addr", required=True)
console_p.add_argument("--record", action="store_true", default=False)
args = parser.parse_args(argv)
if args.command == "download-files":
logging.basicConfig(level=logging.INFO, format="%(message)s")
return _download_files()
_dispatch(_discover_server(args.entrypoint), args)
return 0
if __name__ == "__main__":
sys.exit(main())