autobyteus 1.1.5__py3-none-any.whl → 1.1.6__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.
Files changed (74) hide show
  1. autobyteus/agent/context/agent_config.py +6 -1
  2. autobyteus/agent/handlers/llm_user_message_ready_event_handler.py +30 -7
  3. autobyteus/agent/handlers/user_input_message_event_handler.py +22 -25
  4. autobyteus/agent/message/__init__.py +7 -5
  5. autobyteus/agent/message/agent_input_user_message.py +6 -16
  6. autobyteus/agent/message/context_file.py +24 -24
  7. autobyteus/agent/message/context_file_type.py +29 -8
  8. autobyteus/agent/message/multimodal_message_builder.py +47 -0
  9. autobyteus/agent/streaming/stream_event_payloads.py +23 -4
  10. autobyteus/agent/system_prompt_processor/tool_manifest_injector_processor.py +6 -2
  11. autobyteus/agent/tool_invocation.py +2 -1
  12. autobyteus/agent_team/bootstrap_steps/agent_configuration_preparation_step.py +9 -2
  13. autobyteus/agent_team/context/agent_team_config.py +1 -0
  14. autobyteus/llm/api/autobyteus_llm.py +33 -33
  15. autobyteus/llm/api/bedrock_llm.py +13 -5
  16. autobyteus/llm/api/claude_llm.py +13 -27
  17. autobyteus/llm/api/gemini_llm.py +108 -42
  18. autobyteus/llm/api/groq_llm.py +4 -3
  19. autobyteus/llm/api/mistral_llm.py +97 -51
  20. autobyteus/llm/api/nvidia_llm.py +6 -5
  21. autobyteus/llm/api/ollama_llm.py +37 -12
  22. autobyteus/llm/api/openai_compatible_llm.py +91 -91
  23. autobyteus/llm/autobyteus_provider.py +1 -1
  24. autobyteus/llm/base_llm.py +42 -139
  25. autobyteus/llm/extensions/base_extension.py +6 -6
  26. autobyteus/llm/extensions/token_usage_tracking_extension.py +3 -2
  27. autobyteus/llm/llm_factory.py +106 -4
  28. autobyteus/llm/token_counter/token_counter_factory.py +1 -1
  29. autobyteus/llm/user_message.py +43 -35
  30. autobyteus/llm/utils/llm_config.py +34 -18
  31. autobyteus/llm/utils/media_payload_formatter.py +99 -0
  32. autobyteus/llm/utils/messages.py +32 -25
  33. autobyteus/llm/utils/response_types.py +9 -3
  34. autobyteus/llm/utils/token_usage.py +6 -5
  35. autobyteus/multimedia/__init__.py +31 -0
  36. autobyteus/multimedia/audio/__init__.py +11 -0
  37. autobyteus/multimedia/audio/api/__init__.py +4 -0
  38. autobyteus/multimedia/audio/api/autobyteus_audio_client.py +59 -0
  39. autobyteus/multimedia/audio/api/gemini_audio_client.py +219 -0
  40. autobyteus/multimedia/audio/audio_client_factory.py +120 -0
  41. autobyteus/multimedia/audio/audio_model.py +96 -0
  42. autobyteus/multimedia/audio/autobyteus_audio_provider.py +108 -0
  43. autobyteus/multimedia/audio/base_audio_client.py +40 -0
  44. autobyteus/multimedia/image/__init__.py +11 -0
  45. autobyteus/multimedia/image/api/__init__.py +9 -0
  46. autobyteus/multimedia/image/api/autobyteus_image_client.py +97 -0
  47. autobyteus/multimedia/image/api/gemini_image_client.py +188 -0
  48. autobyteus/multimedia/image/api/openai_image_client.py +142 -0
  49. autobyteus/multimedia/image/autobyteus_image_provider.py +109 -0
  50. autobyteus/multimedia/image/base_image_client.py +67 -0
  51. autobyteus/multimedia/image/image_client_factory.py +118 -0
  52. autobyteus/multimedia/image/image_model.py +96 -0
  53. autobyteus/multimedia/providers.py +5 -0
  54. autobyteus/multimedia/runtimes.py +8 -0
  55. autobyteus/multimedia/utils/__init__.py +10 -0
  56. autobyteus/multimedia/utils/api_utils.py +19 -0
  57. autobyteus/multimedia/utils/multimedia_config.py +29 -0
  58. autobyteus/multimedia/utils/response_types.py +13 -0
  59. autobyteus/tools/__init__.py +3 -0
  60. autobyteus/tools/multimedia/__init__.py +8 -0
  61. autobyteus/tools/multimedia/audio_tools.py +116 -0
  62. autobyteus/tools/multimedia/image_tools.py +186 -0
  63. autobyteus/tools/tool_category.py +1 -0
  64. autobyteus/tools/usage/parsers/provider_aware_tool_usage_parser.py +5 -2
  65. autobyteus/tools/usage/providers/tool_manifest_provider.py +5 -3
  66. autobyteus/tools/usage/registries/tool_formatting_registry.py +9 -2
  67. autobyteus/tools/usage/registries/tool_usage_parser_registry.py +9 -2
  68. {autobyteus-1.1.5.dist-info → autobyteus-1.1.6.dist-info}/METADATA +9 -9
  69. {autobyteus-1.1.5.dist-info → autobyteus-1.1.6.dist-info}/RECORD +73 -45
  70. examples/run_browser_agent.py +1 -1
  71. autobyteus/llm/utils/image_payload_formatter.py +0 -89
  72. {autobyteus-1.1.5.dist-info → autobyteus-1.1.6.dist-info}/WHEEL +0 -0
  73. {autobyteus-1.1.5.dist-info → autobyteus-1.1.6.dist-info}/licenses/LICENSE +0 -0
  74. {autobyteus-1.1.5.dist-info → autobyteus-1.1.6.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,116 @@
1
+ import os
2
+ import logging
3
+ from typing import Optional, List
4
+
5
+ from autobyteus.tools.base_tool import BaseTool
6
+ from autobyteus.tools.parameter_schema import ParameterSchema, ParameterDefinition, ParameterType
7
+ from autobyteus.tools.tool_category import ToolCategory
8
+ from autobyteus.multimedia.audio import audio_client_factory, AudioModel, AudioClientFactory
9
+
10
+ logger = logging.getLogger(__name__)
11
+
12
+
13
+ def _get_configured_model_identifier(env_var: str, default_model: Optional[str] = None) -> str:
14
+ """
15
+ Retrieves a model identifier from an environment variable.
16
+ """
17
+ model_identifier = os.getenv(env_var)
18
+ if not model_identifier:
19
+ if default_model:
20
+ return default_model
21
+ raise ValueError(f"The '{env_var}' environment variable is not set. Please configure it.")
22
+ return model_identifier
23
+
24
+
25
+ def _build_dynamic_audio_schema(base_params: List[ParameterDefinition], model_env_var: str, default_model: str) -> ParameterSchema:
26
+ """
27
+ Builds a tool schema dynamically based on a configured audio model.
28
+ """
29
+ try:
30
+ model_identifier = _get_configured_model_identifier(model_env_var, default_model)
31
+ AudioClientFactory.ensure_initialized()
32
+ model = AudioModel[model_identifier]
33
+ except (ValueError, KeyError) as e:
34
+ logger.error(f"Cannot generate audio tool schema. Check environment and model registry. Error: {e}")
35
+ raise RuntimeError(f"Failed to configure audio tool. Error: {e}")
36
+
37
+ config_schema = ParameterSchema()
38
+ if model.parameter_schema:
39
+ for name, meta in model.parameter_schema.items():
40
+ param_type_str = meta.get("type", "string").upper()
41
+ param_type = getattr(ParameterType, param_type_str, ParameterType.STRING)
42
+
43
+ allowed_values = meta.get("allowed_values")
44
+ if param_type == ParameterType.STRING and allowed_values:
45
+ param_type = ParameterType.ENUM
46
+
47
+ config_schema.add_parameter(ParameterDefinition(
48
+ name=name,
49
+ param_type=param_type,
50
+ description=meta.get("description", ""),
51
+ required=False,
52
+ default_value=meta.get("default"),
53
+ enum_values=allowed_values
54
+ ))
55
+
56
+ schema = ParameterSchema()
57
+ for param in base_params:
58
+ schema.add_parameter(param)
59
+
60
+ if config_schema.parameters:
61
+ schema.add_parameter(ParameterDefinition(
62
+ name="generation_config",
63
+ param_type=ParameterType.OBJECT,
64
+ description=f"Model-specific parameters for the configured '{model_identifier}' model.",
65
+ required=False,
66
+ object_schema=config_schema.to_json_schema_dict()
67
+ ))
68
+ return schema
69
+
70
+
71
+ class GenerateSpeechTool(BaseTool):
72
+ """
73
+ An agent tool for generating speech from text using a Text-to-Speech (TTS) model.
74
+ """
75
+ CATEGORY = ToolCategory.MULTIMEDIA
76
+ MODEL_ENV_VAR = "DEFAULT_SPEECH_GENERATION_MODEL"
77
+ DEFAULT_MODEL = "gemini-2.5-flash-tts"
78
+
79
+ @classmethod
80
+ def get_name(cls) -> str:
81
+ return "GenerateSpeech"
82
+
83
+ @classmethod
84
+ def get_description(cls) -> str:
85
+ return (
86
+ "Generates spoken audio from text using the system's default Text-to-Speech (TTS) model. "
87
+ "Returns a list of local file paths to the generated audio files (.wav) upon success."
88
+ )
89
+
90
+ @classmethod
91
+ def get_argument_schema(cls) -> Optional[ParameterSchema]:
92
+ base_params = [
93
+ ParameterDefinition(
94
+ name="prompt",
95
+ param_type=ParameterType.STRING,
96
+ description="The text to be converted into spoken audio.",
97
+ required=True
98
+ )
99
+ ]
100
+ return _build_dynamic_audio_schema(base_params, cls.MODEL_ENV_VAR, cls.DEFAULT_MODEL)
101
+
102
+ async def _execute(self, context, prompt: str, generation_config: Optional[dict] = None) -> str:
103
+ model_identifier = _get_configured_model_identifier(self.MODEL_ENV_VAR, self.DEFAULT_MODEL)
104
+ logger.info(f"GenerateSpeechTool executing with configured model '{model_identifier}'.")
105
+ client = None
106
+ try:
107
+ client = audio_client_factory.create_audio_client(model_identifier=model_identifier)
108
+ response = await client.generate_speech(prompt=prompt, generation_config=generation_config)
109
+
110
+ if not response.audio_urls:
111
+ raise ValueError("Speech generation failed to return any audio file paths.")
112
+
113
+ return f"Speech generation successful. Audio file(s) saved at: {response.audio_urls}"
114
+ finally:
115
+ if client:
116
+ await client.cleanup()
@@ -0,0 +1,186 @@
1
+ import os
2
+ import logging
3
+ from typing import Optional, List
4
+
5
+ from autobyteus.tools.base_tool import BaseTool
6
+ from autobyteus.tools.parameter_schema import ParameterSchema, ParameterDefinition, ParameterType
7
+ from autobyteus.tools.tool_category import ToolCategory
8
+ from autobyteus.multimedia.image import image_client_factory, ImageModel, ImageClientFactory
9
+
10
+ logger = logging.getLogger(__name__)
11
+
12
+
13
+ def _get_configured_model_identifier(env_var: str, default_model: Optional[str] = None) -> str:
14
+ """
15
+ Retrieves a model identifier from an environment variable, with a fallback to a default.
16
+ """
17
+ model_identifier = os.getenv(env_var)
18
+ if not model_identifier:
19
+ if default_model:
20
+ return default_model
21
+ raise ValueError(f"The '{env_var}' environment variable is not set. Please configure it.")
22
+ return model_identifier
23
+
24
+
25
+ def _build_dynamic_image_schema(base_params: List[ParameterDefinition], model_env_var: str, default_model: str) -> ParameterSchema:
26
+ """
27
+ Builds the tool schema dynamically based on the configured image model.
28
+ """
29
+ try:
30
+ model_identifier = _get_configured_model_identifier(model_env_var, default_model)
31
+ ImageClientFactory.ensure_initialized()
32
+ model = ImageModel[model_identifier]
33
+ except (ValueError, KeyError) as e:
34
+ logger.error(f"Cannot generate image tool schema. Check environment and model registry. Error: {e}")
35
+ raise RuntimeError(f"Failed to configure image tool. Error: {e}")
36
+
37
+ config_schema = ParameterSchema()
38
+ if model.parameter_schema:
39
+ for name, meta in model.parameter_schema.items():
40
+ param_type_str = meta.get("type", "string").upper()
41
+ param_type = getattr(ParameterType, param_type_str, ParameterType.STRING)
42
+
43
+ allowed_values = meta.get("allowed_values")
44
+ if param_type == ParameterType.STRING and allowed_values:
45
+ param_type = ParameterType.ENUM
46
+
47
+ config_schema.add_parameter(ParameterDefinition(
48
+ name=name,
49
+ param_type=param_type,
50
+ description=meta.get("description", ""),
51
+ required=False,
52
+ default_value=meta.get("default"),
53
+ enum_values=allowed_values
54
+ ))
55
+
56
+ schema = ParameterSchema()
57
+ for param in base_params:
58
+ schema.add_parameter(param)
59
+
60
+ if config_schema.parameters:
61
+ schema.add_parameter(ParameterDefinition(
62
+ name="generation_config",
63
+ param_type=ParameterType.OBJECT,
64
+ description=f"Model-specific generation parameters for the configured '{model_identifier}' model.",
65
+ required=False,
66
+ object_schema=config_schema.to_json_schema_dict()
67
+ ))
68
+ return schema
69
+
70
+
71
+ class GenerateImageTool(BaseTool):
72
+ """
73
+ An agent tool for generating images from a text prompt using a pre-configured model.
74
+ """
75
+ CATEGORY = ToolCategory.MULTIMEDIA
76
+ MODEL_ENV_VAR = "DEFAULT_IMAGE_GENERATION_MODEL"
77
+ DEFAULT_MODEL = "gpt-image-1"
78
+
79
+ @classmethod
80
+ def get_name(cls) -> str:
81
+ return "GenerateImage"
82
+
83
+ @classmethod
84
+ def get_description(cls) -> str:
85
+ return (
86
+ "Generates one or more images based on a textual description (prompt) using the system's default image model. "
87
+ "Returns a list of URLs to the generated images upon success."
88
+ )
89
+
90
+ @classmethod
91
+ def get_argument_schema(cls) -> Optional[ParameterSchema]:
92
+ base_params = [
93
+ ParameterDefinition(
94
+ name="prompt",
95
+ param_type=ParameterType.STRING,
96
+ description="A detailed textual description of the image to generate.",
97
+ required=True
98
+ )
99
+ ]
100
+ return _build_dynamic_image_schema(base_params, cls.MODEL_ENV_VAR, cls.DEFAULT_MODEL)
101
+
102
+ async def _execute(self, context, prompt: str, generation_config: Optional[dict] = None) -> str:
103
+ model_identifier = _get_configured_model_identifier(self.MODEL_ENV_VAR, self.DEFAULT_MODEL)
104
+ logger.info(f"GenerateImageTool executing with configured model '{model_identifier}'.")
105
+ client = None
106
+ try:
107
+ client = image_client_factory.create_image_client(model_identifier=model_identifier)
108
+ response = await client.generate_image(prompt=prompt, generation_config=generation_config)
109
+
110
+ if not response.image_urls:
111
+ raise ValueError("Image generation failed to return any image URLs.")
112
+
113
+ return f"Image generation successful. URLs: {response.image_urls}"
114
+ finally:
115
+ if client:
116
+ await client.cleanup()
117
+
118
+
119
+ class EditImageTool(BaseTool):
120
+ """
121
+ An agent tool for editing an existing image using a text prompt and a pre-configured model.
122
+ """
123
+ CATEGORY = ToolCategory.MULTIMEDIA
124
+ MODEL_ENV_VAR = "DEFAULT_IMAGE_GENERATION_MODEL"
125
+ DEFAULT_MODEL = "gpt-image-1"
126
+
127
+ @classmethod
128
+ def get_name(cls) -> str:
129
+ return "EditImage"
130
+
131
+ @classmethod
132
+ def get_description(cls) -> str:
133
+ return (
134
+ "Edits an existing image based on a textual description (prompt) using the system's default image model. "
135
+ "A mask can be provided to specify the exact area to edit (inpainting). "
136
+ "Returns a list of URLs to the edited images."
137
+ )
138
+
139
+ @classmethod
140
+ def get_argument_schema(cls) -> Optional[ParameterSchema]:
141
+ base_params = [
142
+ ParameterDefinition(
143
+ name="prompt",
144
+ param_type=ParameterType.STRING,
145
+ description="A detailed textual description of the edits to apply to the image.",
146
+ required=True
147
+ ),
148
+ ParameterDefinition(
149
+ name="input_image_urls",
150
+ param_type=ParameterType.STRING,
151
+ description="A comma-separated string of URLs to the source images that need to be edited. Some models may only use the first URL.",
152
+ required=True
153
+ ),
154
+ ParameterDefinition(
155
+ name="mask_image_url",
156
+ param_type=ParameterType.STRING,
157
+ description="Optional. A URL to a mask image (PNG). The transparent areas of this mask define where the input image should be edited.",
158
+ required=False
159
+ )
160
+ ]
161
+ return _build_dynamic_image_schema(base_params, cls.MODEL_ENV_VAR, cls.DEFAULT_MODEL)
162
+
163
+ async def _execute(self, context, prompt: str, input_image_urls: str, generation_config: Optional[dict] = None, mask_image_url: Optional[str] = None) -> str:
164
+ model_identifier = _get_configured_model_identifier(self.MODEL_ENV_VAR, self.DEFAULT_MODEL)
165
+ logger.info(f"EditImageTool executing with configured model '{model_identifier}'.")
166
+ client = None
167
+ try:
168
+ urls_list = [url.strip() for url in input_image_urls.split(',') if url.strip()]
169
+ if not urls_list:
170
+ raise ValueError("The 'input_image_urls' parameter cannot be empty.")
171
+
172
+ client = image_client_factory.create_image_client(model_identifier=model_identifier)
173
+ response = await client.edit_image(
174
+ prompt=prompt,
175
+ input_image_urls=urls_list,
176
+ mask_url=mask_image_url,
177
+ generation_config=generation_config
178
+ )
179
+
180
+ if not response.image_urls:
181
+ raise ValueError("Image editing failed to return any image URLs.")
182
+
183
+ return f"Image editing successful. URLs: {response.image_urls}"
184
+ finally:
185
+ if client:
186
+ await client.cleanup()
@@ -17,6 +17,7 @@ class ToolCategory(str, Enum):
17
17
  TASK_MANAGEMENT = "Task Management" # NEW CATEGORY ADDED
18
18
  GENERAL = "General"
19
19
  MCP = "MCP"
20
+ MULTIMEDIA = "Multimedia"
20
21
 
21
22
  def __str__(self) -> str:
22
23
  return self.value
@@ -44,8 +44,11 @@ class ProviderAwareToolUsageParser:
44
44
  else:
45
45
  logger.warning(f"Agent '{context.agent_id}': LLM instance or model not available. Cannot determine provider for tool response parsing.")
46
46
 
47
- # Get the correct parser directly from the new central registry.
48
- parser = self._parser_registry.get_parser(llm_provider)
47
+ # Retrieve the override flag from the agent's configuration.
48
+ use_xml_tool_format = context.config.use_xml_tool_format
49
+
50
+ # Get the correct parser from the registry, passing the override flag.
51
+ parser = self._parser_registry.get_parser(llm_provider, use_xml_tool_format=use_xml_tool_format)
49
52
 
50
53
  logger.debug(f"ProviderAwareToolUsageParser selected delegate parser '{parser.get_name()}' for LLM provider '{llm_provider.name if llm_provider else 'Unknown'}'.")
51
54
 
@@ -30,21 +30,23 @@ class ToolManifestProvider:
30
30
 
31
31
  def provide(self,
32
32
  tool_definitions: List['ToolDefinition'],
33
- provider: Optional[LLMProvider] = None) -> str:
33
+ provider: Optional[LLMProvider] = None,
34
+ use_xml_tool_format: bool = False) -> str:
34
35
  """
35
36
  Generates the manifest string for a list of tools.
36
37
 
37
38
  Args:
38
39
  tool_definitions: A list of ToolDefinition objects.
39
40
  provider: The LLM provider, for provider-specific formatting.
41
+ use_xml_tool_format: If True, forces the use of XML formatters.
40
42
 
41
43
  Returns:
42
44
  A single string containing the formatted manifest.
43
45
  """
