141 lines
4.7 KiB
Python
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())
|