jarvis-ai-assistant 0.1.102__py3-none-any.whl → 0.1.104__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 (55) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/agent.py +138 -117
  3. jarvis/jarvis_code_agent/code_agent.py +234 -0
  4. jarvis/{jarvis_coder → jarvis_code_agent}/file_select.py +19 -22
  5. jarvis/jarvis_code_agent/patch.py +120 -0
  6. jarvis/jarvis_code_agent/relevant_files.py +97 -0
  7. jarvis/jarvis_codebase/main.py +871 -0
  8. jarvis/jarvis_platform/main.py +5 -3
  9. jarvis/jarvis_rag/main.py +818 -0
  10. jarvis/jarvis_smart_shell/main.py +2 -2
  11. jarvis/models/ai8.py +3 -1
  12. jarvis/models/kimi.py +36 -30
  13. jarvis/models/ollama.py +17 -11
  14. jarvis/models/openai.py +15 -12
  15. jarvis/models/oyi.py +24 -7
  16. jarvis/models/registry.py +1 -25
  17. jarvis/tools/__init__.py +0 -6
  18. jarvis/tools/ask_codebase.py +96 -0
  19. jarvis/tools/ask_user.py +1 -9
  20. jarvis/tools/chdir.py +2 -37
  21. jarvis/tools/code_review.py +210 -0
  22. jarvis/tools/create_code_test_agent.py +115 -0
  23. jarvis/tools/create_ctags_agent.py +164 -0
  24. jarvis/tools/create_sub_agent.py +2 -2
  25. jarvis/tools/execute_shell.py +2 -2
  26. jarvis/tools/file_operation.py +2 -2
  27. jarvis/tools/find_in_codebase.py +78 -0
  28. jarvis/tools/git_commiter.py +68 -0
  29. jarvis/tools/methodology.py +3 -3
  30. jarvis/tools/rag.py +141 -0
  31. jarvis/tools/read_code.py +116 -0
  32. jarvis/tools/read_webpage.py +1 -1
  33. jarvis/tools/registry.py +47 -31
  34. jarvis/tools/search.py +8 -6
  35. jarvis/tools/select_code_files.py +4 -4
  36. jarvis/utils.py +375 -85
  37. {jarvis_ai_assistant-0.1.102.dist-info → jarvis_ai_assistant-0.1.104.dist-info}/METADATA +107 -32
  38. jarvis_ai_assistant-0.1.104.dist-info/RECORD +50 -0
  39. jarvis_ai_assistant-0.1.104.dist-info/entry_points.txt +11 -0
  40. jarvis/jarvis_code_agent/main.py +0 -200
  41. jarvis/jarvis_coder/git_utils.py +0 -123
  42. jarvis/jarvis_coder/patch_handler.py +0 -340
  43. jarvis/jarvis_github/main.py +0 -232
  44. jarvis/tools/create_code_sub_agent.py +0 -56
  45. jarvis/tools/execute_code_modification.py +0 -70
  46. jarvis/tools/find_files.py +0 -119
  47. jarvis/tools/generate_tool.py +0 -174
  48. jarvis/tools/thinker.py +0 -151
  49. jarvis_ai_assistant-0.1.102.dist-info/RECORD +0 -46
  50. jarvis_ai_assistant-0.1.102.dist-info/entry_points.txt +0 -6
  51. /jarvis/{jarvis_coder → jarvis_codebase}/__init__.py +0 -0
  52. /jarvis/{jarvis_github → jarvis_rag}/__init__.py +0 -0
  53. {jarvis_ai_assistant-0.1.102.dist-info → jarvis_ai_assistant-0.1.104.dist-info}/LICENSE +0 -0
  54. {jarvis_ai_assistant-0.1.102.dist-info → jarvis_ai_assistant-0.1.104.dist-info}/WHEEL +0 -0
  55. {jarvis_ai_assistant-0.1.102.dist-info → jarvis_ai_assistant-0.1.104.dist-info}/top_level.txt +0 -0