44
46
  tool_blocks = []
45
47
 
46
- # Get the correct formatting pair from the registry using only the provider.
47
- formatter_pair = self._formatting_registry.get_formatter_pair(provider)
48
+ # Get the correct formatting pair from the registry, passing the override flag.
49
+ formatter_pair = self._formatting_registry.get_formatter_pair(provider, use_xml_tool_format=use_xml_tool_format)
48
50
  schema_formatter = formatter_pair.schema_formatter
49
51
  example_formatter = formatter_pair.example_formatter
50
52
 
@@ -36,19 +36,26 @@ class ToolFormattingRegistry(metaclass=SingletonMeta):
36
36
  }
37
37
  # A default pair for any provider not explicitly listed (defaults to JSON)
38
38
  self._default_pair = ToolFormatterPair(DefaultJsonSchemaFormatter(), DefaultJsonExampleFormatter())
39
+ # A specific pair for the XML override
40
+ self._xml_override_pair = ToolFormatterPair(DefaultXmlSchemaFormatter(), DefaultXmlExampleFormatter())
39
41
 
40
42
  logger.info("ToolFormattingRegistry initialized with direct provider-to-formatter mappings.")
41
43
 
42
- def get_formatter_pair(self, provider: Optional[LLMProvider]) -> ToolFormatterPair:
44
+ def get_formatter_pair(self, provider: Optional[LLMProvider], use_xml_tool_format: bool = False) -> ToolFormatterPair:
43
45
  """
44
- Retrieves the appropriate formatting pair for a given provider.
46
+ Retrieves the appropriate formatting pair for a given provider, honoring the XML override.
45
47
 
46
48
  Args:
47
49
  provider: The LLMProvider enum member.
50
+ use_xml_tool_format: If True, forces the use of XML formatters.
48
51
 
49
52
  Returns:
50
53
  The corresponding ToolFormatterPair instance.
51
54
  """
