jarvis-ai-assistant 0.1.97__tar.gz → 0.1.99__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.97/src/jarvis_ai_assistant.egg-info → jarvis_ai_assistant-0.1.99}/PKG-INFO +1 -1
- {jarvis_ai_assistant-0.1.97 → jarvis_ai_assistant-0.1.99}/pyproject.toml +3 -2
- {jarvis_ai_assistant-0.1.97 → jarvis_ai_assistant-0.1.99}/setup.py +3 -2
- {jarvis_ai_assistant-0.1.97 → jarvis_ai_assistant-0.1.99}/src/jarvis/__init__.py +1 -1
- {jarvis_ai_assistant-0.1.97 → jarvis_ai_assistant-0.1.99}/src/jarvis/agent.py +199 -157
- jarvis_ai_assistant-0.1.99/src/jarvis/jarvis_code_agent/main.py +203 -0
- jarvis_ai_assistant-0.1.99/src/jarvis/jarvis_codebase/main.py +875 -0
- jarvis_ai_assistant-0.1.99/src/jarvis/jarvis_coder/file_select.py +209 -0
- jarvis_ai_assistant-0.1.99/src/jarvis/jarvis_coder/git_utils.py +123 -0
- jarvis_ai_assistant-0.1.99/src/jarvis/jarvis_coder/main.py +247 -0
- jarvis_ai_assistant-0.1.99/src/jarvis/jarvis_coder/patch_handler.py +262 -0
- jarvis_ai_assistant-0.1.99/src/jarvis/jarvis_coder/plan_generator.py +145 -0
- {jarvis_ai_assistant-0.1.97 → jarvis_ai_assistant-0.1.99}/src/jarvis/jarvis_platform/main.py +38 -38
- {jarvis_ai_assistant-0.1.97 → jarvis_ai_assistant-0.1.99}/src/jarvis/jarvis_rag/main.py +189 -189
- jarvis_ai_assistant-0.1.99/src/jarvis/jarvis_smart_shell/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.97 → jarvis_ai_assistant-0.1.99}/src/jarvis/jarvis_smart_shell/main.py +22 -24
- {jarvis_ai_assistant-0.1.97 → jarvis_ai_assistant-0.1.99}/src/jarvis/models/base.py +6 -1
- {jarvis_ai_assistant-0.1.97 → jarvis_ai_assistant-0.1.99}/src/jarvis/models/ollama.py +2 -2
- {jarvis_ai_assistant-0.1.97 → jarvis_ai_assistant-0.1.99}/src/jarvis/models/registry.py +3 -6
- {jarvis_ai_assistant-0.1.97 → jarvis_ai_assistant-0.1.99}/src/jarvis/tools/ask_user.py +6 -6
- {jarvis_ai_assistant-0.1.97 → jarvis_ai_assistant-0.1.99}/src/jarvis/tools/codebase_qa.py +5 -7
- jarvis_ai_assistant-0.1.99/src/jarvis/tools/create_code_sub_agent.py +55 -0
- jarvis_ai_assistant-0.1.97/src/jarvis/tools/sub_agent.py → jarvis_ai_assistant-0.1.99/src/jarvis/tools/create_sub_agent.py +4 -1
- jarvis_ai_assistant-0.1.99/src/jarvis/tools/execute_code_modification.py +72 -0
- jarvis_ai_assistant-0.1.97/src/jarvis/tools/file_ops.py → jarvis_ai_assistant-0.1.99/src/jarvis/tools/file_operation.py +13 -14
- jarvis_ai_assistant-0.1.99/src/jarvis/tools/find_related_files.py +86 -0
- {jarvis_ai_assistant-0.1.97 → jarvis_ai_assistant-0.1.99}/src/jarvis/tools/methodology.py +25 -25
- {jarvis_ai_assistant-0.1.97 → jarvis_ai_assistant-0.1.99}/src/jarvis/tools/rag.py +32 -32
- {jarvis_ai_assistant-0.1.97 → jarvis_ai_assistant-0.1.99}/src/jarvis/tools/registry.py +72 -36
- {jarvis_ai_assistant-0.1.97 → jarvis_ai_assistant-0.1.99}/src/jarvis/tools/search.py +1 -1
- jarvis_ai_assistant-0.1.99/src/jarvis/tools/select_code_files.py +64 -0
- {jarvis_ai_assistant-0.1.97 → jarvis_ai_assistant-0.1.99}/src/jarvis/utils.py +153 -49
- {jarvis_ai_assistant-0.1.97 → jarvis_ai_assistant-0.1.99/src/jarvis_ai_assistant.egg-info}/PKG-INFO +1 -1
- {jarvis_ai_assistant-0.1.97 → jarvis_ai_assistant-0.1.99}/src/jarvis_ai_assistant.egg-info/SOURCES.txt +12 -7
- {jarvis_ai_assistant-0.1.97 → jarvis_ai_assistant-0.1.99}/src/jarvis_ai_assistant.egg-info/entry_points.txt +2 -1
- jarvis_ai_assistant-0.1.97/src/jarvis/jarvis_codebase/main.py +0 -747
- jarvis_ai_assistant-0.1.97/src/jarvis/jarvis_coder/git_utils.py +0 -61
- jarvis_ai_assistant-0.1.97/src/jarvis/jarvis_coder/main.py +0 -625
- jarvis_ai_assistant-0.1.97/src/jarvis/jarvis_coder/patch_handler.py +0 -192
- jarvis_ai_assistant-0.1.97/src/jarvis/jarvis_coder/plan_generator.py +0 -103
- jarvis_ai_assistant-0.1.97/src/jarvis/main.py +0 -155
- jarvis_ai_assistant-0.1.97/src/jarvis/tools/coder.py +0 -69
- {jarvis_ai_assistant-0.1.97 → jarvis_ai_assistant-0.1.99}/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.97 → jarvis_ai_assistant-0.1.99}/MANIFEST.in +0 -0
- {jarvis_ai_assistant-0.1.97 → jarvis_ai_assistant-0.1.99}/README.md +0 -0
- {jarvis_ai_assistant-0.1.97 → jarvis_ai_assistant-0.1.99}/setup.cfg +0 -0
- {jarvis_ai_assistant-0.1.97/src/jarvis/jarvis_codebase → jarvis_ai_assistant-0.1.99/src/jarvis/jarvis_code_agent}/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.97/src/jarvis/jarvis_coder → jarvis_ai_assistant-0.1.99/src/jarvis/jarvis_codebase}/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.97/src/jarvis/jarvis_platform → jarvis_ai_assistant-0.1.99/src/jarvis/jarvis_coder}/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.97/src/jarvis/jarvis_rag → jarvis_ai_assistant-0.1.99/src/jarvis/jarvis_platform}/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.97/src/jarvis/jarvis_smart_shell → jarvis_ai_assistant-0.1.99/src/jarvis/jarvis_rag}/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.97 → jarvis_ai_assistant-0.1.99}/src/jarvis/models/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.97 → jarvis_ai_assistant-0.1.99}/src/jarvis/models/ai8.py +0 -0
- {jarvis_ai_assistant-0.1.97 → jarvis_ai_assistant-0.1.99}/src/jarvis/models/kimi.py +0 -0
- {jarvis_ai_assistant-0.1.97 → jarvis_ai_assistant-0.1.99}/src/jarvis/models/openai.py +0 -0
- {jarvis_ai_assistant-0.1.97 → jarvis_ai_assistant-0.1.99}/src/jarvis/models/oyi.py +0 -0
- {jarvis_ai_assistant-0.1.97 → jarvis_ai_assistant-0.1.99}/src/jarvis/tools/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.97 → jarvis_ai_assistant-0.1.99}/src/jarvis/tools/base.py +0 -0
- {jarvis_ai_assistant-0.1.97 → jarvis_ai_assistant-0.1.99}/src/jarvis/tools/chdir.py +0 -0
- /jarvis_ai_assistant-0.1.97/src/jarvis/tools/shell.py → /jarvis_ai_assistant-0.1.99/src/jarvis/tools/execute_shell.py +0 -0
- /jarvis_ai_assistant-0.1.97/src/jarvis/tools/generator.py → /jarvis_ai_assistant-0.1.99/src/jarvis/tools/generate_tool.py +0 -0
- /jarvis_ai_assistant-0.1.97/src/jarvis/tools/webpage.py → /jarvis_ai_assistant-0.1.99/src/jarvis/tools/read_webpage.py +0 -0
- {jarvis_ai_assistant-0.1.97 → jarvis_ai_assistant-0.1.99}/src/jarvis/tools/thinker.py +0 -0
- {jarvis_ai_assistant-0.1.97 → jarvis_ai_assistant-0.1.99}/src/jarvis_ai_assistant.egg-info/dependency_links.txt +0 -0
- {jarvis_ai_assistant-0.1.97 → jarvis_ai_assistant-0.1.99}/src/jarvis_ai_assistant.egg-info/requires.txt +0 -0
- {jarvis_ai_assistant-0.1.97 → jarvis_ai_assistant-0.1.99}/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.99"
|
|
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" }]
|
|
@@ -47,7 +47,8 @@ dev = ["pytest", "black", "isort", "mypy"]
|
|
|
47
47
|
Homepage = "https://github.com/skyfireitdiy/Jarvis"
|
|
48
48
|
|
|
49
49
|
[project.scripts]
|
|
50
|
-
jarvis = "jarvis.
|
|
50
|
+
jarvis = "jarvis.agent:main"
|
|
51
|
+
jarvis-code-agent = "jarvis.jarvis_code_agent.main:main"
|
|
51
52
|
jarvis-coder = "jarvis.jarvis_coder.main:main"
|
|
52
53
|
jarvis-codebase = "jarvis.jarvis_codebase.main:main"
|
|
53
54
|
jarvis-rag = "jarvis.jarvis_rag.main:main"
|
|
@@ -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.99",
|
|
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",
|
|
@@ -32,7 +32,8 @@ setup(
|
|
|
32
32
|
],
|
|
33
33
|
entry_points={
|
|
34
34
|
"console_scripts": [
|
|
35
|
-
"jarvis=jarvis.
|
|
35
|
+
"jarvis=jarvis.agent:main",
|
|
36
|
+
"jarvis-code-agent=jarvis.jarvis_code_agent.main:main",
|
|
36
37
|
"jarvis-coder=jarvis.jarvis_coder.main:main",
|
|
37
38
|
"jarvis-codebase=jarvis.jarvis_codebase.main:main",
|
|
38
39
|
"jarvis-rag=jarvis.jarvis_rag.main:main",
|
|
@@ -1,32 +1,39 @@
|
|
|
1
|
+
import argparse
|
|
1
2
|
import time
|
|
2
3
|
from typing import Dict, List, Optional
|
|
3
4
|
|
|
5
|
+
from prompt_toolkit import prompt
|
|
4
6
|
import yaml
|
|
5
|
-
import numpy as np
|
|
6
|
-
import faiss
|
|
7
7
|
|
|
8
|
-
from .models.registry import PlatformRegistry
|
|
9
|
-
from .tools import ToolRegistry
|
|
10
|
-
from .
|
|
8
|
+
from jarvis.models.registry import PlatformRegistry
|
|
9
|
+
from jarvis.tools import ToolRegistry
|
|
10
|
+
from jarvis.tools.registry import load_tools
|
|
11
|
+
from jarvis.utils import PrettyOutput, OutputType, get_single_line_input, load_methodology, add_agent, delete_current_agent, get_max_context_length, get_multiline_input, load_embedding_model, load_env_from_file
|
|
11
12
|
import os
|
|
12
13
|
|
|
13
14
|
class Agent:
|
|
14
|
-
|
|
15
|
+
|
|
16
|
+
def __del__(self):
|
|
17
|
+
delete_current_agent()
|
|
18
|
+
|
|
19
|
+
def __init__(self, system_prompt: str, name: str = "Jarvis", is_sub_agent: bool = False, tool_registry: Optional[ToolRegistry] = None):
|
|
15
20
|
"""Initialize Agent with a model, optional tool registry and name
|
|
16
21
|
|
|
17
22
|
Args:
|
|
18
|
-
|
|
19
|
-
tool_registry: Tool registry instance
|
|
23
|
+
system_prompt: System prompt
|
|
20
24
|
name: Agent name, default is "Jarvis"
|
|
21
25
|
is_sub_agent: Whether it is a sub-agent, default is False
|
|
26
|
+
tool_registry: Tool registry instance
|
|
22
27
|
"""
|
|
28
|
+
add_agent(name)
|
|
29
|
+
PrettyOutput.print(f"Welcome to Jarvis, your AI assistant, Initiating...", OutputType.SYSTEM)
|
|
23
30
|
self.model = PlatformRegistry.get_global_platform_registry().get_normal_platform()
|
|
24
|
-
self.tool_registry = ToolRegistry.get_global_tool_registry()
|
|
31
|
+
self.tool_registry = tool_registry if tool_registry else ToolRegistry.get_global_tool_registry()
|
|
25
32
|
self.name = name
|
|
26
33
|
self.is_sub_agent = is_sub_agent
|
|
27
34
|
self.prompt = ""
|
|
28
35
|
self.conversation_length = 0 # Use length counter instead
|
|
29
|
-
|
|
36
|
+
self.system_prompt = system_prompt
|
|
30
37
|
# Load configuration from environment variables
|
|
31
38
|
self.embedding_dimension = 1536 # Default for many embedding models
|
|
32
39
|
self.max_context_length = get_max_context_length()
|
|
@@ -46,10 +53,7 @@ class Agent:
|
|
|
46
53
|
PrettyOutput.print("Successfully loaded embedding model", OutputType.SUCCESS)
|
|
47
54
|
|
|
48
55
|
# Initialize HNSW index (use correct dimension)
|
|
49
|
-
|
|
50
|
-
hnsw_index.hnsw.efConstruction = 40
|
|
51
|
-
hnsw_index.hnsw.efSearch = 16
|
|
52
|
-
self.methodology_index = faiss.IndexIDMap(hnsw_index)
|
|
56
|
+
|
|
53
57
|
|
|
54
58
|
except Exception as e:
|
|
55
59
|
PrettyOutput.print(f"Failed to load embedding model: {str(e)}", OutputType.ERROR)
|
|
@@ -58,6 +62,8 @@ class Agent:
|
|
|
58
62
|
# Initialize methodology related attributes
|
|
59
63
|
self.methodology_data = []
|
|
60
64
|
|
|
65
|
+
PrettyOutput.section(f"Jarvis initialized - With {self.model.name()}", OutputType.SYSTEM)
|
|
66
|
+
|
|
61
67
|
@staticmethod
|
|
62
68
|
def extract_tool_calls(content: str) -> List[Dict]:
|
|
63
69
|
"""Extract tool calls from content, if multiple tool calls are detected, raise an exception, and return the content before the tool call and the tool call"""
|
|
@@ -65,7 +71,16 @@ class Agent:
|
|
|
65
71
|
lines = content.split('\n')
|
|
66
72
|
tool_call_lines = []
|
|
67
73
|
in_tool_call = False
|
|
68
|
-
|
|
74
|
+
|
|
75
|
+
tool_call_help = """Tool Usage Format:
|
|
76
|
+
|
|
77
|
+
<TOOL_CALL>
|
|
78
|
+
name: tool_name
|
|
79
|
+
arguments:
|
|
80
|
+
param1: value1
|
|
81
|
+
param2: value2
|
|
82
|
+
</TOOL_CALL>"""
|
|
83
|
+
|
|
69
84
|
# Process line by line
|
|
70
85
|
for line in lines:
|
|
71
86
|
if '<TOOL_CALL>' in line:
|
|
@@ -87,7 +102,7 @@ class Agent:
|
|
|
87
102
|
}]
|
|
88
103
|
else:
|
|
89
104
|
PrettyOutput.print("Tool call missing necessary fields", OutputType.ERROR)
|
|
90
|
-
raise Exception("Tool call missing necessary fields")
|
|
105
|
+
raise Exception("Tool call missing necessary fields, " + tool_call_help)
|
|
91
106
|
except yaml.YAMLError as e:
|
|
92
107
|
PrettyOutput.print(f"YAML parsing error: {str(e)}", OutputType.ERROR)
|
|
93
108
|
raise Exception(f"YAML parsing error: {str(e)}")
|
|
@@ -117,78 +132,6 @@ class Agent:
|
|
|
117
132
|
sleep_time = 30
|
|
118
133
|
continue
|
|
119
134
|
|
|
120
|
-
def _create_methodology_embedding(self, methodology_text: str) -> np.ndarray:
|
|
121
|
-
"""Create embedding vector for methodology text"""
|
|
122
|
-
try:
|
|
123
|
-
# Truncate long text
|
|
124
|
-
max_length = 512
|
|
125
|
-
text = ' '.join(methodology_text.split()[:max_length])
|
|
126
|
-
|
|
127
|
-
# 使用sentence_transformers模型获取嵌入向量
|
|
128
|
-
embedding = self.embedding_model.encode([text],
|
|
129
|
-
convert_to_tensor=True,
|
|
130
|
-
normalize_embeddings=True)
|
|
131
|
-
vector = np.array(embedding.cpu().numpy(), dtype=np.float32)
|
|
132
|
-
return vector[0] # Return first vector, because we only encoded one text
|
|
133
|
-
except Exception as e:
|
|
134
|
-
PrettyOutput.print(f"Failed to create methodology embedding vector: {str(e)}", OutputType.ERROR)
|
|
135
|
-
return np.zeros(self.embedding_dimension, dtype=np.float32)
|
|
136
|
-
|
|
137
|
-
def _load_methodology(self, user_input: str) -> Dict[str, str]:
|
|
138
|
-
"""Load methodology and build vector index"""
|
|
139
|
-
PrettyOutput.print("Loading methodology...", OutputType.PROGRESS)
|
|
140
|
-
user_jarvis_methodology = os.path.expanduser("~/.jarvis_methodology")
|
|
141
|
-
if not os.path.exists(user_jarvis_methodology):
|
|
142
|
-
return {}
|
|
143
|
-
|
|
144
|
-
try:
|
|
145
|
-
with open(user_jarvis_methodology, "r", encoding="utf-8") as f:
|
|
146
|
-
data = yaml.safe_load(f)
|
|
147
|
-
|
|
148
|
-
# Reset data structure
|
|
149
|
-
self.methodology_data = []
|
|
150
|
-
vectors = []
|
|
151
|
-
ids = []
|
|
152
|
-
|
|
153
|
-
# Create embedding vector for each methodology
|
|
154
|
-
for i, (key, value) in enumerate(data.items()):
|
|
155
|
-
PrettyOutput.print(f"Vectorizing methodology: {key} ...", OutputType.INFO)
|
|
156
|
-
methodology_text = f"{key}\n{value}"
|
|
157
|
-
embedding = self._create_methodology_embedding(methodology_text)
|
|
158
|
-
vectors.append(embedding)
|
|
159
|
-
ids.append(i)
|
|
160
|
-
self.methodology_data.append({"key": key, "value": value})
|
|
161
|
-
|
|
162
|
-
if vectors:
|
|
163
|
-
vectors_array = np.vstack(vectors)
|
|
164
|
-
self.methodology_index.add_with_ids(vectors_array, np.array(ids)) # type: ignore
|
|
165
|
-
query_embedding = self._create_methodology_embedding(user_input)
|
|
166
|
-
k = min(5, len(self.methodology_data))
|
|
167
|
-
PrettyOutput.print(f"Retrieving methodology...", OutputType.INFO)
|
|
168
|
-
distances, indices = self.methodology_index.search(
|
|
169
|
-
query_embedding.reshape(1, -1), k
|
|
170
|
-
) # type: ignore
|
|
171
|
-
|
|
172
|
-
relevant_methodologies = {}
|
|
173
|
-
for dist, idx in zip(distances[0], indices[0]):
|
|
174
|
-
if idx >= 0:
|
|
175
|
-
similarity = 1.0 / (1.0 + float(dist))
|
|
176
|
-
methodology = self.methodology_data[idx]
|
|
177
|
-
PrettyOutput.print(
|
|
178
|
-
f"Methodology '{methodology['key']}' similarity: {similarity:.3f}",
|
|
179
|
-
OutputType.INFO
|
|
180
|
-
)
|
|
181
|
-
if similarity >= 0.5:
|
|
182
|
-
relevant_methodologies[methodology["key"]] = methodology["value"]
|
|
183
|
-
|
|
184
|
-
if relevant_methodologies:
|
|
185
|
-
return relevant_methodologies
|
|
186
|
-
|
|
187
|
-
return {}
|
|
188
|
-
|
|
189
|
-
except Exception as e:
|
|
190
|
-
PrettyOutput.print(f"Error loading methodology: {str(e)}", OutputType.ERROR)
|
|
191
|
-
return {}
|
|
192
135
|
|
|
193
136
|
def _summarize_and_clear_history(self) -> None:
|
|
194
137
|
"""
|
|
@@ -244,7 +187,7 @@ Please continue the task based on the above information.
|
|
|
244
187
|
|
|
245
188
|
# 询问是否生成方法论,带输入验证
|
|
246
189
|
while True:
|
|
247
|
-
user_input =
|
|
190
|
+
user_input = get_single_line_input("Generate methodology for this task? (y/n)").strip().lower()
|
|
248
191
|
if user_input in ['y', 'n', '']:
|
|
249
192
|
break
|
|
250
193
|
PrettyOutput.print("Invalid input, please enter y or n", OutputType.WARNING)
|
|
@@ -307,84 +250,20 @@ Please describe in concise bullet points, highlighting important information.
|
|
|
307
250
|
self.model.upload_files(file_list)
|
|
308
251
|
|
|
309
252
|
# Load methodology
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
if methodology:
|
|
313
|
-
methodology_prompt = f"""This is the standard methodology for handling previous problems, if the current task is similar, you can refer to it:
|
|
314
|
-
{methodology}
|
|
315
|
-
|
|
316
|
-
"""
|
|
317
|
-
tools_prompt = ""
|
|
318
|
-
|
|
319
|
-
# 选择工具
|
|
320
|
-
PrettyOutput.section("Available tools", OutputType.PLANNING)
|
|
321
|
-
tools = self.tool_registry.get_all_tools()
|
|
322
|
-
if tools:
|
|
323
|
-
tools_prompt += "Available tools:\n"
|
|
324
|
-
for tool in tools:
|
|
325
|
-
PrettyOutput.print(f"{tool['name']}: {tool['description']}", OutputType.INFO)
|
|
326
|
-
tools_prompt += f"- Name: {tool['name']}\n"
|
|
327
|
-
tools_prompt += f" Description: {tool['description']}\n"
|
|
328
|
-
tools_prompt += f" Parameters: {tool['parameters']}\n"
|
|
253
|
+
methodology_prompt = load_methodology(user_input)
|
|
254
|
+
tools_prompt = load_tools()
|
|
329
255
|
|
|
330
256
|
# 显示任务开始
|
|
331
257
|
PrettyOutput.section(f"Starting new task: {self.name}", OutputType.PLANNING)
|
|
332
258
|
|
|
333
259
|
self.clear_history()
|
|
334
260
|
|
|
335
|
-
self.model.set_system_message(f"""
|
|
336
|
-
|
|
337
|
-
When users need to execute tasks, you will strictly follow these steps to handle problems:
|
|
338
|
-
1. Problem Restatement: Confirm understanding of the problem
|
|
339
|
-
2. Root Cause Analysis (only if needed for problem analysis tasks)
|
|
340
|
-
3. Set Objectives: Define achievable and verifiable goals
|
|
341
|
-
4. Generate Solutions: Create one or more actionable solutions
|
|
342
|
-
5. Evaluate Solutions: Select the optimal solution from multiple options
|
|
343
|
-
6. Create Action Plan: Based on available tools, create an action plan using PlantUML format for clear execution flow
|
|
344
|
-
7. Execute Action Plan: Execute one step at a time, **use at most one tool** (wait for tool execution results before proceeding)
|
|
345
|
-
8. Monitor and Adjust: If execution results don't match expectations, reflect and adjust the action plan, iterate previous steps
|
|
346
|
-
9. Methodology: If the current task has general applicability and valuable experience is gained, use methodology tools to record it for future similar problems
|
|
347
|
-
10. Task Completion: End the task using task completion command when finished
|
|
348
|
-
|
|
349
|
-
Methodology Template:
|
|
350
|
-
1. Problem Restatement
|
|
351
|
-
2. Optimal Solution
|
|
352
|
-
3. Optimal Solution Steps (exclude failed actions)
|
|
353
|
-
|
|
354
|
-
-------------------------------------------------------------
|
|
261
|
+
self.model.set_system_message(f"""
|
|
262
|
+
{self.system_prompt}
|
|
355
263
|
|
|
356
264
|
{tools_prompt}
|
|
357
265
|
|
|
358
|
-
-------------------------------------------------------------
|
|
359
|
-
|
|
360
|
-
Tool Usage Format:
|
|
361
|
-
|
|
362
|
-
<TOOL_CALL>
|
|
363
|
-
name: tool_name
|
|
364
|
-
arguments:
|
|
365
|
-
param1: value1
|
|
366
|
-
param2: value2
|
|
367
|
-
</TOOL_CALL>
|
|
368
|
-
|
|
369
|
-
-------------------------------------------------------------
|
|
370
|
-
|
|
371
|
-
Strict Rules:
|
|
372
|
-
- Execute only one tool at a time
|
|
373
|
-
- Tool execution must strictly follow the tool usage format
|
|
374
|
-
- Wait for user to provide execution results
|
|
375
|
-
- Don't assume or imagine results
|
|
376
|
-
- Don't create fake dialogues
|
|
377
|
-
- If current information is insufficient, you may ask the user
|
|
378
|
-
- Not all problem-solving steps are mandatory, skip as appropriate
|
|
379
|
-
- Ask user before executing tools that might damage system or user's codebase
|
|
380
|
-
- Request user guidance when multiple iterations show no progress
|
|
381
|
-
- If yaml string contains colons, wrap the entire string in quotes to avoid yaml parsing errors
|
|
382
|
-
- Use | syntax for multi-line strings in yaml
|
|
383
|
-
|
|
384
266
|
{methodology_prompt}
|
|
385
|
-
|
|
386
|
-
-------------------------------------------------------------
|
|
387
|
-
|
|
388
267
|
""")
|
|
389
268
|
self.prompt = f"{user_input}"
|
|
390
269
|
|
|
@@ -446,3 +325,166 @@ Strict Rules:
|
|
|
446
325
|
|
|
447
326
|
|
|
448
327
|
|
|
328
|
+
|
|
329
|
+
def load_tasks() -> dict:
|
|
330
|
+
"""Load tasks from .jarvis files in user home and current directory."""
|
|
331
|
+
tasks = {}
|
|
332
|
+
|
|
333
|
+
# Check .jarvis in user directory
|
|
334
|
+
user_jarvis = os.path.expanduser("~/.jarvis")
|
|
335
|
+
if os.path.exists(user_jarvis):
|
|
336
|
+
try:
|
|
337
|
+
with open(user_jarvis, "r", encoding="utf-8") as f:
|
|
338
|
+
user_tasks = yaml.safe_load(f)
|
|
339
|
+
|
|
340
|
+
if isinstance(user_tasks, dict):
|
|
341
|
+
# Validate and add user directory tasks
|
|
342
|
+
for name, desc in user_tasks.items():
|
|
343
|
+
if desc: # Ensure description is not empty
|
|
344
|
+
tasks[str(name)] = str(desc)
|
|
345
|
+
else:
|
|
346
|
+
PrettyOutput.print("Warning: ~/.jarvis file should contain a dictionary of task_name: task_description", OutputType.ERROR)
|
|
347
|
+
except Exception as e:
|
|
348
|
+
PrettyOutput.print(f"Error loading ~/.jarvis file: {str(e)}", OutputType.ERROR)
|
|
349
|
+
|
|
350
|
+
# Check .jarvis in current directory
|
|
351
|
+
if os.path.exists(".jarvis"):
|
|
352
|
+
try:
|
|
353
|
+
with open(".jarvis", "r", encoding="utf-8") as f:
|
|
354
|
+
local_tasks = yaml.safe_load(f)
|
|
355
|
+
|
|
356
|
+
if isinstance(local_tasks, dict):
|
|
357
|
+
# Validate and add current directory tasks, overwrite user directory tasks if there is a name conflict
|
|
358
|
+
for name, desc in local_tasks.items():
|
|
359
|
+
if desc: # Ensure description is not empty
|
|
360
|
+
tasks[str(name)] = str(desc)
|
|
361
|
+
else:
|
|
362
|
+
PrettyOutput.print("Warning: .jarvis file should contain a dictionary of task_name: task_description", OutputType.ERROR)
|
|
363
|
+
except Exception as e:
|
|
364
|
+
PrettyOutput.print(f"Error loading .jarvis file: {str(e)}", OutputType.ERROR)
|
|
365
|
+
|
|
366
|
+
# Read methodology
|
|
367
|
+
method_path = os.path.expanduser("~/.jarvis_methodology")
|
|
368
|
+
if os.path.exists(method_path):
|
|
369
|
+
with open(method_path, "r", encoding="utf-8") as f:
|
|
370
|
+
methodology = yaml.safe_load(f)
|
|
371
|
+
if isinstance(methodology, dict):
|
|
372
|
+
for name, desc in methodology.items():
|
|
373
|
+
tasks[f"Run Methodology: {str(name)}\n {str(desc)}" ] = str(desc)
|
|
374
|
+
|
|
375
|
+
return tasks
|
|
376
|
+
|
|
377
|
+
def select_task(tasks: dict) -> str:
|
|
378
|
+
"""Let user select a task from the list or skip. Returns task description if selected."""
|
|
379
|
+
if not tasks:
|
|
380
|
+
return ""
|
|
381
|
+
|
|
382
|
+
# Convert tasks to list for ordered display
|
|
383
|
+
task_names = list(tasks.keys())
|
|
384
|
+
|
|
385
|
+
PrettyOutput.print("\nAvailable tasks:", OutputType.INFO)
|
|
386
|
+
for i, name in enumerate(task_names, 1):
|
|
387
|
+
PrettyOutput.print(f"[{i}] {name}", OutputType.INFO)
|
|
388
|
+
PrettyOutput.print("[0] Skip predefined tasks", OutputType.INFO)
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
while True:
|
|
392
|
+
try:
|
|
393
|
+
choice = prompt(
|
|
394
|
+
"\nPlease select a task number (0 to skip): ",
|
|
395
|
+
).strip()
|
|
396
|
+
|
|
397
|
+
if not choice:
|
|
398
|
+
return ""
|
|
399
|
+
|
|
400
|
+
choice = int(choice)
|
|
401
|
+
if choice == 0:
|
|
402
|
+
return ""
|
|
403
|
+
elif 1 <= choice <= len(task_names):
|
|
404
|
+
selected_name = task_names[choice - 1]
|
|
405
|
+
return tasks[selected_name] # Return the task description
|
|
406
|
+
else:
|
|
407
|
+
PrettyOutput.print("Invalid choice. Please select a number from the list.", OutputType.ERROR)
|
|
408
|
+
|
|
409
|
+
except KeyboardInterrupt:
|
|
410
|
+
return "" # Return empty on Ctrl+C
|
|
411
|
+
except EOFError:
|
|
412
|
+
return "" # Return empty on Ctrl+D
|
|
413
|
+
except Exception as e:
|
|
414
|
+
PrettyOutput.print(f"Failed to select task: {str(e)}", OutputType.ERROR)
|
|
415
|
+
continue
|
|
416
|
+
|
|
417
|
+
origin_agent_system_prompt = """You are Jarvis, an AI assistant with powerful problem-solving capabilities.
|
|
418
|
+
|
|
419
|
+
When users need to execute tasks, you will strictly follow these steps to handle problems:
|
|
420
|
+
1. Problem Restatement: Confirm understanding of the problem
|
|
421
|
+
2. Root Cause Analysis (only if needed for problem analysis tasks)
|
|
422
|
+
3. Set Objectives: Define achievable and verifiable goals
|
|
423
|
+
4. Generate Solutions: Create one or more actionable solutions
|
|
424
|
+
5. Evaluate Solutions: Select the optimal solution from multiple options
|
|
425
|
+
6. Create Action Plan: Based on available tools, create an action plan using PlantUML format for clear execution flow
|
|
426
|
+
7. Execute Action Plan: Execute one step at a time, **use at most one tool** (wait for tool execution results before proceeding)
|
|
427
|
+
8. Monitor and Adjust: If execution results don't match expectations, reflect and adjust the action plan, iterate previous steps
|
|
428
|
+
9. Methodology: If the current task has general applicability and valuable experience is gained, use methodology tools to record it for future similar problems
|
|
429
|
+
10. Task Completion: End the task using task completion command when finished
|
|
430
|
+
|
|
431
|
+
Methodology Template:
|
|
432
|
+
1. Problem Restatement
|
|
433
|
+
2. Optimal Solution
|
|
434
|
+
3. Optimal Solution Steps (exclude failed actions)
|
|
435
|
+
|
|
436
|
+
Strict Rules:
|
|
437
|
+
- Execute only one tool at a time
|
|
438
|
+
- Tool execution must strictly follow the tool usage format
|
|
439
|
+
- Wait for user to provide execution results
|
|
440
|
+
- Don't assume or imagine results
|
|
441
|
+
- Don't create fake dialogues
|
|
442
|
+
- If current information is insufficient, you may ask the user
|
|
443
|
+
- Not all problem-solving steps are mandatory, skip as appropriate
|
|
444
|
+
- Ask user before executing tools that might damage system or user's codebase
|
|
445
|
+
- Request user guidance when multiple iterations show no progress
|
|
446
|
+
- If yaml string contains colons, wrap the entire string in quotes to avoid yaml parsing errors
|
|
447
|
+
- Use | syntax for multi-line strings in yaml
|
|
448
|
+
- If you can start executing the task, please start directly without asking the user if you can begin.
|
|
449
|
+
|
|
450
|
+
-------------------------------------------------------------"""
|
|
451
|
+
|
|
452
|
+
def main():
|
|
453
|
+
"""Jarvis main entry point"""
|
|
454
|
+
# Add argument parser
|
|
455
|
+
load_env_from_file()
|
|
456
|
+
parser = argparse.ArgumentParser(description='Jarvis AI assistant')
|
|
457
|
+
parser.add_argument('-f', '--files', nargs='*', help='List of files to process')
|
|
458
|
+
args = parser.parse_args()
|
|
459
|
+
|
|
460
|
+
try:
|
|
461
|
+
# 获取全局模型实例
|
|
462
|
+
agent = Agent(system_prompt=origin_agent_system_prompt)
|
|
463
|
+
|
|
464
|
+
# 加载预定义任务
|
|
465
|
+
tasks = load_tasks()
|
|
466
|
+
if tasks:
|
|
467
|
+
selected_task = select_task(tasks)
|
|
468
|
+
if selected_task:
|
|
469
|
+
PrettyOutput.print(f"\nExecute task: {selected_task}", OutputType.INFO)
|
|
470
|
+
agent.run(selected_task, args.files)
|
|
471
|
+
return 0
|
|
472
|
+
|
|
473
|
+
# 如果没有选择预定义任务,进入交互模式
|
|
474
|
+
while True:
|
|
475
|
+
try:
|
|
476
|
+
user_input = get_multiline_input("Please enter your task (input empty line to exit):")
|
|
477
|
+
if not user_input or user_input == "__interrupt__":
|
|
478
|
+
break
|
|
479
|
+
agent.run(user_input, args.files)
|
|
480
|
+
except Exception as e:
|
|
481
|
+
PrettyOutput.print(f"Error: {str(e)}", OutputType.ERROR)
|
|
482
|
+
|
|
483
|
+
except Exception as e:
|
|
484
|
+
PrettyOutput.print(f"Initialization error: {str(e)}", OutputType.ERROR)
|
|
485
|
+
return 1
|
|
486
|
+
|
|
487
|
+
return 0
|
|
488
|
+
|
|
489
|
+
if __name__ == "__main__":
|
|
490
|
+
exit(main())
|