autobyteus 1.0.0__tar.gz
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.
- autobyteus-1.0.0/LICENSE +14 -0
- autobyteus-1.0.0/PKG-INFO +138 -0
- autobyteus-1.0.0/README.md +75 -0
- autobyteus-1.0.0/autobyteus/__init__.py +5 -0
- autobyteus-1.0.0/autobyteus/agent/__init__.py +0 -0
- autobyteus-1.0.0/autobyteus/agent/agent.py +231 -0
- autobyteus-1.0.0/autobyteus/agent/async_agent.py +175 -0
- autobyteus-1.0.0/autobyteus/agent/async_group_aware_agent.py +136 -0
- autobyteus-1.0.0/autobyteus/agent/exceptions.py +6 -0
- autobyteus-1.0.0/autobyteus/agent/factory/__init__.py +0 -0
- autobyteus-1.0.0/autobyteus/agent/group/__init__.py +0 -0
- autobyteus-1.0.0/autobyteus/agent/group/async_group_aware_agent.py +122 -0
- autobyteus-1.0.0/autobyteus/agent/group/coordinator_agent.py +36 -0
- autobyteus-1.0.0/autobyteus/agent/group/group_aware_agent.py +121 -0
- autobyteus-1.0.0/autobyteus/agent/message/__init__.py +0 -0
- autobyteus-1.0.0/autobyteus/agent/message/message.py +41 -0
- autobyteus-1.0.0/autobyteus/agent/message/message_types.py +29 -0
- autobyteus-1.0.0/autobyteus/agent/message/send_message_to.py +47 -0
- autobyteus-1.0.0/autobyteus/agent/orchestrator/__init__.py +0 -0
- autobyteus-1.0.0/autobyteus/agent/orchestrator/base_agent_orchestrator.py +82 -0
- autobyteus-1.0.0/autobyteus/agent/orchestrator/multi_replica_agent_orchestrator.py +72 -0
- autobyteus-1.0.0/autobyteus/agent/orchestrator/single_replica_agent_orchestrator.py +43 -0
- autobyteus-1.0.0/autobyteus/agent/response_parser/__init__.py +0 -0
- autobyteus-1.0.0/autobyteus/agent/response_parser/tool_usage_command_parser.py +100 -0
- autobyteus-1.0.0/autobyteus/agent/status.py +12 -0
- autobyteus-1.0.0/autobyteus/agent/tool_invocation.py +7 -0
- autobyteus-1.0.0/autobyteus/check_requirements.py +33 -0
- autobyteus-1.0.0/autobyteus/conversation/__init__.py +0 -0
- autobyteus-1.0.0/autobyteus/conversation/conversation.py +54 -0
- autobyteus-1.0.0/autobyteus/conversation/user_message.py +59 -0
- autobyteus-1.0.0/autobyteus/events/__init__.py +0 -0
- autobyteus-1.0.0/autobyteus/events/decorators.py +29 -0
- autobyteus-1.0.0/autobyteus/events/event_emitter.py +74 -0
- autobyteus-1.0.0/autobyteus/events/event_manager.py +73 -0
- autobyteus-1.0.0/autobyteus/events/event_types.py +17 -0
- autobyteus-1.0.0/autobyteus/llm/__init__.py +0 -0
- autobyteus-1.0.0/autobyteus/llm/api/__init__.py +0 -0
- autobyteus-1.0.0/autobyteus/llm/api/autobyteus_llm.py +136 -0
- autobyteus-1.0.0/autobyteus/llm/api/bedrock_llm.py +78 -0
- autobyteus-1.0.0/autobyteus/llm/api/claude_llm.py +138 -0
- autobyteus-1.0.0/autobyteus/llm/api/deepseek_llm.py +226 -0
- autobyteus-1.0.0/autobyteus/llm/api/gemini_llm.py +79 -0
- autobyteus-1.0.0/autobyteus/llm/api/grok_llm.py +211 -0
- autobyteus-1.0.0/autobyteus/llm/api/groq_llm.py +88 -0
- autobyteus-1.0.0/autobyteus/llm/api/mistral_llm.py +120 -0
- autobyteus-1.0.0/autobyteus/llm/api/nvidia_llm.py +102 -0
- autobyteus-1.0.0/autobyteus/llm/api/ollama_llm.py +130 -0
- autobyteus-1.0.0/autobyteus/llm/api/openai_llm.py +148 -0
- autobyteus-1.0.0/autobyteus/llm/autobyteus_provider.py +172 -0
- autobyteus-1.0.0/autobyteus/llm/base_llm.py +222 -0
- autobyteus-1.0.0/autobyteus/llm/extensions/__init__.py +0 -0
- autobyteus-1.0.0/autobyteus/llm/extensions/base_extension.py +45 -0
- autobyteus-1.0.0/autobyteus/llm/extensions/extension_registry.py +37 -0
- autobyteus-1.0.0/autobyteus/llm/extensions/token_usage_tracking_extension.py +79 -0
- autobyteus-1.0.0/autobyteus/llm/llm_factory.py +292 -0
- autobyteus-1.0.0/autobyteus/llm/models.py +73 -0
- autobyteus-1.0.0/autobyteus/llm/ollama_provider.py +98 -0
- autobyteus-1.0.0/autobyteus/llm/providers.py +14 -0
- autobyteus-1.0.0/autobyteus/llm/token_counter/__init__.py +0 -0
- autobyteus-1.0.0/autobyteus/llm/token_counter/base_token_counter.py +69 -0
- autobyteus-1.0.0/autobyteus/llm/token_counter/claude_token_counter.py +77 -0
- autobyteus-1.0.0/autobyteus/llm/token_counter/deepseek_token_counter.py +24 -0
- autobyteus-1.0.0/autobyteus/llm/token_counter/mistral_token_counter.py +115 -0
- autobyteus-1.0.0/autobyteus/llm/token_counter/openai_token_counter.py +84 -0
- autobyteus-1.0.0/autobyteus/llm/token_counter/token_counter_factory.py +40 -0
- autobyteus-1.0.0/autobyteus/llm/utils/__init__.py +0 -0
- autobyteus-1.0.0/autobyteus/llm/utils/image_payload_formatter.py +89 -0
- autobyteus-1.0.0/autobyteus/llm/utils/llm_config.py +90 -0
- autobyteus-1.0.0/autobyteus/llm/utils/messages.py +40 -0
- autobyteus-1.0.0/autobyteus/llm/utils/rate_limiter.py +41 -0
- autobyteus-1.0.0/autobyteus/llm/utils/response_types.py +19 -0
- autobyteus-1.0.0/autobyteus/llm/utils/token_pricing_config.py +87 -0
- autobyteus-1.0.0/autobyteus/llm/utils/token_usage.py +13 -0
- autobyteus-1.0.0/autobyteus/llm/utils/token_usage_tracker.py +98 -0
- autobyteus-1.0.0/autobyteus/person/__init__.py +0 -0
- autobyteus-1.0.0/autobyteus/person/examples/__init__.py +0 -0
- autobyteus-1.0.0/autobyteus/person/examples/sample_persons.py +14 -0
- autobyteus-1.0.0/autobyteus/person/examples/sample_roles.py +14 -0
- autobyteus-1.0.0/autobyteus/person/person.py +29 -0
- autobyteus-1.0.0/autobyteus/person/role.py +14 -0
- autobyteus-1.0.0/autobyteus/prompt/__init__.py +0 -0
- autobyteus-1.0.0/autobyteus/prompt/prompt_builder.py +64 -0
- autobyteus-1.0.0/autobyteus/prompt/prompt_template.py +44 -0
- autobyteus-1.0.0/autobyteus/prompt/prompt_version_manager.py +58 -0
- autobyteus-1.0.0/autobyteus/prompt/storage/__init__.py +0 -0
- autobyteus-1.0.0/autobyteus/prompt/storage/prompt_version_model.py +29 -0
- autobyteus-1.0.0/autobyteus/prompt/storage/prompt_version_repository.py +83 -0
- autobyteus-1.0.0/autobyteus/tools/__init__.py +0 -0
- autobyteus-1.0.0/autobyteus/tools/ask_user_input.py +93 -0
- autobyteus-1.0.0/autobyteus/tools/base_tool.py +49 -0
- autobyteus-1.0.0/autobyteus/tools/bash/__init__.py +0 -0
- autobyteus-1.0.0/autobyteus/tools/bash/bash_executor.py +103 -0
- autobyteus-1.0.0/autobyteus/tools/bash/factory/__init__.py +0 -0
- autobyteus-1.0.0/autobyteus/tools/bash/factory/bash_executor_factory.py +6 -0
- autobyteus-1.0.0/autobyteus/tools/browser/__init__.py +0 -0
- autobyteus-1.0.0/autobyteus/tools/browser/session_aware/__init__.py +0 -0
- autobyteus-1.0.0/autobyteus/tools/browser/session_aware/browser_session_aware_navigate_to.py +61 -0
- autobyteus-1.0.0/autobyteus/tools/browser/session_aware/browser_session_aware_tool.py +27 -0
- autobyteus-1.0.0/autobyteus/tools/browser/session_aware/browser_session_aware_web_element_trigger.py +202 -0
- autobyteus-1.0.0/autobyteus/tools/browser/session_aware/browser_session_aware_webpage_reader.py +29 -0
- autobyteus-1.0.0/autobyteus/tools/browser/session_aware/browser_session_aware_webpage_screenshot_taker.py +34 -0
- autobyteus-1.0.0/autobyteus/tools/browser/session_aware/factory/__init__.py +0 -0
- autobyteus-1.0.0/autobyteus/tools/browser/session_aware/factory/browser_session_aware_web_element_trigger_factory.py +6 -0
- autobyteus-1.0.0/autobyteus/tools/browser/session_aware/factory/browser_session_aware_webpage_reader_factory.py +10 -0
- autobyteus-1.0.0/autobyteus/tools/browser/session_aware/factory/browser_session_aware_webpage_screenshot_taker_factory.py +6 -0
- autobyteus-1.0.0/autobyteus/tools/browser/session_aware/shared_browser_session.py +11 -0
- autobyteus-1.0.0/autobyteus/tools/browser/session_aware/shared_browser_session_manager.py +24 -0
- autobyteus-1.0.0/autobyteus/tools/browser/session_aware/web_element_action.py +20 -0
- autobyteus-1.0.0/autobyteus/tools/browser/standalone/__init__.py +0 -0
- autobyteus-1.0.0/autobyteus/tools/browser/standalone/factory/__init__.py +0 -0
- autobyteus-1.0.0/autobyteus/tools/browser/standalone/factory/google_search_factory.py +10 -0
- autobyteus-1.0.0/autobyteus/tools/browser/standalone/factory/webpage_reader_factory.py +10 -0
- autobyteus-1.0.0/autobyteus/tools/browser/standalone/factory/webpage_screenshot_taker_factory.py +6 -0
- autobyteus-1.0.0/autobyteus/tools/browser/standalone/google_search_ui.py +113 -0
- autobyteus-1.0.0/autobyteus/tools/browser/standalone/navigate_to.py +62 -0
- autobyteus-1.0.0/autobyteus/tools/browser/standalone/webpage_image_downloader.py +128 -0
- autobyteus-1.0.0/autobyteus/tools/browser/standalone/webpage_reader.py +78 -0
- autobyteus-1.0.0/autobyteus/tools/browser/standalone/webpage_screenshot_taker.py +49 -0
- autobyteus-1.0.0/autobyteus/tools/factory/__init__.py +0 -0
- autobyteus-1.0.0/autobyteus/tools/factory/ask_user_input_factory.py +6 -0
- autobyteus-1.0.0/autobyteus/tools/factory/image_downloader_factory.py +9 -0
- autobyteus-1.0.0/autobyteus/tools/factory/pdf_downloader_factory.py +9 -0
- autobyteus-1.0.0/autobyteus/tools/factory/tool_factory.py +8 -0
- autobyteus-1.0.0/autobyteus/tools/factory/webpage_image_downloader_factory.py +6 -0
- autobyteus-1.0.0/autobyteus/tools/file/__init__.py +0 -0
- autobyteus-1.0.0/autobyteus/tools/file/factory/__init__.py +0 -0
- autobyteus-1.0.0/autobyteus/tools/file/factory/file_reader_factory.py +6 -0
- autobyteus-1.0.0/autobyteus/tools/file/factory/file_writer_factory.py +6 -0
- autobyteus-1.0.0/autobyteus/tools/file/file_reader.py +60 -0
- autobyteus-1.0.0/autobyteus/tools/file/file_writer.py +65 -0
- autobyteus-1.0.0/autobyteus/tools/handlers/__init__.py +0 -0
- autobyteus-1.0.0/autobyteus/tools/handlers/shell_handler.py +32 -0
- autobyteus-1.0.0/autobyteus/tools/image_downloader.py +142 -0
- autobyteus-1.0.0/autobyteus/tools/operation/__init__.py +0 -0
- autobyteus-1.0.0/autobyteus/tools/operation/file_operation.py +73 -0
- autobyteus-1.0.0/autobyteus/tools/operation/file_rename_operation.py +52 -0
- autobyteus-1.0.0/autobyteus/tools/operation/operation.py +64 -0
- autobyteus-1.0.0/autobyteus/tools/operation/shell_operation.py +65 -0
- autobyteus-1.0.0/autobyteus/tools/pdf_downloader.py +94 -0
- autobyteus-1.0.0/autobyteus/tools/timer.py +123 -0
- autobyteus-1.0.0/autobyteus/tools/utils.py +17 -0
- autobyteus-1.0.0/autobyteus/tools/web_page_pdf_generator.py +86 -0
- autobyteus-1.0.0/autobyteus/utils/__init__.py +0 -0
- autobyteus-1.0.0/autobyteus/utils/dynamic_enum.py +35 -0
- autobyteus-1.0.0/autobyteus/utils/file_utils.py +15 -0
- autobyteus-1.0.0/autobyteus/utils/html_cleaner.py +240 -0
- autobyteus-1.0.0/autobyteus/utils/singleton.py +26 -0
- autobyteus-1.0.0/autobyteus/workflow/__init__.py +0 -0
- autobyteus-1.0.0/autobyteus/workflow/simple_task.py +98 -0
- autobyteus-1.0.0/autobyteus/workflow/task.py +147 -0
- autobyteus-1.0.0/autobyteus/workflow/workflow.py +49 -0
- autobyteus-1.0.0/autobyteus.egg-info/PKG-INFO +138 -0
- autobyteus-1.0.0/autobyteus.egg-info/SOURCES.txt +157 -0
- autobyteus-1.0.0/autobyteus.egg-info/dependency_links.txt +1 -0
- autobyteus-1.0.0/autobyteus.egg-info/requires.txt +37 -0
- autobyteus-1.0.0/autobyteus.egg-info/top_level.txt +1 -0
- autobyteus-1.0.0/pyproject.toml +6 -0
- autobyteus-1.0.0/setup.cfg +4 -0
- autobyteus-1.0.0/setup.py +72 -0
autobyteus-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
MIT License with Additional Terms for Commercial Use
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person or organization obtaining a copy of this software and associated documentation files (the "Software"), to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, subject to the following conditions:
|
|
4
|
+
|
|
5
|
+
1. Commercial Use: The use of the Software for commercial purposes requires the payment of a licensing fee. For details regarding licensing and fees, please contact ryan.zheng at ryan.zheng.work@gmail.com.
|
|
6
|
+
|
|
7
|
+
2. Redistributions: Redistributions of the Software in source code or other forms must include the above copyright notice, this list of conditions, and the following disclaimer.
|
|
8
|
+
|
|
9
|
+
3. Patent Grant: The provisions of the Apache 2.0 License regarding patent grants apply to this License.
|
|
10
|
+
|
|
11
|
+
4. No Warranty/Liability: The Software is provided "as is," without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and non-infringement. In no event shall the authors or copyright holders be liable for any claim, damages, or other liability, whether in an action of contract, tort, or otherwise, arising from, out of, or in connection with the Software or the use or other dealings in the Software.
|
|
12
|
+
|
|
13
|
+
AutoByteus
|
|
14
|
+
17.07.2023
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: autobyteus
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Multi-Agent framework
|
|
5
|
+
Home-page: https://github.com/AutoByteus/autobyteus
|
|
6
|
+
Author: Ryan Zheng
|
|
7
|
+
Author-email: ryan.zheng.work@gmail.com
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Requires-Python: >=3.8
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
Requires-Dist: beautifulsoup4>=4.12.2
|
|
18
|
+
Requires-Dist: openai
|
|
19
|
+
Requires-Dist: requests
|
|
20
|
+
Requires-Dist: tiktoken==0.7.0
|
|
21
|
+
Requires-Dist: google-api-python-client
|
|
22
|
+
Requires-Dist: google-generativeai
|
|
23
|
+
Requires-Dist: mistralai
|
|
24
|
+
Requires-Dist: boto3
|
|
25
|
+
Requires-Dist: botocore
|
|
26
|
+
Requires-Dist: anthropic==0.37.1
|
|
27
|
+
Requires-Dist: Jinja2
|
|
28
|
+
Requires-Dist: ollama==0.4.5
|
|
29
|
+
Requires-Dist: mistral_common
|
|
30
|
+
Requires-Dist: aiohttp
|
|
31
|
+
Requires-Dist: autobyteus-llm-client==1.0.8
|
|
32
|
+
Requires-Dist: brui-core==1.0.4
|
|
33
|
+
Provides-Extra: dev
|
|
34
|
+
Requires-Dist: coverage; extra == "dev"
|
|
35
|
+
Requires-Dist: flake8; extra == "dev"
|
|
36
|
+
Requires-Dist: numpy; extra == "dev"
|
|
37
|
+
Requires-Dist: pre-commit; extra == "dev"
|
|
38
|
+
Requires-Dist: black; extra == "dev"
|
|
39
|
+
Requires-Dist: isort; extra == "dev"
|
|
40
|
+
Requires-Dist: gitpython==3.1.31; extra == "dev"
|
|
41
|
+
Requires-Dist: auto-gpt-plugin-template; extra == "dev"
|
|
42
|
+
Requires-Dist: mkdocs; extra == "dev"
|
|
43
|
+
Requires-Dist: pytest; extra == "dev"
|
|
44
|
+
Requires-Dist: asynctest; extra == "dev"
|
|
45
|
+
Requires-Dist: pytest-asyncio; extra == "dev"
|
|
46
|
+
Requires-Dist: pytest-benchmark; extra == "dev"
|
|
47
|
+
Requires-Dist: pytest-cov; extra == "dev"
|
|
48
|
+
Requires-Dist: pytest-integration; extra == "dev"
|
|
49
|
+
Requires-Dist: pytest-mock; extra == "dev"
|
|
50
|
+
Requires-Dist: vcrpy; extra == "dev"
|
|
51
|
+
Requires-Dist: pytest-vcr; extra == "dev"
|
|
52
|
+
Requires-Dist: load_dotenv; extra == "dev"
|
|
53
|
+
Dynamic: author
|
|
54
|
+
Dynamic: author-email
|
|
55
|
+
Dynamic: classifier
|
|
56
|
+
Dynamic: description
|
|
57
|
+
Dynamic: description-content-type
|
|
58
|
+
Dynamic: home-page
|
|
59
|
+
Dynamic: provides-extra
|
|
60
|
+
Dynamic: requires-dist
|
|
61
|
+
Dynamic: requires-python
|
|
62
|
+
Dynamic: summary
|
|
63
|
+
|
|
64
|
+
# Autobyteus
|
|
65
|
+
|
|
66
|
+
Autobyteus is an open-source coding assistance tool designed to enhance the software development workflow by making it context-aware. Each step in the workflow is interactive through a user-friendly interface, incorporating the entire software development lifecycle into each stage.
|
|
67
|
+
|
|
68
|
+
## Features
|
|
69
|
+
|
|
70
|
+
- **Context-Aware Workflows**: Each step in the development process interacts with large language models to provide relevant assistance.
|
|
71
|
+
- **Lifecycle Integration**: Supports the entire software development lifecycle, starting from requirement engineering.
|
|
72
|
+
- **Memory Management**: Custom memory management system supporting different memory providers and embeddings.
|
|
73
|
+
|
|
74
|
+
## Knowledge Base
|
|
75
|
+
|
|
76
|
+
A significant part of Autobytus is our custom-designed knowledge base focused on software and application development. The knowledge base is structured to support the entire development process, with particular emphasis on requirement engineering, which is crucial for successful project outcomes.
|
|
77
|
+
|
|
78
|
+
## Getting Started
|
|
79
|
+
|
|
80
|
+
### Installation
|
|
81
|
+
|
|
82
|
+
1. **For users:**
|
|
83
|
+
To install Autobyteus, run:
|
|
84
|
+
```
|
|
85
|
+
pip install .
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
2. **For developers:**
|
|
89
|
+
To install Autobyteus with development dependencies, run:
|
|
90
|
+
```
|
|
91
|
+
pip install -r requirements-dev.txt
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
3. **Platform-specific dependencies:**
|
|
95
|
+
To install platform-specific dependencies, run:
|
|
96
|
+
```
|
|
97
|
+
python setup.py install_platform_deps
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Building the Library
|
|
101
|
+
|
|
102
|
+
To build Autobyteus as a distributable package, follow these steps:
|
|
103
|
+
|
|
104
|
+
1. Ensure you have the latest version of `setuptools` and `wheel` installed:
|
|
105
|
+
```
|
|
106
|
+
pip install --upgrade setuptools wheel
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
2. Build the distribution packages:
|
|
110
|
+
```
|
|
111
|
+
python setup.py sdist bdist_wheel
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
This will create a `dist` directory containing the built distributions.
|
|
115
|
+
|
|
116
|
+
3. (Optional) To create a source distribution only:
|
|
117
|
+
```
|
|
118
|
+
python setup.py sdist
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
4. (Optional) To create a wheel distribution only:
|
|
122
|
+
```
|
|
123
|
+
python setup.py bdist_wheel
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
The built packages will be in the `dist` directory and can be installed using pip or distributed as needed.
|
|
127
|
+
|
|
128
|
+
### Usage
|
|
129
|
+
|
|
130
|
+
(Add basic commands and examples to get users started)
|
|
131
|
+
|
|
132
|
+
### Contributing
|
|
133
|
+
|
|
134
|
+
(Add guidelines for contributing to the project)
|
|
135
|
+
|
|
136
|
+
## License
|
|
137
|
+
|
|
138
|
+
This project is licensed under the MIT License.
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Autobyteus
|
|
2
|
+
|
|
3
|
+
Autobyteus is an open-source coding assistance tool designed to enhance the software development workflow by making it context-aware. Each step in the workflow is interactive through a user-friendly interface, incorporating the entire software development lifecycle into each stage.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Context-Aware Workflows**: Each step in the development process interacts with large language models to provide relevant assistance.
|
|
8
|
+
- **Lifecycle Integration**: Supports the entire software development lifecycle, starting from requirement engineering.
|
|
9
|
+
- **Memory Management**: Custom memory management system supporting different memory providers and embeddings.
|
|
10
|
+
|
|
11
|
+
## Knowledge Base
|
|
12
|
+
|
|
13
|
+
A significant part of Autobytus is our custom-designed knowledge base focused on software and application development. The knowledge base is structured to support the entire development process, with particular emphasis on requirement engineering, which is crucial for successful project outcomes.
|
|
14
|
+
|
|
15
|
+
## Getting Started
|
|
16
|
+
|
|
17
|
+
### Installation
|
|
18
|
+
|
|
19
|
+
1. **For users:**
|
|
20
|
+
To install Autobyteus, run:
|
|
21
|
+
```
|
|
22
|
+
pip install .
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
2. **For developers:**
|
|
26
|
+
To install Autobyteus with development dependencies, run:
|
|
27
|
+
```
|
|
28
|
+
pip install -r requirements-dev.txt
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
3. **Platform-specific dependencies:**
|
|
32
|
+
To install platform-specific dependencies, run:
|
|
33
|
+
```
|
|
34
|
+
python setup.py install_platform_deps
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Building the Library
|
|
38
|
+
|
|
39
|
+
To build Autobyteus as a distributable package, follow these steps:
|
|
40
|
+
|
|
41
|
+
1. Ensure you have the latest version of `setuptools` and `wheel` installed:
|
|
42
|
+
```
|
|
43
|
+
pip install --upgrade setuptools wheel
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
2. Build the distribution packages:
|
|
47
|
+
```
|
|
48
|
+
python setup.py sdist bdist_wheel
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
This will create a `dist` directory containing the built distributions.
|
|
52
|
+
|
|
53
|
+
3. (Optional) To create a source distribution only:
|
|
54
|
+
```
|
|
55
|
+
python setup.py sdist
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
4. (Optional) To create a wheel distribution only:
|
|
59
|
+
```
|
|
60
|
+
python setup.py bdist_wheel
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
The built packages will be in the `dist` directory and can be installed using pip or distributed as needed.
|
|
64
|
+
|
|
65
|
+
### Usage
|
|
66
|
+
|
|
67
|
+
(Add basic commands and examples to get users started)
|
|
68
|
+
|
|
69
|
+
### Contributing
|
|
70
|
+
|
|
71
|
+
(Add guidelines for contributing to the project)
|
|
72
|
+
|
|
73
|
+
## License
|
|
74
|
+
|
|
75
|
+
This project is licensed under the MIT License.
|
|
File without changes
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import logging
|
|
3
|
+
from typing import List, Optional
|
|
4
|
+
from autobyteus.agent.response_parser.tool_usage_command_parser import ToolUsageCommandParser
|
|
5
|
+
from autobyteus.events.event_emitter import EventEmitter
|
|
6
|
+
from autobyteus.llm.base_llm import BaseLLM
|
|
7
|
+
from autobyteus.tools.base_tool import BaseTool
|
|
8
|
+
from autobyteus.prompt.prompt_builder import PromptBuilder
|
|
9
|
+
from autobyteus.events.event_types import EventType
|
|
10
|
+
from autobyteus.agent.status import AgentStatus
|
|
11
|
+
from autobyteus.conversation.user_message import UserMessage
|
|
12
|
+
from autobyteus.conversation.conversation import Conversation
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
class Agent(EventEmitter):
|
|
17
|
+
def __init__(self, role: str, llm: BaseLLM, tools: Optional[List[BaseTool]] = None,
|
|
18
|
+
agent_id=None,
|
|
19
|
+
prompt_builder: Optional[PromptBuilder] = None,
|
|
20
|
+
initial_user_message: Optional[UserMessage] = None):
|
|
21
|
+
super().__init__()
|
|
22
|
+
self.role = role
|
|
23
|
+
self.llm = llm
|
|
24
|
+
self.tools = tools or []
|
|
25
|
+
self.tool_usage_response_parser = ToolUsageCommandParser() if self.tools else None
|
|
26
|
+
self.conversation = None
|
|
27
|
+
self.agent_id = agent_id or f"{self.role}-001"
|
|
28
|
+
self.status = AgentStatus.NOT_STARTED
|
|
29
|
+
self._run_task = None
|
|
30
|
+
self._queues_initialized = False
|
|
31
|
+
self.task_completed = None
|
|
32
|
+
self.prompt_builder = prompt_builder
|
|
33
|
+
self.initial_user_message = initial_user_message
|
|
34
|
+
|
|
35
|
+
if not self.prompt_builder and not self.initial_user_message:
|
|
36
|
+
raise ValueError("Either prompt_builder or initial_user_message must be provided")
|
|
37
|
+
|
|
38
|
+
if self.tools:
|
|
39
|
+
self.set_agent_id_on_tools()
|
|
40
|
+
|
|
41
|
+
logger.info(f"StandaloneAgent initialized with role: {self.role}, agent_id: {self.agent_id}")
|
|
42
|
+
|
|
43
|
+
def _initialize_queues(self):
|
|
44
|
+
if not self._queues_initialized:
|
|
45
|
+
self.tool_result_messages = asyncio.Queue()
|
|
46
|
+
self.user_messages = asyncio.Queue()
|
|
47
|
+
self._queues_initialized = True
|
|
48
|
+
logger.info(f"Queues initialized for agent {self.role}")
|
|
49
|
+
|
|
50
|
+
def _initialize_task_completed(self):
|
|
51
|
+
if self.task_completed is None:
|
|
52
|
+
self.task_completed = asyncio.Event()
|
|
53
|
+
logger.info(f"task_completed Event initialized for agent {self.role}")
|
|
54
|
+
|
|
55
|
+
def get_task_completed(self):
|
|
56
|
+
if self.task_completed is None:
|
|
57
|
+
raise RuntimeError("task_completed Event accessed before initialization")
|
|
58
|
+
return self.task_completed
|
|
59
|
+
|
|
60
|
+
async def run(self):
|
|
61
|
+
try:
|
|
62
|
+
logger.info(f"Starting execution for agent: {self.role}")
|
|
63
|
+
self._initialize_queues()
|
|
64
|
+
self._initialize_task_completed()
|
|
65
|
+
await self.initialize_conversation()
|
|
66
|
+
|
|
67
|
+
user_message_handler = asyncio.create_task(self.handle_user_messages())
|
|
68
|
+
tool_result_handler = asyncio.create_task(self.handle_tool_result_messages())
|
|
69
|
+
|
|
70
|
+
# Once everything is ready, set the status to RUNNING
|
|
71
|
+
self.status = AgentStatus.RUNNING
|
|
72
|
+
|
|
73
|
+
await asyncio.gather(user_message_handler, tool_result_handler)
|
|
74
|
+
|
|
75
|
+
except Exception as e:
|
|
76
|
+
logger.error(f"Error in agent {self.role} execution: {str(e)}")
|
|
77
|
+
self.status = AgentStatus.ERROR
|
|
78
|
+
finally:
|
|
79
|
+
self.status = AgentStatus.ENDED
|
|
80
|
+
await self.cleanup()
|
|
81
|
+
|
|
82
|
+
async def handle_user_messages(self):
|
|
83
|
+
logger.info(f"Agent {self.role} started handling user messages")
|
|
84
|
+
while not self.task_completed.is_set() and self.status == AgentStatus.RUNNING:
|
|
85
|
+
try:
|
|
86
|
+
user_message: UserMessage = await asyncio.wait_for(self.user_messages.get(), timeout=1.0)
|
|
87
|
+
logger.info(f"Agent {self.role} handling user message")
|
|
88
|
+
response = await self.conversation.send_user_message(user_message.content, user_message.file_paths)
|
|
89
|
+
await self.process_llm_response(response)
|
|
90
|
+
except asyncio.TimeoutError:
|
|
91
|
+
continue
|
|
92
|
+
except asyncio.CancelledError:
|
|
93
|
+
logger.info(f"User message handler for agent {self.role} cancelled")
|
|
94
|
+
break
|
|
95
|
+
except Exception as e:
|
|
96
|
+
logger.error(f"Error handling user message for agent {self.role}: {str(e)}")
|
|
97
|
+
|
|
98
|
+
async def receive_user_message(self, message: UserMessage):
|
|
99
|
+
"""
|
|
100
|
+
This method gracefully waits for the agent to become RUNNING
|
|
101
|
+
if it's in the process of starting up, ensuring the queues are
|
|
102
|
+
initialized before we put a message into them.
|
|
103
|
+
"""
|
|
104
|
+
logger.info(f"Agent {self.agent_id} received user message")
|
|
105
|
+
|
|
106
|
+
# If the agent is not started (or ended), begin the start process
|
|
107
|
+
if self.status in [AgentStatus.NOT_STARTED, AgentStatus.ENDED]:
|
|
108
|
+
self.start()
|
|
109
|
+
|
|
110
|
+
# If the agent is still starting, wait until it transitions to RUNNING
|
|
111
|
+
while self.status == AgentStatus.STARTING:
|
|
112
|
+
await asyncio.sleep(0.1)
|
|
113
|
+
|
|
114
|
+
if self.status != AgentStatus.RUNNING:
|
|
115
|
+
logger.error(f"Agent is not in a running state: {self.status}")
|
|
116
|
+
return
|
|
117
|
+
|
|
118
|
+
# Now that we are running, safely place the message in the queue
|
|
119
|
+
await self.user_messages.put(message)
|
|
120
|
+
|
|
121
|
+
async def handle_tool_result_messages(self):
|
|
122
|
+
logger.info(f"Agent {self.role} started handling tool result messages")
|
|
123
|
+
while not self.task_completed.is_set() and self.status == AgentStatus.RUNNING:
|
|
124
|
+
try:
|
|
125
|
+
message = await asyncio.wait_for(self.tool_result_messages.get(), timeout=1.0)
|
|
126
|
+
logger.info(f"Agent {self.role} handling tool result message: {message}")
|
|
127
|
+
response = await self.conversation.send_user_message(f"Tool execution result: {message}")
|
|
128
|
+
await self.process_llm_response(response)
|
|
129
|
+
except asyncio.TimeoutError:
|
|
130
|
+
continue
|
|
131
|
+
except asyncio.CancelledError:
|
|
132
|
+
logger.info(f"Tool result handler for agent {self.role} cancelled")
|
|
133
|
+
break
|
|
134
|
+
except Exception as e:
|
|
135
|
+
logger.error(f"Error handling tool result for agent {self.role}: {str(e)}")
|
|
136
|
+
|
|
137
|
+
async def initialize_conversation(self):
|
|
138
|
+
logger.info(f"Initializing conversation for agent: {self.role}")
|
|
139
|
+
self.conversation = Conversation(self.llm)
|
|
140
|
+
|
|
141
|
+
if self.initial_user_message:
|
|
142
|
+
initial_message = self.initial_user_message
|
|
143
|
+
else:
|
|
144
|
+
prompt_content = self.prompt_builder.set_variable_value(
|
|
145
|
+
"external_tools",
|
|
146
|
+
self._get_external_tools_section()
|
|
147
|
+
).build()
|
|
148
|
+
initial_message = UserMessage(content=prompt_content)
|
|
149
|
+
|
|
150
|
+
logger.debug(f"Initial user message for agent {self.role}: {initial_message}")
|
|
151
|
+
initial_llm_response = await self.conversation.send_user_message(
|
|
152
|
+
initial_message.content,
|
|
153
|
+
initial_message.file_paths
|
|
154
|
+
)
|
|
155
|
+
await self.process_llm_response(initial_llm_response)
|
|
156
|
+
|
|
157
|
+
async def process_llm_response(self, response: str) -> None:
|
|
158
|
+
self.emit(EventType.ASSISTANT_RESPONSE, response=response)
|
|
159
|
+
|
|
160
|
+
if self.tools and self.tool_usage_response_parser:
|
|
161
|
+
tool_invocation = self.tool_usage_response_parser.parse_response(response)
|
|
162
|
+
if tool_invocation.is_valid():
|
|
163
|
+
await self.execute_tool(tool_invocation)
|
|
164
|
+
return
|
|
165
|
+
|
|
166
|
+
logger.info(f"Assistant response for agent {self.role}: {response}")
|
|
167
|
+
|
|
168
|
+
async def execute_tool(self, tool_invocation):
|
|
169
|
+
name = tool_invocation.name
|
|
170
|
+
arguments = tool_invocation.arguments
|
|
171
|
+
logger.info(f"Agent {self.role} attempting to execute tool: {name}")
|
|
172
|
+
|
|
173
|
+
tool = next((t for t in self.tools if t.get_name() == name), None)
|
|
174
|
+
if tool:
|
|
175
|
+
try:
|
|
176
|
+
result = await tool.execute(**arguments)
|
|
177
|
+
logger.info(f"Tool '{name}' executed successfully by agent {self.role}. Result: {result}")
|
|
178
|
+
await self.tool_result_messages.put(result)
|
|
179
|
+
except Exception as e:
|
|
180
|
+
error_message = str(e)
|
|
181
|
+
logger.error(f"Error executing tool '{name}' by agent {self.role}: {error_message}")
|
|
182
|
+
await self.tool_result_messages.put(f"Error: {error_message}")
|
|
183
|
+
else:
|
|
184
|
+
logger.warning(f"Tool '{name}' not found for agent {self.role}.")
|
|
185
|
+
|
|
186
|
+
def start(self):
|
|
187
|
+
"""
|
|
188
|
+
Starts the agent by creating a task that runs the main loop (run).
|
|
189
|
+
Sets the AgentStatus to STARTING to prevent message enqueuing before
|
|
190
|
+
the system is fully initialized.
|
|
191
|
+
"""
|
|
192
|
+
if self.status in [AgentStatus.NOT_STARTED, AgentStatus.ENDED]:
|
|
193
|
+
logger.info(f"Starting agent {self.role}")
|
|
194
|
+
self.status = AgentStatus.STARTING
|
|
195
|
+
self._run_task = asyncio.create_task(self.run())
|
|
196
|
+
elif self.status == AgentStatus.STARTING:
|
|
197
|
+
logger.info(f"Agent {self.role} is already in STARTING state.")
|
|
198
|
+
elif self.status == AgentStatus.RUNNING:
|
|
199
|
+
logger.info(f"Agent {self.role} is already running.")
|
|
200
|
+
else:
|
|
201
|
+
logger.warning(f"Agent {self.role} is in an unexpected state: {self.status}")
|
|
202
|
+
|
|
203
|
+
def stop(self):
|
|
204
|
+
if self._run_task and not self._run_task.done():
|
|
205
|
+
self._run_task.cancel()
|
|
206
|
+
|
|
207
|
+
async def cleanup(self):
|
|
208
|
+
while not self.tool_result_messages.empty():
|
|
209
|
+
self.tool_result_messages.get_nowait()
|
|
210
|
+
while not self.user_messages.empty():
|
|
211
|
+
self.user_messages.get_nowait()
|
|
212
|
+
await self.llm.cleanup()
|
|
213
|
+
logger.info(f"Cleanup completed for agent: {self.role}")
|
|
214
|
+
|
|
215
|
+
def set_agent_id_on_tools(self):
|
|
216
|
+
if self.tools:
|
|
217
|
+
for tool in self.tools:
|
|
218
|
+
tool.set_agent_id(self.agent_id)
|
|
219
|
+
|
|
220
|
+
def _get_external_tools_section(self) -> str:
|
|
221
|
+
if not self.tools:
|
|
222
|
+
return ""
|
|
223
|
+
|
|
224
|
+
external_tools_section = ""
|
|
225
|
+
for i, tool in enumerate(self.tools):
|
|
226
|
+
external_tools_section += f" {i + 1} {tool.tool_usage_xml()}\n\n"
|
|
227
|
+
return external_tools_section.strip()
|
|
228
|
+
|
|
229
|
+
def on_task_completed(self, *args, **kwargs):
|
|
230
|
+
logger.info(f"Task completed event received for agent: {self.role}")
|
|
231
|
+
self.task_completed.set()
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import logging
|
|
3
|
+
from typing import (
|
|
4
|
+
List,
|
|
5
|
+
Optional,
|
|
6
|
+
AsyncGenerator,
|
|
7
|
+
Any,
|
|
8
|
+
NoReturn,
|
|
9
|
+
Union,
|
|
10
|
+
AsyncIterator
|
|
11
|
+
)
|
|
12
|
+
from autobyteus.agent.agent import Agent
|
|
13
|
+
from autobyteus.llm.base_llm import BaseLLM
|
|
14
|
+
from autobyteus.tools.base_tool import BaseTool
|
|
15
|
+
from autobyteus.prompt.prompt_builder import PromptBuilder
|
|
16
|
+
from autobyteus.events.event_types import EventType
|
|
17
|
+
from autobyteus.agent.status import AgentStatus
|
|
18
|
+
from autobyteus.conversation.user_message import UserMessage
|
|
19
|
+
from autobyteus.conversation.conversation import Conversation
|
|
20
|
+
from autobyteus.agent.tool_invocation import ToolInvocation
|
|
21
|
+
|
|
22
|
+
logger = logging.getLogger(__name__)
|
|
23
|
+
|
|
24
|
+
class AsyncAgent(Agent):
|
|
25
|
+
"""
|
|
26
|
+
An asynchronous agent that supports streaming LLM responses while maintaining
|
|
27
|
+
compatibility with the base agent functionality.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
def __init__(
|
|
31
|
+
self,
|
|
32
|
+
role: str,
|
|
33
|
+
llm: BaseLLM,
|
|
34
|
+
tools: Optional[List[BaseTool]] = None,
|
|
35
|
+
agent_id: Optional[str] = None,
|
|
36
|
+
prompt_builder: Optional[PromptBuilder] = None,
|
|
37
|
+
initial_user_message: Optional[UserMessage] = None
|
|
38
|
+
) -> None:
|
|
39
|
+
"""
|
|
40
|
+
Initialize the AsyncAgent with the given parameters.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
role: The role of the agent
|
|
44
|
+
llm: The language model instance
|
|
45
|
+
tools: List of available tools
|
|
46
|
+
use_xml_parser: Whether to use XML parser for responses
|
|
47
|
+
agent_id: Optional unique identifier for the agent
|
|
48
|
+
prompt_builder: Optional prompt builder instance
|
|
49
|
+
initial_user_message: Optional initial message to start the conversation
|
|
50
|
+
"""
|
|
51
|
+
super().__init__(
|
|
52
|
+
role,
|
|
53
|
+
llm,
|
|
54
|
+
tools,
|
|
55
|
+
agent_id,
|
|
56
|
+
prompt_builder,
|
|
57
|
+
initial_user_message
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
async def initialize_conversation(self) -> None:
|
|
61
|
+
"""Initialize the conversation with initial message or prompt."""
|
|
62
|
+
logger.info(f"Initializing conversation for agent: {self.role}")
|
|
63
|
+
self.conversation = Conversation(self.llm)
|
|
64
|
+
|
|
65
|
+
if self.initial_user_message:
|
|
66
|
+
initial_message = self.initial_user_message
|
|
67
|
+
else:
|
|
68
|
+
prompt_content = self.prompt_builder.set_variable_value(
|
|
69
|
+
"external_tools",
|
|
70
|
+
self._get_external_tools_section()
|
|
71
|
+
).build()
|
|
72
|
+
initial_message = UserMessage(content=prompt_content)
|
|
73
|
+
|
|
74
|
+
logger.debug(f"Initial user message for agent {self.role}: {initial_message}")
|
|
75
|
+
await self.process_streaming_response(
|
|
76
|
+
self.conversation.stream_user_message(
|
|
77
|
+
initial_message.content,
|
|
78
|
+
initial_message.file_paths
|
|
79
|
+
)
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
async def handle_user_messages(self) -> NoReturn:
|
|
83
|
+
"""
|
|
84
|
+
Handle incoming user messages continuously.
|
|
85
|
+
Processes messages using streaming responses.
|
|
86
|
+
"""
|
|
87
|
+
logger.info(f"Agent {self.role} started handling user messages")
|
|
88
|
+
while not self.task_completed.is_set() and self.status == AgentStatus.RUNNING:
|
|
89
|
+
try:
|
|
90
|
+
user_message: UserMessage = await asyncio.wait_for(
|
|
91
|
+
self.user_messages.get(),
|
|
92
|
+
timeout=1.0
|
|
93
|
+
)
|
|
94
|
+
logger.info(f"Agent {self.role} handling user message")
|
|
95
|
+
await self.process_streaming_response(
|
|
96
|
+
self.conversation.stream_user_message(
|
|
97
|
+
user_message.content,
|
|
98
|
+
user_message.file_paths
|
|
99
|
+
)
|
|
100
|
+
)
|
|
101
|
+
except asyncio.TimeoutError:
|
|
102
|
+
continue
|
|
103
|
+
except asyncio.CancelledError:
|
|
104
|
+
logger.info(f"User message handler for agent {self.role} cancelled")
|
|
105
|
+
break
|
|
106
|
+
except Exception as e:
|
|
107
|
+
logger.error(f"Error handling user message for agent {self.role}: {str(e)}")
|
|
108
|
+
|
|
109
|
+
async def handle_tool_result_messages(self) -> NoReturn:
|
|
110
|
+
"""
|
|
111
|
+
Handle tool execution result messages continuously.
|
|
112
|
+
Processes messages using streaming responses.
|
|
113
|
+
"""
|
|
114
|
+
logger.info(f"Agent {self.role} started handling tool result messages")
|
|
115
|
+
while not self.task_completed.is_set() and self.status == AgentStatus.RUNNING:
|
|
116
|
+
try:
|
|
117
|
+
message: str = await asyncio.wait_for(
|
|
118
|
+
self.tool_result_messages.get(),
|
|
119
|
+
timeout=1.0
|
|
120
|
+
)
|
|
121
|
+
logger.info(f"Agent {self.role} handling tool result message: {message}")
|
|
122
|
+
await self.process_streaming_response(
|
|
123
|
+
self.conversation.stream_user_message(
|
|
124
|
+
f"Tool execution result: {message}"
|
|
125
|
+
)
|
|
126
|
+
)
|
|
127
|
+
except asyncio.TimeoutError:
|
|
128
|
+
continue
|
|
129
|
+
except asyncio.CancelledError:
|
|
130
|
+
logger.info(f"Tool result handler for agent {self.role} cancelled")
|
|
131
|
+
break
|
|
132
|
+
except Exception as e:
|
|
133
|
+
logger.error(f"Error handling tool result for agent {self.role}: {str(e)}")
|
|
134
|
+
|
|
135
|
+
async def process_streaming_response(
|
|
136
|
+
self,
|
|
137
|
+
response_stream: AsyncIterator[str]
|
|
138
|
+
) -> None:
|
|
139
|
+
"""
|
|
140
|
+
Process streaming responses from the LLM, emitting each chunk and handling
|
|
141
|
+
tool invocations after receiving the complete response.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
response_stream: AsyncIterator yielding response tokens
|
|
145
|
+
"""
|
|
146
|
+
complete_response: str = ""
|
|
147
|
+
try:
|
|
148
|
+
async for chunk in response_stream:
|
|
149
|
+
# Emit each chunk as it arrives
|
|
150
|
+
self.emit(
|
|
151
|
+
EventType.ASSISTANT_RESPONSE,
|
|
152
|
+
response=chunk,
|
|
153
|
+
is_complete=False
|
|
154
|
+
)
|
|
155
|
+
complete_response += chunk
|
|
156
|
+
# Emit the complete response
|
|
157
|
+
self.emit(
|
|
158
|
+
EventType.ASSISTANT_RESPONSE,
|
|
159
|
+
response=complete_response,
|
|
160
|
+
is_complete=True
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
if self.tools and self.tool_usage_response_parser:
|
|
164
|
+
tool_invocation: ToolInvocation = self.tool_usage_response_parser.parse_response(complete_response)
|
|
165
|
+
if tool_invocation.is_valid():
|
|
166
|
+
await self.execute_tool(tool_invocation)
|
|
167
|
+
return
|
|
168
|
+
|
|
169
|
+
logger.info(f"Assistant response for agent {self.role}: {complete_response}")
|
|
170
|
+
|
|
171
|
+
except Exception as e:
|
|
172
|
+
logger.error(f"Error processing streaming response for agent {self.role}: {str(e)}")
|
|
173
|
+
self.emit(
|
|
174
|
+
EventType.ERROR,
|
|
175
|
+
error=str(e))
|