55
+ if use_xml_tool_format:
56
+ logger.debug("XML tool format is forced by configuration. Returning XML formatter pair.")
57
+ return self._xml_override_pair
58
+
52
59
  if provider and provider in self._pairs:
53
60
  pair = self._pairs[provider]
54
61
  logger.debug(f"Found specific formatter pair for provider {provider.name}: {pair}")
@@ -34,18 +34,25 @@ class ToolUsageParserRegistry(metaclass=SingletonMeta):
34
34
  }
35
35
  # A default parser for any provider not explicitly listed (defaults to JSON)
36
36
  self._default_parser = DefaultJsonToolUsageParser()
37
+ # A specific parser for the XML override
38
+ self._xml_override_parser = DefaultXmlToolUsageParser()
37
39
  logger.info("ToolUsageParserRegistry initialized with direct provider-to-parser mappings.")
38
40
 
39
- def get_parser(self, provider: Optional[LLMProvider]) -> BaseToolUsageParser:
41
+ def get_parser(self, provider: Optional[LLMProvider], use_xml_tool_format: bool = False) -> BaseToolUsageParser:
40
42
  """
41
- Retrieves the appropriate tool usage parser for a given provider.
43
+ Retrieves the appropriate tool usage parser for a given provider, honoring the XML override.
42
44
 
43
45
  Args:
44
46
  provider: The LLMProvider enum member.
47
+ use_xml_tool_format: If True, forces the use of the XML parser.
45
48
 
46
49
  Returns:
47
50
  The corresponding BaseToolUsageParser instance.
48
51
  """
