agno 1.7.8__py3-none-any.whl → 1.7.10__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agno/agent/agent.py +33 -27
- agno/document/reader/pdf_reader.py +302 -143
- agno/knowledge/agent.py +68 -72
- agno/knowledge/pdf.py +32 -8
- agno/knowledge/pdf_url.py +13 -5
- agno/models/openai/responses.py +30 -1
- agno/run/response.py +10 -0
- agno/run/team.py +10 -0
- agno/team/team.py +39 -20
- agno/tools/aws_lambda.py +10 -0
- agno/tools/github.py +54 -18
- agno/vectordb/lancedb/lance_db.py +10 -2
- agno/vectordb/pgvector/pgvector.py +3 -0
- agno/vectordb/weaviate/weaviate.py +84 -18
- {agno-1.7.8.dist-info → agno-1.7.10.dist-info}/METADATA +2 -1
- {agno-1.7.8.dist-info → agno-1.7.10.dist-info}/RECORD +20 -20
- {agno-1.7.8.dist-info → agno-1.7.10.dist-info}/WHEEL +0 -0
- {agno-1.7.8.dist-info → agno-1.7.10.dist-info}/entry_points.txt +0 -0
- {agno-1.7.8.dist-info → agno-1.7.10.dist-info}/licenses/LICENSE +0 -0
- {agno-1.7.8.dist-info → agno-1.7.10.dist-info}/top_level.txt +0 -0
agno/team/team.py
CHANGED
|
@@ -310,6 +310,7 @@ class Team:
|
|
|
310
310
|
model: Optional[Model] = None,
|
|
311
311
|
name: Optional[str] = None,
|
|
312
312
|
team_id: Optional[str] = None,
|
|
313
|
+
role: Optional[str] = None,
|
|
313
314
|
user_id: Optional[str] = None,
|
|
314
315
|
session_id: Optional[str] = None,
|
|
315
316
|
session_name: Optional[str] = None,
|
|
@@ -390,6 +391,7 @@ class Team:
|
|
|
390
391
|
|
|
391
392
|
self.name = name
|
|
392
393
|
self.team_id = team_id
|
|
394
|
+
self.role = role
|
|
393
395
|
|
|
394
396
|
self.user_id = user_id
|
|
395
397
|
self.session_id = session_id
|
|
@@ -1110,16 +1112,21 @@ class Team:
|
|
|
1110
1112
|
response_format=response_format,
|
|
1111
1113
|
stream_intermediate_steps=stream_intermediate_steps,
|
|
1112
1114
|
):
|
|
1113
|
-
from agno.run.team import RunResponseContentEvent
|
|
1115
|
+
from agno.run.team import IntermediateRunResponseContentEvent, RunResponseContentEvent
|
|
1114
1116
|
|
|
1115
1117
|
if isinstance(event, RunResponseContentEvent):
|
|
1116
1118
|
if stream_intermediate_steps:
|
|
1117
|
-
yield
|
|
1119
|
+
yield IntermediateRunResponseContentEvent(
|
|
1120
|
+
content=event.content,
|
|
1121
|
+
content_type=event.content_type,
|
|
1122
|
+
)
|
|
1118
1123
|
else:
|
|
1119
1124
|
yield event
|
|
1120
1125
|
|
|
1121
1126
|
yield from self._generate_response_with_output_model_stream(
|
|
1122
|
-
run_response=run_response,
|
|
1127
|
+
run_response=run_response,
|
|
1128
|
+
run_messages=run_messages,
|
|
1129
|
+
stream_intermediate_steps=stream_intermediate_steps,
|
|
1123
1130
|
)
|
|
1124
1131
|
|
|
1125
1132
|
# If a parser model is provided, structure the response separately
|
|
@@ -1519,19 +1526,28 @@ class Team:
|
|
|
1519
1526
|
):
|
|
1520
1527
|
yield event
|
|
1521
1528
|
else:
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
async for event in self._agenerate_response_with_output_model_stream(
|
|
1529
|
+
async for event in self._ahandle_model_response_stream(
|
|
1525
1530
|
run_response=run_response,
|
|
1526
1531
|
run_messages=run_messages,
|
|
1532
|
+
response_format=response_format,
|
|
1527
1533
|
stream_intermediate_steps=stream_intermediate_steps,
|
|
1528
1534
|
):
|
|
1535
|
+
from agno.run.team import IntermediateRunResponseContentEvent, RunResponseContentEvent
|
|
1536
|
+
|
|
1529
1537
|
if isinstance(event, RunResponseContentEvent):
|
|
1530
1538
|
if stream_intermediate_steps:
|
|
1531
|
-
yield
|
|
1539
|
+
yield IntermediateRunResponseContentEvent(
|
|
1540
|
+
content=event.content,
|
|
1541
|
+
content_type=event.content_type,
|
|
1542
|
+
)
|
|
1532
1543
|
else:
|
|
1533
1544
|
yield event
|
|
1534
1545
|
|
|
1546
|
+
async for event in self._agenerate_response_with_output_model_stream(
|
|
1547
|
+
run_response=run_response,
|
|
1548
|
+
run_messages=run_messages,
|
|
1549
|
+
stream_intermediate_steps=stream_intermediate_steps,
|
|
1550
|
+
):
|
|
1535
1551
|
yield event
|
|
1536
1552
|
|
|
1537
1553
|
# If a parser model is provided, structure the response separately
|
|
@@ -2446,10 +2462,9 @@ class Team:
|
|
|
2446
2462
|
model_response.content = output_model_response.content
|
|
2447
2463
|
|
|
2448
2464
|
def _generate_response_with_output_model_stream(
|
|
2449
|
-
self, run_response: TeamRunResponse, run_messages: RunMessages, stream_intermediate_steps: bool =
|
|
2465
|
+
self, run_response: TeamRunResponse, run_messages: RunMessages, stream_intermediate_steps: bool = False
|
|
2450
2466
|
):
|
|
2451
2467
|
"""Parse the model response using the output model stream."""
|
|
2452
|
-
|
|
2453
2468
|
from agno.utils.events import (
|
|
2454
2469
|
create_team_output_model_response_completed_event,
|
|
2455
2470
|
create_team_output_model_response_started_event,
|
|
@@ -2497,7 +2512,7 @@ class Team:
|
|
|
2497
2512
|
model_response.content = output_model_response.content
|
|
2498
2513
|
|
|
2499
2514
|
async def _agenerate_response_with_output_model_stream(
|
|
2500
|
-
self, run_response: TeamRunResponse, run_messages: RunMessages, stream_intermediate_steps: bool =
|
|
2515
|
+
self, run_response: TeamRunResponse, run_messages: RunMessages, stream_intermediate_steps: bool = False
|
|
2501
2516
|
):
|
|
2502
2517
|
"""Parse the model response using the output model stream."""
|
|
2503
2518
|
from agno.utils.events import (
|
|
@@ -2514,9 +2529,7 @@ class Team:
|
|
|
2514
2529
|
messages_for_output_model = self.get_messages_for_output_model(run_messages.messages)
|
|
2515
2530
|
model_response = ModelResponse(content="")
|
|
2516
2531
|
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
async for model_response_event in model_response_stream:
|
|
2532
|
+
async for model_response_event in self.output_model.aresponse_stream(messages=messages_for_output_model):
|
|
2520
2533
|
for event in self._handle_model_response_chunk(
|
|
2521
2534
|
run_response=run_response,
|
|
2522
2535
|
full_model_response=model_response,
|
|
@@ -5442,6 +5455,10 @@ class Team:
|
|
|
5442
5455
|
if self.description is not None:
|
|
5443
5456
|
system_message_content += f"<description>\n{self.description}\n</description>\n\n"
|
|
5444
5457
|
|
|
5458
|
+
# 3.3.4 Then add the Team role if provided
|
|
5459
|
+
if self.role is not None:
|
|
5460
|
+
system_message_content += f"\n<your_role>\n{self.role}\n</your_role>\n\n"
|
|
5461
|
+
|
|
5445
5462
|
# 3.3.5 Then add instructions for the Agent
|
|
5446
5463
|
if len(instructions) > 0:
|
|
5447
5464
|
system_message_content += "<instructions>"
|
|
@@ -5634,7 +5651,7 @@ class Team:
|
|
|
5634
5651
|
if isinstance(message, str):
|
|
5635
5652
|
user_message_content = message
|
|
5636
5653
|
else:
|
|
5637
|
-
user_message_content = "\n".join(message)
|
|
5654
|
+
user_message_content = "\n".join(str(message))
|
|
5638
5655
|
|
|
5639
5656
|
# Add references to user message
|
|
5640
5657
|
if (
|
|
@@ -7141,9 +7158,10 @@ class Team:
|
|
|
7141
7158
|
# If the team_session_state is already set, merge the team_session_state from the database with the current team_session_state
|
|
7142
7159
|
if self.team_session_state is not None and len(self.team_session_state) > 0:
|
|
7143
7160
|
# This updates team_session_state_from_db
|
|
7144
|
-
merge_dictionaries(
|
|
7145
|
-
|
|
7146
|
-
|
|
7161
|
+
merge_dictionaries(self.team_session_state, team_session_state_from_db)
|
|
7162
|
+
else:
|
|
7163
|
+
# Update the current team_session_state
|
|
7164
|
+
self.team_session_state = team_session_state_from_db
|
|
7147
7165
|
|
|
7148
7166
|
if "workflow_session_state" in session.session_data:
|
|
7149
7167
|
workflow_session_state_from_db = session.session_data.get("workflow_session_state")
|
|
@@ -7155,9 +7173,10 @@ class Team:
|
|
|
7155
7173
|
# If the workflow_session_state is already set, merge the workflow_session_state from the database with the current workflow_session_state
|
|
7156
7174
|
if self.workflow_session_state is not None and len(self.workflow_session_state) > 0:
|
|
7157
7175
|
# This updates workflow_session_state_from_db
|
|
7158
|
-
merge_dictionaries(
|
|
7159
|
-
|
|
7160
|
-
|
|
7176
|
+
merge_dictionaries(self.workflow_session_state, workflow_session_state_from_db)
|
|
7177
|
+
else:
|
|
7178
|
+
# Update the current workflow_session_state
|
|
7179
|
+
self.workflow_session_state = workflow_session_state_from_db
|
|
7161
7180
|
|
|
7162
7181
|
# Get the session_metrics from the database
|
|
7163
7182
|
if "session_metrics" in session.session_data:
|
agno/tools/aws_lambda.py
CHANGED
|
@@ -26,6 +26,9 @@ class AWSLambdaTools(Toolkit):
|
|
|
26
26
|
super().__init__(name="aws-lambda", tools=tools, **kwargs)
|
|
27
27
|
|
|
28
28
|
def list_functions(self) -> str:
|
|
29
|
+
"""
|
|
30
|
+
List all AWS Lambda functions in the configured AWS account.
|
|
31
|
+
"""
|
|
29
32
|
try:
|
|
30
33
|
response = self.client.list_functions()
|
|
31
34
|
functions = [func["FunctionName"] for func in response["Functions"]]
|
|
@@ -34,6 +37,13 @@ class AWSLambdaTools(Toolkit):
|
|
|
34
37
|
return f"Error listing functions: {str(e)}"
|
|
35
38
|
|
|
36
39
|
def invoke_function(self, function_name: str, payload: str = "{}") -> str:
|
|
40
|
+
"""
|
|
41
|
+
Invoke a specific AWS Lambda function with an optional JSON payload.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
function_name (str): The name of the Lambda function to invoke.
|
|
45
|
+
payload (str): The JSON payload to send to the function. Defaults to "{}".
|
|
46
|
+
"""
|
|
37
47
|
try:
|
|
38
48
|
response = self.client.invoke(FunctionName=function_name, Payload=payload)
|
|
39
49
|
return f"Function invoked successfully. Status code: {response['StatusCode']}, Payload: {response['Payload'].read().decode('utf-8')}"
|
agno/tools/github.py
CHANGED
|
@@ -458,35 +458,71 @@ class GithubTools(Toolkit):
|
|
|
458
458
|
logger.error(f"Error creating issue: {e}")
|
|
459
459
|
return json.dumps({"error": str(e)})
|
|
460
460
|
|
|
461
|
-
def list_issues(self, repo_name: str, state: str = "open",
|
|
462
|
-
"""List issues for a repository.
|
|
461
|
+
def list_issues(self, repo_name: str, state: str = "open", page: int = 1, per_page: int = 20) -> str:
|
|
462
|
+
"""List issues for a repository with pagination.
|
|
463
463
|
|
|
464
464
|
Args:
|
|
465
465
|
repo_name (str): The full name of the repository (e.g., 'owner/repo').
|
|
466
466
|
state (str, optional): The state of issues to list ('open', 'closed', 'all'). Defaults to 'open'.
|
|
467
|
-
|
|
467
|
+
page (int, optional): Page number of results to return, counting from 1. Defaults to 1.
|
|
468
|
+
per_page (int, optional): Number of results per page. Defaults to 20.
|
|
468
469
|
Returns:
|
|
469
|
-
A JSON-formatted string containing a list of issues.
|
|
470
|
+
A JSON-formatted string containing a list of issues with pagination metadata.
|
|
470
471
|
"""
|
|
471
|
-
log_debug(f"Listing issues for repository: {repo_name} with state: {state}")
|
|
472
|
+
log_debug(f"Listing issues for repository: {repo_name} with state: {state}, page: {page}, per_page: {per_page}")
|
|
472
473
|
try:
|
|
473
474
|
repo = self.g.get_repo(repo_name)
|
|
475
|
+
|
|
474
476
|
issues = repo.get_issues(state=state)
|
|
477
|
+
|
|
475
478
|
# Filter out pull requests after fetching issues
|
|
476
|
-
|
|
477
|
-
|
|
479
|
+
total_issues = 0
|
|
480
|
+
all_issues = []
|
|
481
|
+
for issue in issues:
|
|
482
|
+
if not issue.pull_request:
|
|
483
|
+
all_issues.append(issue)
|
|
484
|
+
total_issues += 1
|
|
485
|
+
|
|
486
|
+
# Calculate pagination metadata
|
|
487
|
+
total_pages = (total_issues + per_page - 1) // per_page
|
|
488
|
+
|
|
489
|
+
# Validate page number
|
|
490
|
+
if page < 1:
|
|
491
|
+
page = 1
|
|
492
|
+
elif page > total_pages and total_pages > 0:
|
|
493
|
+
page = total_pages
|
|
494
|
+
|
|
495
|
+
# Get the specified page of results
|
|
478
496
|
issue_list = []
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
497
|
+
page_start = (page - 1) * per_page
|
|
498
|
+
page_end = page_start + per_page
|
|
499
|
+
|
|
500
|
+
for i in range(page_start, min(page_end, total_issues)):
|
|
501
|
+
if i < len(all_issues):
|
|
502
|
+
issue = all_issues[i]
|
|
503
|
+
issue_info = {
|
|
504
|
+
"number": issue.number,
|
|
505
|
+
"title": issue.title,
|
|
506
|
+
"user": issue.user.login,
|
|
507
|
+
"created_at": issue.created_at.isoformat(),
|
|
508
|
+
"state": issue.state,
|
|
509
|
+
"url": issue.html_url,
|
|
510
|
+
}
|
|
511
|
+
issue_list.append(issue_info)
|
|
512
|
+
|
|
513
|
+
meta = {
|
|
514
|
+
"current_page": page,
|
|
515
|
+
"per_page": per_page,
|
|
516
|
+
"total_items": total_issues,
|
|
517
|
+
"total_pages": total_pages
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
response = {
|
|
521
|
+
"data": issue_list,
|
|
522
|
+
"meta": meta
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
return json.dumps(response, indent=2)
|
|
490
526
|
except GithubException as e:
|
|
491
527
|
logger.error(f"Error listing issues: {e}")
|
|
492
528
|
return json.dumps({"error": str(e)})
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import json
|
|
2
2
|
from hashlib import md5
|
|
3
|
+
from os import getenv
|
|
3
4
|
from typing import Any, Dict, List, Optional
|
|
4
5
|
|
|
5
6
|
try:
|
|
@@ -74,9 +75,12 @@ class LanceDb(VectorDb):
|
|
|
74
75
|
# Distance metric
|
|
75
76
|
self.distance: Distance = distance
|
|
76
77
|
|
|
78
|
+
# Remote LanceDB connection details
|
|
79
|
+
self.api_key: Optional[str] = api_key
|
|
80
|
+
|
|
77
81
|
# LanceDB connection details
|
|
78
82
|
self.uri: lancedb.URI = uri
|
|
79
|
-
self.connection: lancedb.
|
|
83
|
+
self.connection: lancedb.DBConnection = connection or lancedb.connect(uri=self.uri, api_key=api_key)
|
|
80
84
|
self.table: Optional[lancedb.db.LanceTable] = table
|
|
81
85
|
|
|
82
86
|
self.async_connection: Optional[lancedb.AsyncConnection] = async_connection
|
|
@@ -168,7 +172,11 @@ class LanceDb(VectorDb):
|
|
|
168
172
|
schema = self._base_schema()
|
|
169
173
|
|
|
170
174
|
log_info(f"Creating table: {self.table_name}")
|
|
171
|
-
|
|
175
|
+
if self.api_key or getenv("LANCEDB_API_KEY"):
|
|
176
|
+
log_info("API key found, creating table in remote LanceDB")
|
|
177
|
+
tbl = self.connection.create_table(name=self.table_name, schema=schema, mode="overwrite") # type: ignore
|
|
178
|
+
else:
|
|
179
|
+
tbl = self.connection.create_table(name=self.table_name, schema=schema, mode="overwrite", exist_ok=True) # type: ignore
|
|
172
180
|
return tbl # type: ignore
|
|
173
181
|
|
|
174
182
|
def doc_exists(self, document: Document) -> bool:
|
|
@@ -766,6 +766,9 @@ class PgVector(VectorDb):
|
|
|
766
766
|
)
|
|
767
767
|
)
|
|
768
768
|
|
|
769
|
+
if self.reranker:
|
|
770
|
+
search_results = self.reranker.rerank(query=query, documents=search_results)
|
|
771
|
+
|
|
769
772
|
log_info(f"Found {len(search_results)} documents")
|
|
770
773
|
return search_results
|
|
771
774
|
except Exception as e:
|
|
@@ -2,7 +2,7 @@ import json
|
|
|
2
2
|
import uuid
|
|
3
3
|
from hashlib import md5
|
|
4
4
|
from os import getenv
|
|
5
|
-
from typing import Any, Dict, List, Optional
|
|
5
|
+
from typing import Any, Dict, List, Optional, Tuple
|
|
6
6
|
|
|
7
7
|
try:
|
|
8
8
|
from warnings import filterwarnings
|
|
@@ -73,6 +73,13 @@ class Weaviate(VectorDb):
|
|
|
73
73
|
self.reranker: Optional[Reranker] = reranker
|
|
74
74
|
self.hybrid_search_alpha = hybrid_search_alpha
|
|
75
75
|
|
|
76
|
+
@staticmethod
|
|
77
|
+
def _get_doc_uuid(document: Document) -> Tuple[uuid.UUID, str]:
|
|
78
|
+
cleaned_content = document.content.replace("\x00", "\ufffd")
|
|
79
|
+
content_hash = md5(cleaned_content.encode()).hexdigest()
|
|
80
|
+
doc_uuid = uuid.UUID(hex=content_hash[:32])
|
|
81
|
+
return doc_uuid, cleaned_content
|
|
82
|
+
|
|
76
83
|
def get_client(self) -> weaviate.WeaviateClient:
|
|
77
84
|
"""Initialize and return a Weaviate client instance.
|
|
78
85
|
|
|
@@ -118,7 +125,7 @@ class Weaviate(VectorDb):
|
|
|
118
125
|
await self.async_client.connect() # type: ignore
|
|
119
126
|
|
|
120
127
|
if not await self.async_client.is_ready(): # type: ignore
|
|
121
|
-
raise
|
|
128
|
+
raise ConnectionError("Weaviate async client is not ready")
|
|
122
129
|
|
|
123
130
|
return self.async_client # type: ignore
|
|
124
131
|
|
|
@@ -155,6 +162,54 @@ class Weaviate(VectorDb):
|
|
|
155
162
|
finally:
|
|
156
163
|
await client.close()
|
|
157
164
|
|
|
165
|
+
def doc_content_changed(self, document: Document, check_existing: Optional[bool] = True) -> Optional[bool]:
|
|
166
|
+
"""
|
|
167
|
+
Check if the content of the document has changed by comparing its UUID.
|
|
168
|
+
|
|
169
|
+
Args:
|
|
170
|
+
document (Document): Document to check
|
|
171
|
+
|
|
172
|
+
Returns:
|
|
173
|
+
bool: True if the document content has changed, False otherwise. None on wrong input.
|
|
174
|
+
check_existing (bool): If True, check if the document exists before checking if the content changed.
|
|
175
|
+
"""
|
|
176
|
+
if not document or not document.content:
|
|
177
|
+
logger.warning("Invalid document: Missing content.")
|
|
178
|
+
return None
|
|
179
|
+
|
|
180
|
+
if check_existing and document.name and not self.name_exists(document.name):
|
|
181
|
+
logger.warning(f"A document by this name does not exist: {document.name}")
|
|
182
|
+
return None
|
|
183
|
+
|
|
184
|
+
doc_uuid, _ = self._get_doc_uuid(document)
|
|
185
|
+
|
|
186
|
+
collection = self.get_client().collections.get(self.collection)
|
|
187
|
+
existing_doc = collection.query.fetch_object_by_id(doc_uuid)
|
|
188
|
+
|
|
189
|
+
if not existing_doc:
|
|
190
|
+
return True
|
|
191
|
+
else:
|
|
192
|
+
return False
|
|
193
|
+
|
|
194
|
+
def doc_delete(self, name: str) -> None:
|
|
195
|
+
"""
|
|
196
|
+
Delete all documents from Weaviate with a specific 'name' property.
|
|
197
|
+
|
|
198
|
+
Args:
|
|
199
|
+
name (str): Document name to delete.
|
|
200
|
+
"""
|
|
201
|
+
collection = self.get_client().collections.get(self.collection)
|
|
202
|
+
filter_expr = Filter.by_property("name").equal(name)
|
|
203
|
+
|
|
204
|
+
result = collection.data.delete_many(where=filter_expr)
|
|
205
|
+
|
|
206
|
+
log_debug(f"Deleted document by name: '{name}' - {result.successful} documents deleted.")
|
|
207
|
+
if result.failed > 0:
|
|
208
|
+
logger.warning(
|
|
209
|
+
f"Failed to delete (some chunks of) document with name: '{name}' - "
|
|
210
|
+
f"Failed {result.failed} out of {result.matches} times. {result.successful} successful deletions."
|
|
211
|
+
)
|
|
212
|
+
|
|
158
213
|
def doc_exists(self, document: Document) -> bool:
|
|
159
214
|
"""
|
|
160
215
|
Validate if the document exists using consistent UUID generation.
|
|
@@ -169,9 +224,7 @@ class Weaviate(VectorDb):
|
|
|
169
224
|
logger.warning("Invalid document: Missing content.")
|
|
170
225
|
return False # Early exit for invalid input
|
|
171
226
|
|
|
172
|
-
|
|
173
|
-
content_hash = md5(cleaned_content.encode()).hexdigest()
|
|
174
|
-
doc_uuid = uuid.UUID(hex=content_hash[:32])
|
|
227
|
+
doc_uuid, _ = self._get_doc_uuid(document)
|
|
175
228
|
|
|
176
229
|
collection = self.get_client().collections.get(self.collection)
|
|
177
230
|
return collection.data.exists(doc_uuid)
|
|
@@ -190,9 +243,7 @@ class Weaviate(VectorDb):
|
|
|
190
243
|
logger.warning("Invalid document: Missing content.")
|
|
191
244
|
return False # Early exit for invalid input
|
|
192
245
|
|
|
193
|
-
|
|
194
|
-
content_hash = md5(cleaned_content.encode()).hexdigest()
|
|
195
|
-
doc_uuid = uuid.UUID(hex=content_hash[:32])
|
|
246
|
+
doc_uuid, _ = self._get_doc_uuid(document)
|
|
196
247
|
|
|
197
248
|
client = await self.get_async_client()
|
|
198
249
|
try:
|
|
@@ -256,9 +307,7 @@ class Weaviate(VectorDb):
|
|
|
256
307
|
logger.error(f"Document embedding is None: {document.name}")
|
|
257
308
|
continue
|
|
258
309
|
|
|
259
|
-
cleaned_content =
|
|
260
|
-
content_hash = md5(cleaned_content.encode()).hexdigest()
|
|
261
|
-
doc_uuid = uuid.UUID(hex=content_hash[:32])
|
|
310
|
+
doc_uuid, cleaned_content = self._get_doc_uuid(document)
|
|
262
311
|
|
|
263
312
|
# Merge filters with metadata
|
|
264
313
|
meta_data = document.meta_data or {}
|
|
@@ -305,9 +354,7 @@ class Weaviate(VectorDb):
|
|
|
305
354
|
continue
|
|
306
355
|
|
|
307
356
|
# Clean content and generate UUID
|
|
308
|
-
cleaned_content =
|
|
309
|
-
content_hash = md5(cleaned_content.encode()).hexdigest()
|
|
310
|
-
doc_uuid = uuid.UUID(hex=content_hash[:32])
|
|
357
|
+
doc_uuid, cleaned_content = self._get_doc_uuid(document)
|
|
311
358
|
|
|
312
359
|
# Serialize meta_data to JSON string
|
|
313
360
|
meta_data_str = json.dumps(document.meta_data) if document.meta_data else None
|
|
@@ -338,7 +385,28 @@ class Weaviate(VectorDb):
|
|
|
338
385
|
filters (Optional[Dict[str, Any]]): Filters to apply while upserting
|
|
339
386
|
"""
|
|
340
387
|
log_debug(f"Upserting {len(documents)} documents into Weaviate.")
|
|
341
|
-
|
|
388
|
+
|
|
389
|
+
_docs_to_insert = []
|
|
390
|
+
for document in documents:
|
|
391
|
+
assert document.name is not None, "Document name must be set for upsert operation."
|
|
392
|
+
|
|
393
|
+
if self.name_exists(document.name):
|
|
394
|
+
if self.doc_content_changed(document, check_existing=False):
|
|
395
|
+
log_debug(
|
|
396
|
+
f"Document already exists, but content changed. Document will be deleted and added again: {document.name}"
|
|
397
|
+
)
|
|
398
|
+
|
|
399
|
+
is_first_or_only_chunk = ("chunk" in document.meta_data and document.meta_data["chunk"] == 1) or (
|
|
400
|
+
"chunk" not in document.meta_data
|
|
401
|
+
)
|
|
402
|
+
if is_first_or_only_chunk:
|
|
403
|
+
self.doc_delete(document.name)
|
|
404
|
+
_docs_to_insert.append(document)
|
|
405
|
+
else:
|
|
406
|
+
log_debug(f"Document skipped, content is unchanged: {document.name}")
|
|
407
|
+
else:
|
|
408
|
+
_docs_to_insert.append(document)
|
|
409
|
+
self.insert(_docs_to_insert)
|
|
342
410
|
|
|
343
411
|
async def async_upsert(self, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
|
|
344
412
|
"""
|
|
@@ -365,9 +433,7 @@ class Weaviate(VectorDb):
|
|
|
365
433
|
logger.error(f"Document embedding is None: {document.name}")
|
|
366
434
|
continue
|
|
367
435
|
|
|
368
|
-
cleaned_content =
|
|
369
|
-
content_hash = md5(cleaned_content.encode()).hexdigest()
|
|
370
|
-
doc_uuid = uuid.UUID(hex=content_hash[:32])
|
|
436
|
+
doc_uuid, cleaned_content = self._get_doc_uuid(document)
|
|
371
437
|
|
|
372
438
|
# Serialize meta_data to JSON string
|
|
373
439
|
meta_data_str = json.dumps(document.meta_data) if document.meta_data else None
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agno
|
|
3
|
-
Version: 1.7.
|
|
3
|
+
Version: 1.7.10
|
|
4
4
|
Summary: Agno: a lightweight library for building Multi-Agent Systems
|
|
5
5
|
Author-email: Ashpreet Bedi <ashpreet@agno.com>
|
|
6
6
|
License: Copyright (c) Agno, Inc.
|
|
@@ -400,6 +400,7 @@ License-File: LICENSE
|
|
|
400
400
|
Requires-Dist: docstring-parser
|
|
401
401
|
Requires-Dist: gitpython
|
|
402
402
|
Requires-Dist: httpx
|
|
403
|
+
Requires-Dist: packaging
|
|
403
404
|
Requires-Dist: pydantic-settings
|
|
404
405
|
Requires-Dist: pydantic
|
|
405
406
|
Requires-Dist: python-dotenv
|
|
@@ -5,7 +5,7 @@ agno/exceptions.py,sha256=HWuuNFS5J0l1RYJsdUrSx51M22aFEoh9ltoeonXBoBw,2891
|
|
|
5
5
|
agno/media.py,sha256=lXJuylmhuIEWThKZkQ9pUZPp8Kms7EdT4N_U4YN9I00,12656
|
|
6
6
|
agno/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
7
|
agno/agent/__init__.py,sha256=Ai6GVyw-0rkA2eYAfoEQIvbi_mrWQUxuPFaFbSDJYCQ,1306
|
|
8
|
-
agno/agent/agent.py,sha256=
|
|
8
|
+
agno/agent/agent.py,sha256=9qp01o6lX72-fflCY74J7XIeFpz4jm7mnvpvF6m7n_0,381409
|
|
9
9
|
agno/agent/metrics.py,sha256=Lf7JYgPPdqRCyPfCDVUjnmUZ1SkWXrJClL80aW2ffEw,4379
|
|
10
10
|
agno/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
11
|
agno/api/agent.py,sha256=J-Y4HI-J0Bu6r9gxRYCM3U7SnVBGwLIouDy806KSIIw,2821
|
|
@@ -92,7 +92,7 @@ agno/document/reader/docx_reader.py,sha256=fNSZNzBlROQow7nagouEfN8E4KgVp3hTcSj3d
|
|
|
92
92
|
agno/document/reader/firecrawl_reader.py,sha256=4CFACPA22t0gI1YgYL1mZLZQN_T6LrLj8V9mAmU2In8,5748
|
|
93
93
|
agno/document/reader/json_reader.py,sha256=TrE14YAPkEd3q1e1dFf1ZX-GJPlXadsbeCzNh6EGpgg,2189
|
|
94
94
|
agno/document/reader/markdown_reader.py,sha256=SX0Zydj_0AmBr8Grk8z9jDiNmebU7rnPg2aAJoFEHAk,3546
|
|
95
|
-
agno/document/reader/pdf_reader.py,sha256=
|
|
95
|
+
agno/document/reader/pdf_reader.py,sha256=CGh2aYSJb7dAu-blSDz8ZkjiyU3U5-F_Foag7Eebnko,19584
|
|
96
96
|
agno/document/reader/text_reader.py,sha256=jtCuhWHkC5QNPmRF3DyXcXVKHM1jnqqxXVxHKZIpkfQ,3315
|
|
97
97
|
agno/document/reader/url_reader.py,sha256=dQmuO1NkJg9A9m2YeiVMuR7GikLl_K1FudE0UO62Um4,1988
|
|
98
98
|
agno/document/reader/website_reader.py,sha256=Ei-FIsdw0FWhGOBVge24JcNMfiAHL8nUA1tawrfBZPM,17307
|
|
@@ -138,7 +138,7 @@ agno/infra/db_app.py,sha256=W_XeDK0FhIkc--kfB0Jd34MJmgOfFQeT9M2y5840vlA,1794
|
|
|
138
138
|
agno/infra/resource.py,sha256=yPRZI4uprQtaugLD6x8_WAmFTPNPy5rlLvT1-bNIa5c,8491
|
|
139
139
|
agno/infra/resources.py,sha256=FKmDaDFup4cDiSA_y8eZRxpXEAmlEPxWzXKcY8xqF5w,1681
|
|
140
140
|
agno/knowledge/__init__.py,sha256=H1opQqY6oTPYJiLAiaIHtPuaVCry5GAhPoyT1ojdJwg,85
|
|
141
|
-
agno/knowledge/agent.py,sha256=
|
|
141
|
+
agno/knowledge/agent.py,sha256=udSFrUyHAwUA4RWT6iLR_hzYKh4-TnbKkQg_4xfksJk,29773
|
|
142
142
|
agno/knowledge/arxiv.py,sha256=0q1teC40wmau50ZTmdbvewCNxgxF_92QtfhJ87Evagk,1140
|
|
143
143
|
agno/knowledge/combined.py,sha256=6aHPfbjdKSfkE0D-vt8CocU3WOVAQaPWhuNjKBVLrv4,1262
|
|
144
144
|
agno/knowledge/csv.py,sha256=uUusY3Gf2HrYDtAOxoXsWfw11z95NEE9x71YNDqoK6g,5732
|
|
@@ -151,9 +151,9 @@ agno/knowledge/langchain.py,sha256=nHk4ohORSRwEY00DcdgXSwMewcv-caKMG24wghnUXaM,2
|
|
|
151
151
|
agno/knowledge/light_rag.py,sha256=8grl8nRirgqUyaoExNNJ1MwEiqqyRXdtM7hQw7w5z3s,11516
|
|
152
152
|
agno/knowledge/llamaindex.py,sha256=Lclu1rA0XMf4Y1xuupwUrtPvTi75gj9XvJ-so6oWxfw,2332
|
|
153
153
|
agno/knowledge/markdown.py,sha256=4DS3nb25ZP-Gld-H0TMijUIsqq2D8E2BVgfZzXKI0A8,5639
|
|
154
|
-
agno/knowledge/pdf.py,sha256=
|
|
154
|
+
agno/knowledge/pdf.py,sha256=ioV5szNDIVR1kzG3gZPwrM9FJprLSY0YzSP3VC9xpHo,6366
|
|
155
155
|
agno/knowledge/pdf_bytes.py,sha256=VmLuWO-UCJQ9CCXuWfYB0nG3W90_69g1xCoFxiKbaEM,1399
|
|
156
|
-
agno/knowledge/pdf_url.py,sha256=
|
|
156
|
+
agno/knowledge/pdf_url.py,sha256=gXskDyRbWqRK1mtBH6OfujlCy7OTQLOZY1LlqGfh84g,6119
|
|
157
157
|
agno/knowledge/text.py,sha256=SHVnvEF6Qa2yksuXY0tpdEvP8Y4cbFneKzyUi1V3tNw,5620
|
|
158
158
|
agno/knowledge/url.py,sha256=OTy-4BFP32Hg8N3IRvb-7LaoAlKAW61iewhkAASDL84,1488
|
|
159
159
|
agno/knowledge/website.py,sha256=W_vnFKAYteuNwnoNVnESEw55q-o3C9JHpfDyDxcnZNA,6556
|
|
@@ -252,7 +252,7 @@ agno/models/ollama/tools.py,sha256=PLYT9VSCGSwKAHNDEgOtyKg0HuUlYUxzGzvhoK19Vr0,1
|
|
|
252
252
|
agno/models/openai/__init__.py,sha256=OssVgQRpsriU6aJZ3lIp_jFuqvX6y78L4Fd3uTlmI3E,225
|
|
253
253
|
agno/models/openai/chat.py,sha256=PQ8GfVNZxM17rvLtY5UqeOPo4faGmX-1H_hx8BSLphI,30033
|
|
254
254
|
agno/models/openai/like.py,sha256=wmw9PfAVqluBs4MMY73dgjelKn1yl5JDKyCRvaNFjFw,745
|
|
255
|
-
agno/models/openai/responses.py,sha256=
|
|
255
|
+
agno/models/openai/responses.py,sha256=CxNS39S2O6eiXCY540ls2pJDu5m8XmYWvT_jvyEhDTQ,37951
|
|
256
256
|
agno/models/openrouter/__init__.py,sha256=ZpZhNyy_EGSXp58uC9e2iyjnxBctql7GaY8rUG-599I,90
|
|
257
257
|
agno/models/openrouter/openrouter.py,sha256=Ng-_ztpq_lghGI3tM94nsC8minKhiZ6d265c6IYXtg4,869
|
|
258
258
|
agno/models/perplexity/__init__.py,sha256=JNmOElDLwcZ9_Lk5owkEdgwmAhaH3YJ-VJqOI8rgp5c,90
|
|
@@ -291,8 +291,8 @@ agno/reranker/sentence_transformer.py,sha256=Pqv38uZ5MhwYPQkei8ixs3jANoBOIKqVwI3
|
|
|
291
291
|
agno/run/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
292
292
|
agno/run/base.py,sha256=cueGFKz_TOCNO9aMe8IBFwohax4z6IgL0e3HAK7XqRQ,7546
|
|
293
293
|
agno/run/messages.py,sha256=rAC4CLW-xBA6qFS1BOvcjJ9j_qYf0a7sX1mcdY04zMU,1126
|
|
294
|
-
agno/run/response.py,sha256=
|
|
295
|
-
agno/run/team.py,sha256=
|
|
294
|
+
agno/run/response.py,sha256=CafLgeLszVbdre7jm1A5TNG4WMpN0OiPMPk6ioeN-cg,15766
|
|
295
|
+
agno/run/team.py,sha256=WT5HbqVA1fvKPQg8gr2tpdeaNq2aM3WoWpas93P07ck,16504
|
|
296
296
|
agno/run/workflow.py,sha256=2eBvNXbGini3-cWwl3dOf-o-VgGq51ZEl4GCbQFblaw,1581
|
|
297
297
|
agno/run/v2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
298
298
|
agno/run/v2/workflow.py,sha256=FiZY5eWl6oEJCEfBUIX2q1WDHLI8mqVmaWWwKBA1PL8,18903
|
|
@@ -328,14 +328,14 @@ agno/storage/workflow/mongodb.py,sha256=x-0Jl2WovupTfwuVNOSndE9-7V4U7BBIjejtJ1Wa
|
|
|
328
328
|
agno/storage/workflow/postgres.py,sha256=66bvx6eT7PtFvd4EtTCfI2smynAyvpjvAPYtPo-PCNg,91
|
|
329
329
|
agno/storage/workflow/sqlite.py,sha256=PLqEA1YC8AtIklINr6wy8lzK6KABEqvlJW-nz5KacWM,85
|
|
330
330
|
agno/team/__init__.py,sha256=OSkwJhm4uSoOwpHLeDdcH4q2R_BmfS-7a9_aPxB-Skw,967
|
|
331
|
-
agno/team/team.py,sha256=
|
|
331
|
+
agno/team/team.py,sha256=bWK4aaNyipoN0BbqaKkqWWocH8yflXQFLJo3eESTvo8,377734
|
|
332
332
|
agno/tools/__init__.py,sha256=jNll2sELhPPbqm5nPeT4_uyzRO2_KRTW-8Or60kioS0,210
|
|
333
333
|
agno/tools/agentql.py,sha256=w6FlCfhuS0cc2BHa9K6dZjqO1ycA66fSZbR_nvXiVSo,3813
|
|
334
334
|
agno/tools/airflow.py,sha256=2ZCwx65w_tSXm4xEzZQR_teOiXJlnEgIqU9AgQTQemI,2493
|
|
335
335
|
agno/tools/api.py,sha256=gd86Fvk_3kHcaNWepTQ_Bmzs9RwajwiwcsEHJKdngB8,4238
|
|
336
336
|
agno/tools/apify.py,sha256=WWs9NWiiyMW5jKRRYLDHBoPPX4ScGMMt87VCXHowTy0,13555
|
|
337
337
|
agno/tools/arxiv.py,sha256=xnfbzOBDuHRj5SHImlz_q-pdRT9o_Vnna-VtDt1JuDU,5202
|
|
338
|
-
agno/tools/aws_lambda.py,sha256=
|
|
338
|
+
agno/tools/aws_lambda.py,sha256=CbVQpoLudpmle1KkgecuVDqE_JdapBBf26OdIj8fUsY,1831
|
|
339
339
|
agno/tools/aws_ses.py,sha256=fl5NTRWcljzxp4WxTg2gIAjLMNcuEWs_vnjeRtEKRHY,2090
|
|
340
340
|
agno/tools/baidusearch.py,sha256=HBdhLz1HUtKXJjIQru21jKiSonG9jEjNB_W6FPjklew,2883
|
|
341
341
|
agno/tools/bitbucket.py,sha256=CLhYdB_HTriy44VHtsRtqCY-BhnHpZMBHQ9vgL4vpWg,11207
|
|
@@ -368,7 +368,7 @@ agno/tools/financial_datasets.py,sha256=rvGSjz7gRdouB0PRJGngRSlO0wOwQE7cnrI8YaNI
|
|
|
368
368
|
agno/tools/firecrawl.py,sha256=0jeJlupLXCJTf2tDckEXlCV6EpLeDEO_G27-w4EWDL0,4985
|
|
369
369
|
agno/tools/function.py,sha256=VWgQAjIqxJl7MJrrMmMr7tNNvz3L3m7jXaUoIqxdlKY,36119
|
|
370
370
|
agno/tools/giphy.py,sha256=HKzTHEmiUdrkJsguG0qkpnsmXPikbrQyCoAHvAzI6XU,2422
|
|
371
|
-
agno/tools/github.py,sha256=
|
|
371
|
+
agno/tools/github.py,sha256=GMKuULX_9bzJY3PVocJsUVJITMR7g0hsjxY4gquL7wg,73271
|
|
372
372
|
agno/tools/gmail.py,sha256=p7zKW2NLuRIYsZZ6ru4WMdwMPQpoBt4JbuCwfMI3YTs,28845
|
|
373
373
|
agno/tools/google_bigquery.py,sha256=i93QJLJCH39sZDMPWYmie_A_ElBxVC6D36TVDcSaplo,4423
|
|
374
374
|
agno/tools/google_maps.py,sha256=iZa6FgjNID_G6T96ZXUOe5JnXIWn0c3AgzFU7O6S2WE,10123
|
|
@@ -511,14 +511,14 @@ agno/vectordb/clickhouse/index.py,sha256=_YW-8AuEYy5kzOHi0zIzjngpQPgJOBdSrn9BfEL
|
|
|
511
511
|
agno/vectordb/couchbase/__init__.py,sha256=dKZkcQLFN4r2_NIdXby4inzAAn4BDMlb9T2BW_i0_gQ,93
|
|
512
512
|
agno/vectordb/couchbase/couchbase.py,sha256=I-nWRPAEyEoww-1FpQJLM6CyxWXWPtR9dRjpAyzLWyo,48814
|
|
513
513
|
agno/vectordb/lancedb/__init__.py,sha256=tb9qvinKyWMTLjJYMwW_lhYHFvrfWTfHODtBfMj-NLE,111
|
|
514
|
-
agno/vectordb/lancedb/lance_db.py,sha256=
|
|
514
|
+
agno/vectordb/lancedb/lance_db.py,sha256=PBLtn0AkAVEEYJywYKzdf5gWbQWvka6yJXeAfsJQdtI,22886
|
|
515
515
|
agno/vectordb/milvus/__init__.py,sha256=I9V-Rm-rIYxWdRVIs6bKI-6JSJsyOd1-vvasvVpYHuE,127
|
|
516
516
|
agno/vectordb/milvus/milvus.py,sha256=SwLPmgP80dPWFeN9ehj3D1yseyVXbHJDIBNCu-NPs9s,30002
|
|
517
517
|
agno/vectordb/mongodb/__init__.py,sha256=yYwaWdxZRnFTd87Hfgs8_DO4QxcJxy1iL3__bnxP71I,73
|
|
518
518
|
agno/vectordb/mongodb/mongodb.py,sha256=yG_bs7iJrXatrmI2BMLALxkVT1qVx4BYoiUcXWXlSsg,48537
|
|
519
519
|
agno/vectordb/pgvector/__init__.py,sha256=Lui0HBzoHPIsKh5QuiT0eyTvYW88nQPfd_723jjHFCk,288
|
|
520
520
|
agno/vectordb/pgvector/index.py,sha256=qfGgPP33SwZkXLfUcAC_XgQsyZIyggpGS2bfIkjjs-E,495
|
|
521
|
-
agno/vectordb/pgvector/pgvector.py,sha256=
|
|
521
|
+
agno/vectordb/pgvector/pgvector.py,sha256=JE52MgXSXRqbySPMzgy1DcvJxZhabiw1ufFHf6QImWA,44305
|
|
522
522
|
agno/vectordb/pineconedb/__init__.py,sha256=D7iThXtUCxNO0Nyjunv5Z91Jc1vHG1pgAFXthqD1I_w,92
|
|
523
523
|
agno/vectordb/pineconedb/pineconedb.py,sha256=NaYmkskY1eLAWIM-HSBa-DVHEMQ6ZuZDqqUmmHZhlro,18399
|
|
524
524
|
agno/vectordb/qdrant/__init__.py,sha256=x1ReQt79f9aI_T4JUWb36KNFnvdd-kVwZ1sLsU4sW7Q,76
|
|
@@ -532,7 +532,7 @@ agno/vectordb/upstashdb/__init__.py,sha256=set3Sx1F3ZCw0--0AeC036EAS0cC1xKsvQUK5
|
|
|
532
532
|
agno/vectordb/upstashdb/upstashdb.py,sha256=PNV_Wt0LTszwt-jzn2E87y_6aulCr8BaeA2YlJrkTtQ,13088
|
|
533
533
|
agno/vectordb/weaviate/__init__.py,sha256=FIoFJgqSmGuFgpvmsg8EjAn8FDAhuqAXed7fjaW4exY,182
|
|
534
534
|
agno/vectordb/weaviate/index.py,sha256=y4XYPRZFksMfrrF85B4hn5AtmXM4SH--4CyLo27EHgM,253
|
|
535
|
-
agno/vectordb/weaviate/weaviate.py,sha256=
|
|
535
|
+
agno/vectordb/weaviate/weaviate.py,sha256=ZOHCHIuenpBcSx--jIA8l8nvUzZ-DzER2ISSfdGHtSc,33253
|
|
536
536
|
agno/workflow/__init__.py,sha256=jPTHCWpHZbfR34-KqIX-SLA7tO7VdZqgZ8C2I0Nhbps,407
|
|
537
537
|
agno/workflow/workflow.py,sha256=iHWjowKjw_gKE-JTigHseY9DDL1rpqQrP6ihBUO9d-A,35227
|
|
538
538
|
agno/workflow/v2/__init__.py,sha256=tACFZfj7OqbmjOtyZ8nllYnsal3w8xN2SHrIXXmA6Ys,566
|
|
@@ -550,9 +550,9 @@ agno/workspace/enums.py,sha256=MxF1CUMXBaZMTKLEfiR-7kEhTki2Gfz6W7u49RdYYaE,123
|
|
|
550
550
|
agno/workspace/helpers.py,sha256=Mp-VlRsPVhW10CfDWYVhc9ANLk9RjNurDfCgXmycZCg,2066
|
|
551
551
|
agno/workspace/operator.py,sha256=CNLwVR45eE5dSRjto2o0c9NgCi2xD-JZR5uLt9kfIt8,30758
|
|
552
552
|
agno/workspace/settings.py,sha256=bcyHHN7lH1LPSMt4i_20XpTjZLoNXdzwyW-G9nHYV40,5703
|
|
553
|
-
agno-1.7.
|
|
554
|
-
agno-1.7.
|
|
555
|
-
agno-1.7.
|
|
556
|
-
agno-1.7.
|
|
557
|
-
agno-1.7.
|
|
558
|
-
agno-1.7.
|
|
553
|
+
agno-1.7.10.dist-info/licenses/LICENSE,sha256=m2rfTWFUfIwCaQqgT2WeBjuKzMKEJRwnaiofg9n8MsQ,16751
|
|
554
|
+
agno-1.7.10.dist-info/METADATA,sha256=39SoZig58R20Lust76guW14N2t8HpMHYRa-zAgXLVIU,44303
|
|
555
|
+
agno-1.7.10.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
556
|
+
agno-1.7.10.dist-info/entry_points.txt,sha256=Be-iPnPVabMohESsuUdV5w6IAYEIlpc2emJZbyNnfGI,88
|
|
557
|
+
agno-1.7.10.dist-info/top_level.txt,sha256=MKyeuVesTyOKIXUhc-d_tPa2Hrh0oTA4LM0izowpx70,5
|
|
558
|
+
agno-1.7.10.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|