jarvis-ai-assistant 0.1.114__py3-none-any.whl → 0.1.116__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.
- jarvis/__init__.py +1 -1
- jarvis/{agent.py → jarvis_agent/__init__.py} +35 -159
- jarvis/jarvis_agent/output_handler.py +23 -0
- jarvis/jarvis_code_agent/code_agent.py +11 -11
- jarvis/jarvis_code_agent/file_select.py +28 -7
- jarvis/jarvis_code_agent/patch.py +25 -2
- jarvis/jarvis_code_agent/relevant_files.py +1 -1
- jarvis/jarvis_codebase/main.py +2 -2
- 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 +147 -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 +2 -2
- jarvis/jarvis_smart_shell/main.py +17 -16
- 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 +53 -6
- 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.114.dist-info → jarvis_ai_assistant-0.1.116.dist-info}/METADATA +1 -1
- jarvis_ai_assistant-0.1.116.dist-info/RECORD +64 -0
- {jarvis_ai_assistant-0.1.114.dist-info → jarvis_ai_assistant-0.1.116.dist-info}/WHEEL +1 -1
- {jarvis_ai_assistant-0.1.114.dist-info → jarvis_ai_assistant-0.1.116.dist-info}/entry_points.txt +1 -2
- jarvis/jarvis_dev/main.py +0 -664
- jarvis/multi_agent.py +0 -76
- jarvis/utils/date_utils.py +0 -19
- jarvis_ai_assistant-0.1.114.dist-info/RECORD +0 -64
- {jarvis_ai_assistant-0.1.114.dist-info → jarvis_ai_assistant-0.1.116.dist-info}/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.114.dist-info → jarvis_ai_assistant-0.1.116.dist-info}/top_level.txt +0 -0
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": "",
|
jarvis/jarvis_tools/registry.py
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
import json
|
|
2
2
|
from pathlib import Path
|
|
3
|
+
import re
|
|
3
4
|
import sys
|
|
4
|
-
from typing import Any, Callable, Dict, List, Optional
|
|
5
|
+
from typing import Any, Callable, Dict, List, Optional, Tuple
|
|
5
6
|
|
|
7
|
+
import yaml
|
|
8
|
+
|
|
9
|
+
from jarvis.jarvis_agent.output_handler import OutputHandler
|
|
6
10
|
from jarvis.jarvis_platform.registry import PlatformRegistry
|
|
7
11
|
from jarvis.jarvis_tools.base import Tool
|
|
8
|
-
from jarvis.
|
|
9
|
-
|
|
12
|
+
from jarvis.jarvis_utils import OutputType, PrettyOutput, get_context_token_count, get_max_token_count
|
|
10
13
|
|
|
11
|
-
tool_call_help = """## Tool Usage Format
|
|
12
14
|
|
|
15
|
+
tool_call_help = """
|
|
16
|
+
Tool Usage Format
|
|
13
17
|
<TOOL_CALL>
|
|
14
18
|
name: tool_name
|
|
15
19
|
arguments:
|
|
@@ -44,8 +48,17 @@ STRICT RULES:
|
|
|
44
48
|
- If you can start executing the task, please start directly without asking the user if you can begin.
|
|
45
49
|
"""
|
|
46
50
|
|
|
47
|
-
class ToolRegistry:
|
|
48
|
-
|
|
51
|
+
class ToolRegistry(OutputHandler):
|
|
52
|
+
|
|
53
|
+
def name(self) -> str:
|
|
54
|
+
return "TOOL_CALL"
|
|
55
|
+
|
|
56
|
+
def can_handle(self, response: str) -> bool:
|
|
57
|
+
if self._extract_tool_calls(response):
|
|
58
|
+
return True
|
|
59
|
+
return False
|
|
60
|
+
|
|
61
|
+
def prompt(self) -> str:
|
|
49
62
|
"""Load tools"""
|
|
50
63
|
tools = self.get_all_tools()
|
|
51
64
|
if tools:
|
|
@@ -57,6 +70,16 @@ class ToolRegistry:
|
|
|
57
70
|
tools_prompt += tool_call_help
|
|
58
71
|
return tools_prompt
|
|
59
72
|
return ""
|
|
73
|
+
|
|
74
|
+
def handle(self, response: str) -> Tuple[bool, Any]:
|
|
75
|
+
tool_calls = self._extract_tool_calls(response)
|
|
76
|
+
if len(tool_calls) > 1:
|
|
77
|
+
PrettyOutput.print(f"操作失败:检测到多个操作。一次只能执行一个操作。尝试执行的操作:{', '.join([tool_call['name'] for tool_call in tool_calls])}", OutputType.WARNING)
|
|
78
|
+
return False, f"Call failed: Handle multiple tool calls, please ONLY handle one tool call at a time."
|
|
79
|
+
if len(tool_calls) == 0:
|
|
80
|
+
return False, ""
|
|
81
|
+
tool_call = tool_calls[0]
|
|
82
|
+
return False, self.handle_tool_calls(tool_call)
|
|
60
83
|
|
|
61
84
|
def __init__(self):
|
|
62
85
|
"""Initialize tool registry"""
|
|
@@ -169,6 +192,30 @@ class ToolRegistry:
|
|
|
169
192
|
except Exception as e:
|
|
170
193
|
PrettyOutput.print(f"从 {Path(file_path).name} 加载工具失败: {str(e)}", OutputType.ERROR)
|
|
171
194
|
return False
|
|
195
|
+
@staticmethod
|
|
196
|
+
def _extract_tool_calls(content: str) -> List[Dict]:
|
|
197
|
+
"""Extract tool calls from content.
|
|
198
|
+
|
|
199
|
+
Args:
|
|
200
|
+
content: The content containing tool calls
|
|
201
|
+
|
|
202
|
+
Returns:
|
|
203
|
+
List[Dict]: List of extracted tool calls with name and arguments
|
|
204
|
+
|
|
205
|
+
Raises:
|
|
206
|
+
Exception: If tool call is missing necessary fields
|
|
207
|
+
"""
|
|
208
|
+
# Split content into lines
|
|
209
|
+
data = re.findall(r'<TOOL_CALL>(.*?)</TOOL_CALL>', content, re.DOTALL)
|
|
210
|
+
ret = []
|
|
211
|
+
for item in data:
|
|
212
|
+
try:
|
|
213
|
+
msg = yaml.safe_load(item)
|
|
214
|
+
if 'name' in msg and 'arguments' in msg:
|
|
215
|
+
ret.append(msg)
|
|
216
|
+
except Exception as e:
|
|
217
|
+
continue
|
|
218
|
+
return ret
|
|
172
219
|
|
|
173
220
|
def register_tool(self, name: str, description: str, parameters: Dict, func: Callable):
|
|
174
221
|
"""Register a new tool"""
|
jarvis/jarvis_tools/search.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from typing import Dict, Any, List
|
|
2
2
|
from jarvis.jarvis_platform.registry import PlatformRegistry
|
|
3
|
-
from jarvis.
|
|
3
|
+
from jarvis.jarvis_utils import PrettyOutput, OutputType, get_context_token_count, get_max_token_count
|
|
4
4
|
from jarvis.jarvis_tools.read_webpage import WebpageTool
|
|
5
5
|
from playwright.sync_api import sync_playwright
|
|
6
6
|
from urllib.parse import quote
|
|
@@ -29,7 +29,8 @@ from rich.syntax import Syntax
|
|
|
29
29
|
|
|
30
30
|
from prompt_toolkit.completion import Completer, Completion, PathCompleter
|
|
31
31
|
from prompt_toolkit.document import Document
|
|
32
|
-
from fuzzywuzzy import
|
|
32
|
+
from fuzzywuzzy import process
|
|
33
|
+
from prompt_toolkit.key_binding import KeyBindings
|
|
33
34
|
|
|
34
35
|
# 初始化colorama
|
|
35
36
|
colorama.init()
|
|
@@ -271,8 +272,8 @@ class FileCompleter(Completer):
|
|
|
271
272
|
"""Custom completer for file paths with fuzzy matching."""
|
|
272
273
|
def __init__(self):
|
|
273
274
|
self.path_completer = PathCompleter()
|
|
274
|
-
self.max_suggestions = 10
|
|
275
|
-
self.min_score = 10
|
|
275
|
+
self.max_suggestions = 10
|
|
276
|
+
self.min_score = 10
|
|
276
277
|
|
|
277
278
|
def get_completions(self, document: Document, complete_event):
|
|
278
279
|
text = document.text_before_cursor
|
|
@@ -299,23 +300,33 @@ class FileCompleter(Completer):
|
|
|
299
300
|
# Get the text after the current @
|
|
300
301
|
file_path = text_after_at.strip()
|
|
301
302
|
|
|
302
|
-
#
|
|
303
|
+
# 计算需要删除的字符数(包括@符号)
|
|
304
|
+
replace_length = len(text_after_at) + 1 # +1 包含@符号
|
|
305
|
+
|
|
306
|
+
# Get all possible files using git ls-files only
|
|
303
307
|
all_files = []
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
308
|
+
try:
|
|
309
|
+
# Use git ls-files to get tracked files
|
|
310
|
+
import subprocess
|
|
311
|
+
result = subprocess.run(['git', 'ls-files'],
|
|
312
|
+
stdout=subprocess.PIPE,
|
|
313
|
+
stderr=subprocess.PIPE,
|
|
314
|
+
text=True)
|
|
315
|
+
if result.returncode == 0:
|
|
316
|
+
all_files = [line.strip() for line in result.stdout.splitlines() if line.strip()]
|
|
317
|
+
except Exception:
|
|
318
|
+
# If git command fails, just use an empty list
|
|
319
|
+
pass
|
|
310
320
|
|
|
311
321
|
# If no input after @, show all files
|
|
312
322
|
# Otherwise use fuzzy matching
|
|
313
323
|
if not file_path:
|
|
314
324
|
scored_files = [(path, 100) for path in all_files[:self.max_suggestions]]
|
|
315
325
|
else:
|
|
326
|
+
scored_files_data = process.extract(file_path, all_files, limit=self.max_suggestions)
|
|
316
327
|
scored_files = [
|
|
317
|
-
(
|
|
318
|
-
for
|
|
328
|
+
(m[0], m[1])
|
|
329
|
+
for m in scored_files_data
|
|
319
330
|
]
|
|
320
331
|
# Sort by score and take top results
|
|
321
332
|
scored_files.sort(key=lambda x: x[1], reverse=True)
|
|
@@ -324,66 +335,71 @@ class FileCompleter(Completer):
|
|
|
324
335
|
# Return completions for files
|
|
325
336
|
for path, score in scored_files:
|
|
326
337
|
if not file_path or score > self.min_score:
|
|
327
|
-
display_text = path
|
|
338
|
+
display_text = path # 显示时不带反引号
|
|
328
339
|
if file_path and score < 100:
|
|
329
340
|
display_text = f"{path} ({score}%)"
|
|
330
341
|
completion = Completion(
|
|
331
|
-
text=path,
|
|
332
|
-
start_position=-
|
|
342
|
+
text=f"`{path}`", # 添加反引号包裹路径
|
|
343
|
+
start_position=-replace_length,
|
|
333
344
|
display=display_text,
|
|
334
345
|
display_meta="File"
|
|
335
346
|
)
|
|
336
347
|
yield completion
|
|
337
348
|
|
|
338
349
|
def get_multiline_input(tip: str) -> str:
|
|
339
|
-
"""Get multi-line input
|
|
350
|
+
"""Get multi-line input with enhanced completion confirmation"""
|
|
351
|
+
# 单行输入说明
|
|
352
|
+
PrettyOutput.section("用户输入 - 使用 @ 触发文件补全,Tab 选择补全项,Ctrl+J 提交", OutputType.USER)
|
|
340
353
|
|
|
341
|
-
Args:
|
|
342
|
-
tip: The prompt tip to display
|
|
343
|
-
|
|
344
|
-
Returns:
|
|
345
|
-
str: The entered text
|
|
346
|
-
"""
|
|
347
354
|
print(f"{Fore.GREEN}{tip}{ColoramaStyle.RESET_ALL}")
|
|
348
355
|
|
|
349
|
-
#
|
|
356
|
+
# 自定义按键绑定
|
|
357
|
+
bindings = KeyBindings()
|
|
358
|
+
|
|
359
|
+
@bindings.add('enter')
|
|
360
|
+
def _(event):
|
|
361
|
+
# 当有补全菜单时,回车键确认补全
|
|
362
|
+
if event.current_buffer.complete_state:
|
|
363
|
+
event.current_buffer.apply_completion(event.current_buffer.complete_state.current_completion)
|
|
364
|
+
else:
|
|
365
|
+
# 没有补全菜单时插入换行
|
|
366
|
+
event.current_buffer.insert_text('\n')
|
|
367
|
+
|
|
368
|
+
@bindings.add('c-j') # 修改为支持的按键组合
|
|
369
|
+
def _(event):
|
|
370
|
+
# 使用 Ctrl+J 提交输入
|
|
371
|
+
event.current_buffer.validate_and_handle()
|
|
372
|
+
|
|
350
373
|
style = PromptStyle.from_dict({
|
|
351
374
|
'prompt': 'ansicyan',
|
|
352
375
|
})
|
|
353
|
-
|
|
354
|
-
lines = []
|
|
376
|
+
|
|
355
377
|
try:
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
break # End multi-line input
|
|
379
|
-
|
|
380
|
-
lines.append(line)
|
|
381
|
-
|
|
378
|
+
session = PromptSession(
|
|
379
|
+
history=None,
|
|
380
|
+
completer=FileCompleter(),
|
|
381
|
+
key_bindings=bindings,
|
|
382
|
+
complete_while_typing=True,
|
|
383
|
+
multiline=True, # 启用原生多行支持
|
|
384
|
+
vi_mode=False,
|
|
385
|
+
mouse_support=False
|
|
386
|
+
)
|
|
387
|
+
|
|
388
|
+
prompt = FormattedText([
|
|
389
|
+
('class:prompt', '>>> ')
|
|
390
|
+
])
|
|
391
|
+
|
|
392
|
+
# 单次获取多行输入
|
|
393
|
+
text = session.prompt(
|
|
394
|
+
prompt,
|
|
395
|
+
style=style,
|
|
396
|
+
).strip()
|
|
397
|
+
|
|
398
|
+
return text
|
|
399
|
+
|
|
382
400
|
except KeyboardInterrupt:
|
|
383
401
|
PrettyOutput.print("输入已取消", OutputType.INFO)
|
|
384
402
|
return ""
|
|
385
|
-
|
|
386
|
-
return "\n".join(lines)
|
|
387
403
|
|
|
388
404
|
def init_env():
|
|
389
405
|
"""Load environment variables from ~/.jarvis/env"""
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
jarvis/__init__.py,sha256=auL2YXQX-_S1mgO9Yyo0mfHN657i7dn_WX2B-daZ5gc,51
|
|
2
|
+
jarvis/jarvis_agent/__init__.py,sha256=949RsfwtecmezrWWU5VNCUbMZx2FXDToZBuHopEiRtc,21599
|
|
3
|
+
jarvis/jarvis_agent/output_handler.py,sha256=kJeFTjjSu0K_2p0wyhq2veSZuhRXoaFC_8wVaoBKX0w,401
|
|
4
|
+
jarvis/jarvis_code_agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
|
+
jarvis/jarvis_code_agent/code_agent.py,sha256=F7SifQk7M-M8HUf8MORFqgNI8MVZIAHPAckCgCnJHtQ,7795
|
|
6
|
+
jarvis/jarvis_code_agent/file_select.py,sha256=uxNA0ODy7NHMDNnCS9tFhttQ-omILUya7OjX3WuhSfo,8850
|
|
7
|
+
jarvis/jarvis_code_agent/patch.py,sha256=Xhaa_OOrZRC9WuDD9LvR5YPJdVekOyuiYlesIoU6ITE,5375
|
|
8
|
+
jarvis/jarvis_code_agent/relevant_files.py,sha256=0woLVR0umeIoi2kVCjz1gTJODEyP57Z_SzktunuitdE,3330
|
|
9
|
+
jarvis/jarvis_codebase/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
+
jarvis/jarvis_codebase/main.py,sha256=1kJ4c2qG9j0tZfUmYB-FEYr5QoAkgs4Rbr038L0usf4,39336
|
|
11
|
+
jarvis/jarvis_lsp/base.py,sha256=_7pdbMKjdtYBW0DsRbjIodDHM3J7df-YgXHejN_WIrU,4490
|
|
12
|
+
jarvis/jarvis_lsp/cpp.py,sha256=sYQHEl0FoVC5Iw2pJvvGKpeNLD95XjNuTOINvdZLgME,4986
|
|
13
|
+
jarvis/jarvis_lsp/go.py,sha256=3soEuID2XV65zaxyR70RxNsvtm02l9PEZ46F_nsDdqY,5311
|
|
14
|
+
jarvis/jarvis_lsp/python.py,sha256=_Vo2pPwVh_vAsyS0XowXMbT4Syd78naPEZj586bi004,4747
|
|
15
|
+
jarvis/jarvis_lsp/registry.py,sha256=x7OFlW10AWQ_tWEbHWkdpngoFHTP3t1vSyGxVVLk46w,9933
|
|
16
|
+
jarvis/jarvis_lsp/rust.py,sha256=ZvUoOZm9GWLl3kobfByBuTGrQ8aM2dLuNxS_NHr1aQQ,5542
|
|
17
|
+
jarvis/jarvis_multi_agent/__init__.py,sha256=-NY3KqwFjEcSUICXn99aiZIg7fBK9wuZo8uZhxHY45E,6087
|
|
18
|
+
jarvis/jarvis_platform/__init__.py,sha256=mrOt67nselz_H1gX9wdAO4y2DY5WPXzABqJbr5Des8k,63
|
|
19
|
+
jarvis/jarvis_platform/ai8.py,sha256=AO42OVzrwQMDY74TR2B4gtrsfeRVxJRf5OmHBM3cVQY,11948
|
|
20
|
+
jarvis/jarvis_platform/base.py,sha256=8iYNCe7PGSs9sDG66jeNDr2TYzWUYBiGVvKgHTDsFLg,2641
|
|
21
|
+
jarvis/jarvis_platform/kimi.py,sha256=WCRyG7jnqnpHNu6M9_pGFE_RBVKqYDtd_F1EPdT_FKU,15761
|
|
22
|
+
jarvis/jarvis_platform/ollama.py,sha256=TsBEg8crPmBiLvMRDtXYVa2AIdeog36MmW2tn5j9x8U,5613
|
|
23
|
+
jarvis/jarvis_platform/openai.py,sha256=rHzc20Frd5LzS0Wm97FxglSai65UKkY2ju8rg6q-gOg,4445
|
|
24
|
+
jarvis/jarvis_platform/oyi.py,sha256=3yuWHEGtGV--6IuFCCc1R2F1Y-p21xy4Vk-P5pQRAys,14994
|
|
25
|
+
jarvis/jarvis_platform/registry.py,sha256=SmBcf86h6uf4TB7cut-Bhb9Ivj5z2wAg1pWkcJLi_80,8508
|
|
26
|
+
jarvis/jarvis_platform_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
27
|
+
jarvis/jarvis_platform_manager/main.py,sha256=Ja0f-PiYxABIj-Ioh9NNZuqy0dB2Jk7dhrObgzgXApw,20958
|
|
28
|
+
jarvis/jarvis_platform_manager/openai_test.py,sha256=BAoZgOJ431gjjbbdgiX-ARfI0aLXK_cRLAQQJzQI6MI,5200
|
|
29
|
+
jarvis/jarvis_rag/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
30
|
+
jarvis/jarvis_rag/main.py,sha256=U5h8PbVatNuZ5uFpXNV77W3TXSOGG8CrZ3huqfpPre0,31326
|
|
31
|
+
jarvis/jarvis_smart_shell/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
32
|
+
jarvis/jarvis_smart_shell/main.py,sha256=73tSL1nCXNCPGXeLAiFq6cckv3ot5Vt5QyPkSAXhMcE,4038
|
|
33
|
+
jarvis/jarvis_tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
34
|
+
jarvis/jarvis_tools/ask_codebase.py,sha256=MF7zeBqVDa7T45JxDR9mePA92kzZm5bQ9op8o5Qo9lM,3003
|
|
35
|
+
jarvis/jarvis_tools/ask_user.py,sha256=tIyiKk9F8xchjQ3Yh5fMQjhpflQTuh75HTuXMftGxZY,1827
|
|
36
|
+
jarvis/jarvis_tools/base.py,sha256=c0DMoDDPxmsqUYJR989zgUs7nIYRY6GWBrAdusIZKjc,656
|
|
37
|
+
jarvis/jarvis_tools/chdir.py,sha256=06GAtMqoi5fT1FXD2HUUlHKosVtz-Z8KI13lpEFQw3g,1820
|
|
38
|
+
jarvis/jarvis_tools/code_review.py,sha256=DFnw-li4afcpHdfDC2TX_PHSNn7GxEHbtagCAkLQ-9U,8598
|
|
39
|
+
jarvis/jarvis_tools/create_code_agent.py,sha256=4tJLcKk_e1AOyN2wgOeAWVB9N4aa7GsusUNdaYmAYww,3906
|
|
40
|
+
jarvis/jarvis_tools/create_sub_agent.py,sha256=ldpNn5LczybExvt9Sz4t1ybetLX-dTJIAF5f_oH-Z3M,2869
|
|
41
|
+
jarvis/jarvis_tools/execute_shell.py,sha256=MwgVyI1O1wshU9yR-DvSWIgoSQpVjtH9JpjVQvSrKF0,2566
|
|
42
|
+
jarvis/jarvis_tools/file_operation.py,sha256=8CAWozKfsRx_TzCmRPcNSj-bRo3K69IEDmmN8IWMlmg,5647
|
|
43
|
+
jarvis/jarvis_tools/git_commiter.py,sha256=oq_jh6YkB-cZi2XRhu139seZeF7Vubwx04cvpugjmt4,2732
|
|
44
|
+
jarvis/jarvis_tools/lsp_find_definition.py,sha256=xV8YeN1RJfwd2F3gE6OnDeTwl-AnCmrxueHocbXkQOc,4800
|
|
45
|
+
jarvis/jarvis_tools/lsp_find_references.py,sha256=FohlJeLfTxcMUASfbjOT93hQGtI2WeyTpMGwRwShW_I,4043
|
|
46
|
+
jarvis/jarvis_tools/lsp_get_diagnostics.py,sha256=bEvbDk8TnKg9TTFFxMrYOJm5TBDgz5gO04WJFQUwQQE,4490
|
|
47
|
+
jarvis/jarvis_tools/lsp_get_document_symbols.py,sha256=dspL6r9HYnXL5TpARSApFY3IQLm2kcYVNVWCff2xoXI,3080
|
|
48
|
+
jarvis/jarvis_tools/lsp_prepare_rename.py,sha256=RxUyIef4awtp-jgupcD1LcPlno9P3mOE8AS3_Fm71Ys,4832
|
|
49
|
+
jarvis/jarvis_tools/lsp_validate_edit.py,sha256=M0iglK2QbnIEFv0RYK6o2iAYnv259jB6EU7To-rc51E,5247
|
|
50
|
+
jarvis/jarvis_tools/methodology.py,sha256=JvHV6rHhC6fbPuSqC6UHFaGEE39d4g7zFLodR72wM0g,5758
|
|
51
|
+
jarvis/jarvis_tools/rag.py,sha256=ZhmvwVUHBFsttDRdVncc-S-a-XVOy5jbdNd7Vk4uTlk,4942
|
|
52
|
+
jarvis/jarvis_tools/read_code.py,sha256=rt5m-bcXY0W-WLrGgr5xG08KxB1nNGD5UD0TSj7v7lg,6826
|
|
53
|
+
jarvis/jarvis_tools/read_webpage.py,sha256=7QamwBi5s7lD-jTcjD0wsBvkmWPRC9-K-0JkGgeTpvs,3063
|
|
54
|
+
jarvis/jarvis_tools/registry.py,sha256=Kvec2iS9FPm9yScn3ef68HjtvnM98hLesdA-5jTTWec,13232
|
|
55
|
+
jarvis/jarvis_tools/search.py,sha256=NHrFpAqg6dtws_9wLJvIZimjeJ-kekETi0Bg0AWMG08,11437
|
|
56
|
+
jarvis/jarvis_tools/select_code_files.py,sha256=242K79SiNF_gY7fpThY3xoi2ihfgJdjB27X1jKkeXK0,1889
|
|
57
|
+
jarvis/jarvis_tools/tool_generator.py,sha256=jdniHyKcEyF9KyouudrCoZBH3czZmQXc3ns0_trZ3yU,6332
|
|
58
|
+
jarvis/jarvis_utils/__init__.py,sha256=2GbATVP6NXe8obg2YYArNRAeSj0X4-GCULZrMiHh3fw,29885
|
|
59
|
+
jarvis_ai_assistant-0.1.116.dist-info/LICENSE,sha256=AGgVgQmTqFvaztRtCAXsAMryUymB18gZif7_l2e1XOg,1063
|
|
60
|
+
jarvis_ai_assistant-0.1.116.dist-info/METADATA,sha256=JKKbhXVCkjyFGh6oo5txk5cv48exb112sNO7kWVJuwU,13701
|
|
61
|
+
jarvis_ai_assistant-0.1.116.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
|
|
62
|
+
jarvis_ai_assistant-0.1.116.dist-info/entry_points.txt,sha256=vjXpb5GC60FGbIqnVdr4hfoVzQQJLP_QRgNkkld5kPw,487
|
|
63
|
+
jarvis_ai_assistant-0.1.116.dist-info/top_level.txt,sha256=1BOxyWfzOP_ZXj8rVTDnNCJ92bBGB0rwq8N1PCpoMIs,7
|
|
64
|
+
jarvis_ai_assistant-0.1.116.dist-info/RECORD,,
|
{jarvis_ai_assistant-0.1.114.dist-info → jarvis_ai_assistant-0.1.116.dist-info}/entry_points.txt
RENAMED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
[console_scripts]
|
|
2
|
-
jarvis = jarvis.
|
|
2
|
+
jarvis = jarvis.jarvis_agent:main
|
|
3
3
|
jarvis-code-agent = jarvis.jarvis_code_agent.code_agent:main
|
|
4
4
|
jarvis-code-review = jarvis.jarvis_tools.code_review:main
|
|
5
5
|
jarvis-codebase = jarvis.jarvis_codebase.main:main
|
|
6
|
-
jarvis-dev = jarvis.jarvis_dev.main:main
|
|
7
6
|
jarvis-git-commit = jarvis.jarvis_tools.git_commiter:main
|
|
8
7
|
jarvis-platform-manager = jarvis.jarvis_platform_manager.main:main
|
|
9
8
|
jarvis-rag = jarvis.jarvis_rag.main:main
|