jarvis-ai-assistant 0.1.115__py3-none-any.whl → 0.1.117__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 (51) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/{agent.py → jarvis_agent/__init__.py} +122 -203
  3. jarvis/jarvis_agent/output_handler.py +23 -0
  4. jarvis/jarvis_code_agent/code_agent.py +113 -100
  5. jarvis/jarvis_code_agent/file_select.py +28 -7
  6. jarvis/jarvis_code_agent/patch.py +80 -2
  7. jarvis/jarvis_code_agent/relevant_files.py +82 -42
  8. jarvis/jarvis_codebase/main.py +53 -25
  9. jarvis/jarvis_dev/main.py +719 -547
  10. jarvis/jarvis_lsp/cpp.py +1 -1
  11. jarvis/jarvis_lsp/go.py +1 -1
  12. jarvis/jarvis_lsp/registry.py +1 -1
  13. jarvis/jarvis_lsp/rust.py +1 -1
  14. jarvis/jarvis_multi_agent/__init__.py +170 -0
  15. jarvis/jarvis_platform/ai8.py +2 -2
  16. jarvis/jarvis_platform/base.py +14 -4
  17. jarvis/jarvis_platform/kimi.py +2 -2
  18. jarvis/jarvis_platform/ollama.py +1 -1
  19. jarvis/jarvis_platform/openai.py +1 -1
  20. jarvis/jarvis_platform/oyi.py +1 -1
  21. jarvis/jarvis_platform/registry.py +1 -1
  22. jarvis/jarvis_platform_manager/main.py +422 -6
  23. jarvis/jarvis_platform_manager/openai_test.py +139 -0
  24. jarvis/jarvis_rag/main.py +57 -20
  25. jarvis/jarvis_smart_shell/main.py +55 -29
  26. jarvis/jarvis_tools/ask_codebase.py +1 -1
  27. jarvis/jarvis_tools/ask_user.py +1 -1
  28. jarvis/jarvis_tools/chdir.py +1 -1
  29. jarvis/jarvis_tools/code_review.py +3 -3
  30. jarvis/jarvis_tools/create_code_agent.py +1 -1
  31. jarvis/jarvis_tools/create_sub_agent.py +2 -2
  32. jarvis/jarvis_tools/execute_shell.py +1 -1
  33. jarvis/jarvis_tools/file_operation.py +16 -14
  34. jarvis/jarvis_tools/git_commiter.py +2 -2
  35. jarvis/jarvis_tools/methodology.py +1 -1
  36. jarvis/jarvis_tools/rag.py +1 -1
  37. jarvis/jarvis_tools/read_code.py +19 -8
  38. jarvis/jarvis_tools/read_webpage.py +1 -1
  39. jarvis/jarvis_tools/registry.py +157 -31
  40. jarvis/jarvis_tools/search.py +1 -1
  41. jarvis/jarvis_tools/select_code_files.py +1 -1
  42. jarvis/{utils.py → jarvis_utils/__init__.py} +69 -53
  43. {jarvis_ai_assistant-0.1.115.dist-info → jarvis_ai_assistant-0.1.117.dist-info}/METADATA +1 -1
  44. jarvis_ai_assistant-0.1.117.dist-info/RECORD +65 -0
  45. {jarvis_ai_assistant-0.1.115.dist-info → jarvis_ai_assistant-0.1.117.dist-info}/WHEEL +1 -1
  46. {jarvis_ai_assistant-0.1.115.dist-info → jarvis_ai_assistant-0.1.117.dist-info}/entry_points.txt +1 -1
  47. jarvis/multi_agent.py +0 -76
  48. jarvis/utils/date_utils.py +0 -19
  49. jarvis_ai_assistant-0.1.115.dist-info/RECORD +0 -64
  50. {jarvis_ai_assistant-0.1.115.dist-info → jarvis_ai_assistant-0.1.117.dist-info}/LICENSE +0 -0
  51. {jarvis_ai_assistant-0.1.115.dist-info → jarvis_ai_assistant-0.1.117.dist-info}/top_level.txt +0 -0
