jarvis-ai-assistant 0.1.222__py3-none-any.whl → 0.7.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +1143 -245
  3. jarvis/jarvis_agent/agent_manager.py +97 -0
  4. jarvis/jarvis_agent/builtin_input_handler.py +12 -10
  5. jarvis/jarvis_agent/config_editor.py +57 -0
  6. jarvis/jarvis_agent/edit_file_handler.py +392 -99
  7. jarvis/jarvis_agent/event_bus.py +48 -0
  8. jarvis/jarvis_agent/events.py +157 -0
  9. jarvis/jarvis_agent/file_context_handler.py +79 -0
  10. jarvis/jarvis_agent/file_methodology_manager.py +117 -0
  11. jarvis/jarvis_agent/jarvis.py +1117 -147
  12. jarvis/jarvis_agent/main.py +78 -34
  13. jarvis/jarvis_agent/memory_manager.py +195 -0
  14. jarvis/jarvis_agent/methodology_share_manager.py +174 -0
  15. jarvis/jarvis_agent/prompt_manager.py +82 -0
  16. jarvis/jarvis_agent/prompts.py +46 -9
  17. jarvis/jarvis_agent/protocols.py +4 -1
  18. jarvis/jarvis_agent/rewrite_file_handler.py +141 -0
  19. jarvis/jarvis_agent/run_loop.py +146 -0
  20. jarvis/jarvis_agent/session_manager.py +9 -9
  21. jarvis/jarvis_agent/share_manager.py +228 -0
  22. jarvis/jarvis_agent/shell_input_handler.py +23 -3
  23. jarvis/jarvis_agent/stdio_redirect.py +295 -0
  24. jarvis/jarvis_agent/task_analyzer.py +212 -0
  25. jarvis/jarvis_agent/task_manager.py +154 -0
  26. jarvis/jarvis_agent/task_planner.py +496 -0
  27. jarvis/jarvis_agent/tool_executor.py +8 -4
  28. jarvis/jarvis_agent/tool_share_manager.py +139 -0
  29. jarvis/jarvis_agent/user_interaction.py +42 -0
  30. jarvis/jarvis_agent/utils.py +54 -0
  31. jarvis/jarvis_agent/web_bridge.py +189 -0
  32. jarvis/jarvis_agent/web_output_sink.py +53 -0
  33. jarvis/jarvis_agent/web_server.py +751 -0
  34. jarvis/jarvis_c2rust/__init__.py +26 -0
  35. jarvis/jarvis_c2rust/cli.py +613 -0
  36. jarvis/jarvis_c2rust/collector.py +258 -0
  37. jarvis/jarvis_c2rust/library_replacer.py +1122 -0
  38. jarvis/jarvis_c2rust/llm_module_agent.py +1300 -0
  39. jarvis/jarvis_c2rust/optimizer.py +960 -0
  40. jarvis/jarvis_c2rust/scanner.py +1681 -0
  41. jarvis/jarvis_c2rust/transpiler.py +2325 -0
  42. jarvis/jarvis_code_agent/build_validation_config.py +133 -0
  43. jarvis/jarvis_code_agent/code_agent.py +1605 -178
  44. jarvis/jarvis_code_agent/code_analyzer/__init__.py +62 -0
  45. jarvis/jarvis_code_agent/code_analyzer/base_language.py +74 -0
  46. jarvis/jarvis_code_agent/code_analyzer/build_validator/__init__.py +44 -0
  47. jarvis/jarvis_code_agent/code_analyzer/build_validator/base.py +102 -0
  48. jarvis/jarvis_code_agent/code_analyzer/build_validator/cmake.py +59 -0
  49. jarvis/jarvis_code_agent/code_analyzer/build_validator/detector.py +125 -0
  50. jarvis/jarvis_code_agent/code_analyzer/build_validator/fallback.py +69 -0
  51. jarvis/jarvis_code_agent/code_analyzer/build_validator/go.py +38 -0
  52. jarvis/jarvis_code_agent/code_analyzer/build_validator/java_gradle.py +44 -0
  53. jarvis/jarvis_code_agent/code_analyzer/build_validator/java_maven.py +38 -0
  54. jarvis/jarvis_code_agent/code_analyzer/build_validator/makefile.py +50 -0
  55. jarvis/jarvis_code_agent/code_analyzer/build_validator/nodejs.py +93 -0
  56. jarvis/jarvis_code_agent/code_analyzer/build_validator/python.py +129 -0
  57. jarvis/jarvis_code_agent/code_analyzer/build_validator/rust.py +54 -0
  58. jarvis/jarvis_code_agent/code_analyzer/build_validator/validator.py +154 -0
  59. jarvis/jarvis_code_agent/code_analyzer/build_validator.py +43 -0
  60. jarvis/jarvis_code_agent/code_analyzer/context_manager.py +363 -0
  61. jarvis/jarvis_code_agent/code_analyzer/context_recommender.py +18 -0
  62. jarvis/jarvis_code_agent/code_analyzer/dependency_analyzer.py +132 -0
  63. jarvis/jarvis_code_agent/code_analyzer/file_ignore.py +330 -0
  64. jarvis/jarvis_code_agent/code_analyzer/impact_analyzer.py +781 -0
  65. jarvis/jarvis_code_agent/code_analyzer/language_registry.py +185 -0
  66. jarvis/jarvis_code_agent/code_analyzer/language_support.py +89 -0
  67. jarvis/jarvis_code_agent/code_analyzer/languages/__init__.py +31 -0
  68. jarvis/jarvis_code_agent/code_analyzer/languages/c_cpp_language.py +231 -0
  69. jarvis/jarvis_code_agent/code_analyzer/languages/go_language.py +183 -0
  70. jarvis/jarvis_code_agent/code_analyzer/languages/python_language.py +219 -0
  71. jarvis/jarvis_code_agent/code_analyzer/languages/rust_language.py +209 -0
  72. jarvis/jarvis_code_agent/code_analyzer/llm_context_recommender.py +451 -0
  73. jarvis/jarvis_code_agent/code_analyzer/symbol_extractor.py +77 -0
  74. jarvis/jarvis_code_agent/code_analyzer/tree_sitter_extractor.py +48 -0
  75. jarvis/jarvis_code_agent/lint.py +275 -13
  76. jarvis/jarvis_code_agent/utils.py +142 -0
  77. jarvis/jarvis_code_analysis/checklists/loader.py +20 -6
  78. jarvis/jarvis_code_analysis/code_review.py +583 -548
  79. jarvis/jarvis_data/config_schema.json +339 -28
  80. jarvis/jarvis_git_squash/main.py +22 -13
  81. jarvis/jarvis_git_utils/git_commiter.py +171 -55
  82. jarvis/jarvis_mcp/sse_mcp_client.py +22 -15
  83. jarvis/jarvis_mcp/stdio_mcp_client.py +4 -4
  84. jarvis/jarvis_mcp/streamable_mcp_client.py +36 -16
  85. jarvis/jarvis_memory_organizer/memory_organizer.py +753 -0
  86. jarvis/jarvis_methodology/main.py +48 -63
  87. jarvis/jarvis_multi_agent/__init__.py +302 -43
  88. jarvis/jarvis_multi_agent/main.py +70 -24
  89. jarvis/jarvis_platform/ai8.py +40 -23
  90. jarvis/jarvis_platform/base.py +210 -49
  91. jarvis/jarvis_platform/human.py +11 -1
  92. jarvis/jarvis_platform/kimi.py +82 -76
  93. jarvis/jarvis_platform/openai.py +73 -1
  94. jarvis/jarvis_platform/registry.py +8 -15
  95. jarvis/jarvis_platform/tongyi.py +115 -101
  96. jarvis/jarvis_platform/yuanbao.py +89 -63
  97. jarvis/jarvis_platform_manager/main.py +194 -132
  98. jarvis/jarvis_platform_manager/service.py +122 -86
  99. jarvis/jarvis_rag/cli.py +156 -53
  100. jarvis/jarvis_rag/embedding_manager.py +155 -12
  101. jarvis/jarvis_rag/llm_interface.py +10 -13
  102. jarvis/jarvis_rag/query_rewriter.py +63 -12
  103. jarvis/jarvis_rag/rag_pipeline.py +222 -40
  104. jarvis/jarvis_rag/reranker.py +26 -3
  105. jarvis/jarvis_rag/retriever.py +270 -14
  106. jarvis/jarvis_sec/__init__.py +3605 -0
  107. jarvis/jarvis_sec/checkers/__init__.py +32 -0
  108. jarvis/jarvis_sec/checkers/c_checker.py +2680 -0
  109. jarvis/jarvis_sec/checkers/rust_checker.py +1108 -0
  110. jarvis/jarvis_sec/cli.py +116 -0
  111. jarvis/jarvis_sec/report.py +257 -0
  112. jarvis/jarvis_sec/status.py +264 -0
  113. jarvis/jarvis_sec/types.py +20 -0
  114. jarvis/jarvis_sec/workflow.py +219 -0
  115. jarvis/jarvis_smart_shell/main.py +405 -137
  116. jarvis/jarvis_stats/__init__.py +13 -0
  117. jarvis/jarvis_stats/cli.py +387 -0
  118. jarvis/jarvis_stats/stats.py +711 -0
  119. jarvis/jarvis_stats/storage.py +612 -0
  120. jarvis/jarvis_stats/visualizer.py +282 -0
  121. jarvis/jarvis_tools/ask_user.py +1 -0
  122. jarvis/jarvis_tools/base.py +18 -2
  123. jarvis/jarvis_tools/clear_memory.py +239 -0
  124. jarvis/jarvis_tools/cli/main.py +220 -144
  125. jarvis/jarvis_tools/execute_script.py +52 -12
  126. jarvis/jarvis_tools/file_analyzer.py +17 -12
  127. jarvis/jarvis_tools/generate_new_tool.py +46 -24
  128. jarvis/jarvis_tools/read_code.py +277 -18
  129. jarvis/jarvis_tools/read_symbols.py +141 -0
  130. jarvis/jarvis_tools/read_webpage.py +86 -13
  131. jarvis/jarvis_tools/registry.py +294 -90
  132. jarvis/jarvis_tools/retrieve_memory.py +227 -0
  133. jarvis/jarvis_tools/save_memory.py +194 -0
  134. jarvis/jarvis_tools/search_web.py +62 -28
  135. jarvis/jarvis_tools/sub_agent.py +205 -0
  136. jarvis/jarvis_tools/sub_code_agent.py +217 -0
  137. jarvis/jarvis_tools/virtual_tty.py +330 -62
  138. jarvis/jarvis_utils/builtin_replace_map.py +4 -5
  139. jarvis/jarvis_utils/clipboard.py +90 -0
  140. jarvis/jarvis_utils/config.py +607 -50
  141. jarvis/jarvis_utils/embedding.py +3 -0
  142. jarvis/jarvis_utils/fzf.py +57 -0
  143. jarvis/jarvis_utils/git_utils.py +251 -29
  144. jarvis/jarvis_utils/globals.py +174 -17
  145. jarvis/jarvis_utils/http.py +58 -79
  146. jarvis/jarvis_utils/input.py +899 -153
  147. jarvis/jarvis_utils/methodology.py +210 -83
  148. jarvis/jarvis_utils/output.py +220 -137
  149. jarvis/jarvis_utils/utils.py +1906 -135
  150. jarvis_ai_assistant-0.7.0.dist-info/METADATA +465 -0
  151. jarvis_ai_assistant-0.7.0.dist-info/RECORD +192 -0
  152. {jarvis_ai_assistant-0.1.222.dist-info → jarvis_ai_assistant-0.7.0.dist-info}/entry_points.txt +8 -2
  153. jarvis/jarvis_git_details/main.py +0 -265
  154. jarvis/jarvis_platform/oyi.py +0 -357
  155. jarvis/jarvis_tools/edit_file.py +0 -255
  156. jarvis/jarvis_tools/rewrite_file.py +0 -195
  157. jarvis_ai_assistant-0.1.222.dist-info/METADATA +0 -767
  158. jarvis_ai_assistant-0.1.222.dist-info/RECORD +0 -110
  159. /jarvis/{jarvis_git_details → jarvis_memory_organizer}/__init__.py +0 -0
  160. {jarvis_ai_assistant-0.1.222.dist-info → jarvis_ai_assistant-0.7.0.dist-info}/WHEEL +0 -0
  161. {jarvis_ai_assistant-0.1.222.dist-info → jarvis_ai_assistant-0.7.0.dist-info}/licenses/LICENSE +0 -0
  162. {jarvis_ai_assistant-0.1.222.dist-info → jarvis_ai_assistant-0.7.0.dist-info}/top_level.txt +0 -0
