mirror of
https://github.com/lllin000/PaperForge.git
synced 2026-07-22 06:50:53 +00:00
feat(update): smart update with auto-detection + Windows one-click script
paperforge update: - Auto-detects installation method (pip/pip-editable/git/zip) - Routes to appropriate update strategy - pip users: pip install --upgrade - pip-editable users: git pull + pip install -e . - git users: git pull - unknown: zip download fallback scripts/update-paperforge.ps1: - Windows one-click update script - Auto-detects install method - Supports -Force (skip confirm) and -DryRun - Clear colored output with error handling AGENTS.md: - Added comprehensive update section with 4 methods - Documented auto-update and PowerShell script
This commit is contained in:
parent
660204352f
commit
ec2e91d4ac
6 changed files with 581 additions and 9 deletions
133
05_Bases/Literature Hub.base
Normal file
133
05_Bases/Literature Hub.base
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
filters:
|
||||
and:
|
||||
- file.inFolder("03_Resources/LiteratureControl/library-records")
|
||||
properties:
|
||||
zotero_key:
|
||||
displayName: "Zotero Key"
|
||||
title:
|
||||
displayName: "Title"
|
||||
year:
|
||||
displayName: "Year"
|
||||
has_pdf:
|
||||
displayName: "PDF"
|
||||
do_ocr:
|
||||
displayName: "OCR"
|
||||
analyze:
|
||||
displayName: "Analyze"
|
||||
ocr_status:
|
||||
displayName: "OCR Status"
|
||||
deep_reading_status:
|
||||
displayName: "Deep Reading"
|
||||
pdf_path:
|
||||
displayName: "PDF Path"
|
||||
fulltext_md_path:
|
||||
displayName: "Fulltext"
|
||||
views:
|
||||
# PAPERFORGE_VIEW: 控制面板
|
||||
- type: table
|
||||
name: "控制面板"
|
||||
order:
|
||||
- file.name
|
||||
- title
|
||||
- year
|
||||
- has_pdf
|
||||
- do_ocr
|
||||
- analyze
|
||||
- ocr_status
|
||||
- deep_reading_status
|
||||
- pdf_path
|
||||
- fulltext_md_path
|
||||
|
||||
|
||||
# PAPERFORGE_VIEW: 推荐分析
|
||||
- type: table
|
||||
name: "推荐分析"
|
||||
order:
|
||||
- year
|
||||
- title
|
||||
- has_pdf
|
||||
- do_ocr
|
||||
- analyze
|
||||
- ocr_status
|
||||
- deep_reading_status
|
||||
- pdf_path
|
||||
- fulltext_md_path
|
||||
filter: 'analyze = true AND recommend_analyze = true'
|
||||
|
||||
# PAPERFORGE_VIEW: 待 OCR
|
||||
- type: table
|
||||
name: "待 OCR"
|
||||
order:
|
||||
- year
|
||||
- title
|
||||
- has_pdf
|
||||
- do_ocr
|
||||
- ocr_status
|
||||
- pdf_path
|
||||
filter: 'do_ocr = true AND ocr_status = "pending"'
|
||||
|
||||
# PAPERFORGE_VIEW: OCR 完成
|
||||
- type: table
|
||||
name: "OCR 完成"
|
||||
order:
|
||||
- year
|
||||
- title
|
||||
- has_pdf
|
||||
- do_ocr
|
||||
- ocr_status
|
||||
- pdf_path
|
||||
filter: 'ocr_status = "done"'
|
||||
|
||||
# PAPERFORGE_VIEW: 待深度阅读
|
||||
- type: table
|
||||
name: "待深度阅读"
|
||||
order:
|
||||
- year
|
||||
- title
|
||||
- has_pdf
|
||||
- do_ocr
|
||||
- analyze
|
||||
- ocr_status
|
||||
- deep_reading_status
|
||||
- pdf_path
|
||||
filter: 'analyze = true AND ocr_status = "done" AND deep_reading_status = "pending"'
|
||||
|
||||
# PAPERFORGE_VIEW: 深度阅读完成
|
||||
- type: table
|
||||
name: "深度阅读完成"
|
||||
order:
|
||||
- year
|
||||
- title
|
||||
- has_pdf
|
||||
- do_ocr
|
||||
- analyze
|
||||
- ocr_status
|
||||
- deep_reading_status
|
||||
- pdf_path
|
||||
filter: 'deep_reading_status = "done"'
|
||||
|
||||
# PAPERFORGE_VIEW: 正式卡片
|
||||
- type: table
|
||||
name: "正式卡片"
|
||||
order:
|
||||
- title
|
||||
- year
|
||||
- has_pdf
|
||||
- deep_reading_status
|
||||
- pdf_path
|
||||
filter: 'deep_reading_status = "done"'
|
||||
|
||||
# PAPERFORGE_VIEW: 全记录
|
||||
- type: table
|
||||
name: "全记录"
|
||||
order:
|
||||
- title
|
||||
- year
|
||||
- has_pdf
|
||||
- do_ocr
|
||||
- analyze
|
||||
- ocr_status
|
||||
- deep_reading_status
|
||||
- pdf_path
|
||||
- fulltext_md_path
|
||||
|
||||
133
05_Bases/PaperForge.base
Normal file
133
05_Bases/PaperForge.base
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
filters:
|
||||
and:
|
||||
- file.inFolder("03_Resources/LiteratureControl/library-records")
|
||||
properties:
|
||||
zotero_key:
|
||||
displayName: "Zotero Key"
|
||||
title:
|
||||
displayName: "Title"
|
||||
year:
|
||||
displayName: "Year"
|
||||
has_pdf:
|
||||
displayName: "PDF"
|
||||
do_ocr:
|
||||
displayName: "OCR"
|
||||
analyze:
|
||||
displayName: "Analyze"
|
||||
ocr_status:
|
||||
displayName: "OCR Status"
|
||||
deep_reading_status:
|
||||
displayName: "Deep Reading"
|
||||
pdf_path:
|
||||
displayName: "PDF Path"
|
||||
fulltext_md_path:
|
||||
displayName: "Fulltext"
|
||||
views:
|
||||
# PAPERFORGE_VIEW: 控制面板
|
||||
- type: table
|
||||
name: "控制面板"
|
||||
order:
|
||||
- file.name
|
||||
- title
|
||||
- year
|
||||
- has_pdf
|
||||
- do_ocr
|
||||
- analyze
|
||||
- ocr_status
|
||||
- deep_reading_status
|
||||
- pdf_path
|
||||
- fulltext_md_path
|
||||
|
||||
|
||||
# PAPERFORGE_VIEW: 推荐分析
|
||||
- type: table
|
||||
name: "推荐分析"
|
||||
order:
|
||||
- year
|
||||
- title
|
||||
- has_pdf
|
||||
- do_ocr
|
||||
- analyze
|
||||
- ocr_status
|
||||
- deep_reading_status
|
||||
- pdf_path
|
||||
- fulltext_md_path
|
||||
filter: 'analyze = true AND recommend_analyze = true'
|
||||
|
||||
# PAPERFORGE_VIEW: 待 OCR
|
||||
- type: table
|
||||
name: "待 OCR"
|
||||
order:
|
||||
- year
|
||||
- title
|
||||
- has_pdf
|
||||
- do_ocr
|
||||
- ocr_status
|
||||
- pdf_path
|
||||
filter: 'do_ocr = true AND ocr_status = "pending"'
|
||||
|
||||
# PAPERFORGE_VIEW: OCR 完成
|
||||
- type: table
|
||||
name: "OCR 完成"
|
||||
order:
|
||||
- year
|
||||
- title
|
||||
- has_pdf
|
||||
- do_ocr
|
||||
- ocr_status
|
||||
- pdf_path
|
||||
filter: 'ocr_status = "done"'
|
||||
|
||||
# PAPERFORGE_VIEW: 待深度阅读
|
||||
- type: table
|
||||
name: "待深度阅读"
|
||||
order:
|
||||
- year
|
||||
- title
|
||||
- has_pdf
|
||||
- do_ocr
|
||||
- analyze
|
||||
- ocr_status
|
||||
- deep_reading_status
|
||||
- pdf_path
|
||||
filter: 'analyze = true AND ocr_status = "done" AND deep_reading_status = "pending"'
|
||||
|
||||
# PAPERFORGE_VIEW: 深度阅读完成
|
||||
- type: table
|
||||
name: "深度阅读完成"
|
||||
order:
|
||||
- year
|
||||
- title
|
||||
- has_pdf
|
||||
- do_ocr
|
||||
- analyze
|
||||
- ocr_status
|
||||
- deep_reading_status
|
||||
- pdf_path
|
||||
filter: 'deep_reading_status = "done"'
|
||||
|
||||
# PAPERFORGE_VIEW: 正式卡片
|
||||
- type: table
|
||||
name: "正式卡片"
|
||||
order:
|
||||
- title
|
||||
- year
|
||||
- has_pdf
|
||||
- deep_reading_status
|
||||
- pdf_path
|
||||
filter: 'deep_reading_status = "done"'
|
||||
|
||||
# PAPERFORGE_VIEW: 全记录
|
||||
- type: table
|
||||
name: "全记录"
|
||||
order:
|
||||
- title
|
||||
- year
|
||||
- has_pdf
|
||||
- do_ocr
|
||||
- analyze
|
||||
- ocr_status
|
||||
- deep_reading_status
|
||||
- pdf_path
|
||||
- fulltext_md_path
|
||||
|
||||
3
99_System/PaperForge/config/domain-collections.json
Normal file
3
99_System/PaperForge/config/domain-collections.json
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"domains": []
|
||||
}
|
||||
57
AGENTS.md
57
AGENTS.md
|
|
@ -455,15 +455,62 @@ paperforge doctor
|
|||
## 10. 升级与维护
|
||||
|
||||
### 更新 PaperForge 代码
|
||||
|
||||
#### 方式 1:自动更新(推荐)
|
||||
|
||||
```bash
|
||||
# 自动检测安装方式并更新
|
||||
paperforge update
|
||||
```
|
||||
|
||||
系统会自动检测你是通过 pip、git 还是手动安装,并执行对应的更新方式。
|
||||
|
||||
#### 方式 2:Windows 一键脚本
|
||||
|
||||
双击运行 Vault 根目录下的 `scripts/update-paperforge.ps1`:
|
||||
- 自动检测安装方式
|
||||
- 自动执行更新
|
||||
- 无需手动输入命令
|
||||
|
||||
```powershell
|
||||
# 或在 PowerShell 中执行
|
||||
.\scripts\update-paperforge.ps1
|
||||
|
||||
# 强制更新(跳过确认)
|
||||
.\scripts\update-paperforge.ps1 -Force
|
||||
|
||||
# 只检测不更新
|
||||
.\scripts\update-paperforge.ps1 -DryRun
|
||||
```
|
||||
|
||||
#### 方式 3:手动更新
|
||||
|
||||
**pip 安装用户:**
|
||||
```bash
|
||||
pip install --upgrade paperforge
|
||||
```
|
||||
|
||||
**pip editable 安装用户:**
|
||||
```bash
|
||||
cd 你的Vault路径
|
||||
# 如果你有 git 跟踪 PaperForge
|
||||
git pull origin main
|
||||
|
||||
# 或手动复制更新文件
|
||||
cp -r 新下载的scripts/* <system_dir>/PaperForge/worker/scripts/
|
||||
git pull origin master
|
||||
pip install -e .
|
||||
```
|
||||
|
||||
**git clone 用户:**
|
||||
```bash
|
||||
cd 你的Vault路径
|
||||
git pull origin master
|
||||
```
|
||||
|
||||
#### 方式 4:手动复制(最后手段)
|
||||
|
||||
```bash
|
||||
cp -r 新下载的代码/* <vault_path>/
|
||||
```
|
||||
|
||||
> [!WARNING] 手动复制容易遗漏文件,建议优先使用自动更新。
|
||||
|
||||
### 备份注意事项
|
||||
- `<resources_dir>/` 和 `<system_dir>/PaperForge/ocr/` 包含你的数据,需备份
|
||||
- `.env` 包含 API Key,不要提交到 git
|
||||
|
|
|
|||
|
|
@ -299,7 +299,49 @@ def _rollback(vault: Path, backup_dir: Path) -> None:
|
|||
_log("[OK] 回滚完成", "g")
|
||||
|
||||
|
||||
def update_via_git(vault: Path) -> bool:
|
||||
def _detect_install_method() -> tuple[str, Path | None]:
|
||||
"""Detect how paperforge is installed."""
|
||||
import paperforge
|
||||
pkg_dir = Path(paperforge.__file__).parent.resolve()
|
||||
|
||||
# Check if installed in site-packages (pip install)
|
||||
if "site-packages" in str(pkg_dir) or "dist-packages" in str(pkg_dir):
|
||||
return ("pip", pkg_dir)
|
||||
|
||||
# Check if in editable mode (pip install -e .)
|
||||
if pkg_dir.name == "paperforge" and (pkg_dir.parent / ".git").exists():
|
||||
return ("pip-editable", pkg_dir.parent)
|
||||
|
||||
# Check if vault has .git (git clone)
|
||||
vault = Path.cwd()
|
||||
if (vault / ".git").exists():
|
||||
return ("git", vault)
|
||||
|
||||
return ("unknown", None)
|
||||
|
||||
|
||||
def _update_via_pip(editable: bool = False) -> bool:
|
||||
"""Update via pip install."""
|
||||
cmd = [sys.executable, "-m", "pip", "install"]
|
||||
if editable:
|
||||
cmd.extend(["-e", "."])
|
||||
else:
|
||||
cmd.append("--upgrade")
|
||||
cmd.append("paperforge")
|
||||
|
||||
_log(f"[INFO] 执行: {' '.join(cmd)}", "b")
|
||||
r = subprocess.run(cmd, capture_output=True, text=True, encoding="utf-8")
|
||||
if r.returncode != 0:
|
||||
_log(f"[ERR] pip 更新失败: {r.stderr}", "r")
|
||||
return False
|
||||
_log("[OK] pip 更新成功", "g")
|
||||
if r.stdout.strip():
|
||||
print(r.stdout)
|
||||
return True
|
||||
|
||||
|
||||
def _update_via_git(vault: Path) -> bool:
|
||||
"""Update via git pull."""
|
||||
if not (vault / ".git").is_dir():
|
||||
_log("[ERR] 不是 git 仓库", "r")
|
||||
return False
|
||||
|
|
@ -383,10 +425,32 @@ def run_update(vault: Path) -> int:
|
|||
if ans not in ("y", "yes"):
|
||||
_log("[INFO] 已取消", "c")
|
||||
return 0
|
||||
if (vault / ".git").is_dir():
|
||||
success = update_via_git(vault)
|
||||
|
||||
# Auto-detect installation method
|
||||
method, path = _detect_install_method()
|
||||
_log(f"[检测] 安装方式: {method}", "c")
|
||||
|
||||
if method == "pip":
|
||||
_log("[INFO] 通过 pip 更新...", "b")
|
||||
success = _update_via_pip(editable=False)
|
||||
elif method == "pip-editable":
|
||||
_log("[INFO] 通过 pip editable 模式更新...", "b")
|
||||
# For editable install, need to git pull first then reinstall
|
||||
if path and (path / ".git").exists():
|
||||
success = _update_via_git(path)
|
||||
if success:
|
||||
_log("[INFO] 重新安装 editable 模式...", "b")
|
||||
os.chdir(path)
|
||||
success = _update_via_pip(editable=True)
|
||||
else:
|
||||
_log("[WARN] 无法找到 git 仓库,尝试 pip 更新...", "y")
|
||||
success = _update_via_pip(editable=False)
|
||||
elif method == "git":
|
||||
success = _update_via_git(vault)
|
||||
else:
|
||||
success = update_via_zip(vault)
|
||||
_log("[WARN] 未检测到标准安装方式,尝试 zip 下载...", "y")
|
||||
success = _update_via_zip(vault)
|
||||
|
||||
if success:
|
||||
_log("\n[OK] 更新完成!请重启 Obsidian", "g")
|
||||
return 0 if success else 1
|
||||
|
|
|
|||
192
scripts/update-paperforge.ps1
Normal file
192
scripts/update-paperforge.ps1
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
# PaperForge Lite Update Script for Windows
|
||||
# 一键更新脚本 — 双击运行即可
|
||||
#
|
||||
# 功能:
|
||||
# 1. 自动检测安装方式(pip/pip-editable/git/zip)
|
||||
# 2. 执行对应的更新命令
|
||||
# 3. 如果自动检测失败,提供手动选项
|
||||
#
|
||||
# 用法:
|
||||
# 1. 右键此文件 → "使用 PowerShell 运行"
|
||||
# 2. 或在终端执行: .\update-paperforge.ps1
|
||||
|
||||
param(
|
||||
[switch]$Force, # 跳过确认提示
|
||||
[switch]$DryRun # 只检测不执行
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
# 颜色输出
|
||||
function Write-Color($text, $color = "White") {
|
||||
Write-Host $text -ForegroundColor $color
|
||||
}
|
||||
|
||||
Write-Color @"
|
||||
========================================
|
||||
PaperForge Lite 更新助手
|
||||
========================================
|
||||
"@ "Cyan"
|
||||
|
||||
# 检测 Python
|
||||
$python = Get-Command python -ErrorAction SilentlyContinue
|
||||
if (-not $python) {
|
||||
$python = Get-Command python3 -ErrorAction SilentlyContinue
|
||||
}
|
||||
if (-not $python) {
|
||||
Write-Color "[错误] 未找到 Python。请先安装 Python 3.10+" "Red"
|
||||
exit 1
|
||||
}
|
||||
|
||||
$pyVersion = & $python.Source --version 2>&1
|
||||
Write-Color "[检测] Python: $pyVersion" "Gray"
|
||||
|
||||
# 检测 pip
|
||||
$pip = Get-Command pip -ErrorAction SilentlyContinue
|
||||
if (-not $pip) {
|
||||
$pip = Get-Command pip3 -ErrorAction SilentlyContinue
|
||||
}
|
||||
if (-not $pip) {
|
||||
Write-Color "[错误] 未找到 pip。请检查 Python 安装" "Red"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# 检测 paperforge 安装方式
|
||||
Write-Color "`n[检测] 正在分析 PaperForge 安装方式..." "Yellow"
|
||||
|
||||
$installMethod = "unknown"
|
||||
$installPath = $null
|
||||
|
||||
try {
|
||||
$pkgPath = & $python.Source -c "import paperforge; print(paperforge.__file__)" 2>$null
|
||||
if ($pkgPath) {
|
||||
$pkgDir = Split-Path $pkgPath -Parent
|
||||
$installPath = $pkgDir
|
||||
|
||||
if ($pkgDir -match "site-packages|dist-packages") {
|
||||
# pip install (non-editable)
|
||||
$installMethod = "pip"
|
||||
} elseif (Test-Path (Join-Path $pkgDir "..\.git")) {
|
||||
# pip install -e .
|
||||
$installMethod = "pip-editable"
|
||||
$installPath = Resolve-Path (Join-Path $pkgDir "..") | Select-Object -ExpandProperty Path
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
# paperforge not installed via pip
|
||||
}
|
||||
|
||||
# 如果上面没检测到,检查当前目录是否有 .git
|
||||
if ($installMethod -eq "unknown" -and (Test-Path ".git")) {
|
||||
$installMethod = "git"
|
||||
$installPath = (Get-Location).Path
|
||||
}
|
||||
|
||||
# 显示检测结果
|
||||
Write-Color "[结果] 安装方式: $installMethod" $(if ($installMethod -ne "unknown") { "Green" } else { "Red" })
|
||||
if ($installPath) {
|
||||
Write-Color "[路径] $installPath" "Gray"
|
||||
}
|
||||
|
||||
if ($DryRun) {
|
||||
Write-Color "`n[干运行模式] 仅检测,不执行更新" "Yellow"
|
||||
exit 0
|
||||
}
|
||||
|
||||
# 根据安装方式执行更新
|
||||
$success = $false
|
||||
|
||||
switch ($installMethod) {
|
||||
"pip" {
|
||||
Write-Color "`n[更新] 通过 pip 升级..." "Cyan"
|
||||
Write-Color "命令: pip install --upgrade paperforge" "Gray"
|
||||
|
||||
if (-not $Force) {
|
||||
$confirm = Read-Host "确认更新? [y/N]"
|
||||
if ($confirm -notmatch "^[Yy]") {
|
||||
Write-Color "[取消] 更新已取消" "Yellow"
|
||||
exit 0
|
||||
}
|
||||
}
|
||||
|
||||
& $pip.Source install --upgrade paperforge
|
||||
$success = ($LASTEXITCODE -eq 0)
|
||||
}
|
||||
|
||||
"pip-editable" {
|
||||
Write-Color "`n[更新] pip editable 模式 detected" "Cyan"
|
||||
Write-Color "步骤 1: git pull 拉取最新代码..." "Yellow"
|
||||
|
||||
if (-not $Force) {
|
||||
$confirm = Read-Host "确认更新? [y/N]"
|
||||
if ($confirm -notmatch "^[Yy]") {
|
||||
Write-Color "[取消] 更新已取消" "Yellow"
|
||||
exit 0
|
||||
}
|
||||
}
|
||||
|
||||
Push-Location $installPath
|
||||
try {
|
||||
git pull origin master
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Color "步骤 2: 重新安装 editable 模式..." "Yellow"
|
||||
& $pip.Source install -e .
|
||||
$success = ($LASTEXITCODE -eq 0)
|
||||
}
|
||||
} finally {
|
||||
Pop-Location
|
||||
}
|
||||
}
|
||||
|
||||
"git" {
|
||||
Write-Color "`n[更新] 通过 git pull 更新..." "Cyan"
|
||||
Write-Color "命令: git pull origin master" "Gray"
|
||||
|
||||
if (-not $Force) {
|
||||
$confirm = Read-Host "确认更新? [y/N]"
|
||||
if ($confirm -notmatch "^[Yy]") {
|
||||
Write-Color "[取消] 更新已取消" "Yellow"
|
||||
exit 0
|
||||
}
|
||||
}
|
||||
|
||||
git pull origin master
|
||||
$success = ($LASTEXITCODE -eq 0)
|
||||
}
|
||||
|
||||
default {
|
||||
Write-Color "`n[错误] 无法自动检测安装方式" "Red"
|
||||
Write-Color @"
|
||||
|
||||
可能的解决方案:
|
||||
1. 如果你是通过 pip 安装的:
|
||||
pip install --upgrade paperforge
|
||||
|
||||
2. 如果你是通过 git clone 的:
|
||||
git pull origin master
|
||||
pip install -e .
|
||||
|
||||
3. 如果你不确定:
|
||||
- 删除现有安装
|
||||
- 重新运行: pip install -e .
|
||||
"@ "Yellow"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
# 验证更新
|
||||
if ($success) {
|
||||
Write-Color "`n[验证] 检查更新结果..." "Cyan"
|
||||
try {
|
||||
$newVersion = & $python.Source -c "import paperforge; print(paperforge.__version__)" 2>$null
|
||||
Write-Color "[成功] 更新完成!当前版本: $newVersion" "Green"
|
||||
Write-Color "`n提示: 请重启 Obsidian 以应用更新" "Yellow"
|
||||
} catch {
|
||||
Write-Color "[成功] 更新完成!请重启 Obsidian" "Green"
|
||||
}
|
||||
exit 0
|
||||
} else {
|
||||
Write-Color "`n[失败] 更新过程中出现错误" "Red"
|
||||
Write-Color "建议: 检查网络连接,或稍后重试" "Yellow"
|
||||
exit 1
|
||||
}
|
||||
Loading…
Reference in a new issue