jarvis-ai-assistant 0.1.98__tar.gz → 0.1.100__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.98/src/jarvis_ai_assistant.egg-info → jarvis_ai_assistant-0.1.100}/PKG-INFO +9 -8
- {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.100}/README.md +8 -7
- {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.100}/pyproject.toml +3 -2
- {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.100}/setup.py +3 -2
- {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.100}/src/jarvis/__init__.py +1 -1
- {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.100}/src/jarvis/agent.py +199 -157
- jarvis_ai_assistant-0.1.100/src/jarvis/jarvis_code_agent/main.py +202 -0
- jarvis_ai_assistant-0.1.100/src/jarvis/jarvis_codebase/main.py +875 -0
- jarvis_ai_assistant-0.1.100/src/jarvis/jarvis_coder/file_select.py +209 -0
- jarvis_ai_assistant-0.1.100/src/jarvis/jarvis_coder/git_utils.py +123 -0
- jarvis_ai_assistant-0.1.100/src/jarvis/jarvis_coder/main.py +241 -0
- jarvis_ai_assistant-0.1.100/src/jarvis/jarvis_coder/patch_handler.py +340 -0
- {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.100}/src/jarvis/jarvis_coder/plan_generator.py +49 -7
- {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.100}/src/jarvis/jarvis_platform/main.py +2 -2
- {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.100}/src/jarvis/jarvis_rag/main.py +11 -11
- jarvis_ai_assistant-0.1.100/src/jarvis/jarvis_smart_shell/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.100}/src/jarvis/jarvis_smart_shell/main.py +5 -5
- {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.100}/src/jarvis/models/base.py +6 -1
- {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.100}/src/jarvis/models/kimi.py +2 -2
- {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.100}/src/jarvis/models/ollama.py +2 -2
- {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.100}/src/jarvis/models/openai.py +1 -1
- {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.100}/src/jarvis/models/registry.py +38 -18
- {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.100}/src/jarvis/tools/ask_user.py +12 -9
- {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.100}/src/jarvis/tools/chdir.py +9 -5
- jarvis_ai_assistant-0.1.100/src/jarvis/tools/create_code_sub_agent.py +56 -0
- jarvis_ai_assistant-0.1.98/src/jarvis/tools/sub_agent.py → jarvis_ai_assistant-0.1.100/src/jarvis/tools/create_sub_agent.py +6 -2
- jarvis_ai_assistant-0.1.100/src/jarvis/tools/execute_code_modification.py +70 -0
- jarvis_ai_assistant-0.1.98/src/jarvis/tools/shell.py → jarvis_ai_assistant-0.1.100/src/jarvis/tools/execute_shell.py +2 -2
- jarvis_ai_assistant-0.1.98/src/jarvis/tools/file_ops.py → jarvis_ai_assistant-0.1.100/src/jarvis/tools/file_operation.py +19 -15
- jarvis_ai_assistant-0.1.100/src/jarvis/tools/find_files.py +119 -0
- jarvis_ai_assistant-0.1.98/src/jarvis/tools/generator.py → jarvis_ai_assistant-0.1.100/src/jarvis/tools/generate_tool.py +27 -25
- {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.100}/src/jarvis/tools/methodology.py +32 -26
- {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.100}/src/jarvis/tools/rag.py +37 -33
- jarvis_ai_assistant-0.1.98/src/jarvis/tools/webpage.py → jarvis_ai_assistant-0.1.100/src/jarvis/tools/read_webpage.py +4 -2
- {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.100}/src/jarvis/tools/registry.py +94 -48
- {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.100}/src/jarvis/tools/search.py +19 -16
- jarvis_ai_assistant-0.1.100/src/jarvis/tools/select_code_files.py +61 -0
- {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.100}/src/jarvis/tools/thinker.py +7 -5
- {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.100}/src/jarvis/utils.py +155 -32
- {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.100/src/jarvis_ai_assistant.egg-info}/PKG-INFO +9 -8
- {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.100}/src/jarvis_ai_assistant.egg-info/SOURCES.txt +12 -8
- {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.100}/src/jarvis_ai_assistant.egg-info/entry_points.txt +2 -1
- jarvis_ai_assistant-0.1.98/src/jarvis/jarvis_codebase/main.py +0 -747
- jarvis_ai_assistant-0.1.98/src/jarvis/jarvis_coder/git_utils.py +0 -61
- jarvis_ai_assistant-0.1.98/src/jarvis/jarvis_coder/main.py +0 -625
- jarvis_ai_assistant-0.1.98/src/jarvis/jarvis_coder/patch_handler.py +0 -192
- jarvis_ai_assistant-0.1.98/src/jarvis/main.py +0 -155
- jarvis_ai_assistant-0.1.98/src/jarvis/tools/codebase_qa.py +0 -74
- jarvis_ai_assistant-0.1.98/src/jarvis/tools/coder.py +0 -69
- {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.100}/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.100}/MANIFEST.in +0 -0
- {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.100}/setup.cfg +0 -0
- {jarvis_ai_assistant-0.1.98/src/jarvis/jarvis_codebase → jarvis_ai_assistant-0.1.100/src/jarvis/jarvis_code_agent}/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.98/src/jarvis/jarvis_coder → jarvis_ai_assistant-0.1.100/src/jarvis/jarvis_codebase}/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.98/src/jarvis/jarvis_platform → jarvis_ai_assistant-0.1.100/src/jarvis/jarvis_coder}/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.98/src/jarvis/jarvis_rag → jarvis_ai_assistant-0.1.100/src/jarvis/jarvis_platform}/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.98/src/jarvis/jarvis_smart_shell → jarvis_ai_assistant-0.1.100/src/jarvis/jarvis_rag}/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.100}/src/jarvis/models/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.100}/src/jarvis/models/ai8.py +0 -0
- {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.100}/src/jarvis/models/oyi.py +0 -0
- {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.100}/src/jarvis/tools/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.100}/src/jarvis/tools/base.py +0 -0
- {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.100}/src/jarvis_ai_assistant.egg-info/dependency_links.txt +0 -0
- {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.100}/src/jarvis_ai_assistant.egg-info/requires.txt +0 -0
- {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.100}/src/jarvis_ai_assistant.egg-info/top_level.txt +0 -0
{jarvis_ai_assistant-0.1.98/src/jarvis_ai_assistant.egg-info → jarvis_ai_assistant-0.1.100}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: jarvis-ai-assistant
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.100
|
|
4
4
|
Summary: Jarvis: An AI assistant that uses tools to interact with the system
|
|
5
5
|
Home-page: https://github.com/skyfireitdiy/Jarvis
|
|
6
6
|
Author: skyfire
|
|
@@ -125,7 +125,7 @@ pip install jarvis-ai-assistant
|
|
|
125
125
|
|
|
126
126
|
## 🔧 Configuration
|
|
127
127
|
|
|
128
|
-
Jarvis supports configuration through environment variables that can be set in the `~/.
|
|
128
|
+
Jarvis supports configuration through environment variables that can be set in the `~/.jarvis/env` file:
|
|
129
129
|
|
|
130
130
|
| Environment Variable | Description | Default Value | Required |
|
|
131
131
|
|---------|------|--------|------|
|
|
@@ -204,7 +204,7 @@ jarvis-search "your query" --max 3
|
|
|
204
204
|
|
|
205
205
|
### Tool Locations
|
|
206
206
|
- Built-in tools: `src/jarvis/tools/`
|
|
207
|
-
- User tools: `~/.
|
|
207
|
+
- User tools: `~/.jarvis/tools/`
|
|
208
208
|
|
|
209
209
|
|
|
210
210
|
### Key Features
|
|
@@ -241,7 +241,7 @@ jarvis-search "your query" --max 3
|
|
|
241
241
|
|
|
242
242
|
### Adding New Tools
|
|
243
243
|
|
|
244
|
-
Create a new Python file in `~/.
|
|
244
|
+
Create a new Python file in `~/.jarvis/tools/` or `src/jarvis/tools/`:
|
|
245
245
|
|
|
246
246
|
```python
|
|
247
247
|
from typing import Dict, Any
|
|
@@ -273,7 +273,6 @@ class CustomTool:
|
|
|
273
273
|
"success": bool,
|
|
274
274
|
"stdout": str, # On success
|
|
275
275
|
"stderr": str, # Optional error details
|
|
276
|
-
"error": str # On failure
|
|
277
276
|
}
|
|
278
277
|
"""
|
|
279
278
|
try:
|
|
@@ -281,18 +280,20 @@ class CustomTool:
|
|
|
281
280
|
result = "Tool execution result"
|
|
282
281
|
return {
|
|
283
282
|
"success": True,
|
|
284
|
-
"stdout": result
|
|
283
|
+
"stdout": result,
|
|
284
|
+
"stderr": ""
|
|
285
285
|
}
|
|
286
286
|
except Exception as e:
|
|
287
287
|
return {
|
|
288
288
|
"success": False,
|
|
289
|
-
"
|
|
289
|
+
"stdout": "",
|
|
290
|
+
"stderr": str(e)
|
|
290
291
|
}
|
|
291
292
|
```
|
|
292
293
|
|
|
293
294
|
### Adding New Models
|
|
294
295
|
|
|
295
|
-
Create a new Python file in `~/.
|
|
296
|
+
Create a new Python file in `~/.jarvis/models/`:
|
|
296
297
|
|
|
297
298
|
```python
|
|
298
299
|
from typing import Dict, List
|
|
@@ -59,7 +59,7 @@ pip install jarvis-ai-assistant
|
|
|
59
59
|
|
|
60
60
|
## 🔧 Configuration
|
|
61
61
|
|
|
62
|
-
Jarvis supports configuration through environment variables that can be set in the `~/.
|
|
62
|
+
Jarvis supports configuration through environment variables that can be set in the `~/.jarvis/env` file:
|
|
63
63
|
|
|
64
64
|
| Environment Variable | Description | Default Value | Required |
|
|
65
65
|
|---------|------|--------|------|
|
|
@@ -138,7 +138,7 @@ jarvis-search "your query" --max 3
|
|
|
138
138
|
|
|
139
139
|
### Tool Locations
|
|
140
140
|
- Built-in tools: `src/jarvis/tools/`
|
|
141
|
-
- User tools: `~/.
|
|
141
|
+
- User tools: `~/.jarvis/tools/`
|
|
142
142
|
|
|
143
143
|
|
|
144
144
|
### Key Features
|
|
@@ -175,7 +175,7 @@ jarvis-search "your query" --max 3
|
|
|
175
175
|
|
|
176
176
|
### Adding New Tools
|
|
177
177
|
|
|
178
|
-
Create a new Python file in `~/.
|
|
178
|
+
Create a new Python file in `~/.jarvis/tools/` or `src/jarvis/tools/`:
|
|
179
179
|
|
|
180
180
|
```python
|
|
181
181
|
from typing import Dict, Any
|
|
@@ -207,7 +207,6 @@ class CustomTool:
|
|
|
207
207
|
"success": bool,
|
|
208
208
|
"stdout": str, # On success
|
|
209
209
|
"stderr": str, # Optional error details
|
|
210
|
-
"error": str # On failure
|
|
211
210
|
}
|
|
212
211
|
"""
|
|
213
212
|
try:
|
|
@@ -215,18 +214,20 @@ class CustomTool:
|
|
|
215
214
|
result = "Tool execution result"
|
|
216
215
|
return {
|
|
217
216
|
"success": True,
|
|
218
|
-
"stdout": result
|
|
217
|
+
"stdout": result,
|
|
218
|
+
"stderr": ""
|
|
219
219
|
}
|
|
220
220
|
except Exception as e:
|
|
221
221
|
return {
|
|
222
222
|
"success": False,
|
|
223
|
-
"
|
|
223
|
+
"stdout": "",
|
|
224
|
+
"stderr": str(e)
|
|
224
225
|
}
|
|
225
226
|
```
|
|
226
227
|
|
|
227
228
|
### Adding New Models
|
|
228
229
|
|
|
229
|
-
Create a new Python file in `~/.
|
|
230
|
+
Create a new Python file in `~/.jarvis/models/`:
|
|
230
231
|
|
|
231
232
|
```python
|
|
232
233
|
from typing import Dict, List
|
|
@@ -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.100"
|
|
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.100",
|
|
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, init_env
|
|
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/pre-command in user directory
|
|
334
|
+
user_jarvis = os.path.expanduser("~/.jarvis/pre-command")
|
|
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/pre-command file should contain a dictionary of task_name: task_description", OutputType.ERROR)
|
|
347
|
+
except Exception as e:
|
|
348
|
+
PrettyOutput.print(f"Error loading ~/.jarvis/pre-command file: {str(e)}", OutputType.ERROR)
|
|
349
|
+
|
|
350
|
+
# Check .jarvis/pre-command in current directory
|
|
351
|
+
if os.path.exists(".jarvis/pre-command"):
|
|
352
|
+
try:
|
|
353
|
+
with open(".jarvis/pre-command", "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/pre-command file should contain a dictionary of task_name: task_description", OutputType.ERROR)
|
|
363
|
+
except Exception as e:
|
|
364
|
+
PrettyOutput.print(f"Error loading .jarvis/pre-command 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
|
+
init_env()
|
|
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())
|