jarvis-ai-assistant 0.1.18__tar.gz → 0.1.22__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.
Potentially problematic release.
This version of jarvis-ai-assistant might be problematic. Click here for more details.
- {jarvis_ai_assistant-0.1.18/src/jarvis_ai_assistant.egg-info → jarvis_ai_assistant-0.1.22}/PKG-INFO +1 -1
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/pyproject.toml +1 -1
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/setup.py +1 -1
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis/__init__.py +1 -1
- jarvis_ai_assistant-0.1.22/src/jarvis/__pycache__/__init__.cpython-313.pyc +0 -0
- jarvis_ai_assistant-0.1.22/src/jarvis/__pycache__/agent.cpython-313.pyc +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis/__pycache__/main.cpython-313.pyc +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis/agent.py +59 -74
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis/main.py +34 -4
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis/tools/__pycache__/base.cpython-313.pyc +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis/tools/__pycache__/generator.cpython-313.pyc +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis/tools/base.py +1 -1
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis/tools/generator.py +6 -2
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22/src/jarvis_ai_assistant.egg-info}/PKG-INFO +1 -1
- jarvis_ai_assistant-0.1.18/src/jarvis/__pycache__/__init__.cpython-313.pyc +0 -0
- jarvis_ai_assistant-0.1.18/src/jarvis/__pycache__/agent.cpython-313.pyc +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/MANIFEST.in +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/README.md +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/setup.cfg +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis/__pycache__/models.cpython-313.pyc +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis/__pycache__/tools.cpython-313.pyc +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis/__pycache__/utils.cpython-313.pyc +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis/__pycache__/zte_llm.cpython-313.pyc +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis/models/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis/models/__pycache__/__init__.cpython-313.pyc +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis/models/__pycache__/base.cpython-313.pyc +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis/models/__pycache__/kimi.cpython-313.pyc +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis/models/base.py +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis/models/kimi.py +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis/tools/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis/tools/__pycache__/__init__.cpython-313.pyc +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis/tools/__pycache__/bing_search.cpython-313.pyc +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis/tools/__pycache__/calculator.cpython-313.pyc +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis/tools/__pycache__/calculator_tool.cpython-313.pyc +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis/tools/__pycache__/file_ops.cpython-313.pyc +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis/tools/__pycache__/python_script.cpython-313.pyc +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis/tools/__pycache__/rag.cpython-313.pyc +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis/tools/__pycache__/search.cpython-313.pyc +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis/tools/__pycache__/shell.cpython-313.pyc +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis/tools/__pycache__/sub_agent.cpython-313.pyc +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis/tools/__pycache__/user_confirmation.cpython-313.pyc +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis/tools/__pycache__/user_input.cpython-313.pyc +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis/tools/__pycache__/user_interaction.cpython-313.pyc +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis/tools/__pycache__/webpage.cpython-313.pyc +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis/tools/file_ops.py +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis/tools/shell.py +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis/utils.py +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis_ai_assistant.egg-info/SOURCES.txt +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis_ai_assistant.egg-info/dependency_links.txt +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis_ai_assistant.egg-info/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis_ai_assistant.egg-info/requires.txt +0 -0
- {jarvis_ai_assistant-0.1.18 → jarvis_ai_assistant-0.1.22}/src/jarvis_ai_assistant.egg-info/top_level.txt +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "jarvis-ai-assistant"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.22"
|
|
8
8
|
description = "Jarvis: An AI assistant that uses tools to interact with the system"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [{ name = "Your Name", email = "your.email@example.com" }]
|
|
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
|
|
2
2
|
|
|
3
3
|
setup(
|
|
4
4
|
name="jarvis-ai-assistant",
|
|
5
|
-
version="0.1.
|
|
5
|
+
version="0.1.22",
|
|
6
6
|
author="skyfire",
|
|
7
7
|
author_email="skyfireitdiy@hotmail.com",
|
|
8
8
|
description="An AI assistant that uses various tools to interact with the system",
|
|
Binary file
|
|
Binary file
|
|
@@ -11,7 +11,7 @@ import os
|
|
|
11
11
|
from datetime import datetime
|
|
12
12
|
|
|
13
13
|
class Agent:
|
|
14
|
-
def __init__(self, model: BaseModel, tool_registry: ToolRegistry, name: str = "Jarvis"):
|
|
14
|
+
def __init__(self, model: BaseModel, tool_registry: ToolRegistry, name: str = "Jarvis", is_sub_agent: bool = False):
|
|
15
15
|
"""Initialize Agent with a model, optional tool registry and name
|
|
16
16
|
|
|
17
17
|
Args:
|
|
@@ -23,6 +23,7 @@ class Agent:
|
|
|
23
23
|
self.model = model
|
|
24
24
|
self.tool_registry = tool_registry or ToolRegistry(model)
|
|
25
25
|
self.name = name
|
|
26
|
+
self.is_sub_agent = is_sub_agent
|
|
26
27
|
self.prompt = ""
|
|
27
28
|
|
|
28
29
|
|
|
@@ -77,7 +78,7 @@ class Agent:
|
|
|
77
78
|
except Exception as e:
|
|
78
79
|
raise Exception(f"{self.name}: 模型调用失败: {str(e)}")
|
|
79
80
|
|
|
80
|
-
def run(self, user_input: str, file_list: Optional[List[str]] = None, keep_history: bool = False):
|
|
81
|
+
def run(self, user_input: str, file_list: Optional[List[str]] = None, keep_history: bool = False) -> str:
|
|
81
82
|
"""处理用户输入并返回响应,返回任务总结报告
|
|
82
83
|
|
|
83
84
|
Args:
|
|
@@ -103,55 +104,32 @@ class Agent:
|
|
|
103
104
|
tools_prompt += f" 描述: {tool['description']}\n"
|
|
104
105
|
tools_prompt += f" 参数: {tool['parameters']}\n"
|
|
105
106
|
|
|
106
|
-
self.prompt = f"""你是 {self.name},一个严格遵循 ReAct
|
|
107
|
+
self.prompt = f"""你是 {self.name},一个严格遵循 ReAct 框架的 AI 助手。
|
|
107
108
|
|
|
108
109
|
{tools_prompt}
|
|
109
110
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
‼️ 只回应用户实际说的内容
|
|
115
|
-
‼️ 每个动作后停止并等待
|
|
111
|
+
核心能力:
|
|
112
|
+
1. 使用现有工具完成任务
|
|
113
|
+
2. 通过 generate_tool 创建新工具扩展功能
|
|
114
|
+
3. 遵循 ReAct (思考-行动-观察) 框架
|
|
116
115
|
|
|
117
|
-
|
|
116
|
+
工作流程:
|
|
118
117
|
1. 思考
|
|
119
|
-
-
|
|
120
|
-
-
|
|
121
|
-
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
- 如果需要更多信息,直接询问用户
|
|
129
|
-
- 使用工具时:
|
|
130
|
-
- 只使用下面列出的工具
|
|
131
|
-
- 每次只执行一个工具
|
|
132
|
-
- 工具由用户手动执行
|
|
133
|
-
- 必须使用有效合法的YAML格式:
|
|
134
|
-
<START_TOOL_CALL>
|
|
135
|
-
name: tool_name
|
|
136
|
-
arguments:
|
|
137
|
-
param1: value1 # 所有参数必须正确缩进
|
|
138
|
-
param2: | # 使用YAML块样式表示多行字符串
|
|
139
|
-
line1
|
|
140
|
-
line2
|
|
141
|
-
<END_TOOL_CALL>
|
|
142
|
-
|
|
118
|
+
- 分析需求和可用工具
|
|
119
|
+
- 评估是否需要新工具
|
|
120
|
+
- 规划解决方案
|
|
121
|
+
|
|
122
|
+
2. 行动 (如果需要)
|
|
123
|
+
- 使用现有工具
|
|
124
|
+
- 创建新工具
|
|
125
|
+
- 询问更多信息
|
|
126
|
+
|
|
143
127
|
3. 观察
|
|
144
|
-
-
|
|
145
|
-
-
|
|
146
|
-
-
|
|
147
|
-
- 不要创建虚假对话
|
|
148
|
-
- 停止并等待实际输入
|
|
149
|
-
|
|
150
|
-
回应格式:
|
|
151
|
-
思考:我分析当前情况[具体情况]... 基于[事实],我需要[目标]...
|
|
128
|
+
- 等待执行结果
|
|
129
|
+
- 分析反馈
|
|
130
|
+
- 规划下一步
|
|
152
131
|
|
|
153
|
-
|
|
154
|
-
行动:我将使用[工具]来[具体目的]...
|
|
132
|
+
工具使用格式:
|
|
155
133
|
<START_TOOL_CALL>
|
|
156
134
|
name: tool_name
|
|
157
135
|
arguments:
|
|
@@ -161,37 +139,28 @@ arguments:
|
|
|
161
139
|
value
|
|
162
140
|
<END_TOOL_CALL>
|
|
163
141
|
|
|
164
|
-
|
|
165
|
-
|
|
142
|
+
创建新工具示例:
|
|
143
|
+
<START_TOOL_CALL>
|
|
144
|
+
name: generate_tool
|
|
145
|
+
arguments:
|
|
146
|
+
tool_name: custom_tool_name
|
|
147
|
+
class_name: CustomToolName
|
|
148
|
+
description: 详细的工具描述
|
|
149
|
+
parameters:
|
|
150
|
+
type: object
|
|
151
|
+
properties:
|
|
152
|
+
param1:
|
|
153
|
+
type: string
|
|
154
|
+
description: 参数1的描述
|
|
155
|
+
required: [param1]
|
|
156
|
+
<END_TOOL_CALL>
|
|
166
157
|
|
|
167
158
|
严格规则:
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
‼️ 使用YAML块样式(|)表示多行值
|
|
174
|
-
‼️ 工具由用户手动执行
|
|
175
|
-
‼️ 等待用户提供工具执行结果
|
|
176
|
-
‼️ 不要假设或想象用户回应
|
|
177
|
-
‼️ 没有用户输入时不要继续对话
|
|
178
|
-
‼️ 不要创建虚假对话
|
|
179
|
-
‼️ 每个动作后停止
|
|
180
|
-
‼️ 不要假设结果
|
|
181
|
-
‼️ 不要假设行动
|
|
182
|
-
|
|
183
|
-
注意事项:
|
|
184
|
-
- 先思考再行动
|
|
185
|
-
- 需要时询问用户
|
|
186
|
-
- 只使用列出的工具
|
|
187
|
-
- 一次一个工具
|
|
188
|
-
- 严格遵循YAML格式
|
|
189
|
-
- 等待用户回应
|
|
190
|
-
- 工具结果来自用户
|
|
191
|
-
- 不要假设回应
|
|
192
|
-
- 不要虚构对话
|
|
193
|
-
- 每个动作后停止
|
|
194
|
-
- 只在有实际用户输入时继续
|
|
159
|
+
1. 每次只能执行一个工具
|
|
160
|
+
2. 等待用户提供执行结果
|
|
161
|
+
3. 不要假设或想象结果
|
|
162
|
+
4. 不要创建虚假对话
|
|
163
|
+
5. 每个动作后停止等待
|
|
195
164
|
|
|
196
165
|
任务:
|
|
197
166
|
{user_input}
|
|
@@ -235,7 +204,23 @@ arguments:
|
|
|
235
204
|
|
|
236
205
|
if not user_input:
|
|
237
206
|
PrettyOutput.section("任务完成", OutputType.SUCCESS)
|
|
238
|
-
|
|
207
|
+
if self.is_sub_agent:
|
|
208
|
+
# 生成任务总结
|
|
209
|
+
summary_prompt = f"""请对以上任务执行情况生成一个简洁的总结报告,包括:
|
|
210
|
+
|
|
211
|
+
1. 任务目标: xxxx
|
|
212
|
+
2. 执行结果: 成功/失败
|
|
213
|
+
3. 关键信息: 提取执行过程中的重要信息
|
|
214
|
+
4. 重要发现: 任何值得注意的发现
|
|
215
|
+
5. 后续建议: 如果有的话
|
|
216
|
+
|
|
217
|
+
请用简洁的要点形式描述,突出重要信息。
|
|
218
|
+
"""
|
|
219
|
+
self.prompt = summary_prompt
|
|
220
|
+
summary = self.model.chat(self.prompt)
|
|
221
|
+
return summary
|
|
222
|
+
else:
|
|
223
|
+
return "Task completed"
|
|
239
224
|
|
|
240
225
|
except Exception as e:
|
|
241
226
|
PrettyOutput.print(str(e), OutputType.ERROR)
|
|
@@ -6,6 +6,9 @@ import yaml
|
|
|
6
6
|
import os
|
|
7
7
|
import sys
|
|
8
8
|
from pathlib import Path
|
|
9
|
+
from prompt_toolkit import prompt
|
|
10
|
+
from prompt_toolkit.completion import WordCompleter
|
|
11
|
+
from prompt_toolkit.validation import Validator, ValidationError
|
|
9
12
|
|
|
10
13
|
# 添加父目录到Python路径以支持导入
|
|
11
14
|
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
@@ -55,6 +58,19 @@ def load_tasks() -> dict:
|
|
|
55
58
|
|
|
56
59
|
return tasks
|
|
57
60
|
|
|
61
|
+
class NumberValidator(Validator):
|
|
62
|
+
def validate(self, document):
|
|
63
|
+
text = document.text.strip()
|
|
64
|
+
if not text: # Allow empty input
|
|
65
|
+
return
|
|
66
|
+
|
|
67
|
+
try:
|
|
68
|
+
number = int(text)
|
|
69
|
+
if number < 0:
|
|
70
|
+
raise ValidationError(message='Please enter a non-negative number')
|
|
71
|
+
except ValueError:
|
|
72
|
+
raise ValidationError(message='Please enter a valid number')
|
|
73
|
+
|
|
58
74
|
def select_task(tasks: dict) -> str:
|
|
59
75
|
"""Let user select a task from the list or skip. Returns task description if selected."""
|
|
60
76
|
if not tasks:
|
|
@@ -68,9 +84,20 @@ def select_task(tasks: dict) -> str:
|
|
|
68
84
|
PrettyOutput.print(f"[{i}] {name}", OutputType.INFO)
|
|
69
85
|
PrettyOutput.print("[0] Skip predefined tasks", OutputType.INFO)
|
|
70
86
|
|
|
87
|
+
# Create completer with valid numbers
|
|
88
|
+
valid_numbers = [str(i) for i in range(len(task_names) + 1)]
|
|
89
|
+
number_completer = WordCompleter(valid_numbers)
|
|
90
|
+
|
|
71
91
|
while True:
|
|
72
92
|
try:
|
|
73
|
-
choice =
|
|
93
|
+
choice = prompt(
|
|
94
|
+
"\nSelect a task number (0 to skip): ",
|
|
95
|
+
completer=number_completer,
|
|
96
|
+
validator=NumberValidator(),
|
|
97
|
+
validate_while_typing=False,
|
|
98
|
+
enable_history_search=True,
|
|
99
|
+
).strip()
|
|
100
|
+
|
|
74
101
|
if not choice:
|
|
75
102
|
return ""
|
|
76
103
|
|
|
@@ -81,9 +108,12 @@ def select_task(tasks: dict) -> str:
|
|
|
81
108
|
selected_name = task_names[choice - 1]
|
|
82
109
|
return tasks[selected_name] # Return the task description
|
|
83
110
|
else:
|
|
84
|
-
PrettyOutput.print("Invalid choice. Please
|
|
85
|
-
|
|
86
|
-
|
|
111
|
+
PrettyOutput.print("Invalid choice. Please select a number from the list.", OutputType.ERROR)
|
|
112
|
+
|
|
113
|
+
except KeyboardInterrupt:
|
|
114
|
+
return "" # Return empty on Ctrl+C
|
|
115
|
+
except EOFError:
|
|
116
|
+
return "" # Return empty on Ctrl+D
|
|
87
117
|
|
|
88
118
|
def main():
|
|
89
119
|
"""Main entry point for Jarvis."""
|
|
Binary file
|
|
Binary file
|
|
@@ -115,7 +115,7 @@ class ToolRegistry:
|
|
|
115
115
|
parameters=tool_instance.parameters,
|
|
116
116
|
func=tool_instance.execute
|
|
117
117
|
)
|
|
118
|
-
self.output_handler.print(f"已加载工具: {tool_instance.name}", OutputType.INFO)
|
|
118
|
+
self.output_handler.print(f"已加载工具: {tool_instance.name}: {tool_instance.description}", OutputType.INFO)
|
|
119
119
|
tool_found = True
|
|
120
120
|
|
|
121
121
|
if not tool_found:
|
|
@@ -15,7 +15,7 @@ class ModelHandler(Protocol):
|
|
|
15
15
|
|
|
16
16
|
class ToolGeneratorTool:
|
|
17
17
|
name = "generate_tool"
|
|
18
|
-
description = "生成新的工具代码并自动注册到
|
|
18
|
+
description = "生成新的工具代码并自动注册到Jarvis,自动扩充Jarvis的能力"
|
|
19
19
|
parameters = {
|
|
20
20
|
"type": "object",
|
|
21
21
|
"properties": {
|
|
@@ -113,9 +113,13 @@ class ExampleTool:
|
|
|
113
113
|
def __init__(self, **kwargs):
|
|
114
114
|
'''初始化工具
|
|
115
115
|
Args:
|
|
116
|
-
model: 模型处理器
|
|
116
|
+
model: 模型处理器
|
|
117
|
+
与大模型交互: model.chat(prompt)
|
|
118
|
+
使用完成后删除会话: model.delete_chat()
|
|
117
119
|
output_handler: 输出处理器
|
|
120
|
+
输出信息: output_handler.print(text, output_type)
|
|
118
121
|
register: 注册器
|
|
122
|
+
注册工具: register.register_tool_by_file(tool_file)
|
|
119
123
|
'''
|
|
120
124
|
self.model = kwargs.get('model')
|
|
121
125
|
self.output = kwargs.get('output_handler')
|
|
Binary file
|
|
Binary file
|
|
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
|