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
|
@@ -3,33 +3,47 @@
|
|
|
3
3
|
|
|
4
4
|
该模块提供了Jarvis平台管理器的主要入口点。
|
|
5
5
|
"""
|
|
6
|
-
import argparse
|
|
7
6
|
import os
|
|
7
|
+
import sys
|
|
8
8
|
from typing import Any, Dict, List, Optional
|
|
9
9
|
|
|
10
|
+
import typer
|
|
11
|
+
from jarvis.jarvis_utils.config import (
|
|
12
|
+
get_normal_platform_name,
|
|
13
|
+
get_normal_model_name,
|
|
14
|
+
)
|
|
15
|
+
|
|
10
16
|
from jarvis.jarvis_platform.registry import PlatformRegistry
|
|
11
17
|
from jarvis.jarvis_utils.input import get_multiline_input, get_single_line_input
|
|
12
18
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
13
19
|
from jarvis.jarvis_utils.utils import init_env
|
|
14
20
|
from jarvis.jarvis_platform_manager.service import start_service
|
|
21
|
+
from jarvis.jarvis_utils.fzf import fzf_select
|
|
22
|
+
|
|
23
|
+
app = typer.Typer(help="Jarvis AI 平台")
|
|
15
24
|
|
|
16
25
|
|
|
17
|
-
|
|
18
|
-
|
|
26
|
+
@app.command("info")
|
|
27
|
+
def list_platforms(
|
|
28
|
+
platform: Optional[str] = typer.Option(
|
|
29
|
+
None, "--platform", "-p", help="指定要查看的平台"
|
|
30
|
+
)
|
|
31
|
+
) -> None:
|
|
32
|
+
"""列出所有支持的平台和模型,或指定平台的详细信息。"""
|
|
19
33
|
registry = PlatformRegistry.get_global_platform_registry()
|
|
20
|
-
|
|
34
|
+
platform_names = [platform] if platform else registry.get_available_platforms()
|
|
21
35
|
|
|
22
36
|
PrettyOutput.section("Supported platforms and models", OutputType.SUCCESS)
|
|
23
37
|
|
|
24
|
-
for platform_name in
|
|
25
|
-
# Create platform instance
|
|
26
|
-
platform = registry.create_platform(platform_name)
|
|
27
|
-
if not platform:
|
|
28
|
-
continue
|
|
29
|
-
|
|
30
|
-
# Get the list of models supported by the platform
|
|
38
|
+
for platform_name in platform_names:
|
|
31
39
|
try:
|
|
32
|
-
|
|
40
|
+
# Create platform instance
|
|
41
|
+
platform_instance = registry.create_platform(platform_name)
|
|
42
|
+
if not platform_instance:
|
|
43
|
+
continue
|
|
44
|
+
|
|
45
|
+
# Get the list of models supported by the platform
|
|
46
|
+
models = platform_instance.get_model_list()
|
|
33
47
|
|
|
34
48
|
# Print platform name
|
|
35
49
|
PrettyOutput.section(f"{platform_name}", OutputType.SUCCESS)
|
|
@@ -46,19 +60,29 @@ def list_platforms() -> None:
|
|
|
46
60
|
else:
|
|
47
61
|
PrettyOutput.print(" • 没有可用的模型信息", OutputType.WARNING)
|
|
48
62
|
|
|
49
|
-
except Exception
|
|
50
|
-
PrettyOutput.print(
|
|
51
|
-
|
|
52
|
-
)
|
|
63
|
+
except Exception:
|
|
64
|
+
PrettyOutput.print(f"创建 {platform_name} 平台失败", OutputType.WARNING)
|
|
65
|
+
|
|
53
66
|
|
|
67
|
+
def chat_with_model(
|
|
68
|
+
platform_name: str, model_name: str, system_prompt: str
|
|
69
|
+
) -> None:
|
|
70
|
+
"""与指定平台和模型进行对话。
|
|
54
71
|
|
|
55
|
-
|
|
56
|
-
|
|
72
|
+
参数:
|
|
73
|
+
platform_name: 平台名称
|
|
74
|
+
model_name: 模型名称
|
|
75
|
+
system_prompt: 系统提示语
|
|
76
|
+
|
|
77
|
+
"""
|
|
57
78
|
registry = PlatformRegistry.get_global_platform_registry()
|
|
58
79
|
conversation_history: List[Dict[str, str]] = [] # 存储对话记录
|
|
59
80
|
|
|
60
81
|
# Create platform instance
|
|
61
82
|
platform = registry.create_platform(platform_name)
|
|
83
|
+
if platform:
|
|
84
|
+
platform.set_model_name(model_name)
|
|
85
|
+
|
|
62
86
|
if not platform:
|
|
63
87
|
PrettyOutput.print(f"创建平台 {platform_name} 失败", OutputType.WARNING)
|
|
64
88
|
return
|
|
@@ -94,10 +118,16 @@ def chat_with_model(platform_name: str, model_name: str, system_prompt: str) ->
|
|
|
94
118
|
PrettyOutput.print("检测到空输入,退出聊天", OutputType.INFO)
|
|
95
119
|
break
|
|
96
120
|
|
|
121
|
+
# Parse command and arguments
|
|
122
|
+
stripped_input = user_input.strip()
|
|
123
|
+
parts = stripped_input.split(None, 1)
|
|
124
|
+
command = parts[0] if parts else ""
|
|
125
|
+
args = parts[1] if len(parts) > 1 else ""
|
|
126
|
+
|
|
97
127
|
# Check if it is a clear session command
|
|
98
|
-
if
|
|
128
|
+
if command == "/clear":
|
|
99
129
|
try:
|
|
100
|
-
platform.reset()
|
|
130
|
+
platform.reset() # type: ignore[no-untyped-call] # type: ignore[no-untyped-call] # type: ignore[no-untyped-call]
|
|
101
131
|
platform.set_model_name(model_name) # Reinitialize session
|
|
102
132
|
conversation_history = [] # 重置对话记录
|
|
103
133
|
PrettyOutput.print("会话已清除", OutputType.SUCCESS)
|
|
@@ -106,9 +136,9 @@ def chat_with_model(platform_name: str, model_name: str, system_prompt: str) ->
|
|
|
106
136
|
continue
|
|
107
137
|
|
|
108
138
|
# Check if it is an upload command
|
|
109
|
-
if
|
|
139
|
+
if command == "/upload":
|
|
110
140
|
try:
|
|
111
|
-
file_path =
|
|
141
|
+
file_path = args
|
|
112
142
|
if not file_path:
|
|
113
143
|
PrettyOutput.print(
|
|
114
144
|
'请指定要上传的文件路径,例如: /upload /path/to/file 或 /upload "/path/with spaces/file"',
|
|
@@ -136,9 +166,9 @@ def chat_with_model(platform_name: str, model_name: str, system_prompt: str) ->
|
|
|
136
166
|
continue
|
|
137
167
|
|
|
138
168
|
# Check if it is a save command
|
|
139
|
-
if
|
|
169
|
+
if command == "/save":
|
|
140
170
|
try:
|
|
141
|
-
file_path =
|
|
171
|
+
file_path = args
|
|
142
172
|
if not file_path:
|
|
143
173
|
PrettyOutput.print(
|
|
144
174
|
"请指定保存文件名,例如: /save last_message.txt",
|
|
@@ -167,9 +197,9 @@ def chat_with_model(platform_name: str, model_name: str, system_prompt: str) ->
|
|
|
167
197
|
continue
|
|
168
198
|
|
|
169
199
|
# Check if it is a saveall command
|
|
170
|
-
if
|
|
200
|
+
if command == "/saveall":
|
|
171
201
|
try:
|
|
172
|
-
file_path =
|
|
202
|
+
file_path = args
|
|
173
203
|
if not file_path:
|
|
174
204
|
PrettyOutput.print(
|
|
175
205
|
"请指定保存文件名,例如: /saveall all_conversations.txt",
|
|
@@ -188,15 +218,19 @@ def chat_with_model(platform_name: str, model_name: str, system_prompt: str) ->
|
|
|
188
218
|
for entry in conversation_history:
|
|
189
219
|
file_obj.write(f"{entry['role']}: {entry['content']}\n\n")
|
|
190
220
|
|
|
191
|
-
PrettyOutput.print(
|
|
221
|
+
PrettyOutput.print(
|
|
222
|
+
f"所有对话已保存到 {file_path}", OutputType.SUCCESS
|
|
223
|
+
)
|
|
192
224
|
except Exception as exc:
|
|
193
|
-
PrettyOutput.print(
|
|
225
|
+
PrettyOutput.print(
|
|
226
|
+
f"保存所有对话失败: {str(exc)}", OutputType.ERROR
|
|
227
|
+
)
|
|
194
228
|
continue
|
|
195
229
|
|
|
196
230
|
# Check if it is a save_session command
|
|
197
|
-
if
|
|
231
|
+
if command == "/save_session":
|
|
198
232
|
try:
|
|
199
|
-
file_path =
|
|
233
|
+
file_path = args
|
|
200
234
|
if not file_path:
|
|
201
235
|
PrettyOutput.print(
|
|
202
236
|
"请指定保存会话的文件名,例如: /save_session session.json",
|
|
@@ -211,7 +245,9 @@ def chat_with_model(platform_name: str, model_name: str, system_prompt: str) ->
|
|
|
211
245
|
file_path = file_path[1:-1]
|
|
212
246
|
|
|
213
247
|
if platform.save(file_path):
|
|
214
|
-
PrettyOutput.print(
|
|
248
|
+
PrettyOutput.print(
|
|
249
|
+
f"会话已保存到 {file_path}", OutputType.SUCCESS
|
|
250
|
+
)
|
|
215
251
|
else:
|
|
216
252
|
PrettyOutput.print("保存会话失败", OutputType.ERROR)
|
|
217
253
|
except Exception as exc:
|
|
@@ -219,9 +255,9 @@ def chat_with_model(platform_name: str, model_name: str, system_prompt: str) ->
|
|
|
219
255
|
continue
|
|
220
256
|
|
|
221
257
|
# Check if it is a load_session command
|
|
222
|
-
if
|
|
258
|
+
if command == "/load_session":
|
|
223
259
|
try:
|
|
224
|
-
file_path =
|
|
260
|
+
file_path = args
|
|
225
261
|
if not file_path:
|
|
226
262
|
PrettyOutput.print(
|
|
227
263
|
"请指定加载会话的文件名,例如: /load_session session.json",
|
|
@@ -237,7 +273,9 @@ def chat_with_model(platform_name: str, model_name: str, system_prompt: str) ->
|
|
|
237
273
|
|
|
238
274
|
if platform.restore(file_path):
|
|
239
275
|
conversation_history = [] # Clear local history after loading
|
|
240
|
-
PrettyOutput.print(
|
|
276
|
+
PrettyOutput.print(
|
|
277
|
+
f"会话已从 {file_path} 加载", OutputType.SUCCESS
|
|
278
|
+
)
|
|
241
279
|
else:
|
|
242
280
|
PrettyOutput.print("加载会话失败", OutputType.ERROR)
|
|
243
281
|
except Exception as exc:
|
|
@@ -245,18 +283,18 @@ def chat_with_model(platform_name: str, model_name: str, system_prompt: str) ->
|
|
|
245
283
|
continue
|
|
246
284
|
|
|
247
285
|
# Check if it is a shell command
|
|
248
|
-
if
|
|
286
|
+
if command == "/shell":
|
|
249
287
|
try:
|
|
250
|
-
|
|
251
|
-
if not
|
|
288
|
+
shell_command = args
|
|
289
|
+
if not shell_command:
|
|
252
290
|
PrettyOutput.print(
|
|
253
291
|
"请指定要执行的shell命令,例如: /shell ls -l",
|
|
254
292
|
OutputType.WARNING,
|
|
255
293
|
)
|
|
256
294
|
continue
|
|
257
295
|
|
|
258
|
-
PrettyOutput.print(f"执行命令: {
|
|
259
|
-
return_code = os.system(
|
|
296
|
+
PrettyOutput.print(f"执行命令: {shell_command}", OutputType.INFO)
|
|
297
|
+
return_code = os.system(shell_command)
|
|
260
298
|
if return_code == 0:
|
|
261
299
|
PrettyOutput.print("命令执行完成", OutputType.SUCCESS)
|
|
262
300
|
else:
|
|
@@ -283,8 +321,11 @@ def chat_with_model(platform_name: str, model_name: str, system_prompt: str) ->
|
|
|
283
321
|
except Exception as exc:
|
|
284
322
|
PrettyOutput.print(f"聊天失败: {str(exc)}", OutputType.ERROR)
|
|
285
323
|
|
|
324
|
+
except typer.Exit:
|
|
325
|
+
raise
|
|
286
326
|
except Exception as exc:
|
|
287
327
|
PrettyOutput.print(f"初始化会话失败: {str(exc)}", OutputType.ERROR)
|
|
328
|
+
sys.exit(1)
|
|
288
329
|
finally:
|
|
289
330
|
# Clean up resources
|
|
290
331
|
try:
|
|
@@ -293,16 +334,17 @@ def chat_with_model(platform_name: str, model_name: str, system_prompt: str) ->
|
|
|
293
334
|
pass
|
|
294
335
|
|
|
295
336
|
|
|
296
|
-
def validate_platform_model(
|
|
337
|
+
def validate_platform_model(platform: Optional[str], model: Optional[str]) -> bool:
|
|
297
338
|
"""验证平台和模型参数。
|
|
298
339
|
|
|
299
340
|
参数:
|
|
300
|
-
|
|
341
|
+
platform: 平台名称。
|
|
342
|
+
model: 模型名称。
|
|
301
343
|
|
|
302
344
|
返回:
|
|
303
345
|
bool: 如果平台和模型有效返回True,否则返回False。
|
|
304
346
|
"""
|
|
305
|
-
if not
|
|
347
|
+
if not platform or not model:
|
|
306
348
|
PrettyOutput.print(
|
|
307
349
|
"请指定平台和模型。使用 'jarvis info' 查看可用平台和模型。",
|
|
308
350
|
OutputType.WARNING,
|
|
@@ -311,38 +353,43 @@ def validate_platform_model(args: argparse.Namespace) -> bool:
|
|
|
311
353
|
return True
|
|
312
354
|
|
|
313
355
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
"""
|
|
320
|
-
if not validate_platform_model(args):
|
|
321
|
-
return
|
|
322
|
-
chat_with_model(args.platform, args.model, "")
|
|
323
|
-
|
|
356
|
+
@app.command("chat")
|
|
357
|
+
def chat_command(
|
|
358
|
+
platform: Optional[str] = typer.Option(
|
|
359
|
+
None, "--platform", "-p", help="指定要使用的平台"
|
|
360
|
+
),
|
|
361
|
+
model: Optional[str] = typer.Option(None, "--model", "-m", help="指定要使用的模型"),
|
|
324
362
|
|
|
325
|
-
|
|
326
|
-
|
|
363
|
+
llm_group: Optional[str] = typer.Option(
|
|
364
|
+
None, "-g", "--llm-group", help="使用的模型组,覆盖配置文件中的设置"
|
|
365
|
+
),
|
|
366
|
+
) -> None:
|
|
367
|
+
"""与指定平台和模型聊天。"""
|
|
368
|
+
# 如果未提供平台或模型参数,则从config获取默认值
|
|
369
|
+
platform = platform or get_normal_platform_name(llm_group)
|
|
370
|
+
model = model or get_normal_model_name(llm_group)
|
|
327
371
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
""
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
def service_command(
|
|
335
|
-
"""
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
372
|
+
if not validate_platform_model(platform, model):
|
|
373
|
+
return
|
|
374
|
+
chat_with_model(platform, model, "")
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
@app.command("service")
|
|
378
|
+
def service_command(
|
|
379
|
+
host: str = typer.Option("127.0.0.1", help="服务主机地址 (默认: 127.0.0.1)"),
|
|
380
|
+
port: int = typer.Option(8000, help="服务端口 (默认: 8000)"),
|
|
381
|
+
platform: Optional[str] = typer.Option(
|
|
382
|
+
None, "-p", "--platform", help="指定默认平台,当客户端未指定平台时使用"
|
|
383
|
+
),
|
|
384
|
+
model: Optional[str] = typer.Option(
|
|
385
|
+
None, "-m", "--model", help="指定默认模型,当客户端未指定平台时使用"
|
|
386
|
+
),
|
|
387
|
+
) -> None:
|
|
388
|
+
"""启动OpenAI兼容的API服务。"""
|
|
389
|
+
# 如果未提供平台或模型参数,则从config获取默认值
|
|
390
|
+
platform = platform or get_normal_platform_name()
|
|
391
|
+
model = model or get_normal_model_name()
|
|
392
|
+
start_service(host=host, port=port, default_platform=platform, default_model=model)
|
|
346
393
|
|
|
347
394
|
|
|
348
395
|
def load_role_config(config_path: str) -> Dict[str, Any]:
|
|
@@ -369,13 +416,28 @@ def load_role_config(config_path: str) -> Dict[str, Any]:
|
|
|
369
416
|
return {}
|
|
370
417
|
|
|
371
418
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
419
|
+
@app.command("role")
|
|
420
|
+
def role_command(
|
|
421
|
+
config_file: str = typer.Option(
|
|
422
|
+
"~/.jarvis/roles.yaml",
|
|
423
|
+
"--config",
|
|
424
|
+
"-c",
|
|
425
|
+
help="角色配置文件路径(YAML格式,默认: ~/.jarvis/roles.yaml)",
|
|
426
|
+
),
|
|
427
|
+
platform: Optional[str] = typer.Option(
|
|
428
|
+
None, "--platform", "-p", help="指定要使用的平台,覆盖角色配置"
|
|
429
|
+
),
|
|
430
|
+
model: Optional[str] = typer.Option(
|
|
431
|
+
None, "--model", "-m", help="指定要使用的模型,覆盖角色配置"
|
|
432
|
+
),
|
|
433
|
+
|
|
434
|
+
llm_group: Optional[str] = typer.Option(
|
|
435
|
+
None, "-g", "--llm-group", help="使用的模型组,覆盖配置文件中的设置"
|
|
436
|
+
),
|
|
437
|
+
) -> None:
|
|
438
|
+
"""加载角色配置文件并开始对话。"""
|
|
439
|
+
config_path = os.path.expanduser(config_file)
|
|
440
|
+
config = load_role_config(config_path)
|
|
379
441
|
if not config or "roles" not in config:
|
|
380
442
|
PrettyOutput.print("无效的角色配置文件", OutputType.ERROR)
|
|
381
443
|
return
|
|
@@ -390,17 +452,60 @@ def role_command(args: argparse.Namespace) -> None:
|
|
|
390
452
|
)
|
|
391
453
|
PrettyOutput.print(output_str, OutputType.INFO)
|
|
392
454
|
|
|
393
|
-
#
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
455
|
+
# 让用户选择角色(优先 fzf,回退编号输入)
|
|
456
|
+
selected_role = None # type: ignore[var-annotated]
|
|
457
|
+
fzf_options = [
|
|
458
|
+
f"{i:>3} | {role['name']} - {role.get('description', '')}"
|
|
459
|
+
for i, role in enumerate(config["roles"], 1)
|
|
460
|
+
]
|
|
461
|
+
selected_str = fzf_select(fzf_options, prompt="选择角色编号 (Enter退出) > ")
|
|
462
|
+
if selected_str:
|
|
463
|
+
try:
|
|
464
|
+
num_part = selected_str.split("|", 1)[0].strip()
|
|
465
|
+
idx = int(num_part)
|
|
466
|
+
if 1 <= idx <= len(config["roles"]):
|
|
467
|
+
selected_role = config["roles"][idx - 1]
|
|
468
|
+
except Exception:
|
|
469
|
+
selected_role = None
|
|
470
|
+
|
|
471
|
+
if selected_role is None:
|
|
472
|
+
raw_choice = get_single_line_input("请选择角色(输入编号,直接回车退出): ")
|
|
473
|
+
if not raw_choice.strip():
|
|
474
|
+
PrettyOutput.print("已取消,退出程序", OutputType.INFO)
|
|
475
|
+
raise typer.Exit(code=0)
|
|
476
|
+
try:
|
|
477
|
+
choice = int(raw_choice)
|
|
478
|
+
selected_role = config["roles"][choice - 1]
|
|
479
|
+
except (ValueError, IndexError):
|
|
480
|
+
PrettyOutput.print("无效的选择", OutputType.ERROR)
|
|
481
|
+
return
|
|
482
|
+
|
|
483
|
+
|
|
400
484
|
|
|
401
485
|
# 初始化平台和模型
|
|
402
|
-
|
|
403
|
-
|
|
486
|
+
# 如果提供了platform或model参数,优先使用命令行参数
|
|
487
|
+
# 否则,如果提供了 llm_group,则从配置中获取
|
|
488
|
+
# 最后才使用角色配置中的platform和model
|
|
489
|
+
if platform:
|
|
490
|
+
platform_name = platform
|
|
491
|
+
elif llm_group:
|
|
492
|
+
platform_name = get_normal_platform_name(llm_group)
|
|
493
|
+
else:
|
|
494
|
+
platform_name = selected_role.get("platform")
|
|
495
|
+
if not platform_name:
|
|
496
|
+
# 如果角色配置中没有platform,使用默认配置
|
|
497
|
+
platform_name = get_normal_platform_name()
|
|
498
|
+
|
|
499
|
+
if model:
|
|
500
|
+
model_name = model
|
|
501
|
+
elif llm_group:
|
|
502
|
+
model_name = get_normal_model_name(llm_group)
|
|
503
|
+
else:
|
|
504
|
+
model_name = selected_role.get("model")
|
|
505
|
+
if not model_name:
|
|
506
|
+
# 如果角色配置中没有model,使用默认配置
|
|
507
|
+
model_name = get_normal_model_name()
|
|
508
|
+
|
|
404
509
|
system_prompt = selected_role.get("system_prompt", "")
|
|
405
510
|
|
|
406
511
|
# 开始对话
|
|
@@ -411,50 +516,7 @@ def role_command(args: argparse.Namespace) -> None:
|
|
|
411
516
|
def main() -> None:
|
|
412
517
|
"""Jarvis平台管理器的主入口点。"""
|
|
413
518
|
init_env("欢迎使用 Jarvis-PlatformManager,您的平台管理助手已准备就绪!")
|
|
414
|
-
|
|
415
|
-
parser = argparse.ArgumentParser(description="Jarvis AI 平台")
|
|
416
|
-
subparsers = parser.add_subparsers(dest="command", help="可用子命令")
|
|
417
|
-
|
|
418
|
-
# info subcommand
|
|
419
|
-
info_parser = subparsers.add_parser("info", help="显示支持的平台和模型信息")
|
|
420
|
-
info_parser.set_defaults(func=info_command)
|
|
421
|
-
|
|
422
|
-
# chat subcommand
|
|
423
|
-
chat_parser = subparsers.add_parser("chat", help="与指定平台和模型聊天")
|
|
424
|
-
chat_parser.add_argument("--platform", "-p", help="指定要使用的平台")
|
|
425
|
-
chat_parser.add_argument("--model", "-m", help="指定要使用的模型")
|
|
426
|
-
chat_parser.set_defaults(func=chat_command)
|
|
427
|
-
|
|
428
|
-
# service subcommand
|
|
429
|
-
service_parser = subparsers.add_parser("service", help="启动OpenAI兼容的API服务")
|
|
430
|
-
service_parser.add_argument(
|
|
431
|
-
"--host", default="127.0.0.1", help="服务主机地址 (默认: 127.0.0.1)"
|
|
432
|
-
)
|
|
433
|
-
service_parser.add_argument(
|
|
434
|
-
"--port", type=int, default=8000, help="服务端口 (默认: 8000)"
|
|
435
|
-
)
|
|
436
|
-
service_parser.add_argument("--platform", "-p", help="指定默认平台,当客户端未指定平台时使用")
|
|
437
|
-
service_parser.add_argument("--model", "-m", help="指定默认模型,当客户端未指定平台时使用")
|
|
438
|
-
service_parser.set_defaults(func=service_command)
|
|
439
|
-
|
|
440
|
-
# role subcommand
|
|
441
|
-
role_parser = subparsers.add_parser("role", help="加载角色配置文件并开始对话")
|
|
442
|
-
role_parser.add_argument(
|
|
443
|
-
"--config",
|
|
444
|
-
"-c",
|
|
445
|
-
default="~/.jarvis/roles.yaml",
|
|
446
|
-
help="角色配置文件路径(YAML格式,默认: ~/.jarvis/roles.yaml)",
|
|
447
|
-
)
|
|
448
|
-
role_parser.add_argument("--platform", "-p", help="指定要使用的平台,覆盖角色配置")
|
|
449
|
-
role_parser.add_argument("--model", "-m", help="指定要使用的模型,覆盖角色配置")
|
|
450
|
-
role_parser.set_defaults(func=role_command)
|
|
451
|
-
|
|
452
|
-
args = parser.parse_args()
|
|
453
|
-
|
|
454
|
-
if hasattr(args, "func"):
|
|
455
|
-
args.func(args)
|
|
456
|
-
else:
|
|
457
|
-
parser.print_help()
|
|
519
|
+
app()
|
|
458
520
|
|
|
459
521
|
|
|
460
522
|
if __name__ == "__main__":
|