@@ -24,8 +24,8 @@ class KimiModel(BasePlatform):
24
24
  def get_model_list(self) -> List[Tuple[str, str]]:
25
25
  """Get model list"""
26
26
  return [
27
- ("kimi", "基于网页的 Kimi,免费接口"),
28
- ("k1", "基于网页的 Kimi,深度思考模型"),
27
+ ("k1.5", "基于网页的 Kimi,免费接口"),
28
+ ("k1.5-thinking", "基于网页的 Kimi,深度思考模型"),
29
29
  ("k2", "基于网页的 Kimi,深度思考模型 K2"),
30
30
  ]
31
31
 
@@ -156,39 +156,24 @@ class KimiModel(BasePlatform):
156
156
  sleep_time=5,
157
157
  )
158
158
 
159
- response_data = b""
160
-
161
159
  # 处理流式响应
162
- for chunk in response_stream:
163
- response_data += chunk
164
-
165
- # 尝试解析SSE格式的数据
166
- try:
167
- # 查找完整的数据行
168
- lines = response_data.decode("utf-8").split("\n")
169
- response_data = b"" # 重置缓冲区
170
-
171
- for line in lines:
172
- if not line.strip():
173
- continue
174
-
175
- # SSE格式的行通常以"data: "开头
176
- if line.startswith("data: "):
177
- try:
178
- data = json.loads(line[6:])
179
- if data.get("event") == "resp":
180
- status = data.get("file_info", {}).get("status")
181
- if status == "parsed":
182
- return True
183
- elif status == "failed":
184
- return False
185
- except json.JSONDecodeError:
186
- continue
187
-
188
- except UnicodeDecodeError:
189
- # 如果解码失败,继续累积数据
160
+ for line in response_stream:
161
+ if not line.strip():
190
162
  continue