@@ -13,7 +13,7 @@ from jarvis.utils import PrettyOutput, OutputType, init_env
13
13
  def execute_command(command: str) -> None:
14
14
  """Show command and allow user to edit, then execute, Ctrl+C to cancel"""
15
15
  try:
16
- print("\nGenerated command (can be edited, press Enter to execute, Ctrl+C to cancel):")
16
+ print("Generated command (can be edited, press Enter to execute, Ctrl+C to cancel):")
17
17
  # Pre-fill input line
18
18
  readline.set_startup_hook(lambda: readline.insert_text(command))
19
19
  try:
@@ -21,7 +21,7 @@ def execute_command(command: str) -> None:
21
21
  if edited_command.strip(): # Ensure command is not empty
22
22
  os.system(edited_command)
23
23
  except KeyboardInterrupt:
24
- print("\nExecution cancelled")
24
+ print("Execution cancelled")
25
25
  finally:
26
26
  readline.set_startup_hook() # Clear pre-filled
27
27
  except Exception as e:
jarvis/models/ai8.py CHANGED
@@ -31,7 +31,9 @@ class AI8Model(BasePlatform):
31
31
 
32
32
 
33
33
  self.model_name = os.getenv("JARVIS_MODEL") or "deepseek-chat"
34
-
34
+ if self.model_name not in self.get_available_models():
35
+ PrettyOutput.print(f"Warning: The selected model {self.model_name} is not in the available list", OutputType.WARNING)
36
+
35
37
 
36
38
  def set_model_name(self, model_name: str):
37
39
  """Set model name"""
jarvis/models/kimi.py CHANGED
@@ -25,21 +25,24 @@ class KimiModel(BasePlatform):
25
25
  self.chat_id = ""
26
26
  self.api_key = os.getenv("KIMI_API_KEY")
27
27
  if not self.api_key:
28
- PrettyOutput.print("\nNeed to set KIMI_API_KEY to use Jarvis. Please follow the steps below:", OutputType.INFO)
29
- PrettyOutput.print("\n1. Get Kimi API Key:", OutputType.INFO)
30
- PrettyOutput.print(" • Visit Kimi AI platform: https://kimi.moonshot.cn", OutputType.INFO)
31
- PrettyOutput.print(" • Login to your account", OutputType.INFO)
32
- PrettyOutput.print(" • Open browser developer tools (F12 or right-click -> Inspect)", OutputType.INFO)
33
- PrettyOutput.print(" • Switch to the Network tab", OutputType.INFO)
34
- PrettyOutput.print(" • Send any message", OutputType.INFO)
35
- PrettyOutput.print(" • Find the Authorization header in the request", OutputType.INFO)
36
- PrettyOutput.print(" • Copy the token value (remove the 'Bearer ' prefix)", OutputType.INFO)
37
- PrettyOutput.print("\n2. Set environment variable:", OutputType.INFO)
38
- PrettyOutput.print(" • Method 1: Create or edit ~/.jarvis/env file:", OutputType.INFO)
39
- PrettyOutput.print(" echo 'KIMI_API_KEY=your_key_here' > ~/.jarvis/env", OutputType.INFO)
40
- PrettyOutput.print("\n Method 2: Set environment variable directly:", OutputType.INFO)
41
- PrettyOutput.print(" export KIMI_API_KEY=your_key_here", OutputType.INFO)
42
- PrettyOutput.print("\nAfter setting, run Jarvis again.", OutputType.INFO)
28
+ message = (
29
+ "Need to set KIMI_API_KEY to use Jarvis. Please follow the steps below:\n"
30
+ "1. Get Kimi API Key:\n"
31
+ " • Visit Kimi AI platform: https://kimi.moonshot.cn\n"
32
+ " • Login to your account\n"
33
+ " • Open browser developer tools (F12 or right-click -> Inspect)\n"
34
+ " • Switch to the Network tab\n"
35
+ " • Send any message\n"
36
+ " • Find the Authorization header in the request\n"
37
+ " Copy the token value (remove the 'Bearer ' prefix)\n"
38
+ "2. Set environment variable:\n"
39
+ " Method 1: Create or edit ~/.jarvis/env file:\n"
40
+ " echo 'KIMI_API_KEY=your_key_here' > ~/.jarvis/env\n"
41
+ " Method 2: Set environment variable directly:\n"
42
+ " export KIMI_API_KEY=your_key_here\n"
43
+ "After setting, run Jarvis again."
44
+ )
45
+ PrettyOutput.print(message, OutputType.INFO)
43
46
  PrettyOutput.print("KIMI_API_KEY is not set", OutputType.WARNING)
