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.
- jarvis/__init__.py +1 -1
- jarvis/jarvis_agent/__init__.py +1143 -245
- jarvis/jarvis_agent/agent_manager.py +97 -0
- jarvis/jarvis_agent/builtin_input_handler.py +12 -10
- jarvis/jarvis_agent/config_editor.py +57 -0
- jarvis/jarvis_agent/edit_file_handler.py +392 -99
- jarvis/jarvis_agent/event_bus.py +48 -0
- jarvis/jarvis_agent/events.py +157 -0
- jarvis/jarvis_agent/file_context_handler.py +79 -0
- jarvis/jarvis_agent/file_methodology_manager.py +117 -0
- jarvis/jarvis_agent/jarvis.py +1117 -147
- jarvis/jarvis_agent/main.py +78 -34
- jarvis/jarvis_agent/memory_manager.py +195 -0
- jarvis/jarvis_agent/methodology_share_manager.py +174 -0
- jarvis/jarvis_agent/prompt_manager.py +82 -0
- jarvis/jarvis_agent/prompts.py +46 -9
- jarvis/jarvis_agent/protocols.py +4 -1
- jarvis/jarvis_agent/rewrite_file_handler.py +141 -0
- jarvis/jarvis_agent/run_loop.py +146 -0
- jarvis/jarvis_agent/session_manager.py +9 -9
- jarvis/jarvis_agent/share_manager.py +228 -0
- jarvis/jarvis_agent/shell_input_handler.py +23 -3
- jarvis/jarvis_agent/stdio_redirect.py +295 -0
- jarvis/jarvis_agent/task_analyzer.py +212 -0
- jarvis/jarvis_agent/task_manager.py +154 -0
- jarvis/jarvis_agent/task_planner.py +496 -0
- jarvis/jarvis_agent/tool_executor.py +8 -4
- jarvis/jarvis_agent/tool_share_manager.py +139 -0
- jarvis/jarvis_agent/user_interaction.py +42 -0
- jarvis/jarvis_agent/utils.py +54 -0
- jarvis/jarvis_agent/web_bridge.py +189 -0
- jarvis/jarvis_agent/web_output_sink.py +53 -0
- jarvis/jarvis_agent/web_server.py +751 -0
- jarvis/jarvis_c2rust/__init__.py +26 -0
- jarvis/jarvis_c2rust/cli.py +613 -0
- jarvis/jarvis_c2rust/collector.py +258 -0
- jarvis/jarvis_c2rust/library_replacer.py +1122 -0
- jarvis/jarvis_c2rust/llm_module_agent.py +1300 -0
- jarvis/jarvis_c2rust/optimizer.py +960 -0
- jarvis/jarvis_c2rust/scanner.py +1681 -0
- jarvis/jarvis_c2rust/transpiler.py +2325 -0
- jarvis/jarvis_code_agent/build_validation_config.py +133 -0
- jarvis/jarvis_code_agent/code_agent.py +1605 -178
- jarvis/jarvis_code_agent/code_analyzer/__init__.py +62 -0
- jarvis/jarvis_code_agent/code_analyzer/base_language.py +74 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/__init__.py +44 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/base.py +102 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/cmake.py +59 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/detector.py +125 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/fallback.py +69 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/go.py +38 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/java_gradle.py +44 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/java_maven.py +38 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/makefile.py +50 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/nodejs.py +93 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/python.py +129 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/rust.py +54 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/validator.py +154 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator.py +43 -0
- jarvis/jarvis_code_agent/code_analyzer/context_manager.py +363 -0
- jarvis/jarvis_code_agent/code_analyzer/context_recommender.py +18 -0
- jarvis/jarvis_code_agent/code_analyzer/dependency_analyzer.py +132 -0
- jarvis/jarvis_code_agent/code_analyzer/file_ignore.py +330 -0
- jarvis/jarvis_code_agent/code_analyzer/impact_analyzer.py +781 -0
- jarvis/jarvis_code_agent/code_analyzer/language_registry.py +185 -0
- jarvis/jarvis_code_agent/code_analyzer/language_support.py +89 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/__init__.py +31 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/c_cpp_language.py +231 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/go_language.py +183 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/python_language.py +219 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/rust_language.py +209 -0
- jarvis/jarvis_code_agent/code_analyzer/llm_context_recommender.py +451 -0
- jarvis/jarvis_code_agent/code_analyzer/symbol_extractor.py +77 -0
- jarvis/jarvis_code_agent/code_analyzer/tree_sitter_extractor.py +48 -0
- jarvis/jarvis_code_agent/lint.py +275 -13
- jarvis/jarvis_code_agent/utils.py +142 -0
- jarvis/jarvis_code_analysis/checklists/loader.py +20 -6
- jarvis/jarvis_code_analysis/code_review.py +583 -548
- jarvis/jarvis_data/config_schema.json +339 -28
- jarvis/jarvis_git_squash/main.py +22 -13
- jarvis/jarvis_git_utils/git_commiter.py +171 -55
- jarvis/jarvis_mcp/sse_mcp_client.py +22 -15
- jarvis/jarvis_mcp/stdio_mcp_client.py +4 -4
- jarvis/jarvis_mcp/streamable_mcp_client.py +36 -16
- jarvis/jarvis_memory_organizer/memory_organizer.py +753 -0
- jarvis/jarvis_methodology/main.py +48 -63
- jarvis/jarvis_multi_agent/__init__.py +302 -43
- jarvis/jarvis_multi_agent/main.py +70 -24
- jarvis/jarvis_platform/ai8.py +40 -23
- jarvis/jarvis_platform/base.py +210 -49
- jarvis/jarvis_platform/human.py +11 -1
- jarvis/jarvis_platform/kimi.py +82 -76
- jarvis/jarvis_platform/openai.py +73 -1
- jarvis/jarvis_platform/registry.py +8 -15
- jarvis/jarvis_platform/tongyi.py +115 -101
- jarvis/jarvis_platform/yuanbao.py +89 -63
- jarvis/jarvis_platform_manager/main.py +194 -132
- jarvis/jarvis_platform_manager/service.py +122 -86
- jarvis/jarvis_rag/cli.py +156 -53
- jarvis/jarvis_rag/embedding_manager.py +155 -12
- jarvis/jarvis_rag/llm_interface.py +10 -13
- jarvis/jarvis_rag/query_rewriter.py +63 -12
- jarvis/jarvis_rag/rag_pipeline.py +222 -40
- jarvis/jarvis_rag/reranker.py +26 -3
- jarvis/jarvis_rag/retriever.py +270 -14
- jarvis/jarvis_sec/__init__.py +3605 -0
- jarvis/jarvis_sec/checkers/__init__.py +32 -0
- jarvis/jarvis_sec/checkers/c_checker.py +2680 -0
- jarvis/jarvis_sec/checkers/rust_checker.py +1108 -0
- jarvis/jarvis_sec/cli.py +116 -0
- jarvis/jarvis_sec/report.py +257 -0
- jarvis/jarvis_sec/status.py +264 -0
- jarvis/jarvis_sec/types.py +20 -0
- jarvis/jarvis_sec/workflow.py +219 -0
- jarvis/jarvis_smart_shell/main.py +405 -137
- jarvis/jarvis_stats/__init__.py +13 -0
- jarvis/jarvis_stats/cli.py +387 -0
- jarvis/jarvis_stats/stats.py +711 -0
- jarvis/jarvis_stats/storage.py +612 -0
- jarvis/jarvis_stats/visualizer.py +282 -0
- jarvis/jarvis_tools/ask_user.py +1 -0
- jarvis/jarvis_tools/base.py +18 -2
- jarvis/jarvis_tools/clear_memory.py +239 -0
- jarvis/jarvis_tools/cli/main.py +220 -144
- jarvis/jarvis_tools/execute_script.py +52 -12
- jarvis/jarvis_tools/file_analyzer.py +17 -12
- jarvis/jarvis_tools/generate_new_tool.py +46 -24
- jarvis/jarvis_tools/read_code.py +277 -18
- jarvis/jarvis_tools/read_symbols.py +141 -0
- jarvis/jarvis_tools/read_webpage.py +86 -13
- jarvis/jarvis_tools/registry.py +294 -90
- jarvis/jarvis_tools/retrieve_memory.py +227 -0
- jarvis/jarvis_tools/save_memory.py +194 -0
- jarvis/jarvis_tools/search_web.py +62 -28
- jarvis/jarvis_tools/sub_agent.py +205 -0
- jarvis/jarvis_tools/sub_code_agent.py +217 -0
- jarvis/jarvis_tools/virtual_tty.py +330 -62
- jarvis/jarvis_utils/builtin_replace_map.py +4 -5
- jarvis/jarvis_utils/clipboard.py +90 -0
- jarvis/jarvis_utils/config.py +607 -50
- jarvis/jarvis_utils/embedding.py +3 -0
- jarvis/jarvis_utils/fzf.py +57 -0
- jarvis/jarvis_utils/git_utils.py +251 -29
- jarvis/jarvis_utils/globals.py +174 -17
- jarvis/jarvis_utils/http.py +58 -79
- jarvis/jarvis_utils/input.py +899 -153
- jarvis/jarvis_utils/methodology.py +210 -83
- jarvis/jarvis_utils/output.py +220 -137
- jarvis/jarvis_utils/utils.py +1906 -135
- jarvis_ai_assistant-0.7.0.dist-info/METADATA +465 -0
- jarvis_ai_assistant-0.7.0.dist-info/RECORD +192 -0
- {jarvis_ai_assistant-0.1.222.dist-info → jarvis_ai_assistant-0.7.0.dist-info}/entry_points.txt +8 -2
- jarvis/jarvis_git_details/main.py +0 -265
- jarvis/jarvis_platform/oyi.py +0 -357
- jarvis/jarvis_tools/edit_file.py +0 -255
- jarvis/jarvis_tools/rewrite_file.py +0 -195
- jarvis_ai_assistant-0.1.222.dist-info/METADATA +0 -767
- jarvis_ai_assistant-0.1.222.dist-info/RECORD +0 -110
- /jarvis/{jarvis_git_details → jarvis_memory_organizer}/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.222.dist-info → jarvis_ai_assistant-0.7.0.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.1.222.dist-info → jarvis_ai_assistant-0.7.0.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.222.dist-info → jarvis_ai_assistant-0.7.0.dist-info}/top_level.txt +0 -0
jarvis/jarvis_platform/kimi.py
CHANGED
|
@@ -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
|
-
("
|
|
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
|
|
163
|
-
|
|
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
|
-
|
|
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
|
-
|
|
205
|
+
log_lines.append(f"获取上传URL: {file_name}")
|
|
221
206
|
presigned_data = self._get_presigned_url(file_path, action)
|
|
222
207
|
|
|
223
208
|
# 上传文件
|
|
224
|
-
|
|
209
|
+
log_lines.append(f"上传文件: {file_name}")
|
|
225
210
|
if self._upload_file(file_path, presigned_data["url"]):
|
|
226
211
|
# 获取文件信息
|
|
227
|
-
|
|
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
|
-
|
|
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
|
-
|
|
220
|
+
log_lines.append(f"文件处理完成: {file_name}")
|
|
236
221
|
else:
|
|
237
|
-
|
|
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
|
-
|
|
227
|
+
log_lines.append(f"图片处理完成: {file_name}")
|
|
242
228
|
else:
|
|
243
|
-
|
|
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
|
-
|
|
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
|
|
306
|
-
|
|
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
|
+
}
|
jarvis/jarvis_platform/openai.py
CHANGED
|
@@ -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
|
-
|
|
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
|
-
)
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|