191
163
 
164
+ # SSE格式的行通常以"data: "开头
165
+ if line.startswith("data: "):
166
+ try:
167
+ data = json.loads(line[6:])
168
+ if data.get("event") == "resp":
169
+ status = data.get("file_info", {}).get("status")
170
+ if status == "parsed":
171
+ return True
172
+ elif status == "failed":
173
+ return False
174
+ except json.JSONDecodeError:
175
+ continue
176
+
192
177
  retry_count += 1
193
178
  time.sleep(1)
194
179
 
@@ -200,16 +185,16 @@ class KimiModel(BasePlatform):
200
185
  return True
201
186
 
202
187
  if not self.chat_id:
203
- print("🚀 正在创建聊天会话...")
188
+ PrettyOutput.print("正在创建聊天会话...", OutputType.INFO)
204
189
  if not self._create_chat():
205
- print("创建聊天会话失败")
190
+ PrettyOutput.print("创建聊天会话失败", OutputType.ERROR)
206
191
  return False
207
- print("创建聊天会话成功")
192
+ PrettyOutput.print("创建聊天会话成功", OutputType.SUCCESS)
208
193
 
209
194
  uploaded_files = []
210
195
  for index, file_path in enumerate(file_list, 1):
211
196
  file_name = os.path.basename(file_path)