44
47
  self.auth_header = f"Bearer {self.api_key}"
45
48
  self.chat_id = ""
@@ -308,42 +311,45 @@ class KimiModel(BasePlatform):
308
311
 
309
312
  # 显示搜索结果摘要
310
313
  if search_results and not self.suppress_output:
311
- PrettyOutput.print("\n搜索结果:", OutputType.PROGRESS)
314
+ output = ["搜索结果:"]
312
315
  for result in search_results:
313
- PrettyOutput.print(f"- {result['title']}", OutputType.PROGRESS)
316
+ output.append(f"- {result['title']}")
314
317
  if result['date']:
315
- PrettyOutput.print(f" 日期: {result['date']}", OutputType.PROGRESS)
316
- PrettyOutput.print(f" 来源: {result['site_name']}", OutputType.PROGRESS)
318
+ output.append(f" 日期: {result['date']}")
319
+ output.append(f" 来源: {result['site_name']}")
317
320
  if result['snippet']:
318
- PrettyOutput.print(f" 摘要: {result['snippet']}", OutputType.PROGRESS)
319
- PrettyOutput.print(f" 链接: {result['url']}", OutputType.PROGRESS)
320
- PrettyOutput.print("", OutputType.PROGRESS)
321
+ output.append(f" 摘要: {result['snippet']}")
322
+ output.append(f" 链接: {result['url']}")
323
+ output.append("")
324
+ PrettyOutput.print("\n".join(output), OutputType.PROGRESS)
321
325
 
322
326
  # 显示引用来源
323
327
  if ref_sources and not self.suppress_output:
324
- PrettyOutput.print("\n引用来源:", OutputType.PROGRESS)
328
+ output = ["引用来源:"]
325
329
  for source in ref_sources:
326
- PrettyOutput.print(f"- [{source['ref_id']}] {source['title']} ({source['source']})", OutputType.PROGRESS)
327
- PrettyOutput.print(f" 链接: {source['url']}", OutputType.PROGRESS)
330
+ output.append(f"- [{source['ref_id']}] {source['title']} ({source['source']})")
331
+ output.append(f" 链接: {source['url']}")
328
332
  if source['abstract']:
329
- PrettyOutput.print(f" 摘要: {source['abstract']}", OutputType.PROGRESS)
333
+ output.append(f" 摘要: {source['abstract']}")
330
334
 
331
335
  # 显示相关段落
332
336
  if source['rag_segments']:
333
- PrettyOutput.print(" 相关段落:", OutputType.PROGRESS)
337
+ output.append(" 相关段落:")
334
338
  for segment in source['rag_segments']:
335
339
  text = segment.get('text', '').replace('\n', ' ').strip()
336
340
  if text:
337
- PrettyOutput.print(f" - {text}", OutputType.PROGRESS)
341
+ output.append(f" - {text}")
338
342
 
339
343
  # 显示原文引用
340
344
  origin = source['origin']
341
345
  if origin:
342
346
  text = origin.get('text', '')
343
347
  if text:
344
- PrettyOutput.print(f" 原文: {text}", OutputType.PROGRESS)
348
+ output.append(f" 原文: {text}")
345
349
 
346
- PrettyOutput.print("", OutputType.PROGRESS)
350
+ output.append("")
351
+
352
+ PrettyOutput.print("\n".join(output), OutputType.PROGRESS)
347
353
 
348
354
  PrettyOutput.print(full_response, OutputType.RESULT)
349
355
 
