livekit-agents 1.0.0.dev2__tar.gz → 1.0.0.dev4__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.
Files changed (128) hide show
  1. livekit_agents-1.0.0.dev4/.gitignore +168 -0
  2. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/PKG-INFO +24 -34
  3. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/__init__.py +3 -14
  4. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/cli/cli.py +2 -2
  5. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/cli/log.py +9 -7
  6. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/cli/watcher.py +2 -2
  7. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/debug/tracing.py +2 -2
  8. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/inference_runner.py +3 -3
  9. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/ipc/job_proc_executor.py +2 -1
  10. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/ipc/job_proc_lazy_main.py +15 -8
  11. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/ipc/job_thread_executor.py +2 -1
  12. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/ipc/proc_client.py +4 -9
  13. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/ipc/proc_pool.py +2 -1
  14. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/job.py +17 -8
  15. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/llm/__init__.py +16 -17
  16. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/llm/_strict.py +1 -1
  17. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/llm/chat_context.py +74 -28
  18. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/llm/fallback_adapter.py +15 -18
  19. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/llm/llm.py +20 -43
  20. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/llm/realtime.py +12 -18
  21. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/llm/remote_chat_context.py +2 -2
  22. livekit_agents-1.0.0.dev2/livekit/agents/llm/function_context.py → livekit_agents-1.0.0.dev4/livekit/agents/llm/tool_context.py +51 -37
  23. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/llm/utils.py +83 -50
  24. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/metrics/__init__.py +1 -8
  25. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/metrics/base.py +11 -11
  26. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/metrics/utils.py +1 -6
  27. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/plugin.py +3 -3
  28. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/stt/fallback_adapter.py +2 -10
  29. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/stt/stream_adapter.py +1 -1
  30. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/stt/stt.py +4 -3
  31. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/tokenize/__init__.py +2 -11
  32. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/tokenize/_basic_sent.py +18 -6
  33. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/tokenize/basic.py +8 -9
  34. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/tokenize/token_stream.py +3 -1
  35. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/tokenize/tokenizer.py +3 -3
  36. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/tokenize/utils.py +2 -1
  37. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/tts/__init__.py +2 -0
  38. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/tts/fallback_adapter.py +15 -18
  39. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/tts/stream_adapter.py +7 -10
  40. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/tts/tts.py +56 -14
  41. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/types.py +4 -0
  42. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/utils/aio/channel.py +5 -4
  43. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/utils/aio/interval.py +1 -1
  44. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/utils/aio/itertools.py +7 -21
  45. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/utils/aio/task_set.py +2 -1
  46. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/utils/audio.py +2 -2
  47. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/utils/codecs/__init__.py +1 -2
  48. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/utils/codecs/decoder.py +25 -20
  49. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/utils/connection_pool.py +41 -15
  50. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/utils/hw/cpu.py +2 -2
  51. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/utils/log.py +12 -11
  52. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/vad.py +4 -3
  53. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/version.py +1 -1
  54. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/voice/__init__.py +6 -6
  55. livekit_agents-1.0.0.dev4/livekit/agents/voice/agent.py +511 -0
  56. livekit_agents-1.0.0.dev2/livekit/agents/voice/task_activity.py → livekit_agents-1.0.0.dev4/livekit/agents/voice/agent_activity.py +439 -229
  57. livekit_agents-1.0.0.dev2/livekit/agents/voice/voice_agent.py → livekit_agents-1.0.0.dev4/livekit/agents/voice/agent_session.py +81 -62
  58. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/voice/audio_recognition.py +10 -5
  59. livekit_agents-1.0.0.dev4/livekit/agents/voice/avatar/__init__.py +14 -0
  60. livekit_agents-1.0.0.dev2/livekit/agents/voice/datastream_io.py → livekit_agents-1.0.0.dev4/livekit/agents/voice/avatar/_datastream_io.py +18 -29
  61. livekit_agents-1.0.0.dev4/livekit/agents/voice/avatar/_queue_io.py +59 -0
  62. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/voice/avatar/_runner.py +40 -54
  63. livekit_agents-1.0.0.dev4/livekit/agents/voice/avatar/_types.py +40 -0
  64. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/voice/chat_cli.py +37 -24
  65. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/voice/events.py +23 -9
  66. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/voice/generation.py +224 -198
  67. livekit_agents-1.0.0.dev4/livekit/agents/voice/io.py +355 -0
  68. livekit_agents-1.0.0.dev4/livekit/agents/voice/room_io/__init__.py +17 -0
  69. livekit_agents-1.0.0.dev4/livekit/agents/voice/room_io/_input.py +184 -0
  70. livekit_agents-1.0.0.dev4/livekit/agents/voice/room_io/_output.py +360 -0
  71. livekit_agents-1.0.0.dev4/livekit/agents/voice/room_io/room_io.py +360 -0
  72. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/voice/speech_handle.py +24 -4
  73. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/voice/transcription/_utils.py +4 -0
  74. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/voice/transcription/synchronizer.py +104 -63
  75. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/worker.py +15 -13
  76. livekit_agents-1.0.0.dev4/pyproject.toml +61 -0
  77. livekit_agents-1.0.0.dev2/livekit/agents/utils/codecs/mp3.py +0 -83
  78. livekit_agents-1.0.0.dev2/livekit/agents/voice/agent_task.py +0 -274
  79. livekit_agents-1.0.0.dev2/livekit/agents/voice/avatar/__init__.py +0 -3
  80. livekit_agents-1.0.0.dev2/livekit/agents/voice/io.py +0 -340
  81. livekit_agents-1.0.0.dev2/livekit/agents/voice/room_io.py +0 -949
  82. livekit_agents-1.0.0.dev2/livekit_agents.egg-info/PKG-INFO +0 -54
  83. livekit_agents-1.0.0.dev2/livekit_agents.egg-info/SOURCES.txt +0 -115
  84. livekit_agents-1.0.0.dev2/livekit_agents.egg-info/dependency_links.txt +0 -1
  85. livekit_agents-1.0.0.dev2/livekit_agents.egg-info/requires.txt +0 -22
  86. livekit_agents-1.0.0.dev2/livekit_agents.egg-info/top_level.txt +0 -1
  87. livekit_agents-1.0.0.dev2/pyproject.toml +0 -3
  88. livekit_agents-1.0.0.dev2/setup.cfg +0 -4
  89. livekit_agents-1.0.0.dev2/setup.py +0 -77
  90. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/README.md +0 -0
  91. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/_exceptions.py +0 -0
  92. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/cli/__init__.py +0 -0
  93. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/cli/proto.py +0 -0
  94. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/debug/__init__.py +0 -0
  95. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/debug/index.html +0 -0
  96. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/http_server.py +0 -0
  97. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/ipc/__init__.py +0 -0
  98. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/ipc/channel.py +0 -0
  99. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/ipc/inference_executor.py +0 -0
  100. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/ipc/inference_proc_executor.py +0 -0
  101. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/ipc/inference_proc_lazy_main.py +0 -0
  102. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/ipc/job_executor.py +0 -0
  103. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/ipc/log_queue.py +0 -0
  104. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/ipc/mock_room.py +0 -0
  105. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/ipc/proto.py +0 -0
  106. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/ipc/supervised_proc.py +0 -0
  107. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/log.py +0 -0
  108. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/metrics/usage_collector.py +0 -0
  109. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/py.typed +0 -0
  110. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/stt/__init__.py +0 -0
  111. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/tokenize/_basic_hyphenator.py +0 -0
  112. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/tokenize/_basic_paragraph.py +0 -0
  113. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/tokenize/_basic_word.py +0 -0
  114. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/utils/__init__.py +0 -0
  115. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/utils/aio/__init__.py +0 -0
  116. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/utils/aio/debug.py +0 -0
  117. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/utils/aio/duplex_unix.py +0 -0
  118. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/utils/aio/sleep.py +0 -0
  119. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/utils/aio/utils.py +0 -0
  120. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/utils/aio/wait_group.py +0 -0
  121. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/utils/exp_filter.py +0 -0
  122. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/utils/http_context.py +0 -0
  123. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/utils/hw/__init__.py +0 -0
  124. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/utils/images/__init__.py +0 -0
  125. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/utils/images/image.py +0 -0
  126. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/utils/misc.py +0 -0
  127. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/utils/moving_average.py +0 -0
  128. {livekit_agents-1.0.0.dev2 → livekit_agents-1.0.0.dev4}/livekit/agents/voice/transcription/__init__.py +0 -0
