agno 2.0.9__py3-none-any.whl → 2.0.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 CHANGED
@@ -135,6 +135,8 @@ class Agent:
135
135
  add_session_state_to_context: bool = False
136
136
  # Set to True to give the agent tools to update the session_state dynamically
137
137
  enable_agentic_state: bool = False
138
+ # Set to True to overwrite the stored session_state with the session_state provided in the run. Default behaviour merges the current session state with the session state in the db
139
+ overwrite_db_session_state: bool = False
138
140
  # If True, cache the current Agent session in memory for faster access
139
141
  cache_session: bool = False
140
142
 
@@ -348,6 +350,7 @@ class Agent:
348
350
  session_id: Optional[str] = None,
349
351
  session_state: Optional[Dict[str, Any]] = None,
350
352
  add_session_state_to_context: bool = False,
353
+ overwrite_db_session_state: bool = False,
351
354
  enable_agentic_state: bool = False,
352
355
  cache_session: bool = False,
353
356
  search_session_history: Optional[bool] = False,
@@ -432,6 +435,7 @@ class Agent:
432
435
 
433
436
  self.session_id = session_id
434
437
  self.session_state = session_state
438
+ self.overwrite_db_session_state = overwrite_db_session_state
435
439
  self.enable_agentic_state = enable_agentic_state
436
440
  self.cache_session = cache_session
437
441
 
@@ -1113,7 +1117,7 @@ class Agent:
1113
1117
  self._update_metadata(session=agent_session)
1114
1118
 
1115
1119
  # Update session state from DB
1116
- session_state = self._update_session_state(session=agent_session, session_state=session_state)
1120
+ session_state = self._load_session_state(session=agent_session, session_state=session_state)
1117
1121
 
1118
1122
  # Determine runtime dependencies
1119
1123
  run_dependencies = dependencies if dependencies is not None else self.dependencies
@@ -1752,7 +1756,7 @@ class Agent:
1752
1756
  self._update_metadata(session=agent_session)
1753
1757
 
1754
1758
  # Update session state from DB
1755
- session_state = self._update_session_state(session=agent_session, session_state=session_state)
1759
+ session_state = self._load_session_state(session=agent_session, session_state=session_state)
1756
1760
 
1757
1761
  # Determine run dependencies
1758
1762
  run_dependencies = dependencies if dependencies is not None else self.dependencies
@@ -2019,7 +2023,7 @@ class Agent:
2019
2023
  self._update_metadata(session=agent_session)
2020
2024
 
2021
2025
  # Update session state from DB
2022
- session_state = self._update_session_state(session=agent_session, session_state=session_state)
2026
+ session_state = self._load_session_state(session=agent_session, session_state=session_state)
2023
2027
 
2024
2028
  run_dependencies = dependencies if dependencies is not None else self.dependencies
2025
2029
 
@@ -2403,7 +2407,7 @@ class Agent:
2403
2407
  self._update_metadata(session=agent_session)
2404
2408
 
2405
2409
  # Update session state from DB
2406
- session_state = self._update_session_state(session=agent_session, session_state=session_state)
2410
+ session_state = self._load_session_state(session=agent_session, session_state=session_state)
2407
2411
 
2408
2412
  run_dependencies = dependencies if dependencies is not None else self.dependencies
2409
2413
 
@@ -4252,8 +4256,8 @@ class Agent:
4252
4256
  log_warning(f"Error upserting session into db: {e}")
4253
4257
  return None
4254
4258
 
4255
- def _update_session_state(self, session: AgentSession, session_state: Dict[str, Any]):
4256
- """Load the existing Agent from an AgentSession (from the database)"""
4259
+ def _load_session_state(self, session: AgentSession, session_state: Dict[str, Any]):
4260
+ """Load and return the stored session_state from the database, optionally merging it with the given one"""
4257
4261
 
4258
4262
  # Get the session_state from the database and merge with proper precedence
4259
4263
  # At this point session_state contains: agent_defaults + run_params