jarvis/models/ollama.py CHANGED
@@ -25,18 +25,24 @@ class OllamaPlatform(BasePlatform):
25
25
  available_models = [model["name"] for model in response.json().get("models", [])]
26
26
 
27
27
  if not available_models:
28
- PrettyOutput.print("\nNeed to download Ollama model first to use:", OutputType.INFO)
29
- PrettyOutput.print("1. Install Ollama: https://ollama.ai", OutputType.INFO)
30
- PrettyOutput.print("2. Download model:", OutputType.INFO)
31
- PrettyOutput.print(f" ollama pull {self.model_name}", OutputType.INFO)
28
+ message = (
29
+ "Need to download Ollama model first to use:\n"
30
+ "1. Install Ollama: https://ollama.ai\n"
31
+ "2. Download model:\n"
32
+ f" ollama pull {self.model_name}"
33
+ )
34
+ PrettyOutput.print(message, OutputType.INFO)
32
35
  PrettyOutput.print("Ollama has no available models", OutputType.WARNING)
33
36
 
34
37
  except requests.exceptions.ConnectionError:
35
- PrettyOutput.print("\nOllama service is not started or cannot be connected", OutputType.WARNING)
36
- PrettyOutput.print("Please ensure that you have:", OutputType.INFO)
37
- PrettyOutput.print("1. Installed Ollama: https://ollama.ai", OutputType.INFO)
38
- PrettyOutput.print("2. Started Ollama service", OutputType.INFO)
39
- PrettyOutput.print("3. Service address configured correctly (default: http://localhost:11434)", OutputType.INFO)
38
+ message = (
39
+ "Ollama service is not started or cannot be connected\n"
40
+ "Please ensure that you have:\n"
41
+ "1. Installed Ollama: https://ollama.ai\n"
42
+ "2. Started Ollama service\n"
43
+ "3. Service address configured correctly (default: http://localhost:11434)"
44
+ )
45
+ PrettyOutput.print(message, OutputType.WARNING)
40
46
 
41
47
 
42
48
  self.messages = []
@@ -136,10 +142,10 @@ if __name__ == "__main__":
136
142
  ollama = OllamaPlatform()
137
143
  while True:
138
144
  try:
139
- message = get_single_line_input("\nInput question (Ctrl+C to exit)")
145
+ message = get_single_line_input("Input question (Ctrl+C to exit)")
140
146
  ollama.chat_until_success(message)
141
147
  except KeyboardInterrupt:
142
- print("\nGoodbye!")
148
+ print("Goodbye!")
143
149
  break
144
150
  except Exception as e:
145
151
  PrettyOutput.print(f"Program exited with an exception: {str(e)}", OutputType.ERROR)
jarvis/models/openai.py CHANGED
@@ -19,18 +19,21 @@ class OpenAIModel(BasePlatform):
19
19
  self.system_message = ""
20
20
  self.api_key = os.getenv("OPENAI_API_KEY")
21
21
  if not self.api_key:
