auto-coder 0.1.355__py3-none-any.whl → 0.1.357__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.

Potentially problematic release.


This version of auto-coder might be problematic. Click here for more details.

@@ -0,0 +1,458 @@
1
+ import os
2
+ import io
3
+ import fnmatch
4
+ import json
5
+ import pathspec
6
+ from typing import Dict, Any, List, Callable, Optional
7
+ from rich.console import Console
8
+ from rich.panel import Panel
9
+ from rich.table import Table
10
+ from rich.text import Text
11
+ from rich.markdown import Markdown
12
+ from autocoder.auto_coder_runner import get_memory, save_memory
13
+ from autocoder.common.rulefiles.autocoderrules_utils import AutocoderRulesManager
14
+ from autocoder.agent.auto_learn import AutoLearn
15
+ from autocoder.common import SourceCode, SourceCodeList
16
+ from autocoder.auto_coder_runner import get_final_config, get_single_llm
17
+ from autocoder.chat_auto_coder_lang import get_message, get_message_with_format
18
+ from autocoder.rag.token_counter import count_tokens
19
+ from autocoder.common.printer import Printer
20
+ from autocoder.command_parser import CommandParser
21
+ from loguru import logger
22
+
23
+ printer = Printer()
24
+
25
+ # Helper function to print the rules files table (internal implementation)
26
+ def _print_rules_table(rules: Dict[str, str], pattern: str = "*"):
27
+ """Display rules files in a Rich table format."""
28
+ console = Console() # Capture output
29
+
30
+ # Create a styled table with rounded borders
31
+ title_text = get_message_with_format("rules_file_list_title", pattern=pattern)
32
+ printer.print_str_in_terminal(title_text)
33
+ table = Table(
34
+ show_header=True,
35
+ header_style="bold magenta",
36
+ title=title_text,
37
+ title_style="bold blue",
38
+ border_style="blue",
39
+ show_lines=True
40
+ )
41
+
42
+ # Add columns with explicit width and alignment
43
+ column_title = get_message("rules_file_path")
44
+ printer.print_str_in_terminal(column_title)
45
+ table.add_column(column_title, style="cyan", justify="left", width=80, no_wrap=False)
46
+ table.add_column("Token数", style="green", justify="right", width=15, no_wrap=False)
47
+
48
+ # Sort keys for consistent display
49
+ for file_path in sorted(rules.keys()):
50
+ if not fnmatch.fnmatch(os.path.basename(file_path), pattern):
51
+ continue
52
+
53
+ content = rules[file_path]
54
+ token_count = count_tokens(content)
55
+
56
+ # Format display values
57
+ formatted_path = Text(file_path, style="cyan")
58
+ formatted_token_count = Text(str(token_count), style="bright_cyan")
59
+
60
+ table.add_row(formatted_path, formatted_token_count)
61
+
62
+ # Add padding and print with a panel
63
+ console.print(Panel(
64
+ table,
65
+ padding=(1, 2),
66
+ subtitle=f"[italic]{get_message('rules_help_subtitle')}[/italic]",
67
+ border_style="blue"
68
+ ))
69
+
70
+ # --- Command Handlers ---
71
+
72
+ def _handle_list_rules(memory: Dict[str, Any], args: List[str]) -> str:
73
+ """Handles listing rules files, supports wildcard filtering."""
74
+ from autocoder.common.rulefiles.autocoderrules_utils import get_rules
75
+
76
+ # 获取项目根目录(当前工作目录)
77
+ project_root = os.getcwd()
78
+
79
+ # 获取所有规则文件
80
+ rules = get_rules(project_root)
81
+
82
+ if not rules:
83
+ message = get_message("rules_no_files_found")
84
+ printer.print_str_in_terminal(message)
85
+ return message
86
+
87
+ # 如果提供了参数,使用它作为过滤模式
88
+ pattern = args[0] if args else "*"
89
+
90
+ # 使用通配符匹配规则文件
91
+ if pattern != "*":
92
+ # 使用 pathspec 处理通配符路径
93
+ try:
94
+ # 创建 pathspec 对象,支持 .gitignore 风格的路径匹配
95
+ spec = pathspec.PathSpec.from_lines(
96
+ pathspec.patterns.GitWildMatchPattern, [pattern]
97
+ )
98
+
99
+ # 获取相对于项目根目录的路径
100
+ rel_paths = {}
101
+ for file_path in rules.keys():
102
+ # 计算相对路径用于匹配
103
+ if os.path.isabs(file_path):
104
+ rel_path = os.path.relpath(file_path, project_root)
105
+ else:
106
+ rel_path = file_path
107
+ rel_paths[file_path] = rel_path
108
+
109
+ # 使用 pathspec 匹配文件
110
+ filtered_rules = {}
111
+ for file_path, rel_path in rel_paths.items():
112
+ if spec.match_file(rel_path):
113
+ filtered_rules[file_path] = rules[file_path]
114
+
115
+ if not filtered_rules:
116
+ message = get_message_with_format("rules_no_matching_files", pattern=pattern)
117
+ printer.print_str_in_terminal(message)
118
+ return message
119
+ return _print_rules_table(filtered_rules, pattern)
120
+ except Exception as e:
121
+ message = f"Error matching pattern '{pattern}': {str(e)}"
122
+ printer.print_str_in_terminal(message)
123
+ return message
124
+ else:
125
+ return _print_rules_table(rules)
126
+
127
+ def _handle_remove_rules(memory: Dict[str, Any], args: List[str]) -> str:
128
+ """Handles removing rules files based on glob pattern."""
129
+ if not args:
130
+ message = get_message("rules_remove_param_required")
131
+ printer.print_str_in_terminal(message)
132
+ return message
133
+
134
+ pattern = args[0]
135
+
136
+ # 获取规则管理器
137
+ rules_manager = AutocoderRulesManager()
138
+ rules = rules_manager.get_rules()
139
+
140
+ if not rules:
141
+ message = get_message("rules_no_files_found")
142
+ printer.print_str_in_terminal(message)
143
+ return message
144
+
145
+ # 获取项目根目录
146
+ project_root = os.getcwd()
147
+
148
+ # 使用 pathspec 匹配要删除的文件
149
+ files_to_remove = []
150
+ try:
151
+ # 创建 pathspec 对象,支持 .gitignore 风格的路径匹配
152
+ spec = pathspec.PathSpec.from_lines(
153
+ pathspec.patterns.GitWildMatchPattern, [pattern]
154
+ )
155
+
156
+ # 获取相对于项目根目录的路径
157
+ for file_path in rules.keys():
158
+ # 计算相对路径用于匹配
159
+ if os.path.isabs(file_path):
160
+ rel_path = os.path.relpath(file_path, project_root)
161
+ else:
162
+ rel_path = file_path
163
+
164
+ if spec.match_file(rel_path):
165
+ files_to_remove.append(file_path)
166
+ except Exception as e:
167
+ message = f"Error matching pattern '{pattern}': {str(e)}"
168
+ printer.print_str_in_terminal(message)
169
+ return message
170
+
171
+ if not files_to_remove:
172
+ message = get_message_with_format("rules_no_files_to_remove", pattern=pattern)
173
+ printer.print_str_in_terminal(message)
174
+ return message
175
+
176
+ # 删除匹配的文件
177
+ removed_count = 0
178
+ for file_path in files_to_remove:
179
+ try:
180
+ os.remove(file_path)
181
+ removed_count += 1
182
+ except Exception as e:
183
+ message = get_message_with_format("rules_delete_error", file_path=file_path, error=str(e))
184
+ printer.print_str_in_terminal(message)
185
+ return message
186
+
187
+ # 重新加载规则
188
+ rules_manager._load_rules()
189
+
190
+ message = get_message_with_format("rules_delete_success", count=removed_count)
191
+ printer.print_str_in_terminal(message)
192
+ return message
193
+
194
+ def _handle_analyze_commit_rules(memory: Dict[str, Any], args: List[str],commit_id: str, coding_func=None) -> str:
195
+ """Handles analyzing current files with rules."""
196
+ query = " ".join(args) if args else ""
197
+
198
+ args = get_final_config()
199
+ llm = get_single_llm(args.model, product_mode=args.product_mode)
200
+ auto_learn = AutoLearn(llm=llm, args=args)
201
+ changes, _ = auto_learn.get_commit_changes(commit_id)
202
+
203
+ try:
204
+ result = auto_learn.analyze_commit.prompt(
205
+ querie_with_urls_and_changes=changes,
206
+ new_query=query
207
+ )
208
+ # 如果传入了 coding_func,则执行
209
+ if coding_func is not None:
210
+ coding_func(query=result)
211
+ return result
212
+ except Exception as e:
213
+ logger.exception(e)
214
+ import traceback
215
+ traceback.print_exc()
216
+ message = get_message_with_format("rules_analysis_error", error=str(e))
217
+ printer.print_str_in_terminal(message)
218
+ return message
219
+
220
+ def _handle_analyze_rules(memory: Dict[str, Any], args: List[str], coding_func=None) -> str:
221
+ """Handles analyzing current files with rules."""
222
+ query = " ".join(args) if args else ""
223
+
224
+ args = get_final_config()
225
+ llm = get_single_llm(args.model, product_mode=args.product_mode)
226
+ auto_learn = AutoLearn(llm=llm, args=args)
227
+
228
+ files = memory.get("current_files", {}).get("files", [])
229
+ if not files:
230
+ message = get_message("rules_no_active_files")
231
+ printer.print_str_in_terminal(message)
232
+ return message
233
+
234
+ sources = SourceCodeList([])
235
+ for file in files:
236
+ try:
237
+ with open(file, "r", encoding="utf-8") as f:
238
+ source_code = f.read()
239
+ sources.sources.append(SourceCode(module_name=file, source_code=source_code))
240
+ except Exception as e:
241
+ message = get_message_with_format("rules_file_read_error", file_path=file, error=str(e))
242
+ printer.print_str_in_terminal(message)
243
+ continue
244
+
245
+ try:
246
+ result = auto_learn.analyze_modules.prompt(sources=sources, query=query)
247
+ # 如果传入了 coding_func,则执行
248
+ if coding_func is not None:
249
+ coding_func(query=result)
250
+ return result
251
+ except Exception as e:
252
+ message = get_message_with_format("rules_analysis_error", error=str(e))
253
+ printer.print_str_in_terminal(message)
254
+ return message
255
+
256
+ def _handle_get_rules(memory: Dict[str, Any], args: List[str]) -> str:
257
+ """Handles displaying the content of rules files based on glob pattern."""
258
+ if not args:
259
+ message = get_message("rules_get_param_required")
260
+ printer.print_str_in_terminal(message)
261
+ return message
262
+
263
+ pattern = args[0]
264
+
265
+ # 获取规则管理器
266
+ from autocoder.common.rulefiles.autocoderrules_utils import get_rules
267
+ project_root = os.getcwd()
268
+ rules = get_rules(project_root)
269
+
270
+ if not rules:
271
+ message = get_message("rules_no_files_found")
272
+ printer.print_str_in_terminal(message)
273
+ return message
274
+
275
+ # 使用 pathspec 匹配文件
276
+ matched_files = []
277
+ try:
278
+ # 创建 pathspec 对象,支持 .gitignore 风格的路径匹配
279
+ spec = pathspec.PathSpec.from_lines(
280
+ pathspec.patterns.GitWildMatchPattern, [pattern]
281
+ )
282
+
283
+ # 获取相对于项目根目录的路径
284
+ for file_path in rules.keys():
285
+ # 计算相对路径用于匹配
286
+ if os.path.isabs(file_path):
287
+ rel_path = os.path.relpath(file_path, project_root)
288
+ else:
289
+ rel_path = file_path
290
+
291
+ if spec.match_file(rel_path):
292
+ matched_files.append(file_path)
293
+ except Exception as e:
294
+ message = f"Error matching pattern '{pattern}': {str(e)}"
295
+ printer.print_str_in_terminal(message)
296
+ return message
297
+
298
+ if not matched_files:
299
+ message = get_message_with_format("rules_get_no_matching_files", pattern=pattern)
300
+ printer.print_str_in_terminal(message)
301
+ return message
302
+
303
+ # 创建一个真实的控制台,而不是捕获输出
304
+ console = Console()
305
+
306
+ # 打印每个匹配文件的内容
307
+ for file_path in sorted(matched_files):
308
+ try:
309
+ # 获取文件内容
310
+ content = rules[file_path]
311
+
312
+ # 打印文件标题
313
+ console.print("\n")
314
+ console.print(Panel(
315
+ get_message_with_format("rules_get_file_title", file_path=file_path),
316
+ style="bold blue"
317
+ ))
318
+
319
+ # 以Markdown格式打印内容
320
+ md = Markdown(content)
321
+ console.print(md)
322
+
323
+ except Exception as e:
324
+ printer.print_str_in_terminal(get_message_with_format("rules_get_read_error", file_path=file_path, error=str(e)))
325
+ logger.exception(e)
326
+
327
+ # 由于控制台直接打印,返回空字符串
328
+ return ""
329
+
330
+ def _handle_help(memory: Dict[str, Any], args: List[str]) -> str:
331
+ """Provides help text for the /rules command."""
332
+ help_text = get_message("rules_help_text")
333
+ if not help_text:
334
+ # 如果没有翻译好的帮助文本,提供默认的中文帮助文本
335
+ help_text = """
336
+ /rules 命令帮助:
337
+ /rules /list [通配符] - 列出规则文件,可选通配符过滤
338
+ /rules /get [通配符] - 查看规则文件内容,可选通配符过滤
339
+ /rules /remove [通配符] - 删除规则文件,使用通配符匹配
340
+ /rules /analyze [查询] - 分析当前文件,可选提供查询内容
341
+ /rules /commit <提交ID> /query <查询> - 分析特定提交,必须提供提交ID和查询内容
342
+ /rules /help - 显示此帮助信息
343
+
344
+ 默认情况下,直接使用 /rules [查询] 相当于 /rules /analyze [查询]
345
+ """
346
+
347
+ printer.print_str_in_terminal(help_text)
348
+ return help_text
349
+
350
+ def _handle_commit_rules(memory: Dict[str, Any], args: List[str], coding_func=None) -> str:
351
+ """处理 commit 命令,要求格式为 /commit <commit_id> /query <查询内容>"""
352
+ if not args:
353
+ message = get_message("rules_commit_param_required")
354
+ printer.print_str_in_terminal(message)
355
+ return message
356
+
357
+ # 构建要解析的完整命令字符串
358
+ command_str = " ".join(args)
359
+
360
+ # 使用 CommandParser 解析命令
361
+ parser = CommandParser()
362
+
363
+ ## 传递过来的命令行是没有 /commit 子命令的,需要补充上
364
+ commands = parser.parse(f"/commit {command_str}")
365
+
366
+ # 验证必须包含 commit 和 query 命令
367
+ if not commands.get('commit') or not commands.get('query'):
368
+ message = get_message("rules_commit_format_error")
369
+ printer.print_str_in_terminal(message)
370
+ return message
371
+
372
+ # 获取 commit_id 和查询内容
373
+ commit_args = commands.get('commit', {}).get('args', [])
374
+ if not commit_args:
375
+ message = get_message("rules_commit_id_required")
376
+ printer.print_str_in_terminal(message)
377
+ return message
378
+
379
+ commit_id = commit_args[0]
380
+
381
+ # 获取查询内容
382
+ query_args = commands.get('query', {}).get('args', [])
383
+ if not query_args:
384
+ message = get_message("rules_query_required")
385
+ printer.print_str_in_terminal(message)
386
+ return message
387
+
388
+ query = " ".join(query_args)
389
+
390
+ # 实现实际的 commit 分析逻辑...
391
+ try:
392
+ _handle_analyze_commit_rules(memory, [query], commit_id=commit_id, coding_func=coding_func)
393
+ message = get_message_with_format("rules_commit_success", commit_id=commit_id, query=query)
394
+ printer.print_str_in_terminal(message)
395
+ return message
396
+ except Exception as e:
397
+ message = get_message_with_format("rules_commit_error", commit_id=commit_id, error=str(e))
398
+ printer.print_str_in_terminal(message)
399
+ return message
400
+
401
+ # Command dispatch table
402
+ COMMAND_HANDLERS: Dict[str, Callable[[Dict[str, Any], List[str]], str]] = {
403
+ "list": _handle_list_rules,
404
+ "remove": _handle_remove_rules,
405
+ "get": _handle_get_rules,
406
+ "analyze": _handle_analyze_rules, # 默认行为
407
+ "help": _handle_help,
408
+ "commit": _handle_commit_rules, # 添加新的命令处理函数
409
+ }
410
+
411
+ def handle_rules_command(command_args: str, memory: Dict[str, Any], coding_func=None) -> str:
412
+ """
413
+ Handles the /rules command and its subcommands.
414
+
415
+ Args:
416
+ command_args: The arguments string following the /rules command.
417
+ Example: "analyze code quality", "/list", "/remove *.md"
418
+ memory: The current session memory dictionary.
419
+
420
+ Returns:
421
+ A string response to be displayed to the user.
422
+ """
423
+ rules_str = command_args.strip()
424
+ # 处理空命令
425
+ if not rules_str:
426
+ return _handle_help(memory, [])
427
+
428
+ # 处理子命令
429
+ if rules_str.startswith("/"):
430
+ # 解析子命令
431
+ parts = rules_str[1:].strip().split(maxsplit=1)
432
+ subcommand = parts[0].lower() if parts else ""
433
+ args = parts[1].split() if len(parts) > 1 else []
434
+
435
+ handler = COMMAND_HANDLERS.get(subcommand)
436
+ if handler:
437
+ try:
438
+ # 仅 analyze 需要 coding_func
439
+ if subcommand == "analyze":
440
+ return handler(memory, args, coding_func=coding_func)
441
+ elif subcommand == "commit":
442
+ return handler(memory, args, coding_func=coding_func)
443
+ else:
444
+ return handler(memory, args)
445
+ except Exception as e:
446
+ message = get_message_with_format("rules_command_error", subcommand=subcommand, error=str(e))
447
+ printer.print_str_in_terminal(message)
448
+ return message
449
+ else:
450
+ message = get_message_with_format("rules_unknown_command", subcommand=subcommand)
451
+ printer.print_str_in_terminal(message)
452
+ return message
453
+ elif rules_str.lower() == "help":
454
+ # 处理无斜杠的 help 命令
455
+ return _handle_help(memory, [])
456
+ else:
457
+ # 将整个字符串作为查询参数传递给 analyze
458
+ return _handle_analyze_rules(memory, [rules_str], coding_func=coding_func)
@@ -53,6 +53,7 @@ from autocoder.auto_coder_runner import (
53
53
  summon,
54
54
  get_memory,
55
55
  active_context,
56
+ rules
56
57
  )