jarvis/jarvis_rag/main.py CHANGED
@@ -3,8 +3,8 @@ import numpy as np
3
3
  import faiss
4
4
  from typing import List, Tuple, Optional, Dict
5
5
  import pickle
6
- from jarvis.utils import OutputType, PrettyOutput, get_context_token_count, get_embedding, get_embedding_batch, get_file_md5, get_max_token_count, get_max_paragraph_length, get_min_paragraph_length, get_thread_count, init_gpu_config, load_embedding_model
7
- from jarvis.utils import init_env
6
+ from jarvis.jarvis_utils import OutputType, PrettyOutput, get_context_token_count, get_embedding, get_embedding_batch, get_file_md5, get_max_token_count, get_max_paragraph_length, get_min_paragraph_length, get_thread_count, init_gpu_config, load_embedding_model
7
+ from jarvis.jarvis_utils import init_env
8
8
  from dataclasses import dataclass
9
9
  from tqdm import tqdm
10
10
  import fitz # PyMuPDF for PDF files
@@ -642,32 +642,64 @@ class RAGTool:
642
642
  def ask(self, question: str) -> Optional[str]:
643
643
  """Ask questions about documents with enhanced context building"""
644
644
  try:
645
- # 搜索相关文档
646
645
  results = self.search(question)
647
646
  if not results:
648
647
  return None
649
648
 
650
- # 构建提示词
651
- prompt = f"""Based on the following document fragments, please answer the user's question accurately and comprehensively.
652
-
649
+ prompt = f"""
650
+ # 🤖 Role Definition
651
+ You are a document analysis expert who provides accurate and comprehensive answers based on provided documents.
652
+
653
+ # 🎯 Core Responsibilities
654
+ - Analyze document fragments thoroughly
655
+ - Answer questions accurately
656
+ - Reference source documents
657
+ - Identify missing information
658
+ - Maintain professional tone
659
+
660
+ # 📋 Answer Requirements
661
+ ## Content Quality
662
+ - Base answers strictly on provided documents
663
+ - Be specific and precise
664
+ - Include relevant quotes when helpful
665
+ - Indicate any information gaps
666
+ - Use professional language
667
+
668
+ ## Answer Structure
669
+ 1. Direct Answer
670
+ - Clear and concise response
671
+ - Based on document evidence
672
+ - Professional terminology
673
+
674
+ 2. Supporting Details
675
+ - Relevant document quotes
676
+ - File references
677
+ - Context explanation
678
+
679
+ 3. Information Gaps (if any)
680
+ - Missing information
681
+ - Additional context needed
682
+ - Potential limitations
683
+
684
+ # 🔍 Analysis Context
653
685
  Question: {question}
654
686
 
655
- Relevant documents (ordered by relevance):
687
+ Relevant Documents (by relevance):
656
688
  """
657
- # 添加上下文,控制长度
689
+
690
+ # Add context with length control
658
691
  available_count = self.max_token_count - get_context_token_count(prompt) - 1000
659
692
  current_count = 0
660
693
 
661
694
  for doc, score in results:
662
695
  doc_content = f"""
663
- [Score: {score:.3f}] {doc.metadata['file_path']}:
696
+ ## Document Fragment [Score: {score:.3f}]
697
+ Source: {doc.metadata['file_path']}
698
+ ```
664
699
  {doc.content}
700
+ ```
665
701
  ---
