jarvis-ai-assistant 0.1.193__py3-none-any.whl → 0.1.195__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 (92) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +45 -41
  3. jarvis/jarvis_agent/builtin_input_handler.py +26 -4
  4. jarvis/jarvis_agent/jarvis.py +30 -19
  5. jarvis/jarvis_agent/main.py +20 -12
  6. jarvis/jarvis_agent/output_handler.py +7 -7
  7. jarvis/jarvis_agent/shell_input_handler.py +14 -11
  8. jarvis/jarvis_code_agent/code_agent.py +81 -79
  9. jarvis/jarvis_code_agent/lint.py +92 -105
  10. jarvis/jarvis_code_analysis/checklists/__init__.py +1 -1
  11. jarvis/jarvis_code_analysis/checklists/c_cpp.py +1 -1
  12. jarvis/jarvis_code_analysis/checklists/csharp.py +1 -1
  13. jarvis/jarvis_code_analysis/checklists/data_format.py +1 -1
  14. jarvis/jarvis_code_analysis/checklists/devops.py +1 -1
  15. jarvis/jarvis_code_analysis/checklists/docs.py +1 -1
  16. jarvis/jarvis_code_analysis/checklists/go.py +1 -1
  17. jarvis/jarvis_code_analysis/checklists/infrastructure.py +1 -1
  18. jarvis/jarvis_code_analysis/checklists/java.py +1 -1
  19. jarvis/jarvis_code_analysis/checklists/javascript.py +1 -1
  20. jarvis/jarvis_code_analysis/checklists/kotlin.py +1 -1
  21. jarvis/jarvis_code_analysis/checklists/loader.py +31 -29
  22. jarvis/jarvis_code_analysis/checklists/php.py +1 -1
  23. jarvis/jarvis_code_analysis/checklists/python.py +1 -1
  24. jarvis/jarvis_code_analysis/checklists/ruby.py +1 -1
  25. jarvis/jarvis_code_analysis/checklists/rust.py +1 -1
  26. jarvis/jarvis_code_analysis/checklists/shell.py +1 -1
  27. jarvis/jarvis_code_analysis/checklists/sql.py +1 -1
  28. jarvis/jarvis_code_analysis/checklists/swift.py +1 -1
  29. jarvis/jarvis_code_analysis/checklists/web.py +1 -1
  30. jarvis/jarvis_code_analysis/code_review.py +292 -190
  31. jarvis/jarvis_dev/main.py +73 -56
  32. jarvis/jarvis_git_details/main.py +29 -33
  33. jarvis/jarvis_git_squash/main.py +13 -11
  34. jarvis/jarvis_git_utils/git_commiter.py +15 -5
  35. jarvis/jarvis_mcp/__init__.py +8 -10
  36. jarvis/jarvis_mcp/sse_mcp_client.py +182 -205
  37. jarvis/jarvis_mcp/stdio_mcp_client.py +93 -120
  38. jarvis/jarvis_mcp/streamable_mcp_client.py +117 -142
  39. jarvis/jarvis_methodology/main.py +71 -39
  40. jarvis/jarvis_multi_agent/__init__.py +24 -16
  41. jarvis/jarvis_multi_agent/main.py +10 -4
  42. jarvis/jarvis_platform/__init__.py +1 -1
  43. jarvis/jarvis_platform/base.py +44 -18
  44. jarvis/jarvis_platform/human.py +15 -3
  45. jarvis/jarvis_platform/kimi.py +117 -81
  46. jarvis/jarvis_platform/openai.py +23 -28
  47. jarvis/jarvis_platform/registry.py +43 -29
  48. jarvis/jarvis_platform/tongyi.py +16 -10
  49. jarvis/jarvis_platform/yuanbao.py +197 -144
  50. jarvis/jarvis_platform_manager/main.py +4 -2
  51. jarvis/jarvis_smart_shell/main.py +35 -30
  52. jarvis/jarvis_tools/ask_user.py +8 -16
  53. jarvis/jarvis_tools/base.py +3 -2
  54. jarvis/jarvis_tools/chdir.py +7 -19
  55. jarvis/jarvis_tools/cli/main.py +14 -10
  56. jarvis/jarvis_tools/code_plan.py +10 -31
  57. jarvis/jarvis_tools/create_code_agent.py +6 -11
  58. jarvis/jarvis_tools/create_sub_agent.py +10 -22
  59. jarvis/jarvis_tools/edit_file.py +98 -76
  60. jarvis/jarvis_tools/execute_script.py +46 -46
  61. jarvis/jarvis_tools/file_analyzer.py +22 -34
  62. jarvis/jarvis_tools/file_operation.py +69 -62
  63. jarvis/jarvis_tools/generate_new_tool.py +0 -2
  64. jarvis/jarvis_tools/methodology.py +19 -23
  65. jarvis/jarvis_tools/read_code.py +35 -35
  66. jarvis/jarvis_tools/read_webpage.py +7 -16
  67. jarvis/jarvis_tools/registry.py +63 -30
  68. jarvis/jarvis_tools/rewrite_file.py +26 -29
  69. jarvis/jarvis_tools/search_web.py +5 -8
  70. jarvis/jarvis_tools/virtual_tty.py +133 -122
  71. jarvis/jarvis_utils/__init__.py +0 -1
  72. jarvis/jarvis_utils/builtin_replace_map.py +9 -9
  73. jarvis/jarvis_utils/config.py +60 -37
  74. jarvis/jarvis_utils/embedding.py +24 -19
  75. jarvis/jarvis_utils/file_processors.py +16 -9
  76. jarvis/jarvis_utils/git_utils.py +157 -107
  77. jarvis/jarvis_utils/globals.py +1 -1
  78. jarvis/jarvis_utils/input.py +85 -52
  79. jarvis/jarvis_utils/jarvis_history.py +43 -0
  80. jarvis/jarvis_utils/methodology.py +31 -24
  81. jarvis/jarvis_utils/output.py +164 -80
  82. jarvis/jarvis_utils/tag.py +2 -1
  83. jarvis/jarvis_utils/utils.py +84 -52
  84. {jarvis_ai_assistant-0.1.193.dist-info → jarvis_ai_assistant-0.1.195.dist-info}/METADATA +362 -230
  85. jarvis_ai_assistant-0.1.195.dist-info/RECORD +98 -0
  86. jarvis/jarvis_agent/file_input_handler.py +0 -112
  87. jarvis/jarvis_event/__init__.py +0 -0
  88. jarvis_ai_assistant-0.1.193.dist-info/RECORD +0 -99
  89. {jarvis_ai_assistant-0.1.193.dist-info → jarvis_ai_assistant-0.1.195.dist-info}/WHEEL +0 -0
  90. {jarvis_ai_assistant-0.1.193.dist-info → jarvis_ai_assistant-0.1.195.dist-info}/entry_points.txt +0 -0
  91. {jarvis_ai_assistant-0.1.193.dist-info → jarvis_ai_assistant-0.1.195.dist-info}/licenses/LICENSE +0 -0
  92. {jarvis_ai_assistant-0.1.193.dist-info → jarvis_ai_assistant-0.1.195.dist-info}/top_level.txt +0 -0
