versionhq 1.1.10.3__tar.gz → 1.1.10.5__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.10.3 → versionhq-1.1.10.5}/PKG-INFO +1 -1
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/pyproject.toml +1 -1
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/__init__.py +1 -1
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/agent/model.py +3 -10
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/llm/model.py +1 -2
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/task/model.py +5 -3
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/task/structured_response.py +5 -7
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq.egg-info/PKG-INFO +1 -1
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/tests/agent/agent_test.py +4 -8
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/tests/task/task_test.py +47 -4
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/.github/workflows/publish.yml +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/.github/workflows/publish_testpypi.yml +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/.github/workflows/run_tests.yml +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/.github/workflows/security_check.yml +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/.gitignore +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/.pre-commit-config.yaml +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/.python-version +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/LICENSE +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/README.md +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/SECURITY.md +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/db/preprocess.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/requirements-dev.txt +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/requirements.txt +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/runtime.txt +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/setup.cfg +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/_utils/__init__.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/_utils/i18n.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/_utils/logger.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/_utils/process_config.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/_utils/rpm_controller.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/_utils/usage_metrics.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/agent/TEMPLATES/Backstory.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/agent/TEMPLATES/__init__.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/agent/__init__.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/agent/parser.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/cli/__init__.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/clients/__init__.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/clients/customer/__init__.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/clients/customer/model.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/clients/product/__init__.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/clients/product/model.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/clients/workflow/__init__.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/clients/workflow/model.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/llm/__init__.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/llm/llm_vars.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/storage/__init__.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/storage/task_output_storage.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/task/__init__.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/task/formatter.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/task/log_handler.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/team/__init__.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/team/model.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/team/team_planner.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/tool/__init__.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/tool/cache_handler.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/tool/composio_tool.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/tool/composio_tool_vars.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/tool/decorator.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/tool/model.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq/tool/tool_handler.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq.egg-info/SOURCES.txt +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq.egg-info/dependency_links.txt +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq.egg-info/requires.txt +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/src/versionhq.egg-info/top_level.txt +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/tests/__init__.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/tests/agent/__init__.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/tests/cli/__init__.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/tests/clients/customer_test.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/tests/clients/product_test.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/tests/clients/workflow_test.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/tests/conftest.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/tests/llm/__init__.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/tests/llm/llm_test.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/tests/task/__init__.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/tests/team/Prompts/Demo_test.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/tests/team/__init__.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/tests/team/team_test.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/tests/tool/__init__.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/tests/tool/composio_test.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/tests/tool/tool_test.py +0 -0
- {versionhq-1.1.10.3 → versionhq-1.1.10.5}/uv.lock +0 -0
@@ -15,7 +15,7 @@ exclude = ["test*", "__pycache__"]
|
|
15
15
|
|
16
16
|
[project]
|
17
17
|
name = "versionhq"
|
18
|
-
version = "1.1.10.
|
18
|
+
version = "1.1.10.5"
|
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"
|
@@ -255,9 +255,9 @@ class Agent(BaseModel):
|
|
255
255
|
llm.timeout = self.max_execution_time if llm.timeout is None else llm.timeout
|
256
256
|
llm.max_tokens = self.max_tokens if self.max_tokens else llm.max_tokens
|
257
257
|
|
258
|
-
|
259
|
-
|
260
|
-
|
258
|
+
if self.callbacks:
|
259
|
+
llm.callbacks = self.callbacks
|
260
|
+
llm._set_callbacks(llm.callbacks)
|
261
261
|
|
262
262
|
if self.respect_context_window == False:
|
263
263
|
llm.context_window_size = DEFAULT_CONTEXT_WINDOW_SIZE
|
@@ -364,9 +364,6 @@ class Agent(BaseModel):
|
|
364
364
|
task_execution_counter += 1
|
365
365
|
self._logger.log(level="info", message=f"Agent response: {raw_response}", color="blue")
|
366
366
|
|
367
|
-
if raw_response and self.callbacks:
|
368
|
-
for item in self.callbacks:
|
369
|
-
raw_response = item(raw_response)
|
370
367
|
|
371
368
|
except Exception as e:
|
372
369
|
self._logger.log(level="error", message=f"An error occured. The agent will retry: {str(e)}", color="red")
|
@@ -379,10 +376,6 @@ class Agent(BaseModel):
|
|
379
376
|
task_execution_counter += 1
|
380
377
|
self._logger.log(level="info", message=f"Agent #{task_execution_counter} response: {raw_response}", color="blue")
|
381
378
|
|
382
|
-
if raw_response and self.callbacks:
|
383
|
-
for item in self.callbacks:
|
384
|
-
raw_response = item(raw_response)
|
385
|
-
|
386
379
|
if not raw_response:
|
387
380
|
self._logger.log(level="error", message="Received None or empty response from the model", color="red")
|
388
381
|
raise ValueError("Invalid response from LLM call - None or empty.")
|
@@ -200,7 +200,7 @@ class LLM(BaseModel):
|
|
200
200
|
|
201
201
|
with suppress_warnings():
|
202
202
|
if len(self.callbacks) > 0:
|
203
|
-
self._set_callbacks(self.callbacks)
|
203
|
+
self._set_callbacks(self.callbacks) # passed by agent
|
204
204
|
|
205
205
|
try:
|
206
206
|
if tools:
|
@@ -261,7 +261,6 @@ class LLM(BaseModel):
|
|
261
261
|
return tool_res
|
262
262
|
|
263
263
|
else:
|
264
|
-
print(messages)
|
265
264
|
res = litellm.completion(messages=messages, stream=False, **params)
|
266
265
|
|
267
266
|
return res["choices"][0]["message"]["content"]
|
@@ -169,6 +169,7 @@ class TaskOutput(BaseModel):
|
|
169
169
|
json_dict: Dict[str, Any] = Field(default=None, description="`raw` converted to dictionary")
|
170
170
|
pydantic: Optional[Any] = Field(default=None)
|
171
171
|
tool_output: Optional[Any] = Field(default=None, description="store tool result when the task takes tool output as its final output")
|
172
|
+
callback_output: Optional[Any] = Field(default=None, description="store task or agent callback outcome")
|
172
173
|
|
173
174
|
def __str__(self) -> str:
|
174
175
|
return str(self.pydantic) if self.pydantic else str(self.json_dict) if self.json_dict else self.raw
|
@@ -243,7 +244,7 @@ class Task(BaseModel):
|
|
243
244
|
# execution rules
|
244
245
|
allow_delegation: bool = Field(default=False, description="ask other agents for help and run the task instead")
|
245
246
|
async_execution: bool = Field(default=False,description="whether the task should be executed asynchronously or not")
|
246
|
-
callback: Optional[
|
247
|
+
callback: Optional[Callable] = Field(default=None, description="callback to be executed after the task is completed.")
|
247
248
|
callback_kwargs: Optional[Dict[str, Any]] = Field(default_factory=dict, description="kwargs for the callback when the callback is callable")
|
248
249
|
|
249
250
|
# recording
|
@@ -574,8 +575,9 @@ Ref. Output image: {output_formats_to_follow}
|
|
574
575
|
self.output = task_output
|
575
576
|
self.processed_by_agents.add(agent.role)
|
576
577
|
|
577
|
-
if self.callback:
|
578
|
-
self.callback(
|
578
|
+
if self.callback and isinstance(self.callback, Callable):
|
579
|
+
callback_res = self.callback(**self.callback_kwargs, **task_output.json_dict)
|
580
|
+
task_output.callback_output = callback_res
|
579
581
|
|
580
582
|
# if self.output_file: ## disabled for now
|
581
583
|
# content = (
|
@@ -1,4 +1,3 @@
|
|
1
|
-
#! FIXME
|
2
1
|
from typing import Dict, Optional, Type, List, Any, TypeVar
|
3
2
|
|
4
3
|
from pydantic import BaseModel, Field, InstanceOf
|
@@ -92,12 +91,13 @@ class StructuredList:
|
|
92
91
|
|
93
92
|
elif nested_object_type == list:
|
94
93
|
props.update({
|
95
|
-
"nest": {
|
94
|
+
# "nest": {
|
96
95
|
"type": "array",
|
97
|
-
"items": { "
|
98
|
-
}
|
96
|
+
"items": { "type": "string" } , #! REFINEME - field title <>`item`
|
97
|
+
# }
|
98
|
+
})
|
99
99
|
else:
|
100
|
-
props.update({ "
|
100
|
+
props.update({ "type": SchemaType(nested_object_type).convert() })
|
101
101
|
|
102
102
|
self.items = { **props }
|
103
103
|
return {
|
@@ -109,8 +109,6 @@ class StructuredList:
|
|
109
109
|
}
|
110
110
|
|
111
111
|
|
112
|
-
|
113
|
-
|
114
112
|
class StructuredOutput(BaseModel):
|
115
113
|
response_format: Any = None
|
116
114
|
provider: str = "openai"
|
@@ -122,7 +122,7 @@ def test_build_agent_with_llm_config():
|
|
122
122
|
assert agent.llm.max_tokens == 4000
|
123
123
|
assert agent.llm.logprobs == False
|
124
124
|
assert [hasattr(agent.llm, k) and v for k, v in llm_config.items() if v is not None]
|
125
|
-
assert agent.llm.callbacks == []
|
125
|
+
assert agent.llm.callbacks == [dummy_func]
|
126
126
|
|
127
127
|
|
128
128
|
def test_build_agent_with_llm_instance():
|
@@ -142,7 +142,7 @@ def test_build_agent_with_llm_instance():
|
|
142
142
|
assert agent.llm.api_key is not None
|
143
143
|
assert agent.llm.max_tokens == 3000
|
144
144
|
assert agent.llm.logprobs == False
|
145
|
-
assert agent.llm.callbacks == []
|
145
|
+
assert agent.llm.callbacks == [dummy_func]
|
146
146
|
|
147
147
|
|
148
148
|
def test_build_agent_with_llm_and_func_llm_config():
|
@@ -163,7 +163,7 @@ def test_build_agent_with_llm_and_func_llm_config():
|
|
163
163
|
assert agent.function_calling_llm.api_key is not None
|
164
164
|
assert agent.function_calling_llm.max_tokens == 4000
|
165
165
|
assert agent.function_calling_llm.logprobs == False
|
166
|
-
assert agent.function_calling_llm.callbacks == []
|
166
|
+
assert agent.function_calling_llm.callbacks == [dummy_func]
|
167
167
|
|
168
168
|
|
169
169
|
def test_build_agent_with_llm_and_func_llm_instance():
|
@@ -185,7 +185,7 @@ def test_build_agent_with_llm_and_func_llm_instance():
|
|
185
185
|
assert agent.function_calling_llm.api_key is not None
|
186
186
|
assert agent.function_calling_llm.max_tokens == 3000
|
187
187
|
assert agent.function_calling_llm.logprobs == False
|
188
|
-
assert agent.function_calling_llm.callbacks == []
|
188
|
+
assert agent.function_calling_llm.callbacks == [dummy_func]
|
189
189
|
|
190
190
|
|
191
191
|
def test_agent_with_random_dict_tools():
|
@@ -234,7 +234,3 @@ def test_agent_custom_max_iterations():
|
|
234
234
|
)
|
235
235
|
agent.execute_task(task=task)
|
236
236
|
assert private_mock.call_count == 1
|
237
|
-
|
238
|
-
|
239
|
-
if __name__ == "__main__":
|
240
|
-
test_agent_custom_max_iterations()
|
@@ -1,5 +1,7 @@
|
|
1
1
|
import os
|
2
2
|
import pytest
|
3
|
+
import sys
|
4
|
+
import threading
|
3
5
|
from unittest.mock import patch
|
4
6
|
from typing import Dict, Any, List, Optional, Callable
|
5
7
|
|
@@ -10,7 +12,8 @@ from versionhq.task.model import Task, ResponseField, TaskOutput, ConditionalTas
|
|
10
12
|
from versionhq.tool.model import Tool, ToolSet
|
11
13
|
from tests.task import DemoOutcome, demo_response_fields, base_agent
|
12
14
|
|
13
|
-
|
15
|
+
sys.setrecursionlimit(2097152)
|
16
|
+
threading.stack_size(134217728)
|
14
17
|
|
15
18
|
def test_sync_execute_task_with_pydantic_outcome():
|
16
19
|
task = Task(
|
@@ -144,7 +147,7 @@ def test_callback():
|
|
144
147
|
|
145
148
|
|
146
149
|
def test_delegate():
|
147
|
-
agent = Agent(role="demo agent 6", goal="My amazing goals")
|
150
|
+
agent = Agent(role="demo agent 6", goal="My amazing goals", maxit=1, max_tokens=3000)
|
148
151
|
task = Task(
|
149
152
|
description="return the output following the given prompt.",
|
150
153
|
response_fields=[
|
@@ -193,7 +196,7 @@ def test_store_task_log():
|
|
193
196
|
|
194
197
|
def test_task_with_agent_tools():
|
195
198
|
simple_tool = Tool(name="simple tool", func=lambda x: "simple func")
|
196
|
-
agent = Agent(role="demo", goal="execute tools", tools=[simple_tool,])
|
199
|
+
agent = Agent(role="demo", goal="execute tools", tools=[simple_tool,], maxit=1, max_tokens=3000)
|
197
200
|
task = Task(description="execute tool", can_use_agent_tools=True, tool_res_as_final=True)
|
198
201
|
res = task.execute_sync(agent=agent)
|
199
202
|
assert res.tool_output == "simple func"
|
@@ -227,7 +230,7 @@ def test_task_with_tools():
|
|
227
230
|
tool = Tool(name="tool", func=random_func)
|
228
231
|
tool_set = ToolSet(tool=tool, kwargs=dict(message="empty func"))
|
229
232
|
|
230
|
-
agent = Agent(role="Tool Handler", goal="execute tools")
|
233
|
+
agent = Agent(role="Tool Handler", goal="execute tools", maxit=1, max_tokens=3000)
|
231
234
|
task = Task(description="execute the function", tools=[tool_set,], tool_res_as_final=True)
|
232
235
|
res = task.execute_sync(agent=agent)
|
233
236
|
assert res.tool_output == "empty func_demo"
|
@@ -272,5 +275,45 @@ def test_build_agent_without_developer_prompt():
|
|
272
275
|
|
273
276
|
|
274
277
|
|
278
|
+
def test_callback():
|
279
|
+
from pydantic import BaseModel
|
280
|
+
from versionhq.agent.model import Agent
|
281
|
+
from versionhq.task.model import Task
|
282
|
+
|
283
|
+
class CustomOutput(BaseModel):
|
284
|
+
test1: str
|
285
|
+
test2: list[str]
|
286
|
+
|
287
|
+
def dummy_func(message: str, test1: str, test2: list[str]) -> str:
|
288
|
+
return f"{message}: {test1}, {", ".join(test2)}"
|
289
|
+
|
290
|
+
agent = Agent(role="demo", goal="amazing project goal", maxit=1, max_tokens=3000)
|
291
|
+
|
292
|
+
task = Task(
|
293
|
+
description="Amazing task",
|
294
|
+
pydantic_custom_output=CustomOutput,
|
295
|
+
callback=dummy_func,
|
296
|
+
callback_kwargs=dict(message="Hi! Here is the result: ")
|
297
|
+
)
|
298
|
+
res = task.execute_sync(agent=agent, context="amazing context to consider.")
|
299
|
+
|
300
|
+
assert res.task_id == task.id
|
301
|
+
assert res.pydantic.test1 and res.pydantic.test2
|
302
|
+
assert "Hi! Here is the result: " in res.callback_output and res.pydantic.test1 in res.callback_output and ", ".join(res.pydantic.test2) in res.callback_output
|
303
|
+
|
304
|
+
|
305
|
+
def test_task_with_agent_callback():
|
306
|
+
def dummy_func(*args, **kwargs) -> str:
|
307
|
+
return "Demo func"
|
308
|
+
|
309
|
+
agent = Agent(role="demo", goal="amazing project goal", maxit=1, max_tokens=3000, callbacks=[dummy_func,])
|
310
|
+
task = Task(description="Amazing task")
|
311
|
+
res = task.execute_sync(agent=agent)
|
312
|
+
|
313
|
+
assert res.raw and res.task_id == task.id
|
275
314
|
|
276
315
|
# task - maxit, loop, rpm
|
316
|
+
|
317
|
+
|
318
|
+
if __name__ == "__main__":
|
319
|
+
test_task_with_agent_callback()
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|