chore: import upstream snapshot with attribution
Ruff Format Check / Ruff Format & Lint (push) Failing after 7m39s
Deploy VitePress site to Pages / build (push) Failing after 9m11s
Deploy VitePress site to Pages / Deploy (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 12:32:26 +08:00
commit 1443d3fdf9
732 changed files with 196602 additions and 0 deletions
+219
View File
@@ -0,0 +1,219 @@
#!/usr/bin/env bash
set -euo pipefail
# =============================================================================
# Yuxi 版本号升级脚本
# =============================================================================
# 用法: ./scripts/bump-version.sh [--dev] <新版本号>
# 示例: ./scripts/bump-version.sh 0.6.2
# 示例: ./scripts/bump-version.sh --dev 0.6.2.dev1
#
# 该脚本从 backend/package/pyproject.toml 读取当前版本,
# 自动同步所有需要硬编码版本号的位置。
# --dev 模式不会更新 README.md、docs/intro/quick-start.md 和文档首页中 git clone --branch 的版本号。
#
# 更新 tag 标准流程(给人工和 agent 使用):
#
# 1. 先判断目标版本,不要直接打 tag。
# - 用户给完整版本号时,直接使用该版本,例如 0.7.1.dev2。
# - 用户只说“更新到 dev2”时,沿用当前主版本号 x.y.z,目标版本为 x.y.z.dev2。
# 例如当前是 0.7.1.dev1,则运行: ./scripts/bump-version.sh --dev 0.7.1.dev2
# - 用户只说“更新 tag”或“添加 tag”时,先读取 backend/package/pyproject.toml:
# * 如果当前是 x.y.z.dev0,默认推断为要发布第一个开发 tag,目标版本是 x.y.z.dev1。
# * 如果当前已经是 x.y.z.devNN >= 1)或 x.y.z,默认给当前版本打 tag。
# * 如果上下文里提到 dev2/dev3 等,则按提到的 devN 推断目标版本。
#
# 2. 如需升级版本,先运行本脚本。开发版必须带 --dev:
# ./scripts/bump-version.sh --dev 0.7.1.dev2
# 正式版不带 --dev:
# ./scripts/bump-version.sh 0.7.1
#
# 3. 脚本运行后必须检查:
# - git diff,确认只有预期版本文件变化。
# - backend/package/pyproject.toml、backend/pyproject.toml、web/package.json、
# docker-compose*.yml、backend/*uv.lock 中的 Yuxi 版本一致。
# - dev 模式下 README.md、README.en.md、docs/intro/quick-start.md 和文档首页
# 不应被更新。
#
# 4. 必须先提交版本更新,再创建 tag。tag 要指向包含版本更新的提交:
# git add backend/package/pyproject.toml backend/package/uv.lock backend/pyproject.toml backend/uv.lock docker-compose.yml docker-compose.prod.yml web/package.json
# git commit -m 'chore(release): 升级版本到 0.7.1.dev2'
# git tag v0.7.1.dev2
#
# 5. 创建 tag 后必须检查:
# - git status --short 应为空。
# - git show --no-patch --decorate --oneline HEAD 应显示 tag。
# - git tag --points-at HEAD 应包含刚创建的 tag。
# - 如果 tag 已存在,不要强制覆盖,先停下来确认。
#
# 6. 推送时推荐显式推送当前分支和本次 tag,避免误推其它本地 tag:
# git push origin main
# git push origin v0.7.1.dev2
# =============================================================================
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
# 检查参数
DEV_MODE=false
if [ "${1:-}" = "--dev" ]; then
DEV_MODE=true
shift
fi
if [ $# -ne 1 ]; then
echo "用法: $0 [--dev] <新版本号>"
echo "示例: $0 0.6.2"
echo "示例: $0 --dev 0.6.2.dev1"
exit 1
fi
NEW_VERSION="$1"
# 验证版本号格式(支持 x.y.z 或 x.y.z.devN
if [[ ! "$NEW_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(\.[a-zA-Z0-9]+)?$ ]]; then
echo "错误: 版本号格式无效,期望格式如 0.6.2 或 0.6.2.dev1"
exit 1
fi
# 读取当前版本号(以 backend/package/pyproject.toml 为 SSOT
PYPROJECT_FILE="${PROJECT_ROOT}/backend/package/pyproject.toml"
if [ ! -f "$PYPROJECT_FILE" ]; then
echo "错误: 找不到 ${PYPROJECT_FILE}"
exit 1
fi
CURRENT_VERSION=$(grep -E '^version[[:space:]]*=[[:space:]]*"' "$PYPROJECT_FILE" | head -1 | sed -E 's/^version[[:space:]]*=[[:space:]]*"([^"]+)".*/\1/')
if [ -z "$CURRENT_VERSION" ]; then
echo "错误: 无法从 ${PYPROJECT_FILE} 读取当前版本号"
exit 1
fi
if [ "$CURRENT_VERSION" = "$NEW_VERSION" ]; then
echo "当前版本已经是 ${NEW_VERSION},无需更新"
exit 0
fi
echo "准备将版本号从 ${CURRENT_VERSION} 升级到 ${NEW_VERSION}"
echo "受影响的文件:"
echo " - backend/package/pyproject.toml"
echo " - backend/pyproject.toml"
echo " - web/package.json"
echo " - docker-compose.yml"
echo " - docker-compose.prod.yml"
echo " - backend/uv.lock"
echo " - backend/package/uv.lock"
if [ "$DEV_MODE" = false ]; then
echo " - README.md"
echo " - README.en.md"
echo " - docs/intro/quick-start.md"
echo " - docs/.vitepress/theme/components/YuxiHome.vue"
fi
echo ""
read -rp "确认继续? [y/N] " confirm
if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
echo "已取消"
exit 0
fi
# -----------------------------------------------------------------------------
# 1. 更新 Python 包版本 (backend/package/pyproject.toml)
# -----------------------------------------------------------------------------
echo "→ 更新 backend/package/pyproject.toml"
perl -pi -e "s/^version = \"[^\"]+\"/version = \"${NEW_VERSION}\"/" \
"${PROJECT_ROOT}/backend/package/pyproject.toml"
# -----------------------------------------------------------------------------
# 2. 更新后端工作区版本 (backend/pyproject.toml)
# -----------------------------------------------------------------------------
echo "→ 更新 backend/pyproject.toml"
perl -pi -e "s/^version = \"[^\"]+\"/version = \"${NEW_VERSION}\"/" \
"${PROJECT_ROOT}/backend/pyproject.toml"
# -----------------------------------------------------------------------------
# 3. 更新前端版本 (web/package.json)
# -----------------------------------------------------------------------------
echo "→ 更新 web/package.json"
perl -pi -e "s/\"version\": \"[^\"]+\"/\"version\": \"${NEW_VERSION}\"/" \
"${PROJECT_ROOT}/web/package.json"
# -----------------------------------------------------------------------------
# 4. 更新 Docker Compose 镜像标签默认值
# -----------------------------------------------------------------------------
echo "→ 更新 docker-compose.yml"
perl -pi -e "s/\\\$\\{YUXI_VERSION:-[^}]+\\}/\\\${YUXI_VERSION:-${NEW_VERSION}}/g" \
"${PROJECT_ROOT}/docker-compose.yml"
echo "→ 更新 docker-compose.prod.yml"
perl -pi -e "s/\\\$\\{YUXI_VERSION:-[^}]+\\}/\\\${YUXI_VERSION:-${NEW_VERSION}}/g" \
"${PROJECT_ROOT}/docker-compose.prod.yml"
# -----------------------------------------------------------------------------
# 5. 更新 uv.lock 中的项目版本号
# -----------------------------------------------------------------------------
echo "→ 更新 backend/uv.lock"
# yuxi 包版本
perl -0pi -e "s/(^name = \"yuxi\"\nversion = \")[^\"]+/\${1}${NEW_VERSION}/m" \
"${PROJECT_ROOT}/backend/uv.lock"
# yuxi-workspace 版本
perl -0pi -e "s/(^name = \"yuxi-workspace\"\nversion = \")[^\"]+/\${1}${NEW_VERSION}/m" \
"${PROJECT_ROOT}/backend/uv.lock"
echo "→ 更新 backend/package/uv.lock"
perl -0pi -e "s/(^name = \"yuxi\"\nversion = \")[^\"]+/\${1}${NEW_VERSION}/m" \
"${PROJECT_ROOT}/backend/package/uv.lock"
# -----------------------------------------------------------------------------
# 6. 更新文档中的版本引用
# -----------------------------------------------------------------------------
# 只替换 git clone 命令中的版本标签(确保总是指向最新版本)
# 发布历史记录(如 [2026/04/01] v0.6.1 版本发布)不修改,保持为历史版本记录
if [ "$DEV_MODE" = false ]; then
echo "→ 更新 README.md"
perl -pi -e "s/(git clone --branch v)[0-9]+\\.[0-9]+\\.[0-9]+(\\.[a-zA-Z0-9]+)?/\${1}${NEW_VERSION}/g" \
"${PROJECT_ROOT}/README.md"
echo "→ 更新 README.en.md"
perl -pi -e "s/(git clone --branch v)[0-9]+\\.[0-9]+\\.[0-9]+(\\.[a-zA-Z0-9]+)?/\${1}${NEW_VERSION}/g" \
"${PROJECT_ROOT}/README.en.md"
echo "→ 更新 docs/intro/quick-start.md"
perl -pi -e "s/(git clone --branch v)[0-9]+\\.[0-9]+\\.[0-9]+(\\.[a-zA-Z0-9]+)?/\${1}${NEW_VERSION}/g" \
"${PROJECT_ROOT}/docs/intro/quick-start.md"
echo "→ 更新 docs/.vitepress/theme/components/YuxiHome.vue"
perl -pi -e "s/(git clone --branch v)[0-9]+\\.[0-9]+\\.[0-9]+(\\.[a-zA-Z0-9]+)?/\${1}${NEW_VERSION}/g" \
"${PROJECT_ROOT}/docs/.vitepress/theme/components/YuxiHome.vue"
else
echo "→ dev 模式,跳过 README.md、README.en.md、docs/intro/quick-start.md 和文档首页的分支版本更新"
fi
# -----------------------------------------------------------------------------
# 7. 验证
# -----------------------------------------------------------------------------
echo ""
echo "版本号升级完成,验证结果:"
echo ""
echo " backend/package/pyproject.toml:"
grep -E "^version = \"" "${PROJECT_ROOT}/backend/package/pyproject.toml" | head -1 | sed 's/^/ /'
echo " backend/pyproject.toml:"
grep -E "^version = \"" "${PROJECT_ROOT}/backend/pyproject.toml" | head -1 | sed 's/^/ /'
echo " web/package.json:"
grep -E '"version"' "${PROJECT_ROOT}/web/package.json" | head -1 | sed 's/^/ /'
echo " docker-compose.yml (api):"
grep -E "image: yuxi-api:" "${PROJECT_ROOT}/docker-compose.yml" | head -1 | sed 's/^/ /'
echo " docker-compose.prod.yml (web):"
grep -E "image: yuxi-web:" "${PROJECT_ROOT}/docker-compose.prod.yml" | head -1 | sed 's/^/ /'
echo ""
echo "后续步骤:"
echo " 1. 检查 git diff 确认修改无误"
echo " 2. git add . && git commit -m 'chore(release): bump version to ${NEW_VERSION}'"
echo " 3. git tag v${NEW_VERSION}"
echo " 4. git push origin main --tags"
@@ -0,0 +1,129 @@
from __future__ import annotations
import argparse
from datetime import UTC, datetime
from langfuse import Langfuse
PYTHON_TASK_ITEMS = [
{
"id": "py-task-001",
"input": (
"请用 Python 完成任务并给出最终答案:给定 nums = [7, -2, 5, 11, -8, 4]"
"只保留正数,平方后求和。请只输出最终整数。"
),
"expected_output": "211",
},
{
"id": "py-task-002",
"input": (
"请用 Python 完成任务并给出最终答案:给定文本 'alpha,beta;gamma delta\\nepsilon'"
"按逗号、分号、空白和换行切分 token,统计 token 数。请只输出最终整数。"
),
"expected_output": "5",
},
{
"id": "py-task-003",
"input": (
"请用 Python 完成任务并给出最终答案:计算 1 到 200 中所有能被 7 整除但不能被 5 整除的整数个数。"
"请只输出最终整数。"
),
"expected_output": "23",
},
{
"id": "py-task-004",
"input": (
"请用 Python 完成任务并给出最终答案:给定 records = [('a', 3), ('b', 5), ('a', 4), ('c', 2), ('b', -1)]"
"按 key 汇总数值,并按 key 字母序输出形如 a=7,b=4,c=2 的字符串。"
),
"expected_output": "a=7,b=4,c=2",
},
{
"id": "py-task-005",
"input": (
"请用 Python 完成任务并给出最终答案:给定矩阵 [[1, 2, 3], [4, 5, 6], [7, 8, 9]]"
"计算主对角线之和减去副对角线之和。请只输出最终整数。"
),
"expected_output": "0",
},
{
"id": "py-task-006",
"input": (
"请用 Python 完成任务并给出最终答案:给定 s = 'Yuxi Agent Evaluation'"
"忽略大小写统计元音字母 a/e/i/o/u 的总数。请只输出最终整数。"
),
"expected_output": "10",
},
{
"id": "py-task-007",
"input": (
"请用 Python 完成任务并给出最终答案:给定区间 [10, 50],找出所有质数并求和。"
"请只输出最终整数。"
),
"expected_output": "311",
},
{
"id": "py-task-008",
"input": (
"请用 Python 完成任务并给出最终答案:给定 JSON 字符串 "
"'{\"items\":[{\"price\":12.5,\"qty\":2},{\"price\":3,\"qty\":5},{\"price\":8,\"qty\":1}]}'"
"计算所有 price * qty 的总和。请只输出最终数字,保留一位小数。"
),
"expected_output": "48.0",
},
{
"id": "py-task-009",
"input": (
"请用 Python 完成任务并给出最终答案:给定 words = ['graph', 'rag', 'agent', 'tool', 'trace']"
"按单词长度升序、长度相同时按字母序排序,并用 '-' 连接。"
),
"expected_output": "rag-tool-agent-graph-trace",
},
{
"id": "py-task-010",
"input": (
"请用 Python 完成任务并给出最终答案:生成 Fibonacci 序列前 12 项(从 0, 1 开始),"
"取偶数项求和。请只输出最终整数。"
),
"expected_output": "44",
},
]
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(description="Upload a Python task dataset to Langfuse.")
parser.add_argument(
"--dataset-name",
default=f"yuxi-python-tasks-{datetime.now(UTC).strftime('%Y%m%dT%H%M%SZ')}",
help="Langfuse dataset name. Defaults to a timestamped name.",
)
return parser.parse_args()
def main() -> None:
args = parse_args()
client = Langfuse()
client.create_dataset(
name=args.dataset_name,
description="Yuxi agent evaluation dataset: deterministic Python programming tasks.",
metadata={
"source": "scripts/eval/upload_langfuse_python_tasks_dataset.py",
"task_type": "python_programming",
"item_count": len(PYTHON_TASK_ITEMS),
},
)
for item in PYTHON_TASK_ITEMS:
client.create_dataset_item(
dataset_name=args.dataset_name,
id=item["id"],
input={"input": item["input"]},
expected_output=item["expected_output"],
metadata={"category": "python_programming", "source": "yuxi_eval_smoke"},
)
client.flush()
print(args.dataset_name)
if __name__ == "__main__":
main()
+170
View File
@@ -0,0 +1,170 @@
# Yuxi Initialization Script for PowerShell
# This script helps set up the environment for the Yuxi project
# Note: API keys will be visible during input - use with care
function New-RandomHex($ByteCount) {
$bytes = [byte[]]::new($ByteCount)
$rng = [System.Security.Cryptography.RandomNumberGenerator]::Create()
try {
$rng.GetBytes($bytes)
return -join ($bytes | ForEach-Object { $_.ToString("x2") })
} finally {
$rng.Dispose()
}
}
function Test-EnvValue($Name) {
return [bool](Select-String -Path ".env" -Pattern "^$Name=.+" -Quiet)
}
function Ensure-JwtEnv {
if ((Test-EnvValue "JWT_SECRET_KEY") -and (Test-EnvValue "YUXI_INSTANCE_ID")) {
return
}
Write-Host "JWT security settings are missing in .env." -ForegroundColor Yellow
$JWT_SECRET_KEY = Read-Host "Please enter your JWT_SECRET_KEY (press Enter to auto-generate)"
if ([string]::IsNullOrEmpty($JWT_SECRET_KEY)) {
$JWT_SECRET_KEY = New-RandomHex 32
Write-Host "Generated JWT_SECRET_KEY and saved it to .env." -ForegroundColor Green
}
$YUXI_INSTANCE_ID = Read-Host "Please enter your YUXI_INSTANCE_ID (press Enter to auto-generate)"
if ([string]::IsNullOrEmpty($YUXI_INSTANCE_ID)) {
$YUXI_INSTANCE_ID = "instance-$(New-RandomHex 8)"
Write-Host "Generated YUXI_INSTANCE_ID and saved it to .env." -ForegroundColor Green
}
@"
# JWT security settings
JWT_SECRET_KEY=$JWT_SECRET_KEY
YUXI_INSTANCE_ID=$YUXI_INSTANCE_ID
"@ | Add-Content -Path ".env" -Encoding UTF8
}
Write-Host "🚀 Initializing Yuxi project..." -ForegroundColor Cyan
Write-Host "==================================" -ForegroundColor Cyan
# Check if .env file exists
if (Test-Path ".env") {
Write-Host "✅ .env file already exists. Skipping environment setup." -ForegroundColor Green
Ensure-JwtEnv
} else {
Write-Host "📝 .env file not found. Let's set up your environment variables." -ForegroundColor Yellow
Write-Host ""
# Get SILICONFLOW_API_KEY
Write-Host "🔑 SiliconFlow API Key required" -ForegroundColor Yellow
Write-Host "Get your API key from: https://cloud.siliconflow.cn/i/Eo5yTHGJ" -ForegroundColor Blue
Write-Host "Note: Press Ctrl+C at any time to cancel" -ForegroundColor Gray
Write-Host ""
do {
$apiKey = Read-Host "Please enter your SILICONFLOW_API_KEY"
if ([string]::IsNullOrEmpty($apiKey)) {
Write-Host "❌ API Key cannot be empty. Please try again." -ForegroundColor Red
}
} while ([string]::IsNullOrEmpty($apiKey))
# Get TAVILY_API_KEY (optional)
Write-Host ""
Write-Host "🔍 Tavily API Key (optional) - for search service" -ForegroundColor Yellow
Write-Host "Get your API key from: https://app.tavily.com/" -ForegroundColor Blue
$TAVILY_API_KEY = Read-Host "Please enter your TAVILY_API_KEY (press Enter to skip)"
Write-Host ""
Write-Host "JWT security settings" -ForegroundColor Yellow
$JWT_SECRET_KEY = Read-Host "Please enter your JWT_SECRET_KEY (press Enter to auto-generate)"
if ([string]::IsNullOrEmpty($JWT_SECRET_KEY)) {
$JWT_SECRET_KEY = New-RandomHex 32
Write-Host "Generated JWT_SECRET_KEY and saved it to .env." -ForegroundColor Green
}
$YUXI_INSTANCE_ID = Read-Host "Please enter your YUXI_INSTANCE_ID (press Enter to auto-generate)"
if ([string]::IsNullOrEmpty($YUXI_INSTANCE_ID)) {
$YUXI_INSTANCE_ID = "instance-$(New-RandomHex 8)"
Write-Host "Generated YUXI_INSTANCE_ID and saved it to .env." -ForegroundColor Green
}
# Create .env file
$envContent = @"
# SiliconFlow API Key (required)
SILICONFLOW_API_KEY=$apiKey
# Tavily API Key (optional - for search service)
"@
if (-not [string]::IsNullOrEmpty($TAVILY_API_KEY)) {
$envContent += "`nTAVILY_API_KEY=$TAVILY_API_KEY"
}
$envContent += @"
# JWT security settings
JWT_SECRET_KEY=$JWT_SECRET_KEY
YUXI_INSTANCE_ID=$YUXI_INSTANCE_ID
"@
$envContent | Out-File -FilePath ".env" -Encoding UTF8
Write-Host "✅ .env file created successfully!" -ForegroundColor Green
# Clear the variables from memory
Remove-Variable -Name "apiKey" -ErrorAction SilentlyContinue
Remove-Variable -Name "TAVILY_API_KEY" -ErrorAction SilentlyContinue
Remove-Variable -Name "JWT_SECRET_KEY" -ErrorAction SilentlyContinue
Remove-Variable -Name "YUXI_INSTANCE_ID" -ErrorAction SilentlyContinue
}
Write-Host ""
Write-Host "📦 Pulling Docker images..." -ForegroundColor Cyan
Write-Host "=========================" -ForegroundColor Cyan
# List of Docker images to pull
$images = @(
"python:3.13-slim",
"node:24-slim",
"node:24-alpine",
"milvusdb/milvus:v2.5.6",
"neo4j:5.26",
"minio/minio:RELEASE.2023-03-20T20-16-18Z",
"ghcr.io/astral-sh/uv:0.11.26",
"nginx:alpine",
"quay.io/coreos/etcd:v3.5.5",
"postgres:16",
"redis:7-alpine"
)
# Pull each image
foreach ($image in $images) {
Write-Host "🔄 Pulling ${image}..." -ForegroundColor Yellow
try {
& scripts/pull_image.ps1 $image
if ($LASTEXITCODE -eq 0) {
Write-Host "✅ Successfully pulled ${image}" -ForegroundColor Green
} else {
Write-Host "❌ Failed to pull ${image}" -ForegroundColor Red
exit 1
}
} catch {
Write-Host "❌ Error pulling ${image}: $_" -ForegroundColor Red
exit 1
}
}
$sandboxImage = "enterprise-public-cn-beijing.cr.volces.com/vefaas-public/all-in-one-sandbox:latest"
Write-Host "🔄 Pulling ${sandboxImage}..." -ForegroundColor Yellow
docker pull $sandboxImage
if ($LASTEXITCODE -eq 0) {
Write-Host "✅ Successfully pulled ${sandboxImage}" -ForegroundColor Green
} else {
Write-Host "❌ Failed to pull ${sandboxImage}" -ForegroundColor Red
exit 1
}
Write-Host ""
Write-Host "🎉 Initialization complete!" -ForegroundColor Green
Write-Host "==========================" -ForegroundColor Green
Write-Host "You can now run: docker compose up -d --build" -ForegroundColor Cyan
Write-Host "This will start all services in development mode with hot-reload enabled." -ForegroundColor Cyan
+149
View File
@@ -0,0 +1,149 @@
#!/bin/bash
# Yuxi Initialization Script for Bash/Linux/macOS
# This script helps set up the environment for the Yuxi project
set -e
generate_hex() {
local length="$1"
if command -v openssl >/dev/null 2>&1; then
openssl rand -hex "$length"
else
tr -dc 'a-f0-9' < /dev/urandom | head -c $((length * 2))
fi
}
ensure_jwt_env() {
if grep -Eq '^JWT_SECRET_KEY=.+' .env && grep -Eq '^YUXI_INSTANCE_ID=.+' .env; then
return
fi
echo "JWT security settings are missing in .env."
read -s -p "Please enter your JWT_SECRET_KEY (press Enter to auto-generate): " JWT_SECRET_KEY
echo ""
if [ -z "$JWT_SECRET_KEY" ]; then
JWT_SECRET_KEY=$(generate_hex 32)
echo "Generated JWT_SECRET_KEY and saved it to .env."
fi
read -p "Please enter your YUXI_INSTANCE_ID (press Enter to auto-generate): " YUXI_INSTANCE_ID
if [ -z "$YUXI_INSTANCE_ID" ]; then
YUXI_INSTANCE_ID="instance-$(generate_hex 8)"
echo "Generated YUXI_INSTANCE_ID and saved it to .env."
fi
cat >> .env << EOF
# JWT security settings
JWT_SECRET_KEY=${JWT_SECRET_KEY}
YUXI_INSTANCE_ID=${YUXI_INSTANCE_ID}
EOF
}
echo "🚀 Initializing Yuxi project..."
echo "=================================="
# Check if .env file exists
if [ -f ".env" ]; then
echo "✅ .env file already exists. Skipping environment setup."
ensure_jwt_env
else
echo "📝 .env file not found. Let's set up your environment variables."
echo ""
# Get SILICONFLOW_API_KEY
echo "🔑 SiliconFlow API Key required"
echo "Get your API key from: https://cloud.siliconflow.cn/i/Eo5yTHGJ"
while true; do
read -s -p "Please enter your SILICONFLOW_API_KEY: " SILICONFLOW_API_KEY
echo ""
if [ -z "$SILICONFLOW_API_KEY" ]; then
echo "❌ API Key cannot be empty. Please try again."
else
break
fi
done
# Get TAVILY_API_KEY (optional)
echo ""
echo "🔍 Tavily API Key (optional) - for search service"
echo "Get your API key from: https://app.tavily.com/"
read -p "Please enter your TAVILY_API_KEY (press Enter to skip): " TAVILY_API_KEY
echo ""
echo "JWT security settings"
read -s -p "Please enter your JWT_SECRET_KEY (press Enter to auto-generate): " JWT_SECRET_KEY
echo ""
if [ -z "$JWT_SECRET_KEY" ]; then
JWT_SECRET_KEY=$(generate_hex 32)
echo "Generated JWT_SECRET_KEY and saved it to .env."
fi
read -p "Please enter your YUXI_INSTANCE_ID (press Enter to auto-generate): " YUXI_INSTANCE_ID
if [ -z "$YUXI_INSTANCE_ID" ]; then
YUXI_INSTANCE_ID="instance-$(generate_hex 8)"
echo "Generated YUXI_INSTANCE_ID and saved it to .env."
fi
# Create .env file
cat > .env << EOF
# SiliconFlow API Key (required)
SILICONFLOW_API_KEY=${SILICONFLOW_API_KEY}
# Tavily API Key (optional - for search service)
EOF
if [ -n "$TAVILY_API_KEY" ]; then
echo "TAVILY_API_KEY=${TAVILY_API_KEY}" >> .env
fi
cat >> .env << EOF
# JWT security settings
JWT_SECRET_KEY=${JWT_SECRET_KEY}
YUXI_INSTANCE_ID=${YUXI_INSTANCE_ID}
EOF
echo "✅ .env file created successfully!"
fi
echo ""
echo "📦 Pulling Docker images..."
echo "========================="
# List of Docker images to pull
images=(
"python:3.13-slim"
"node:24-slim"
"node:24-alpine"
"milvusdb/milvus:v2.5.6"
"neo4j:5.26"
"minio/minio:RELEASE.2023-03-20T20-16-18Z"
"ghcr.io/astral-sh/uv:0.11.26"
"nginx:alpine"
"quay.io/coreos/etcd:v3.5.5"
"postgres:16"
"redis:7-alpine"
)
# Pull each image
for image in "${images[@]}"; do
echo "🔄 Pulling ${image}..."
if bash scripts/pull_image.sh "$image"; then
echo "✅ Successfully pulled ${image}"
else
echo "❌ Failed to pull ${image}"
exit 1
fi
done
echo "🔄 Pulling enterprise-public-cn-beijing.cr.volces.com/vefaas-public/all-in-one-sandbox:latest..."
docker pull enterprise-public-cn-beijing.cr.volces.com/vefaas-public/all-in-one-sandbox:latest
echo "✅ Successfully pulled enterprise-public-cn-beijing.cr.volces.com/vefaas-public/all-in-one-sandbox:latest"
echo ""
echo "🎉 Initialization complete!"
echo "=========================="
echo "You can now run: docker compose up -d --build"
echo "This will start all services in development mode with hot-reload enabled."
+56
View File
@@ -0,0 +1,56 @@
param(
[Parameter(Mandatory=$true)]
[string]$ImageTag
)
# 当命令失败时,立即退出脚本
$ErrorActionPreference = "Stop"
Write-Host "Pulling image: $ImageTag" -ForegroundColor Green
# 计算斜杠数量来确定镜像格式
$slashCount = ($ImageTag -split '/' | Measure-Object).Count - 1
# 根据镜像格式设置镜像 URL
switch ($slashCount) {
0 {
# 无前缀 (例如: python:3.13-slim)
$mirrorUrl = "m.daocloud.io/docker.io/library"
Write-Host "Image format: Official image (no prefix)" -ForegroundColor Cyan
}
1 {
# 一个前缀 (例如: milvusdb/milvus:latest)
$mirrorUrl = "m.daocloud.io/docker.io"
Write-Host "Image format: Hub repository (one prefix)" -ForegroundColor Cyan
}
default {
# 两个或更多前缀 (例如: quay.io/coreos/etcd:v3.5.5)
$mirrorUrl = "m.daocloud.io"
Write-Host "Image format: Third-party registry (multiple prefixes)" -ForegroundColor Cyan
}
}
$fullMirrorUrl = "$mirrorUrl/$ImageTag"
Write-Host "Mirror URL: $fullMirrorUrl" -ForegroundColor Yellow
try {
# 从镜像加速器拉取镜像
Write-Host "Step 1: Pulling image from mirror..." -ForegroundColor Blue
docker pull $fullMirrorUrl
# 重新标记为原始名称
Write-Host "Step 2: Tagging image with original name..." -ForegroundColor Blue
docker tag $fullMirrorUrl $ImageTag
# 删除镜像加速器标签
Write-Host "Step 3: Removing mirror tag..." -ForegroundColor Blue
docker rmi $fullMirrorUrl
Write-Host "`nProcess completed successfully!" -ForegroundColor Green
Write-Host "`nCurrent Docker images:" -ForegroundColor Yellow
docker images
} catch {
Write-Host "`nError occurred: $_" -ForegroundColor Red
exit 1
}
+39
View File
@@ -0,0 +1,39 @@
#!/bin/bash
if [ $# -ne 1 ]; then
echo "Usage: $0 <image:tag>"
exit 1
fi
set -e # 当命令失败时,立即退出脚本
IMAGE_TAG=$1
# Count the number of slashes to determine the image format
SLASH_COUNT=$(echo $IMAGE_TAG | tr -cd '/' | wc -c)
# Set mirror URL based on image format
if [ $SLASH_COUNT -eq 0 ]; then
# No prefix (e.g., python:3.13-slim)
MIRROR_URL="m.daocloud.io/docker.io/library"
elif [ $SLASH_COUNT -eq 1 ]; then
# One prefix (e.g., milvusdb/milvus:latest)
MIRROR_URL="m.daocloud.io/docker.io"
else
# Two or more prefixes (e.g., quay.io/coreos/etcd:v3.5.5)
MIRROR_URL="m.daocloud.io"
fi
# Pull image from mirror
echo "Pulling image from mirror: $MIRROR_URL/$IMAGE_TAG"
docker pull $MIRROR_URL/$IMAGE_TAG
# Tag image with original name
docker tag $MIRROR_URL/$IMAGE_TAG $IMAGE_TAG
# Remove mirror image
docker rmi $MIRROR_URL/$IMAGE_TAG
docker images
echo "Process completed successfully!"