autocoder-nano 0.1.28__py3-none-any.whl → 0.1.29__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.
@@ -1,6 +1,6 @@
1
1
  import time
2
2
 
3
- from loguru import logger
3
+ # from loguru import logger
4
4
 
5
5
  from autocoder_nano.edit.code.generate_editblock import CodeAutoGenerateEditBlock
6
6
  from autocoder_nano.edit.code.merge_editblock import CodeAutoMergeEditBlock
@@ -8,6 +8,10 @@ from autocoder_nano.index.entry import build_index_and_filter_files
8
8
  from autocoder_nano.llm_client import AutoLLM
9
9
  from autocoder_nano.llm_types import AutoCoderArgs
10
10
  from autocoder_nano.project import PyProject, SuffixProject
11
+ from autocoder_nano.utils.printer_utils import Printer
12
+
13
+
14
+ printer = Printer()
11
15
 
12
16
 
13
17
  class BaseAction:
@@ -39,13 +43,14 @@ class ActionPyProject(BaseAction):
39
43
  if self.args.execute and self.llm:
40
44
  content_length = self._get_content_length(content)
41
45
  if content_length > self.args.model_max_input_length:
42
- logger.warning(
43
- f"发送给模型的内容长度为 {content_length} 个 token(可能收集了过多文件),"
44
- f"已超过最大输入长度限制 {self.args.model_max_input_length}"
46
+ printer.print_text(
47
+ f"发送给模型的内容长度为 {content_length} 个 token(可能收集了过多文件),"
48
+ f"已超过最大输入长度限制 {self.args.model_max_input_length}.",
49
+ style="yellow"
45
50
  )
46
51
 
47
52
  if self.args.execute:
48
- logger.info("正在自动生成代码...")
53
+ printer.print_text("正在自动生成代码...", style="green")
49
54
  start_time = time.time()
50
55
  # diff, strict_diff, editblock 是代码自动生成或合并的不同策略, 通常用于处理代码的变更或生成
51
56
  # diff 模式,基于差异生成代码,生成最小的变更集,适用于局部优化,代码重构
@@ -60,10 +65,10 @@ class ActionPyProject(BaseAction):
60
65
  generate_result = generate.multi_round_run(query=self.args.query, source_content=content)
61
66
  else:
62
67
  generate_result = generate.single_round_run(query=self.args.query, source_content=content)
63
- logger.info(f"代码生成完成,耗时 {time.time() - start_time:.2f} 秒")
68
+ printer.print_text(f"代码生成完毕,耗时 {time.time() - start_time:.2f} 秒", style="green")
64
69
 
65
70
  if self.args.auto_merge:
66
- logger.info("正在自动合并代码...")
71
+ printer.print_text("正在自动合并代码...", style="green")
67
72
  if self.args.auto_merge == "editblock":
68
73
  code_merge = CodeAutoMergeEditBlock(args=self.args, llm=self.llm)
69
74
  merge_result = code_merge.merge_code(generate_result=generate_result)
@@ -97,13 +102,14 @@ class ActionSuffixProject(BaseAction):
97
102
  if self.args.execute and self.llm:
98
103
  content_length = self._get_content_length(content)
99
104
  if content_length > self.args.model_max_input_length:
100
- logger.warning(
101
- f"发送给模型的内容长度为 {content_length} 个 token(可能收集了过多文件),"
102
- f"已超过最大输入长度限制 {self.args.model_max_input_length}"
105
+ printer.print_text(
106
+ f"发送给模型的内容长度为 {content_length} 个 token(可能收集了过多文件),"
107
+ f"已超过最大输入长度限制 {self.args.model_max_input_length}.",
108
+ style="yellow"
103
109
  )
104
110
 
105
111
  if self.args.execute:
106
- logger.info("正在自动生成代码...")
112
+ printer.print_text("正在自动生成代码...", style="green")
107
113
  start_time = time.time()
108
114
  # diff, strict_diff, editblock 是代码自动生成或合并的不同策略, 通常用于处理代码的变更或生成
109
115
  # diff 模式,基于差异生成代码,生成最小的变更集,适用于局部优化,代码重构
@@ -118,10 +124,10 @@ class ActionSuffixProject(BaseAction):
118
124
  generate_result = generate.multi_round_run(query=self.args.query, source_content=content)
119
125
  else:
120
126
  generate_result = generate.single_round_run(query=self.args.query, source_content=content)
121
- logger.info(f"代码生成完成,耗时 {time.time() - start_time:.2f} 秒")
127
+ printer.print_text(f"代码生成完毕,耗时 {time.time() - start_time:.2f} 秒", style="green")
122
128
 
123
129
  if self.args.auto_merge:
124
- logger.info("正在自动合并代码...")
130
+ printer.print_text("正在自动合并代码...", style="green")
125
131
  if self.args.auto_merge == "editblock":
126
132
  code_merge = CodeAutoMergeEditBlock(args=self.args, llm=self.llm)
127
133
  merge_result = code_merge.merge_code(generate_result=generate_result)
@@ -17,33 +17,29 @@ from autocoder_nano.llm_client import AutoLLM
17
17
  from autocoder_nano.llm_prompt import prompt
18
18
  from autocoder_nano.llm_types import AutoCoderArgs, PathAndCode, MergeCodeWithoutEffect, CodeGenerateResult, \
19
19
  CommitResult
20
+ from autocoder_nano.utils.printer_utils import Printer
20
21
 
21
22
 
22
- console = Console()
23
+ printer = Printer()
24
+ console = printer.get_console()
25
+ # console = Console()
23
26
 
24
27
 
25
28
  def git_print_commit_info(commit_result: CommitResult):
26
- table = Table(
27
- title="Commit Information (Use /revert to revert this commit)", show_header=True, header_style="bold magenta"
28
- )
29
- table.add_column("Attribute", style="cyan", no_wrap=True)
30
- table.add_column("Value", style="green")
31
-
32
- table.add_row("Commit Hash", commit_result.commit_hash)
33
- table.add_row("Commit Message", commit_result.commit_message)
34
- table.add_row("Changed Files", "\n".join(commit_result.changed_files))
35
-
36
- console.print(
37
- Panel(table, expand=False, border_style="green", title="Git Commit Summary")
29
+ printer.print_table_compact(
30
+ data=[
31
+ ["Commit Hash", commit_result.commit_hash],
32
+ ["Commit Message", commit_result.commit_message],
33
+ ["Changed Files", "\n".join(commit_result.changed_files)]
34
+ ],
35
+ title="Commit 信息", headers=["Attribute", "Value"], caption="(Use /revert to revert this commit)"
38
36
  )
39
37
 
40
38
  if commit_result.diffs:
41
39
  for file, diff in commit_result.diffs.items():
42
- console.print(f"\n[bold blue]File: {file}[/bold blue]")
40
+ printer.print_text(f"File: {file}", style="green")
43
41
  syntax = Syntax(diff, "diff", theme="monokai", line_numbers=True)
44
- console.print(
45
- Panel(syntax, expand=False, border_style="yellow", title="File Diff")
46
- )
42
+ printer.print_panel(syntax, title="File Diff", center=True)
47
43
 
48
44
 
49
45
  class CodeAutoMergeEditBlock:
@@ -79,12 +75,12 @@ class CodeAutoMergeEditBlock:
79
75
  os.unlink(temp_file_path)
80
76
  if result.returncode != 0:
81
77
  error_message = result.stdout.strip() or result.stderr.strip()
82
- logger.warning(f"Pylint 检查代码失败: {error_message}")
78
+ printer.print_text(f"Pylint 检查代码失败: {error_message}", style="yellow")
83
79
  return False, error_message
84
80
  return True, ""
85
81
  except subprocess.CalledProcessError as e:
86
82
  error_message = f"运行 Pylint 时发生错误: {str(e)}"
87
- logger.error(error_message)
83
+ printer.print_text(error_message, style="red")
88
84
  os.unlink(temp_file_path)
89
85
  return False, error_message
90
86
 
@@ -257,7 +253,7 @@ class CodeAutoMergeEditBlock:
257
253
  def choose_best_choice(self, generate_result: CodeGenerateResult) -> CodeGenerateResult:
258
254
  """ 选择最佳代码 """
259
255
  if len(generate_result.contents) == 1: # 仅一份代码立即返回
260
- logger.info("仅有一个候选结果,跳过排序")
256
+ printer.print_text("仅有一个候选结果,跳过排序", style="green")
261
257
  return generate_result
262
258
 
263
259
  ranker = CodeModificationRanker(args=self.args, llm=self.llm)
@@ -339,7 +335,8 @@ class CodeAutoMergeEditBlock:
339
335
  }
340
336
  )
341
337
  return
342
- logger.warning(f"发现 {len(unmerged_blocks)} 个未合并的代码块,更改将不会应用,请手动检查这些代码块后重试。")
338
+ printer.print_text(f"发现 {len(unmerged_blocks)} 个未合并的代码块,更改将不会应用,请手动检查这些代码块后重试.",
339
+ style="yellow")
343
340
  self._print_unmerged_blocks(unmerged_blocks)
344
341
  return
345
342
 
@@ -348,16 +345,15 @@ class CodeAutoMergeEditBlock:
348
345
  if file_path.endswith(".py"):
349
346
  pylint_passed, error_message = self.run_pylint(new_content)
350
347
  if not pylint_passed:
351
- logger.warning(f"代码文件 {file_path} 的 Pylint 检查未通过,本次更改未应用。错误信息: {error_message}")
348
+ printer.print_text(
349
+ f"代码文件 {file_path} 的 Pylint 检查未通过,本次更改未应用。错误信息: {error_message}",
350
+ style="yellow")
352
351
 
353
352
  if changes_made and not force_skip_git and not self.args.skip_commit:
354
353
  try:
355
354
  commit_changes(self.args.source_dir, f"auto_coder_pre_{file_name}_{md5}")
356
355
  except Exception as e:
357
- logger.error(
358
- self.git_require_msg(
359
- source_dir=self.args.source_dir, error=str(e))
360
- )
356
+ printer.print_text(self.git_require_msg(source_dir=self.args.source_dir, error=str(e)), style="red")
361
357
  return
362
358
  # Now, apply the changes
363
359
  for file_path, new_content in file_content_mapping.items():
@@ -385,17 +381,14 @@ class CodeAutoMergeEditBlock:
385
381
  commit_result = commit_changes(self.args.source_dir, f"auto_coder_{file_name}_{md5}")
386
382
  git_print_commit_info(commit_result=commit_result)
387
383
  except Exception as e:
388
- logger.error(
389
- self.git_require_msg(
390
- source_dir=self.args.source_dir, error=str(e)
391
- )
392
- )
393
- logger.info(
394
- f"已在 {len(file_content_mapping.keys())} 个文件中合并更改,"
395
- f"完成 {len(changes_to_make)}/{len(codes)} 个代码块。"
384
+ printer.print_text(self.git_require_msg(source_dir=self.args.source_dir, error=str(e)),
385
+ style="red")
386
+ printer.print_text(
387
+ f"已在 {len(file_content_mapping.keys())} 个文件中合并更改,完成 {len(changes_to_make)}/{len(codes)} 个代码块.",
388
+ style="green"
396
389
  )
397
390
  else:
398
- logger.warning("未对任何文件进行更改。")
391
+ printer.print_text("未对任何文件进行更改.", style="yellow")
399
392
 
400
393
  def merge_code(self, generate_result: CodeGenerateResult, force_skip_git: bool = False):
401
394
  result = self.choose_best_choice(generate_result)
@@ -404,15 +397,14 @@ class CodeAutoMergeEditBlock:
404
397
 
405
398
  @staticmethod
406
399
  def _print_unmerged_blocks(unmerged_blocks: List[tuple]):
407
- console.print(f"\n[bold red]未合并的代码块:[/bold red]")
400
+ printer.print_text("未合并的代码块:", style="yellow")
408
401
  for file_path, head, update, similarity in unmerged_blocks:
409
- console.print(f"\n[bold blue]文件:[/bold blue] {file_path}")
410
- console.print(
411
- f"\n[bold green]搜索代码块(相似度:{similarity}):[/bold green]")
402
+ printer.print_text(f"文件: {file_path}", style="yellow")
403
+ printer.print_text(f"搜索代码块(相似度:{similarity}):", style="yellow")
412
404
  syntax = Syntax(head, "python", theme="monokai", line_numbers=True)
413
- console.print(Panel(syntax, expand=False))
414
- console.print("\n[bold yellow]替换代码块:[/bold yellow]")
405
+ printer.print_panel(syntax)
406
+ printer.print_text(f"替换代码块:", style="yellow")
415
407
  syntax = Syntax(update, "python", theme="monokai",
416
408
  line_numbers=True)
417
- console.print(Panel(syntax, expand=False))
418
- console.print(f"\n[bold red]未合并的代码块总数: {len(unmerged_blocks)}[/bold red]")
409
+ printer.print_panel(syntax)
410
+ printer.print_text(f"未合并的代码块总数: {len(unmerged_blocks)}", style="yellow")
@@ -2,9 +2,13 @@ import os
2
2
 
3
3
  from autocoder_nano.llm_prompt import prompt
4
4
  from git import Repo, GitCommandError
5
- from loguru import logger
5
+ # from loguru import logger
6
6
 
7
7
  from autocoder_nano.llm_types import CommitResult
8
+ from autocoder_nano.utils.printer_utils import Printer
9
+
10
+
11
+ printer = Printer()
8
12
 
9
13
 
10
14
  def repo_init(repo_path: str) -> bool:
@@ -12,14 +16,14 @@ def repo_init(repo_path: str) -> bool:
12
16
  os.makedirs(repo_path)
13
17
 
14
18
  if os.path.exists(os.path.join(repo_path, ".git")):
15
- logger.warning(f"目录 {repo_path} 已是一个 Git 仓库,跳过初始化操作。")
19
+ printer.print_text(f"目录 {repo_path} 已是一个 Git 仓库,跳过初始化操作.", style="yellow")
16
20
  return False
17
21
  try:
18
22
  Repo.init(repo_path)
19
- logger.info(f"已在 {repo_path} 初始化新的 Git 仓库")
23
+ printer.print_text(f"已在 {repo_path} 初始化新的 Git 仓库.", style="green")
20
24
  return True
21
25
  except GitCommandError as e:
22
- logger.error(f"Git 初始化过程中发生错误: {e}")
26
+ printer.print_text(f"Git 初始化过程中发生错误: {e}.", style="red")
23
27
  return False
24
28
 
25
29
 
@@ -72,19 +76,19 @@ def commit_changes(repo_path: str, message: str) -> CommitResult:
72
76
  def revert_changes(repo_path: str, message: str) -> bool:
73
77
  repo = get_repo(repo_path)
74
78
  if repo is None:
75
- logger.error("仓库未初始化。")
79
+ printer.print_text("仓库未初始化.", style="red")
76
80
  return False
77
81
 
78
82
  try:
79
83
  # 检查当前工作目录是否有未提交的更改
80
84
  if repo.is_dirty():
81
- logger.warning("工作目录有未提交的更改,请在回退前提交或暂存您的修改。")
85
+ printer.print_text("工作目录有未提交的更改,请在回退前提交或暂存您的修改.", style="yellow")
82
86
  return False
83
87
 
84
88
  # 通过message定位到commit_hash
85
89
  commit = repo.git.log("--all", f"--grep={message}", "--format=%H", "-n", "1")
86
90
  if not commit:
87
- logger.warning(f"未找到提交信息包含 '{message}' 的提交记录。")
91
+ printer.print_text(f"未找到提交信息包含 '{message}' 的提交记录.", style="yellow")
88
92
  return False
89
93
 
90
94
  commit_hash = commit
@@ -94,25 +98,25 @@ def revert_changes(repo_path: str, message: str) -> bool:
94
98
 
95
99
  if not commits:
96
100
  repo.git.revert(commit, no_edit=True)
97
- logger.info(f"已回退单条提交记录: {commit}")
101
+ printer.print_text(f"已回退单条提交记录: {commit}", style="green")
98
102
  else:
99
103
  # 从最新的提交开始,逐个回滚
100
104
  for commit in reversed(commits):
101
105
  try:
102
106
  repo.git.revert(commit.hexsha, no_commit=True)
103
- logger.info(f"已回退提交 {commit.hexsha} 的更改")
107
+ printer.print_text(f"已回退提交 {commit.hexsha} 的更改", style="green")
104
108
  except GitCommandError as e:
105
- logger.error(f"回退提交 {commit.hexsha} 时发生错误: {e}")
109
+ printer.print_text(f"回退提交 {commit.hexsha} 时发生错误: {e}", style="red")
106
110
  repo.git.revert("--abort")
107
111
  return False
108
112
  # 提交所有的回滚更改
109
113
  repo.git.commit(message=f"Reverted all changes up to {commit_hash}")
110
- logger.info(f"已成功回退到提交 {commit_hash} 的状态")
114
+ printer.print_text(f"已成功回退到提交 {commit_hash} 的状态", style="green")
111
115
  # this is a mark, chat_auto_coder.py need this
112
116
  print(f"Successfully reverted changes", flush=True)
113
117
  return True
114
118
  except GitCommandError as e:
115
- logger.error(f"回退操作过程中发生错误: {e}")
119
+ printer.print_text(f"回退操作过程中发生错误: {e}", style="red")
116
120
  return False
117
121
 
118
122
 
@@ -154,7 +158,7 @@ def get_uncommitted_changes(repo_path: str) -> str:
154
158
  content = f.read()
155
159
  changes['new'].append((file_path, f'+++ {file_path}\n{content}'))
156
160
  except Exception as e:
157
- logger.error(f"Error reading file {file_path}: {e}")
161
+ printer.print_text(f"Error reading file {file_path}: {e}", style="red")
158
162
  # 生成markdown报告
159
163
  report = ["# Git Changes Report\n"]
160
164
  # 新增文件
@@ -187,7 +191,7 @@ def get_uncommitted_changes(repo_path: str) -> str:
187
191
 
188
192
  return "\n".join(report)
189
193
  except GitCommandError as e:
190
- logger.error(f"Error getting uncommitted changes: {e}")
194
+ printer.print_text(f"Error getting uncommitted changes: {e}", style="red")
191
195
  return f"Error: {str(e)}"
192
196
 
193
197
 
@@ -2,15 +2,17 @@ import os
2
2
  import time
3
3
  from typing import List, Dict
4
4
 
5
- from loguru import logger
6
- from rich.console import Console
7
- from rich.table import Table
5
+ # from loguru import logger
6
+ # from rich.console import Console
7
+ # from rich.table import Table
8
8
 
9
9
  from autocoder_nano.index.index_manager import IndexManager
10
10
  from autocoder_nano.llm_types import SourceCode, TargetFile, VerifyFileRelevance, AutoCoderArgs
11
11
  from autocoder_nano.llm_client import AutoLLM
12
+ from autocoder_nano.utils.printer_utils import Printer
12
13
 
13
- console = Console()
14
+
15
+ printer = Printer()
14
16
 
15
17
 
16
18
  def build_index_and_filter_files(args: AutoCoderArgs, llm: AutoLLM, sources: List[SourceCode]) -> str:
@@ -20,7 +22,7 @@ def build_index_and_filter_files(args: AutoCoderArgs, llm: AutoLLM, sources: Lis
20
22
  return _file_path
21
23
 
22
24
  final_files: Dict[str, TargetFile] = {}
23
- logger.info("第一阶段:处理 REST/RAG/Search 资源...")
25
+ printer.print_text("第一阶段:处理 REST/RAG/Search 资源...", style="green")
24
26
  for source in sources:
25
27
  if source.tag in ["REST", "RAG", "SEARCH"]:
26
28
  final_files[get_file_path(source.module_name)] = TargetFile(
@@ -28,14 +30,14 @@ def build_index_and_filter_files(args: AutoCoderArgs, llm: AutoLLM, sources: Lis
28
30
  )
29
31
 
30
32
  if not args.skip_build_index and llm:
31
- logger.info("第二阶段:为所有文件构建索引...")
33
+ printer.print_text("第二阶段:为所有文件构建索引...", style="green")
32
34
  index_manager = IndexManager(args=args, llm=llm, source_codes=sources)
33
35
  index_data = index_manager.build_index()
34
36
  indexed_files_count = len(index_data) if index_data else 0
35
- logger.info(f"总索引文件数: {indexed_files_count}")
37
+ printer.print_text(f"总索引文件数: {indexed_files_count}", style="green")
36
38
 
37
39
  if not args.skip_filter_index and args.index_filter_level >= 1:
38
- logger.info("第三阶段:执行 Level 1 过滤(基于查询) ...")
40
+ printer.print_text("第三阶段:执行 Level 1 过滤(基于查询) ...", style="green")
39
41
  target_files = index_manager.get_target_files_by_query(args.query)
40
42
  if target_files:
41
43
  for file in target_files.file_list:
@@ -43,7 +45,7 @@ def build_index_and_filter_files(args: AutoCoderArgs, llm: AutoLLM, sources: Lis
43
45
  final_files[get_file_path(file_path)] = file
44
46
 
45
47
  if target_files is not None and args.index_filter_level >= 2:
46
- logger.info("第四阶段:执行 Level 2 过滤(基于相关文件)...")
48
+ printer.print_text("第四阶段:执行 Level 2 过滤(基于相关文件)...", style="green")
47
49
  related_files = index_manager.get_related_files(
48
50
  [file.file_path for file in target_files.file_list]
49
51
  )
@@ -54,29 +56,28 @@ def build_index_and_filter_files(args: AutoCoderArgs, llm: AutoLLM, sources: Lis
54
56
 
55
57
  # 如果 Level 1 filtering 和 Level 2 filtering 都未获取路径,则使用全部文件
56
58
  if not final_files:
57
- logger.warning("Level 1, Level 2 过滤未找到相关文件, 将使用所有文件 ...")
59
+ printer.print_text("Level 1, Level 2 过滤未找到相关文件, 将使用所有文件 ...", style="yellow")
58
60
  for source in sources:
59
61
  final_files[get_file_path(source.module_name)] = TargetFile(
60
62
  file_path=source.module_name,
61
63
  reason="No related files found, use all files",
62
64
  )
63
65
 
64
- logger.info("第五阶段:执行相关性验证 ...")
66
+ printer.print_text("第五阶段:执行相关性验证 ...", style="green")
65
67
  verified_files = {}
66
68
  temp_files = list(final_files.values())
67
69
  verification_results = []
68
70
 
69
71
  def _print_verification_results(results):
70
- table = Table(title="文件相关性验证结果", expand=True, show_lines=True)
71
- table.add_column("文件路径", style="cyan", no_wrap=True)
72
- table.add_column("得分", justify="right", style="green")
73
- table.add_column("状态", style="yellow")
74
- table.add_column("原因/错误")
72
+ data_list = []
75
73
  if result:
76
74
  for _file_path, _score, _status, _reason in results:
77
- table.add_row(_file_path,
78
- str(_score) if _score is not None else "N/A", _status, _reason)
79
- console.print(table)
75
+ data_list.append([_file_path, str(_score) if _score is not None else "N/A", _status, _reason])
76
+ printer.print_table_compact(
77
+ data=data_list,
78
+ title="文件相关性验证结果",
79
+ headers=["文件路径", "得分", "状态", "原因/错误"]
80
+ )
80
81
 
81
82
  def _verify_single_file(single_file: TargetFile):
82
83
  for _source in sources:
@@ -115,12 +116,12 @@ def build_index_and_filter_files(args: AutoCoderArgs, llm: AutoLLM, sources: Lis
115
116
  # Keep all files, not just verified ones
116
117
  final_files = verified_files
117
118
 
118
- logger.info("第六阶段:筛选文件并应用限制条件 ...")
119
+ printer.print_text("第六阶段:筛选文件并应用限制条件 ...", style="green")
119
120
  if args.index_filter_file_num > 0:
120
- logger.info(f"从 {len(final_files)} 个文件中获取前 {args.index_filter_file_num} 个文件(Limit)")
121
+ printer.print_text(f"> 从 {len(final_files)} 个文件中获取前 {args.index_filter_file_num} 个文件(Limit)", style="green")
121
122
  final_filenames = [file.file_path for file in final_files.values()]
122
123
  if not final_filenames:
123
- logger.warning("未找到目标文件,你可能需要重新编写查询并重试.")
124
+ printer.print_text("未找到目标文件,你可能需要重新编写查询并重试.", style="yellow")
124
125
  if args.index_filter_file_num > 0:
125
126
  final_filenames = final_filenames[: args.index_filter_file_num]
126
127
 
@@ -135,16 +136,13 @@ def build_index_and_filter_files(args: AutoCoderArgs, llm: AutoLLM, sources: Lis
135
136
  return path
136
137
 
137
138
  def _print_selected(data):
138
- table = Table(title="代码上下文文件", expand=True, show_lines=True)
139
- table.add_column("文件路径", style="cyan")
140
- table.add_column("原因", style="cyan")
141
- for _file, _reason in data:
142
- # 路径截取优化:保留最后 3 级路径
143
- _processed_path = _shorten_path(_file, keep_levels=3)
144
- table.add_row(_processed_path, _reason)
145
- console.print(table)
146
-
147
- logger.info("第七阶段:准备最终输出 ...")
139
+ printer.print_table_compact(
140
+ data=[[_shorten_path(_file, keep_levels=3), _reason] for _file, _reason in data],
141
+ title="代码上下文文件",
142
+ headers=["文件路径", "原因"]
143
+ )
144
+
145
+ printer.print_text("第七阶段:准备最终输出 ...", style="green")
148
146
  _print_selected(
149
147
  [
150
148
  (file.file_path, file.reason)
@@ -4,12 +4,16 @@ import os
4
4
  import time
5
5
  from typing import List, Optional
6
6
 
7
- from loguru import logger
7
+ # from loguru import logger
8
8
 
9
9
  from autocoder_nano.index.symbols_utils import extract_symbols, symbols_info_to_str
10
10
  from autocoder_nano.llm_client import AutoLLM
11
11
  from autocoder_nano.llm_prompt import prompt
12
12
  from autocoder_nano.llm_types import SourceCode, AutoCoderArgs, IndexItem, SymbolType, FileList
13
+ from autocoder_nano.utils.printer_utils import Printer
14
+
15
+
16
+ printer = Printer()
13
17
 
14
18
 
15
19
  class IndexManager:
@@ -34,7 +38,7 @@ class IndexManager:
34
38
  with open(self.index_file, "r") as file: # 读缓存
35
39
  index_data = json.load(file)
36
40
  else: # 首次 build index
37
- logger.info("首次生成索引.")
41
+ printer.print_text("首次生成索引.", style="green")
38
42
  index_data = {}
39
43
 
40
44
  @prompt()
@@ -47,7 +51,7 @@ class IndexManager:
47
51
 
48
52
  for item in index_data.keys():
49
53
  if not item.startswith(self.source_dir):
50
- logger.warning(error_message(source_dir=self.source_dir, file_path=item))
54
+ printer.print_text(error_message.prompt(source_dir=self.source_dir, file_path=item), style="yellow")
51
55
  break
52
56
 
53
57
  updated_sources = []
@@ -60,13 +64,13 @@ class IndexManager:
60
64
  counter = 0
61
65
  num_files = len(wait_to_build_files)
62
66
  total_files = len(self.sources)
63
- logger.info(f"总文件数: {total_files}, 需要索引文件数: {num_files}")
67
+ printer.print_text(f"总文件数: {total_files}, 需要索引文件数: {num_files}", style="green")
64
68
 
65
69
  for source in wait_to_build_files:
66
70
  build_result = self.build_index_for_single_source(source)
67
71
  if build_result is not None:
68
72
  counter += 1
69
- logger.info(f"正在构建索引:{counter}/{num_files}...")
73
+ printer.print_text(f"正在构建索引:{counter}/{num_files}...", style="green")
70
74
  module_name = build_result["module_name"]
71
75
  index_data[module_name] = build_result
72
76
  updated_sources.append(module_name)
@@ -168,10 +172,13 @@ class IndexManager:
168
172
  start_time = time.monotonic()
169
173
  source_code = source.source_code
170
174
  if len(source.source_code) > self.max_input_length:
171
- logger.warning(
172
- f"警告[构建索引]: 源代码({source.module_name})长度过长 "
173
- f"({len(source.source_code)}) > 模型最大输入长度({self.max_input_length}),"
174
- f"正在分割为多个块..."
175
+ printer.print_text(
176
+ f"""
177
+ 警告[构建索引]: 源代码({source.module_name})长度过长,
178
+ ({len(source.source_code)}) > 模型最大输入长度({self.max_input_length}),
179
+ 正在分割为多个块...
180
+ """,
181
+ style="yellow"
175
182
  )
176
183
  chunks = self.split_text_into_chunks(source_code)
177
184
  symbols_list = []
@@ -185,9 +192,10 @@ class IndexManager:
185
192
  symbols = single_symbols.output
186
193
  time.sleep(self.anti_quota_limit)
187
194
 
188
- logger.info(f"解析并更新索引:文件 {file_path}(MD5: {md5}),耗时 {time.monotonic() - start_time:.2f} 秒")
195
+ printer.print_text(f"解析并更新索引:{file_path}(MD5: {md5}),耗时 {time.monotonic() - start_time:.2f} 秒",
196
+ style="green")
189
197
  except Exception as e:
190
- logger.warning(f"源文件 {file_path} 处理失败: {e}")
198
+ printer.print_text(f"源文件 {file_path} 处理失败: {e}", style="yellow")
191
199
  return None
192
200
 
193
201
  return {
@@ -313,11 +321,11 @@ class IndexManager:
313
321
  all_results.extend(result.file_list)
314
322
  completed += 1
315
323
  else:
316
- logger.warning(f"无法找到分块的目标文件。原因可能是模型响应未返回 JSON 格式数据,或返回的 JSON 为空。")
324
+ printer.print_text(f"无法找到分块的目标文件.原因可能是模型响应未返回格式错误.", style="yellow")
317
325
  total += 1
318
326
  time.sleep(self.anti_quota_limit)
319
327
 
320
- logger.info(f"已完成 {completed}/{total} 个分块(基于查询条件)")
328
+ printer.print_text(f"已完成 {completed}/{total} 个分块(基于查询条件)", style="green")
321
329
  all_results = list({file.file_path: file for file in all_results}.values())
322
330
  if self.args.index_filter_file_num > 0:
323
331
  limited_results = all_results[: self.args.index_filter_file_num]
@@ -378,10 +386,10 @@ class IndexManager:
378
386
  all_results.extend(result.file_list)
379
387
  completed += 1
380
388
  else:
381
- logger.warning(f"无法找到与分块相关的文件。原因可能是模型限制或查询条件与文件不匹配。")
389
+ printer.print_text(f"无法找到与分块相关的文件。原因可能是模型限制或查询条件与文件不匹配.", style="yellow")
382
390
  total += 1
383
391
  time.sleep(self.anti_quota_limit)
384
- logger.info(f"已完成 {completed}/{total} 个分块(基于相关文件)")
392
+ printer.print_text(f"已完成 {completed}/{total} 个分块(基于相关文件)", style="green")
385
393
  all_results = list({file.file_path: file for file in all_results}.values())
386
394
  return FileList(file_list=all_results)
387
395
 
@@ -1,10 +1,14 @@
1
1
  from typing import List
2
2
 
3
- from loguru import logger
3
+ # from loguru import logger
4
4
  from openai import OpenAI, Stream
5
5
  from openai.types.chat import ChatCompletionChunk, ChatCompletion
6
6
 
7
7
  from autocoder_nano.llm_types import LLMRequest, LLMResponse
8
+ from autocoder_nano.utils.printer_utils import Printer
9
+
10
+
11
+ printer = Printer()
8
12
 
9
13
 
10
14
  class AutoLLM:
@@ -37,7 +41,11 @@ class AutoLLM:
37
41
  model = self.default_model_name
38
42
 
39
43
  model_name = self.sub_clients[model]["model_name"]
40
- logger.info(f"正在使用 {model} 模型, 模型名称 {model_name}")
44
+ printer.print_card(
45
+ title="模型调用",
46
+ content=f"调用函数: stream_chat_ai\n使用模型: {model}\n模型名称: {model_name}",
47
+ width=60
48
+ )
41
49
  request = LLMRequest(
42
50
  model=model_name,
43
51
  messages=conversations
@@ -57,7 +65,11 @@ class AutoLLM:
57
65
  conversations = [{"role": "user", "content": conversations}]
58
66
 
59
67
  model_name = self.sub_clients[model]["model_name"]
60
- logger.info(f"正在使用 {model} 模型, 模型名称 {model_name}")
68
+ printer.print_card(
69
+ title="模型调用",
70
+ content=f"调用函数: chat_ai\n使用模型: {model}\n模型名称: {model_name}",
71
+ width=60
72
+ )
61
73
  request = LLMRequest(
62
74
  model=model_name,
63
75
  messages=conversations
@@ -98,7 +110,11 @@ class AutoLLM:
98
110
  model = self.default_model_name
99
111
 
100
112
  model_name = self.sub_clients[model]["model_name"]
101
- # logger.info(f"正在使用 {model} 模型, 模型名称 {model_name}")
113
+ printer.print_card(
114
+ title="模型调用",
115
+ content=f"调用函数: embedding\n使用模型: {model}\n模型名称: {model_name}",
116
+ width=60
117
+ )
102
118
 
103
119
  res = self.sub_clients[model]["client"].embeddings.create(
104
120
  model=model_name,
File without changes