52
+ if use_xml_tool_format:
53
+ logger.debug("XML tool format is forced by configuration. Returning XML parser.")
54
+ return self._xml_override_parser
55
+
49
56
  if provider and provider in self._parsers:
50
57
  parser = self._parsers[provider]
51
58
  logger.debug(f"Found specific tool usage parser for provider {provider.name}: {parser.get_name()}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: autobyteus
3
- Version: 1.1.5
3
+ Version: 1.1.6
4
4
  Summary: Multi-Agent framework
5
5
  Home-page: https://github.com/AutoByteus/autobyteus
6
6
  Author: Ryan Zheng
@@ -15,9 +15,9 @@ Requires-Python: >=3.8
15
15
  Description-Content-Type: text/markdown
16
16
  License-File: LICENSE
17
17
  Requires-Dist: aiohttp
18
- Requires-Dist: anthropic==0.37.1
19
- Requires-Dist: autobyteus-llm-client==1.1.2
20
- Requires-Dist: beautifulsoup4>=4.12.2
18
+ Requires-Dist: anthropic
19
+ Requires-Dist: autobyteus-llm-client==1.1.3
20
+ Requires-Dist: beautifulsoup4
21
21
  Requires-Dist: boto3
22
22
  Requires-Dist: botocore
23
23
  Requires-Dist: brui-core==1.0.9
@@ -25,17 +25,17 @@ Requires-Dist: certifi==2025.4.26
25
25
  Requires-Dist: google-api-python-client
26
26
  Requires-Dist: google-generativeai
27
27
  Requires-Dist: Jinja2
28
- Requires-Dist: mcp[cli]==1.9.1
29
- Requires-Dist: mistral_common==1.6.3
28
+ Requires-Dist: mcp[cli]
29
+ Requires-Dist: mistral_common
30
30
  Requires-Dist: mistralai
31
- Requires-Dist: mistralai==1.5.2
32
- Requires-Dist: numpy==2.2.5
31
+ Requires-Dist: numpy
33
32
  Requires-Dist: ollama
34
33
  Requires-Dist: openai
35
34
  Requires-Dist: requests
36
35
  Requires-Dist: rich
37
36
  Requires-Dist: textual
38
- Requires-Dist: tiktoken==0.7.0
37
+ Requires-Dist: tiktoken
38
+ Requires-Dist: tokenizers
39
39
  Provides-Extra: dev
40
40
  Requires-Dist: coverage; extra == "dev"
41
41
  Requires-Dist: flake8; extra == "dev"