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
|
@@ -1,23 +1,29 @@
|
|
|
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
8
|
from jarvis.jarvis_agent import Agent
|
|
8
|
-
from jarvis.
|
|
9
|
-
from jarvis.
|
|
9
|
+
from jarvis.jarvis_utils.output import PrettyOutput
|
|
10
|
+
from jarvis.jarvis_utils.tag import ot
|
|
11
|
+
from jarvis.jarvis_sec.agents import create_analysis_agent
|
|
12
|
+
from jarvis.jarvis_sec.agents import subscribe_summary_event
|
|
13
|
+
from jarvis.jarvis_sec.analysis import build_analysis_task_context
|
|
14
|
+
from jarvis.jarvis_sec.analysis import expand_and_filter_analysis_results
|
|
15
|
+
from jarvis.jarvis_sec.analysis import run_analysis_agent_with_retry
|
|
10
16
|
from jarvis.jarvis_sec.parsers import try_parse_summary_report
|
|
11
|
-
from jarvis.jarvis_sec.
|
|
12
|
-
from jarvis.jarvis_sec.utils import
|
|
13
|
-
from jarvis.jarvis_sec.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
expand_and_filter_analysis_results,
|
|
17
|
-
)
|
|
17
|
+
from jarvis.jarvis_sec.prompts import build_verification_summary_prompt
|
|
18
|
+
from jarvis.jarvis_sec.utils import count_issues_from_file
|
|
19
|
+
from jarvis.jarvis_sec.utils import git_restore_if_dirty
|
|
20
|
+
from jarvis.jarvis_sec.utils import sig_of
|
|
21
|
+
from jarvis.jarvis_tools.registry import ToolRegistry
|
|
18
22
|
|
|
19
23
|
|
|
20
|
-
def build_gid_to_verification_mapping(
|
|
24
|
+
def build_gid_to_verification_mapping(
|
|
25
|
+
verification_results: List[Dict],
|
|
26
|
+
) -> Dict[int, Dict]:
|
|
21
27
|
"""构建gid到验证结果的映射"""
|
|
22
28
|
gid_to_verification: Dict[int, Dict] = {}
|
|
23
29
|
for vr in verification_results:
|
|
@@ -32,7 +38,9 @@ def build_gid_to_verification_mapping(verification_results: List[Dict]) -> Dict[
|
|
|
32
38
|
gids_to_process.append(gid_int)
|
|
33
39
|
except Exception as e:
|
|
34
40
|
try:
|
|
35
|
-
|
|
41
|
+
PrettyOutput.auto_print(
|
|
42
|
+
f"[jarvis-sec] 警告:验证结果中 gids 数组元素格式错误: {gid_val}, 错误: {e}"
|
|
43
|
+
)
|
|
36
44
|
except Exception:
|
|
37
45
|
pass
|
|
38
46
|
elif "gid" in vr:
|
|
@@ -43,26 +51,32 @@ def build_gid_to_verification_mapping(verification_results: List[Dict]) -> Dict[
|
|
|
43
51
|
gids_to_process.append(gid_int)
|
|
44
52
|
else:
|
|
45
53
|
try:
|
|
46
|
-
|
|
54
|
+
PrettyOutput.auto_print(
|
|
55
|
+
f"[jarvis-sec] 警告:验证结果中 gid 值无效: {gid_val} (必须 >= 1)"
|
|
56
|
+
)
|
|
47
57
|
except Exception:
|
|
48
58
|
pass
|
|
49
59
|
except Exception as e:
|
|
50
60
|
try:
|
|
51
|
-
|
|
61
|
+
PrettyOutput.auto_print(
|
|
62
|
+
f"[jarvis-sec] 警告:验证结果中 gid 格式错误: {vr.get('gid')}, 错误: {e}"
|
|
63
|
+
)
|
|
52
64
|
except Exception:
|
|
53
65
|
pass
|
|
54
66
|
else:
|
|
55
67
|
try:
|
|
56
|
-
|
|
68
|
+
PrettyOutput.auto_print(
|
|
69
|
+
f"[jarvis-sec] 警告:验证结果项缺少 gid 或 gids 字段: {vr}"
|
|
70
|
+
)
|
|
57
71
|
except Exception:
|
|
58
72
|
pass
|
|
59
|
-
|
|
73
|
+
|
|
60
74
|
is_valid = vr.get("is_valid")
|
|
61
75
|
verification_notes = str(vr.get("verification_notes", "")).strip()
|
|
62
76
|
for gid in gids_to_process:
|
|
63
77
|
gid_to_verification[gid] = {
|
|
64
78
|
"is_valid": is_valid,
|
|
65
|
-
"verification_notes": verification_notes
|
|
79
|
+
"verification_notes": verification_notes,
|
|
66
80
|
}
|
|
67
81
|
return gid_to_verification
|
|
68
82
|
|
|
@@ -81,7 +95,7 @@ def merge_verified_items(
|
|
|
81
95
|
gid_to_candidate[c_gid] = c
|
|
82
96
|
except Exception:
|
|
83
97
|
pass
|
|
84
|
-
|
|
98
|
+
|
|
85
99
|
verified_items: List[Dict] = []
|
|
86
100
|
for item in items_with_risk:
|
|
87
101
|
item_gid = int(item.get("gid", 0))
|
|
@@ -92,17 +106,23 @@ def merge_verified_items(
|
|
|
92
106
|
merged_item = {
|
|
93
107
|
**candidate, # 原始候选信息
|
|
94
108
|
**item, # 分析结果
|
|
95
|
-
"verification_notes": str(
|
|
109
|
+
"verification_notes": str(
|
|
110
|
+
verification.get("verification_notes", "")
|
|
111
|
+
).strip(),
|
|
96
112
|
}
|
|
97
113
|
verified_items.append(merged_item)
|
|
98
114
|
elif verification and verification.get("is_valid") is False:
|
|
99
115
|
try:
|
|
100
|
-
|
|
116
|
+
PrettyOutput.auto_print(
|
|
117
|
+
f"[jarvis-sec] 验证 Agent 判定 gid={item_gid} 为误报: {verification.get('verification_notes', '')}"
|
|
118
|
+
)
|
|
101
119
|
except Exception:
|
|
102
120
|
pass
|
|
103
121
|
else:
|
|
104
122
|
try:
|
|
105
|
-
|
|
123
|
+
PrettyOutput.auto_print(
|
|
124
|
+
f"[jarvis-sec] 警告:验证结果中未找到 gid={item_gid},视为验证不通过"
|
|
125
|
+
)
|
|
106
126
|
except Exception:
|
|
107
127
|
pass
|
|
108
128
|
return verified_items
|
|
@@ -121,7 +141,7 @@ def merge_verified_items_without_verification(
|
|
|
121
141
|
gid_to_candidate[c_gid] = c
|
|
122
142
|
except Exception:
|
|
123
143
|
pass
|
|
124
|
-
|
|
144
|
+
|
|
125
145
|
verified_items: List[Dict] = []
|
|
126
146
|
for item in items_with_risk:
|
|
127
147
|
item_gid = int(item.get("gid", 0))
|
|
@@ -188,68 +208,84 @@ def run_verification_agent_with_retry(
|
|
|
188
208
|
use_direct_model_verify = False
|
|
189
209
|
prev_parse_error_verify: Optional[str] = None
|
|
190
210
|
verify_attempt = 0
|
|
191
|
-
|
|
211
|
+
|
|
192
212
|
while True:
|
|
193
213
|
verify_attempt += 1
|
|
194
214
|
verification_summary_container["text"] = ""
|
|
195
|
-
|
|
215
|
+
|
|
196
216
|
if use_direct_model_verify:
|
|
197
217
|
verification_summary_prompt_text = build_verification_summary_prompt()
|
|
198
218
|
error_guidance = ""
|
|
199
219
|
if prev_parse_error_verify:
|
|
200
220
|
error_guidance = f"\n\n**格式错误详情(请根据以下错误修复输出格式):**\n- JSON解析失败: {prev_parse_error_verify}\n\n请确保输出的JSON格式正确,包括正确的引号、逗号、大括号等。仅输出一个 <REPORT> 块,块内直接包含 JSON 数组(不需要额外的标签)。支持jsonnet语法(如尾随逗号、注释、||| 或 ``` 分隔符多行字符串等)。"
|
|
201
|
-
|
|
221
|
+
|
|
202
222
|
full_verify_prompt = f"{verification_task}{error_guidance}\n\n{verification_summary_prompt_text}"
|
|
203
223
|
try:
|
|
204
|
-
verify_response = verification_agent.model.chat_until_success(
|
|
224
|
+
verify_response = verification_agent.model.chat_until_success(
|
|
225
|
+
full_verify_prompt
|
|
226
|
+
)
|
|
205
227
|
verification_summary_container["text"] = verify_response
|
|
206
228
|
except Exception as e:
|
|
207
229
|
try:
|
|
208
|
-
|
|
230
|
+
PrettyOutput.auto_print(
|
|
231
|
+
f"[jarvis-sec] 验证阶段直接模型调用失败: {e},回退到 run()"
|
|
232
|
+
)
|
|
209
233
|
except Exception:
|
|
210
234
|
pass
|
|
211
235
|
verification_agent.run(verification_task)
|
|
212
236
|
else:
|
|
213
237
|
verification_agent.run(verification_task)
|
|
214
|
-
|
|
238
|
+
|
|
215
239
|
# 工作区保护
|
|
216
240
|
try:
|
|
217
241
|
_changed_verify = git_restore_if_dirty(entry_path)
|
|
218
242
|
if _changed_verify:
|
|
219
243
|
try:
|
|
220
|
-
|
|
244
|
+
PrettyOutput.auto_print(
|
|
245
|
+
f"[jarvis-sec] 验证 Agent 工作区已恢复 ({_changed_verify} 个文件)"
|
|
246
|
+
)
|
|
221
247
|
except Exception:
|
|
222
248
|
pass
|
|
223
249
|
except Exception:
|
|
224
250
|
pass
|
|
225
|
-
|
|
251
|
+
|
|
226
252
|
# 解析验证结果
|
|
227
253
|
verification_summary_text = verification_summary_container.get("text", "")
|
|
228
254
|
parse_error_verify = None
|
|
229
255
|
if verification_summary_text:
|
|
230
|
-
verification_parsed, parse_error_verify = try_parse_summary_report(
|
|
256
|
+
verification_parsed, parse_error_verify = try_parse_summary_report(
|
|
257
|
+
verification_summary_text
|
|
258
|
+
)
|
|
231
259
|
if parse_error_verify:
|
|
232
260
|
prev_parse_error_verify = parse_error_verify
|
|
233
261
|
try:
|
|
234
|
-
|
|
262
|
+
PrettyOutput.auto_print(
|
|
263
|
+
f"[jarvis-sec] 验证结果JSON解析失败: {parse_error_verify}"
|
|
264
|
+
)
|
|
235
265
|
except Exception:
|
|
236
266
|
pass
|
|
237
267
|
else:
|
|
238
268
|
prev_parse_error_verify = None
|
|
239
269
|
if isinstance(verification_parsed, list):
|
|
240
|
-
if verification_parsed and all(
|
|
270
|
+
if verification_parsed and all(
|
|
271
|
+
is_valid_verification_item(item) for item in verification_parsed
|
|
272
|
+
):
|
|
241
273
|
return verification_parsed, None
|
|
242
|
-
|
|
274
|
+
|
|
243
275
|
# 格式校验失败,后续重试使用直接模型调用
|
|
244
276
|
use_direct_model_verify = True
|
|
245
277
|
if parse_error_verify:
|
|
246
278
|
try:
|
|
247
|
-
|
|
279
|
+
PrettyOutput.auto_print(
|
|
280
|
+
f"[jarvis-sec] 验证结果JSON解析失败 -> 重试第 {verify_attempt} 次 (批次={bidx},使用直接模型调用,将反馈解析错误)"
|
|
281
|
+
)
|
|
248
282
|
except Exception:
|
|
249
283
|
pass
|
|
250
284
|
else:
|
|
251
285
|
try:
|
|
252
|
-
|
|
286
|
+
PrettyOutput.auto_print(
|
|
287
|
+
f"[jarvis-sec] 验证结果格式无效 -> 重试第 {verify_attempt} 次 (批次={bidx},使用直接模型调用)"
|
|
288
|
+
)
|
|
253
289
|
except Exception:
|
|
254
290
|
pass
|
|
255
291
|
|
|
@@ -272,7 +308,7 @@ def process_verification_batch(
|
|
|
272
308
|
) -> None:
|
|
273
309
|
"""
|
|
274
310
|
处理单个验证批次。
|
|
275
|
-
|
|
311
|
+
|
|
276
312
|
参数:
|
|
277
313
|
- batch: 当前批次的候选列表
|
|
278
314
|
- bidx: 批次索引
|
|
@@ -281,7 +317,7 @@ def process_verification_batch(
|
|
|
281
317
|
"""
|
|
282
318
|
task_id = f"JARVIS-SEC-Batch-{bidx}"
|
|
283
319
|
batch_file = batch[0].get("file") if batch else None
|
|
284
|
-
|
|
320
|
+
|
|
285
321
|
# 进度:批次开始
|
|
286
322
|
_progress_append(
|
|
287
323
|
{
|
|
@@ -300,7 +336,7 @@ def process_verification_batch(
|
|
|
300
336
|
total_batches=total_batches,
|
|
301
337
|
batch_id=task_id,
|
|
302
338
|
file_name=batch_file,
|
|
303
|
-
message=f"正在验证批次 {bidx}/{total_batches}"
|
|
339
|
+
message=f"正在验证批次 {bidx}/{total_batches}",
|
|
304
340
|
)
|
|
305
341
|
|
|
306
342
|
# 显示进度(提取批次中的所有 gid,用于后续打印)
|
|
@@ -317,42 +353,56 @@ def process_verification_batch(
|
|
|
317
353
|
batch_gids_all_sorted = sorted(batch_gids_all)
|
|
318
354
|
except Exception:
|
|
319
355
|
batch_gids_all_sorted = []
|
|
320
|
-
|
|
356
|
+
|
|
321
357
|
# 显示进度
|
|
322
358
|
try:
|
|
323
359
|
if batch_gids_all_sorted:
|
|
324
360
|
gids_str = str(batch_gids_all_sorted)
|
|
325
|
-
|
|
361
|
+
PrettyOutput.auto_print(
|
|
362
|
+
f"\n[jarvis-sec] 分析批次 {bidx}/{total_batches}: 大小={len(batch)} 文件='{batch_file}' gids={gids_str}"
|
|
363
|
+
)
|
|
326
364
|
else:
|
|
327
|
-
|
|
365
|
+
PrettyOutput.auto_print(
|
|
366
|
+
f"\n[jarvis-sec] 分析批次 {bidx}/{total_batches}: 大小={len(batch)} 文件='{batch_file}' (无有效gid)"
|
|
367
|
+
)
|
|
328
368
|
except Exception:
|
|
329
369
|
pass
|
|
330
370
|
|
|
331
371
|
# 创建分析Agent
|
|
332
|
-
agent = create_analysis_agent(
|
|
333
|
-
|
|
372
|
+
agent = create_analysis_agent(
|
|
373
|
+
task_id, llm_group, force_save_memory=force_save_memory
|
|
374
|
+
)
|
|
375
|
+
|
|
334
376
|
# 构建任务上下文
|
|
335
377
|
per_task = build_analysis_task_context(batch, entry_path, langs)
|
|
336
|
-
|
|
378
|
+
|
|
337
379
|
# 订阅摘要事件
|
|
338
380
|
summary_container = subscribe_summary_event(agent)
|
|
339
|
-
|
|
381
|
+
|
|
340
382
|
# 运行分析Agent并重试
|
|
341
383
|
summary_items, workspace_restore_info = run_analysis_agent_with_retry(
|
|
342
384
|
agent, per_task, summary_container, entry_path, task_id, bidx, meta_records
|
|
343
385
|
)
|
|
344
|
-
|
|
386
|
+
|
|
345
387
|
# 处理分析结果
|
|
346
388
|
parse_fail = summary_items is None
|
|
347
389
|
verified_items: List[Dict] = []
|
|
348
|
-
|
|
390
|
+
|
|
349
391
|
# 处理空数组情况:分析 Agent 返回 [] 表示所有候选都被判定为无风险
|
|
350
392
|
if summary_items is not None and len(summary_items) == 0:
|
|
351
393
|
# 空数组表示所有候选都被判定为无风险,需要保存到 analysis.jsonl
|
|
352
394
|
try:
|
|
353
|
-
batch_gids = sorted(
|
|
354
|
-
|
|
355
|
-
|
|
395
|
+
batch_gids = sorted(
|
|
396
|
+
[
|
|
397
|
+
int(item.get("gid", 0))
|
|
398
|
+
for item in batch
|
|
399
|
+
if int(item.get("gid", 0)) >= 1
|
|
400
|
+
]
|
|
401
|
+
)
|
|
402
|
+
PrettyOutput.auto_print(
|
|
403
|
+
f"[jarvis-sec] 批次 {bidx}/{total_batches} 分析 Agent 返回空数组,判定所有候选为无风险: 有风险gid=[], 无风险gid={batch_gids}"
|
|
404
|
+
)
|
|
405
|
+
|
|
356
406
|
# 构建无风险项(将批次中的所有候选标记为无风险)
|
|
357
407
|
no_risk_items = []
|
|
358
408
|
for item in batch:
|
|
@@ -367,76 +417,141 @@ def process_verification_batch(
|
|
|
367
417
|
no_risk_items.append(no_risk_item)
|
|
368
418
|
except Exception:
|
|
369
419
|
pass
|
|
370
|
-
|
|
420
|
+
|
|
371
421
|
# 保存到 analysis.jsonl
|
|
372
422
|
if no_risk_items:
|
|
373
|
-
merged_no_risk_items = merge_verified_items_without_verification(
|
|
423
|
+
merged_no_risk_items = merge_verified_items_without_verification(
|
|
424
|
+
no_risk_items, batch
|
|
425
|
+
)
|
|
374
426
|
if merged_no_risk_items:
|
|
375
|
-
_append_report(
|
|
376
|
-
|
|
427
|
+
_append_report(
|
|
428
|
+
merged_no_risk_items,
|
|
429
|
+
"analysis_only",
|
|
430
|
+
task_id,
|
|
431
|
+
{"batch": True, "candidates": batch},
|
|
432
|
+
)
|
|
433
|
+
PrettyOutput.auto_print(
|
|
434
|
+
f"[jarvis-sec] 批次 {bidx}/{total_batches} 已将所有无风险候选保存到 analysis.jsonl: gids={batch_gids}"
|
|
435
|
+
)
|
|
377
436
|
except Exception as e:
|
|
378
437
|
try:
|
|
379
|
-
|
|
438
|
+
PrettyOutput.auto_print(f"[jarvis-sec] 警告:处理空数组结果失败: {e}")
|
|
380
439
|
except Exception:
|
|
381
440
|
pass
|
|
382
|
-
|
|
441
|
+
|
|
383
442
|
elif summary_items:
|
|
384
443
|
# 展开并过滤分析结果
|
|
385
|
-
items_with_risk, items_without_risk = expand_and_filter_analysis_results(
|
|
386
|
-
|
|
444
|
+
items_with_risk, items_without_risk = expand_and_filter_analysis_results(
|
|
445
|
+
summary_items
|
|
446
|
+
)
|
|
447
|
+
|
|
387
448
|
# 记录分析结论(分别显示有风险和无风险的gid)
|
|
388
|
-
risk_gids =
|
|
389
|
-
|
|
390
|
-
|
|
449
|
+
risk_gids = (
|
|
450
|
+
sorted(
|
|
451
|
+
[
|
|
452
|
+
int(item.get("gid", 0))
|
|
453
|
+
for item in items_with_risk
|
|
454
|
+
if int(item.get("gid", 0)) >= 1
|
|
455
|
+
]
|
|
456
|
+
)
|
|
457
|
+
if items_with_risk
|
|
458
|
+
else []
|
|
459
|
+
)
|
|
460
|
+
no_risk_gids = (
|
|
461
|
+
sorted(
|
|
462
|
+
[
|
|
463
|
+
int(item.get("gid", 0))
|
|
464
|
+
for item in items_without_risk
|
|
465
|
+
if int(item.get("gid", 0)) >= 1
|
|
466
|
+
]
|
|
467
|
+
)
|
|
468
|
+
if items_without_risk
|
|
469
|
+
else []
|
|
470
|
+
)
|
|
471
|
+
|
|
391
472
|
if items_with_risk or items_without_risk:
|
|
392
473
|
try:
|
|
393
|
-
|
|
474
|
+
PrettyOutput.auto_print(
|
|
475
|
+
f"[jarvis-sec] 批次 {bidx}/{total_batches} 分析 Agent 判定结果: 有风险gid={risk_gids}, 无风险gid={no_risk_gids}"
|
|
476
|
+
)
|
|
394
477
|
except Exception:
|
|
395
478
|
pass
|
|
396
|
-
|
|
479
|
+
|
|
397
480
|
# 如果所有 gid 都被判定为无风险,也需要保存到 analysis.jsonl
|
|
398
481
|
if not items_with_risk and items_without_risk:
|
|
399
482
|
try:
|
|
400
483
|
# 将所有无风险的 gid 保存到 analysis.jsonl,确保它们被标记为已分析
|
|
401
|
-
no_risk_items = merge_verified_items_without_verification(
|
|
484
|
+
no_risk_items = merge_verified_items_without_verification(
|
|
485
|
+
items_without_risk, batch
|
|
486
|
+
)
|
|
402
487
|
if no_risk_items:
|
|
403
|
-
_append_report(
|
|
488
|
+
_append_report(
|
|
489
|
+
no_risk_items,
|
|
490
|
+
"analysis_only",
|
|
491
|
+
task_id,
|
|
492
|
+
{"batch": True, "candidates": batch},
|
|
493
|
+
)
|
|
404
494
|
try:
|
|
405
|
-
|
|
495
|
+
PrettyOutput.auto_print(
|
|
496
|
+
f"[jarvis-sec] 批次 {bidx}/{total_batches} 所有候选均为无风险,已保存到 analysis.jsonl"
|
|
497
|
+
)
|
|
406
498
|
except Exception:
|
|
407
499
|
pass
|
|
408
500
|
except Exception as e:
|
|
409
501
|
try:
|
|
410
|
-
|
|
502
|
+
PrettyOutput.auto_print(
|
|
503
|
+
f"[jarvis-sec] 警告:保存无风险 gid 失败: {e}"
|
|
504
|
+
)
|
|
411
505
|
except Exception:
|
|
412
506
|
pass
|
|
413
|
-
|
|
507
|
+
|
|
414
508
|
# 运行验证Agent(仅当分析Agent发现有风险的问题时,且启用二次验证)
|
|
415
509
|
if items_with_risk:
|
|
416
510
|
if not enable_verification:
|
|
417
511
|
# 如果关闭二次验证,直接将分析Agent确认的问题作为已验证的问题
|
|
418
|
-
verified_items = merge_verified_items_without_verification(
|
|
512
|
+
verified_items = merge_verified_items_without_verification(
|
|
513
|
+
items_with_risk, batch
|
|
514
|
+
)
|
|
419
515
|
if verified_items:
|
|
420
|
-
verified_gids = sorted(
|
|
516
|
+
verified_gids = sorted(
|
|
517
|
+
[
|
|
518
|
+
int(item.get("gid", 0))
|
|
519
|
+
for item in verified_items
|
|
520
|
+
if int(item.get("gid", 0)) >= 1
|
|
521
|
+
]
|
|
522
|
+
)
|
|
421
523
|
for item in verified_items:
|
|
422
524
|
gid = int(item.get("gid", 0))
|
|
423
525
|
if gid >= 1:
|
|
424
526
|
gid_counts[gid] = gid_counts.get(gid, 0) + 1
|
|
425
527
|
# 计算无风险的gid(批次中不在verified_gids中的gid)
|
|
426
|
-
no_risk_gids_in_batch = sorted(
|
|
427
|
-
|
|
428
|
-
|
|
528
|
+
no_risk_gids_in_batch = sorted(
|
|
529
|
+
[
|
|
530
|
+
gid
|
|
531
|
+
for gid in batch_gids_all_sorted
|
|
532
|
+
if gid not in verified_gids
|
|
533
|
+
]
|
|
534
|
+
)
|
|
535
|
+
PrettyOutput.auto_print(
|
|
536
|
+
f"[jarvis-sec] 批次 {bidx}/{total_batches} 跳过验证,直接写入: 数量={len(verified_items)} 有风险gid={verified_gids}, 无风险gid={no_risk_gids_in_batch}"
|
|
537
|
+
)
|
|
538
|
+
_append_report(
|
|
539
|
+
verified_items,
|
|
540
|
+
"analysis_only",
|
|
541
|
+
task_id,
|
|
542
|
+
{"batch": True, "candidates": batch},
|
|
543
|
+
)
|
|
429
544
|
current_count = count_issues_from_file(sec_dir)
|
|
430
545
|
status_mgr.update_verification(
|
|
431
546
|
current_batch=bidx,
|
|
432
547
|
total_batches=total_batches,
|
|
433
548
|
issues_found=current_count,
|
|
434
|
-
message=f"已处理 {bidx}/{total_batches} 批次,发现 {current_count} 个问题(未验证)"
|
|
549
|
+
message=f"已处理 {bidx}/{total_batches} 批次,发现 {current_count} 个问题(未验证)",
|
|
435
550
|
)
|
|
436
551
|
else:
|
|
437
552
|
# 启用二次验证,运行验证Agent
|
|
438
553
|
# 创建验证 Agent 来验证分析 Agent 的结论
|
|
439
|
-
verification_system_prompt = """
|
|
554
|
+
verification_system_prompt = f"""
|
|
440
555
|
# 验证 Agent 约束
|
|
441
556
|
- 你的核心任务是验证分析 Agent 给出的安全结论是否正确。
|
|
442
557
|
- 你需要仔细检查分析 Agent 给出的前置条件、触发路径、后果和建议是否合理、准确。
|
|
@@ -448,9 +563,9 @@ def process_verification_batch(
|
|
|
448
563
|
- 在验证过程中,充分利用 retrieve_memory 工具检索已有的记忆,特别是分析 Agent 保存的与当前验证函数相关的记忆。
|
|
449
564
|
- 这些记忆可能包含函数的分析要点、指针判空情况、输入校验情况、调用路径分析结果等,可以帮助你更准确地验证分析结论。
|
|
450
565
|
- 如果发现分析 Agent 的结论与记忆中的信息不一致,需要仔细核实。
|
|
451
|
-
- 完成验证后,主输出仅打印结束符
|
|
566
|
+
- 完成验证后,主输出仅打印结束符 {ot("!!!COMPLETE!!!")},不要输出其他任何内容。任务总结将会在后面的交互中被询问。
|
|
452
567
|
""".strip()
|
|
453
|
-
|
|
568
|
+
|
|
454
569
|
verification_task_id = f"JARVIS-SEC-Verify-Batch-{bidx}"
|
|
455
570
|
verification_agent_kwargs: Dict = dict(
|
|
456
571
|
system_prompt=verification_system_prompt,
|
|
@@ -468,9 +583,10 @@ def process_verification_batch(
|
|
|
468
583
|
if llm_group:
|
|
469
584
|
verification_agent_kwargs["model_group"] = llm_group
|
|
470
585
|
verification_agent = Agent(**verification_agent_kwargs)
|
|
471
|
-
|
|
586
|
+
|
|
472
587
|
# 构造验证任务上下文
|
|
473
588
|
import json as _json3
|
|
589
|
+
|
|
474
590
|
verification_task = f"""
|
|
475
591
|
# 验证分析结论任务
|
|
476
592
|
上下文参数:
|
|
@@ -488,11 +604,16 @@ def process_verification_batch(
|
|
|
488
604
|
|
|
489
605
|
对于每个 gid,请判断分析结论是否正确(is_valid: true/false),并给出验证说明。
|
|
490
606
|
""".strip()
|
|
491
|
-
|
|
607
|
+
|
|
492
608
|
# 订阅验证 Agent 的摘要
|
|
493
|
-
verification_summary_container = subscribe_summary_event(
|
|
494
|
-
|
|
495
|
-
|
|
609
|
+
verification_summary_container = subscribe_summary_event(
|
|
610
|
+
verification_agent
|
|
611
|
+
)
|
|
612
|
+
|
|
613
|
+
(
|
|
614
|
+
verification_results,
|
|
615
|
+
verification_parse_error,
|
|
616
|
+
) = run_verification_agent_with_retry(
|
|
496
617
|
verification_agent,
|
|
497
618
|
verification_task,
|
|
498
619
|
build_verification_summary_prompt(),
|
|
@@ -500,117 +621,195 @@ def process_verification_batch(
|
|
|
500
621
|
verification_summary_container,
|
|
501
622
|
bidx,
|
|
502
623
|
)
|
|
503
|
-
|
|
624
|
+
|
|
504
625
|
# 调试日志:显示验证结果
|
|
505
626
|
if verification_results is None:
|
|
506
627
|
try:
|
|
507
|
-
|
|
628
|
+
PrettyOutput.auto_print(
|
|
629
|
+
"[jarvis-sec] 警告:验证 Agent 返回 None,可能解析失败"
|
|
630
|
+
)
|
|
508
631
|
except Exception:
|
|
509
632
|
pass
|
|
510
633
|
elif not isinstance(verification_results, list):
|
|
511
634
|
try:
|
|
512
|
-
|
|
635
|
+
PrettyOutput.auto_print(
|
|
636
|
+
f"[jarvis-sec] 警告:验证 Agent 返回类型错误,期望 list,实际: {type(verification_results)}"
|
|
637
|
+
)
|
|
513
638
|
except Exception:
|
|
514
639
|
pass
|
|
515
640
|
elif len(verification_results) == 0:
|
|
516
641
|
try:
|
|
517
|
-
|
|
642
|
+
PrettyOutput.auto_print(
|
|
643
|
+
"[jarvis-sec] 警告:验证 Agent 返回空列表"
|
|
644
|
+
)
|
|
518
645
|
except Exception:
|
|
519
646
|
pass
|
|
520
647
|
else:
|
|
521
648
|
try:
|
|
522
|
-
|
|
649
|
+
PrettyOutput.auto_print(
|
|
650
|
+
f"[jarvis-sec] 验证 Agent 返回 {len(verification_results)} 个结果项"
|
|
651
|
+
)
|
|
523
652
|
except Exception:
|
|
524
653
|
pass
|
|
525
|
-
|
|
654
|
+
|
|
526
655
|
# 根据验证结果筛选:只保留验证通过(is_valid: true)的告警
|
|
527
656
|
if verification_results:
|
|
528
|
-
gid_to_verification = build_gid_to_verification_mapping(
|
|
529
|
-
|
|
657
|
+
gid_to_verification = build_gid_to_verification_mapping(
|
|
658
|
+
verification_results
|
|
659
|
+
)
|
|
660
|
+
|
|
530
661
|
# 调试日志:显示提取到的验证结果(包含gid列表)
|
|
531
662
|
if gid_to_verification:
|
|
532
663
|
try:
|
|
533
664
|
# 分类显示验证结果:通过和不通过的gid
|
|
534
|
-
valid_gids = sorted(
|
|
535
|
-
|
|
665
|
+
valid_gids = sorted(
|
|
666
|
+
[
|
|
667
|
+
gid
|
|
668
|
+
for gid, v in gid_to_verification.items()
|
|
669
|
+
if v.get("is_valid") is True
|
|
670
|
+
]
|
|
671
|
+
)
|
|
672
|
+
invalid_gids = sorted(
|
|
673
|
+
[
|
|
674
|
+
gid
|
|
675
|
+
for gid, v in gid_to_verification.items()
|
|
676
|
+
if v.get("is_valid") is False
|
|
677
|
+
]
|
|
678
|
+
)
|
|
536
679
|
all_verified_gids = sorted(gid_to_verification.keys())
|
|
537
|
-
|
|
680
|
+
|
|
538
681
|
# 计算未验证的gid(批次中不在验证结果中的gid,视为无风险)
|
|
539
|
-
unverified_gids = sorted(
|
|
682
|
+
unverified_gids = sorted(
|
|
683
|
+
[
|
|
684
|
+
gid
|
|
685
|
+
for gid in batch_gids_all_sorted
|
|
686
|
+
if gid not in all_verified_gids
|
|
687
|
+
]
|
|
688
|
+
)
|
|
540
689
|
# 合并所有无风险的gid(验证不通过的 + 未验证的)
|
|
541
|
-
all_no_risk_gids = sorted(
|
|
542
|
-
|
|
690
|
+
all_no_risk_gids = sorted(
|
|
691
|
+
list(set(invalid_gids + unverified_gids))
|
|
692
|
+
)
|
|
693
|
+
PrettyOutput.auto_print(
|
|
694
|
+
f"[jarvis-sec] 验证 Agent 返回 {len(gid_to_verification)} 个验证结果: 有风险gid={valid_gids}, 无风险gid={all_no_risk_gids}"
|
|
695
|
+
)
|
|
543
696
|
if valid_gids:
|
|
544
|
-
|
|
697
|
+
PrettyOutput.auto_print(
|
|
698
|
+
f"[jarvis-sec] 验证 Agent 判定 {len(valid_gids)} 个候选验证通过(is_valid: true): 有风险gid={valid_gids}"
|
|
699
|
+
)
|
|
545
700
|
if invalid_gids:
|
|
546
|
-
|
|
701
|
+
PrettyOutput.auto_print(
|
|
702
|
+
f"[jarvis-sec] 验证 Agent 判定 {len(invalid_gids)} 个候选验证不通过(is_valid: false): 无风险gid={invalid_gids}"
|
|
703
|
+
)
|
|
547
704
|
if unverified_gids:
|
|
548
|
-
|
|
705
|
+
PrettyOutput.auto_print(
|
|
706
|
+
f"[jarvis-sec] 验证 Agent 未验证的候选(不在验证结果中,视为无风险): 无风险gid={unverified_gids}"
|
|
707
|
+
)
|
|
549
708
|
except Exception:
|
|
550
709
|
pass
|
|
551
710
|
else:
|
|
552
711
|
try:
|
|
553
|
-
|
|
712
|
+
PrettyOutput.auto_print(
|
|
713
|
+
f"[jarvis-sec] 警告:验证结果解析成功,但未提取到任何有效的 gid。验证结果: {verification_results}"
|
|
714
|
+
)
|
|
554
715
|
except Exception:
|
|
555
716
|
pass
|
|
556
|
-
|
|
717
|
+
|
|
557
718
|
# 合并验证通过的告警
|
|
558
|
-
verified_items = merge_verified_items(
|
|
719
|
+
verified_items = merge_verified_items(
|
|
720
|
+
items_with_risk, batch, gid_to_verification
|
|
721
|
+
)
|
|
559
722
|
else:
|
|
560
|
-
|
|
561
|
-
|
|
723
|
+
PrettyOutput.auto_print(
|
|
724
|
+
"[jarvis-sec] 警告:验证 Agent 结果解析失败,不保留任何告警(保守策略)"
|
|
725
|
+
)
|
|
726
|
+
|
|
562
727
|
# 只有验证通过的告警才写入文件
|
|
563
728
|
if verified_items:
|
|
564
|
-
verified_gids = sorted(
|
|
729
|
+
verified_gids = sorted(
|
|
730
|
+
[
|
|
731
|
+
int(item.get("gid", 0))
|
|
732
|
+
for item in verified_items
|
|
733
|
+
if int(item.get("gid", 0)) >= 1
|
|
734
|
+
]
|
|
735
|
+
)
|
|
565
736
|
for item in verified_items:
|
|
566
737
|
gid = int(item.get("gid", 0))
|
|
567
738
|
if gid >= 1:
|
|
568
739
|
gid_counts[gid] = gid_counts.get(gid, 0) + 1
|
|
569
740
|
# 计算无风险的gid(批次中不在verified_gids中的gid)
|
|
570
|
-
no_risk_gids_in_batch = sorted(
|
|
571
|
-
|
|
572
|
-
|
|
741
|
+
no_risk_gids_in_batch = sorted(
|
|
742
|
+
[
|
|
743
|
+
gid
|
|
744
|
+
for gid in batch_gids_all_sorted
|
|
745
|
+
if gid not in verified_gids
|
|
746
|
+
]
|
|
747
|
+
)
|
|
748
|
+
PrettyOutput.auto_print(
|
|
749
|
+
f"[jarvis-sec] 批次 {bidx}/{total_batches} 验证通过: 数量={len(verified_items)}/{len(items_with_risk)} -> 写入文件 有风险gid={verified_gids}, 无风险gid={no_risk_gids_in_batch}"
|
|
750
|
+
)
|
|
751
|
+
_append_report(
|
|
752
|
+
verified_items,
|
|
753
|
+
"verified",
|
|
754
|
+
task_id,
|
|
755
|
+
{"batch": True, "candidates": batch},
|
|
756
|
+
)
|
|
573
757
|
# 从文件读取当前总数(用于状态显示)
|
|
574
758
|
current_count = count_issues_from_file(sec_dir)
|
|
575
759
|
status_mgr.update_verification(
|
|
576
760
|
current_batch=bidx,
|
|
577
761
|
total_batches=total_batches,
|
|
578
762
|
issues_found=current_count,
|
|
579
|
-
message=f"已验证 {bidx}/{total_batches} 批次,发现 {current_count} 个问题(验证通过)"
|
|
763
|
+
message=f"已验证 {bidx}/{total_batches} 批次,发现 {current_count} 个问题(验证通过)",
|
|
580
764
|
)
|
|
581
765
|
else:
|
|
582
766
|
# 验证后无有效告警时也要打印gid列表(所有都视为无风险)
|
|
583
767
|
try:
|
|
584
|
-
risk_gids = sorted(
|
|
585
|
-
|
|
586
|
-
|
|
768
|
+
risk_gids = sorted(
|
|
769
|
+
[
|
|
770
|
+
int(item.get("gid", 0))
|
|
771
|
+
for item in items_with_risk
|
|
772
|
+
if int(item.get("gid", 0)) >= 1
|
|
773
|
+
]
|
|
774
|
+
)
|
|
775
|
+
# 验证后全部不通过,所以所有gid都是无风险 PrettyOutput.auto_print(f"[jarvis-sec] 批次 {bidx}/{total_batches} 验证后无有效告警: 分析 Agent 发现 {len(items_with_risk)} 个有风险的问题,验证后全部不通过 有风险gid=[], 无风险gid={batch_gids_all_sorted}")
|
|
587
776
|
except Exception:
|
|
588
|
-
|
|
777
|
+
PrettyOutput.auto_print(
|
|
778
|
+
f"[jarvis-sec] 批次 {bidx}/{total_batches} 验证后无有效告警: 分析 Agent 发现 {len(items_with_risk)} 个有风险的问题,验证后全部不通过 有风险gid=[], 无风险gid={batch_gids_all_sorted}"
|
|
779
|
+
)
|
|
589
780
|
current_count = count_issues_from_file(sec_dir)
|
|
590
781
|
status_mgr.update_verification(
|
|
591
782
|
current_batch=bidx,
|
|
592
783
|
total_batches=total_batches,
|
|
593
784
|
issues_found=current_count,
|
|
594
|
-
message=f"已验证 {bidx}/{total_batches} 批次,验证后无有效告警"
|
|
785
|
+
message=f"已验证 {bidx}/{total_batches} 批次,验证后无有效告警",
|
|
595
786
|
)
|
|
596
787
|
elif parse_fail:
|
|
597
788
|
# 解析失败时也要打印gid列表(无法判断风险,但显示所有gid)
|
|
598
789
|
try:
|
|
599
|
-
|
|
790
|
+
PrettyOutput.auto_print(
|
|
791
|
+
f"[jarvis-sec] 批次 {bidx}/{total_batches} 解析失败 (摘要中无 <REPORT> 或字段无效): 有风险gid=?, 无风险gid=? (无法判断,gids={batch_gids_all_sorted})"
|
|
792
|
+
)
|
|
600
793
|
except Exception:
|
|
601
|
-
|
|
794
|
+
PrettyOutput.auto_print(
|
|
795
|
+
f"[jarvis-sec] 批次 {bidx}/{total_batches} 解析失败 (摘要中无 <REPORT> 或字段无效)"
|
|
796
|
+
)
|
|
602
797
|
else:
|
|
603
798
|
# 未发现问题时也要打印gid列表(所有都视为无风险)
|
|
604
799
|
try:
|
|
605
|
-
|
|
800
|
+
PrettyOutput.auto_print(
|
|
801
|
+
f"[jarvis-sec] 批次 {bidx}/{total_batches} 未发现问题: 有风险gid=[], 无风险gid={batch_gids_all_sorted}"
|
|
802
|
+
)
|
|
606
803
|
except Exception:
|
|
607
|
-
|
|
804
|
+
PrettyOutput.auto_print(
|
|
805
|
+
f"[jarvis-sec] 批次 {bidx}/{total_batches} 未发现问题"
|
|
806
|
+
)
|
|
608
807
|
current_count = count_issues_from_file(sec_dir)
|
|
609
808
|
status_mgr.update_verification(
|
|
610
809
|
current_batch=bidx,
|
|
611
810
|
total_batches=total_batches,
|
|
612
811
|
issues_found=current_count,
|
|
613
|
-
message=f"已验证 {bidx}/{total_batches} 批次"
|
|
812
|
+
message=f"已验证 {bidx}/{total_batches} 批次",
|
|
614
813
|
)
|
|
615
814
|
|
|
616
815
|
# 为本批次所有候选写入 done 记录
|
|
@@ -621,28 +820,32 @@ def process_verification_batch(
|
|
|
621
820
|
except Exception:
|
|
622
821
|
c_gid = 0
|
|
623
822
|
cnt = gid_counts.get(c_gid, 0)
|
|
624
|
-
_progress_append(
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
823
|
+
_progress_append(
|
|
824
|
+
{
|
|
825
|
+
"event": "task_status",
|
|
826
|
+
"status": "done",
|
|
827
|
+
"task_id": task_id,
|
|
828
|
+
"candidate_signature": sig,
|
|
829
|
+
"candidate": c,
|
|
830
|
+
"issues_count": int(cnt),
|
|
831
|
+
"parse_fail": parse_fail,
|
|
832
|
+
"workspace_restore": workspace_restore_info,
|
|
833
|
+
"batch_index": bidx,
|
|
834
|
+
}
|
|
835
|
+
)
|
|
635
836
|
|
|
636
837
|
# 批次结束记录
|
|
637
|
-
_progress_append(
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
838
|
+
_progress_append(
|
|
839
|
+
{
|
|
840
|
+
"event": "batch_status",
|
|
841
|
+
"status": "done",
|
|
842
|
+
"batch_id": task_id,
|
|
843
|
+
"batch_index": bidx,
|
|
844
|
+
"total_batches": total_batches,
|
|
845
|
+
"issues_count": len(verified_items),
|
|
846
|
+
"parse_fail": parse_fail,
|
|
847
|
+
}
|
|
848
|
+
)
|
|
646
849
|
|
|
647
850
|
|
|
648
851
|
def process_verification_phase(
|
|
@@ -658,61 +861,73 @@ def process_verification_phase(
|
|
|
658
861
|
force_save_memory: bool = False,
|
|
659
862
|
) -> List[Dict]:
|
|
660
863
|
"""处理验证阶段,返回所有已保存的告警"""
|
|
661
|
-
from jarvis.jarvis_sec.file_manager import
|
|
662
|
-
|
|
864
|
+
from jarvis.jarvis_sec.file_manager import get_all_analyzed_gids
|
|
865
|
+
from jarvis.jarvis_sec.file_manager import load_analysis_results
|
|
866
|
+
|
|
663
867
|
batches: List[List[Dict]] = cluster_batches
|
|
664
868
|
total_batches = len(batches)
|
|
665
|
-
|
|
869
|
+
|
|
666
870
|
# 从 analysis.jsonl 中读取已分析的结果
|
|
667
871
|
analysis_results = load_analysis_results(sec_dir)
|
|
668
872
|
analyzed_gids = get_all_analyzed_gids(sec_dir)
|
|
669
|
-
|
|
873
|
+
|
|
670
874
|
# 构建已完成的批次集合(通过 cluster_id 匹配)
|
|
671
875
|
completed_cluster_ids = set()
|
|
672
876
|
for result in analysis_results:
|
|
673
877
|
cluster_id = result.get("cluster_id", "")
|
|
674
878
|
if cluster_id:
|
|
675
879
|
completed_cluster_ids.add(cluster_id)
|
|
676
|
-
|
|
880
|
+
|
|
677
881
|
if completed_cluster_ids:
|
|
678
882
|
try:
|
|
679
|
-
|
|
883
|
+
PrettyOutput.auto_print(
|
|
884
|
+
f"[jarvis-sec] 断点恢复:从 analysis.jsonl 读取到 {len(completed_cluster_ids)} 个已完成的聚类"
|
|
885
|
+
)
|
|
680
886
|
except Exception:
|
|
681
887
|
pass
|
|
682
|
-
|
|
888
|
+
|
|
683
889
|
if analyzed_gids:
|
|
684
890
|
try:
|
|
685
|
-
|
|
891
|
+
PrettyOutput.auto_print(
|
|
892
|
+
f"[jarvis-sec] 断点恢复:从 analysis.jsonl 读取到 {len(analyzed_gids)} 个已分析的 gids"
|
|
893
|
+
)
|
|
686
894
|
except Exception:
|
|
687
895
|
pass
|
|
688
|
-
|
|
896
|
+
|
|
689
897
|
meta_records: List[Dict] = []
|
|
690
898
|
gid_counts: Dict[int, int] = {}
|
|
691
|
-
|
|
899
|
+
|
|
692
900
|
# 加载 clusters.jsonl 以匹配批次和聚类
|
|
693
901
|
from jarvis.jarvis_sec.file_manager import load_clusters
|
|
902
|
+
|
|
694
903
|
clusters = load_clusters(sec_dir)
|
|
695
|
-
|
|
904
|
+
|
|
696
905
|
# 计算实际需要处理的批次数量(排除已完成的批次)
|
|
697
906
|
pending_batches = []
|
|
698
907
|
skipped_count = 0
|
|
699
|
-
|
|
908
|
+
|
|
700
909
|
# 调试:显示已分析的 gid 信息
|
|
701
910
|
if analyzed_gids:
|
|
702
911
|
try:
|
|
703
912
|
analyzed_gids_sorted = sorted(list(analyzed_gids))
|
|
704
|
-
sample_gids =
|
|
705
|
-
|
|
913
|
+
sample_gids = (
|
|
914
|
+
analyzed_gids_sorted[:10]
|
|
915
|
+
if len(analyzed_gids_sorted) > 10
|
|
916
|
+
else analyzed_gids_sorted
|
|
917
|
+
)
|
|
918
|
+
PrettyOutput.auto_print(
|
|
919
|
+
f"[jarvis-sec] 断点恢复:已分析的 gid 示例: {sample_gids}{'...' if len(analyzed_gids_sorted) > 10 else ''} (共 {len(analyzed_gids)} 个)"
|
|
920
|
+
)
|
|
706
921
|
except Exception:
|
|
707
922
|
pass
|
|
708
|
-
|
|
923
|
+
|
|
709
924
|
for bidx, batch in enumerate(batches, start=1):
|
|
710
925
|
batch_file = batch[0].get("file") if batch else None
|
|
711
|
-
|
|
926
|
+
|
|
712
927
|
# 检查批次是否已完成
|
|
713
928
|
is_batch_completed = False
|
|
714
929
|
completion_reason = ""
|
|
715
|
-
|
|
930
|
+
|
|
716
931
|
# 从批次中提取 gids(确保类型为整数)
|
|
717
932
|
batch_gids = set()
|
|
718
933
|
for item in batch:
|
|
@@ -723,12 +938,12 @@ def process_verification_phase(
|
|
|
723
938
|
batch_gids.add(_gid)
|
|
724
939
|
except Exception:
|
|
725
940
|
pass
|
|
726
|
-
|
|
941
|
+
|
|
727
942
|
if not batch_gids:
|
|
728
943
|
# 批次中没有有效的 gid,跳过
|
|
729
944
|
skipped_count += 1
|
|
730
945
|
continue
|
|
731
|
-
|
|
946
|
+
|
|
732
947
|
# 方法1:通过 cluster_id 检查是否已完成
|
|
733
948
|
# 查找匹配的聚类(精确匹配:文件相同且 gid 集合完全相同)
|
|
734
949
|
for cluster in clusters:
|
|
@@ -741,25 +956,28 @@ def process_verification_phase(
|
|
|
741
956
|
cluster_gids.add(int(gid_val))
|
|
742
957
|
except Exception:
|
|
743
958
|
pass
|
|
744
|
-
|
|
959
|
+
|
|
745
960
|
# 文件路径匹配:使用标准化路径进行比较(去除尾部斜杠等)
|
|
746
961
|
def normalize_path(p: str) -> str:
|
|
747
962
|
if not p:
|
|
748
963
|
return ""
|
|
749
964
|
# 统一使用正斜杠,去除尾部斜杠
|
|
750
965
|
return p.replace("\\", "/").rstrip("/")
|
|
751
|
-
|
|
966
|
+
|
|
752
967
|
batch_file_normalized = normalize_path(batch_file or "")
|
|
753
968
|
cluster_file_normalized = normalize_path(cluster_file)
|
|
754
|
-
|
|
969
|
+
|
|
755
970
|
# 匹配条件:文件路径相同(标准化后)且 gid 集合完全相同
|
|
756
|
-
if
|
|
971
|
+
if (
|
|
972
|
+
cluster_file_normalized == batch_file_normalized
|
|
973
|
+
and cluster_gids == batch_gids
|
|
974
|
+
):
|
|
757
975
|
cluster_id = cluster.get("cluster_id", "")
|
|
758
976
|
if cluster_id and cluster_id in completed_cluster_ids:
|
|
759
977
|
is_batch_completed = True
|
|
760
978
|
completion_reason = f"通过 cluster_id 匹配: {cluster_id}"
|
|
761
979
|
break
|
|
762
|
-
|
|
980
|
+
|
|
763
981
|
# 方法2:如果所有 gid 都已分析,则认为该批次已完成
|
|
764
982
|
if not is_batch_completed and batch_gids and analyzed_gids:
|
|
765
983
|
# batch_gids已经是整数集合,analyzed_gids也应该是整数集合
|
|
@@ -770,51 +988,61 @@ def process_verification_phase(
|
|
|
770
988
|
completion_reason = f"所有 gid 已分析 (批次 gids: {sorted(list(batch_gids))[:5]}{'...' if len(batch_gids) > 5 else ''})"
|
|
771
989
|
elif bidx <= 3: # 调试:显示前3个批次的匹配情况
|
|
772
990
|
try:
|
|
773
|
-
|
|
991
|
+
PrettyOutput.auto_print(
|
|
992
|
+
f"[jarvis-sec] 批次 {bidx} 部分 gid 未分析: 缺失={sorted(list(missing_gids))[:5]}{'...' if len(missing_gids) > 5 else ''}, 已分析={sorted(list(batch_gids & analyzed_gids))[:5]}{'...' if len(batch_gids & analyzed_gids) > 5 else ''}"
|
|
993
|
+
)
|
|
774
994
|
except Exception:
|
|
775
995
|
pass
|
|
776
|
-
|
|
996
|
+
|
|
777
997
|
if is_batch_completed:
|
|
778
998
|
skipped_count += 1
|
|
779
999
|
# 调试日志:显示跳过的批次信息
|
|
780
1000
|
try:
|
|
781
|
-
|
|
1001
|
+
PrettyOutput.auto_print(
|
|
1002
|
+
f"[jarvis-sec] 跳过批次 {bidx}/{total_batches} (文件={batch_file}, gids={sorted(list(batch_gids))[:5]}{'...' if len(batch_gids) > 5 else ''}): {completion_reason}"
|
|
1003
|
+
)
|
|
782
1004
|
except Exception:
|
|
783
1005
|
pass
|
|
784
1006
|
else:
|
|
785
1007
|
# 调试日志:显示待处理的批次信息
|
|
786
1008
|
if bidx <= 3: # 只显示前3个待处理批次
|
|
787
1009
|
try:
|
|
788
|
-
missing_gids =
|
|
789
|
-
|
|
1010
|
+
missing_gids = (
|
|
1011
|
+
batch_gids - analyzed_gids if analyzed_gids else batch_gids
|
|
1012
|
+
)
|
|
1013
|
+
PrettyOutput.auto_print(
|
|
1014
|
+
f"[jarvis-sec] 待处理批次 {bidx}/{total_batches} (文件={batch_file}, gids={sorted(list(batch_gids))[:5]}{'...' if len(batch_gids) > 5 else ''}, 未分析={sorted(list(missing_gids))[:5]}{'...' if len(missing_gids) > 5 else ''})"
|
|
1015
|
+
)
|
|
790
1016
|
except Exception:
|
|
791
1017
|
pass
|
|
792
1018
|
pending_batches.append((bidx, batch))
|
|
793
|
-
|
|
1019
|
+
|
|
794
1020
|
# 实际需要处理的批次数量
|
|
795
1021
|
actual_total_batches = len(pending_batches)
|
|
796
1022
|
processed_count = 0
|
|
797
|
-
|
|
1023
|
+
|
|
798
1024
|
# 显示跳过批次的信息
|
|
799
1025
|
if skipped_count > 0:
|
|
800
1026
|
try:
|
|
801
|
-
|
|
1027
|
+
PrettyOutput.auto_print(
|
|
1028
|
+
f"[jarvis-sec] 断点恢复:跳过 {skipped_count} 个已完成的批次,剩余 {actual_total_batches} 个批次待处理"
|
|
1029
|
+
)
|
|
802
1030
|
except Exception:
|
|
803
1031
|
pass
|
|
804
|
-
|
|
1032
|
+
|
|
805
1033
|
# 更新验证阶段状态(使用实际需要处理的总批次数)
|
|
806
1034
|
if actual_total_batches > 0:
|
|
807
1035
|
status_mgr.update_verification(
|
|
808
1036
|
current_batch=0,
|
|
809
1037
|
total_batches=actual_total_batches,
|
|
810
|
-
message=f"开始安全验证...(共 {actual_total_batches} 个批次待处理)"
|
|
1038
|
+
message=f"开始安全验证...(共 {actual_total_batches} 个批次待处理)",
|
|
811
1039
|
)
|
|
812
|
-
|
|
1040
|
+
|
|
813
1041
|
# 处理待处理的批次
|
|
814
1042
|
for bidx, batch in pending_batches:
|
|
815
1043
|
processed_count += 1
|
|
816
1044
|
batch_file = batch[0].get("file") if batch else None
|
|
817
|
-
|
|
1045
|
+
|
|
818
1046
|
# 处理验证批次(使用实际已处理的批次编号)
|
|
819
1047
|
process_verification_batch(
|
|
820
1048
|
batch,
|
|
@@ -832,17 +1060,19 @@ def process_verification_phase(
|
|
|
832
1060
|
enable_verification=enable_verification,
|
|
833
1061
|
force_save_memory=force_save_memory,
|
|
834
1062
|
)
|
|
835
|
-
|
|
1063
|
+
|
|
836
1064
|
# 从 analysis.jsonl 读取所有已验证的问题
|
|
837
|
-
from jarvis.jarvis_sec.file_manager import get_verified_issue_gids
|
|
1065
|
+
from jarvis.jarvis_sec.file_manager import get_verified_issue_gids
|
|
1066
|
+
from jarvis.jarvis_sec.file_manager import load_candidates
|
|
1067
|
+
|
|
838
1068
|
get_verified_issue_gids(sec_dir)
|
|
839
1069
|
load_candidates(sec_dir)
|
|
840
|
-
|
|
1070
|
+
|
|
841
1071
|
# 构建问题列表(从 analysis.jsonl 的 issues 字段)
|
|
842
1072
|
all_issues = []
|
|
843
1073
|
for result in analysis_results:
|
|
844
1074
|
issues = result.get("issues", [])
|
|
845
1075
|
if isinstance(issues, list):
|
|
846
1076
|
all_issues.extend(issues)
|
|
847
|
-
|
|
1077
|
+
|
|
848
1078
|
return all_issues
|