jarvis-ai-assistant 0.1.159__py3-none-any.whl → 0.1.161__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/jarvis_agent/file_input_handler.py +2 -3
- jarvis/jarvis_agent/jarvis.py +1 -1
- jarvis/jarvis_agent/patch.py +107 -91
- jarvis/jarvis_code_agent/code_agent.py +126 -15
- jarvis/jarvis_code_analysis/code_review.py +29 -35
- jarvis/jarvis_git_utils/git_commiter.py +33 -61
- jarvis/jarvis_methodology/main.py +2 -2
- jarvis/jarvis_platform/base.py +43 -30
- jarvis/jarvis_platform/kimi.py +2 -2
- jarvis/jarvis_tools/file_analyzer.py +2 -2
- jarvis/jarvis_tools/file_operation.py +1 -1
- jarvis/jarvis_tools/read_webpage.py +1 -1
- jarvis/jarvis_tools/registry.py +33 -41
- jarvis/jarvis_tools/search_web.py +1 -1
- jarvis/jarvis_utils/input.py +40 -37
- jarvis/jarvis_utils/methodology.py +71 -61
- jarvis/jarvis_utils/utils.py +5 -12
- {jarvis_ai_assistant-0.1.159.dist-info → jarvis_ai_assistant-0.1.161.dist-info}/METADATA +2 -2
- {jarvis_ai_assistant-0.1.159.dist-info → jarvis_ai_assistant-0.1.161.dist-info}/RECORD +24 -24
- {jarvis_ai_assistant-0.1.159.dist-info → jarvis_ai_assistant-0.1.161.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.1.159.dist-info → jarvis_ai_assistant-0.1.161.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.1.159.dist-info → jarvis_ai_assistant-0.1.161.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.159.dist-info → jarvis_ai_assistant-0.1.161.dist-info}/top_level.txt +0 -0
|
@@ -10,11 +10,9 @@ import sys
|
|
|
10
10
|
import argparse
|
|
11
11
|
import os
|
|
12
12
|
|
|
13
|
-
from jarvis.jarvis_utils.config import INPUT_WINDOW_REVERSE_SIZE, get_max_input_token_count
|
|
14
|
-
from jarvis.jarvis_utils.embedding import get_context_token_count
|
|
15
13
|
from jarvis.jarvis_utils.git_utils import find_git_root, has_uncommitted_changes
|
|
16
14
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
17
|
-
from jarvis.jarvis_utils.utils import init_env,
|
|
15
|
+
from jarvis.jarvis_utils.utils import init_env, is_context_overflow
|
|
18
16
|
from jarvis.jarvis_utils.tag import ot, ct
|
|
19
17
|
|
|
20
18
|
|
|
@@ -107,7 +105,7 @@ class GitCommitTool:
|
|
|
107
105
|
diff = process.communicate()[0].decode()
|
|
108
106
|
spinner.write(f"✅ 获取差异 ({file_count} 个文件)")
|
|
109
107
|
try:
|
|
110
|
-
|
|
108
|
+
temp_diff_file_path = None
|
|
111
109
|
# 生成提交信息
|
|
112
110
|
spinner.text = "正在生成提交消息..."
|
|
113
111
|
|
|
@@ -132,13 +130,12 @@ class GitCommitTool:
|
|
|
132
130
|
|
|
133
131
|
# 获取模型并尝试上传文件
|
|
134
132
|
platform = PlatformRegistry().get_normal_platform()
|
|
133
|
+
upload_success = False
|
|
135
134
|
|
|
136
|
-
#
|
|
137
|
-
|
|
135
|
+
# Check if content is too large
|
|
136
|
+
is_large_content = is_context_overflow(diff)
|
|
138
137
|
|
|
139
|
-
if
|
|
140
|
-
# 文件较大,尝试上传
|
|
141
|
-
upload_success = False
|
|
138
|
+
if is_large_content and hasattr(platform, 'upload_files'):
|
|
142
139
|
spinner.text = "正在上传代码差异文件..."
|
|
143
140
|
try:
|
|
144
141
|
with spinner.hidden():
|
|
@@ -148,75 +145,49 @@ class GitCommitTool:
|
|
|
148
145
|
temp_diff_file.write(diff)
|
|
149
146
|
temp_diff_file.flush()
|
|
150
147
|
spinner.write(f"✅ 差异内容已写入临时文件")
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
else:
|
|
157
|
-
spinner.write("⚠️ 上传代码差异文件失败,将使用chat_with_files处理")
|
|
158
|
-
else:
|
|
159
|
-
spinner.write("⚠️ 模型不支持文件上传,将使用chat_with_files处理")
|
|
148
|
+
upload_success = platform.upload_files([temp_diff_file_path])
|
|
149
|
+
if upload_success:
|
|
150
|
+
spinner.write("✅ 成功上传代码差异文件")
|
|
151
|
+
else:
|
|
152
|
+
spinner.write("⚠️ 上传代码差异文件失败,将使用分块处理")
|
|
160
153
|
except Exception as e:
|
|
161
154
|
spinner.write(f"⚠️ 上传文件时出错: {str(e)}")
|
|
162
155
|
upload_success = False
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
156
|
+
|
|
157
|
+
# 根据上传状态准备完整的提示
|
|
158
|
+
if upload_success:
|
|
159
|
+
# 使用上传的文件
|
|
160
|
+
prompt = base_prompt + f'''
|
|
167
161
|
# 变更概述
|
|
168
162
|
- 变更文件数量: {file_count} 个文件
|
|
169
163
|
- 已上传包含完整代码差异的文件
|
|
170
164
|
|
|
171
165
|
请详细分析已上传的代码差异文件,生成符合上述格式的提交信息。
|
|
172
166
|
'''
|
|
173
|
-
|
|
174
|
-
# 使用chat_with_files处理大文件
|
|
175
|
-
spinner.write("使用chat_with_files处理大文件...")
|
|
176
|
-
commit_message = chat_with_files(
|
|
177
|
-
[temp_diff_file_path],
|
|
178
|
-
platform,
|
|
179
|
-
base_prompt,
|
|
180
|
-
"请基于以上代码差异生成符合格式的提交信息。"
|
|
181
|
-
)
|
|
182
|
-
commit_message = self._extract_commit_message(commit_message)
|
|
183
|
-
if commit_message:
|
|
184
|
-
spinner.write("✅ 生成提交消息")
|
|
185
|
-
# 执行提交
|
|
186
|
-
spinner.text = "正在准备提交..."
|
|
187
|
-
with tempfile.NamedTemporaryFile(mode='w', delete=True) as tmp_file:
|
|
188
|
-
tmp_file.write(commit_message)
|
|
189
|
-
tmp_file.flush()
|
|
190
|
-
spinner.text = "正在执行提交..."
|
|
191
|
-
commit_cmd = ["git", "commit", "-F", tmp_file.name]
|
|
192
|
-
subprocess.Popen(
|
|
193
|
-
commit_cmd,
|
|
194
|
-
stdout=subprocess.DEVNULL,
|
|
195
|
-
stderr=subprocess.DEVNULL
|
|
196
|
-
).wait()
|
|
197
|
-
spinner.write("✅ 提交")
|
|
198
|
-
return {
|
|
199
|
-
"success": True,
|
|
200
|
-
"stdout": yaml.safe_dump({
|
|
201
|
-
"commit_hash": self._get_last_commit_hash(),
|
|
202
|
-
"commit_message": commit_message
|
|
203
|
-
}),
|
|
204
|
-
"stderr": ""
|
|
205
|
-
}
|
|
167
|
+
commit_message = platform.chat_until_success(prompt)
|
|
206
168
|
else:
|
|
207
|
-
#
|
|
208
|
-
|
|
169
|
+
# 如果上传失败但内容较大,使用chat_big_content
|
|
170
|
+
if is_large_content and hasattr(platform, 'chat_big_content'):
|
|
171
|
+
spinner.text = "正在使用分块处理生成提交信息..."
|
|
172
|
+
commit_message = platform.chat_big_content(diff, base_prompt)
|
|
173
|
+
else:
|
|
174
|
+
# 直接在提示中包含差异内容
|
|
175
|
+
prompt = base_prompt + f'''
|
|
209
176
|
# 分析材料
|
|
210
177
|
{diff}
|
|
211
178
|
'''
|
|
179
|
+
commit_message = platform.chat_until_success(prompt)
|
|
212
180
|
|
|
213
181
|
# 尝试生成提交信息
|
|
214
182
|
spinner.text = "正在生成提交消息..."
|
|
215
183
|
while True:
|
|
216
|
-
commit_message
|
|
217
|
-
|
|
184
|
+
# 只在特定情况下重新获取commit_message
|
|
185
|
+
if not upload_success and not is_large_content and not commit_message:
|
|
186
|
+
commit_message = platform.chat_until_success(prompt)
|
|
187
|
+
extracted_message = self._extract_commit_message(commit_message)
|
|
218
188
|
# 如果成功提取,就跳出循环
|
|
219
|
-
if
|
|
189
|
+
if extracted_message:
|
|
190
|
+
commit_message = extracted_message
|
|
220
191
|
break
|
|
221
192
|
prompt = f"""格式错误,请按照以下格式重新生成提交信息:
|
|
222
193
|
{ot("COMMIT_MESSAGE")}
|
|
@@ -225,6 +196,7 @@ class GitCommitTool:
|
|
|
225
196
|
[可选] 详细描述变更内容和原因
|
|
226
197
|
{ct("COMMIT_MESSAGE")}
|
|
227
198
|
"""
|
|
199
|
+
commit_message = platform.chat_until_success(prompt)
|
|
228
200
|
spinner.write("✅ 生成提交消息")
|
|
229
201
|
|
|
230
202
|
# 执行提交
|
|
@@ -246,7 +218,7 @@ class GitCommitTool:
|
|
|
246
218
|
spinner.ok("✅")
|
|
247
219
|
finally:
|
|
248
220
|
# 清理临时差异文件
|
|
249
|
-
if
|
|
221
|
+
if temp_diff_file_path is not None and os.path.exists(temp_diff_file_path):
|
|
250
222
|
try:
|
|
251
223
|
os.unlink(temp_diff_file_path)
|
|
252
224
|
except Exception as e:
|
|
@@ -11,14 +11,14 @@ import hashlib
|
|
|
11
11
|
import os
|
|
12
12
|
import json
|
|
13
13
|
import argparse
|
|
14
|
-
import yaml
|
|
14
|
+
import yaml # type: ignore
|
|
15
15
|
from jarvis.jarvis_utils.methodology import (
|
|
16
16
|
_get_methodology_directory,
|
|
17
17
|
_load_all_methodologies
|
|
18
18
|
)
|
|
19
19
|
from jarvis.jarvis_platform.registry import PlatformRegistry
|
|
20
20
|
from jarvis.jarvis_utils.output import PrettyOutput, OutputType
|
|
21
|
-
from yaspin import yaspin
|
|
21
|
+
from yaspin import yaspin # type: ignore
|
|
22
22
|
|
|
23
23
|
def import_methodology(input_file):
|
|
24
24
|
"""导入方法论文件(合并策略)"""
|
jarvis/jarvis_platform/base.py
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from abc import ABC, abstractmethod
|
|
2
2
|
import re
|
|
3
3
|
from typing import List, Tuple
|
|
4
|
+
from jarvis.jarvis_utils.config import get_max_input_token_count
|
|
5
|
+
from jarvis.jarvis_utils.embedding import split_text_into_chunks
|
|
4
6
|
from jarvis.jarvis_utils.globals import clear_read_file_record
|
|
5
7
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
6
8
|
from jarvis.jarvis_utils.utils import get_context_token_count, while_success, while_true
|
|
@@ -37,38 +39,49 @@ class BasePlatform(ABC):
|
|
|
37
39
|
@abstractmethod
|
|
38
40
|
def upload_files(self, file_list: List[str]) -> bool:
|
|
39
41
|
raise NotImplementedError("upload_files is not implemented")
|
|
42
|
+
|
|
43
|
+
def chat_big_content(self, content: str, prompt: str) -> str:
|
|
44
|
+
prefix_prompt = f"""
|
|
45
|
+
我将分多次提供大量的上下文内容,在我明确告诉你内容已经全部提供完毕之前,每次仅需要输出“已收到”。
|
|
46
|
+
"""
|
|
47
|
+
self.chat_until_success(prefix_prompt)
|
|
48
|
+
split_content = split_text_into_chunks(content, get_max_input_token_count() - 1024)
|
|
49
|
+
for chunk in split_content:
|
|
50
|
+
self.chat_until_success(f"<part_content>{chunk}</part_content>")
|
|
51
|
+
return self.chat_until_success(f"内容已经全部提供完毕\n\n{prompt}")
|
|
40
52
|
|
|
53
|
+
|
|
54
|
+
def _chat(self, message: str):
|
|
55
|
+
import time
|
|
56
|
+
start_time = time.time()
|
|
57
|
+
response = self.chat(message)
|
|
58
|
+
|
|
59
|
+
end_time = time.time()
|
|
60
|
+
duration = end_time - start_time
|
|
61
|
+
char_count = len(response)
|
|
62
|
+
|
|
63
|
+
# Calculate token count and tokens per second
|
|
64
|
+
try:
|
|
65
|
+
token_count = get_context_token_count(response)
|
|
66
|
+
tokens_per_second = token_count / duration if duration > 0 else 0
|
|
67
|
+
except Exception as e:
|
|
68
|
+
PrettyOutput.print(f"Tokenization failed: {str(e)}", OutputType.WARNING)
|
|
69
|
+
token_count = 0
|
|
70
|
+
tokens_per_second = 0
|
|
71
|
+
|
|
72
|
+
# Print statistics
|
|
73
|
+
if not self.suppress_output:
|
|
74
|
+
PrettyOutput.print(
|
|
75
|
+
f"对话完成 - 耗时: {duration:.2f}秒, 输出字符数: {char_count}, 输出Token数量: {token_count}, 每秒Token数量: {tokens_per_second:.2f}",
|
|
76
|
+
OutputType.INFO,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
# Keep original think tag handling
|
|
80
|
+
response = re.sub(ot("think")+r'.*?'+ct("think"), '', response, flags=re.DOTALL)
|
|
81
|
+
return response
|
|
82
|
+
|
|
41
83
|
def chat_until_success(self, message: str) -> str:
|
|
42
|
-
|
|
43
|
-
import time
|
|
44
|
-
start_time = time.time()
|
|
45
|
-
response = self.chat(message)
|
|
46
|
-
|
|
47
|
-
end_time = time.time()
|
|
48
|
-
duration = end_time - start_time
|
|
49
|
-
char_count = len(response)
|
|
50
|
-
|
|
51
|
-
# Calculate token count and tokens per second
|
|
52
|
-
try:
|
|
53
|
-
token_count = get_context_token_count(response)
|
|
54
|
-
tokens_per_second = token_count / duration if duration > 0 else 0
|
|
55
|
-
except Exception as e:
|
|
56
|
-
PrettyOutput.print(f"Tokenization failed: {str(e)}", OutputType.WARNING)
|
|
57
|
-
token_count = 0
|
|
58
|
-
tokens_per_second = 0
|
|
59
|
-
|
|
60
|
-
# Print statistics
|
|
61
|
-
if not self.suppress_output:
|
|
62
|
-
PrettyOutput.print(
|
|
63
|
-
f"对话完成 - 耗时: {duration:.2f}秒, 输出字符数: {char_count}, 输出Token数量: {token_count}, 每秒Token数量: {tokens_per_second:.2f}",
|
|
64
|
-
OutputType.INFO,
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
# Keep original think tag handling
|
|
68
|
-
response = re.sub(ot("think")+r'.*?'+ct("think"), '', response, flags=re.DOTALL)
|
|
69
|
-
return response
|
|
70
|
-
|
|
71
|
-
return while_true(lambda: while_success(lambda: _chat(), 5), 5)
|
|
84
|
+
return while_true(lambda: while_success(lambda: self._chat(message), 5), 5)
|
|
72
85
|
|
|
73
86
|
@abstractmethod
|
|
74
87
|
def name(self) -> str:
|
jarvis/jarvis_platform/kimi.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from typing import Dict, List, Tuple
|
|
2
|
-
import requests
|
|
2
|
+
import requests # type: ignore
|
|
3
3
|
import json
|
|
4
4
|
import os
|
|
5
5
|
import mimetypes
|
|
@@ -178,7 +178,7 @@ class KimiModel(BasePlatform):
|
|
|
178
178
|
if not file_list:
|
|
179
179
|
return True
|
|
180
180
|
|
|
181
|
-
from yaspin import yaspin
|
|
181
|
+
from yaspin import yaspin # type: ignore
|
|
182
182
|
|
|
183
183
|
if not self.chat_id:
|
|
184
184
|
with yaspin(text="创建聊天会话...", color="yellow") as spinner:
|
|
@@ -3,8 +3,8 @@ import os
|
|
|
3
3
|
|
|
4
4
|
from jarvis.jarvis_platform.registry import PlatformRegistry
|
|
5
5
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
6
|
-
from yaspin import yaspin
|
|
7
|
-
from yaspin.spinners import Spinners
|
|
6
|
+
from yaspin import yaspin # type: ignore
|
|
7
|
+
from yaspin.spinners import Spinners # type: ignore
|
|
8
8
|
|
|
9
9
|
class FileAnalyzerTool:
|
|
10
10
|
name = "file_analyzer"
|
|
@@ -2,7 +2,7 @@ from typing import Dict, Any
|
|
|
2
2
|
import os
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
|
|
5
|
-
from yaspin import yaspin
|
|
5
|
+
from yaspin import yaspin # type: ignore
|
|
6
6
|
|
|
7
7
|
from jarvis.jarvis_utils.globals import add_read_file_record
|
|
8
8
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
jarvis/jarvis_tools/registry.py
CHANGED
|
@@ -3,6 +3,7 @@ from pathlib import Path
|
|
|
3
3
|
import re
|
|
4
4
|
import sys
|
|
5
5
|
import tempfile
|
|
6
|
+
import os
|
|
6
7
|
from typing import Any, Callable, Dict, List, Optional, Tuple
|
|
7
8
|
|
|
8
9
|
import yaml
|
|
@@ -10,14 +11,9 @@ import yaml
|
|
|
10
11
|
from jarvis.jarvis_agent.output_handler import OutputHandler
|
|
11
12
|
from jarvis.jarvis_platform.registry import PlatformRegistry
|
|
12
13
|
from jarvis.jarvis_tools.base import Tool
|
|
13
|
-
from jarvis.jarvis_utils.config import
|
|
14
|
-
INPUT_WINDOW_REVERSE_SIZE,
|
|
15
|
-
get_max_input_token_count,
|
|
16
|
-
get_data_dir,
|
|
17
|
-
)
|
|
18
|
-
from jarvis.jarvis_utils.embedding import get_context_token_count
|
|
14
|
+
from jarvis.jarvis_utils.config import get_data_dir
|
|
19
15
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
20
|
-
from jarvis.jarvis_utils.utils import init_env
|
|
16
|
+
from jarvis.jarvis_utils.utils import init_env, is_context_overflow
|
|
21
17
|
from jarvis.jarvis_utils.tag import ot, ct
|
|
22
18
|
from jarvis.jarvis_mcp.stdio_mcp_client import StdioMcpClient
|
|
23
19
|
from jarvis.jarvis_mcp.sse_mcp_client import SSEMcpClient
|
|
@@ -175,9 +171,6 @@ class ToolRegistry(OutputHandler):
|
|
|
175
171
|
self._load_builtin_tools()
|
|
176
172
|
self._load_external_tools()
|
|
177
173
|
self._load_mcp_tools()
|
|
178
|
-
self.max_input_token_count = (
|
|
179
|
-
get_max_input_token_count() - INPUT_WINDOW_REVERSE_SIZE
|
|
180
|
-
)
|
|
181
174
|
|
|
182
175
|
def use_tools(self, name: List[str]) -> None:
|
|
183
176
|
"""使用指定工具
|
|
@@ -618,46 +611,45 @@ class ToolRegistry(OutputHandler):
|
|
|
618
611
|
result["stdout"], result.get("stderr", "")
|
|
619
612
|
)
|
|
620
613
|
|
|
621
|
-
#
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
614
|
+
# 检查内容是否过大
|
|
615
|
+
is_large_content = is_context_overflow(output)
|
|
616
|
+
|
|
617
|
+
if is_large_content:
|
|
618
|
+
# 创建临时文件
|
|
619
|
+
with tempfile.NamedTemporaryFile(mode="w", suffix=".txt", delete=False) as tmp_file:
|
|
626
620
|
output_file = tmp_file.name
|
|
627
621
|
tmp_file.write(output)
|
|
628
622
|
tmp_file.flush()
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
623
|
+
|
|
624
|
+
try:
|
|
625
|
+
# 获取平台实例
|
|
626
|
+
platform = PlatformRegistry().get_normal_platform()
|
|
627
|
+
if platform and hasattr(platform, 'upload_files'):
|
|
628
|
+
platform.set_suppress_output(False)
|
|
633
629
|
# 尝试上传文件
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
2. 如果文件内容包含错误信息,请特别关注并提取
|
|
640
|
-
3. 提取的信息应该直接回答用户的问题,不要包含无关内容"""
|
|
630
|
+
upload_success = platform.upload_files([output_file])
|
|
631
|
+
|
|
632
|
+
if upload_success:
|
|
633
|
+
# 使用上传的文件生成摘要
|
|
634
|
+
prompt = f"该文件为工具执行结果,请阅读文件内容,并根据文件提取出以下信息:{want}"
|
|
641
635
|
return f"""工具调用原始输出过长,以下是根据输出提出的信息:
|
|
642
636
|
|
|
643
637
|
{platform.chat_until_success(prompt)}"""
|
|
644
|
-
|
|
645
|
-
#
|
|
646
|
-
|
|
647
|
-
from jarvis.jarvis_utils.utils import chat_with_files
|
|
648
|
-
prompt = f"""请阅读以下文件内容,并根据文件提取出以下信息:{want}
|
|
649
|
-
|
|
650
|
-
注意:
|
|
651
|
-
1. 请仔细阅读文件内容,确保提取的信息准确完整
|
|
652
|
-
2. 如果文件内容包含错误信息,请特别关注并提取
|
|
653
|
-
3. 提取的信息应该直接回答用户的问题,不要包含无关内容"""
|
|
638
|
+
elif hasattr(platform, 'chat_big_content'):
|
|
639
|
+
# 如果上传失败但支持大内容处理,使用chat_big_content
|
|
640
|
+
prompt = f"以下内容为工具执行结果,请阅读内容,并根据内容提取出以下信息:{want}\n\n{output}"
|
|
654
641
|
return f"""工具调用原始输出过长,以下是根据输出提出的信息:
|
|
655
642
|
|
|
656
|
-
{
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
643
|
+
{platform.chat_big_content(output, prompt)}"""
|
|
644
|
+
|
|
645
|
+
# 如果都不支持,返回截断的输出
|
|
646
|
+
return self._truncate_output(output)
|
|
647
|
+
finally:
|
|
648
|
+
# 清理临时文件
|
|
649
|
+
try:
|
|
650
|
+
os.unlink(output_file)
|
|
651
|
+
except Exception:
|
|
652
|
+
pass
|
|
661
653
|
|
|
662
654
|
return output
|
|
663
655
|
|
|
@@ -16,7 +16,7 @@ class SearchWebTool:
|
|
|
16
16
|
def execute(self, args: Dict[str, Any]) -> Dict[str, Any]: # type: ignore
|
|
17
17
|
query = args.get("query")
|
|
18
18
|
model = PlatformRegistry().get_normal_platform()
|
|
19
|
-
model.
|
|
19
|
+
model.set_web(True)
|
|
20
20
|
model.set_suppress_output(False) # type: ignore
|
|
21
21
|
return {
|
|
22
22
|
"stdout": model.chat_until_success(query), # type: ignore
|
jarvis/jarvis_utils/input.py
CHANGED
|
@@ -82,29 +82,20 @@ class FileCompleter(Completer):
|
|
|
82
82
|
# 计算替换长度
|
|
83
83
|
replace_length = len(text_after_at) + 1
|
|
84
84
|
|
|
85
|
-
#
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
85
|
+
# 获取所有可能的补全项
|
|
86
|
+
all_completions = []
|
|
87
|
+
|
|
88
|
+
# 1. 添加特殊标记
|
|
89
|
+
all_completions.extend([
|
|
90
|
+
(ot(tag), self._get_description(tag))
|
|
91
|
+
for tag in self.replace_map.keys()
|
|
92
|
+
])
|
|
93
|
+
all_completions.extend([
|
|
94
94
|
(ot("Summary"), '总结'),
|
|
95
95
|
(ot("Clear"), '清除历史'),
|
|
96
96
|
])
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
text=f"'{name}'",
|
|
100
|
-
start_position=-replace_length,
|
|
101
|
-
display=name,
|
|
102
|
-
display_meta=desc
|
|
103
|
-
) # type: ignore
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
# 使用git ls-files获取所有可能的文件
|
|
107
|
-
all_files = []
|
|
97
|
+
|
|
98
|
+
# 2. 添加文件列表
|
|
108
99
|
try:
|
|
109
100
|
import subprocess
|
|
110
101
|
result = subprocess.run(['git', 'ls-files'],
|
|
@@ -112,28 +103,40 @@ class FileCompleter(Completer):
|
|
|
112
103
|
stderr=subprocess.PIPE,
|
|
113
104
|
text=True)
|
|
114
105
|
if result.returncode == 0:
|
|
115
|
-
|
|
106
|
+
all_completions.extend([
|
|
107
|
+
(path, "File")
|
|
108
|
+
for path in result.stdout.splitlines()
|
|
109
|
+
if path.strip()
|
|
110
|
+
])
|
|
116
111
|
except Exception:
|
|
117
112
|
pass
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
display_text = f"{path} ({score}%)"
|
|
113
|
+
|
|
114
|
+
# 统一过滤和排序
|
|
115
|
+
if file_path:
|
|
116
|
+
# 使用模糊匹配过滤
|
|
117
|
+
scored_items = process.extract(file_path, [item[0] for item in all_completions], limit=self.max_suggestions)
|
|
118
|
+
scored_items = [(item[0], item[1]) for item in scored_items if item[1] > self.min_score]
|
|
119
|
+
# 创建映射以便查找描述
|
|
120
|
+
completion_map = {item[0]: item[1] for item in all_completions}
|
|
121
|
+
# 生成补全项
|
|
122
|
+
for text, score in scored_items:
|
|
123
|
+
display_text = text
|
|
124
|
+
if score < 100:
|
|
125
|
+
display_text = f"{text} ({score}%)"
|
|
132
126
|
yield Completion(
|
|
133
|
-
text=f"'{
|
|
127
|
+
text=f"'{text}'",
|
|
134
128
|
start_position=-replace_length,
|
|
135
129
|
display=display_text,
|
|
136
|
-
display_meta="
|
|
130
|
+
display_meta=completion_map.get(text, "")
|
|
131
|
+
) # type: ignore
|
|
132
|
+
else:
|
|
133
|
+
# 没有输入时返回前max_suggestions个建议
|
|
134
|
+
for text, desc in all_completions[:self.max_suggestions]:
|
|
135
|
+
yield Completion(
|
|
136
|
+
text=f"'{text}'",
|
|
137
|
+
start_position=-replace_length,
|
|
138
|
+
display=text,
|
|
139
|
+
display_meta=desc
|
|
137
140
|
) # type: ignore
|
|
138
141
|
|
|
139
142
|
def _get_description(self, tag: str) -> str:
|