666
702
  """
667
- prompt += "Answer Format:\n"
668
- prompt += "1. Answer the question accurately and comprehensively.\n"
669
- prompt += "2. If the documents don't fully answer the question, please indicate what information is missing.\n"
670
- prompt += "3. Reference the documents in the answer.\n"
671
703
  if current_count + get_context_token_count(doc_content) > available_count:
672
704
  PrettyOutput.print(
673
705
  "由于上下文长度限制,部分内容被省略",
@@ -677,14 +709,19 @@ Relevant documents (ordered by relevance):
677
709
 
678
710
  prompt += doc_content
679
711
  current_count += get_context_token_count(doc_content)
680
-
681
- prompt += "\nIf the documents don't fully answer the question, please indicate what information is missing."
682
-
683
- # 使用 normal 平台处理文档问答
712
+
713
+ prompt += """
714
+ # ❗ Important Rules
715
+ 1. Only use provided documents
716
+ 2. Be precise and accurate
717
+ 3. Quote sources when relevant
718
+ 4. Indicate missing information
719
+ 5. Maintain professional tone
720
+ 6. Answer in user's language
721
+ """
722
+
684
723
  model = PlatformRegistry.get_global_platform_registry().get_normal_platform()
685
- response = model.chat_until_success(prompt)
686
-
687
- return response
724
+ return model.chat_until_success(prompt)
688
725
 
689
726
  except Exception as e:
690
727
  PrettyOutput.print(f"回答失败:{str(e)}", OutputType.ERROR)
@@ -8,7 +8,7 @@ from yaspin import yaspin # type: ignore
8
8
  from yaspin.spinners import Spinners # type: ignore
9
9
 
10
10
  from jarvis.jarvis_platform.registry import PlatformRegistry
11
- from jarvis.utils import PrettyOutput, OutputType, get_shell_name, init_env
11
+ from jarvis.jarvis_utils import PrettyOutput, OutputType, get_multiline_input, get_shell_name, init_env
12
12
 
13
13
  def execute_command(command: str) -> None:
14
14
  """Show command and allow user to edit, then execute, Ctrl+C to cancel"""
@@ -46,43 +46,63 @@ def process_request(request: str) -> Optional[str]:
46
46
  current_path = os.getcwd()
47
47
 
48
48
  # Set system prompt
49
- system_message = f"""You are a shell command generation assistant.
49
+ system_message = """
50
+ # 🤖 Role Definition
51
+ You are a shell command generation expert who converts natural language requirements into precise shell commands.
50
52
 
51
- Your only task is to convert user's natural language requirements into corresponding shell commands.
53
+ # 🎯 Core Responsibilities
54
+ - Convert natural language to shell commands
55
+ - Generate accurate and efficient commands
56
+ - Follow strict output format rules
57
+ - Maintain command simplicity
52
58
 
53
- Strict requirements:
54
- 1. Only return the shell command itself
55
- 2. Do not add any markers (like ```, /**/, // etc.)
56
- 3. Do not add any explanations or descriptions
57
- 4. Do not add any line breaks or extra spaces
58
- 5. If multiple commands are needed, connect them with &&
59
+ # 📋 Output Requirements
60
+ ## Format Rules
61
+ 1. Return ONLY the command
62
+ 2. NO markers (```, /*, //)
63
+ 3. NO explanations
64
+ 4. NO line breaks
65
+ 5. NO extra spaces
66
+ 6. Multiple commands: use &&
59
67
 
60
- Example input:
61
- "Find all Python files in the current directory"
68
+ ## Command Style
69
+ - Use standard shell syntax
70
+ - Keep commands concise
71
+ - Follow best practices
72
+ - Ensure proper quoting
73
+ - Handle spaces correctly
62
74
 
63
- Example output:
64
- find . -name "*.py"
75
+ # 📝 Example Format
76
+ Input: "Find all Python files in the current directory"
77
+ Output: find . -name "*.py"
65
78
 
66
- Remember: Only return the command itself, without any additional content.
79
+ # Critical Rules
80
+ 1. ONLY output the command
81
+ 2. NO additional content
82
+ 3. NO formatting markers
83
+ 4. NO explanations
84
+ 5. ONE line only
85
+
86
+ # 💡 Command Guidelines
87
+ - Use standard tools
88
+ - Prefer portable syntax
89
+ - Handle edge cases
90
+ - Escape special chars
91
+ - Quote when needed
67
92
  """
