jarvis-ai-assistant 0.7.0__py3-none-any.whl → 0.7.8__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/jarvis_agent/__init__.py +243 -139
- jarvis/jarvis_agent/agent_manager.py +5 -10
- jarvis/jarvis_agent/builtin_input_handler.py +2 -6
- jarvis/jarvis_agent/config_editor.py +2 -7
- jarvis/jarvis_agent/event_bus.py +82 -12
- jarvis/jarvis_agent/file_context_handler.py +265 -15
- jarvis/jarvis_agent/file_methodology_manager.py +3 -4
- jarvis/jarvis_agent/jarvis.py +113 -98
- jarvis/jarvis_agent/language_extractors/__init__.py +57 -0
- jarvis/jarvis_agent/language_extractors/c_extractor.py +21 -0
- jarvis/jarvis_agent/language_extractors/cpp_extractor.py +21 -0
- jarvis/jarvis_agent/language_extractors/go_extractor.py +21 -0
- jarvis/jarvis_agent/language_extractors/java_extractor.py +84 -0
- jarvis/jarvis_agent/language_extractors/javascript_extractor.py +79 -0
- jarvis/jarvis_agent/language_extractors/python_extractor.py +21 -0
- jarvis/jarvis_agent/language_extractors/rust_extractor.py +21 -0
- jarvis/jarvis_agent/language_extractors/typescript_extractor.py +84 -0
- jarvis/jarvis_agent/language_support_info.py +486 -0
- jarvis/jarvis_agent/main.py +6 -12
- jarvis/jarvis_agent/memory_manager.py +7 -16
- jarvis/jarvis_agent/methodology_share_manager.py +10 -16
- jarvis/jarvis_agent/prompt_manager.py +1 -1
- jarvis/jarvis_agent/prompts.py +193 -171
- jarvis/jarvis_agent/protocols.py +8 -12
- jarvis/jarvis_agent/run_loop.py +77 -14
- jarvis/jarvis_agent/session_manager.py +2 -3
- jarvis/jarvis_agent/share_manager.py +12 -21
- jarvis/jarvis_agent/shell_input_handler.py +1 -2
- jarvis/jarvis_agent/task_analyzer.py +26 -4
- jarvis/jarvis_agent/task_manager.py +11 -27
- jarvis/jarvis_agent/tool_executor.py +2 -3
- jarvis/jarvis_agent/tool_share_manager.py +12 -24
- jarvis/jarvis_agent/web_server.py +55 -20
- jarvis/jarvis_c2rust/__init__.py +5 -5
- jarvis/jarvis_c2rust/cli.py +461 -499
- jarvis/jarvis_c2rust/collector.py +45 -53
- jarvis/jarvis_c2rust/constants.py +26 -0
- jarvis/jarvis_c2rust/library_replacer.py +264 -132
- jarvis/jarvis_c2rust/llm_module_agent.py +162 -190
- jarvis/jarvis_c2rust/loaders.py +207 -0
- jarvis/jarvis_c2rust/models.py +28 -0
- jarvis/jarvis_c2rust/optimizer.py +1592 -395
- jarvis/jarvis_c2rust/transpiler.py +1722 -1064
- jarvis/jarvis_c2rust/utils.py +385 -0
- jarvis/jarvis_code_agent/build_validation_config.py +2 -3
- jarvis/jarvis_code_agent/code_agent.py +394 -320
- jarvis/jarvis_code_agent/code_analyzer/__init__.py +3 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/base.py +4 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/cmake.py +17 -2
- jarvis/jarvis_code_agent/code_analyzer/build_validator/fallback.py +3 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/go.py +36 -4
- jarvis/jarvis_code_agent/code_analyzer/build_validator/java_gradle.py +9 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/java_maven.py +9 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/makefile.py +12 -1
- jarvis/jarvis_code_agent/code_analyzer/build_validator/nodejs.py +22 -5
- jarvis/jarvis_code_agent/code_analyzer/build_validator/python.py +57 -32
- jarvis/jarvis_code_agent/code_analyzer/build_validator/rust.py +62 -6
- jarvis/jarvis_code_agent/code_analyzer/build_validator/validator.py +8 -9
- jarvis/jarvis_code_agent/code_analyzer/context_manager.py +290 -5
- jarvis/jarvis_code_agent/code_analyzer/language_support.py +21 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/__init__.py +21 -3
- jarvis/jarvis_code_agent/code_analyzer/languages/c_cpp_language.py +72 -4
- jarvis/jarvis_code_agent/code_analyzer/languages/go_language.py +35 -3
- jarvis/jarvis_code_agent/code_analyzer/languages/java_language.py +212 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/javascript_language.py +254 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/python_language.py +52 -2
- jarvis/jarvis_code_agent/code_analyzer/languages/rust_language.py +73 -1
- jarvis/jarvis_code_agent/code_analyzer/languages/typescript_language.py +280 -0
- jarvis/jarvis_code_agent/code_analyzer/llm_context_recommender.py +306 -152
- jarvis/jarvis_code_agent/code_analyzer/structured_code.py +556 -0
- jarvis/jarvis_code_agent/code_analyzer/symbol_extractor.py +193 -18
- jarvis/jarvis_code_agent/code_analyzer/tree_sitter_extractor.py +18 -8
- jarvis/jarvis_code_agent/lint.py +258 -27
- jarvis/jarvis_code_agent/utils.py +0 -1
- jarvis/jarvis_code_analysis/code_review.py +19 -24
- jarvis/jarvis_data/config_schema.json +53 -26
- jarvis/jarvis_git_squash/main.py +4 -5
- jarvis/jarvis_git_utils/git_commiter.py +44 -49
- jarvis/jarvis_mcp/sse_mcp_client.py +20 -27
- jarvis/jarvis_mcp/stdio_mcp_client.py +11 -12
- jarvis/jarvis_mcp/streamable_mcp_client.py +15 -14
- jarvis/jarvis_memory_organizer/memory_organizer.py +55 -74
- jarvis/jarvis_methodology/main.py +32 -48
- jarvis/jarvis_multi_agent/__init__.py +79 -61
- jarvis/jarvis_multi_agent/main.py +3 -7
- jarvis/jarvis_platform/base.py +469 -199
- jarvis/jarvis_platform/human.py +7 -8
- jarvis/jarvis_platform/kimi.py +30 -36
- jarvis/jarvis_platform/openai.py +65 -27
- jarvis/jarvis_platform/registry.py +26 -10
- jarvis/jarvis_platform/tongyi.py +24 -25
- jarvis/jarvis_platform/yuanbao.py +31 -42
- jarvis/jarvis_platform_manager/main.py +66 -77
- jarvis/jarvis_platform_manager/service.py +8 -13
- jarvis/jarvis_rag/cli.py +49 -51
- jarvis/jarvis_rag/embedding_manager.py +13 -18
- jarvis/jarvis_rag/llm_interface.py +8 -9
- jarvis/jarvis_rag/query_rewriter.py +10 -21
- jarvis/jarvis_rag/rag_pipeline.py +24 -27
- jarvis/jarvis_rag/reranker.py +4 -5
- jarvis/jarvis_rag/retriever.py +28 -30
- jarvis/jarvis_sec/__init__.py +220 -3520
- jarvis/jarvis_sec/agents.py +143 -0
- jarvis/jarvis_sec/analysis.py +276 -0
- jarvis/jarvis_sec/cli.py +29 -6
- jarvis/jarvis_sec/clustering.py +1439 -0
- jarvis/jarvis_sec/file_manager.py +427 -0
- jarvis/jarvis_sec/parsers.py +73 -0
- jarvis/jarvis_sec/prompts.py +268 -0
- jarvis/jarvis_sec/report.py +83 -4
- jarvis/jarvis_sec/review.py +453 -0
- jarvis/jarvis_sec/utils.py +499 -0
- jarvis/jarvis_sec/verification.py +848 -0
- jarvis/jarvis_sec/workflow.py +7 -0
- jarvis/jarvis_smart_shell/main.py +38 -87
- jarvis/jarvis_stats/cli.py +1 -1
- jarvis/jarvis_stats/stats.py +7 -7
- jarvis/jarvis_stats/storage.py +15 -21
- jarvis/jarvis_tools/clear_memory.py +3 -20
- jarvis/jarvis_tools/cli/main.py +20 -23
- jarvis/jarvis_tools/edit_file.py +1066 -0
- jarvis/jarvis_tools/execute_script.py +42 -21
- jarvis/jarvis_tools/file_analyzer.py +6 -9
- jarvis/jarvis_tools/generate_new_tool.py +11 -20
- jarvis/jarvis_tools/lsp_client.py +1552 -0
- jarvis/jarvis_tools/methodology.py +2 -3
- jarvis/jarvis_tools/read_code.py +1525 -87
- jarvis/jarvis_tools/read_symbols.py +2 -3
- jarvis/jarvis_tools/read_webpage.py +7 -10
- jarvis/jarvis_tools/registry.py +370 -181
- jarvis/jarvis_tools/retrieve_memory.py +20 -19
- jarvis/jarvis_tools/rewrite_file.py +105 -0
- jarvis/jarvis_tools/save_memory.py +3 -15
- jarvis/jarvis_tools/search_web.py +3 -7
- jarvis/jarvis_tools/sub_agent.py +17 -6
- jarvis/jarvis_tools/sub_code_agent.py +14 -16
- jarvis/jarvis_tools/virtual_tty.py +54 -32
- jarvis/jarvis_utils/clipboard.py +7 -10
- jarvis/jarvis_utils/config.py +98 -63
- jarvis/jarvis_utils/embedding.py +5 -5
- jarvis/jarvis_utils/fzf.py +8 -8
- jarvis/jarvis_utils/git_utils.py +81 -67
- jarvis/jarvis_utils/input.py +24 -49
- jarvis/jarvis_utils/jsonnet_compat.py +465 -0
- jarvis/jarvis_utils/methodology.py +33 -35
- jarvis/jarvis_utils/utils.py +245 -202
- {jarvis_ai_assistant-0.7.0.dist-info → jarvis_ai_assistant-0.7.8.dist-info}/METADATA +205 -70
- jarvis_ai_assistant-0.7.8.dist-info/RECORD +218 -0
- jarvis/jarvis_agent/edit_file_handler.py +0 -584
- jarvis/jarvis_agent/rewrite_file_handler.py +0 -141
- jarvis/jarvis_agent/task_planner.py +0 -496
- jarvis/jarvis_platform/ai8.py +0 -332
- jarvis/jarvis_tools/ask_user.py +0 -54
- jarvis_ai_assistant-0.7.0.dist-info/RECORD +0 -192
- {jarvis_ai_assistant-0.7.0.dist-info → jarvis_ai_assistant-0.7.8.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.7.0.dist-info → jarvis_ai_assistant-0.7.8.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.7.0.dist-info → jarvis_ai_assistant-0.7.8.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.7.0.dist-info → jarvis_ai_assistant-0.7.8.dist-info}/top_level.txt +0 -0
|
@@ -7,7 +7,7 @@ from abc import ABC, abstractmethod
|
|
|
7
7
|
|
|
8
8
|
from prompt_toolkit import prompt
|
|
9
9
|
|
|
10
|
-
from jarvis.jarvis_agent import
|
|
10
|
+
from jarvis.jarvis_agent import user_confirm
|
|
11
11
|
from jarvis.jarvis_utils.config import get_data_dir
|
|
12
12
|
|
|
13
13
|
|
|
@@ -61,9 +61,7 @@ class ShareManager(ABC):
|
|
|
61
61
|
def update_central_repo(self) -> None:
|
|
62
62
|
"""克隆或更新中心仓库"""
|
|
63
63
|
if not os.path.exists(self.repo_path):
|
|
64
|
-
|
|
65
|
-
f"正在克隆中心{self.get_resource_type()}仓库...", OutputType.INFO
|
|
66
|
-
)
|
|
64
|
+
print(f"ℹ️ 正在克隆中心{self.get_resource_type()}仓库...")
|
|
67
65
|
subprocess.run(
|
|
68
66
|
["git", "clone", self.central_repo_url, self.repo_path], check=True
|
|
69
67
|
)
|
|
@@ -92,9 +90,7 @@ class ShareManager(ABC):
|
|
|
92
90
|
)
|
|
93
91
|
subprocess.run(["git", "push"], cwd=self.repo_path, check=True)
|
|
94
92
|
else:
|
|
95
|
-
|
|
96
|
-
f"正在更新中心{self.get_resource_type()}仓库...", OutputType.INFO
|
|
97
|
-
)
|
|
93
|
+
print(f"ℹ️ 正在更新中心{self.get_resource_type()}仓库...")
|
|
98
94
|
# 检查是否是空仓库
|
|
99
95
|
try:
|
|
100
96
|
# 先尝试获取远程分支信息
|
|
@@ -123,24 +119,18 @@ class ShareManager(ABC):
|
|
|
123
119
|
["git", "checkout", "."], cwd=self.repo_path, check=True
|
|
124
120
|
)
|
|
125
121
|
else:
|
|
126
|
-
|
|
127
|
-
f"跳过更新 '{self.repo_name}' 以保留未提交的更改。",
|
|
128
|
-
OutputType.INFO,
|
|
129
|
-
)
|
|
122
|
+
print(f"ℹ️ 跳过更新 '{self.repo_name}' 以保留未提交的更改。")
|
|
130
123
|
return
|
|
131
124
|
subprocess.run(["git", "pull"], cwd=self.repo_path, check=True)
|
|
132
125
|
else:
|
|
133
|
-
|
|
134
|
-
f"中心{self.get_resource_type()}仓库是空的,将初始化为新仓库",
|
|
135
|
-
OutputType.INFO,
|
|
136
|
-
)
|
|
126
|
+
print(f"ℹ️ 中心{self.get_resource_type()}仓库是空的,将初始化为新仓库")
|
|
137
127
|
except subprocess.CalledProcessError:
|
|
138
128
|
# 如果命令失败,可能是网络问题或其他错误
|
|
139
|
-
|
|
129
|
+
print("⚠️ 无法连接到远程仓库,将跳过更新")
|
|
140
130
|
|
|
141
131
|
def commit_and_push(self, count: int) -> None:
|
|
142
132
|
"""提交并推送更改"""
|
|
143
|
-
|
|
133
|
+
print("ℹ️ 正在提交更改...")
|
|
144
134
|
subprocess.run(["git", "add", "."], cwd=self.repo_path, check=True)
|
|
145
135
|
|
|
146
136
|
commit_msg = f"Add {count} {self.get_resource_type()}(s) from local collection"
|
|
@@ -148,7 +138,7 @@ class ShareManager(ABC):
|
|
|
148
138
|
["git", "commit", "-m", commit_msg], cwd=self.repo_path, check=True
|
|
149
139
|
)
|
|
150
140
|
|
|
151
|
-
|
|
141
|
+
print("ℹ️ 正在推送到远程仓库...")
|
|
152
142
|
# 检查是否需要设置上游分支(空仓库的情况)
|
|
153
143
|
try:
|
|
154
144
|
# 先尝试普通推送
|
|
@@ -179,7 +169,8 @@ class ShareManager(ABC):
|
|
|
179
169
|
resource_list.append(f"[{i}] {self.format_resource_display(resource)}")
|
|
180
170
|
|
|
181
171
|
# 一次性打印所有资源
|
|
182
|
-
|
|
172
|
+
joined_resources = '\n'.join(resource_list)
|
|
173
|
+
print(f"ℹ️ {joined_resources}")
|
|
183
174
|
|
|
184
175
|
# 让用户选择
|
|
185
176
|
while True:
|
|
@@ -195,12 +186,12 @@ class ShareManager(ABC):
|
|
|
195
186
|
else:
|
|
196
187
|
selected_indices = parse_selection(choice_str, len(resources))
|
|
197
188
|
if not selected_indices:
|
|
198
|
-
|
|
189
|
+
print("⚠️ 无效的选择")
|
|
199
190
|
continue
|
|
200
191
|
return [resources[i - 1] for i in selected_indices]
|
|
201
192
|
|
|
202
193
|
except ValueError:
|
|
203
|
-
|
|
194
|
+
print("⚠️ 请输入有效的数字")
|
|
204
195
|
|
|
205
196
|
@abstractmethod
|
|
206
197
|
def get_resource_type(self) -> str:
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
from typing import Any, Tuple
|
|
3
3
|
|
|
4
|
-
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
5
4
|
from jarvis.jarvis_utils.input import user_confirm
|
|
6
5
|
from jarvis.jarvis_agent.utils import join_prompts
|
|
7
6
|
|
|
@@ -24,7 +23,7 @@ def shell_input_handler(user_input: str, agent: Any) -> Tuple[str, bool]:
|
|
|
24
23
|
|
|
25
24
|
# Build script while stripping the no-confirm marker from each line
|
|
26
25
|
script = "\n".join([_clean(c) for c in cmdline])
|
|
27
|
-
|
|
26
|
+
print(script)
|
|
28
27
|
|
|
29
28
|
# If any line contains the no-confirm marker, skip the pre-execution confirmation
|
|
30
29
|
no_confirm = any(marker in c for c in cmdline)
|
|
@@ -6,8 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
from jarvis.jarvis_utils.globals import get_interrupt, set_interrupt
|
|
8
8
|
|
|
9
|
-
from jarvis.jarvis_agent.prompts import
|
|
10
|
-
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
9
|
+
from jarvis.jarvis_agent.prompts import get_task_analysis_prompt
|
|
11
10
|
from jarvis.jarvis_agent.utils import join_prompts
|
|
12
11
|
from jarvis.jarvis_agent.events import BEFORE_TOOL_CALL, AFTER_TOOL_CALL, BEFORE_SUMMARY, TASK_COMPLETED
|
|
13
12
|
|
|
@@ -46,7 +45,7 @@ class TaskAnalyzer:
|
|
|
46
45
|
self._process_analysis_loop()
|
|
47
46
|
|
|
48
47
|
except Exception:
|
|
49
|
-
|
|
48
|
+
print("❌ 分析失败")
|
|
50
49
|
finally:
|
|
51
50
|
# 标记已完成一次分析,避免事件回调重复执行
|
|
52
51
|
self._analysis_done = True
|
|
@@ -57,7 +56,30 @@ class TaskAnalyzer:
|
|
|
57
56
|
|
|
58
57
|
def _prepare_analysis_prompt(self, satisfaction_feedback: str) -> str:
|
|
59
58
|
"""准备分析提示"""
|
|
60
|
-
|
|
59
|
+
# 检查是否有 save_memory 工具(工具可用性)
|
|
60
|
+
has_save_memory = False
|
|
61
|
+
# 检查是否有 generate_new_tool 工具
|
|
62
|
+
has_generate_new_tool = False
|
|
63
|
+
try:
|
|
64
|
+
tool_registry = self.agent.get_tool_registry()
|
|
65
|
+
if tool_registry:
|
|
66
|
+
# 检查 save_memory 工具
|
|
67
|
+
save_memory_tool = tool_registry.get_tool("save_memory")
|
|
68
|
+
has_save_memory = save_memory_tool is not None
|
|
69
|
+
|
|
70
|
+
# 检查 generate_new_tool 工具
|
|
71
|
+
generate_tool = tool_registry.get_tool("generate_new_tool")
|
|
72
|
+
has_generate_new_tool = generate_tool is not None
|
|
73
|
+
except Exception:
|
|
74
|
+
pass
|
|
75
|
+
|
|
76
|
+
# 根据配置获取相应的提示词
|
|
77
|
+
analysis_prompt = get_task_analysis_prompt(
|
|
78
|
+
has_save_memory=has_save_memory,
|
|
79
|
+
has_generate_new_tool=has_generate_new_tool
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
return join_prompts([analysis_prompt, satisfaction_feedback])
|
|
61
83
|
|
|
62
84
|
def _process_analysis_loop(self):
|
|
63
85
|
"""处理分析循环"""
|
|
@@ -9,8 +9,6 @@ from rich.table import Table
|
|
|
9
9
|
from rich.console import Console
|
|
10
10
|
|
|
11
11
|
from jarvis.jarvis_agent import (
|
|
12
|
-
OutputType,
|
|
13
|
-
PrettyOutput,
|
|
14
12
|
get_multiline_input,
|
|
15
13
|
user_confirm,
|
|
16
14
|
)
|
|
@@ -31,9 +29,7 @@ class TaskManager:
|
|
|
31
29
|
data_dir = get_data_dir()
|
|
32
30
|
pre_command_path = os.path.join(data_dir, "pre-command")
|
|
33
31
|
if os.path.exists(pre_command_path):
|
|
34
|
-
|
|
35
|
-
f"从{pre_command_path}加载预定义任务...", OutputType.INFO
|
|
36
|
-
)
|
|
32
|
+
print(f"ℹ️ 从{pre_command_path}加载预定义任务...")
|
|
37
33
|
try:
|
|
38
34
|
with open(
|
|
39
35
|
pre_command_path, "r", encoding="utf-8", errors="ignore"
|
|
@@ -43,19 +39,15 @@ class TaskManager:
|
|
|
43
39
|
for name, desc in user_tasks.items():
|
|
44
40
|
if desc:
|
|
45
41
|
tasks[str(name)] = str(desc)
|
|
46
|
-
|
|
47
|
-
f"预定义任务加载完成 {pre_command_path}", OutputType.SUCCESS
|
|
48
|
-
)
|
|
42
|
+
print(f"✅ 预定义任务加载完成 {pre_command_path}")
|
|
49
43
|
except (yaml.YAMLError, OSError):
|
|
50
|
-
|
|
51
|
-
f"预定义任务加载失败 {pre_command_path}", OutputType.ERROR
|
|
52
|
-
)
|
|
44
|
+
print(f"❌ 预定义任务加载失败 {pre_command_path}")
|
|
53
45
|
|
|
54
46
|
# Check .jarvis/pre-command in current directory
|
|
55
47
|
pre_command_path = ".jarvis/pre-command"
|
|
56
48
|
if os.path.exists(pre_command_path):
|
|
57
49
|
abs_path = os.path.abspath(pre_command_path)
|
|
58
|
-
|
|
50
|
+
print(f"ℹ️ 从{abs_path}加载预定义任务...")
|
|
59
51
|
try:
|
|
60
52
|
with open(
|
|
61
53
|
pre_command_path, "r", encoding="utf-8", errors="ignore"
|
|
@@ -65,13 +57,9 @@ class TaskManager:
|
|
|
65
57
|
for name, desc in local_tasks.items():
|
|
66
58
|
if desc:
|
|
67
59
|
tasks[str(name)] = str(desc)
|
|
68
|
-
|
|
69
|
-
f"预定义任务加载完成 {pre_command_path}", OutputType.SUCCESS
|
|
70
|
-
)
|
|
60
|
+
print(f"✅ 预定义任务加载完成 {pre_command_path}")
|
|
71
61
|
except (yaml.YAMLError, OSError):
|
|
72
|
-
|
|
73
|
-
f"预定义任务加载失败 {pre_command_path}", OutputType.ERROR
|
|
74
|
-
)
|
|
62
|
+
print(f"❌ 预定义任务加载失败 {pre_command_path}")
|
|
75
63
|
|
|
76
64
|
return tasks
|
|
77
65
|
|
|
@@ -89,7 +77,7 @@ class TaskManager:
|
|
|
89
77
|
for i, name in enumerate(task_names, 1):
|
|
90
78
|
table.add_row(str(i), name)
|
|
91
79
|
Console().print(table)
|
|
92
|
-
|
|
80
|
+
print("ℹ️ [0] 跳过预定义任务")
|
|
93
81
|
|
|
94
82
|
# Try fzf selection first (with numbered options and a skip option)
|
|
95
83
|
fzf_list = [f"{0:>3} | 跳过预定义任务"] + [
|
|
@@ -104,7 +92,7 @@ class TaskManager:
|
|
|
104
92
|
return ""
|
|
105
93
|
if 1 <= idx <= len(task_names):
|
|
106
94
|
selected_task = tasks[task_names[idx - 1]]
|
|
107
|
-
|
|
95
|
+
print(f"ℹ️ 将要执行任务:\n {selected_task}")
|
|
108
96
|
# 询问是否需要补充信息
|
|
109
97
|
need_additional = user_confirm("需要为此任务添加补充信息吗?", default=False)
|
|
110
98
|
if need_additional:
|
|
@@ -129,9 +117,7 @@ class TaskManager:
|
|
|
129
117
|
return ""
|
|
130
118
|
if 1 <= choice <= len(task_names):
|
|
131
119
|
selected_task = tasks[task_names[choice - 1]]
|
|
132
|
-
|
|
133
|
-
f"将要执行任务:\n {selected_task}", OutputType.INFO
|
|
134
|
-
)
|
|
120
|
+
print(f"ℹ️ 将要执行任务:\n {selected_task}")
|
|
135
121
|
# 询问是否需要补充信息
|
|
136
122
|
need_additional = user_confirm(
|
|
137
123
|
"需要为此任务添加补充信息吗?", default=False
|
|
@@ -144,11 +130,9 @@ class TaskManager:
|
|
|
144
130
|
f"补充信息:\n{additional_input}"
|
|
145
131
|
])
|
|
146
132
|
return selected_task
|
|
147
|
-
|
|
148
|
-
"无效的选择。请选择列表中的一个号码。", OutputType.WARNING
|
|
149
|
-
)
|
|
133
|
+
print("⚠️ 无效的选择。请选择列表中的一个号码。")
|
|
150
134
|
|
|
151
135
|
except (KeyboardInterrupt, EOFError):
|
|
152
136
|
return ""
|
|
153
137
|
except ValueError as val_err:
|
|
154
|
-
|
|
138
|
+
print(f"❌ 选择任务失败: {str(val_err)}")
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
from typing import Any, Tuple, TYPE_CHECKING
|
|
3
3
|
|
|
4
4
|
from jarvis.jarvis_utils.input import user_confirm
|
|
5
|
-
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
6
5
|
|
|
7
6
|
if TYPE_CHECKING:
|
|
8
7
|
from jarvis.jarvis_agent import Agent
|
|
@@ -31,7 +30,7 @@ def execute_tool_call(response: str, agent: "Agent") -> Tuple[bool, Any]:
|
|
|
31
30
|
f"操作失败:检测到多个操作。一次只能执行一个操作。"
|
|
32
31
|
f"尝试执行的操作:{', '.join([handler.name() for handler in tool_list])}"
|
|
33
32
|
)
|
|
34
|
-
|
|
33
|
+
print(f"⚠️ {error_message}")
|
|
35
34
|
return False, error_message
|
|
36
35
|
|
|
37
36
|
if not tool_list:
|
|
@@ -47,7 +46,7 @@ def execute_tool_call(response: str, agent: "Agent") -> Tuple[bool, Any]:
|
|
|
47
46
|
print(f"✅ {tool_to_execute.name()}执行完成")
|
|
48
47
|
return result
|
|
49
48
|
except Exception as e:
|
|
50
|
-
|
|
49
|
+
print(f"❌ 工具执行失败: {str(e)}")
|
|
51
50
|
return False, str(e)
|
|
52
51
|
|
|
53
52
|
return False, ""
|
|
@@ -7,7 +7,7 @@ from typing import List, Dict, Any, Set
|
|
|
7
7
|
|
|
8
8
|
import typer
|
|
9
9
|
|
|
10
|
-
from jarvis.jarvis_agent import
|
|
10
|
+
from jarvis.jarvis_agent import user_confirm
|
|
11
11
|
from jarvis.jarvis_agent.share_manager import ShareManager
|
|
12
12
|
from jarvis.jarvis_utils.config import get_central_tool_repo, get_data_dir
|
|
13
13
|
|
|
@@ -18,13 +18,8 @@ class ToolShareManager(ShareManager):
|
|
|
18
18
|
def __init__(self):
|
|
19
19
|
central_repo = get_central_tool_repo()
|
|
20
20
|
if not central_repo:
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
OutputType.ERROR,
|
|
24
|
-
)
|
|
25
|
-
PrettyOutput.print(
|
|
26
|
-
"请在配置文件中设置中心工具仓库的Git地址", OutputType.INFO
|
|
27
|
-
)
|
|
21
|
+
print("❌ 错误:未配置中心工具仓库(JARVIS_CENTRAL_TOOL_REPO)")
|
|
22
|
+
print("ℹ️ 请在配置文件中设置中心工具仓库的Git地址")
|
|
28
23
|
raise typer.Exit(code=1)
|
|
29
24
|
|
|
30
25
|
super().__init__(central_repo, "central_tool_repo")
|
|
@@ -52,10 +47,7 @@ class ToolShareManager(ShareManager):
|
|
|
52
47
|
# 只从数据目录的tools目录获取工具
|
|
53
48
|
local_tools_dir = os.path.join(get_data_dir(), "tools")
|
|
54
49
|
if not os.path.exists(local_tools_dir):
|
|
55
|
-
|
|
56
|
-
f"本地工具目录不存在: {local_tools_dir}",
|
|
57
|
-
OutputType.WARNING,
|
|
58
|
-
)
|
|
50
|
+
print(f"⚠️ 本地工具目录不存在: {local_tools_dir}")
|
|
59
51
|
return []
|
|
60
52
|
|
|
61
53
|
# 收集本地工具文件(排除已存在的)
|
|
@@ -84,7 +76,8 @@ class ToolShareManager(ShareManager):
|
|
|
84
76
|
share_list = ["\n将要分享以下工具到中心仓库(注意:文件将被移动而非复制):"]
|
|
85
77
|
for tool in resources:
|
|
86
78
|
share_list.append(f"- {tool['tool_name']} ({tool['filename']})")
|
|
87
|
-
|
|
79
|
+
joined_list = '\n'.join(share_list)
|
|
80
|
+
print(f"⚠️ {joined_list}")
|
|
88
81
|
|
|
89
82
|
if not user_confirm("确认移动这些工具到中心仓库吗?(原文件将被删除)"):
|
|
90
83
|
return []
|
|
@@ -108,10 +101,7 @@ class ToolShareManager(ShareManager):
|
|
|
108
101
|
# 获取本地资源
|
|
109
102
|
local_resources = self.get_local_resources()
|
|
110
103
|
if not local_resources:
|
|
111
|
-
|
|
112
|
-
"没有找到新的工具文件(所有工具可能已存在于中心仓库)",
|
|
113
|
-
OutputType.WARNING,
|
|
114
|
-
)
|
|
104
|
+
print("⚠️ 没有找到新的工具文件(所有工具可能已存在于中心仓库)")
|
|
115
105
|
return
|
|
116
106
|
|
|
117
107
|
# 选择要分享的资源
|
|
@@ -123,17 +113,15 @@ class ToolShareManager(ShareManager):
|
|
|
123
113
|
moved_list = self.share_resources(selected_resources)
|
|
124
114
|
if moved_list:
|
|
125
115
|
# 一次性显示所有移动结果
|
|
126
|
-
|
|
116
|
+
joined_moved = '\n'.join(moved_list)
|
|
117
|
+
print(f"✅ {joined_moved}")
|
|
127
118
|
|
|
128
119
|
# 提交并推送
|
|
129
120
|
self.commit_and_push(len(selected_resources))
|
|
130
121
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
f"原文件已从 {os.path.join(get_data_dir(), 'tools')} 移动到中心仓库",
|
|
134
|
-
OutputType.INFO,
|
|
135
|
-
)
|
|
122
|
+
print("✅ 工具已成功分享到中心仓库!")
|
|
123
|
+
print(f"ℹ️ 原文件已从 {os.path.join(get_data_dir(), 'tools')} 移动到中心仓库")
|
|
136
124
|
|
|
137
125
|
except Exception as e:
|
|
138
|
-
|
|
126
|
+
print(f"❌ 分享工具时出错: {str(e)}")
|
|
139
127
|
raise typer.Exit(code=1)
|
|
@@ -18,7 +18,7 @@ import os
|
|
|
18
18
|
import signal
|
|
19
19
|
import atexit
|
|
20
20
|
from pathlib import Path
|
|
21
|
-
from typing import Any, Dict, Callable, Optional
|
|
21
|
+
from typing import Any, Dict, Callable, Optional, List
|
|
22
22
|
|
|
23
23
|
import uvicorn
|
|
24
24
|
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
|
|
@@ -27,7 +27,6 @@ from fastapi.middleware.cors import CORSMiddleware
|
|
|
27
27
|
|
|
28
28
|
from jarvis.jarvis_agent.web_bridge import WebBridge
|
|
29
29
|
from jarvis.jarvis_utils.globals import set_interrupt, console
|
|
30
|
-
from jarvis.jarvis_utils.output import PrettyOutput, OutputType
|
|
31
30
|
|
|
32
31
|
# ---------------------------
|
|
33
32
|
# 应用与页面
|
|
@@ -290,10 +289,14 @@ def _run_and_notify(agent: Any, text: str) -> None:
|
|
|
290
289
|
except Exception:
|
|
291
290
|
pass
|
|
292
291
|
|
|
293
|
-
def start_web_server(agent: Any, host: str = "127.0.0.1", port: int = 8765) -> None:
|
|
292
|
+
def start_web_server(agent: Any, host: str = "127.0.0.1", port: int = 8765, launch_command: Optional[List[str]] = None) -> None:
|
|
294
293
|
"""
|
|
295
294
|
启动Web服务,并将Agent绑定到应用上下文。
|
|
296
295
|
- agent: 现有的 Agent 实例(已完成初始化)
|
|
296
|
+
- host: Web 服务主机地址
|
|
297
|
+
- port: Web 服务端口
|
|
298
|
+
- launch_command: 交互式终端启动命令(列表格式,如 ["jvs", "--task", "xxx"]),
|
|
299
|
+
如果为 None,则从环境变量 JARVIS_WEB_LAUNCH_JSON 读取
|
|
297
300
|
"""
|
|
298
301
|
app = _build_app()
|
|
299
302
|
app.state.agent = agent # 供 WS 端点调用
|
|
@@ -304,6 +307,8 @@ def start_web_server(agent: Any, host: str = "127.0.0.1", port: int = 8765) -> N
|
|
|
304
307
|
app.state.agent_manager = agent if hasattr(agent, "initialize") else None
|
|
305
308
|
except Exception:
|
|
306
309
|
app.state.agent_manager = None
|
|
310
|
+
# 存储启动命令到应用状态
|
|
311
|
+
app.state.launch_command = launch_command
|
|
307
312
|
|
|
308
313
|
@app.websocket("/stdio")
|
|
309
314
|
async def websocket_stdio(ws: WebSocket) -> None:
|
|
@@ -451,26 +456,48 @@ def start_web_server(agent: Any, host: str = "127.0.0.1", port: int = 8765) -> N
|
|
|
451
456
|
# 会话结束后等待用户按回车再重启
|
|
452
457
|
waiting_for_ack = False
|
|
453
458
|
ack_event = asyncio.Event()
|
|
454
|
-
|
|
459
|
+
|
|
460
|
+
# 在 fork 前获取启动命令(避免在子进程中访问 app.state)
|
|
461
|
+
_launch_cmd = None
|
|
462
|
+
try:
|
|
463
|
+
if hasattr(app.state, "launch_command") and app.state.launch_command:
|
|
464
|
+
_launch_cmd = app.state.launch_command
|
|
465
|
+
# 调试输出
|
|
466
|
+
if _os.environ.get("JARVIS_DEBUG_WEB_LAUNCH_CMD") == "1":
|
|
467
|
+
print(f"🔍 Web服务器: 使用传入的启动命令: {_launch_cmd}")
|
|
468
|
+
else:
|
|
469
|
+
# 回退到环境变量
|
|
470
|
+
import json as _json
|
|
471
|
+
_cmd_json = _os.environ.get("JARVIS_WEB_LAUNCH_JSON", "")
|
|
472
|
+
if _cmd_json:
|
|
473
|
+
try:
|
|
474
|
+
_launch_cmd = _json.loads(_cmd_json)
|
|
475
|
+
if _os.environ.get("JARVIS_DEBUG_WEB_LAUNCH_CMD") == "1":
|
|
476
|
+
print(f"🔍 Web服务器: 从环境变量读取启动命令: {_launch_cmd}")
|
|
477
|
+
except Exception:
|
|
478
|
+
_launch_cmd = None
|
|
479
|
+
except Exception:
|
|
480
|
+
_launch_cmd = None
|
|
455
481
|
|
|
456
482
|
def _spawn_jvs_session() -> bool:
|
|
457
|
-
nonlocal session
|
|
483
|
+
nonlocal session, _launch_cmd
|
|
458
484
|
try:
|
|
459
485
|
pid, master_fd = _pty.fork()
|
|
460
486
|
if pid == 0:
|
|
461
|
-
#
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
487
|
+
# 子进程:执行启动命令,失败时回退到系统 shell
|
|
488
|
+
# 使用在 fork 前获取的命令
|
|
489
|
+
_argv = _launch_cmd
|
|
490
|
+
|
|
491
|
+
# 如果获取到有效命令,执行它
|
|
492
|
+
if _argv and isinstance(_argv, list) and len(_argv) > 0 and isinstance(_argv[0], str):
|
|
493
|
+
try:
|
|
494
|
+
if _os.environ.get("JARVIS_DEBUG_WEB_LAUNCH_CMD") == "1":
|
|
495
|
+
print(f"🔍 子进程: 执行命令: {_argv}")
|
|
496
|
+
_os.execvp(_argv[0], _argv)
|
|
497
|
+
except Exception as e:
|
|
498
|
+
if _os.environ.get("JARVIS_DEBUG_WEB_LAUNCH_CMD") == "1":
|
|
499
|
+
print(f"⚠️ 子进程: 执行命令失败: {e}")
|
|
500
|
+
pass
|
|
474
501
|
# 若未配置或执行失败,回退到 /bin/bash 或 /bin/sh
|
|
475
502
|
try:
|
|
476
503
|
_os.execvp("/bin/bash", ["/bin/bash"])
|
|
@@ -707,7 +734,7 @@ def start_web_server(agent: Any, host: str = "127.0.0.1", port: int = 8765) -> N
|
|
|
707
734
|
except Exception:
|
|
708
735
|
pass
|
|
709
736
|
|
|
710
|
-
|
|
737
|
+
print(f"✅ 启动 Jarvis Web 服务: http://{host}:{port}")
|
|
711
738
|
# 在服务端进程内也写入并维护 PID 文件,增强可检测性与可清理性
|
|
712
739
|
try:
|
|
713
740
|
pidfile = Path(os.path.expanduser("~/.jarvis")) / f"jarvis_web_{port}.pid"
|
|
@@ -748,4 +775,12 @@ def start_web_server(agent: Any, host: str = "127.0.0.1", port: int = 8765) -> N
|
|
|
748
775
|
pass
|
|
749
776
|
except Exception:
|
|
750
777
|
pass
|
|
751
|
-
uvicorn
|
|
778
|
+
# 配置 uvicorn 日志级别,隐藏连接信息和访问日志
|
|
779
|
+
import logging
|
|
780
|
+
# 禁用 uvicorn 的访问日志
|
|
781
|
+
logging.getLogger("uvicorn.access").setLevel(logging.WARNING)
|
|
782
|
+
# 禁用 uvicorn 的常规日志(连接信息等)
|
|
783
|
+
logging.getLogger("uvicorn").setLevel(logging.WARNING)
|
|
784
|
+
# 禁用 uvicorn.error 的 INFO 级别日志
|
|
785
|
+
logging.getLogger("uvicorn.error").setLevel(logging.WARNING)
|
|
786
|
+
uvicorn.run(app, host=host, port=port, log_level="warning", access_log=False)
|
jarvis/jarvis_c2rust/__init__.py
CHANGED
|
@@ -5,16 +5,16 @@ Jarvis C2Rust 工具集。
|
|
|
5
5
|
核心数据:
|
|
6
6
|
- 统一符号表(JSONL):<project_root>/.jarvis/c2rust/symbols.jsonl(后续流程的主输入)
|
|
7
7
|
- 原始符号表(JSONL):<project_root>/.jarvis/c2rust/symbols_raw.jsonl
|
|
8
|
-
- 其他产物:translation_order.jsonl、library_replacements.jsonl、progress.json、symbol_map.jsonl 等
|
|
8
|
+
- 其他产物:translation_order.jsonl、library_replacements.jsonl、progress.json、config.json、symbol_map.jsonl 等
|
|
9
9
|
|
|
10
10
|
推荐用法(CLI):
|
|
11
|
+
- 配置管理: jarvis-c2rust config --files <hdrs...> [--root-list-syms ...] [--disabled-libs ...]
|
|
11
12
|
- 扫描: jarvis-c2rust scan
|
|
12
|
-
- 库替代评估: jarvis-c2rust lib-replace
|
|
13
|
+
- 库替代评估: jarvis-c2rust lib-replace [-g <llm-group>]
|
|
13
14
|
- 规划/落盘: jarvis-c2rust prepare [-g <llm-group>]
|
|
14
|
-
- 转译: jarvis-c2rust transpile [-g <llm-group>] [
|
|
15
|
+
- 转译: jarvis-c2rust transpile [-g <llm-group>] [-m <max-retries>](断点续跑默认始终启用)
|
|
15
16
|
- 代码优化: jarvis-c2rust optimize [--crate-dir ...] [--unsafe/--no-unsafe] [--structure/--no-structure] [--visibility/--no-visibility] [--doc/--no-doc] [-m N] [--dry-run]
|
|
16
|
-
-
|
|
17
|
-
- 一键流水线: jarvis-c2rust run [--files <hdrs...> -o roots.txt | --root-list-syms ...] [-g <llm-group>] [--disabled-libs ...]
|
|
17
|
+
- 一键流水线: jarvis-c2rust run [-g <llm-group>] [-m <max-retries>]
|
|
18
18
|
|
|
19
19
|
或(模块方式):
|
|
20
20
|
python -m jarvis.jarvis_c2rust.cli <subcommand>
|