shreyankisiri commited on
Commit
26751f7
·
verified ·
1 Parent(s): 385894a

Upload 3 files

Browse files
Files changed (3) hide show
  1. __init__.py +1 -0
  2. main.py +214 -0
  3. requirements.txt +300 -0
__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ # Initialize app package
main.py ADDED
@@ -0,0 +1,214 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import asyncio
2
+ import base64
3
+ import json
4
+ import os
5
+ from pathlib import Path
6
+ from typing import AsyncIterable
7
+
8
+ from dotenv import load_dotenv
9
+ from fastapi import FastAPI, Query, WebSocket
10
+ from fastapi.responses import FileResponse
11
+ from fastapi.staticfiles import StaticFiles
12
+ from google.adk.agents import LiveRequestQueue
13
+ from google.adk.agents.run_config import RunConfig
14
+ from google.adk.events.event import Event
15
+ from google.adk.runners import Runner
16
+ from google.adk.sessions.in_memory_session_service import InMemorySessionService
17
+ from google.genai import types
18
+ from jarvis.utils import root_agent
19
+
20
+ #
21
+ # ADK Streaming
22
+ #
23
+
24
+ # Load Gemini API Key
25
+ load_dotenv()
26
+
27
+ APP_NAME = "ADK Streaming example"
28
+ session_service = InMemorySessionService()
29
+
30
+
31
+ def start_agent_session(session_id, is_audio=False):
32
+ """Starts an agent session"""
33
+
34
+ # Create a Session
35
+ session = session_service.create_session(
36
+ app_name=APP_NAME,
37
+ user_id=session_id,
38
+ session_id=session_id,
39
+ )
40
+
41
+ # Create a Runner
42
+ runner = Runner(
43
+ app_name=APP_NAME,
44
+ agent=root_agent,
45
+ session_service=session_service,
46
+ )
47
+
48
+ # Set response modality
49
+ modality = "AUDIO" if is_audio else "TEXT"
50
+
51
+ # Create speech config with voice settings
52
+ speech_config = types.SpeechConfig(
53
+ voice_config=types.VoiceConfig(
54
+ # Puck, Charon, Kore, Fenrir, Aoede, Leda, Orus, and Zephyr
55
+ prebuilt_voice_config=types.PrebuiltVoiceConfig(voice_name="Puck")
56
+ )
57
+ )
58
+
59
+ # Create run config with basic settings
60
+ config = {"response_modalities": [modality], "speech_config": speech_config}
61
+
62
+ # Add output_audio_transcription when audio is enabled to get both audio and text
63
+ if is_audio:
64
+ config["output_audio_transcription"] = {}
65
+
66
+ run_config = RunConfig(**config)
67
+
68
+ # Create a LiveRequestQueue for this session
69
+ live_request_queue = LiveRequestQueue()
70
+
71
+ # Start agent session
72
+ live_events = runner.run_live(
73
+ session=session,
74
+ live_request_queue=live_request_queue,
75
+ run_config=run_config,
76
+ )
77
+ return live_events, live_request_queue
78
+
79
+
80
+ async def agent_to_client_messaging(
81
+ websocket: WebSocket, live_events: AsyncIterable[Event | None]
82
+ ):
83
+ """Agent to client communication"""
84
+ while True:
85
+ async for event in live_events:
86
+ if event is None:
87
+ continue
88
+
89
+ # If the turn complete or interrupted, send it
90
+ if event.turn_complete or event.interrupted:
91
+ message = {
92
+ "turn_complete": event.turn_complete,
93
+ "interrupted": event.interrupted,
94
+ }
95
+ await websocket.send_text(json.dumps(message))
96
+ print(f"[AGENT TO CLIENT]: {message}")
97
+ continue
98
+
99
+ # Read the Content and its first Part
100
+ part = event.content and event.content.parts and event.content.parts[0]
101
+ if not part:
102
+ continue
103
+
104
+ # Make sure we have a valid Part
105
+ if not isinstance(part, types.Part):
106
+ continue
107
+
108
+ # Only send text if it's a partial response (streaming)
109
+ # Skip the final complete message to avoid duplication
110
+ if part.text and event.partial:
111
+ message = {
112
+ "mime_type": "text/plain",
113
+ "data": part.text,
114
+ "role": "model",
115
+ }
116
+ await websocket.send_text(json.dumps(message))
117
+ print(f"[AGENT TO CLIENT]: text/plain: {part.text}")
118
+
119
+ # If it's audio, send Base64 encoded audio data
120
+ is_audio = (
121
+ part.inline_data
122
+ and part.inline_data.mime_type
123
+ and part.inline_data.mime_type.startswith("audio/pcm")
124
+ )
125
+ if is_audio:
126
+ audio_data = part.inline_data and part.inline_data.data
127
+ if audio_data:
128
+ message = {
129
+ "mime_type": "audio/pcm",
130
+ "data": base64.b64encode(audio_data).decode("ascii"),
131
+ "role": "model",
132
+ }
133
+ await websocket.send_text(json.dumps(message))
134
+ print(f"[AGENT TO CLIENT]: audio/pcm: {len(audio_data)} bytes.")
135
+
136
+
137
+ async def client_to_agent_messaging(
138
+ websocket: WebSocket, live_request_queue: LiveRequestQueue
139
+ ):
140
+ """Client to agent communication"""
141
+ while True:
142
+ # Decode JSON message
143
+ message_json = await websocket.receive_text()
144
+ message = json.loads(message_json)
145
+ mime_type = message["mime_type"]
146
+ data = message["data"]
147
+ role = message.get("role", "user") # Default to 'user' if role is not provided
148
+
149
+ # Send the message to the agent
150
+ if mime_type == "text/plain":
151
+ # Send a text message
152
+ content = types.Content(role=role, parts=[types.Part.from_text(text=data)])
153
+ live_request_queue.send_content(content=content)
154
+ print(f"[CLIENT TO AGENT PRINT]: {data}")
155
+ elif mime_type == "audio/pcm":
156
+ # Send audio data
157
+ decoded_data = base64.b64decode(data)
158
+
159
+ # Send the audio data - note that ActivityStart/End and transcription
160
+ # handling is done automatically by the ADK when input_audio_transcription
161
+ # is enabled in the config
162
+ live_request_queue.send_realtime(
163
+ types.Blob(data=decoded_data, mime_type=mime_type)
164
+ )
165
+ print(f"[CLIENT TO AGENT]: audio/pcm: {len(decoded_data)} bytes")
166
+
167
+ else:
168
+ raise ValueError(f"Mime type not supported: {mime_type}")
169
+
170
+
171
+ #
172
+ # FastAPI web app
173
+ #
174
+
175
+ app = FastAPI()
176
+
177
+ STATIC_DIR = Path("static")
178
+ app.mount("/static", StaticFiles(directory=STATIC_DIR), name="static")
179
+
180
+
181
+ @app.get("/")
182
+ async def root():
183
+ """Serves the index.html"""
184
+ return FileResponse(os.path.join(STATIC_DIR, "index.html"))
185
+
186
+
187
+ @app.websocket("/ws/{session_id}")
188
+ async def websocket_endpoint(
189
+ websocket: WebSocket,
190
+ session_id: str,
191
+ is_audio: str = Query(...),
192
+ ):
193
+ """Client websocket endpoint"""
194
+
195
+ # Wait for client connection
196
+ await websocket.accept()
197
+ print(f"Client #{session_id} connected, audio mode: {is_audio}")
198
+
199
+ # Start agent session
200
+ live_events, live_request_queue = start_agent_session(
201
+ session_id, is_audio == "true"
202
+ )
203
+
204
+ # Start tasks
205
+ agent_to_client_task = asyncio.create_task(
206
+ agent_to_client_messaging(websocket, live_events)
207
+ )
208
+ client_to_agent_task = asyncio.create_task(
209
+ client_to_agent_messaging(websocket, live_request_queue)
210
+ )
211
+ await asyncio.gather(agent_to_client_task, client_to_agent_task)
212
+
213
+ # Disconnected
214
+ print(f"Client #{session_id} disconnected")
requirements.txt ADDED
@@ -0,0 +1,300 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ aiofiles==24.1.0
2
+ aiohappyeyeballs==2.6.1
3
+ aiohttp==3.11.18
4
+ aiosignal==1.3.2
5
+ aiosqlite==0.21.0
6
+ altair==5.5.0
7
+ annotated-types==0.7.0
8
+ anyio==4.9.0
9
+ asgiref==3.8.1
10
+ #asttokens @ file:///home/conda/feedstock_root/build_artifacts/asttokens_1733250440834/work
11
+ attrs==25.3.0
12
+ Authlib==1.5.2
13
+ backcall==0.2.0
14
+ backoff==2.2.1
15
+ bcrypt==4.3.0
16
+ beautifulsoup4==4.13.4
17
+ bleach==6.2.0
18
+ blinker==1.9.0
19
+ Brotli==1.1.0
20
+ build==1.2.2.post1
21
+ cachetools==5.5.2
22
+ certifi==2025.4.26
23
+ cffi==1.17.1
24
+ chardet==5.2.0
25
+ charset-normalizer==3.4.2
26
+ chromadb==1.0.12
27
+ click==8.2.0
28
+ colorama==0.4.6
29
+ coloredlogs==15.0.1
30
+ colorthief==0.2.1
31
+ #comm @ file:///home/conda/feedstock_root/build_artifacts/comm_1733502965406/work
32
+ Crawl4AI==0.6.3
33
+ cryptography==44.0.3
34
+ cssselect==1.3.0
35
+ cssselect2==0.8.0
36
+ curl_cffi==0.11.1
37
+ dataclasses-json==0.6.7
38
+ #debugpy @ file:///home/conda/feedstock_root/build_artifacts/debugpy_1744321234906/work
39
+ #decorator @ file:///home/conda/feedstock_root/build_artifacts/decorator_1740384970518/work
40
+ defusedxml==0.7.1
41
+ Deprecated==1.2.18
42
+ distro==1.9.0
43
+ docopt==0.6.2
44
+ docstring_parser==0.16
45
+ docx==0.2.4
46
+ docx2txt==0.9
47
+ dotenv==0.9.9
48
+ durationpy==0.10
49
+ #exceptiongroup @ file:///home/conda/feedstock_root/build_artifacts/exceptiongroup_1746947292760/work
50
+ #executing @ file:///home/conda/feedstock_root/build_artifacts/executing_1745502089858/work
51
+ fake-http-header==0.3.5
52
+ fake-useragent==2.2.0
53
+ fastapi==0.115.9
54
+ fastjsonschema==2.21.1
55
+ filelock==3.18.0
56
+ filetype==1.2.0
57
+ flatbuffers==25.2.10
58
+ fonttools==4.58.2
59
+ frozendict==2.4.6
60
+ frozenlist==1.6.0
61
+ fsspec==2025.5.1
62
+ gitdb==4.0.12
63
+ GitPython==3.1.44
64
+ google-adk==0.5.0
65
+ google-ai-generativelanguage==0.6.15
66
+ google-api-core==2.24.2
67
+ google-api-python-client==2.169.0
68
+ google-auth==2.40.1
69
+ google-auth-httplib2==0.2.0
70
+ google-cloud-aiplatform==1.92.0
71
+ google-cloud-bigquery==3.32.0
72
+ google-cloud-core==2.4.3
73
+ google-cloud-resource-manager==1.14.2
74
+ google-cloud-secret-manager==2.23.3
75
+ google-cloud-speech==2.32.0
76
+ google-cloud-storage==2.19.0
77
+ google-cloud-trace==1.16.1
78
+ google-crc32c==1.7.1
79
+ google-genai==1.15.0
80
+ google-generativeai==0.8.5
81
+ google-resumable-media==2.7.2
82
+ googleapis-common-protos==1.70.0
83
+ grandalf==0.8
84
+ graphviz==0.20.3
85
+ greenlet==3.2.2
86
+ groq==0.28.0
87
+ grpc-google-iam-v1==0.14.2
88
+ grpcio==1.71.0
89
+ grpcio-status==1.71.0
90
+ h11==0.16.0
91
+ httpcore==1.0.9
92
+ httplib2==0.22.0
93
+ httptools==0.6.4
94
+ httpx==0.28.1
95
+ httpx-sse==0.4.0
96
+ huggingface-hub==0.31.2
97
+ humanfriendly==10.0
98
+ humanize==4.12.3
99
+ idna==3.10
100
+ #importlib_metadata @ file:///home/conda/feedstock_root/build_artifacts/importlib-metadata_1737420181517/work
101
+ importlib_resources==6.5.2
102
+ #ipykernel @ file:///home/conda/feedstock_root/build_artifacts/ipykernel_1719845459717/work
103
+ ipython==8.12.3
104
+ #ipython_pygments_lexers @ file:///home/conda/feedstock_root/build_artifacts/ipython_pygments_lexers_1737123620466/work
105
+ #jedi @ file:///home/conda/feedstock_root/build_artifacts/jedi_1733300866624/work
106
+ Jinja2==3.1.6
107
+ jiter==0.9.0
108
+ joblib==1.5.1
109
+ jsonpatch==1.33
110
+ jsonpointer==3.0.0
111
+ jsonschema==4.23.0
112
+ jsonschema-specifications==2025.4.1
113
+ #jupyter_client @ file:///home/conda/feedstock_root/build_artifacts/jupyter_client_1733440914442/work
114
+ #jupyter_core @ file:///home/conda/feedstock_root/build_artifacts/jupyter_core_1727163409502/work
115
+ jupyterlab_pygments==0.3.0
116
+ kubernetes==33.1.0
117
+ langchain==0.3.25
118
+ langchain-chroma==0.2.4
119
+ langchain-community==0.3.25
120
+ langchain-core==0.3.65
121
+ langchain-google-genai==2.0.10
122
+ langchain-groq==0.3.2
123
+ langchain-huggingface==0.3.0
124
+ langchain-text-splitters==0.3.8
125
+ langgraph==0.4.8
126
+ langgraph-checkpoint==2.0.26
127
+ langgraph-cli==0.3.3
128
+ langgraph-prebuilt==0.2.2
129
+ langgraph-sdk==0.1.70
130
+ langsmith==0.3.45
131
+ litellm==1.69.3
132
+ lxml==5.4.0
133
+ markdown-it-py==3.0.0
134
+ MarkupSafe==3.0.2
135
+ marshmallow==3.26.1
136
+ matplotlib-#inline @ file:///home/conda/feedstock_root/build_artifacts/matplotlib-inline_1733416936468/work
137
+ mcp==1.8.1
138
+ mdurl==0.1.2
139
+ mistune==3.1.3
140
+ mmh3==5.1.0
141
+ mpmath==1.3.0
142
+ multidict==6.4.3
143
+ multitasking==0.0.11
144
+ mypy_extensions==1.1.0
145
+ narwhals==1.41.0
146
+ nbclient==0.10.2
147
+ nbconvert==7.16.6
148
+ nbformat==5.10.4
149
+ #nest_asyncio @ file:///home/conda/feedstock_root/build_artifacts/nest-asyncio_1733325553580/work
150
+ networkx==3.5
151
+ nltk==3.9.1
152
+ numpy==2.2.5
153
+ nvidia-cublas-cu12==12.6.4.1
154
+ nvidia-cuda-cupti-cu12==12.6.80
155
+ nvidia-cuda-nvrtc-cu12==12.6.77
156
+ nvidia-cuda-runtime-cu12==12.6.77
157
+ nvidia-cudnn-cu12==9.5.1.17
158
+ nvidia-cufft-cu12==11.3.0.4
159
+ nvidia-cufile-cu12==1.11.1.6
160
+ nvidia-curand-cu12==10.3.7.77
161
+ nvidia-cusolver-cu12==11.7.1.2
162
+ nvidia-cusparse-cu12==12.5.4.2
163
+ nvidia-cusparselt-cu12==0.6.3
164
+ nvidia-nccl-cu12==2.26.2
165
+ nvidia-nvjitlink-cu12==12.6.85
166
+ nvidia-nvtx-cu12==12.6.77
167
+ oauthlib==3.2.2
168
+ onnxruntime==1.22.0
169
+ openai==1.75.0
170
+ opentelemetry-api==1.33.0
171
+ opentelemetry-exporter-gcp-trace==1.9.0
172
+ opentelemetry-exporter-otlp-proto-common==1.33.0
173
+ opentelemetry-exporter-otlp-proto-grpc==1.33.0
174
+ opentelemetry-instrumentation==0.54b0
175
+ opentelemetry-instrumentation-asgi==0.54b0
176
+ opentelemetry-instrumentation-fastapi==0.54b0
177
+ opentelemetry-proto==1.33.0
178
+ opentelemetry-resourcedetector-gcp==1.9.0a0
179
+ opentelemetry-sdk==1.33.0
180
+ opentelemetry-semantic-conventions==0.54b0
181
+ opentelemetry-util-http==0.54b0
182
+ orjson==3.10.18
183
+ ormsgpack==1.10.0
184
+ overrides==7.7.0
185
+ packaging==24.2
186
+ pandas==2.2.3
187
+ pandocfilters==1.5.1
188
+ #parso @ file:///home/conda/feedstock_root/build_artifacts/parso_1733271261340/work
189
+ pdf2image==1.17.0
190
+ pdfkit==1.0.0
191
+ peewee==3.18.1
192
+ #pexpect @ file:///home/conda/feedstock_root/build_artifacts/pexpect_1733301927746/work
193
+ #pickleshare @ file:///home/conda/feedstock_root/build_artifacts/pickleshare_1733327343728/work
194
+ pillow==10.4.0
195
+ pipreqs==0.4.13
196
+ #platformdirs @ file:///home/conda/feedstock_root/build_artifacts/bld/rattler-build_platformdirs_1746710438/work
197
+ playwright==1.52.0
198
+ posthog==4.10.0
199
+ #prompt_toolkit @ file:///home/conda/feedstock_root/build_artifacts/prompt-toolkit_1744724089886/work
200
+ propcache==0.3.1
201
+ proto-plus==1.26.1
202
+ protobuf==5.29.4
203
+ #psutil @ file:///home/conda/feedstock_root/build_artifacts/psutil_1740663131878/work
204
+ #ptyprocess @ file:///home/conda/feedstock_root/build_artifacts/ptyprocess_1733302279685/work/dist/ptyprocess-0.7.0-py2.py3-none-any.whl#sha256=92c32ff62b5fd8cf325bec5ab90d7be3d2a8ca8c8a3813ff487a8d2002630d1f
205
+ #pure_eval @ file:///home/conda/feedstock_root/build_artifacts/pure_eval_1733569405015/work
206
+ pyarrow==20.0.0
207
+ pyasn1==0.6.1
208
+ pyasn1_modules==0.4.2
209
+ pycparser==2.22
210
+ pydantic==2.11.4
211
+ pydantic-settings==2.9.1
212
+ pydantic_core==2.33.2
213
+ pydeck==0.9.1
214
+ pydyf==0.11.0
215
+ pyee==13.0.0
216
+ #Pygments @ file:///home/conda/feedstock_root/build_artifacts/pygments_1736243443484/work
217
+ pyOpenSSL==25.1.0
218
+ pyparsing==3.2.3
219
+ pypdf==5.6.0
220
+ pyperclip==1.9.0
221
+ pyphen==0.17.2
222
+ PyPika==0.48.9
223
+ pyproject_hooks==1.2.0
224
+ python-#dateutil @ file:///home/conda/feedstock_root/build_artifacts/python-dateutil_1733215673016/work
225
+ python-docx==1.2.0
226
+ python-dotenv==1.1.0
227
+ python-multipart==0.0.20
228
+ python-pptx==1.0.2
229
+ pytz==2025.2
230
+ PyYAML==6.0.2
231
+ #pyzmq @ file:///home/conda/feedstock_root/build_artifacts/pyzmq_1743831247381/work
232
+ rank-bm25==0.2.2
233
+ referencing==0.36.2
234
+ regex==2024.11.6
235
+ requests==2.32.3
236
+ requests-oauthlib==2.0.0
237
+ requests-toolbelt==1.0.0
238
+ rich==14.0.0
239
+ rpds-py==0.25.0
240
+ rsa==4.9.1
241
+ safetensors==0.5.3
242
+ scikit-learn==1.7.0
243
+ scipy==1.15.3
244
+ sentence-transformers==4.1.0
245
+ setuptools==80.9.0
246
+ shapely==2.1.0
247
+ shellingham==1.5.4
248
+ #six @ file:///home/conda/feedstock_root/build_artifacts/six_1733380938961/work
249
+ smmap==5.0.2
250
+ sniffio==1.3.1
251
+ snowballstemmer==2.2.0
252
+ soupsieve==2.7
253
+ SQLAlchemy==2.0.41
254
+ sse-starlette==2.3.5
255
+ #stack_data @ file:///home/conda/feedstock_root/build_artifacts/stack_data_1733569443808/work
256
+ starlette==0.45.3
257
+ streamlit==1.45.1
258
+ sympy==1.14.0
259
+ tenacity==9.1.2
260
+ tf-playwright-stealth==1.1.2
261
+ threadpoolctl==3.6.0
262
+ tiktoken==0.9.0
263
+ tinycss2==1.4.0
264
+ tinyhtml5==2.0.0
265
+ tokenizers==0.21.1
266
+ toml==0.10.2
267
+ torch==2.7.1
268
+ #tornado @ file:///home/conda/feedstock_root/build_artifacts/tornado_1747384461250/work
269
+ tqdm==4.67.1
270
+ #traitlets @ file:///home/conda/feedstock_root/build_artifacts/traitlets_1733367359838/work
271
+ transformers==4.52.4
272
+ triton==3.3.1
273
+ typer==0.16.0
274
+ typing-inspect==0.9.0
275
+ typing-inspection==0.4.0
276
+ typing_extensions==4.14.0
277
+ tzdata==2025.2
278
+ tzlocal==5.3.1
279
+ uritemplate==4.1.1
280
+ urllib3==2.4.0
281
+ uv==0.7.3
282
+ uvicorn==0.34.2
283
+ uvloop==0.21.0
284
+ watchdog==6.0.0
285
+ watchfiles==1.1.0
286
+ #wcwidth @ file:///home/conda/feedstock_root/build_artifacts/wcwidth_1733231326287/work
287
+ weasyprint==65.1
288
+ webencodings==0.5.1
289
+ websocket-client==1.8.0
290
+ websockets==15.0.1
291
+ wheel==0.45.1
292
+ wrapt==1.17.2
293
+ XlsxWriter==3.2.3
294
+ xxhash==3.5.0
295
+ yarg==0.1.9
296
+ yarl==1.20.0
297
+ yfinance==0.2.61
298
+ #zipp @ file:///home/conda/feedstock_root/build_artifacts/zipp_1732827521216/work
299
+ zopfli==0.2.3.post1
300
+ zstandard==0.23.0