@@ -12,7 +12,8 @@ from colorama import Fore
12
12
  from colorama import Style as ColoramaStyle
13
13
  from fuzzywuzzy import process
14
14
  from prompt_toolkit import PromptSession
15
- from prompt_toolkit.completion import Completer, Completion, PathCompleter
15
+ from prompt_toolkit.completion import (CompleteEvent, Completer, Completion,
16
+ PathCompleter)
16
17
  from prompt_toolkit.document import Document
17
18
  from prompt_toolkit.formatted_text import FormattedText
18
19
  from prompt_toolkit.key_binding import KeyBindings
@@ -34,10 +35,14 @@ def get_single_line_input(tip: str) -> str:
34
35
  str: 用户的输入
35
36
  """
36
37
  session = PromptSession(history=None)
37
- style = PromptStyle.from_dict({
38
- 'prompt': 'ansicyan',
39
- })
38
+ style = PromptStyle.from_dict(
39
+ {
40
+ "prompt": "ansicyan",
41
+ }
42
+ )
40
43
  return session.prompt(f"{tip}", style=style)
44
+
45
+
41
46
  class FileCompleter(Completer):
42
47
  """
43
48
  带有模糊匹配的文件路径自定义补全器。
@@ -47,13 +52,15 @@ class FileCompleter(Completer):
47
52
  max_suggestions: 显示的最大建议数量
48
53
  min_score: 建议的最小匹配分数