22
- PrettyOutput.print("\nNeed to set the following environment variables to use OpenAI model:", OutputType.INFO)
23
- PrettyOutput.print(" OPENAI_API_KEY: API key", OutputType.INFO)
24
- PrettyOutput.print(" • OPENAI_API_BASE: (optional) API base address, default using https://api.openai.com/v1", OutputType.INFO)
25
- PrettyOutput.print("\nYou can set them in the following ways:", OutputType.INFO)
26
- PrettyOutput.print("1. Create or edit ~/.jarvis/env file:", OutputType.INFO)
27
- PrettyOutput.print(" OPENAI_API_KEY=your_api_key", OutputType.INFO)
28
- PrettyOutput.print(" OPENAI_API_BASE=your_api_base", OutputType.INFO)
29
- PrettyOutput.print(" OPENAI_MODEL_NAME=your_model_name", OutputType.INFO)
30
- PrettyOutput.print("\n2. Or set the environment variables directly:", OutputType.INFO)
31
- PrettyOutput.print(" export OPENAI_API_KEY=your_api_key", OutputType.INFO)
32
- PrettyOutput.print(" export OPENAI_API_BASE=your_api_base", OutputType.INFO)
33
- PrettyOutput.print(" export OPENAI_MODEL_NAME=your_model_name", OutputType.INFO)
22
+ message = (
23
+ "Need to set the following environment variables to use OpenAI model:\n"
24
+ " • OPENAI_API_KEY: API key\n"
25
+ " OPENAI_API_BASE: (optional) API base address, default using https://api.openai.com/v1\n"
26
+ "You can set them in the following ways:\n"
27
+ "1. Create or edit ~/.jarvis/env file:\n"
28
+ " OPENAI_API_KEY=your_api_key\n"
29
+ " OPENAI_API_BASE=your_api_base\n"
30
+ " OPENAI_MODEL_NAME=your_model_name\n"
31
+ "2. Or set the environment variables directly:\n"
32
+ " export OPENAI_API_KEY=your_api_key\n"
33
+ " export OPENAI_API_BASE=your_api_base\n"
34
+ " export OPENAI_MODEL_NAME=your_model_name"
35
+ )
36
+ PrettyOutput.print(message, OutputType.INFO)
34
37
  PrettyOutput.print("OPENAI_API_KEY is not set", OutputType.WARNING)
35
38
 
36
39
  self.base_url = os.getenv("OPENAI_API_BASE", "https://api.openai.com/v1")
jarvis/models/oyi.py CHANGED
@@ -32,6 +32,9 @@ class OyiModel(BasePlatform):
32
32
  PrettyOutput.print("OYI_API_KEY is not set", OutputType.WARNING)
33
33
 
34
34
  self.model_name = os.getenv("JARVIS_MODEL") or "deepseek-chat"
35
+ if self.model_name not in [m.split()[0] for m in self.get_available_models()]:
36
+ PrettyOutput.print(f"Warning: The selected model {self.model_name} is not in the available list", OutputType.WARNING)
37
+
35
38
 
36
39
  def set_model_name(self, model_name: str):
37
40
  """Set model name"""
@@ -63,7 +66,7 @@ class OyiModel(BasePlatform):
63
66
  "requestMsgCount": 65536,
64
67
  "temperature": 0.8,
65
68
  "speechVoice": "Alloy",
66
- "max_tokens": get_max_context_length(),
69
+ "max_tokens": 8192,
67
70
  "chatPluginIds": []
68
71
  })
69
72
  }
@@ -168,19 +171,33 @@ class OyiModel(BasePlatform):
168
171
  # 获取响应内容
169
172
  response = requests.post(
170
173
  f"{self.BASE_URL}/chatapi/chat/message/{message_id}",
171
- headers=headers
174
+ headers=headers,
175
+ stream=True
172
176
  )
173
177
 
174
178
  if response.status_code == 200:
175
- if not self.suppress_output:
176
- PrettyOutput.print(response.text, OutputType.SYSTEM)
177
- self.messages.append({"role": "assistant", "content": response.text})
178
- return response.text
179
+ full_response = ""
180
+ bin = b""
181
+ for chunk in response.iter_content(decode_unicode=True):
182
+ if chunk:
183
+ bin += chunk
184
+ try:
185
+ text = bin.decode('utf-8')
186
+ except UnicodeDecodeError:
187
+ continue
188
+ if not self.suppress_output:
189
+ PrettyOutput.print_stream(text)
190
+ full_response += text
191
+ bin = b""
192
+
193
+ PrettyOutput.print_stream_end()
194
+
195
+ self.messages.append({"role": "assistant", "content": full_response})
196
+ return full_response
179
197
  else:
180
198
  error_msg = f"Get response failed: {response.status_code}"
181
199
  PrettyOutput.print(error_msg, OutputType.ERROR)
182
200
  raise Exception(error_msg)
183
-
184
201
  except Exception as e:
185
202
  PrettyOutput.print(f"Chat failed: {str(e)}", OutputType.ERROR)
186
203
  raise e
