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
jarvis/jarvis_code_agent/lint.py
CHANGED
|
@@ -146,17 +146,17 @@ def get_lint_tools(filename: str) -> List[str]:
|
|
|
146
146
|
"""
|
|
147
147
|
filename = os.path.basename(filename)
|
|
148
148
|
filename_lower = filename.lower()
|
|
149
|
-
|
|
149
|
+
|
|
150
150
|
# 优先尝试完整文件名匹配(例如 docker-compose.yml, .eslintrc, .prettierrc)
|
|
151
151
|
lint_tools = LINT_TOOLS.get(filename_lower, [])
|
|
152
152
|
if lint_tools:
|
|
153
153
|
return lint_tools
|
|
154
|
-
|
|
154
|
+
|
|
155
155
|
# 如果文件名匹配失败,再尝试扩展名匹配
|
|
156
156
|
ext = os.path.splitext(filename)[1]
|
|
157
157
|
if ext:
|
|
158
158
|
return LINT_TOOLS.get(ext.lower(), [])
|
|
159
|
-
|
|
159
|
+
|
|
160
160
|
return []
|
|
161
161
|
|
|
162
162
|
|
|
@@ -216,23 +216,27 @@ LINT_COMMAND_TEMPLATES: Dict[str, str] = {
|
|
|
216
216
|
}
|
|
217
217
|
|
|
218
218
|
|
|
219
|
-
def find_config_file(
|
|
219
|
+
def find_config_file(
|
|
220
|
+
config_names: List[str],
|
|
221
|
+
project_root: Optional[str] = None,
|
|
222
|
+
file_path: Optional[str] = None,
|
|
223
|
+
) -> Optional[str]:
|
|
220
224
|
"""
|
|
221
225
|
查找配置文件
|
|
222
|
-
|
|
226
|
+
|
|
223
227
|
Args:
|
|
224
228
|
config_names: 配置文件名列表(按优先级排序)
|
|
225
229
|
project_root: 项目根目录
|
|
226
230
|
file_path: 当前文件路径(可选,用于从文件所在目录向上查找)
|
|
227
|
-
|
|
231
|
+
|
|
228
232
|
Returns:
|
|
229
233
|
配置文件的绝对路径,如果未找到则返回None
|
|
230
234
|
"""
|
|
231
235
|
search_dirs = []
|
|
232
|
-
|
|
236
|
+
|
|
233
237
|
if project_root:
|
|
234
238
|
search_dirs.append(project_root)
|
|
235
|
-
|
|
239
|
+
|
|
236
240
|
# 如果提供了文件路径,从文件所在目录向上查找
|
|
237
241
|
if file_path:
|
|
238
242
|
if os.path.isabs(file_path):
|
|
@@ -241,7 +245,7 @@ def find_config_file(config_names: List[str], project_root: Optional[str] = None
|
|
|
241
245
|
current_dir = os.path.dirname(os.path.join(project_root, file_path))
|
|
242
246
|
else:
|
|
243
247
|
current_dir = os.path.dirname(os.path.abspath(file_path))
|
|
244
|
-
|
|
248
|
+
|
|
245
249
|
# 向上查找直到项目根目录
|
|
246
250
|
while current_dir:
|
|
247
251
|
if current_dir not in search_dirs:
|
|
@@ -252,22 +256,34 @@ def find_config_file(config_names: List[str], project_root: Optional[str] = None
|
|
|
252
256
|
if parent == current_dir: # 到达根目录
|
|
253
257
|
break
|
|
254
258
|
current_dir = parent
|
|
255
|
-
|
|
259
|
+
|
|
256
260
|
# 按优先级查找配置文件
|
|
257
261
|
for config_name in config_names:
|
|
258
262
|
for search_dir in search_dirs:
|
|
259
263
|
config_path = os.path.join(search_dir, config_name)
|
|
260
264
|
if os.path.exists(config_path) and os.path.isfile(config_path):
|
|
261
265
|
return os.path.abspath(config_path)
|
|
262
|
-
|
|
266
|
+
|
|
263
267
|
return None
|
|
264
268
|
|
|
265
269
|
|
|
266
270
|
# 工具配置文件映射(工具名 -> 可能的配置文件名列表)
|
|
267
271
|
TOOL_CONFIG_FILES: Dict[str, List[str]] = {
|
|
268
272
|
"checkstyle": ["checkstyle.xml", ".checkstyle.xml", "checkstyle-config.xml"],
|
|
269
|
-
"eslint": [
|
|
270
|
-
|
|
273
|
+
"eslint": [
|
|
274
|
+
".eslintrc.js",
|
|
275
|
+
".eslintrc.json",
|
|
276
|
+
".eslintrc.yml",
|
|
277
|
+
".eslintrc.yaml",
|
|
278
|
+
".eslintrc",
|
|
279
|
+
],
|
|
280
|
+
"stylelint": [
|
|
281
|
+
".stylelintrc",
|
|
282
|
+
".stylelintrc.json",
|
|
283
|
+
".stylelintrc.yml",
|
|
284
|
+
".stylelintrc.yaml",
|
|
285
|
+
"stylelint.config.js",
|
|
286
|
+
],
|
|
271
287
|
"yamllint": [".yamllint", ".yamllint.yml", ".yamllint.yaml"],
|
|
272
288
|
"markdownlint": [".markdownlint.json", ".markdownlintrc"],
|
|
273
289
|
"rubocop": [".rubocop.yml", ".rubocop.yaml", ".rubocop.toml"],
|
|
@@ -280,10 +296,21 @@ TOOL_CONFIG_FILES: Dict[str, List[str]] = {
|
|
|
280
296
|
REQUIRED_CONFIG_TOOLS = {"checkstyle"}
|
|
281
297
|
|
|
282
298
|
# 可选配置文件的工具(未找到配置文件时可以使用默认配置)
|
|
283
|
-
OPTIONAL_CONFIG_TOOLS = {
|
|
299
|
+
OPTIONAL_CONFIG_TOOLS = {
|
|
300
|
+
"eslint",
|
|
301
|
+
"stylelint",
|
|
302
|
+
"yamllint",
|
|
303
|
+
"markdownlint",
|
|
304
|
+
"rubocop",
|
|
305
|
+
"phpstan",
|
|
306
|
+
"sqlfluff",
|
|
307
|
+
"hadolint",
|
|
308
|
+
}
|
|
284
309
|
|
|
285
310
|
|
|
286
|
-
def get_lint_command(
|
|
311
|
+
def get_lint_command(
|
|
312
|
+
tool_name: str, file_path: str, project_root: Optional[str] = None
|
|
313
|
+
) -> Optional[str]:
|
|
287
314
|
"""
|
|
288
315
|
获取lint工具的具体命令
|
|
289
316
|
|
|
@@ -298,12 +325,12 @@ def get_lint_command(tool_name: str, file_path: str, project_root: Optional[str]
|
|
|
298
325
|
template = LINT_COMMAND_TEMPLATES.get(tool_name)
|
|
299
326
|
if not template:
|
|
300
327
|
return None
|
|
301
|
-
|
|
328
|
+
|
|
302
329
|
# 特殊处理:某些工具不需要文件路径(如 cargo clippy)
|
|
303
330
|
if "{file_path}" not in template and "{file_name}" not in template:
|
|
304
331
|
# 不需要文件路径,直接返回模板
|
|
305
332
|
return template
|
|
306
|
-
|
|
333
|
+
|
|
307
334
|
# 如果是绝对路径,直接使用;否则转换为绝对路径
|
|
308
335
|
if os.path.isabs(file_path):
|
|
309
336
|
abs_file_path = file_path
|
|
@@ -311,13 +338,13 @@ def get_lint_command(tool_name: str, file_path: str, project_root: Optional[str]
|
|
|
311
338
|
abs_file_path = os.path.join(project_root, file_path)
|
|
312
339
|
else:
|
|
313
340
|
abs_file_path = os.path.abspath(file_path)
|
|
314
|
-
|
|
341
|
+
|
|
315
342
|
# 准备占位符替换字典
|
|
316
343
|
placeholders = {
|
|
317
344
|
"file_path": abs_file_path,
|
|
318
345
|
"file_name": os.path.basename(abs_file_path),
|
|
319
346
|
}
|
|
320
|
-
|
|
347
|
+
|
|
321
348
|
# 如果模板需要配置文件,尝试查找
|
|
322
349
|
if "{config}" in template:
|
|
323
350
|
config_names = TOOL_CONFIG_FILES.get(tool_name, [])
|
|
@@ -344,20 +371,19 @@ def get_lint_command(tool_name: str, file_path: str, project_root: Optional[str]
|
|
|
344
371
|
else:
|
|
345
372
|
# 工具需要配置但未定义配置文件名,返回None
|
|
346
373
|
return None
|
|
347
|
-
|
|
374
|
+
|
|
348
375
|
# 替换占位符
|
|
349
376
|
try:
|
|
350
377
|
command = template.format(**placeholders)
|
|
351
378
|
except KeyError:
|
|
352
379
|
# 如果模板中有未定义的占位符,返回None
|
|
353
380
|
return None
|
|
354
|
-
|
|
381
|
+
|
|
355
382
|
return command
|
|
356
383
|
|
|
357
384
|
|
|
358
385
|
def get_lint_commands_for_files(
|
|
359
|
-
files: List[str],
|
|
360
|
-
project_root: Optional[str] = None
|
|
386
|
+
files: List[str], project_root: Optional[str] = None
|
|
361
387
|
) -> List[Tuple[str, str, str]]:
|
|
362
388
|
"""
|
|
363
389
|
获取多个文件的lint命令列表
|
|
@@ -372,13 +398,17 @@ def get_lint_commands_for_files(
|
|
|
372
398
|
commands = []
|
|
373
399
|
# 记录不需要文件路径的工具(如 cargo clippy),避免重复执行
|
|
374
400
|
project_level_tools = set()
|
|
375
|
-
|
|
401
|
+
|
|
376
402
|
for file_path in files:
|
|
377
403
|
tools = get_lint_tools(file_path)
|
|
378
404
|
for tool_name in tools:
|
|
379
405
|
# 检查是否是项目级别的工具(不需要文件路径)
|
|
380
406
|
template = LINT_COMMAND_TEMPLATES.get(tool_name)
|
|
381
|
-
if
|
|
407
|
+
if (
|
|
408
|
+
template
|
|
409
|
+
and "{file_path}" not in template
|
|
410
|
+
and "{file_name}" not in template
|
|
411
|
+
):
|
|
382
412
|
# 项目级别工具,每个项目只执行一次
|
|
383
413
|
if tool_name not in project_level_tools:
|
|
384
414
|
project_level_tools.add(tool_name)
|
|
@@ -391,11 +421,13 @@ def get_lint_commands_for_files(
|
|
|
391
421
|
command = get_lint_command(tool_name, file_path, project_root)
|
|
392
422
|
if command:
|
|
393
423
|
commands.append((tool_name, file_path, command))
|
|
394
|
-
|
|
424
|
+
|
|
395
425
|
return commands
|
|
396
426
|
|
|
397
427
|
|
|
398
|
-
def group_commands_by_tool(
|
|
428
|
+
def group_commands_by_tool(
|
|
429
|
+
commands: List[Tuple[str, str, str]],
|
|
430
|
+
) -> Dict[str, List[Tuple[str, str]]]:
|
|
399
431
|
"""
|
|
400
432
|
按工具分组命令
|
|
401
433
|
|
|
@@ -411,3 +443,202 @@ def group_commands_by_tool(commands: List[Tuple[str, str, str]]) -> Dict[str, Li
|
|
|
411
443
|
grouped[tool_name] = []
|
|
412
444
|
grouped[tool_name].append((file_path, command))
|
|
413
445
|
return grouped
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
# 格式化工具配置(文件扩展名/文件名 -> 格式化工具列表)
|
|
449
|
+
FORMAT_TOOLS = {
|
|
450
|
+
# Python
|
|
451
|
+
".py": ["ruff format"],
|
|
452
|
+
".pyw": ["ruff format"],
|
|
453
|
+
".pyi": ["ruff format"],
|
|
454
|
+
".pyx": ["ruff format"],
|
|
455
|
+
".pxd": ["ruff format"],
|
|
456
|
+
# JavaScript/TypeScript
|
|
457
|
+
".js": ["prettier"],
|
|
458
|
+
".mjs": ["prettier"],
|
|
459
|
+
".cjs": ["prettier"],
|
|
460
|
+
".jsx": ["prettier"],
|
|
461
|
+
".ts": ["prettier"],
|
|
462
|
+
".tsx": ["prettier"],
|
|
463
|
+
".cts": ["prettier"],
|
|
464
|
+
".mts": ["prettier"],
|
|
465
|
+
# Rust
|
|
466
|
+
".rs": ["rustfmt"],
|
|
467
|
+
# Go
|
|
468
|
+
".go": ["gofmt"],
|
|
469
|
+
# Java
|
|
470
|
+
".java": ["google-java-format"],
|
|
471
|
+
# C/C++
|
|
472
|
+
".c": ["clang-format"],
|
|
473
|
+
".cpp": ["clang-format"],
|
|
474
|
+
".cc": ["clang-format"],
|
|
475
|
+
".cxx": ["clang-format"],
|
|
476
|
+
".h": ["clang-format"],
|
|
477
|
+
".hpp": ["clang-format"],
|
|
478
|
+
".hxx": ["clang-format"],
|
|
479
|
+
".inl": ["clang-format"],
|
|
480
|
+
".ipp": ["clang-format"],
|
|
481
|
+
# HTML/CSS
|
|
482
|
+
".html": ["prettier"],
|
|
483
|
+
".htm": ["prettier"],
|
|
484
|
+
".xhtml": ["prettier"],
|
|
485
|
+
".css": ["prettier"],
|
|
486
|
+
".scss": ["prettier"],
|
|
487
|
+
".sass": ["prettier"],
|
|
488
|
+
".less": ["prettier"],
|
|
489
|
+
# JSON/YAML
|
|
490
|
+
".json": ["prettier"],
|
|
491
|
+
".jsonl": ["prettier"],
|
|
492
|
+
".json5": ["prettier"],
|
|
493
|
+
".yaml": ["prettier"],
|
|
494
|
+
".yml": ["prettier"],
|
|
495
|
+
# Markdown
|
|
496
|
+
".md": ["prettier"],
|
|
497
|
+
".markdown": ["prettier"],
|
|
498
|
+
# SQL
|
|
499
|
+
".sql": ["sqlfluff format"],
|
|
500
|
+
# Shell/Bash
|
|
501
|
+
".sh": ["shfmt"],
|
|
502
|
+
".bash": ["shfmt"],
|
|
503
|
+
# XML
|
|
504
|
+
".xml": ["xmllint --format"],
|
|
505
|
+
".xsd": ["xmllint --format"],
|
|
506
|
+
".dtd": ["xmllint --format"],
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
def load_format_tools_config() -> Dict[str, List[str]]:
|
|
511
|
+
"""从yaml文件加载格式化工具配置"""
|
|
512
|
+
config_path = os.path.join(get_data_dir(), "format_tools.yaml")
|
|
513
|
+
if not os.path.exists(config_path):
|
|
514
|
+
return {}
|
|
515
|
+
|
|
516
|
+
with open(config_path, "r") as f:
|
|
517
|
+
config = yaml.safe_load(f) or {}
|
|
518
|
+
return {k.lower(): v for k, v in config.items()} # 确保key是小写
|
|
519
|
+
|
|
520
|
+
|
|
521
|
+
# 合并默认配置和yaml配置
|
|
522
|
+
FORMAT_TOOLS.update(load_format_tools_config())
|
|
523
|
+
|
|
524
|
+
|
|
525
|
+
def get_format_tools(filename: str) -> List[str]:
|
|
526
|
+
"""
|
|
527
|
+
根据文件扩展名或文件名获取对应的格式化工具列表
|
|
528
|
+
优先级:完整文件名匹配 > 扩展名匹配
|
|
529
|
+
|
|
530
|
+
Args:
|
|
531
|
+
filename: 文件路径或文件名(如'test.py'或'Makefile')
|
|
532
|
+
|
|
533
|
+
Returns:
|
|
534
|
+
对应的格式化工具列表,如果找不到则返回空列表
|
|
535
|
+
"""
|
|
536
|
+
filename = os.path.basename(filename)
|
|
537
|
+
filename_lower = filename.lower()
|
|
538
|
+
|
|
539
|
+
# 优先尝试完整文件名匹配
|
|
540
|
+
format_tools = FORMAT_TOOLS.get(filename_lower, [])
|
|
541
|
+
if format_tools:
|
|
542
|
+
return format_tools
|
|
543
|
+
|
|
544
|
+
# 如果文件名匹配失败,再尝试扩展名匹配
|
|
545
|
+
ext = os.path.splitext(filename)[1]
|
|
546
|
+
if ext:
|
|
547
|
+
return FORMAT_TOOLS.get(ext.lower(), [])
|
|
548
|
+
|
|
549
|
+
return []
|
|
550
|
+
|
|
551
|
+
|
|
552
|
+
# 格式化工具命令模板映射
|
|
553
|
+
# 占位符说明:
|
|
554
|
+
# - {file_path}: 单个文件的完整路径
|
|
555
|
+
# - {files}: 多个文件路径,用空格分隔
|
|
556
|
+
# - {file_name}: 文件名(不含路径)
|
|
557
|
+
FORMAT_COMMAND_TEMPLATES: Dict[str, str] = {
|
|
558
|
+
# Python
|
|
559
|
+
"black": "black {file_path}",
|
|
560
|
+
"ruff format": "ruff format {file_path}",
|
|
561
|
+
# JavaScript/TypeScript
|
|
562
|
+
"prettier": "prettier --write {file_path}",
|
|
563
|
+
# Rust
|
|
564
|
+
"rustfmt": "rustfmt {file_path}",
|
|
565
|
+
# Go
|
|
566
|
+
"gofmt": "gofmt -w {file_path}",
|
|
567
|
+
# Java
|
|
568
|
+
"google-java-format": "google-java-format -i {file_path}",
|
|
569
|
+
# C/C++
|
|
570
|
+
"clang-format": "clang-format -i {file_path}",
|
|
571
|
+
# SQL
|
|
572
|
+
"sqlfluff format": "sqlfluff format {file_path}",
|
|
573
|
+
# Shell/Bash
|
|
574
|
+
"shfmt": "shfmt -w {file_path}",
|
|
575
|
+
# XML (xmllint格式化需要特殊处理,使用临时文件)
|
|
576
|
+
"xmllint --format": "xmllint --format {file_path} > {file_path}.tmp && mv {file_path}.tmp {file_path}",
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
|
|
580
|
+
def get_format_command(
|
|
581
|
+
tool_name: str, file_path: str, project_root: Optional[str] = None
|
|
582
|
+
) -> Optional[str]:
|
|
583
|
+
"""
|
|
584
|
+
获取格式化工具的具体命令
|
|
585
|
+
|
|
586
|
+
Args:
|
|
587
|
+
tool_name: 格式化工具名称(如 'black', 'prettier')
|
|
588
|
+
file_path: 文件路径(相对或绝对路径)
|
|
589
|
+
project_root: 项目根目录(可选,用于处理相对路径)
|
|
590
|
+
|
|
591
|
+
Returns:
|
|
592
|
+
命令字符串,如果工具不支持则返回None
|
|
593
|
+
"""
|
|
594
|
+
template = FORMAT_COMMAND_TEMPLATES.get(tool_name)
|
|
595
|
+
if not template:
|
|
596
|
+
return None
|
|
597
|
+
|
|
598
|
+
# 如果是绝对路径,直接使用;否则转换为绝对路径
|
|
599
|
+
if os.path.isabs(file_path):
|
|
600
|
+
abs_file_path = file_path
|
|
601
|
+
elif project_root:
|
|
602
|
+
abs_file_path = os.path.join(project_root, file_path)
|
|
603
|
+
else:
|
|
604
|
+
abs_file_path = os.path.abspath(file_path)
|
|
605
|
+
|
|
606
|
+
# 准备占位符替换字典
|
|
607
|
+
placeholders = {
|
|
608
|
+
"file_path": abs_file_path,
|
|
609
|
+
"file_name": os.path.basename(abs_file_path),
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
# 替换占位符
|
|
613
|
+
try:
|
|
614
|
+
command = template.format(**placeholders)
|
|
615
|
+
except KeyError:
|
|
616
|
+
# 如果模板中有未定义的占位符,返回None
|
|
617
|
+
return None
|
|
618
|
+
|
|
619
|
+
return command
|
|
620
|
+
|
|
621
|
+
|
|
622
|
+
def get_format_commands_for_files(
|
|
623
|
+
files: List[str], project_root: Optional[str] = None
|
|
624
|
+
) -> List[Tuple[str, str, str]]:
|
|
625
|
+
"""
|
|
626
|
+
获取多个文件的格式化命令列表
|
|
627
|
+
|
|
628
|
+
Args:
|
|
629
|
+
files: 文件路径列表
|
|
630
|
+
project_root: 项目根目录(可选)
|
|
631
|
+
|
|
632
|
+
Returns:
|
|
633
|
+
[(tool_name, file_path, command), ...] 格式的命令列表
|
|
634
|
+
"""
|
|
635
|
+
commands = []
|
|
636
|
+
|
|
637
|
+
for file_path in files:
|
|
638
|
+
tools = get_format_tools(file_path)
|
|
639
|
+
for tool_name in tools:
|
|
640
|
+
command = get_format_command(tool_name, file_path, project_root)
|
|
641
|
+
if command:
|
|
642
|
+
commands.append((tool_name, file_path, command))
|
|
643
|
+
|
|
644
|
+
return commands
|
|
@@ -12,7 +12,7 @@ from jarvis.jarvis_code_analysis.checklists.loader import get_language_checklist
|
|
|
12
12
|
|
|
13
13
|
from jarvis.jarvis_tools.read_code import ReadCodeTool
|
|
14
14
|
|
|
15
|
-
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
15
|
+
from jarvis.jarvis_utils.output import OutputType, PrettyOutput # 保留用于语法高亮
|
|
16
16
|
from jarvis.jarvis_utils.tag import ct, ot
|
|
17
17
|
from jarvis.jarvis_utils.utils import init_env, is_context_overflow
|
|
18
18
|
|
|
@@ -408,7 +408,7 @@ def execute_code_review(
|
|
|
408
408
|
# Combine review info with diff output
|
|
409
409
|
diff_output = review_info + diff_output
|
|
410
410
|
|
|
411
|
-
PrettyOutput.print(diff_output, OutputType.CODE, lang="diff")
|
|
411
|
+
PrettyOutput.print(diff_output, OutputType.CODE, lang="diff") # 保留语法高亮
|
|
412
412
|
|
|
413
413
|
system_prompt = """<code_review_guide>
|
|
414
414
|
<role>
|
|
@@ -621,10 +621,7 @@ def execute_code_review(
|
|
|
621
621
|
max_diff_size = 100 * 1024 * 1024 # Limit to 100MB
|
|
622
622
|
|
|
623
623
|
if len(diff_output) > max_diff_size:
|
|
624
|
-
|
|
625
|
-
f"代码差异内容总大小超过限制 ({len(diff_output)} > {max_diff_size} 字节),将截断内容",
|
|
626
|
-
OutputType.WARNING,
|
|
627
|
-
)
|
|
624
|
+
print(f"⚠️ 代码差异内容总大小超过限制 ({len(diff_output)} > {max_diff_size} 字节),将截断内容")
|
|
628
625
|
diff_output = (
|
|
629
626
|
diff_output[:max_diff_size]
|
|
630
627
|
+ "\n\n[diff content truncated due to size limitations...]"
|
|
@@ -648,8 +645,9 @@ def execute_code_review(
|
|
|
648
645
|
|
|
649
646
|
try:
|
|
650
647
|
# Check if content is too large
|
|
648
|
+
platform = agent.model if agent and agent.model else None
|
|
651
649
|
is_large_content = is_context_overflow(
|
|
652
|
-
diff_output, model_group
|
|
650
|
+
diff_output, model_group, platform
|
|
653
651
|
)
|
|
654
652
|
|
|
655
653
|
# Upload the file to the agent's model
|
|
@@ -701,10 +699,7 @@ def execute_code_review(
|
|
|
701
699
|
try:
|
|
702
700
|
os.unlink(temp_file_path)
|
|
703
701
|
except Exception:
|
|
704
|
-
|
|
705
|
-
f"临时文件 {temp_file_path} 未能删除",
|
|
706
|
-
OutputType.WARNING,
|
|
707
|
-
)
|
|
702
|
+
print(f"⚠️ 临时文件 {temp_file_path} 未能删除")
|
|
708
703
|
|
|
709
704
|
return {"success": True, "stdout": result, "stderr": ""}
|
|
710
705
|
finally:
|
|
@@ -745,11 +740,11 @@ def review_commit(
|
|
|
745
740
|
}
|
|
746
741
|
result = execute_code_review(tool_args)
|
|
747
742
|
if result["success"]:
|
|
748
|
-
|
|
743
|
+
print("✅ 自动代码审查结果:")
|
|
749
744
|
report = extract_code_report(result["stdout"])
|
|
750
|
-
PrettyOutput.print(report, OutputType.SUCCESS, lang="markdown")
|
|
745
|
+
PrettyOutput.print(report, OutputType.SUCCESS, lang="markdown") # 保留语法高亮
|
|
751
746
|
else:
|
|
752
|
-
|
|
747
|
+
print(f"⚠️ {result['stderr']}")
|
|
753
748
|
|
|
754
749
|
|
|
755
750
|
@app.command("current")
|
|
@@ -769,11 +764,11 @@ def review_current(
|
|
|
769
764
|
}
|
|
770
765
|
result = execute_code_review(tool_args)
|
|
771
766
|
if result["success"]:
|
|
772
|
-
|
|
767
|
+
print("✅ 自动代码审查结果:")
|
|
773
768
|
report = extract_code_report(result["stdout"])
|
|
774
|
-
PrettyOutput.print(report, OutputType.SUCCESS, lang="markdown")
|
|
769
|
+
PrettyOutput.print(report, OutputType.SUCCESS, lang="markdown") # 保留语法高亮
|
|
775
770
|
else:
|
|
776
|
-
|
|
771
|
+
print(f"⚠️ {result['stderr']}")
|
|
777
772
|
|
|
778
773
|
|
|
779
774
|
@app.command("range")
|
|
@@ -797,11 +792,11 @@ def review_range(
|
|
|
797
792
|
}
|
|
798
793
|
result = execute_code_review(tool_args)
|
|
799
794
|
if result["success"]:
|
|
800
|
-
|
|
795
|
+
print("✅ 自动代码审查结果:")
|
|
801
796
|
report = extract_code_report(result["stdout"])
|
|
802
|
-
PrettyOutput.print(report, OutputType.SUCCESS, lang="markdown")
|
|
797
|
+
PrettyOutput.print(report, OutputType.SUCCESS, lang="markdown") # 保留语法高亮
|
|
803
798
|
else:
|
|
804
|
-
|
|
799
|
+
print(f"⚠️ {result['stderr']}")
|
|
805
800
|
|
|
806
801
|
|
|
807
802
|
@app.command("file")
|
|
@@ -823,16 +818,16 @@ def review_file(
|
|
|
823
818
|
}
|
|
824
819
|
result = execute_code_review(tool_args)
|
|
825
820
|
if result["success"]:
|
|
826
|
-
|
|
821
|
+
print("✅ 自动代码审查结果:")
|
|
827
822
|
report = extract_code_report(result["stdout"])
|
|
828
|
-
PrettyOutput.print(report, OutputType.SUCCESS, lang="markdown")
|
|
823
|
+
PrettyOutput.print(report, OutputType.SUCCESS, lang="markdown") # 保留语法高亮
|
|
829
824
|
else:
|
|
830
|
-
|
|
825
|
+
print(f"⚠️ {result['stderr']}")
|
|
831
826
|
|
|
832
827
|
|
|
833
828
|
def cli():
|
|
834
829
|
"""Typer application entry point"""
|
|
835
|
-
init_env("
|
|
830
|
+
init_env("")
|
|
836
831
|
app()
|
|
837
832
|
|
|
838
833
|
|
|
@@ -120,12 +120,32 @@
|
|
|
120
120
|
"JARVIS_PLATFORM": {
|
|
121
121
|
"type": "string",
|
|
122
122
|
"description": "常规操作平台名称",
|
|
123
|
-
"default": "
|
|
123
|
+
"default": "openai"
|
|
124
124
|
},
|
|
125
125
|
"JARVIS_MODEL": {
|
|
126
126
|
"type": "string",
|
|
127
127
|
"description": "常规操作模型名称",
|
|
128
|
-
"default": "
|
|
128
|
+
"default": "gpt-5"
|
|
129
|
+
},
|
|
130
|
+
"JARVIS_CHEAP_PLATFORM": {
|
|
131
|
+
"type": "string",
|
|
132
|
+
"description": "廉价操作的平台名称。如未配置,则使用 JARVIS_PLATFORM 的值",
|
|
133
|
+
"default": ""
|
|
134
|
+
},
|
|
135
|
+
"JARVIS_CHEAP_MODEL": {
|
|
136
|
+
"type": "string",
|
|
137
|
+
"description": "廉价操作的模型名称。如未配置,则使用 JARVIS_MODEL 的值",
|
|
138
|
+
"default": ""
|
|
139
|
+
},
|
|
140
|
+
"JARVIS_SMART_PLATFORM": {
|
|
141
|
+
"type": "string",
|
|
142
|
+
"description": "智能操作的平台名称。如未配置,则使用 JARVIS_PLATFORM 的值",
|
|
143
|
+
"default": ""
|
|
144
|
+
},
|
|
145
|
+
"JARVIS_SMART_MODEL": {
|
|
146
|
+
"type": "string",
|
|
147
|
+
"description": "智能操作的模型名称。如未配置,则使用 JARVIS_MODEL 的值",
|
|
148
|
+
"default": ""
|
|
129
149
|
},
|
|
130
150
|
"JARVIS_WEB_SEARCH_PLATFORM": {
|
|
131
151
|
"type": "string",
|
|
@@ -153,16 +173,32 @@
|
|
|
153
173
|
"properties": {
|
|
154
174
|
"JARVIS_PLATFORM": {
|
|
155
175
|
"type": "string",
|
|
156
|
-
"default": "
|
|
176
|
+
"default": "openai"
|
|
157
177
|
},
|
|
158
178
|
"JARVIS_MODEL": {
|
|
159
179
|
"type": "string",
|
|
160
|
-
"default": "
|
|
180
|
+
"default": "gpt-5"
|
|
161
181
|
},
|
|
162
182
|
"JARVIS_MAX_INPUT_TOKEN_COUNT": {
|
|
163
183
|
"type": "number",
|
|
164
184
|
"default": 32000
|
|
165
185
|
},
|
|
186
|
+
"JARVIS_CHEAP_PLATFORM": {
|
|
187
|
+
"type": "string",
|
|
188
|
+
"description": "廉价操作的平台名称。如未配置,则使用 JARVIS_PLATFORM 的值"
|
|
189
|
+
},
|
|
190
|
+
"JARVIS_CHEAP_MODEL": {
|
|
191
|
+
"type": "string",
|
|
192
|
+
"description": "廉价操作的模型名称。如未配置,则使用 JARVIS_MODEL 的值"
|
|
193
|
+
},
|
|
194
|
+
"JARVIS_SMART_PLATFORM": {
|
|
195
|
+
"type": "string",
|
|
196
|
+
"description": "智能操作的平台名称。如未配置,则使用 JARVIS_PLATFORM 的值"
|
|
197
|
+
},
|
|
198
|
+
"JARVIS_SMART_MODEL": {
|
|
199
|
+
"type": "string",
|
|
200
|
+
"description": "智能操作的模型名称。如未配置,则使用 JARVIS_MODEL 的值"
|
|
201
|
+
},
|
|
166
202
|
"ENV": {
|
|
167
203
|
"type": "object",
|
|
168
204
|
"description": "该模型组特定的环境变量,会覆盖全局 ENV 配置",
|
|
@@ -188,37 +224,16 @@
|
|
|
188
224
|
"description": "AI工具筛选阈值:当可用工具数量超过此值时触发AI筛选",
|
|
189
225
|
"default": 30
|
|
190
226
|
},
|
|
191
|
-
"JARVIS_PLAN_ENABLED": {
|
|
192
|
-
"type": "boolean",
|
|
193
|
-
"description": "是否默认启用任务规划。当 Agent 初始化时 plan 参数未指定,将从此配置加载。默认 true。",
|
|
194
|
-
"default": true
|
|
195
|
-
},
|
|
196
|
-
"JARVIS_PLAN_MAX_DEPTH": {
|
|
197
|
-
"type": "number",
|
|
198
|
-
"description": "任务规划的最大层数。用于限制 plan 模式的递归拆分深度。仅在启用规划时生效(通过 CLI --plan/--no-plan 控制),默认 2。",
|
|
199
|
-
"default": 2
|
|
200
|
-
},
|
|
201
227
|
"JARVIS_SCRIPT_EXECUTION_TIMEOUT": {
|
|
202
228
|
"type": "number",
|
|
203
229
|
"description": "脚本执行的超时时间(秒),仅在非交互模式下生效。",
|
|
204
230
|
"default": 300
|
|
205
231
|
},
|
|
206
|
-
"JARVIS_AUTO_SUMMARY_ROUNDS": {
|
|
207
|
-
"type": "number",
|
|
208
|
-
"description": "基于对话轮次的自动总结阈值(达到该轮次后自动总结并清理历史)",
|
|
209
|
-
"default": 50
|
|
210
|
-
},
|
|
211
232
|
"JARVIS_CONFIRM_BEFORE_APPLY_PATCH": {
|
|
212
233
|
"type": "boolean",
|
|
213
234
|
"description": "应用补丁前是否需要确认",
|
|
214
235
|
"default": false
|
|
215
236
|
},
|
|
216
|
-
"JARVIS_PATCH_FORMAT": {
|
|
217
|
-
"type": "string",
|
|
218
|
-
"enum": ["all", "search", "search_range"],
|
|
219
|
-
"description": "补丁格式处理模式:all 同时支持 SEARCH 与 SEARCH_START/SEARCH_END;search 仅允许精确片段匹配;search_range 仅允许范围匹配。",
|
|
220
|
-
"default": "all"
|
|
221
|
-
},
|
|
222
237
|
"JARVIS_DATA_PATH": {
|
|
223
238
|
"type": "string",
|
|
224
239
|
"description": "Jarvis数据存储目录路径",
|
|
@@ -320,7 +335,7 @@
|
|
|
320
335
|
"JARVIS_BUILD_VALIDATION_TIMEOUT": {
|
|
321
336
|
"type": "number",
|
|
322
337
|
"description": "构建验证的超时时间(秒)。当构建验证执行时间超过此值时,将终止验证并报告超时。",
|
|
323
|
-
"default":
|
|
338
|
+
"default": 600
|
|
324
339
|
},
|
|
325
340
|
"JARVIS_ENABLE_IMPACT_ANALYSIS": {
|
|
326
341
|
"type": "boolean",
|
|
@@ -367,6 +382,11 @@
|
|
|
367
382
|
"description": "是否启用意图识别功能。用于智能上下文推荐中的LLM意图提取和语义分析",
|
|
368
383
|
"default": true
|
|
369
384
|
},
|
|
385
|
+
"JARVIS_ENABLE_MEMORY_ORGANIZER": {
|
|
386
|
+
"type": "boolean",
|
|
387
|
+
"description": "是否启用自动记忆整理功能。在任务完成后自动检测记忆库状态,当记忆数量超过200条且存在重叠时提示用户整理",
|
|
388
|
+
"default": false
|
|
389
|
+
},
|
|
370
390
|
"JARVIS_GIT_CHECK_MODE": {
|
|
371
391
|
"type": "string",
|
|
372
392
|
"enum": ["strict", "warn"],
|
|
@@ -540,6 +560,13 @@
|
|
|
540
560
|
"type": "string",
|
|
541
561
|
"description": "系统Shell路径,用于获取当前使用的shell类型",
|
|
542
562
|
"default": "/bin/bash"
|
|
563
|
+
},
|
|
564
|
+
"JARVIS_CONVERSATION_TURN_THRESHOLD": {
|
|
565
|
+
"type": "number",
|
|
566
|
+
"description": "对话轮次阈值,用于触发总结。当对话轮次超过此值时,系统会自动触发对话总结",
|
|
567
|
+
"default": 50,
|
|
568
|
+
"minimum": 1,
|
|
569
|
+
"maximum": 1000
|
|
543
570
|
}
|
|
544
571
|
},
|
|
545
572
|
"additionalProperties": true
|