49
54
  """
55
+
50
56
  def __init__(self):
51
57
  """使用默认设置初始化文件补全器。"""
52
58
  self.path_completer = PathCompleter()
53
59
  self.max_suggestions = 10
54
60
  self.min_score = 10
55
61
  self.replace_map = get_replace_map()
56
- def get_completions(self, document: Document, complete_event) -> Completion: # type: ignore
62
+
63
+ def get_completions(self, document: Document, _: CompleteEvent) -> Completion: # type: ignore
57
64
  """
58
65
  生成带有模糊匹配的文件路径补全建议。
59
66
 
@@ -67,7 +74,7 @@ class FileCompleter(Completer):
67
74
  text = document.text_before_cursor
68
75
  cursor_pos = document.cursor_position
69
76
  # 查找文本中的所有@位置
70
- at_positions = [i for i, char in enumerate(text) if char == '@']
77
+ at_positions = [i for i, char in enumerate(text) if char == "@"]
71
78
  if not at_positions:
72
79
  return
73
80
  # 获取最后一个@位置
@@ -76,12 +83,10 @@ class FileCompleter(Completer):
76
83
  if cursor_pos <= current_at_pos:
77
84
  return
78
85
  # 检查@之后是否有空格
79
- text_after_at = text[current_at_pos + 1:cursor_pos]
80
- if ' ' in text_after_at:
86
+ text_after_at = text[current_at_pos + 1 : cursor_pos]
87
+ if " " in text_after_at:
81
88
  return
82
-
83
89
 
84
-
85
90
  # 获取当前@之后的文本
86
91
  file_path = text_after_at.strip()
87
92
  # 计算替换长度
@@ -89,38 +94,52 @@ class FileCompleter(Completer):
89
94
 
90
95
  # 获取所有可能的补全项
91
96
  all_completions = []
92
-
97
+
93
98
  # 1. 添加特殊标记
94
- all_completions.extend([
95
- (ot(tag), self._get_description(tag))
96
- for tag in self.replace_map.keys()
97
- ])
98
- all_completions.extend([
99
- (ot("Summary"), '总结'),
100
- (ot("Clear"), '清除历史'),
101
- ])
102
-
99
+ all_completions.extend(
100
+ [(ot(tag), self._get_description(tag)) for tag in self.replace_map.keys()]
101
+ )
102
+ all_completions.extend(
103
+ [
104
+ (ot("Summary"), "总结"),
105
+ (ot("Clear"), "清除历史"),
106
+ (ot("ToolUsage"), "工具使用说明"),
107
+ (ot("ReloadConfig"), "重新加载配置"),
108
+ ]
109
+ )
110
+
103
111
  # 2. 添加文件列表
104
112
  try:
105
113
  import subprocess
106
- result = subprocess.run(['git', 'ls-files'],
107
- stdout=subprocess.PIPE,
108
- stderr=subprocess.PIPE,
109
- text=True)
114
+
115
+ result = subprocess.run(
116
+ ["git", "ls-files"],
117
+ stdout=subprocess.PIPE,
118
+ stderr=subprocess.PIPE,
119
+ text=True,
120
+ )
110
121
  if result.returncode == 0:
111
- all_completions.extend([
112
- (path, "File")
113
- for path in result.stdout.splitlines()
114
- if path.strip()
115
- ])
122
+ all_completions.extend(
123
+ [
124
+ (path, "File")
125
+ for path in result.stdout.splitlines()
126
+ if path.strip()
127
+ ]
128
+ )
116
129
  except Exception:
117
130
  pass
118
-
131
+
119
132
  # 统一过滤和排序
120
133
  if file_path:
121
134
  # 使用模糊匹配过滤
122
- scored_items = process.extract(file_path, [item[0] for item in all_completions], limit=self.max_suggestions)
123
- scored_items = [(item[0], item[1]) for item in scored_items if item[1] > self.min_score]
135
+ scored_items = process.extract(
136
+ file_path,
137
+ [item[0] for item in all_completions],
138
+ limit=self.max_suggestions,
139
+ )
140
+ scored_items = [
141
+ (item[0], item[1]) for item in scored_items if item[1] > self.min_score
142
+ ]
124
143
  # 创建映射以便查找描述
125
144
  completion_map = {item[0]: item[1] for item in all_completions}
126
145
  # 生成补全项
@@ -132,23 +151,29 @@ class FileCompleter(Completer):
132
151
  text=f"'{text}'",
133
152
  start_position=-replace_length,
134
153
  display=display_text,
