jarvis-ai-assistant 0.1.98__tar.gz → 0.1.99__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of jarvis-ai-assistant might be problematic. Click here for more details.

Files changed (64) hide show
  1. {jarvis_ai_assistant-0.1.98/src/jarvis_ai_assistant.egg-info → jarvis_ai_assistant-0.1.99}/PKG-INFO +1 -1
  2. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99}/pyproject.toml +3 -2
  3. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99}/setup.py +3 -2
  4. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99}/src/jarvis/__init__.py +1 -1
  5. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99}/src/jarvis/agent.py +199 -157
  6. jarvis_ai_assistant-0.1.99/src/jarvis/jarvis_code_agent/main.py +203 -0
  7. jarvis_ai_assistant-0.1.99/src/jarvis/jarvis_codebase/main.py +875 -0
  8. jarvis_ai_assistant-0.1.99/src/jarvis/jarvis_coder/file_select.py +209 -0
  9. jarvis_ai_assistant-0.1.99/src/jarvis/jarvis_coder/git_utils.py +123 -0
  10. jarvis_ai_assistant-0.1.99/src/jarvis/jarvis_coder/main.py +247 -0
  11. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99}/src/jarvis/jarvis_coder/patch_handler.py +84 -14
  12. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99}/src/jarvis/jarvis_coder/plan_generator.py +49 -7
  13. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99}/src/jarvis/jarvis_rag/main.py +9 -9
  14. jarvis_ai_assistant-0.1.99/src/jarvis/jarvis_smart_shell/__init__.py +0 -0
  15. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99}/src/jarvis/jarvis_smart_shell/main.py +5 -7
  16. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99}/src/jarvis/models/base.py +6 -1
  17. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99}/src/jarvis/models/ollama.py +2 -2
  18. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99}/src/jarvis/models/registry.py +3 -6
  19. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99}/src/jarvis/tools/ask_user.py +6 -6
  20. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99}/src/jarvis/tools/codebase_qa.py +5 -7
  21. jarvis_ai_assistant-0.1.99/src/jarvis/tools/create_code_sub_agent.py +55 -0
  22. jarvis_ai_assistant-0.1.98/src/jarvis/tools/sub_agent.py → jarvis_ai_assistant-0.1.99/src/jarvis/tools/create_sub_agent.py +4 -1
  23. jarvis_ai_assistant-0.1.99/src/jarvis/tools/execute_code_modification.py +72 -0
  24. jarvis_ai_assistant-0.1.98/src/jarvis/tools/file_ops.py → jarvis_ai_assistant-0.1.99/src/jarvis/tools/file_operation.py +13 -14
  25. jarvis_ai_assistant-0.1.99/src/jarvis/tools/find_related_files.py +86 -0
  26. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99}/src/jarvis/tools/methodology.py +25 -25
  27. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99}/src/jarvis/tools/rag.py +32 -32
  28. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99}/src/jarvis/tools/registry.py +72 -36
  29. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99}/src/jarvis/tools/search.py +1 -1
  30. jarvis_ai_assistant-0.1.99/src/jarvis/tools/select_code_files.py +64 -0
  31. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99}/src/jarvis/utils.py +153 -49
  32. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99/src/jarvis_ai_assistant.egg-info}/PKG-INFO +1 -1
  33. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99}/src/jarvis_ai_assistant.egg-info/SOURCES.txt +12 -7
  34. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99}/src/jarvis_ai_assistant.egg-info/entry_points.txt +2 -1
  35. jarvis_ai_assistant-0.1.98/src/jarvis/jarvis_codebase/main.py +0 -747
  36. jarvis_ai_assistant-0.1.98/src/jarvis/jarvis_coder/git_utils.py +0 -61
  37. jarvis_ai_assistant-0.1.98/src/jarvis/jarvis_coder/main.py +0 -625
  38. jarvis_ai_assistant-0.1.98/src/jarvis/main.py +0 -155
  39. jarvis_ai_assistant-0.1.98/src/jarvis/tools/coder.py +0 -69
  40. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99}/LICENSE +0 -0
  41. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99}/MANIFEST.in +0 -0
  42. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99}/README.md +0 -0
  43. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99}/setup.cfg +0 -0
  44. {jarvis_ai_assistant-0.1.98/src/jarvis/jarvis_codebase → jarvis_ai_assistant-0.1.99/src/jarvis/jarvis_code_agent}/__init__.py +0 -0
  45. {jarvis_ai_assistant-0.1.98/src/jarvis/jarvis_coder → jarvis_ai_assistant-0.1.99/src/jarvis/jarvis_codebase}/__init__.py +0 -0
  46. {jarvis_ai_assistant-0.1.98/src/jarvis/jarvis_platform → jarvis_ai_assistant-0.1.99/src/jarvis/jarvis_coder}/__init__.py +0 -0
  47. {jarvis_ai_assistant-0.1.98/src/jarvis/jarvis_rag → jarvis_ai_assistant-0.1.99/src/jarvis/jarvis_platform}/__init__.py +0 -0
  48. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99}/src/jarvis/jarvis_platform/main.py +0 -0
  49. {jarvis_ai_assistant-0.1.98/src/jarvis/jarvis_smart_shell → jarvis_ai_assistant-0.1.99/src/jarvis/jarvis_rag}/__init__.py +0 -0
  50. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99}/src/jarvis/models/__init__.py +0 -0
  51. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99}/src/jarvis/models/ai8.py +0 -0
  52. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99}/src/jarvis/models/kimi.py +0 -0
  53. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99}/src/jarvis/models/openai.py +0 -0
  54. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99}/src/jarvis/models/oyi.py +0 -0
  55. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99}/src/jarvis/tools/__init__.py +0 -0
  56. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99}/src/jarvis/tools/base.py +0 -0
  57. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99}/src/jarvis/tools/chdir.py +0 -0
  58. /jarvis_ai_assistant-0.1.98/src/jarvis/tools/shell.py → /jarvis_ai_assistant-0.1.99/src/jarvis/tools/execute_shell.py +0 -0
  59. /jarvis_ai_assistant-0.1.98/src/jarvis/tools/generator.py → /jarvis_ai_assistant-0.1.99/src/jarvis/tools/generate_tool.py +0 -0
  60. /jarvis_ai_assistant-0.1.98/src/jarvis/tools/webpage.py → /jarvis_ai_assistant-0.1.99/src/jarvis/tools/read_webpage.py +0 -0
  61. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99}/src/jarvis/tools/thinker.py +0 -0
  62. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99}/src/jarvis_ai_assistant.egg-info/dependency_links.txt +0 -0
  63. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99}/src/jarvis_ai_assistant.egg-info/requires.txt +0 -0
  64. {jarvis_ai_assistant-0.1.98 → jarvis_ai_assistant-0.1.99}/src/jarvis_ai_assistant.egg-info/top_level.txt +0 -0
