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.

Files changed (45) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/agent.py +199 -157
  3. jarvis/jarvis_code_agent/__init__.py +0 -0
  4. jarvis/jarvis_code_agent/main.py +202 -0
  5. jarvis/jarvis_codebase/main.py +415 -287
  6. jarvis/jarvis_coder/file_select.py +209 -0
  7. jarvis/jarvis_coder/git_utils.py +64 -2
  8. jarvis/jarvis_coder/main.py +13 -397
  9. jarvis/jarvis_coder/patch_handler.py +229 -81
  10. jarvis/jarvis_coder/plan_generator.py +49 -7
  11. jarvis/jarvis_platform/main.py +2 -2
  12. jarvis/jarvis_rag/main.py +11 -11
  13. jarvis/jarvis_smart_shell/main.py +5 -5
  14. jarvis/models/base.py +6 -1
  15. jarvis/models/kimi.py +2 -2
  16. jarvis/models/ollama.py +2 -2
  17. jarvis/models/openai.py +1 -1
  18. jarvis/models/registry.py +38 -18
  19. jarvis/tools/ask_user.py +12 -9
  20. jarvis/tools/chdir.py +9 -5
  21. jarvis/tools/create_code_sub_agent.py +56 -0
  22. jarvis/tools/{sub_agent.py → create_sub_agent.py} +6 -2
  23. jarvis/tools/execute_code_modification.py +70 -0
  24. jarvis/tools/{shell.py → execute_shell.py} +2 -2
  25. jarvis/tools/{file_ops.py → file_operation.py} +19 -15
  26. jarvis/tools/find_files.py +119 -0
  27. jarvis/tools/{generator.py → generate_tool.py} +27 -25
  28. jarvis/tools/methodology.py +32 -26
  29. jarvis/tools/rag.py +37 -33
  30. jarvis/tools/{webpage.py → read_webpage.py} +4 -2
  31. jarvis/tools/registry.py +94 -48
  32. jarvis/tools/search.py +19 -16
  33. jarvis/tools/select_code_files.py +61 -0
  34. jarvis/tools/thinker.py +7 -5
  35. jarvis/utils.py +155 -32
  36. {jarvis_ai_assistant-0.1.98.dist-info → jarvis_ai_assistant-0.1.100.dist-info}/METADATA +9 -8
  37. jarvis_ai_assistant-0.1.100.dist-info/RECORD +51 -0
  38. {jarvis_ai_assistant-0.1.98.dist-info → jarvis_ai_assistant-0.1.100.dist-info}/entry_points.txt +2 -1
  39. jarvis/main.py +0 -155
  40. jarvis/tools/codebase_qa.py +0 -74
  41. jarvis/tools/coder.py +0 -69
  42. jarvis_ai_assistant-0.1.98.dist-info/RECORD +0 -47
  43. {jarvis_ai_assistant-0.1.98.dist-info → jarvis_ai_assistant-0.1.100.dist-info}/LICENSE +0 -0
  44. {jarvis_ai_assistant-0.1.98.dist-info → jarvis_ai_assistant-0.1.100.dist-info}/WHEEL +0 -0
  45. {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 = 60
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 - 10), output_type, timestamp=True)
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 load_env_from_file():
175
- """Load environment variables from ~/.jarvis_env"""
176
- env_file = Path.home() / ".jarvis_env"
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 ~/.jarvis_env: {e}", OutputType.WARNING)
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-large-zh-v1.5"
221
- PrettyOutput.print(f"Loading embedding model: {model_name}...", OutputType.INFO)
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=os.path.expanduser("~/.cache/huggingface/hub"),
256
+ cache_folder=cache_dir,
227
257
  local_files_only=True
228
258
  )
229
- PrettyOutput.print("Successfully loaded model using local cache", OutputType.SUCCESS)
230
- except Exception as local_error:
231
- PrettyOutput.print(f"Failed to load locally, trying to download online: {str(local_error)}", OutputType.WARNING)
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=os.path.expanduser("~/.cache/huggingface/hub")
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
- local_files_only=True,
251
- cache_dir=os.path.expanduser("~/.cache/huggingface/hub")
282
+ cache_dir=cache_dir,
283
+ local_files_only=True
252
284
  )
253
285
  model = AutoModelForSequenceClassification.from_pretrained(
254
286
  model_name,
255
- local_files_only=True,
256
- cache_dir=os.path.expanduser("~/.cache/huggingface/hub")
287
+ cache_dir=cache_dir,
288
+ local_files_only=True
257
289
  )
258
- PrettyOutput.print("Successfully loaded model using local cache", OutputType.SUCCESS)
259
- except Exception as local_error:
260
- PrettyOutput.print(f"Failed to load locally, trying to download online: {str(local_error)}", OutputType.WARNING)
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=os.path.expanduser("~/.cache/huggingface/hub")
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=os.path.expanduser("~/.cache/huggingface/hub")
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
- # 如果有 GPU 就使用 GPU
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.98
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 `~/.jarvis_env` file:
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: `~/.jarvis_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 `~/.jarvis_tools/` or `src/jarvis/tools/`:
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
- "error": str(e)
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 `~/.jarvis_models/`:
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,,
@@ -1,5 +1,6 @@
1
1
  [console_scripts]
2
- jarvis = jarvis.main:main
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())
@@ -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()