135
- display_meta=completion_map.get(text, "")
136
- ) # type: ignore
154
+ display_meta=completion_map.get(text, ""),
155
+ ) # type: ignore
137
156
  else:
138
157
  # 没有输入时返回前max_suggestions个建议
139
- for text, desc in all_completions[:self.max_suggestions]:
158
+ for text, desc in all_completions[: self.max_suggestions]:
140
159
  yield Completion(
141
160
  text=f"'{text}'",
142
161
  start_position=-replace_length,
143
162
  display=text,
144
- display_meta=desc
145
- ) # type: ignore
146
-
163
+ display_meta=desc,
164
+ ) # type: ignore
165
+
147
166
  def _get_description(self, tag: str) -> str:
148
167
  """获取标记的描述信息"""
149
168
  if tag in self.replace_map:
150
- return self.replace_map[tag].get("description", tag) + "(Append)" if "append" in self.replace_map[tag] and self.replace_map[tag]["append"] else "(Replace)"
169
+ return (
170
+ self.replace_map[tag].get("description", tag) + "(Append)"
171
+ if "append" in self.replace_map[tag] and self.replace_map[tag]["append"]
172
+ else "(Replace)"
173
+ )
151
174
  return tag
175
+
176
+
152
177
  def get_multiline_input(tip: str) -> str:
153
178
  """
154
179
  获取带有增强补全和确认功能的多行输入。
@@ -160,25 +185,35 @@ def get_multiline_input(tip: str) -> str:
160
185
  str: 用户的输入,如果取消则返回空字符串
161
186
  """
162
187
  # 显示输入说明
163
- PrettyOutput.section("用户输入 - 使用 @ 触发文件补全,Tab 选择补全项,Ctrl+J 提交,按 Ctrl+C 取消输入", OutputType.USER)
188
+ PrettyOutput.section(
189
+ "用户输入 - 使用 @ 触发文件补全,Tab 选择补全项,Ctrl+J 提交,按 Ctrl+C 取消输入",
190
+ OutputType.USER,
191
+ )
164
192
  print(f"{Fore.GREEN}{tip}{ColoramaStyle.RESET_ALL}")
165
193
  # 配置键绑定
166
194
  bindings = KeyBindings()
167
- @bindings.add('enter')
195
+
196
+ @bindings.add("enter")
168
197
  def _(event):
169
198
  """处理回车键以进行补全或换行。"""
170
199
  if event.current_buffer.complete_state:
171
- event.current_buffer.apply_completion(event.current_buffer.complete_state.current_completion)
200
+ event.current_buffer.apply_completion(
201
+ event.current_buffer.complete_state.current_completion
202
+ )
172
203
  else:
173
- event.current_buffer.insert_text('\n')
174
- @bindings.add('c-j')
204
+ event.current_buffer.insert_text("\n")
205
+
206
+ @bindings.add("c-j")
175
207
  def _(event):
176
208
  """处理Ctrl+J以提交输入。"""
177
209
  event.current_buffer.validate_and_handle()
210
+
178
211
  # 配置提示会话
179
- style = PromptStyle.from_dict({
180
- 'prompt': 'ansicyan',
181
- })
212
+ style = PromptStyle.from_dict(
213
+ {
214
+ "prompt": "ansicyan",
215
+ }
216
+ )
182
217
  try:
183
218
  import os
184
219
 
@@ -190,17 +225,15 @@ def get_multiline_input(tip: str) -> str:
190
225
  history_dir = get_data_dir()
191
226
  # 初始化带历史记录的会话
192
227
  session = PromptSession(
193
- history=FileHistory(os.path.join(history_dir, 'multiline_input_history')),
228
+ history=FileHistory(os.path.join(history_dir, "multiline_input_history")),
194
229
  completer=FileCompleter(),
195
230
  key_bindings=bindings,
196
231
  complete_while_typing=True,
197
232
  multiline=True,
198
233
  vi_mode=False,
199
- mouse_support=False
234
+ mouse_support=False,
200
235
  )
201
- prompt = FormattedText([
202
- ('class:prompt', '>>> ')
203
- ])
236
+ prompt = FormattedText([("class:prompt", ">>> ")])
204
237
  # 获取输入