212
- print(f"🔍 处理文件 [{index}/{len(file_list)}]: {file_name}")
197
+ log_lines: List[str] = [f"处理文件 [{index}/{len(file_list)}]: {file_name}"]
213
198
  try:
214
199
  mime_type, _ = mimetypes.guess_type(file_path)
215
200
  action = (
@@ -217,34 +202,40 @@ class KimiModel(BasePlatform):
217
202
  )
218
203
 
219
204
  # 获取预签名URL
220
- print(f"🔍 获取上传URL: {file_name}")
205
+ log_lines.append(f"获取上传URL: {file_name}")
221
206
  presigned_data = self._get_presigned_url(file_path, action)
222
207
 
223
208
  # 上传文件
224
- print(f"🔍 上传文件: {file_name}")
209
+ log_lines.append(f"上传文件: {file_name}")
225
210
  if self._upload_file(file_path, presigned_data["url"]):
226
211
  # 获取文件信息
227
- print(f"🔍 获取文件信息: {file_name}")
212
+ log_lines.append(f"获取文件信息: {file_name}")
228
213
  file_info = self._get_file_info(presigned_data, file_name, action)
229
214
 
230
215
  # 只有文件需要解析
231
216
  if action == "file":
232
- print(f"🔍 等待文件解析: {file_name}")
217
+ log_lines.append(f"等待文件解析: {file_name}")
233
218
  if self._wait_for_parse(file_info["id"]):