@@ -4264,6 +4268,7 @@ class Agent:
4264
4268
  session_state_from_db is not None
4265
4269
  and isinstance(session_state_from_db, dict)
4266
4270
  and len(session_state_from_db) > 0
4271
+ and not self.overwrite_db_session_state
4267
4272
  ):
4268
4273
  # This preserves precedence: run_params > db_state > agent_defaults
4269
4274
  merged_state = session_state_from_db.copy()
agno/models/aws/claude.py CHANGED
@@ -10,7 +10,7 @@ from agno.models.message import Message
10
10
  from agno.models.response import ModelResponse
11
11
  from agno.run.agent import RunOutput
12
12
  from agno.utils.log import log_debug, log_error, log_warning
13
- from agno.utils.models.aws_claude import format_messages
13
+ from agno.utils.models.claude import format_messages
14
14
 
15
15
  try:
16
16
  from anthropic import AnthropicBedrock, APIConnectionError, APIStatusError, AsyncAnthropicBedrock, RateLimitError
agno/team/team.py CHANGED
@@ -156,6 +156,8 @@ class Team:
156
156
  add_session_state_to_context: bool = False
157
157
  # Set to True to give the team tools to update the session_state dynamically
158
158
  enable_agentic_state: bool = False
159
+ # Set to True to overwrite the stored session_state with the session_state provided in the run
160
+ overwrite_db_session_state: bool = False
159
161
  # If True, cache the current Team session in memory for faster access
160
162
  cache_session: bool = False
161
163
 
@@ -364,6 +366,7 @@ class Team:
364
366
  session_state: Optional[Dict[str, Any]] = None,
365
367
  add_session_state_to_context: bool = False,
366
368
  enable_agentic_state: bool = False,
369
+ overwrite_db_session_state: bool = False,
367
370
  resolve_in_context: bool = True,
368
371
  cache_session: bool = False,
369
372
  description: Optional[str] = None,
@@ -453,6 +456,7 @@ class Team:
453
456
  self.session_state = session_state
454
457
  self.add_session_state_to_context = add_session_state_to_context
455
458
  self.enable_agentic_state = enable_agentic_state
459
+ self.overwrite_db_session_state = overwrite_db_session_state
456
460
  self.resolve_in_context = resolve_in_context
457
461
  self.cache_session = cache_session
458
462
 
@@ -1156,7 +1160,7 @@ class Team:
1156
1160
  self._update_metadata(session=team_session)
1157
1161
 
1158
1162
  # Update session state from DB
1159
- session_state = self._update_session_state(session=team_session, session_state=session_state)
1163
+ session_state = self._load_session_state(session=team_session, session_state=session_state)
1160
1164
 
1161
1165
  # Determine runtime dependencies
1162
1166
  run_dependencies = dependencies if dependencies is not None else self.dependencies
@@ -1780,7 +1784,7 @@ class Team:
1780
1784
  self._update_metadata(session=team_session)
1781
1785
 
1782
1786
  # Update session state from DB
1783
- session_state = self._update_session_state(session=team_session, session_state=session_state)
1787
+ session_state = self._load_session_state(session=team_session, session_state=session_state)
1784
1788
 
1785
1789
  # Determine run dependencies (runtime override takes priority)
1786
1790
  run_dependencies = dependencies if dependencies is not None else self.dependencies
@@ -4270,7 +4274,7 @@ class Team:
4270
4274
  system_message_content += f"{indent * ' '} - Name: {member.name}\n"
4271
4275
  if member.role is not None:
4272
4276
  system_message_content += f"{indent * ' '} - Role: {member.role}\n"
4273
- if member.tools is not None and self.add_member_tools_to_context:
4277
+ if member.tools and self.add_member_tools_to_context:
4274
4278
  system_message_content += f"{indent * ' '} - Member tools:\n"
4275
4279
  for _tool in member.tools:
4276
4280
  if isinstance(_tool, Toolkit):
@@ -6104,8 +6108,8 @@ class Team:
6104
6108
  self._upsert_session(session=session)