@@ -0,0 +1,168 @@
1
+ **/.vscode
2
+ **/.DS_Store
3
+
4
+ # Byte-compiled / optimized / DLL files
5
+ __pycache__/
6
+ *.py[cod]
7
+ *$py.class
8
+
9
+ # C extensions
10
+ *.so
11
+
12
+ # Distribution / packaging
13
+ .Python
14
+ build/
15
+ develop-eggs/
16
+ dist/
17
+ downloads/
18
+ eggs/
19
+ .eggs/
20
+ lib/
21
+ lib64/
22
+ parts/
23
+ sdist/
24
+ var/
25
+ wheels/
26
+ share/python-wheels/
27
+ *.egg-info/
28
+ .installed.cfg
29
+ *.egg
30
+ MANIFEST
31
+
32
+ # PyInstaller
33
+ # Usually these files are written by a python script from a template
34
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
35
+ *.manifest
36
+ *.spec
37
+
38
+ # Installer logs
39
+ pip-log.txt
40
+ pip-delete-this-directory.txt
41
+
42
+ # Unit test / coverage reports
43
+ htmlcov/
44
+ .tox/
45
+ .nox/
46
+ .coverage
47
+ .coverage.*
48
+ .cache
49
+ nosetests.xml
50
+ coverage.xml
51
+ *.cover
52
+ *.py,cover
53
+ .hypothesis/
54
+ .pytest_cache/
55
+ cover/
56
+
57
+ # Translations
58
+ *.mo
59
+ *.pot
60
+
61
+ # Django stuff:
62
+ *.log
63
+ local_settings.py
64
+ db.sqlite3
65
+ db.sqlite3-journal
66
+
67
+ # Flask stuff:
68
+ instance/
69
+ .webassets-cache
70
+
71
+ # Scrapy stuff:
72
+ .scrapy
73
+
74
+ # Sphinx documentation
75
+ docs/_build/
76
+
77
+ # PyBuilder
78
+ .pybuilder/
79
+ target/
80
+
81
+ # Jupyter Notebook
82
+ .ipynb_checkpoints
83
+
84
+ # IPython
85
+ profile_default/
86
+ ipython_config.py
87
+
88
+ # pyenv
89
+ # For a library or package, you might want to ignore these files since the code is
90
+ # intended to run in multiple environments; otherwise, check them in:
91
+ # .python-version
92
+
93
+ # pipenv
94
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
95
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
96
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
97
+ # install all needed dependencies.
98
+ #Pipfile.lock
99
+
100
+ # poetry
101
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
102
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
103
+ # commonly ignored for libraries.
104
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
105
+ #poetry.lock
106
+
107
+ # pdm
108
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
109
+ #pdm.lock
110
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
111
+ # in version control.
112
+ # https://pdm.fming.dev/#use-with-ide
113
+ .pdm.toml
114
+
115
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
116
+ __pypackages__/
117
+
118
+ # Celery stuff
119
+ celerybeat-schedule
120
+ celerybeat.pid
121
+
122
+ # SageMath parsed files
123
+ *.sage.py
124
+
125
+ # Environments
126
+ .env
127
+ .venv
128
+ env/
129
+ venv/
130
+ ENV/
131
+ env.bak/
132
+ venv.bak/
133
+
134
+ # Spyder project settings
135
+ .spyderproject
136
+ .spyproject
137
+
138
+ # Rope project settings
139
+ .ropeproject
140
+
141
+ # mkdocs documentation
142
+ /site
143
+
144
+ # mypy
145
+ .mypy_cache/
146
+ .dmypy.json
147
+ dmypy.json
148
+
149
+ # Pyre type checker
150
+ .pyre/
151
+
152
+ # pytype static type analyzer
153
+ .pytype/
154
+
155
+ # Cython debug symbols
156
+ cython_debug/
157
+
158
+ # PyCharm
159
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
160
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
161
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
162
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
163
+ .idea/
164
+
165
+ node_modules
166
+
167
+ credentials.json
168
+ pyrightconfig.json
@@ -1,53 +1,43 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: livekit-agents
3
- Version: 1.0.0.dev2
3
+ Version: 1.0.0.dev4
4
4
  Summary: LiveKit Python Agents