234
219
  uploaded_files.append(file_info)
235
- print(f"文件处理完成: {file_name}")
220
+ log_lines.append(f"文件处理完成: {file_name}")
236
221
  else:
237
- print(f"文件解析失败: {file_name}")
222
+ log_lines.append(f"文件解析失败: {file_name}")
223
+ PrettyOutput.print("\n".join(log_lines), OutputType.ERROR)
238
224
  return False
239
225
  else:
240
226
  uploaded_files.append(file_info)
241
- print(f"图片处理完成: {file_name}")
227
+ log_lines.append(f"图片处理完成: {file_name}")
242
228
  else:
243
- print(f"文件上传失败: {file_name}")
229
+ log_lines.append(f"文件上传失败: {file_name}")
230
+ PrettyOutput.print("\n".join(log_lines), OutputType.ERROR)
244
231
  return False
245
232
 
233
+ # 成功路径统一输出本文件的处理日志
234
+ PrettyOutput.print("\n".join(log_lines), OutputType.INFO)
235
+
246
236
  except Exception as e:
247
- print(f"处理文件出错 {file_path}: {str(e)}")
237
+ log_lines.append(f"处理文件出错 {file_path}: {str(e)}")
238
+ PrettyOutput.print("\n".join(log_lines), OutputType.ERROR)
248
239
  return False
249
240
 
250
241
  self.uploaded_files = uploaded_files
@@ -299,40 +290,25 @@ class KimiModel(BasePlatform):
299
290
  sleep_time=5,
300
291
  )
301
292
 
302
- response_data = b""
303
-
304
293
  # 处理流式响应
305
- for chunk in response_stream:
306
- response_data += chunk
307
-
308
- # 尝试解析SSE格式的数据
309
- try:
310
- # 查找完整的数据行
311
- lines = response_data.decode("utf-8").split("\n")
312
- response_data = b"" # 重置缓冲区
313
-
314
- for line in lines:
315
- if not line.strip():
316
- continue
317
-
318
- # SSE格式的行通常以"data: "开头
319
- if line.startswith("data: "):
320
- try:
321
- data = json.loads(line[6:])
322
- event = data.get("event")
323
-
324
- if event == "cmpl":
325
- # 处理补全文本
326
- text = data.get("text", "")
327
- if text:
328
- yield text
329
- except json.JSONDecodeError:
330
- continue
331
-
332
- except UnicodeDecodeError:
333
- # 如果解码失败,继续累积数据
294
+ for line in response_stream:
295
+ if not line.strip():
334
296
  continue
335
297
 
298
+ # SSE格式的行通常以"data: "开头
299
+ if line.startswith("data: "):
300
+ try:
301
+ data = json.loads(line[6:])
302
+ event = data.get("event")
303
+
304
+ if event == "cmpl":
305
+ # 处理补全文本
306
+ text = data.get("text", "")
307
+ if text:
308
+ yield text
309
+ except json.JSONDecodeError:
310
+ continue
311
+
336
312
  return None
337
313
 
338
314
  except Exception as e:
@@ -425,3 +401,33 @@ class KimiModel(BasePlatform):
425
401
  def support_web(self) -> bool:
426
402
  """Kimi平台支持web功能"""
427
403
  return True
