jarvis-ai-assistant 0.7.16__py3-none-any.whl → 1.0.2__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 +567 -222
- jarvis/jarvis_agent/agent_manager.py +19 -12
- jarvis/jarvis_agent/builtin_input_handler.py +79 -11
- jarvis/jarvis_agent/config_editor.py +7 -2
- jarvis/jarvis_agent/event_bus.py +24 -13
- jarvis/jarvis_agent/events.py +19 -1
- jarvis/jarvis_agent/file_context_handler.py +67 -64
- jarvis/jarvis_agent/file_methodology_manager.py +38 -24
- jarvis/jarvis_agent/jarvis.py +186 -114
- jarvis/jarvis_agent/language_extractors/__init__.py +8 -1
- jarvis/jarvis_agent/language_extractors/c_extractor.py +7 -4
- jarvis/jarvis_agent/language_extractors/cpp_extractor.py +9 -4
- jarvis/jarvis_agent/language_extractors/go_extractor.py +7 -4
- jarvis/jarvis_agent/language_extractors/java_extractor.py +27 -20
- jarvis/jarvis_agent/language_extractors/javascript_extractor.py +22 -17
- jarvis/jarvis_agent/language_extractors/python_extractor.py +7 -4
- jarvis/jarvis_agent/language_extractors/rust_extractor.py +7 -4
- jarvis/jarvis_agent/language_extractors/typescript_extractor.py +22 -17
- jarvis/jarvis_agent/language_support_info.py +250 -219
- jarvis/jarvis_agent/main.py +19 -23
- jarvis/jarvis_agent/memory_manager.py +9 -6
- jarvis/jarvis_agent/methodology_share_manager.py +21 -15
- jarvis/jarvis_agent/output_handler.py +4 -2
- jarvis/jarvis_agent/prompt_builder.py +7 -6
- jarvis/jarvis_agent/prompt_manager.py +113 -8
- jarvis/jarvis_agent/prompts.py +317 -85
- jarvis/jarvis_agent/protocols.py +5 -2
- jarvis/jarvis_agent/run_loop.py +192 -32
- jarvis/jarvis_agent/session_manager.py +7 -3
- jarvis/jarvis_agent/share_manager.py +23 -13
- jarvis/jarvis_agent/shell_input_handler.py +12 -8
- jarvis/jarvis_agent/stdio_redirect.py +25 -26
- jarvis/jarvis_agent/task_analyzer.py +29 -23
- jarvis/jarvis_agent/task_list.py +869 -0
- jarvis/jarvis_agent/task_manager.py +26 -23
- jarvis/jarvis_agent/tool_executor.py +6 -5
- jarvis/jarvis_agent/tool_share_manager.py +24 -14
- jarvis/jarvis_agent/user_interaction.py +3 -3
- jarvis/jarvis_agent/utils.py +9 -1
- jarvis/jarvis_agent/web_bridge.py +37 -17
- jarvis/jarvis_agent/web_output_sink.py +5 -2
- jarvis/jarvis_agent/web_server.py +165 -36
- jarvis/jarvis_c2rust/__init__.py +1 -1
- jarvis/jarvis_c2rust/cli.py +260 -141
- jarvis/jarvis_c2rust/collector.py +37 -18
- jarvis/jarvis_c2rust/constants.py +60 -0
- jarvis/jarvis_c2rust/library_replacer.py +242 -1010
- jarvis/jarvis_c2rust/library_replacer_checkpoint.py +133 -0
- jarvis/jarvis_c2rust/library_replacer_llm.py +287 -0
- jarvis/jarvis_c2rust/library_replacer_loader.py +191 -0
- jarvis/jarvis_c2rust/library_replacer_output.py +134 -0
- jarvis/jarvis_c2rust/library_replacer_prompts.py +124 -0
- jarvis/jarvis_c2rust/library_replacer_utils.py +188 -0
- jarvis/jarvis_c2rust/llm_module_agent.py +98 -1044
- jarvis/jarvis_c2rust/llm_module_agent_apply.py +170 -0
- jarvis/jarvis_c2rust/llm_module_agent_executor.py +288 -0
- jarvis/jarvis_c2rust/llm_module_agent_loader.py +170 -0
- jarvis/jarvis_c2rust/llm_module_agent_prompts.py +268 -0
- jarvis/jarvis_c2rust/llm_module_agent_types.py +57 -0
- jarvis/jarvis_c2rust/llm_module_agent_utils.py +150 -0
- jarvis/jarvis_c2rust/llm_module_agent_validator.py +119 -0
- jarvis/jarvis_c2rust/loaders.py +28 -10
- jarvis/jarvis_c2rust/models.py +5 -2
- jarvis/jarvis_c2rust/optimizer.py +192 -1974
- jarvis/jarvis_c2rust/optimizer_build_fix.py +286 -0
- jarvis/jarvis_c2rust/optimizer_clippy.py +766 -0
- jarvis/jarvis_c2rust/optimizer_config.py +49 -0
- jarvis/jarvis_c2rust/optimizer_docs.py +183 -0
- jarvis/jarvis_c2rust/optimizer_options.py +48 -0
- jarvis/jarvis_c2rust/optimizer_progress.py +469 -0
- jarvis/jarvis_c2rust/optimizer_report.py +52 -0
- jarvis/jarvis_c2rust/optimizer_unsafe.py +309 -0
- jarvis/jarvis_c2rust/optimizer_utils.py +469 -0
- jarvis/jarvis_c2rust/optimizer_visibility.py +185 -0
- jarvis/jarvis_c2rust/scanner.py +229 -166
- jarvis/jarvis_c2rust/transpiler.py +531 -2732
- jarvis/jarvis_c2rust/transpiler_agents.py +503 -0
- jarvis/jarvis_c2rust/transpiler_build.py +1294 -0
- jarvis/jarvis_c2rust/transpiler_codegen.py +204 -0
- jarvis/jarvis_c2rust/transpiler_compile.py +146 -0
- jarvis/jarvis_c2rust/transpiler_config.py +178 -0
- jarvis/jarvis_c2rust/transpiler_context.py +122 -0
- jarvis/jarvis_c2rust/transpiler_executor.py +516 -0
- jarvis/jarvis_c2rust/transpiler_generation.py +278 -0
- jarvis/jarvis_c2rust/transpiler_git.py +163 -0
- jarvis/jarvis_c2rust/transpiler_mod_utils.py +225 -0
- jarvis/jarvis_c2rust/transpiler_modules.py +336 -0
- jarvis/jarvis_c2rust/transpiler_planning.py +394 -0
- jarvis/jarvis_c2rust/transpiler_review.py +1196 -0
- jarvis/jarvis_c2rust/transpiler_symbols.py +176 -0
- jarvis/jarvis_c2rust/utils.py +269 -79
- jarvis/jarvis_code_agent/after_change.py +233 -0
- jarvis/jarvis_code_agent/build_validation_config.py +37 -30
- jarvis/jarvis_code_agent/builtin_rules.py +68 -0
- jarvis/jarvis_code_agent/code_agent.py +976 -1517
- jarvis/jarvis_code_agent/code_agent_build.py +227 -0
- jarvis/jarvis_code_agent/code_agent_diff.py +246 -0
- jarvis/jarvis_code_agent/code_agent_git.py +525 -0
- jarvis/jarvis_code_agent/code_agent_impact.py +177 -0
- jarvis/jarvis_code_agent/code_agent_lint.py +283 -0
- jarvis/jarvis_code_agent/code_agent_llm.py +159 -0
- jarvis/jarvis_code_agent/code_agent_postprocess.py +105 -0
- jarvis/jarvis_code_agent/code_agent_prompts.py +46 -0
- jarvis/jarvis_code_agent/code_agent_rules.py +305 -0
- jarvis/jarvis_code_agent/code_analyzer/__init__.py +52 -48
- jarvis/jarvis_code_agent/code_analyzer/base_language.py +12 -10
- jarvis/jarvis_code_agent/code_analyzer/build_validator/__init__.py +12 -11
- jarvis/jarvis_code_agent/code_analyzer/build_validator/base.py +16 -12
- jarvis/jarvis_code_agent/code_analyzer/build_validator/cmake.py +26 -17
- jarvis/jarvis_code_agent/code_analyzer/build_validator/detector.py +558 -104
- jarvis/jarvis_code_agent/code_analyzer/build_validator/fallback.py +27 -16
- jarvis/jarvis_code_agent/code_analyzer/build_validator/go.py +22 -18
- jarvis/jarvis_code_agent/code_analyzer/build_validator/java_gradle.py +21 -16
- jarvis/jarvis_code_agent/code_analyzer/build_validator/java_maven.py +20 -16
- jarvis/jarvis_code_agent/code_analyzer/build_validator/makefile.py +27 -16
- jarvis/jarvis_code_agent/code_analyzer/build_validator/nodejs.py +47 -23
- jarvis/jarvis_code_agent/code_analyzer/build_validator/python.py +71 -37
- jarvis/jarvis_code_agent/code_analyzer/build_validator/rust.py +162 -35
- jarvis/jarvis_code_agent/code_analyzer/build_validator/validator.py +111 -57
- jarvis/jarvis_code_agent/code_analyzer/build_validator.py +18 -12
- jarvis/jarvis_code_agent/code_analyzer/context_manager.py +185 -183
- jarvis/jarvis_code_agent/code_analyzer/context_recommender.py +2 -1
- jarvis/jarvis_code_agent/code_analyzer/dependency_analyzer.py +24 -15
- jarvis/jarvis_code_agent/code_analyzer/file_ignore.py +227 -141
- jarvis/jarvis_code_agent/code_analyzer/impact_analyzer.py +321 -247
- jarvis/jarvis_code_agent/code_analyzer/language_registry.py +37 -29
- jarvis/jarvis_code_agent/code_analyzer/language_support.py +21 -13
- jarvis/jarvis_code_agent/code_analyzer/languages/__init__.py +15 -9
- jarvis/jarvis_code_agent/code_analyzer/languages/c_cpp_language.py +75 -45
- jarvis/jarvis_code_agent/code_analyzer/languages/go_language.py +87 -52
- jarvis/jarvis_code_agent/code_analyzer/languages/java_language.py +84 -51
- jarvis/jarvis_code_agent/code_analyzer/languages/javascript_language.py +94 -64
- jarvis/jarvis_code_agent/code_analyzer/languages/python_language.py +109 -71
- jarvis/jarvis_code_agent/code_analyzer/languages/rust_language.py +97 -63
- jarvis/jarvis_code_agent/code_analyzer/languages/typescript_language.py +103 -69
- jarvis/jarvis_code_agent/code_analyzer/llm_context_recommender.py +271 -268
- jarvis/jarvis_code_agent/code_analyzer/symbol_extractor.py +76 -64
- jarvis/jarvis_code_agent/code_analyzer/tree_sitter_extractor.py +92 -19
- jarvis/jarvis_code_agent/diff_visualizer.py +998 -0
- jarvis/jarvis_code_agent/lint.py +223 -524
- jarvis/jarvis_code_agent/rule_share_manager.py +158 -0
- jarvis/jarvis_code_agent/rules/clean_code.md +144 -0
- jarvis/jarvis_code_agent/rules/code_review.md +115 -0
- jarvis/jarvis_code_agent/rules/documentation.md +165 -0
- jarvis/jarvis_code_agent/rules/generate_rules.md +52 -0
- jarvis/jarvis_code_agent/rules/performance.md +158 -0
- jarvis/jarvis_code_agent/rules/refactoring.md +139 -0
- jarvis/jarvis_code_agent/rules/security.md +160 -0
- jarvis/jarvis_code_agent/rules/tdd.md +78 -0
- jarvis/jarvis_code_agent/test_rules/cpp_test.md +118 -0
- jarvis/jarvis_code_agent/test_rules/go_test.md +98 -0
- jarvis/jarvis_code_agent/test_rules/java_test.md +99 -0
- jarvis/jarvis_code_agent/test_rules/javascript_test.md +113 -0
- jarvis/jarvis_code_agent/test_rules/php_test.md +117 -0
- jarvis/jarvis_code_agent/test_rules/python_test.md +91 -0
- jarvis/jarvis_code_agent/test_rules/ruby_test.md +102 -0
- jarvis/jarvis_code_agent/test_rules/rust_test.md +86 -0
- jarvis/jarvis_code_agent/utils.py +36 -26
- jarvis/jarvis_code_analysis/checklists/loader.py +21 -21
- jarvis/jarvis_code_analysis/code_review.py +64 -33
- jarvis/jarvis_data/config_schema.json +285 -192
- jarvis/jarvis_git_squash/main.py +8 -6
- jarvis/jarvis_git_utils/git_commiter.py +53 -76
- jarvis/jarvis_mcp/__init__.py +5 -2
- jarvis/jarvis_mcp/sse_mcp_client.py +40 -30
- jarvis/jarvis_mcp/stdio_mcp_client.py +27 -19
- jarvis/jarvis_mcp/streamable_mcp_client.py +35 -26
- jarvis/jarvis_memory_organizer/memory_organizer.py +78 -55
- jarvis/jarvis_methodology/main.py +48 -39
- jarvis/jarvis_multi_agent/__init__.py +56 -23
- jarvis/jarvis_multi_agent/main.py +15 -18
- jarvis/jarvis_platform/base.py +179 -111
- jarvis/jarvis_platform/human.py +27 -16
- jarvis/jarvis_platform/kimi.py +52 -45
- jarvis/jarvis_platform/openai.py +101 -40
- jarvis/jarvis_platform/registry.py +51 -33
- jarvis/jarvis_platform/tongyi.py +68 -38
- jarvis/jarvis_platform/yuanbao.py +59 -43
- jarvis/jarvis_platform_manager/main.py +68 -76
- jarvis/jarvis_platform_manager/service.py +24 -14
- jarvis/jarvis_rag/README_CONFIG.md +314 -0
- jarvis/jarvis_rag/README_DYNAMIC_LOADING.md +311 -0
- jarvis/jarvis_rag/README_ONLINE_MODELS.md +230 -0
- jarvis/jarvis_rag/__init__.py +57 -4
- jarvis/jarvis_rag/cache.py +3 -1
- jarvis/jarvis_rag/cli.py +48 -68
- jarvis/jarvis_rag/embedding_interface.py +39 -0
- jarvis/jarvis_rag/embedding_manager.py +7 -230
- jarvis/jarvis_rag/embeddings/__init__.py +41 -0
- jarvis/jarvis_rag/embeddings/base.py +114 -0
- jarvis/jarvis_rag/embeddings/cohere.py +66 -0
- jarvis/jarvis_rag/embeddings/edgefn.py +117 -0
- jarvis/jarvis_rag/embeddings/local.py +260 -0
- jarvis/jarvis_rag/embeddings/openai.py +62 -0
- jarvis/jarvis_rag/embeddings/registry.py +293 -0
- jarvis/jarvis_rag/llm_interface.py +8 -6
- jarvis/jarvis_rag/query_rewriter.py +8 -9
- jarvis/jarvis_rag/rag_pipeline.py +61 -52
- jarvis/jarvis_rag/reranker.py +7 -75
- jarvis/jarvis_rag/reranker_interface.py +32 -0
- jarvis/jarvis_rag/rerankers/__init__.py +41 -0
- jarvis/jarvis_rag/rerankers/base.py +109 -0
- jarvis/jarvis_rag/rerankers/cohere.py +67 -0
- jarvis/jarvis_rag/rerankers/edgefn.py +140 -0
- jarvis/jarvis_rag/rerankers/jina.py +79 -0
- jarvis/jarvis_rag/rerankers/local.py +89 -0
- jarvis/jarvis_rag/rerankers/registry.py +293 -0
- jarvis/jarvis_rag/retriever.py +58 -43
- jarvis/jarvis_sec/__init__.py +66 -141
- jarvis/jarvis_sec/agents.py +21 -17
- jarvis/jarvis_sec/analysis.py +80 -33
- jarvis/jarvis_sec/checkers/__init__.py +7 -13
- jarvis/jarvis_sec/checkers/c_checker.py +356 -164
- jarvis/jarvis_sec/checkers/rust_checker.py +47 -29
- jarvis/jarvis_sec/cli.py +43 -21
- jarvis/jarvis_sec/clustering.py +430 -272
- jarvis/jarvis_sec/file_manager.py +99 -55
- jarvis/jarvis_sec/parsers.py +9 -6
- jarvis/jarvis_sec/prompts.py +4 -3
- jarvis/jarvis_sec/report.py +44 -22
- jarvis/jarvis_sec/review.py +180 -107
- jarvis/jarvis_sec/status.py +50 -41
- jarvis/jarvis_sec/types.py +3 -0
- jarvis/jarvis_sec/utils.py +160 -83
- jarvis/jarvis_sec/verification.py +411 -181
- jarvis/jarvis_sec/workflow.py +132 -21
- jarvis/jarvis_smart_shell/main.py +28 -41
- jarvis/jarvis_stats/cli.py +14 -12
- jarvis/jarvis_stats/stats.py +28 -19
- jarvis/jarvis_stats/storage.py +14 -8
- jarvis/jarvis_stats/visualizer.py +12 -7
- jarvis/jarvis_tools/base.py +5 -2
- jarvis/jarvis_tools/clear_memory.py +13 -9
- jarvis/jarvis_tools/cli/main.py +23 -18
- jarvis/jarvis_tools/edit_file.py +572 -873
- jarvis/jarvis_tools/execute_script.py +10 -7
- jarvis/jarvis_tools/file_analyzer.py +7 -8
- jarvis/jarvis_tools/meta_agent.py +287 -0
- jarvis/jarvis_tools/methodology.py +5 -3
- jarvis/jarvis_tools/read_code.py +305 -1438
- jarvis/jarvis_tools/read_symbols.py +50 -17
- jarvis/jarvis_tools/read_webpage.py +19 -18
- jarvis/jarvis_tools/registry.py +435 -156
- jarvis/jarvis_tools/retrieve_memory.py +16 -11
- jarvis/jarvis_tools/save_memory.py +8 -6
- jarvis/jarvis_tools/search_web.py +31 -31
- jarvis/jarvis_tools/sub_agent.py +32 -28
- jarvis/jarvis_tools/sub_code_agent.py +44 -60
- jarvis/jarvis_tools/task_list_manager.py +1811 -0
- jarvis/jarvis_tools/virtual_tty.py +29 -19
- jarvis/jarvis_utils/__init__.py +4 -0
- jarvis/jarvis_utils/builtin_replace_map.py +2 -1
- jarvis/jarvis_utils/clipboard.py +9 -8
- jarvis/jarvis_utils/collections.py +331 -0
- jarvis/jarvis_utils/config.py +699 -194
- jarvis/jarvis_utils/dialogue_recorder.py +294 -0
- jarvis/jarvis_utils/embedding.py +6 -3
- jarvis/jarvis_utils/file_processors.py +7 -1
- jarvis/jarvis_utils/fzf.py +9 -3
- jarvis/jarvis_utils/git_utils.py +71 -42
- jarvis/jarvis_utils/globals.py +116 -32
- jarvis/jarvis_utils/http.py +6 -2
- jarvis/jarvis_utils/input.py +318 -83
- jarvis/jarvis_utils/jsonnet_compat.py +119 -104
- jarvis/jarvis_utils/methodology.py +37 -28
- jarvis/jarvis_utils/output.py +201 -44
- jarvis/jarvis_utils/utils.py +986 -628
- {jarvis_ai_assistant-0.7.16.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/METADATA +49 -33
- jarvis_ai_assistant-1.0.2.dist-info/RECORD +304 -0
- jarvis/jarvis_code_agent/code_analyzer/structured_code.py +0 -556
- jarvis/jarvis_tools/generate_new_tool.py +0 -205
- jarvis/jarvis_tools/lsp_client.py +0 -1552
- jarvis/jarvis_tools/rewrite_file.py +0 -105
- jarvis_ai_assistant-0.7.16.dist-info/RECORD +0 -218
- {jarvis_ai_assistant-0.7.16.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.7.16.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.7.16.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.7.16.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/top_level.txt +0 -0
jarvis/jarvis_sec/review.py
CHANGED
|
@@ -1,18 +1,27 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
"""复核相关模块"""
|
|
3
3
|
|
|
4
|
-
from typing import Dict
|
|
5
|
-
import
|
|
4
|
+
from typing import Dict
|
|
5
|
+
from typing import List
|
|
6
|
+
from typing import Optional
|
|
6
7
|
|
|
7
|
-
from jarvis.
|
|
8
|
+
from jarvis.jarvis_utils.output import PrettyOutput
|
|
9
|
+
|
|
10
|
+
from jarvis.jarvis_sec.agents import create_review_agent
|
|
11
|
+
from jarvis.jarvis_sec.agents import subscribe_summary_event
|
|
8
12
|
from jarvis.jarvis_sec.parsers import try_parse_summary_report
|
|
9
|
-
from jarvis.jarvis_sec.
|
|
13
|
+
from jarvis.jarvis_sec.prompts import build_verification_summary_prompt
|
|
14
|
+
from jarvis.jarvis_sec.prompts import get_review_summary_prompt
|
|
15
|
+
from jarvis.jarvis_sec.prompts import get_review_system_prompt
|
|
10
16
|
from jarvis.jarvis_sec.utils import git_restore_if_dirty
|
|
11
17
|
|
|
12
18
|
|
|
13
|
-
def build_review_task(
|
|
19
|
+
def build_review_task(
|
|
20
|
+
review_batch: List[Dict], entry_path: str, langs: List[str]
|
|
21
|
+
) -> str:
|
|
14
22
|
"""构建复核任务上下文"""
|
|
15
23
|
import json as _json_review
|
|
24
|
+
|
|
16
25
|
return f"""
|
|
17
26
|
# 复核无效聚类任务
|
|
18
27
|
上下文参数:
|
|
@@ -56,9 +65,6 @@ def build_gid_to_review_mapping(review_results: List[Dict]) -> Dict[int, Dict]:
|
|
|
56
65
|
"""构建gid到复核结果的映射(支持 gid 和 gids 两种格式)"""
|
|
57
66
|
gid_to_review: Dict[int, Dict] = {}
|
|
58
67
|
for rr in review_results:
|
|
59
|
-
if not isinstance(rr, dict):
|
|
60
|
-
continue
|
|
61
|
-
|
|
62
68
|
# 支持 gid 和 gids 两种格式
|
|
63
69
|
gids_to_process: List[int] = []
|
|
64
70
|
if "gids" in rr and isinstance(rr.get("gids"), list):
|
|
@@ -78,14 +84,14 @@ def build_gid_to_review_mapping(review_results: List[Dict]) -> Dict[int, Dict]:
|
|
|
78
84
|
gids_to_process.append(gid_int)
|
|
79
85
|
except Exception:
|
|
80
86
|
pass
|
|
81
|
-
|
|
87
|
+
|
|
82
88
|
# 为每个 gid 创建复核结果映射
|
|
83
89
|
is_reason_sufficient = rr.get("is_reason_sufficient")
|
|
84
90
|
review_notes = str(rr.get("review_notes", "")).strip()
|
|
85
91
|
for gid in gids_to_process:
|
|
86
92
|
gid_to_review[gid] = {
|
|
87
93
|
"is_reason_sufficient": is_reason_sufficient,
|
|
88
|
-
"review_notes": review_notes
|
|
94
|
+
"review_notes": review_notes,
|
|
89
95
|
}
|
|
90
96
|
return gid_to_review
|
|
91
97
|
|
|
@@ -101,12 +107,12 @@ def process_review_batch(
|
|
|
101
107
|
if review_results:
|
|
102
108
|
# 构建gid到复核结果的映射
|
|
103
109
|
gid_to_review = build_gid_to_review_mapping(review_results)
|
|
104
|
-
|
|
110
|
+
|
|
105
111
|
# 处理每个无效聚类
|
|
106
112
|
for invalid_cluster in review_batch:
|
|
107
113
|
cluster_gids = invalid_cluster.get("gids", [])
|
|
108
114
|
cluster_members = invalid_cluster.get("members", [])
|
|
109
|
-
|
|
115
|
+
|
|
110
116
|
# 检查该聚类中的所有gid的复核结果
|
|
111
117
|
all_sufficient = True
|
|
112
118
|
any_reviewed = False
|
|
@@ -120,41 +126,56 @@ def process_review_batch(
|
|
|
120
126
|
if not insufficient_review_result:
|
|
121
127
|
insufficient_review_result = review_result
|
|
122
128
|
break
|
|
123
|
-
|
|
129
|
+
|
|
124
130
|
if any_reviewed and not all_sufficient:
|
|
125
131
|
# 理由不充分,重新加入验证流程
|
|
126
|
-
|
|
132
|
+
PrettyOutput.auto_print(
|
|
133
|
+
f"🔵 [jarvis-sec] 复核结果:无效聚类(gids={cluster_gids})理由不充分,重新加入验证流程"
|
|
134
|
+
)
|
|
127
135
|
for member in cluster_members:
|
|
128
136
|
reinstated_candidates.append(member)
|
|
129
|
-
reviewed_clusters.append(
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
137
|
+
reviewed_clusters.append(
|
|
138
|
+
{
|
|
139
|
+
**invalid_cluster,
|
|
140
|
+
"review_result": "reinstated",
|
|
141
|
+
"review_notes": insufficient_review_result.get(
|
|
142
|
+
"review_notes", ""
|
|
143
|
+
)
|
|
144
|
+
if insufficient_review_result
|
|
145
|
+
else "",
|
|
146
|
+
}
|
|
147
|
+
)
|
|
134
148
|
else:
|
|
135
149
|
# 理由充分,确认无效
|
|
136
150
|
review_notes = ""
|
|
137
151
|
if cluster_gids and gid_to_review.get(cluster_gids[0]):
|
|
138
|
-
review_notes = gid_to_review[cluster_gids[0]].get(
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
"
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
152
|
+
review_notes = gid_to_review[cluster_gids[0]].get(
|
|
153
|
+
"review_notes", ""
|
|
154
|
+
)
|
|
155
|
+
PrettyOutput.auto_print(
|
|
156
|
+
f"✅ [jarvis-sec] 复核结果:无效聚类(gids={cluster_gids})理由充分,确认为无效"
|
|
157
|
+
)
|
|
158
|
+
reviewed_clusters.append(
|
|
159
|
+
{
|
|
160
|
+
**invalid_cluster,
|
|
161
|
+
"review_result": "confirmed_invalid",
|
|
162
|
+
"review_notes": review_notes,
|
|
163
|
+
}
|
|
164
|
+
)
|
|
165
|
+
|
|
146
166
|
# 将确认无效的gids保存到analysis.jsonl的false_positive_gids中,以便断点恢复时能正确识别已复核的无效聚类
|
|
147
167
|
if sec_dir:
|
|
148
168
|
try:
|
|
169
|
+
from datetime import datetime
|
|
149
170
|
from pathlib import Path
|
|
171
|
+
|
|
150
172
|
from jarvis.jarvis_sec.file_manager import save_analysis_result
|
|
151
|
-
|
|
152
|
-
|
|
173
|
+
|
|
153
174
|
# 构建cluster_id
|
|
154
175
|
file_name = invalid_cluster.get("file", "")
|
|
155
176
|
batch_index = invalid_cluster.get("batch_index", 1)
|
|
156
177
|
cluster_id = f"{file_name}|{batch_index}|review"
|
|
157
|
-
|
|
178
|
+
|
|
158
179
|
# 将gids转换为整数列表
|
|
159
180
|
false_positive_gids = []
|
|
160
181
|
for gid_val in cluster_gids:
|
|
@@ -164,7 +185,7 @@ def process_review_batch(
|
|
|
164
185
|
false_positive_gids.append(gid_int)
|
|
165
186
|
except Exception:
|
|
166
187
|
pass
|
|
167
|
-
|
|
188
|
+
|
|
168
189
|
# 保存分析结果
|
|
169
190
|
if false_positive_gids:
|
|
170
191
|
analysis_result = {
|
|
@@ -181,21 +202,27 @@ def process_review_batch(
|
|
|
181
202
|
except Exception as e:
|
|
182
203
|
# 保存失败不影响主流程,只记录警告
|
|
183
204
|
try:
|
|
184
|
-
|
|
205
|
+
PrettyOutput.auto_print(
|
|
206
|
+
f"⚠️ [jarvis-sec] 警告:保存复核结果到analysis.jsonl失败: {str(e)}"
|
|
207
|
+
)
|
|
185
208
|
except Exception:
|
|
186
209
|
pass
|
|
187
210
|
else:
|
|
188
211
|
# 复核结果解析失败,保守策略:重新加入验证流程
|
|
189
|
-
|
|
212
|
+
PrettyOutput.auto_print(
|
|
213
|
+
"⚠️ [jarvis-sec] 警告:复核结果解析失败,保守策略:将批次中的所有候选重新加入验证流程"
|
|
214
|
+
)
|
|
190
215
|
for invalid_cluster in review_batch:
|
|
191
216
|
cluster_members = invalid_cluster.get("members", [])
|
|
192
217
|
for member in cluster_members:
|
|
193
218
|
reinstated_candidates.append(member)
|
|
194
|
-
reviewed_clusters.append(
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
219
|
+
reviewed_clusters.append(
|
|
220
|
+
{
|
|
221
|
+
**invalid_cluster,
|
|
222
|
+
"review_result": "reinstated",
|
|
223
|
+
"review_notes": "复核结果解析失败,保守策略重新加入验证",
|
|
224
|
+
}
|
|
225
|
+
)
|
|
199
226
|
|
|
200
227
|
|
|
201
228
|
def process_review_batch_items(
|
|
@@ -222,27 +249,31 @@ def reinstated_candidates_to_cluster_batches(
|
|
|
222
249
|
) -> None:
|
|
223
250
|
"""将重新加入的候选添加到cluster_batches"""
|
|
224
251
|
from collections import defaultdict as _dd2
|
|
225
|
-
|
|
252
|
+
|
|
226
253
|
if not reinstated_candidates:
|
|
227
254
|
return
|
|
228
|
-
|
|
229
|
-
|
|
255
|
+
|
|
256
|
+
PrettyOutput.auto_print(
|
|
257
|
+
f"🔄 [jarvis-sec] 复核完成:{len(reinstated_candidates)} 个候选重新加入验证流程"
|
|
258
|
+
)
|
|
230
259
|
# 按文件分组重新加入的候选
|
|
231
260
|
reinstated_by_file: Dict[str, List[Dict]] = _dd2(list)
|
|
232
261
|
for cand in reinstated_candidates:
|
|
233
262
|
file_key = str(cand.get("file") or "")
|
|
234
263
|
reinstated_by_file[file_key].append(cand)
|
|
235
|
-
|
|
264
|
+
|
|
236
265
|
# 为每个文件的重新加入候选创建批次
|
|
237
266
|
for file_key, cands in reinstated_by_file.items():
|
|
238
267
|
if cands:
|
|
239
268
|
cluster_batches.append(cands)
|
|
240
|
-
_progress_append(
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
269
|
+
_progress_append(
|
|
270
|
+
{
|
|
271
|
+
"event": "review_reinstated",
|
|
272
|
+
"file": file_key,
|
|
273
|
+
"gids": [c.get("gid") for c in cands],
|
|
274
|
+
"count": len(cands),
|
|
275
|
+
}
|
|
276
|
+
)
|
|
246
277
|
|
|
247
278
|
|
|
248
279
|
def run_review_agent_with_retry(
|
|
@@ -256,70 +287,93 @@ def run_review_agent_with_retry(
|
|
|
256
287
|
use_direct_model_review = False
|
|
257
288
|
prev_parse_error_review: Optional[str] = None
|
|
258
289
|
review_attempt = 0
|
|
259
|
-
|
|
290
|
+
|
|
260
291
|
while True:
|
|
261
292
|
review_attempt += 1
|
|
262
293
|
review_summary_container["text"] = ""
|
|
263
|
-
|
|
294
|
+
|
|
264
295
|
if use_direct_model_review:
|
|
265
296
|
# 格式校验失败后,直接调用模型接口
|
|
266
297
|
review_summary_prompt_text = build_verification_summary_prompt()
|
|
267
298
|
error_guidance = ""
|
|
268
299
|
if prev_parse_error_review:
|
|
269
300
|
error_guidance = f"\n\n**格式错误详情(请根据以下错误修复输出格式):**\n- JSON解析失败: {prev_parse_error_review}\n\n请确保输出的JSON格式正确,包括正确的引号、逗号、大括号等。仅输出一个 <REPORT> 块,块内直接包含 JSON 数组(不需要额外的标签)。支持jsonnet语法(如尾随逗号、注释、||| 或 ``` 分隔符多行字符串等)。"
|
|
270
|
-
|
|
271
|
-
full_review_prompt =
|
|
301
|
+
|
|
302
|
+
full_review_prompt = (
|
|
303
|
+
f"{review_task}{error_guidance}\n\n{review_summary_prompt_text}"
|
|
304
|
+
)
|
|
272
305
|
try:
|
|
273
|
-
review_response = review_agent.model.chat_until_success(
|
|
306
|
+
review_response = review_agent.model.chat_until_success(
|
|
307
|
+
full_review_prompt
|
|
308
|
+
)
|
|
274
309
|
review_summary_container["text"] = review_response
|
|
275
310
|
except Exception as e:
|
|
276
311
|
try:
|
|
277
|
-
|
|
312
|
+
PrettyOutput.auto_print(
|
|
313
|
+
f"✨ [jarvis-sec] 复核阶段直接模型调用失败: {e},回退到 run()",
|
|
314
|
+
timestamp=True,
|
|
315
|
+
)
|
|
278
316
|
except Exception:
|
|
279
317
|
pass
|
|
280
318
|
review_agent.run(review_task)
|
|
281
319
|
else:
|
|
282
320
|
review_agent.run(review_task)
|
|
283
|
-
|
|
321
|
+
|
|
284
322
|
# 工作区保护
|
|
285
323
|
try:
|
|
286
324
|
_changed_review = git_restore_if_dirty(entry_path)
|
|
287
325
|
if _changed_review:
|
|
288
326
|
try:
|
|
289
|
-
|
|
327
|
+
PrettyOutput.auto_print(
|
|
328
|
+
f"✨ [jarvis-sec] 复核 Agent 工作区已恢复 ({_changed_review} 个文件)",
|
|
329
|
+
timestamp=True,
|
|
330
|
+
)
|
|
290
331
|
except Exception:
|
|
291
332
|
pass
|
|
292
333
|
except Exception:
|
|
293
334
|
pass
|
|
294
|
-
|
|
335
|
+
|
|
295
336
|
# 解析复核结果
|
|
296
337
|
review_summary_text = review_summary_container.get("text", "")
|
|
297
338
|
parse_error_review = None
|
|
298
339
|
if review_summary_text:
|
|
299
|
-
review_parsed, parse_error_review = try_parse_summary_report(
|
|
340
|
+
review_parsed, parse_error_review = try_parse_summary_report(
|
|
341
|
+
review_summary_text
|
|
342
|
+
)
|
|
300
343
|
if parse_error_review:
|
|
301
344
|
prev_parse_error_review = parse_error_review
|
|
302
345
|
try:
|
|
303
|
-
|
|
346
|
+
PrettyOutput.auto_print(
|
|
347
|
+
f"✨ [jarvis-sec] 复核结果JSON解析失败: {parse_error_review}",
|
|
348
|
+
timestamp=True,
|
|
349
|
+
)
|
|
304
350
|
except Exception:
|
|
305
351
|
pass
|
|
306
352
|
else:
|
|
307
353
|
prev_parse_error_review = None
|
|
308
354
|
if isinstance(review_parsed, list):
|
|
309
355
|
# 验证复核结果格式
|
|
310
|
-
if review_parsed and all(
|
|
356
|
+
if review_parsed and all(
|
|
357
|
+
is_valid_review_item(item) for item in review_parsed
|
|
358
|
+
):
|
|
311
359
|
return review_parsed, None
|
|
312
|
-
|
|
360
|
+
|
|
313
361
|
# 格式校验失败,后续重试使用直接模型调用
|
|
314
362
|
use_direct_model_review = True
|
|
315
363
|
if parse_error_review:
|
|
316
364
|
try:
|
|
317
|
-
|
|
365
|
+
PrettyOutput.auto_print(
|
|
366
|
+
f"✨ [jarvis-sec] 复核结果JSON解析失败 -> 重试第 {review_attempt} 次 (使用直接模型调用,将反馈解析错误)",
|
|
367
|
+
timestamp=True,
|
|
368
|
+
)
|
|
318
369
|
except Exception:
|
|
319
370
|
pass
|
|
320
371
|
else:
|
|
321
372
|
try:
|
|
322
|
-
|
|
373
|
+
PrettyOutput.auto_print(
|
|
374
|
+
f"✨ [jarvis-sec] 复核结果格式无效 -> 重试第 {review_attempt} 次 (使用直接模型调用)",
|
|
375
|
+
timestamp=True,
|
|
376
|
+
)
|
|
323
377
|
except Exception:
|
|
324
378
|
pass
|
|
325
379
|
|
|
@@ -336,49 +390,59 @@ def process_review_phase(
|
|
|
336
390
|
) -> List[List[Dict]]:
|
|
337
391
|
"""
|
|
338
392
|
处理复核阶段:验证所有标记为无效的聚类。
|
|
339
|
-
|
|
393
|
+
|
|
340
394
|
返回: 更新后的 cluster_batches(包含重新加入验证的候选)
|
|
341
395
|
"""
|
|
342
396
|
if not invalid_clusters_for_review:
|
|
343
|
-
|
|
397
|
+
PrettyOutput.auto_print("🔵 [jarvis-sec] 无无效聚类需要复核")
|
|
344
398
|
return cluster_batches
|
|
345
|
-
|
|
346
|
-
|
|
399
|
+
|
|
400
|
+
PrettyOutput.auto_print(
|
|
401
|
+
f"✨ \n[jarvis-sec] 开始复核 {len(invalid_clusters_for_review)} 个无效聚类...",
|
|
402
|
+
timestamp=True,
|
|
403
|
+
)
|
|
347
404
|
status_mgr.update_review(
|
|
348
405
|
current_review=0,
|
|
349
406
|
total_reviews=len(invalid_clusters_for_review),
|
|
350
|
-
message="开始复核无效聚类..."
|
|
407
|
+
message="开始复核无效聚类...",
|
|
351
408
|
)
|
|
352
|
-
|
|
409
|
+
|
|
353
410
|
# 按批次复核(每批最多10个无效聚类,避免上下文过长)
|
|
354
411
|
review_batch_size = 10
|
|
355
412
|
reviewed_clusters: List[Dict] = []
|
|
356
413
|
reinstated_candidates: List[Dict] = [] # 重新加入验证的候选
|
|
357
|
-
|
|
414
|
+
|
|
358
415
|
get_review_system_prompt()
|
|
359
416
|
review_summary_prompt = get_review_summary_prompt()
|
|
360
|
-
|
|
417
|
+
|
|
361
418
|
for review_idx in range(0, len(invalid_clusters_for_review), review_batch_size):
|
|
362
|
-
review_batch = invalid_clusters_for_review[
|
|
419
|
+
review_batch = invalid_clusters_for_review[
|
|
420
|
+
review_idx : review_idx + review_batch_size
|
|
421
|
+
]
|
|
363
422
|
current_review_num = review_idx // review_batch_size + 1
|
|
364
|
-
total_review_batches = (
|
|
365
|
-
|
|
366
|
-
|
|
423
|
+
total_review_batches = (
|
|
424
|
+
len(invalid_clusters_for_review) + review_batch_size - 1
|
|
425
|
+
) // review_batch_size
|
|
426
|
+
|
|
427
|
+
PrettyOutput.auto_print(
|
|
428
|
+
f"✨ [jarvis-sec] 复核批次 {current_review_num}/{total_review_batches}: {len(review_batch)} 个无效聚类",
|
|
429
|
+
timestamp=True,
|
|
430
|
+
)
|
|
367
431
|
status_mgr.update_review(
|
|
368
432
|
current_review=current_review_num,
|
|
369
433
|
total_reviews=total_review_batches,
|
|
370
|
-
message=f"正在复核批次 {current_review_num}/{total_review_batches}"
|
|
434
|
+
message=f"正在复核批次 {current_review_num}/{total_review_batches}",
|
|
371
435
|
)
|
|
372
|
-
|
|
436
|
+
|
|
373
437
|
# 构建复核任务
|
|
374
438
|
review_task = build_review_task(review_batch, entry_path, langs)
|
|
375
|
-
|
|
439
|
+
|
|
376
440
|
# 创建复核Agent
|
|
377
441
|
review_agent = create_review_agent(current_review_num, llm_group)
|
|
378
|
-
|
|
442
|
+
|
|
379
443
|
# 订阅复核Agent的摘要
|
|
380
444
|
review_summary_container = subscribe_summary_event(review_agent)
|
|
381
|
-
|
|
445
|
+
|
|
382
446
|
# 运行复核Agent(永久重试直到格式正确)
|
|
383
447
|
review_results, parse_error = run_review_agent_with_retry(
|
|
384
448
|
review_agent,
|
|
@@ -387,7 +451,7 @@ def process_review_phase(
|
|
|
387
451
|
entry_path,
|
|
388
452
|
review_summary_container,
|
|
389
453
|
)
|
|
390
|
-
|
|
454
|
+
|
|
391
455
|
# 处理复核结果
|
|
392
456
|
process_review_batch_items(
|
|
393
457
|
review_batch,
|
|
@@ -396,36 +460,43 @@ def process_review_phase(
|
|
|
396
460
|
reinstated_candidates,
|
|
397
461
|
sec_dir,
|
|
398
462
|
)
|
|
399
|
-
|
|
463
|
+
|
|
400
464
|
# 记录每个已复核的无效聚类的 gids(包括确认无效的和重新加入验证的)
|
|
401
465
|
for invalid_cluster in review_batch:
|
|
402
466
|
cluster_gids = invalid_cluster.get("gids", [])
|
|
403
467
|
if cluster_gids:
|
|
404
|
-
_progress_append(
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
468
|
+
_progress_append(
|
|
469
|
+
{
|
|
470
|
+
"event": "review_invalid_cluster",
|
|
471
|
+
"gids": cluster_gids,
|
|
472
|
+
"file": invalid_cluster.get("file"),
|
|
473
|
+
"batch_index": invalid_cluster.get("batch_index"),
|
|
474
|
+
}
|
|
475
|
+
)
|
|
476
|
+
|
|
411
477
|
# 将重新加入验证的候选添加到cluster_batches
|
|
412
478
|
reinstated_candidates_to_cluster_batches(
|
|
413
479
|
reinstated_candidates,
|
|
414
480
|
cluster_batches,
|
|
415
481
|
_progress_append,
|
|
416
482
|
)
|
|
417
|
-
|
|
483
|
+
|
|
418
484
|
if not reinstated_candidates:
|
|
419
|
-
|
|
420
|
-
|
|
485
|
+
PrettyOutput.auto_print(
|
|
486
|
+
"✨ [jarvis-sec] 复核完成:所有无效聚类理由充分,确认为无效", timestamp=True
|
|
487
|
+
)
|
|
488
|
+
|
|
421
489
|
# 记录复核结果(汇总)
|
|
422
|
-
_progress_append(
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
490
|
+
_progress_append(
|
|
491
|
+
{
|
|
492
|
+
"event": "review_completed",
|
|
493
|
+
"total_reviewed": len(invalid_clusters_for_review),
|
|
494
|
+
"reinstated": len(reinstated_candidates),
|
|
495
|
+
"confirmed_invalid": len(invalid_clusters_for_review)
|
|
496
|
+
- len(reinstated_candidates),
|
|
497
|
+
}
|
|
498
|
+
)
|
|
499
|
+
|
|
429
500
|
# 记录所有已复核的无效聚类的 gids(用于断点恢复时跳过已复核的聚类)
|
|
430
501
|
all_reviewed_gids = set()
|
|
431
502
|
for invalid_cluster in invalid_clusters_for_review:
|
|
@@ -437,17 +508,19 @@ def process_review_phase(
|
|
|
437
508
|
all_reviewed_gids.add(gid_int)
|
|
438
509
|
except Exception:
|
|
439
510
|
pass
|
|
440
|
-
|
|
511
|
+
|
|
441
512
|
if all_reviewed_gids:
|
|
442
|
-
_progress_append(
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
513
|
+
_progress_append(
|
|
514
|
+
{
|
|
515
|
+
"event": "review_all_gids",
|
|
516
|
+
"gids": sorted(list(all_reviewed_gids)),
|
|
517
|
+
"total": len(all_reviewed_gids),
|
|
518
|
+
}
|
|
519
|
+
)
|
|
447
520
|
status_mgr.update_review(
|
|
448
521
|
current_review=len(invalid_clusters_for_review),
|
|
449
522
|
total_reviews=len(invalid_clusters_for_review),
|
|
450
|
-
message=f"复核完成:{len(reinstated_candidates)} 个候选重新加入验证"
|
|
523
|
+
message=f"复核完成:{len(reinstated_candidates)} 个候选重新加入验证",
|
|
451
524
|
)
|
|
452
|
-
|
|
525
|
+
|
|
453
526
|
return cluster_batches
|