205
238
  text = session.prompt(
206
239
  prompt,
@@ -0,0 +1,43 @@
1
+ import os
2
+ from datetime import datetime
3
+ from typing import Dict, List, Optional
4
+
5
+ import yaml
6
+
7
+
8
+ class JarvisHistory:
9
+ def __init__(self):
10
+ self.records: List[Dict[str, str]] = []
11
+ self.current_file: Optional[str] = None
12
+
13
+ def start_record(self, data_dir: str) -> None:
14
+ """Start a new recording session with timestamped filename"""
15
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
16
+ self.current_file = os.path.join(data_dir, f"history_{timestamp}.yaml")
17
+ self.records = []
18
+
19
+ def append_msg(self, role: str, msg: str) -> None:
20
+ """Append a message to current recording session"""
21
+ if not self.current_file:
22
+ raise RuntimeError("Recording not started. Call start_record first.")
23
+ self.records.append({"role": role, "message": msg})
24
+
25
+ def stop_record(self) -> None:
26
+ """Save recorded messages to YAML file"""
27
+ if not self.current_file:
28
+ raise RuntimeError("No recording session to stop.")
29
+
30
+ # Skip saving if records is empty
31
+ if not self.records:
32
+ self.current_file = None
33
+ self.records = []
34
+ return
35
+
36
+ # Ensure directory exists
37
+ os.makedirs(os.path.dirname(self.current_file), exist_ok=True)
38
+
39
+ with open(self.current_file, "w") as f:
40
+ yaml.safe_dump({"conversation": self.records}, f, allow_unicode=True)
41
+
42
+ self.current_file = None
43
+ self.records = []
@@ -10,7 +10,7 @@
10
10
  import json
11
11
  import os
12
12
  import tempfile
13
- from typing import Any, Dict, Optional
13
+ from typing import Any, Dict, List, Optional
14
14
 
15
15
  from jarvis.jarvis_platform.base import BasePlatform
16
16
  from jarvis.jarvis_platform.registry import PlatformRegistry
@@ -34,6 +34,7 @@ def _get_methodology_directory() -> str:
34
34
  PrettyOutput.print(f"创建方法论目录失败: {str(e)}", OutputType.ERROR)
35
35
  return methodology_dir
36
36
 
37
+
37
38
  def _load_all_methodologies() -> Dict[str, str]:
38
39
  """
39
40
  加载所有方法论文件
@@ -48,6 +49,7 @@ def _load_all_methodologies() -> Dict[str, str]:
48
49
  return all_methodologies
49
50
 
50
51
  import glob
52
+
51
53
  for filepath in glob.glob(os.path.join(methodology_dir, "*.json")):
52
54
  try:
53
55
  with open(filepath, "r", encoding="utf-8", errors="ignore") as f:
@@ -58,10 +60,13 @@ def _load_all_methodologies() -> Dict[str, str]:
58
60
  all_methodologies[problem_type] = content
59
61
  except Exception as e:
60
62
  filename = os.path.basename(filepath)
61
- PrettyOutput.print(f"加载方法论文件 {filename} 失败: {str(e)}", OutputType.WARNING)
63
+ PrettyOutput.print(
64
+ f"加载方法论文件 {filename} 失败: {str(e)}", OutputType.WARNING
65
+ )
62
66
 
63
67
  return all_methodologies
64
68
 
69
+
65
70
  def _create_methodology_temp_file(methodologies: Dict[str, str]) -> Optional[str]:
66
71
  """
67
72
  创建包含所有方法论的临时文件
@@ -74,33 +79,34 @@ def _create_methodology_temp_file(methodologies: Dict[str, str]) -> Optional[str
74
79
  """
75
80
  if not methodologies:
76
81
  return None
77
-
82
+
78
83
  try:
79
84
  # 创建临时文件
80
- fd, temp_path = tempfile.mkstemp(suffix='.md', prefix='methodologies_')
85
+ fd, temp_path = tempfile.mkstemp(suffix=".md", prefix="methodologies_")
81
86
  os.close(fd)
82
-
87
+
83
88
  # 写入方法论内容
84
- with open(temp_path, 'w', encoding='utf-8') as f:
89
+ with open(temp_path, "w", encoding="utf-8") as f:
85
90
  f.write("# 方法论集合\n\n")
86
91
  for problem_type, content in methodologies.items():
87
92
  f.write(f"## {problem_type}\n\n")
88
93
  f.write(f"{content}\n\n")
89
94
  f.write("---\n\n")
90
95
  f.flush()
91
-
96
+
92
97
  return temp_path
93
98
  except Exception as e:
94
99
  PrettyOutput.print(f"创建方法论临时文件失败: {str(e)}", OutputType.ERROR)
95
100
  return None
96
101
 
97
- def upload_methodology(platform: BasePlatform) -> bool:
102
+
103
+ def upload_methodology(platform: BasePlatform, other_files: List[str] = []) -> bool:
98
104
  """
99
105
  上传方法论文件到指定平台
100
-
106
+
101
107
  参数:
102
108
  platform: 平台实例,需实现upload_files方法
103
-
109
+
104
110
  返回:
105
111
  bool: 上传是否成功
106
112
  """
@@ -108,19 +114,19 @@ def upload_methodology(platform: BasePlatform) -> bool:
108
114
  if not os.path.exists(methodology_dir):
109
115
  PrettyOutput.print("方法论文档不存在", OutputType.WARNING)
110
116
  return False
111
-
117
+
112
118
  methodologies = _load_all_methodologies()
113
119
  if not methodologies:
114
120
  PrettyOutput.print("没有可用的方法论文档", OutputType.WARNING)
115
121
  return False
116
-
122
+
117
123
  temp_file_path = _create_methodology_temp_file(methodologies)
118
124
  if not temp_file_path:
119
125
  return False
120
-
126
+
121
127
  try:
122
- return platform.upload_files([temp_file_path])
123
-
128
+ return platform.upload_files([temp_file_path, *other_files])
129
+
124
130
  finally:
125
131
  if temp_file_path and os.path.exists(temp_file_path):
126
132
  try:
@@ -141,8 +147,6 @@ def load_methodology(user_input: str, tool_registery: Optional[Any] = None) -> s
141
147
  """
142
148
  from yaspin import yaspin # type: ignore
143
149
 
144
- from jarvis.jarvis_tools.registry import ToolRegistry
145
-
146
150
  prompt = tool_registery.prompt() if tool_registery else ""
147
151
 
148
152
  # 获取方法论目录
@@ -178,7 +182,7 @@ def load_methodology(user_input: str, tool_registery: Optional[Any] = None) -> s
178
182
 
179
183
  full_content += f"以下是所有可用的工具内容:\n\n"
180
184
  full_content += prompt
181
-
185
+
182
186
  # 添加用户输入和输出要求
183
187
  full_content += f"""
184
188
  请根据以上方法论和可调用的工具内容,规划/总结出以下用户需求的执行步骤: {user_input}
@@ -199,7 +203,7 @@ def load_methodology(user_input: str, tool_registery: Optional[Any] = None) -> s
199
203
  # 检查内容是否过大
200
204
  is_large_content = is_context_overflow(full_content)
201
205
  temp_file_path = None
202
-
206
+
203
207
  try:
204
208
  if is_large_content:
205
209
  # 创建临时文件
@@ -214,10 +218,12 @@ def load_methodology(user_input: str, tool_registery: Optional[Any] = None) -> s
214
218
 
215
219
  # 尝试上传文件
216
220
  upload_success = platform.upload_files([temp_file_path])
217
-
221
+
218
222
  if upload_success:
219
223
  # 使用上传的文件生成摘要
220
- return platform.chat_until_success(base_prompt + f"""
224
+ return platform.chat_until_success(
225
+ base_prompt
226
+ + f"""
221
227
  请根据已上传的方法论和可调用的工具文件内容,规划/总结出以下用户需求的执行步骤: {user_input}
222
228
 
223
229
  请按以下格式回复:
@@ -231,12 +237,13 @@ def load_methodology(user_input: str, tool_registery: Optional[Any] = None) -> s
231
237
 
232
238
  如果没有匹配的方法论,请输出:没有历史方法论可参考
233
239
  除以上要求外,不要输出任何内容
234
- """)
240
+ """
241
+ )
235
242
  else:
236
243
  return "没有历史方法论可参考"
237
244
  # 如果内容不大或上传失败,直接使用chat_until_success
238
245
  return platform.chat_until_success(full_content)
239
-
246
+
240
247
  finally:
241
248
  # 清理临时文件
242
249
  if temp_file_path and os.path.exists(temp_file_path):
@@ -244,7 +251,7 @@ def load_methodology(user_input: str, tool_registery: Optional[Any] = None) -> s
244
251
  os.remove(temp_file_path)
245
252
  except Exception:
246
253
  pass
247
-
254
+
248
255
  except Exception as e:
249
256
  PrettyOutput.print(f"加载方法论失败: {str(e)}", OutputType.ERROR)
250
257
  return ""