68
93
  model.set_system_message(system_message)
69
94
 
70
95
  prefix = f"Current path: {current_path}\n"
71
96
  prefix += f"Current shell: {shell}\n"
72
97
 
73
- # 使用yaspin显示Thinking状态
74
- with yaspin(Spinners.dots, text="Thinking", color="yellow") as spinner:
75
- # 处理请求
76
- result = model.chat_until_success(prefix + request)
77
-
78
- # 提取命令
79
- if result and isinstance(result, str):
80
- command = result.strip()
81
- spinner.ok("✓")
82
- return command
83
-
84
- spinner.fail("✗")
85
- return None
98
+ result = model.chat_until_success(prefix + request)
99
+
100
+ # 提取命令
101
+ if result and isinstance(result, str):
102
+ command = result.strip()
103
+ return command
104
+
105
+ return None
86
106
 
87
107
  except Exception as e:
88
108
  PrettyOutput.print(f"处理请求失败: {str(e)}", OutputType.WARNING)
@@ -101,15 +121,21 @@ Example:
101
121
  %(prog)s "Find documents modified in the last week"
102
122
  """)
103
123
 
104
- # 添加参数
124
+ # 修改为可选参数,添加从stdin读取的支持
105
125
  parser.add_argument(
106
126
  "request",
107
- help="描述您想要执行的操作, 用自然语言描述"
127
+ nargs='?', # 设置为可选参数
128
+ help="描述您想要执行的操作(用自然语言描述),如果未提供则从标准输入读取"
108
129
  )
109
130
 
110
131
  # 解析参数
111
132
  args = parser.parse_args()
112
133
 
134
+ # 添加标准输入处理
135
+ if not args.request:
136
+ # 检查是否在交互式终端中运行
137
+ args.request = get_multiline_input(tip="请输入您要执行的功能:")
138
+
113
139
  # 处理请求
114
140
  command = process_request(args.request)
115
141
 
@@ -1,5 +1,5 @@
1
1
  from typing import Dict, Any
2
- from jarvis.utils import OutputType, PrettyOutput, dont_use_local_model, find_git_root
2
+ from jarvis.jarvis_utils import OutputType, PrettyOutput, dont_use_local_model, find_git_root
3
3
  from jarvis.jarvis_codebase.main import CodeBase
4
4
 
5
5
  class AskCodebaseTool:
@@ -1,6 +1,6 @@
1
1
  from typing import Dict, Any
2
2
  from jarvis.jarvis_tools.base import Tool
3
- from jarvis.utils import get_multiline_input, PrettyOutput, OutputType
3
+ from jarvis.jarvis_utils import get_multiline_input, PrettyOutput, OutputType
4
4
 
5
5
  class AskUserTool:
6
6
  name="ask_user"
@@ -1,6 +1,6 @@
1
1
  from typing import Dict, Any
2
2
  import os
3
- from jarvis.utils import PrettyOutput, OutputType
3
+ from jarvis.jarvis_utils import PrettyOutput, OutputType
4
4
 
5
5
  class ChdirTool:
6
6
  name = "chdir"
@@ -3,8 +3,8 @@ import subprocess
3
3
  import yaml
4
4
  from jarvis.jarvis_platform.registry import PlatformRegistry
5
5
  from jarvis.jarvis_tools.registry import ToolRegistry
6
- from jarvis.utils import OutputType, PrettyOutput, init_env, find_git_root
7
- from jarvis.agent import Agent
6
+ from jarvis.jarvis_utils import OutputType, PrettyOutput, init_env, find_git_root
7
+ from jarvis.jarvis_agent import Agent
8
8
  import re
9
9
 
10
10
  class CodeReviewTool:
@@ -168,7 +168,7 @@ OUTPUT REQUIREMENTS:
168
168
  suggestion: # Specific, actionable improvements for the observed code
169
169
  </REPORT>""",