5
- Home-page: https://github.com/livekit/agents
6
- License: Apache-2.0
7
5
  Project-URL: Documentation, https://docs.livekit.io
8
6
  Project-URL: Website, https://livekit.io/
9
7
  Project-URL: Source, https://github.com/livekit/agents
10
- Keywords: webrtc,realtime,audio,video,livekit,agents,AI
8
+ Author-email: LiveKit <support@livekit.io>
9
+ License-Expression: Apache-2.0
10
+ Keywords: AI,agents,audio,livekit,realtime,video,webrtc
11
11
  Classifier: Intended Audience :: Developers
12
12
  Classifier: License :: OSI Approved :: Apache Software License
13
- Classifier: Topic :: Multimedia :: Sound/Audio
14
- Classifier: Topic :: Multimedia :: Video
15
- Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
16
13
  Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3 :: Only
17
15
  Classifier: Programming Language :: Python :: 3.9
18
16
  Classifier: Programming Language :: Python :: 3.10
19
- Classifier: Programming Language :: Python :: 3 :: Only
20
- Requires-Python: >=3.9.0
21
- Description-Content-Type: text/markdown
17
+ Classifier: Topic :: Multimedia :: Sound/Audio
18
+ Classifier: Topic :: Multimedia :: Video
19
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
20
+ Requires-Python: >=3.9
21
+ Requires-Dist: aiohttp~=3.10
22
22
  Requires-Dist: click~=8.1
