versionhq 1.1.7.5__tar.gz → 1.1.7.7__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.
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/.gitignore +2 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/PKG-INFO +9 -7
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/README.md +2 -3
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/pyproject.toml +8 -6
- versionhq-1.1.7.7/requirements-dev.txt +9 -0
- versionhq-1.1.7.7/requirements.txt +220 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/src/versionhq/__init__.py +1 -1
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/src/versionhq/agent/model.py +5 -5
- versionhq-1.1.7.7/src/versionhq/storage/task_output_storage.py +141 -0
- versionhq-1.1.7.7/src/versionhq/task/log_handler.py +59 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/src/versionhq/task/model.py +49 -31
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/src/versionhq/team/model.py +28 -67
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/src/versionhq.egg-info/PKG-INFO +9 -7
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/src/versionhq.egg-info/SOURCES.txt +4 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/src/versionhq.egg-info/requires.txt +3 -3
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/tests/task/task_test.py +26 -5
- versionhq-1.1.7.7/tests/team/__init__.py +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/tests/team/team_test.py +9 -104
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/uv.lock +19 -24
- versionhq-1.1.7.5/requirements.txt +0 -20
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/.github/workflows/publish.yml +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/.github/workflows/publish_testpypi.yml +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/.github/workflows/run_tests.yml +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/.github/workflows/security_check.yml +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/.pre-commit-config.yaml +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/.python-version +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/LICENSE +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/SECURITY.md +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/db/preprocess.py +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/runtime.txt +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/setup.cfg +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/src/versionhq/_utils/__init__.py +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/src/versionhq/_utils/cache_handler.py +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/src/versionhq/_utils/i18n.py +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/src/versionhq/_utils/logger.py +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/src/versionhq/_utils/process_config.py +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/src/versionhq/_utils/rpm_controller.py +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/src/versionhq/_utils/usage_metrics.py +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/src/versionhq/agent/TEMPLATES/Backstory.py +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/src/versionhq/agent/TEMPLATES/__init__.py +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/src/versionhq/agent/__init__.py +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/src/versionhq/agent/parser.py +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/src/versionhq/cli/__init__.py +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/src/versionhq/clients/__init__.py +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/src/versionhq/clients/customer/__init__.py +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/src/versionhq/clients/customer/model.py +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/src/versionhq/clients/product/__init__.py +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/src/versionhq/clients/product/model.py +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/src/versionhq/clients/workflow/__init__.py +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/src/versionhq/clients/workflow/model.py +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/src/versionhq/llm/__init__.py +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/src/versionhq/llm/llm_vars.py +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/src/versionhq/llm/model.py +0 -0
- {versionhq-1.1.7.5/src/versionhq/team → versionhq-1.1.7.7/src/versionhq/storage}/__init__.py +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/src/versionhq/task/__init__.py +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/src/versionhq/task/formatter.py +0 -0
- {versionhq-1.1.7.5/src/versionhq/tool → versionhq-1.1.7.7/src/versionhq/team}/__init__.py +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/src/versionhq/team/team_planner.py +0 -0
- {versionhq-1.1.7.5/tests → versionhq-1.1.7.7/src/versionhq/tool}/__init__.py +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/src/versionhq/tool/decorator.py +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/src/versionhq/tool/model.py +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/src/versionhq/tool/tool_handler.py +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/src/versionhq.egg-info/dependency_links.txt +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/src/versionhq.egg-info/top_level.txt +0 -0
- {versionhq-1.1.7.5/tests/agent → versionhq-1.1.7.7/tests}/__init__.py +0 -0
- {versionhq-1.1.7.5/tests/cli → versionhq-1.1.7.7/tests/agent}/__init__.py +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/tests/agent/agent_test.py +0 -0
- {versionhq-1.1.7.5/tests/task → versionhq-1.1.7.7/tests/cli}/__init__.py +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/tests/clients/workflow_test.py +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/tests/conftest.py +0 -0
- {versionhq-1.1.7.5/tests/team → versionhq-1.1.7.7/tests/task}/__init__.py +0 -0
- {versionhq-1.1.7.5 → versionhq-1.1.7.7}/tests/team/Prompts/Demo_test.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: versionhq
|
3
|
-
Version: 1.1.7.
|
3
|
+
Version: 1.1.7.7
|
4
4
|
Summary: LLM orchestration frameworks for model-agnostic AI agents that handle complex outbound workflows
|
5
5
|
Author-email: Kuriko Iwai <kuriko@versi0n.io>
|
6
6
|
License: MIT License
|
@@ -32,6 +32,9 @@ Keywords: orchestration framework,orchestration,ai agent,multi-agent system,RAG,
|
|
32
32
|
Classifier: Programming Language :: Python
|
33
33
|
Classifier: License :: OSI Approved :: MIT License
|
34
34
|
Classifier: Operating System :: OS Independent
|
35
|
+
Classifier: Development Status :: 3 - Alpha
|
36
|
+
Classifier: Intended Audience :: Developers
|
37
|
+
Classifier: Topic :: Software Development :: Build Tools
|
35
38
|
Requires-Python: >=3.12
|
36
39
|
Description-Content-Type: text/markdown
|
37
40
|
License-File: LICENSE
|
@@ -43,12 +46,12 @@ Requires-Dist: typing
|
|
43
46
|
Requires-Dist: json-repair>=0.31.0
|
44
47
|
Requires-Dist: litellm>=1.55.8
|
45
48
|
Requires-Dist: openai>=1.57.0
|
46
|
-
Requires-Dist: composio-openai>=0.6.
|
47
|
-
Requires-Dist: pre-commit>=4.0.1
|
48
|
-
Requires-Dist: gunicorn>=23.0.0
|
49
|
+
Requires-Dist: composio-openai>=0.6.9
|
49
50
|
Requires-Dist: composio>=0.1.0
|
50
51
|
Requires-Dist: setuptools>=75.6.0
|
51
52
|
Requires-Dist: wheel>=0.45.1
|
53
|
+
Requires-Dist: python-dotenv>=1.0.0
|
54
|
+
Requires-Dist: appdirs>=1.4.4
|
52
55
|
|
53
56
|
# Overview
|
54
57
|
|
@@ -56,7 +59,7 @@ Requires-Dist: wheel>=0.45.1
|
|
56
59
|
[](https://github.com/versionHQ/multi-agent-system/actions/workflows/publish.yml)
|
57
60
|

|
58
61
|

|
59
|
-

|
60
63
|
|
61
64
|
|
62
65
|
An LLM orchestration frameworks for multi-agent systems with RAG to autopilot outbound workflows.
|
@@ -276,8 +279,7 @@ src/
|
|
276
279
|
```
|
277
280
|
uv venv
|
278
281
|
source .venv/bin/activate
|
279
|
-
|
280
|
-
uv pip install -r requirements.txt -v
|
282
|
+
uv pip sync
|
281
283
|
```
|
282
284
|
|
283
285
|
* In case of AssertionError/module mismatch, run Python version control using `.pyenv`
|
@@ -4,7 +4,7 @@
|
|
4
4
|
[](https://github.com/versionHQ/multi-agent-system/actions/workflows/publish.yml)
|
5
5
|

|
6
6
|

|
7
|
-

|
8
8
|
|
9
9
|
|
10
10
|
An LLM orchestration frameworks for multi-agent systems with RAG to autopilot outbound workflows.
|
@@ -224,8 +224,7 @@ src/
|
|
224
224
|
```
|
225
225
|
uv venv
|
226
226
|
source .venv/bin/activate
|
227
|
-
|
228
|
-
uv pip install -r requirements.txt -v
|
227
|
+
uv pip sync
|
229
228
|
```
|
230
229
|
|
231
230
|
* In case of AssertionError/module mismatch, run Python version control using `.pyenv`
|
@@ -15,7 +15,7 @@ exclude = ["test*", "__pycache__"]
|
|
15
15
|
|
16
16
|
[project]
|
17
17
|
name = "versionhq"
|
18
|
-
version = "1.1.7.
|
18
|
+
version = "1.1.7.7"
|
19
19
|
authors = [{ name = "Kuriko Iwai", email = "kuriko@versi0n.io" }]
|
20
20
|
description = "LLM orchestration frameworks for model-agnostic AI agents that handle complex outbound workflows"
|
21
21
|
readme = "README.md"
|
@@ -31,17 +31,20 @@ dependencies = [
|
|
31
31
|
"json-repair>=0.31.0",
|
32
32
|
"litellm>=1.55.8",
|
33
33
|
"openai>=1.57.0",
|
34
|
-
"composio-openai>=0.6.
|
35
|
-
"pre-commit>=4.0.1",
|
36
|
-
"gunicorn>=23.0.0",
|
34
|
+
"composio-openai>=0.6.9",
|
37
35
|
"composio>=0.1.0",
|
38
36
|
"setuptools>=75.6.0",
|
39
37
|
"wheel>=0.45.1",
|
38
|
+
"python-dotenv>=1.0.0",
|
39
|
+
"appdirs>=1.4.4",
|
40
40
|
]
|
41
41
|
classifiers = [
|
42
42
|
"Programming Language :: Python",
|
43
43
|
"License :: OSI Approved :: MIT License",
|
44
44
|
"Operating System :: OS Independent",
|
45
|
+
"Development Status :: 3 - Alpha",
|
46
|
+
"Intended Audience :: Developers",
|
47
|
+
"Topic :: Software Development :: Build Tools",
|
45
48
|
]
|
46
49
|
|
47
50
|
[project.urls]
|
@@ -52,10 +55,9 @@ Issues = "https://github.com/versionHQ/multi-agent-system/issues"
|
|
52
55
|
[tool.uv]
|
53
56
|
dev-dependencies = [
|
54
57
|
"mypy>=1.10.0",
|
55
|
-
"pre-commit>=
|
58
|
+
"pre-commit>=4.0.1",
|
56
59
|
"pytest>=8.0.0",
|
57
60
|
"pytest-vcr>=1.0.2",
|
58
|
-
"python-dotenv>=1.0.0",
|
59
61
|
"black",
|
60
62
|
"bandit",
|
61
63
|
"twine",
|
@@ -0,0 +1,220 @@
|
|
1
|
+
# This file was autogenerated by uv via the following command:
|
2
|
+
# uv pip compile pyproject.toml -o requirements.txt
|
3
|
+
aiohappyeyeballs==2.4.4
|
4
|
+
# via aiohttp
|
5
|
+
aiohttp==3.11.11
|
6
|
+
# via
|
7
|
+
# composio-core
|
8
|
+
# litellm
|
9
|
+
aiosignal==1.3.2
|
10
|
+
# via aiohttp
|
11
|
+
annotated-types==0.7.0
|
12
|
+
# via pydantic
|
13
|
+
anyio==4.7.0
|
14
|
+
# via
|
15
|
+
# httpx
|
16
|
+
# openai
|
17
|
+
# starlette
|
18
|
+
appdirs==1.4.4
|
19
|
+
# via versionhq (pyproject.toml)
|
20
|
+
attrs==24.3.0
|
21
|
+
# via
|
22
|
+
# aiohttp
|
23
|
+
# jsonschema
|
24
|
+
# referencing
|
25
|
+
bcrypt==4.2.1
|
26
|
+
# via paramiko
|
27
|
+
certifi==2024.12.14
|
28
|
+
# via
|
29
|
+
# httpcore
|
30
|
+
# httpx
|
31
|
+
# requests
|
32
|
+
# sentry-sdk
|
33
|
+
cffi==1.17.1
|
34
|
+
# via
|
35
|
+
# cryptography
|
36
|
+
# pynacl
|
37
|
+
charset-normalizer==3.4.1
|
38
|
+
# via requests
|
39
|
+
click==8.1.8
|
40
|
+
# via
|
41
|
+
# composio-core
|
42
|
+
# litellm
|
43
|
+
# uvicorn
|
44
|
+
composio==0.1.0
|
45
|
+
# via versionhq (pyproject.toml)
|
46
|
+
composio-core==0.6.9
|
47
|
+
# via composio-openai
|
48
|
+
composio-openai==0.6.9
|
49
|
+
# via versionhq (pyproject.toml)
|
50
|
+
cryptography==44.0.0
|
51
|
+
# via paramiko
|
52
|
+
distro==1.9.0
|
53
|
+
# via openai
|
54
|
+
fastapi==0.115.6
|
55
|
+
# via composio-core
|
56
|
+
filelock==3.16.1
|
57
|
+
# via huggingface-hub
|
58
|
+
frozenlist==1.5.0
|
59
|
+
# via
|
60
|
+
# aiohttp
|
61
|
+
# aiosignal
|
62
|
+
fsspec==2024.12.0
|
63
|
+
# via huggingface-hub
|
64
|
+
h11==0.14.0
|
65
|
+
# via
|
66
|
+
# httpcore
|
67
|
+
# uvicorn
|
68
|
+
httpcore==1.0.7
|
69
|
+
# via httpx
|
70
|
+
httpx==0.27.2
|
71
|
+
# via
|
72
|
+
# litellm
|
73
|
+
# openai
|
74
|
+
huggingface-hub==0.27.0
|
75
|
+
# via tokenizers
|
76
|
+
idna==3.10
|
77
|
+
# via
|
78
|
+
# anyio
|
79
|
+
# httpx
|
80
|
+
# requests
|
81
|
+
# yarl
|
82
|
+
importlib-metadata==8.5.0
|
83
|
+
# via
|
84
|
+
# composio-core
|
85
|
+
# litellm
|
86
|
+
inflection==0.5.1
|
87
|
+
# via composio-core
|
88
|
+
jinja2==3.1.5
|
89
|
+
# via litellm
|
90
|
+
jiter==0.8.2
|
91
|
+
# via openai
|
92
|
+
json-repair==0.35.0
|
93
|
+
# via versionhq (pyproject.toml)
|
94
|
+
jsonref==1.1.0
|
95
|
+
# via composio-core
|
96
|
+
jsonschema==4.23.0
|
97
|
+
# via
|
98
|
+
# composio-core
|
99
|
+
# litellm
|
100
|
+
jsonschema-specifications==2024.10.1
|
101
|
+
# via jsonschema
|
102
|
+
litellm==1.56.5
|
103
|
+
# via versionhq (pyproject.toml)
|
104
|
+
markdown-it-py==3.0.0
|
105
|
+
# via rich
|
106
|
+
markupsafe==3.0.2
|
107
|
+
# via
|
108
|
+
# jinja2
|
109
|
+
# werkzeug
|
110
|
+
mdurl==0.1.2
|
111
|
+
# via markdown-it-py
|
112
|
+
multidict==6.1.0
|
113
|
+
# via
|
114
|
+
# aiohttp
|
115
|
+
# yarl
|
116
|
+
openai==1.58.1
|
117
|
+
# via
|
118
|
+
# versionhq (pyproject.toml)
|
119
|
+
# composio-openai
|
120
|
+
# litellm
|
121
|
+
packaging==24.2
|
122
|
+
# via huggingface-hub
|
123
|
+
paramiko==3.5.0
|
124
|
+
# via composio-core
|
125
|
+
propcache==0.2.1
|
126
|
+
# via
|
127
|
+
# aiohttp
|
128
|
+
# yarl
|
129
|
+
pycparser==2.22
|
130
|
+
# via cffi
|
131
|
+
pydantic==2.10.4
|
132
|
+
# via
|
133
|
+
# versionhq (pyproject.toml)
|
134
|
+
# composio-core
|
135
|
+
# fastapi
|
136
|
+
# litellm
|
137
|
+
# openai
|
138
|
+
pydantic-core==2.27.2
|
139
|
+
# via pydantic
|
140
|
+
pygments==2.18.0
|
141
|
+
# via rich
|
142
|
+
pynacl==1.5.0
|
143
|
+
# via paramiko
|
144
|
+
pyperclip==1.9.0
|
145
|
+
# via composio-core
|
146
|
+
pysher==1.0.8
|
147
|
+
# via composio-core
|
148
|
+
python-dotenv==1.0.1
|
149
|
+
# via
|
150
|
+
# versionhq (pyproject.toml)
|
151
|
+
# litellm
|
152
|
+
pyyaml==6.0.2
|
153
|
+
# via huggingface-hub
|
154
|
+
referencing==0.35.1
|
155
|
+
# via
|
156
|
+
# jsonschema
|
157
|
+
# jsonschema-specifications
|
158
|
+
regex==2024.11.6
|
159
|
+
# via
|
160
|
+
# versionhq (pyproject.toml)
|
161
|
+
# tiktoken
|
162
|
+
requests==2.32.3
|
163
|
+
# via
|
164
|
+
# versionhq (pyproject.toml)
|
165
|
+
# composio-core
|
166
|
+
# huggingface-hub
|
167
|
+
# pysher
|
168
|
+
# tiktoken
|
169
|
+
rich==13.9.4
|
170
|
+
# via composio-core
|
171
|
+
rpds-py==0.22.3
|
172
|
+
# via
|
173
|
+
# jsonschema
|
174
|
+
# referencing
|
175
|
+
semver==3.0.2
|
176
|
+
# via composio-core
|
177
|
+
sentry-sdk==2.19.2
|
178
|
+
# via composio-core
|
179
|
+
setuptools==75.6.0
|
180
|
+
# via versionhq (pyproject.toml)
|
181
|
+
sniffio==1.3.1
|
182
|
+
# via
|
183
|
+
# anyio
|
184
|
+
# httpx
|
185
|
+
# openai
|
186
|
+
starlette==0.41.3
|
187
|
+
# via fastapi
|
188
|
+
tiktoken==0.8.0
|
189
|
+
# via litellm
|
190
|
+
tokenizers==0.21.0
|
191
|
+
# via litellm
|
192
|
+
tqdm==4.67.1
|
193
|
+
# via
|
194
|
+
# huggingface-hub
|
195
|
+
# openai
|
196
|
+
typing==3.10.0.0
|
197
|
+
# via versionhq (pyproject.toml)
|
198
|
+
typing-extensions==4.12.2
|
199
|
+
# via
|
200
|
+
# fastapi
|
201
|
+
# huggingface-hub
|
202
|
+
# openai
|
203
|
+
# pydantic
|
204
|
+
# pydantic-core
|
205
|
+
urllib3==2.3.0
|
206
|
+
# via
|
207
|
+
# requests
|
208
|
+
# sentry-sdk
|
209
|
+
uvicorn==0.34.0
|
210
|
+
# via composio-core
|
211
|
+
websocket-client==1.8.0
|
212
|
+
# via pysher
|
213
|
+
werkzeug==3.1.3
|
214
|
+
# via versionhq (pyproject.toml)
|
215
|
+
wheel==0.45.1
|
216
|
+
# via versionhq (pyproject.toml)
|
217
|
+
yarl==1.18.3
|
218
|
+
# via aiohttp
|
219
|
+
zipp==3.21.0
|
220
|
+
# via importlib-metadata
|
@@ -85,7 +85,7 @@ class Agent(ABC, BaseModel):
|
|
85
85
|
"""
|
86
86
|
|
87
87
|
__hash__ = object.__hash__
|
88
|
-
_logger: Logger = PrivateAttr(default_factory=lambda: Logger(verbose=
|
88
|
+
_logger: Logger = PrivateAttr(default_factory=lambda: Logger(verbose=True))
|
89
89
|
_rpm_controller: Optional[RPMController] = PrivateAttr(default=None)
|
90
90
|
_request_within_rpm_limit: Any = PrivateAttr(default=None)
|
91
91
|
_token_process: TokenProcess = PrivateAttr(default_factory=TokenProcess)
|
@@ -327,7 +327,7 @@ class Agent(ABC, BaseModel):
|
|
327
327
|
messages = []
|
328
328
|
messages.append({"role": "user", "content": prompts}) #! REFINEME
|
329
329
|
messages.append({"role": "assistant", "content": self.backstory})
|
330
|
-
|
330
|
+
self._logger.log(level="info", message=f"Messages sent to the model: {messages}", color="blue")
|
331
331
|
|
332
332
|
callbacks = kwargs.get("callbacks", None)
|
333
333
|
|
@@ -338,7 +338,7 @@ class Agent(ABC, BaseModel):
|
|
338
338
|
callbacks=callbacks,
|
339
339
|
)
|
340
340
|
task_execution_counter += 1
|
341
|
-
|
341
|
+
self._logger.log(level="info", message=f"Agent's first response: {response}", color="blue")
|
342
342
|
|
343
343
|
if (response is None or response == "") and task_execution_counter < self.max_retry_limit:
|
344
344
|
while task_execution_counter <= self.max_retry_limit:
|
@@ -349,10 +349,10 @@ class Agent(ABC, BaseModel):
|
|
349
349
|
callbacks=callbacks,
|
350
350
|
)
|
351
351
|
task_execution_counter += 1
|
352
|
-
|
352
|
+
self._logger.log(level="info", message=f"Agent's next response: {response}", color="blue")
|
353
353
|
|
354
354
|
elif response is None or response == "":
|
355
|
-
|
355
|
+
self._logger.log(level="error", message="Received None or empty response from the model", color="red")
|
356
356
|
raise ValueError("Invalid response from LLM call - None or empty.")
|
357
357
|
|
358
358
|
return {"output": response.output if hasattr(response, "output") else response}
|
@@ -0,0 +1,141 @@
|
|
1
|
+
import appdirs
|
2
|
+
import os
|
3
|
+
import json
|
4
|
+
import sqlite3
|
5
|
+
import datetime
|
6
|
+
from typing import Any, Dict, List, Optional
|
7
|
+
from dotenv import load_dotenv
|
8
|
+
from pathlib import Path
|
9
|
+
|
10
|
+
from versionhq._utils.logger import Logger
|
11
|
+
|
12
|
+
load_dotenv(override=True)
|
13
|
+
|
14
|
+
|
15
|
+
def fetch_db_storage_path():
|
16
|
+
project_directory_name = os.environ.get("STORAGE_DIR", Path.cwd().name)
|
17
|
+
app_author = "versionhq"
|
18
|
+
data_dir = Path(appdirs.user_data_dir(project_directory_name, app_author))
|
19
|
+
data_dir.mkdir(parents=True, exist_ok=True)
|
20
|
+
return data_dir
|
21
|
+
|
22
|
+
storage_path = fetch_db_storage_path()
|
23
|
+
default_db_name = "task_outputs"
|
24
|
+
|
25
|
+
|
26
|
+
class TaskOutputSQLiteStorage:
|
27
|
+
"""
|
28
|
+
An SQLite storage class to handle storing task outputs.
|
29
|
+
"""
|
30
|
+
|
31
|
+
def __init__(self, db_path: str = f"{storage_path}/{default_db_name}.db") -> None:
|
32
|
+
self.db_path = db_path
|
33
|
+
self._logger = Logger(verbose=True)
|
34
|
+
self._initialize_db()
|
35
|
+
|
36
|
+
|
37
|
+
def _initialize_db(self):
|
38
|
+
"""
|
39
|
+
Initializes the SQLite database and creates LTM table.
|
40
|
+
"""
|
41
|
+
|
42
|
+
try:
|
43
|
+
with sqlite3.connect(self.db_path) as conn:
|
44
|
+
cursor = conn.cursor()
|
45
|
+
cursor.execute(
|
46
|
+
"""
|
47
|
+
CREATE TABLE IF NOT EXISTS task_outputs (
|
48
|
+
task_id TEXT PRIMARY KEY,
|
49
|
+
output JSON,
|
50
|
+
task_index INTEGER,
|
51
|
+
inputs JSON,
|
52
|
+
was_replayed BOOLEAN,
|
53
|
+
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
|
54
|
+
)
|
55
|
+
"""
|
56
|
+
)
|
57
|
+
conn.commit()
|
58
|
+
|
59
|
+
except sqlite3.Error as e:
|
60
|
+
self._logger.log(level="error", message=f"DATABASE INITIALIZATION ERROR: {e}", color="red")
|
61
|
+
|
62
|
+
|
63
|
+
def add(self, task, output: Dict[str, Any], task_index: int, was_replayed: bool = False, inputs: Dict[str, Any] = {}):
|
64
|
+
try:
|
65
|
+
with sqlite3.connect(self.db_path) as conn:
|
66
|
+
cursor = conn.cursor()
|
67
|
+
cursor.execute(
|
68
|
+
"""INSERT OR REPLACE INTO task_outputs
|
69
|
+
(task_id, output, task_index, inputs, was_replayed, timestamp)
|
70
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
71
|
+
""",
|
72
|
+
(str(task.id), json.dumps(output), task_index, json.dumps(inputs), was_replayed, datetime.datetime.now())
|
73
|
+
)
|
74
|
+
conn.commit()
|
75
|
+
|
76
|
+
except sqlite3.Error as e:
|
77
|
+
self._logger.log(level="error", message=f"SAVING TASK OUTPUTS ERROR: {e}", color="red")
|
78
|
+
|
79
|
+
|
80
|
+
def update(self, task_index: int, **kwargs):
|
81
|
+
try:
|
82
|
+
with sqlite3.connect(self.db_path) as conn:
|
83
|
+
cursor = conn.cursor()
|
84
|
+
|
85
|
+
fields, values = [], []
|
86
|
+
for k, v in kwargs.items():
|
87
|
+
fields.append(f"{k} = ?")
|
88
|
+
values.append(json.dumps(v) if isinstance(v, dict) else v)
|
89
|
+
|
90
|
+
query = f"UPDATE latest_kickoff_task_outputs SET {', '.join(fields)} WHERE task_index = ?" # nosec
|
91
|
+
values.append(task_index)
|
92
|
+
cursor.execute(query, tuple(values))
|
93
|
+
conn.commit()
|
94
|
+
|
95
|
+
if cursor.rowcount == 0:
|
96
|
+
self._logger.log(
|
97
|
+
level="info", message=f"No row found with task_index {task_index}. No update performed.", color="yellow",
|
98
|
+
)
|
99
|
+
|
100
|
+
except sqlite3.Error as e:
|
101
|
+
self._logger.log(level="error", message=f"UPDATE TASK OUTPUTS ERROR: {e}", color="red")
|
102
|
+
|
103
|
+
|
104
|
+
def load(self) -> Optional[List[Dict[str, Any]]]:
|
105
|
+
try:
|
106
|
+
with sqlite3.connect(self.db_path) as conn:
|
107
|
+
cursor = conn.cursor()
|
108
|
+
cursor.execute("""
|
109
|
+
SELECT *
|
110
|
+
FROM task_outputs
|
111
|
+
ORDER BY task_index
|
112
|
+
""")
|
113
|
+
|
114
|
+
rows = cursor.fetchall()
|
115
|
+
results = []
|
116
|
+
for row in rows:
|
117
|
+
result = {
|
118
|
+
"task_id": row[0],
|
119
|
+
"output": json.loads(row[1]),
|
120
|
+
"task_index": row[2],
|
121
|
+
"inputs": json.loads(row[3]),
|
122
|
+
"was_replayed": row[4],
|
123
|
+
"timestamp": row[5],
|
124
|
+
}
|
125
|
+
results.append(result)
|
126
|
+
return results
|
127
|
+
|
128
|
+
except sqlite3.Error as e:
|
129
|
+
self._logger.log(level="error", message=f"LOADING TASK OUTPUTS ERROR: {e}", color="red")
|
130
|
+
return None
|
131
|
+
|
132
|
+
|
133
|
+
def delete_all(self):
|
134
|
+
try:
|
135
|
+
with sqlite3.connect(self.db_path) as conn:
|
136
|
+
cursor = conn.cursor()
|
137
|
+
cursor.execute("DELETE FROM task_outputs")
|
138
|
+
conn.commit()
|
139
|
+
|
140
|
+
except sqlite3.Error as e:
|
141
|
+
self._logger.log(level="error", message=f"ERROR: Failed to delete all: {e}", color="red")
|
@@ -0,0 +1,59 @@
|
|
1
|
+
from datetime import datetime
|
2
|
+
from typing import Any, Dict, List, Optional
|
3
|
+
|
4
|
+
from pydantic import BaseModel, Field
|
5
|
+
|
6
|
+
from versionhq.storage.task_output_storage import TaskOutputSQLiteStorage
|
7
|
+
|
8
|
+
|
9
|
+
class ExecutionLog(BaseModel):
|
10
|
+
task_id: str
|
11
|
+
output: Dict[str, Any]
|
12
|
+
timestamp: datetime = Field(default_factory=datetime.now)
|
13
|
+
task_index: int
|
14
|
+
inputs: Dict[str, Any] = Field(default_factory=dict)
|
15
|
+
was_replayed: bool = False
|
16
|
+
|
17
|
+
def __getitem__(self, key: str) -> Any:
|
18
|
+
return getattr(self, key)
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
class TaskOutputStorageHandler:
|
23
|
+
|
24
|
+
def __init__(self):
|
25
|
+
self.storage = TaskOutputSQLiteStorage()
|
26
|
+
|
27
|
+
|
28
|
+
def update(self, task, task_index: int, was_replayed: bool = False, inputs: Dict[str, Any] = {}) -> None:
|
29
|
+
"""
|
30
|
+
task: task instance
|
31
|
+
"""
|
32
|
+
saved_outputs = self.load()
|
33
|
+
if saved_outputs is None:
|
34
|
+
raise ValueError("Logs cannot be None")
|
35
|
+
|
36
|
+
self.add(task, task_index, was_replayed, inputs)
|
37
|
+
|
38
|
+
|
39
|
+
def add(self, task, task_index: int, was_replayed: bool = False, inputs: Dict[str, Any] = {}) -> None:
|
40
|
+
from versionhq.task.model import Task
|
41
|
+
|
42
|
+
output_to_store = dict()
|
43
|
+
|
44
|
+
if isinstance(task, Task):
|
45
|
+
output_to_store = dict(
|
46
|
+
description=str(task.description),
|
47
|
+
raw=str(task.output.raw),
|
48
|
+
responsible_agent=str(task.processed_by_agents),
|
49
|
+
)
|
50
|
+
|
51
|
+
self.storage.add(task=task, output=output_to_store, task_index=task_index, was_replayed=was_replayed, inputs=inputs)
|
52
|
+
|
53
|
+
|
54
|
+
def reset(self) -> None:
|
55
|
+
self.storage.delete_all()
|
56
|
+
|
57
|
+
|
58
|
+
def load(self) -> Optional[List[Dict[str, Any]]]:
|
59
|
+
return self.storage.load()
|