yuanbot-cli 1.0.0__tar.gz
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.
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
*$py.class
|
|
4
|
+
*.so
|
|
5
|
+
.Python
|
|
6
|
+
*.egg-info/
|
|
7
|
+
*.egg
|
|
8
|
+
dist/
|
|
9
|
+
build/
|
|
10
|
+
.eggs/
|
|
11
|
+
.venv/
|
|
12
|
+
venv/
|
|
13
|
+
ENV/
|
|
14
|
+
.env
|
|
15
|
+
.env.*
|
|
16
|
+
data/
|
|
17
|
+
logs/
|
|
18
|
+
*.db
|
|
19
|
+
*.sqlite
|
|
20
|
+
*.log
|
|
21
|
+
.mypy_cache/
|
|
22
|
+
.pytest_cache/
|
|
23
|
+
.ruff_cache/
|
|
24
|
+
.coverage
|
|
25
|
+
htmlcov/
|
|
26
|
+
.idea/
|
|
27
|
+
.vscode/
|
|
28
|
+
*.swp
|
|
29
|
+
*.swo
|
|
30
|
+
.DS_Store
|
|
31
|
+
Thumbs.db
|
|
32
|
+
yuanbot.yaml
|
|
33
|
+
*.tar.gz
|
|
34
|
+
*.zip
|
|
35
|
+
public/
|
|
36
|
+
site/
|
|
37
|
+
|
|
38
|
+
# Agent workspace files
|
|
39
|
+
.openclaw/
|
|
40
|
+
AGENTS.md
|
|
41
|
+
HEARTBEAT.md
|
|
42
|
+
IDENTITY.md
|
|
43
|
+
SOUL.md
|
|
44
|
+
TOOLS.md
|
|
45
|
+
USER.md
|
|
46
|
+
docs-vitepress/node_modules
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: yuanbot-cli
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: YuanBot 安装引导工具 — 一行命令部署 YuanBot AI 虚拟伴侣
|
|
5
|
+
Project-URL: Homepage, https://grabrun.github.io/YuanBot
|
|
6
|
+
Project-URL: Repository, https://github.com/Grabrun/YuanBot
|
|
7
|
+
Project-URL: Documentation, https://grabrun.github.io/YuanBot/guide/getting-started
|
|
8
|
+
Author-email: Grabrun <grabrun@users.noreply.github.com>
|
|
9
|
+
License: MIT
|
|
10
|
+
Keywords: ai,chatbot,companion,installer,yuanbot
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Natural Language :: Chinese (Simplified)
|
|
17
|
+
Classifier: Natural Language :: English
|
|
18
|
+
Classifier: Operating System :: OS Independent
|
|
19
|
+
Classifier: Programming Language :: Python :: 3
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Topic :: Utilities
|
|
23
|
+
Requires-Python: >=3.12
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: build>=1.0; extra == 'dev'
|
|
26
|
+
Requires-Dist: twine>=4.0; extra == 'dev'
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
# yuanbot-cli
|
|
30
|
+
|
|
31
|
+
> YuanBot 安装引导工具 — 一行命令部署完整的 [YuanBot](https://github.com/Grabrun/YuanBot) AI 虚拟伴侣。
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pip install yuanbot-cli
|
|
35
|
+
yuanbot install
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## 这是什么
|
|
39
|
+
|
|
40
|
+
`yuanbot-cli` 是一个**轻量级安装器**,只有一个任务:帮你把完整的 YuanBot 部署到本地。
|
|
41
|
+
|
|
42
|
+
你只需要安装这一个 100KB 的小包,然后 `yuanbot install` 就会自动完成剩下的所有事情:
|
|
43
|
+
|
|
44
|
+
1. ✅ 检查 Python 3.12+ 环境
|
|
45
|
+
2. ✅ 从 GitHub 克隆最新代码
|
|
46
|
+
3. ✅ 创建虚拟环境
|
|
47
|
+
4. ✅ 安装 YuanBot 及其依赖
|
|
48
|
+
5. ✅ 生成初始配置
|
|
49
|
+
6. ✅ 交互式配置 AI 提供商和 API Key
|
|
50
|
+
7. ✅ 运行系统诊断验证
|
|
51
|
+
8. ✅ 打印下一步指引
|
|
52
|
+
|
|
53
|
+
## 快速开始
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# 1. 安装
|
|
57
|
+
pip install yuanbot-cli
|
|
58
|
+
|
|
59
|
+
# 2. 全自动安装 YuanBot
|
|
60
|
+
yuanbot install
|
|
61
|
+
|
|
62
|
+
# 3. 根据提示选择 AI 提供商并输入 API Key
|
|
63
|
+
|
|
64
|
+
# 4. 安装完成后
|
|
65
|
+
cd YuanBot
|
|
66
|
+
source .venv/bin/activate
|
|
67
|
+
yuanbot start
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## 非交互式安装
|
|
71
|
+
|
|
72
|
+
适合 Docker 和自动化脚本:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
pip install yuanbot-cli
|
|
76
|
+
yuanbot install \
|
|
77
|
+
--provider deepseek \
|
|
78
|
+
--api-key "sk-..." \
|
|
79
|
+
--non-interactive
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## 指定安装目录
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
yuanbot install --dir /opt/yuanbot
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## 工作原理
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
yuanbot install
|
|
92
|
+
│
|
|
93
|
+
├── git clone https://github.com/Grabrun/YuanBot.git
|
|
94
|
+
├── python -m venv .venv
|
|
95
|
+
├── pip install -e .[dev] ← 这里安装完整的 yuanbot 包
|
|
96
|
+
├── yuanbot config init
|
|
97
|
+
├── 配置 AI 提供商 + API Key
|
|
98
|
+
└── yuanbot doctor ← 验证安装
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
安装完成后,完整的 `yuanbot` 命令(包含 start/tui/webui/doctor 等所有功能)会在虚拟环境中可用。
|
|
102
|
+
|
|
103
|
+
## 与完整 yuanbot 包的关系
|
|
104
|
+
|
|
105
|
+
| | yuanbot-cli | yuanbot (完整版) |
|
|
106
|
+
|---|---|---|
|
|
107
|
+
| 大小 | ~100KB | ~10MB (含依赖) |
|
|
108
|
+
| 安装方式 | `pip install yuanbot-cli` | 由 `yuanbot install` 自动安装 |
|
|
109
|
+
| 命令 | `install`, `version` | `start`, `tui`, `doctor`, `config`, `provider`, `persona`, ... |
|
|
110
|
+
| 用途 | 安装引导 | 日常使用 |
|
|
111
|
+
|
|
112
|
+
## 发布到 PyPI
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
pip install build twine
|
|
116
|
+
cd yuanbot-cli
|
|
117
|
+
python -m build
|
|
118
|
+
twine upload dist/*
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## License
|
|
122
|
+
|
|
123
|
+
MIT
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# yuanbot-cli
|
|
2
|
+
|
|
3
|
+
> YuanBot 安装引导工具 — 一行命令部署完整的 [YuanBot](https://github.com/Grabrun/YuanBot) AI 虚拟伴侣。
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
pip install yuanbot-cli
|
|
7
|
+
yuanbot install
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
## 这是什么
|
|
11
|
+
|
|
12
|
+
`yuanbot-cli` 是一个**轻量级安装器**,只有一个任务:帮你把完整的 YuanBot 部署到本地。
|
|
13
|
+
|
|
14
|
+
你只需要安装这一个 100KB 的小包,然后 `yuanbot install` 就会自动完成剩下的所有事情:
|
|
15
|
+
|
|
16
|
+
1. ✅ 检查 Python 3.12+ 环境
|
|
17
|
+
2. ✅ 从 GitHub 克隆最新代码
|
|
18
|
+
3. ✅ 创建虚拟环境
|
|
19
|
+
4. ✅ 安装 YuanBot 及其依赖
|
|
20
|
+
5. ✅ 生成初始配置
|
|
21
|
+
6. ✅ 交互式配置 AI 提供商和 API Key
|
|
22
|
+
7. ✅ 运行系统诊断验证
|
|
23
|
+
8. ✅ 打印下一步指引
|
|
24
|
+
|
|
25
|
+
## 快速开始
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# 1. 安装
|
|
29
|
+
pip install yuanbot-cli
|
|
30
|
+
|
|
31
|
+
# 2. 全自动安装 YuanBot
|
|
32
|
+
yuanbot install
|
|
33
|
+
|
|
34
|
+
# 3. 根据提示选择 AI 提供商并输入 API Key
|
|
35
|
+
|
|
36
|
+
# 4. 安装完成后
|
|
37
|
+
cd YuanBot
|
|
38
|
+
source .venv/bin/activate
|
|
39
|
+
yuanbot start
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## 非交互式安装
|
|
43
|
+
|
|
44
|
+
适合 Docker 和自动化脚本:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pip install yuanbot-cli
|
|
48
|
+
yuanbot install \
|
|
49
|
+
--provider deepseek \
|
|
50
|
+
--api-key "sk-..." \
|
|
51
|
+
--non-interactive
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## 指定安装目录
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
yuanbot install --dir /opt/yuanbot
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## 工作原理
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
yuanbot install
|
|
64
|
+
│
|
|
65
|
+
├── git clone https://github.com/Grabrun/YuanBot.git
|
|
66
|
+
├── python -m venv .venv
|
|
67
|
+
├── pip install -e .[dev] ← 这里安装完整的 yuanbot 包
|
|
68
|
+
├── yuanbot config init
|
|
69
|
+
├── 配置 AI 提供商 + API Key
|
|
70
|
+
└── yuanbot doctor ← 验证安装
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
安装完成后,完整的 `yuanbot` 命令(包含 start/tui/webui/doctor 等所有功能)会在虚拟环境中可用。
|
|
74
|
+
|
|
75
|
+
## 与完整 yuanbot 包的关系
|
|
76
|
+
|
|
77
|
+
| | yuanbot-cli | yuanbot (完整版) |
|
|
78
|
+
|---|---|---|
|
|
79
|
+
| 大小 | ~100KB | ~10MB (含依赖) |
|
|
80
|
+
| 安装方式 | `pip install yuanbot-cli` | 由 `yuanbot install` 自动安装 |
|
|
81
|
+
| 命令 | `install`, `version` | `start`, `tui`, `doctor`, `config`, `provider`, `persona`, ... |
|
|
82
|
+
| 用途 | 安装引导 | 日常使用 |
|
|
83
|
+
|
|
84
|
+
## 发布到 PyPI
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
pip install build twine
|
|
88
|
+
cd yuanbot-cli
|
|
89
|
+
python -m build
|
|
90
|
+
twine upload dist/*
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## License
|
|
94
|
+
|
|
95
|
+
MIT
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "yuanbot-cli"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "YuanBot 安装引导工具 — 一行命令部署 YuanBot AI 虚拟伴侣"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { text = "MIT" }
|
|
11
|
+
requires-python = ">=3.12"
|
|
12
|
+
keywords = ["yuanbot", "ai", "companion", "chatbot", "installer"]
|
|
13
|
+
|
|
14
|
+
authors = [
|
|
15
|
+
{ name = "Grabrun", email = "grabrun@users.noreply.github.com" },
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
classifiers = [
|
|
19
|
+
"Development Status :: 4 - Beta",
|
|
20
|
+
"Environment :: Console",
|
|
21
|
+
"Intended Audience :: Developers",
|
|
22
|
+
"Intended Audience :: End Users/Desktop",
|
|
23
|
+
"License :: OSI Approved :: MIT License",
|
|
24
|
+
"Natural Language :: Chinese (Simplified)",
|
|
25
|
+
"Natural Language :: English",
|
|
26
|
+
"Operating System :: OS Independent",
|
|
27
|
+
"Programming Language :: Python :: 3",
|
|
28
|
+
"Programming Language :: Python :: 3.12",
|
|
29
|
+
"Programming Language :: Python :: 3.13",
|
|
30
|
+
"Topic :: Utilities",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
[project.urls]
|
|
34
|
+
Homepage = "https://grabrun.github.io/YuanBot"
|
|
35
|
+
Repository = "https://github.com/Grabrun/YuanBot"
|
|
36
|
+
Documentation = "https://grabrun.github.io/YuanBot/guide/getting-started"
|
|
37
|
+
|
|
38
|
+
[project.scripts]
|
|
39
|
+
yuanbot = "yuanbot_cli.cli:main"
|
|
40
|
+
|
|
41
|
+
[project.optional-dependencies]
|
|
42
|
+
dev = [
|
|
43
|
+
"build>=1.0",
|
|
44
|
+
"twine>=4.0",
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
[tool.hatch.build.targets.wheel]
|
|
48
|
+
packages = ["src/yuanbot_cli"]
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
"""YuanBot CLI — 安装引导工具
|
|
2
|
+
|
|
3
|
+
用法:
|
|
4
|
+
yuanbot install 全自动交互式安装 YuanBot
|
|
5
|
+
yuanbot install --help 查看帮助
|
|
6
|
+
yuanbot version 查看版本
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import argparse
|
|
12
|
+
import os
|
|
13
|
+
import shutil
|
|
14
|
+
import subprocess
|
|
15
|
+
import sys
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# ── ANSI 颜色 ──────────────────────────────
|
|
20
|
+
|
|
21
|
+
_CYAN = "\033[36m"
|
|
22
|
+
_GREEN = "\033[32m"
|
|
23
|
+
_YELLOW = "\033[33m"
|
|
24
|
+
_RED = "\033[31m"
|
|
25
|
+
_BOLD = "\033[1m"
|
|
26
|
+
_DIM = "\033[2m"
|
|
27
|
+
_RESET = "\033[0m"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _c(text: str, color: str) -> str:
|
|
31
|
+
if not sys.stderr.isatty():
|
|
32
|
+
return text
|
|
33
|
+
return f"{color}{text}{_RESET}"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _header(title: str) -> None:
|
|
37
|
+
print(f"\n {_c('==', _CYAN + _BOLD)} {title}")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _ok(msg: str) -> None:
|
|
41
|
+
print(f" {_c('✅', '')} {msg}")
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _fail(msg: str) -> None:
|
|
45
|
+
print(f" {_c('❌', '')} {_c(msg, _RED)}")
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _warn(msg: str) -> None:
|
|
49
|
+
print(f" {_c('⚠️', '')} {_c(msg, _YELLOW)}")
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _info(msg: str) -> None:
|
|
53
|
+
print(f" {_c('ℹ️', '')} {msg}")
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
# ── 核心安装逻辑 ──────────────────────────
|
|
57
|
+
|
|
58
|
+
VERSION = "1.0.0"
|
|
59
|
+
REPO_URL = "https://github.com/Grabrun/YuanBot.git"
|
|
60
|
+
MIN_PYTHON = (3, 12)
|
|
61
|
+
|
|
62
|
+
# 支持的 AI 提供商
|
|
63
|
+
PROVIDERS = {
|
|
64
|
+
"deepseek": {
|
|
65
|
+
"name": "DeepSeek",
|
|
66
|
+
"file": "deepseek.yaml",
|
|
67
|
+
"model": "deepseek-v4-flash",
|
|
68
|
+
"key_hint": "sk-...",
|
|
69
|
+
},
|
|
70
|
+
"openai": {
|
|
71
|
+
"name": "OpenAI",
|
|
72
|
+
"file": "openai.yaml",
|
|
73
|
+
"model": "gpt-5.5",
|
|
74
|
+
"key_hint": "sk-...",
|
|
75
|
+
},
|
|
76
|
+
"anthropic": {
|
|
77
|
+
"name": "Anthropic Claude",
|
|
78
|
+
"file": "anthropic.yaml",
|
|
79
|
+
"model": "claude-sonnet-4-6",
|
|
80
|
+
"key_hint": "sk-ant-...",
|
|
81
|
+
},
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _run_install(args: argparse.Namespace) -> None:
|
|
86
|
+
"""全自动安装 YuanBot"""
|
|
87
|
+
|
|
88
|
+
provider_id: str | None = args.provider
|
|
89
|
+
api_key: str | None = args.api_key
|
|
90
|
+
non_interactive: bool = args.non_interactive
|
|
91
|
+
|
|
92
|
+
# ── 1. 欢迎 ─────────────────────────
|
|
93
|
+
print()
|
|
94
|
+
print(f" {_c('🌸 YuanBot 安装程序', _CYAN + _BOLD)}")
|
|
95
|
+
print(f" {_c('版本', _DIM)} {VERSION}")
|
|
96
|
+
print(f" {_c('—' * 40, _DIM)}")
|
|
97
|
+
print()
|
|
98
|
+
|
|
99
|
+
# ── 2. Python 版本 ───────────────────
|
|
100
|
+
_header("环境检查")
|
|
101
|
+
if sys.version_info < MIN_PYTHON:
|
|
102
|
+
_fail(f"需要 Python 3.12+,当前 {sys.version_info.major}.{sys.version_info.minor}")
|
|
103
|
+
sys.exit(1)
|
|
104
|
+
_ok(f"Python {sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}")
|
|
105
|
+
|
|
106
|
+
if not shutil.which("git"):
|
|
107
|
+
_warn("未检测到 git,将跳过版本控制")
|
|
108
|
+
else:
|
|
109
|
+
_ok("git 已安装")
|
|
110
|
+
print()
|
|
111
|
+
|
|
112
|
+
# ── 3. 确定安装目录 ─────────────────
|
|
113
|
+
_header("安装位置")
|
|
114
|
+
target_dir: Path
|
|
115
|
+
if args.dir:
|
|
116
|
+
target_dir = Path(args.dir).resolve()
|
|
117
|
+
target_dir.mkdir(parents=True, exist_ok=True)
|
|
118
|
+
_info(f"目标目录: {target_dir}")
|
|
119
|
+
else:
|
|
120
|
+
target_dir = Path.cwd() / "YuanBot"
|
|
121
|
+
_info(f"默认目录: {target_dir}")
|
|
122
|
+
|
|
123
|
+
# 检查是否已存在
|
|
124
|
+
is_existing = (target_dir / "pyproject.toml").exists() and (target_dir / "src" / "yuanbot").exists()
|
|
125
|
+
if is_existing:
|
|
126
|
+
if args.force:
|
|
127
|
+
_warn("目录已有 YuanBot 项目,--force 模式下将覆盖安装")
|
|
128
|
+
else:
|
|
129
|
+
_info("检测到已有 YuanBot 项目")
|
|
130
|
+
answer = input(f" {_c('?', _CYAN)} 是否重新安装?(y/N): ").strip().lower()
|
|
131
|
+
if answer not in ("y", "yes"):
|
|
132
|
+
_info("已取消")
|
|
133
|
+
return
|
|
134
|
+
print()
|
|
135
|
+
|
|
136
|
+
# ── 4. 克隆/更新代码 ────────────────
|
|
137
|
+
_header("获取代码")
|
|
138
|
+
if target_dir.exists() and is_existing:
|
|
139
|
+
_info("拉取最新代码...")
|
|
140
|
+
subprocess.run(["git", "pull"], cwd=target_dir, capture_output=True)
|
|
141
|
+
_ok("代码已更新")
|
|
142
|
+
else:
|
|
143
|
+
_info(f"正在从 GitHub 克隆...")
|
|
144
|
+
result = subprocess.run(
|
|
145
|
+
["git", "clone", "--depth=1", REPO_URL, str(target_dir)],
|
|
146
|
+
capture_output=True, text=True,
|
|
147
|
+
)
|
|
148
|
+
if result.returncode != 0:
|
|
149
|
+
_fail(f"克隆失败: {result.stderr.strip()}")
|
|
150
|
+
sys.exit(1)
|
|
151
|
+
_ok("代码已下载")
|
|
152
|
+
print()
|
|
153
|
+
|
|
154
|
+
# ── 5. 创建虚拟环境 ─────────────────
|
|
155
|
+
_header("虚拟环境")
|
|
156
|
+
venv_path = target_dir / ".venv"
|
|
157
|
+
if not venv_path.exists():
|
|
158
|
+
_info("创建中...")
|
|
159
|
+
result = subprocess.run(
|
|
160
|
+
[sys.executable, "-m", "venv", str(venv_path)],
|
|
161
|
+
capture_output=True, text=True,
|
|
162
|
+
)
|
|
163
|
+
if result.returncode != 0:
|
|
164
|
+
_fail(f"创建失败: {result.stderr.strip()}")
|
|
165
|
+
sys.exit(1)
|
|
166
|
+
_ok(".venv 已创建")
|
|
167
|
+
else:
|
|
168
|
+
_ok(".venv 已存在")
|
|
169
|
+
|
|
170
|
+
# venv 里的 python/pip
|
|
171
|
+
if sys.platform == "win32":
|
|
172
|
+
py_venv = venv_path / "Scripts" / "python"
|
|
173
|
+
pip_venv = venv_path / "Scripts" / "pip"
|
|
174
|
+
else:
|
|
175
|
+
py_venv = venv_path / "bin" / "python"
|
|
176
|
+
pip_venv = venv_path / "bin" / "pip"
|
|
177
|
+
print()
|
|
178
|
+
|
|
179
|
+
# ── 6. 安装依赖 ─────────────────────
|
|
180
|
+
_header("安装依赖")
|
|
181
|
+
_info("正在安装 YuanBot (这可能需要几分钟)...")
|
|
182
|
+
result = subprocess.run(
|
|
183
|
+
[str(pip_venv), "install", "-e", str(target_dir)],
|
|
184
|
+
capture_output=True, text=True, timeout=300,
|
|
185
|
+
)
|
|
186
|
+
if result.returncode != 0:
|
|
187
|
+
_warn(f"安装输出: {result.stderr[-200:]}")
|
|
188
|
+
# 额外安装开发依赖
|
|
189
|
+
subprocess.run(
|
|
190
|
+
[str(pip_venv), "install", "-e", str(target_dir) + "[dev]"],
|
|
191
|
+
capture_output=True, timeout=300,
|
|
192
|
+
)
|
|
193
|
+
_ok("YuanBot 已安装")
|
|
194
|
+
print()
|
|
195
|
+
|
|
196
|
+
# ── 7. 初始化配置 ───────────────────
|
|
197
|
+
_header("初始化配置")
|
|
198
|
+
result = subprocess.run(
|
|
199
|
+
[str(py_venv), "-m", "yuanbot.cli", "config", "init"],
|
|
200
|
+
capture_output=True, text=True, cwd=target_dir,
|
|
201
|
+
)
|
|
202
|
+
if result.returncode == 0:
|
|
203
|
+
_ok("配置模板已生成")
|
|
204
|
+
else:
|
|
205
|
+
_warn(f"config init 输出: {result.stderr[-200:]}")
|
|
206
|
+
print()
|
|
207
|
+
|
|
208
|
+
# ── 8. 配置 AI 提供商 ───────────────
|
|
209
|
+
if not non_interactive and not (provider_id and api_key):
|
|
210
|
+
_header("AI 提供商")
|
|
211
|
+
print(f" {_c('选择 AI 提供商:', _BOLD)}")
|
|
212
|
+
choices = list(PROVIDERS.keys())
|
|
213
|
+
for i, pid in enumerate(choices, 1):
|
|
214
|
+
p = PROVIDERS[pid]
|
|
215
|
+
print(f" {i}. {p['name']} ({p['model']})")
|
|
216
|
+
print(f" {len(choices) + 1}. 稍后手动配置")
|
|
217
|
+
|
|
218
|
+
try:
|
|
219
|
+
sel = input(f"\n {_c('?', _CYAN)} 请选择 [1-{len(choices) + 1}] (默认 1): ").strip()
|
|
220
|
+
if not sel or sel == "1":
|
|
221
|
+
provider_id = "deepseek"
|
|
222
|
+
else:
|
|
223
|
+
idx = int(sel) - 1
|
|
224
|
+
provider_id = choices[idx] if 0 <= idx < len(choices) else None
|
|
225
|
+
except (ValueError, IndexError):
|
|
226
|
+
provider_id = None
|
|
227
|
+
|
|
228
|
+
if provider_id:
|
|
229
|
+
p = PROVIDERS[provider_id]
|
|
230
|
+
api_key = input(f" {_c('?', _CYAN)} 输入 {p['name']} API Key (如 {p['key_hint']}): ").strip()
|
|
231
|
+
|
|
232
|
+
if provider_id and api_key:
|
|
233
|
+
_header("写入配置")
|
|
234
|
+
p = PROVIDERS[provider_id]
|
|
235
|
+
|
|
236
|
+
# 写 API Key 到 provider 配置
|
|
237
|
+
provider_path = target_dir / "configs" / "Providers" / p["file"]
|
|
238
|
+
if provider_path.exists():
|
|
239
|
+
import yaml # type: ignore[import-untyped]
|
|
240
|
+
with open(provider_path) as f:
|
|
241
|
+
cfg = yaml.safe_load(f) or {}
|
|
242
|
+
cfg.setdefault("config", {})["api_key"] = api_key
|
|
243
|
+
cfg["enabled"] = True
|
|
244
|
+
with open(provider_path, "w") as f:
|
|
245
|
+
yaml.safe_dump(cfg, f, allow_unicode=True, default_flow_style=False)
|
|
246
|
+
_ok(f"API Key 已配置到 {p['file']}")
|
|
247
|
+
|
|
248
|
+
# 写默认提供商到 bot.yaml
|
|
249
|
+
bot_path = target_dir / "configs" / "bot.yaml"
|
|
250
|
+
if bot_path.exists():
|
|
251
|
+
import yaml
|
|
252
|
+
with open(bot_path) as f:
|
|
253
|
+
bot_cfg = yaml.safe_load(f) or {}
|
|
254
|
+
bot_cfg.setdefault("ai", {})["default_provider"] = provider_id
|
|
255
|
+
bot_cfg["ai"]["default_model"] = p["model"]
|
|
256
|
+
with open(bot_path, "w") as f:
|
|
257
|
+
yaml.safe_dump(bot_cfg, f, allow_unicode=True, default_flow_style=False)
|
|
258
|
+
_ok(f"默认提供商设为 {p['name']}")
|
|
259
|
+
|
|
260
|
+
print()
|
|
261
|
+
|
|
262
|
+
# ── 9. 运行诊断 ─────────────────────
|
|
263
|
+
_header("运行诊断")
|
|
264
|
+
subprocess.run(
|
|
265
|
+
[str(py_venv), "-m", "yuanbot.cli", "doctor"],
|
|
266
|
+
cwd=target_dir,
|
|
267
|
+
)
|
|
268
|
+
print()
|
|
269
|
+
|
|
270
|
+
# ── 10. 完成 ─────────────────────────
|
|
271
|
+
if sys.platform == "win32":
|
|
272
|
+
activate_cmd = f"{venv_path}\\Scripts\\activate"
|
|
273
|
+
else:
|
|
274
|
+
activate_cmd = f"source {venv_path / 'bin' / 'activate'}"
|
|
275
|
+
|
|
276
|
+
print(f" {_c('🎉 YuanBot 安装成功!', _GREEN + _BOLD)}")
|
|
277
|
+
print()
|
|
278
|
+
_info(f"安装目录: {target_dir}")
|
|
279
|
+
print()
|
|
280
|
+
_header("下一步")
|
|
281
|
+
print(f" {_c(activate_cmd, _CYAN)} # 激活虚拟环境")
|
|
282
|
+
print(f" {_c('yuanbot start', _CYAN)} # 启动服务")
|
|
283
|
+
print(f" {_c('yuanbot tui', _CYAN)} # 终端聊天")
|
|
284
|
+
print(f" 打开 {_c('http://localhost:8000', _CYAN)} # WebUI")
|
|
285
|
+
print()
|
|
286
|
+
_info(f"📖 文档: https://grabrun.github.io/YuanBot")
|
|
287
|
+
print()
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
# ── CLI 入口 ──────────────────────────────
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
def main() -> None:
|
|
294
|
+
parser = argparse.ArgumentParser(
|
|
295
|
+
prog="yuanbot",
|
|
296
|
+
description="YuanBot 安装引导工具 — 一行命令部署 AI 虚拟伴侣",
|
|
297
|
+
)
|
|
298
|
+
parser.add_argument(
|
|
299
|
+
"-v", "--version",
|
|
300
|
+
action="version",
|
|
301
|
+
version=f"yuanbot-cli {VERSION}",
|
|
302
|
+
help="显示版本号",
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
sub = parser.add_subparsers(dest="command")
|
|
306
|
+
|
|
307
|
+
# yuanbot install
|
|
308
|
+
install_parser = sub.add_parser("install", help="全自动安装 YuanBot")
|
|
309
|
+
install_parser.add_argument(
|
|
310
|
+
"--dir", default="",
|
|
311
|
+
help="安装目录(默认当前目录下的 YuanBot/)",
|
|
312
|
+
)
|
|
313
|
+
install_parser.add_argument(
|
|
314
|
+
"--provider", default=None,
|
|
315
|
+
help="AI 提供商 (deepseek/openai/anthropic)",
|
|
316
|
+
)
|
|
317
|
+
install_parser.add_argument(
|
|
318
|
+
"--api-key", default=None,
|
|
319
|
+
help="API Key",
|
|
320
|
+
)
|
|
321
|
+
install_parser.add_argument(
|
|
322
|
+
"--non-interactive", action="store_true",
|
|
323
|
+
help="非交互式安装(需同时指定 --provider 和 --api-key)",
|
|
324
|
+
)
|
|
325
|
+
install_parser.add_argument(
|
|
326
|
+
"--force", action="store_true",
|
|
327
|
+
help="强制重新安装",
|
|
328
|
+
)
|
|
329
|
+
|
|
330
|
+
# yuanbot version
|
|
331
|
+
sub.add_parser("version", help="显示版本号")
|
|
332
|
+
|
|
333
|
+
args = parser.parse_args()
|
|
334
|
+
|
|
335
|
+
if args.command == "install":
|
|
336
|
+
_run_install(args)
|
|
337
|
+
else:
|
|
338
|
+
parser.print_help()
|