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.
- jarvis/__init__.py +1 -1
- jarvis/{agent.py → jarvis_agent/__init__.py} +122 -203
- jarvis/jarvis_agent/output_handler.py +23 -0
- jarvis/jarvis_code_agent/code_agent.py +113 -100
- jarvis/jarvis_code_agent/file_select.py +28 -7
- jarvis/jarvis_code_agent/patch.py +80 -2
- jarvis/jarvis_code_agent/relevant_files.py +82 -42
- jarvis/jarvis_codebase/main.py +53 -25
- jarvis/jarvis_dev/main.py +719 -547
- jarvis/jarvis_lsp/cpp.py +1 -1
- jarvis/jarvis_lsp/go.py +1 -1
- jarvis/jarvis_lsp/registry.py +1 -1
- jarvis/jarvis_lsp/rust.py +1 -1
- jarvis/jarvis_multi_agent/__init__.py +170 -0
- jarvis/jarvis_platform/ai8.py +2 -2
- jarvis/jarvis_platform/base.py +14 -4
- jarvis/jarvis_platform/kimi.py +2 -2
- jarvis/jarvis_platform/ollama.py +1 -1
- jarvis/jarvis_platform/openai.py +1 -1
- jarvis/jarvis_platform/oyi.py +1 -1
- jarvis/jarvis_platform/registry.py +1 -1
- jarvis/jarvis_platform_manager/main.py +422 -6
- jarvis/jarvis_platform_manager/openai_test.py +139 -0
- jarvis/jarvis_rag/main.py +57 -20
- jarvis/jarvis_smart_shell/main.py +55 -29
- jarvis/jarvis_tools/ask_codebase.py +1 -1
- jarvis/jarvis_tools/ask_user.py +1 -1
- jarvis/jarvis_tools/chdir.py +1 -1
- jarvis/jarvis_tools/code_review.py +3 -3
- jarvis/jarvis_tools/create_code_agent.py +1 -1
- jarvis/jarvis_tools/create_sub_agent.py +2 -2
- jarvis/jarvis_tools/execute_shell.py +1 -1
- jarvis/jarvis_tools/file_operation.py +16 -14
- jarvis/jarvis_tools/git_commiter.py +2 -2
- jarvis/jarvis_tools/methodology.py +1 -1
- jarvis/jarvis_tools/rag.py +1 -1
- jarvis/jarvis_tools/read_code.py +19 -8
- jarvis/jarvis_tools/read_webpage.py +1 -1
- jarvis/jarvis_tools/registry.py +157 -31
- jarvis/jarvis_tools/search.py +1 -1
- jarvis/jarvis_tools/select_code_files.py +1 -1
- jarvis/{utils.py → jarvis_utils/__init__.py} +69 -53
- {jarvis_ai_assistant-0.1.115.dist-info → jarvis_ai_assistant-0.1.117.dist-info}/METADATA +1 -1
- jarvis_ai_assistant-0.1.117.dist-info/RECORD +65 -0
- {jarvis_ai_assistant-0.1.115.dist-info → jarvis_ai_assistant-0.1.117.dist-info}/WHEEL +1 -1
- {jarvis_ai_assistant-0.1.115.dist-info → jarvis_ai_assistant-0.1.117.dist-info}/entry_points.txt +1 -1
- jarvis/multi_agent.py +0 -76
- jarvis/utils/date_utils.py +0 -19
- jarvis_ai_assistant-0.1.115.dist-info/RECORD +0 -64
- {jarvis_ai_assistant-0.1.115.dist-info → jarvis_ai_assistant-0.1.117.dist-info}/LICENSE +0 -0
- {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.
|
|
7
|
-
from jarvis.
|
|
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
|
-
|
|
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
|
|
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}]
|
|
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 += "
|
|
682
|
-
|
|
683
|
-
|
|
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
|
-
|
|
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.
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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
|
-
|
|
61
|
-
|
|
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
|
|
64
|
-
|
|
75
|
+
# 📝 Example Format
|
|
76
|
+
Input: "Find all Python files in the current directory"
|
|
77
|
+
Output: find . -name "*.py"
|
|
65
78
|
|
|
66
|
-
|
|
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
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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
|
-
|
|
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.
|
|
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:
|
jarvis/jarvis_tools/ask_user.py
CHANGED
jarvis/jarvis_tools/chdir.py
CHANGED
|
@@ -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.
|
|
7
|
-
from jarvis.
|
|
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
|
-
|
|
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.
|
|
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.
|
|
4
|
+
from jarvis.jarvis_agent import Agent, origin_agent_system_prompt
|
|
5
5
|
from jarvis.jarvis_tools.registry import ToolRegistry
|
|
6
|
-
from jarvis.
|
|
6
|
+
from jarvis.jarvis_utils import OutputType, PrettyOutput
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class SubAgentTool:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from typing import Dict, Any, List, Union
|
|
2
2
|
import os
|
|
3
3
|
|
|
4
|
-
from jarvis.
|
|
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(
|
|
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"文件不存在: {
|
|
46
|
+
"stderr": f"文件不存在: {abs_path}"
|
|
46
47
|
}
|
|
47
48
|
|
|
48
|
-
if os.path.getsize(
|
|
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(
|
|
56
|
-
output = f"File: {
|
|
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"读取文件: {
|
|
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(
|
|
69
|
-
with open(
|
|
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"写入文件: {
|
|
74
|
+
PrettyOutput.print(f"写入文件: {abs_path}", OutputType.INFO)
|
|
73
75
|
return {
|
|
74
76
|
"success": True,
|
|
75
|
-
"stdout": f"Successfully wrote content to {
|
|
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 {
|
|
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.
|
|
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.
|
|
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
|
|
jarvis/jarvis_tools/rag.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from typing import Dict, Any
|
|
2
2
|
import os
|
|
3
|
-
from jarvis.
|
|
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:
|
jarvis/jarvis_tools/read_code.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from typing import Dict, Any, List
|
|
2
2
|
import os
|
|
3
|
-
from jarvis.
|
|
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(
|
|
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: {
|
|
62
|
+
"stderr": f"File does not exist: {abs_path}"
|
|
62
63
|
}
|
|
63
64
|
|
|
64
|
-
if os.path.getsize(
|
|
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
|
-
|
|
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": "",
|