6105
6109
  log_debug(f"Created or updated TeamSession record: {session.session_id}")
6106
6110
 
6107
- def _update_session_state(self, session: TeamSession, session_state: Dict[str, Any]) -> Dict[str, Any]:
6108
- """Load the existing Agent from an AgentSession (from the database)"""
6111
+ def _load_session_state(self, session: TeamSession, session_state: Dict[str, Any]) -> Dict[str, Any]:
6112
+ """Load and return the stored session_state from the database, optionally merging it with the given one"""
6109
6113
 
6110
6114
  from agno.utils.merge_dict import merge_dictionaries
6111
6115
 
@@ -6118,6 +6122,7 @@ class Team:
6118
6122
  session_state_from_db is not None
6119
6123
  and isinstance(session_state_from_db, dict)
6120
6124
  and len(session_state_from_db) > 0
6125
+ and not self.overwrite_db_session_state
6121
6126
  ):
6122
6127
  # This preserves precedence: run_params > db_state > agent_defaults
6123
6128
  merged_state = session_state_from_db.copy()
@@ -69,11 +69,11 @@ def _format_image_for_message(image: Image) -> Optional[Dict[str, Any]]:
69
69
  try:
70
70
  # Case 0: Image is an Anthropic uploaded file
71
71
  if image.content is not None and hasattr(image.content, "id"):
72
- return {"type": "image", "source": {"type": "file", "file_id": image.content.id}}
72
+ content_bytes = image.content
73
73
 
74
74
  # Case 1: Image is a URL
75
75
  if image.url is not None:
76
- return {"type": "image", "source": {"type": "url", "url": image.url}}
76
+ content_bytes = image.get_content_bytes() # type: ignore
77
77
 
78
78
  # Case 2: Image is a local file path
79
79
  elif image.filepath is not None:
agno/workflow/workflow.py CHANGED
@@ -136,6 +136,8 @@ class Workflow:
136
136
  user_id: Optional[str] = None
137
137
  # Default session state (stored in the database to persist across runs)
138
138
  session_state: Optional[Dict[str, Any]] = None
139
+ # Set to True to overwrite the stored session_state with the session_state provided in the run
140
+ overwrite_db_session_state: bool = False
139
141
 
140
142
  # If True, the workflow runs in debug mode
141
143
  debug_mode: Optional[bool] = False
@@ -176,6 +178,7 @@ class Workflow:
176
178
  steps: Optional[WorkflowSteps] = None,
177
179
  session_id: Optional[str] = None,
178
180
  session_state: Optional[Dict[str, Any]] = None,
181
+ overwrite_db_session_state: bool = False,
179
182
  user_id: Optional[str] = None,
180
183
  debug_mode: Optional[bool] = False,
181
184
  stream: Optional[bool] = None,
@@ -194,6 +197,7 @@ class Workflow:
194
197
  self.steps = steps
195
198
  self.session_id = session_id
196
199
  self.session_state = session_state
200
+ self.overwrite_db_session_state = overwrite_db_session_state
197
201
  self.user_id = user_id
198
202
  self.debug_mode = debug_mode
199
203
  self.store_events = store_events
@@ -599,8 +603,8 @@ class Workflow:
599
603
  # Update the current metadata with the metadata from the database which is updated in place
600
604
  self.metadata = session.metadata
601
605
 
602
- def _update_session_state(self, session: WorkflowSession, session_state: Dict[str, Any]):
603
- """Load the existing Workflow from a WorkflowSession (from the database)"""
606
+ def _load_session_state(self, session: WorkflowSession, session_state: Dict[str, Any]):
607
+ """Load and return the stored session_state from the database, optionally merging it with the given one"""
604
608
 
605
609
  from agno.utils.merge_dict import merge_dictionaries
606
610
 
@@ -613,6 +617,7 @@ class Workflow:
613
617
  session_state_from_db is not None
614
618
  and isinstance(session_state_from_db, dict)