57
58
  # Ensure the correct import is present
58
59
  from autocoder.chat.conf_command import handle_conf_command
@@ -628,6 +629,10 @@ def main():
628
629
  args = user_input[len("/lib") :].strip().split()
629
630
  lib_command(args)
630
631
 
632
+ elif user_input.startswith("/rules"):
633
+ query = user_input[len("/rules") :].strip()
634
+ rules(query)
635
+
631
636
  elif user_input.startswith("/mcp"):
632
637
  query = user_input[len("/mcp") :].strip()
633
638
  if not query:
@@ -593,6 +593,136 @@ Available subcommands:
593
593
  "marketplace_add_error": {
594
594
  "en": "Error adding marketplace item: {{name}} - {{error}}",
595
595
  "zh": "添加市场项目时出错:{{name}} - {{error}}"
596
+ },
597
+ "rules_desc": {
598
+ "en": "Analyze current files with rules and create code learning notes",
599
+ "zh": "使用规则分析当前文件并创建代码学习笔记"
600
+ },
601
+ "rules_file_list_title": {
602
+ "en": "Rules Files List (Pattern: {{pattern}})",
603
+ "zh": "规则文件列表 (匹配: {{pattern}})"
604
+ },
605
+ "rules_file_path": {
606
+ "en": "File Path",
607
+ "zh": "文件路径"
608
+ },
609
+ "rules_content_length": {
610
+ "en": "Content Length",
611
+ "zh": "内容长度"
612
+ },
613
+ "rules_help_subtitle": {
614
+ "en": "Use '/rules help' for more information",
615
+ "zh": "使用 '/rules help' 获取更多帮助"
616
+ },
617
+ "rules_no_files_found": {
618
+ "en": "No rules files found. Use '/rules /help' to learn how to add rules.",
619
+ "zh": "未找到任何规则文件。请使用 '/rules /help' 了解如何添加规则。"
620
+ },
621
+ "rules_no_matching_files": {
622
+ "en": "No rules files found matching pattern '{{pattern}}'.",
623
+ "zh": "没有找到匹配模式 '{{pattern}}' 的规则文件。"
624
+ },
625
+ "rules_remove_param_required": {
626
+ "en": "Error: 'remove' command requires a parameter (file pattern). Usage: /rules /remove <pattern>",
627
+ "zh": "错误: 'remove' 命令需要一个参数(文件匹配模式)。用法: /rules /remove <匹配模式>"
628
+ },
629
+ "rules_no_files_to_remove": {
630
+ "en": "No rules files found matching pattern '{{pattern}}'.",
631
+ "zh": "没有找到匹配模式 '{{pattern}}' 的规则文件。"
632
+ },
633
+ "rules_delete_error": {
634
+ "en": "Error deleting file '{{file_path}}': {{error}}",
635
+ "zh": "删除文件 '{{file_path}}' 时出错: {{error}}"
636
+ },
637
+ "rules_delete_success": {
638
+ "en": "Successfully deleted {{count}} rules files.",
639
+ "zh": "成功删除了 {{count}} 个规则文件。"
640
+ },
641
+ "rules_no_active_files": {
642
+ "en": "Error: No files selected for analysis. Please use 'add_files' command to add files first.",
643
+ "zh": "错误: 没有选择任何文件进行分析。请先使用 'add_files' 命令添加文件。"
644
+ },
645
+ "rules_file_read_error": {
646
+ "en": "Error reading file '{{file_path}}': {{error}}",
647
+ "zh": "读取文件 '{{file_path}}' 时出错: {{error}}"
648
+ },
649
+ "rules_analysis_error": {
650
+ "en": "Error analyzing code: {{error}}",
651
+ "zh": "分析代码时出错: {{error}}"
652
+ },
653
+ "rules_help_text": {
654
+ "en": """
655
+ /rules command usage:
656
+ /rules [query] - Analyze current added files, optionally provide specific query content.
657
+ /rules /list [pattern] - List all rules files. Optionally provide wildcard pattern (e.g. *.md).
658
+ /rules /remove <pattern> - Delete rules files matching the specified pattern.
659
+ /rules /get <pattern> - Display the content of rules files matching the specified pattern.
660
+ /rules /help or /rules help - Show this help message.
661
+
662
+ Rules file usage:
663
+ Rules files are stored in the project's .autocoderrules/ directory, in Markdown format.
664
+ The system automatically monitors changes to this directory and updates rules.
665
+ """,
666
+ "zh": """
667
+ /rules 命令用法:
668
+ /rules [查询内容] - 分析当前已添加的文件,可选提供具体查询内容。
669
+ /rules /list [匹配模式] - 列出所有规则文件。可选提供通配符匹配模式 (例如: *.md).
670
+ /rules /remove <匹配模式> - 删除匹配指定模式的规则文件。
671
+ /rules /get <匹配模式> - 显示匹配指定模式的规则文件内容。
672
+ /rules /help 或 /rules help - 显示此帮助信息。
673
+
674
+ 规则文件用法:
675
+ 规则文件存储在项目的 .autocoderrules/ 目录下,为 Markdown 格式。
676
+ 系统会自动监控该目录的变化并更新规则。
677
+ """
678
+ },
679
+ "rules_unknown_command": {
680
+ "en": "Unknown subcommand '/rules {{subcommand}}'. Use '/rules /help' for help.",
681
+ "zh": "未知的子命令 '/rules {{subcommand}}'。请使用 '/rules /help' 获取帮助。"
682
+ },
683
+ "rules_command_error": {
684
+ "en": "Error executing '/rules {{subcommand}}': {{error}}",
685
+ "zh": "执行 '/rules {{subcommand}}' 时发生错误: {{error}}"
686
+ },
687
+ "rules_get_param_required": {
688
+ "en": "Error: 'get' command requires a parameter (file pattern). Usage: /rules /get <pattern>",
689
+ "zh": "错误: 'get' 命令需要一个参数(文件匹配模式)。用法: /rules /get <匹配模式>"
690
+ },
691
+ "rules_get_no_matching_files": {
692
+ "en": "No rules files found matching pattern '{{pattern}}'.",
693
+ "zh": "没有找到匹配模式 '{{pattern}}' 的规则文件。"
694
+ },
695
+ "rules_get_file_title": {
696
+ "en": "Rule File: {{file_path}}",
697
+ "zh": "规则文件: {{file_path}}"
698
+ },
699
+ "rules_get_read_error": {
700
+ "en": "Error reading file '{{file_path}}': {{error}}",
701
+ "zh": "读取文件 '{{file_path}}' 时出错: {{error}}"
702
+ },
703
+ "rules_commit_param_required": {
704
+ "en": "Error: 'commit' command requires parameters. Usage: /rules /commit <commit_id> /query <query>",
705
+ "zh": "错误: 'commit' 命令需要参数。用法: /rules /commit <commit_id> /query <查询内容>"
706
+ },
707
+ "rules_commit_format_error": {
708
+ "en": "Error: Command format must be '/rules /commit <commit_id> /query <query>'",
709
+ "zh": "错误:命令格式必须为 '/rules /commit <commit_id> /query <你的需求>'"
710
+ },
711
+ "rules_commit_id_required": {
712
+ "en": "Error: Commit ID must be provided",
713
+ "zh": "错误:必须提供 commit ID"
714
+ },
715
+ "rules_query_required": {
716
+ "en": "Error: Query content must be provided",
717
+ "zh": "错误:必须提供查询内容"
718
+ },
719
+ "rules_commit_success": {
720
+ "en": "Successfully analyzed commit {{commit_id}}, query: {{query}}",
721
+ "zh": "成功分析 commit {{commit_id}},查询:{{query}}"
722
+ },
723
+ "rules_commit_error": {
724
+ "en": "Error analyzing commit {{commit_id}}: {{error}}",
725
+ "zh": "分析 commit {{commit_id}} 时出错:{{error}}"
596
726
  }
