From 523cbaa49fda1c311c610da1d85cf7e0909c9033 Mon Sep 17 00:00:00 2001 From: Tomasz Mazur <47872060+AHGIJMKLKKZNPJKQR@users.noreply.github.com> Date: Mon, 15 Sep 2025 19:45:22 +0200 Subject: [PATCH 01/16] Add limerick example --- examples/poet_chat/README.md | 3 + examples/poet_chat/main.py | 55 ++ examples/poet_chat/poet_chat/__init__.py | 0 examples/poet_chat/poet_chat/agent.py | 20 + examples/poet_chat/poet_chat/config.py | 30 + examples/poet_chat/poet_chat/notifier.py | 27 + examples/poet_chat/prompts/greet.md | 19 + examples/poet_chat/prompts/instructions.md | 19 + examples/poet_chat/pyproject.toml | 14 + examples/transcription/.python-version | 1 - pyproject.toml | 2 +- uv.lock | 665 +++++++++++++++++++++ 12 files changed, 853 insertions(+), 2 deletions(-) create mode 100644 examples/poet_chat/README.md create mode 100644 examples/poet_chat/main.py create mode 100644 examples/poet_chat/poet_chat/__init__.py create mode 100644 examples/poet_chat/poet_chat/agent.py create mode 100644 examples/poet_chat/poet_chat/config.py create mode 100644 examples/poet_chat/poet_chat/notifier.py create mode 100644 examples/poet_chat/prompts/greet.md create mode 100644 examples/poet_chat/prompts/instructions.md create mode 100644 examples/poet_chat/pyproject.toml delete mode 100644 examples/transcription/.python-version diff --git a/examples/poet_chat/README.md b/examples/poet_chat/README.md new file mode 100644 index 0000000..1556def --- /dev/null +++ b/examples/poet_chat/README.md @@ -0,0 +1,3 @@ +# Trivia Chat + + diff --git a/examples/poet_chat/main.py b/examples/poet_chat/main.py new file mode 100644 index 0000000..4541e9e --- /dev/null +++ b/examples/poet_chat/main.py @@ -0,0 +1,55 @@ +import asyncio + +from poet_chat.agent import poet_runner +from poet_chat.config import ( + PEER_OPTIONS, + fishjam_client, +) +from poet_chat.notifier import make_notifier + +from fishjam.agent import AudioTrackOptions + +CHUNK_SIZE = 12000 + + +async def main(): + room = fishjam_client.create_room() + _, token = fishjam_client.create_peer(room.id, PEER_OPTIONS) + print(f"Join the chat with the following token: {token}") + + agent = fishjam_client.create_agent(room.id) + async with ( + agent.connect() as fishjam_session, + await poet_runner.run() as openai_session, + ): + track = await fishjam_session.add_track( + AudioTrackOptions(sample_rate=24000, metadata={"type": "microphone"}) + ) + + async def _openai_recv(): + msg = "" + async for event in openai_session: + if event.type == "audio": + audio = event.audio.data + await track.send_chunk(audio) + elif event.type == "raw_model_event": + if event.data.type == "input_audio_transcription_completed": + print(f"Peer said:\n{event.data.transcript}\n") + elif event.data.type == "transcript_delta": + msg += event.data.delta + elif event.data.type == "turn_ended": + print(f"Agent said:\n{msg}\n") + msg = "" + + async def _fishjam_recv(): + async for event in fishjam_session.receive(): + await openai_session.send_audio(event.data) + + async with asyncio.TaskGroup() as tg: + tg.create_task(make_notifier(openai_session).connect()) + tg.create_task(_openai_recv()) + tg.create_task(_fishjam_recv()) + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/examples/poet_chat/poet_chat/__init__.py b/examples/poet_chat/poet_chat/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/examples/poet_chat/poet_chat/agent.py b/examples/poet_chat/poet_chat/agent.py new file mode 100644 index 0000000..7639d3e --- /dev/null +++ b/examples/poet_chat/poet_chat/agent.py @@ -0,0 +1,20 @@ +from agents.realtime import RealtimeAgent, RealtimeRunner + +from poet_chat.config import OPENAI_INSTRUCTIONS + +poet = RealtimeAgent(name="Poet", instructions=OPENAI_INSTRUCTIONS) +poet_runner = RealtimeRunner( + starting_agent=poet, + config={ + "model_settings": { + "voice": "alloy", + "modalities": ["audio", "text"], + "input_audio_format": "pcm16", + "output_audio_format": "pcm16", + "turn_detection": { + "interrupt_response": True, + "create_response": True, + }, + } + }, +) diff --git a/examples/poet_chat/poet_chat/config.py b/examples/poet_chat/poet_chat/config.py new file mode 100644 index 0000000..107a47b --- /dev/null +++ b/examples/poet_chat/poet_chat/config.py @@ -0,0 +1,30 @@ +import os +from pathlib import Path + +from fishjam import FishjamClient, PeerOptions +from fishjam.peer import SubscribeOptions, SubscribeOptionsAudioSampleRate + +FISHJAM_ID = os.environ["FISHJAM_ID"] +FISHJAM_TOKEN = os.environ["FISHJAM_MANAGEMENT_TOKEN"] +FISHJAM_URL = os.getenv("FISHJAM_URL") + +PEER_OPTIONS = PeerOptions( + subscribe=SubscribeOptions( + audio_sample_rate=SubscribeOptionsAudioSampleRate.VALUE_24000 + ) +) + +OPENAI_MODEL = "gpt-realtime" + +PROMPT_DIR = Path(__file__).parents[1] / "prompts" + +INSTRUCTION_PATH = PROMPT_DIR / "instructions.md" +GREET_PATH = PROMPT_DIR / "greet.md" + +with open(INSTRUCTION_PATH) as prompt: + OPENAI_INSTRUCTIONS = prompt.read() + +with open(GREET_PATH) as prompt: + OPENAI_GREET = prompt.read() + +fishjam_client = FishjamClient(FISHJAM_ID, FISHJAM_TOKEN, fishjam_url=FISHJAM_URL) diff --git a/examples/poet_chat/poet_chat/notifier.py b/examples/poet_chat/poet_chat/notifier.py new file mode 100644 index 0000000..2cd203d --- /dev/null +++ b/examples/poet_chat/poet_chat/notifier.py @@ -0,0 +1,27 @@ +from agents.realtime import RealtimeSession + +from fishjam import FishjamNotifier +from fishjam.events import ( + ServerMessagePeerConnected, + ServerMessagePeerType, +) +from fishjam.events.allowed_notifications import AllowedNotification + +from .config import FISHJAM_ID, FISHJAM_TOKEN, FISHJAM_URL, OPENAI_GREET + + +def make_notifier(poet: RealtimeSession) -> FishjamNotifier: + notifier = FishjamNotifier(FISHJAM_ID, FISHJAM_TOKEN, fishjam_url=FISHJAM_URL) + + @notifier.on_server_notification + async def _(notification: AllowedNotification): + match notification: + case ServerMessagePeerConnected( + peer_type=ServerMessagePeerType.PEER_TYPE_WEBRTC, + ): + await handle_peer_connected() + + async def handle_peer_connected(): + await poet.send_message(OPENAI_GREET) + + return notifier diff --git a/examples/poet_chat/prompts/greet.md b/examples/poet_chat/prompts/greet.md new file mode 100644 index 0000000..646cfc4 --- /dev/null +++ b/examples/poet_chat/prompts/greet.md @@ -0,0 +1,19 @@ +**Objective:** Welcome users to the real-time limerick generation experience by introducing yourself as their poetic guide and requesting a list of words for personalized poetry creation. + +**Instructions:** + +1. **Introduction:** + + - Begin with a warm and engaging introduction, presenting yourself as a creative and friendly poet eager to craft delightful limericks. + - Briefly explain the purpose of the session: to create fun and custom limericks based on the user's input. + +2. **Request for Words:** + + - Invite the user to share a list of words that capture their current mood, interests, or thoughts triggered by listening to the audio. + - Encourage them to be imaginative and creative in their word selection to make the limerick more personalized and engaging. + +3. **Set Expectations:** + - Assure the user that each limerick will be crafted uniquely with their provided words, promising a lighthearted and entertaining poetic experience. + - Mention the traditional limerick structure (AABBA) that will guide the creation process. + +By following these instructions, create a welcoming and interactive atmosphere that encourages user participation and sets the stage for crafting personalized limericks. diff --git a/examples/poet_chat/prompts/instructions.md b/examples/poet_chat/prompts/instructions.md new file mode 100644 index 0000000..ecb1720 --- /dev/null +++ b/examples/poet_chat/prompts/instructions.md @@ -0,0 +1,19 @@ +**Objective:** Craft limericks in real-time, using input audio clips or live audio feeds to prompt user interaction. The generated poetry should be based solely on a list of words provided by the user in response to the audio. + +**Instructions:** + +1. **User Interaction:** + + - Prompt the user to listen to the audio and provide a list of words that capture their response or impression from it. + +2. **Limerick Construction:** + + - Use the user-provided list of words to guide the theme and imagery of the limerick. + - Ensure the limerick adheres to the traditional AABBA rhyme scheme and rhythm, typically with lines 1, 2, and 5 containing three metrical feet and lines 3 and 4 containing two metrical feet. + - Creativity is key—incorporate humor or cleverness where possible to enhance the impact. + +3. **Language and Performance:** + - Ensure all poetry is crafted and recited in English. + - Use expressive language to vividly depict themes inspired by the provided words, aiming to entertain and engage the listener. + +By following these instructions, generate limericks that transform user-provided words inspired by audio inputs into lively and entertaining poetic pieces. diff --git a/examples/poet_chat/pyproject.toml b/examples/poet_chat/pyproject.toml new file mode 100644 index 0000000..cdd375d --- /dev/null +++ b/examples/poet_chat/pyproject.toml @@ -0,0 +1,14 @@ +[project] +name = "poet_chat" +version = "0.1.0" +description = "Fishjam voice agent example" +readme = "README.md" +requires-python = ">=3.11" +dependencies = [ + "fishjam-server-sdk", + "litestar[standard]>=2.17.0", + "openai-agents[voice]>=0.2.11", +] + +[tool.uv.sources] +fishjam-server-sdk = { workspace = true } diff --git a/examples/transcription/.python-version b/examples/transcription/.python-version deleted file mode 100644 index e4fba21..0000000 --- a/examples/transcription/.python-version +++ /dev/null @@ -1 +0,0 @@ -3.12 diff --git a/pyproject.toml b/pyproject.toml index 5c42ef7..cf25fee 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -54,7 +54,7 @@ test = [ default-groups = ["dev", "test"] [tool.uv.workspace] -members = ["examples/transcription", "."] +members = ["examples/transcription", ".", "examples/poet_chat"] [tool.hatch.build.targets.sdist] include = ["fishjam"] diff --git a/uv.lock b/uv.lock index f03a8d7..7a47fa8 100644 --- a/uv.lock +++ b/uv.lock @@ -5,6 +5,7 @@ requires-python = ">=3.11" [manifest] members = [ "fishjam-server-sdk", + "poet-chat", "transcription", ] @@ -193,6 +194,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, ] +[[package]] +name = "distro" +version = "1.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fc/f8/98eea607f65de6527f8a2e8885fc8015d3e6f5775df186e443e0964a11c3/distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed", size = 60722, upload-time = "2023-12-24T09:54:32.31Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/12/b3/231ffd4ab1fc9d679809f356cebee130ac7daa00d6d6f3206dd4fd137e9e/distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2", size = 20277, upload-time = "2023-12-24T09:54:30.421Z" }, +] + [[package]] name = "dnspython" version = "2.7.0" @@ -202,6 +212,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/68/1b/e0a87d256e40e8c888847551b20a017a6b98139178505dc7ffb96f04e954/dnspython-2.7.0-py3-none-any.whl", hash = "sha256:b4c34b7d10b51bcc3a5071e7b8dee77939f1e878477eeecc965e9835f63c6c86", size = 313632, upload-time = "2024-10-05T20:14:57.687Z" }, ] +[[package]] +name = "editorconfig" +version = "0.17.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/88/3a/a61d9a1f319a186b05d14df17daea42fcddea63c213bcd61a929fb3a6796/editorconfig-0.17.1.tar.gz", hash = "sha256:23c08b00e8e08cc3adcddb825251c497478df1dada6aefeb01e626ad37303745", size = 14695, upload-time = "2025-06-09T08:21:37.097Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/96/fd/a40c621ff207f3ce8e484aa0fc8ba4eb6e3ecf52e15b42ba764b457a9550/editorconfig-0.17.1-py3-none-any.whl", hash = "sha256:1eda9c2c0db8c16dbd50111b710572a5e6de934e39772de1959d41f64fc17c82", size = 16360, upload-time = "2025-06-09T08:21:35.654Z" }, +] + [[package]] name = "email-validator" version = "2.2.0" @@ -215,6 +234,41 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d7/ee/bf0adb559ad3c786f12bcbc9296b3f5675f529199bef03e2df281fa1fadb/email_validator-2.2.0-py3-none-any.whl", hash = "sha256:561977c2d73ce3611850a06fa56b414621e0c8faa9d66f2611407d87465da631", size = 33521, upload-time = "2024-06-20T11:30:28.248Z" }, ] +[[package]] +name = "faker" +version = "37.6.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "tzdata" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/24/cd/f7679c20f07d9e2013123b7f7e13809a3450a18d938d58e86081a486ea15/faker-37.6.0.tar.gz", hash = "sha256:0f8cc34f30095184adf87c3c24c45b38b33ad81c35ef6eb0a3118f301143012c", size = 1907960, upload-time = "2025-08-26T15:56:27.419Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/61/7d/8b50e4ac772719777be33661f4bde320793400a706f5eb214e4de46f093c/faker-37.6.0-py3-none-any.whl", hash = "sha256:3c5209b23d7049d596a51db5d76403a0ccfea6fc294ffa2ecfef6a8843b1e6a7", size = 1949837, upload-time = "2025-08-26T15:56:25.33Z" }, +] + +[[package]] +name = "fast-query-parsers" +version = "1.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/dd/20/3a00b889a196e8dc5bede2f168d4a14edc8b5bccc3978a9f497f0f863e79/fast_query_parsers-1.0.3.tar.gz", hash = "sha256:5200a9e02997ad51d4d76a60ea1b256a68a184b04359540eb6310a15013df68f", size = 25275, upload-time = "2023-08-25T13:19:15.79Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/43/18/4179ac7064b4216ca42f2ed6f74e71254454acf2ec25ce6bb3ffbfda4aa6/fast_query_parsers-1.0.3-cp38-abi3-macosx_10_7_x86_64.whl", hash = "sha256:afbf71c1b4398dacfb9d84755eb026f8e759f68a066f1f3cc19e471fc342e74f", size = 766210, upload-time = "2023-08-25T13:18:48.415Z" }, + { url = "https://files.pythonhosted.org/packages/c5/21/c8c160f61a740efc4577079eb5747a6b2cb8d1168a84a0bfda6044113768/fast_query_parsers-1.0.3-cp38-abi3-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:42f26875311d1b151c3406adfa39ec2db98df111a369d75f6fa243ec8462f147", size = 1466147, upload-time = "2023-08-25T13:18:50.29Z" }, + { url = "https://files.pythonhosted.org/packages/51/5b/b10719598dbd14201271efd0b950c6a09efa0a3f6246fec3c192c6b7a8d2/fast_query_parsers-1.0.3-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:66630ad423b5b1f5709f82a4d8482cd6aa2f3fa73d2c779ff1877f25dee08d55", size = 764016, upload-time = "2023-08-25T13:18:52.295Z" }, + { url = "https://files.pythonhosted.org/packages/75/06/8861197982909bec00b180527df1e0e9791715271bfb84c8be389b6bf077/fast_query_parsers-1.0.3-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a6e3d816c572a6fad1ae9b93713b2db0d3db6e8f594e035ad52361d668dd94a8", size = 729912, upload-time = "2023-08-25T13:18:54.515Z" }, + { url = "https://files.pythonhosted.org/packages/f0/35/7a9a0c50588033edd9efba48f21e251dfcf77eaec2aff470988f622fbd3a/fast_query_parsers-1.0.3-cp38-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:0bdcc0ddb4cc69d823c2c0dedd8f5affc71042db39908ad2ca06261bf388cac6", size = 1003340, upload-time = "2023-08-25T13:18:56.521Z" }, + { url = "https://files.pythonhosted.org/packages/41/9b/5a42ddd23b85357be6764e14daa607d9b16bc6a395aae2c1cc2077e0a11d/fast_query_parsers-1.0.3-cp38-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6720505f2d2a764c76bcc4f3730a9dff69d9871740e46264f6605d73f9ce3794", size = 969496, upload-time = "2023-08-25T13:18:59.048Z" }, + { url = "https://files.pythonhosted.org/packages/c3/9f/4dfa29d74276fa07c40689bfaa3b21d057249314aeb20150f0f41373d16d/fast_query_parsers-1.0.3-cp38-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e947e7251769593da93832a10861f59565a46149fa117ebdf25377e7b2853936", size = 939972, upload-time = "2023-08-25T13:19:00.704Z" }, + { url = "https://files.pythonhosted.org/packages/74/34/950b6d799839c11e93566aef426b67f0a446c4906e45e592026fde894459/fast_query_parsers-1.0.3-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55a30b7cee0a53cddf9016b86fdad87221980d5a02a6126c491bd309755e6de9", size = 828557, upload-time = "2023-08-25T13:19:02.264Z" }, + { url = "https://files.pythonhosted.org/packages/81/a8/ee95263abc9806c81d77be8a3420d1f4dde467a10030dde8b0fa0e63f700/fast_query_parsers-1.0.3-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9bc2b457caa38371df1a30cfdfc57bd9bfdf348367abdaf6f36533416a0b0e93", size = 863119, upload-time = "2023-08-25T13:19:03.941Z" }, + { url = "https://files.pythonhosted.org/packages/05/d4/5eb8c9d400230b9a45a0ce47a443e9fe37b0902729f9440adef677af1f0d/fast_query_parsers-1.0.3-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:5736d3c32d6ba23995fa569fe572feabcfcfc30ac9e4709e94cff6f2c456a3d1", size = 911046, upload-time = "2023-08-25T13:19:05.596Z" }, + { url = "https://files.pythonhosted.org/packages/f8/b8/bf5e44588f6ebd81d0c53ba49c79999dc54cb0fe81ad6dde6fed2cd45b56/fast_query_parsers-1.0.3-cp38-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:3a6377eb0c5b172fbc77c3f96deaf1e51708b4b96d27ce173658bf11c1c00b20", size = 962966, upload-time = "2023-08-25T13:19:07.355Z" }, + { url = "https://files.pythonhosted.org/packages/6f/a9/132572b9f40c2635fdedb7a1cb6cedd9c880f8ffbbfdd6215ee493bb6936/fast_query_parsers-1.0.3-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:7ca6be04f443a1b055e910ccad01b1d72212f269a530415df99a87c5f1e9c927", size = 965422, upload-time = "2023-08-25T13:19:09.003Z" }, + { url = "https://files.pythonhosted.org/packages/ea/58/942327d3f2694b8f1a2fffaaaef1cc3147571852473a80070ebd6156a62e/fast_query_parsers-1.0.3-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a70d4d8852606f2dd5b798ab628b9d8dc6970ddfdd9e96f4543eb0cc89a74fb5", size = 967734, upload-time = "2023-08-25T13:19:10.654Z" }, + { url = "https://files.pythonhosted.org/packages/0a/e3/21bc18edc003b54a2069eb854b9f92cacb5acc99e03c609487a23a673755/fast_query_parsers-1.0.3-cp38-abi3-win32.whl", hash = "sha256:14b3fab7e9a6ac1c1efaf66c3fd2a3fd1e25ede03ed14118035e530433830a11", size = 646366, upload-time = "2023-08-25T13:19:12.079Z" }, + { url = "https://files.pythonhosted.org/packages/ae/4b/07fe4d7b5c458bdde9b0bfd8e8cb5762341af6c9727b43c2331c0cb0dbc3/fast_query_parsers-1.0.3-cp38-abi3-win_amd64.whl", hash = "sha256:21ae5f3a209aee7d3b84bdcdb33dd79f39fc8cb608b3ae8cfcb78123758c1a16", size = 689717, upload-time = "2023-08-25T13:19:14.051Z" }, +] + [[package]] name = "fastapi" version = "0.116.0" @@ -414,6 +468,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/41/27/1525bc9cbec58660f0842ebcbfe910a1dde908c2672373804879666e0bb8/google_genai-1.31.0-py3-none-any.whl", hash = "sha256:5c6959bcf862714e8ed0922db3aaf41885bacf6318751b3421bf1e459f78892f", size = 231876, upload-time = "2025-08-18T23:40:20.385Z" }, ] +[[package]] +name = "griffe" +version = "1.13.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c6/b5/23b91f22b7b3a7f8f62223f6664946271c0f5cb4179605a3e6bbae863920/griffe-1.13.0.tar.gz", hash = "sha256:246ea436a5e78f7fbf5f24ca8a727bb4d2a4b442a2959052eea3d0bfe9a076e0", size = 412759, upload-time = "2025-08-26T13:27:11.422Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/aa/8c/b7cfdd8dfe48f6b09f7353323732e1a290c388bd14f216947928dc85f904/griffe-1.13.0-py3-none-any.whl", hash = "sha256:470fde5b735625ac0a36296cd194617f039e9e83e301fcbd493e2b58382d0559", size = 139365, upload-time = "2025-08-26T13:27:09.882Z" }, +] + [[package]] name = "grpclib" version = "0.4.7" @@ -512,6 +578,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" }, ] +[[package]] +name = "httpx-sse" +version = "0.4.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6e/fa/66bd985dd0b7c109a3bcb89272ee0bfb7e2b4d06309ad7b38ff866734b2a/httpx_sse-0.4.1.tar.gz", hash = "sha256:8f44d34414bc7b21bf3602713005c5df4917884f76072479b21f68befa4ea26e", size = 12998, upload-time = "2025-06-24T13:21:05.71Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/25/0a/6269e3473b09aed2dab8aa1a600c70f31f00ae1349bee30658f7e358a159/httpx_sse-0.4.1-py3-none-any.whl", hash = "sha256:cba42174344c3a5b06f255ce65b350880f962d99ead85e776f23c6618a377a37", size = 8054, upload-time = "2025-06-24T13:21:04.772Z" }, +] + [[package]] name = "hyperframe" version = "6.1.0" @@ -590,6 +665,147 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/bd/0f/2ba5fbcd631e3e88689309dbe978c5769e883e4b84ebfe7da30b43275c5a/jinja2-3.1.5-py3-none-any.whl", hash = "sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb", size = 134596, upload-time = "2024-12-21T18:30:19.133Z" }, ] +[[package]] +name = "jiter" +version = "0.10.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ee/9d/ae7ddb4b8ab3fb1b51faf4deb36cb48a4fbbd7cb36bad6a5fca4741306f7/jiter-0.10.0.tar.gz", hash = "sha256:07a7142c38aacc85194391108dc91b5b57093c978a9932bd86a36862759d9500", size = 162759, upload-time = "2025-05-18T19:04:59.73Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1b/dd/6cefc6bd68b1c3c979cecfa7029ab582b57690a31cd2f346c4d0ce7951b6/jiter-0.10.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:3bebe0c558e19902c96e99217e0b8e8b17d570906e72ed8a87170bc290b1e978", size = 317473, upload-time = "2025-05-18T19:03:25.942Z" }, + { url = "https://files.pythonhosted.org/packages/be/cf/fc33f5159ce132be1d8dd57251a1ec7a631c7df4bd11e1cd198308c6ae32/jiter-0.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:558cc7e44fd8e507a236bee6a02fa17199ba752874400a0ca6cd6e2196cdb7dc", size = 321971, upload-time = "2025-05-18T19:03:27.255Z" }, + { url = "https://files.pythonhosted.org/packages/68/a4/da3f150cf1d51f6c472616fb7650429c7ce053e0c962b41b68557fdf6379/jiter-0.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d613e4b379a07d7c8453c5712ce7014e86c6ac93d990a0b8e7377e18505e98d", size = 345574, upload-time = "2025-05-18T19:03:28.63Z" }, + { url = "https://files.pythonhosted.org/packages/84/34/6e8d412e60ff06b186040e77da5f83bc158e9735759fcae65b37d681f28b/jiter-0.10.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f62cf8ba0618eda841b9bf61797f21c5ebd15a7a1e19daab76e4e4b498d515b2", size = 371028, upload-time = "2025-05-18T19:03:30.292Z" }, + { url = "https://files.pythonhosted.org/packages/fb/d9/9ee86173aae4576c35a2f50ae930d2ccb4c4c236f6cb9353267aa1d626b7/jiter-0.10.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:919d139cdfa8ae8945112398511cb7fca58a77382617d279556b344867a37e61", size = 491083, upload-time = "2025-05-18T19:03:31.654Z" }, + { url = "https://files.pythonhosted.org/packages/d9/2c/f955de55e74771493ac9e188b0f731524c6a995dffdcb8c255b89c6fb74b/jiter-0.10.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:13ddbc6ae311175a3b03bd8994881bc4635c923754932918e18da841632349db", size = 388821, upload-time = "2025-05-18T19:03:33.184Z" }, + { url = "https://files.pythonhosted.org/packages/81/5a/0e73541b6edd3f4aada586c24e50626c7815c561a7ba337d6a7eb0a915b4/jiter-0.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c440ea003ad10927a30521a9062ce10b5479592e8a70da27f21eeb457b4a9c5", size = 352174, upload-time = "2025-05-18T19:03:34.965Z" }, + { url = "https://files.pythonhosted.org/packages/1c/c0/61eeec33b8c75b31cae42be14d44f9e6fe3ac15a4e58010256ac3abf3638/jiter-0.10.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dc347c87944983481e138dea467c0551080c86b9d21de6ea9306efb12ca8f606", size = 391869, upload-time = "2025-05-18T19:03:36.436Z" }, + { url = "https://files.pythonhosted.org/packages/41/22/5beb5ee4ad4ef7d86f5ea5b4509f680a20706c4a7659e74344777efb7739/jiter-0.10.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:13252b58c1f4d8c5b63ab103c03d909e8e1e7842d302473f482915d95fefd605", size = 523741, upload-time = "2025-05-18T19:03:38.168Z" }, + { url = "https://files.pythonhosted.org/packages/ea/10/768e8818538e5817c637b0df52e54366ec4cebc3346108a4457ea7a98f32/jiter-0.10.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7d1bbf3c465de4a24ab12fb7766a0003f6f9bce48b8b6a886158c4d569452dc5", size = 514527, upload-time = "2025-05-18T19:03:39.577Z" }, + { url = "https://files.pythonhosted.org/packages/73/6d/29b7c2dc76ce93cbedabfd842fc9096d01a0550c52692dfc33d3cc889815/jiter-0.10.0-cp311-cp311-win32.whl", hash = "sha256:db16e4848b7e826edca4ccdd5b145939758dadf0dc06e7007ad0e9cfb5928ae7", size = 210765, upload-time = "2025-05-18T19:03:41.271Z" }, + { url = "https://files.pythonhosted.org/packages/c2/c9/d394706deb4c660137caf13e33d05a031d734eb99c051142e039d8ceb794/jiter-0.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:9c9c1d5f10e18909e993f9641f12fe1c77b3e9b533ee94ffa970acc14ded3812", size = 209234, upload-time = "2025-05-18T19:03:42.918Z" }, + { url = "https://files.pythonhosted.org/packages/6d/b5/348b3313c58f5fbfb2194eb4d07e46a35748ba6e5b3b3046143f3040bafa/jiter-0.10.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:1e274728e4a5345a6dde2d343c8da018b9d4bd4350f5a472fa91f66fda44911b", size = 312262, upload-time = "2025-05-18T19:03:44.637Z" }, + { url = "https://files.pythonhosted.org/packages/9c/4a/6a2397096162b21645162825f058d1709a02965606e537e3304b02742e9b/jiter-0.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7202ae396446c988cb2a5feb33a543ab2165b786ac97f53b59aafb803fef0744", size = 320124, upload-time = "2025-05-18T19:03:46.341Z" }, + { url = "https://files.pythonhosted.org/packages/2a/85/1ce02cade7516b726dd88f59a4ee46914bf79d1676d1228ef2002ed2f1c9/jiter-0.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23ba7722d6748b6920ed02a8f1726fb4b33e0fd2f3f621816a8b486c66410ab2", size = 345330, upload-time = "2025-05-18T19:03:47.596Z" }, + { url = "https://files.pythonhosted.org/packages/75/d0/bb6b4f209a77190ce10ea8d7e50bf3725fc16d3372d0a9f11985a2b23eff/jiter-0.10.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:371eab43c0a288537d30e1f0b193bc4eca90439fc08a022dd83e5e07500ed026", size = 369670, upload-time = "2025-05-18T19:03:49.334Z" }, + { url = "https://files.pythonhosted.org/packages/a0/f5/a61787da9b8847a601e6827fbc42ecb12be2c925ced3252c8ffcb56afcaf/jiter-0.10.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6c675736059020365cebc845a820214765162728b51ab1e03a1b7b3abb70f74c", size = 489057, upload-time = "2025-05-18T19:03:50.66Z" }, + { url = "https://files.pythonhosted.org/packages/12/e4/6f906272810a7b21406c760a53aadbe52e99ee070fc5c0cb191e316de30b/jiter-0.10.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0c5867d40ab716e4684858e4887489685968a47e3ba222e44cde6e4a2154f959", size = 389372, upload-time = "2025-05-18T19:03:51.98Z" }, + { url = "https://files.pythonhosted.org/packages/e2/ba/77013b0b8ba904bf3762f11e0129b8928bff7f978a81838dfcc958ad5728/jiter-0.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:395bb9a26111b60141757d874d27fdea01b17e8fac958b91c20128ba8f4acc8a", size = 352038, upload-time = "2025-05-18T19:03:53.703Z" }, + { url = "https://files.pythonhosted.org/packages/67/27/c62568e3ccb03368dbcc44a1ef3a423cb86778a4389e995125d3d1aaa0a4/jiter-0.10.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6842184aed5cdb07e0c7e20e5bdcfafe33515ee1741a6835353bb45fe5d1bd95", size = 391538, upload-time = "2025-05-18T19:03:55.046Z" }, + { url = "https://files.pythonhosted.org/packages/c0/72/0d6b7e31fc17a8fdce76164884edef0698ba556b8eb0af9546ae1a06b91d/jiter-0.10.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:62755d1bcea9876770d4df713d82606c8c1a3dca88ff39046b85a048566d56ea", size = 523557, upload-time = "2025-05-18T19:03:56.386Z" }, + { url = "https://files.pythonhosted.org/packages/2f/09/bc1661fbbcbeb6244bd2904ff3a06f340aa77a2b94e5a7373fd165960ea3/jiter-0.10.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:533efbce2cacec78d5ba73a41756beff8431dfa1694b6346ce7af3a12c42202b", size = 514202, upload-time = "2025-05-18T19:03:57.675Z" }, + { url = "https://files.pythonhosted.org/packages/1b/84/5a5d5400e9d4d54b8004c9673bbe4403928a00d28529ff35b19e9d176b19/jiter-0.10.0-cp312-cp312-win32.whl", hash = "sha256:8be921f0cadd245e981b964dfbcd6fd4bc4e254cdc069490416dd7a2632ecc01", size = 211781, upload-time = "2025-05-18T19:03:59.025Z" }, + { url = "https://files.pythonhosted.org/packages/9b/52/7ec47455e26f2d6e5f2ea4951a0652c06e5b995c291f723973ae9e724a65/jiter-0.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:a7c7d785ae9dda68c2678532a5a1581347e9c15362ae9f6e68f3fdbfb64f2e49", size = 206176, upload-time = "2025-05-18T19:04:00.305Z" }, + { url = "https://files.pythonhosted.org/packages/2e/b0/279597e7a270e8d22623fea6c5d4eeac328e7d95c236ed51a2b884c54f70/jiter-0.10.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:e0588107ec8e11b6f5ef0e0d656fb2803ac6cf94a96b2b9fc675c0e3ab5e8644", size = 311617, upload-time = "2025-05-18T19:04:02.078Z" }, + { url = "https://files.pythonhosted.org/packages/91/e3/0916334936f356d605f54cc164af4060e3e7094364add445a3bc79335d46/jiter-0.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cafc4628b616dc32530c20ee53d71589816cf385dd9449633e910d596b1f5c8a", size = 318947, upload-time = "2025-05-18T19:04:03.347Z" }, + { url = "https://files.pythonhosted.org/packages/6a/8e/fd94e8c02d0e94539b7d669a7ebbd2776e51f329bb2c84d4385e8063a2ad/jiter-0.10.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:520ef6d981172693786a49ff5b09eda72a42e539f14788124a07530f785c3ad6", size = 344618, upload-time = "2025-05-18T19:04:04.709Z" }, + { url = "https://files.pythonhosted.org/packages/6f/b0/f9f0a2ec42c6e9c2e61c327824687f1e2415b767e1089c1d9135f43816bd/jiter-0.10.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:554dedfd05937f8fc45d17ebdf298fe7e0c77458232bcb73d9fbbf4c6455f5b3", size = 368829, upload-time = "2025-05-18T19:04:06.912Z" }, + { url = "https://files.pythonhosted.org/packages/e8/57/5bbcd5331910595ad53b9fd0c610392ac68692176f05ae48d6ce5c852967/jiter-0.10.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5bc299da7789deacf95f64052d97f75c16d4fc8c4c214a22bf8d859a4288a1c2", size = 491034, upload-time = "2025-05-18T19:04:08.222Z" }, + { url = "https://files.pythonhosted.org/packages/9b/be/c393df00e6e6e9e623a73551774449f2f23b6ec6a502a3297aeeece2c65a/jiter-0.10.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5161e201172de298a8a1baad95eb85db4fb90e902353b1f6a41d64ea64644e25", size = 388529, upload-time = "2025-05-18T19:04:09.566Z" }, + { url = "https://files.pythonhosted.org/packages/42/3e/df2235c54d365434c7f150b986a6e35f41ebdc2f95acea3036d99613025d/jiter-0.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e2227db6ba93cb3e2bf67c87e594adde0609f146344e8207e8730364db27041", size = 350671, upload-time = "2025-05-18T19:04:10.98Z" }, + { url = "https://files.pythonhosted.org/packages/c6/77/71b0b24cbcc28f55ab4dbfe029f9a5b73aeadaba677843fc6dc9ed2b1d0a/jiter-0.10.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:15acb267ea5e2c64515574b06a8bf393fbfee6a50eb1673614aa45f4613c0cca", size = 390864, upload-time = "2025-05-18T19:04:12.722Z" }, + { url = "https://files.pythonhosted.org/packages/6a/d3/ef774b6969b9b6178e1d1e7a89a3bd37d241f3d3ec5f8deb37bbd203714a/jiter-0.10.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:901b92f2e2947dc6dfcb52fd624453862e16665ea909a08398dde19c0731b7f4", size = 522989, upload-time = "2025-05-18T19:04:14.261Z" }, + { url = "https://files.pythonhosted.org/packages/0c/41/9becdb1d8dd5d854142f45a9d71949ed7e87a8e312b0bede2de849388cb9/jiter-0.10.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:d0cb9a125d5a3ec971a094a845eadde2db0de85b33c9f13eb94a0c63d463879e", size = 513495, upload-time = "2025-05-18T19:04:15.603Z" }, + { url = "https://files.pythonhosted.org/packages/9c/36/3468e5a18238bdedae7c4d19461265b5e9b8e288d3f86cd89d00cbb48686/jiter-0.10.0-cp313-cp313-win32.whl", hash = "sha256:48a403277ad1ee208fb930bdf91745e4d2d6e47253eedc96e2559d1e6527006d", size = 211289, upload-time = "2025-05-18T19:04:17.541Z" }, + { url = "https://files.pythonhosted.org/packages/7e/07/1c96b623128bcb913706e294adb5f768fb7baf8db5e1338ce7b4ee8c78ef/jiter-0.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:75f9eb72ecb640619c29bf714e78c9c46c9c4eaafd644bf78577ede459f330d4", size = 205074, upload-time = "2025-05-18T19:04:19.21Z" }, + { url = "https://files.pythonhosted.org/packages/54/46/caa2c1342655f57d8f0f2519774c6d67132205909c65e9aa8255e1d7b4f4/jiter-0.10.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:28ed2a4c05a1f32ef0e1d24c2611330219fed727dae01789f4a335617634b1ca", size = 318225, upload-time = "2025-05-18T19:04:20.583Z" }, + { url = "https://files.pythonhosted.org/packages/43/84/c7d44c75767e18946219ba2d703a5a32ab37b0bc21886a97bc6062e4da42/jiter-0.10.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14a4c418b1ec86a195f1ca69da8b23e8926c752b685af665ce30777233dfe070", size = 350235, upload-time = "2025-05-18T19:04:22.363Z" }, + { url = "https://files.pythonhosted.org/packages/01/16/f5a0135ccd968b480daad0e6ab34b0c7c5ba3bc447e5088152696140dcb3/jiter-0.10.0-cp313-cp313t-win_amd64.whl", hash = "sha256:d7bfed2fe1fe0e4dda6ef682cee888ba444b21e7a6553e03252e4feb6cf0adca", size = 207278, upload-time = "2025-05-18T19:04:23.627Z" }, + { url = "https://files.pythonhosted.org/packages/1c/9b/1d646da42c3de6c2188fdaa15bce8ecb22b635904fc68be025e21249ba44/jiter-0.10.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:5e9251a5e83fab8d87799d3e1a46cb4b7f2919b895c6f4483629ed2446f66522", size = 310866, upload-time = "2025-05-18T19:04:24.891Z" }, + { url = "https://files.pythonhosted.org/packages/ad/0e/26538b158e8a7c7987e94e7aeb2999e2e82b1f9d2e1f6e9874ddf71ebda0/jiter-0.10.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:023aa0204126fe5b87ccbcd75c8a0d0261b9abdbbf46d55e7ae9f8e22424eeb8", size = 318772, upload-time = "2025-05-18T19:04:26.161Z" }, + { url = "https://files.pythonhosted.org/packages/7b/fb/d302893151caa1c2636d6574d213e4b34e31fd077af6050a9c5cbb42f6fb/jiter-0.10.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c189c4f1779c05f75fc17c0c1267594ed918996a231593a21a5ca5438445216", size = 344534, upload-time = "2025-05-18T19:04:27.495Z" }, + { url = "https://files.pythonhosted.org/packages/01/d8/5780b64a149d74e347c5128d82176eb1e3241b1391ac07935693466d6219/jiter-0.10.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:15720084d90d1098ca0229352607cd68256c76991f6b374af96f36920eae13c4", size = 369087, upload-time = "2025-05-18T19:04:28.896Z" }, + { url = "https://files.pythonhosted.org/packages/e8/5b/f235a1437445160e777544f3ade57544daf96ba7e96c1a5b24a6f7ac7004/jiter-0.10.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e4f2fb68e5f1cfee30e2b2a09549a00683e0fde4c6a2ab88c94072fc33cb7426", size = 490694, upload-time = "2025-05-18T19:04:30.183Z" }, + { url = "https://files.pythonhosted.org/packages/85/a9/9c3d4617caa2ff89cf61b41e83820c27ebb3f7b5fae8a72901e8cd6ff9be/jiter-0.10.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ce541693355fc6da424c08b7edf39a2895f58d6ea17d92cc2b168d20907dee12", size = 388992, upload-time = "2025-05-18T19:04:32.028Z" }, + { url = "https://files.pythonhosted.org/packages/68/b1/344fd14049ba5c94526540af7eb661871f9c54d5f5601ff41a959b9a0bbd/jiter-0.10.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31c50c40272e189d50006ad5c73883caabb73d4e9748a688b216e85a9a9ca3b9", size = 351723, upload-time = "2025-05-18T19:04:33.467Z" }, + { url = "https://files.pythonhosted.org/packages/41/89/4c0e345041186f82a31aee7b9d4219a910df672b9fef26f129f0cda07a29/jiter-0.10.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fa3402a2ff9815960e0372a47b75c76979d74402448509ccd49a275fa983ef8a", size = 392215, upload-time = "2025-05-18T19:04:34.827Z" }, + { url = "https://files.pythonhosted.org/packages/55/58/ee607863e18d3f895feb802154a2177d7e823a7103f000df182e0f718b38/jiter-0.10.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:1956f934dca32d7bb647ea21d06d93ca40868b505c228556d3373cbd255ce853", size = 522762, upload-time = "2025-05-18T19:04:36.19Z" }, + { url = "https://files.pythonhosted.org/packages/15/d0/9123fb41825490d16929e73c212de9a42913d68324a8ce3c8476cae7ac9d/jiter-0.10.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:fcedb049bdfc555e261d6f65a6abe1d5ad68825b7202ccb9692636c70fcced86", size = 513427, upload-time = "2025-05-18T19:04:37.544Z" }, + { url = "https://files.pythonhosted.org/packages/d8/b3/2bd02071c5a2430d0b70403a34411fc519c2f227da7b03da9ba6a956f931/jiter-0.10.0-cp314-cp314-win32.whl", hash = "sha256:ac509f7eccca54b2a29daeb516fb95b6f0bd0d0d8084efaf8ed5dfc7b9f0b357", size = 210127, upload-time = "2025-05-18T19:04:38.837Z" }, + { url = "https://files.pythonhosted.org/packages/03/0c/5fe86614ea050c3ecd728ab4035534387cd41e7c1855ef6c031f1ca93e3f/jiter-0.10.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5ed975b83a2b8639356151cef5c0d597c68376fc4922b45d0eb384ac058cfa00", size = 318527, upload-time = "2025-05-18T19:04:40.612Z" }, + { url = "https://files.pythonhosted.org/packages/b3/4a/4175a563579e884192ba6e81725fc0448b042024419be8d83aa8a80a3f44/jiter-0.10.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3aa96f2abba33dc77f79b4cf791840230375f9534e5fac927ccceb58c5e604a5", size = 354213, upload-time = "2025-05-18T19:04:41.894Z" }, +] + +[[package]] +name = "jsbeautifier" +version = "1.15.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "editorconfig" }, + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ea/98/d6cadf4d5a1c03b2136837a435682418c29fdeb66be137128544cecc5b7a/jsbeautifier-1.15.4.tar.gz", hash = "sha256:5bb18d9efb9331d825735fbc5360ee8f1aac5e52780042803943aa7f854f7592", size = 75257, upload-time = "2025-02-27T17:53:53.252Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2d/14/1c65fccf8413d5f5c6e8425f84675169654395098000d8bddc4e9d3390e1/jsbeautifier-1.15.4-py3-none-any.whl", hash = "sha256:72f65de312a3f10900d7685557f84cb61a9733c50dcc27271a39f5b0051bf528", size = 94707, upload-time = "2025-02-27T17:53:46.152Z" }, +] + +[[package]] +name = "jsonschema" +version = "4.25.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "jsonschema-specifications" }, + { name = "referencing" }, + { name = "rpds-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/74/69/f7185de793a29082a9f3c7728268ffb31cb5095131a9c139a74078e27336/jsonschema-4.25.1.tar.gz", hash = "sha256:e4a9655ce0da0c0b67a085847e00a3a51449e1157f4f75e9fb5aa545e122eb85", size = 357342, upload-time = "2025-08-18T17:03:50.038Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bf/9c/8c95d856233c1f82500c2450b8c68576b4cf1c871db3afac5c34ff84e6fd/jsonschema-4.25.1-py3-none-any.whl", hash = "sha256:3fba0169e345c7175110351d456342c364814cfcf3b964ba4587f22915230a63", size = 90040, upload-time = "2025-08-18T17:03:48.373Z" }, +] + +[[package]] +name = "jsonschema-specifications" +version = "2025.4.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "referencing" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bf/ce/46fbd9c8119cfc3581ee5643ea49464d168028cfb5caff5fc0596d0cf914/jsonschema_specifications-2025.4.1.tar.gz", hash = "sha256:630159c9f4dbea161a6a2205c3011cc4f18ff381b189fff48bb39b9bf26ae608", size = 15513, upload-time = "2025-04-23T12:34:07.418Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/01/0e/b27cdbaccf30b890c40ed1da9fd4a3593a5cf94dae54fb34f8a4b74fcd3f/jsonschema_specifications-2025.4.1-py3-none-any.whl", hash = "sha256:4653bffbd6584f7de83a67e0d620ef16900b390ddc7939d56684d6c81e33f1af", size = 18437, upload-time = "2025-04-23T12:34:05.422Z" }, +] + +[[package]] +name = "litestar" +version = "2.17.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "click" }, + { name = "httpx" }, + { name = "litestar-htmx" }, + { name = "msgspec" }, + { name = "multidict" }, + { name = "multipart" }, + { name = "polyfactory" }, + { name = "pyyaml" }, + { name = "rich" }, + { name = "rich-click" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3f/62/36619846adb94d24d31e1aad7a52632544f2db7b0df22c8839cfa1db0b2e/litestar-2.17.0.tar.gz", hash = "sha256:0f50c3b7063417c338b32902f9eb40b81a7b14c9802edbff921a24aec3b0ea5b", size = 372203, upload-time = "2025-08-10T13:37:41.401Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/52/04/0935667c3cee2a26152102b9319fdfe987b0f765e14e0311c17ca6698820/litestar-2.17.0-py3-none-any.whl", hash = "sha256:2e62f01f852195362d69e3305cccddaf6371f5ab0ced30a081a66fb85e1df532", size = 564343, upload-time = "2025-08-10T13:37:39.462Z" }, +] + +[package.optional-dependencies] +standard = [ + { name = "fast-query-parsers" }, + { name = "jinja2" }, + { name = "jsbeautifier" }, + { name = "uvicorn", extra = ["standard"] }, + { name = "uvloop", marker = "sys_platform != 'win32'" }, +] + +[[package]] +name = "litestar-htmx" +version = "0.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3f/b9/7e296aa1adada25cce8e5f89a996b0e38d852d93b1b656a2058226c542a2/litestar_htmx-0.5.0.tar.gz", hash = "sha256:e02d1a3a92172c874835fa3e6749d65ae9fc626d0df46719490a16293e2146fb", size = 119755, upload-time = "2025-06-11T21:19:45.573Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f2/24/8d99982f0aa9c1cd82073c6232b54a0dbe6797c7d63c0583a6c68ee3ddf2/litestar_htmx-0.5.0-py3-none-any.whl", hash = "sha256:92833aa47e0d0e868d2a7dbfab75261f124f4b83d4f9ad12b57b9a68f86c50e6", size = 9970, upload-time = "2025-06-11T21:19:44.465Z" }, +] + [[package]] name = "markdown" version = "3.7" @@ -659,6 +875,28 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739, upload-time = "2024-10-18T15:21:42.784Z" }, ] +[[package]] +name = "mcp" +version = "1.12.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "httpx" }, + { name = "httpx-sse" }, + { name = "jsonschema" }, + { name = "pydantic" }, + { name = "pydantic-settings" }, + { name = "python-multipart" }, + { name = "pywin32", marker = "sys_platform == 'win32'" }, + { name = "sse-starlette" }, + { name = "starlette" }, + { name = "uvicorn", marker = "sys_platform != 'emscripten'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/31/88/f6cb7e7c260cd4b4ce375f2b1614b33ce401f63af0f49f7141a2e9bf0a45/mcp-1.12.4.tar.gz", hash = "sha256:0765585e9a3a5916a3c3ab8659330e493adc7bd8b2ca6120c2d7a0c43e034ca5", size = 431148, upload-time = "2025-08-07T20:31:18.082Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ad/68/316cbc54b7163fa22571dcf42c9cc46562aae0a021b974e0a8141e897200/mcp-1.12.4-py3-none-any.whl", hash = "sha256:7aa884648969fab8e78b89399d59a683202972e12e6bc9a1c88ce7eda7743789", size = 160145, upload-time = "2025-08-07T20:31:15.69Z" }, +] + [[package]] name = "mdurl" version = "0.1.2" @@ -734,6 +972,35 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/9f/d4/029f984e8d3f3b6b726bd33cafc473b75e9e44c0f7e80a5b29abc466bdea/mkdocs_get_deps-0.2.0-py3-none-any.whl", hash = "sha256:2bf11d0b133e77a0dd036abeeb06dec8775e46efa526dc70667d8863eefc6134", size = 9521, upload-time = "2023-11-20T17:51:08.587Z" }, ] +[[package]] +name = "msgspec" +version = "0.19.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cf/9b/95d8ce458462b8b71b8a70fa94563b2498b89933689f3a7b8911edfae3d7/msgspec-0.19.0.tar.gz", hash = "sha256:604037e7cd475345848116e89c553aa9a233259733ab51986ac924ab1b976f8e", size = 216934, upload-time = "2024-12-27T17:40:28.597Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/24/d4/2ec2567ac30dab072cce3e91fb17803c52f0a37aab6b0c24375d2b20a581/msgspec-0.19.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aa77046904db764b0462036bc63ef71f02b75b8f72e9c9dd4c447d6da1ed8f8e", size = 187939, upload-time = "2024-12-27T17:39:32.347Z" }, + { url = "https://files.pythonhosted.org/packages/2b/c0/18226e4328897f4f19875cb62bb9259fe47e901eade9d9376ab5f251a929/msgspec-0.19.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:047cfa8675eb3bad68722cfe95c60e7afabf84d1bd8938979dd2b92e9e4a9551", size = 182202, upload-time = "2024-12-27T17:39:33.633Z" }, + { url = "https://files.pythonhosted.org/packages/81/25/3a4b24d468203d8af90d1d351b77ea3cffb96b29492855cf83078f16bfe4/msgspec-0.19.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e78f46ff39a427e10b4a61614a2777ad69559cc8d603a7c05681f5a595ea98f7", size = 209029, upload-time = "2024-12-27T17:39:35.023Z" }, + { url = "https://files.pythonhosted.org/packages/85/2e/db7e189b57901955239f7689b5dcd6ae9458637a9c66747326726c650523/msgspec-0.19.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c7adf191e4bd3be0e9231c3b6dc20cf1199ada2af523885efc2ed218eafd011", size = 210682, upload-time = "2024-12-27T17:39:36.384Z" }, + { url = "https://files.pythonhosted.org/packages/03/97/7c8895c9074a97052d7e4a1cc1230b7b6e2ca2486714eb12c3f08bb9d284/msgspec-0.19.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f04cad4385e20be7c7176bb8ae3dca54a08e9756cfc97bcdb4f18560c3042063", size = 214003, upload-time = "2024-12-27T17:39:39.097Z" }, + { url = "https://files.pythonhosted.org/packages/61/61/e892997bcaa289559b4d5869f066a8021b79f4bf8e955f831b095f47a4cd/msgspec-0.19.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:45c8fb410670b3b7eb884d44a75589377c341ec1392b778311acdbfa55187716", size = 216833, upload-time = "2024-12-27T17:39:41.203Z" }, + { url = "https://files.pythonhosted.org/packages/ce/3d/71b2dffd3a1c743ffe13296ff701ee503feaebc3f04d0e75613b6563c374/msgspec-0.19.0-cp311-cp311-win_amd64.whl", hash = "sha256:70eaef4934b87193a27d802534dc466778ad8d536e296ae2f9334e182ac27b6c", size = 186184, upload-time = "2024-12-27T17:39:43.702Z" }, + { url = "https://files.pythonhosted.org/packages/b2/5f/a70c24f075e3e7af2fae5414c7048b0e11389685b7f717bb55ba282a34a7/msgspec-0.19.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f98bd8962ad549c27d63845b50af3f53ec468b6318400c9f1adfe8b092d7b62f", size = 190485, upload-time = "2024-12-27T17:39:44.974Z" }, + { url = "https://files.pythonhosted.org/packages/89/b0/1b9763938cfae12acf14b682fcf05c92855974d921a5a985ecc197d1c672/msgspec-0.19.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:43bbb237feab761b815ed9df43b266114203f53596f9b6e6f00ebd79d178cdf2", size = 183910, upload-time = "2024-12-27T17:39:46.401Z" }, + { url = "https://files.pythonhosted.org/packages/87/81/0c8c93f0b92c97e326b279795f9c5b956c5a97af28ca0fbb9fd86c83737a/msgspec-0.19.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4cfc033c02c3e0aec52b71710d7f84cb3ca5eb407ab2ad23d75631153fdb1f12", size = 210633, upload-time = "2024-12-27T17:39:49.099Z" }, + { url = "https://files.pythonhosted.org/packages/d0/ef/c5422ce8af73928d194a6606f8ae36e93a52fd5e8df5abd366903a5ca8da/msgspec-0.19.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d911c442571605e17658ca2b416fd8579c5050ac9adc5e00c2cb3126c97f73bc", size = 213594, upload-time = "2024-12-27T17:39:51.204Z" }, + { url = "https://files.pythonhosted.org/packages/19/2b/4137bc2ed45660444842d042be2cf5b18aa06efd2cda107cff18253b9653/msgspec-0.19.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:757b501fa57e24896cf40a831442b19a864f56d253679f34f260dcb002524a6c", size = 214053, upload-time = "2024-12-27T17:39:52.866Z" }, + { url = "https://files.pythonhosted.org/packages/9d/e6/8ad51bdc806aac1dc501e8fe43f759f9ed7284043d722b53323ea421c360/msgspec-0.19.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5f0f65f29b45e2816d8bded36e6b837a4bf5fb60ec4bc3c625fa2c6da4124537", size = 219081, upload-time = "2024-12-27T17:39:55.142Z" }, + { url = "https://files.pythonhosted.org/packages/b1/ef/27dd35a7049c9a4f4211c6cd6a8c9db0a50647546f003a5867827ec45391/msgspec-0.19.0-cp312-cp312-win_amd64.whl", hash = "sha256:067f0de1c33cfa0b6a8206562efdf6be5985b988b53dd244a8e06f993f27c8c0", size = 187467, upload-time = "2024-12-27T17:39:56.531Z" }, + { url = "https://files.pythonhosted.org/packages/3c/cb/2842c312bbe618d8fefc8b9cedce37f773cdc8fa453306546dba2c21fd98/msgspec-0.19.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f12d30dd6266557aaaf0aa0f9580a9a8fbeadfa83699c487713e355ec5f0bd86", size = 190498, upload-time = "2024-12-27T17:40:00.427Z" }, + { url = "https://files.pythonhosted.org/packages/58/95/c40b01b93465e1a5f3b6c7d91b10fb574818163740cc3acbe722d1e0e7e4/msgspec-0.19.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82b2c42c1b9ebc89e822e7e13bbe9d17ede0c23c187469fdd9505afd5a481314", size = 183950, upload-time = "2024-12-27T17:40:04.219Z" }, + { url = "https://files.pythonhosted.org/packages/e8/f0/5b764e066ce9aba4b70d1db8b087ea66098c7c27d59b9dd8a3532774d48f/msgspec-0.19.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19746b50be214a54239aab822964f2ac81e38b0055cca94808359d779338c10e", size = 210647, upload-time = "2024-12-27T17:40:05.606Z" }, + { url = "https://files.pythonhosted.org/packages/9d/87/bc14f49bc95c4cb0dd0a8c56028a67c014ee7e6818ccdce74a4862af259b/msgspec-0.19.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60ef4bdb0ec8e4ad62e5a1f95230c08efb1f64f32e6e8dd2ced685bcc73858b5", size = 213563, upload-time = "2024-12-27T17:40:10.516Z" }, + { url = "https://files.pythonhosted.org/packages/53/2f/2b1c2b056894fbaa975f68f81e3014bb447516a8b010f1bed3fb0e016ed7/msgspec-0.19.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac7f7c377c122b649f7545810c6cd1b47586e3aa3059126ce3516ac7ccc6a6a9", size = 213996, upload-time = "2024-12-27T17:40:12.244Z" }, + { url = "https://files.pythonhosted.org/packages/aa/5a/4cd408d90d1417e8d2ce6a22b98a6853c1b4d7cb7669153e4424d60087f6/msgspec-0.19.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a5bc1472223a643f5ffb5bf46ccdede7f9795078194f14edd69e3aab7020d327", size = 219087, upload-time = "2024-12-27T17:40:14.881Z" }, + { url = "https://files.pythonhosted.org/packages/23/d8/f15b40611c2d5753d1abb0ca0da0c75348daf1252220e5dda2867bd81062/msgspec-0.19.0-cp313-cp313-win_amd64.whl", hash = "sha256:317050bc0f7739cb30d257ff09152ca309bf5a369854bbf1e57dffc310c1f20f", size = 187432, upload-time = "2024-12-27T17:40:16.256Z" }, +] + [[package]] name = "multidict" version = "6.1.0" @@ -788,6 +1055,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/99/b7/b9e70fde2c0f0c9af4cc5277782a89b66d35948ea3369ec9f598358c3ac5/multidict-6.1.0-py3-none-any.whl", hash = "sha256:48e171e52d1c4d33888e529b999e5900356b9ae588c2f09a52dcefb158b27506", size = 10051, upload-time = "2024-09-09T23:49:36.506Z" }, ] +[[package]] +name = "multipart" +version = "1.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6d/c9/c6f5ab81bae667d4fe42a58df29f4c2db6ad8377cfd0e9baa729e4fa3ebb/multipart-1.3.0.tar.gz", hash = "sha256:a46bd6b0eb4c1ba865beb88ddd886012a3da709b6e7b86084fc37e99087e5cf1", size = 38816, upload-time = "2025-07-26T15:09:38.056Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9a/d6/d547a7004b81fa0b2aafa143b09196f6635e4105cd9d2c641fa8a4051c05/multipart-1.3.0-py3-none-any.whl", hash = "sha256:439bf4b00fd7cb2dbff08ae13f49f4f49798931ecd8d496372c63537fa19f304", size = 14938, upload-time = "2025-07-26T15:09:36.884Z" }, +] + [[package]] name = "mypy-extensions" version = "1.0.0" @@ -806,6 +1082,130 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d2/1d/1b658dbd2b9fa9c4c9f32accbfc0205d532c8c6194dc0f2a4c0428e7128a/nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9", size = 22314, upload-time = "2024-06-04T18:44:08.352Z" }, ] +[[package]] +name = "numpy" +version = "2.3.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/37/7d/3fec4199c5ffb892bed55cff901e4f39a58c81df9c44c280499e92cad264/numpy-2.3.2.tar.gz", hash = "sha256:e0486a11ec30cdecb53f184d496d1c6a20786c81e55e41640270130056f8ee48", size = 20489306, upload-time = "2025-07-24T21:32:07.553Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/96/26/1320083986108998bd487e2931eed2aeedf914b6e8905431487543ec911d/numpy-2.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:852ae5bed3478b92f093e30f785c98e0cb62fa0a939ed057c31716e18a7a22b9", size = 21259016, upload-time = "2025-07-24T20:24:35.214Z" }, + { url = "https://files.pythonhosted.org/packages/c4/2b/792b341463fa93fc7e55abbdbe87dac316c5b8cb5e94fb7a59fb6fa0cda5/numpy-2.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7a0e27186e781a69959d0230dd9909b5e26024f8da10683bd6344baea1885168", size = 14451158, upload-time = "2025-07-24T20:24:58.397Z" }, + { url = "https://files.pythonhosted.org/packages/b7/13/e792d7209261afb0c9f4759ffef6135b35c77c6349a151f488f531d13595/numpy-2.3.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:f0a1a8476ad77a228e41619af2fa9505cf69df928e9aaa165746584ea17fed2b", size = 5379817, upload-time = "2025-07-24T20:25:07.746Z" }, + { url = "https://files.pythonhosted.org/packages/49/ce/055274fcba4107c022b2113a213c7287346563f48d62e8d2a5176ad93217/numpy-2.3.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:cbc95b3813920145032412f7e33d12080f11dc776262df1712e1638207dde9e8", size = 6913606, upload-time = "2025-07-24T20:25:18.84Z" }, + { url = "https://files.pythonhosted.org/packages/17/f2/e4d72e6bc5ff01e2ab613dc198d560714971900c03674b41947e38606502/numpy-2.3.2-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f75018be4980a7324edc5930fe39aa391d5734531b1926968605416ff58c332d", size = 14589652, upload-time = "2025-07-24T20:25:40.356Z" }, + { url = "https://files.pythonhosted.org/packages/c8/b0/fbeee3000a51ebf7222016e2939b5c5ecf8000a19555d04a18f1e02521b8/numpy-2.3.2-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:20b8200721840f5621b7bd03f8dcd78de33ec522fc40dc2641aa09537df010c3", size = 16938816, upload-time = "2025-07-24T20:26:05.721Z" }, + { url = "https://files.pythonhosted.org/packages/a9/ec/2f6c45c3484cc159621ea8fc000ac5a86f1575f090cac78ac27193ce82cd/numpy-2.3.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1f91e5c028504660d606340a084db4b216567ded1056ea2b4be4f9d10b67197f", size = 16370512, upload-time = "2025-07-24T20:26:30.545Z" }, + { url = "https://files.pythonhosted.org/packages/b5/01/dd67cf511850bd7aefd6347aaae0956ed415abea741ae107834aae7d6d4e/numpy-2.3.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:fb1752a3bb9a3ad2d6b090b88a9a0ae1cd6f004ef95f75825e2f382c183b2097", size = 18884947, upload-time = "2025-07-24T20:26:58.24Z" }, + { url = "https://files.pythonhosted.org/packages/a7/17/2cf60fd3e6a61d006778735edf67a222787a8c1a7842aed43ef96d777446/numpy-2.3.2-cp311-cp311-win32.whl", hash = "sha256:4ae6863868aaee2f57503c7a5052b3a2807cf7a3914475e637a0ecd366ced220", size = 6599494, upload-time = "2025-07-24T20:27:09.786Z" }, + { url = "https://files.pythonhosted.org/packages/d5/03/0eade211c504bda872a594f045f98ddcc6caef2b7c63610946845e304d3f/numpy-2.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:240259d6564f1c65424bcd10f435145a7644a65a6811cfc3201c4a429ba79170", size = 13087889, upload-time = "2025-07-24T20:27:29.558Z" }, + { url = "https://files.pythonhosted.org/packages/13/32/2c7979d39dafb2a25087e12310fc7f3b9d3c7d960df4f4bc97955ae0ce1d/numpy-2.3.2-cp311-cp311-win_arm64.whl", hash = "sha256:4209f874d45f921bde2cff1ffcd8a3695f545ad2ffbef6d3d3c6768162efab89", size = 10459560, upload-time = "2025-07-24T20:27:46.803Z" }, + { url = "https://files.pythonhosted.org/packages/00/6d/745dd1c1c5c284d17725e5c802ca4d45cfc6803519d777f087b71c9f4069/numpy-2.3.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bc3186bea41fae9d8e90c2b4fb5f0a1f5a690682da79b92574d63f56b529080b", size = 20956420, upload-time = "2025-07-24T20:28:18.002Z" }, + { url = "https://files.pythonhosted.org/packages/bc/96/e7b533ea5740641dd62b07a790af5d9d8fec36000b8e2d0472bd7574105f/numpy-2.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f4f0215edb189048a3c03bd5b19345bdfa7b45a7a6f72ae5945d2a28272727f", size = 14184660, upload-time = "2025-07-24T20:28:39.522Z" }, + { url = "https://files.pythonhosted.org/packages/2b/53/102c6122db45a62aa20d1b18c9986f67e6b97e0d6fbc1ae13e3e4c84430c/numpy-2.3.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:8b1224a734cd509f70816455c3cffe13a4f599b1bf7130f913ba0e2c0b2006c0", size = 5113382, upload-time = "2025-07-24T20:28:48.544Z" }, + { url = "https://files.pythonhosted.org/packages/2b/21/376257efcbf63e624250717e82b4fae93d60178f09eb03ed766dbb48ec9c/numpy-2.3.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:3dcf02866b977a38ba3ec10215220609ab9667378a9e2150615673f3ffd6c73b", size = 6647258, upload-time = "2025-07-24T20:28:59.104Z" }, + { url = "https://files.pythonhosted.org/packages/91/ba/f4ebf257f08affa464fe6036e13f2bf9d4642a40228781dc1235da81be9f/numpy-2.3.2-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:572d5512df5470f50ada8d1972c5f1082d9a0b7aa5944db8084077570cf98370", size = 14281409, upload-time = "2025-07-24T20:40:30.298Z" }, + { url = "https://files.pythonhosted.org/packages/59/ef/f96536f1df42c668cbacb727a8c6da7afc9c05ece6d558927fb1722693e1/numpy-2.3.2-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8145dd6d10df13c559d1e4314df29695613575183fa2e2d11fac4c208c8a1f73", size = 16641317, upload-time = "2025-07-24T20:40:56.625Z" }, + { url = "https://files.pythonhosted.org/packages/f6/a7/af813a7b4f9a42f498dde8a4c6fcbff8100eed00182cc91dbaf095645f38/numpy-2.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:103ea7063fa624af04a791c39f97070bf93b96d7af7eb23530cd087dc8dbe9dc", size = 16056262, upload-time = "2025-07-24T20:41:20.797Z" }, + { url = "https://files.pythonhosted.org/packages/8b/5d/41c4ef8404caaa7f05ed1cfb06afe16a25895260eacbd29b4d84dff2920b/numpy-2.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fc927d7f289d14f5e037be917539620603294454130b6de200091e23d27dc9be", size = 18579342, upload-time = "2025-07-24T20:41:50.753Z" }, + { url = "https://files.pythonhosted.org/packages/a1/4f/9950e44c5a11636f4a3af6e825ec23003475cc9a466edb7a759ed3ea63bd/numpy-2.3.2-cp312-cp312-win32.whl", hash = "sha256:d95f59afe7f808c103be692175008bab926b59309ade3e6d25009e9a171f7036", size = 6320610, upload-time = "2025-07-24T20:42:01.551Z" }, + { url = "https://files.pythonhosted.org/packages/7c/2f/244643a5ce54a94f0a9a2ab578189c061e4a87c002e037b0829dd77293b6/numpy-2.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:9e196ade2400c0c737d93465327d1ae7c06c7cb8a1756121ebf54b06ca183c7f", size = 12786292, upload-time = "2025-07-24T20:42:20.738Z" }, + { url = "https://files.pythonhosted.org/packages/54/cd/7b5f49d5d78db7badab22d8323c1b6ae458fbf86c4fdfa194ab3cd4eb39b/numpy-2.3.2-cp312-cp312-win_arm64.whl", hash = "sha256:ee807923782faaf60d0d7331f5e86da7d5e3079e28b291973c545476c2b00d07", size = 10194071, upload-time = "2025-07-24T20:42:36.657Z" }, + { url = "https://files.pythonhosted.org/packages/1c/c0/c6bb172c916b00700ed3bf71cb56175fd1f7dbecebf8353545d0b5519f6c/numpy-2.3.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c8d9727f5316a256425892b043736d63e89ed15bbfe6556c5ff4d9d4448ff3b3", size = 20949074, upload-time = "2025-07-24T20:43:07.813Z" }, + { url = "https://files.pythonhosted.org/packages/20/4e/c116466d22acaf4573e58421c956c6076dc526e24a6be0903219775d862e/numpy-2.3.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:efc81393f25f14d11c9d161e46e6ee348637c0a1e8a54bf9dedc472a3fae993b", size = 14177311, upload-time = "2025-07-24T20:43:29.335Z" }, + { url = "https://files.pythonhosted.org/packages/78/45/d4698c182895af189c463fc91d70805d455a227261d950e4e0f1310c2550/numpy-2.3.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:dd937f088a2df683cbb79dda9a772b62a3e5a8a7e76690612c2737f38c6ef1b6", size = 5106022, upload-time = "2025-07-24T20:43:37.999Z" }, + { url = "https://files.pythonhosted.org/packages/9f/76/3e6880fef4420179309dba72a8c11f6166c431cf6dee54c577af8906f914/numpy-2.3.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:11e58218c0c46c80509186e460d79fbdc9ca1eb8d8aee39d8f2dc768eb781089", size = 6640135, upload-time = "2025-07-24T20:43:49.28Z" }, + { url = "https://files.pythonhosted.org/packages/34/fa/87ff7f25b3c4ce9085a62554460b7db686fef1e0207e8977795c7b7d7ba1/numpy-2.3.2-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5ad4ebcb683a1f99f4f392cc522ee20a18b2bb12a2c1c42c3d48d5a1adc9d3d2", size = 14278147, upload-time = "2025-07-24T20:44:10.328Z" }, + { url = "https://files.pythonhosted.org/packages/1d/0f/571b2c7a3833ae419fe69ff7b479a78d313581785203cc70a8db90121b9a/numpy-2.3.2-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:938065908d1d869c7d75d8ec45f735a034771c6ea07088867f713d1cd3bbbe4f", size = 16635989, upload-time = "2025-07-24T20:44:34.88Z" }, + { url = "https://files.pythonhosted.org/packages/24/5a/84ae8dca9c9a4c592fe11340b36a86ffa9fd3e40513198daf8a97839345c/numpy-2.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:66459dccc65d8ec98cc7df61307b64bf9e08101f9598755d42d8ae65d9a7a6ee", size = 16053052, upload-time = "2025-07-24T20:44:58.872Z" }, + { url = "https://files.pythonhosted.org/packages/57/7c/e5725d99a9133b9813fcf148d3f858df98511686e853169dbaf63aec6097/numpy-2.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a7af9ed2aa9ec5950daf05bb11abc4076a108bd3c7db9aa7251d5f107079b6a6", size = 18577955, upload-time = "2025-07-24T20:45:26.714Z" }, + { url = "https://files.pythonhosted.org/packages/ae/11/7c546fcf42145f29b71e4d6f429e96d8d68e5a7ba1830b2e68d7418f0bbd/numpy-2.3.2-cp313-cp313-win32.whl", hash = "sha256:906a30249315f9c8e17b085cc5f87d3f369b35fedd0051d4a84686967bdbbd0b", size = 6311843, upload-time = "2025-07-24T20:49:24.444Z" }, + { url = "https://files.pythonhosted.org/packages/aa/6f/a428fd1cb7ed39b4280d057720fed5121b0d7754fd2a9768640160f5517b/numpy-2.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:c63d95dc9d67b676e9108fe0d2182987ccb0f11933c1e8959f42fa0da8d4fa56", size = 12782876, upload-time = "2025-07-24T20:49:43.227Z" }, + { url = "https://files.pythonhosted.org/packages/65/85/4ea455c9040a12595fb6c43f2c217257c7b52dd0ba332c6a6c1d28b289fe/numpy-2.3.2-cp313-cp313-win_arm64.whl", hash = "sha256:b05a89f2fb84d21235f93de47129dd4f11c16f64c87c33f5e284e6a3a54e43f2", size = 10192786, upload-time = "2025-07-24T20:49:59.443Z" }, + { url = "https://files.pythonhosted.org/packages/80/23/8278f40282d10c3f258ec3ff1b103d4994bcad78b0cba9208317f6bb73da/numpy-2.3.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:4e6ecfeddfa83b02318f4d84acf15fbdbf9ded18e46989a15a8b6995dfbf85ab", size = 21047395, upload-time = "2025-07-24T20:45:58.821Z" }, + { url = "https://files.pythonhosted.org/packages/1f/2d/624f2ce4a5df52628b4ccd16a4f9437b37c35f4f8a50d00e962aae6efd7a/numpy-2.3.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:508b0eada3eded10a3b55725b40806a4b855961040180028f52580c4729916a2", size = 14300374, upload-time = "2025-07-24T20:46:20.207Z" }, + { url = "https://files.pythonhosted.org/packages/f6/62/ff1e512cdbb829b80a6bd08318a58698867bca0ca2499d101b4af063ee97/numpy-2.3.2-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:754d6755d9a7588bdc6ac47dc4ee97867271b17cee39cb87aef079574366db0a", size = 5228864, upload-time = "2025-07-24T20:46:30.58Z" }, + { url = "https://files.pythonhosted.org/packages/7d/8e/74bc18078fff03192d4032cfa99d5a5ca937807136d6f5790ce07ca53515/numpy-2.3.2-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:a9f66e7d2b2d7712410d3bc5684149040ef5f19856f20277cd17ea83e5006286", size = 6737533, upload-time = "2025-07-24T20:46:46.111Z" }, + { url = "https://files.pythonhosted.org/packages/19/ea/0731efe2c9073ccca5698ef6a8c3667c4cf4eea53fcdcd0b50140aba03bc/numpy-2.3.2-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:de6ea4e5a65d5a90c7d286ddff2b87f3f4ad61faa3db8dabe936b34c2275b6f8", size = 14352007, upload-time = "2025-07-24T20:47:07.1Z" }, + { url = "https://files.pythonhosted.org/packages/cf/90/36be0865f16dfed20f4bc7f75235b963d5939707d4b591f086777412ff7b/numpy-2.3.2-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a3ef07ec8cbc8fc9e369c8dcd52019510c12da4de81367d8b20bc692aa07573a", size = 16701914, upload-time = "2025-07-24T20:47:32.459Z" }, + { url = "https://files.pythonhosted.org/packages/94/30/06cd055e24cb6c38e5989a9e747042b4e723535758e6153f11afea88c01b/numpy-2.3.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:27c9f90e7481275c7800dc9c24b7cc40ace3fdb970ae4d21eaff983a32f70c91", size = 16132708, upload-time = "2025-07-24T20:47:58.129Z" }, + { url = "https://files.pythonhosted.org/packages/9a/14/ecede608ea73e58267fd7cb78f42341b3b37ba576e778a1a06baffbe585c/numpy-2.3.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:07b62978075b67eee4065b166d000d457c82a1efe726cce608b9db9dd66a73a5", size = 18651678, upload-time = "2025-07-24T20:48:25.402Z" }, + { url = "https://files.pythonhosted.org/packages/40/f3/2fe6066b8d07c3685509bc24d56386534c008b462a488b7f503ba82b8923/numpy-2.3.2-cp313-cp313t-win32.whl", hash = "sha256:c771cfac34a4f2c0de8e8c97312d07d64fd8f8ed45bc9f5726a7e947270152b5", size = 6441832, upload-time = "2025-07-24T20:48:37.181Z" }, + { url = "https://files.pythonhosted.org/packages/0b/ba/0937d66d05204d8f28630c9c60bc3eda68824abde4cf756c4d6aad03b0c6/numpy-2.3.2-cp313-cp313t-win_amd64.whl", hash = "sha256:72dbebb2dcc8305c431b2836bcc66af967df91be793d63a24e3d9b741374c450", size = 12927049, upload-time = "2025-07-24T20:48:56.24Z" }, + { url = "https://files.pythonhosted.org/packages/e9/ed/13542dd59c104d5e654dfa2ac282c199ba64846a74c2c4bcdbc3a0f75df1/numpy-2.3.2-cp313-cp313t-win_arm64.whl", hash = "sha256:72c6df2267e926a6d5286b0a6d556ebe49eae261062059317837fda12ddf0c1a", size = 10262935, upload-time = "2025-07-24T20:49:13.136Z" }, + { url = "https://files.pythonhosted.org/packages/c9/7c/7659048aaf498f7611b783e000c7268fcc4dcf0ce21cd10aad7b2e8f9591/numpy-2.3.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:448a66d052d0cf14ce9865d159bfc403282c9bc7bb2a31b03cc18b651eca8b1a", size = 20950906, upload-time = "2025-07-24T20:50:30.346Z" }, + { url = "https://files.pythonhosted.org/packages/80/db/984bea9d4ddf7112a04cfdfb22b1050af5757864cfffe8e09e44b7f11a10/numpy-2.3.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:546aaf78e81b4081b2eba1d105c3b34064783027a06b3ab20b6eba21fb64132b", size = 14185607, upload-time = "2025-07-24T20:50:51.923Z" }, + { url = "https://files.pythonhosted.org/packages/e4/76/b3d6f414f4eca568f469ac112a3b510938d892bc5a6c190cb883af080b77/numpy-2.3.2-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:87c930d52f45df092f7578889711a0768094debf73cfcde105e2d66954358125", size = 5114110, upload-time = "2025-07-24T20:51:01.041Z" }, + { url = "https://files.pythonhosted.org/packages/9e/d2/6f5e6826abd6bca52392ed88fe44a4b52aacb60567ac3bc86c67834c3a56/numpy-2.3.2-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:8dc082ea901a62edb8f59713c6a7e28a85daddcb67454c839de57656478f5b19", size = 6642050, upload-time = "2025-07-24T20:51:11.64Z" }, + { url = "https://files.pythonhosted.org/packages/c4/43/f12b2ade99199e39c73ad182f103f9d9791f48d885c600c8e05927865baf/numpy-2.3.2-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:af58de8745f7fa9ca1c0c7c943616c6fe28e75d0c81f5c295810e3c83b5be92f", size = 14296292, upload-time = "2025-07-24T20:51:33.488Z" }, + { url = "https://files.pythonhosted.org/packages/5d/f9/77c07d94bf110a916b17210fac38680ed8734c236bfed9982fd8524a7b47/numpy-2.3.2-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed5527c4cf10f16c6d0b6bee1f89958bccb0ad2522c8cadc2efd318bcd545f5", size = 16638913, upload-time = "2025-07-24T20:51:58.517Z" }, + { url = "https://files.pythonhosted.org/packages/9b/d1/9d9f2c8ea399cc05cfff8a7437453bd4e7d894373a93cdc46361bbb49a7d/numpy-2.3.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:095737ed986e00393ec18ec0b21b47c22889ae4b0cd2d5e88342e08b01141f58", size = 16071180, upload-time = "2025-07-24T20:52:22.827Z" }, + { url = "https://files.pythonhosted.org/packages/4c/41/82e2c68aff2a0c9bf315e47d61951099fed65d8cb2c8d9dc388cb87e947e/numpy-2.3.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b5e40e80299607f597e1a8a247ff8d71d79c5b52baa11cc1cce30aa92d2da6e0", size = 18576809, upload-time = "2025-07-24T20:52:51.015Z" }, + { url = "https://files.pythonhosted.org/packages/14/14/4b4fd3efb0837ed252d0f583c5c35a75121038a8c4e065f2c259be06d2d8/numpy-2.3.2-cp314-cp314-win32.whl", hash = "sha256:7d6e390423cc1f76e1b8108c9b6889d20a7a1f59d9a60cac4a050fa734d6c1e2", size = 6366410, upload-time = "2025-07-24T20:56:44.949Z" }, + { url = "https://files.pythonhosted.org/packages/11/9e/b4c24a6b8467b61aced5c8dc7dcfce23621baa2e17f661edb2444a418040/numpy-2.3.2-cp314-cp314-win_amd64.whl", hash = "sha256:b9d0878b21e3918d76d2209c924ebb272340da1fb51abc00f986c258cd5e957b", size = 12918821, upload-time = "2025-07-24T20:57:06.479Z" }, + { url = "https://files.pythonhosted.org/packages/0e/0f/0dc44007c70b1007c1cef86b06986a3812dd7106d8f946c09cfa75782556/numpy-2.3.2-cp314-cp314-win_arm64.whl", hash = "sha256:2738534837c6a1d0c39340a190177d7d66fdf432894f469728da901f8f6dc910", size = 10477303, upload-time = "2025-07-24T20:57:22.879Z" }, + { url = "https://files.pythonhosted.org/packages/8b/3e/075752b79140b78ddfc9c0a1634d234cfdbc6f9bbbfa6b7504e445ad7d19/numpy-2.3.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:4d002ecf7c9b53240be3bb69d80f86ddbd34078bae04d87be81c1f58466f264e", size = 21047524, upload-time = "2025-07-24T20:53:22.086Z" }, + { url = "https://files.pythonhosted.org/packages/fe/6d/60e8247564a72426570d0e0ea1151b95ce5bd2f1597bb878a18d32aec855/numpy-2.3.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:293b2192c6bcce487dbc6326de5853787f870aeb6c43f8f9c6496db5b1781e45", size = 14300519, upload-time = "2025-07-24T20:53:44.053Z" }, + { url = "https://files.pythonhosted.org/packages/4d/73/d8326c442cd428d47a067070c3ac6cc3b651a6e53613a1668342a12d4479/numpy-2.3.2-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:0a4f2021a6da53a0d580d6ef5db29947025ae8b35b3250141805ea9a32bbe86b", size = 5228972, upload-time = "2025-07-24T20:53:53.81Z" }, + { url = "https://files.pythonhosted.org/packages/34/2e/e71b2d6dad075271e7079db776196829019b90ce3ece5c69639e4f6fdc44/numpy-2.3.2-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:9c144440db4bf3bb6372d2c3e49834cc0ff7bb4c24975ab33e01199e645416f2", size = 6737439, upload-time = "2025-07-24T20:54:04.742Z" }, + { url = "https://files.pythonhosted.org/packages/15/b0/d004bcd56c2c5e0500ffc65385eb6d569ffd3363cb5e593ae742749b2daa/numpy-2.3.2-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f92d6c2a8535dc4fe4419562294ff957f83a16ebdec66df0805e473ffaad8bd0", size = 14352479, upload-time = "2025-07-24T20:54:25.819Z" }, + { url = "https://files.pythonhosted.org/packages/11/e3/285142fcff8721e0c99b51686426165059874c150ea9ab898e12a492e291/numpy-2.3.2-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cefc2219baa48e468e3db7e706305fcd0c095534a192a08f31e98d83a7d45fb0", size = 16702805, upload-time = "2025-07-24T20:54:50.814Z" }, + { url = "https://files.pythonhosted.org/packages/33/c3/33b56b0e47e604af2c7cd065edca892d180f5899599b76830652875249a3/numpy-2.3.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:76c3e9501ceb50b2ff3824c3589d5d1ab4ac857b0ee3f8f49629d0de55ecf7c2", size = 16133830, upload-time = "2025-07-24T20:55:17.306Z" }, + { url = "https://files.pythonhosted.org/packages/6e/ae/7b1476a1f4d6a48bc669b8deb09939c56dd2a439db1ab03017844374fb67/numpy-2.3.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:122bf5ed9a0221b3419672493878ba4967121514b1d7d4656a7580cd11dddcbf", size = 18652665, upload-time = "2025-07-24T20:55:46.665Z" }, + { url = "https://files.pythonhosted.org/packages/14/ba/5b5c9978c4bb161034148ade2de9db44ec316fab89ce8c400db0e0c81f86/numpy-2.3.2-cp314-cp314t-win32.whl", hash = "sha256:6f1ae3dcb840edccc45af496f312528c15b1f79ac318169d094e85e4bb35fdf1", size = 6514777, upload-time = "2025-07-24T20:55:57.66Z" }, + { url = "https://files.pythonhosted.org/packages/eb/46/3dbaf0ae7c17cdc46b9f662c56da2054887b8d9e737c1476f335c83d33db/numpy-2.3.2-cp314-cp314t-win_amd64.whl", hash = "sha256:087ffc25890d89a43536f75c5fe8770922008758e8eeeef61733957041ed2f9b", size = 13111856, upload-time = "2025-07-24T20:56:17.318Z" }, + { url = "https://files.pythonhosted.org/packages/c1/9e/1652778bce745a67b5fe05adde60ed362d38eb17d919a540e813d30f6874/numpy-2.3.2-cp314-cp314t-win_arm64.whl", hash = "sha256:092aeb3449833ea9c0bf0089d70c29ae480685dd2377ec9cdbbb620257f84631", size = 10544226, upload-time = "2025-07-24T20:56:34.509Z" }, + { url = "https://files.pythonhosted.org/packages/cf/ea/50ebc91d28b275b23b7128ef25c3d08152bc4068f42742867e07a870a42a/numpy-2.3.2-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:14a91ebac98813a49bc6aa1a0dfc09513dcec1d97eaf31ca21a87221a1cdcb15", size = 21130338, upload-time = "2025-07-24T20:57:54.37Z" }, + { url = "https://files.pythonhosted.org/packages/9f/57/cdd5eac00dd5f137277355c318a955c0d8fb8aa486020c22afd305f8b88f/numpy-2.3.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:71669b5daae692189540cffc4c439468d35a3f84f0c88b078ecd94337f6cb0ec", size = 14375776, upload-time = "2025-07-24T20:58:16.303Z" }, + { url = "https://files.pythonhosted.org/packages/83/85/27280c7f34fcd305c2209c0cdca4d70775e4859a9eaa92f850087f8dea50/numpy-2.3.2-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:69779198d9caee6e547adb933941ed7520f896fd9656834c300bdf4dd8642712", size = 5304882, upload-time = "2025-07-24T20:58:26.199Z" }, + { url = "https://files.pythonhosted.org/packages/48/b4/6500b24d278e15dd796f43824e69939d00981d37d9779e32499e823aa0aa/numpy-2.3.2-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:2c3271cc4097beb5a60f010bcc1cc204b300bb3eafb4399376418a83a1c6373c", size = 6818405, upload-time = "2025-07-24T20:58:37.341Z" }, + { url = "https://files.pythonhosted.org/packages/9b/c9/142c1e03f199d202da8e980c2496213509291b6024fd2735ad28ae7065c7/numpy-2.3.2-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8446acd11fe3dc1830568c941d44449fd5cb83068e5c70bd5a470d323d448296", size = 14419651, upload-time = "2025-07-24T20:58:59.048Z" }, + { url = "https://files.pythonhosted.org/packages/8b/95/8023e87cbea31a750a6c00ff9427d65ebc5fef104a136bfa69f76266d614/numpy-2.3.2-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:aa098a5ab53fa407fded5870865c6275a5cd4101cfdef8d6fafc48286a96e981", size = 16760166, upload-time = "2025-07-24T21:28:56.38Z" }, + { url = "https://files.pythonhosted.org/packages/78/e3/6690b3f85a05506733c7e90b577e4762517404ea78bab2ca3a5cb1aeb78d/numpy-2.3.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:6936aff90dda378c09bea075af0d9c675fe3a977a9d2402f95a87f440f59f619", size = 12977811, upload-time = "2025-07-24T21:29:18.234Z" }, +] + +[[package]] +name = "openai" +version = "1.105.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "distro" }, + { name = "httpx" }, + { name = "jiter" }, + { name = "pydantic" }, + { name = "sniffio" }, + { name = "tqdm" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6f/a9/c8c2dea8066a8f3079f69c242f7d0d75aaad4c4c3431da5b0df22a24e75d/openai-1.105.0.tar.gz", hash = "sha256:a68a47adce0506d34def22dd78a42cbb6cfecae1cf6a5fe37f38776d32bbb514", size = 557265, upload-time = "2025-09-03T14:14:08.586Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/51/01/186845829d3a3609bb5b474067959076244dd62540d3e336797319b13924/openai-1.105.0-py3-none-any.whl", hash = "sha256:3ad7635132b0705769ccae31ca7319f59ec0c7d09e94e5e713ce2d130e5b021f", size = 928203, upload-time = "2025-09-03T14:14:06.842Z" }, +] + +[[package]] +name = "openai-agents" +version = "0.2.11" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "griffe" }, + { name = "mcp" }, + { name = "openai" }, + { name = "pydantic" }, + { name = "requests" }, + { name = "types-requests" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/dd/c7/e8b588851bdbb33f16397b45d182998a01e6e57ff028a143788036a89d53/openai_agents-0.2.11.tar.gz", hash = "sha256:1a2e3fade02b3d8571560dbd121bfe0d84c80f48da04c838d9d5195966714abc", size = 1677542, upload-time = "2025-09-03T22:16:05.856Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6a/71/a8712a89502b95da64db6b0b31c12ac5039542ae8e31caddba369b6bd324/openai_agents-0.2.11-py3-none-any.whl", hash = "sha256:ed26f7bb2b08bd7607ae87eb7bcfcee8c8f4431da134252757b31120a68b9086", size = 179141, upload-time = "2025-09-03T22:16:03.823Z" }, +] + +[package.optional-dependencies] +voice = [ + { name = "numpy" }, + { name = "websockets" }, +] + [[package]] name = "openapi-python-client" version = "0.25.3" @@ -878,6 +1278,36 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556, upload-time = "2024-04-20T21:34:40.434Z" }, ] +[[package]] +name = "poet-chat" +version = "0.1.0" +source = { virtual = "examples/poet_chat" } +dependencies = [ + { name = "fishjam-server-sdk" }, + { name = "litestar", extra = ["standard"] }, + { name = "openai-agents", extra = ["voice"] }, +] + +[package.metadata] +requires-dist = [ + { name = "fishjam-server-sdk", editable = "." }, + { name = "litestar", extras = ["standard"], specifier = ">=2.17.0" }, + { name = "openai-agents", extras = ["voice"], specifier = ">=0.2.11" }, +] + +[[package]] +name = "polyfactory" +version = "2.22.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "faker" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4e/a6/950d13856d995705df33b92451559fd317207a9c43629ab1771135a0c966/polyfactory-2.22.2.tar.gz", hash = "sha256:a3297aa0b004f2b26341e903795565ae88507c4d86e68b132c2622969028587a", size = 254462, upload-time = "2025-08-15T06:23:21.28Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/fe/d52c90e07c458f38b26f9972a25cb011b2744813f76fcd6121dde64744fa/polyfactory-2.22.2-py3-none-any.whl", hash = "sha256:9bea58ac9a80375b4153cd60820f75e558b863e567e058794d28c6a52b84118a", size = 63715, upload-time = "2025-08-15T06:23:19.664Z" }, +] + [[package]] name = "pyasn1" version = "0.6.1" @@ -971,6 +1401,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/51/b2/b2b50d5ecf21acf870190ae5d093602d95f66c9c31f9d5de6062eb329ad1/pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b", size = 1885186, upload-time = "2024-12-18T11:29:37.649Z" }, ] +[[package]] +name = "pydantic-settings" +version = "2.10.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pydantic" }, + { name = "python-dotenv" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/68/85/1ea668bbab3c50071ca613c6ab30047fb36ab0da1b92fa8f17bbc38fd36c/pydantic_settings-2.10.1.tar.gz", hash = "sha256:06f0062169818d0f5524420a360d632d5857b83cffd4d42fe29597807a1614ee", size = 172583, upload-time = "2025-06-24T13:26:46.841Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/58/f0/427018098906416f580e3cf1366d3b1abfb408a0652e9f31600c24a1903c/pydantic_settings-2.10.1-py3-none-any.whl", hash = "sha256:a60952460b99cf661dc25c29c0ef171721f98bfcb52ef8d9ea4c943d7c8cc796", size = 45235, upload-time = "2025-06-24T13:26:45.485Z" }, +] + [[package]] name = "pygments" version = "2.19.1" @@ -1059,6 +1503,25 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/45/58/38b5afbc1a800eeea951b9285d3912613f2603bdf897a4ab0f4bd7f405fc/python_multipart-0.0.20-py3-none-any.whl", hash = "sha256:8a62d3a8335e06589fe01f2a3e178cdcc632f3fbe0d492ad9ee0ec35aab1f104", size = 24546, upload-time = "2024-12-16T19:45:44.423Z" }, ] +[[package]] +name = "pywin32" +version = "311" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7c/af/449a6a91e5d6db51420875c54f6aff7c97a86a3b13a0b4f1a5c13b988de3/pywin32-311-cp311-cp311-win32.whl", hash = "sha256:184eb5e436dea364dcd3d2316d577d625c0351bf237c4e9a5fabbcfa5a58b151", size = 8697031, upload-time = "2025-07-14T20:13:13.266Z" }, + { url = "https://files.pythonhosted.org/packages/51/8f/9bb81dd5bb77d22243d33c8397f09377056d5c687aa6d4042bea7fbf8364/pywin32-311-cp311-cp311-win_amd64.whl", hash = "sha256:3ce80b34b22b17ccbd937a6e78e7225d80c52f5ab9940fe0506a1a16f3dab503", size = 9508308, upload-time = "2025-07-14T20:13:15.147Z" }, + { url = "https://files.pythonhosted.org/packages/44/7b/9c2ab54f74a138c491aba1b1cd0795ba61f144c711daea84a88b63dc0f6c/pywin32-311-cp311-cp311-win_arm64.whl", hash = "sha256:a733f1388e1a842abb67ffa8e7aad0e70ac519e09b0f6a784e65a136ec7cefd2", size = 8703930, upload-time = "2025-07-14T20:13:16.945Z" }, + { url = "https://files.pythonhosted.org/packages/e7/ab/01ea1943d4eba0f850c3c61e78e8dd59757ff815ff3ccd0a84de5f541f42/pywin32-311-cp312-cp312-win32.whl", hash = "sha256:750ec6e621af2b948540032557b10a2d43b0cee2ae9758c54154d711cc852d31", size = 8706543, upload-time = "2025-07-14T20:13:20.765Z" }, + { url = "https://files.pythonhosted.org/packages/d1/a8/a0e8d07d4d051ec7502cd58b291ec98dcc0c3fff027caad0470b72cfcc2f/pywin32-311-cp312-cp312-win_amd64.whl", hash = "sha256:b8c095edad5c211ff31c05223658e71bf7116daa0ecf3ad85f3201ea3190d067", size = 9495040, upload-time = "2025-07-14T20:13:22.543Z" }, + { url = "https://files.pythonhosted.org/packages/ba/3a/2ae996277b4b50f17d61f0603efd8253cb2d79cc7ae159468007b586396d/pywin32-311-cp312-cp312-win_arm64.whl", hash = "sha256:e286f46a9a39c4a18b319c28f59b61de793654af2f395c102b4f819e584b5852", size = 8710102, upload-time = "2025-07-14T20:13:24.682Z" }, + { url = "https://files.pythonhosted.org/packages/a5/be/3fd5de0979fcb3994bfee0d65ed8ca9506a8a1260651b86174f6a86f52b3/pywin32-311-cp313-cp313-win32.whl", hash = "sha256:f95ba5a847cba10dd8c4d8fefa9f2a6cf283b8b88ed6178fa8a6c1ab16054d0d", size = 8705700, upload-time = "2025-07-14T20:13:26.471Z" }, + { url = "https://files.pythonhosted.org/packages/e3/28/e0a1909523c6890208295a29e05c2adb2126364e289826c0a8bc7297bd5c/pywin32-311-cp313-cp313-win_amd64.whl", hash = "sha256:718a38f7e5b058e76aee1c56ddd06908116d35147e133427e59a3983f703a20d", size = 9494700, upload-time = "2025-07-14T20:13:28.243Z" }, + { url = "https://files.pythonhosted.org/packages/04/bf/90339ac0f55726dce7d794e6d79a18a91265bdf3aa70b6b9ca52f35e022a/pywin32-311-cp313-cp313-win_arm64.whl", hash = "sha256:7b4075d959648406202d92a2310cb990fea19b535c7f4a78d3f5e10b926eeb8a", size = 8709318, upload-time = "2025-07-14T20:13:30.348Z" }, + { url = "https://files.pythonhosted.org/packages/c9/31/097f2e132c4f16d99a22bfb777e0fd88bd8e1c634304e102f313af69ace5/pywin32-311-cp314-cp314-win32.whl", hash = "sha256:b7a2c10b93f8986666d0c803ee19b5990885872a7de910fc460f9b0c2fbf92ee", size = 8840714, upload-time = "2025-07-14T20:13:32.449Z" }, + { url = "https://files.pythonhosted.org/packages/90/4b/07c77d8ba0e01349358082713400435347df8426208171ce297da32c313d/pywin32-311-cp314-cp314-win_amd64.whl", hash = "sha256:3aca44c046bd2ed8c90de9cb8427f581c479e594e99b5c0bb19b29c10fd6cb87", size = 9656800, upload-time = "2025-07-14T20:13:34.312Z" }, + { url = "https://files.pythonhosted.org/packages/c0/d2/21af5c535501a7233e734b8af901574572da66fcc254cb35d0609c9080dd/pywin32-311-cp314-cp314-win_arm64.whl", hash = "sha256:a508e2d9025764a8270f93111a970e1d0fbfc33f4153b388bb649b7eec4f9b42", size = 8932540, upload-time = "2025-07-14T20:13:36.379Z" }, +] + [[package]] name = "pyyaml" version = "6.0.2" @@ -1106,6 +1569,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5a/66/bbb1dd374f5c870f59c5bb1db0e18cbe7fa739415a24cbd95b2d1f5ae0c4/pyyaml_env_tag-0.1-py3-none-any.whl", hash = "sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069", size = 3911, upload-time = "2020-11-12T02:38:24.638Z" }, ] +[[package]] +name = "referencing" +version = "0.36.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "rpds-py" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2f/db/98b5c277be99dd18bfd91dd04e1b759cad18d1a338188c936e92f921c7e2/referencing-0.36.2.tar.gz", hash = "sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa", size = 74744, upload-time = "2025-01-25T08:48:16.138Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/b1/3baf80dc6d2b7bc27a95a67752d0208e410351e3feb4eb78de5f77454d8d/referencing-0.36.2-py3-none-any.whl", hash = "sha256:e8699adbbf8b5c7de96d8ffa0eb5c158b3beafce084968e2ea8bb08c6794dcd0", size = 26775, upload-time = "2025-01-25T08:48:14.241Z" }, +] + [[package]] name = "requests" version = "2.32.3" @@ -1134,6 +1611,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e3/30/3c4d035596d3cf444529e0b2953ad0466f6049528a879d27534700580395/rich-14.1.0-py3-none-any.whl", hash = "sha256:536f5f1785986d6dbdea3c75205c473f970777b4a0d6c6dd1b696aa05a3fa04f", size = 243368, upload-time = "2025-07-25T07:32:56.73Z" }, ] +[[package]] +name = "rich-click" +version = "1.8.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "rich" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b7/a8/dcc0a8ec9e91d76ecad9413a84b6d3a3310c6111cfe012d75ed385c78d96/rich_click-1.8.9.tar.gz", hash = "sha256:fd98c0ab9ddc1cf9c0b7463f68daf28b4d0033a74214ceb02f761b3ff2af3136", size = 39378, upload-time = "2025-05-19T21:33:05.569Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b6/c2/9fce4c8a9587c4e90500114d742fe8ef0fd92d7bad29d136bb9941add271/rich_click-1.8.9-py3-none-any.whl", hash = "sha256:c3fa81ed8a671a10de65a9e20abf642cfdac6fdb882db1ef465ee33919fbcfe2", size = 36082, upload-time = "2025-05-19T21:33:04.195Z" }, +] + [[package]] name = "rich-toolkit" version = "0.15.0" @@ -1218,6 +1709,114 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/84/9c/3881ad34f01942af0cf713e25e476bf851e04e389cc3ff146c3b459ab861/rignore-0.6.4-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:7e6c425603db2c147eace4f752ca3cd4551e7568c9d332175d586c68bcbe3d8d", size = 1122433, upload-time = "2025-07-19T19:24:43.973Z" }, ] +[[package]] +name = "rpds-py" +version = "0.27.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e9/dd/2c0cbe774744272b0ae725f44032c77bdcab6e8bcf544bffa3b6e70c8dba/rpds_py-0.27.1.tar.gz", hash = "sha256:26a1c73171d10b7acccbded82bf6a586ab8203601e565badc74bbbf8bc5a10f8", size = 27479, upload-time = "2025-08-27T12:16:36.024Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b5/c1/7907329fbef97cbd49db6f7303893bd1dd5a4a3eae415839ffdfb0762cae/rpds_py-0.27.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:be898f271f851f68b318872ce6ebebbc62f303b654e43bf72683dbdc25b7c881", size = 371063, upload-time = "2025-08-27T12:12:47.856Z" }, + { url = "https://files.pythonhosted.org/packages/11/94/2aab4bc86228bcf7c48760990273653a4900de89c7537ffe1b0d6097ed39/rpds_py-0.27.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:62ac3d4e3e07b58ee0ddecd71d6ce3b1637de2d373501412df395a0ec5f9beb5", size = 353210, upload-time = "2025-08-27T12:12:49.187Z" }, + { url = "https://files.pythonhosted.org/packages/3a/57/f5eb3ecf434342f4f1a46009530e93fd201a0b5b83379034ebdb1d7c1a58/rpds_py-0.27.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4708c5c0ceb2d034f9991623631d3d23cb16e65c83736ea020cdbe28d57c0a0e", size = 381636, upload-time = "2025-08-27T12:12:50.492Z" }, + { url = "https://files.pythonhosted.org/packages/ae/f4/ef95c5945e2ceb5119571b184dd5a1cc4b8541bbdf67461998cfeac9cb1e/rpds_py-0.27.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:abfa1171a9952d2e0002aba2ad3780820b00cc3d9c98c6630f2e93271501f66c", size = 394341, upload-time = "2025-08-27T12:12:52.024Z" }, + { url = "https://files.pythonhosted.org/packages/5a/7e/4bd610754bf492d398b61725eb9598ddd5eb86b07d7d9483dbcd810e20bc/rpds_py-0.27.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4b507d19f817ebaca79574b16eb2ae412e5c0835542c93fe9983f1e432aca195", size = 523428, upload-time = "2025-08-27T12:12:53.779Z" }, + { url = "https://files.pythonhosted.org/packages/9f/e5/059b9f65a8c9149361a8b75094864ab83b94718344db511fd6117936ed2a/rpds_py-0.27.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:168b025f8fd8d8d10957405f3fdcef3dc20f5982d398f90851f4abc58c566c52", size = 402923, upload-time = "2025-08-27T12:12:55.15Z" }, + { url = "https://files.pythonhosted.org/packages/f5/48/64cabb7daced2968dd08e8a1b7988bf358d7bd5bcd5dc89a652f4668543c/rpds_py-0.27.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb56c6210ef77caa58e16e8c17d35c63fe3f5b60fd9ba9d424470c3400bcf9ed", size = 384094, upload-time = "2025-08-27T12:12:57.194Z" }, + { url = "https://files.pythonhosted.org/packages/ae/e1/dc9094d6ff566bff87add8a510c89b9e158ad2ecd97ee26e677da29a9e1b/rpds_py-0.27.1-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:d252f2d8ca0195faa707f8eb9368955760880b2b42a8ee16d382bf5dd807f89a", size = 401093, upload-time = "2025-08-27T12:12:58.985Z" }, + { url = "https://files.pythonhosted.org/packages/37/8e/ac8577e3ecdd5593e283d46907d7011618994e1d7ab992711ae0f78b9937/rpds_py-0.27.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6e5e54da1e74b91dbc7996b56640f79b195d5925c2b78efaa8c5d53e1d88edde", size = 417969, upload-time = "2025-08-27T12:13:00.367Z" }, + { url = "https://files.pythonhosted.org/packages/66/6d/87507430a8f74a93556fe55c6485ba9c259949a853ce407b1e23fea5ba31/rpds_py-0.27.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ffce0481cc6e95e5b3f0a47ee17ffbd234399e6d532f394c8dce320c3b089c21", size = 558302, upload-time = "2025-08-27T12:13:01.737Z" }, + { url = "https://files.pythonhosted.org/packages/3a/bb/1db4781ce1dda3eecc735e3152659a27b90a02ca62bfeea17aee45cc0fbc/rpds_py-0.27.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:a205fdfe55c90c2cd8e540ca9ceba65cbe6629b443bc05db1f590a3db8189ff9", size = 589259, upload-time = "2025-08-27T12:13:03.127Z" }, + { url = "https://files.pythonhosted.org/packages/7b/0e/ae1c8943d11a814d01b482e1f8da903f88047a962dff9bbdadf3bd6e6fd1/rpds_py-0.27.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:689fb5200a749db0415b092972e8eba85847c23885c8543a8b0f5c009b1a5948", size = 554983, upload-time = "2025-08-27T12:13:04.516Z" }, + { url = "https://files.pythonhosted.org/packages/b2/d5/0b2a55415931db4f112bdab072443ff76131b5ac4f4dc98d10d2d357eb03/rpds_py-0.27.1-cp311-cp311-win32.whl", hash = "sha256:3182af66048c00a075010bc7f4860f33913528a4b6fc09094a6e7598e462fe39", size = 217154, upload-time = "2025-08-27T12:13:06.278Z" }, + { url = "https://files.pythonhosted.org/packages/24/75/3b7ffe0d50dc86a6a964af0d1cc3a4a2cdf437cb7b099a4747bbb96d1819/rpds_py-0.27.1-cp311-cp311-win_amd64.whl", hash = "sha256:b4938466c6b257b2f5c4ff98acd8128ec36b5059e5c8f8372d79316b1c36bb15", size = 228627, upload-time = "2025-08-27T12:13:07.625Z" }, + { url = "https://files.pythonhosted.org/packages/8d/3f/4fd04c32abc02c710f09a72a30c9a55ea3cc154ef8099078fd50a0596f8e/rpds_py-0.27.1-cp311-cp311-win_arm64.whl", hash = "sha256:2f57af9b4d0793e53266ee4325535a31ba48e2f875da81a9177c9926dfa60746", size = 220998, upload-time = "2025-08-27T12:13:08.972Z" }, + { url = "https://files.pythonhosted.org/packages/bd/fe/38de28dee5df58b8198c743fe2bea0c785c6d40941b9950bac4cdb71a014/rpds_py-0.27.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:ae2775c1973e3c30316892737b91f9283f9908e3cc7625b9331271eaaed7dc90", size = 361887, upload-time = "2025-08-27T12:13:10.233Z" }, + { url = "https://files.pythonhosted.org/packages/7c/9a/4b6c7eedc7dd90986bf0fab6ea2a091ec11c01b15f8ba0a14d3f80450468/rpds_py-0.27.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2643400120f55c8a96f7c9d858f7be0c88d383cd4653ae2cf0d0c88f668073e5", size = 345795, upload-time = "2025-08-27T12:13:11.65Z" }, + { url = "https://files.pythonhosted.org/packages/6f/0e/e650e1b81922847a09cca820237b0edee69416a01268b7754d506ade11ad/rpds_py-0.27.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16323f674c089b0360674a4abd28d5042947d54ba620f72514d69be4ff64845e", size = 385121, upload-time = "2025-08-27T12:13:13.008Z" }, + { url = "https://files.pythonhosted.org/packages/1b/ea/b306067a712988e2bff00dcc7c8f31d26c29b6d5931b461aa4b60a013e33/rpds_py-0.27.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9a1f4814b65eacac94a00fc9a526e3fdafd78e439469644032032d0d63de4881", size = 398976, upload-time = "2025-08-27T12:13:14.368Z" }, + { url = "https://files.pythonhosted.org/packages/2c/0a/26dc43c8840cb8fe239fe12dbc8d8de40f2365e838f3d395835dde72f0e5/rpds_py-0.27.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ba32c16b064267b22f1850a34051121d423b6f7338a12b9459550eb2096e7ec", size = 525953, upload-time = "2025-08-27T12:13:15.774Z" }, + { url = "https://files.pythonhosted.org/packages/22/14/c85e8127b573aaf3a0cbd7fbb8c9c99e735a4a02180c84da2a463b766e9e/rpds_py-0.27.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5c20f33fd10485b80f65e800bbe5f6785af510b9f4056c5a3c612ebc83ba6cb", size = 407915, upload-time = "2025-08-27T12:13:17.379Z" }, + { url = "https://files.pythonhosted.org/packages/ed/7b/8f4fee9ba1fb5ec856eb22d725a4efa3deb47f769597c809e03578b0f9d9/rpds_py-0.27.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:466bfe65bd932da36ff279ddd92de56b042f2266d752719beb97b08526268ec5", size = 386883, upload-time = "2025-08-27T12:13:18.704Z" }, + { url = "https://files.pythonhosted.org/packages/86/47/28fa6d60f8b74fcdceba81b272f8d9836ac0340570f68f5df6b41838547b/rpds_py-0.27.1-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:41e532bbdcb57c92ba3be62c42e9f096431b4cf478da9bc3bc6ce5c38ab7ba7a", size = 405699, upload-time = "2025-08-27T12:13:20.089Z" }, + { url = "https://files.pythonhosted.org/packages/d0/fd/c5987b5e054548df56953a21fe2ebed51fc1ec7c8f24fd41c067b68c4a0a/rpds_py-0.27.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f149826d742b406579466283769a8ea448eed82a789af0ed17b0cd5770433444", size = 423713, upload-time = "2025-08-27T12:13:21.436Z" }, + { url = "https://files.pythonhosted.org/packages/ac/ba/3c4978b54a73ed19a7d74531be37a8bcc542d917c770e14d372b8daea186/rpds_py-0.27.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:80c60cfb5310677bd67cb1e85a1e8eb52e12529545441b43e6f14d90b878775a", size = 562324, upload-time = "2025-08-27T12:13:22.789Z" }, + { url = "https://files.pythonhosted.org/packages/b5/6c/6943a91768fec16db09a42b08644b960cff540c66aab89b74be6d4a144ba/rpds_py-0.27.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:7ee6521b9baf06085f62ba9c7a3e5becffbc32480d2f1b351559c001c38ce4c1", size = 593646, upload-time = "2025-08-27T12:13:24.122Z" }, + { url = "https://files.pythonhosted.org/packages/11/73/9d7a8f4be5f4396f011a6bb7a19fe26303a0dac9064462f5651ced2f572f/rpds_py-0.27.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a512c8263249a9d68cac08b05dd59d2b3f2061d99b322813cbcc14c3c7421998", size = 558137, upload-time = "2025-08-27T12:13:25.557Z" }, + { url = "https://files.pythonhosted.org/packages/6e/96/6772cbfa0e2485bcceef8071de7821f81aeac8bb45fbfd5542a3e8108165/rpds_py-0.27.1-cp312-cp312-win32.whl", hash = "sha256:819064fa048ba01b6dadc5116f3ac48610435ac9a0058bbde98e569f9e785c39", size = 221343, upload-time = "2025-08-27T12:13:26.967Z" }, + { url = "https://files.pythonhosted.org/packages/67/b6/c82f0faa9af1c6a64669f73a17ee0eeef25aff30bb9a1c318509efe45d84/rpds_py-0.27.1-cp312-cp312-win_amd64.whl", hash = "sha256:d9199717881f13c32c4046a15f024971a3b78ad4ea029e8da6b86e5aa9cf4594", size = 232497, upload-time = "2025-08-27T12:13:28.326Z" }, + { url = "https://files.pythonhosted.org/packages/e1/96/2817b44bd2ed11aebacc9251da03689d56109b9aba5e311297b6902136e2/rpds_py-0.27.1-cp312-cp312-win_arm64.whl", hash = "sha256:33aa65b97826a0e885ef6e278fbd934e98cdcfed80b63946025f01e2f5b29502", size = 222790, upload-time = "2025-08-27T12:13:29.71Z" }, + { url = "https://files.pythonhosted.org/packages/cc/77/610aeee8d41e39080c7e14afa5387138e3c9fa9756ab893d09d99e7d8e98/rpds_py-0.27.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:e4b9fcfbc021633863a37e92571d6f91851fa656f0180246e84cbd8b3f6b329b", size = 361741, upload-time = "2025-08-27T12:13:31.039Z" }, + { url = "https://files.pythonhosted.org/packages/3a/fc/c43765f201c6a1c60be2043cbdb664013def52460a4c7adace89d6682bf4/rpds_py-0.27.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1441811a96eadca93c517d08df75de45e5ffe68aa3089924f963c782c4b898cf", size = 345574, upload-time = "2025-08-27T12:13:32.902Z" }, + { url = "https://files.pythonhosted.org/packages/20/42/ee2b2ca114294cd9847d0ef9c26d2b0851b2e7e00bf14cc4c0b581df0fc3/rpds_py-0.27.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55266dafa22e672f5a4f65019015f90336ed31c6383bd53f5e7826d21a0e0b83", size = 385051, upload-time = "2025-08-27T12:13:34.228Z" }, + { url = "https://files.pythonhosted.org/packages/fd/e8/1e430fe311e4799e02e2d1af7c765f024e95e17d651612425b226705f910/rpds_py-0.27.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d78827d7ac08627ea2c8e02c9e5b41180ea5ea1f747e9db0915e3adf36b62dcf", size = 398395, upload-time = "2025-08-27T12:13:36.132Z" }, + { url = "https://files.pythonhosted.org/packages/82/95/9dc227d441ff2670651c27a739acb2535ccaf8b351a88d78c088965e5996/rpds_py-0.27.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae92443798a40a92dc5f0b01d8a7c93adde0c4dc965310a29ae7c64d72b9fad2", size = 524334, upload-time = "2025-08-27T12:13:37.562Z" }, + { url = "https://files.pythonhosted.org/packages/87/01/a670c232f401d9ad461d9a332aa4080cd3cb1d1df18213dbd0d2a6a7ab51/rpds_py-0.27.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c46c9dd2403b66a2a3b9720ec4b74d4ab49d4fabf9f03dfdce2d42af913fe8d0", size = 407691, upload-time = "2025-08-27T12:13:38.94Z" }, + { url = "https://files.pythonhosted.org/packages/03/36/0a14aebbaa26fe7fab4780c76f2239e76cc95a0090bdb25e31d95c492fcd/rpds_py-0.27.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2efe4eb1d01b7f5f1939f4ef30ecea6c6b3521eec451fb93191bf84b2a522418", size = 386868, upload-time = "2025-08-27T12:13:40.192Z" }, + { url = "https://files.pythonhosted.org/packages/3b/03/8c897fb8b5347ff6c1cc31239b9611c5bf79d78c984430887a353e1409a1/rpds_py-0.27.1-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:15d3b4d83582d10c601f481eca29c3f138d44c92187d197aff663a269197c02d", size = 405469, upload-time = "2025-08-27T12:13:41.496Z" }, + { url = "https://files.pythonhosted.org/packages/da/07/88c60edc2df74850d496d78a1fdcdc7b54360a7f610a4d50008309d41b94/rpds_py-0.27.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4ed2e16abbc982a169d30d1a420274a709949e2cbdef119fe2ec9d870b42f274", size = 422125, upload-time = "2025-08-27T12:13:42.802Z" }, + { url = "https://files.pythonhosted.org/packages/6b/86/5f4c707603e41b05f191a749984f390dabcbc467cf833769b47bf14ba04f/rpds_py-0.27.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a75f305c9b013289121ec0f1181931975df78738cdf650093e6b86d74aa7d8dd", size = 562341, upload-time = "2025-08-27T12:13:44.472Z" }, + { url = "https://files.pythonhosted.org/packages/b2/92/3c0cb2492094e3cd9baf9e49bbb7befeceb584ea0c1a8b5939dca4da12e5/rpds_py-0.27.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:67ce7620704745881a3d4b0ada80ab4d99df390838839921f99e63c474f82cf2", size = 592511, upload-time = "2025-08-27T12:13:45.898Z" }, + { url = "https://files.pythonhosted.org/packages/10/bb/82e64fbb0047c46a168faa28d0d45a7851cd0582f850b966811d30f67ad8/rpds_py-0.27.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9d992ac10eb86d9b6f369647b6a3f412fc0075cfd5d799530e84d335e440a002", size = 557736, upload-time = "2025-08-27T12:13:47.408Z" }, + { url = "https://files.pythonhosted.org/packages/00/95/3c863973d409210da7fb41958172c6b7dbe7fc34e04d3cc1f10bb85e979f/rpds_py-0.27.1-cp313-cp313-win32.whl", hash = "sha256:4f75e4bd8ab8db624e02c8e2fc4063021b58becdbe6df793a8111d9343aec1e3", size = 221462, upload-time = "2025-08-27T12:13:48.742Z" }, + { url = "https://files.pythonhosted.org/packages/ce/2c/5867b14a81dc217b56d95a9f2a40fdbc56a1ab0181b80132beeecbd4b2d6/rpds_py-0.27.1-cp313-cp313-win_amd64.whl", hash = "sha256:f9025faafc62ed0b75a53e541895ca272815bec18abe2249ff6501c8f2e12b83", size = 232034, upload-time = "2025-08-27T12:13:50.11Z" }, + { url = "https://files.pythonhosted.org/packages/c7/78/3958f3f018c01923823f1e47f1cc338e398814b92d83cd278364446fac66/rpds_py-0.27.1-cp313-cp313-win_arm64.whl", hash = "sha256:ed10dc32829e7d222b7d3b93136d25a406ba9788f6a7ebf6809092da1f4d279d", size = 222392, upload-time = "2025-08-27T12:13:52.587Z" }, + { url = "https://files.pythonhosted.org/packages/01/76/1cdf1f91aed5c3a7bf2eba1f1c4e4d6f57832d73003919a20118870ea659/rpds_py-0.27.1-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:92022bbbad0d4426e616815b16bc4127f83c9a74940e1ccf3cfe0b387aba0228", size = 358355, upload-time = "2025-08-27T12:13:54.012Z" }, + { url = "https://files.pythonhosted.org/packages/c3/6f/bf142541229374287604caf3bb2a4ae17f0a580798fd72d3b009b532db4e/rpds_py-0.27.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:47162fdab9407ec3f160805ac3e154df042e577dd53341745fc7fb3f625e6d92", size = 342138, upload-time = "2025-08-27T12:13:55.791Z" }, + { url = "https://files.pythonhosted.org/packages/1a/77/355b1c041d6be40886c44ff5e798b4e2769e497b790f0f7fd1e78d17e9a8/rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb89bec23fddc489e5d78b550a7b773557c9ab58b7946154a10a6f7a214a48b2", size = 380247, upload-time = "2025-08-27T12:13:57.683Z" }, + { url = "https://files.pythonhosted.org/packages/d6/a4/d9cef5c3946ea271ce2243c51481971cd6e34f21925af2783dd17b26e815/rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e48af21883ded2b3e9eb48cb7880ad8598b31ab752ff3be6457001d78f416723", size = 390699, upload-time = "2025-08-27T12:13:59.137Z" }, + { url = "https://files.pythonhosted.org/packages/3a/06/005106a7b8c6c1a7e91b73169e49870f4af5256119d34a361ae5240a0c1d/rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6f5b7bd8e219ed50299e58551a410b64daafb5017d54bbe822e003856f06a802", size = 521852, upload-time = "2025-08-27T12:14:00.583Z" }, + { url = "https://files.pythonhosted.org/packages/e5/3e/50fb1dac0948e17a02eb05c24510a8fe12d5ce8561c6b7b7d1339ab7ab9c/rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:08f1e20bccf73b08d12d804d6e1c22ca5530e71659e6673bce31a6bb71c1e73f", size = 402582, upload-time = "2025-08-27T12:14:02.034Z" }, + { url = "https://files.pythonhosted.org/packages/cb/b0/f4e224090dc5b0ec15f31a02d746ab24101dd430847c4d99123798661bfc/rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0dc5dceeaefcc96dc192e3a80bbe1d6c410c469e97bdd47494a7d930987f18b2", size = 384126, upload-time = "2025-08-27T12:14:03.437Z" }, + { url = "https://files.pythonhosted.org/packages/54/77/ac339d5f82b6afff1df8f0fe0d2145cc827992cb5f8eeb90fc9f31ef7a63/rpds_py-0.27.1-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:d76f9cc8665acdc0c9177043746775aa7babbf479b5520b78ae4002d889f5c21", size = 399486, upload-time = "2025-08-27T12:14:05.443Z" }, + { url = "https://files.pythonhosted.org/packages/d6/29/3e1c255eee6ac358c056a57d6d6869baa00a62fa32eea5ee0632039c50a3/rpds_py-0.27.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:134fae0e36022edad8290a6661edf40c023562964efea0cc0ec7f5d392d2aaef", size = 414832, upload-time = "2025-08-27T12:14:06.902Z" }, + { url = "https://files.pythonhosted.org/packages/3f/db/6d498b844342deb3fa1d030598db93937a9964fcf5cb4da4feb5f17be34b/rpds_py-0.27.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:eb11a4f1b2b63337cfd3b4d110af778a59aae51c81d195768e353d8b52f88081", size = 557249, upload-time = "2025-08-27T12:14:08.37Z" }, + { url = "https://files.pythonhosted.org/packages/60/f3/690dd38e2310b6f68858a331399b4d6dbb9132c3e8ef8b4333b96caf403d/rpds_py-0.27.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:13e608ac9f50a0ed4faec0e90ece76ae33b34c0e8656e3dceb9a7db994c692cd", size = 587356, upload-time = "2025-08-27T12:14:10.034Z" }, + { url = "https://files.pythonhosted.org/packages/86/e3/84507781cccd0145f35b1dc32c72675200c5ce8d5b30f813e49424ef68fc/rpds_py-0.27.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dd2135527aa40f061350c3f8f89da2644de26cd73e4de458e79606384f4f68e7", size = 555300, upload-time = "2025-08-27T12:14:11.783Z" }, + { url = "https://files.pythonhosted.org/packages/e5/ee/375469849e6b429b3516206b4580a79e9ef3eb12920ddbd4492b56eaacbe/rpds_py-0.27.1-cp313-cp313t-win32.whl", hash = "sha256:3020724ade63fe320a972e2ffd93b5623227e684315adce194941167fee02688", size = 216714, upload-time = "2025-08-27T12:14:13.629Z" }, + { url = "https://files.pythonhosted.org/packages/21/87/3fc94e47c9bd0742660e84706c311a860dcae4374cf4a03c477e23ce605a/rpds_py-0.27.1-cp313-cp313t-win_amd64.whl", hash = "sha256:8ee50c3e41739886606388ba3ab3ee2aae9f35fb23f833091833255a31740797", size = 228943, upload-time = "2025-08-27T12:14:14.937Z" }, + { url = "https://files.pythonhosted.org/packages/70/36/b6e6066520a07cf029d385de869729a895917b411e777ab1cde878100a1d/rpds_py-0.27.1-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:acb9aafccaae278f449d9c713b64a9e68662e7799dbd5859e2c6b3c67b56d334", size = 362472, upload-time = "2025-08-27T12:14:16.333Z" }, + { url = "https://files.pythonhosted.org/packages/af/07/b4646032e0dcec0df9c73a3bd52f63bc6c5f9cda992f06bd0e73fe3fbebd/rpds_py-0.27.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:b7fb801aa7f845ddf601c49630deeeccde7ce10065561d92729bfe81bd21fb33", size = 345676, upload-time = "2025-08-27T12:14:17.764Z" }, + { url = "https://files.pythonhosted.org/packages/b0/16/2f1003ee5d0af4bcb13c0cf894957984c32a6751ed7206db2aee7379a55e/rpds_py-0.27.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fe0dd05afb46597b9a2e11c351e5e4283c741237e7f617ffb3252780cca9336a", size = 385313, upload-time = "2025-08-27T12:14:19.829Z" }, + { url = "https://files.pythonhosted.org/packages/05/cd/7eb6dd7b232e7f2654d03fa07f1414d7dfc980e82ba71e40a7c46fd95484/rpds_py-0.27.1-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b6dfb0e058adb12d8b1d1b25f686e94ffa65d9995a5157afe99743bf7369d62b", size = 399080, upload-time = "2025-08-27T12:14:21.531Z" }, + { url = "https://files.pythonhosted.org/packages/20/51/5829afd5000ec1cb60f304711f02572d619040aa3ec033d8226817d1e571/rpds_py-0.27.1-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ed090ccd235f6fa8bb5861684567f0a83e04f52dfc2e5c05f2e4b1309fcf85e7", size = 523868, upload-time = "2025-08-27T12:14:23.485Z" }, + { url = "https://files.pythonhosted.org/packages/05/2c/30eebca20d5db95720ab4d2faec1b5e4c1025c473f703738c371241476a2/rpds_py-0.27.1-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bf876e79763eecf3e7356f157540d6a093cef395b65514f17a356f62af6cc136", size = 408750, upload-time = "2025-08-27T12:14:24.924Z" }, + { url = "https://files.pythonhosted.org/packages/90/1a/cdb5083f043597c4d4276eae4e4c70c55ab5accec078da8611f24575a367/rpds_py-0.27.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:12ed005216a51b1d6e2b02a7bd31885fe317e45897de81d86dcce7d74618ffff", size = 387688, upload-time = "2025-08-27T12:14:27.537Z" }, + { url = "https://files.pythonhosted.org/packages/7c/92/cf786a15320e173f945d205ab31585cc43969743bb1a48b6888f7a2b0a2d/rpds_py-0.27.1-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:ee4308f409a40e50593c7e3bb8cbe0b4d4c66d1674a316324f0c2f5383b486f9", size = 407225, upload-time = "2025-08-27T12:14:28.981Z" }, + { url = "https://files.pythonhosted.org/packages/33/5c/85ee16df5b65063ef26017bef33096557a4c83fbe56218ac7cd8c235f16d/rpds_py-0.27.1-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0b08d152555acf1f455154d498ca855618c1378ec810646fcd7c76416ac6dc60", size = 423361, upload-time = "2025-08-27T12:14:30.469Z" }, + { url = "https://files.pythonhosted.org/packages/4b/8e/1c2741307fcabd1a334ecf008e92c4f47bb6f848712cf15c923becfe82bb/rpds_py-0.27.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:dce51c828941973a5684d458214d3a36fcd28da3e1875d659388f4f9f12cc33e", size = 562493, upload-time = "2025-08-27T12:14:31.987Z" }, + { url = "https://files.pythonhosted.org/packages/04/03/5159321baae9b2222442a70c1f988cbbd66b9be0675dd3936461269be360/rpds_py-0.27.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:c1476d6f29eb81aa4151c9a31219b03f1f798dc43d8af1250a870735516a1212", size = 592623, upload-time = "2025-08-27T12:14:33.543Z" }, + { url = "https://files.pythonhosted.org/packages/ff/39/c09fd1ad28b85bc1d4554a8710233c9f4cefd03d7717a1b8fbfd171d1167/rpds_py-0.27.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:3ce0cac322b0d69b63c9cdb895ee1b65805ec9ffad37639f291dd79467bee675", size = 558800, upload-time = "2025-08-27T12:14:35.436Z" }, + { url = "https://files.pythonhosted.org/packages/c5/d6/99228e6bbcf4baa764b18258f519a9035131d91b538d4e0e294313462a98/rpds_py-0.27.1-cp314-cp314-win32.whl", hash = "sha256:dfbfac137d2a3d0725758cd141f878bf4329ba25e34979797c89474a89a8a3a3", size = 221943, upload-time = "2025-08-27T12:14:36.898Z" }, + { url = "https://files.pythonhosted.org/packages/be/07/c802bc6b8e95be83b79bdf23d1aa61d68324cb1006e245d6c58e959e314d/rpds_py-0.27.1-cp314-cp314-win_amd64.whl", hash = "sha256:a6e57b0abfe7cc513450fcf529eb486b6e4d3f8aee83e92eb5f1ef848218d456", size = 233739, upload-time = "2025-08-27T12:14:38.386Z" }, + { url = "https://files.pythonhosted.org/packages/c8/89/3e1b1c16d4c2d547c5717377a8df99aee8099ff050f87c45cb4d5fa70891/rpds_py-0.27.1-cp314-cp314-win_arm64.whl", hash = "sha256:faf8d146f3d476abfee026c4ae3bdd9ca14236ae4e4c310cbd1cf75ba33d24a3", size = 223120, upload-time = "2025-08-27T12:14:39.82Z" }, + { url = "https://files.pythonhosted.org/packages/62/7e/dc7931dc2fa4a6e46b2a4fa744a9fe5c548efd70e0ba74f40b39fa4a8c10/rpds_py-0.27.1-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:ba81d2b56b6d4911ce735aad0a1d4495e808b8ee4dc58715998741a26874e7c2", size = 358944, upload-time = "2025-08-27T12:14:41.199Z" }, + { url = "https://files.pythonhosted.org/packages/e6/22/4af76ac4e9f336bfb1a5f240d18a33c6b2fcaadb7472ac7680576512b49a/rpds_py-0.27.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:84f7d509870098de0e864cad0102711c1e24e9b1a50ee713b65928adb22269e4", size = 342283, upload-time = "2025-08-27T12:14:42.699Z" }, + { url = "https://files.pythonhosted.org/packages/1c/15/2a7c619b3c2272ea9feb9ade67a45c40b3eeb500d503ad4c28c395dc51b4/rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9e960fc78fecd1100539f14132425e1d5fe44ecb9239f8f27f079962021523e", size = 380320, upload-time = "2025-08-27T12:14:44.157Z" }, + { url = "https://files.pythonhosted.org/packages/a2/7d/4c6d243ba4a3057e994bb5bedd01b5c963c12fe38dde707a52acdb3849e7/rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:62f85b665cedab1a503747617393573995dac4600ff51869d69ad2f39eb5e817", size = 391760, upload-time = "2025-08-27T12:14:45.845Z" }, + { url = "https://files.pythonhosted.org/packages/b4/71/b19401a909b83bcd67f90221330bc1ef11bc486fe4e04c24388d28a618ae/rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fed467af29776f6556250c9ed85ea5a4dd121ab56a5f8b206e3e7a4c551e48ec", size = 522476, upload-time = "2025-08-27T12:14:47.364Z" }, + { url = "https://files.pythonhosted.org/packages/e4/44/1a3b9715c0455d2e2f0f6df5ee6d6f5afdc423d0773a8a682ed2b43c566c/rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f2729615f9d430af0ae6b36cf042cb55c0936408d543fb691e1a9e36648fd35a", size = 403418, upload-time = "2025-08-27T12:14:49.991Z" }, + { url = "https://files.pythonhosted.org/packages/1c/4b/fb6c4f14984eb56673bc868a66536f53417ddb13ed44b391998100a06a96/rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b207d881a9aef7ba753d69c123a35d96ca7cb808056998f6b9e8747321f03b8", size = 384771, upload-time = "2025-08-27T12:14:52.159Z" }, + { url = "https://files.pythonhosted.org/packages/c0/56/d5265d2d28b7420d7b4d4d85cad8ef891760f5135102e60d5c970b976e41/rpds_py-0.27.1-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:639fd5efec029f99b79ae47e5d7e00ad8a773da899b6309f6786ecaf22948c48", size = 400022, upload-time = "2025-08-27T12:14:53.859Z" }, + { url = "https://files.pythonhosted.org/packages/8f/e9/9f5fc70164a569bdd6ed9046486c3568d6926e3a49bdefeeccfb18655875/rpds_py-0.27.1-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fecc80cb2a90e28af8a9b366edacf33d7a91cbfe4c2c4544ea1246e949cfebeb", size = 416787, upload-time = "2025-08-27T12:14:55.673Z" }, + { url = "https://files.pythonhosted.org/packages/d4/64/56dd03430ba491db943a81dcdef115a985aac5f44f565cd39a00c766d45c/rpds_py-0.27.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:42a89282d711711d0a62d6f57d81aa43a1368686c45bc1c46b7f079d55692734", size = 557538, upload-time = "2025-08-27T12:14:57.245Z" }, + { url = "https://files.pythonhosted.org/packages/3f/36/92cc885a3129993b1d963a2a42ecf64e6a8e129d2c7cc980dbeba84e55fb/rpds_py-0.27.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:cf9931f14223de59551ab9d38ed18d92f14f055a5f78c1d8ad6493f735021bbb", size = 588512, upload-time = "2025-08-27T12:14:58.728Z" }, + { url = "https://files.pythonhosted.org/packages/dd/10/6b283707780a81919f71625351182b4f98932ac89a09023cb61865136244/rpds_py-0.27.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f39f58a27cc6e59f432b568ed8429c7e1641324fbe38131de852cd77b2d534b0", size = 555813, upload-time = "2025-08-27T12:15:00.334Z" }, + { url = "https://files.pythonhosted.org/packages/04/2e/30b5ea18c01379da6272a92825dd7e53dc9d15c88a19e97932d35d430ef7/rpds_py-0.27.1-cp314-cp314t-win32.whl", hash = "sha256:d5fa0ee122dc09e23607a28e6d7b150da16c662e66409bbe85230e4c85bb528a", size = 217385, upload-time = "2025-08-27T12:15:01.937Z" }, + { url = "https://files.pythonhosted.org/packages/32/7d/97119da51cb1dd3f2f3c0805f155a3aa4a95fa44fe7d78ae15e69edf4f34/rpds_py-0.27.1-cp314-cp314t-win_amd64.whl", hash = "sha256:6567d2bb951e21232c2f660c24cf3470bb96de56cdcb3f071a83feeaff8a2772", size = 230097, upload-time = "2025-08-27T12:15:03.961Z" }, + { url = "https://files.pythonhosted.org/packages/0c/ed/e1fba02de17f4f76318b834425257c8ea297e415e12c68b4361f63e8ae92/rpds_py-0.27.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:cdfe4bb2f9fe7458b7453ad3c33e726d6d1c7c0a72960bcc23800d77384e42df", size = 371402, upload-time = "2025-08-27T12:15:51.561Z" }, + { url = "https://files.pythonhosted.org/packages/af/7c/e16b959b316048b55585a697e94add55a4ae0d984434d279ea83442e460d/rpds_py-0.27.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:8fabb8fd848a5f75a2324e4a84501ee3a5e3c78d8603f83475441866e60b94a3", size = 354084, upload-time = "2025-08-27T12:15:53.219Z" }, + { url = "https://files.pythonhosted.org/packages/de/c1/ade645f55de76799fdd08682d51ae6724cb46f318573f18be49b1e040428/rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eda8719d598f2f7f3e0f885cba8646644b55a187762bec091fa14a2b819746a9", size = 383090, upload-time = "2025-08-27T12:15:55.158Z" }, + { url = "https://files.pythonhosted.org/packages/1f/27/89070ca9b856e52960da1472efcb6c20ba27cfe902f4f23ed095b9cfc61d/rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3c64d07e95606ec402a0a1c511fe003873fa6af630bda59bac77fac8b4318ebc", size = 394519, upload-time = "2025-08-27T12:15:57.238Z" }, + { url = "https://files.pythonhosted.org/packages/b3/28/be120586874ef906aa5aeeae95ae8df4184bc757e5b6bd1c729ccff45ed5/rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:93a2ed40de81bcff59aabebb626562d48332f3d028ca2036f1d23cbb52750be4", size = 523817, upload-time = "2025-08-27T12:15:59.237Z" }, + { url = "https://files.pythonhosted.org/packages/a8/ef/70cc197bc11cfcde02a86f36ac1eed15c56667c2ebddbdb76a47e90306da/rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:387ce8c44ae94e0ec50532d9cb0edce17311024c9794eb196b90e1058aadeb66", size = 403240, upload-time = "2025-08-27T12:16:00.923Z" }, + { url = "https://files.pythonhosted.org/packages/cf/35/46936cca449f7f518f2f4996e0e8344db4b57e2081e752441154089d2a5f/rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aaf94f812c95b5e60ebaf8bfb1898a7d7cb9c1af5744d4a67fa47796e0465d4e", size = 385194, upload-time = "2025-08-27T12:16:02.802Z" }, + { url = "https://files.pythonhosted.org/packages/e1/62/29c0d3e5125c3270b51415af7cbff1ec587379c84f55a5761cc9efa8cd06/rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:4848ca84d6ded9b58e474dfdbad4b8bfb450344c0551ddc8d958bf4b36aa837c", size = 402086, upload-time = "2025-08-27T12:16:04.806Z" }, + { url = "https://files.pythonhosted.org/packages/8f/66/03e1087679227785474466fdd04157fb793b3b76e3fcf01cbf4c693c1949/rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2bde09cbcf2248b73c7c323be49b280180ff39fadcfe04e7b6f54a678d02a7cf", size = 419272, upload-time = "2025-08-27T12:16:06.471Z" }, + { url = "https://files.pythonhosted.org/packages/6a/24/e3e72d265121e00b063aef3e3501e5b2473cf1b23511d56e529531acf01e/rpds_py-0.27.1-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:94c44ee01fd21c9058f124d2d4f0c9dc7634bec93cd4b38eefc385dabe71acbf", size = 560003, upload-time = "2025-08-27T12:16:08.06Z" }, + { url = "https://files.pythonhosted.org/packages/26/ca/f5a344c534214cc2d41118c0699fffbdc2c1bc7046f2a2b9609765ab9c92/rpds_py-0.27.1-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:df8b74962e35c9249425d90144e721eed198e6555a0e22a563d29fe4486b51f6", size = 590482, upload-time = "2025-08-27T12:16:10.137Z" }, + { url = "https://files.pythonhosted.org/packages/ce/08/4349bdd5c64d9d193c360aa9db89adeee6f6682ab8825dca0a3f535f434f/rpds_py-0.27.1-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:dc23e6820e3b40847e2f4a7726462ba0cf53089512abe9ee16318c366494c17a", size = 556523, upload-time = "2025-08-27T12:16:12.188Z" }, +] + [[package]] name = "rsa" version = "4.9.1" @@ -1341,6 +1940,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" }, ] +[[package]] +name = "sse-starlette" +version = "3.0.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/42/6f/22ed6e33f8a9e76ca0a412405f31abb844b779d52c5f96660766edcd737c/sse_starlette-3.0.2.tar.gz", hash = "sha256:ccd60b5765ebb3584d0de2d7a6e4f745672581de4f5005ab31c3a25d10b52b3a", size = 20985, upload-time = "2025-07-27T09:07:44.565Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/10/c78f463b4ef22eef8491f218f692be838282cd65480f6e423d7730dfd1fb/sse_starlette-3.0.2-py3-none-any.whl", hash = "sha256:16b7cbfddbcd4eaca11f7b586f3b8a080f1afe952c15813455b162edea619e5a", size = 11297, upload-time = "2025-07-27T09:07:43.268Z" }, +] + [[package]] name = "starlette" version = "0.46.2" @@ -1362,6 +1973,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e5/30/643397144bfbfec6f6ef821f36f33e57d35946c44a2352d3c9f0ae847619/tenacity-9.1.2-py3-none-any.whl", hash = "sha256:f77bf36710d8b73a50b2dd155c97b870017ad21afe6ab300326b0371b3b05138", size = 28248, upload-time = "2025-04-02T08:25:07.678Z" }, ] +[[package]] +name = "tqdm" +version = "4.67.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a8/4b/29b4ef32e036bb34e4ab51796dd745cdba7ed47ad142a9f4a1eb8e0c744d/tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2", size = 169737, upload-time = "2024-11-24T20:12:22.481Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl", hash = "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2", size = 78540, upload-time = "2024-11-24T20:12:19.698Z" }, +] + [[package]] name = "transcription" version = "0.1.0" @@ -1394,6 +2017,27 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2d/76/06dbe78f39b2203d2a47d5facc5df5102d0561e2807396471b5f7c5a30a1/typer-0.16.1-py3-none-any.whl", hash = "sha256:90ee01cb02d9b8395ae21ee3368421faf21fa138cb2a541ed369c08cec5237c9", size = 46397, upload-time = "2025-08-18T19:18:21.663Z" }, ] +[[package]] +name = "types-requests" +version = "2.31.0.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "types-urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f9/b8/c1e8d39996b4929b918aba10dba5de07a8b3f4c8487bb61bb79882544e69/types-requests-2.31.0.6.tar.gz", hash = "sha256:cd74ce3b53c461f1228a9b783929ac73a666658f223e28ed29753771477b3bd0", size = 15535, upload-time = "2023-09-27T06:19:38.443Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5c/a1/6f8dc74d9069e790d604ddae70cb46dcbac668f1bb08136e7b0f2f5cd3bf/types_requests-2.31.0.6-py3-none-any.whl", hash = "sha256:a2db9cb228a81da8348b49ad6db3f5519452dd20a9c1e1a868c83c5fe88fd1a9", size = 14516, upload-time = "2023-09-27T06:19:36.373Z" }, +] + +[[package]] +name = "types-urllib3" +version = "1.26.25.14" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/73/de/b9d7a68ad39092368fb21dd6194b362b98a1daeea5dcfef5e1adb5031c7e/types-urllib3-1.26.25.14.tar.gz", hash = "sha256:229b7f577c951b8c1b92c1bc2b2fdb0b49847bd2af6d1cc2a2e3dd340f3bda8f", size = 11239, upload-time = "2023-07-20T15:19:31.307Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/11/7b/3fc711b2efea5e85a7a0bbfe269ea944aa767bbba5ec52f9ee45d362ccf3/types_urllib3-1.26.25.14-py3-none-any.whl", hash = "sha256:9683bbb7fb72e32bfe9d2be6e04875fbe1b3eeec3cbb4ea231435aa7fd6b4f0e", size = 15377, upload-time = "2023-07-20T15:19:30.379Z" }, +] + [[package]] name = "typing-extensions" version = "4.12.2" @@ -1403,6 +2047,27 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438, upload-time = "2024-06-07T18:52:13.582Z" }, ] +[[package]] +name = "typing-inspection" +version = "0.4.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f8/b1/0c11f5058406b3af7609f121aaa6b609744687f1d158b3c3a5bf4cc94238/typing_inspection-0.4.1.tar.gz", hash = "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28", size = 75726, upload-time = "2025-05-21T18:55:23.885Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/17/69/cd203477f944c353c31bade965f880aa1061fd6bf05ded0726ca845b6ff7/typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51", size = 14552, upload-time = "2025-05-21T18:55:22.152Z" }, +] + +[[package]] +name = "tzdata" +version = "2025.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/95/32/1a225d6164441be760d75c2c42e2780dc0873fe382da3e98a2e1e48361e5/tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9", size = 196380, upload-time = "2025-03-23T13:54:43.652Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5c/23/c7abc0ca0a1526a0774eca151daeb8de62ec457e77262b66b359c3c7679e/tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8", size = 347839, upload-time = "2025-03-23T13:54:41.845Z" }, +] + [[package]] name = "urllib3" version = "1.26.20" From 1b5ed2023fbb62e67ae5eebcd00aa23e4248cf91 Mon Sep 17 00:00:00 2001 From: Tomasz Mazur <47872060+AHGIJMKLKKZNPJKQR@users.noreply.github.com> Date: Mon, 15 Sep 2025 19:47:19 +0200 Subject: [PATCH 02/16] Remove redundant var --- examples/poet_chat/main.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/poet_chat/main.py b/examples/poet_chat/main.py index 4541e9e..67a1792 100644 --- a/examples/poet_chat/main.py +++ b/examples/poet_chat/main.py @@ -9,8 +9,6 @@ from fishjam.agent import AudioTrackOptions -CHUNK_SIZE = 12000 - async def main(): room = fishjam_client.create_room() From 3ec40d162c09d6b55237630f11395ed7d33f9335 Mon Sep 17 00:00:00 2001 From: Tomasz Mazur <47872060+AHGIJMKLKKZNPJKQR@users.noreply.github.com> Date: Tue, 23 Sep 2025 17:40:36 +0200 Subject: [PATCH 03/16] Add interruptions to agents and update poet example --- examples/poet_chat/main.py | 2 ++ examples/poet_chat/poet_chat/agent.py | 1 + fishjam/agent/agent.py | 18 ++++++++++++++++++ fishjam/events/_protos/fishjam/__init__.py | 13 +++++++++++++ protos | 2 +- 5 files changed, 35 insertions(+), 1 deletion(-) diff --git a/examples/poet_chat/main.py b/examples/poet_chat/main.py index 67a1792..8b3a8f1 100644 --- a/examples/poet_chat/main.py +++ b/examples/poet_chat/main.py @@ -30,6 +30,8 @@ async def _openai_recv(): if event.type == "audio": audio = event.audio.data await track.send_chunk(audio) + elif event.type == "audio_interrupted": + await track.interrupt() elif event.type == "raw_model_event": if event.data.type == "input_audio_transcription_completed": print(f"Peer said:\n{event.data.transcript}\n") diff --git a/examples/poet_chat/poet_chat/agent.py b/examples/poet_chat/poet_chat/agent.py index 7639d3e..e533a2f 100644 --- a/examples/poet_chat/poet_chat/agent.py +++ b/examples/poet_chat/poet_chat/agent.py @@ -14,6 +14,7 @@ "turn_detection": { "interrupt_response": True, "create_response": True, + "type": "semantic_vad", }, } }, diff --git a/fishjam/agent/agent.py b/fishjam/agent/agent.py index f0ecd11..93710a2 100644 --- a/fishjam/agent/agent.py +++ b/fishjam/agent/agent.py @@ -16,6 +16,7 @@ AgentRequestAddTrack, AgentRequestAddTrackCodecParameters, AgentRequestAuthRequest, + AgentRequestInterruptTrack, AgentResponse, ) from fishjam.events._protos.fishjam import AgentRequestTrackData as OutgoingTrackData @@ -82,6 +83,23 @@ async def send_chunk(self, data: bytes): await self.session._send(message) + async def interrupt(self): + """ + Interrupt current track. + + Any audio that has been sent, but not played + will be cleared and be prevented from playing. + + Audio sent after the interrupt will be played normally. + """ + message = AgentRequest( + interrupt_track=AgentRequestInterruptTrack( + track_id=self.id, + ) + ) + + await self.session._send(message) + class AgentSession: def __init__(self, agent: Agent, websocket: ClientConnection): diff --git a/fishjam/events/_protos/fishjam/__init__.py b/fishjam/events/_protos/fishjam/__init__.py index 518c413..480efa8 100644 --- a/fishjam/events/_protos/fishjam/__init__.py +++ b/fishjam/events/_protos/fishjam/__init__.py @@ -35,6 +35,9 @@ class AgentRequest(betterproto.Message): 3, group="content" ) track_data: "AgentRequestTrackData" = betterproto.message_field(4, group="content") + interrupt_track: "AgentRequestInterruptTrack" = betterproto.message_field( + 5, group="content" + ) @dataclass(eq=False, repr=False) @@ -82,6 +85,16 @@ class AgentRequestTrackData(betterproto.Message): data: bytes = betterproto.bytes_field(2) +@dataclass(eq=False, repr=False) +class AgentRequestInterruptTrack(betterproto.Message): + """ + Interrupts an agent's outgoing track, preventing already queued audio from + being played + """ + + track_id: str = betterproto.string_field(1) + + @dataclass(eq=False, repr=False) class AgentResponse(betterproto.Message): """Defines any type of message passed from Fishjam to agent peer""" diff --git a/protos b/protos index 6aba480..20e4f49 160000 --- a/protos +++ b/protos @@ -1 +1 @@ -Subproject commit 6aba480b5f40ddc9148a433bca8c8e91b6c644ac +Subproject commit 20e4f4903dcb92c4baf79990746bbc1cebda73d7 From 2d00723078bcb725c03b227544db550ffdd59fcf Mon Sep 17 00:00:00 2001 From: Tomasz Mazur <47872060+AHGIJMKLKKZNPJKQR@users.noreply.github.com> Date: Thu, 25 Sep 2025 15:49:41 +0200 Subject: [PATCH 04/16] Update dockerfile --- tests/Dockerfile | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/tests/Dockerfile b/tests/Dockerfile index 61bf34c..9f831c2 100644 --- a/tests/Dockerfile +++ b/tests/Dockerfile @@ -9,15 +9,11 @@ COPY --from=uv-image /uv /uvx /bin/ WORKDIR /app - COPY pyproject.toml . COPY uv.lock . -COPY examples/transcription/pyproject.toml ./examples/transcription/ - -RUN --mount=type=cache,target=/root/.cache/uv \ - uv sync --locked --no-install-project +RUN uv sync --locked --no-install-project COPY . /app -RUN --mount=type=cache,target=/root/.cache/uv \ - uv sync --locked + +RUN uv sync --locked From a4efe9e6f1cd7ae5108ee0172858dd95039f5bc4 Mon Sep 17 00:00:00 2001 From: Tomasz Mazur <47872060+AHGIJMKLKKZNPJKQR@users.noreply.github.com> Date: Thu, 25 Sep 2025 15:54:22 +0200 Subject: [PATCH 05/16] Update dockerfile --- tests/Dockerfile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/Dockerfile b/tests/Dockerfile index 9f831c2..2a03a50 100644 --- a/tests/Dockerfile +++ b/tests/Dockerfile @@ -10,6 +10,10 @@ COPY --from=uv-image /uv /uvx /bin/ WORKDIR /app COPY pyproject.toml . + +COPY examples/transcription/pyproject.toml ./examples/transcription/ +COPY examples/poet_chat/pyproject.toml ./examples/poet_chat/ + COPY uv.lock . RUN uv sync --locked --no-install-project From 8541b3ae01ab7e085c7e1e35fccc2d37c9a5733e Mon Sep 17 00:00:00 2001 From: Tomasz Mazur <47872060+AHGIJMKLKKZNPJKQR@users.noreply.github.com> Date: Thu, 25 Sep 2025 17:23:21 +0200 Subject: [PATCH 06/16] Update openapi --- examples/poet_chat/main.py | 12 +- examples/poet_chat/poet_chat/config.py | 9 +- examples/transcription/main.py | 8 +- fishjam/__init__.py | 4 + .../api/room/subscribe_peer.py | 202 +++++++++++++++++ .../api/room/subscribe_tracks.py | 203 ++++++++++++++++++ .../_openapi_client/api/stream/__init__.py | 1 + .../api/stream/create_stream.py | 172 +++++++++++++++ .../api/stream/delete_stream.py | 159 ++++++++++++++ .../api/stream/get_all_streams.py | 135 ++++++++++++ .../_openapi_client/api/stream/get_stream.py | 165 ++++++++++++++ .../api/streamer/create_streamer.py | 165 ++++++++++++++ .../api/streamer/delete_streamer.py | 173 +++++++++++++++ .../api/streamer/generate_streamer_token.py | 8 +- .../api/viewer/create_viewer.py | 165 ++++++++++++++ .../api/viewer/delete_viewer.py | 173 +++++++++++++++ .../api/viewer/generate_viewer_token.py | 8 +- fishjam/_openapi_client/models/__init__.py | 46 ++-- fishjam/_openapi_client/models/peer.py | 44 ++-- .../models/peer_options_agent.py | 60 +++++- .../models/peer_options_agent_output.py | 101 +++++++++ ...peer_options_agent_output_audio_format.py} | 2 +- ...options_agent_output_audio_sample_rate.py} | 2 +- .../peer_options_agent_subscribe_mode.py | 11 + .../models/peer_options_web_rtc.py | 60 ++---- .../peer_options_web_rtc_subscribe_mode.py | 11 + .../peer_options_web_rtc_subscribe_options.py | 87 -------- ..._web_rtc_subscribe_options_audio_format.py | 10 - ...rtc_subscribe_options_audio_sample_rate.py | 9 - fishjam/_openapi_client/models/stream.py | 124 +++++++++++ .../_openapi_client/models/stream_config.py | 86 ++++++++ fishjam/_openapi_client/models/streamer.py | 88 ++++++++ .../_openapi_client/models/streamer_status.py | 11 + .../models/streams_listing_response.py | 78 +++++++ .../_openapi_client/models/subscribe_mode.py | 11 + .../models/subscribe_options.py | 79 ------- .../models/subscribe_tracks_body.py | 63 ++++++ fishjam/_openapi_client/models/track.py | 4 +- fishjam/_openapi_client/models/viewer.py | 88 ++++++++ .../_openapi_client/models/viewer_status.py | 11 + fishjam/agent/__init__.py | 4 +- fishjam/agent/agent.py | 8 +- fishjam/api/_fishjam_client.py | 51 +++-- fishjam/peer/__init__.py | 6 - 44 files changed, 2584 insertions(+), 333 deletions(-) create mode 100644 fishjam/_openapi_client/api/room/subscribe_peer.py create mode 100644 fishjam/_openapi_client/api/room/subscribe_tracks.py create mode 100644 fishjam/_openapi_client/api/stream/__init__.py create mode 100644 fishjam/_openapi_client/api/stream/create_stream.py create mode 100644 fishjam/_openapi_client/api/stream/delete_stream.py create mode 100644 fishjam/_openapi_client/api/stream/get_all_streams.py create mode 100644 fishjam/_openapi_client/api/stream/get_stream.py create mode 100644 fishjam/_openapi_client/api/streamer/create_streamer.py create mode 100644 fishjam/_openapi_client/api/streamer/delete_streamer.py create mode 100644 fishjam/_openapi_client/api/viewer/create_viewer.py create mode 100644 fishjam/_openapi_client/api/viewer/delete_viewer.py create mode 100644 fishjam/_openapi_client/models/peer_options_agent_output.py rename fishjam/_openapi_client/models/{subscribe_options_audio_format.py => peer_options_agent_output_audio_format.py} (74%) rename fishjam/_openapi_client/models/{subscribe_options_audio_sample_rate.py => peer_options_agent_output_audio_sample_rate.py} (71%) create mode 100644 fishjam/_openapi_client/models/peer_options_agent_subscribe_mode.py create mode 100644 fishjam/_openapi_client/models/peer_options_web_rtc_subscribe_mode.py delete mode 100644 fishjam/_openapi_client/models/peer_options_web_rtc_subscribe_options.py delete mode 100644 fishjam/_openapi_client/models/peer_options_web_rtc_subscribe_options_audio_format.py delete mode 100644 fishjam/_openapi_client/models/peer_options_web_rtc_subscribe_options_audio_sample_rate.py create mode 100644 fishjam/_openapi_client/models/stream.py create mode 100644 fishjam/_openapi_client/models/stream_config.py create mode 100644 fishjam/_openapi_client/models/streamer.py create mode 100644 fishjam/_openapi_client/models/streamer_status.py create mode 100644 fishjam/_openapi_client/models/streams_listing_response.py create mode 100644 fishjam/_openapi_client/models/subscribe_mode.py delete mode 100644 fishjam/_openapi_client/models/subscribe_options.py create mode 100644 fishjam/_openapi_client/models/subscribe_tracks_body.py create mode 100644 fishjam/_openapi_client/models/viewer.py create mode 100644 fishjam/_openapi_client/models/viewer_status.py diff --git a/examples/poet_chat/main.py b/examples/poet_chat/main.py index 8b3a8f1..84e879d 100644 --- a/examples/poet_chat/main.py +++ b/examples/poet_chat/main.py @@ -2,26 +2,28 @@ from poet_chat.agent import poet_runner from poet_chat.config import ( - PEER_OPTIONS, + AGENT_OPTIONS, fishjam_client, ) from poet_chat.notifier import make_notifier -from fishjam.agent import AudioTrackOptions +from fishjam.agent import OutgoingAudioTrackOptions async def main(): room = fishjam_client.create_room() - _, token = fishjam_client.create_peer(room.id, PEER_OPTIONS) + _, token = fishjam_client.create_peer(room.id) print(f"Join the chat with the following token: {token}") - agent = fishjam_client.create_agent(room.id) + agent = fishjam_client.create_agent(room.id, AGENT_OPTIONS) async with ( agent.connect() as fishjam_session, await poet_runner.run() as openai_session, ): track = await fishjam_session.add_track( - AudioTrackOptions(sample_rate=24000, metadata={"type": "microphone"}) + OutgoingAudioTrackOptions( + sample_rate=24000, metadata={"type": "microphone"} + ) ) async def _openai_recv(): diff --git a/examples/poet_chat/poet_chat/config.py b/examples/poet_chat/poet_chat/config.py index 107a47b..1fb5a7b 100644 --- a/examples/poet_chat/poet_chat/config.py +++ b/examples/poet_chat/poet_chat/config.py @@ -1,18 +1,13 @@ import os from pathlib import Path -from fishjam import FishjamClient, PeerOptions -from fishjam.peer import SubscribeOptions, SubscribeOptionsAudioSampleRate +from fishjam import AgentOptions, AgentOutputOptions, FishjamClient FISHJAM_ID = os.environ["FISHJAM_ID"] FISHJAM_TOKEN = os.environ["FISHJAM_MANAGEMENT_TOKEN"] FISHJAM_URL = os.getenv("FISHJAM_URL") -PEER_OPTIONS = PeerOptions( - subscribe=SubscribeOptions( - audio_sample_rate=SubscribeOptionsAudioSampleRate.VALUE_24000 - ) -) +AGENT_OPTIONS = AgentOptions(output=AgentOutputOptions(audio_sample_rate=24000)) OPENAI_MODEL = "gpt-realtime" diff --git a/examples/transcription/main.py b/examples/transcription/main.py index 7a7e374..49f5f76 100644 --- a/examples/transcription/main.py +++ b/examples/transcription/main.py @@ -6,9 +6,6 @@ from transcription.room import RoomService, fishjam from transcription.worker import async_worker -from fishjam import PeerOptions -from fishjam.peer import SubscribeOptions - _room_service: RoomService | None = None @@ -34,8 +31,5 @@ async def lifespan(_app: FastAPI): @app.get("/") def get_peer(room_service: Annotated[RoomService, Depends(get_room_service)]): - _peer, token = fishjam.create_peer( - room_service.get_room().id, - PeerOptions(subscribe=SubscribeOptions()), - ) + _peer, token = fishjam.create_peer(room_service.get_room().id) return token diff --git a/fishjam/__init__.py b/fishjam/__init__.py index c597338..02ba691 100644 --- a/fishjam/__init__.py +++ b/fishjam/__init__.py @@ -17,6 +17,8 @@ from fishjam._webhook_notifier import receive_binary from fishjam._ws_notifier import FishjamNotifier from fishjam.api._fishjam_client import ( + AgentOptions, + AgentOutputOptions, FishjamClient, Peer, PeerOptions, @@ -31,6 +33,8 @@ "PeerMetadata", "PeerOptions", "RoomOptions", + "AgentOptions", + "AgentOutputOptions", "Room", "Peer", "events", diff --git a/fishjam/_openapi_client/api/room/subscribe_peer.py b/fishjam/_openapi_client/api/room/subscribe_peer.py new file mode 100644 index 0000000..cfac6e8 --- /dev/null +++ b/fishjam/_openapi_client/api/room/subscribe_peer.py @@ -0,0 +1,202 @@ +from http import HTTPStatus +from typing import Any, Optional, Union, cast + +import httpx + +from ... import errors +from ...client import AuthenticatedClient, Client +from ...models.error import Error +from ...types import UNSET, Response, Unset + + +def _get_kwargs( + room_id: str, + id: str, + *, + peer_id: Union[Unset, str] = UNSET, +) -> dict[str, Any]: + params: dict[str, Any] = {} + + params["peer_id"] = peer_id + + params = {k: v for k, v in params.items() if v is not UNSET and v is not None} + + _kwargs: dict[str, Any] = { + "method": "post", + "url": "/room/{room_id}/peer/{id}/subscribe_peer".format( + room_id=room_id, + id=id, + ), + "params": params, + } + + return _kwargs + + +def _parse_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Optional[Union[Any, Error]]: + if response.status_code == 200: + response_200 = cast(Any, None) + return response_200 + if response.status_code == 400: + response_400 = Error.from_dict(response.json()) + + return response_400 + if response.status_code == 401: + response_401 = Error.from_dict(response.json()) + + return response_401 + if response.status_code == 404: + response_404 = Error.from_dict(response.json()) + + return response_404 + if response.status_code == 503: + response_503 = Error.from_dict(response.json()) + + return response_503 + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Response[Union[Any, Error]]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + room_id: str, + id: str, + *, + client: AuthenticatedClient, + peer_id: Union[Unset, str] = UNSET, +) -> Response[Union[Any, Error]]: + """Subscribe peer to another peer's tracks + + Args: + room_id (str): + id (str): + peer_id (Union[Unset, str]): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Any, Error]] + """ + + kwargs = _get_kwargs( + room_id=room_id, + id=id, + peer_id=peer_id, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + room_id: str, + id: str, + *, + client: AuthenticatedClient, + peer_id: Union[Unset, str] = UNSET, +) -> Optional[Union[Any, Error]]: + """Subscribe peer to another peer's tracks + + Args: + room_id (str): + id (str): + peer_id (Union[Unset, str]): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Any, Error] + """ + + return sync_detailed( + room_id=room_id, + id=id, + client=client, + peer_id=peer_id, + ).parsed + + +async def asyncio_detailed( + room_id: str, + id: str, + *, + client: AuthenticatedClient, + peer_id: Union[Unset, str] = UNSET, +) -> Response[Union[Any, Error]]: + """Subscribe peer to another peer's tracks + + Args: + room_id (str): + id (str): + peer_id (Union[Unset, str]): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Any, Error]] + """ + + kwargs = _get_kwargs( + room_id=room_id, + id=id, + peer_id=peer_id, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + room_id: str, + id: str, + *, + client: AuthenticatedClient, + peer_id: Union[Unset, str] = UNSET, +) -> Optional[Union[Any, Error]]: + """Subscribe peer to another peer's tracks + + Args: + room_id (str): + id (str): + peer_id (Union[Unset, str]): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Any, Error] + """ + + return ( + await asyncio_detailed( + room_id=room_id, + id=id, + client=client, + peer_id=peer_id, + ) + ).parsed diff --git a/fishjam/_openapi_client/api/room/subscribe_tracks.py b/fishjam/_openapi_client/api/room/subscribe_tracks.py new file mode 100644 index 0000000..413bb14 --- /dev/null +++ b/fishjam/_openapi_client/api/room/subscribe_tracks.py @@ -0,0 +1,203 @@ +from http import HTTPStatus +from typing import Any, Optional, Union, cast + +import httpx + +from ... import errors +from ...client import AuthenticatedClient, Client +from ...models.error import Error +from ...models.subscribe_tracks_body import SubscribeTracksBody +from ...types import Response + + +def _get_kwargs( + room_id: str, + id: str, + *, + body: SubscribeTracksBody, +) -> dict[str, Any]: + headers: dict[str, Any] = {} + + _kwargs: dict[str, Any] = { + "method": "post", + "url": "/room/{room_id}/peer/{id}/subscribe_tracks".format( + room_id=room_id, + id=id, + ), + } + + _kwargs["json"] = body.to_dict() + + headers["Content-Type"] = "application/json" + + _kwargs["headers"] = headers + return _kwargs + + +def _parse_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Optional[Union[Any, Error]]: + if response.status_code == 200: + response_200 = cast(Any, None) + return response_200 + if response.status_code == 400: + response_400 = Error.from_dict(response.json()) + + return response_400 + if response.status_code == 401: + response_401 = Error.from_dict(response.json()) + + return response_401 + if response.status_code == 404: + response_404 = Error.from_dict(response.json()) + + return response_404 + if response.status_code == 503: + response_503 = Error.from_dict(response.json()) + + return response_503 + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Response[Union[Any, Error]]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + room_id: str, + id: str, + *, + client: AuthenticatedClient, + body: SubscribeTracksBody, +) -> Response[Union[Any, Error]]: + """Subscribe peer to specific tracks + + Args: + room_id (str): + id (str): + body (SubscribeTracksBody): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Any, Error]] + """ + + kwargs = _get_kwargs( + room_id=room_id, + id=id, + body=body, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + room_id: str, + id: str, + *, + client: AuthenticatedClient, + body: SubscribeTracksBody, +) -> Optional[Union[Any, Error]]: + """Subscribe peer to specific tracks + + Args: + room_id (str): + id (str): + body (SubscribeTracksBody): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Any, Error] + """ + + return sync_detailed( + room_id=room_id, + id=id, + client=client, + body=body, + ).parsed + + +async def asyncio_detailed( + room_id: str, + id: str, + *, + client: AuthenticatedClient, + body: SubscribeTracksBody, +) -> Response[Union[Any, Error]]: + """Subscribe peer to specific tracks + + Args: + room_id (str): + id (str): + body (SubscribeTracksBody): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Any, Error]] + """ + + kwargs = _get_kwargs( + room_id=room_id, + id=id, + body=body, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + room_id: str, + id: str, + *, + client: AuthenticatedClient, + body: SubscribeTracksBody, +) -> Optional[Union[Any, Error]]: + """Subscribe peer to specific tracks + + Args: + room_id (str): + id (str): + body (SubscribeTracksBody): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Any, Error] + """ + + return ( + await asyncio_detailed( + room_id=room_id, + id=id, + client=client, + body=body, + ) + ).parsed diff --git a/fishjam/_openapi_client/api/stream/__init__.py b/fishjam/_openapi_client/api/stream/__init__.py new file mode 100644 index 0000000..c9921b5 --- /dev/null +++ b/fishjam/_openapi_client/api/stream/__init__.py @@ -0,0 +1 @@ +""" Contains endpoint functions for accessing the API """ diff --git a/fishjam/_openapi_client/api/stream/create_stream.py b/fishjam/_openapi_client/api/stream/create_stream.py new file mode 100644 index 0000000..6dc8015 --- /dev/null +++ b/fishjam/_openapi_client/api/stream/create_stream.py @@ -0,0 +1,172 @@ +from http import HTTPStatus +from typing import Any, Optional, Union + +import httpx + +from ... import errors +from ...client import AuthenticatedClient, Client +from ...models.error import Error +from ...models.stream import Stream +from ...models.stream_config import StreamConfig +from ...types import Response + + +def _get_kwargs( + *, + body: StreamConfig, +) -> dict[str, Any]: + headers: dict[str, Any] = {} + + _kwargs: dict[str, Any] = { + "method": "post", + "url": "/livestream", + } + + _kwargs["json"] = body.to_dict() + + headers["Content-Type"] = "application/json" + + _kwargs["headers"] = headers + return _kwargs + + +def _parse_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Optional[Union[Error, Stream]]: + if response.status_code == 201: + response_201 = Stream.from_dict(response.json()) + + return response_201 + if response.status_code == 400: + response_400 = Error.from_dict(response.json()) + + return response_400 + if response.status_code == 401: + response_401 = Error.from_dict(response.json()) + + return response_401 + if response.status_code == 503: + response_503 = Error.from_dict(response.json()) + + return response_503 + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Response[Union[Error, Stream]]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + *, + client: AuthenticatedClient, + body: StreamConfig, +) -> Response[Union[Error, Stream]]: + """Creates stream + + Args: + body (StreamConfig): Stream configuration + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Error, Stream]] + """ + + kwargs = _get_kwargs( + body=body, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + *, + client: AuthenticatedClient, + body: StreamConfig, +) -> Optional[Union[Error, Stream]]: + """Creates stream + + Args: + body (StreamConfig): Stream configuration + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Error, Stream] + """ + + return sync_detailed( + client=client, + body=body, + ).parsed + + +async def asyncio_detailed( + *, + client: AuthenticatedClient, + body: StreamConfig, +) -> Response[Union[Error, Stream]]: + """Creates stream + + Args: + body (StreamConfig): Stream configuration + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Error, Stream]] + """ + + kwargs = _get_kwargs( + body=body, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + *, + client: AuthenticatedClient, + body: StreamConfig, +) -> Optional[Union[Error, Stream]]: + """Creates stream + + Args: + body (StreamConfig): Stream configuration + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Error, Stream] + """ + + return ( + await asyncio_detailed( + client=client, + body=body, + ) + ).parsed diff --git a/fishjam/_openapi_client/api/stream/delete_stream.py b/fishjam/_openapi_client/api/stream/delete_stream.py new file mode 100644 index 0000000..af2ee1d --- /dev/null +++ b/fishjam/_openapi_client/api/stream/delete_stream.py @@ -0,0 +1,159 @@ +from http import HTTPStatus +from typing import Any, Optional, Union, cast + +import httpx + +from ... import errors +from ...client import AuthenticatedClient, Client +from ...models.error import Error +from ...types import Response + + +def _get_kwargs( + stream_id: str, +) -> dict[str, Any]: + _kwargs: dict[str, Any] = { + "method": "delete", + "url": "/livestream/{stream_id}".format( + stream_id=stream_id, + ), + } + + return _kwargs + + +def _parse_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Optional[Union[Any, Error]]: + if response.status_code == 204: + response_204 = cast(Any, None) + return response_204 + if response.status_code == 401: + response_401 = Error.from_dict(response.json()) + + return response_401 + if response.status_code == 503: + response_503 = Error.from_dict(response.json()) + + return response_503 + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Response[Union[Any, Error]]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + stream_id: str, + *, + client: AuthenticatedClient, +) -> Response[Union[Any, Error]]: + """Deletes stream + + Args: + stream_id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Any, Error]] + """ + + kwargs = _get_kwargs( + stream_id=stream_id, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + stream_id: str, + *, + client: AuthenticatedClient, +) -> Optional[Union[Any, Error]]: + """Deletes stream + + Args: + stream_id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Any, Error] + """ + + return sync_detailed( + stream_id=stream_id, + client=client, + ).parsed + + +async def asyncio_detailed( + stream_id: str, + *, + client: AuthenticatedClient, +) -> Response[Union[Any, Error]]: + """Deletes stream + + Args: + stream_id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Any, Error]] + """ + + kwargs = _get_kwargs( + stream_id=stream_id, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + stream_id: str, + *, + client: AuthenticatedClient, +) -> Optional[Union[Any, Error]]: + """Deletes stream + + Args: + stream_id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Any, Error] + """ + + return ( + await asyncio_detailed( + stream_id=stream_id, + client=client, + ) + ).parsed diff --git a/fishjam/_openapi_client/api/stream/get_all_streams.py b/fishjam/_openapi_client/api/stream/get_all_streams.py new file mode 100644 index 0000000..db97398 --- /dev/null +++ b/fishjam/_openapi_client/api/stream/get_all_streams.py @@ -0,0 +1,135 @@ +from http import HTTPStatus +from typing import Any, Optional, Union + +import httpx + +from ... import errors +from ...client import AuthenticatedClient, Client +from ...models.error import Error +from ...models.streams_listing_response import StreamsListingResponse +from ...types import Response + + +def _get_kwargs() -> dict[str, Any]: + _kwargs: dict[str, Any] = { + "method": "get", + "url": "/livestream", + } + + return _kwargs + + +def _parse_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Optional[Union[Error, StreamsListingResponse]]: + if response.status_code == 200: + response_200 = StreamsListingResponse.from_dict(response.json()) + + return response_200 + if response.status_code == 401: + response_401 = Error.from_dict(response.json()) + + return response_401 + if response.status_code == 503: + response_503 = Error.from_dict(response.json()) + + return response_503 + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Response[Union[Error, StreamsListingResponse]]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + *, + client: AuthenticatedClient, +) -> Response[Union[Error, StreamsListingResponse]]: + """Show information about all streams + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Error, StreamsListingResponse]] + """ + + kwargs = _get_kwargs() + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + *, + client: AuthenticatedClient, +) -> Optional[Union[Error, StreamsListingResponse]]: + """Show information about all streams + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Error, StreamsListingResponse] + """ + + return sync_detailed( + client=client, + ).parsed + + +async def asyncio_detailed( + *, + client: AuthenticatedClient, +) -> Response[Union[Error, StreamsListingResponse]]: + """Show information about all streams + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Error, StreamsListingResponse]] + """ + + kwargs = _get_kwargs() + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + *, + client: AuthenticatedClient, +) -> Optional[Union[Error, StreamsListingResponse]]: + """Show information about all streams + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Error, StreamsListingResponse] + """ + + return ( + await asyncio_detailed( + client=client, + ) + ).parsed diff --git a/fishjam/_openapi_client/api/stream/get_stream.py b/fishjam/_openapi_client/api/stream/get_stream.py new file mode 100644 index 0000000..92244b5 --- /dev/null +++ b/fishjam/_openapi_client/api/stream/get_stream.py @@ -0,0 +1,165 @@ +from http import HTTPStatus +from typing import Any, Optional, Union + +import httpx + +from ... import errors +from ...client import AuthenticatedClient, Client +from ...models.error import Error +from ...models.stream import Stream +from ...types import Response + + +def _get_kwargs( + stream_id: str, +) -> dict[str, Any]: + _kwargs: dict[str, Any] = { + "method": "get", + "url": "/livestream/{stream_id}".format( + stream_id=stream_id, + ), + } + + return _kwargs + + +def _parse_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Optional[Union[Error, Stream]]: + if response.status_code == 200: + response_200 = Stream.from_dict(response.json()) + + return response_200 + if response.status_code == 401: + response_401 = Error.from_dict(response.json()) + + return response_401 + if response.status_code == 404: + response_404 = Error.from_dict(response.json()) + + return response_404 + if response.status_code == 503: + response_503 = Error.from_dict(response.json()) + + return response_503 + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Response[Union[Error, Stream]]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + stream_id: str, + *, + client: AuthenticatedClient, +) -> Response[Union[Error, Stream]]: + """Shows information about the stream + + Args: + stream_id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Error, Stream]] + """ + + kwargs = _get_kwargs( + stream_id=stream_id, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + stream_id: str, + *, + client: AuthenticatedClient, +) -> Optional[Union[Error, Stream]]: + """Shows information about the stream + + Args: + stream_id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Error, Stream] + """ + + return sync_detailed( + stream_id=stream_id, + client=client, + ).parsed + + +async def asyncio_detailed( + stream_id: str, + *, + client: AuthenticatedClient, +) -> Response[Union[Error, Stream]]: + """Shows information about the stream + + Args: + stream_id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Error, Stream]] + """ + + kwargs = _get_kwargs( + stream_id=stream_id, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + stream_id: str, + *, + client: AuthenticatedClient, +) -> Optional[Union[Error, Stream]]: + """Shows information about the stream + + Args: + stream_id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Error, Stream] + """ + + return ( + await asyncio_detailed( + stream_id=stream_id, + client=client, + ) + ).parsed diff --git a/fishjam/_openapi_client/api/streamer/create_streamer.py b/fishjam/_openapi_client/api/streamer/create_streamer.py new file mode 100644 index 0000000..a0be94a --- /dev/null +++ b/fishjam/_openapi_client/api/streamer/create_streamer.py @@ -0,0 +1,165 @@ +from http import HTTPStatus +from typing import Any, Optional, Union + +import httpx + +from ... import errors +from ...client import AuthenticatedClient, Client +from ...models.error import Error +from ...models.streamer import Streamer +from ...types import Response + + +def _get_kwargs( + stream_id: str, +) -> dict[str, Any]: + _kwargs: dict[str, Any] = { + "method": "post", + "url": "/livestream/{stream_id}/streamer".format( + stream_id=stream_id, + ), + } + + return _kwargs + + +def _parse_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Optional[Union[Error, Streamer]]: + if response.status_code == 201: + response_201 = Streamer.from_dict(response.json()) + + return response_201 + if response.status_code == 401: + response_401 = Error.from_dict(response.json()) + + return response_401 + if response.status_code == 404: + response_404 = Error.from_dict(response.json()) + + return response_404 + if response.status_code == 503: + response_503 = Error.from_dict(response.json()) + + return response_503 + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Response[Union[Error, Streamer]]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + stream_id: str, + *, + client: AuthenticatedClient, +) -> Response[Union[Error, Streamer]]: + """Creates streamer + + Args: + stream_id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Error, Streamer]] + """ + + kwargs = _get_kwargs( + stream_id=stream_id, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + stream_id: str, + *, + client: AuthenticatedClient, +) -> Optional[Union[Error, Streamer]]: + """Creates streamer + + Args: + stream_id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Error, Streamer] + """ + + return sync_detailed( + stream_id=stream_id, + client=client, + ).parsed + + +async def asyncio_detailed( + stream_id: str, + *, + client: AuthenticatedClient, +) -> Response[Union[Error, Streamer]]: + """Creates streamer + + Args: + stream_id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Error, Streamer]] + """ + + kwargs = _get_kwargs( + stream_id=stream_id, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + stream_id: str, + *, + client: AuthenticatedClient, +) -> Optional[Union[Error, Streamer]]: + """Creates streamer + + Args: + stream_id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Error, Streamer] + """ + + return ( + await asyncio_detailed( + stream_id=stream_id, + client=client, + ) + ).parsed diff --git a/fishjam/_openapi_client/api/streamer/delete_streamer.py b/fishjam/_openapi_client/api/streamer/delete_streamer.py new file mode 100644 index 0000000..dd38830 --- /dev/null +++ b/fishjam/_openapi_client/api/streamer/delete_streamer.py @@ -0,0 +1,173 @@ +from http import HTTPStatus +from typing import Any, Optional, Union, cast + +import httpx + +from ... import errors +from ...client import AuthenticatedClient, Client +from ...models.error import Error +from ...types import Response + + +def _get_kwargs( + stream_id: str, + streamer_id: str, +) -> dict[str, Any]: + _kwargs: dict[str, Any] = { + "method": "delete", + "url": "/livestream/{stream_id}/streamer/{streamer_id}".format( + stream_id=stream_id, + streamer_id=streamer_id, + ), + } + + return _kwargs + + +def _parse_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Optional[Union[Any, Error]]: + if response.status_code == 204: + response_204 = cast(Any, None) + return response_204 + if response.status_code == 401: + response_401 = Error.from_dict(response.json()) + + return response_401 + if response.status_code == 503: + response_503 = Error.from_dict(response.json()) + + return response_503 + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Response[Union[Any, Error]]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + stream_id: str, + streamer_id: str, + *, + client: AuthenticatedClient, +) -> Response[Union[Any, Error]]: + """Deletes streamer + + Args: + stream_id (str): + streamer_id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Any, Error]] + """ + + kwargs = _get_kwargs( + stream_id=stream_id, + streamer_id=streamer_id, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + stream_id: str, + streamer_id: str, + *, + client: AuthenticatedClient, +) -> Optional[Union[Any, Error]]: + """Deletes streamer + + Args: + stream_id (str): + streamer_id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Any, Error] + """ + + return sync_detailed( + stream_id=stream_id, + streamer_id=streamer_id, + client=client, + ).parsed + + +async def asyncio_detailed( + stream_id: str, + streamer_id: str, + *, + client: AuthenticatedClient, +) -> Response[Union[Any, Error]]: + """Deletes streamer + + Args: + stream_id (str): + streamer_id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Any, Error]] + """ + + kwargs = _get_kwargs( + stream_id=stream_id, + streamer_id=streamer_id, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + stream_id: str, + streamer_id: str, + *, + client: AuthenticatedClient, +) -> Optional[Union[Any, Error]]: + """Deletes streamer + + Args: + stream_id (str): + streamer_id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Any, Error] + """ + + return ( + await asyncio_detailed( + stream_id=stream_id, + streamer_id=streamer_id, + client=client, + ) + ).parsed diff --git a/fishjam/_openapi_client/api/streamer/generate_streamer_token.py b/fishjam/_openapi_client/api/streamer/generate_streamer_token.py index d1092fb..53f12e0 100644 --- a/fishjam/_openapi_client/api/streamer/generate_streamer_token.py +++ b/fishjam/_openapi_client/api/streamer/generate_streamer_token.py @@ -66,7 +66,7 @@ def _build_response( def sync_detailed( room_id: str, *, - client: Union[AuthenticatedClient, Client], + client: AuthenticatedClient, ) -> Response[Union[Error, StreamerToken]]: """Generate a token that can be used by a streamer to start streaming @@ -95,7 +95,7 @@ def sync_detailed( def sync( room_id: str, *, - client: Union[AuthenticatedClient, Client], + client: AuthenticatedClient, ) -> Optional[Union[Error, StreamerToken]]: """Generate a token that can be used by a streamer to start streaming @@ -119,7 +119,7 @@ def sync( async def asyncio_detailed( room_id: str, *, - client: Union[AuthenticatedClient, Client], + client: AuthenticatedClient, ) -> Response[Union[Error, StreamerToken]]: """Generate a token that can be used by a streamer to start streaming @@ -146,7 +146,7 @@ async def asyncio_detailed( async def asyncio( room_id: str, *, - client: Union[AuthenticatedClient, Client], + client: AuthenticatedClient, ) -> Optional[Union[Error, StreamerToken]]: """Generate a token that can be used by a streamer to start streaming diff --git a/fishjam/_openapi_client/api/viewer/create_viewer.py b/fishjam/_openapi_client/api/viewer/create_viewer.py new file mode 100644 index 0000000..d19484e --- /dev/null +++ b/fishjam/_openapi_client/api/viewer/create_viewer.py @@ -0,0 +1,165 @@ +from http import HTTPStatus +from typing import Any, Optional, Union + +import httpx + +from ... import errors +from ...client import AuthenticatedClient, Client +from ...models.error import Error +from ...models.viewer import Viewer +from ...types import Response + + +def _get_kwargs( + stream_id: str, +) -> dict[str, Any]: + _kwargs: dict[str, Any] = { + "method": "post", + "url": "/livestream/{stream_id}/viewer".format( + stream_id=stream_id, + ), + } + + return _kwargs + + +def _parse_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Optional[Union[Error, Viewer]]: + if response.status_code == 201: + response_201 = Viewer.from_dict(response.json()) + + return response_201 + if response.status_code == 401: + response_401 = Error.from_dict(response.json()) + + return response_401 + if response.status_code == 404: + response_404 = Error.from_dict(response.json()) + + return response_404 + if response.status_code == 503: + response_503 = Error.from_dict(response.json()) + + return response_503 + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Response[Union[Error, Viewer]]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + stream_id: str, + *, + client: AuthenticatedClient, +) -> Response[Union[Error, Viewer]]: + """Creates viewer + + Args: + stream_id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Error, Viewer]] + """ + + kwargs = _get_kwargs( + stream_id=stream_id, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + stream_id: str, + *, + client: AuthenticatedClient, +) -> Optional[Union[Error, Viewer]]: + """Creates viewer + + Args: + stream_id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Error, Viewer] + """ + + return sync_detailed( + stream_id=stream_id, + client=client, + ).parsed + + +async def asyncio_detailed( + stream_id: str, + *, + client: AuthenticatedClient, +) -> Response[Union[Error, Viewer]]: + """Creates viewer + + Args: + stream_id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Error, Viewer]] + """ + + kwargs = _get_kwargs( + stream_id=stream_id, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + stream_id: str, + *, + client: AuthenticatedClient, +) -> Optional[Union[Error, Viewer]]: + """Creates viewer + + Args: + stream_id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Error, Viewer] + """ + + return ( + await asyncio_detailed( + stream_id=stream_id, + client=client, + ) + ).parsed diff --git a/fishjam/_openapi_client/api/viewer/delete_viewer.py b/fishjam/_openapi_client/api/viewer/delete_viewer.py new file mode 100644 index 0000000..82f577c --- /dev/null +++ b/fishjam/_openapi_client/api/viewer/delete_viewer.py @@ -0,0 +1,173 @@ +from http import HTTPStatus +from typing import Any, Optional, Union, cast + +import httpx + +from ... import errors +from ...client import AuthenticatedClient, Client +from ...models.error import Error +from ...types import Response + + +def _get_kwargs( + stream_id: str, + viewer_id: str, +) -> dict[str, Any]: + _kwargs: dict[str, Any] = { + "method": "delete", + "url": "/livestream/{stream_id}/viewer/{viewer_id}".format( + stream_id=stream_id, + viewer_id=viewer_id, + ), + } + + return _kwargs + + +def _parse_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Optional[Union[Any, Error]]: + if response.status_code == 204: + response_204 = cast(Any, None) + return response_204 + if response.status_code == 401: + response_401 = Error.from_dict(response.json()) + + return response_401 + if response.status_code == 503: + response_503 = Error.from_dict(response.json()) + + return response_503 + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response( + *, client: Union[AuthenticatedClient, Client], response: httpx.Response +) -> Response[Union[Any, Error]]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + stream_id: str, + viewer_id: str, + *, + client: AuthenticatedClient, +) -> Response[Union[Any, Error]]: + """Deletes viewer + + Args: + stream_id (str): + viewer_id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Any, Error]] + """ + + kwargs = _get_kwargs( + stream_id=stream_id, + viewer_id=viewer_id, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + stream_id: str, + viewer_id: str, + *, + client: AuthenticatedClient, +) -> Optional[Union[Any, Error]]: + """Deletes viewer + + Args: + stream_id (str): + viewer_id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Any, Error] + """ + + return sync_detailed( + stream_id=stream_id, + viewer_id=viewer_id, + client=client, + ).parsed + + +async def asyncio_detailed( + stream_id: str, + viewer_id: str, + *, + client: AuthenticatedClient, +) -> Response[Union[Any, Error]]: + """Deletes viewer + + Args: + stream_id (str): + viewer_id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Union[Any, Error]] + """ + + kwargs = _get_kwargs( + stream_id=stream_id, + viewer_id=viewer_id, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + stream_id: str, + viewer_id: str, + *, + client: AuthenticatedClient, +) -> Optional[Union[Any, Error]]: + """Deletes viewer + + Args: + stream_id (str): + viewer_id (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Union[Any, Error] + """ + + return ( + await asyncio_detailed( + stream_id=stream_id, + viewer_id=viewer_id, + client=client, + ) + ).parsed diff --git a/fishjam/_openapi_client/api/viewer/generate_viewer_token.py b/fishjam/_openapi_client/api/viewer/generate_viewer_token.py index f2fe5c1..5e45f08 100644 --- a/fishjam/_openapi_client/api/viewer/generate_viewer_token.py +++ b/fishjam/_openapi_client/api/viewer/generate_viewer_token.py @@ -66,7 +66,7 @@ def _build_response( def sync_detailed( room_id: str, *, - client: Union[AuthenticatedClient, Client], + client: AuthenticatedClient, ) -> Response[Union[Error, ViewerToken]]: """Generates token that a viewer can use to watch a livestream @@ -95,7 +95,7 @@ def sync_detailed( def sync( room_id: str, *, - client: Union[AuthenticatedClient, Client], + client: AuthenticatedClient, ) -> Optional[Union[Error, ViewerToken]]: """Generates token that a viewer can use to watch a livestream @@ -119,7 +119,7 @@ def sync( async def asyncio_detailed( room_id: str, *, - client: Union[AuthenticatedClient, Client], + client: AuthenticatedClient, ) -> Response[Union[Error, ViewerToken]]: """Generates token that a viewer can use to watch a livestream @@ -146,7 +146,7 @@ async def asyncio_detailed( async def asyncio( room_id: str, *, - client: Union[AuthenticatedClient, Client], + client: AuthenticatedClient, ) -> Optional[Union[Error, ViewerToken]]: """Generates token that a viewer can use to watch a livestream diff --git a/fishjam/_openapi_client/models/__init__.py b/fishjam/_openapi_client/models/__init__.py index 0a60927..4261daf 100644 --- a/fishjam/_openapi_client/models/__init__.py +++ b/fishjam/_openapi_client/models/__init__.py @@ -7,15 +7,15 @@ from .peer_details_response_data import PeerDetailsResponseData from .peer_metadata import PeerMetadata from .peer_options_agent import PeerOptionsAgent +from .peer_options_agent_output import PeerOptionsAgentOutput +from .peer_options_agent_output_audio_format import PeerOptionsAgentOutputAudioFormat +from .peer_options_agent_output_audio_sample_rate import ( + PeerOptionsAgentOutputAudioSampleRate, +) +from .peer_options_agent_subscribe_mode import PeerOptionsAgentSubscribeMode from .peer_options_web_rtc import PeerOptionsWebRTC from .peer_options_web_rtc_metadata import PeerOptionsWebRTCMetadata -from .peer_options_web_rtc_subscribe_options import PeerOptionsWebRTCSubscribeOptions -from .peer_options_web_rtc_subscribe_options_audio_format import ( - PeerOptionsWebRTCSubscribeOptionsAudioFormat, -) -from .peer_options_web_rtc_subscribe_options_audio_sample_rate import ( - PeerOptionsWebRTCSubscribeOptionsAudioSampleRate, -) +from .peer_options_web_rtc_subscribe_mode import PeerOptionsWebRTCSubscribeMode from .peer_refresh_token_response import PeerRefreshTokenResponse from .peer_refresh_token_response_data import PeerRefreshTokenResponseData from .peer_status import PeerStatus @@ -28,13 +28,19 @@ from .room_create_details_response_data import RoomCreateDetailsResponseData from .room_details_response import RoomDetailsResponse from .rooms_listing_response import RoomsListingResponse +from .stream import Stream +from .stream_config import StreamConfig +from .streamer import Streamer +from .streamer_status import StreamerStatus from .streamer_token import StreamerToken -from .subscribe_options import SubscribeOptions -from .subscribe_options_audio_format import SubscribeOptionsAudioFormat -from .subscribe_options_audio_sample_rate import SubscribeOptionsAudioSampleRate +from .streams_listing_response import StreamsListingResponse +from .subscribe_mode import SubscribeMode +from .subscribe_tracks_body import SubscribeTracksBody from .track import Track from .track_metadata_type_0 import TrackMetadataType0 from .track_type import TrackType +from .viewer import Viewer +from .viewer_status import ViewerStatus from .viewer_token import ViewerToken __all__ = ( @@ -45,11 +51,13 @@ "PeerDetailsResponseData", "PeerMetadata", "PeerOptionsAgent", + "PeerOptionsAgentOutput", + "PeerOptionsAgentOutputAudioFormat", + "PeerOptionsAgentOutputAudioSampleRate", + "PeerOptionsAgentSubscribeMode", "PeerOptionsWebRTC", "PeerOptionsWebRTCMetadata", - "PeerOptionsWebRTCSubscribeOptions", - "PeerOptionsWebRTCSubscribeOptionsAudioFormat", - "PeerOptionsWebRTCSubscribeOptionsAudioSampleRate", + "PeerOptionsWebRTCSubscribeMode", "PeerRefreshTokenResponse", "PeerRefreshTokenResponseData", "PeerStatus", @@ -62,12 +70,18 @@ "RoomCreateDetailsResponseData", "RoomDetailsResponse", "RoomsListingResponse", + "Stream", + "StreamConfig", + "Streamer", + "StreamerStatus", "StreamerToken", - "SubscribeOptions", - "SubscribeOptionsAudioFormat", - "SubscribeOptionsAudioSampleRate", + "StreamsListingResponse", + "SubscribeMode", + "SubscribeTracksBody", "Track", "TrackMetadataType0", "TrackType", + "Viewer", + "ViewerStatus", "ViewerToken", ) diff --git a/fishjam/_openapi_client/models/peer.py b/fishjam/_openapi_client/models/peer.py index 3099774..9203218 100644 --- a/fishjam/_openapi_client/models/peer.py +++ b/fishjam/_openapi_client/models/peer.py @@ -12,10 +12,10 @@ from ..models.peer_status import PeerStatus from ..models.peer_type import PeerType +from ..models.subscribe_mode import SubscribeMode if TYPE_CHECKING: from ..models.peer_metadata import PeerMetadata - from ..models.subscribe_options import SubscribeOptions from ..models.track import Track @@ -27,11 +27,11 @@ class Peer: """Describes peer status Attributes: - id (str): Assigned peer id Example: peer-1. + id (str): Assigned peer id Example: 4a1c1164-5fb7-425d-89d7-24cdb8fff1cf. metadata (Union['PeerMetadata', None]): Custom metadata set by the peer Example: {'name': 'FishjamUser'}. status (PeerStatus): Informs about the peer status Example: disconnected. - subscribe (Union['SubscribeOptions', None]): Configuration of server-side subscriptions to the peer's tracks - Example: {'audioFormat': 'pcm16'}. + subscribe_mode (SubscribeMode): Configuration of peer's subscribing policy + subscriptions (list[str]): Describes peer's subscriptions in manual mode tracks (list['Track']): List of all peer's tracks type_ (PeerType): Peer type Example: webrtc. """ @@ -39,14 +39,14 @@ class Peer: id: str metadata: Union["PeerMetadata", None] status: PeerStatus - subscribe: Union["SubscribeOptions", None] + subscribe_mode: SubscribeMode + subscriptions: list[str] tracks: list["Track"] type_: PeerType additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> dict[str, Any]: from ..models.peer_metadata import PeerMetadata - from ..models.subscribe_options import SubscribeOptions id = self.id @@ -58,11 +58,9 @@ def to_dict(self) -> dict[str, Any]: status = self.status.value - subscribe: Union[None, dict[str, Any]] - if isinstance(self.subscribe, SubscribeOptions): - subscribe = self.subscribe.to_dict() - else: - subscribe = self.subscribe + subscribe_mode = self.subscribe_mode.value + + subscriptions = self.subscriptions tracks = [] for tracks_item_data in self.tracks: @@ -78,7 +76,8 @@ def to_dict(self) -> dict[str, Any]: "id": id, "metadata": metadata, "status": status, - "subscribe": subscribe, + "subscribeMode": subscribe_mode, + "subscriptions": subscriptions, "tracks": tracks, "type": type_, } @@ -89,7 +88,6 @@ def to_dict(self) -> dict[str, Any]: @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: from ..models.peer_metadata import PeerMetadata - from ..models.subscribe_options import SubscribeOptions from ..models.track import Track d = dict(src_dict) @@ -112,22 +110,9 @@ def _parse_metadata(data: object) -> Union["PeerMetadata", None]: status = PeerStatus(d.pop("status")) - def _parse_subscribe(data: object) -> Union["SubscribeOptions", None]: - if data is None: - return data - try: - if not isinstance(data, dict): - raise TypeError() - componentsschemas_subscribe_options_type_0 = SubscribeOptions.from_dict( - data - ) - - return componentsschemas_subscribe_options_type_0 - except: # noqa: E722 - pass - return cast(Union["SubscribeOptions", None], data) + subscribe_mode = SubscribeMode(d.pop("subscribeMode")) - subscribe = _parse_subscribe(d.pop("subscribe")) + subscriptions = cast(list[str], d.pop("subscriptions")) tracks = [] _tracks = d.pop("tracks") @@ -142,7 +127,8 @@ def _parse_subscribe(data: object) -> Union["SubscribeOptions", None]: id=id, metadata=metadata, status=status, - subscribe=subscribe, + subscribe_mode=subscribe_mode, + subscriptions=subscriptions, tracks=tracks, type_=type_, ) diff --git a/fishjam/_openapi_client/models/peer_options_agent.py b/fishjam/_openapi_client/models/peer_options_agent.py index c80409e..0656184 100644 --- a/fishjam/_openapi_client/models/peer_options_agent.py +++ b/fishjam/_openapi_client/models/peer_options_agent.py @@ -1,28 +1,82 @@ from collections.abc import Mapping -from typing import Any, TypeVar +from typing import ( + TYPE_CHECKING, + Any, + TypeVar, + Union, +) from attrs import define as _attrs_define from attrs import field as _attrs_field +from ..models.peer_options_agent_subscribe_mode import PeerOptionsAgentSubscribeMode +from ..types import UNSET, Unset + +if TYPE_CHECKING: + from ..models.peer_options_agent_output import PeerOptionsAgentOutput + + T = TypeVar("T", bound="PeerOptionsAgent") @_attrs_define class PeerOptionsAgent: - """Options specific to the Agent peer""" + """Options specific to the Agent peer + Attributes: + output (Union[Unset, PeerOptionsAgentOutput]): Output audio options + subscribe_mode (Union[Unset, PeerOptionsAgentSubscribeMode]): Configuration of peer's subscribing policy + Default: PeerOptionsAgentSubscribeMode.AUTO. + """ + + output: Union[Unset, "PeerOptionsAgentOutput"] = UNSET + subscribe_mode: Union[ + Unset, PeerOptionsAgentSubscribeMode + ] = PeerOptionsAgentSubscribeMode.AUTO additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> dict[str, Any]: + output: Union[Unset, dict[str, Any]] = UNSET + if not isinstance(self.output, Unset): + output = self.output.to_dict() + + subscribe_mode: Union[Unset, str] = UNSET + if not isinstance(self.subscribe_mode, Unset): + subscribe_mode = self.subscribe_mode.value + field_dict: dict[str, Any] = {} field_dict.update(self.additional_properties) + field_dict.update({}) + if output is not UNSET: + field_dict["output"] = output + if subscribe_mode is not UNSET: + field_dict["subscribeMode"] = subscribe_mode return field_dict @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.peer_options_agent_output import PeerOptionsAgentOutput + d = dict(src_dict) - peer_options_agent = cls() + _output = d.pop("output", UNSET) + output: Union[Unset, PeerOptionsAgentOutput] + if isinstance(_output, Unset): + output = UNSET + else: + output = PeerOptionsAgentOutput.from_dict(_output) + + _subscribe_mode = d.pop("subscribeMode", UNSET) + subscribe_mode: Union[Unset, PeerOptionsAgentSubscribeMode] + if isinstance(_subscribe_mode, Unset): + subscribe_mode = UNSET + else: + subscribe_mode = PeerOptionsAgentSubscribeMode(_subscribe_mode) + + peer_options_agent = cls( + output=output, + subscribe_mode=subscribe_mode, + ) peer_options_agent.additional_properties = d return peer_options_agent diff --git a/fishjam/_openapi_client/models/peer_options_agent_output.py b/fishjam/_openapi_client/models/peer_options_agent_output.py new file mode 100644 index 0000000..25ae3dc --- /dev/null +++ b/fishjam/_openapi_client/models/peer_options_agent_output.py @@ -0,0 +1,101 @@ +from collections.abc import Mapping +from typing import ( + Any, + TypeVar, + Union, +) + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..models.peer_options_agent_output_audio_format import ( + PeerOptionsAgentOutputAudioFormat, +) +from ..models.peer_options_agent_output_audio_sample_rate import ( + PeerOptionsAgentOutputAudioSampleRate, +) +from ..types import UNSET, Unset + +T = TypeVar("T", bound="PeerOptionsAgentOutput") + + +@_attrs_define +class PeerOptionsAgentOutput: + """Output audio options + + Attributes: + audio_format (Union[Unset, PeerOptionsAgentOutputAudioFormat]): The format of the output audio Default: + PeerOptionsAgentOutputAudioFormat.PCM16. Example: pcm16. + audio_sample_rate (Union[Unset, PeerOptionsAgentOutputAudioSampleRate]): The sample rate of the output audio + Default: PeerOptionsAgentOutputAudioSampleRate.VALUE_16000. Example: 16000. + """ + + audio_format: Union[ + Unset, PeerOptionsAgentOutputAudioFormat + ] = PeerOptionsAgentOutputAudioFormat.PCM16 + audio_sample_rate: Union[ + Unset, PeerOptionsAgentOutputAudioSampleRate + ] = PeerOptionsAgentOutputAudioSampleRate.VALUE_16000 + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + audio_format: Union[Unset, str] = UNSET + if not isinstance(self.audio_format, Unset): + audio_format = self.audio_format.value + + audio_sample_rate: Union[Unset, int] = UNSET + if not isinstance(self.audio_sample_rate, Unset): + audio_sample_rate = self.audio_sample_rate.value + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update({}) + if audio_format is not UNSET: + field_dict["audioFormat"] = audio_format + if audio_sample_rate is not UNSET: + field_dict["audioSampleRate"] = audio_sample_rate + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + _audio_format = d.pop("audioFormat", UNSET) + audio_format: Union[Unset, PeerOptionsAgentOutputAudioFormat] + if isinstance(_audio_format, Unset): + audio_format = UNSET + else: + audio_format = PeerOptionsAgentOutputAudioFormat(_audio_format) + + _audio_sample_rate = d.pop("audioSampleRate", UNSET) + audio_sample_rate: Union[Unset, PeerOptionsAgentOutputAudioSampleRate] + if isinstance(_audio_sample_rate, Unset): + audio_sample_rate = UNSET + else: + audio_sample_rate = PeerOptionsAgentOutputAudioSampleRate( + _audio_sample_rate + ) + + peer_options_agent_output = cls( + audio_format=audio_format, + audio_sample_rate=audio_sample_rate, + ) + + peer_options_agent_output.additional_properties = d + return peer_options_agent_output + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/fishjam/_openapi_client/models/subscribe_options_audio_format.py b/fishjam/_openapi_client/models/peer_options_agent_output_audio_format.py similarity index 74% rename from fishjam/_openapi_client/models/subscribe_options_audio_format.py rename to fishjam/_openapi_client/models/peer_options_agent_output_audio_format.py index e067554..46cef67 100644 --- a/fishjam/_openapi_client/models/subscribe_options_audio_format.py +++ b/fishjam/_openapi_client/models/peer_options_agent_output_audio_format.py @@ -1,7 +1,7 @@ from enum import Enum -class SubscribeOptionsAudioFormat(str, Enum): +class PeerOptionsAgentOutputAudioFormat(str, Enum): """The format of the output audio""" PCM16 = "pcm16" diff --git a/fishjam/_openapi_client/models/subscribe_options_audio_sample_rate.py b/fishjam/_openapi_client/models/peer_options_agent_output_audio_sample_rate.py similarity index 71% rename from fishjam/_openapi_client/models/subscribe_options_audio_sample_rate.py rename to fishjam/_openapi_client/models/peer_options_agent_output_audio_sample_rate.py index 7c5bea9..ee4ff98 100644 --- a/fishjam/_openapi_client/models/subscribe_options_audio_sample_rate.py +++ b/fishjam/_openapi_client/models/peer_options_agent_output_audio_sample_rate.py @@ -1,7 +1,7 @@ from enum import IntEnum -class SubscribeOptionsAudioSampleRate(IntEnum): +class PeerOptionsAgentOutputAudioSampleRate(IntEnum): VALUE_16000 = 16000 VALUE_24000 = 24000 diff --git a/fishjam/_openapi_client/models/peer_options_agent_subscribe_mode.py b/fishjam/_openapi_client/models/peer_options_agent_subscribe_mode.py new file mode 100644 index 0000000..e0515c5 --- /dev/null +++ b/fishjam/_openapi_client/models/peer_options_agent_subscribe_mode.py @@ -0,0 +1,11 @@ +from enum import Enum + + +class PeerOptionsAgentSubscribeMode(str, Enum): + """Configuration of peer's subscribing policy""" + + AUTO = "auto" + MANUAL = "manual" + + def __str__(self) -> str: + return str(self.value) diff --git a/fishjam/_openapi_client/models/peer_options_web_rtc.py b/fishjam/_openapi_client/models/peer_options_web_rtc.py index 51119a2..17aca64 100644 --- a/fishjam/_openapi_client/models/peer_options_web_rtc.py +++ b/fishjam/_openapi_client/models/peer_options_web_rtc.py @@ -4,19 +4,16 @@ Any, TypeVar, Union, - cast, ) from attrs import define as _attrs_define from attrs import field as _attrs_field +from ..models.peer_options_web_rtc_subscribe_mode import PeerOptionsWebRTCSubscribeMode from ..types import UNSET, Unset if TYPE_CHECKING: from ..models.peer_options_web_rtc_metadata import PeerOptionsWebRTCMetadata - from ..models.peer_options_web_rtc_subscribe_options import ( - PeerOptionsWebRTCSubscribeOptions, - ) T = TypeVar("T", bound="PeerOptionsWebRTC") @@ -29,33 +26,27 @@ class PeerOptionsWebRTC: Attributes: enable_simulcast (Union[Unset, bool]): Enables the peer to use simulcast Default: True. metadata (Union[Unset, PeerOptionsWebRTCMetadata]): Custom peer metadata - subscribe (Union['PeerOptionsWebRTCSubscribeOptions', None, Unset]): Configuration of server-side subscriptions - to the peer's tracks Example: {'audioFormat': 'pcm16'}. + subscribe_mode (Union[Unset, PeerOptionsWebRTCSubscribeMode]): Configuration of peer's subscribing policy + Default: PeerOptionsWebRTCSubscribeMode.AUTO. """ enable_simulcast: Union[Unset, bool] = True metadata: Union[Unset, "PeerOptionsWebRTCMetadata"] = UNSET - subscribe: Union["PeerOptionsWebRTCSubscribeOptions", None, Unset] = UNSET + subscribe_mode: Union[ + Unset, PeerOptionsWebRTCSubscribeMode + ] = PeerOptionsWebRTCSubscribeMode.AUTO additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> dict[str, Any]: - from ..models.peer_options_web_rtc_subscribe_options import ( - PeerOptionsWebRTCSubscribeOptions, - ) - enable_simulcast = self.enable_simulcast metadata: Union[Unset, dict[str, Any]] = UNSET if not isinstance(self.metadata, Unset): metadata = self.metadata.to_dict() - subscribe: Union[None, Unset, dict[str, Any]] - if isinstance(self.subscribe, Unset): - subscribe = UNSET - elif isinstance(self.subscribe, PeerOptionsWebRTCSubscribeOptions): - subscribe = self.subscribe.to_dict() - else: - subscribe = self.subscribe + subscribe_mode: Union[Unset, str] = UNSET + if not isinstance(self.subscribe_mode, Unset): + subscribe_mode = self.subscribe_mode.value field_dict: dict[str, Any] = {} field_dict.update(self.additional_properties) @@ -64,17 +55,14 @@ def to_dict(self) -> dict[str, Any]: field_dict["enableSimulcast"] = enable_simulcast if metadata is not UNSET: field_dict["metadata"] = metadata - if subscribe is not UNSET: - field_dict["subscribe"] = subscribe + if subscribe_mode is not UNSET: + field_dict["subscribeMode"] = subscribe_mode return field_dict @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: from ..models.peer_options_web_rtc_metadata import PeerOptionsWebRTCMetadata - from ..models.peer_options_web_rtc_subscribe_options import ( - PeerOptionsWebRTCSubscribeOptions, - ) d = dict(src_dict) enable_simulcast = d.pop("enableSimulcast", UNSET) @@ -86,29 +74,17 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: else: metadata = PeerOptionsWebRTCMetadata.from_dict(_metadata) - def _parse_subscribe( - data: object, - ) -> Union["PeerOptionsWebRTCSubscribeOptions", None, Unset]: - if data is None: - return data - if isinstance(data, Unset): - return data - try: - if not isinstance(data, dict): - raise TypeError() - subscribe_type_0 = PeerOptionsWebRTCSubscribeOptions.from_dict(data) - - return subscribe_type_0 - except: # noqa: E722 - pass - return cast(Union["PeerOptionsWebRTCSubscribeOptions", None, Unset], data) - - subscribe = _parse_subscribe(d.pop("subscribe", UNSET)) + _subscribe_mode = d.pop("subscribeMode", UNSET) + subscribe_mode: Union[Unset, PeerOptionsWebRTCSubscribeMode] + if isinstance(_subscribe_mode, Unset): + subscribe_mode = UNSET + else: + subscribe_mode = PeerOptionsWebRTCSubscribeMode(_subscribe_mode) peer_options_web_rtc = cls( enable_simulcast=enable_simulcast, metadata=metadata, - subscribe=subscribe, + subscribe_mode=subscribe_mode, ) peer_options_web_rtc.additional_properties = d diff --git a/fishjam/_openapi_client/models/peer_options_web_rtc_subscribe_mode.py b/fishjam/_openapi_client/models/peer_options_web_rtc_subscribe_mode.py new file mode 100644 index 0000000..11bc286 --- /dev/null +++ b/fishjam/_openapi_client/models/peer_options_web_rtc_subscribe_mode.py @@ -0,0 +1,11 @@ +from enum import Enum + + +class PeerOptionsWebRTCSubscribeMode(str, Enum): + """Configuration of peer's subscribing policy""" + + AUTO = "auto" + MANUAL = "manual" + + def __str__(self) -> str: + return str(self.value) diff --git a/fishjam/_openapi_client/models/peer_options_web_rtc_subscribe_options.py b/fishjam/_openapi_client/models/peer_options_web_rtc_subscribe_options.py deleted file mode 100644 index b0d9dc4..0000000 --- a/fishjam/_openapi_client/models/peer_options_web_rtc_subscribe_options.py +++ /dev/null @@ -1,87 +0,0 @@ -from collections.abc import Mapping -from typing import ( - Any, - TypeVar, - Union, -) - -from attrs import define as _attrs_define - -from ..models.peer_options_web_rtc_subscribe_options_audio_format import ( - PeerOptionsWebRTCSubscribeOptionsAudioFormat, -) -from ..models.peer_options_web_rtc_subscribe_options_audio_sample_rate import ( - PeerOptionsWebRTCSubscribeOptionsAudioSampleRate, -) -from ..types import UNSET, Unset - -T = TypeVar("T", bound="PeerOptionsWebRTCSubscribeOptions") - - -@_attrs_define -class PeerOptionsWebRTCSubscribeOptions: - """Configuration of server-side subscriptions to the peer's tracks - - Example: - {'audioFormat': 'pcm16'} - - Attributes: - audio_format (Union[Unset, PeerOptionsWebRTCSubscribeOptionsAudioFormat]): The format of the output audio - Default: PeerOptionsWebRTCSubscribeOptionsAudioFormat.PCM16. Example: pcm16. - audio_sample_rate (Union[Unset, PeerOptionsWebRTCSubscribeOptionsAudioSampleRate]): The sample rate of the - output audio Default: PeerOptionsWebRTCSubscribeOptionsAudioSampleRate.VALUE_16000. Example: 16000. - """ - - audio_format: Union[ - Unset, PeerOptionsWebRTCSubscribeOptionsAudioFormat - ] = PeerOptionsWebRTCSubscribeOptionsAudioFormat.PCM16 - audio_sample_rate: Union[ - Unset, PeerOptionsWebRTCSubscribeOptionsAudioSampleRate - ] = PeerOptionsWebRTCSubscribeOptionsAudioSampleRate.VALUE_16000 - - def to_dict(self) -> dict[str, Any]: - audio_format: Union[Unset, str] = UNSET - if not isinstance(self.audio_format, Unset): - audio_format = self.audio_format.value - - audio_sample_rate: Union[Unset, int] = UNSET - if not isinstance(self.audio_sample_rate, Unset): - audio_sample_rate = self.audio_sample_rate.value - - field_dict: dict[str, Any] = {} - - field_dict.update({}) - if audio_format is not UNSET: - field_dict["audioFormat"] = audio_format - if audio_sample_rate is not UNSET: - field_dict["audioSampleRate"] = audio_sample_rate - - return field_dict - - @classmethod - def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: - d = dict(src_dict) - _audio_format = d.pop("audioFormat", UNSET) - audio_format: Union[Unset, PeerOptionsWebRTCSubscribeOptionsAudioFormat] - if isinstance(_audio_format, Unset): - audio_format = UNSET - else: - audio_format = PeerOptionsWebRTCSubscribeOptionsAudioFormat(_audio_format) - - _audio_sample_rate = d.pop("audioSampleRate", UNSET) - audio_sample_rate: Union[ - Unset, PeerOptionsWebRTCSubscribeOptionsAudioSampleRate - ] - if isinstance(_audio_sample_rate, Unset): - audio_sample_rate = UNSET - else: - audio_sample_rate = PeerOptionsWebRTCSubscribeOptionsAudioSampleRate( - _audio_sample_rate - ) - - peer_options_web_rtc_subscribe_options = cls( - audio_format=audio_format, - audio_sample_rate=audio_sample_rate, - ) - - return peer_options_web_rtc_subscribe_options diff --git a/fishjam/_openapi_client/models/peer_options_web_rtc_subscribe_options_audio_format.py b/fishjam/_openapi_client/models/peer_options_web_rtc_subscribe_options_audio_format.py deleted file mode 100644 index dc17c75..0000000 --- a/fishjam/_openapi_client/models/peer_options_web_rtc_subscribe_options_audio_format.py +++ /dev/null @@ -1,10 +0,0 @@ -from enum import Enum - - -class PeerOptionsWebRTCSubscribeOptionsAudioFormat(str, Enum): - """The format of the output audio""" - - PCM16 = "pcm16" - - def __str__(self) -> str: - return str(self.value) diff --git a/fishjam/_openapi_client/models/peer_options_web_rtc_subscribe_options_audio_sample_rate.py b/fishjam/_openapi_client/models/peer_options_web_rtc_subscribe_options_audio_sample_rate.py deleted file mode 100644 index 7d384f0..0000000 --- a/fishjam/_openapi_client/models/peer_options_web_rtc_subscribe_options_audio_sample_rate.py +++ /dev/null @@ -1,9 +0,0 @@ -from enum import IntEnum - - -class PeerOptionsWebRTCSubscribeOptionsAudioSampleRate(IntEnum): - VALUE_16000 = 16000 - VALUE_24000 = 24000 - - def __str__(self) -> str: - return str(self.value) diff --git a/fishjam/_openapi_client/models/stream.py b/fishjam/_openapi_client/models/stream.py new file mode 100644 index 0000000..dca2cfa --- /dev/null +++ b/fishjam/_openapi_client/models/stream.py @@ -0,0 +1,124 @@ +from collections.abc import Mapping +from typing import ( + TYPE_CHECKING, + Any, + TypeVar, + Union, +) + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +if TYPE_CHECKING: + from ..models.streamer import Streamer + from ..models.viewer import Viewer + + +T = TypeVar("T", bound="Stream") + + +@_attrs_define +class Stream: + """Describes stream status + + Attributes: + id (str): Assigned stream id + public (bool): + streamers (list['Streamer']): List of all streamers + viewers (list['Viewer']): List of all viewers + audio_only (Union[Unset, bool]): True if stream is restricted to audio only + """ + + id: str + public: bool + streamers: list["Streamer"] + viewers: list["Viewer"] + audio_only: Union[Unset, bool] = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + id = self.id + + public = self.public + + streamers = [] + for streamers_item_data in self.streamers: + streamers_item = streamers_item_data.to_dict() + streamers.append(streamers_item) + + viewers = [] + for viewers_item_data in self.viewers: + viewers_item = viewers_item_data.to_dict() + viewers.append(viewers_item) + + audio_only = self.audio_only + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "id": id, + "public": public, + "streamers": streamers, + "viewers": viewers, + } + ) + if audio_only is not UNSET: + field_dict["audioOnly"] = audio_only + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.streamer import Streamer + from ..models.viewer import Viewer + + d = dict(src_dict) + id = d.pop("id") + + public = d.pop("public") + + streamers = [] + _streamers = d.pop("streamers") + for streamers_item_data in _streamers: + streamers_item = Streamer.from_dict(streamers_item_data) + + streamers.append(streamers_item) + + viewers = [] + _viewers = d.pop("viewers") + for viewers_item_data in _viewers: + viewers_item = Viewer.from_dict(viewers_item_data) + + viewers.append(viewers_item) + + audio_only = d.pop("audioOnly", UNSET) + + stream = cls( + id=id, + public=public, + streamers=streamers, + viewers=viewers, + audio_only=audio_only, + ) + + stream.additional_properties = d + return stream + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/fishjam/_openapi_client/models/stream_config.py b/fishjam/_openapi_client/models/stream_config.py new file mode 100644 index 0000000..1697925 --- /dev/null +++ b/fishjam/_openapi_client/models/stream_config.py @@ -0,0 +1,86 @@ +from collections.abc import Mapping +from typing import ( + Any, + TypeVar, + Union, + cast, +) + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="StreamConfig") + + +@_attrs_define +class StreamConfig: + """Stream configuration + + Attributes: + audio_only (Union[None, Unset, bool]): Restrics stream to audio only Default: False. + public (Union[Unset, bool]): True if livestream viewers can omit specifying a token. Default: False. + """ + + audio_only: Union[None, Unset, bool] = False + public: Union[Unset, bool] = False + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + audio_only: Union[None, Unset, bool] + if isinstance(self.audio_only, Unset): + audio_only = UNSET + else: + audio_only = self.audio_only + + public = self.public + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update({}) + if audio_only is not UNSET: + field_dict["audioOnly"] = audio_only + if public is not UNSET: + field_dict["public"] = public + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + + def _parse_audio_only(data: object) -> Union[None, Unset, bool]: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(Union[None, Unset, bool], data) + + audio_only = _parse_audio_only(d.pop("audioOnly", UNSET)) + + public = d.pop("public", UNSET) + + stream_config = cls( + audio_only=audio_only, + public=public, + ) + + stream_config.additional_properties = d + return stream_config + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/fishjam/_openapi_client/models/streamer.py b/fishjam/_openapi_client/models/streamer.py new file mode 100644 index 0000000..bc8b8f7 --- /dev/null +++ b/fishjam/_openapi_client/models/streamer.py @@ -0,0 +1,88 @@ +from collections.abc import Mapping +from typing import ( + TYPE_CHECKING, + Any, + TypeVar, +) + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..models.streamer_status import StreamerStatus + +if TYPE_CHECKING: + from ..models.streamer_token import StreamerToken + + +T = TypeVar("T", bound="Streamer") + + +@_attrs_define +class Streamer: + """Describes streamer status + + Attributes: + id (str): Assigned streamer id + status (StreamerStatus): + token (StreamerToken): Token for authorizing broadcaster streamer connection + """ + + id: str + status: StreamerStatus + token: "StreamerToken" + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + id = self.id + + status = self.status.value + + token = self.token.to_dict() + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "id": id, + "status": status, + "token": token, + } + ) + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.streamer_token import StreamerToken + + d = dict(src_dict) + id = d.pop("id") + + status = StreamerStatus(d.pop("status")) + + token = StreamerToken.from_dict(d.pop("token")) + + streamer = cls( + id=id, + status=status, + token=token, + ) + + streamer.additional_properties = d + return streamer + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/fishjam/_openapi_client/models/streamer_status.py b/fishjam/_openapi_client/models/streamer_status.py new file mode 100644 index 0000000..f8a5cf2 --- /dev/null +++ b/fishjam/_openapi_client/models/streamer_status.py @@ -0,0 +1,11 @@ +from enum import Enum + + +class StreamerStatus(str, Enum): + """None""" + + CONNECTED = "connected" + DISCONNECTED = "disconnected" + + def __str__(self) -> str: + return str(self.value) diff --git a/fishjam/_openapi_client/models/streams_listing_response.py b/fishjam/_openapi_client/models/streams_listing_response.py new file mode 100644 index 0000000..86c9fef --- /dev/null +++ b/fishjam/_openapi_client/models/streams_listing_response.py @@ -0,0 +1,78 @@ +from collections.abc import Mapping +from typing import ( + TYPE_CHECKING, + Any, + TypeVar, +) + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +if TYPE_CHECKING: + from ..models.stream import Stream + + +T = TypeVar("T", bound="StreamsListingResponse") + + +@_attrs_define +class StreamsListingResponse: + """Response containing list of all streams + + Attributes: + data (list['Stream']): + """ + + data: list["Stream"] + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + data = [] + for data_item_data in self.data: + data_item = data_item_data.to_dict() + data.append(data_item) + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "data": data, + } + ) + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.stream import Stream + + d = dict(src_dict) + data = [] + _data = d.pop("data") + for data_item_data in _data: + data_item = Stream.from_dict(data_item_data) + + data.append(data_item) + + streams_listing_response = cls( + data=data, + ) + + streams_listing_response.additional_properties = d + return streams_listing_response + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/fishjam/_openapi_client/models/subscribe_mode.py b/fishjam/_openapi_client/models/subscribe_mode.py new file mode 100644 index 0000000..e92e06a --- /dev/null +++ b/fishjam/_openapi_client/models/subscribe_mode.py @@ -0,0 +1,11 @@ +from enum import Enum + + +class SubscribeMode(str, Enum): + """Configuration of peer's subscribing policy""" + + AUTO = "auto" + MANUAL = "manual" + + def __str__(self) -> str: + return str(self.value) diff --git a/fishjam/_openapi_client/models/subscribe_options.py b/fishjam/_openapi_client/models/subscribe_options.py deleted file mode 100644 index 2c824c9..0000000 --- a/fishjam/_openapi_client/models/subscribe_options.py +++ /dev/null @@ -1,79 +0,0 @@ -from collections.abc import Mapping -from typing import ( - Any, - TypeVar, - Union, -) - -from attrs import define as _attrs_define - -from ..models.subscribe_options_audio_format import SubscribeOptionsAudioFormat -from ..models.subscribe_options_audio_sample_rate import SubscribeOptionsAudioSampleRate -from ..types import UNSET, Unset - -T = TypeVar("T", bound="SubscribeOptions") - - -@_attrs_define -class SubscribeOptions: - """Configuration of server-side subscriptions to the peer's tracks - - Example: - {'audioFormat': 'pcm16'} - - Attributes: - audio_format (Union[Unset, SubscribeOptionsAudioFormat]): The format of the output audio Default: - SubscribeOptionsAudioFormat.PCM16. Example: pcm16. - audio_sample_rate (Union[Unset, SubscribeOptionsAudioSampleRate]): The sample rate of the output audio Default: - SubscribeOptionsAudioSampleRate.VALUE_16000. Example: 16000. - """ - - audio_format: Union[ - Unset, SubscribeOptionsAudioFormat - ] = SubscribeOptionsAudioFormat.PCM16 - audio_sample_rate: Union[ - Unset, SubscribeOptionsAudioSampleRate - ] = SubscribeOptionsAudioSampleRate.VALUE_16000 - - def to_dict(self) -> dict[str, Any]: - audio_format: Union[Unset, str] = UNSET - if not isinstance(self.audio_format, Unset): - audio_format = self.audio_format.value - - audio_sample_rate: Union[Unset, int] = UNSET - if not isinstance(self.audio_sample_rate, Unset): - audio_sample_rate = self.audio_sample_rate.value - - field_dict: dict[str, Any] = {} - - field_dict.update({}) - if audio_format is not UNSET: - field_dict["audioFormat"] = audio_format - if audio_sample_rate is not UNSET: - field_dict["audioSampleRate"] = audio_sample_rate - - return field_dict - - @classmethod - def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: - d = dict(src_dict) - _audio_format = d.pop("audioFormat", UNSET) - audio_format: Union[Unset, SubscribeOptionsAudioFormat] - if isinstance(_audio_format, Unset): - audio_format = UNSET - else: - audio_format = SubscribeOptionsAudioFormat(_audio_format) - - _audio_sample_rate = d.pop("audioSampleRate", UNSET) - audio_sample_rate: Union[Unset, SubscribeOptionsAudioSampleRate] - if isinstance(_audio_sample_rate, Unset): - audio_sample_rate = UNSET - else: - audio_sample_rate = SubscribeOptionsAudioSampleRate(_audio_sample_rate) - - subscribe_options = cls( - audio_format=audio_format, - audio_sample_rate=audio_sample_rate, - ) - - return subscribe_options diff --git a/fishjam/_openapi_client/models/subscribe_tracks_body.py b/fishjam/_openapi_client/models/subscribe_tracks_body.py new file mode 100644 index 0000000..1ce94a7 --- /dev/null +++ b/fishjam/_openapi_client/models/subscribe_tracks_body.py @@ -0,0 +1,63 @@ +from collections.abc import Mapping +from typing import ( + Any, + TypeVar, + cast, +) + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +T = TypeVar("T", bound="SubscribeTracksBody") + + +@_attrs_define +class SubscribeTracksBody: + """ + Attributes: + track_ids (list[str]): List of track IDs to subscribe to + """ + + track_ids: list[str] + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + track_ids = self.track_ids + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "track_ids": track_ids, + } + ) + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + track_ids = cast(list[str], d.pop("track_ids")) + + subscribe_tracks_body = cls( + track_ids=track_ids, + ) + + subscribe_tracks_body.additional_properties = d + return subscribe_tracks_body + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/fishjam/_openapi_client/models/track.py b/fishjam/_openapi_client/models/track.py index cfbc46e..d6d2d3a 100644 --- a/fishjam/_openapi_client/models/track.py +++ b/fishjam/_openapi_client/models/track.py @@ -22,10 +22,10 @@ @_attrs_define class Track: - """Describes media track of a Peer or Component + """Describes media track of a Peer Attributes: - id (Union[Unset, str]): + id (Union[Unset, str]): Assigned track id Example: 8dbd2e6b-a1e7-4670-95a2-0262aa6c6321. metadata (Union['TrackMetadataType0', None, Unset]): Example: {'source': 'camera'}. type_ (Union[Unset, TrackType]): """ diff --git a/fishjam/_openapi_client/models/viewer.py b/fishjam/_openapi_client/models/viewer.py new file mode 100644 index 0000000..66b8c61 --- /dev/null +++ b/fishjam/_openapi_client/models/viewer.py @@ -0,0 +1,88 @@ +from collections.abc import Mapping +from typing import ( + TYPE_CHECKING, + Any, + TypeVar, +) + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..models.viewer_status import ViewerStatus + +if TYPE_CHECKING: + from ..models.viewer_token import ViewerToken + + +T = TypeVar("T", bound="Viewer") + + +@_attrs_define +class Viewer: + """Describes viewer status + + Attributes: + id (str): Assigned viewer id + status (ViewerStatus): + token (ViewerToken): Token for authorizing broadcaster viewer connection + """ + + id: str + status: ViewerStatus + token: "ViewerToken" + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + id = self.id + + status = self.status.value + + token = self.token.to_dict() + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "id": id, + "status": status, + "token": token, + } + ) + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.viewer_token import ViewerToken + + d = dict(src_dict) + id = d.pop("id") + + status = ViewerStatus(d.pop("status")) + + token = ViewerToken.from_dict(d.pop("token")) + + viewer = cls( + id=id, + status=status, + token=token, + ) + + viewer.additional_properties = d + return viewer + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/fishjam/_openapi_client/models/viewer_status.py b/fishjam/_openapi_client/models/viewer_status.py new file mode 100644 index 0000000..59fe9e2 --- /dev/null +++ b/fishjam/_openapi_client/models/viewer_status.py @@ -0,0 +1,11 @@ +from enum import Enum + + +class ViewerStatus(str, Enum): + """None""" + + CONNECTED = "connected" + DISCONNECTED = "disconnected" + + def __str__(self) -> str: + return str(self.value) diff --git a/fishjam/agent/__init__.py b/fishjam/agent/__init__.py index 2b4601b..b4d4299 100644 --- a/fishjam/agent/__init__.py +++ b/fishjam/agent/__init__.py @@ -1,8 +1,8 @@ from .agent import ( Agent, AgentSession, - AudioTrackOptions, IncomingTrackData, + OutgoingAudioTrackOptions, OutgoingTrack, ) from .errors import AgentAuthError, AgentError @@ -14,5 +14,5 @@ "AgentAuthError", "IncomingTrackData", "OutgoingTrack", - "AudioTrackOptions", + "OutgoingAudioTrackOptions", ] diff --git a/fishjam/agent/agent.py b/fishjam/agent/agent.py index 93710a2..f752568 100644 --- a/fishjam/agent/agent.py +++ b/fishjam/agent/agent.py @@ -27,7 +27,7 @@ @dataclass -class AudioTrackOptions: +class OutgoingAudioTrackOptions: """Parameters of an outgoing audio track.""" encoding: TrackEncoding = TrackEncoding.TRACK_ENCODING_UNSPECIFIED @@ -41,12 +41,14 @@ class AudioTrackOptions: The sample rate of the audio source. Defaults to 16000. """ + channels: Literal[1, 2] = 1 """ The number of channels in the audio source. Supported values are 1 (mono) and 2 (stereo). Defaults to 1 (mono) """ + metadata: dict[str, Any] | None = None """ Custom metadata for the track. @@ -65,7 +67,7 @@ class OutgoingTrack: """The global identifier of the track.""" session: AgentSession """The agent the track belongs to.""" - options: AudioTrackOptions + options: OutgoingAudioTrackOptions """The parameters used to create the track.""" async def send_chunk(self, data: bytes): @@ -120,7 +122,7 @@ async def receive(self) -> AsyncIterator[IncomingAgentMessage]: case IncomingTrackData() as content: yield content - async def add_track(self, options: AudioTrackOptions): + async def add_track(self, options: OutgoingAudioTrackOptions): """ Adds a track to the connected agent, with the specified options and metadata. diff --git a/fishjam/api/_fishjam_client.py b/fishjam/api/_fishjam_client.py index 3e0d7e6..f6bbbbb 100644 --- a/fishjam/api/_fishjam_client.py +++ b/fishjam/api/_fishjam_client.py @@ -2,7 +2,7 @@ Fishjam client used to manage rooms """ -from dataclasses import dataclass +from dataclasses import dataclass, field from typing import Any, Literal, cast from fishjam._openapi_client.api.room import add_peer as room_add_peer @@ -23,9 +23,11 @@ Peer, PeerDetailsResponse, PeerOptionsAgent, + PeerOptionsAgentOutput, + PeerOptionsAgentOutputAudioFormat, + PeerOptionsAgentOutputAudioSampleRate, PeerOptionsWebRTC, PeerOptionsWebRTCMetadata, - PeerOptionsWebRTCSubscribeOptions, PeerRefreshTokenResponse, PeerType, RoomConfig, @@ -35,7 +37,6 @@ RoomDetailsResponse, RoomsListingResponse, StreamerToken, - SubscribeOptions, ViewerToken, ) from fishjam._openapi_client.types import UNSET @@ -75,13 +76,27 @@ class RoomOptions: @dataclass class PeerOptions: - """Options specific to the Peer""" + """Options specific to a WebRTC Peer""" enable_simulcast: bool = True """Enables the peer to use simulcast""" metadata: dict[str, Any] | None = None """Peer metadata""" - subscribe: SubscribeOptions | None = None + + +@dataclass +class AgentOutputOptions: + """Options of the desired format of audio tracks going from Fishjam to the agent.""" + + audio_format: Literal["pcm16"] = "pcm16" + audio_sample_rate: Literal[16000, 24000] = 16000 + + +@dataclass +class AgentOptions: + """Options specific to a WebRTC Peer""" + + output: AgentOutputOptions = field(default_factory=AgentOutputOptions) class FishjamClient(Client): @@ -122,7 +137,6 @@ def create_peer( peer_options = PeerOptionsWebRTC( enable_simulcast=options.enable_simulcast, metadata=peer_metadata, - subscribe=self.__parse_subscribe_options(options.subscribe), ) body = AddPeerBody(type_=PeerType.WEBRTC, options=peer_options) @@ -133,8 +147,21 @@ def create_peer( return (resp.data.peer, resp.data.token) - def create_agent(self, room_id: str): - body = AddPeerBody(type_=PeerType.AGENT, options=PeerOptionsAgent()) + def create_agent(self, room_id: str, options: AgentOptions | None = None): + options = options or AgentOptions() + body = AddPeerBody( + type_=PeerType.AGENT, + options=PeerOptionsAgent( + output=PeerOptionsAgentOutput( + audio_format=PeerOptionsAgentOutputAudioFormat( + options.output.audio_format + ), + audio_sample_rate=PeerOptionsAgentOutputAudioSampleRate( + options.output.audio_sample_rate + ), + ) + ), + ) resp = cast( PeerDetailsResponse, @@ -236,11 +263,3 @@ def __parse_peer_metadata(self, metadata: dict | None) -> PeerOptionsWebRTCMetad peer_metadata.additional_properties[key] = value return peer_metadata - - def __parse_subscribe_options( - self, - options: SubscribeOptions | None, - ) -> PeerOptionsWebRTCSubscribeOptions | None: - if options is None: - return None - return PeerOptionsWebRTCSubscribeOptions.from_dict(options.to_dict()) diff --git a/fishjam/peer/__init__.py b/fishjam/peer/__init__.py index 9e921cf..712fb83 100644 --- a/fishjam/peer/__init__.py +++ b/fishjam/peer/__init__.py @@ -2,16 +2,10 @@ PeerMetadata, PeerStatus, PeerType, - SubscribeOptions, - SubscribeOptionsAudioFormat, - SubscribeOptionsAudioSampleRate, ) __all__ = [ "PeerMetadata", "PeerStatus", "PeerType", - "SubscribeOptions", - "SubscribeOptionsAudioFormat", - "SubscribeOptionsAudioSampleRate", ] From eab3dc19a2031de9c844ba275366f99209141864 Mon Sep 17 00:00:00 2001 From: Tomasz Mazur <47872060+AHGIJMKLKKZNPJKQR@users.noreply.github.com> Date: Thu, 25 Sep 2025 17:49:55 +0200 Subject: [PATCH 07/16] Update tests --- tests/agent/test_agent.py | 26 ++++++++++++++++++++++++++ tests/test_room_api.py | 22 +++++----------------- 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/tests/agent/test_agent.py b/tests/agent/test_agent.py index f41f4d5..6a5d0c5 100644 --- a/tests/agent/test_agent.py +++ b/tests/agent/test_agent.py @@ -6,8 +6,10 @@ import pytest_asyncio from fishjam import FishjamClient, FishjamNotifier, Room +from fishjam._openapi_client.models import SubscribeMode from fishjam.agent.agent import Agent from fishjam.agent.errors import AgentAuthError +from fishjam.api._fishjam_client import AgentOptions, AgentOutputOptions from fishjam.events._protos.fishjam import ( ServerMessagePeerDisconnected, ServerMessagePeerMetadataUpdated, @@ -80,6 +82,30 @@ def test_create_delete_agent(self, room_api: FishjamClient, room: Room): assert room.peers == [] + def test_create_agent_with_options(self, room_api: FishjamClient, room: Room): + agent = room_api.create_agent( + room.id, + AgentOptions( + output=AgentOutputOptions( + audio_format="pcm16", + audio_sample_rate=24000, + ) + ), + ) + room = room_api.get_room(room.id) + + assert len(room.peers) == 1 + assert room.peers[0].id == agent.id + assert room.peers[0].type_ == "agent" + assert room.peers[0].status == "disconnected" + assert room.peers[0].subscribe_mode == SubscribeMode.AUTO + + room_api.delete_peer(room.id, agent.id) + + room = room_api.get_room(room.id) + + assert room.peers == [] + async def wait_event(event: asyncio.Event, timeout: float = 5): await asyncio.wait_for(event.wait(), timeout) diff --git a/tests/test_room_api.py b/tests/test_room_api.py index 57768cb..1c40cd4 100644 --- a/tests/test_room_api.py +++ b/tests/test_room_api.py @@ -1,6 +1,3 @@ -# pylint: disable=locally-disabled, missing-class-docstring, missing-function-docstring, redefined-outer-name, too-few-public-methods, missing-module-docstring - - import os import pytest @@ -12,6 +9,7 @@ Room, RoomOptions, ) +from fishjam._openapi_client.models import SubscribeMode from fishjam.errors import ( BadRequestError, NotFoundError, @@ -22,9 +20,6 @@ PeerMetadata, PeerStatus, PeerType, - SubscribeOptions, - SubscribeOptionsAudioFormat, - SubscribeOptionsAudioSampleRate, ) from fishjam.room import ( RoomConfig, @@ -175,7 +170,6 @@ def _assert_peer_created( webrtc_peer, room_id, server_metadata=None, - subscribe=None, ): server_metadata = server_metadata or {} @@ -185,26 +179,20 @@ def _assert_peer_created( status=PeerStatus("disconnected"), tracks=[], metadata=PeerMetadata.from_dict({"peer": {}, "server": server_metadata}), - subscribe=subscribe, + subscribe_mode=SubscribeMode.AUTO, + subscriptions=[], ) room = room_api.get_room(room_id) assert peer in room.peers def test_with_specified_options(self, room_api: FishjamClient): - subscribe = SubscribeOptions( - audio_format=SubscribeOptionsAudioFormat.PCM16, - audio_sample_rate=SubscribeOptionsAudioSampleRate.VALUE_16000, - ) - options = PeerOptions( - enable_simulcast=True, - subscribe=subscribe, - ) + options = PeerOptions(enable_simulcast=True) room = room_api.create_room() peer, _token = room_api.create_peer(room.id, options=options) - self._assert_peer_created(room_api, peer, room.id, subscribe=subscribe) + self._assert_peer_created(room_api, peer, room.id) def test_with_metadata(self, room_api: FishjamClient): options = PeerOptions(metadata={"is_test": True}) From f19ed000e3f710a33fb72c945a63a2843d03c754 Mon Sep 17 00:00:00 2001 From: Tomasz Mazur <47872060+AHGIJMKLKKZNPJKQR@users.noreply.github.com> Date: Fri, 26 Sep 2025 11:54:33 +0200 Subject: [PATCH 08/16] Update README --- examples/poet_chat/README.md | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/examples/poet_chat/README.md b/examples/poet_chat/README.md index 1556def..541ce03 100644 --- a/examples/poet_chat/README.md +++ b/examples/poet_chat/README.md @@ -1,3 +1,36 @@ -# Trivia Chat +# Limerick Poet demo +This directory contains an example implementation of a real-time chat agent using the [Fishjam](https://fishjam.io) and [OpenAI Agents](https://github.com/openai/openai-agents-python) Python SDKs. +The agent introduces itself when the user joins and creates limericks based on what the user says. +The agent handles interruptions from users to ensure a natural conversation flow. + +## Running + +> ![NOTE] All commands should be run from the parent directory of this README + +Make sure to [install uv](https://docs.astral.sh/uv/getting-started/installation/) if you don't have it already. +Once you have `uv` installed, fetch the dependencies with + +```bash +uv sync +``` + +To run the app, you will need 3 environment variables: + +- `FISHJAM_ID`: Your Fishjam ID, which you can get on the [Fishjam website](https://fishjam.io/app) +- `FISHJAM_MANAGEMENT_TOKEN`: Your Fishjam management token, which you can get on the [Fishjam website](https://fishjam.io/app) +- `OPENAI_API_KEY`: An API key for the OpenAI Realtime API. You can generate one on the [OpenAI website](https://platform.openai.com/api-keys). + +Once you have these variables, you can run the demo with + +```bash +FISHJAM_ID= \ +FISHJAM_MANAGEMENT_TOKEN= \ +GEMINI_API_KEY= \ +uv run ./main.py +``` + +A peer token should be generated and printed to standard output. +You can then use the [minimal-react](https://github.com/fishjam-cloud/web-client-sdk/tree/main/examples/react-client) +demo app to connect with this token and talk with the agent! From aba61b90e0ab13454e2e22911fa38d807eabfe8b Mon Sep 17 00:00:00 2001 From: Tomasz Mazur <47872060+AHGIJMKLKKZNPJKQR@users.noreply.github.com> Date: Fri, 26 Sep 2025 12:55:34 +0200 Subject: [PATCH 09/16] Remove litestar from deps --- examples/poet_chat/pyproject.toml | 6 +- examples/transcription/README.md | 5 +- uv.lock | 174 ------------------------------ 3 files changed, 4 insertions(+), 181 deletions(-) diff --git a/examples/poet_chat/pyproject.toml b/examples/poet_chat/pyproject.toml index cdd375d..52ff388 100644 --- a/examples/poet_chat/pyproject.toml +++ b/examples/poet_chat/pyproject.toml @@ -4,11 +4,7 @@ version = "0.1.0" description = "Fishjam voice agent example" readme = "README.md" requires-python = ">=3.11" -dependencies = [ - "fishjam-server-sdk", - "litestar[standard]>=2.17.0", - "openai-agents[voice]>=0.2.11", -] +dependencies = ["fishjam-server-sdk", "openai-agents[voice]>=0.2.11"] [tool.uv.sources] fishjam-server-sdk = { workspace = true } diff --git a/examples/transcription/README.md b/examples/transcription/README.md index 79f6a81..28e39ee 100644 --- a/examples/transcription/README.md +++ b/examples/transcription/README.md @@ -8,12 +8,13 @@ and uses [uv](https://docs.astral.sh/uv/) for dependency management. ## Running -Make sure to [install uv](https://docs.astral.sh/uv/getting-started/installation/) if you don't have it already. +> ![NOTE] All commands should be run from the parent directory of this README +Make sure to [install uv](https://docs.astral.sh/uv/getting-started/installation/) if you don't have it already. Once you have `uv` installed, fetch the dependencies with ```bash -uv sync --all-packages +uv sync ``` To run the app, you will need 3 environment variables: diff --git a/uv.lock b/uv.lock index 7a47fa8..a6d5cc5 100644 --- a/uv.lock +++ b/uv.lock @@ -212,15 +212,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/68/1b/e0a87d256e40e8c888847551b20a017a6b98139178505dc7ffb96f04e954/dnspython-2.7.0-py3-none-any.whl", hash = "sha256:b4c34b7d10b51bcc3a5071e7b8dee77939f1e878477eeecc965e9835f63c6c86", size = 313632, upload-time = "2024-10-05T20:14:57.687Z" }, ] -[[package]] -name = "editorconfig" -version = "0.17.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/88/3a/a61d9a1f319a186b05d14df17daea42fcddea63c213bcd61a929fb3a6796/editorconfig-0.17.1.tar.gz", hash = "sha256:23c08b00e8e08cc3adcddb825251c497478df1dada6aefeb01e626ad37303745", size = 14695, upload-time = "2025-06-09T08:21:37.097Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/96/fd/a40c621ff207f3ce8e484aa0fc8ba4eb6e3ecf52e15b42ba764b457a9550/editorconfig-0.17.1-py3-none-any.whl", hash = "sha256:1eda9c2c0db8c16dbd50111b710572a5e6de934e39772de1959d41f64fc17c82", size = 16360, upload-time = "2025-06-09T08:21:35.654Z" }, -] - [[package]] name = "email-validator" version = "2.2.0" @@ -234,41 +225,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d7/ee/bf0adb559ad3c786f12bcbc9296b3f5675f529199bef03e2df281fa1fadb/email_validator-2.2.0-py3-none-any.whl", hash = "sha256:561977c2d73ce3611850a06fa56b414621e0c8faa9d66f2611407d87465da631", size = 33521, upload-time = "2024-06-20T11:30:28.248Z" }, ] -[[package]] -name = "faker" -version = "37.6.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "tzdata" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/24/cd/f7679c20f07d9e2013123b7f7e13809a3450a18d938d58e86081a486ea15/faker-37.6.0.tar.gz", hash = "sha256:0f8cc34f30095184adf87c3c24c45b38b33ad81c35ef6eb0a3118f301143012c", size = 1907960, upload-time = "2025-08-26T15:56:27.419Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/61/7d/8b50e4ac772719777be33661f4bde320793400a706f5eb214e4de46f093c/faker-37.6.0-py3-none-any.whl", hash = "sha256:3c5209b23d7049d596a51db5d76403a0ccfea6fc294ffa2ecfef6a8843b1e6a7", size = 1949837, upload-time = "2025-08-26T15:56:25.33Z" }, -] - -[[package]] -name = "fast-query-parsers" -version = "1.0.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/dd/20/3a00b889a196e8dc5bede2f168d4a14edc8b5bccc3978a9f497f0f863e79/fast_query_parsers-1.0.3.tar.gz", hash = "sha256:5200a9e02997ad51d4d76a60ea1b256a68a184b04359540eb6310a15013df68f", size = 25275, upload-time = "2023-08-25T13:19:15.79Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/43/18/4179ac7064b4216ca42f2ed6f74e71254454acf2ec25ce6bb3ffbfda4aa6/fast_query_parsers-1.0.3-cp38-abi3-macosx_10_7_x86_64.whl", hash = "sha256:afbf71c1b4398dacfb9d84755eb026f8e759f68a066f1f3cc19e471fc342e74f", size = 766210, upload-time = "2023-08-25T13:18:48.415Z" }, - { url = "https://files.pythonhosted.org/packages/c5/21/c8c160f61a740efc4577079eb5747a6b2cb8d1168a84a0bfda6044113768/fast_query_parsers-1.0.3-cp38-abi3-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:42f26875311d1b151c3406adfa39ec2db98df111a369d75f6fa243ec8462f147", size = 1466147, upload-time = "2023-08-25T13:18:50.29Z" }, - { url = "https://files.pythonhosted.org/packages/51/5b/b10719598dbd14201271efd0b950c6a09efa0a3f6246fec3c192c6b7a8d2/fast_query_parsers-1.0.3-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:66630ad423b5b1f5709f82a4d8482cd6aa2f3fa73d2c779ff1877f25dee08d55", size = 764016, upload-time = "2023-08-25T13:18:52.295Z" }, - { url = "https://files.pythonhosted.org/packages/75/06/8861197982909bec00b180527df1e0e9791715271bfb84c8be389b6bf077/fast_query_parsers-1.0.3-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a6e3d816c572a6fad1ae9b93713b2db0d3db6e8f594e035ad52361d668dd94a8", size = 729912, upload-time = "2023-08-25T13:18:54.515Z" }, - { url = "https://files.pythonhosted.org/packages/f0/35/7a9a0c50588033edd9efba48f21e251dfcf77eaec2aff470988f622fbd3a/fast_query_parsers-1.0.3-cp38-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:0bdcc0ddb4cc69d823c2c0dedd8f5affc71042db39908ad2ca06261bf388cac6", size = 1003340, upload-time = "2023-08-25T13:18:56.521Z" }, - { url = "https://files.pythonhosted.org/packages/41/9b/5a42ddd23b85357be6764e14daa607d9b16bc6a395aae2c1cc2077e0a11d/fast_query_parsers-1.0.3-cp38-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6720505f2d2a764c76bcc4f3730a9dff69d9871740e46264f6605d73f9ce3794", size = 969496, upload-time = "2023-08-25T13:18:59.048Z" }, - { url = "https://files.pythonhosted.org/packages/c3/9f/4dfa29d74276fa07c40689bfaa3b21d057249314aeb20150f0f41373d16d/fast_query_parsers-1.0.3-cp38-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e947e7251769593da93832a10861f59565a46149fa117ebdf25377e7b2853936", size = 939972, upload-time = "2023-08-25T13:19:00.704Z" }, - { url = "https://files.pythonhosted.org/packages/74/34/950b6d799839c11e93566aef426b67f0a446c4906e45e592026fde894459/fast_query_parsers-1.0.3-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55a30b7cee0a53cddf9016b86fdad87221980d5a02a6126c491bd309755e6de9", size = 828557, upload-time = "2023-08-25T13:19:02.264Z" }, - { url = "https://files.pythonhosted.org/packages/81/a8/ee95263abc9806c81d77be8a3420d1f4dde467a10030dde8b0fa0e63f700/fast_query_parsers-1.0.3-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9bc2b457caa38371df1a30cfdfc57bd9bfdf348367abdaf6f36533416a0b0e93", size = 863119, upload-time = "2023-08-25T13:19:03.941Z" }, - { url = "https://files.pythonhosted.org/packages/05/d4/5eb8c9d400230b9a45a0ce47a443e9fe37b0902729f9440adef677af1f0d/fast_query_parsers-1.0.3-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:5736d3c32d6ba23995fa569fe572feabcfcfc30ac9e4709e94cff6f2c456a3d1", size = 911046, upload-time = "2023-08-25T13:19:05.596Z" }, - { url = "https://files.pythonhosted.org/packages/f8/b8/bf5e44588f6ebd81d0c53ba49c79999dc54cb0fe81ad6dde6fed2cd45b56/fast_query_parsers-1.0.3-cp38-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:3a6377eb0c5b172fbc77c3f96deaf1e51708b4b96d27ce173658bf11c1c00b20", size = 962966, upload-time = "2023-08-25T13:19:07.355Z" }, - { url = "https://files.pythonhosted.org/packages/6f/a9/132572b9f40c2635fdedb7a1cb6cedd9c880f8ffbbfdd6215ee493bb6936/fast_query_parsers-1.0.3-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:7ca6be04f443a1b055e910ccad01b1d72212f269a530415df99a87c5f1e9c927", size = 965422, upload-time = "2023-08-25T13:19:09.003Z" }, - { url = "https://files.pythonhosted.org/packages/ea/58/942327d3f2694b8f1a2fffaaaef1cc3147571852473a80070ebd6156a62e/fast_query_parsers-1.0.3-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a70d4d8852606f2dd5b798ab628b9d8dc6970ddfdd9e96f4543eb0cc89a74fb5", size = 967734, upload-time = "2023-08-25T13:19:10.654Z" }, - { url = "https://files.pythonhosted.org/packages/0a/e3/21bc18edc003b54a2069eb854b9f92cacb5acc99e03c609487a23a673755/fast_query_parsers-1.0.3-cp38-abi3-win32.whl", hash = "sha256:14b3fab7e9a6ac1c1efaf66c3fd2a3fd1e25ede03ed14118035e530433830a11", size = 646366, upload-time = "2023-08-25T13:19:12.079Z" }, - { url = "https://files.pythonhosted.org/packages/ae/4b/07fe4d7b5c458bdde9b0bfd8e8cb5762341af6c9727b43c2331c0cb0dbc3/fast_query_parsers-1.0.3-cp38-abi3-win_amd64.whl", hash = "sha256:21ae5f3a209aee7d3b84bdcdb33dd79f39fc8cb608b3ae8cfcb78123758c1a16", size = 689717, upload-time = "2023-08-25T13:19:14.051Z" }, -] - [[package]] name = "fastapi" version = "0.116.0" @@ -725,19 +681,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b3/4a/4175a563579e884192ba6e81725fc0448b042024419be8d83aa8a80a3f44/jiter-0.10.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3aa96f2abba33dc77f79b4cf791840230375f9534e5fac927ccceb58c5e604a5", size = 354213, upload-time = "2025-05-18T19:04:41.894Z" }, ] -[[package]] -name = "jsbeautifier" -version = "1.15.4" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "editorconfig" }, - { name = "six" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/ea/98/d6cadf4d5a1c03b2136837a435682418c29fdeb66be137128544cecc5b7a/jsbeautifier-1.15.4.tar.gz", hash = "sha256:5bb18d9efb9331d825735fbc5360ee8f1aac5e52780042803943aa7f854f7592", size = 75257, upload-time = "2025-02-27T17:53:53.252Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2d/14/1c65fccf8413d5f5c6e8425f84675169654395098000d8bddc4e9d3390e1/jsbeautifier-1.15.4-py3-none-any.whl", hash = "sha256:72f65de312a3f10900d7685557f84cb61a9733c50dcc27271a39f5b0051bf528", size = 94707, upload-time = "2025-02-27T17:53:46.152Z" }, -] - [[package]] name = "jsonschema" version = "4.25.1" @@ -765,47 +708,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/01/0e/b27cdbaccf30b890c40ed1da9fd4a3593a5cf94dae54fb34f8a4b74fcd3f/jsonschema_specifications-2025.4.1-py3-none-any.whl", hash = "sha256:4653bffbd6584f7de83a67e0d620ef16900b390ddc7939d56684d6c81e33f1af", size = 18437, upload-time = "2025-04-23T12:34:05.422Z" }, ] -[[package]] -name = "litestar" -version = "2.17.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "anyio" }, - { name = "click" }, - { name = "httpx" }, - { name = "litestar-htmx" }, - { name = "msgspec" }, - { name = "multidict" }, - { name = "multipart" }, - { name = "polyfactory" }, - { name = "pyyaml" }, - { name = "rich" }, - { name = "rich-click" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/3f/62/36619846adb94d24d31e1aad7a52632544f2db7b0df22c8839cfa1db0b2e/litestar-2.17.0.tar.gz", hash = "sha256:0f50c3b7063417c338b32902f9eb40b81a7b14c9802edbff921a24aec3b0ea5b", size = 372203, upload-time = "2025-08-10T13:37:41.401Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/52/04/0935667c3cee2a26152102b9319fdfe987b0f765e14e0311c17ca6698820/litestar-2.17.0-py3-none-any.whl", hash = "sha256:2e62f01f852195362d69e3305cccddaf6371f5ab0ced30a081a66fb85e1df532", size = 564343, upload-time = "2025-08-10T13:37:39.462Z" }, -] - -[package.optional-dependencies] -standard = [ - { name = "fast-query-parsers" }, - { name = "jinja2" }, - { name = "jsbeautifier" }, - { name = "uvicorn", extra = ["standard"] }, - { name = "uvloop", marker = "sys_platform != 'win32'" }, -] - -[[package]] -name = "litestar-htmx" -version = "0.5.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/3f/b9/7e296aa1adada25cce8e5f89a996b0e38d852d93b1b656a2058226c542a2/litestar_htmx-0.5.0.tar.gz", hash = "sha256:e02d1a3a92172c874835fa3e6749d65ae9fc626d0df46719490a16293e2146fb", size = 119755, upload-time = "2025-06-11T21:19:45.573Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/f2/24/8d99982f0aa9c1cd82073c6232b54a0dbe6797c7d63c0583a6c68ee3ddf2/litestar_htmx-0.5.0-py3-none-any.whl", hash = "sha256:92833aa47e0d0e868d2a7dbfab75261f124f4b83d4f9ad12b57b9a68f86c50e6", size = 9970, upload-time = "2025-06-11T21:19:44.465Z" }, -] - [[package]] name = "markdown" version = "3.7" @@ -972,35 +874,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/9f/d4/029f984e8d3f3b6b726bd33cafc473b75e9e44c0f7e80a5b29abc466bdea/mkdocs_get_deps-0.2.0-py3-none-any.whl", hash = "sha256:2bf11d0b133e77a0dd036abeeb06dec8775e46efa526dc70667d8863eefc6134", size = 9521, upload-time = "2023-11-20T17:51:08.587Z" }, ] -[[package]] -name = "msgspec" -version = "0.19.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/cf/9b/95d8ce458462b8b71b8a70fa94563b2498b89933689f3a7b8911edfae3d7/msgspec-0.19.0.tar.gz", hash = "sha256:604037e7cd475345848116e89c553aa9a233259733ab51986ac924ab1b976f8e", size = 216934, upload-time = "2024-12-27T17:40:28.597Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/24/d4/2ec2567ac30dab072cce3e91fb17803c52f0a37aab6b0c24375d2b20a581/msgspec-0.19.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aa77046904db764b0462036bc63ef71f02b75b8f72e9c9dd4c447d6da1ed8f8e", size = 187939, upload-time = "2024-12-27T17:39:32.347Z" }, - { url = "https://files.pythonhosted.org/packages/2b/c0/18226e4328897f4f19875cb62bb9259fe47e901eade9d9376ab5f251a929/msgspec-0.19.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:047cfa8675eb3bad68722cfe95c60e7afabf84d1bd8938979dd2b92e9e4a9551", size = 182202, upload-time = "2024-12-27T17:39:33.633Z" }, - { url = "https://files.pythonhosted.org/packages/81/25/3a4b24d468203d8af90d1d351b77ea3cffb96b29492855cf83078f16bfe4/msgspec-0.19.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e78f46ff39a427e10b4a61614a2777ad69559cc8d603a7c05681f5a595ea98f7", size = 209029, upload-time = "2024-12-27T17:39:35.023Z" }, - { url = "https://files.pythonhosted.org/packages/85/2e/db7e189b57901955239f7689b5dcd6ae9458637a9c66747326726c650523/msgspec-0.19.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c7adf191e4bd3be0e9231c3b6dc20cf1199ada2af523885efc2ed218eafd011", size = 210682, upload-time = "2024-12-27T17:39:36.384Z" }, - { url = "https://files.pythonhosted.org/packages/03/97/7c8895c9074a97052d7e4a1cc1230b7b6e2ca2486714eb12c3f08bb9d284/msgspec-0.19.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f04cad4385e20be7c7176bb8ae3dca54a08e9756cfc97bcdb4f18560c3042063", size = 214003, upload-time = "2024-12-27T17:39:39.097Z" }, - { url = "https://files.pythonhosted.org/packages/61/61/e892997bcaa289559b4d5869f066a8021b79f4bf8e955f831b095f47a4cd/msgspec-0.19.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:45c8fb410670b3b7eb884d44a75589377c341ec1392b778311acdbfa55187716", size = 216833, upload-time = "2024-12-27T17:39:41.203Z" }, - { url = "https://files.pythonhosted.org/packages/ce/3d/71b2dffd3a1c743ffe13296ff701ee503feaebc3f04d0e75613b6563c374/msgspec-0.19.0-cp311-cp311-win_amd64.whl", hash = "sha256:70eaef4934b87193a27d802534dc466778ad8d536e296ae2f9334e182ac27b6c", size = 186184, upload-time = "2024-12-27T17:39:43.702Z" }, - { url = "https://files.pythonhosted.org/packages/b2/5f/a70c24f075e3e7af2fae5414c7048b0e11389685b7f717bb55ba282a34a7/msgspec-0.19.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f98bd8962ad549c27d63845b50af3f53ec468b6318400c9f1adfe8b092d7b62f", size = 190485, upload-time = "2024-12-27T17:39:44.974Z" }, - { url = "https://files.pythonhosted.org/packages/89/b0/1b9763938cfae12acf14b682fcf05c92855974d921a5a985ecc197d1c672/msgspec-0.19.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:43bbb237feab761b815ed9df43b266114203f53596f9b6e6f00ebd79d178cdf2", size = 183910, upload-time = "2024-12-27T17:39:46.401Z" }, - { url = "https://files.pythonhosted.org/packages/87/81/0c8c93f0b92c97e326b279795f9c5b956c5a97af28ca0fbb9fd86c83737a/msgspec-0.19.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4cfc033c02c3e0aec52b71710d7f84cb3ca5eb407ab2ad23d75631153fdb1f12", size = 210633, upload-time = "2024-12-27T17:39:49.099Z" }, - { url = "https://files.pythonhosted.org/packages/d0/ef/c5422ce8af73928d194a6606f8ae36e93a52fd5e8df5abd366903a5ca8da/msgspec-0.19.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d911c442571605e17658ca2b416fd8579c5050ac9adc5e00c2cb3126c97f73bc", size = 213594, upload-time = "2024-12-27T17:39:51.204Z" }, - { url = "https://files.pythonhosted.org/packages/19/2b/4137bc2ed45660444842d042be2cf5b18aa06efd2cda107cff18253b9653/msgspec-0.19.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:757b501fa57e24896cf40a831442b19a864f56d253679f34f260dcb002524a6c", size = 214053, upload-time = "2024-12-27T17:39:52.866Z" }, - { url = "https://files.pythonhosted.org/packages/9d/e6/8ad51bdc806aac1dc501e8fe43f759f9ed7284043d722b53323ea421c360/msgspec-0.19.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5f0f65f29b45e2816d8bded36e6b837a4bf5fb60ec4bc3c625fa2c6da4124537", size = 219081, upload-time = "2024-12-27T17:39:55.142Z" }, - { url = "https://files.pythonhosted.org/packages/b1/ef/27dd35a7049c9a4f4211c6cd6a8c9db0a50647546f003a5867827ec45391/msgspec-0.19.0-cp312-cp312-win_amd64.whl", hash = "sha256:067f0de1c33cfa0b6a8206562efdf6be5985b988b53dd244a8e06f993f27c8c0", size = 187467, upload-time = "2024-12-27T17:39:56.531Z" }, - { url = "https://files.pythonhosted.org/packages/3c/cb/2842c312bbe618d8fefc8b9cedce37f773cdc8fa453306546dba2c21fd98/msgspec-0.19.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f12d30dd6266557aaaf0aa0f9580a9a8fbeadfa83699c487713e355ec5f0bd86", size = 190498, upload-time = "2024-12-27T17:40:00.427Z" }, - { url = "https://files.pythonhosted.org/packages/58/95/c40b01b93465e1a5f3b6c7d91b10fb574818163740cc3acbe722d1e0e7e4/msgspec-0.19.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82b2c42c1b9ebc89e822e7e13bbe9d17ede0c23c187469fdd9505afd5a481314", size = 183950, upload-time = "2024-12-27T17:40:04.219Z" }, - { url = "https://files.pythonhosted.org/packages/e8/f0/5b764e066ce9aba4b70d1db8b087ea66098c7c27d59b9dd8a3532774d48f/msgspec-0.19.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19746b50be214a54239aab822964f2ac81e38b0055cca94808359d779338c10e", size = 210647, upload-time = "2024-12-27T17:40:05.606Z" }, - { url = "https://files.pythonhosted.org/packages/9d/87/bc14f49bc95c4cb0dd0a8c56028a67c014ee7e6818ccdce74a4862af259b/msgspec-0.19.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60ef4bdb0ec8e4ad62e5a1f95230c08efb1f64f32e6e8dd2ced685bcc73858b5", size = 213563, upload-time = "2024-12-27T17:40:10.516Z" }, - { url = "https://files.pythonhosted.org/packages/53/2f/2b1c2b056894fbaa975f68f81e3014bb447516a8b010f1bed3fb0e016ed7/msgspec-0.19.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac7f7c377c122b649f7545810c6cd1b47586e3aa3059126ce3516ac7ccc6a6a9", size = 213996, upload-time = "2024-12-27T17:40:12.244Z" }, - { url = "https://files.pythonhosted.org/packages/aa/5a/4cd408d90d1417e8d2ce6a22b98a6853c1b4d7cb7669153e4424d60087f6/msgspec-0.19.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a5bc1472223a643f5ffb5bf46ccdede7f9795078194f14edd69e3aab7020d327", size = 219087, upload-time = "2024-12-27T17:40:14.881Z" }, - { url = "https://files.pythonhosted.org/packages/23/d8/f15b40611c2d5753d1abb0ca0da0c75348daf1252220e5dda2867bd81062/msgspec-0.19.0-cp313-cp313-win_amd64.whl", hash = "sha256:317050bc0f7739cb30d257ff09152ca309bf5a369854bbf1e57dffc310c1f20f", size = 187432, upload-time = "2024-12-27T17:40:16.256Z" }, -] - [[package]] name = "multidict" version = "6.1.0" @@ -1055,15 +928,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/99/b7/b9e70fde2c0f0c9af4cc5277782a89b66d35948ea3369ec9f598358c3ac5/multidict-6.1.0-py3-none-any.whl", hash = "sha256:48e171e52d1c4d33888e529b999e5900356b9ae588c2f09a52dcefb158b27506", size = 10051, upload-time = "2024-09-09T23:49:36.506Z" }, ] -[[package]] -name = "multipart" -version = "1.3.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6d/c9/c6f5ab81bae667d4fe42a58df29f4c2db6ad8377cfd0e9baa729e4fa3ebb/multipart-1.3.0.tar.gz", hash = "sha256:a46bd6b0eb4c1ba865beb88ddd886012a3da709b6e7b86084fc37e99087e5cf1", size = 38816, upload-time = "2025-07-26T15:09:38.056Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9a/d6/d547a7004b81fa0b2aafa143b09196f6635e4105cd9d2c641fa8a4051c05/multipart-1.3.0-py3-none-any.whl", hash = "sha256:439bf4b00fd7cb2dbff08ae13f49f4f49798931ecd8d496372c63537fa19f304", size = 14938, upload-time = "2025-07-26T15:09:36.884Z" }, -] - [[package]] name = "mypy-extensions" version = "1.0.0" @@ -1284,30 +1148,15 @@ version = "0.1.0" source = { virtual = "examples/poet_chat" } dependencies = [ { name = "fishjam-server-sdk" }, - { name = "litestar", extra = ["standard"] }, { name = "openai-agents", extra = ["voice"] }, ] [package.metadata] requires-dist = [ { name = "fishjam-server-sdk", editable = "." }, - { name = "litestar", extras = ["standard"], specifier = ">=2.17.0" }, { name = "openai-agents", extras = ["voice"], specifier = ">=0.2.11" }, ] -[[package]] -name = "polyfactory" -version = "2.22.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "faker" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/4e/a6/950d13856d995705df33b92451559fd317207a9c43629ab1771135a0c966/polyfactory-2.22.2.tar.gz", hash = "sha256:a3297aa0b004f2b26341e903795565ae88507c4d86e68b132c2622969028587a", size = 254462, upload-time = "2025-08-15T06:23:21.28Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e7/fe/d52c90e07c458f38b26f9972a25cb011b2744813f76fcd6121dde64744fa/polyfactory-2.22.2-py3-none-any.whl", hash = "sha256:9bea58ac9a80375b4153cd60820f75e558b863e567e058794d28c6a52b84118a", size = 63715, upload-time = "2025-08-15T06:23:19.664Z" }, -] - [[package]] name = "pyasn1" version = "0.6.1" @@ -1611,20 +1460,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e3/30/3c4d035596d3cf444529e0b2953ad0466f6049528a879d27534700580395/rich-14.1.0-py3-none-any.whl", hash = "sha256:536f5f1785986d6dbdea3c75205c473f970777b4a0d6c6dd1b696aa05a3fa04f", size = 243368, upload-time = "2025-07-25T07:32:56.73Z" }, ] -[[package]] -name = "rich-click" -version = "1.8.9" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "click" }, - { name = "rich" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/b7/a8/dcc0a8ec9e91d76ecad9413a84b6d3a3310c6111cfe012d75ed385c78d96/rich_click-1.8.9.tar.gz", hash = "sha256:fd98c0ab9ddc1cf9c0b7463f68daf28b4d0033a74214ceb02f761b3ff2af3136", size = 39378, upload-time = "2025-05-19T21:33:05.569Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b6/c2/9fce4c8a9587c4e90500114d742fe8ef0fd92d7bad29d136bb9941add271/rich_click-1.8.9-py3-none-any.whl", hash = "sha256:c3fa81ed8a671a10de65a9e20abf642cfdac6fdb882db1ef465ee33919fbcfe2", size = 36082, upload-time = "2025-05-19T21:33:04.195Z" }, -] - [[package]] name = "rich-toolkit" version = "0.15.0" @@ -2059,15 +1894,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/17/69/cd203477f944c353c31bade965f880aa1061fd6bf05ded0726ca845b6ff7/typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51", size = 14552, upload-time = "2025-05-21T18:55:22.152Z" }, ] -[[package]] -name = "tzdata" -version = "2025.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/95/32/1a225d6164441be760d75c2c42e2780dc0873fe382da3e98a2e1e48361e5/tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9", size = 196380, upload-time = "2025-03-23T13:54:43.652Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/5c/23/c7abc0ca0a1526a0774eca151daeb8de62ec457e77262b66b359c3c7679e/tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8", size = 347839, upload-time = "2025-03-23T13:54:41.845Z" }, -] - [[package]] name = "urllib3" version = "1.26.20" From a673ac8d5a387dd6c101ba79f1934117b4a8414a Mon Sep 17 00:00:00 2001 From: Tomasz Mazur <47872060+AHGIJMKLKKZNPJKQR@users.noreply.github.com> Date: Fri, 26 Sep 2025 12:56:31 +0200 Subject: [PATCH 10/16] Fix readme format --- examples/poet_chat/README.md | 3 ++- examples/transcription/README.md | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/poet_chat/README.md b/examples/poet_chat/README.md index 541ce03..9c38656 100644 --- a/examples/poet_chat/README.md +++ b/examples/poet_chat/README.md @@ -7,7 +7,8 @@ The agent handles interruptions from users to ensure a natural conversation flow ## Running -> ![NOTE] All commands should be run from the parent directory of this README +> [!IMPORTANT] +> All commands should be run from the parent directory of this README Make sure to [install uv](https://docs.astral.sh/uv/getting-started/installation/) if you don't have it already. Once you have `uv` installed, fetch the dependencies with diff --git a/examples/transcription/README.md b/examples/transcription/README.md index 28e39ee..971b7f6 100644 --- a/examples/transcription/README.md +++ b/examples/transcription/README.md @@ -8,7 +8,8 @@ and uses [uv](https://docs.astral.sh/uv/) for dependency management. ## Running -> ![NOTE] All commands should be run from the parent directory of this README +> [!IMPORTANT] +> All commands should be run from the parent directory of this README Make sure to [install uv](https://docs.astral.sh/uv/getting-started/installation/) if you don't have it already. Once you have `uv` installed, fetch the dependencies with From 986a1be7e508be97bc26a1eb01b19d82518567f8 Mon Sep 17 00:00:00 2001 From: Tomasz Mazur <47872060+AHGIJMKLKKZNPJKQR@users.noreply.github.com> Date: Mon, 29 Sep 2025 09:45:52 +0200 Subject: [PATCH 11/16] Fix typo in README --- examples/poet_chat/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/poet_chat/README.md b/examples/poet_chat/README.md index 9c38656..7550982 100644 --- a/examples/poet_chat/README.md +++ b/examples/poet_chat/README.md @@ -28,7 +28,7 @@ Once you have these variables, you can run the demo with ```bash FISHJAM_ID= \ FISHJAM_MANAGEMENT_TOKEN= \ -GEMINI_API_KEY= \ +OPENAI_API_KEY= \ uv run ./main.py ``` From 8afac4b894b1c5e487bbde5e5046ff69dae65efd Mon Sep 17 00:00:00 2001 From: Tomasz Mazur <47872060+AHGIJMKLKKZNPJKQR@users.noreply.github.com> Date: Mon, 29 Sep 2025 10:01:51 +0200 Subject: [PATCH 12/16] Handle OpenAI errors --- examples/poet_chat/main.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/examples/poet_chat/main.py b/examples/poet_chat/main.py index 84e879d..6e33cd1 100644 --- a/examples/poet_chat/main.py +++ b/examples/poet_chat/main.py @@ -42,6 +42,11 @@ async def _openai_recv(): elif event.data.type == "turn_ended": print(f"Agent said:\n{msg}\n") msg = "" + elif event.data.type == "error": + print(event.data.error) + raise RuntimeError("Unexpected error from OpenAI API!") + elif event.data.type == "exception": + raise event.data.exception async def _fishjam_recv(): async for event in fishjam_session.receive(): From 899c5bb1d3ebcc61167f9ce4c37e7972df4f1a99 Mon Sep 17 00:00:00 2001 From: Tomasz Mazur <47872060+AHGIJMKLKKZNPJKQR@users.noreply.github.com> Date: Mon, 29 Sep 2025 10:08:27 +0200 Subject: [PATCH 13/16] Print raw OpenAI server errors --- examples/poet_chat/main.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/examples/poet_chat/main.py b/examples/poet_chat/main.py index 6e33cd1..f052a1e 100644 --- a/examples/poet_chat/main.py +++ b/examples/poet_chat/main.py @@ -47,6 +47,11 @@ async def _openai_recv(): raise RuntimeError("Unexpected error from OpenAI API!") elif event.data.type == "exception": raise event.data.exception + elif event.data.type == "raw_server_event": + match event.data.data: + case {"response": {"status": "failed"}}: + print(event.data.data) + raise RuntimeError("Raw server error from OpenAI API!") async def _fishjam_recv(): async for event in fishjam_session.receive(): From 88a6119fe217103c35e6ac3423e7596567873063 Mon Sep 17 00:00:00 2001 From: Tomasz Mazur <47872060+AHGIJMKLKKZNPJKQR@users.noreply.github.com> Date: Mon, 29 Sep 2025 13:37:47 +0200 Subject: [PATCH 14/16] Remove errors --- examples/poet_chat/main.py | 3 --- examples/poet_chat/poet_chat/agent.py | 2 -- 2 files changed, 5 deletions(-) diff --git a/examples/poet_chat/main.py b/examples/poet_chat/main.py index f052a1e..a77607a 100644 --- a/examples/poet_chat/main.py +++ b/examples/poet_chat/main.py @@ -42,9 +42,6 @@ async def _openai_recv(): elif event.data.type == "turn_ended": print(f"Agent said:\n{msg}\n") msg = "" - elif event.data.type == "error": - print(event.data.error) - raise RuntimeError("Unexpected error from OpenAI API!") elif event.data.type == "exception": raise event.data.exception elif event.data.type == "raw_server_event": diff --git a/examples/poet_chat/poet_chat/agent.py b/examples/poet_chat/poet_chat/agent.py index e533a2f..8d90564 100644 --- a/examples/poet_chat/poet_chat/agent.py +++ b/examples/poet_chat/poet_chat/agent.py @@ -12,8 +12,6 @@ "input_audio_format": "pcm16", "output_audio_format": "pcm16", "turn_detection": { - "interrupt_response": True, - "create_response": True, "type": "semantic_vad", }, } From 629aec7f30caf18cc50f335af521de13a8084172 Mon Sep 17 00:00:00 2001 From: Tomasz Mazur <47872060+AHGIJMKLKKZNPJKQR@users.noreply.github.com> Date: Tue, 30 Sep 2025 14:50:00 +0200 Subject: [PATCH 15/16] Use dotenv --- examples/poet_chat/.env.example | 6 ++++++ examples/poet_chat/README.md | 11 ++--------- examples/poet_chat/poet_chat/config.py | 4 ++++ 3 files changed, 12 insertions(+), 9 deletions(-) create mode 100644 examples/poet_chat/.env.example diff --git a/examples/poet_chat/.env.example b/examples/poet_chat/.env.example new file mode 100644 index 0000000..0ea80ea --- /dev/null +++ b/examples/poet_chat/.env.example @@ -0,0 +1,6 @@ +# Your Fishjam envs, which you can get at https://fishjam.io/app +FISHJAM_ID="your-fishjam-id" +FISHJAM_MANAGEMENT_TOKEN="your-management-token" + +# An API key for the OpenAI Realtime API. You can generate one at https://platform.openai.com/api-keys +OPENAI_API_KEY="your-api-key" diff --git a/examples/poet_chat/README.md b/examples/poet_chat/README.md index 7550982..a83308d 100644 --- a/examples/poet_chat/README.md +++ b/examples/poet_chat/README.md @@ -17,18 +17,11 @@ Once you have `uv` installed, fetch the dependencies with uv sync ``` -To run the app, you will need 3 environment variables: +To run the app, first copy [`.env.example`](./.env.example) to `.env` and populate your environment variables. -- `FISHJAM_ID`: Your Fishjam ID, which you can get on the [Fishjam website](https://fishjam.io/app) -- `FISHJAM_MANAGEMENT_TOKEN`: Your Fishjam management token, which you can get on the [Fishjam website](https://fishjam.io/app) -- `OPENAI_API_KEY`: An API key for the OpenAI Realtime API. You can generate one on the [OpenAI website](https://platform.openai.com/api-keys). - -Once you have these variables, you can run the demo with +Once you have populated `.env`, you can run the demo with ```bash -FISHJAM_ID= \ -FISHJAM_MANAGEMENT_TOKEN= \ -OPENAI_API_KEY= \ uv run ./main.py ``` diff --git a/examples/poet_chat/poet_chat/config.py b/examples/poet_chat/poet_chat/config.py index 1fb5a7b..eeb2625 100644 --- a/examples/poet_chat/poet_chat/config.py +++ b/examples/poet_chat/poet_chat/config.py @@ -1,8 +1,12 @@ import os from pathlib import Path +import dotenv + from fishjam import AgentOptions, AgentOutputOptions, FishjamClient +dotenv.load_dotenv() + FISHJAM_ID = os.environ["FISHJAM_ID"] FISHJAM_TOKEN = os.environ["FISHJAM_MANAGEMENT_TOKEN"] FISHJAM_URL = os.getenv("FISHJAM_URL") From f14e480c41de01a1cfe1aa7026f0531be97dbc8f Mon Sep 17 00:00:00 2001 From: Tomasz Mazur <47872060+AHGIJMKLKKZNPJKQR@users.noreply.github.com> Date: Tue, 30 Sep 2025 14:52:58 +0200 Subject: [PATCH 16/16] Make note more clear --- examples/poet_chat/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/poet_chat/README.md b/examples/poet_chat/README.md index a83308d..1c12a82 100644 --- a/examples/poet_chat/README.md +++ b/examples/poet_chat/README.md @@ -8,7 +8,7 @@ The agent handles interruptions from users to ensure a natural conversation flow ## Running > [!IMPORTANT] -> All commands should be run from the parent directory of this README +> All commands should be run from the `examples/poet_chat` directory Make sure to [install uv](https://docs.astral.sh/uv/getting-started/installation/) if you don't have it already. Once you have `uv` installed, fetch the dependencies with