mirror of
https://github.com/Tencent/WeKnora.git
synced 2026-06-04 13:30:32 +08:00
Revert "chore: make Lite edition support and related configurations hidden"
This reverts commit 88d5b303b8.
This commit is contained in:
45
.env.lite.example
Normal file
45
.env.lite.example
Normal file
@@ -0,0 +1,45 @@
|
||||
# WeKnora Lite 配置模板
|
||||
# 复制此文件为 .env.lite 并按需修改
|
||||
# cp .env.lite.example .env.lite
|
||||
|
||||
GIN_MODE=release
|
||||
|
||||
# === 数据库 ===
|
||||
DB_DRIVER=sqlite
|
||||
DB_PATH=./data/weknora.db
|
||||
|
||||
# === 检索引擎(FTS5 + sqlite-vec)===
|
||||
RETRIEVE_DRIVER=sqlite
|
||||
|
||||
# === 文件存储 ===
|
||||
STORAGE_TYPE=local
|
||||
LOCAL_STORAGE_BASE_DIR=./data/files
|
||||
|
||||
# === 流管理(内存,无 Redis)===
|
||||
STREAM_MANAGER_TYPE=memory
|
||||
|
||||
# === LLM 服务 ===
|
||||
# Ollama 本地服务(默认地址,按需修改)
|
||||
OLLAMA_BASE_URL=http://127.0.0.1:11434
|
||||
# 如使用其他 OpenAI 兼容服务,取消注释:
|
||||
# OPENAI_API_KEY=sk-xxx
|
||||
# OPENAI_BASE_URL=https://api.openai.com/v1
|
||||
|
||||
# === 安全配置(生产环境请务必修改!)===
|
||||
TENANT_AES_KEY=CHANGE-ME-32-char-secret-key!!!!
|
||||
JWT_SECRET=CHANGE-ME-jwt-secret
|
||||
|
||||
# === 功能开关 ===
|
||||
NEO4J_ENABLE=false
|
||||
WEKNORA_SANDBOX_MODE=disabled
|
||||
ENABLE_GRAPH_RAG=false
|
||||
DISABLE_REGISTRATION=false
|
||||
|
||||
# === 性能 ===
|
||||
CONCURRENCY_POOL_SIZE=3
|
||||
|
||||
# Docreader 地址
|
||||
DOCREADER_ADDR=127.0.0.1:50051
|
||||
|
||||
# Docreader 传输方式
|
||||
DOCREADER_TRANSPORT=grpc
|
||||
246
.github/workflows/release-lite.yml
vendored
Normal file
246
.github/workflows/release-lite.yml
vendored
Normal file
@@ -0,0 +1,246 @@
|
||||
name: Release Lite Binaries
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: "Release tag (e.g. v0.2.0)"
|
||||
required: true
|
||||
|
||||
concurrency:
|
||||
group: release-lite-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
env:
|
||||
GO_VERSION: "1.24"
|
||||
NODE_VERSION: "22"
|
||||
|
||||
jobs:
|
||||
# ── 1. Build frontend once, share as artifact ──
|
||||
build-frontend:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: npm
|
||||
cache-dependency-path: frontend/package-lock.json
|
||||
|
||||
- name: Build frontend
|
||||
working-directory: frontend
|
||||
run: |
|
||||
npm ci
|
||||
npm run build
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: frontend-dist
|
||||
path: frontend/dist/
|
||||
retention-days: 1
|
||||
|
||||
# ── 2. Build Go binary per platform (native CGO) ──
|
||||
build-binary:
|
||||
needs: build-frontend
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
goos: linux
|
||||
goarch: amd64
|
||||
- os: ubuntu-24.04-arm
|
||||
goos: linux
|
||||
goarch: arm64
|
||||
- os: macos-13
|
||||
goos: darwin
|
||||
goarch: amd64
|
||||
- os: macos-14
|
||||
goos: darwin
|
||||
goarch: arm64
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
CGO_ENABLED: 1
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
cache: true
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: frontend-dist
|
||||
path: web/
|
||||
|
||||
- name: Resolve version
|
||||
id: ver
|
||||
run: |
|
||||
if [ -n "${{ inputs.tag }}" ]; then
|
||||
VERSION="${{ inputs.tag }}"
|
||||
else
|
||||
VERSION="${GITHUB_REF#refs/tags/}"
|
||||
fi
|
||||
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
||||
echo "Building ${VERSION} for ${{ matrix.goos }}/${{ matrix.goarch }}"
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
export EDITION=lite
|
||||
eval "$(./scripts/get_version.sh env)"
|
||||
LDFLAGS="-w -s $(./scripts/get_version.sh ldflags)"
|
||||
export CGO_CFLAGS="-Wno-deprecated-declarations"
|
||||
if [ "${{ matrix.goos }}" = "darwin" ]; then
|
||||
export CGO_LDFLAGS="-Wl,-no_warn_duplicate_libraries"
|
||||
fi
|
||||
go build -tags "sqlite_fts5" -ldflags="${LDFLAGS}" \
|
||||
-o WeKnora-lite ./cmd/server
|
||||
|
||||
- name: Package tarball
|
||||
run: |
|
||||
ARCHIVE="WeKnora-lite_${{ steps.ver.outputs.version }}_${{ matrix.goos }}_${{ matrix.goarch }}"
|
||||
mkdir -p "${ARCHIVE}/web"
|
||||
cp WeKnora-lite "${ARCHIVE}/"
|
||||
cp -r web/* "${ARCHIVE}/web/"
|
||||
cp .env.lite.example "${ARCHIVE}/"
|
||||
cp docs/LITE.md "${ARCHIVE}/README.md"
|
||||
if [ -d config ]; then
|
||||
cp -r config "${ARCHIVE}/config"
|
||||
fi
|
||||
if [ -d migrations/sqlite ]; then
|
||||
mkdir -p "${ARCHIVE}/migrations/sqlite"
|
||||
cp -r migrations/sqlite/* "${ARCHIVE}/migrations/sqlite/"
|
||||
fi
|
||||
if [ -f deploy/weknora-lite.service ]; then
|
||||
cp deploy/weknora-lite.service "${ARCHIVE}/"
|
||||
fi
|
||||
tar czf "${ARCHIVE}.tar.gz" "${ARCHIVE}"
|
||||
shasum -a 256 "${ARCHIVE}.tar.gz" > "${ARCHIVE}.tar.gz.sha256"
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: release-${{ matrix.goos }}-${{ matrix.goarch }}
|
||||
path: |
|
||||
WeKnora-lite_*.tar.gz
|
||||
WeKnora-lite_*.tar.gz.sha256
|
||||
retention-days: 3
|
||||
|
||||
# ── 3. Create GitHub Release ──
|
||||
release:
|
||||
needs: build-binary
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: release-*
|
||||
merge-multiple: true
|
||||
|
||||
- name: Resolve version
|
||||
id: ver
|
||||
run: |
|
||||
if [ -n "${{ inputs.tag }}" ]; then
|
||||
VERSION="${{ inputs.tag }}"
|
||||
else
|
||||
VERSION="${GITHUB_REF#refs/tags/}"
|
||||
fi
|
||||
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Generate release notes
|
||||
id: notes
|
||||
run: |
|
||||
cat > notes.md << 'NOTES'
|
||||
## WeKnora Lite ${{ steps.ver.outputs.version }}
|
||||
|
||||
单二进制部署,零外部依赖(无需 Docker / PostgreSQL / Redis)。
|
||||
|
||||
### 快速开始
|
||||
|
||||
```bash
|
||||
# 1. 解压
|
||||
tar xzf WeKnora-lite_${{ steps.ver.outputs.version }}_<os>_<arch>.tar.gz
|
||||
cd WeKnora-lite_${{ steps.ver.outputs.version }}_<os>_<arch>
|
||||
|
||||
# 2. 配置
|
||||
cp .env.lite.example .env.lite
|
||||
# 编辑 .env.lite,至少确认 OLLAMA_BASE_URL 正确
|
||||
|
||||
# 3. 启动 Ollama(如尚未运行)
|
||||
ollama serve &
|
||||
ollama pull qwen2.5:7b
|
||||
ollama pull nomic-embed-text
|
||||
|
||||
# 4. 运行
|
||||
set -a && source .env.lite && set +a
|
||||
./WeKnora-lite
|
||||
# 访问 http://localhost:8080
|
||||
```
|
||||
|
||||
### 平台支持
|
||||
|
||||
| 文件 | 平台 |
|
||||
|------|------|
|
||||
| `WeKnora-lite_*_linux_amd64.tar.gz` | Linux x86_64 |
|
||||
| `WeKnora-lite_*_linux_arm64.tar.gz` | Linux ARM64 |
|
||||
| `WeKnora-lite_*_darwin_amd64.tar.gz` | macOS Intel |
|
||||
| `WeKnora-lite_*_darwin_arm64.tar.gz` | macOS Apple Silicon |
|
||||
|
||||
详细文档见 [LITE.md](docs/LITE.md)。
|
||||
NOTES
|
||||
|
||||
- name: Create release
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
gh release create "${{ steps.ver.outputs.version }}" \
|
||||
--title "WeKnora Lite ${{ steps.ver.outputs.version }}" \
|
||||
--notes-file notes.md \
|
||||
WeKnora-lite_*.tar.gz \
|
||||
WeKnora-lite_*.tar.gz.sha256
|
||||
|
||||
# ── 4. Update Homebrew Formula ──
|
||||
update-homebrew:
|
||||
needs: release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: main
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Resolve version
|
||||
id: ver
|
||||
run: |
|
||||
if [ -n "${{ inputs.tag }}" ]; then
|
||||
VERSION="${{ inputs.tag }}"
|
||||
else
|
||||
VERSION="${GITHUB_REF#refs/tags/}"
|
||||
fi
|
||||
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Wait for release assets to be available
|
||||
run: sleep 15
|
||||
|
||||
- name: Update Formula
|
||||
run: ./scripts/update-homebrew-formula.sh "${{ steps.ver.outputs.version }}"
|
||||
|
||||
- name: Commit and push
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git add Formula/weknora-lite.rb
|
||||
if git diff --cached --quiet; then
|
||||
echo "No changes to Formula"
|
||||
else
|
||||
git commit -m "formula: update weknora-lite to ${{ steps.ver.outputs.version }}"
|
||||
git push origin main
|
||||
fi
|
||||
118
Formula/weknora-lite.rb
Normal file
118
Formula/weknora-lite.rb
Normal file
@@ -0,0 +1,118 @@
|
||||
class WeknoraLite < Formula
|
||||
desc "Knowledge base management system — single-binary Lite edition"
|
||||
homepage "https://github.com/Tencent/WeKnora"
|
||||
version "0.0.0"
|
||||
license "Apache-2.0"
|
||||
|
||||
on_macos do
|
||||
on_arm do
|
||||
url "https://github.com/Tencent/WeKnora/releases/download/v#{version}/WeKnora-lite_v#{version}_darwin_arm64.tar.gz"
|
||||
sha256 "PLACEHOLDER"
|
||||
end
|
||||
on_intel do
|
||||
url "https://github.com/Tencent/WeKnora/releases/download/v#{version}/WeKnora-lite_v#{version}_darwin_amd64.tar.gz"
|
||||
sha256 "PLACEHOLDER"
|
||||
end
|
||||
end
|
||||
|
||||
on_linux do
|
||||
on_arm do
|
||||
url "https://github.com/Tencent/WeKnora/releases/download/v#{version}/WeKnora-lite_v#{version}_linux_arm64.tar.gz"
|
||||
sha256 "PLACEHOLDER"
|
||||
end
|
||||
on_intel do
|
||||
url "https://github.com/Tencent/WeKnora/releases/download/v#{version}/WeKnora-lite_v#{version}_linux_amd64.tar.gz"
|
||||
sha256 "PLACEHOLDER"
|
||||
end
|
||||
end
|
||||
|
||||
def install
|
||||
libexec.install "WeKnora-lite"
|
||||
pkgshare.install "web" if File.directory?("web")
|
||||
pkgshare.install "config" if File.directory?("config")
|
||||
pkgshare.install ".env.lite.example"
|
||||
doc.install "README.md"
|
||||
pkgshare.install "migrations" if File.directory?("migrations")
|
||||
|
||||
(bin/"weknora-lite").write <<~SH
|
||||
#!/bin/bash
|
||||
CONFIG_DIR="${WEKNORA_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/weknora}"
|
||||
DATA_DIR="${WEKNORA_DATA_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/weknora}"
|
||||
|
||||
mkdir -p "$DATA_DIR/files" "$CONFIG_DIR/config" 2>/dev/null
|
||||
|
||||
if [ ! -f "$CONFIG_DIR/config/config.yaml" ]; then
|
||||
cp -r "#{pkgshare}/config/" "$CONFIG_DIR/config/"
|
||||
fi
|
||||
|
||||
if [ ! -d "$CONFIG_DIR/migrations" ] && [ -d "#{pkgshare}/migrations" ]; then
|
||||
ln -sf "#{pkgshare}/migrations" "$CONFIG_DIR/migrations"
|
||||
fi
|
||||
|
||||
if [ ! -f "$CONFIG_DIR/.env.lite" ]; then
|
||||
cp "#{pkgshare}/.env.lite.example" "$CONFIG_DIR/.env.lite"
|
||||
sed -i '' "s|DB_PATH=.*|DB_PATH=$DATA_DIR/weknora.db|" "$CONFIG_DIR/.env.lite"
|
||||
sed -i '' "s|LOCAL_STORAGE_BASE_DIR=.*|LOCAL_STORAGE_BASE_DIR=$DATA_DIR/files|" "$CONFIG_DIR/.env.lite"
|
||||
rm -f "$CONFIG_DIR/.env.lite-e"
|
||||
echo ""
|
||||
echo "已创建配置文件: $CONFIG_DIR/.env.lite"
|
||||
echo "请根据需要编辑(如修改 LLM 地址、安全密钥等)。"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
set -a
|
||||
source "$CONFIG_DIR/.env.lite"
|
||||
set +a
|
||||
|
||||
export DB_PATH="${DB_PATH:-$DATA_DIR/weknora.db}"
|
||||
export LOCAL_STORAGE_BASE_DIR="${LOCAL_STORAGE_BASE_DIR:-$DATA_DIR/files}"
|
||||
export WEKNORA_WEB_DIR="${WEKNORA_WEB_DIR:-#{pkgshare}/web}"
|
||||
|
||||
cd "$CONFIG_DIR"
|
||||
exec "#{libexec}/WeKnora-lite" "$@"
|
||||
SH
|
||||
end
|
||||
|
||||
def post_install
|
||||
(var/"weknora").mkpath
|
||||
(var/"log").mkpath
|
||||
end
|
||||
|
||||
service do
|
||||
run [bin/"weknora-lite"]
|
||||
keep_alive true
|
||||
working_dir var/"weknora"
|
||||
log_path var/"log/weknora-lite.log"
|
||||
error_log_path var/"log/weknora-lite.log"
|
||||
end
|
||||
|
||||
def caveats
|
||||
<<~EOS
|
||||
前台运行:
|
||||
weknora-lite
|
||||
|
||||
后台服务(推荐):
|
||||
brew services start weknora-lite # 启动并开机自启
|
||||
brew services stop weknora-lite # 停止
|
||||
brew services restart weknora-lite # 重启
|
||||
brew services info weknora-lite # 查看状态
|
||||
|
||||
日志:
|
||||
#{var}/log/weknora-lite.log
|
||||
|
||||
首次运行会自动创建配置文件:
|
||||
~/.config/weknora/.env.lite
|
||||
|
||||
数据存储在:
|
||||
~/.local/share/weknora/
|
||||
|
||||
如需修改配置(LLM 服务地址、安全密钥等):
|
||||
$EDITOR ~/.config/weknora/.env.lite
|
||||
brew services restart weknora-lite
|
||||
EOS
|
||||
end
|
||||
|
||||
test do
|
||||
assert_predicate bin/"weknora-lite", :executable?
|
||||
end
|
||||
end
|
||||
36
Makefile
36
Makefile
@@ -1,4 +1,4 @@
|
||||
.PHONY: help build run test clean docker-build-app docker-build-docreader docker-build-frontend docker-build-all docker-run migrate-up migrate-down docker-restart docker-stop start-all stop-all start-ollama stop-ollama build-images build-images-app build-images-docreader build-images-frontend clean-images check-env list-containers pull-images show-platform dev-start dev-stop dev-restart dev-logs dev-status dev-app dev-frontend docs install-swagger
|
||||
.PHONY: help build run test clean docker-build-app docker-build-docreader docker-build-frontend docker-build-all docker-run migrate-up migrate-down docker-restart docker-stop start-all stop-all start-ollama stop-ollama build-images build-images-app build-images-docreader build-images-frontend clean-images check-env list-containers pull-images show-platform dev-start dev-stop dev-restart dev-logs dev-status dev-app dev-frontend docs install-swagger build-lite run-lite package-lite
|
||||
|
||||
# Show help
|
||||
help:
|
||||
@@ -56,6 +56,11 @@ help:
|
||||
@echo " dev-status 查看开发环境状态"
|
||||
@echo " dev-app 启动后端应用(本地运行,需先运行 dev-start)"
|
||||
@echo " dev-frontend 启动前端(本地运行,需先运行 dev-start)"
|
||||
@echo ""
|
||||
@echo "Lite 模式(零外部依赖):"
|
||||
@echo " build-lite 构建 Lite 版本(先构建前端到 web/,再构建 Go;SKIP_FRONTEND=1 跳过前端)"
|
||||
@echo " run-lite 构建并启动 Lite 版本"
|
||||
@echo " package-lite 构建并打包 Lite 发行包(tarball)"
|
||||
|
||||
# Go related variables
|
||||
BINARY_NAME=WeKnora
|
||||
@@ -231,6 +236,35 @@ build-prod:
|
||||
LDFLAGS="-X 'github.com/Tencent/WeKnora/internal/handler.Version=$$VERSION' -X 'github.com/Tencent/WeKnora/internal/handler.Edition=standard' -X 'github.com/Tencent/WeKnora/internal/handler.CommitID=$$COMMIT_ID' -X 'github.com/Tencent/WeKnora/internal/handler.BuildTime=$$BUILD_TIME' -X 'github.com/Tencent/WeKnora/internal/handler.GoVersion=$$GO_VERSION' -X 'google.golang.org/protobuf/reflect/protoregistry.conflictPolicy=warn'"; \
|
||||
go build -ldflags="-w -s $$LDFLAGS" -o $(BINARY_NAME) $(MAIN_PATH)
|
||||
|
||||
# Build Lite version (single binary, SQLite + in-memory queue)
|
||||
# 会先构建前端到 web/,再构建 Go 二进制;SKIP_FRONTEND=1 可跳过前端
|
||||
build-lite:
|
||||
@if [ -f frontend/package.json ] && [ "$${SKIP_FRONTEND:-}" != "1" ]; then \
|
||||
echo ">> Building frontend for Lite..."; \
|
||||
(cd frontend && npm ci --prefer-offline && npm run build) && \
|
||||
rm -rf web && cp -r frontend/dist web; \
|
||||
elif [ "$${SKIP_FRONTEND:-}" = "1" ]; then \
|
||||
echo ">> Skipping frontend (SKIP_FRONTEND=1)"; \
|
||||
else \
|
||||
echo ">> No frontend/package.json, skipping frontend"; \
|
||||
fi
|
||||
export EDITION=lite; \
|
||||
eval "$$(./scripts/get_version.sh env)"; \
|
||||
LDFLAGS="$$(./scripts/get_version.sh ldflags)"; \
|
||||
CGO_ENABLED=1 \
|
||||
CGO_CFLAGS="-Wno-deprecated-declarations" \
|
||||
CGO_LDFLAGS="-Wl,-no_warn_duplicate_libraries" \
|
||||
go build -tags "sqlite_fts5" -ldflags="-w -s $$LDFLAGS" -o $(BINARY_NAME)-lite $(MAIN_PATH)
|
||||
|
||||
# Run Lite version with .env.lite defaults
|
||||
run-lite: build-lite
|
||||
@if [ ! -f .env.lite ]; then echo "Error: .env.lite not found"; exit 1; fi
|
||||
@set -a && . ./.env.lite && set +a && ./$(BINARY_NAME)-lite
|
||||
|
||||
# Package Lite version into distributable tarball
|
||||
package-lite:
|
||||
./scripts/package-lite.sh
|
||||
|
||||
download_spatial:
|
||||
go run cmd/download/duckdb/duckdb.go
|
||||
|
||||
|
||||
23
deploy/weknora-lite.service
Normal file
23
deploy/weknora-lite.service
Normal file
@@ -0,0 +1,23 @@
|
||||
[Unit]
|
||||
Description=WeKnora Lite - Knowledge Base Management System
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=weknora
|
||||
Group=weknora
|
||||
WorkingDirectory=/opt/weknora
|
||||
EnvironmentFile=/opt/weknora/.env.lite
|
||||
ExecStart=/opt/weknora/WeKnora-lite
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
LimitNOFILE=65536
|
||||
|
||||
# Security hardening
|
||||
NoNewPrivileges=true
|
||||
ProtectSystem=strict
|
||||
ProtectHome=true
|
||||
ReadWritePaths=/opt/weknora/data
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
165
docs/LITE.md
Normal file
165
docs/LITE.md
Normal file
@@ -0,0 +1,165 @@
|
||||
# WeKnora Lite
|
||||
|
||||
零外部依赖的单二进制部署模式。无需 Docker、PostgreSQL、Redis,适合快速体验和小规模私有部署。
|
||||
|
||||
## 架构
|
||||
|
||||
| 组件 | 标准版 | Lite 版 |
|
||||
|------|--------|---------|
|
||||
| 数据库 | PostgreSQL | SQLite (WAL) |
|
||||
| 向量检索 | pgvector / Qdrant / ES | sqlite-vec (vec0) |
|
||||
| 关键词检索 | ParadeDB BM25 / ES | SQLite FTS5 |
|
||||
| 消息队列 | Redis + Asynq | 内存 SyncTaskExecutor |
|
||||
| 会话存储 | Redis | 内存 |
|
||||
| 流管理 | Redis / 内存 | 内存 |
|
||||
| 文件存储 | MinIO / COS / 本地 | 本地 |
|
||||
| 文档解析 | DocReader (gRPC) | 不可用(文本/段落导入可用)|
|
||||
| 前端 | Nginx 容器 | Go 内置静态文件服务 |
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 方式一:Homebrew 安装(macOS / Linux,推荐)
|
||||
|
||||
```bash
|
||||
brew tap Tencent/weknora https://github.com/Tencent/WeKnora
|
||||
brew install weknora-lite
|
||||
```
|
||||
|
||||
安装完成后,推荐使用 **brew services** 以后台服务方式运行:
|
||||
|
||||
```bash
|
||||
brew services start weknora-lite # 启动服务(开机自动启动)
|
||||
brew services info weknora-lite # 查看运行状态
|
||||
# 首次启动自动创建配置文件 ~/.config/weknora/.env.lite
|
||||
# 数据存储在 ~/.local/share/weknora/
|
||||
# 访问 http://localhost:8080
|
||||
```
|
||||
|
||||
常用服务管理命令:
|
||||
|
||||
```bash
|
||||
brew services stop weknora-lite # 停止服务
|
||||
brew services restart weknora-lite # 重启服务(修改配置后需重启)
|
||||
brew services info weknora-lite # 查看状态
|
||||
```
|
||||
|
||||
日志位于 `$(brew --prefix)/var/log/weknora-lite.log`。
|
||||
|
||||
也可以前台直接运行:
|
||||
|
||||
```bash
|
||||
weknora-lite
|
||||
```
|
||||
|
||||
如需修改配置(LLM 服务地址、安全密钥等):
|
||||
|
||||
```bash
|
||||
$EDITOR ~/.config/weknora/.env.lite
|
||||
brew services restart weknora-lite # 修改配置后重启生效
|
||||
```
|
||||
|
||||
> **LLM 服务**:WeKnora Lite 需要一个 OpenAI 兼容的 LLM 服务来提供对话和 Embedding 能力。
|
||||
> 可以使用 [Ollama](https://ollama.com/)(本地)、通义千问、OpenAI 等任何兼容服务,
|
||||
> 在配置文件中设置对应的地址和 API Key 即可。
|
||||
|
||||
### 方式二:下载预编译包
|
||||
|
||||
从 [GitHub Releases](https://github.com/Tencent/WeKnora/releases) 下载对应平台的 tarball:
|
||||
|
||||
| 文件 | 平台 |
|
||||
|------|------|
|
||||
| `WeKnora-lite_*_linux_amd64.tar.gz` | Linux x86_64 |
|
||||
| `WeKnora-lite_*_linux_arm64.tar.gz` | Linux ARM64 |
|
||||
| `WeKnora-lite_*_darwin_amd64.tar.gz` | macOS Intel |
|
||||
| `WeKnora-lite_*_darwin_arm64.tar.gz` | macOS Apple Silicon |
|
||||
|
||||
```bash
|
||||
# 1. 解压
|
||||
tar xzf WeKnora-lite_v0.2.0_darwin_arm64.tar.gz
|
||||
cd WeKnora-lite_v0.2.0_darwin_arm64
|
||||
|
||||
# 2. 配置
|
||||
cp .env.lite.example .env.lite
|
||||
# 编辑 .env.lite,配置 LLM 服务地址和安全密钥
|
||||
|
||||
# 3. 运行
|
||||
set -a && source .env.lite && set +a
|
||||
./WeKnora-lite
|
||||
# 访问 http://localhost:8080
|
||||
```
|
||||
|
||||
### 方式三:从源码构建
|
||||
|
||||
前置条件:Go 1.22+(需要 CGO)、C 编译器 (gcc/clang)、Node.js 22+(前端构建)。
|
||||
|
||||
```bash
|
||||
make run-lite
|
||||
```
|
||||
|
||||
## 配置
|
||||
|
||||
Lite 模式通过 `.env.lite` 文件配置(模板见 `.env.lite.example`)。关键环境变量:
|
||||
|
||||
```bash
|
||||
DB_DRIVER=sqlite # 使用 SQLite
|
||||
DB_PATH=./data/weknora.db # 数据库文件路径
|
||||
RETRIEVE_DRIVER=sqlite # SQLite 检索引擎 (FTS5 + sqlite-vec)
|
||||
STORAGE_TYPE=local # 本地文件存储
|
||||
LOCAL_STORAGE_BASE_DIR=./data/files
|
||||
STREAM_MANAGER_TYPE=memory # 内存流管理
|
||||
# REDIS_ADDR= # 留空 = 不使用 Redis
|
||||
OLLAMA_BASE_URL=http://127.0.0.1:11434
|
||||
```
|
||||
|
||||
完整配置参见 [.env.lite.example](../.env.lite.example)。
|
||||
|
||||
## 后台运行
|
||||
|
||||
### Homebrew 用户(macOS / Linux)
|
||||
|
||||
Homebrew 安装后直接使用 `brew services` 管理,详见上方「快速开始 → 方式一」。
|
||||
|
||||
### Linux systemd(tarball 安装)
|
||||
|
||||
tarball 中附带 `weknora-lite.service` 模板,按需修改路径后安装:
|
||||
|
||||
```bash
|
||||
# 创建用户和目录
|
||||
sudo useradd -r -s /sbin/nologin weknora
|
||||
sudo mkdir -p /opt/weknora/data
|
||||
sudo cp WeKnora-lite web/ .env.lite /opt/weknora/
|
||||
sudo chown -R weknora:weknora /opt/weknora
|
||||
|
||||
# 安装并启动服务
|
||||
sudo cp weknora-lite.service /etc/systemd/system/
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable --now weknora-lite
|
||||
|
||||
# 管理
|
||||
sudo systemctl status weknora-lite # 查看状态
|
||||
sudo journalctl -u weknora-lite -f # 查看日志
|
||||
```
|
||||
|
||||
## 功能限制
|
||||
|
||||
与标准版相比,Lite 版有以下限制:
|
||||
|
||||
- **文档解析**:不支持文件上传和 URL 导入的自动解析(PDF/Word/Excel 等)。可使用文本和段落方式手动导入。
|
||||
- **向量检索**:sqlite-vec 使用精确 KNN(非近似),适合 10 万条以下的小规模数据集。
|
||||
- **并发**:SQLite 单写者模型,高并发写入场景下性能不如 PostgreSQL。
|
||||
- **任务队列**:无持久化队列,进程重启后未完成的异步任务会丢失。
|
||||
- **知识图谱**:默认禁用 (`NEO4J_ENABLE=false`)。
|
||||
- **Agent Skills 沙箱**:默认禁用 (`WEKNORA_SANDBOX_MODE=disabled`)。
|
||||
|
||||
## 数据目录
|
||||
|
||||
默认所有数据存储在 `./data/` 目录下:
|
||||
|
||||
```
|
||||
data/
|
||||
├── weknora.db # SQLite 数据库
|
||||
├── weknora.db-wal # WAL 日志
|
||||
└── files/ # 上传文件
|
||||
```
|
||||
|
||||
备份只需复制整个 `data/` 目录。
|
||||
@@ -4,6 +4,7 @@
|
||||
<div class="logo_row" v-if="!uiStore.sidebarCollapsed">
|
||||
<div class="logo_box" @click="router.push('/platform/knowledge-bases')" style="cursor: pointer;">
|
||||
<img class="logo" src="@/assets/img/weknora.png" alt="">
|
||||
<span v-if="isLiteEdition" class="lite-badge">Lite</span>
|
||||
</div>
|
||||
<div class="sidebar-toggle"
|
||||
@click="uiStore.toggleSidebar"
|
||||
@@ -137,6 +138,7 @@ import { MessagePlugin, DialogPlugin, Icon as TIcon } from "tdesign-vue-next";
|
||||
import UserMenu from '@/components/UserMenu.vue';
|
||||
import TenantSelector from '@/components/TenantSelector.vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { getSystemInfo } from '@/api/system';
|
||||
|
||||
const { t } = useI18n();
|
||||
const usemenuStore = useMenuStore();
|
||||
@@ -157,6 +159,7 @@ const hasMore = computed(() => currentPage.value < totalPages.value);
|
||||
type MenuItem = { title: string; icon: string; path: string; childrenPath?: string; children?: any[] };
|
||||
const { menuArr } = storeToRefs(usemenuStore);
|
||||
let activeSubmenu = ref<string>('');
|
||||
const isLiteEdition = ref(false);
|
||||
|
||||
// 批量管理状态
|
||||
const batchMode = ref(false)
|
||||
@@ -539,6 +542,10 @@ onMounted(async () => {
|
||||
currentSecondpath.value = `chat/${route.params.chatid}`;
|
||||
}
|
||||
|
||||
getSystemInfo().then(res => {
|
||||
isLiteEdition.value = res.data?.edition === 'lite'
|
||||
}).catch(() => {})
|
||||
|
||||
// 初始化知识库信息
|
||||
const kbId = (route.params as any)?.kbId as string
|
||||
if (kbId && isInKnowledgeBase.value) {
|
||||
@@ -836,6 +843,19 @@ const onDragHandleMouseDown = (e: MouseEvent) => {
|
||||
width: 134px;
|
||||
height: auto;
|
||||
}
|
||||
.lite-badge {
|
||||
margin-left: 4px;
|
||||
padding: 1px 6px;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
line-height: 18px;
|
||||
color: #07c05f;
|
||||
background: #07c05f1a;
|
||||
border: 1px solid #07c05f40;
|
||||
border-radius: 4px;
|
||||
letter-spacing: 0.5px;
|
||||
user-select: none;
|
||||
}
|
||||
}
|
||||
|
||||
.logo_img {
|
||||
|
||||
@@ -33,11 +33,11 @@
|
||||
{{ systemInfo?.version || $t('system.unknown') }}
|
||||
<t-tag
|
||||
v-if="systemInfo?.edition"
|
||||
theme="default"
|
||||
:theme="systemInfo.edition === 'lite' ? 'primary' : 'default'"
|
||||
variant="light"
|
||||
size="small"
|
||||
style="margin-left: 8px;"
|
||||
>{{ systemInfo.edition || 'Standard' }}</t-tag>
|
||||
>{{ systemInfo.edition === 'lite' ? 'Lite' : 'Standard' }}</t-tag>
|
||||
<span v-if="systemInfo?.commit_id" class="commit-info">
|
||||
({{ systemInfo.commit_id }})
|
||||
</span>
|
||||
|
||||
97
scripts/package-lite.sh
Executable file
97
scripts/package-lite.sh
Executable file
@@ -0,0 +1,97 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
#
|
||||
# 本地构建 + 打包 WeKnora Lite 发行包
|
||||
#
|
||||
# 用法:
|
||||
# ./scripts/package-lite.sh # 自动检测版本
|
||||
# ./scripts/package-lite.sh v0.2.0 # 指定版本号
|
||||
# SKIP_FRONTEND=1 ./scripts/package-lite.sh # 跳过前端构建(使用已有 web/)
|
||||
#
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
ROOT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||
cd "${ROOT_DIR}"
|
||||
|
||||
# Resolve version
|
||||
if [ -n "${1:-}" ]; then
|
||||
VERSION="$1"
|
||||
elif command -v git >/dev/null 2>&1; then
|
||||
VERSION=$(git describe --tags --abbrev=0 2>/dev/null || echo "dev")
|
||||
else
|
||||
VERSION="dev"
|
||||
fi
|
||||
|
||||
GOOS=$(go env GOOS)
|
||||
GOARCH=$(go env GOARCH)
|
||||
ARCHIVE="WeKnora-lite_${VERSION}_${GOOS}_${GOARCH}"
|
||||
DIST_DIR="dist/${ARCHIVE}"
|
||||
|
||||
echo "=== WeKnora Lite Packager ==="
|
||||
echo " Version : ${VERSION}"
|
||||
echo " Platform: ${GOOS}/${GOARCH}"
|
||||
echo " Output : dist/${ARCHIVE}.tar.gz"
|
||||
echo ""
|
||||
|
||||
# ── Step 1: Build frontend (if not skipped) ──
|
||||
if [ "${SKIP_FRONTEND:-}" != "1" ]; then
|
||||
if [ -f frontend/package.json ]; then
|
||||
echo ">> Building frontend..."
|
||||
(cd frontend && npm ci --prefer-offline && npm run build)
|
||||
rm -rf web
|
||||
cp -r frontend/dist web
|
||||
else
|
||||
echo ">> No frontend/package.json found, skipping frontend build"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -f web/index.html ]; then
|
||||
echo "WARNING: web/index.html not found — package will not include frontend"
|
||||
fi
|
||||
|
||||
# ── Step 2: Build Go binary ──
|
||||
echo ">> Building WeKnora-lite binary..."
|
||||
export EDITION=lite
|
||||
eval "$(./scripts/get_version.sh env)"
|
||||
LDFLAGS="-w -s $(./scripts/get_version.sh ldflags)"
|
||||
export CGO_CFLAGS="-Wno-deprecated-declarations"
|
||||
if [ "$(uname)" = "Darwin" ]; then
|
||||
export CGO_LDFLAGS="-Wl,-no_warn_duplicate_libraries"
|
||||
fi
|
||||
CGO_ENABLED=1 go build -tags "sqlite_fts5" -ldflags="${LDFLAGS}" \
|
||||
-o WeKnora-lite ./cmd/server
|
||||
|
||||
# ── Step 3: Assemble package ──
|
||||
echo ">> Assembling package..."
|
||||
rm -rf "${DIST_DIR}"
|
||||
mkdir -p "${DIST_DIR}/web"
|
||||
|
||||
cp WeKnora-lite "${DIST_DIR}/"
|
||||
if [ -d web ] && [ -f web/index.html ]; then
|
||||
cp -r web/* "${DIST_DIR}/web/"
|
||||
fi
|
||||
cp .env.lite.example "${DIST_DIR}/"
|
||||
cp docs/LITE.md "${DIST_DIR}/README.md"
|
||||
if [ -d config ]; then
|
||||
cp -r config "${DIST_DIR}/config"
|
||||
fi
|
||||
if [ -d migrations/sqlite ]; then
|
||||
mkdir -p "${DIST_DIR}/migrations/sqlite"
|
||||
cp -r migrations/sqlite/* "${DIST_DIR}/migrations/sqlite/"
|
||||
fi
|
||||
if [ -f deploy/weknora-lite.service ]; then
|
||||
cp deploy/weknora-lite.service "${DIST_DIR}/"
|
||||
fi
|
||||
|
||||
# ── Step 4: Create tarball ──
|
||||
echo ">> Creating tarball..."
|
||||
(cd dist && tar czf "${ARCHIVE}.tar.gz" "${ARCHIVE}")
|
||||
(cd dist && shasum -a 256 "${ARCHIVE}.tar.gz" > "${ARCHIVE}.tar.gz.sha256")
|
||||
|
||||
echo ""
|
||||
echo "=== Done ==="
|
||||
echo " dist/${ARCHIVE}.tar.gz"
|
||||
echo " dist/${ARCHIVE}.tar.gz.sha256"
|
||||
SIZE=$(du -h "dist/${ARCHIVE}.tar.gz" | cut -f1)
|
||||
echo " Size: ${SIZE}"
|
||||
178
scripts/test-homebrew.sh
Executable file
178
scripts/test-homebrew.sh
Executable file
@@ -0,0 +1,178 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
#
|
||||
# 本地测试 Homebrew Formula
|
||||
#
|
||||
# 流程:打包 → 创建本地 tap → 写入 Formula → brew install → 验证
|
||||
#
|
||||
# 用法:
|
||||
# ./scripts/test-homebrew.sh # 完整测试(含前端构建)
|
||||
# SKIP_FRONTEND=1 ./scripts/test-homebrew.sh # 跳过前端构建
|
||||
# SKIP_BUILD=1 ./scripts/test-homebrew.sh # 跳过构建(使用已有 tarball)
|
||||
#
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
ROOT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||
cd "${ROOT_DIR}"
|
||||
|
||||
TAP_NAME="weknora/test"
|
||||
FORMULA_NAME="weknora-lite-test"
|
||||
VERSION="test"
|
||||
GOOS=$(go env GOOS)
|
||||
GOARCH=$(go env GOARCH)
|
||||
ARCHIVE="WeKnora-lite_${VERSION}_${GOOS}_${GOARCH}"
|
||||
TARBALL="${ROOT_DIR}/dist/${ARCHIVE}.tar.gz"
|
||||
|
||||
# ── Step 1: Build package ──
|
||||
if [ "${SKIP_BUILD:-}" != "1" ]; then
|
||||
echo "=== Step 1: Build local package ==="
|
||||
SKIP_FRONTEND="${SKIP_FRONTEND:-0}" ./scripts/package-lite.sh "${VERSION}"
|
||||
else
|
||||
echo "=== Step 1: Skipped (SKIP_BUILD=1) ==="
|
||||
fi
|
||||
|
||||
if [ ! -f "${TARBALL}" ]; then
|
||||
echo "Error: tarball not found at ${TARBALL}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SHA=$(shasum -a 256 "${TARBALL}" | awk '{print $1}')
|
||||
echo ""
|
||||
echo " Tarball: ${TARBALL}"
|
||||
echo " SHA256: ${SHA}"
|
||||
|
||||
# ── Step 2: Create local tap ──
|
||||
echo ""
|
||||
echo "=== Step 2: Set up local tap ==="
|
||||
|
||||
# Create tap if it doesn't exist
|
||||
TAP_DIR="$(brew --repository)/Library/Taps/weknora/homebrew-test"
|
||||
if [ ! -d "${TAP_DIR}" ]; then
|
||||
mkdir -p "${TAP_DIR}/Formula"
|
||||
(cd "${TAP_DIR}" && git init -q && git commit --allow-empty -m "init" -q)
|
||||
echo " Created tap: ${TAP_NAME}"
|
||||
else
|
||||
echo " Tap already exists: ${TAP_NAME}"
|
||||
fi
|
||||
|
||||
# ── Step 3: Write Formula into tap ──
|
||||
echo ""
|
||||
echo "=== Step 3: Generate Formula ==="
|
||||
|
||||
cat > "${TAP_DIR}/Formula/${FORMULA_NAME}.rb" << RUBY
|
||||
class WeknoraLiteTest < Formula
|
||||
desc "WeKnora Lite (local test)"
|
||||
homepage "https://github.com/Tencent/WeKnora"
|
||||
version "${VERSION}"
|
||||
license "Apache-2.0"
|
||||
|
||||
url "file://${TARBALL}"
|
||||
sha256 "${SHA}"
|
||||
|
||||
def install
|
||||
libexec.install "WeKnora-lite"
|
||||
pkgshare.install "web" if File.directory?("web")
|
||||
pkgshare.install "config" if File.directory?("config")
|
||||
pkgshare.install ".env.lite.example"
|
||||
if File.directory?("migrations")
|
||||
pkgshare.install "migrations"
|
||||
end
|
||||
|
||||
(bin/"weknora-lite-test").write <<~SH
|
||||
#!/bin/bash
|
||||
CONFIG_DIR="\\\${WEKNORA_CONFIG_DIR:-\\\${XDG_CONFIG_HOME:-\\\$HOME/.config}/weknora-test}"
|
||||
DATA_DIR="\\\${WEKNORA_DATA_DIR:-\\\${XDG_DATA_HOME:-\\\$HOME/.local/share}/weknora-test}"
|
||||
|
||||
mkdir -p "\\\$DATA_DIR/files" "\\\$CONFIG_DIR/config" 2>/dev/null
|
||||
|
||||
if [ ! -f "\\\$CONFIG_DIR/config/config.yaml" ]; then
|
||||
cp -r "#{pkgshare}/config/" "\\\$CONFIG_DIR/config/"
|
||||
fi
|
||||
|
||||
if [ ! -d "\\\$CONFIG_DIR/migrations" ] && [ -d "#{pkgshare}/migrations" ]; then
|
||||
ln -sf "#{pkgshare}/migrations" "\\\$CONFIG_DIR/migrations"
|
||||
fi
|
||||
|
||||
if [ ! -f "\\\$CONFIG_DIR/.env.lite" ]; then
|
||||
cp "#{pkgshare}/.env.lite.example" "\\\$CONFIG_DIR/.env.lite"
|
||||
sed -i'' -e "s|DB_PATH=.*|DB_PATH=\\\$DATA_DIR/weknora.db|" "\\\$CONFIG_DIR/.env.lite"
|
||||
sed -i'' -e "s|LOCAL_STORAGE_BASE_DIR=.*|LOCAL_STORAGE_BASE_DIR=\\\$DATA_DIR/files|" "\\\$CONFIG_DIR/.env.lite"
|
||||
echo ""
|
||||
echo "已创建配置文件: \\\$CONFIG_DIR/.env.lite"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
set -a
|
||||
source "\\\$CONFIG_DIR/.env.lite"
|
||||
set +a
|
||||
|
||||
export DB_PATH="\\\${DB_PATH:-\\\$DATA_DIR/weknora.db}"
|
||||
export LOCAL_STORAGE_BASE_DIR="\\\${LOCAL_STORAGE_BASE_DIR:-\\\$DATA_DIR/files}"
|
||||
export WEKNORA_WEB_DIR="\\\${WEKNORA_WEB_DIR:-#{pkgshare}/web}"
|
||||
|
||||
cd "\\\$CONFIG_DIR"
|
||||
exec "#{libexec}/WeKnora-lite" "\\\$@"
|
||||
SH
|
||||
end
|
||||
|
||||
def post_install
|
||||
(var/"weknora-test").mkpath
|
||||
(var/"log").mkpath
|
||||
end
|
||||
|
||||
service do
|
||||
run [bin/"weknora-lite-test"]
|
||||
keep_alive true
|
||||
working_dir var/"weknora-test"
|
||||
log_path var/"log/weknora-lite-test.log"
|
||||
error_log_path var/"log/weknora-lite-test.log"
|
||||
end
|
||||
|
||||
test do
|
||||
assert_predicate bin/"weknora-lite-test", :executable?
|
||||
end
|
||||
end
|
||||
RUBY
|
||||
|
||||
(cd "${TAP_DIR}" && git add -A && git commit -m "update formula" -q --allow-empty)
|
||||
echo " Formula written to: ${TAP_DIR}/Formula/${FORMULA_NAME}.rb"
|
||||
|
||||
# ── Step 4: Install ──
|
||||
echo ""
|
||||
echo "=== Step 4: Install ==="
|
||||
brew reinstall "${TAP_NAME}/${FORMULA_NAME}" 2>&1 || brew install "${TAP_NAME}/${FORMULA_NAME}"
|
||||
|
||||
# ── Step 5: Verify ──
|
||||
echo ""
|
||||
echo "=== Step 5: Verify ==="
|
||||
echo ""
|
||||
echo " which:"
|
||||
which weknora-lite-test || true
|
||||
echo ""
|
||||
echo " Installed files:"
|
||||
brew list "${TAP_NAME}/${FORMULA_NAME}"
|
||||
echo ""
|
||||
echo " Test paths (isolated from production):"
|
||||
echo " Config: ~/.config/weknora-test/.env.lite"
|
||||
echo " Data: ~/.local/share/weknora-test/"
|
||||
|
||||
echo ""
|
||||
echo "=== Done ==="
|
||||
echo ""
|
||||
echo "前台运行:"
|
||||
echo " weknora-lite-test"
|
||||
echo ""
|
||||
echo "后台服务:"
|
||||
echo " brew services start ${TAP_NAME}/${FORMULA_NAME}"
|
||||
echo " brew services info ${TAP_NAME}/${FORMULA_NAME}"
|
||||
echo " brew services stop ${TAP_NAME}/${FORMULA_NAME}"
|
||||
echo ""
|
||||
echo "日志:"
|
||||
echo " $(brew --prefix)/var/log/weknora-lite-test.log"
|
||||
echo ""
|
||||
echo "卸载测试:"
|
||||
echo " brew services stop ${FORMULA_NAME} 2>/dev/null"
|
||||
echo " brew uninstall ${FORMULA_NAME}"
|
||||
echo " brew untap ${TAP_NAME}"
|
||||
echo " rm -rf ~/.config/weknora-test ~/.local/share/weknora-test"
|
||||
74
scripts/update-homebrew-formula.sh
Executable file
74
scripts/update-homebrew-formula.sh
Executable file
@@ -0,0 +1,74 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
#
|
||||
# 更新 Homebrew Formula 中的版本号和 sha256
|
||||
#
|
||||
# 用法:
|
||||
# ./scripts/update-homebrew-formula.sh v0.2.0
|
||||
#
|
||||
# 会自动从 GitHub Releases 下载 .sha256 文件来填充 Formula。
|
||||
# 在 CI 中被 release-lite workflow 调用。
|
||||
#
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
ROOT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||
|
||||
VERSION="${1:?Usage: $0 <version> (e.g. v0.2.0)}"
|
||||
VERSION_BARE="${VERSION#v}"
|
||||
FORMULA="${ROOT_DIR}/Formula/weknora-lite.rb"
|
||||
REPO="Tencent/WeKnora"
|
||||
BASE_URL="https://github.com/${REPO}/releases/download/${VERSION}"
|
||||
|
||||
if [ ! -f "${FORMULA}" ]; then
|
||||
echo "Error: Formula not found at ${FORMULA}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Updating Formula to version ${VERSION_BARE}..."
|
||||
|
||||
fetch_sha256() {
|
||||
local file="$1"
|
||||
local url="${BASE_URL}/${file}.sha256"
|
||||
local sha
|
||||
sha=$(curl -sSL "${url}" | awk '{print $1}')
|
||||
if [ -z "${sha}" ] || [ "${#sha}" -ne 64 ]; then
|
||||
echo "Error: Failed to fetch sha256 from ${url}" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "${sha}"
|
||||
}
|
||||
|
||||
SHA_DARWIN_ARM64=$(fetch_sha256 "WeKnora-lite_${VERSION}_darwin_arm64.tar.gz")
|
||||
SHA_DARWIN_AMD64=$(fetch_sha256 "WeKnora-lite_${VERSION}_darwin_amd64.tar.gz")
|
||||
SHA_LINUX_ARM64=$(fetch_sha256 "WeKnora-lite_${VERSION}_linux_arm64.tar.gz")
|
||||
SHA_LINUX_AMD64=$(fetch_sha256 "WeKnora-lite_${VERSION}_linux_amd64.tar.gz")
|
||||
|
||||
echo " darwin_arm64 : ${SHA_DARWIN_ARM64}"
|
||||
echo " darwin_amd64 : ${SHA_DARWIN_AMD64}"
|
||||
echo " linux_arm64 : ${SHA_LINUX_ARM64}"
|
||||
echo " linux_amd64 : ${SHA_LINUX_AMD64}"
|
||||
|
||||
# Use a temp file for portable sed
|
||||
TMP=$(mktemp)
|
||||
cp "${FORMULA}" "${TMP}"
|
||||
|
||||
# Update version
|
||||
sed -i.bak "s/^ version \".*\"/ version \"${VERSION_BARE}\"/" "${TMP}"
|
||||
|
||||
# Update sha256 values in order of appearance.
|
||||
# The formula has sha256 lines in this order:
|
||||
# 1. darwin arm64
|
||||
# 2. darwin amd64
|
||||
# 3. linux arm64
|
||||
# 4. linux amd64
|
||||
awk -v s1="${SHA_DARWIN_ARM64}" \
|
||||
-v s2="${SHA_DARWIN_AMD64}" \
|
||||
-v s3="${SHA_LINUX_ARM64}" \
|
||||
-v s4="${SHA_LINUX_AMD64}" \
|
||||
'BEGIN{n=0} /sha256 "/{n++; if(n==1) sub(/"[^"]*"$/,"\"" s1 "\""); else if(n==2) sub(/"[^"]*"$/,"\"" s2 "\""); else if(n==3) sub(/"[^"]*"$/,"\"" s3 "\""); else if(n==4) sub(/"[^"]*"$/,"\"" s4 "\"")} {print}' \
|
||||
"${TMP}" > "${FORMULA}"
|
||||
|
||||
rm -f "${TMP}" "${TMP}.bak"
|
||||
|
||||
echo "Formula updated: ${FORMULA}"
|
||||
Reference in New Issue
Block a user