myagent-ai 1.4.2 → 1.4.3
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.
- package/core/version.py +1 -1
- package/install/install.ps1 +1 -1
- package/install/install.sh +1 -1
- package/main.py +256 -0
- package/package.json +1 -1
- package/setup.py +1 -1
package/core/version.py
CHANGED
package/install/install.ps1
CHANGED
package/install/install.sh
CHANGED
package/main.py
CHANGED
|
@@ -1007,6 +1007,251 @@ WantedBy=default.target
|
|
|
1007
1007
|
print("✅ 已取消 Linux 开机自启")
|
|
1008
1008
|
|
|
1009
1009
|
|
|
1010
|
+
# ==============================================================================
|
|
1011
|
+
# 首次运行引导
|
|
1012
|
+
# ==============================================================================
|
|
1013
|
+
|
|
1014
|
+
def _first_run_setup(config_mgr: ConfigManager):
|
|
1015
|
+
"""
|
|
1016
|
+
首次运行引导:检测是否已配置 LLM API Key。
|
|
1017
|
+
如果没有,进入交互式配置向导。
|
|
1018
|
+
"""
|
|
1019
|
+
cfg = config_mgr.config
|
|
1020
|
+
|
|
1021
|
+
# 判断是否需要配置: api_key 为空且 provider 不是 ollama(ollama 本地无需 key)
|
|
1022
|
+
has_api_key = bool(cfg.llm.api_key) or bool(cfg.llm.anthropic_api_key)
|
|
1023
|
+
is_ollama = cfg.llm.provider == "ollama"
|
|
1024
|
+
has_env_key = bool(os.environ.get("MYAGENT_LLM_API_KEY")) or \
|
|
1025
|
+
bool(os.environ.get("MYAGENT_ANTHROPIC_API_KEY")) or \
|
|
1026
|
+
bool(os.environ.get("OPENAI_API_KEY")) or \
|
|
1027
|
+
bool(os.environ.get("ANTHROPIC_API_KEY"))
|
|
1028
|
+
|
|
1029
|
+
if has_api_key or is_ollama or has_env_key:
|
|
1030
|
+
return # 已配置或通过环境变量提供,跳过
|
|
1031
|
+
|
|
1032
|
+
# 进入配置向导
|
|
1033
|
+
print()
|
|
1034
|
+
print("=" * 55)
|
|
1035
|
+
print(" MyAgent - LLM API 配置向导")
|
|
1036
|
+
print(f" 版本: v{get_version()}")
|
|
1037
|
+
print("=" * 55)
|
|
1038
|
+
print()
|
|
1039
|
+
print(" 检测到尚未配置 LLM API Key,MyAgent 需要")
|
|
1040
|
+
print(" 一个大模型 API 才能工作。")
|
|
1041
|
+
print()
|
|
1042
|
+
print(" 支持的提供商:")
|
|
1043
|
+
print(" 1. OpenAI / 兼容 API (推荐)")
|
|
1044
|
+
print(" 2. Anthropic (Claude)")
|
|
1045
|
+
print(" 3. Ollama (本地模型,无需 API Key)")
|
|
1046
|
+
print()
|
|
1047
|
+
|
|
1048
|
+
while True:
|
|
1049
|
+
try:
|
|
1050
|
+
choice = input(" 请选择 [1/2/3]: ").strip()
|
|
1051
|
+
except (EOFError, KeyboardInterrupt):
|
|
1052
|
+
print("\n\n 已取消配置。可通过 myagent-ai setup 重新配置。")
|
|
1053
|
+
sys.exit(0)
|
|
1054
|
+
|
|
1055
|
+
if choice == "1":
|
|
1056
|
+
_setup_openai_compatible(config_mgr)
|
|
1057
|
+
break
|
|
1058
|
+
elif choice == "2":
|
|
1059
|
+
_setup_anthropic(config_mgr)
|
|
1060
|
+
break
|
|
1061
|
+
elif choice == "3":
|
|
1062
|
+
_setup_ollama(config_mgr)
|
|
1063
|
+
break
|
|
1064
|
+
else:
|
|
1065
|
+
print(" 无效选择,请输入 1/2/3")
|
|
1066
|
+
|
|
1067
|
+
# 保存配置
|
|
1068
|
+
config_mgr.save()
|
|
1069
|
+
print()
|
|
1070
|
+
print(" 配置已保存!")
|
|
1071
|
+
print(f" 配置文件: {config_mgr._config_file}")
|
|
1072
|
+
print()
|
|
1073
|
+
|
|
1074
|
+
|
|
1075
|
+
def _setup_openai_compatible(config_mgr: ConfigManager):
|
|
1076
|
+
"""配置 OpenAI 或兼容 API"""
|
|
1077
|
+
print()
|
|
1078
|
+
print(" -- OpenAI / 兼容 API 配置 --")
|
|
1079
|
+
print()
|
|
1080
|
+
|
|
1081
|
+
# 预设模板
|
|
1082
|
+
print(" 预设模板:")
|
|
1083
|
+
print(" 1. OpenAI 官方 (https://api.openai.com/v1)")
|
|
1084
|
+
print(" 2. 智谱 GLM (https://open.bigmodel.cn/api/paas/v4)")
|
|
1085
|
+
print(" 3. DeepSeek (https://api.deepseek.com/v1)")
|
|
1086
|
+
print(" 4. 月之暗面 Moonshot (https://api.moonshot.cn/v1)")
|
|
1087
|
+
print(" 5. 自定义 Base URL")
|
|
1088
|
+
print()
|
|
1089
|
+
|
|
1090
|
+
while True:
|
|
1091
|
+
try:
|
|
1092
|
+
choice = input(" 选择模板 [1/2/3/4/5]: ").strip()
|
|
1093
|
+
except (EOFError, KeyboardInterrupt):
|
|
1094
|
+
sys.exit(0)
|
|
1095
|
+
|
|
1096
|
+
templates = {
|
|
1097
|
+
"1": ("https://api.openai.com/v1", "gpt-4o"),
|
|
1098
|
+
"2": ("https://open.bigmodel.cn/api/paas/v4", "glm-4-flash"),
|
|
1099
|
+
"3": ("https://api.deepseek.com/v1", "deepseek-chat"),
|
|
1100
|
+
"4": ("https://api.moonshot.cn/v1", "moonshot-v1-8k"),
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
if choice in templates:
|
|
1104
|
+
base_url, model = templates[choice]
|
|
1105
|
+
break
|
|
1106
|
+
elif choice == "5":
|
|
1107
|
+
try:
|
|
1108
|
+
base_url = input(" Base URL: ").strip().rstrip("/")
|
|
1109
|
+
model = input(" 模型名称 (如 gpt-4o): ").strip() or "gpt-4o"
|
|
1110
|
+
except (EOFError, KeyboardInterrupt):
|
|
1111
|
+
sys.exit(0)
|
|
1112
|
+
break
|
|
1113
|
+
else:
|
|
1114
|
+
print(" 无效选择")
|
|
1115
|
+
|
|
1116
|
+
while True:
|
|
1117
|
+
try:
|
|
1118
|
+
api_key = input(" API Key: ").strip()
|
|
1119
|
+
except (EOFError, KeyboardInterrupt):
|
|
1120
|
+
sys.exit(0)
|
|
1121
|
+
if api_key:
|
|
1122
|
+
break
|
|
1123
|
+
print(" API Key 不能为空!")
|
|
1124
|
+
|
|
1125
|
+
print()
|
|
1126
|
+
try:
|
|
1127
|
+
temp_input = input(f" Temperature (默认 0.1, 直接回车跳过): ").strip()
|
|
1128
|
+
temperature = float(temp_input) if temp_input else 0.1
|
|
1129
|
+
except (EOFError, KeyboardInterrupt, ValueError):
|
|
1130
|
+
temperature = 0.1
|
|
1131
|
+
|
|
1132
|
+
# 写入配置
|
|
1133
|
+
config_mgr.config.llm.provider = "openai"
|
|
1134
|
+
config_mgr.config.llm.api_key = api_key
|
|
1135
|
+
config_mgr.config.llm.base_url = base_url
|
|
1136
|
+
config_mgr.config.llm.model = model
|
|
1137
|
+
config_mgr.config.llm.temperature = temperature
|
|
1138
|
+
|
|
1139
|
+
# 验证连接
|
|
1140
|
+
print()
|
|
1141
|
+
print(" 正在验证连接...")
|
|
1142
|
+
try:
|
|
1143
|
+
import requests
|
|
1144
|
+
headers = {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"}
|
|
1145
|
+
test_body = {
|
|
1146
|
+
"model": model,
|
|
1147
|
+
"messages": [{"role": "user", "content": "hi"}],
|
|
1148
|
+
"max_tokens": 5,
|
|
1149
|
+
}
|
|
1150
|
+
resp = requests.post(
|
|
1151
|
+
f"{base_url}/chat/completions",
|
|
1152
|
+
headers=headers, json=test_body, timeout=15,
|
|
1153
|
+
)
|
|
1154
|
+
if resp.status_code == 200:
|
|
1155
|
+
print(" 连接成功!")
|
|
1156
|
+
else:
|
|
1157
|
+
print(f" API 返回 {resp.status_code},请检查 Key 和 URL 是否正确")
|
|
1158
|
+
print(f" (已保存配置,启动后可在 Web 界面修改)")
|
|
1159
|
+
except Exception as e:
|
|
1160
|
+
print(f" 连接测试失败: {e}")
|
|
1161
|
+
print(f" (已保存配置,启动后可在 Web 界面修改)")
|
|
1162
|
+
|
|
1163
|
+
|
|
1164
|
+
def _setup_anthropic(config_mgr: ConfigManager):
|
|
1165
|
+
"""配置 Anthropic Claude"""
|
|
1166
|
+
print()
|
|
1167
|
+
print(" -- Anthropic Claude 配置 --")
|
|
1168
|
+
print()
|
|
1169
|
+
|
|
1170
|
+
while True:
|
|
1171
|
+
try:
|
|
1172
|
+
api_key = input(" Anthropic API Key: ").strip()
|
|
1173
|
+
except (EOFError, KeyboardInterrupt):
|
|
1174
|
+
sys.exit(0)
|
|
1175
|
+
if api_key:
|
|
1176
|
+
break
|
|
1177
|
+
print(" API Key 不能为空!")
|
|
1178
|
+
|
|
1179
|
+
print()
|
|
1180
|
+
print(" 可选模型: claude-sonnet-4-20250514 / claude-opus-4-20250514")
|
|
1181
|
+
try:
|
|
1182
|
+
model = input(" 模型 (默认 claude-sonnet-4-20250514): ").strip() or "claude-sonnet-4-20250514"
|
|
1183
|
+
except (EOFError, KeyboardInterrupt):
|
|
1184
|
+
model = "claude-sonnet-4-20250514"
|
|
1185
|
+
|
|
1186
|
+
config_mgr.config.llm.provider = "anthropic"
|
|
1187
|
+
config_mgr.config.llm.anthropic_api_key = api_key
|
|
1188
|
+
config_mgr.config.llm.model = model
|
|
1189
|
+
|
|
1190
|
+
print()
|
|
1191
|
+
print(" 正在验证连接...")
|
|
1192
|
+
try:
|
|
1193
|
+
import requests
|
|
1194
|
+
headers = {
|
|
1195
|
+
"x-api-key": api_key,
|
|
1196
|
+
"anthropic-version": "2023-06-01",
|
|
1197
|
+
"Content-Type": "application/json",
|
|
1198
|
+
}
|
|
1199
|
+
test_body = {
|
|
1200
|
+
"model": model,
|
|
1201
|
+
"messages": [{"role": "user", "content": "hi"}],
|
|
1202
|
+
"max_tokens": 5,
|
|
1203
|
+
}
|
|
1204
|
+
resp = requests.post(
|
|
1205
|
+
"https://api.anthropic.com/v1/messages",
|
|
1206
|
+
headers=headers, json=test_body, timeout=15,
|
|
1207
|
+
)
|
|
1208
|
+
if resp.status_code == 200:
|
|
1209
|
+
print(" 连接成功!")
|
|
1210
|
+
else:
|
|
1211
|
+
print(f" API 返回 {resp.status_code},请检查 Key 是否正确")
|
|
1212
|
+
print(f" (已保存配置,启动后可在 Web 界面修改)")
|
|
1213
|
+
except Exception as e:
|
|
1214
|
+
print(f" 连接测试失败: {e}")
|
|
1215
|
+
print(f" (已保存配置,启动后可在 Web 界面修改)")
|
|
1216
|
+
|
|
1217
|
+
|
|
1218
|
+
def _setup_ollama(config_mgr: ConfigManager):
|
|
1219
|
+
"""配置 Ollama 本地模型"""
|
|
1220
|
+
print()
|
|
1221
|
+
print(" -- Ollama 本地模型配置 --")
|
|
1222
|
+
print()
|
|
1223
|
+
|
|
1224
|
+
try:
|
|
1225
|
+
base_url = input(" Ollama 地址 (默认 http://localhost:11434): ").strip()
|
|
1226
|
+
except (EOFError, KeyboardInterrupt):
|
|
1227
|
+
sys.exit(0)
|
|
1228
|
+
base_url = base_url or "http://localhost:11434"
|
|
1229
|
+
|
|
1230
|
+
try:
|
|
1231
|
+
model = input(" 模型名称 (默认 llama3): ").strip() or "llama3"
|
|
1232
|
+
except (EOFError, KeyboardInterrupt):
|
|
1233
|
+
model = "llama3"
|
|
1234
|
+
|
|
1235
|
+
config_mgr.config.llm.provider = "ollama"
|
|
1236
|
+
config_mgr.config.llm.ollama_base_url = base_url
|
|
1237
|
+
config_mgr.config.llm.ollama_model = model
|
|
1238
|
+
|
|
1239
|
+
print()
|
|
1240
|
+
print(" 正在验证连接...")
|
|
1241
|
+
try:
|
|
1242
|
+
import requests
|
|
1243
|
+
resp = requests.get(f"{base_url}/api/tags", timeout=5)
|
|
1244
|
+
if resp.status_code == 200:
|
|
1245
|
+
models = [m.get("name", "") for m in resp.json().get("models", [])]
|
|
1246
|
+
print(f" 连接成功! 可用模型: {', '.join(models) if models else '(无)'}")
|
|
1247
|
+
else:
|
|
1248
|
+
print(f" 无法连接 Ollama,请确认 Ollama 已启动")
|
|
1249
|
+
print(f" (已保存配置,启动后可在 Web 界面修改)")
|
|
1250
|
+
except Exception as e:
|
|
1251
|
+
print(f" 连接测试失败: {e}")
|
|
1252
|
+
print(f" (已保存配置,启动后可在 Web 界面修改)")
|
|
1253
|
+
|
|
1254
|
+
|
|
1010
1255
|
# ==============================================================================
|
|
1011
1256
|
# 主函数
|
|
1012
1257
|
# ==============================================================================
|
|
@@ -1024,6 +1269,7 @@ def main():
|
|
|
1024
1269
|
parser.add_argument("--no-autostart", action="store_true", help="取消开机自启")
|
|
1025
1270
|
parser.add_argument("--config", type=str, help="指定配置文件路径")
|
|
1026
1271
|
parser.add_argument("--debug", action="store_true", help="调试模式")
|
|
1272
|
+
parser.add_argument("--setup", action="store_true", help="配置向导")
|
|
1027
1273
|
args = parser.parse_args()
|
|
1028
1274
|
|
|
1029
1275
|
# 配置
|
|
@@ -1042,6 +1288,16 @@ def main():
|
|
|
1042
1288
|
setup_auto_start(False)
|
|
1043
1289
|
return
|
|
1044
1290
|
|
|
1291
|
+
# 手动触发配置向导
|
|
1292
|
+
if args.setup:
|
|
1293
|
+
_first_run_setup(config_mgr)
|
|
1294
|
+
return
|
|
1295
|
+
|
|
1296
|
+
# ══════════════════════════════════════════════════════════
|
|
1297
|
+
# 首次运行: 引导配置 LLM API Key
|
|
1298
|
+
# ══════════════════════════════════════════════════════════
|
|
1299
|
+
_first_run_setup(config_mgr)
|
|
1300
|
+
|
|
1045
1301
|
# 创建应用
|
|
1046
1302
|
app = MyAgentApp()
|
|
1047
1303
|
app._restart_requested = False
|
package/package.json
CHANGED
package/setup.py
CHANGED
|
@@ -9,7 +9,7 @@ from pathlib import Path
|
|
|
9
9
|
_version_path = Path(__file__).parent / "core" / "version.py"
|
|
10
10
|
_version_vars = {}
|
|
11
11
|
exec(_version_path.read_text(), _version_vars)
|
|
12
|
-
__version__ = _version_vars.get("BASE_VERSION", "1.4.
|
|
12
|
+
__version__ = _version_vars.get("BASE_VERSION", "1.4.3")
|
|
13
13
|
|
|
14
14
|
setup(
|
|
15
15
|
name="myagent",
|