jarvis-ai-assistant 0.1.98__py3-none-any.whl → 0.1.100__py3-none-any.whl
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/__init__.py +1 -1
- jarvis/agent.py +199 -157
- jarvis/jarvis_code_agent/__init__.py +0 -0
- jarvis/jarvis_code_agent/main.py +202 -0
- jarvis/jarvis_codebase/main.py +415 -287
- jarvis/jarvis_coder/file_select.py +209 -0
- jarvis/jarvis_coder/git_utils.py +64 -2
- jarvis/jarvis_coder/main.py +13 -397
- jarvis/jarvis_coder/patch_handler.py +229 -81
- jarvis/jarvis_coder/plan_generator.py +49 -7
- jarvis/jarvis_platform/main.py +2 -2
- jarvis/jarvis_rag/main.py +11 -11
- jarvis/jarvis_smart_shell/main.py +5 -5
- jarvis/models/base.py +6 -1
- jarvis/models/kimi.py +2 -2
- jarvis/models/ollama.py +2 -2
- jarvis/models/openai.py +1 -1
- jarvis/models/registry.py +38 -18
- jarvis/tools/ask_user.py +12 -9
- jarvis/tools/chdir.py +9 -5
- jarvis/tools/create_code_sub_agent.py +56 -0
- jarvis/tools/{sub_agent.py → create_sub_agent.py} +6 -2
- jarvis/tools/execute_code_modification.py +70 -0
- jarvis/tools/{shell.py → execute_shell.py} +2 -2
- jarvis/tools/{file_ops.py → file_operation.py} +19 -15
- jarvis/tools/find_files.py +119 -0
- jarvis/tools/{generator.py → generate_tool.py} +27 -25
- jarvis/tools/methodology.py +32 -26
- jarvis/tools/rag.py +37 -33
- jarvis/tools/{webpage.py → read_webpage.py} +4 -2
- jarvis/tools/registry.py +94 -48
- jarvis/tools/search.py +19 -16
- jarvis/tools/select_code_files.py +61 -0
- jarvis/tools/thinker.py +7 -5
- jarvis/utils.py +155 -32
- {jarvis_ai_assistant-0.1.98.dist-info → jarvis_ai_assistant-0.1.100.dist-info}/METADATA +9 -8
- jarvis_ai_assistant-0.1.100.dist-info/RECORD +51 -0
- {jarvis_ai_assistant-0.1.98.dist-info → jarvis_ai_assistant-0.1.100.dist-info}/entry_points.txt +2 -1
- jarvis/main.py +0 -155
- jarvis/tools/codebase_qa.py +0 -74
- jarvis/tools/coder.py +0 -69
- jarvis_ai_assistant-0.1.98.dist-info/RECORD +0 -47
- {jarvis_ai_assistant-0.1.98.dist-info → jarvis_ai_assistant-0.1.100.dist-info}/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.98.dist-info → jarvis_ai_assistant-0.1.100.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.1.98.dist-info → jarvis_ai_assistant-0.1.100.dist-info}/top_level.txt +0 -0
jarvis/utils.py
CHANGED
|
@@ -6,20 +6,35 @@ import time
|
|
|
6
6
|
import os
|
|
7
7
|
from enum import Enum
|
|
8
8
|
from datetime import datetime
|
|
9
|
+
from typing import Any, Dict
|
|
9
10
|
import colorama
|
|
10
11
|
from colorama import Fore, Style as ColoramaStyle
|
|
12
|
+
import numpy as np
|
|
11
13
|
from prompt_toolkit import PromptSession
|
|
12
14
|
from prompt_toolkit.styles import Style as PromptStyle
|
|
13
15
|
from prompt_toolkit.formatted_text import FormattedText
|
|
14
16
|
from sentence_transformers import SentenceTransformer
|
|
15
17
|
from transformers import AutoModelForSequenceClassification, AutoTokenizer
|
|
16
18
|
import torch
|
|
19
|
+
import yaml
|
|
20
|
+
import faiss
|
|
17
21
|
|
|
18
22
|
# 初始化colorama
|
|
19
23
|
colorama.init()
|
|
20
24
|
|
|
21
|
-
os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"
|
|
22
25
|
os.environ["TOKENIZERS_PARALLELISM"] = "false"
|
|
26
|
+
os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"
|
|
27
|
+
|
|
28
|
+
current_agent = []
|
|
29
|
+
|
|
30
|
+
def add_agent(agent_name: str):
|
|
31
|
+
current_agent.append(agent_name)
|
|
32
|
+
|
|
33
|
+
def get_current_agent():
|
|
34
|
+
return current_agent[-1] if current_agent else "No Agent"
|
|
35
|
+
|
|
36
|
+
def delete_current_agent():
|
|
37
|
+
current_agent.pop()
|
|
23
38
|
|
|
24
39
|
class OutputType(Enum):
|
|
25
40
|
SYSTEM = "system" # AI assistant message
|
|
@@ -94,7 +109,7 @@ class PrettyOutput:
|
|
|
94
109
|
prefix = PrettyOutput.PREFIXES.get(output_type, "")
|
|
95
110
|
|
|
96
111
|
# 添加时间戳 - 使用白色
|
|
97
|
-
time_str = f"{Fore.WHITE}[{datetime.now().strftime('%H:%M:%S')}]{ColoramaStyle.RESET_ALL} " if timestamp else ""
|
|
112
|
+
time_str = f"{Fore.BLUE}[{get_current_agent()}]{ColoramaStyle.RESET_ALL}{Fore.WHITE}[{datetime.now().strftime('%H:%M:%S')}]{ColoramaStyle.RESET_ALL} " if timestamp else ""
|
|
98
113
|
|
|
99
114
|
# 格式化输出
|
|
100
115
|
formatted_text = f"{time_str}{color}{icon} {prefix}: {text}{ColoramaStyle.RESET_ALL}"
|
|
@@ -112,10 +127,10 @@ class PrettyOutput:
|
|
|
112
127
|
@staticmethod
|
|
113
128
|
def section(title: str, output_type: OutputType = OutputType.INFO):
|
|
114
129
|
"""Print paragraph title with separator"""
|
|
115
|
-
width =
|
|
130
|
+
width = 100
|
|
116
131
|
color = PrettyOutput.COLORS.get(output_type, "")
|
|
117
132
|
print(f"\n{color}" + "=" * width + f"{ColoramaStyle.RESET_ALL}")
|
|
118
|
-
PrettyOutput.print(title.center(width -
|
|
133
|
+
PrettyOutput.print(title.center(width - 25), output_type, timestamp=False)
|
|
119
134
|
print(f"{color}" + "=" * width + f"{ColoramaStyle.RESET_ALL}\n")
|
|
120
135
|
|
|
121
136
|
@staticmethod
|
|
@@ -131,6 +146,14 @@ class PrettyOutput:
|
|
|
131
146
|
sys.stdout.write("\n")
|
|
132
147
|
sys.stdout.flush()
|
|
133
148
|
|
|
149
|
+
def get_single_line_input(tip: str) -> str:
|
|
150
|
+
"""Get single line input, support direction key, history function, etc."""
|
|
151
|
+
session = PromptSession(history=None)
|
|
152
|
+
style = PromptStyle.from_dict({
|
|
153
|
+
'prompt': 'ansicyan',
|
|
154
|
+
})
|
|
155
|
+
return session.prompt(f"{tip}", style=style)
|
|
156
|
+
|
|
134
157
|
def get_multiline_input(tip: str) -> str:
|
|
135
158
|
"""Get multi-line input, support direction key, history function, etc."""
|
|
136
159
|
print(f"{Fore.GREEN}{tip}{ColoramaStyle.RESET_ALL}")
|
|
@@ -171,10 +194,15 @@ def get_multiline_input(tip: str) -> str:
|
|
|
171
194
|
|
|
172
195
|
return "\n".join(lines)
|
|
173
196
|
|
|
174
|
-
def
|
|
175
|
-
"""Load environment variables from ~/.
|
|
176
|
-
|
|
197
|
+
def init_env():
|
|
198
|
+
"""Load environment variables from ~/.jarvis/env"""
|
|
199
|
+
jarvis_dir = Path.home() / ".jarvis"
|
|
200
|
+
env_file = jarvis_dir / "env"
|
|
177
201
|
|
|
202
|
+
# Check if ~/.jarvis directory exists
|
|
203
|
+
if not jarvis_dir.exists():
|
|
204
|
+
jarvis_dir.mkdir(parents=True)
|
|
205
|
+
|
|
178
206
|
if env_file.exists():
|
|
179
207
|
try:
|
|
180
208
|
with open(env_file, "r", encoding="utf-8") as f:
|
|
@@ -187,7 +215,7 @@ def load_env_from_file():
|
|
|
187
215
|
except ValueError:
|
|
188
216
|
continue
|
|
189
217
|
except Exception as e:
|
|
190
|
-
PrettyOutput.print(f"Warning: Failed to read
|
|
218
|
+
PrettyOutput.print(f"Warning: Failed to read {env_file}: {e}", OutputType.WARNING)
|
|
191
219
|
|
|
192
220
|
|
|
193
221
|
def while_success(func, sleep_time: float = 0.1):
|
|
@@ -217,59 +245,64 @@ def find_git_root(dir="."):
|
|
|
217
245
|
return ret
|
|
218
246
|
|
|
219
247
|
def load_embedding_model():
|
|
220
|
-
model_name = "BAAI/bge-
|
|
221
|
-
|
|
248
|
+
model_name = "BAAI/bge-m3"
|
|
249
|
+
cache_dir = os.path.expanduser("~/.cache/huggingface/hub")
|
|
250
|
+
|
|
251
|
+
|
|
222
252
|
try:
|
|
223
|
-
#
|
|
253
|
+
# Load model
|
|
224
254
|
embedding_model = SentenceTransformer(
|
|
225
255
|
model_name,
|
|
226
|
-
cache_folder=
|
|
256
|
+
cache_folder=cache_dir,
|
|
227
257
|
local_files_only=True
|
|
228
258
|
)
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
#
|
|
259
|
+
except Exception as e:
|
|
260
|
+
PrettyOutput.print(f"Failed to load embedding model: {str(e)}", OutputType.ERROR)
|
|
261
|
+
os.system(f'huggingface-cli download --repo-type model --local-dir {cache_dir} {model_name}')
|
|
262
|
+
# Load model
|
|
233
263
|
embedding_model = SentenceTransformer(
|
|
234
264
|
model_name,
|
|
235
|
-
cache_folder=
|
|
265
|
+
cache_folder=cache_dir,
|
|
266
|
+
local_files_only=True
|
|
236
267
|
)
|
|
237
|
-
PrettyOutput.print("Successfully downloaded and loaded model", OutputType.SUCCESS)
|
|
238
268
|
|
|
239
269
|
return embedding_model
|
|
240
270
|
|
|
241
271
|
def load_rerank_model():
|
|
242
272
|
"""Load reranking model"""
|
|
243
273
|
model_name = "BAAI/bge-reranker-v2-m3"
|
|
274
|
+
cache_dir = os.path.expanduser("~/.cache/huggingface/hub")
|
|
275
|
+
|
|
244
276
|
PrettyOutput.print(f"Loading reranking model: {model_name}...", OutputType.INFO)
|
|
245
277
|
|
|
246
278
|
try:
|
|
247
|
-
#
|
|
279
|
+
# Load model and tokenizer
|
|
248
280
|
tokenizer = AutoTokenizer.from_pretrained(
|
|
249
281
|
model_name,
|
|
250
|
-
|
|
251
|
-
|
|
282
|
+
cache_dir=cache_dir,
|
|
283
|
+
local_files_only=True
|
|
252
284
|
)
|
|
253
285
|
model = AutoModelForSequenceClassification.from_pretrained(
|
|
254
286
|
model_name,
|
|
255
|
-
|
|
256
|
-
|
|
287
|
+
cache_dir=cache_dir,
|
|
288
|
+
local_files_only=True
|
|
257
289
|
)
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
#
|
|
290
|
+
except Exception as e:
|
|
291
|
+
PrettyOutput.print(f"Failed to load reranking model: {str(e)}", OutputType.ERROR)
|
|
292
|
+
os.system(f'huggingface-cli download --repo-type model --local-dir {cache_dir} {model_name}')
|
|
293
|
+
# Load model and tokenizer
|
|
262
294
|
tokenizer = AutoTokenizer.from_pretrained(
|
|
263
295
|
model_name,
|
|
264
|
-
cache_dir=
|
|
296
|
+
cache_dir=cache_dir,
|
|
297
|
+
local_files_only=True
|
|
265
298
|
)
|
|
266
299
|
model = AutoModelForSequenceClassification.from_pretrained(
|
|
267
300
|
model_name,
|
|
268
|
-
cache_dir=
|
|
301
|
+
cache_dir=cache_dir,
|
|
302
|
+
local_files_only=True
|
|
269
303
|
)
|
|
270
|
-
PrettyOutput.print("Successfully downloaded and loaded model", OutputType.SUCCESS)
|
|
271
304
|
|
|
272
|
-
#
|
|
305
|
+
# Use GPU if available
|
|
273
306
|
if torch.cuda.is_available():
|
|
274
307
|
model = model.cuda()
|
|
275
308
|
model.eval()
|
|
@@ -303,4 +336,94 @@ def get_thread_count():
|
|
|
303
336
|
return int(os.getenv('JARVIS_THREAD_COUNT', '1'))
|
|
304
337
|
|
|
305
338
|
def get_file_md5(filepath: str)->str:
|
|
306
|
-
return hashlib.md5(open(filepath, "rb").read(100*1024*1024)).hexdigest()
|
|
339
|
+
return hashlib.md5(open(filepath, "rb").read(100*1024*1024)).hexdigest()
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
def _create_methodology_embedding(embedding_model: Any, methodology_text: str) -> np.ndarray:
|
|
343
|
+
"""Create embedding vector for methodology text"""
|
|
344
|
+
try:
|
|
345
|
+
# Truncate long text
|
|
346
|
+
max_length = 512
|
|
347
|
+
text = ' '.join(methodology_text.split()[:max_length])
|
|
348
|
+
|
|
349
|
+
# 使用sentence_transformers模型获取嵌入向量
|
|
350
|
+
embedding = embedding_model.encode([text],
|
|
351
|
+
convert_to_tensor=True,
|
|
352
|
+
normalize_embeddings=True)
|
|
353
|
+
vector = np.array(embedding.cpu().numpy(), dtype=np.float32)
|
|
354
|
+
return vector[0] # Return first vector, because we only encoded one text
|
|
355
|
+
except Exception as e:
|
|
356
|
+
PrettyOutput.print(f"Failed to create methodology embedding vector: {str(e)}", OutputType.ERROR)
|
|
357
|
+
return np.zeros(1536, dtype=np.float32)
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
def load_methodology(user_input: str) -> str:
|
|
361
|
+
"""Load methodology and build vector index"""
|
|
362
|
+
PrettyOutput.print("Loading methodology...", OutputType.PROGRESS)
|
|
363
|
+
user_jarvis_methodology = os.path.expanduser("~/.jarvis/methodology")
|
|
364
|
+
if not os.path.exists(user_jarvis_methodology):
|
|
365
|
+
return ""
|
|
366
|
+
|
|
367
|
+
try:
|
|
368
|
+
with open(user_jarvis_methodology, "r", encoding="utf-8") as f:
|
|
369
|
+
data = yaml.safe_load(f)
|
|
370
|
+
|
|
371
|
+
# Reset data structure
|
|
372
|
+
methodology_data = []
|
|
373
|
+
vectors = []
|
|
374
|
+
ids = []
|
|
375
|
+
|
|
376
|
+
# Get embedding model
|
|
377
|
+
embedding_model = load_embedding_model()
|
|
378
|
+
|
|
379
|
+
# Create test embedding to get correct dimension
|
|
380
|
+
test_embedding = _create_methodology_embedding(embedding_model, "test")
|
|
381
|
+
embedding_dimension = len(test_embedding)
|
|
382
|
+
|
|
383
|
+
# Create embedding vector for each methodology
|
|
384
|
+
for i, (key, value) in enumerate(data.items()):
|
|
385
|
+
PrettyOutput.print(f"Vectorizing methodology: {key} ...", OutputType.INFO)
|
|
386
|
+
methodology_text = f"{key}\n{value}"
|
|
387
|
+
embedding = _create_methodology_embedding(embedding_model, methodology_text)
|
|
388
|
+
vectors.append(embedding)
|
|
389
|
+
ids.append(i)
|
|
390
|
+
methodology_data.append({"key": key, "value": value})
|
|
391
|
+
|
|
392
|
+
if vectors:
|
|
393
|
+
vectors_array = np.vstack(vectors)
|
|
394
|
+
# Use correct dimension from test embedding
|
|
395
|
+
hnsw_index = faiss.IndexHNSWFlat(embedding_dimension, 16)
|
|
396
|
+
hnsw_index.hnsw.efConstruction = 40
|
|
397
|
+
hnsw_index.hnsw.efSearch = 16
|
|
398
|
+
methodology_index = faiss.IndexIDMap(hnsw_index)
|
|
399
|
+
methodology_index.add_with_ids(vectors_array, np.array(ids)) # type: ignore
|
|
400
|
+
query_embedding = _create_methodology_embedding(embedding_model, user_input)
|
|
401
|
+
k = min(5, len(methodology_data))
|
|
402
|
+
PrettyOutput.print(f"Retrieving methodology...", OutputType.INFO)
|
|
403
|
+
distances, indices = methodology_index.search(
|
|
404
|
+
query_embedding.reshape(1, -1), k
|
|
405
|
+
) # type: ignore
|
|
406
|
+
|
|
407
|
+
relevant_methodologies = {}
|
|
408
|
+
for dist, idx in zip(distances[0], indices[0]):
|
|
409
|
+
if idx >= 0:
|
|
410
|
+
similarity = 1.0 / (1.0 + float(dist))
|
|
411
|
+
methodology = methodology_data[idx]
|
|
412
|
+
PrettyOutput.print(
|
|
413
|
+
f"Methodology '{methodology['key']}' similarity: {similarity:.3f}",
|
|
414
|
+
OutputType.INFO
|
|
415
|
+
)
|
|
416
|
+
if similarity >= 0.5:
|
|
417
|
+
relevant_methodologies[methodology["key"]] = methodology["value"]
|
|
418
|
+
|
|
419
|
+
if relevant_methodologies:
|
|
420
|
+
return f"""This is the standard methodology for handling previous problems, if the current task is similar, you can refer to it:
|
|
421
|
+
{relevant_methodologies}
|
|
422
|
+
"""
|
|
423
|
+
return ""
|
|
424
|
+
|
|
425
|
+
except Exception as e:
|
|
426
|
+
PrettyOutput.print(f"Error loading methodology: {str(e)}", OutputType.ERROR)
|
|
427
|
+
import traceback
|
|
428
|
+
PrettyOutput.print(f"Error trace: {traceback.format_exc()}", OutputType.INFO)
|
|
429
|
+
return ""
|
|
@@ -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
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
jarvis/__init__.py,sha256=CCLUaAlEVc1W7PRJT3CV9kBGq5ZA-5WXMJMM1wOz6jk,51
|
|
2
|
+
jarvis/agent.py,sha256=dneYp0w25eeJpodcm59-r8V6fu7G_4MtCntvGNCLgBI,20868
|
|
3
|
+
jarvis/utils.py,sha256=feUUqe8nA7MobPwVKH9ogMZrD1kH87-zeZxHvxWf83s,15807
|
|
4
|
+
jarvis/jarvis_code_agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
|
+
jarvis/jarvis_code_agent/main.py,sha256=wZkYy_VmTg1iJBmQ6fD39hv2eC8FE6CVgtx7lxIUYHo,7050
|
|
6
|
+
jarvis/jarvis_codebase/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
+
jarvis/jarvis_codebase/main.py,sha256=rnA4rSyRmtVsKQ5HkQnNc57sZnT5sCBcmQFLWdzYJv8,36854
|
|
8
|
+
jarvis/jarvis_coder/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
+
jarvis/jarvis_coder/file_select.py,sha256=BobNj5Kirr6jSwy59LOghC3o8Uff1CwTXNtlTO-idEo,8475
|
|
10
|
+
jarvis/jarvis_coder/git_utils.py,sha256=R83iDYkDHIntQCd6p9g8Nne9oR5TVNhM-frd_2qR8Jo,5021
|
|
11
|
+
jarvis/jarvis_coder/main.py,sha256=jicy9IN_94Dp8hDubOJX8t5h3vAmciAiS3v34WrvJZc,8469
|
|
12
|
+
jarvis/jarvis_coder/patch_handler.py,sha256=zTCjei1rv00-iA2zTh4UlJYEZka_AoCsgisAWA5PDug,14803
|
|
13
|
+
jarvis/jarvis_coder/plan_generator.py,sha256=x-FalwoRg79h-fvDgFQ8Cl-I8zJ7x2qcXsEUnRip9GA,6186
|
|
14
|
+
jarvis/jarvis_platform/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
|
+
jarvis/jarvis_platform/main.py,sha256=h08SaaIRBhqX8yIp_mG9vSKZYVBrBVfcC9gDK4A45RQ,4961
|
|
16
|
+
jarvis/jarvis_rag/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
|
+
jarvis/jarvis_rag/main.py,sha256=tp9skDCrassVTHRlbWJmA880CoF8OZTSFCiknoHRirU,33605
|
|
18
|
+
jarvis/jarvis_smart_shell/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
19
|
+
jarvis/jarvis_smart_shell/main.py,sha256=G03M39Bfwq8ieNZ8zoDbn0QeDs8Z9h2A0TxP8Hqf9GY,3951
|
|
20
|
+
jarvis/models/__init__.py,sha256=mrOt67nselz_H1gX9wdAO4y2DY5WPXzABqJbr5Des8k,63
|
|
21
|
+
jarvis/models/ai8.py,sha256=ZRNO3aRjmICRjCXl-_F9pTNQTY4j1tUd-WJoJpb9n4Y,11958
|
|
22
|
+
jarvis/models/base.py,sha256=nQ-rsJL1Z-gMev3TPoY7tYdwxhCJY8LG6_gtJ-maiW0,2181
|
|
23
|
+
jarvis/models/kimi.py,sha256=JSjSp_Hmmj_3bn0jxArE4lpG8jkQwhWx8qosjRMHdZE,16391
|
|
24
|
+
jarvis/models/ollama.py,sha256=LzEA4kbkw1KflQ1T__hkmXu4--6xUPho2NTnj_ZQe6k,5761
|
|
25
|
+
jarvis/models/openai.py,sha256=7AYKM0CKlI-tU5NtNdVaw5gobhgqSrXwGQLo5b2MJ7c,4404
|
|
26
|
+
jarvis/models/oyi.py,sha256=iA8E5vzN9VIt-rlzpT5wmbyl7umVU1_y5yo_5gz3DXc,14534
|
|
27
|
+
jarvis/models/registry.py,sha256=SM-jPu9TMommz0Fr_WrXpQE4X24QGyH39h0FwEQ-CWU,9448
|
|
28
|
+
jarvis/tools/__init__.py,sha256=7Rqyj5hBAv5cWDVr5T9ZTZASO7ssBHeQNm2_4ZARdkA,72
|
|
29
|
+
jarvis/tools/ask_user.py,sha256=cSxFn8cOZGQYHtfBtXlbdVQ7mlgC1JZCFBylparWShE,2102
|
|
30
|
+
jarvis/tools/base.py,sha256=c0DMoDDPxmsqUYJR989zgUs7nIYRY6GWBrAdusIZKjc,656
|
|
31
|
+
jarvis/tools/chdir.py,sha256=Nr16rLnrQ_eJH5E5HQ1a9o-UqAckKbWeboB3_SBVdVI,2926
|
|
32
|
+
jarvis/tools/create_code_sub_agent.py,sha256=r5Ec3Ri9TGAj1M4c0Ur10I33aZ1i8dbtGK2DqqeebkQ,1718
|
|
33
|
+
jarvis/tools/create_sub_agent.py,sha256=Nf_37sj8uQp1R1f7G1PkMRzwUFrHXj17WYLbusoDzO0,2807
|
|
34
|
+
jarvis/tools/execute_code_modification.py,sha256=_LpzTiUfK7aprKzCrTDhBuu78miDcVyx7VV1Kh682DA,2508
|
|
35
|
+
jarvis/tools/execute_shell.py,sha256=woJq-fivoXppp8rEhg46WVAImf6O89gHJnA7XOuYSM8,2568
|
|
36
|
+
jarvis/tools/file_operation.py,sha256=Aq1EJA59AHR9XomxuxNiyLNon4p8w-Gk9iionl--odU,4082
|
|
37
|
+
jarvis/tools/find_files.py,sha256=MTqijsXO6uFghb79pGaHWsa1NTgjP07p333BvUgMt5s,3696
|
|
38
|
+
jarvis/tools/generate_tool.py,sha256=qhk73UFEPtMC-QfiWBUxnMhkgZMZM-esd0TdcFhWSmc,6181
|
|
39
|
+
jarvis/tools/methodology.py,sha256=f6rF6vw-qaSIuJUrLbZdsLqzXMmAaw1aCwvJuezRX8k,5586
|
|
40
|
+
jarvis/tools/rag.py,sha256=m_G4ct6SBLKKdUXfPkokK-qVlWeFCJ2B9J5IZhHXBXQ,4879
|
|
41
|
+
jarvis/tools/read_webpage.py,sha256=AqE9Og_OzwFYIHZDTnCe_gB-szcUXbVZh-xZat4WgOU,2467
|
|
42
|
+
jarvis/tools/registry.py,sha256=O-vzSaWr9VR3lrCIPF5NPl4V-zHHmz3H3l1_9ORyKsA,11057
|
|
43
|
+
jarvis/tools/search.py,sha256=qf39Zm2Ad9-z4EyZKJrBCvZg1uqMeLuLQ9Zu8WB-TvI,9230
|
|
44
|
+
jarvis/tools/select_code_files.py,sha256=hJwfh_CnyOn4QOBuNpKh9AD7-iH92mj7FP-6EifSH0w,1875
|
|
45
|
+
jarvis/tools/thinker.py,sha256=-aWbjOjV3tGmYeIgAmyKVjd0teFs4ZK7mzPBA09R7hE,4847
|
|
46
|
+
jarvis_ai_assistant-0.1.100.dist-info/LICENSE,sha256=AGgVgQmTqFvaztRtCAXsAMryUymB18gZif7_l2e1XOg,1063
|
|
47
|
+
jarvis_ai_assistant-0.1.100.dist-info/METADATA,sha256=Q7gLFWY8g_jky5kbsJ9F1YVeBloi1hqQoTKDdF9K9AU,12783
|
|
48
|
+
jarvis_ai_assistant-0.1.100.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
49
|
+
jarvis_ai_assistant-0.1.100.dist-info/entry_points.txt,sha256=x0jA_mYRc7hBVdLuOFQBYQjpXjf8NPrAn0C54DJ9t2I,387
|
|
50
|
+
jarvis_ai_assistant-0.1.100.dist-info/top_level.txt,sha256=1BOxyWfzOP_ZXj8rVTDnNCJ92bBGB0rwq8N1PCpoMIs,7
|
|
51
|
+
jarvis_ai_assistant-0.1.100.dist-info/RECORD,,
|
{jarvis_ai_assistant-0.1.98.dist-info → jarvis_ai_assistant-0.1.100.dist-info}/entry_points.txt
RENAMED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
[console_scripts]
|
|
2
|
-
jarvis = jarvis.
|
|
2
|
+
jarvis = jarvis.agent:main
|
|
3
|
+
jarvis-code-agent = jarvis.jarvis_code_agent.main:main
|
|
3
4
|
jarvis-codebase = jarvis.jarvis_codebase.main:main
|
|
4
5
|
jarvis-coder = jarvis.jarvis_coder.main:main
|
|
5
6
|
jarvis-platform = jarvis.jarvis_platform.main:main
|
jarvis/main.py
DELETED
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""Command line interface for Jarvis."""
|
|
3
|
-
|
|
4
|
-
import argparse
|
|
5
|
-
import yaml
|
|
6
|
-
import os
|
|
7
|
-
import sys
|
|
8
|
-
from pathlib import Path
|
|
9
|
-
from prompt_toolkit import prompt
|
|
10
|
-
|
|
11
|
-
from jarvis.models.registry import PlatformRegistry
|
|
12
|
-
|
|
13
|
-
# Add parent directory to Python path to support imports
|
|
14
|
-
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
15
|
-
|
|
16
|
-
from jarvis.agent import Agent
|
|
17
|
-
from jarvis.tools import ToolRegistry
|
|
18
|
-
from jarvis.utils import PrettyOutput, OutputType, get_multiline_input, load_env_from_file
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
def load_tasks() -> dict:
|
|
22
|
-
"""Load tasks from .jarvis files in user home and current directory."""
|
|
23
|
-
tasks = {}
|
|
24
|
-
|
|
25
|
-
# Check .jarvis in user directory
|
|
26
|
-
user_jarvis = os.path.expanduser("~/.jarvis")
|
|
27
|
-
if os.path.exists(user_jarvis):
|
|
28
|
-
try:
|
|
29
|
-
with open(user_jarvis, "r", encoding="utf-8") as f:
|
|
30
|
-
user_tasks = yaml.safe_load(f)
|
|
31
|
-
|
|
32
|
-
if isinstance(user_tasks, dict):
|
|
33
|
-
# Validate and add user directory tasks
|
|
34
|
-
for name, desc in user_tasks.items():
|
|
35
|
-
if desc: # Ensure description is not empty
|
|
36
|
-
tasks[str(name)] = str(desc)
|
|
37
|
-
else:
|
|
38
|
-
PrettyOutput.print("Warning: ~/.jarvis file should contain a dictionary of task_name: task_description", OutputType.ERROR)
|
|
39
|
-
except Exception as e:
|
|
40
|
-
PrettyOutput.print(f"Error loading ~/.jarvis file: {str(e)}", OutputType.ERROR)
|
|
41
|
-
|
|
42
|
-
# Check .jarvis in current directory
|
|
43
|
-
if os.path.exists(".jarvis"):
|
|
44
|
-
try:
|
|
45
|
-
with open(".jarvis", "r", encoding="utf-8") as f:
|
|
46
|
-
local_tasks = yaml.safe_load(f)
|
|
47
|
-
|
|
48
|
-
if isinstance(local_tasks, dict):
|
|
49
|
-
# Validate and add current directory tasks, overwrite user directory tasks if there is a name conflict
|
|
50
|
-
for name, desc in local_tasks.items():
|
|
51
|
-
if desc: # Ensure description is not empty
|
|
52
|
-
tasks[str(name)] = str(desc)
|
|
53
|
-
else:
|
|
54
|
-
PrettyOutput.print("Warning: .jarvis file should contain a dictionary of task_name: task_description", OutputType.ERROR)
|
|
55
|
-
except Exception as e:
|
|
56
|
-
PrettyOutput.print(f"Error loading .jarvis file: {str(e)}", OutputType.ERROR)
|
|
57
|
-
|
|
58
|
-
# Read methodology
|
|
59
|
-
method_path = os.path.expanduser("~/.jarvis_methodology")
|
|
60
|
-
if os.path.exists(method_path):
|
|
61
|
-
with open(method_path, "r", encoding="utf-8") as f:
|
|
62
|
-
methodology = yaml.safe_load(f)
|
|
63
|
-
if isinstance(methodology, dict):
|
|
64
|
-
for name, desc in methodology.items():
|
|
65
|
-
tasks[f"Run Methodology: {str(name)}\n {str(desc)}" ] = str(desc)
|
|
66
|
-
|
|
67
|
-
return tasks
|
|
68
|
-
|
|
69
|
-
def select_task(tasks: dict) -> str:
|
|
70
|
-
"""Let user select a task from the list or skip. Returns task description if selected."""
|
|
71
|
-
if not tasks:
|
|
72
|
-
return ""
|
|
73
|
-
|
|
74
|
-
# Convert tasks to list for ordered display
|
|
75
|
-
task_names = list(tasks.keys())
|
|
76
|
-
|
|
77
|
-
PrettyOutput.print("\nAvailable tasks:", OutputType.INFO)
|
|
78
|
-
for i, name in enumerate(task_names, 1):
|
|
79
|
-
PrettyOutput.print(f"[{i}] {name}", OutputType.INFO)
|
|
80
|
-
PrettyOutput.print("[0] Skip predefined tasks", OutputType.INFO)
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
while True:
|
|
84
|
-
try:
|
|
85
|
-
choice = prompt(
|
|
86
|
-
"\nPlease select a task number (0 to skip): ",
|
|
87
|
-
).strip()
|
|
88
|
-
|
|
89
|
-
if not choice:
|
|
90
|
-
return ""
|
|
91
|
-
|
|
92
|
-
choice = int(choice)
|
|
93
|
-
if choice == 0:
|
|
94
|
-
return ""
|
|
95
|
-
elif 1 <= choice <= len(task_names):
|
|
96
|
-
selected_name = task_names[choice - 1]
|
|
97
|
-
return tasks[selected_name] # Return the task description
|
|
98
|
-
else:
|
|
99
|
-
PrettyOutput.print("Invalid choice. Please select a number from the list.", OutputType.ERROR)
|
|
100
|
-
|
|
101
|
-
except KeyboardInterrupt:
|
|
102
|
-
return "" # Return empty on Ctrl+C
|
|
103
|
-
except EOFError:
|
|
104
|
-
return "" # Return empty on Ctrl+D
|
|
105
|
-
except Exception as e:
|
|
106
|
-
PrettyOutput.print(f"Failed to select task: {str(e)}", OutputType.ERROR)
|
|
107
|
-
continue
|
|
108
|
-
|
|
109
|
-
def main():
|
|
110
|
-
"""Jarvis main entry point"""
|
|
111
|
-
# Add argument parser
|
|
112
|
-
load_env_from_file()
|
|
113
|
-
parser = argparse.ArgumentParser(description='Jarvis AI assistant')
|
|
114
|
-
parser.add_argument('-f', '--files', nargs='*', help='List of files to process')
|
|
115
|
-
parser.add_argument('--keep-history', action='store_true', help='Keep chat history (do not delete session)')
|
|
116
|
-
args = parser.parse_args()
|
|
117
|
-
|
|
118
|
-
try:
|
|
119
|
-
# 获取全局模型实例
|
|
120
|
-
agent = Agent()
|
|
121
|
-
|
|
122
|
-
# 如果用户传入了模型参数,则更换当前模型为用户指定的模型
|
|
123
|
-
|
|
124
|
-
# Welcome information
|
|
125
|
-
PrettyOutput.print(f"Jarvis initialized - With {agent.model.name()}", OutputType.SYSTEM)
|
|
126
|
-
if args.keep_history:
|
|
127
|
-
PrettyOutput.print("History preservation mode enabled", OutputType.INFO)
|
|
128
|
-
|
|
129
|
-
# 加载预定义任务
|
|
130
|
-
tasks = load_tasks()
|
|
131
|
-
if tasks:
|
|
132
|
-
selected_task = select_task(tasks)
|
|
133
|
-
if selected_task:
|
|
134
|
-
PrettyOutput.print(f"\nExecute task: {selected_task}", OutputType.INFO)
|
|
135
|
-
agent.run(selected_task, args.files)
|
|
136
|
-
return 0
|
|
137
|
-
|
|
138
|
-
# 如果没有选择预定义任务,进入交互模式
|
|
139
|
-
while True:
|
|
140
|
-
try:
|
|
141
|
-
user_input = get_multiline_input("Please enter your task (input empty line to exit):")
|
|
142
|
-
if not user_input or user_input == "__interrupt__":
|
|
143
|
-
break
|
|
144
|
-
agent.run(user_input, args.files)
|
|
145
|
-
except Exception as e:
|
|
146
|
-
PrettyOutput.print(f"Error: {str(e)}", OutputType.ERROR)
|
|
147
|
-
|
|
148
|
-
except Exception as e:
|
|
149
|
-
PrettyOutput.print(f"Initialization error: {str(e)}", OutputType.ERROR)
|
|
150
|
-
return 1
|
|
151
|
-
|
|
152
|
-
return 0
|
|
153
|
-
|
|
154
|
-
if __name__ == "__main__":
|
|
155
|
-
exit(main())
|
jarvis/tools/codebase_qa.py
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
from typing import Any, Dict
|
|
3
|
-
from jarvis.jarvis_codebase.main import CodeBase
|
|
4
|
-
from jarvis.utils import find_git_root, PrettyOutput, OutputType
|
|
5
|
-
|
|
6
|
-
class CodebaseQATool:
|
|
7
|
-
"""代码库问答工具,用于回答关于代码库的问题"""
|
|
8
|
-
|
|
9
|
-
name = "codebase_qa"
|
|
10
|
-
description = "Answer questions about the codebase, can query and understand code functionality, structure, and implementation details"
|
|
11
|
-
parameters = {
|
|
12
|
-
"type": "object",
|
|
13
|
-
"properties": {
|
|
14
|
-
"dir": {
|
|
15
|
-
"type": "string",
|
|
16
|
-
"description": "Project root directory"
|
|
17
|
-
},
|
|
18
|
-
"question": {
|
|
19
|
-
"type": "string",
|
|
20
|
-
"description": "Question about the codebase"
|
|
21
|
-
},
|
|
22
|
-
"top_k": {
|
|
23
|
-
"type": "integer",
|
|
24
|
-
"description": "Number of relevant files to search",
|
|
25
|
-
"default": 5
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
|
-
"required": ["question"]
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
def execute(self, params: Dict[str, Any]) -> Dict[str, Any]:
|
|
32
|
-
"""执行代码问答"""
|
|
33
|
-
try:
|
|
34
|
-
dir = params.get("dir")
|
|
35
|
-
question = params["question"]
|
|
36
|
-
top_k = params.get("top_k", 5)
|
|
37
|
-
|
|
38
|
-
# 初始化代码库
|
|
39
|
-
current_dir = os.getcwd()
|
|
40
|
-
root_dir = find_git_root(dir or current_dir)
|
|
41
|
-
if not root_dir:
|
|
42
|
-
return {
|
|
43
|
-
"success": False,
|
|
44
|
-
"stdout": "",
|
|
45
|
-
"stderr": "错误:当前目录不在Git仓库中",
|
|
46
|
-
"error": "NotInGitRepository"
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
os.chdir(root_dir)
|
|
50
|
-
codebase = CodeBase(root_dir)
|
|
51
|
-
# 生成索引
|
|
52
|
-
|
|
53
|
-
codebase.generate_codebase()
|
|
54
|
-
# 执行问答
|
|
55
|
-
response = codebase.ask_codebase(question, top_k)
|
|
56
|
-
os.chdir(current_dir)
|
|
57
|
-
return {
|
|
58
|
-
"success": True,
|
|
59
|
-
"stdout": response,
|
|
60
|
-
"stderr": "",
|
|
61
|
-
"error": None
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
except Exception as e:
|
|
65
|
-
PrettyOutput.print(f"代码问答出错: {str(e)}", output_type=OutputType.ERROR)
|
|
66
|
-
return {
|
|
67
|
-
"success": False,
|
|
68
|
-
"stdout": "",
|
|
69
|
-
"stderr": f"执行代码问答时发生错误: {str(e)}",
|
|
70
|
-
"error": str(type(e).__name__)
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
def register():
|
|
74
|
-
return CodebaseQATool()
|