404
+
405
+ @classmethod
406
+ def get_required_env_keys(cls) -> List[str]:
407
+ """
408
+ 获取Kimi平台所需的环境变量键列表
409
+
410
+ 返回:
411
+ List[str]: 环境变量键的列表
412
+ """
413
+ return ["KIMI_API_KEY"]
414
+
415
+ @classmethod
416
+ def get_env_config_guide(cls) -> Dict[str, str]:
417
+ """
418
+ 获取环境变量配置指导
419
+
420
+ 返回:
421
+ Dict[str, str]: 环境变量名到配置指导的映射
422
+ """
423
+ return {
424
+ "KIMI_API_KEY": (
425
+ "1. 登录 Kimi 网页版: https://kimi.moonshot.cn/\n"
426
+ "2. 打开浏览器开发者工具 (F12)\n"
427
+ '3. 切换到"网络"(Network)标签页\n'
428
+ "4. 在 Kimi 中发送一条消息\n"
429
+ "5. 找到 stream 请求\n"
430
+ '6. 在"请求标头"中找到 authorization 字段\n'
431
+ "7. 复制 Bearer 后面的 API Key 部分"
432
+ )
433
+ }
@@ -24,7 +24,32 @@ class OpenAIModel(BasePlatform):
24
24
  self.base_url = os.getenv("OPENAI_API_BASE", "https://api.openai.com/v1")
25
25
  self.model_name = os.getenv("JARVIS_MODEL") or "gpt-4o"
26
26
 
27
- self.client = OpenAI(api_key=self.api_key, base_url=self.base_url)
27
+ # Optional: Inject extra HTTP headers via environment variable
28
+ # Expected format: OPENAI_EXTRA_HEADERS='{"Header-Name": "value", "X-Trace": "abc"}'
29
+ headers_str = os.getenv("OPENAI_EXTRA_HEADERS")
30
+ self.extra_headers: Dict[str, str] = {}
31
+ if headers_str:
32
+ try:
33
+ parsed = json.loads(headers_str)
34
+ if isinstance(parsed, dict):
35
+ # Ensure all header keys/values are strings
36
+ self.extra_headers = {str(k): str(v) for k, v in parsed.items()}
37
+ else:
38
+ PrettyOutput.print("OPENAI_EXTRA_HEADERS 应为 JSON 对象,如 {'X-Source':'jarvis'}", OutputType.WARNING)
39
+ except Exception as e:
40
+ PrettyOutput.print(f"解析 OPENAI_EXTRA_HEADERS 失败: {e}", OutputType.WARNING)
41
+
42
+ # Initialize OpenAI client, try to pass default headers if SDK supports it
43
+ try:
44
+ if self.extra_headers:
45
+ self.client = OpenAI(api_key=self.api_key, base_url=self.base_url, default_headers=self.extra_headers)
46
+ else:
47
+ self.client = OpenAI(api_key=self.api_key, base_url=self.base_url)
48
+ except TypeError:
49
+ # Fallback: SDK version may not support default_headers
50
+ self.client = OpenAI(api_key=self.api_key, base_url=self.base_url)
51
+ if self.extra_headers:
52
+ PrettyOutput.print("当前 OpenAI SDK 不支持 default_headers,未能注入额外 HTTP 头", OutputType.WARNING)
28
53
  self.messages: List[Dict[str, str]] = []
29
54
  self.system_message = ""
30
55
 
@@ -211,3 +236,50 @@ class OpenAIModel(BasePlatform):
211
236
  bool: 当前是否支持上传文件 (OpenAI平台始终返回False)
