jarvis-ai-assistant 0.5.1__py3-none-any.whl → 0.6.0__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 (29) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +15 -4
  3. jarvis/jarvis_agent/agent_manager.py +3 -0
  4. jarvis/jarvis_agent/jarvis.py +44 -14
  5. jarvis/jarvis_agent/run_loop.py +6 -1
  6. jarvis/jarvis_agent/task_planner.py +1 -0
  7. jarvis/jarvis_c2rust/__init__.py +13 -0
  8. jarvis/jarvis_c2rust/cli.py +405 -0
  9. jarvis/jarvis_c2rust/collector.py +209 -0
  10. jarvis/jarvis_c2rust/library_replacer.py +933 -0
  11. jarvis/jarvis_c2rust/llm_module_agent.py +1265 -0
  12. jarvis/jarvis_c2rust/scanner.py +1671 -0
  13. jarvis/jarvis_c2rust/transpiler.py +1236 -0
  14. jarvis/jarvis_code_agent/code_agent.py +144 -18
  15. jarvis/jarvis_data/config_schema.json +8 -3
  16. jarvis/jarvis_tools/cli/main.py +1 -0
  17. jarvis/jarvis_tools/execute_script.py +1 -1
  18. jarvis/jarvis_tools/read_code.py +11 -1
  19. jarvis/jarvis_tools/read_symbols.py +129 -0
  20. jarvis/jarvis_tools/registry.py +9 -1
  21. jarvis/jarvis_utils/config.py +14 -4
  22. jarvis/jarvis_utils/git_utils.py +39 -0
  23. jarvis/jarvis_utils/utils.py +13 -5
  24. {jarvis_ai_assistant-0.5.1.dist-info → jarvis_ai_assistant-0.6.0.dist-info}/METADATA +13 -1
  25. {jarvis_ai_assistant-0.5.1.dist-info → jarvis_ai_assistant-0.6.0.dist-info}/RECORD +29 -21
  26. {jarvis_ai_assistant-0.5.1.dist-info → jarvis_ai_assistant-0.6.0.dist-info}/entry_points.txt +2 -0
  27. {jarvis_ai_assistant-0.5.1.dist-info → jarvis_ai_assistant-0.6.0.dist-info}/WHEEL +0 -0
  28. {jarvis_ai_assistant-0.5.1.dist-info → jarvis_ai_assistant-0.6.0.dist-info}/licenses/LICENSE +0 -0
  29. {jarvis_ai_assistant-0.5.1.dist-info → jarvis_ai_assistant-0.6.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,209 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ C/C++ 头文件函数名收集器(基于 libclang)。
4
+
5
+ 功能:
6
+ - 接受一个或多个头文件路径(.h/.hh/.hpp/.hxx),使用 libclang 精确解析,收集这些头文件中声明或定义的函数名。
7
+ - 优先输出限定名(qualified_name),回退到普通名称(name)。
8
+ - 自动逐层向上查找 compile_commands.json(直到文件系统根目录);若未找到则跳过并使用基础 -I 参数;失败时回退为空参数。
9
+ - 自动为头文件设置语言选项 (-x c-header 或 -x c++-header),提升解析成功率。
10
+
11
+ 输出:
12
+ - 将唯一的函数名集合写入指定输出文件(每行一个函数名,UTF-8 编码)。
13
+
14
+ 与现有实现的关系:
15
+ - 复用 jarvis.jarvis_c2rust.scanner 中的能力:
16
+ - _try_import_libclang: 兼容多版本 libclang 的加载器
17
+ - find_compile_commands / load_compile_commands: compile_commands.json 解析与逐层向上搜索
18
+ - get_qualified_name / is_function_like: 统一限定名生成和函数节点类型判断
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ from pathlib import Path
24
+ from typing import Dict, List, Optional, Set
25
+
26
+ # 复用 scanner 内的核心能力
27
+ from jarvis.jarvis_c2rust.scanner import ( # type: ignore
28
+ _try_import_libclang,
29
+ find_compile_commands,
30
+ load_compile_commands,
31
+ get_qualified_name,
32
+ is_function_like,
33
+ )
34
+
35
+
36
+ HEADER_EXTS = {".h", ".hh", ".hpp", ".hxx"}
37
+
38
+
39
+ def _resolve_compile_args_map(files: List[Path]) -> Dict[str, List[str]]:
40
+ """
41
+ 逐文件尝试向上查找 compile_commands.json(直到根目录),并合并解析为:
42
+ file_abs_path_str -> compile_args(list[str])
43
+ 若未找到任何 compile_commands.json,则返回空映射。
44
+ """
45
+ mapping: Dict[str, List[str]] = {}
46
+ visited_cc_paths: Set[Path] = set()
47
+
48
+ for f in files:
49
+ try:
50
+ cc_path = find_compile_commands(f.parent)
51
+ except Exception:
52
+ cc_path = None
53
+ if cc_path and cc_path.exists() and cc_path not in visited_cc_paths:
54
+ try:
55
+ m = load_compile_commands(cc_path)
56
+ if isinstance(m, dict):
57
+ mapping.update(m)
58
+ visited_cc_paths.add(cc_path)
59
+ except Exception:
60
+ # ignore parse errors, continue searching next file's tree
61
+ pass
62
+
63
+ return mapping
64
+
65
+
66
+ def _ensure_lang_header_args(file_path: Path, base_args: List[str]) -> List[str]:
67
+ """
68
+ 确保为头文件设置合适的语言选项:
69
+ - C 头文件: -x c-header
70
+ - C++ 头文件: -x c++-header
71
+ 若 base_args 已包含 -x,则尊重现有设置,不再强制覆盖。
72
+ """
73
+ args = list(base_args or [])
74
+ has_x = any(a == "-x" or a.startswith("-x") for a in args)
75
+ if has_x:
76
+ return args
77
+ ext = file_path.suffix.lower()
78
+ if ext in {".hpp", ".hxx", ".hh"}:
79
+ args.extend(["-x", "c++-header"])
80
+ else:
81
+ args.extend(["-x", "c-header"])
82
+ return args
83
+
84
+
85
+ def _scan_header_for_names(cindex, file_path: Path, args: List[str]) -> List[str]:
86
+ """
87
+ 扫描单个头文件,返回该文件中声明或定义的函数的限定名/名称列表。
88
+ - 不要求 is_definition(),以捕获函数原型声明
89
+ - 仅收集位于该文件本身的符号(根据 location.file 判断)
90
+ """
91
+ index = cindex.Index.create()
92
+ tu = index.parse(
93
+ str(file_path),
94
+ args=args,
95
+ options=0,
96
+ )
97
+ names: List[str] = []
98
+
99
+ def visit(node):
100
+ # 只收集属于当前文件的节点
101
+ loc_file = node.location.file
102
+ if loc_file is None or Path(loc_file.name).resolve() != file_path.resolve():
103
+ for ch in node.get_children():
104
+ visit(ch)
105
+ return
106
+
107
+ if is_function_like(node):
108
+ try:
109
+ qn = get_qualified_name(node)
110
+ nm = node.spelling or ""
111
+ label = (qn or nm or "").strip()
112
+ if label:
113
+ names.append(label)
114
+ except Exception:
115
+ nm = (node.spelling or "").strip()
116
+ if nm:
117
+ names.append(nm)
118
+
119
+ for ch in node.get_children():
120
+ visit(ch)
121
+
122
+ visit(tu.cursor)
123
+ return names
124
+
125
+
126
+ def collect_function_names(
127
+ files: List[Path],
128
+ out_path: Path,
129
+ ) -> Path:
130
+ """
131
+ 收集给定头文件中的函数名并写入指定文件。
132
+
133
+ 参数:
134
+ - files: 一个或多个 C/C++ 头文件路径(.h/.hh/.hpp/.hxx)
135
+ - out_path: 输出文件路径(将创建目录)
136
+
137
+ 返回:
138
+ - 写入的输出文件路径
139
+ """
140
+ if not files:
141
+ raise ValueError("必须至少提供一个头文件路径")
142
+
143
+ # 归一化与存在性检查,仅保留头文件
144
+ file_list: List[Path] = []
145
+ for p in files:
146
+ rp = Path(p).resolve()
147
+ if not rp.exists():
148
+ print(f"[c2rust-collector] 警告: 文件不存在,已跳过: {rp}")
149
+ continue
150
+ if not rp.is_file():
151
+ print(f"[c2rust-collector] 警告: 非普通文件,已跳过: {rp}")
152
+ continue
153
+ if rp.suffix.lower() not in HEADER_EXTS:
154
+ print(f"[c2rust-collector] 警告: 非头文件(仅支持 .h/.hh/.hpp/.hxx),已跳过: {rp}")
155
+ continue
156
+ file_list.append(rp)
157
+
158
+ if not file_list:
159
+ raise FileNotFoundError("提供的文件列表均不可用或不包含头文件(支持 .h/.hh/.hpp/.hxx)")
160
+
161
+ # 准备 libclang
162
+ cindex = _try_import_libclang()
163
+ if cindex is None:
164
+ # 与 scanner 的防御式处理保持一致:尽量不让 None 向下游传播
165
+ from clang import cindex as _ci # type: ignore
166
+ cindex = _ci
167
+
168
+ # 预检 Index 创建
169
+ try:
170
+ _ = cindex.Index.create()
171
+ except Exception as e:
172
+ raise RuntimeError(f"libclang 初始化失败: {e}")
173
+
174
+ # 逐层向上自动查找 compile_commands.json,构建参数映射
175
+ cc_args_map = _resolve_compile_args_map(file_list)
176
+
177
+ # 收集唯一函数名(优先限定名)
178
+ names: Set[str] = set()
179
+
180
+ for f in file_list:
181
+ # 优先使用 compile_commands 的精确参数;若无则提供基础 -I 与头文件语言选项
182
+ base_args = cc_args_map.get(str(f), ["-I", str(f.parent)])
183
+ args = _ensure_lang_header_args(f, base_args)
184
+ try:
185
+ fn_names = _scan_header_for_names(cindex, f, args)
186
+ except Exception:
187
+ # 回退到无参数解析(仍添加语言选项)
188
+ try:
189
+ fn_names = _scan_header_for_names(cindex, f, _ensure_lang_header_args(f, []))
190
+ except Exception as e2:
191
+ print(f"[c2rust-collector] 解析失败,已跳过 {f}: {e2}")
192
+ continue
193
+
194
+ for label in fn_names:
195
+ if label:
196
+ names.add(label.strip())
197
+
198
+ # 写出结果
199
+ out_path = Path(out_path)
200
+ out_path.parent.mkdir(parents=True, exist_ok=True)
201
+ try:
202
+ with out_path.open("w", encoding="utf-8") as fo:
203
+ for nm in sorted(names):
204
+ fo.write(nm + "\n")
205
+ except Exception as e:
206
+ raise RuntimeError(f"写入输出文件失败: {out_path}: {e}")
207
+
208
+ print(f"[c2rust-collector] 已收集到 {len(names)} 个函数名(来自头文件) -> {out_path}")
209
+ return out_path