jarvis-ai-assistant 0.3.30__py3-none-any.whl → 0.7.6__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.
Files changed (181) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +458 -152
  3. jarvis/jarvis_agent/agent_manager.py +17 -13
  4. jarvis/jarvis_agent/builtin_input_handler.py +2 -6
  5. jarvis/jarvis_agent/config_editor.py +2 -7
  6. jarvis/jarvis_agent/event_bus.py +82 -12
  7. jarvis/jarvis_agent/file_context_handler.py +329 -0
  8. jarvis/jarvis_agent/file_methodology_manager.py +3 -4
  9. jarvis/jarvis_agent/jarvis.py +628 -55
  10. jarvis/jarvis_agent/language_extractors/__init__.py +57 -0
  11. jarvis/jarvis_agent/language_extractors/c_extractor.py +21 -0
  12. jarvis/jarvis_agent/language_extractors/cpp_extractor.py +21 -0
  13. jarvis/jarvis_agent/language_extractors/go_extractor.py +21 -0
  14. jarvis/jarvis_agent/language_extractors/java_extractor.py +84 -0
  15. jarvis/jarvis_agent/language_extractors/javascript_extractor.py +79 -0
  16. jarvis/jarvis_agent/language_extractors/python_extractor.py +21 -0
  17. jarvis/jarvis_agent/language_extractors/rust_extractor.py +21 -0
  18. jarvis/jarvis_agent/language_extractors/typescript_extractor.py +84 -0
  19. jarvis/jarvis_agent/language_support_info.py +486 -0
  20. jarvis/jarvis_agent/main.py +34 -10
  21. jarvis/jarvis_agent/memory_manager.py +7 -16
  22. jarvis/jarvis_agent/methodology_share_manager.py +10 -16
  23. jarvis/jarvis_agent/prompt_manager.py +1 -1
  24. jarvis/jarvis_agent/prompts.py +193 -171
  25. jarvis/jarvis_agent/protocols.py +8 -12
  26. jarvis/jarvis_agent/run_loop.py +105 -9
  27. jarvis/jarvis_agent/session_manager.py +2 -3
  28. jarvis/jarvis_agent/share_manager.py +20 -22
  29. jarvis/jarvis_agent/shell_input_handler.py +1 -2
  30. jarvis/jarvis_agent/stdio_redirect.py +295 -0
  31. jarvis/jarvis_agent/task_analyzer.py +31 -6
  32. jarvis/jarvis_agent/task_manager.py +11 -27
  33. jarvis/jarvis_agent/tool_executor.py +2 -3
  34. jarvis/jarvis_agent/tool_share_manager.py +12 -24
  35. jarvis/jarvis_agent/utils.py +5 -1
  36. jarvis/jarvis_agent/web_bridge.py +189 -0
  37. jarvis/jarvis_agent/web_output_sink.py +53 -0
  38. jarvis/jarvis_agent/web_server.py +786 -0
  39. jarvis/jarvis_c2rust/__init__.py +26 -0
  40. jarvis/jarvis_c2rust/cli.py +575 -0
  41. jarvis/jarvis_c2rust/collector.py +250 -0
  42. jarvis/jarvis_c2rust/constants.py +26 -0
  43. jarvis/jarvis_c2rust/library_replacer.py +1254 -0
  44. jarvis/jarvis_c2rust/llm_module_agent.py +1272 -0
  45. jarvis/jarvis_c2rust/loaders.py +207 -0
  46. jarvis/jarvis_c2rust/models.py +28 -0
  47. jarvis/jarvis_c2rust/optimizer.py +2157 -0
  48. jarvis/jarvis_c2rust/scanner.py +1681 -0
  49. jarvis/jarvis_c2rust/transpiler.py +2983 -0
  50. jarvis/jarvis_c2rust/utils.py +385 -0
  51. jarvis/jarvis_code_agent/build_validation_config.py +132 -0
  52. jarvis/jarvis_code_agent/code_agent.py +1371 -220
  53. jarvis/jarvis_code_agent/code_analyzer/__init__.py +65 -0
  54. jarvis/jarvis_code_agent/code_analyzer/base_language.py +74 -0
  55. jarvis/jarvis_code_agent/code_analyzer/build_validator/__init__.py +44 -0
  56. jarvis/jarvis_code_agent/code_analyzer/build_validator/base.py +106 -0
  57. jarvis/jarvis_code_agent/code_analyzer/build_validator/cmake.py +74 -0
  58. jarvis/jarvis_code_agent/code_analyzer/build_validator/detector.py +125 -0
  59. jarvis/jarvis_code_agent/code_analyzer/build_validator/fallback.py +72 -0
  60. jarvis/jarvis_code_agent/code_analyzer/build_validator/go.py +70 -0
  61. jarvis/jarvis_code_agent/code_analyzer/build_validator/java_gradle.py +53 -0
  62. jarvis/jarvis_code_agent/code_analyzer/build_validator/java_maven.py +47 -0
  63. jarvis/jarvis_code_agent/code_analyzer/build_validator/makefile.py +61 -0
  64. jarvis/jarvis_code_agent/code_analyzer/build_validator/nodejs.py +110 -0
  65. jarvis/jarvis_code_agent/code_analyzer/build_validator/python.py +154 -0
  66. jarvis/jarvis_code_agent/code_analyzer/build_validator/rust.py +110 -0
  67. jarvis/jarvis_code_agent/code_analyzer/build_validator/validator.py +153 -0
  68. jarvis/jarvis_code_agent/code_analyzer/build_validator.py +43 -0
  69. jarvis/jarvis_code_agent/code_analyzer/context_manager.py +648 -0
  70. jarvis/jarvis_code_agent/code_analyzer/context_recommender.py +18 -0
  71. jarvis/jarvis_code_agent/code_analyzer/dependency_analyzer.py +132 -0
  72. jarvis/jarvis_code_agent/code_analyzer/file_ignore.py +330 -0
  73. jarvis/jarvis_code_agent/code_analyzer/impact_analyzer.py +781 -0
  74. jarvis/jarvis_code_agent/code_analyzer/language_registry.py +185 -0
  75. jarvis/jarvis_code_agent/code_analyzer/language_support.py +110 -0
  76. jarvis/jarvis_code_agent/code_analyzer/languages/__init__.py +49 -0
  77. jarvis/jarvis_code_agent/code_analyzer/languages/c_cpp_language.py +299 -0
  78. jarvis/jarvis_code_agent/code_analyzer/languages/go_language.py +215 -0
  79. jarvis/jarvis_code_agent/code_analyzer/languages/java_language.py +212 -0
  80. jarvis/jarvis_code_agent/code_analyzer/languages/javascript_language.py +254 -0
  81. jarvis/jarvis_code_agent/code_analyzer/languages/python_language.py +269 -0
  82. jarvis/jarvis_code_agent/code_analyzer/languages/rust_language.py +281 -0
  83. jarvis/jarvis_code_agent/code_analyzer/languages/typescript_language.py +280 -0
  84. jarvis/jarvis_code_agent/code_analyzer/llm_context_recommender.py +605 -0
  85. jarvis/jarvis_code_agent/code_analyzer/structured_code.py +556 -0
  86. jarvis/jarvis_code_agent/code_analyzer/symbol_extractor.py +252 -0
  87. jarvis/jarvis_code_agent/code_analyzer/tree_sitter_extractor.py +58 -0
  88. jarvis/jarvis_code_agent/lint.py +501 -8
  89. jarvis/jarvis_code_agent/utils.py +141 -0
  90. jarvis/jarvis_code_analysis/code_review.py +493 -584
  91. jarvis/jarvis_data/config_schema.json +128 -12
  92. jarvis/jarvis_git_squash/main.py +4 -5
  93. jarvis/jarvis_git_utils/git_commiter.py +82 -75
  94. jarvis/jarvis_mcp/sse_mcp_client.py +22 -29
  95. jarvis/jarvis_mcp/stdio_mcp_client.py +12 -13
  96. jarvis/jarvis_mcp/streamable_mcp_client.py +15 -14
  97. jarvis/jarvis_memory_organizer/memory_organizer.py +55 -74
  98. jarvis/jarvis_methodology/main.py +32 -48
  99. jarvis/jarvis_multi_agent/__init__.py +287 -55
  100. jarvis/jarvis_multi_agent/main.py +36 -4
  101. jarvis/jarvis_platform/base.py +524 -202
  102. jarvis/jarvis_platform/human.py +7 -8
  103. jarvis/jarvis_platform/kimi.py +30 -36
  104. jarvis/jarvis_platform/openai.py +88 -25
  105. jarvis/jarvis_platform/registry.py +26 -10
  106. jarvis/jarvis_platform/tongyi.py +24 -25
  107. jarvis/jarvis_platform/yuanbao.py +32 -43
  108. jarvis/jarvis_platform_manager/main.py +66 -77
  109. jarvis/jarvis_platform_manager/service.py +8 -13
  110. jarvis/jarvis_rag/cli.py +53 -55
  111. jarvis/jarvis_rag/embedding_manager.py +13 -18
  112. jarvis/jarvis_rag/llm_interface.py +8 -9
  113. jarvis/jarvis_rag/query_rewriter.py +10 -21
  114. jarvis/jarvis_rag/rag_pipeline.py +24 -27
  115. jarvis/jarvis_rag/reranker.py +4 -5
  116. jarvis/jarvis_rag/retriever.py +28 -30
  117. jarvis/jarvis_sec/__init__.py +305 -0
  118. jarvis/jarvis_sec/agents.py +143 -0
  119. jarvis/jarvis_sec/analysis.py +276 -0
  120. jarvis/jarvis_sec/checkers/__init__.py +32 -0
  121. jarvis/jarvis_sec/checkers/c_checker.py +2680 -0
  122. jarvis/jarvis_sec/checkers/rust_checker.py +1108 -0
  123. jarvis/jarvis_sec/cli.py +139 -0
  124. jarvis/jarvis_sec/clustering.py +1439 -0
  125. jarvis/jarvis_sec/file_manager.py +427 -0
  126. jarvis/jarvis_sec/parsers.py +73 -0
  127. jarvis/jarvis_sec/prompts.py +268 -0
  128. jarvis/jarvis_sec/report.py +336 -0
  129. jarvis/jarvis_sec/review.py +453 -0
  130. jarvis/jarvis_sec/status.py +264 -0
  131. jarvis/jarvis_sec/types.py +20 -0
  132. jarvis/jarvis_sec/utils.py +499 -0
  133. jarvis/jarvis_sec/verification.py +848 -0
  134. jarvis/jarvis_sec/workflow.py +226 -0
  135. jarvis/jarvis_smart_shell/main.py +38 -87
  136. jarvis/jarvis_stats/cli.py +2 -2
  137. jarvis/jarvis_stats/stats.py +8 -8
  138. jarvis/jarvis_stats/storage.py +15 -21
  139. jarvis/jarvis_stats/visualizer.py +1 -1
  140. jarvis/jarvis_tools/clear_memory.py +3 -20
  141. jarvis/jarvis_tools/cli/main.py +21 -23
  142. jarvis/jarvis_tools/edit_file.py +1019 -132
  143. jarvis/jarvis_tools/execute_script.py +83 -25
  144. jarvis/jarvis_tools/file_analyzer.py +6 -9
  145. jarvis/jarvis_tools/generate_new_tool.py +14 -21
  146. jarvis/jarvis_tools/lsp_client.py +1552 -0
  147. jarvis/jarvis_tools/methodology.py +2 -3
  148. jarvis/jarvis_tools/read_code.py +1736 -35
  149. jarvis/jarvis_tools/read_symbols.py +140 -0
  150. jarvis/jarvis_tools/read_webpage.py +12 -13
  151. jarvis/jarvis_tools/registry.py +427 -200
  152. jarvis/jarvis_tools/retrieve_memory.py +20 -19
  153. jarvis/jarvis_tools/rewrite_file.py +72 -158
  154. jarvis/jarvis_tools/save_memory.py +3 -15
  155. jarvis/jarvis_tools/search_web.py +18 -18
  156. jarvis/jarvis_tools/sub_agent.py +36 -43
  157. jarvis/jarvis_tools/sub_code_agent.py +25 -26
  158. jarvis/jarvis_tools/virtual_tty.py +55 -33
  159. jarvis/jarvis_utils/clipboard.py +7 -10
  160. jarvis/jarvis_utils/config.py +232 -45
  161. jarvis/jarvis_utils/embedding.py +8 -5
  162. jarvis/jarvis_utils/fzf.py +8 -8
  163. jarvis/jarvis_utils/git_utils.py +225 -36
  164. jarvis/jarvis_utils/globals.py +3 -3
  165. jarvis/jarvis_utils/http.py +1 -1
  166. jarvis/jarvis_utils/input.py +99 -48
  167. jarvis/jarvis_utils/jsonnet_compat.py +465 -0
  168. jarvis/jarvis_utils/methodology.py +52 -48
  169. jarvis/jarvis_utils/utils.py +819 -491
  170. jarvis_ai_assistant-0.7.6.dist-info/METADATA +600 -0
  171. jarvis_ai_assistant-0.7.6.dist-info/RECORD +218 -0
  172. {jarvis_ai_assistant-0.3.30.dist-info → jarvis_ai_assistant-0.7.6.dist-info}/entry_points.txt +4 -0
  173. jarvis/jarvis_agent/config.py +0 -92
  174. jarvis/jarvis_agent/edit_file_handler.py +0 -296
  175. jarvis/jarvis_platform/ai8.py +0 -332
  176. jarvis/jarvis_tools/ask_user.py +0 -54
  177. jarvis_ai_assistant-0.3.30.dist-info/METADATA +0 -381
  178. jarvis_ai_assistant-0.3.30.dist-info/RECORD +0 -137
  179. {jarvis_ai_assistant-0.3.30.dist-info → jarvis_ai_assistant-0.7.6.dist-info}/WHEEL +0 -0
  180. {jarvis_ai_assistant-0.3.30.dist-info → jarvis_ai_assistant-0.7.6.dist-info}/licenses/LICENSE +0 -0
  181. {jarvis_ai_assistant-0.3.30.dist-info → jarvis_ai_assistant-0.7.6.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,276 @@
1
+ # -*- coding: utf-8 -*-
2
+ """分析相关模块"""
3
+
4
+ from typing import Dict, List, Optional
5
+ import typer
6
+
7
+ from jarvis.jarvis_agent import Agent
8
+ from jarvis.jarvis_sec.prompts import build_summary_prompt
9
+ from jarvis.jarvis_sec.parsers import try_parse_summary_report
10
+ from jarvis.jarvis_sec.utils import git_restore_if_dirty
11
+
12
+
13
+ def valid_items(items: Optional[List]) -> bool:
14
+ """验证分析结果项的格式"""
15
+ if not isinstance(items, list):
16
+ return False
17
+ for it in items:
18
+ if not isinstance(it, dict):
19
+ return False
20
+ has_gid = "gid" in it
21
+ has_gids = "gids" in it
22
+ if not has_gid and not has_gids:
23
+ return False
24
+ if has_gid and has_gids:
25
+ return False
26
+ if has_gid:
27
+ try:
28
+ if int(it["gid"]) < 1:
29
+ return False
30
+ except Exception:
31
+ return False
32
+ elif has_gids:
33
+ if not isinstance(it["gids"], list) or len(it["gids"]) == 0:
34
+ return False
35
+ for gid_val in it["gids"]:
36
+ try:
37
+ if int(gid_val) < 1:
38
+ return False
39
+ except Exception:
40
+ return False
41
+ if "has_risk" not in it or not isinstance(it["has_risk"], bool):
42
+ return False
43
+ if it.get("has_risk"):
44
+ for key in ["preconditions", "trigger_path", "consequences", "suggestions"]:
45
+ if key not in it:
46
+ return False
47
+ if not isinstance(it[key], str) or not it[key].strip():
48
+ return False
49
+ return True
50
+
51
+
52
+ def build_analysis_task_context(batch: List[Dict], entry_path: str, langs: List[str]) -> str:
53
+ """构建分析任务上下文"""
54
+ import json as _json2
55
+ batch_ctx: List[Dict] = list(batch)
56
+ cluster_verify = str(batch_ctx[0].get("verify") if batch_ctx else "")
57
+ cluster_gids_ctx = [it.get("gid") for it in batch_ctx]
58
+ return f"""
59
+ # 安全子任务批次
60
+ 上下文参数:
61
+ - entry_path: {entry_path}
62
+ - languages: {langs}
63
+ - cluster_verification: {cluster_verify}
64
+
65
+ - cluster_gids: {cluster_gids_ctx}
66
+ - note: 每个候选含 gid/verify 字段,模型仅需输出 gid 统一给出验证/判断结论(全局编号);无需使用局部 id
67
+
68
+ 批次候选(JSON数组):
69
+ {_json2.dumps(batch_ctx, ensure_ascii=False, indent=2)}
70
+ """.strip()
71
+
72
+
73
+ def build_validation_error_guidance(
74
+ parse_error_analysis: Optional[str],
75
+ prev_parsed_items: Optional[List],
76
+ ) -> str:
77
+ """构建验证错误指导信息"""
78
+ if parse_error_analysis:
79
+ return f"\n\n**格式错误详情(请根据以下错误修复输出格式):**\n- JSON解析失败: {parse_error_analysis}\n\n请确保输出的JSON格式正确,包括正确的引号、逗号、大括号等。仅输出一个 <REPORT> 块,块内直接包含 JSON 数组(不需要额外的标签)。支持jsonnet语法(如尾随逗号、注释、||| 或 ``` 分隔符多行字符串等)。"
80
+ elif prev_parsed_items is None:
81
+ return "\n\n**格式错误详情(请根据以下错误修复输出格式):**\n- 无法从摘要中解析出有效的 JSON 数组"
82
+ elif not valid_items(prev_parsed_items):
83
+ validation_errors = []
84
+ if not isinstance(prev_parsed_items, list):
85
+ validation_errors.append("结果不是数组")
86
+ else:
87
+ for idx, it in enumerate(prev_parsed_items):
88
+ if not isinstance(it, dict):
89
+ validation_errors.append(f"元素{idx}不是字典")
90
+ break
91
+ has_gid = "gid" in it
92
+ has_gids = "gids" in it
93
+ if not has_gid and not has_gids:
94
+ validation_errors.append(f"元素{idx}缺少必填字段 gid 或 gids")
95
+ break
96
+ if has_gid and has_gids:
97
+ validation_errors.append(f"元素{idx}不能同时包含 gid 和 gids")
98
+ break
99
+ if has_gid:
100
+ try:
101
+ if int(it.get("gid", 0)) < 1:
102
+ validation_errors.append(f"元素{idx}的 gid 必须 >= 1")
103
+ break
104
+ except Exception:
105
+ validation_errors.append(f"元素{idx}的 gid 格式错误(必须是整数)")
106
+ break
107
+ elif has_gids:
108
+ if not isinstance(it.get("gids"), list) or len(it.get("gids", [])) == 0:
109
+ validation_errors.append(f"元素{idx}的 gids 必须是非空数组")
110
+ break
111
+ try:
112
+ for gid_idx, gid_val in enumerate(it.get("gids", [])):
113
+ if int(gid_val) < 1:
114
+ validation_errors.append(f"元素{idx}的 gids[{gid_idx}] 必须 >= 1")
115
+ break
116
+ if validation_errors:
117
+ break
118
+ except Exception:
119
+ validation_errors.append(f"元素{idx}的 gids 格式错误(必须是整数数组)")
120
+ break
121
+ if "has_risk" not in it or not isinstance(it.get("has_risk"), bool):
122
+ validation_errors.append(f"元素{idx}缺少必填字段 has_risk(必须是布尔值)")
123
+ break
124
+ if it.get("has_risk"):
125
+ for key in ["preconditions", "trigger_path", "consequences", "suggestions"]:
126
+ if key not in it:
127
+ validation_errors.append(f"元素{idx}的 has_risk 为 true,但缺少必填字段 {key}")
128
+ break
129
+ if not isinstance(it[key], str) or not it[key].strip():
130
+ validation_errors.append(f"元素{idx}的 {key} 字段不能为空")
131
+ break
132
+ if validation_errors:
133
+ break
134
+ if validation_errors:
135
+ return "\n\n**格式错误详情(请根据以下错误修复输出格式):**\n" + "\n".join(f"- {err}" for err in validation_errors)
136
+ return ""
137
+
138
+
139
+ def run_analysis_agent_with_retry(
140
+ agent: Agent,
141
+ per_task: str,
142
+ summary_container: Dict[str, str],
143
+ entry_path: str,
144
+ task_id: str,
145
+ bidx: int,
146
+ meta_records: List[Dict],
147
+ ) -> tuple[Optional[List[Dict]], Optional[Dict]]:
148
+ """运行分析Agent并重试直到成功"""
149
+ summary_items: Optional[List[Dict]] = None
150
+ workspace_restore_info: Optional[Dict] = None
151
+ use_direct_model_analysis = False
152
+ prev_parsed_items: Optional[List] = None
153
+ parse_error_analysis: Optional[str] = None
154
+ attempt = 0
155
+
156
+ while True:
157
+ attempt += 1
158
+ summary_container["text"] = ""
159
+
160
+ if use_direct_model_analysis:
161
+ summary_prompt_text = build_summary_prompt()
162
+ error_guidance = build_validation_error_guidance(parse_error_analysis, prev_parsed_items)
163
+ full_prompt = f"{per_task}{error_guidance}\n\n{summary_prompt_text}"
164
+ try:
165
+ response = agent.model.chat_until_success(full_prompt) # type: ignore
166
+ summary_container["text"] = response
167
+ except Exception as e:
168
+ try:
169
+ typer.secho(f"[jarvis-sec] 直接模型调用失败: {e},回退到 run()", fg=typer.colors.YELLOW)
170
+ except Exception:
171
+ pass
172
+ agent.run(per_task)
173
+ else:
174
+ agent.run(per_task)
175
+
176
+ # 工作区保护
177
+ try:
178
+ _changed = git_restore_if_dirty(entry_path)
179
+ workspace_restore_info = {
180
+ "performed": bool(_changed),
181
+ "changed_files_count": int(_changed or 0),
182
+ "action": "git checkout -- .",
183
+ }
184
+ meta_records.append({
185
+ "task_id": task_id,
186
+ "batch_index": bidx,
187
+ "workspace_restore": workspace_restore_info,
188
+ "attempt": attempt + 1,
189
+ })
190
+ if _changed:
191
+ try:
192
+ typer.secho(f"[jarvis-sec] 工作区已恢复 ({_changed} 个文件),操作: git checkout -- .", fg=typer.colors.BLUE)
193
+ except Exception:
194
+ pass
195
+ except Exception:
196
+ pass
197
+
198
+ # 解析摘要中的 <REPORT>(JSON)
199
+ summary_text = summary_container.get("text", "")
200
+ parsed_items: Optional[List] = None
201
+ parse_error_analysis = None
202
+ if summary_text:
203
+ rep, parse_error_analysis = try_parse_summary_report(summary_text)
204
+ if parse_error_analysis:
205
+ try:
206
+ typer.secho(f"[jarvis-sec] 分析结果JSON解析失败: {parse_error_analysis}", fg=typer.colors.YELLOW)
207
+ except Exception:
208
+ pass
209
+ elif isinstance(rep, list):
210
+ parsed_items = rep
211
+ elif isinstance(rep, dict):
212
+ items = rep.get("issues")
213
+ if isinstance(items, list):
214
+ parsed_items = items
215
+
216
+ # 关键字段校验
217
+ # 空数组 [] 是有效的(表示没有发现问题),需要单独处理
218
+ if parsed_items is not None:
219
+ if len(parsed_items) == 0:
220
+ # 空数组表示没有发现问题,这是有效的格式
221
+ summary_items = parsed_items
222
+ break
223
+ elif valid_items(parsed_items):
224
+ # 非空数组需要验证格式
225
+ summary_items = parsed_items
226
+ break
227
+
228
+ # 格式校验失败,后续重试使用直接模型调用
229
+ use_direct_model_analysis = True
230
+ prev_parsed_items = parsed_items
231
+ if parse_error_analysis:
232
+ try:
233
+ typer.secho(f"[jarvis-sec] 分析结果JSON解析失败 -> 重试第 {attempt} 次 (批次={bidx},使用直接模型调用,将反馈解析错误)", fg=typer.colors.YELLOW)
234
+ except Exception:
235
+ pass
236
+ else:
237
+ try:
238
+ typer.secho(f"[jarvis-sec] 分析结果格式无效 -> 重试第 {attempt} 次 (批次={bidx},使用直接模型调用)", fg=typer.colors.YELLOW)
239
+ except Exception:
240
+ pass
241
+
242
+ return summary_items, workspace_restore_info
243
+
244
+
245
+ def expand_and_filter_analysis_results(summary_items: List[Dict]) -> tuple[List[Dict], List[Dict]]:
246
+ """展开gids格式为单个gid格式,并过滤出有风险的项目"""
247
+ items_with_risk: List[Dict] = []
248
+ items_without_risk: List[Dict] = []
249
+ merged_items: List[Dict] = []
250
+
251
+ for it in summary_items:
252
+ has_risk = it.get("has_risk") is True
253
+ if "gids" in it and isinstance(it.get("gids"), list):
254
+ for gid_val in it.get("gids", []):
255
+ try:
256
+ gid_int = int(gid_val)
257
+ if gid_int >= 1:
258
+ item = {
259
+ **{k: v for k, v in it.items() if k != "gids"},
260
+ "gid": gid_int,
261
+ }
262
+ if has_risk:
263
+ merged_items.append(item)
264
+ items_with_risk.append(item)
265
+ else:
266
+ items_without_risk.append(item)
267
+ except Exception:
268
+ pass
269
+ elif "gid" in it:
270
+ if has_risk:
271
+ merged_items.append(it)
272
+ items_with_risk.append(it)
273
+ else:
274
+ items_without_risk.append(it)
275
+
276
+ return items_with_risk, items_without_risk
@@ -0,0 +1,32 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ Jarvis 安全演进多Agent套件 —— Checkers 包初始化
4
+
5
+ 说明:
6
+ - 统一导出 C/C++ 与 Rust 启发式检查器的对外接口,便于上层工作流按需调用。
7
+ - 保持最小依赖,不在此处执行任何扫描逻辑,仅做导入与别名暴露。
8
+ """
9
+
10
+
11
+
12
+ from .c_checker import (
13
+ analyze_files as analyze_c_files,
14
+ analyze_c_cpp_file,
15
+ analyze_c_cpp_text,
16
+ )
17
+ from .rust_checker import (
18
+ analyze_rust_files,
19
+ analyze_rust_file,
20
+ analyze_rust_text,
21
+ )
22
+
23
+ __all__ = [
24
+ # C/C++
25
+ "analyze_c_files",
26
+ "analyze_c_cpp_file",
27
+ "analyze_c_cpp_text",
28
+ # Rust
29
+ "analyze_rust_files",
30
+ "analyze_rust_file",
31
+ "analyze_rust_text",
32
+ ]