170
170
  is_sub_agent=True,
171
- tool_registry=tool_registry,
171
+ output_handler=[tool_registry],
172
172
  platform=PlatformRegistry().get_thinking_platform(),
173
173
  auto_complete=True
174
174
  )
@@ -3,7 +3,7 @@ from typing import Dict, Any
3
3
  from jarvis.jarvis_code_agent.code_agent import CodeAgent
4
4
  from jarvis.jarvis_tools.git_commiter import GitCommitTool
5
5
  from jarvis.jarvis_tools.code_review import CodeReviewTool, extract_code_report
6
- from jarvis.utils import OutputType, PrettyOutput, has_uncommitted_changes
6
+ from jarvis.jarvis_utils import OutputType, PrettyOutput, has_uncommitted_changes
7
7
 
8
8
  class CreateCodeAgentTool:
9
9
  """Tool for managing the code development workflow."""
@@ -1,9 +1,9 @@
1
1
  from typing import Dict, Any
2
2
 
3
3
 
4
- from jarvis.agent import Agent, origin_agent_system_prompt
4
+ from jarvis.jarvis_agent import Agent, origin_agent_system_prompt
5
5
  from jarvis.jarvis_tools.registry import ToolRegistry
6
- from jarvis.utils import OutputType, PrettyOutput
6
+ from jarvis.jarvis_utils import OutputType, PrettyOutput
7
7
 
8
8
 
9
9
  class SubAgentTool:
@@ -3,7 +3,7 @@ import os
3
3
  import tempfile
4
4
  from pathlib import Path
5
5
 
6
- from jarvis.utils import OutputType, PrettyOutput
6
+ from jarvis.jarvis_utils import OutputType, PrettyOutput
7
7
 
8
8
 
9
9
  class ShellTool:
@@ -1,7 +1,7 @@
1
1
  from typing import Dict, Any, List, Union
2
2
  import os
3
3
 
4
- from jarvis.utils import OutputType, PrettyOutput
4
+ from jarvis.jarvis_utils import OutputType, PrettyOutput
5
5
 
6
6
 
7
7
  class FileOperationTool:
@@ -38,25 +38,27 @@ class FileOperationTool:
38
38
  PrettyOutput.print(f"文件操作: {operation} - {abs_path}", OutputType.INFO)
39
39
 
40
40
  if operation == "read":
41
- if not os.path.exists(filepath):
41
+ if not os.path.exists(abs_path):
42
+ PrettyOutput.print(f"文件不存在: {abs_path}", OutputType.WARNING)
42
43
  return {
43
44
  "success": False,
44
45
  "stdout": "",
45
- "stderr": f"文件不存在: {filepath}"
46
+ "stderr": f"文件不存在: {abs_path}"
46
47
  }
47
48
 
48
- if os.path.getsize(filepath) > 10 * 1024 * 1024: # 10MB
49
+ if os.path.getsize(abs_path) > 10 * 1024 * 1024: # 10MB
50
+ PrettyOutput.print(f"文件太大: {abs_path}", OutputType.WARNING)
49
51
  return {
50
52
  "success": False,
51
53
  "stdout": "",
52
54
  "stderr": "File too large (>10MB)"
53
55
  }
54
56
 
55
- content = open(filepath, 'r', encoding='utf-8').read()
56
- output = f"File: {filepath}\n{content}"
57
+ content = open(abs_path, 'r', encoding='utf-8').read()
58
+ output = f"File: {abs_path}\n{content}"
57
59
 
58
60
  # Print file content
59
- PrettyOutput.print(f"读取文件: {filepath}\n{content}", OutputType.INFO)
61
+ PrettyOutput.print(f"读取文件: {abs_path}\n{content}", OutputType.INFO)
60
62
 