23
+ Requires-Dist: docstring-parser>=0.16
24
+ Requires-Dist: eval-type-backport
25
+ Requires-Dist: livekit-api>=0.8.2
26
+ Requires-Dist: livekit-protocol>=0.8.2
23
27
  Requires-Dist: livekit>=0.21.1
24
- Requires-Dist: livekit-api~=0.8.2
25
- Requires-Dist: livekit-protocol~=0.8.2
26
28
  Requires-Dist: protobuf>=3
27
- Requires-Dist: pyjwt>=2.0.0
28
- Requires-Dist: types-protobuf<5,>=4
29
- Requires-Dist: watchfiles~=0.22
30
- Requires-Dist: psutil~=5.9
31
- Requires-Dist: aiohttp~=3.10
32
- Requires-Dist: typing-extensions~=4.12
29
+ Requires-Dist: psutil>=7.0
30
+ Requires-Dist: pyjwt>=2.0
33
31
  Requires-Dist: sounddevice>=0.5
34
- Requires-Dist: colorama; sys_platform == "win32"
32
+ Requires-Dist: types-protobuf<5,>=4
33
+ Requires-Dist: typing-extensions>=4.12
34
+ Requires-Dist: watchfiles>=1.0
35
35
  Provides-Extra: codecs
36
- Requires-Dist: av>=12.0.0; extra == "codecs"
37
- Requires-Dist: numpy>=1.26.0; extra == "codecs"
36
+ Requires-Dist: av>=12.0.0; extra == 'codecs'
37
+ Requires-Dist: numpy>=1.26.0; extra == 'codecs'
38
38
  Provides-Extra: images
39
- Requires-Dist: pillow>=10.3.0; extra == "images"
40
- Dynamic: classifier
41
- Dynamic: description
42
- Dynamic: description-content-type
43
- Dynamic: home-page
44
- Dynamic: keywords
45
- Dynamic: license
46
- Dynamic: project-url
47
- Dynamic: provides-extra
48
- Dynamic: requires-dist
49
- Dynamic: requires-python
50
- Dynamic: summary
39
+ Requires-Dist: pillow>=10.3.0; extra == 'images'
40
+ Description-Content-Type: text/markdown
51
41
 
52
42
  # LiveKit Agents
53
43
 