597
727
  }
598
728
 
@@ -106,6 +106,10 @@ MESSAGES = {
106
106
  "en": "DeepSeek Official",
107
107
  "zh": "DeepSeek官方"
108
108
  },
109
+ "model_provider_openrouter": {
110
+ "en": "OpenRouter",
111
+ "zh": "OpenRouter"
112
+ },
109
113
  "model_provider_api_key_title": {
110
114
  "en": "API Key",
111
115
  "zh": "API密钥"
@@ -114,6 +118,10 @@ MESSAGES = {
114
118
  "en": "Please enter your Volcano Engine API key:",
115
119
  "zh": "请输入您的火山方舟API密钥:"
116
120
  },
121
+ "model_provider_openrouter_api_key_text": {
122
+ "en": "Please enter your OpenRouter API key:",
123
+ "zh": "请输入您的OpenRouter API密钥:"
124
+ },
117
125
  "model_provider_volcano_r1_text": {
118
126
  "en": "Please enter your Volcano Engine R1 endpoint (format: ep-20250204215011-vzbsg):",
119
127
  "zh": "请输入您的火山方舟 R1 推理点(格式如: ep-20250204215011-vzbsg):"
@@ -129,7 +137,7 @@ MESSAGES = {
129
137
  "model_provider_deepseek_api_key_text": {
130
138
  "en": "Please enter your DeepSeek API key:",
131
139
  "zh": "请输入您的DeepSeek API密钥:"
132
- },
140
+ },
133
141
  "model_provider_selected": {
134
142
  "en": "Provider configuration completed successfully! You can use /models command to view, add and modify all models later.",
135
143
  "zh": "供应商配置已成功完成!后续你可以使用 /models 命令,查看,新增和修改所有模型"