212
237
  """
213
238
  return False
239
+
240
+ @classmethod
241
+ def get_required_env_keys(cls) -> List[str]:
242
+ """
243
+ 获取OpenAI平台所需的环境变量键列表
244
+
245
+ 返回:
246
+ List[str]: 环境变量键的列表
247
+ """
248
+ return ["OPENAI_API_KEY", "OPENAI_API_BASE"]
249
+
250
+ @classmethod
251
+ def get_env_config_guide(cls) -> Dict[str, str]:
252
+ """
253
+ 获取环境变量配置指导
254
+
255
+ 返回:
256
+ Dict[str, str]: 环境变量名到配置指导的映射
257
+ """
258
+ return {
259
+ "OPENAI_API_KEY": (
260
+ "请输入您的 OpenAI API Key:\n"
261
+ "获取方式一(官方):\n"
262
+ "1. 登录 OpenAI 平台: https://platform.openai.com/\n"
263
+ "2. 进入 API Keys 页面\n"
264
+ "3. 创建新的 API Key 或使用现有的\n"
265
+ "4. 复制 API Key (以 sk- 开头)\n"
266
+ "\n获取方式二(第三方代理):\n"
267
+ "如果使用第三方代理服务,请从代理服务商处获取 API Key"
268
+ ),
269
+ "OPENAI_API_BASE": (
270
+ "请输入 API Base URL:\n"
271
+ "- 官方 API: https://api.openai.com/v1\n"
272
+ "- 如使用代理或第三方服务,请输入对应的 Base URL\n"
273
+ "- 例如: https://your-proxy.com/v1"
274
+ ),
275
+ }
276
+
277
+ @classmethod
278
+ def get_env_defaults(cls) -> Dict[str, str]:
279
+ """
280
+ 获取OpenAI平台环境变量的默认值
281
+
282
+ 返回:
283
+ Dict[str, str]: 环境变量默认值的字典
284
+ """
285
+ return {"OPENAI_API_BASE": "https://api.openai.com/v1"}
@@ -10,8 +10,6 @@ from jarvis.jarvis_utils.config import (
10
10
  get_data_dir,
11
11
  get_normal_model_name,
12
12
  get_normal_platform_name,
13
- get_thinking_model_name,
14
- get_thinking_platform_name,
15
13
  )
16
14
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
17
15
 
@@ -41,7 +39,7 @@ class PlatformRegistry:
41
39
  # 创建 __init__.py 使其成为 Python 包
42
40
  with open(
43
41
  os.path.join(user_platform_dir, "__init__.py"), "w", errors="ignore"
44
- ) as f:
42
+ ):
45
43
  pass
46
44
  except Exception as e:
47
45
  PrettyOutput.print(f"创建平台目录失败: {str(e)}", OutputType.ERROR)
@@ -113,6 +111,7 @@ class PlatformRegistry:
113
111
  if directory not in sys.path:
114
112
  sys.path.append(directory)
115
113
 
114
+ error_lines = []
116
115
  # 遍历目录下的所有.py文件
117
116
  for filename in os.listdir(directory):
118
117
  if filename.endswith(".py") and not filename.startswith("__"):
@@ -142,16 +141,15 @@ class PlatformRegistry:
142
141
  platform_name = obj.platform_name()
143
142
  platforms[platform_name] = obj
144
143
  except Exception as e:
145
- PrettyOutput.print(
146
- f"实例化或注册平台失败 {obj.__name__}: {str(e)}",
147
- OutputType.ERROR,
144
+ error_lines.append(
145
+ f"实例化或注册平台失败 {obj.__name__}: {str(e)}"
148
146
  )
149
147
  break
150
148
  except Exception as e:
151
- PrettyOutput.print(
152
- f"加载平台 {module_name} 失败: {str(e)}", OutputType.ERROR
153
- )
149
+ error_lines.append(f"加载平台 {module_name} 失败: {str(e)}")
154
150
 
151
+ if error_lines:
152
+ PrettyOutput.print("\n".join(error_lines), OutputType.ERROR)
155
153
  return platforms
156
154
 
157
155
  @staticmethod
@@ -187,12 +185,7 @@ class PlatformRegistry:
187
185
  platform.set_model_name(model_name) # type: ignore
188
186
  return platform # type: ignore
189
187
 
190
- def get_thinking_platform(self) -> BasePlatform:
191
- platform_name = get_thinking_platform_name()
192
- model_name = get_thinking_model_name()
193
- platform = self.create_platform(platform_name)
194
- platform.set_model_name(model_name) # type: ignore
195
- return platform # type: ignore
188
+
196
189
 
197
190
  def register_platform(self, name: str, platform_class: Type[BasePlatform]) -> None:
198
191
  """Register platform class