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.
Files changed (159) hide show
  1. autobyteus-1.0.0/LICENSE +14 -0
  2. autobyteus-1.0.0/PKG-INFO +138 -0
  3. autobyteus-1.0.0/README.md +75 -0
  4. autobyteus-1.0.0/autobyteus/__init__.py +5 -0
  5. autobyteus-1.0.0/autobyteus/agent/__init__.py +0 -0
  6. autobyteus-1.0.0/autobyteus/agent/agent.py +231 -0
  7. autobyteus-1.0.0/autobyteus/agent/async_agent.py +175 -0
  8. autobyteus-1.0.0/autobyteus/agent/async_group_aware_agent.py +136 -0
  9. autobyteus-1.0.0/autobyteus/agent/exceptions.py +6 -0
  10. autobyteus-1.0.0/autobyteus/agent/factory/__init__.py +0 -0
  11. autobyteus-1.0.0/autobyteus/agent/group/__init__.py +0 -0
  12. autobyteus-1.0.0/autobyteus/agent/group/async_group_aware_agent.py +122 -0
  13. autobyteus-1.0.0/autobyteus/agent/group/coordinator_agent.py +36 -0
  14. autobyteus-1.0.0/autobyteus/agent/group/group_aware_agent.py +121 -0
  15. autobyteus-1.0.0/autobyteus/agent/message/__init__.py +0 -0
  16. autobyteus-1.0.0/autobyteus/agent/message/message.py +41 -0
  17. autobyteus-1.0.0/autobyteus/agent/message/message_types.py +29 -0
  18. autobyteus-1.0.0/autobyteus/agent/message/send_message_to.py +47 -0
  19. autobyteus-1.0.0/autobyteus/agent/orchestrator/__init__.py +0 -0
  20. autobyteus-1.0.0/autobyteus/agent/orchestrator/base_agent_orchestrator.py +82 -0
  21. autobyteus-1.0.0/autobyteus/agent/orchestrator/multi_replica_agent_orchestrator.py +72 -0
  22. autobyteus-1.0.0/autobyteus/agent/orchestrator/single_replica_agent_orchestrator.py +43 -0
  23. autobyteus-1.0.0/autobyteus/agent/response_parser/__init__.py +0 -0
  24. autobyteus-1.0.0/autobyteus/agent/response_parser/tool_usage_command_parser.py +100 -0
  25. autobyteus-1.0.0/autobyteus/agent/status.py +12 -0
  26. autobyteus-1.0.0/autobyteus/agent/tool_invocation.py +7 -0
  27. autobyteus-1.0.0/autobyteus/check_requirements.py +33 -0
  28. autobyteus-1.0.0/autobyteus/conversation/__init__.py +0 -0
  29. autobyteus-1.0.0/autobyteus/conversation/conversation.py +54 -0
  30. autobyteus-1.0.0/autobyteus/conversation/user_message.py +59 -0
  31. autobyteus-1.0.0/autobyteus/events/__init__.py +0 -0
  32. autobyteus-1.0.0/autobyteus/events/decorators.py +29 -0
  33. autobyteus-1.0.0/autobyteus/events/event_emitter.py +74 -0
  34. autobyteus-1.0.0/autobyteus/events/event_manager.py +73 -0
  35. autobyteus-1.0.0/autobyteus/events/event_types.py +17 -0
  36. autobyteus-1.0.0/autobyteus/llm/__init__.py +0 -0
  37. autobyteus-1.0.0/autobyteus/llm/api/__init__.py +0 -0
  38. autobyteus-1.0.0/autobyteus/llm/api/autobyteus_llm.py +136 -0
  39. autobyteus-1.0.0/autobyteus/llm/api/bedrock_llm.py +78 -0
  40. autobyteus-1.0.0/autobyteus/llm/api/claude_llm.py +138 -0
  41. autobyteus-1.0.0/autobyteus/llm/api/deepseek_llm.py +226 -0
  42. autobyteus-1.0.0/autobyteus/llm/api/gemini_llm.py +79 -0
  43. autobyteus-1.0.0/autobyteus/llm/api/grok_llm.py +211 -0
  44. autobyteus-1.0.0/autobyteus/llm/api/groq_llm.py +88 -0
  45. autobyteus-1.0.0/autobyteus/llm/api/mistral_llm.py +120 -0
  46. autobyteus-1.0.0/autobyteus/llm/api/nvidia_llm.py +102 -0
  47. autobyteus-1.0.0/autobyteus/llm/api/ollama_llm.py +130 -0
  48. autobyteus-1.0.0/autobyteus/llm/api/openai_llm.py +148 -0
  49. autobyteus-1.0.0/autobyteus/llm/autobyteus_provider.py +172 -0
  50. autobyteus-1.0.0/autobyteus/llm/base_llm.py +222 -0
  51. autobyteus-1.0.0/autobyteus/llm/extensions/__init__.py +0 -0
  52. autobyteus-1.0.0/autobyteus/llm/extensions/base_extension.py +45 -0
  53. autobyteus-1.0.0/autobyteus/llm/extensions/extension_registry.py +37 -0
  54. autobyteus-1.0.0/autobyteus/llm/extensions/token_usage_tracking_extension.py +79 -0
  55. autobyteus-1.0.0/autobyteus/llm/llm_factory.py +292 -0
  56. autobyteus-1.0.0/autobyteus/llm/models.py +73 -0
  57. autobyteus-1.0.0/autobyteus/llm/ollama_provider.py +98 -0
  58. autobyteus-1.0.0/autobyteus/llm/providers.py +14 -0
  59. autobyteus-1.0.0/autobyteus/llm/token_counter/__init__.py +0 -0
  60. autobyteus-1.0.0/autobyteus/llm/token_counter/base_token_counter.py +69 -0
  61. autobyteus-1.0.0/autobyteus/llm/token_counter/claude_token_counter.py +77 -0
  62. autobyteus-1.0.0/autobyteus/llm/token_counter/deepseek_token_counter.py +24 -0
  63. autobyteus-1.0.0/autobyteus/llm/token_counter/mistral_token_counter.py +115 -0
  64. autobyteus-1.0.0/autobyteus/llm/token_counter/openai_token_counter.py +84 -0
  65. autobyteus-1.0.0/autobyteus/llm/token_counter/token_counter_factory.py +40 -0
  66. autobyteus-1.0.0/autobyteus/llm/utils/__init__.py +0 -0
  67. autobyteus-1.0.0/autobyteus/llm/utils/image_payload_formatter.py +89 -0
  68. autobyteus-1.0.0/autobyteus/llm/utils/llm_config.py +90 -0
  69. autobyteus-1.0.0/autobyteus/llm/utils/messages.py +40 -0
  70. autobyteus-1.0.0/autobyteus/llm/utils/rate_limiter.py +41 -0
  71. autobyteus-1.0.0/autobyteus/llm/utils/response_types.py +19 -0
  72. autobyteus-1.0.0/autobyteus/llm/utils/token_pricing_config.py +87 -0
  73. autobyteus-1.0.0/autobyteus/llm/utils/token_usage.py +13 -0
  74. autobyteus-1.0.0/autobyteus/llm/utils/token_usage_tracker.py +98 -0
  75. autobyteus-1.0.0/autobyteus/person/__init__.py +0 -0
  76. autobyteus-1.0.0/autobyteus/person/examples/__init__.py +0 -0
  77. autobyteus-1.0.0/autobyteus/person/examples/sample_persons.py +14 -0
  78. autobyteus-1.0.0/autobyteus/person/examples/sample_roles.py +14 -0
  79. autobyteus-1.0.0/autobyteus/person/person.py +29 -0
  80. autobyteus-1.0.0/autobyteus/person/role.py +14 -0
  81. autobyteus-1.0.0/autobyteus/prompt/__init__.py +0 -0
  82. autobyteus-1.0.0/autobyteus/prompt/prompt_builder.py +64 -0
  83. autobyteus-1.0.0/autobyteus/prompt/prompt_template.py +44 -0
  84. autobyteus-1.0.0/autobyteus/prompt/prompt_version_manager.py +58 -0
  85. autobyteus-1.0.0/autobyteus/prompt/storage/__init__.py +0 -0
  86. autobyteus-1.0.0/autobyteus/prompt/storage/prompt_version_model.py +29 -0
  87. autobyteus-1.0.0/autobyteus/prompt/storage/prompt_version_repository.py +83 -0
  88. autobyteus-1.0.0/autobyteus/tools/__init__.py +0 -0
  89. autobyteus-1.0.0/autobyteus/tools/ask_user_input.py +93 -0
  90. autobyteus-1.0.0/autobyteus/tools/base_tool.py +49 -0
  91. autobyteus-1.0.0/autobyteus/tools/bash/__init__.py +0 -0
  92. autobyteus-1.0.0/autobyteus/tools/bash/bash_executor.py +103 -0
  93. autobyteus-1.0.0/autobyteus/tools/bash/factory/__init__.py +0 -0
  94. autobyteus-1.0.0/autobyteus/tools/bash/factory/bash_executor_factory.py +6 -0
  95. autobyteus-1.0.0/autobyteus/tools/browser/__init__.py +0 -0
  96. autobyteus-1.0.0/autobyteus/tools/browser/session_aware/__init__.py +0 -0
  97. autobyteus-1.0.0/autobyteus/tools/browser/session_aware/browser_session_aware_navigate_to.py +61 -0
  98. autobyteus-1.0.0/autobyteus/tools/browser/session_aware/browser_session_aware_tool.py +27 -0
  99. autobyteus-1.0.0/autobyteus/tools/browser/session_aware/browser_session_aware_web_element_trigger.py +202 -0
  100. autobyteus-1.0.0/autobyteus/tools/browser/session_aware/browser_session_aware_webpage_reader.py +29 -0
  101. autobyteus-1.0.0/autobyteus/tools/browser/session_aware/browser_session_aware_webpage_screenshot_taker.py +34 -0
  102. autobyteus-1.0.0/autobyteus/tools/browser/session_aware/factory/__init__.py +0 -0
  103. autobyteus-1.0.0/autobyteus/tools/browser/session_aware/factory/browser_session_aware_web_element_trigger_factory.py +6 -0
  104. autobyteus-1.0.0/autobyteus/tools/browser/session_aware/factory/browser_session_aware_webpage_reader_factory.py +10 -0
  105. autobyteus-1.0.0/autobyteus/tools/browser/session_aware/factory/browser_session_aware_webpage_screenshot_taker_factory.py +6 -0
  106. autobyteus-1.0.0/autobyteus/tools/browser/session_aware/shared_browser_session.py +11 -0
  107. autobyteus-1.0.0/autobyteus/tools/browser/session_aware/shared_browser_session_manager.py +24 -0
  108. autobyteus-1.0.0/autobyteus/tools/browser/session_aware/web_element_action.py +20 -0
  109. autobyteus-1.0.0/autobyteus/tools/browser/standalone/__init__.py +0 -0
  110. autobyteus-1.0.0/autobyteus/tools/browser/standalone/factory/__init__.py +0 -0
  111. autobyteus-1.0.0/autobyteus/tools/browser/standalone/factory/google_search_factory.py +10 -0
  112. autobyteus-1.0.0/autobyteus/tools/browser/standalone/factory/webpage_reader_factory.py +10 -0
  113. autobyteus-1.0.0/autobyteus/tools/browser/standalone/factory/webpage_screenshot_taker_factory.py +6 -0
  114. autobyteus-1.0.0/autobyteus/tools/browser/standalone/google_search_ui.py +113 -0
  115. autobyteus-1.0.0/autobyteus/tools/browser/standalone/navigate_to.py +62 -0
  116. autobyteus-1.0.0/autobyteus/tools/browser/standalone/webpage_image_downloader.py +128 -0
  117. autobyteus-1.0.0/autobyteus/tools/browser/standalone/webpage_reader.py +78 -0
  118. autobyteus-1.0.0/autobyteus/tools/browser/standalone/webpage_screenshot_taker.py +49 -0
  119. autobyteus-1.0.0/autobyteus/tools/factory/__init__.py +0 -0
  120. autobyteus-1.0.0/autobyteus/tools/factory/ask_user_input_factory.py +6 -0
  121. autobyteus-1.0.0/autobyteus/tools/factory/image_downloader_factory.py +9 -0
  122. autobyteus-1.0.0/autobyteus/tools/factory/pdf_downloader_factory.py +9 -0
  123. autobyteus-1.0.0/autobyteus/tools/factory/tool_factory.py +8 -0
  124. autobyteus-1.0.0/autobyteus/tools/factory/webpage_image_downloader_factory.py +6 -0
  125. autobyteus-1.0.0/autobyteus/tools/file/__init__.py +0 -0
  126. autobyteus-1.0.0/autobyteus/tools/file/factory/__init__.py +0 -0
  127. autobyteus-1.0.0/autobyteus/tools/file/factory/file_reader_factory.py +6 -0
  128. autobyteus-1.0.0/autobyteus/tools/file/factory/file_writer_factory.py +6 -0
  129. autobyteus-1.0.0/autobyteus/tools/file/file_reader.py +60 -0
  130. autobyteus-1.0.0/autobyteus/tools/file/file_writer.py +65 -0
  131. autobyteus-1.0.0/autobyteus/tools/handlers/__init__.py +0 -0
  132. autobyteus-1.0.0/autobyteus/tools/handlers/shell_handler.py +32 -0
  133. autobyteus-1.0.0/autobyteus/tools/image_downloader.py +142 -0
  134. autobyteus-1.0.0/autobyteus/tools/operation/__init__.py +0 -0
  135. autobyteus-1.0.0/autobyteus/tools/operation/file_operation.py +73 -0
  136. autobyteus-1.0.0/autobyteus/tools/operation/file_rename_operation.py +52 -0
  137. autobyteus-1.0.0/autobyteus/tools/operation/operation.py +64 -0
  138. autobyteus-1.0.0/autobyteus/tools/operation/shell_operation.py +65 -0
  139. autobyteus-1.0.0/autobyteus/tools/pdf_downloader.py +94 -0
  140. autobyteus-1.0.0/autobyteus/tools/timer.py +123 -0
  141. autobyteus-1.0.0/autobyteus/tools/utils.py +17 -0
  142. autobyteus-1.0.0/autobyteus/tools/web_page_pdf_generator.py +86 -0
  143. autobyteus-1.0.0/autobyteus/utils/__init__.py +0 -0
  144. autobyteus-1.0.0/autobyteus/utils/dynamic_enum.py +35 -0
  145. autobyteus-1.0.0/autobyteus/utils/file_utils.py +15 -0
  146. autobyteus-1.0.0/autobyteus/utils/html_cleaner.py +240 -0
  147. autobyteus-1.0.0/autobyteus/utils/singleton.py +26 -0
  148. autobyteus-1.0.0/autobyteus/workflow/__init__.py +0 -0
  149. autobyteus-1.0.0/autobyteus/workflow/simple_task.py +98 -0
  150. autobyteus-1.0.0/autobyteus/workflow/task.py +147 -0
  151. autobyteus-1.0.0/autobyteus/workflow/workflow.py +49 -0
  152. autobyteus-1.0.0/autobyteus.egg-info/PKG-INFO +138 -0
  153. autobyteus-1.0.0/autobyteus.egg-info/SOURCES.txt +157 -0
  154. autobyteus-1.0.0/autobyteus.egg-info/dependency_links.txt +1 -0
  155. autobyteus-1.0.0/autobyteus.egg-info/requires.txt +37 -0
  156. autobyteus-1.0.0/autobyteus.egg-info/top_level.txt +1 -0
  157. autobyteus-1.0.0/pyproject.toml +6 -0
  158. autobyteus-1.0.0/setup.cfg +4 -0
  159. autobyteus-1.0.0/setup.py +72 -0
@@ -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.
@@ -0,0 +1,5 @@
1
+ from pathlib import Path
2
+ import sys
3
+
4
+
5
+ sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "src"))
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))