615
619
  and len(session_state_from_db) > 0
620
+ and not self.overwrite_db_session_state
616
621
  ):
617
622
  # This preserves precedence: run_params > db_state > agent_defaults
618
623
  merged_state = session_state_from_db.copy()
@@ -1716,7 +1721,7 @@ class Workflow:
1716
1721
  self._update_metadata(session=workflow_session)
1717
1722
 
1718
1723
  # Update session state from DB
1719
- session_state = self._update_session_state(session=workflow_session, session_state=session_state)
1724
+ session_state = self._load_session_state(session=workflow_session, session_state=session_state)
1720
1725
 
1721
1726
  self._prepare_steps()
1722
1727
 
@@ -1807,7 +1812,7 @@ class Workflow:
1807
1812
  self._update_metadata(session=workflow_session)
1808
1813
 
1809
1814
  # Update session state from DB
1810
- session_state = self._update_session_state(session=workflow_session, session_state=session_state)
1815
+ session_state = self._load_session_state(session=workflow_session, session_state=session_state)
1811
1816
 
1812
1817
  self._prepare_steps()
1813
1818
 
@@ -1967,7 +1972,7 @@ class Workflow:
1967
1972
  self._update_metadata(session=workflow_session)
1968
1973
 
1969
1974
  # Update session state from DB
1970
- session_state = self._update_session_state(session=workflow_session, session_state=session_state)
1975
+ session_state = self._load_session_state(session=workflow_session, session_state=session_state)
1971
1976
 
1972
1977
  log_debug(f"Workflow Run Start: {self.name}", center=True)
1973
1978
 
@@ -2137,7 +2142,7 @@ class Workflow:
2137
2142
  self._update_metadata(session=workflow_session)
2138
2143
 
2139
2144
  # Update session state from DB
2140
- session_state = self._update_session_state(session=workflow_session, session_state=session_state)
2145
+ session_state = self._load_session_state(session=workflow_session, session_state=session_state)
2141
2146
 
2142
2147
  log_debug(f"Async Workflow Run Start: {self.name}", center=True)
2143
2148
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agno
3
- Version: 2.0.9
3
+ Version: 2.0.10
4
4
  Summary: Agno: a lightweight library for building Multi-Agent Systems
5
5
  Author-email: Ashpreet Bedi <ashpreet@agno.com>
6
6
  Project-URL: homepage, https://agno.com
@@ -4,7 +4,7 @@ agno/exceptions.py,sha256=HWuuNFS5J0l1RYJsdUrSx51M22aFEoh9ltoeonXBoBw,2891
4
4
  agno/media.py,sha256=eTfYb_pwhX_PCIVPSrW4VYRqmoxKABEF1aZClrVvQ30,16500
5
5
  agno/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  agno/agent/__init__.py,sha256=s7S3FgsjZxuaabzi8L5n4aSH8IZAiZ7XaNNcySGR-EQ,1051
7
- agno/agent/agent.py,sha256=ZfLfL6KRQzyPRQh3WS5oyHqGScgzdDvaZMce3KsDNMQ,329965
7
+ agno/agent/agent.py,sha256=jeJp0Nx6z3jabzhWIgJuT9eU24WjKwAAmlrGLNmgBhA,330395
8
8
  agno/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
9
  agno/api/agent.py,sha256=fKlQ62E_C9Rjd7Zus3Gs3R1RG-IhzFV-ICpkb6SLqYc,932
10
10
  agno/api/api.py,sha256=Z7iWbrjheJcGLeeDYrtTCWiKTVqjH0uJI35UNWOtAXw,973
@@ -158,7 +158,7 @@ agno/models/anthropic/__init__.py,sha256=nbReX3p17JCwfrMDR9hR7-OaEFZm80I7dng93dl
158
158
  agno/models/anthropic/claude.py,sha256=8v9AbtYJmhXF-e6X5yRcRki3xE7GOowLbQh6jeGiei0,26363