@@ -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.99
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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "jarvis-ai-assistant"
7
- version = "0.1.98"
7
+ version = "0.1.99"
8
8
  description = "Jarvis: An AI assistant that uses tools to interact with the system"
9
9
  readme = "README.md"
10
10
  authors = [{ name = "Your Name", email = "your.email@example.com" }]
@@ -47,7 +47,8 @@ dev = ["pytest", "black", "isort", "mypy"]
47
47
  Homepage = "https://github.com/skyfireitdiy/Jarvis"
48
48
 
49
49
  [project.scripts]
50
- jarvis = "jarvis.main:main"
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.98",
5
+ version="0.1.99",
6
6
  author="skyfire",
7
7
  author_email="skyfireitdiy@hotmail.com",
8
8
  description="An AI assistant that uses various tools to interact with the system",
@@ -32,7 +32,8 @@ setup(
32
32
  ],
33
33
  entry_points={
34
34
  "console_scripts": [
35
- "jarvis=jarvis.main:main",
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,3 +1,3 @@
1
1
  """Jarvis AI Assistant"""
2
2
 
3
- __version__ = "0.1.98"
3
+ __version__ = "0.1.99"
@@ -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 .utils import PrettyOutput, OutputType, get_max_context_length, get_multiline_input, load_embedding_model
8
+ from jarvis.models.registry import PlatformRegistry
9
+ from jarvis.tools import ToolRegistry
10
+ from jarvis.tools.registry import load_tools
11
+ from jarvis.utils import PrettyOutput, OutputType, get_single_line_input, load_methodology, add_agent, delete_current_agent, get_max_context_length, get_multiline_input, load_embedding_model, load_env_from_file
11
12
  import os
12
13
 
13
14
  class Agent:
14
- def __init__(self, name: str = "Jarvis", is_sub_agent: bool = False):
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
- model: LLM model instance
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
- hnsw_index = faiss.IndexHNSWFlat(self.embedding_dimension, 16)
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 = input("Generate methodology for this task? (y/n): ").strip().lower()
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
- methodology = self._load_methodology(user_input)
311
- methodology_prompt = ""
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"""You are {self.name}, an AI assistant with powerful problem-solving capabilities.
336
-
337
- When users need to execute tasks, you will strictly follow these steps to handle problems:
338
- 1. Problem Restatement: Confirm understanding of the problem
339
- 2. Root Cause Analysis (only if needed for problem analysis tasks)
340
- 3. Set Objectives: Define achievable and verifiable goals
341
- 4. Generate Solutions: Create one or more actionable solutions
342
- 5. Evaluate Solutions: Select the optimal solution from multiple options
343
- 6. Create Action Plan: Based on available tools, create an action plan using PlantUML format for clear execution flow
344
- 7. Execute Action Plan: Execute one step at a time, **use at most one tool** (wait for tool execution results before proceeding)
345
- 8. Monitor and Adjust: If execution results don't match expectations, reflect and adjust the action plan, iterate previous steps
346
- 9. Methodology: If the current task has general applicability and valuable experience is gained, use methodology tools to record it for future similar problems
347
- 10. Task Completion: End the task using task completion command when finished
348
-
349
- Methodology Template:
350
- 1. Problem Restatement
351
- 2. Optimal Solution
352
- 3. Optimal Solution Steps (exclude failed actions)
353
-
354
- -------------------------------------------------------------
261
+ self.model.set_system_message(f"""
262
+ {self.system_prompt}
355
263
 
356
264
  {tools_prompt}
357
265
 
358
- -------------------------------------------------------------
359
-
360
- Tool Usage Format:
361
-
362
- <TOOL_CALL>
363
- name: tool_name
364
- arguments:
365
- param1: value1
366
- param2: value2
367
- </TOOL_CALL>
368
-
369
- -------------------------------------------------------------
370
-
371
- Strict Rules:
372
- - Execute only one tool at a time
373
- - Tool execution must strictly follow the tool usage format
374
- - Wait for user to provide execution results
375
- - Don't assume or imagine results
376
- - Don't create fake dialogues
377
- - If current information is insufficient, you may ask the user
378
- - Not all problem-solving steps are mandatory, skip as appropriate
379
- - Ask user before executing tools that might damage system or user's codebase
380
- - Request user guidance when multiple iterations show no progress
381
- - If yaml string contains colons, wrap the entire string in quotes to avoid yaml parsing errors
382
- - Use | syntax for multi-line strings in yaml
383
-
384
266
  {methodology_prompt}
385
-
386
- -------------------------------------------------------------
387
-
388
267
  """)
389
268
  self.prompt = f"{user_input}"
390
269
 
@@ -446,3 +325,166 @@ Strict Rules:
446
325
 
447
326
 
448
327
 
328
+
329
+ def load_tasks() -> dict:
330
+ """Load tasks from .jarvis files in user home and current directory."""
331
+ tasks = {}
332
+
333
+ # Check .jarvis in user directory
334
+ user_jarvis = os.path.expanduser("~/.jarvis")
335
+ if os.path.exists(user_jarvis):
336
+ try:
337
+ with open(user_jarvis, "r", encoding="utf-8") as f:
338
+ user_tasks = yaml.safe_load(f)
339
+
340
+ if isinstance(user_tasks, dict):
341
+ # Validate and add user directory tasks
342
+ for name, desc in user_tasks.items():
343
+ if desc: # Ensure description is not empty
344
+ tasks[str(name)] = str(desc)
345
+ else:
346
+ PrettyOutput.print("Warning: ~/.jarvis file should contain a dictionary of task_name: task_description", OutputType.ERROR)
347
+ except Exception as e:
348
+ PrettyOutput.print(f"Error loading ~/.jarvis file: {str(e)}", OutputType.ERROR)
349
+
350
+ # Check .jarvis in current directory
351
+ if os.path.exists(".jarvis"):
352
+ try:
353
+ with open(".jarvis", "r", encoding="utf-8") as f:
354
+ local_tasks = yaml.safe_load(f)
355
+
356
+ if isinstance(local_tasks, dict):
357
+ # Validate and add current directory tasks, overwrite user directory tasks if there is a name conflict
358
+ for name, desc in local_tasks.items():
359
+ if desc: # Ensure description is not empty
360
+ tasks[str(name)] = str(desc)
361
+ else:
362
+ PrettyOutput.print("Warning: .jarvis file should contain a dictionary of task_name: task_description", OutputType.ERROR)
363
+ except Exception as e:
364
+ PrettyOutput.print(f"Error loading .jarvis file: {str(e)}", OutputType.ERROR)
365
+
366
+ # Read methodology
367
+ method_path = os.path.expanduser("~/.jarvis_methodology")
368
+ if os.path.exists(method_path):
369
+ with open(method_path, "r", encoding="utf-8") as f:
370
+ methodology = yaml.safe_load(f)
371
+ if isinstance(methodology, dict):
372
+ for name, desc in methodology.items():
373
+ tasks[f"Run Methodology: {str(name)}\n {str(desc)}" ] = str(desc)
374
+
375
+ return tasks
376
+
377
+ def select_task(tasks: dict) -> str:
378
+ """Let user select a task from the list or skip. Returns task description if selected."""
379
+ if not tasks:
380
+ return ""
381
+
382
+ # Convert tasks to list for ordered display
383
+ task_names = list(tasks.keys())
384
+
385
+ PrettyOutput.print("\nAvailable tasks:", OutputType.INFO)
386
+ for i, name in enumerate(task_names, 1):
387
+ PrettyOutput.print(f"[{i}] {name}", OutputType.INFO)
388
+ PrettyOutput.print("[0] Skip predefined tasks", OutputType.INFO)
389
+
390
+
391
+ while True:
392
+ try:
393
+ choice = prompt(
394
+ "\nPlease select a task number (0 to skip): ",
395
+ ).strip()
396
+
397
+ if not choice:
398
+ return ""
399
+
400
+ choice = int(choice)
401
+ if choice == 0:
402
+ return ""
403
+ elif 1 <= choice <= len(task_names):
404
+ selected_name = task_names[choice - 1]
405
+ return tasks[selected_name] # Return the task description
406
+ else:
407
+ PrettyOutput.print("Invalid choice. Please select a number from the list.", OutputType.ERROR)
408
+
409
+ except KeyboardInterrupt:
410
+ return "" # Return empty on Ctrl+C
411
+ except EOFError:
412
+ return "" # Return empty on Ctrl+D
413
+ except Exception as e:
414
+ PrettyOutput.print(f"Failed to select task: {str(e)}", OutputType.ERROR)
415
+ continue
416
+
417
+ origin_agent_system_prompt = """You are Jarvis, an AI assistant with powerful problem-solving capabilities.
418
+
419
+ When users need to execute tasks, you will strictly follow these steps to handle problems:
420
+ 1. Problem Restatement: Confirm understanding of the problem
421
+ 2. Root Cause Analysis (only if needed for problem analysis tasks)
422
+ 3. Set Objectives: Define achievable and verifiable goals
423
+ 4. Generate Solutions: Create one or more actionable solutions
424
+ 5. Evaluate Solutions: Select the optimal solution from multiple options
425
+ 6. Create Action Plan: Based on available tools, create an action plan using PlantUML format for clear execution flow
426
+ 7. Execute Action Plan: Execute one step at a time, **use at most one tool** (wait for tool execution results before proceeding)
427
+ 8. Monitor and Adjust: If execution results don't match expectations, reflect and adjust the action plan, iterate previous steps
428
+ 9. Methodology: If the current task has general applicability and valuable experience is gained, use methodology tools to record it for future similar problems
429
+ 10. Task Completion: End the task using task completion command when finished
430
+
431
+ Methodology Template:
432
+ 1. Problem Restatement
433
+ 2. Optimal Solution
434
+ 3. Optimal Solution Steps (exclude failed actions)
435
+
436
+ Strict Rules:
437
+ - Execute only one tool at a time
438
+ - Tool execution must strictly follow the tool usage format
439
+ - Wait for user to provide execution results
440
+ - Don't assume or imagine results
441
+ - Don't create fake dialogues
442
+ - If current information is insufficient, you may ask the user
443
+ - Not all problem-solving steps are mandatory, skip as appropriate
444
+ - Ask user before executing tools that might damage system or user's codebase
445
+ - Request user guidance when multiple iterations show no progress
446
+ - If yaml string contains colons, wrap the entire string in quotes to avoid yaml parsing errors
447
+ - Use | syntax for multi-line strings in yaml
448
+ - If you can start executing the task, please start directly without asking the user if you can begin.
449
+
450
+ -------------------------------------------------------------"""
451
+
452
+ def main():
453
+ """Jarvis main entry point"""
454
+ # Add argument parser
455
+ load_env_from_file()
456
+ parser = argparse.ArgumentParser(description='Jarvis AI assistant')
457
+ parser.add_argument('-f', '--files', nargs='*', help='List of files to process')
458
+ args = parser.parse_args()
459
+
460
+ try:
461
+ # 获取全局模型实例
462
+ agent = Agent(system_prompt=origin_agent_system_prompt)
463
+
464
+ # 加载预定义任务
465
+ tasks = load_tasks()
466
+ if tasks:
467
+ selected_task = select_task(tasks)
468
+ if selected_task:
469
+ PrettyOutput.print(f"\nExecute task: {selected_task}", OutputType.INFO)
470
+ agent.run(selected_task, args.files)
471
+ return 0
472
+
473
+ # 如果没有选择预定义任务,进入交互模式
474
+ while True:
475
+ try:
476
+ user_input = get_multiline_input("Please enter your task (input empty line to exit):")
477
+ if not user_input or user_input == "__interrupt__":
478
+ break
479
+ agent.run(user_input, args.files)
480
+ except Exception as e:
481
+ PrettyOutput.print(f"Error: {str(e)}", OutputType.ERROR)
482
+
483
+ except Exception as e:
484
+ PrettyOutput.print(f"Initialization error: {str(e)}", OutputType.ERROR)
485
+ return 1
486
+
487
+ return 0
488
+
489
+ if __name__ == "__main__":
490
+ exit(main())