jarvis-ai-assistant 0.7.0__py3-none-any.whl → 0.7.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- jarvis/__init__.py +1 -1
- jarvis/jarvis_agent/__init__.py +243 -139
- jarvis/jarvis_agent/agent_manager.py +5 -10
- jarvis/jarvis_agent/builtin_input_handler.py +2 -6
- jarvis/jarvis_agent/config_editor.py +2 -7
- jarvis/jarvis_agent/event_bus.py +82 -12
- jarvis/jarvis_agent/file_context_handler.py +265 -15
- jarvis/jarvis_agent/file_methodology_manager.py +3 -4
- jarvis/jarvis_agent/jarvis.py +113 -98
- jarvis/jarvis_agent/language_extractors/__init__.py +57 -0
- jarvis/jarvis_agent/language_extractors/c_extractor.py +21 -0
- jarvis/jarvis_agent/language_extractors/cpp_extractor.py +21 -0
- jarvis/jarvis_agent/language_extractors/go_extractor.py +21 -0
- jarvis/jarvis_agent/language_extractors/java_extractor.py +84 -0
- jarvis/jarvis_agent/language_extractors/javascript_extractor.py +79 -0
- jarvis/jarvis_agent/language_extractors/python_extractor.py +21 -0
- jarvis/jarvis_agent/language_extractors/rust_extractor.py +21 -0
- jarvis/jarvis_agent/language_extractors/typescript_extractor.py +84 -0
- jarvis/jarvis_agent/language_support_info.py +486 -0
- jarvis/jarvis_agent/main.py +6 -12
- jarvis/jarvis_agent/memory_manager.py +7 -16
- jarvis/jarvis_agent/methodology_share_manager.py +10 -16
- jarvis/jarvis_agent/prompt_manager.py +1 -1
- jarvis/jarvis_agent/prompts.py +193 -171
- jarvis/jarvis_agent/protocols.py +8 -12
- jarvis/jarvis_agent/run_loop.py +77 -14
- jarvis/jarvis_agent/session_manager.py +2 -3
- jarvis/jarvis_agent/share_manager.py +12 -21
- jarvis/jarvis_agent/shell_input_handler.py +1 -2
- jarvis/jarvis_agent/task_analyzer.py +26 -4
- jarvis/jarvis_agent/task_manager.py +11 -27
- jarvis/jarvis_agent/tool_executor.py +2 -3
- jarvis/jarvis_agent/tool_share_manager.py +12 -24
- jarvis/jarvis_agent/web_server.py +55 -20
- jarvis/jarvis_c2rust/__init__.py +5 -5
- jarvis/jarvis_c2rust/cli.py +461 -499
- jarvis/jarvis_c2rust/collector.py +45 -53
- jarvis/jarvis_c2rust/constants.py +26 -0
- jarvis/jarvis_c2rust/library_replacer.py +264 -132
- jarvis/jarvis_c2rust/llm_module_agent.py +162 -190
- jarvis/jarvis_c2rust/loaders.py +207 -0
- jarvis/jarvis_c2rust/models.py +28 -0
- jarvis/jarvis_c2rust/optimizer.py +1592 -395
- jarvis/jarvis_c2rust/transpiler.py +1722 -1064
- jarvis/jarvis_c2rust/utils.py +385 -0
- jarvis/jarvis_code_agent/build_validation_config.py +2 -3
- jarvis/jarvis_code_agent/code_agent.py +394 -320
- jarvis/jarvis_code_agent/code_analyzer/__init__.py +3 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/base.py +4 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/cmake.py +17 -2
- jarvis/jarvis_code_agent/code_analyzer/build_validator/fallback.py +3 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/go.py +36 -4
- jarvis/jarvis_code_agent/code_analyzer/build_validator/java_gradle.py +9 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/java_maven.py +9 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/makefile.py +12 -1
- jarvis/jarvis_code_agent/code_analyzer/build_validator/nodejs.py +22 -5
- jarvis/jarvis_code_agent/code_analyzer/build_validator/python.py +57 -32
- jarvis/jarvis_code_agent/code_analyzer/build_validator/rust.py +62 -6
- jarvis/jarvis_code_agent/code_analyzer/build_validator/validator.py +8 -9
- jarvis/jarvis_code_agent/code_analyzer/context_manager.py +290 -5
- jarvis/jarvis_code_agent/code_analyzer/language_support.py +21 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/__init__.py +21 -3
- jarvis/jarvis_code_agent/code_analyzer/languages/c_cpp_language.py +72 -4
- jarvis/jarvis_code_agent/code_analyzer/languages/go_language.py +35 -3
- jarvis/jarvis_code_agent/code_analyzer/languages/java_language.py +212 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/javascript_language.py +254 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/python_language.py +52 -2
- jarvis/jarvis_code_agent/code_analyzer/languages/rust_language.py +73 -1
- jarvis/jarvis_code_agent/code_analyzer/languages/typescript_language.py +280 -0
- jarvis/jarvis_code_agent/code_analyzer/llm_context_recommender.py +306 -152
- jarvis/jarvis_code_agent/code_analyzer/structured_code.py +556 -0
- jarvis/jarvis_code_agent/code_analyzer/symbol_extractor.py +193 -18
- jarvis/jarvis_code_agent/code_analyzer/tree_sitter_extractor.py +18 -8
- jarvis/jarvis_code_agent/lint.py +258 -27
- jarvis/jarvis_code_agent/utils.py +0 -1
- jarvis/jarvis_code_analysis/code_review.py +19 -24
- jarvis/jarvis_data/config_schema.json +53 -26
- jarvis/jarvis_git_squash/main.py +4 -5
- jarvis/jarvis_git_utils/git_commiter.py +44 -49
- jarvis/jarvis_mcp/sse_mcp_client.py +20 -27
- jarvis/jarvis_mcp/stdio_mcp_client.py +11 -12
- jarvis/jarvis_mcp/streamable_mcp_client.py +15 -14
- jarvis/jarvis_memory_organizer/memory_organizer.py +55 -74
- jarvis/jarvis_methodology/main.py +32 -48
- jarvis/jarvis_multi_agent/__init__.py +79 -61
- jarvis/jarvis_multi_agent/main.py +3 -7
- jarvis/jarvis_platform/base.py +469 -199
- jarvis/jarvis_platform/human.py +7 -8
- jarvis/jarvis_platform/kimi.py +30 -36
- jarvis/jarvis_platform/openai.py +65 -27
- jarvis/jarvis_platform/registry.py +26 -10
- jarvis/jarvis_platform/tongyi.py +24 -25
- jarvis/jarvis_platform/yuanbao.py +31 -42
- jarvis/jarvis_platform_manager/main.py +66 -77
- jarvis/jarvis_platform_manager/service.py +8 -13
- jarvis/jarvis_rag/cli.py +49 -51
- jarvis/jarvis_rag/embedding_manager.py +13 -18
- jarvis/jarvis_rag/llm_interface.py +8 -9
- jarvis/jarvis_rag/query_rewriter.py +10 -21
- jarvis/jarvis_rag/rag_pipeline.py +24 -27
- jarvis/jarvis_rag/reranker.py +4 -5
- jarvis/jarvis_rag/retriever.py +28 -30
- jarvis/jarvis_sec/__init__.py +220 -3520
- jarvis/jarvis_sec/agents.py +143 -0
- jarvis/jarvis_sec/analysis.py +276 -0
- jarvis/jarvis_sec/cli.py +29 -6
- jarvis/jarvis_sec/clustering.py +1439 -0
- jarvis/jarvis_sec/file_manager.py +427 -0
- jarvis/jarvis_sec/parsers.py +73 -0
- jarvis/jarvis_sec/prompts.py +268 -0
- jarvis/jarvis_sec/report.py +83 -4
- jarvis/jarvis_sec/review.py +453 -0
- jarvis/jarvis_sec/utils.py +499 -0
- jarvis/jarvis_sec/verification.py +848 -0
- jarvis/jarvis_sec/workflow.py +7 -0
- jarvis/jarvis_smart_shell/main.py +38 -87
- jarvis/jarvis_stats/cli.py +1 -1
- jarvis/jarvis_stats/stats.py +7 -7
- jarvis/jarvis_stats/storage.py +15 -21
- jarvis/jarvis_tools/clear_memory.py +3 -20
- jarvis/jarvis_tools/cli/main.py +20 -23
- jarvis/jarvis_tools/edit_file.py +1066 -0
- jarvis/jarvis_tools/execute_script.py +42 -21
- jarvis/jarvis_tools/file_analyzer.py +6 -9
- jarvis/jarvis_tools/generate_new_tool.py +11 -20
- jarvis/jarvis_tools/lsp_client.py +1552 -0
- jarvis/jarvis_tools/methodology.py +2 -3
- jarvis/jarvis_tools/read_code.py +1525 -87
- jarvis/jarvis_tools/read_symbols.py +2 -3
- jarvis/jarvis_tools/read_webpage.py +7 -10
- jarvis/jarvis_tools/registry.py +370 -181
- jarvis/jarvis_tools/retrieve_memory.py +20 -19
- jarvis/jarvis_tools/rewrite_file.py +105 -0
- jarvis/jarvis_tools/save_memory.py +3 -15
- jarvis/jarvis_tools/search_web.py +3 -7
- jarvis/jarvis_tools/sub_agent.py +17 -6
- jarvis/jarvis_tools/sub_code_agent.py +14 -16
- jarvis/jarvis_tools/virtual_tty.py +54 -32
- jarvis/jarvis_utils/clipboard.py +7 -10
- jarvis/jarvis_utils/config.py +98 -63
- jarvis/jarvis_utils/embedding.py +5 -5
- jarvis/jarvis_utils/fzf.py +8 -8
- jarvis/jarvis_utils/git_utils.py +81 -67
- jarvis/jarvis_utils/input.py +24 -49
- jarvis/jarvis_utils/jsonnet_compat.py +465 -0
- jarvis/jarvis_utils/methodology.py +33 -35
- jarvis/jarvis_utils/utils.py +245 -202
- {jarvis_ai_assistant-0.7.0.dist-info → jarvis_ai_assistant-0.7.8.dist-info}/METADATA +205 -70
- jarvis_ai_assistant-0.7.8.dist-info/RECORD +218 -0
- jarvis/jarvis_agent/edit_file_handler.py +0 -584
- jarvis/jarvis_agent/rewrite_file_handler.py +0 -141
- jarvis/jarvis_agent/task_planner.py +0 -496
- jarvis/jarvis_platform/ai8.py +0 -332
- jarvis/jarvis_tools/ask_user.py +0 -54
- jarvis_ai_assistant-0.7.0.dist-info/RECORD +0 -192
- {jarvis_ai_assistant-0.7.0.dist-info → jarvis_ai_assistant-0.7.8.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.7.0.dist-info → jarvis_ai_assistant-0.7.8.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.7.0.dist-info → jarvis_ai_assistant-0.7.8.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.7.0.dist-info → jarvis_ai_assistant-0.7.8.dist-info}/top_level.txt +0 -0
|
@@ -3,24 +3,25 @@
|
|
|
3
3
|
LLM 驱动的 Rust Crate 模块规划 Agent
|
|
4
4
|
|
|
5
5
|
目标:
|
|
6
|
-
- 复用 scanner 中的 find_root_function_ids
|
|
7
|
-
- 通过 jarvis_agent.Agent 调用 LLM,基于上下文生成 Rust crate 的目录规划(
|
|
6
|
+
- 复用 scanner 中的 find_root_function_ids 与调用图信息,构造"以根函数为起点"的上下文
|
|
7
|
+
- 通过 jarvis_agent.Agent 调用 LLM,基于上下文生成 Rust crate 的目录规划(JSON)
|
|
8
8
|
|
|
9
9
|
设计要点:
|
|
10
10
|
- 与现有 scanner/cli 解耦,最小侵入新增模块
|
|
11
11
|
- 使用 jarvis_agent.Agent 的平台与系统提示管理能力,但不走完整工具循环,直接进行一次性对话生成
|
|
12
|
-
- 对输出格式进行强约束:仅输出
|
|
12
|
+
- 对输出格式进行强约束:仅输出 JSON,无解释文本
|
|
13
13
|
|
|
14
14
|
用法:
|
|
15
|
-
from jarvis.jarvis_c2rust.llm_module_agent import
|
|
16
|
-
print(
|
|
15
|
+
from jarvis.jarvis_c2rust.llm_module_agent import plan_crate_json_llm
|
|
16
|
+
print(plan_crate_json_llm(project_root="."))
|
|
17
17
|
|
|
18
18
|
CLI 集成建议:
|
|
19
|
-
可在 jarvis_c2rust/cli.py 中新增 llm-plan 子命令调用本模块的
|
|
19
|
+
可在 jarvis_c2rust/cli.py 中新增 llm-plan 子命令调用本模块的 plan_crate_json_llm(已独立封装,便于后续补充)
|
|
20
20
|
"""
|
|
21
21
|
|
|
22
22
|
from __future__ import annotations
|
|
23
23
|
|
|
24
|
+
from jarvis.jarvis_utils.jsonnet_compat import loads as json_loads
|
|
24
25
|
import json
|
|
25
26
|
# removed sqlite3 (migrated to JSONL/JSON)
|
|
26
27
|
from dataclasses import dataclass
|
|
@@ -111,8 +112,8 @@ class _GraphLoader:
|
|
|
111
112
|
if not line:
|
|
112
113
|
continue
|
|
113
114
|
try:
|
|
114
|
-
obj =
|
|
115
|
-
except
|
|
115
|
+
obj = json_loads(line)
|
|
116
|
+
except Exception:
|
|
116
117
|
# 跳过无效的 JSON 行,但记录以便调试
|
|
117
118
|
continue
|
|
118
119
|
# 不区分函数与类型,统一处理 symbols.jsonl 中的所有记录
|
|
@@ -301,7 +302,7 @@ def _resolve_created_dir(target_root: Union[Path, str]) -> Path:
|
|
|
301
302
|
|
|
302
303
|
class LLMRustCratePlannerAgent:
|
|
303
304
|
"""
|
|
304
|
-
使用 jarvis_agent.Agent 调用 LLM 来生成 Rust crate 规划(
|
|
305
|
+
使用 jarvis_agent.Agent 调用 LLM 来生成 Rust crate 规划(JSON)。
|
|
305
306
|
"""
|
|
306
307
|
|
|
307
308
|
def __init__(
|
|
@@ -318,6 +319,36 @@ class LLMRustCratePlannerAgent:
|
|
|
318
319
|
)
|
|
319
320
|
self.llm_group = llm_group
|
|
320
321
|
self.loader = _GraphLoader(self.db_path, self.project_root)
|
|
322
|
+
# 读取附加说明
|
|
323
|
+
self.additional_notes = self._load_additional_notes()
|
|
324
|
+
|
|
325
|
+
def _load_additional_notes(self) -> str:
|
|
326
|
+
"""从配置文件加载附加说明"""
|
|
327
|
+
try:
|
|
328
|
+
from jarvis.jarvis_c2rust.constants import CONFIG_JSON
|
|
329
|
+
config_path = self.project_root / ".jarvis" / "c2rust" / CONFIG_JSON
|
|
330
|
+
if config_path.exists():
|
|
331
|
+
with config_path.open("r", encoding="utf-8") as f:
|
|
332
|
+
config = json.load(f)
|
|
333
|
+
if isinstance(config, dict):
|
|
334
|
+
return str(config.get("additional_notes", "") or "").strip()
|
|
335
|
+
except Exception:
|
|
336
|
+
pass
|
|
337
|
+
return ""
|
|
338
|
+
|
|
339
|
+
def _append_additional_notes(self, prompt: str) -> str:
|
|
340
|
+
"""
|
|
341
|
+
在提示词末尾追加附加说明(如果存在)。
|
|
342
|
+
|
|
343
|
+
Args:
|
|
344
|
+
prompt: 原始提示词
|
|
345
|
+
|
|
346
|
+
Returns:
|
|
347
|
+
追加了附加说明的提示词
|
|
348
|
+
"""
|
|
349
|
+
if self.additional_notes and self.additional_notes.strip():
|
|
350
|
+
return prompt + "\n\n" + "【附加说明(用户自定义)】\n" + self.additional_notes.strip()
|
|
351
|
+
return prompt
|
|
321
352
|
|
|
322
353
|
def _crate_name(self) -> str:
|
|
323
354
|
"""
|
|
@@ -366,7 +397,7 @@ class LLMRustCratePlannerAgent:
|
|
|
366
397
|
- 跳过无 roots 标签的 residual 步骤(仅保留明确 root 的上下文)
|
|
367
398
|
- 若最终未收集到任何 root 组,则回退为单组 'project',包含所有 items 的函数名集合
|
|
368
399
|
"""
|
|
369
|
-
import
|
|
400
|
+
from jarvis.jarvis_utils.jsonnet_compat import loads as json_loads
|
|
370
401
|
order_path = self._order_path()
|
|
371
402
|
if not order_path.exists():
|
|
372
403
|
raise FileNotFoundError(f"未找到 translation_order.jsonl: {order_path}")
|
|
@@ -398,8 +429,8 @@ class LLMRustCratePlannerAgent:
|
|
|
398
429
|
if not line:
|
|
399
430
|
continue
|
|
400
431
|
try:
|
|
401
|
-
obj =
|
|
402
|
-
except
|
|
432
|
+
obj = json_loads(line)
|
|
433
|
+
except Exception:
|
|
403
434
|
continue
|
|
404
435
|
|
|
405
436
|
roots = obj.get("roots") or []
|
|
@@ -453,21 +484,22 @@ class LLMRustCratePlannerAgent:
|
|
|
453
484
|
ensure_ascii=False,
|
|
454
485
|
indent=2,
|
|
455
486
|
)
|
|
456
|
-
|
|
457
|
-
下面提供了项目的调用图上下文(JSON),请先通读理解,不要输出任何规划或
|
|
487
|
+
prompt = f"""
|
|
488
|
+
下面提供了项目的调用图上下文(JSON),请先通读理解,不要输出任何规划或JSON内容:
|
|
458
489
|
<context>
|
|
459
490
|
{context_json}
|
|
460
491
|
</context>
|
|
461
492
|
|
|
462
493
|
如果已准备好进入总结阶段以生成完整输出,请仅输出:<!!!COMPLETE!!!>
|
|
463
494
|
""".strip()
|
|
495
|
+
return self._append_additional_notes(prompt)
|
|
464
496
|
|
|
465
497
|
def _build_system_prompt(self) -> str:
|
|
466
498
|
"""
|
|
467
499
|
系统提示:描述如何基于依赖关系进行 crate 规划的原则(不涉及对话流程或输出方式)
|
|
468
500
|
"""
|
|
469
501
|
crate_name = self._crate_name()
|
|
470
|
-
|
|
502
|
+
prompt = (
|
|
471
503
|
"你是资深 Rust 架构师。任务:根据给定的函数级调用关系(仅包含 root_function 及其可达的函数名列表),为目标项目规划合理的 Rust crate 结构。\n"
|
|
472
504
|
"\n"
|
|
473
505
|
"规划原则:\n"
|
|
@@ -487,14 +519,15 @@ class LLMRustCratePlannerAgent:
|
|
|
487
519
|
" * 多可执行仅在确有多个清晰入口时才使用 src/bin/<name>.rs;每个 bin 文件仅做入口,尽量调用库;\n"
|
|
488
520
|
" * 二进制命名:<name> 使用小写下划线,体现入口意图,避免与模块/文件重名。\n"
|
|
489
521
|
)
|
|
522
|
+
return self._append_additional_notes(prompt)
|
|
490
523
|
|
|
491
524
|
def _build_summary_prompt(self, roots_context: List[Dict[str, Any]]) -> str:
|
|
492
525
|
"""
|
|
493
|
-
总结阶段:只输出目录结构的
|
|
526
|
+
总结阶段:只输出目录结构的 JSON。
|
|
494
527
|
要求:
|
|
495
528
|
- 仅输出一个 <PROJECT> 块
|
|
496
|
-
- <PROJECT> 与 </PROJECT> 之间必须是可解析的
|
|
497
|
-
-
|
|
529
|
+
- <PROJECT> 与 </PROJECT> 之间必须是可解析的 JSON 数组
|
|
530
|
+
- 目录以对象表示,键为 '目录名/',值为子项数组;文件为字符串
|
|
498
531
|
- 块外不得有任何字符(包括空行、注释、Markdown、解释文字、schema等)
|
|
499
532
|
- 不要输出 crate 名称或其他多余字段
|
|
500
533
|
"""
|
|
@@ -504,10 +537,11 @@ class LLMRustCratePlannerAgent:
|
|
|
504
537
|
输出规范:
|
|
505
538
|
- 只输出一个 <PROJECT> 块
|
|
506
539
|
- 块外不得有任何字符(包括空行、注释、Markdown 等)
|
|
507
|
-
- 块内必须是
|
|
508
|
-
-
|
|
509
|
-
- 文件为字符串项(例如
|
|
540
|
+
- 块内必须是 JSON 数组:
|
|
541
|
+
- 目录项使用对象表示,键为 '<name>/',值为子项数组
|
|
542
|
+
- 文件为字符串项(例如 "lib.rs")
|
|
510
543
|
- 不要创建与入口无关的占位文件
|
|
544
|
+
- 支持jsonnet语法(如尾随逗号、注释、||| 或 ``` 分隔符多行字符串等)
|
|
511
545
|
""".strip()
|
|
512
546
|
if has_main:
|
|
513
547
|
entry_rule = f"""
|
|
@@ -516,13 +550,21 @@ class LLMRustCratePlannerAgent:
|
|
|
516
550
|
- 不要包含 src/main.rs;
|
|
517
551
|
- 必须包含 src/bin/{crate_name}.rs,作为唯一可执行入口(仅做入口,调用库逻辑);
|
|
518
552
|
- 如无明确多个入口,不要创建额外 bin 文件。
|
|
519
|
-
|
|
553
|
+
正确示例(JSON格式):
|
|
520
554
|
<PROJECT>
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
555
|
+
[
|
|
556
|
+
"Cargo.toml",
|
|
557
|
+
{{
|
|
558
|
+
"src/": [
|
|
559
|
+
"lib.rs",
|
|
560
|
+
{{
|
|
561
|
+
"bin/": [
|
|
562
|
+
"{crate_name}.rs"
|
|
563
|
+
]
|
|
564
|
+
}}
|
|
565
|
+
]
|
|
566
|
+
}}
|
|
567
|
+
]
|
|
526
568
|
</PROJECT>
|
|
527
569
|
""".strip()
|
|
528
570
|
else:
|
|
@@ -531,28 +573,34 @@ class LLMRustCratePlannerAgent:
|
|
|
531
573
|
- 必须包含 src/lib.rs;
|
|
532
574
|
- 不要包含 src/main.rs;
|
|
533
575
|
- 不要包含 src/bin/ 目录。
|
|
534
|
-
|
|
576
|
+
正确示例(JSON格式):
|
|
535
577
|
<PROJECT>
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
578
|
+
[
|
|
579
|
+
"Cargo.toml",
|
|
580
|
+
{
|
|
581
|
+
"src/": [
|
|
582
|
+
"lib.rs"
|
|
583
|
+
]
|
|
584
|
+
}
|
|
585
|
+
]
|
|
539
586
|
</PROJECT>
|
|
540
587
|
""".strip()
|
|
541
588
|
guidance = f"{guidance_common}\n{entry_rule}"
|
|
542
|
-
|
|
543
|
-
请基于之前对话中已提供的<context>信息,生成总结输出(项目目录结构的
|
|
589
|
+
prompt = f"""
|
|
590
|
+
请基于之前对话中已提供的<context>信息,生成总结输出(项目目录结构的 JSON)。严格遵循以下要求:
|
|
544
591
|
|
|
545
592
|
{guidance}
|
|
546
593
|
|
|
547
594
|
你的输出必须仅包含以下单个块(用项目的真实目录结构替换块内内容):
|
|
548
595
|
<PROJECT>
|
|
549
|
-
|
|
596
|
+
[...]
|
|
550
597
|
</PROJECT>
|
|
551
598
|
""".strip()
|
|
599
|
+
return self._append_additional_notes(prompt)
|
|
552
600
|
|
|
553
|
-
def
|
|
601
|
+
def _extract_json_from_project(self, text: str) -> str:
|
|
554
602
|
"""
|
|
555
|
-
从 <PROJECT> 块中提取内容作为最终
|
|
603
|
+
从 <PROJECT> 块中提取内容作为最终 JSON;若未匹配,返回原文本(兜底)。
|
|
556
604
|
"""
|
|
557
605
|
if not isinstance(text, str) or not text:
|
|
558
606
|
return ""
|
|
@@ -574,7 +622,7 @@ class LLMRustCratePlannerAgent:
|
|
|
574
622
|
返回 (是否通过, 错误原因)
|
|
575
623
|
"""
|
|
576
624
|
if not isinstance(entries, list) or not entries:
|
|
577
|
-
return False, "
|
|
625
|
+
return False, "JSON 不可解析或为空数组"
|
|
578
626
|
|
|
579
627
|
# 提取 src 目录子项
|
|
580
628
|
src_children: Optional[List[Any]] = None
|
|
@@ -644,13 +692,13 @@ class LLMRustCratePlannerAgent:
|
|
|
644
692
|
"\n\n[格式校验失败,必须重试]\n"
|
|
645
693
|
f"- 失败原因:{error_reason}\n"
|
|
646
694
|
"- 请严格遵循上述“输出规范”与“入口约定”,重新输出;\n"
|
|
647
|
-
"- 仅输出一个 <PROJECT> 块,块内为可解析的
|
|
695
|
+
"- 仅输出一个 <PROJECT> 块,块内为可解析的 JSON 数组;块外不得有任何字符。\n"
|
|
648
696
|
)
|
|
649
697
|
return base_summary_prompt + feedback
|
|
650
698
|
|
|
651
|
-
def
|
|
699
|
+
def _get_project_json_text(self, max_retries: int = 10) -> str:
|
|
652
700
|
"""
|
|
653
|
-
执行主流程并返回原始 <PROJECT>
|
|
701
|
+
执行主流程并返回原始 <PROJECT> JSON 文本,不进行解析。
|
|
654
702
|
若格式校验失败,将自动重试,直到满足为止或达到最大重试次数。
|
|
655
703
|
|
|
656
704
|
Args:
|
|
@@ -687,23 +735,22 @@ class LLMRustCratePlannerAgent:
|
|
|
687
735
|
summary_prompt=summary_prompt,
|
|
688
736
|
need_summary=True,
|
|
689
737
|
auto_complete=True,
|
|
690
|
-
use_tools=["execute_script", "read_code"
|
|
691
|
-
plan=False, # 关闭内置任务规划
|
|
738
|
+
use_tools=["execute_script", "read_code"],
|
|
692
739
|
non_interactive=True, # 非交互
|
|
693
740
|
use_methodology=False,
|
|
694
741
|
use_analysis=False,
|
|
695
742
|
)
|
|
696
743
|
|
|
697
|
-
# 进入主循环:第一轮仅输出 <!!!COMPLETE!!!> 触发自动完成;随后 summary 输出 <PROJECT> 块(仅含
|
|
744
|
+
# 进入主循环:第一轮仅输出 <!!!COMPLETE!!!> 触发自动完成;随后 summary 输出 <PROJECT> 块(仅含 JSON)
|
|
698
745
|
if use_direct_model:
|
|
699
746
|
# 格式校验失败后,直接调用模型接口
|
|
700
747
|
# 构造包含摘要提示词和具体错误信息的完整提示
|
|
701
748
|
error_guidance = ""
|
|
702
749
|
if last_error and last_error != "未知错误":
|
|
703
|
-
if "
|
|
704
|
-
error_guidance = f"\n\n**格式错误详情(请根据以下错误修复输出格式):**\n- {last_error}\n\n请确保输出的
|
|
750
|
+
if "JSON解析失败" in last_error:
|
|
751
|
+
error_guidance = f"\n\n**格式错误详情(请根据以下错误修复输出格式):**\n- {last_error}\n\n请确保输出的JSON格式正确,包括正确的引号、逗号、大括号等。仅输出一个 <PROJECT> 块,块内仅包含 JSON 格式的项目结构定义。支持jsonnet语法(如尾随逗号、注释、||| 或 ``` 分隔符多行字符串等)。"
|
|
705
752
|
else:
|
|
706
|
-
error_guidance = f"\n\n**格式错误详情(请根据以下错误修复输出格式):**\n- {last_error}\n\n请确保输出格式正确:仅输出一个 <PROJECT> 块,块内仅包含
|
|
753
|
+
error_guidance = f"\n\n**格式错误详情(请根据以下错误修复输出格式):**\n- {last_error}\n\n请确保输出格式正确:仅输出一个 <PROJECT> 块,块内仅包含 JSON 格式的项目结构定义。支持jsonnet语法(如尾随逗号、注释、||| 或 ``` 分隔符多行字符串等)。"
|
|
707
754
|
|
|
708
755
|
full_prompt = f"{user_prompt}{error_guidance}\n\n{summary_prompt}"
|
|
709
756
|
try:
|
|
@@ -717,20 +764,20 @@ class LLMRustCratePlannerAgent:
|
|
|
717
764
|
summary_output = agent.run(user_prompt) # type: ignore
|
|
718
765
|
|
|
719
766
|
project_text = str(summary_output) if summary_output is not None else ""
|
|
720
|
-
|
|
767
|
+
json_text = self._extract_json_from_project(project_text)
|
|
721
768
|
|
|
722
769
|
# 尝试解析并校验
|
|
723
|
-
entries,
|
|
724
|
-
if
|
|
725
|
-
#
|
|
726
|
-
last_error =
|
|
770
|
+
entries, parse_error_json = _parse_project_json_entries(json_text)
|
|
771
|
+
if parse_error_json:
|
|
772
|
+
# JSON解析失败,记录错误并重试
|
|
773
|
+
last_error = parse_error_json
|
|
727
774
|
use_direct_model = True # 格式校验失败,后续重试使用直接模型调用
|
|
728
|
-
print(f"[c2rust-llm-planner]
|
|
775
|
+
print(f"[c2rust-llm-planner] JSON解析失败: {parse_error_json}")
|
|
729
776
|
continue
|
|
730
777
|
|
|
731
778
|
ok, reason = self._validate_project_entries(entries)
|
|
732
779
|
if ok:
|
|
733
|
-
return
|
|
780
|
+
return json_text
|
|
734
781
|
else:
|
|
735
782
|
last_error = reason
|
|
736
783
|
use_direct_model = True # 格式校验失败,后续重试使用直接模型调用
|
|
@@ -741,35 +788,35 @@ class LLMRustCratePlannerAgent:
|
|
|
741
788
|
f"最后一次错误: {last_error}"
|
|
742
789
|
)
|
|
743
790
|
|
|
744
|
-
def
|
|
791
|
+
def plan_crate_json_with_project(self) -> List[Any]:
|
|
745
792
|
"""
|
|
746
|
-
执行主流程并返回解析后的
|
|
793
|
+
执行主流程并返回解析后的 JSON 对象(列表):
|
|
747
794
|
- 列表项:
|
|
748
795
|
* 字符串:文件,如 "lib.rs"
|
|
749
|
-
* 字典:目录及其子项,如 {"src": [ ... ]}
|
|
796
|
+
* 字典:目录及其子项,如 {"src/": [ ... ]}
|
|
750
797
|
"""
|
|
751
|
-
|
|
752
|
-
|
|
798
|
+
json_text = self._get_project_json_text()
|
|
799
|
+
json_entries, parse_error = _parse_project_json_entries(json_text)
|
|
753
800
|
if parse_error:
|
|
754
|
-
raise RuntimeError(f"
|
|
755
|
-
return
|
|
801
|
+
raise RuntimeError(f"JSON解析失败: {parse_error}")
|
|
802
|
+
return json_entries
|
|
756
803
|
|
|
757
|
-
def
|
|
804
|
+
def plan_crate_json_text(self) -> str:
|
|
758
805
|
"""
|
|
759
|
-
执行主流程但返回原始 <PROJECT>
|
|
806
|
+
执行主流程但返回原始 <PROJECT> JSON 文本,不进行解析。
|
|
760
807
|
便于后续按原样应用目录结构,避免早期解析失败导致信息丢失。
|
|
761
808
|
"""
|
|
762
|
-
return self.
|
|
809
|
+
return self._get_project_json_text()
|
|
763
810
|
|
|
764
811
|
|
|
765
|
-
def
|
|
812
|
+
def plan_crate_json_text(
|
|
766
813
|
project_root: Union[Path, str] = ".",
|
|
767
814
|
db_path: Optional[Union[Path, str]] = None,
|
|
768
815
|
llm_group: Optional[str] = None,
|
|
769
816
|
skip_cleanup: bool = False,
|
|
770
817
|
) -> str:
|
|
771
818
|
"""
|
|
772
|
-
返回 LLM 生成的目录结构原始
|
|
819
|
+
返回 LLM 生成的目录结构原始 JSON 文本(来自 <PROJECT> 块)。
|
|
773
820
|
在规划前执行预清理并征询用户确认:删除将要生成的 crate 目录、当前目录的 Cargo.toml 工作区文件,以及 .jarvis/c2rust 下的 progress.json 与 symbol_map.jsonl。
|
|
774
821
|
用户不同意则退出程序。
|
|
775
822
|
当 skip_cleanup=True 时,跳过清理与确认(用于外层已处理的场景)。
|
|
@@ -777,15 +824,15 @@ def plan_crate_yaml_text(
|
|
|
777
824
|
# 若外层已处理清理确认,则跳过本函数的清理与确认(避免重复询问)
|
|
778
825
|
if skip_cleanup:
|
|
779
826
|
agent = LLMRustCratePlannerAgent(project_root=project_root, db_path=db_path, llm_group=llm_group)
|
|
780
|
-
return agent.
|
|
827
|
+
return agent.plan_crate_json_text()
|
|
781
828
|
|
|
782
829
|
_perform_pre_cleanup_for_planner(project_root)
|
|
783
830
|
|
|
784
831
|
agent = LLMRustCratePlannerAgent(project_root=project_root, db_path=db_path, llm_group=llm_group)
|
|
785
|
-
return agent.
|
|
832
|
+
return agent.plan_crate_json_text()
|
|
786
833
|
|
|
787
834
|
|
|
788
|
-
def
|
|
835
|
+
def plan_crate_json_llm(
|
|
789
836
|
project_root: Union[Path, str] = ".",
|
|
790
837
|
db_path: Optional[Union[Path, str]] = None,
|
|
791
838
|
skip_cleanup: bool = False,
|
|
@@ -799,135 +846,60 @@ def plan_crate_yaml_llm(
|
|
|
799
846
|
# 若外层已处理清理确认,则跳过本函数的清理与确认(避免重复询问)
|
|
800
847
|
if skip_cleanup:
|
|
801
848
|
agent = LLMRustCratePlannerAgent(project_root=project_root, db_path=db_path)
|
|
802
|
-
return agent.
|
|
849
|
+
return agent.plan_crate_json_with_project()
|
|
803
850
|
|
|
804
851
|
_perform_pre_cleanup_for_planner(project_root)
|
|
805
852
|
|
|
806
853
|
agent = LLMRustCratePlannerAgent(project_root=project_root, db_path=db_path)
|
|
807
|
-
return agent.
|
|
854
|
+
return agent.plan_crate_json_with_project()
|
|
808
855
|
|
|
809
856
|
|
|
810
|
-
def
|
|
857
|
+
def entries_to_json(entries: List[Any]) -> str:
|
|
811
858
|
"""
|
|
812
|
-
将解析后的 entries 列表序列化为
|
|
859
|
+
将解析后的 entries 列表序列化为 JSON 文本(目录使用对象表示,文件为字符串)
|
|
813
860
|
"""
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
lines.append(" " * indent + f"- {it}")
|
|
819
|
-
elif isinstance(it, dict) and len(it) == 1:
|
|
820
|
-
name, children = next(iter(it.items()))
|
|
821
|
-
name = str(name).rstrip("/")
|
|
822
|
-
lines.append(" " * indent + f"- {name}/:")
|
|
823
|
-
lines.extend(_entries_to_yaml(children or [], indent + 1))
|
|
824
|
-
return lines
|
|
825
|
-
|
|
826
|
-
return "\n".join(_entries_to_yaml(entries))
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
def _parse_project_yaml_entries_fallback(yaml_text: str) -> List[Any]:
|
|
861
|
+
return json.dumps(entries, ensure_ascii=False, indent=2)
|
|
862
|
+
|
|
863
|
+
|
|
864
|
+
def _parse_project_json_entries_fallback(json_text: str) -> List[Any]:
|
|
830
865
|
"""
|
|
831
|
-
Fallback 解析器:当
|
|
832
|
-
|
|
833
|
-
- 列表项以 "- " 开头
|
|
834
|
-
- 目录项以 "- <name>/:", 其子项为下一层缩进(+2 空格)的列表
|
|
835
|
-
- 文件项为 "- <filename>"
|
|
866
|
+
Fallback 解析器:当 jsonnet 解析失败时,尝试使用标准 json 解析。
|
|
867
|
+
注意:此函数主要用于兼容性,正常情况下应使用 jsonnet 解析。
|
|
836
868
|
"""
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
while idx < n and not lines[idx].lstrip().startswith("- "):
|
|
846
|
-
idx += 1
|
|
847
|
-
|
|
848
|
-
def parse_list(expected_indent: int) -> List[Any]:
|
|
849
|
-
nonlocal idx
|
|
850
|
-
items: List[Any] = []
|
|
851
|
-
while idx < n:
|
|
852
|
-
line = lines[idx]
|
|
853
|
-
if not line.strip():
|
|
854
|
-
idx += 1
|
|
855
|
-
continue
|
|
856
|
-
indent = leading_spaces(line)
|
|
857
|
-
if indent < expected_indent:
|
|
858
|
-
break
|
|
859
|
-
if not line.lstrip().startswith("- "):
|
|
860
|
-
break
|
|
861
|
-
|
|
862
|
-
# 去掉 "- "
|
|
863
|
-
content = line[indent + 2 :].strip()
|
|
864
|
-
|
|
865
|
-
# 目录项:以 ":" 结尾(形如 "src/:")
|
|
866
|
-
if content.endswith(":"):
|
|
867
|
-
key = content[:-1].strip()
|
|
868
|
-
idx += 1 # 消费当前目录行
|
|
869
|
-
children = parse_list(expected_indent + 2)
|
|
870
|
-
# 规范化目录键为以 "/" 结尾(apply 时会 rstrip("/"),二者均可)
|
|
871
|
-
if not str(key).endswith("/"):
|
|
872
|
-
key = f"{str(key).rstrip('/')}/"
|
|
873
|
-
items.append({key: children})
|
|
874
|
-
else:
|
|
875
|
-
# 文件项
|
|
876
|
-
items.append(content)
|
|
877
|
-
idx += 1
|
|
878
|
-
return items
|
|
879
|
-
|
|
880
|
-
base_indent = leading_spaces(lines[idx]) if idx < n else 0
|
|
881
|
-
return parse_list(base_indent)
|
|
869
|
+
try:
|
|
870
|
+
import json as std_json
|
|
871
|
+
data = std_json.loads(json_text)
|
|
872
|
+
if isinstance(data, list):
|
|
873
|
+
return data
|
|
874
|
+
return []
|
|
875
|
+
except Exception:
|
|
876
|
+
return []
|
|
882
877
|
|
|
883
878
|
|
|
884
|
-
def
|
|
879
|
+
def _parse_project_json_entries(json_text: str) -> Tuple[List[Any], Optional[str]]:
|
|
885
880
|
"""
|
|
886
|
-
使用
|
|
881
|
+
使用 jsonnet 解析 <PROJECT> 块中的目录结构 JSON 为列表结构:
|
|
887
882
|
- 文件项: 字符串,如 "lib.rs"
|
|
888
883
|
- 目录项: 字典,形如 {"src/": [ ... ]} 或 {"src": [ ... ]}
|
|
889
884
|
返回(解析结果, 错误信息)
|
|
890
885
|
如果解析成功,返回(data, None)
|
|
891
886
|
如果解析失败,返回([], 错误信息)
|
|
892
|
-
|
|
887
|
+
使用 jsonnet 解析,支持更宽松的 JSON 语法(如尾随逗号、注释等)。
|
|
893
888
|
"""
|
|
894
889
|
try:
|
|
895
|
-
import yaml # type: ignore
|
|
896
890
|
try:
|
|
897
|
-
data =
|
|
891
|
+
data = json_loads(json_text)
|
|
898
892
|
if isinstance(data, list):
|
|
899
893
|
return data, None
|
|
900
|
-
#
|
|
901
|
-
return [], f"
|
|
902
|
-
except
|
|
903
|
-
#
|
|
904
|
-
error_msg = f"
|
|
905
|
-
|
|
906
|
-
try:
|
|
907
|
-
fallback_result = _parse_project_yaml_entries_fallback(yaml_text)
|
|
908
|
-
return fallback_result, None # 回退解析器成功,不返回错误
|
|
909
|
-
except Exception:
|
|
910
|
-
return [], error_msg
|
|
911
|
-
except ImportError:
|
|
912
|
-
# PyYAML 未安装,使用回退解析器
|
|
913
|
-
try:
|
|
914
|
-
fallback_result = _parse_project_yaml_entries_fallback(yaml_text)
|
|
915
|
-
return fallback_result, None
|
|
916
|
-
except Exception as e:
|
|
917
|
-
return [], f"PyYAML 未安装且回退解析器失败: {str(e)}"
|
|
918
|
-
except Exception as e:
|
|
919
|
-
# 其他未知错误,回退到轻量解析器
|
|
920
|
-
try:
|
|
921
|
-
fallback_result = _parse_project_yaml_entries_fallback(yaml_text)
|
|
922
|
-
return fallback_result, None
|
|
923
|
-
except Exception:
|
|
924
|
-
return [], f"解析过程发生异常: {str(e)}"
|
|
925
|
-
# 回退
|
|
926
|
-
try:
|
|
927
|
-
fallback_result = _parse_project_yaml_entries_fallback(yaml_text)
|
|
928
|
-
return fallback_result, None
|
|
894
|
+
# 如果解析结果不是列表
|
|
895
|
+
return [], f"JSON 解析结果不是数组,而是 {type(data).__name__}"
|
|
896
|
+
except Exception as json_err:
|
|
897
|
+
# JSON 解析错误
|
|
898
|
+
error_msg = f"JSON 解析失败: {str(json_err)}"
|
|
899
|
+
return [], error_msg
|
|
929
900
|
except Exception as e:
|
|
930
|
-
|
|
901
|
+
# 其他未知错误
|
|
902
|
+
return [], f"解析过程发生异常: {str(e)}"
|
|
931
903
|
|
|
932
904
|
|
|
933
905
|
def _ensure_pub_mod_declarations(existing_text: str, child_mods: List[str]) -> str:
|
|
@@ -1024,7 +996,7 @@ def _apply_entries_with_mods(entries: List[Any], base_path: Path) -> None:
|
|
|
1024
996
|
|
|
1025
997
|
# 非 src 目录:
|
|
1026
998
|
# 为避免覆盖现有实现,当前阶段不创建或更新 mod.rs 内容。
|
|
1027
|
-
# 如需创建 mod.rs,应在
|
|
999
|
+
# 如需创建 mod.rs,应在 JSON 中显式指定为文件项;
|
|
1028
1000
|
# 如需补齐模块声明,将由后续的 CodeAgent 阶段根据目录结构自动补齐。
|
|
1029
1001
|
return
|
|
1030
1002
|
|
|
@@ -1049,15 +1021,15 @@ def _ensure_cargo_toml(base_dir: Path, package_name: str) -> None:
|
|
|
1049
1021
|
pass
|
|
1050
1022
|
|
|
1051
1023
|
|
|
1052
|
-
def
|
|
1024
|
+
def apply_project_structure_from_json(json_text: str, project_root: Union[Path, str] = ".") -> None:
|
|
1053
1025
|
"""
|
|
1054
|
-
基于 Agent 返回的 <PROJECT> 中的目录结构
|
|
1055
|
-
- project_root: 目标应用路径;当为 "."
|
|
1026
|
+
基于 Agent 返回的 <PROJECT> 中的目录结构 JSON,创建实际目录与文件(不在此阶段写入或更新任何 Rust 源文件内容)。
|
|
1027
|
+
- project_root: 目标应用路径;当为 "."(默认)时,将使用"父目录/当前目录名_rs"作为crate根目录
|
|
1056
1028
|
注意:模块声明(mod/pub mod)补齐将在后续的 CodeAgent 步骤中完成。按新策略不再创建或更新 workspace(构建直接在 crate 目录内进行)。
|
|
1057
1029
|
"""
|
|
1058
|
-
entries, parse_error =
|
|
1030
|
+
entries, parse_error = _parse_project_json_entries(json_text)
|
|
1059
1031
|
if parse_error:
|
|
1060
|
-
raise ValueError(f"
|
|
1032
|
+
raise ValueError(f"JSON解析失败: {parse_error}")
|
|
1061
1033
|
if not entries:
|
|
1062
1034
|
# 严格模式:解析失败直接报错并退出,由上层 CLI 捕获打印错误
|
|
1063
1035
|
raise ValueError("[c2rust-llm-planner] 从LLM输出解析目录结构失败。正在中止。")
|
|
@@ -1090,15 +1062,15 @@ def execute_llm_plan(
|
|
|
1090
1062
|
non_interactive: bool = True,
|
|
1091
1063
|
) -> List[Any]:
|
|
1092
1064
|
"""
|
|
1093
|
-
返回 LLM 生成的目录结构原始
|
|
1065
|
+
返回 LLM 生成的目录结构原始 JSON 文本(来自 <PROJECT> 块)。
|
|
1094
1066
|
不进行解析,便于后续按原样应用并在需要时使用更健壮的解析器处理。
|
|
1095
1067
|
"""
|
|
1096
1068
|
# execute_llm_plan 是顶层入口,需要执行清理(skip_cleanup=False)
|
|
1097
|
-
#
|
|
1098
|
-
|
|
1099
|
-
entries, parse_error =
|
|
1069
|
+
# plan_crate_json_text 内部会根据 skip_cleanup 决定是否执行清理
|
|
1070
|
+
json_text = plan_crate_json_text(llm_group=llm_group, skip_cleanup=False)
|
|
1071
|
+
entries, parse_error = _parse_project_json_entries(json_text)
|
|
1100
1072
|
if parse_error:
|
|
1101
|
-
raise ValueError(f"
|
|
1073
|
+
raise ValueError(f"JSON解析失败: {parse_error}")
|
|
1102
1074
|
if not entries:
|
|
1103
1075
|
raise ValueError("[c2rust-llm-planner] 从LLM输出解析目录结构失败。正在中止。")
|
|
1104
1076
|
|
|
@@ -1106,7 +1078,7 @@ def execute_llm_plan(
|
|
|
1106
1078
|
if apply:
|
|
1107
1079
|
target_root = crate_name if crate_name else "."
|
|
1108
1080
|
try:
|
|
1109
|
-
|
|
1081
|
+
apply_project_structure_from_json(json_text, project_root=target_root)
|
|
1110
1082
|
print("[c2rust-llm-planner] 项目结构已应用。")
|
|
1111
1083
|
except Exception as e:
|
|
1112
1084
|
print(f"[c2rust-llm-planner] 应用项目结构失败: {e}")
|
|
@@ -1217,7 +1189,7 @@ def execute_llm_plan(
|
|
|
1217
1189
|
print(f"[c2rust-llm-planner] 警告: 无法验证模型配置: {e}")
|
|
1218
1190
|
|
|
1219
1191
|
try:
|
|
1220
|
-
agent = CodeAgent(need_summary=False, non_interactive=non_interactive,
|
|
1192
|
+
agent = CodeAgent(need_summary=False, non_interactive=non_interactive, model_group=llm_group)
|
|
1221
1193
|
# 验证 agent 内部的模型配置
|
|
1222
1194
|
if hasattr(agent, 'model') and agent.model:
|
|
1223
1195
|
actual_model = getattr(agent.model, 'model_name', 'unknown')
|
|
@@ -1276,7 +1248,7 @@ def execute_llm_plan(
|
|
|
1276
1248
|
if llm_group:
|
|
1277
1249
|
print(f"[c2rust-llm-planner][iter={iter_count}] 使用模型组: {llm_group}")
|
|
1278
1250
|
try:
|
|
1279
|
-
repair_agent = CodeAgent(need_summary=False, non_interactive=non_interactive,
|
|
1251
|
+
repair_agent = CodeAgent(need_summary=False, non_interactive=non_interactive, model_group=llm_group)
|
|
1280
1252
|
repair_agent.run(repair_prompt, prefix=f"[c2rust-llm-planner][iter={iter_count}]", suffix="")
|
|
1281
1253
|
except Exception as e:
|
|
1282
1254
|
error_msg = str(e)
|
|
@@ -1289,12 +1261,12 @@ def execute_llm_plan(
|
|
|
1289
1261
|
# 恢复之前的工作目录
|
|
1290
1262
|
os.chdir(prev_cwd)
|
|
1291
1263
|
|
|
1292
|
-
# 3) 输出
|
|
1264
|
+
# 3) 输出 JSON 到文件(如指定),并返回解析后的 entries
|
|
1293
1265
|
if out is not None:
|
|
1294
1266
|
out_path = Path(out)
|
|
1295
1267
|
out_path.parent.mkdir(parents=True, exist_ok=True)
|
|
1296
1268
|
# 使用原始文本写出,便于可读
|
|
1297
|
-
out_path.write_text(
|
|
1298
|
-
print(f"[c2rust-llm-planner]
|
|
1269
|
+
out_path.write_text(json_text, encoding="utf-8")
|
|
1270
|
+
print(f"[c2rust-llm-planner] JSON 已写入: {out_path}")
|
|
1299
1271
|
|
|
1300
1272
|
return entries
|