159
159
  agno/models/aws/__init__.py,sha256=TbcwQwv9A7KjqBM5RQBR8x46GvyyCxbBCjwkpjfVGKE,352
160
160
  agno/models/aws/bedrock.py,sha256=4H4Y-ZC8nz1Dcag1JxT3orpvzSlHPaNhTy9NXaqCSY8,30919
161
- agno/models/aws/claude.py,sha256=rfBA8RZ5Br8QxmLeXWHBWrj1-KGB4OLj1q740SokcMU,14750
161
+ agno/models/aws/claude.py,sha256=sL47z9fM3jxGbARkr0mlAVYEKKX854J3u-Qeb5gIADo,14746
162
162
  agno/models/azure/__init__.py,sha256=EoFdJHjayvmv_VOmaW9cJguwA1K5OFS_nFeazyn0B2w,605
163
163
  agno/models/azure/ai_foundry.py,sha256=V75lk4pH_RVFzVhWYz9-ZSA3dcaQe2SpRF1lrAm_agw,18673
164
164
  agno/models/azure/openai_chat.py,sha256=RYHmcHA7cn79_U6GTjNP5vYiYET6IfPgUp6XZ2WEiyQ,4423
@@ -294,7 +294,7 @@ agno/session/summary.py,sha256=2a74rDzrOGkWjrFkHQ6gf1dsZBU0_G1lgDE7b3fPaQw,8405
294
294
  agno/session/team.py,sha256=ckz-h_sYoFEbqLmNYglS0mamI9QzLfh-2ixsrHW6lU0,10383
295
295
  agno/session/workflow.py,sha256=8dWTona5jen1iPYwjcvxq1XG5EQDFnd28BEjcbqzl4s,5004
296
296
  agno/team/__init__.py,sha256=toHidBOo5M3n_TIVtIKHgcDbLL9HR-_U-YQYuIt_XtE,847
297
- agno/team/team.py,sha256=cTBAn5vZ9ebEO3hUPJM08_LYD4x2qs6ZRM7wAxcLpmY,314695
297
+ agno/team/team.py,sha256=UmVMAPLHqwoW2x2BR4KrjHsJ2emd9dQ989TVNE3-WMw,315032
298
298
  agno/tools/__init__.py,sha256=jNll2sELhPPbqm5nPeT4_uyzRO2_KRTW-8Or60kioS0,210
299
299
  agno/tools/agentql.py,sha256=S82Z9aTNr-E5wnA4fbFs76COljJtiQIjf2grjz3CkHU,4104
300
300
  agno/tools/airflow.py,sha256=uf2rOzZpSU64l_qRJ5Raku-R3Gky-uewmYkh6W0-oxg,2610
@@ -456,8 +456,7 @@ agno/utils/whatsapp.py,sha256=242VwGOdbgkxVeIj4D899mpT3GnG_IpcaKnd5qebhTA,9936
456
456
  agno/utils/yaml_io.py,sha256=cwTqCE-eBGoi87KLDcwB6iyWe0NcvEmadQjWL1cQ7jE,860
457
457
  agno/utils/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
458
458
  agno/utils/models/ai_foundry.py,sha256=PmhETWhdqZCq8NbDe-MdZVuRXx6DbVOePCyPFiPLceo,1511
459
- agno/utils/models/aws_claude.py,sha256=d0PWNNVHiA8Kzg_RzOEvNNkmOsmSzWxOnlA86uLtnQE,5680
460
- agno/utils/models/claude.py,sha256=QYnARhGrLSvP2kfFCa7t-hnaZdU9Nby-B-21ocT9_rA,11293
459
+ agno/utils/models/claude.py,sha256=XkRS4XVIDJt440SlzQFemrIDpIsOs39AvK1fjyMuruU,11229
461
460
  agno/utils/models/cohere.py,sha256=wir2K9u4RmOwq7T7n_2UPZFHfwmnrt_u91Psd_DFqdE,3266
462
461
  agno/utils/models/llama.py,sha256=Z5fdOFUFnov1JgUDcP6ICK3M7o64UB1fkcwAs2XaZkM,2515