jarvis/models/registry.py CHANGED
@@ -211,31 +211,7 @@ class PlatformRegistry:
211
211
  except Exception as e:
212
212
  PrettyOutput.print(f"Create platform failed: {str(e)}", OutputType.ERROR)
213
213
  return None
214
-
215
- def use_platforms(self, platform_names: List[str]):
216
- """Restrict available platforms to the specified list
217
-
218
- Args:
219
- platform_names: List of platform names to use
220
- """
221
- self.platforms = {
222
- name: cls
223
- for name, cls in self.platforms.items()
224
- if name in platform_names
225
- }
226
214
 
227
- def dont_use_platforms(self, platform_names: List[str]):
228
- """Restrict available platforms by excluding the specified list
229
-
230
- Args:
231
- platform_names: List of platform names to exclude
232
- """
233
- self.platforms = {
234
- name: cls
235
- for name, cls in self.platforms.items()
236
- if name not in platform_names
237
- }
238
215
  def get_available_platforms(self) -> List[str]:
239
216
  """Get available platform list"""
240
- return list(self.platforms.keys())
241
-
217
+ return list(self.platforms.keys())
jarvis/tools/__init__.py CHANGED
@@ -1,6 +0,0 @@
1
- from .registry import ToolRegistry
2
-
3
- __all__ = [
4
- 'ToolRegistry',
5
- ]
6
-
@@ -0,0 +1,96 @@
1
+ from typing import Dict, Any
2
+ from jarvis.utils import OutputType, PrettyOutput, dont_use_local_model, find_git_root
3
+ from jarvis.jarvis_codebase.main import CodeBase
4
+
5
+ class AskCodebaseTool:
6
+ """Tool for intelligent codebase querying and analysis using CodeBase"""
7
+
8
+ name = "ask_codebase"
9
+ description = "Ask questions about the codebase and get detailed analysis"
10
+ parameters = {
11
+ "type": "object",
12
+ "properties": {
13
+ "question": {
14
+ "type": "string",
15
+ "description": "Question about the codebase"
16
+ },
17
+ "top_k": {
18
+ "type": "integer",
19
+ "description": "Number of most relevant files to analyze (optional)",
20
+ "default": 20
21
+ }
22
+ },
23
+ "required": ["question"]
24
+ }
25
+
26
+ @staticmethod
27
+ def check() -> bool:
28
+ return not dont_use_local_model()
29
+
30
+ def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
31
+ """Execute codebase analysis using CodeBase
32
+
33
+ Args:
34
+ args: Dictionary containing:
35
+ - question: The question to answer
36
+ - top_k: Optional number of files to analyze
37
+
38
+ Returns:
39
+ Dict containing:
40
+ - success: Boolean indicating success
41
+ - stdout: Analysis result
42
+ - stderr: Error message if any
43
+ """
44
+ try:
45
+ question = args["question"]
46
+ top_k = args.get("top_k", 20)
47
+
48
+ PrettyOutput.print(f"Analyzing codebase for question: {question}", OutputType.INFO)
49
+
50
+ # Create new CodeBase instance
51
+ git_root = find_git_root()
52
+ codebase = CodeBase(git_root)
53
+
54
+ # Use ask_codebase method
55
+ response = codebase.ask_codebase(question, top_k)
56
+
57
+ return {
58
+ "success": True,
59
+ "stdout": response,
60
+ "stderr": ""
61
+ }
62
+
63
+ except Exception as e:
64
+ error_msg = f"Failed to analyze codebase: {str(e)}"
65
+ PrettyOutput.print(error_msg, OutputType.ERROR)
66
+ return {
67
+ "success": False,
68
+ "stdout": "",
69
+ "stderr": error_msg
70
+ }
71
+
72
+
73
+ def main():
74
+ """Command line interface for the tool"""
75
+ import argparse
76
+
77
+ parser = argparse.ArgumentParser(description='Ask questions about the codebase')
78
+ parser.add_argument('question', help='Question about the codebase')
79
+ parser.add_argument('--top-k', type=int, help='Number of files to analyze', default=20)
80
+
81
+ args = parser.parse_args()
82
+
83
+ tool = AskCodebaseTool()
84
+ result = tool.execute({
85
+ "question": args.question,
86
+ "top_k": args.top_k
87
+ })
88
+
89
+ if result["success"]:
90
+ PrettyOutput.print(result["stdout"], OutputType.INFO, lang="markdown")
91
+ else:
92
+ PrettyOutput.print(result["stderr"], OutputType.ERROR)
93
+
94
+
95
+ if __name__ == "__main__":
96
+ main()
jarvis/tools/ask_user.py CHANGED
@@ -30,19 +30,11 @@ class AskUserTool:
30
30
  question = args["question"]