61
63
  return {
62
64
  "success": True,
@@ -65,17 +67,17 @@ class FileOperationTool:
65
67
  }
66
68
 
67
69
  elif operation == "write":
68
- os.makedirs(os.path.dirname(os.path.abspath(filepath)), exist_ok=True)
69
- with open(filepath, 'w', encoding='utf-8') as f:
70
+ os.makedirs(os.path.dirname(os.path.abspath(abs_path)), exist_ok=True)
71
+ with open(abs_path, 'w', encoding='utf-8') as f:
70
72
  f.write(content)
71
73
 
72
- PrettyOutput.print(f"写入文件: {filepath}", OutputType.INFO)
74
+ PrettyOutput.print(f"写入文件: {abs_path}", OutputType.INFO)
73
75
  return {
74
76
  "success": True,
75
- "stdout": f"Successfully wrote content to {filepath}",
77
+ "stdout": f"Successfully wrote content to {abs_path}",
76
78
  "stderr": ""
77
79
  }
78
-
80
+ PrettyOutput.print(f"未知操作: {operation}", OutputType.WARNING)
79
81
  return {
80
82
  "success": False,
81
83
  "stdout": "",
@@ -87,7 +89,7 @@ class FileOperationTool:
87
89
  return {
88
90
  "success": False,
89
91
  "stdout": "",
90
- "stderr": f"File operation failed for {filepath}: {str(e)}"
92
+ "stderr": f"File operation failed for {abs_path}: {str(e)}"
91
93
  }
92
94
 
93
95
  def execute(self, args: Dict) -> Dict[str, Any]:
@@ -120,7 +122,7 @@ class FileOperationTool:
120
122
  continue
121
123
 
122
124
  content = file_info.get("content", "") if operation == "write" else ""
123
- result = self._handle_single_file(operation, file_info["path"], content)
125
+ result = self._handle_single_file(operation, file_info["path"].strip(), content)
124
126
 
125
127
  if result["success"]:
126
128
  all_outputs.append(result["stdout"])
@@ -4,7 +4,7 @@ from typing import Dict, Any
4
4
 
5
5
  import yaml
6
6
  from jarvis.jarvis_platform.registry import PlatformRegistry
7
- from jarvis.utils import OutputType, PrettyOutput, has_uncommitted_changes, init_env
7
+ from jarvis.jarvis_utils import OutputType, PrettyOutput, has_uncommitted_changes, init_env
8
8
  import sys
9
9
 
10
10
 
@@ -53,7 +53,7 @@ class GitCommitTool:
53
53
 
54
54
  commit_hash = self._get_last_commit_hash()
55
55
 
56
- PrettyOutput.section(f"提交哈希: {commit_hash}\n提交消息: {commit_message}", OutputType.SUCCESS)
56
+ PrettyOutput.print(f"提交哈希: {commit_hash}\n提交消息: {commit_message}", OutputType.SUCCESS)
57
57
 
58
58
  return {"success": True, "stdout": yaml.safe_dump({"commit_hash": commit_hash, "commit_message": commit_message}), "stderr": ""}
59
59
 
@@ -1,7 +1,7 @@
1
1
  import os
2
2
  import yaml
3
3
  from typing import Dict, Optional, Any
4
- from jarvis.utils import OutputType, PrettyOutput, is_use_methodology
4
+ from jarvis.jarvis_utils import OutputType, PrettyOutput, is_use_methodology
5
5
 
6
6
 
7
7
  class MethodologyTool:
@@ -1,6 +1,6 @@
1
1
  from typing import Dict, Any
2
2
  import os
3
- from jarvis.utils import OutputType, PrettyOutput, dont_use_local_model
3
+ from jarvis.jarvis_utils import OutputType, PrettyOutput, dont_use_local_model
4
4
  from jarvis.jarvis_rag.main import RAGTool as RAGCore
5
5
 
6
6
  class RAGTool:
@@ -1,6 +1,6 @@
1
1
  from typing import Dict, Any, List
2
2
  import os
3
- from jarvis.utils import OutputType, PrettyOutput
3
+ from jarvis.jarvis_utils import OutputType, PrettyOutput
4
4
 
5
5
 
6
6
  class ReadCodeTool:
@@ -51,17 +51,19 @@ class ReadCodeTool:
51
51
  Dict containing operation result
52
52
  """
53
53
  try:
54
- abs_path = os.path.abspath(filepath)
54
+ abs_path = os.path.abspath(filepath.strip())
55
55
  PrettyOutput.print(f"正在读取代码文件:{abs_path}", OutputType.INFO)
56
56
 
57
- if not os.path.exists(filepath):
57
+ if not os.path.exists(abs_path):
58
+ PrettyOutput.print(f"文件不存在: {abs_path}", OutputType.WARNING)
58
59
  return {
59
60
  "success": False,
60
61
  "stdout": "",
61
- "stderr": f"File does not exist: {filepath}"
62
+ "stderr": f"File does not exist: {abs_path}"
62
63
  }
63
64
 
64
- if os.path.getsize(filepath) > 10 * 1024 * 1024: # 10MB
65
+ if os.path.getsize(abs_path) > 10 * 1024 * 1024: # 10MB
66
+ PrettyOutput.print(f"文件太大: {abs_path}", OutputType.WARNING)
65
67
  return {
66
68
  "success": False,
67
69
  "stdout": "",
@@ -69,20 +71,28 @@ class ReadCodeTool:
69
71
  }
70
72
 
71
73
  try:
72
- with open(filepath, 'r', encoding='utf-8') as f:
73
- lines = f.readlines()
74
+ lines = open(abs_path, 'r', encoding='utf-8').readlines()
74
75
  except UnicodeDecodeError:
76
+ PrettyOutput.print(f"文件解码失败: {abs_path}", OutputType.WARNING)
75
77
  return {
76
78
  "success": False,
77
79
  "stdout": "",
78
80
  "stderr": "Failed to decode file with UTF-8 encoding"
79
81
  }
82
+ except Exception as e:
83
+ PrettyOutput.print(f"读取文件失败: {abs_path}", OutputType.WARNING)
84
+ return {
85
+ "success": False,
86
+ "stdout": "",
87
+ "stderr": f"Failed to read file: {str(e)}"
88
+ }
80
89
 
81
90
  if start_line < 0:
82
91
  start_line = 0
83
92
  if end_line == -1 or end_line > len(lines):
84
93
  end_line = len(lines)
85
94
  if start_line >= end_line:
95
+ PrettyOutput.print(f"无效的行范围: [{start_line}, {end_line})", OutputType.WARNING)
86
96
  return {
87
97
  "success": False,
88
98
  "stdout": "",
@@ -96,7 +106,7 @@ class ReadCodeTool:
96
106
 
97
107
  content = "".join(formatted_lines)
98
108
  output = f"File: {filepath}\nLines: [{start_line}, {end_line})\n{content}"
99
-
109
+ PrettyOutput.print(output, OutputType.CODE)
100
110
  return {
101
111
  "success": True,
102
112
  "stdout": output,
@@ -104,6 +114,7 @@ class ReadCodeTool:
104
114
  }
105
115
 
106
116
  except Exception as e:
117
+ PrettyOutput.print(f"读取代码失败: {filepath}", OutputType.WARNING)
107
118
  return {
108
119
  "success": False,
109
120
  "stdout": "",
@@ -1,7 +1,7 @@
1
1
  from typing import Dict, Any
2
2
  import requests
3
3
  from bs4 import BeautifulSoup
4
- from jarvis.utils import PrettyOutput, OutputType
4
+ from jarvis.jarvis_utils import PrettyOutput, OutputType
5
5
 
6
6
  class WebpageTool:
7
7
  name = "read_webpage"