463
462
  agno/utils/models/mistral.py,sha256=SVcJ8Q8SFeadNwCr8BARbET0gvGiylmaDKzcSJ9kWq0,4189
@@ -520,9 +519,9 @@ agno/workflow/router.py,sha256=ZAiVsh2F_9ssKj0_RzHWzfgimaZ5hfb3Ni1Xx_SkVR0,26625
520
519
  agno/workflow/step.py,sha256=15vZFN5HlO3IkHqsxkM-2InUzCWC0Ee8BtoJ-OAhS5w,52485
521
520
  agno/workflow/steps.py,sha256=uRE4oGWs2cA-TrX881AEa69zu6rheXH81mNOZiRrNvg,23719
522
521
  agno/workflow/types.py,sha256=ZEFyaKH42261_3yx810ABfi70RUfjPGSwiIep7n53yg,17485
523
- agno/workflow/workflow.py,sha256=KZ_8RArdH8iFiSlX2FCMhfcegD6fWjNGr53afgUdjik,112398
524
- agno-2.0.9.dist-info/licenses/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
525
- agno-2.0.9.dist-info/METADATA,sha256=IvqPWldG93r3IZBXtnv0lnb-SDDT26Seww5tBfNkWdo,22017
526
- agno-2.0.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
527
- agno-2.0.9.dist-info/top_level.txt,sha256=MKyeuVesTyOKIXUhc-d_tPa2Hrh0oTA4LM0izowpx70,5
528
- agno-2.0.9.dist-info/RECORD,,
522
+ agno/workflow/workflow.py,sha256=yjjVZ0MvkLjGgVaVt8jFWlm2urx7zZdAuJ0We9KRu2U,112738
523
+ agno-2.0.10.dist-info/licenses/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
524
+ agno-2.0.10.dist-info/METADATA,sha256=PKHm3CQY3sd9WdY5O1VGJyQyVeza95ICLnS3lhPuIA0,22018
525
+ agno-2.0.10.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
526
+ agno-2.0.10.dist-info/top_level.txt,sha256=MKyeuVesTyOKIXUhc-d_tPa2Hrh0oTA4LM0izowpx70,5
527
+ agno-2.0.10.dist-info/RECORD,,
@@ -1,170 +0,0 @@
1
- import json
2
- from typing import Any, Dict, List, Optional, Tuple
3
-
4
- from agno.media import Image
5
- from agno.models.message import Message
6
- from agno.utils.log import log_error, log_warning
7
-
8
- try:
9
- from anthropic.types import (
10
- TextBlock,
11
- ToolUseBlock,
12
- )
13
- except ImportError:
14
- log_error("`anthropic[bedrock]` not installed. Please install it via `pip install anthropic[bedrock]`.")
15
- raise
16
-
17
- ROLE_MAP = {
18
- "system": "system",
19
- "user": "user",
20
- "assistant": "assistant",
21
- "tool": "user",
22
- }
23
-
24
-
25
- def _format_image_for_message(image: Image) -> Optional[Dict[str, Any]]:
26
- """
27
- Add an image to a message by converting it to base64 encoded format.
28
- """
29
- using_filetype = False
30
-
31
- import base64
32
-
33
- # 'imghdr' was deprecated in Python 3.11: https://docs.python.org/3/library/imghdr.html
34
- # 'filetype' used as a fallback
35
- try:
36
- import imghdr
37
- except (ModuleNotFoundError, ImportError):
38
- try:
39
- import filetype
40
-
41
- using_filetype = True
42
- except (ModuleNotFoundError, ImportError):
43
- raise ImportError("`filetype` not installed. Please install using `pip install filetype`")
44
-
45
- type_mapping = {
46
- "jpeg": "image/jpeg",
47
- "jpg": "image/jpeg",
48
- "png": "image/png",
49
- "gif": "image/gif",
50
- "webp": "image/webp",
51
- }
52
-
53
- try:
54
- # Case 1: Image is a URL
55
- if image.url is not None:
56
- content_bytes = image.get_content_bytes() # type: ignore
57
-
58
- # Case 2: Image is a local file path
59
- elif image.filepath is not None:
60
- from pathlib import Path
61
-
62
- path = Path(image.filepath) if isinstance(image.filepath, str) else image.filepath
63
- if path.exists() and path.is_file():
64
- with open(image.filepath, "rb") as f:
65
- content_bytes = f.read()
66
- else:
67
- log_error(f"Image file not found: {image}")
68
- return None
69
-
70
- # Case 3: Image is a bytes object
71
- elif image.content is not None:
72
- content_bytes = image.content
73
-
74
- else:
75
- log_error(f"Unsupported image type: {type(image)}")
76
- return None
77
-
78
- if using_filetype:
79
- kind = filetype.guess(content_bytes)
80
- if not kind:
81
- log_error("Unable to determine image type")
82
- return None
83
-
84
- img_type = kind.extension
85
- else:
86
- img_type = imghdr.what(None, h=content_bytes) # type: ignore
87
-
88
- if not img_type:
89
- log_error("Unable to determine image type")
90
- return None
91
-
92
- media_type = type_mapping.get(img_type)
93
- if not media_type:
94
- log_error(f"Unsupported image type: {img_type}")
95
- return None
96
-
97
- return {
98
- "type": "image",
99
- "source": {
100
- "type": "base64",
101
- "media_type": media_type,
102
- "data": base64.b64encode(content_bytes).decode("utf-8"), # type: ignore
103
- },
104
- }
105
-
106
- except Exception as e:
107
- log_error(f"Error processing image: {e}")
108
- return None
109
-
110
-
111
- def format_messages(messages: List[Message]) -> Tuple[List[Dict[str, str]], str]:
112
- """
113
- Process the list of messages and separate them into API messages and system messages.
114
-
115
- Args:
116
- messages (List[Message]): The list of messages to process.
117
-
118
- Returns:
119
- Tuple[List[Dict[str, str]], str]: A tuple containing the list of API messages and the concatenated system messages.
120
- """
121
-
122
- chat_messages: List[Dict[str, str]] = []
123
- system_messages: List[str] = []
124
-
125
- for message in messages:
126
- content = message.content or ""
127
- if message.role == "system":
128
- if content is not None:
129
- system_messages.append(content) # type: ignore
130
- continue
131
- elif message.role == "user":
132
- if isinstance(content, str):
133
- content = [{"type": "text", "text": content}]
134
-
135
- if message.images is not None:
136
- for image in message.images:
137
- image_content = _format_image_for_message(image)
138
- if image_content:
139
- content.append(image_content)
140
-
141
- if message.files is not None and len(message.files) > 0:
142
- log_warning("Files are not supported for AWS Bedrock Claude")
143
-
144
- if message.audio is not None and len(message.audio) > 0:
145
- log_warning("Audio is not supported for AWS Bedrock Claude")
146
-
147
- if message.videos is not None and len(message.videos) > 0:
148
- log_warning("Video is not supported for AWS Bedrock Claude")
149
-
150
- # Handle tool calls from history
151
- elif message.role == "assistant":
152
- content = []
153
-
154
- if isinstance(message.content, str) and message.content and len(message.content.strip()) > 0:
155
- content.append(TextBlock(text=message.content, type="text"))
156
-
157
- if message.tool_calls:
158
- for tool_call in message.tool_calls:
159
- content.append(
160
- ToolUseBlock(
161
- id=tool_call["id"],
162
- input=json.loads(tool_call["function"]["arguments"])
163
- if "arguments" in tool_call["function"]
164
- else {},
165
- name=tool_call["function"]["name"],
166
- type="tool_use",
167
- )
168
- )
169
- chat_messages.append({"role": ROLE_MAP[message.role], "content": content}) # type: ignore
170
- return chat_messages, " ".join(system_messages)
File without changes