livekit-agents 1.0.0.dev0__tar.gz → 1.0.0.dev2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/PKG-INFO +3 -3
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/__init__.py +4 -2
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/_exceptions.py +9 -9
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/cli/cli.py +42 -33
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/cli/log.py +16 -13
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/cli/proto.py +3 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/cli/watcher.py +2 -6
- livekit_agents-1.0.0.dev2/livekit/agents/debug/index.html +532 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/debug/tracing.py +2 -6
- livekit_agents-1.0.0.dev2/livekit/agents/http_server.py +37 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/inference_runner.py +1 -3
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/ipc/channel.py +1 -3
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/ipc/inference_proc_lazy_main.py +2 -6
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/ipc/job_proc_executor.py +3 -9
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/ipc/job_proc_lazy_main.py +21 -17
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/ipc/job_thread_executor.py +5 -15
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/ipc/log_queue.py +1 -3
- livekit_agents-1.0.0.dev2/livekit/agents/ipc/mock_room.py +12 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/ipc/proc_client.py +3 -9
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/ipc/proc_pool.py +1 -5
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/ipc/supervised_proc.py +6 -20
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/job.py +25 -19
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/llm/__init__.py +4 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/llm/_strict.py +6 -18
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/llm/chat_context.py +3 -7
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/llm/fallback_adapter.py +61 -23
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/llm/function_context.py +1 -3
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/llm/llm.py +2 -6
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/llm/realtime.py +21 -7
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/llm/remote_chat_context.py +4 -3
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/llm/utils.py +10 -13
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/metrics/__init__.py +2 -14
- livekit_agents-1.0.0.dev2/livekit/agents/metrics/base.py +129 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/metrics/utils.py +0 -4
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/stt/fallback_adapter.py +8 -25
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/stt/stream_adapter.py +3 -9
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/stt/stt.py +17 -15
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/tokenize/_basic_sent.py +1 -3
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/tokenize/_basic_word.py +1 -3
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/tokenize/basic.py +2 -6
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/tts/fallback_adapter.py +25 -51
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/tts/stream_adapter.py +1 -3
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/tts/tts.py +50 -31
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/types.py +19 -1
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/utils/__init__.py +2 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/utils/audio.py +1 -3
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/utils/codecs/decoder.py +31 -12
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/utils/codecs/mp3.py +1 -3
- livekit_agents-1.0.0.dev2/livekit/agents/utils/connection_pool.py +152 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/version.py +1 -1
- livekit_agents-1.0.0.dev2/livekit/agents/voice/__init__.py +32 -0
- livekit_agents-1.0.0.dev0/livekit/agents/pipeline/task.py → livekit_agents-1.0.0.dev2/livekit/agents/voice/agent_task.py +108 -15
- {livekit_agents-1.0.0.dev0/livekit/agents/pipeline → livekit_agents-1.0.0.dev2/livekit/agents/voice}/audio_recognition.py +6 -14
- {livekit_agents-1.0.0.dev0/livekit/agents/pipeline → livekit_agents-1.0.0.dev2/livekit/agents/voice}/avatar/_runner.py +8 -16
- {livekit_agents-1.0.0.dev0/livekit/agents/pipeline → livekit_agents-1.0.0.dev2/livekit/agents/voice}/chat_cli.py +91 -41
- {livekit_agents-1.0.0.dev0/livekit/agents/pipeline → livekit_agents-1.0.0.dev2/livekit/agents/voice}/datastream_io.py +11 -27
- livekit_agents-1.0.0.dev2/livekit/agents/voice/events.py +107 -0
- {livekit_agents-1.0.0.dev0/livekit/agents/pipeline → livekit_agents-1.0.0.dev2/livekit/agents/voice}/generation.py +47 -19
- {livekit_agents-1.0.0.dev0/livekit/agents/pipeline → livekit_agents-1.0.0.dev2/livekit/agents/voice}/io.py +135 -10
- livekit_agents-1.0.0.dev2/livekit/agents/voice/room_io.py +949 -0
- {livekit_agents-1.0.0.dev0/livekit/agents/pipeline → livekit_agents-1.0.0.dev2/livekit/agents/voice}/speech_handle.py +2 -4
- {livekit_agents-1.0.0.dev0/livekit/agents/pipeline → livekit_agents-1.0.0.dev2/livekit/agents/voice}/task_activity.py +197 -69
- {livekit_agents-1.0.0.dev0/livekit/agents/pipeline → livekit_agents-1.0.0.dev2/livekit/agents/voice}/transcription/_utils.py +1 -3
- {livekit_agents-1.0.0.dev0/livekit/agents/pipeline → livekit_agents-1.0.0.dev2/livekit/agents/voice}/transcription/synchronizer.py +75 -73
- livekit_agents-1.0.0.dev0/livekit/agents/pipeline/pipeline_agent.py → livekit_agents-1.0.0.dev2/livekit/agents/voice/voice_agent.py +149 -78
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/worker.py +52 -88
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit_agents.egg-info/PKG-INFO +3 -3
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit_agents.egg-info/SOURCES.txt +19 -17
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit_agents.egg-info/requires.txt +2 -4
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/setup.py +3 -7
- livekit_agents-1.0.0.dev0/livekit/agents/debug/index.html +0 -518
- livekit_agents-1.0.0.dev0/livekit/agents/http_server.py +0 -35
- livekit_agents-1.0.0.dev0/livekit/agents/metrics/base.py +0 -143
- livekit_agents-1.0.0.dev0/livekit/agents/pipeline/__init__.py +0 -15
- livekit_agents-1.0.0.dev0/livekit/agents/pipeline/events.py +0 -26
- livekit_agents-1.0.0.dev0/livekit/agents/pipeline/room_io.py +0 -471
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/README.md +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/cli/__init__.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/debug/__init__.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/ipc/__init__.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/ipc/inference_executor.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/ipc/inference_proc_executor.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/ipc/job_executor.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/ipc/proto.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/log.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/metrics/usage_collector.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/plugin.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/py.typed +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/stt/__init__.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/tokenize/__init__.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/tokenize/_basic_hyphenator.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/tokenize/_basic_paragraph.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/tokenize/token_stream.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/tokenize/tokenizer.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/tokenize/utils.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/tts/__init__.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/utils/aio/__init__.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/utils/aio/channel.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/utils/aio/debug.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/utils/aio/duplex_unix.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/utils/aio/interval.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/utils/aio/itertools.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/utils/aio/sleep.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/utils/aio/task_set.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/utils/aio/utils.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/utils/aio/wait_group.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/utils/codecs/__init__.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/utils/exp_filter.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/utils/http_context.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/utils/hw/__init__.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/utils/hw/cpu.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/utils/images/__init__.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/utils/images/image.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/utils/log.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/utils/misc.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/utils/moving_average.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit/agents/vad.py +0 -0
- {livekit_agents-1.0.0.dev0/livekit/agents/pipeline → livekit_agents-1.0.0.dev2/livekit/agents/voice}/avatar/__init__.py +0 -0
- {livekit_agents-1.0.0.dev0/livekit/agents/pipeline → livekit_agents-1.0.0.dev2/livekit/agents/voice}/transcription/__init__.py +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit_agents.egg-info/dependency_links.txt +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/livekit_agents.egg-info/top_level.txt +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/pyproject.toml +0 -0
- {livekit_agents-1.0.0.dev0 → livekit_agents-1.0.0.dev2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: livekit-agents
|
|
3
|
-
Version: 1.0.0.
|
|
3
|
+
Version: 1.0.0.dev2
|
|
4
4
|
Summary: LiveKit Python Agents
|
|
5
5
|
Home-page: https://github.com/livekit/agents
|
|
6
6
|
License: Apache-2.0
|
|
@@ -20,7 +20,7 @@ Classifier: Programming Language :: Python :: 3 :: Only
|
|
|
20
20
|
Requires-Python: >=3.9.0
|
|
21
21
|
Description-Content-Type: text/markdown
|
|
22
22
|
Requires-Dist: click~=8.1
|
|
23
|
-
Requires-Dist: livekit>=0.
|
|
23
|
+
Requires-Dist: livekit>=0.21.1
|
|
24
24
|
Requires-Dist: livekit-api~=0.8.2
|
|
25
25
|
Requires-Dist: livekit-protocol~=0.8.2
|
|
26
26
|
Requires-Dist: protobuf>=3
|
|
@@ -30,8 +30,8 @@ Requires-Dist: watchfiles~=0.22
|
|
|
30
30
|
Requires-Dist: psutil~=5.9
|
|
31
31
|
Requires-Dist: aiohttp~=3.10
|
|
32
32
|
Requires-Dist: typing-extensions~=4.12
|
|
33
|
+
Requires-Dist: sounddevice>=0.5
|
|
33
34
|
Requires-Dist: colorama; sys_platform == "win32"
|
|
34
|
-
Requires-Dist: aiodns~=3.2; sys_platform != "win32"
|
|
35
35
|
Provides-Extra: codecs
|
|
36
36
|
Requires-Dist: av>=12.0.0; extra == "codecs"
|
|
37
37
|
Requires-Dist: numpy>=1.26.0; extra == "codecs"
|
|
@@ -17,12 +17,12 @@ from . import (
|
|
|
17
17
|
ipc,
|
|
18
18
|
llm,
|
|
19
19
|
metrics,
|
|
20
|
-
pipeline,
|
|
21
20
|
stt,
|
|
22
21
|
tokenize,
|
|
23
22
|
tts,
|
|
24
23
|
utils,
|
|
25
24
|
vad,
|
|
25
|
+
voice,
|
|
26
26
|
)
|
|
27
27
|
from ._exceptions import (
|
|
28
28
|
APIConnectionError,
|
|
@@ -43,6 +43,7 @@ from .types import (
|
|
|
43
43
|
NotGivenOr,
|
|
44
44
|
)
|
|
45
45
|
from .version import __version__
|
|
46
|
+
from .voice import VoiceAgent
|
|
46
47
|
from .worker import Worker, WorkerOptions, WorkerPermissions, WorkerType
|
|
47
48
|
|
|
48
49
|
__all__ = [
|
|
@@ -66,7 +67,8 @@ __all__ = [
|
|
|
66
67
|
"tokenize",
|
|
67
68
|
"llm",
|
|
68
69
|
"metrics",
|
|
69
|
-
"
|
|
70
|
+
"voice",
|
|
71
|
+
"VoiceAgent",
|
|
70
72
|
"cli",
|
|
71
73
|
"AssignmentTimeoutError",
|
|
72
74
|
"APIConnectionError",
|
|
@@ -31,9 +31,7 @@ class APIError(Exception):
|
|
|
31
31
|
retryable: bool = False
|
|
32
32
|
"""Whether the error can be retried."""
|
|
33
33
|
|
|
34
|
-
def __init__(
|
|
35
|
-
self, message: str, *, body: object | None, retryable: bool = True
|
|
36
|
-
) -> None:
|
|
34
|
+
def __init__(self, message: str, *, body: object | None, retryable: bool = True) -> None:
|
|
37
35
|
super().__init__(message)
|
|
38
36
|
|
|
39
37
|
self.message = message
|
|
@@ -70,20 +68,22 @@ class APIStatusError(APIError):
|
|
|
70
68
|
self.status_code = status_code
|
|
71
69
|
self.request_id = request_id
|
|
72
70
|
|
|
71
|
+
def __str__(self):
|
|
72
|
+
return (
|
|
73
|
+
f"{self.message} "
|
|
74
|
+
f"(status_code={self.status_code}, request_id={self.request_id}, body={self.body})"
|
|
75
|
+
)
|
|
76
|
+
|
|
73
77
|
|
|
74
78
|
class APIConnectionError(APIError):
|
|
75
79
|
"""Raised when an API request failed due to a connection error."""
|
|
76
80
|
|
|
77
|
-
def __init__(
|
|
78
|
-
self, message: str = "Connection error.", *, retryable: bool = True
|
|
79
|
-
) -> None:
|
|
81
|
+
def __init__(self, message: str = "Connection error.", *, retryable: bool = True) -> None:
|
|
80
82
|
super().__init__(message, body=None, retryable=retryable)
|
|
81
83
|
|
|
82
84
|
|
|
83
85
|
class APITimeoutError(APIConnectionError):
|
|
84
86
|
"""Raised when an API request timed out."""
|
|
85
87
|
|
|
86
|
-
def __init__(
|
|
87
|
-
self, message: str = "Request timed out.", *, retryable: bool = True
|
|
88
|
-
) -> None:
|
|
88
|
+
def __init__(self, message: str = "Request timed out.", *, retryable: bool = True) -> None:
|
|
89
89
|
super().__init__(message, retryable=retryable)
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import asyncio
|
|
2
4
|
import pathlib
|
|
3
5
|
import signal
|
|
@@ -14,6 +16,12 @@ from ..worker import JobExecutorType, Worker, WorkerOptions
|
|
|
14
16
|
from . import proto
|
|
15
17
|
from .log import setup_logging
|
|
16
18
|
|
|
19
|
+
CLI_ARGUMENTS: proto.CliArgs | None = None
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _esc(*codes: int) -> str:
|
|
23
|
+
return "\033[" + ";".join(str(c) for c in codes) + "m"
|
|
24
|
+
|
|
17
25
|
|
|
18
26
|
def run_app(opts: WorkerOptions, *, hot_reload: NotGivenOr[bool] = NOT_GIVEN) -> None:
|
|
19
27
|
"""Run the CLI to interact with the worker"""
|
|
@@ -23,9 +31,7 @@ def run_app(opts: WorkerOptions, *, hot_reload: NotGivenOr[bool] = NOT_GIVEN) ->
|
|
|
23
31
|
@click.option(
|
|
24
32
|
"--log-level",
|
|
25
33
|
default="INFO",
|
|
26
|
-
type=click.Choice(
|
|
27
|
-
["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], case_sensitive=False
|
|
28
|
-
),
|
|
34
|
+
type=click.Choice(["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], case_sensitive=False),
|
|
29
35
|
help="Set the logging level",
|
|
30
36
|
)
|
|
31
37
|
@click.option(
|
|
@@ -48,9 +54,7 @@ def run_app(opts: WorkerOptions, *, hot_reload: NotGivenOr[bool] = NOT_GIVEN) ->
|
|
|
48
54
|
default=60,
|
|
49
55
|
help="Time in seconds to wait for jobs to finish before shutting down",
|
|
50
56
|
)
|
|
51
|
-
def start(
|
|
52
|
-
log_level: str, url: str, api_key: str, api_secret: str, drain_timeout: int
|
|
53
|
-
) -> None:
|
|
57
|
+
def start(log_level: str, url: str, api_key: str, api_secret: str, drain_timeout: int) -> None:
|
|
54
58
|
opts.ws_url = url or opts.ws_url
|
|
55
59
|
opts.api_key = api_key or opts.api_key
|
|
56
60
|
opts.api_secret = api_secret or opts.api_secret
|
|
@@ -69,9 +73,7 @@ def run_app(opts: WorkerOptions, *, hot_reload: NotGivenOr[bool] = NOT_GIVEN) ->
|
|
|
69
73
|
@click.option(
|
|
70
74
|
"--log-level",
|
|
71
75
|
default="DEBUG",
|
|
72
|
-
type=click.Choice(
|
|
73
|
-
["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], case_sensitive=False
|
|
74
|
-
),
|
|
76
|
+
type=click.Choice(["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], case_sensitive=False),
|
|
75
77
|
help="Set the logging level",
|
|
76
78
|
)
|
|
77
79
|
@click.option(
|
|
@@ -138,7 +140,7 @@ def run_app(opts: WorkerOptions, *, hot_reload: NotGivenOr[bool] = NOT_GIVEN) ->
|
|
|
138
140
|
envvar="LIVEKIT_API_SECRET",
|
|
139
141
|
help="LiveKit server or Cloud project's API secret",
|
|
140
142
|
)
|
|
141
|
-
def
|
|
143
|
+
def console(
|
|
142
144
|
url: str,
|
|
143
145
|
api_key: str,
|
|
144
146
|
api_secret: str,
|
|
@@ -149,29 +151,26 @@ def run_app(opts: WorkerOptions, *, hot_reload: NotGivenOr[bool] = NOT_GIVEN) ->
|
|
|
149
151
|
opts.api_key = api_key or opts.api_key
|
|
150
152
|
opts.api_secret = api_secret or opts.api_secret
|
|
151
153
|
|
|
152
|
-
chat_name = utils.shortuuid("chat_cli_")
|
|
153
|
-
|
|
154
154
|
args = proto.CliArgs(
|
|
155
155
|
opts=opts,
|
|
156
|
-
log_level="
|
|
156
|
+
log_level="INFO",
|
|
157
157
|
devmode=True,
|
|
158
158
|
asyncio_debug=False,
|
|
159
159
|
watch=False,
|
|
160
|
+
console=True,
|
|
160
161
|
drain_timeout=0,
|
|
161
162
|
register=False,
|
|
162
163
|
simulate_job=proto.SimulateJobArgs(
|
|
163
|
-
room=
|
|
164
|
+
room="mock-console",
|
|
164
165
|
),
|
|
165
166
|
)
|
|
166
|
-
|
|
167
|
+
run_worker(args)
|
|
167
168
|
|
|
168
169
|
@cli.command(help="Connect to a specific room")
|
|
169
170
|
@click.option(
|
|
170
171
|
"--log-level",
|
|
171
172
|
default="DEBUG",
|
|
172
|
-
type=click.Choice(
|
|
173
|
-
["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], case_sensitive=False
|
|
174
|
-
),
|
|
173
|
+
type=click.Choice(["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], case_sensitive=False),
|
|
175
174
|
help="Set the logging level",
|
|
176
175
|
)
|
|
177
176
|
@click.option(
|
|
@@ -200,9 +199,7 @@ def run_app(opts: WorkerOptions, *, hot_reload: NotGivenOr[bool] = NOT_GIVEN) ->
|
|
|
200
199
|
help="Watch for changes in the current directory and plugins in editable mode",
|
|
201
200
|
)
|
|
202
201
|
@click.option("--room", help="Room name to connect to", required=True)
|
|
203
|
-
@click.option(
|
|
204
|
-
"--participant-identity", help="Participant identity (JobType.JT_PUBLISHER)"
|
|
205
|
-
)
|
|
202
|
+
@click.option("--participant-identity", help="Participant identity (JobType.JT_PUBLISHER)")
|
|
206
203
|
def connect(
|
|
207
204
|
log_level: str,
|
|
208
205
|
url: str,
|
|
@@ -236,13 +233,11 @@ def run_app(opts: WorkerOptions, *, hot_reload: NotGivenOr[bool] = NOT_GIVEN) ->
|
|
|
236
233
|
@click.option(
|
|
237
234
|
"--log-level",
|
|
238
235
|
default="DEBUG",
|
|
239
|
-
type=click.Choice(
|
|
240
|
-
["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], case_sensitive=False
|
|
241
|
-
),
|
|
236
|
+
type=click.Choice(["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], case_sensitive=False),
|
|
242
237
|
help="Set the logging level",
|
|
243
238
|
)
|
|
244
239
|
def download_files(log_level: str) -> None:
|
|
245
|
-
setup_logging(log_level, True)
|
|
240
|
+
setup_logging(log_level, True, False)
|
|
246
241
|
|
|
247
242
|
for plugin in Plugin.registered_plugins:
|
|
248
243
|
logger.info(f"Downloading files for {plugin}")
|
|
@@ -258,13 +253,11 @@ def _run_dev(
|
|
|
258
253
|
if args.watch:
|
|
259
254
|
from .watcher import WatchServer
|
|
260
255
|
|
|
261
|
-
setup_logging(args.log_level, args.devmode)
|
|
256
|
+
setup_logging(args.log_level, args.devmode, args.console)
|
|
262
257
|
main_file = pathlib.Path(sys.argv[0]).parent
|
|
263
258
|
|
|
264
259
|
async def _run_loop():
|
|
265
|
-
server = WatchServer(
|
|
266
|
-
run_worker, main_file, args, loop=asyncio.get_event_loop()
|
|
267
|
-
)
|
|
260
|
+
server = WatchServer(run_worker, main_file, args, loop=asyncio.get_event_loop())
|
|
268
261
|
await server.run()
|
|
269
262
|
|
|
270
263
|
try:
|
|
@@ -276,12 +269,21 @@ def _run_dev(
|
|
|
276
269
|
|
|
277
270
|
|
|
278
271
|
def run_worker(args: proto.CliArgs) -> None:
|
|
279
|
-
|
|
272
|
+
global CLI_ARGUMENTS
|
|
273
|
+
CLI_ARGUMENTS = args
|
|
274
|
+
|
|
275
|
+
setup_logging(args.log_level, args.devmode, args.console)
|
|
280
276
|
args.opts.validate_config(args.devmode)
|
|
281
277
|
|
|
282
278
|
loop = asyncio.new_event_loop()
|
|
283
279
|
asyncio.set_event_loop(loop)
|
|
284
280
|
|
|
281
|
+
if args.console:
|
|
282
|
+
print(_esc(34) + "=" * 50 + _esc(0))
|
|
283
|
+
print(_esc(34) + " Livekit Agents - Console" + _esc(0))
|
|
284
|
+
print(_esc(34) + "=" * 50 + _esc(0))
|
|
285
|
+
print("Press [Ctrl+B] to toggle between Text/Audio mode, [Q] to quit.\n")
|
|
286
|
+
|
|
285
287
|
worker = Worker(args.opts, devmode=args.devmode, register=args.register, loop=loop)
|
|
286
288
|
|
|
287
289
|
loop.set_debug(args.asyncio_debug)
|
|
@@ -293,9 +295,16 @@ def run_worker(args: proto.CliArgs) -> None:
|
|
|
293
295
|
if args.simulate_job and args.reload_count == 0:
|
|
294
296
|
logger.info("connecting to room %s", args.simulate_job.room)
|
|
295
297
|
loop.create_task(
|
|
296
|
-
worker.simulate_job(
|
|
297
|
-
|
|
298
|
-
|
|
298
|
+
worker.simulate_job(args.simulate_job.room, args.simulate_job.participant_identity)
|
|
299
|
+
)
|
|
300
|
+
|
|
301
|
+
if args.devmode:
|
|
302
|
+
logger.info(
|
|
303
|
+
f"{_esc(1)}see tracing information at http://localhost:{worker.worker_info.http_port}/debug{_esc(0)}"
|
|
304
|
+
)
|
|
305
|
+
else:
|
|
306
|
+
logger.info(
|
|
307
|
+
f"see tracing information at http://localhost:{worker.worker_info.http_port}/debug"
|
|
299
308
|
)
|
|
300
309
|
|
|
301
310
|
try:
|
|
@@ -19,6 +19,8 @@ NOISY_LOGGERS = [
|
|
|
19
19
|
"watchfiles",
|
|
20
20
|
"anthropic",
|
|
21
21
|
"websockets.client",
|
|
22
|
+
"aiohttp.access",
|
|
23
|
+
"livekit",
|
|
22
24
|
]
|
|
23
25
|
|
|
24
26
|
|
|
@@ -60,9 +62,7 @@ _RESERVED_ATTRS: Tuple[str, ...] = (
|
|
|
60
62
|
|
|
61
63
|
def _merge_record_extra(record: logging.LogRecord, target: Dict[Any, Any]):
|
|
62
64
|
for key, value in record.__dict__.items():
|
|
63
|
-
if key not in _RESERVED_ATTRS and not (
|
|
64
|
-
hasattr(key, "startswith") and key.startswith("_")
|
|
65
|
-
):
|
|
65
|
+
if key not in _RESERVED_ATTRS and not (hasattr(key, "startswith") and key.startswith("_")):
|
|
66
66
|
target[key] = value
|
|
67
67
|
|
|
68
68
|
|
|
@@ -136,9 +136,7 @@ class JsonFormatter(logging.Formatter):
|
|
|
136
136
|
log_record.update(message_dict)
|
|
137
137
|
_merge_record_extra(record, log_record)
|
|
138
138
|
|
|
139
|
-
log_record["timestamp"] = datetime.fromtimestamp(
|
|
140
|
-
record.created, tz=timezone.utc
|
|
141
|
-
)
|
|
139
|
+
log_record["timestamp"] = datetime.fromtimestamp(record.created, tz=timezone.utc)
|
|
142
140
|
|
|
143
141
|
return json.dumps(log_record, cls=JsonFormatter.JsonEncoder, ensure_ascii=True)
|
|
144
142
|
|
|
@@ -188,9 +186,7 @@ class ColoredFormatter(logging.Formatter):
|
|
|
188
186
|
args.update(self._esc_codes)
|
|
189
187
|
|
|
190
188
|
if extra:
|
|
191
|
-
args["extra"] = json.dumps(
|
|
192
|
-
extra, cls=JsonFormatter.JsonEncoder, ensure_ascii=True
|
|
193
|
-
)
|
|
189
|
+
args["extra"] = json.dumps(extra, cls=JsonFormatter.JsonEncoder, ensure_ascii=True)
|
|
194
190
|
|
|
195
191
|
for field in self._required_fields:
|
|
196
192
|
if field in extra:
|
|
@@ -200,14 +196,21 @@ class ColoredFormatter(logging.Formatter):
|
|
|
200
196
|
return msg + self._esc_codes["esc_reset"]
|
|
201
197
|
|
|
202
198
|
|
|
203
|
-
def setup_logging(log_level: str, devmode: bool) -> None:
|
|
199
|
+
def setup_logging(log_level: str, devmode: bool, console: bool) -> None:
|
|
204
200
|
handler = logging.StreamHandler()
|
|
205
201
|
|
|
206
202
|
if devmode:
|
|
207
203
|
# colorful logs for dev (improves readability)
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
204
|
+
if console:
|
|
205
|
+
# reset the line before each log message
|
|
206
|
+
colored_formatter = ColoredFormatter(
|
|
207
|
+
"\r%(asctime)s - %(esc_levelcolor)s%(levelname)-4s%(esc_reset)s %(name)s - %(message)s %(esc_gray)s%(extra)s"
|
|
208
|
+
)
|
|
209
|
+
else:
|
|
210
|
+
colored_formatter = ColoredFormatter(
|
|
211
|
+
"%(asctime)s - %(esc_levelcolor)s%(levelname)-4s%(esc_reset)s %(name)s - %(message)s %(esc_gray)s%(extra)s"
|
|
212
|
+
)
|
|
213
|
+
|
|
211
214
|
handler.setFormatter(colored_formatter)
|
|
212
215
|
else:
|
|
213
216
|
# production logs (serialized of json)
|
|
@@ -126,9 +126,7 @@ class WatchServer:
|
|
|
126
126
|
with contextlib.suppress(asyncio.InvalidStateError):
|
|
127
127
|
self._recv_jobs_fut.set_result(None)
|
|
128
128
|
if isinstance(msg, proto.ReloadJobsRequest):
|
|
129
|
-
await channel.asend_message(
|
|
130
|
-
self._pch, proto.ReloadJobsResponse(jobs=active_jobs)
|
|
131
|
-
)
|
|
129
|
+
await channel.asend_message(self._pch, proto.ReloadJobsResponse(jobs=active_jobs))
|
|
132
130
|
if isinstance(msg, proto.Reloaded):
|
|
133
131
|
self._worker_reloading = False
|
|
134
132
|
|
|
@@ -151,9 +149,7 @@ class WatchClient:
|
|
|
151
149
|
async def _run(self) -> None:
|
|
152
150
|
assert self._cli_args.mp_cch
|
|
153
151
|
try:
|
|
154
|
-
self._cch = await utils.aio.duplex_unix._AsyncDuplex.open(
|
|
155
|
-
self._cli_args.mp_cch
|
|
156
|
-
)
|
|
152
|
+
self._cch = await utils.aio.duplex_unix._AsyncDuplex.open(self._cli_args.mp_cch)
|
|
157
153
|
|
|
158
154
|
await channel.asend_message(self._cch, proto.ReloadJobsRequest())
|
|
159
155
|
|