@@ -12,18 +12,7 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- from . import (
16
- cli,
17
- ipc,
18
- llm,
19
- metrics,
20
- stt,
21
- tokenize,
22
- tts,
23
- utils,
24
- vad,
25
- voice,
26
- )
15
+ from . import cli, ipc, llm, metrics, stt, tokenize, tts, utils, vad, voice
27
16
  from ._exceptions import (
28
17
  APIConnectionError,
29
18
  APIError,
@@ -43,7 +32,7 @@ from .types import (
43
32
  NotGivenOr,
44
33
  )
45
34
  from .version import __version__
46
- from .voice import VoiceAgent
35
+ from .voice import AgentSession
47
36
  from .worker import Worker, WorkerOptions, WorkerPermissions, WorkerType
48
37
 
49
38
  __all__ = [
@@ -68,7 +57,7 @@ __all__ = [
68
57
  "llm",
69
58
  "metrics",
70
59
  "voice",
71
- "VoiceAgent",
60
+ "AgentSession",
72
61
  "cli",
73
62
  "AssignmentTimeoutError",
74
63
  "APIConnectionError",
@@ -153,7 +153,7 @@ def run_app(opts: WorkerOptions, *, hot_reload: NotGivenOr[bool] = NOT_GIVEN) ->
153
153
 
154
154
  args = proto.CliArgs(
155
155
  opts=opts,
156
- log_level="INFO",
156
+ log_level="DEBUG",
157
157
  devmode=True,
158
158
  asyncio_debug=False,
159
159
  watch=False,
@@ -293,7 +293,7 @@ def run_worker(args: proto.CliArgs) -> None:
293
293
  @worker.once("worker_started")
294
294
  def _worker_started():
295
295
  if args.simulate_job and args.reload_count == 0:
296
- logger.info("connecting to room %s", args.simulate_job.room)
296
+ # logger.info("connecting to room %s", args.simulate_job.room)
297
297
  loop.create_task(
298
298
  worker.simulate_job(args.simulate_job.room, args.simulate_job.participant_identity)
299
299
  )
@@ -7,7 +7,7 @@ import traceback
7
7
  from collections import OrderedDict
8
8
  from datetime import date, datetime, time, timezone
9
9
  from inspect import istraceback
10
- from typing import Any, Dict, Tuple
10
+ from typing import Any
11
11
 
12
12
  from ..plugin import Plugin
13
13
 
@@ -21,6 +21,8 @@ NOISY_LOGGERS = [
21
21
  "websockets.client",
22
22
  "aiohttp.access",
23
23
  "livekit",
24
+ "botocore",
25
+ "aiobotocore",
24
26
  ]
25
27
 
26
28
 
@@ -33,7 +35,7 @@ def _silence_noisy_loggers() -> None:
33
35
 
34
36
  # skip default LogRecord attributes
35
37
  # http://docs.python.org/library/logging.html#logrecord-attributes
36
- _RESERVED_ATTRS: Tuple[str, ...] = (
38
+ _RESERVED_ATTRS: tuple[str, ...] = (
37
39
  "args",
38
40
  "asctime",
39
41
  "created",
@@ -60,7 +62,7 @@ _RESERVED_ATTRS: Tuple[str, ...] = (
60
62
  )
61
63
 
62
64
 
63
- def _merge_record_extra(record: logging.LogRecord, target: Dict[Any, Any]):
65
+ def _merge_record_extra(record: logging.LogRecord, target: dict[Any, Any]):
64
66
  for key, value in record.__dict__.items():
65
67
  if key not in _RESERVED_ATTRS and not (hasattr(key, "startswith") and key.startswith("_")):
66
68
  target[key] = value
@@ -75,7 +77,7 @@ def _parse_style(formatter: logging.Formatter) -> list[str]:
75
77
  elif isinstance(formatter._style, logging.PercentStyle):
76
78
  formatter_style_pattern = re.compile(r"%\((.+?)\)", re.IGNORECASE)
77
79
  else:
78
- raise ValueError("Invalid format: %s" % formatter._fmt)
80
+ raise ValueError(f"Invalid format: {formatter._fmt}")
79
81
 
80
82
  if formatter._fmt:
81
83
  return formatter_style_pattern.findall(formatter._fmt)
@@ -108,7 +110,7 @@ class JsonFormatter(logging.Formatter):
108
110
 
109
111
  def format(self, record: logging.LogRecord) -> str:
110
112
  """Formats a log record and serializes to json"""
111
- message_dict: Dict[str, Any] = {}
113
+ message_dict: dict[str, Any] = {}
112
114
  message_dict["level"] = record.levelname
113
115
  message_dict["name"] = record.name
114
116
 
@@ -128,7 +130,7 @@ class JsonFormatter(logging.Formatter):
128
130
  if record.stack_info and not message_dict.get("stack_info"):
129
131
  message_dict["stack_info"] = self.formatStack(record.stack_info)
130
132
 
131
- log_record: Dict[str, Any] = OrderedDict()
133
+ log_record: dict[str, Any] = OrderedDict()
132
134
 
133
135
  for field in self._required_fields:
134
136
  log_record[field] = record.__dict__.get(field)
@@ -174,7 +176,7 @@ class ColoredFormatter(logging.Formatter):
174
176
  def formatMessage(self, record: logging.LogRecord) -> str:
175
177
  """Formats a log record with colors"""
176
178
 
177
- extra: Dict[Any, Any] = {}
179
+ extra: dict[Any, Any] = {}
178
180
  _merge_record_extra(record, extra)
179
181
 
180
182
  args = {}
@@ -8,7 +8,7 @@ import socket
8
8
  import urllib.parse
9
9
  import urllib.request
10
10
  from importlib.metadata import Distribution, PackageNotFoundError
11
- from typing import Any, Callable, Set
11
+ from typing import Any, Callable
12
12
 
13
13
  import watchfiles
14
14
 
@@ -98,7 +98,7 @@ class WatchServer:
98
98
  await utils.aio.cancel_and_wait(read_ipc_task)
99
99
  await self._pch.aclose()
100
100
 
101
- async def _on_reload(self, _: Set[watchfiles.main.FileChange]) -> None:
101
+ async def _on_reload(self, _: set[watchfiles.main.FileChange]) -> None:
102
102
  if self._worker_reloading:
103
103
  return
104
104
 
@@ -145,7 +145,7 @@ def _create_tracing_app(w: Worker) -> web.Application:
145
145
  import aiofiles
146
146
 
147
147
  with importlib.resources.path("livekit.agents.debug", "index.html") as path:
148
- async with aiofiles.open(path, mode="r") as f:
148
+ async with aiofiles.open(path) as f:
149
149
  content = await f.read()
150
150
 
151
151
  return web.Response(text=content, content_type="text/html")
@@ -160,7 +160,7 @@ def _create_tracing_app(w: Worker) -> web.Application:
160
160
  "room": runner.running_job.job.room.name if runner.running_job else None,
161
161
  }
162
162
  for runner in w._proc_pool.processes
163
- if runner.started
163
+ if runner.started and runner.running_job
164
164
  ]
165
165
  }
166
166
 
@@ -2,14 +2,14 @@ from __future__ import annotations
2
2
 
3
3
  import threading
4
4
  from abc import ABC, abstractmethod
5
- from typing import ClassVar, Protocol, Type
5
+ from typing import ClassVar, Protocol
6
6
 
7
7
 
8
8
  class _RunnerMeta(Protocol):
9
9
  INFERENCE_METHOD: ClassVar[str]
10
10
 
11
11
 
12
- _RunnersDict = dict[str, Type["_InferenceRunner"]]
12
+ _RunnersDict = dict[str, type["_InferenceRunner"]]
13
13
 
14
14
 
15
15
  # kept private until we stabilize the API (only used for EOU today)
@@ -17,7 +17,7 @@ class _InferenceRunner(ABC, _RunnerMeta):
17
17
  registered_runners: _RunnersDict = {}
18
18
 
19
19
  @classmethod
20
- def register_runner(cls, runner_class: Type["_InferenceRunner"]) -> None:
20
+ def register_runner(cls, runner_class: type[_InferenceRunner]) -> None:
21
21
  if threading.current_thread() != threading.main_thread():
22
22
  raise RuntimeError("InferenceRunner must be registered on the main thread")
23
23
 
@@ -3,8 +3,9 @@ from __future__ import annotations
3
3
  import asyncio
4
4
  import multiprocessing as mp
5
5
  import socket
6
+ from collections.abc import Awaitable
6
7
  from multiprocessing.context import BaseContext
7
- from typing import Any, Awaitable, Callable
8
+ from typing import Any, Callable
8
9
 
9
10
  from ..job import JobContext, JobProcess, RunningJobInfo
10
11
  from ..log import logger
@@ -172,6 +172,17 @@ class _JobProc:
172
172
  logger.warning("tracing request received without running job")
173
173
  return
174
174
 
175
+ try:
176
+ tracing_tasks = []
177
+ for callback in self._job_ctx._tracing_callbacks:
178
+ tracing_tasks.append(
179
+ asyncio.create_task(callback(), name="job_tracing_callback")
180
+ )
181
+
182
+ await asyncio.gather(*tracing_tasks)
183
+ except Exception:
184
+ logger.exception("error while exeuting tracing tasks")
185
+
175
186
  await self._client.send(
176
187
  TracingResponse(
177
188
  request_id=msg.request_id,
@@ -241,10 +252,8 @@ class _JobProc:
241
252
  await asyncio.sleep(10)
242
253
  if not self._ctx_connect_called and not self._ctx_shutdown_called:
243
254
  logger.warning(
244
- (
245
- "The room connection was not established within 10 seconds after calling job_entry. "
246
- "This may indicate that job_ctx.connect() was not called. "
247
- )
255
+ "The room connection was not established within 10 seconds after calling job_entry. "
256
+ "This may indicate that job_ctx.connect() was not called. "
248
257
  )
249
258
 
250
259
  warn_unconnected_task = asyncio.create_task(_warn_not_connected_task())
@@ -261,10 +270,8 @@ class _JobProc:
261
270
  return
262
271
 
263
272
  logger.warning(
264
- (
265
- "The job task completed without establishing a connection or performing a proper shutdown. "
266
- "Ensure that job_ctx.connect()/job_ctx.shutdown() is called and the job is correctly finalized."
267
- )
273
+ "The job task completed without establishing a connection or performing a proper shutdown. "
274
+ "Ensure that job_ctx.connect()/job_ctx.shutdown() is called and the job is correctly finalized."
268
275
  )
269
276
 
270
277
  job_entry_task.add_done_callback(log_exception)
@@ -4,8 +4,9 @@ import asyncio
4
4
  import contextlib
5
5
  import socket
6
6
  import threading
7
+ from collections.abc import Awaitable
7
8
  from dataclasses import dataclass
8
- from typing import Any, Awaitable, Callable
9
+ from typing import Any, Callable
9
10
 
10
11
  from .. import utils
11
12
  from ..job import JobContext, JobProcess, RunningJobInfo
@@ -5,19 +5,14 @@ import contextlib
5
5
  import logging
6
6
  import socket
7
7
  import sys
8
- from typing import Callable, Coroutine
8
+ from collections.abc import Coroutine
9
+ from typing import Callable
9
10
 
10
11
  from ..log import logger
11
12
  from ..utils import aio, log_exceptions, time_ms
12
13
  from .channel import Message, arecv_message, asend_message, recv_message, send_message
13
14
  from .log_queue import LogQueueHandler
14
- from .proto import (
15
- IPC_MESSAGES,
16
- InitializeRequest,
17
- InitializeResponse,
18
- PingRequest,
19
- PongResponse,
20
- )
15
+ from .proto import IPC_MESSAGES, InitializeRequest, InitializeResponse, PingRequest, PongResponse
21
16
 
22
17
 
23
18
  class _ProcClient:
@@ -25,7 +20,7 @@ class _ProcClient:
25
20
  self,
26
21
  mp_cch: socket.socket,
27
22
  log_cch: socket.socket | None,
28
- initialize_fnc: Callable[[InitializeRequest, "_ProcClient"], None],
23
+ initialize_fnc: Callable[[InitializeRequest, _ProcClient], None],
29
24
  main_task_fnc: Callable[[aio.ChanReceiver[Message]], Coroutine[None, None, None]],
30
25
  ) -> None:
31
26
  self._mp_cch = mp_cch
@@ -1,8 +1,9 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import asyncio
4
+ from collections.abc import Awaitable
4
5
  from multiprocessing.context import BaseContext
5
- from typing import Any, Awaitable, Callable, Literal
6
+ from typing import Any, Callable, Literal
6
7
 
7
8
  from .. import utils
8
9
  from ..job import JobContext, JobExecutorType, JobProcess, RunningJobInfo
@@ -18,9 +18,10 @@ import asyncio
18
18
  import contextvars
19
19
  import functools
20
20
  import multiprocessing as mp
21
+ from collections.abc import Coroutine
21
22
  from dataclasses import dataclass
22
23
  from enum import Enum, unique
23
- from typing import Any, Callable, Coroutine, Tuple, Union
24
+ from typing import Any, Callable
24
25
 
25
26
  from livekit import api, rtc
26
27
  from livekit.protocol import agent, models
@@ -94,14 +95,15 @@ class JobContext:
94
95
  self._room = room
95
96
  self._on_connect = on_connect
96
97
  self._on_shutdown = on_shutdown
97
- self._shutdown_callbacks: list[Callable[[str], Coroutine[None, None, None]],] = []
98
+ self._shutdown_callbacks: list[Callable[[str], Coroutine[None, None, None]]] = []
99
+ self._tracing_callbacks: list[Callable[[], Coroutine[None, None, None]]] = []
98
100
  self._participant_entrypoints: list[
99
- Tuple[
101
+ tuple[
100
102
  Callable[[JobContext, rtc.RemoteParticipant], Coroutine[None, None, None]],
101
103
  list[rtc.ParticipantKind.ValueType] | rtc.ParticipantKind.ValueType,
102
104
  ]
103
105
  ] = []
104
- self._participant_tasks = dict[Tuple[str, Callable], asyncio.Task[None]]()
106
+ self._participant_tasks = dict[tuple[str, Callable], asyncio.Task[None]]()
105
107
  self._room.on("participant_connected", self._participant_available)
106
108
  self._inf_executor = inference_executor
107
109
 
@@ -141,12 +143,19 @@ class JobContext:
141
143
  def agent(self) -> rtc.LocalParticipant:
142
144
  return self._room.local_participant
143
145
 
146
+ def add_tracing_callback(
147
+ self,
148
+ callback: Callable[[], Coroutine[None, None, None]],
149
+ ) -> None:
150
+ """
151
+ Add a callback to be called when the job is about to receive a new tracing request.
152
+ """
153
+ self._tracing_callbacks.append(callback)
154
+
144
155
  def add_shutdown_callback(
145
156
  self,
146
- callback: Union[
147
- Callable[[], Coroutine[None, None, None]],
148
- Callable[[str], Coroutine[None, None, None]],
149
- ],
157
+ callback: Callable[[], Coroutine[None, None, None]]
158
+ | Callable[[str], Coroutine[None, None, None]],
150
159
  ) -> None:
151
160
  """
152
161
  Add a callback to be called when the job is shutting down.
@@ -11,15 +11,6 @@ from .chat_context import (
11
11
  ImageContent,
12
12
  )
13
13
  from .fallback_adapter import AvailabilityChangedEvent, FallbackAdapter
14
- from .function_context import (
15
- AIError,
16
- AIFunction,
17
- FunctionContext,
18
- StopResponse,
19
- ai_function,
20
- find_ai_functions,
21
- is_ai_function,
22
- )
23
14
  from .llm import (
24
15
  LLM,
25
16
  ChatChunk,
@@ -27,7 +18,6 @@ from .llm import (
27
18
  CompletionUsage,
28
19
  FunctionToolCall,
29
20
  LLMStream,
30
- ToolChoice,
31
21
  )
32
22
  from .realtime import (
33
23
  ErrorEvent,
@@ -35,13 +25,22 @@ from .realtime import (
35
25
  InputSpeechStartedEvent,
36
26
  InputSpeechStoppedEvent,
37
27
  InputTranscriptionCompleted,
38
- InputTranscriptionFailed,
39
28
  MessageGeneration,
40
29
  RealtimeCapabilities,
41
30
  RealtimeError,
42
31
  RealtimeModel,
43
32
  RealtimeSession,
44
33
  )
34
+ from .tool_context import (
35
+ FunctionTool,
36
+ StopResponse,
37
+ ToolContext,
38
+ ToolError,
39
+ find_function_tools,
40
+ function_tool,
41
+ is_function_tool,
42
+ ToolChoice,
43
+ )
45
44
 
46
45
  __all__ = [
47
46
  "LLM",
@@ -62,12 +61,12 @@ __all__ = [
62
61
  "FallbackAdapter",
63
62
  "AvailabilityChangedEvent",
64
63
  "ToolChoice",
65
- "is_ai_function",
66
- "ai_function",
67
- "find_ai_functions",
68
- "AIFunction",
69
- "FunctionContext",
70
- "AIError",
64
+ "is_function_tool",
65
+ "function_tool",
66
+ "find_function_tools",
67
+ "FunctionTool",
68
+ "ToolContext",
69
+ "ToolError",
71
70
  "StopResponse",
72
71
  "utils",
73
72
  "remote_chat_context",
@@ -52,7 +52,7 @@ def _ensure_strict_json_schema(
52
52
  # { 'type': 'object', 'properties': { 'a': {...} } }
53
53
  properties = json_schema.get("properties")
54
54
  if is_dict(properties):
55
- json_schema["required"] = [prop for prop in properties.keys()]
55
+ json_schema["required"] = list(properties.keys())
56
56
  json_schema["properties"] = {
57
57
  key: _ensure_strict_json_schema(prop_schema, path=(*path, "properties", key), root=root)
58
58
  for key, prop_schema in properties.items()