foliko 1.0.19 → 1.0.20
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/README.md +1 -1
- package/SPEC.md +1 -1
- package/docs/user-manual.md +4 -4
- package/install.ps1 +42 -161
- package/install.sh +137 -0
- package/package.json +2 -2
- package/plugins/subagent-plugin.js +1 -1
- package/skills/vb-agent-dev/SKILL.md +4 -4
- package/website/docs/configuration.html +160 -6
- package/website/docs/plugin-development.html +0 -4
- package/website/docs/project-structure.html +1 -1
- package/website/index.html +78 -44
- package/website/script.js +56 -0
- package/website/styles.css +128 -11
package/README.md
CHANGED
package/SPEC.md
CHANGED
package/docs/user-manual.md
CHANGED
|
@@ -31,7 +31,7 @@ VB-Agent 是一个基于插件的 Agent 框架,具有以下特性:
|
|
|
31
31
|
### 项目结构
|
|
32
32
|
|
|
33
33
|
```
|
|
34
|
-
|
|
34
|
+
foliko/
|
|
35
35
|
├── src/ # 核心源码
|
|
36
36
|
│ ├── core/ # 核心模块
|
|
37
37
|
│ │ ├── framework.js # 框架容器
|
|
@@ -733,7 +733,7 @@ module.exports = function(Plugin) {
|
|
|
733
733
|
name: my-skill
|
|
734
734
|
description: 我的技能描述
|
|
735
735
|
license: MIT
|
|
736
|
-
compatibility:
|
|
736
|
+
compatibility: foliko >= 1.0.0
|
|
737
737
|
metadata:
|
|
738
738
|
author: Your Name
|
|
739
739
|
version: 1.0.0
|
|
@@ -753,13 +753,13 @@ Agent 可以通过 `loadSkill` 工具加载技能:
|
|
|
753
753
|
|
|
754
754
|
```
|
|
755
755
|
用户: 帮我创建一个系统信息插件
|
|
756
|
-
Agent: [调用 loadSkill 技能
|
|
756
|
+
Agent: [调用 loadSkill 技能 foliko-dev]
|
|
757
757
|
Agent: [获取插件开发指南后,按照指南创建插件]
|
|
758
758
|
```
|
|
759
759
|
|
|
760
760
|
### 6.4 内置技能
|
|
761
761
|
|
|
762
|
-
- **
|
|
762
|
+
- **foliko-dev** - VB-Agent 插件开发指南
|
|
763
763
|
- **api-patterns** - API 设计模式
|
|
764
764
|
- **app-builder** - 应用程序构建
|
|
765
765
|
- **architecture** - 架构设计
|
package/install.ps1
CHANGED
|
@@ -1,179 +1,60 @@
|
|
|
1
|
-
# Foliko
|
|
2
|
-
# 使用方式: irm https://raw.githubusercontent.com/user/vb-agent/main/install.ps1 | iex
|
|
1
|
+
# Foliko Installer
|
|
3
2
|
|
|
4
|
-
|
|
3
|
+
# Step 1: Fix execution policy first
|
|
4
|
+
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser -Force -ErrorAction SilentlyContinue
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
Write-Host "Foliko 安装器" -ForegroundColor Cyan
|
|
10
|
-
Write-Host "=================" -ForegroundColor Cyan
|
|
6
|
+
Write-Host "Foliko Installer"
|
|
7
|
+
Write-Host "================="
|
|
11
8
|
Write-Host ""
|
|
12
9
|
|
|
13
|
-
#
|
|
14
|
-
|
|
15
|
-
Write-Host "正在检查 Node.js..." -ForegroundColor Cyan
|
|
16
|
-
|
|
17
|
-
if (Get-Command node -ErrorAction SilentlyContinue) {
|
|
18
|
-
Write-Host "Node.js 已安装: $(node --version)" -ForegroundColor Green
|
|
19
|
-
return $true
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
Write-Host "Node.js 未安装,正在安装..." -ForegroundColor Yellow
|
|
23
|
-
|
|
24
|
-
# 下载 Node.js LTS 安装包
|
|
25
|
-
$nodeUrl = "https://nodejs.org/dist/v20.11.0/node-v20.11.0-x64.msi"
|
|
26
|
-
$nodeInstaller = "$env:TEMP\node-installer.msi"
|
|
27
|
-
|
|
28
|
-
Write-Host "下载 Node.js..." -ForegroundColor Cyan
|
|
29
|
-
Invoke-WebRequest -Uri $nodeUrl -OutFile $nodeInstaller
|
|
30
|
-
|
|
31
|
-
Write-Host "安装 Node.js (需要管理员权限)..." -ForegroundColor Yellow
|
|
32
|
-
Start-Process msiexec.exe -ArgumentList "/i", $nodeInstaller, "/quiet", "/norestart" -Wait
|
|
33
|
-
|
|
34
|
-
# 刷新环境变量
|
|
35
|
-
$env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
|
|
36
|
-
|
|
37
|
-
# 验证安装
|
|
38
|
-
Start-Sleep -Seconds 2
|
|
39
|
-
if (Get-Command node -ErrorAction SilentlyContinue) {
|
|
40
|
-
Write-Host "Node.js 安装成功: $(node --version)" -ForegroundColor Green
|
|
41
|
-
Remove-Item $nodeInstaller -Force -ErrorAction SilentlyContinue
|
|
42
|
-
return $true
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
Write-Host "Node.js 安装失败,请手动安装" -ForegroundColor Red
|
|
46
|
-
Write-Host "下载地址: https://nodejs.org/" -ForegroundColor Yellow
|
|
47
|
-
return $false
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
# 检查并安装 Python
|
|
51
|
-
function Install-Python {
|
|
52
|
-
Write-Host "正在检查 Python..." -ForegroundColor Cyan
|
|
10
|
+
# Step 2: Refresh PATH
|
|
11
|
+
$env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
|
|
53
12
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
Write-Host "Python 未安装,正在安装..." -ForegroundColor Yellow
|
|
13
|
+
# Step 3: Check and install Git
|
|
14
|
+
Write-Host "Checking Git..."
|
|
15
|
+
if (-not (Get-Command git -ErrorAction SilentlyContinue)) {
|
|
16
|
+
Write-Host "Git not found, installing..."
|
|
60
17
|
|
|
61
|
-
#
|
|
62
|
-
$
|
|
63
|
-
$
|
|
18
|
+
# Download Git for Windows
|
|
19
|
+
$gitUrl = "https://github.com/git-for-windows/git/releases/download/v2.44.0.windows.1/MinGit-2.44.0-64-bit.zip"
|
|
20
|
+
$gitInstaller = "$env:TEMP\git-installer.zip"
|
|
64
21
|
|
|
65
|
-
Write-Host "
|
|
66
|
-
Invoke-WebRequest -Uri $
|
|
22
|
+
Write-Host "Downloading Git..."
|
|
23
|
+
Invoke-WebRequest -Uri $gitUrl -OutFile $gitInstaller -UseBasicParsing
|
|
67
24
|
|
|
68
|
-
Write-Host "
|
|
69
|
-
|
|
70
|
-
|
|
25
|
+
Write-Host "Installing Git..."
|
|
26
|
+
Expand-Archive -Path $gitInstaller -DestinationPath "C:\Git" -Force
|
|
27
|
+
$env:Path = "C:\Git\cmd;$env:Path"
|
|
71
28
|
|
|
72
|
-
#
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
if (Get-Command python -ErrorAction SilentlyContinue) {
|
|
78
|
-
Write-Host "Python 安装成功: $(python --version)" -ForegroundColor Green
|
|
79
|
-
Remove-Item $pythonInstaller -Force -ErrorAction SilentlyContinue
|
|
80
|
-
return $true
|
|
29
|
+
# Verify
|
|
30
|
+
if (Get-Command git -ErrorAction SilentlyContinue) {
|
|
31
|
+
Write-Host "Git installed"
|
|
32
|
+
} else {
|
|
33
|
+
Write-Host "Git installation failed. Please install Git manually: https://git-scm.com/download/win"
|
|
81
34
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
Write-Host "
|
|
85
|
-
return $false
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
# 创建 Python 虚拟环境
|
|
89
|
-
function Install-PythonVenv {
|
|
90
|
-
param([string]$venvDir)
|
|
91
|
-
|
|
92
|
-
Write-Host "正在检查 Python venv..." -ForegroundColor Cyan
|
|
93
|
-
|
|
94
|
-
if (-not (Get-Command python -ErrorAction SilentlyContinue)) {
|
|
95
|
-
Write-Host "Python 未安装,跳过 venv" -ForegroundColor Yellow
|
|
96
|
-
return $false
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if (Test-Path $venvDir) {
|
|
100
|
-
Write-Host "虚拟环境已存在: $venvDir" -ForegroundColor Green
|
|
101
|
-
return $true
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
Write-Host "创建虚拟环境: $venvDir" -ForegroundColor Cyan
|
|
105
|
-
python -m venv $venvDir
|
|
106
|
-
|
|
107
|
-
if (Test-Path "$venvDir\Scripts\python.exe") {
|
|
108
|
-
Write-Host "虚拟环境创建成功" -ForegroundColor Green
|
|
109
|
-
|
|
110
|
-
# 激活并安装基础包
|
|
111
|
-
Write-Host "安装基础依赖..." -ForegroundColor Cyan
|
|
112
|
-
& "$venvDir\Scripts\pip.exe" install pip --upgrade
|
|
113
|
-
return $true
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
Write-Host "虚拟环境创建失败" -ForegroundColor Red
|
|
117
|
-
return $false
|
|
35
|
+
Remove-Item $gitInstaller -Force -ErrorAction SilentlyContinue
|
|
36
|
+
} else {
|
|
37
|
+
Write-Host "Git ready"
|
|
118
38
|
}
|
|
119
39
|
|
|
120
|
-
#
|
|
121
|
-
Write-Host "
|
|
122
|
-
|
|
123
|
-
Write-Host ""
|
|
124
|
-
|
|
125
|
-
# 检查并安装依赖
|
|
126
|
-
$nodeOk = Install-NodeJS
|
|
127
|
-
Write-Host ""
|
|
128
|
-
$pythonOk = Install-Python
|
|
129
|
-
Write-Host ""
|
|
130
|
-
|
|
131
|
-
if (-not $nodeOk) {
|
|
132
|
-
Write-Host "警告: Node.js 未正确安装,部分功能可能不可用" -ForegroundColor Yellow
|
|
40
|
+
# Step 4: Check Node.js
|
|
41
|
+
Write-Host "Checking Node.js..."
|
|
42
|
+
if (-not (Get-Command npm -ErrorAction SilentlyContinue)) {
|
|
43
|
+
Write-Host "Node.js not found. Please install Node.js first: https://nodejs.org/"
|
|
44
|
+
exit 1
|
|
133
45
|
}
|
|
46
|
+
Write-Host "Node.js ready"
|
|
134
47
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
48
|
+
# Step 5: Install Foliko
|
|
49
|
+
Write-Host "Installing Foliko..."
|
|
50
|
+
npm install -g foliko
|
|
138
51
|
|
|
139
|
-
#
|
|
140
|
-
|
|
141
|
-
if ($pythonOk) {
|
|
52
|
+
# Step 6: Verify
|
|
53
|
+
if (Get-Command foliko -ErrorAction SilentlyContinue) {
|
|
142
54
|
Write-Host ""
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
# 创建安装目录
|
|
147
|
-
if (-not (Test-Path $InstallDir)) {
|
|
148
|
-
New-Item -ItemType Directory -Path $InstallDir -Force | Out-Null
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
Write-Host "安装到: $InstallDir" -ForegroundColor Cyan
|
|
152
|
-
Write-Host ""
|
|
153
|
-
|
|
154
|
-
Push-Location $InstallDir
|
|
155
|
-
|
|
156
|
-
if (Test-Path ".git") {
|
|
157
|
-
Write-Host "更新现有安装..." -ForegroundColor Cyan
|
|
158
|
-
git pull
|
|
55
|
+
Write-Host "Installation complete!"
|
|
56
|
+
Write-Host "Run: foliko chat"
|
|
159
57
|
} else {
|
|
160
|
-
Write-Host "
|
|
161
|
-
|
|
58
|
+
Write-Host ""
|
|
59
|
+
Write-Host "Installation may have failed. Try manually: npm install -g foliko"
|
|
162
60
|
}
|
|
163
|
-
|
|
164
|
-
# 安装依赖
|
|
165
|
-
Write-Host "安装 npm 依赖..." -ForegroundColor Cyan
|
|
166
|
-
npm install
|
|
167
|
-
|
|
168
|
-
# 全局链接 CLI
|
|
169
|
-
Write-Host "安装 CLI..." -ForegroundColor Cyan
|
|
170
|
-
npm link
|
|
171
|
-
|
|
172
|
-
Pop-Location
|
|
173
|
-
|
|
174
|
-
Write-Host ""
|
|
175
|
-
Write-Host "安装完成!" -ForegroundColor Green
|
|
176
|
-
Write-Host ""
|
|
177
|
-
Write-Host "使用方法:" -ForegroundColor Yellow
|
|
178
|
-
Write-Host " foliko chat" -ForegroundColor White
|
|
179
|
-
Write-Host ""
|
package/install.sh
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Foliko Installer (macOS/Linux)
|
|
3
|
+
|
|
4
|
+
set -e
|
|
5
|
+
|
|
6
|
+
echo -e "\033[36mFoliko Installer\033[0m"
|
|
7
|
+
echo -e "\033[36m=================\033[0m"
|
|
8
|
+
echo ""
|
|
9
|
+
|
|
10
|
+
# Detect OS
|
|
11
|
+
detect_os() {
|
|
12
|
+
if [[ "$OSTYPE" == "darwin"* ]]; then
|
|
13
|
+
echo "macOS"
|
|
14
|
+
elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
|
15
|
+
echo "Linux"
|
|
16
|
+
else
|
|
17
|
+
echo "unknown"
|
|
18
|
+
fi
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
OS=$(detect_os)
|
|
22
|
+
|
|
23
|
+
# Check and install Node.js
|
|
24
|
+
install_nodejs() {
|
|
25
|
+
echo -e "\033[36mChecking Node.js...\033[0m"
|
|
26
|
+
|
|
27
|
+
if command -v node &> /dev/null; then
|
|
28
|
+
echo -e "\033[32mNode.js installed: $(node --version)\033[0m"
|
|
29
|
+
return 0
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
echo -e "\033[33mNode.js not found, installing...\033[0m"
|
|
33
|
+
|
|
34
|
+
if [[ "$OS" == "macOS" ]]; then
|
|
35
|
+
if command -v brew &> /dev/null; then
|
|
36
|
+
brew install node
|
|
37
|
+
else
|
|
38
|
+
echo -e "\033[33mHomebrew not found. Install it first:\033[0m"
|
|
39
|
+
echo "/bin/bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\""
|
|
40
|
+
return 1
|
|
41
|
+
fi
|
|
42
|
+
elif [[ "$OS" == "Linux" ]]; then
|
|
43
|
+
if command -v apt-get &> /dev/null; then
|
|
44
|
+
sudo apt-get update
|
|
45
|
+
sudo apt-get install -y nodejs npm
|
|
46
|
+
elif command -v yum &> /dev/null; then
|
|
47
|
+
sudo yum install -y nodejs npm
|
|
48
|
+
elif command -v pacman &> /dev/null; then
|
|
49
|
+
sudo pacman -S nodejs npm
|
|
50
|
+
else
|
|
51
|
+
echo -e "\033[31mNo supported package manager found. Please install Node.js manually\033[0m"
|
|
52
|
+
echo "Download: https://nodejs.org/"
|
|
53
|
+
return 1
|
|
54
|
+
fi
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
if command -v node &> /dev/null; then
|
|
58
|
+
echo -e "\033[32mNode.js installed: $(node --version)\033[0m"
|
|
59
|
+
return 0
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
echo -e "\033[31mNode.js installation failed\033[0m"
|
|
63
|
+
echo "Download: https://nodejs.org/"
|
|
64
|
+
return 1
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
# Check and install Python
|
|
68
|
+
install_python() {
|
|
69
|
+
echo -e "\033[36mChecking Python...\033[0m"
|
|
70
|
+
|
|
71
|
+
if command -v python3 &> /dev/null; then
|
|
72
|
+
echo -e "\033[32mPython installed: $(python3 --version)\033[0m"
|
|
73
|
+
return 0
|
|
74
|
+
fi
|
|
75
|
+
|
|
76
|
+
echo -e "\033[33mPython not found, installing...\033[0m"
|
|
77
|
+
|
|
78
|
+
if [[ "$OS" == "macOS" ]]; then
|
|
79
|
+
if command -v brew &> /dev/null; then
|
|
80
|
+
brew install python3
|
|
81
|
+
fi
|
|
82
|
+
elif [[ "$OS" == "Linux" ]]; then
|
|
83
|
+
if command -v apt-get &> /dev/null; then
|
|
84
|
+
sudo apt-get update
|
|
85
|
+
sudo apt-get install -y python3 python3-venv python3-pip
|
|
86
|
+
elif command -v yum &> /dev/null; then
|
|
87
|
+
sudo yum install -y python3
|
|
88
|
+
elif command -v pacman &> /dev/null; then
|
|
89
|
+
sudo pacman -S python python-pip
|
|
90
|
+
fi
|
|
91
|
+
fi
|
|
92
|
+
|
|
93
|
+
if command -v python3 &> /dev/null; then
|
|
94
|
+
echo -e "\033[32mPython installed: $(python3 --version)\033[0m"
|
|
95
|
+
return 0
|
|
96
|
+
fi
|
|
97
|
+
|
|
98
|
+
echo -e "\033[33mPython not installed (optional)\033[0m"
|
|
99
|
+
return 0
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
# Main installation
|
|
103
|
+
echo -e "\033[36mChecking environment...\033[0m"
|
|
104
|
+
echo -e "\033[36m-------------------\033[0m"
|
|
105
|
+
echo ""
|
|
106
|
+
|
|
107
|
+
NODE_OK=0
|
|
108
|
+
PYTHON_OK=0
|
|
109
|
+
|
|
110
|
+
install_nodejs || NODE_OK=1
|
|
111
|
+
echo ""
|
|
112
|
+
install_python || PYTHON_OK=1
|
|
113
|
+
echo ""
|
|
114
|
+
|
|
115
|
+
if [[ $NODE_OK -ne 0 ]]; then
|
|
116
|
+
echo -e "\033[31mError: Node.js not installed correctly\033[0m"
|
|
117
|
+
echo "Please install Node.js first: https://nodejs.org/"
|
|
118
|
+
exit 1
|
|
119
|
+
fi
|
|
120
|
+
|
|
121
|
+
# Install Foliko
|
|
122
|
+
echo -e "\033[36mInstalling Foliko...\033[0m"
|
|
123
|
+
npm install -g foliko
|
|
124
|
+
|
|
125
|
+
if command -v foliko &> /dev/null; then
|
|
126
|
+
echo ""
|
|
127
|
+
echo -e "\033[32mInstallation complete!\033[0m"
|
|
128
|
+
echo ""
|
|
129
|
+
echo -e "\033[33mUsage:\033[0m"
|
|
130
|
+
echo -e " \033[37mfoliko chat\033[0m"
|
|
131
|
+
else
|
|
132
|
+
echo ""
|
|
133
|
+
echo -e "\033[31mInstallation failed, please try manually:\033[0m"
|
|
134
|
+
echo -e " \033[37mnpm install -g foliko\033[0m"
|
|
135
|
+
fi
|
|
136
|
+
|
|
137
|
+
echo ""
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "foliko",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.20",
|
|
4
4
|
"description": "简约的插件化 Agent 框架",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"@ai-sdk/openai-compatible": "^2.0.35",
|
|
27
27
|
"@anthropic-ai/sdk": "^0.39.0",
|
|
28
28
|
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
29
|
-
"@pinixai/weixin-bot": "github
|
|
29
|
+
"@pinixai/weixin-bot": "git+https://github.com/chnak/weixin-bot.git",
|
|
30
30
|
"ai": "^6.0.116",
|
|
31
31
|
"dotenv": "^17.3.1",
|
|
32
32
|
"imap": "^0.8.19",
|
|
@@ -127,7 +127,7 @@ class SubAgentPlugin extends Plugin {
|
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
// 尝试从framework获取主agent
|
|
130
|
-
// 在
|
|
130
|
+
// 在foliko中,主agent通常是通过framework.createAgent创建的
|
|
131
131
|
if (this._framework._mainAgent) {
|
|
132
132
|
return this._framework._mainAgent
|
|
133
133
|
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
3
|
-
description:
|
|
2
|
+
name: foliko-dev
|
|
3
|
+
description: Foliko Framework 插件开发指南。当用户说"创建插件"、"开发插件"时立即调用此 skill。
|
|
4
4
|
allowed-tools: Read, Write, Edit, Glob, Grep, Bash
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
#
|
|
7
|
+
# Foliko Plugin Development Guide
|
|
8
8
|
|
|
9
9
|
## 概述
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Foliko 是一个基于插件的 Agent 框架,核心简单,通过插件扩展功能。
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
@@ -49,6 +49,29 @@
|
|
|
49
49
|
<div class="main-content">
|
|
50
50
|
<h1>配置指南</h1>
|
|
51
51
|
|
|
52
|
+
<h2>环境变量配置 (.env)</h2>
|
|
53
|
+
<p>在项目根目录创建 <code>.env</code> 文件:</p>
|
|
54
|
+
<pre><code># AI Provider: minimax, deepseek, openai, anthropic 等
|
|
55
|
+
FOLIKO_PROVIDER=minimax
|
|
56
|
+
|
|
57
|
+
# AI Model(可选,不填则使用 provider 默认值)
|
|
58
|
+
# MiniMax: MiniMax-M2.7
|
|
59
|
+
# DeepSeek: deepseek-chat, deepseek-coder 等
|
|
60
|
+
FOLIKO_MODEL=
|
|
61
|
+
|
|
62
|
+
# API Base URL(可选,不填则使用 provider 默认值)
|
|
63
|
+
# MiniMax: https://api.minimaxi.com/v1
|
|
64
|
+
# DeepSeek: https://api.deepseek.com/v1
|
|
65
|
+
FOLIKO_BASE_URL=
|
|
66
|
+
|
|
67
|
+
# API Key(通用,不填则使用 provider 专用 key)
|
|
68
|
+
FOLIKO_API_KEY=
|
|
69
|
+
|
|
70
|
+
# Provider 专用 API Key(可选)
|
|
71
|
+
DEEPSEEK_API_KEY=sk-your-deepseek-api-key
|
|
72
|
+
MINIMAX_API_KEY=sk-your-minimax-api-key</code></pre>
|
|
73
|
+
<p><strong>配置优先级</strong>:命令行参数 > .env配置 > provider默认值</p>
|
|
74
|
+
|
|
52
75
|
<h2>目录结构</h2>
|
|
53
76
|
<p>在项目根目录创建 <code>.agent</code> 目录:</p>
|
|
54
77
|
<pre><code>项目目录/
|
|
@@ -92,28 +115,159 @@ ai_base_url: https://api.minimaxi.com/v1</code></pre>
|
|
|
92
115
|
}</code></pre>
|
|
93
116
|
|
|
94
117
|
<h2>CLI 参数</h2>
|
|
118
|
+
<p>命令行参数会覆盖 .env 配置:</p>
|
|
95
119
|
<table>
|
|
96
120
|
<tr>
|
|
97
121
|
<th>参数</th>
|
|
98
122
|
<th>说明</th>
|
|
99
|
-
|
|
100
|
-
<tr>
|
|
101
|
-
<td><code>--model</code></td>
|
|
102
|
-
<td>指定 AI 模型</td>
|
|
123
|
+
<th>示例</th>
|
|
103
124
|
</tr>
|
|
104
125
|
<tr>
|
|
105
126
|
<td><code>--provider</code></td>
|
|
106
127
|
<td>指定 AI 提供商</td>
|
|
128
|
+
<td><code>deepseek</code>, <code>minimax</code></td>
|
|
107
129
|
</tr>
|
|
108
130
|
<tr>
|
|
109
|
-
<td><code>--
|
|
110
|
-
<td>指定
|
|
131
|
+
<td><code>--model</code></td>
|
|
132
|
+
<td>指定 AI 模型</td>
|
|
133
|
+
<td><code>deepseek-chat</code>, <code>MiniMax-M2.7</code></td>
|
|
111
134
|
</tr>
|
|
112
135
|
<tr>
|
|
113
136
|
<td><code>--base-url</code></td>
|
|
114
137
|
<td>指定 API 地址</td>
|
|
138
|
+
<td><code>https://api.deepseek.com/v1</code></td>
|
|
139
|
+
</tr>
|
|
140
|
+
<tr>
|
|
141
|
+
<td><code>--api-key</code></td>
|
|
142
|
+
<td>指定 API 密钥</td>
|
|
143
|
+
<td><code>sk-xxx</code></td>
|
|
115
144
|
</tr>
|
|
116
145
|
</table>
|
|
146
|
+
|
|
147
|
+
<h3>使用示例</h3>
|
|
148
|
+
<pre><code># 使用 .env 中的配置
|
|
149
|
+
npm run chat
|
|
150
|
+
|
|
151
|
+
# 指定完整配置
|
|
152
|
+
foliko chat --provider deepseek --model deepseek-chat --base-url https://api.deepseek.com/v1 --api-key sk-xxx
|
|
153
|
+
|
|
154
|
+
# 只指定 provider(使用 provider 默认 model 和 baseURL)
|
|
155
|
+
foliko chat --provider deepseek --api-key sk-xxx
|
|
156
|
+
|
|
157
|
+
# 只指定 api-key(使用 FOLIKO_PROVIDER 设定的 provider)
|
|
158
|
+
foliko chat --api-key sk-xxx</code></pre>
|
|
159
|
+
|
|
160
|
+
<h2>插件配置</h2>
|
|
161
|
+
|
|
162
|
+
<h3>Telegram 插件</h3>
|
|
163
|
+
<pre><code>{
|
|
164
|
+
"telegram": {
|
|
165
|
+
"botToken": "your-bot-token",
|
|
166
|
+
"allowedChats": ["123456789"],
|
|
167
|
+
"groupMode": false,
|
|
168
|
+
"prefix": "/"
|
|
169
|
+
}
|
|
170
|
+
}</code></pre>
|
|
171
|
+
<table>
|
|
172
|
+
<tr><th>配置项</th><th>说明</th><th>默认值</th></tr>
|
|
173
|
+
<tr><td>botToken</td><td>Telegram Bot Token</td><td>TELEGRAM_BOT_TOKEN 环境变量</td></tr>
|
|
174
|
+
<tr><td>allowedChats</td><td>允许的聊天 ID 数组</td><td>[] (允许所有人)</td></tr>
|
|
175
|
+
<tr><td>groupMode</td><td>是否启用群组模式</td><td>false</td></tr>
|
|
176
|
+
<tr><td>prefix</td><td>命令前缀</td><td>/</td></tr>
|
|
177
|
+
</table>
|
|
178
|
+
|
|
179
|
+
<h3>WeChat 插件</h3>
|
|
180
|
+
<pre><code>{
|
|
181
|
+
"weixin": {
|
|
182
|
+
"forceLogin": false,
|
|
183
|
+
"qrcodeTerminal": true,
|
|
184
|
+
"allowedUsers": []
|
|
185
|
+
}
|
|
186
|
+
}</code></pre>
|
|
187
|
+
<table>
|
|
188
|
+
<tr><th>配置项</th><th>说明</th><th>默认值</th></tr>
|
|
189
|
+
<tr><td>forceLogin</td><td>强制重新扫码登录</td><td>false</td></tr>
|
|
190
|
+
<tr><td>qrcodeTerminal</td><td>终端渲染二维码</td><td>true</td></tr>
|
|
191
|
+
<tr><td>allowedUsers</td><td>允许的用户 ID 数组</td><td>[] (允许所有人)</td></tr>
|
|
192
|
+
</table>
|
|
193
|
+
|
|
194
|
+
<h3>Session 插件</h3>
|
|
195
|
+
<pre><code>{
|
|
196
|
+
"session": {
|
|
197
|
+
"sessionTTL": 1800000,
|
|
198
|
+
"maxSessions": 100,
|
|
199
|
+
"maxHistoryLength": 50,
|
|
200
|
+
"autoCleanup": true,
|
|
201
|
+
"cleanupInterval": 300000
|
|
202
|
+
}
|
|
203
|
+
}</code></pre>
|
|
204
|
+
<table>
|
|
205
|
+
<tr><th>配置项</th><th>说明</th><th>默认值</th></tr>
|
|
206
|
+
<tr><td>sessionTTL</td><td>会话过期时间(毫秒)</td><td>30分钟</td></tr>
|
|
207
|
+
<tr><td>maxSessions</td><td>最大会话数</td><td>100</td></tr>
|
|
208
|
+
<tr><td>maxHistoryLength</td><td>最大历史消息数</td><td>50</td></tr>
|
|
209
|
+
<tr><td>autoCleanup</td><td>自动清理过期会话</td><td>true</td></tr>
|
|
210
|
+
<tr><td>cleanupInterval</td><td>清理检查间隔(毫秒)</td><td>5分钟</td></tr>
|
|
211
|
+
</table>
|
|
212
|
+
|
|
213
|
+
<h3>Storage 插件</h3>
|
|
214
|
+
<pre><code>{
|
|
215
|
+
"storage": {
|
|
216
|
+
"type": "json",
|
|
217
|
+
"path": ".agent/data",
|
|
218
|
+
"namespace": "default"
|
|
219
|
+
}
|
|
220
|
+
}</code></pre>
|
|
221
|
+
<table>
|
|
222
|
+
<tr><th>配置项</th><th>说明</th><th>默认值</th></tr>
|
|
223
|
+
<tr><td>type</td><td>存储类型 (json/memory)</td><td>json</td></tr>
|
|
224
|
+
<tr><td>path</td><td>存储文件路径</td><td>.agent/data</td></tr>
|
|
225
|
+
<tr><td>namespace</td><td>命名空间</td><td>default</td></tr>
|
|
226
|
+
</table>
|
|
227
|
+
|
|
228
|
+
<h3>Scheduler 插件</h3>
|
|
229
|
+
<pre><code>{
|
|
230
|
+
"scheduler": {
|
|
231
|
+
"checkInterval": 1000
|
|
232
|
+
}
|
|
233
|
+
}</code></pre>
|
|
234
|
+
<table>
|
|
235
|
+
<tr><th>配置项</th><th>说明</th><th>默认值</th></tr>
|
|
236
|
+
<tr><td>checkInterval</td><td>任务检查间隔(毫秒)</td><td>1000</td></tr>
|
|
237
|
+
</table>
|
|
238
|
+
|
|
239
|
+
<h3>Email 插件</h3>
|
|
240
|
+
<p>通过环境变量配置:</p>
|
|
241
|
+
<pre><code># SMTP 配置 (发送邮件)
|
|
242
|
+
SMTP_HOST=smtp.gmail.com
|
|
243
|
+
SMTP_PORT=587
|
|
244
|
+
SMTP_SECURE=false
|
|
245
|
+
SMTP_USER=your-email@gmail.com
|
|
246
|
+
SMTP_PASS=your-app-password
|
|
247
|
+
|
|
248
|
+
# IMAP 配置 (读取邮件)
|
|
249
|
+
IMAP_HOST=imap.gmail.com
|
|
250
|
+
IMAP_PORT=993
|
|
251
|
+
IMAP_USER=your-email@gmail.com
|
|
252
|
+
IMAP_PASS=your-app-password
|
|
253
|
+
|
|
254
|
+
# 默认发件人
|
|
255
|
+
FROM_EMAIL=your-email@gmail.com</code></pre>
|
|
256
|
+
|
|
257
|
+
<h3>MCP 配置</h3>
|
|
258
|
+
<p>在 <code>.agent/mcp_config.json</code> 中配置 MCP 服务器:</p>
|
|
259
|
+
<pre><code>{
|
|
260
|
+
"mcpServers": {
|
|
261
|
+
"fetch": {
|
|
262
|
+
"command": "npx",
|
|
263
|
+
"args": ["-y", "@modelcontextprotocol/server-fetch"]
|
|
264
|
+
},
|
|
265
|
+
"filesystem": {
|
|
266
|
+
"command": "npx",
|
|
267
|
+
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/dir"]
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}</code></pre>
|
|
117
271
|
</div>
|
|
118
272
|
</body>
|
|
119
273
|
</html>
|
package/website/index.html
CHANGED
|
@@ -22,14 +22,28 @@
|
|
|
22
22
|
|
|
23
23
|
<main>
|
|
24
24
|
<section id="home" class="hero">
|
|
25
|
-
<
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
25
|
+
<div class="hero-content">
|
|
26
|
+
<h1>Foliko</h1>
|
|
27
|
+
<p class="tagline">简约的插件化 Agent 框架</p>
|
|
28
|
+
|
|
29
|
+
<div class="install-box">
|
|
30
|
+
<div class="install-tabs">
|
|
31
|
+
<button class="tab active" data-cmd="irm https://foliko.com/install.ps1 | iex">Windows</button>
|
|
32
|
+
<button class="tab" data-cmd="curl -fsSL https://foliko.com/install.sh | bash">Mac / Linux</button>
|
|
33
|
+
<button class="tab" data-cmd="npm install -g foliko">npm</button>
|
|
34
|
+
</div>
|
|
35
|
+
<div class="install-cmd">
|
|
36
|
+
<code id="install-cmd">irm https://foliko.com/install.ps1 | iex</code>
|
|
37
|
+
<button class="copy-btn" onclick="copyCmd()">复制</button>
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
<div class="hero-links">
|
|
42
|
+
<a href="#features">核心特性</a>
|
|
43
|
+
<a href="#quickstart">快速开始</a>
|
|
44
|
+
<a href="#docs">文档</a>
|
|
45
|
+
<a href="#plugins">插件</a>
|
|
46
|
+
</div>
|
|
33
47
|
</div>
|
|
34
48
|
</section>
|
|
35
49
|
|
|
@@ -72,27 +86,19 @@
|
|
|
72
86
|
<section id="quickstart" class="quickstart">
|
|
73
87
|
<h2>快速开始</h2>
|
|
74
88
|
|
|
75
|
-
<div class="code-block">
|
|
76
|
-
<h3>安装</h3>
|
|
77
|
-
<pre><code># PowerShell (Windows)
|
|
78
|
-
irm https://raw.githubusercontent.com/your-username/vb-agent/main/install.ps1 | iex
|
|
79
|
-
|
|
80
|
-
# 或者克隆仓库
|
|
81
|
-
git clone https://github.com/your-username/vb-agent.git
|
|
82
|
-
cd vb-agent
|
|
83
|
-
npm install
|
|
84
|
-
npm link</code></pre>
|
|
85
|
-
</div>
|
|
86
|
-
|
|
87
89
|
<div class="code-block">
|
|
88
90
|
<h3>配置</h3>
|
|
89
|
-
<pre><code>#
|
|
90
|
-
|
|
91
|
+
<pre><code># 创建 .env 文件
|
|
92
|
+
touch .env
|
|
91
93
|
|
|
92
|
-
#
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
94
|
+
# 编辑 .env 添加配置
|
|
95
|
+
# MiniMax 示例:
|
|
96
|
+
# FOLIKO_PROVIDER=minimax
|
|
97
|
+
# MINIMAX_API_KEY=sk-your-api-key
|
|
98
|
+
|
|
99
|
+
# DeepSeek 示例:
|
|
100
|
+
# FOLIKO_PROVIDER=deepseek
|
|
101
|
+
# DEEPSEEK_API_KEY=sk-your-api-key</code></pre>
|
|
96
102
|
</div>
|
|
97
103
|
|
|
98
104
|
<div class="code-block">
|
|
@@ -131,53 +137,81 @@ echo "ai_provider: minimax" >> .agent/config</code></pre>
|
|
|
131
137
|
<th>插件</th>
|
|
132
138
|
<th>说明</th>
|
|
133
139
|
<th>工具</th>
|
|
140
|
+
<th>配置</th>
|
|
134
141
|
</tr>
|
|
135
142
|
</thead>
|
|
136
143
|
<tbody>
|
|
137
144
|
<tr>
|
|
138
|
-
<td>AI</td>
|
|
145
|
+
<td><strong>AI</strong></td>
|
|
139
146
|
<td>AI 提供商集成</td>
|
|
140
147
|
<td>chat, chatStream</td>
|
|
148
|
+
<td>provider, model, apiKey, baseURL</td>
|
|
149
|
+
</tr>
|
|
150
|
+
<tr>
|
|
151
|
+
<td><strong>Session</strong></td>
|
|
152
|
+
<td>会话管理,多会话隔离、历史记录</td>
|
|
153
|
+
<td>session_create, session_get, session_list, session_delete, session_history</td>
|
|
154
|
+
<td>sessionTTL, maxSessions, maxHistoryLength</td>
|
|
155
|
+
</tr>
|
|
156
|
+
<tr>
|
|
157
|
+
<td><strong>Telegram</strong></td>
|
|
158
|
+
<td>Telegram Bot 对话</td>
|
|
159
|
+
<td>Bot 接收消息,自动对话</td>
|
|
160
|
+
<td>botToken, allowedChats, groupMode, prefix</td>
|
|
161
|
+
</tr>
|
|
162
|
+
<tr>
|
|
163
|
+
<td><strong>WeChat</strong></td>
|
|
164
|
+
<td>微信对话</td>
|
|
165
|
+
<td>Bot 接收消息,自动对话</td>
|
|
166
|
+
<td>forceLogin, qrcodeTerminal, allowedUsers</td>
|
|
141
167
|
</tr>
|
|
142
168
|
<tr>
|
|
143
|
-
<td>Storage</td>
|
|
144
|
-
<td
|
|
145
|
-
<td>
|
|
169
|
+
<td><strong>Storage</strong></td>
|
|
170
|
+
<td>数据持久化存储</td>
|
|
171
|
+
<td>storage_set, storage_get, storage_delete, storage_list, storage_clear</td>
|
|
172
|
+
<td>type (json/memory), path, namespace</td>
|
|
146
173
|
</tr>
|
|
147
174
|
<tr>
|
|
148
|
-
<td>
|
|
149
|
-
<td
|
|
150
|
-
<td
|
|
175
|
+
<td><strong>Scheduler</strong></td>
|
|
176
|
+
<td>定时任务调度</td>
|
|
177
|
+
<td>schedule_task, schedule_list, schedule_cancel, cron_examples</td>
|
|
178
|
+
<td>checkInterval</td>
|
|
151
179
|
</tr>
|
|
152
180
|
<tr>
|
|
153
|
-
<td>
|
|
154
|
-
<td
|
|
155
|
-
<td>
|
|
181
|
+
<td><strong>Email</strong></td>
|
|
182
|
+
<td>邮件收发</td>
|
|
183
|
+
<td>email_send, email_read, email_unread_count, email_mark_read, email_configure</td>
|
|
184
|
+
<td>SMTP/IMAP 配置</td>
|
|
156
185
|
</tr>
|
|
157
186
|
<tr>
|
|
158
|
-
<td>Shell</td>
|
|
187
|
+
<td><strong>Shell</strong></td>
|
|
159
188
|
<td>Shell 命令执行</td>
|
|
160
189
|
<td>shell_execute</td>
|
|
190
|
+
<td>-</td>
|
|
161
191
|
</tr>
|
|
162
192
|
<tr>
|
|
163
|
-
<td>Python</td>
|
|
193
|
+
<td><strong>Python</strong></td>
|
|
164
194
|
<td>Python 代码执行</td>
|
|
165
195
|
<td>python_execute</td>
|
|
196
|
+
<td>-</td>
|
|
166
197
|
</tr>
|
|
167
198
|
<tr>
|
|
168
|
-
<td>MCP</td>
|
|
199
|
+
<td><strong>MCP</strong></td>
|
|
169
200
|
<td>MCP 协议支持</td>
|
|
170
201
|
<td>mcp_execute, mcp_reload</td>
|
|
202
|
+
<td>mcp_config.json</td>
|
|
171
203
|
</tr>
|
|
172
204
|
<tr>
|
|
173
|
-
<td>
|
|
174
|
-
<td
|
|
175
|
-
<td>
|
|
205
|
+
<td><strong>Install</strong></td>
|
|
206
|
+
<td>npm 包安装</td>
|
|
207
|
+
<td>install</td>
|
|
208
|
+
<td>-</td>
|
|
176
209
|
</tr>
|
|
177
210
|
<tr>
|
|
178
|
-
<td>Audit</td>
|
|
211
|
+
<td><strong>Audit</strong></td>
|
|
179
212
|
<td>审计日志</td>
|
|
180
213
|
<td>audit_query</td>
|
|
214
|
+
<td>-</td>
|
|
181
215
|
</tr>
|
|
182
216
|
</tbody>
|
|
183
217
|
</table>
|
|
@@ -187,7 +221,7 @@ echo "ai_provider: minimax" >> .agent/config</code></pre>
|
|
|
187
221
|
<footer>
|
|
188
222
|
<p>© 2024 Foliko. MIT License.</p>
|
|
189
223
|
<p>
|
|
190
|
-
<a href="https://
|
|
224
|
+
<a href="https://www.npmjs.com/package/foliko">npm</a> |
|
|
191
225
|
<a href="docs/api.html">API 文档</a>
|
|
192
226
|
</p>
|
|
193
227
|
</footer>
|
package/website/script.js
CHANGED
|
@@ -1,3 +1,59 @@
|
|
|
1
|
+
// Install tab switching
|
|
2
|
+
document.querySelectorAll('.install-tabs .tab').forEach(tab => {
|
|
3
|
+
tab.addEventListener('click', () => {
|
|
4
|
+
document.querySelectorAll('.install-tabs .tab').forEach(t => t.classList.remove('active'));
|
|
5
|
+
tab.classList.add('active');
|
|
6
|
+
document.getElementById('install-cmd').textContent = tab.dataset.cmd;
|
|
7
|
+
});
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
// Copy install command
|
|
11
|
+
function copyCmd() {
|
|
12
|
+
const code = document.getElementById('install-cmd').textContent;
|
|
13
|
+
const btn = document.querySelector('.install-cmd .copy-btn');
|
|
14
|
+
|
|
15
|
+
// 复制到剪贴板
|
|
16
|
+
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
17
|
+
navigator.clipboard.writeText(code).then(() => {
|
|
18
|
+
btn.textContent = '已复制';
|
|
19
|
+
btn.classList.add('copied');
|
|
20
|
+
setTimeout(() => {
|
|
21
|
+
btn.textContent = '复制';
|
|
22
|
+
btn.classList.remove('copied');
|
|
23
|
+
}, 2000);
|
|
24
|
+
}).catch(() => {
|
|
25
|
+
fallbackCopy(code, btn);
|
|
26
|
+
});
|
|
27
|
+
} else {
|
|
28
|
+
fallbackCopy(code, btn);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// 备用复制方法
|
|
33
|
+
function fallbackCopy(text, btn) {
|
|
34
|
+
const textarea = document.createElement('textarea');
|
|
35
|
+
textarea.value = text;
|
|
36
|
+
textarea.style.position = 'fixed';
|
|
37
|
+
textarea.style.opacity = '0';
|
|
38
|
+
document.body.appendChild(textarea);
|
|
39
|
+
textarea.select();
|
|
40
|
+
try {
|
|
41
|
+
document.execCommand('copy');
|
|
42
|
+
btn.textContent = '已复制';
|
|
43
|
+
btn.classList.add('copied');
|
|
44
|
+
setTimeout(() => {
|
|
45
|
+
btn.textContent = '复制';
|
|
46
|
+
btn.classList.remove('copied');
|
|
47
|
+
}, 2000);
|
|
48
|
+
} catch (err) {
|
|
49
|
+
btn.textContent = '复制失败';
|
|
50
|
+
setTimeout(() => {
|
|
51
|
+
btn.textContent = '复制';
|
|
52
|
+
}, 2000);
|
|
53
|
+
}
|
|
54
|
+
document.body.removeChild(textarea);
|
|
55
|
+
}
|
|
56
|
+
|
|
1
57
|
// Smooth scrolling
|
|
2
58
|
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
|
3
59
|
anchor.addEventListener('click', function (e) {
|
package/website/styles.css
CHANGED
|
@@ -69,14 +69,17 @@ nav {
|
|
|
69
69
|
.hero {
|
|
70
70
|
min-height: 100vh;
|
|
71
71
|
display: flex;
|
|
72
|
-
flex-direction: column;
|
|
73
|
-
justify-content: center;
|
|
74
72
|
align-items: center;
|
|
75
|
-
|
|
76
|
-
padding: 6rem 2rem
|
|
73
|
+
justify-content: center;
|
|
74
|
+
padding: 6rem 2rem;
|
|
77
75
|
background: linear-gradient(180deg, var(--bg-dark) 0%, var(--bg-card) 100%);
|
|
78
76
|
}
|
|
79
77
|
|
|
78
|
+
.hero-content {
|
|
79
|
+
text-align: center;
|
|
80
|
+
max-width: 600px;
|
|
81
|
+
}
|
|
82
|
+
|
|
80
83
|
.hero h1 {
|
|
81
84
|
font-size: 4rem;
|
|
82
85
|
font-weight: 800;
|
|
@@ -84,27 +87,112 @@ nav {
|
|
|
84
87
|
-webkit-background-clip: text;
|
|
85
88
|
-webkit-text-fill-color: transparent;
|
|
86
89
|
background-clip: text;
|
|
87
|
-
margin-bottom:
|
|
90
|
+
margin-bottom: 0.5rem;
|
|
88
91
|
}
|
|
89
92
|
|
|
90
93
|
.tagline {
|
|
91
94
|
font-size: 1.5rem;
|
|
92
95
|
color: var(--text-secondary);
|
|
93
|
-
margin-bottom:
|
|
96
|
+
margin-bottom: 2rem;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/* Install Box */
|
|
100
|
+
.install-box {
|
|
101
|
+
background: var(--bg-card);
|
|
102
|
+
border: 1px solid var(--border);
|
|
103
|
+
border-radius: 12px;
|
|
104
|
+
overflow: hidden;
|
|
105
|
+
margin: 0 auto 2rem;
|
|
106
|
+
text-align: left;
|
|
107
|
+
min-width: 600px;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.install-tabs {
|
|
111
|
+
display: flex;
|
|
112
|
+
background: var(--bg-dark);
|
|
113
|
+
border-bottom: 1px solid var(--border);
|
|
94
114
|
}
|
|
95
115
|
|
|
96
|
-
.
|
|
97
|
-
|
|
116
|
+
.install-tabs .tab {
|
|
117
|
+
flex: 1;
|
|
118
|
+
min-width: 100px;
|
|
119
|
+
padding: 0.75rem 1rem;
|
|
120
|
+
background: transparent;
|
|
121
|
+
border: none;
|
|
98
122
|
color: var(--text-secondary);
|
|
99
|
-
|
|
100
|
-
|
|
123
|
+
font-size: 0.9rem;
|
|
124
|
+
cursor: pointer;
|
|
125
|
+
transition: all 0.2s;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.install-tabs .tab:hover {
|
|
129
|
+
color: var(--text-primary);
|
|
130
|
+
background: rgba(255,255,255,0.03);
|
|
101
131
|
}
|
|
102
132
|
|
|
103
|
-
.
|
|
133
|
+
.install-tabs .tab.active {
|
|
134
|
+
color: var(--primary);
|
|
135
|
+
background: var(--bg-card);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.install-cmd {
|
|
104
139
|
display: flex;
|
|
140
|
+
align-items: center;
|
|
141
|
+
justify-content: space-between;
|
|
142
|
+
padding: 1rem 1.25rem;
|
|
105
143
|
gap: 1rem;
|
|
106
144
|
}
|
|
107
145
|
|
|
146
|
+
.install-cmd code {
|
|
147
|
+
font-family: 'SF Mono', Monaco, 'Cascadia Code', monospace;
|
|
148
|
+
font-size: 0.9rem;
|
|
149
|
+
color: var(--secondary);
|
|
150
|
+
flex: 1;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.copy-btn {
|
|
154
|
+
background: transparent;
|
|
155
|
+
color: var(--text-secondary);
|
|
156
|
+
border: 1px solid var(--border);
|
|
157
|
+
border-radius: 6px;
|
|
158
|
+
padding: 0.4rem 0.75rem;
|
|
159
|
+
font-size: 0.8rem;
|
|
160
|
+
cursor: pointer;
|
|
161
|
+
transition: all 0.2s;
|
|
162
|
+
white-space: nowrap;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.copy-btn:hover {
|
|
166
|
+
color: var(--text-primary);
|
|
167
|
+
border-color: var(--primary);
|
|
168
|
+
background: rgba(99, 102, 241, 0.1);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.copy-btn.copied {
|
|
172
|
+
color: #22c55e;
|
|
173
|
+
border-color: #22c55e;
|
|
174
|
+
background: rgba(34, 197, 94, 0.1);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/* Hero Links */
|
|
178
|
+
.hero-links {
|
|
179
|
+
display: flex;
|
|
180
|
+
justify-content: center;
|
|
181
|
+
gap: 1.5rem;
|
|
182
|
+
flex-wrap: wrap;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
.hero-links a {
|
|
186
|
+
color: var(--text-secondary);
|
|
187
|
+
text-decoration: none;
|
|
188
|
+
font-size: 0.95rem;
|
|
189
|
+
transition: color 0.2s;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.hero-links a:hover {
|
|
193
|
+
color: var(--primary);
|
|
194
|
+
}
|
|
195
|
+
|
|
108
196
|
.btn {
|
|
109
197
|
padding: 0.75rem 1.5rem;
|
|
110
198
|
border-radius: 8px;
|
|
@@ -288,10 +376,39 @@ footer a:hover {
|
|
|
288
376
|
|
|
289
377
|
/* Responsive */
|
|
290
378
|
@media (max-width: 768px) {
|
|
379
|
+
.hero {
|
|
380
|
+
padding: 5rem 1rem 3rem;
|
|
381
|
+
min-height: auto;
|
|
382
|
+
}
|
|
383
|
+
|
|
291
384
|
.hero h1 {
|
|
292
385
|
font-size: 2.5rem;
|
|
293
386
|
}
|
|
294
387
|
|
|
388
|
+
.hero .tagline {
|
|
389
|
+
font-size: 1.2rem;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
.install-box {
|
|
393
|
+
min-width: auto;
|
|
394
|
+
width: 100%;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
.install-tabs .tab {
|
|
398
|
+
min-width: 80px;
|
|
399
|
+
padding: 0.6rem 0.5rem;
|
|
400
|
+
font-size: 0.8rem;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
.install-cmd code {
|
|
404
|
+
font-size: 0.75rem;
|
|
405
|
+
word-break: break-all;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
.hero-links {
|
|
409
|
+
gap: 1rem;
|
|
410
|
+
}
|
|
411
|
+
|
|
295
412
|
.nav-links {
|
|
296
413
|
display: none;
|
|
297
414
|
}
|