31
31
 
32
32
  # Display the question
33
- PrettyOutput.print("\nQuestion:", OutputType.SYSTEM)
34
- PrettyOutput.print(question, OutputType.SYSTEM)
33
+ PrettyOutput.print(f"Question: {question}", OutputType.SYSTEM)
35
34
 
36
35
  # Get user input
37
36
  user_response = get_multiline_input("Please enter your answer (input empty line to end)")
38
37
 
39
- if user_response == "__interrupt__":
40
- return {
41
- "success": False,
42
- "stdout": "",
43
- "stderr": "User canceled input"
44
- }
45
-
46
38
  return {
47
39
  "success": True,
48
40
  "stdout": user_response,
jarvis/tools/chdir.py CHANGED
@@ -3,8 +3,6 @@ import os
3
3
  from jarvis.utils import PrettyOutput, OutputType
4
4
 
5
5
  class ChdirTool:
6
- """修改当前工作目录的工具"""
7
-
8
6
  name = "chdir"
9
7
  description = "Change current working directory"
10
8
  parameters = {
@@ -19,22 +17,10 @@ class ChdirTool:
19
17
  }
20
18
 
21
19
  def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
22
- """执行目录切换
23
-
24
- Args:
25
- args: 包含 path 参数的字典
26
-
27
- Returns:
28
- 执行结果字典,包含:
29
- - success: 是否成功
30
- - stdout: 成功时的输出信息
31
- - error: 失败时的错误信息
32
- """
33
20
  try:
34
- path = os.path.expanduser(args["path"]) # 展开 ~ 等路径
35
- path = os.path.abspath(path) # 转换为绝对路径
21
+ path = os.path.expanduser(args["path"].strip())
22
+ path = os.path.abspath(path)
36
23
 
37
- # 检查目录是否存在
38
24
  if not os.path.exists(path):
39
25
  return {
40
26
  "success": False,
@@ -42,7 +28,6 @@ class ChdirTool:
42
28
  "stderr": f"Directory does not exist: {path}"
43
29
  }
44
30
 
45
- # 检查是否是目录
46
31
  if not os.path.isdir(path):
47
32
  return {
48
33
  "success": False,
@@ -50,7 +35,6 @@ class ChdirTool:
50
35
  "stderr": f"The path is not a directory: {path}"
51
36
  }
52
37
 
53
- # 尝试切换目录
54
38
  old_path = os.getcwd()
55
39
  os.chdir(path)
56
40
 
@@ -72,22 +56,3 @@ class ChdirTool:
72
56
  "stdout": "",
73
57
  "stderr": f"Failed to switch directory: {str(e)}"
74
58
  }
75
-
76
- def main():
77
- """命令行直接运行工具"""
78
- import argparse
79
-
80
- parser = argparse.ArgumentParser(description='Change current working directory')
81
- parser.add_argument('path', help='Directory path to switch to, supports both relative and absolute paths')
82
- args = parser.parse_args()
83
-
84
- tool = ChdirTool()
85
- result = tool.execute({"path": args.path})
86
-
87
- if result["success"]:
88
- PrettyOutput.print(result["stdout"], OutputType.SUCCESS)
89
- else:
90
- PrettyOutput.print(result["stderr"], OutputType.ERROR)
91
-
92
- if __name__ == "__main__":
93
- main()