455 lines
16 KiB
Markdown
455 lines
16 KiB
Markdown
---
|
||
name: langgraph-vivado-install
|
||
description: 在 Windows 原生环境下自动化配置基于 Conda 的 LangGraph 开发环境,并强制完成 Vivado 链路的闭环验证。当用户提到"配置langgraph"、"安装langgraph"、"LangGraph环境"、"langgraph vivado"、"配置开发环境 langgraph"、"LangGraph+Vivado"、"搭建langgraph"时,必须触发此技能。即使用户未明确说"用这个技能",只要涉及在 Windows 上安装或配置 LangGraph(含与 Vivado 集成),都应触发。
|
||
---
|
||
|
||
# LangGraph + Vivado 环境配置技能
|
||
|
||
本技能在 Windows 原生环境(Git Bash / 命令提示符)中自动完成以下工作:
|
||
1. 检测并安装 Conda
|
||
2. 确认 conda 路径已永久写入 Windows 用户级 PATH
|
||
3. 创建 `langgraph` 虚拟环境并安装所需包
|
||
4. 迭代检测 Vivado 链路直至成功
|
||
5. 写出配置文件与冒烟测试脚本并运行验证
|
||
|
||
---
|
||
|
||
## 整体流程
|
||
|
||
```
|
||
Step 1: Conda 检测与安装
|
||
Step 1b: 确认 conda 路径已写入 Windows PATH(新安装或已有均执行)
|
||
Step 2: 创建 langgraph 环境,安装依赖
|
||
Step 2c: 检测并安装 Codex CLI,验证 Auth
|
||
Step 3: Vivado 链路迭代检测(循环直到成功)
|
||
Step 4: 写出 env_config.json,提示持久化
|
||
Step 5: 生成并运行 smoke_test.py
|
||
```
|
||
|
||
---
|
||
|
||
## Step 1 — Conda 检测与安装
|
||
|
||
运行:
|
||
```bash
|
||
conda --version
|
||
```
|
||
|
||
- **若成功**:记录版本,进入 **Step 1b**。
|
||
- **若失败**:执行安装命令:
|
||
```bash
|
||
winget install -e --id Anaconda.Miniconda3
|
||
```
|
||
安装完成后,提示用户:
|
||
> "Miniconda 安装完成。请重启 Shell 或运行 `conda init bash` 使 conda 命令生效,然后重新触发本技能。"
|
||
**在用户确认 conda 可用之前,不继续执行后续步骤。用户确认后,进入 Step 1b。**
|
||
|
||
---
|
||
|
||
## Step 1b — 确认 conda 路径已写入 Windows PATH
|
||
|
||
无论 conda 是刚安装的还是之前已存在,都必须执行此步骤,确保 conda 的路径被永久写入 Windows 用户级 PATH,方便在任何新 Shell 中直接使用。
|
||
|
||
### 1. 定位 conda 所在目录
|
||
|
||
在 PowerShell 中运行:
|
||
```powershell
|
||
$condaPath = (Get-Command conda -ErrorAction SilentlyContinue).Source
|
||
$condaBin = if ($condaPath) { Split-Path $condaPath -Parent } else { $null }
|
||
Write-Host "conda 所在目录: $condaBin"
|
||
```
|
||
|
||
若 `$condaBin` 为空(conda 命令本身来自 conda init 脚本而非独立可执行文件),则改用:
|
||
```powershell
|
||
# 方法 B:通过 conda info 获取 base 目录,再拼接 condabin
|
||
$baseDir = (conda info --base 2>$null).Trim()
|
||
$condaBin = Join-Path $baseDir "condabin"
|
||
Write-Host "conda condabin 目录: $condaBin"
|
||
```
|
||
|
||
### 2. 检查路径是否已在 PATH 中
|
||
|
||
```powershell
|
||
$userPath = [System.Environment]::GetEnvironmentVariable("PATH", "User")
|
||
$sysPath = [System.Environment]::GetEnvironmentVariable("PATH", "Machine")
|
||
|
||
$inUserPath = ($userPath -split ";") -contains $condaBin
|
||
$inSysPath = ($sysPath -split ";") -contains $condaBin
|
||
|
||
if ($inUserPath -or $inSysPath) {
|
||
Write-Host "[OK] conda 路径已在 PATH 中,无需修改。"
|
||
} else {
|
||
Write-Host "[INFO] conda 路径不在 PATH 中,准备写入用户级 PATH..."
|
||
}
|
||
```
|
||
|
||
### 3. 若不在 PATH 中则写入
|
||
|
||
```powershell
|
||
if (-not ($inUserPath -or $inSysPath)) {
|
||
$newUserPath = $condaBin + ";" + $userPath
|
||
[System.Environment]::SetEnvironmentVariable("PATH", $newUserPath, "User")
|
||
Write-Host "[OK] 已将以下路径写入用户级 PATH: $condaBin"
|
||
Write-Host " 新开终端后即可直接使用 conda 命令。"
|
||
}
|
||
```
|
||
|
||
> **为什么写用户级 PATH 而非系统级?** 用户级 PATH 不需要管理员权限,且只影响当前用户,更安全。若该机器是多用户共享环境,可改为 `"Machine"` 并以管理员身份运行。
|
||
|
||
完成后进入 Step 2。
|
||
|
||
---
|
||
|
||
## Step 2 — 创建 langgraph Conda 环境
|
||
|
||
### 2a. 检查环境是否已存在
|
||
```bash
|
||
conda env list | grep "^langgraph"
|
||
```
|
||
|
||
- 若已存在:跳过创建,直接进入 2b。
|
||
- 若不存在:
|
||
```bash
|
||
conda create -n langgraph python=3.11 -y
|
||
```
|
||
|
||
### 2b. 安装所需 Python 包
|
||
|
||
一条命令安装全部依赖(包含 `/langgraph-plan-review` skill 所需包):
|
||
|
||
```bash
|
||
conda run -n langgraph pip install \
|
||
langgraph \
|
||
langchain-anthropic \
|
||
pandas \
|
||
"langgraph-cli[inmem]" \
|
||
langgraph-sdk \
|
||
httpx \
|
||
langgraph-checkpoint-sqlite
|
||
```
|
||
|
||
> **为什么这些包?**
|
||
> | 包 | 用途 |
|
||
> |---|---|
|
||
> | `langgraph` | 核心图执行引擎 |
|
||
> | `langchain-anthropic` | Anthropic LLM 集成 |
|
||
> | `pandas` | 数据处理 |
|
||
> | `langgraph-cli[inmem]` | 提供 `langgraph dev` 服务器命令(`/langgraph-plan-review` 必需) |
|
||
> | `langgraph-sdk` | `run_workflow.py` 通过 SDK 向 dev server 提交 run(`/langgraph-plan-review` 必需) |
|
||
> | `httpx` | `run_workflow.py` 健康检查(`/langgraph-plan-review` 必需) |
|
||
> | `langgraph-checkpoint-sqlite` | dev server 状态持久化(`/langgraph-plan-review` 必需) |
|
||
|
||
验证安装:
|
||
```bash
|
||
conda run -n langgraph python -c "import langgraph; print('LangGraph OK:', langgraph.__version__)"
|
||
conda run -n langgraph python -c "from langgraph_sdk import get_sync_client; print('langgraph-sdk OK')"
|
||
conda run -n langgraph python -c "import httpx; print('httpx OK')"
|
||
conda run -n langgraph langgraph --version
|
||
```
|
||
|
||
若任一导入失败,报告错误并停止,请用户检查网络或 pip 源配置。
|
||
|
||
---
|
||
|
||
## Step 2c — 检测并安装 Codex CLI,验证 Auth
|
||
|
||
Codex CLI 是 OpenAI 发布的命令行代码审查工具,以 npm 全局包形式安装在 `langgraph` conda 环境中,供 LangGraph 工作流的 Codex review 节点调用。
|
||
|
||
### 2c-1. 检测 Codex CLI 是否已安装
|
||
|
||
在 PowerShell 中运行:
|
||
|
||
```powershell
|
||
$condaEnvPath = (C:\Users\bowei\miniconda3\Scripts\conda.exe run -n langgraph python -c "import sys; print(sys.prefix)").Trim()
|
||
$codexCmd = Join-Path $condaEnvPath "codex.cmd"
|
||
if (Test-Path $codexCmd) {
|
||
Write-Host "[OK] Codex CLI 已安装: $codexCmd"
|
||
$codexInstalled = $true
|
||
} else {
|
||
Write-Host "[INFO] 未检测到 Codex CLI,准备安装..."
|
||
$codexInstalled = $false
|
||
}
|
||
```
|
||
|
||
### 2c-2. 若未安装,通过 npm 安装
|
||
|
||
首先确认 npm 可用(Node.js 需已安装在 conda 环境或系统 PATH 中):
|
||
|
||
```powershell
|
||
C:\Users\bowei\miniconda3\Scripts\conda.exe run -n langgraph npm --version
|
||
```
|
||
|
||
- **若 npm 可用**:执行安装:
|
||
```powershell
|
||
C:\Users\bowei\miniconda3\Scripts\conda.exe run -n langgraph npm install -g @openai/codex
|
||
```
|
||
安装完成后,再次执行 2c-1 检查 `codex.cmd` 是否出现。若仍不存在,报告错误并停止,请用户手动检查 npm 全局安装路径。
|
||
|
||
- **若 npm 不可用**:停止并提示:
|
||
> "langgraph conda 环境中未找到 npm。请先安装 Node.js(建议通过 `winget install OpenJS.NodeJS.LTS`),重启 Shell 后重新触发本技能。"
|
||
**在用户确认 npm 可用之前,不继续后续步骤。**
|
||
|
||
### 2c-3. 验证 Codex CLI 可执行
|
||
|
||
```powershell
|
||
$env:CODEX_HOME = "C:\Users\bowei\.codex"
|
||
cmd /c "$codexCmd" --version
|
||
```
|
||
|
||
- 若命令输出版本号(如 `0.133.0`):记录版本,继续。
|
||
- 若命令失败:报告错误(输出内容),停止执行,请用户检查 Node.js 版本兼容性。
|
||
|
||
> **为什么用 `cmd /c`?** `.cmd` 文件在 Windows 上不能直接被 PowerShell 或 Python subprocess 执行,必须通过 `cmd /c` 转发。
|
||
|
||
### 2c-4. 验证 Codex Auth
|
||
|
||
Codex CLI 的认证 token 存储在 `$CODEX_HOME\auth.json`(默认 `C:\Users\bowei\.codex\auth.json`)。
|
||
|
||
```powershell
|
||
$codexHome = if ($env:CODEX_HOME) { $env:CODEX_HOME } else { "$env:USERPROFILE\.codex" }
|
||
$authFile = Join-Path $codexHome "auth.json"
|
||
|
||
if (Test-Path $authFile) {
|
||
$authContent = (Get-Content $authFile -Raw -Encoding utf8).Trim()
|
||
if ($authContent.Length -gt 20) {
|
||
Write-Host "[OK] Codex auth.json 存在且内容有效。"
|
||
$authOk = $true
|
||
} else {
|
||
Write-Host "[WARN] auth.json 内容过短,可能已损坏或未完成认证。"
|
||
$authOk = $false
|
||
}
|
||
} else {
|
||
Write-Host "[WARN] 未找到 auth.json: $authFile"
|
||
$authOk = $false
|
||
}
|
||
```
|
||
|
||
- **若 `$authOk = $true`**:继续进入 Step 3。
|
||
- **若 `$authOk = $false`**:停止并提示:
|
||
> "Codex CLI 尚未完成认证,或认证已失效。请在终端运行 `codex` 并按提示完成 ChatGPT OAuth 登录,登录成功后 auth.json 将自动写入 `C:\Users\bowei\.codex\`。完成后重新触发本技能或手动继续到 Step 3。"
|
||
|
||
**在用户确认认证完成之前,不继续后续步骤。**
|
||
|
||
> **为什么检查 auth.json 而非运行 `codex auth status`?** Codex CLI 目前没有独立的状态查询子命令;auth.json 存在且非空即表示 OAuth 流程已完成。若需更严格验证,可在 Step 5 冒烟测试中加入一次受控的 `codex exec --ephemeral` 调用。
|
||
|
||
---
|
||
|
||
## Step 3 — Vivado 链路迭代检测循环
|
||
|
||
这是本技能的核心环节。目标是确保在 `langgraph` 环境中可以调用 Vivado。
|
||
|
||
### Step A:首次尝试检测
|
||
```bash
|
||
conda run -n langgraph vivado -version
|
||
```
|
||
|
||
### Step B:若成功
|
||
- 打印版本信息(取输出第一行)。
|
||
- 进入 Step 4。
|
||
|
||
### Step C:若失败(命令未找到)— 交互式路径收集
|
||
|
||
**停止自动化**,向用户提问:
|
||
|
||
> "未能检测到 Vivado 环境。请输入 Vivado 的 bin 文件夹完整路径(例如:`C:\Xilinx\Vivado\2023.2\bin`):"
|
||
|
||
**收到用户输入后执行:**
|
||
|
||
1. **验证路径有效性** — 检查该目录下 `vivado.bat` 是否存在:
|
||
```bash
|
||
# 将用户输入的 Windows 路径转换为 bash 路径后检查
|
||
# 例:C:\Xilinx\Vivado\2023.2\bin → /c/Xilinx/Vivado/2023.2/bin
|
||
ls "<converted_path>/vivado.bat"
|
||
```
|
||
- 若不存在:提示 "路径无效或找不到 vivado.bat,请重新输入。" 并**重复 Step C**。
|
||
- 若存在:继续。
|
||
|
||
2. **将路径临时加入当前会话 PATH**(Windows 反斜杠转为正斜杠):
|
||
```bash
|
||
export PATH="<converted_path>:$PATH"
|
||
```
|
||
|
||
3. **记录该路径**供后续 Step 4/5 使用(内部变量 `VIVADO_BIN_PATH`)。
|
||
|
||
4. **重试检测**:
|
||
```bash
|
||
vivado -version
|
||
```
|
||
- 若成功:打印版本,进入 Step 4。
|
||
- 若再次失败:回到 Step C 顶部,重新向用户询问路径。
|
||
|
||
> **循环逻辑**:重复 Step C 直到 `vivado -version` 执行成功为止。不要跳过,不要假设路径正确。
|
||
|
||
---
|
||
|
||
## Step 4 — 持久化配置
|
||
|
||
`vivado -version` 成功后:
|
||
|
||
### 4a. 提示用户持久化
|
||
向用户说明:
|
||
> "为了在每次新开 Shell 时自动识别 Vivado,建议将该路径永久添加到 Windows 系统环境变量 PATH 中。操作方法:系统属性 → 高级 → 环境变量 → 编辑 PATH → 新建,粘贴路径。"
|
||
|
||
### 4b. 写出 env_config.json
|
||
在当前工作目录创建:
|
||
```json
|
||
{
|
||
"VIVADO_BIN_PATH": "<Step 3 确认的 Windows 格式路径>",
|
||
"conda_env": "langgraph",
|
||
"python_version": "3.11",
|
||
"packages": [
|
||
"langgraph",
|
||
"langchain-anthropic",
|
||
"pandas",
|
||
"langgraph-cli[inmem]",
|
||
"langgraph-sdk",
|
||
"httpx",
|
||
"langgraph-checkpoint-sqlite"
|
||
]
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Step 5 — 生成冒烟测试脚本并运行
|
||
|
||
在当前工作目录创建 `smoke_test.py`,内容如下:
|
||
|
||
```python
|
||
import subprocess
|
||
import sys
|
||
import json
|
||
import os
|
||
|
||
|
||
def test_langgraph():
|
||
try:
|
||
import langgraph
|
||
import importlib.metadata
|
||
version = importlib.metadata.version("langgraph")
|
||
print(f"[OK] LangGraph import OK, version: {version}")
|
||
return True
|
||
except ImportError as e:
|
||
print(f"[FAIL] LangGraph import failed: {e}")
|
||
return False
|
||
|
||
|
||
def test_langgraph_plan_review_deps():
|
||
"""Verify packages required by the /langgraph-plan-review skill."""
|
||
ok = True
|
||
checks = [
|
||
("langgraph_sdk", "from langgraph_sdk import get_sync_client"),
|
||
("httpx", "import httpx"),
|
||
("langgraph_checkpoint_sqlite", "from langgraph.checkpoint.sqlite import SqliteSaver"),
|
||
]
|
||
for name, stmt in checks:
|
||
try:
|
||
exec(stmt)
|
||
import importlib.metadata
|
||
try:
|
||
ver = importlib.metadata.version(name.replace("_", "-"))
|
||
print(f"[OK] {name} OK (version: {ver})")
|
||
except importlib.metadata.PackageNotFoundError:
|
||
print(f"[OK] {name} importable")
|
||
except Exception as e:
|
||
print(f"[FAIL] {name}: {e}")
|
||
ok = False
|
||
|
||
# Check langgraph dev CLI
|
||
try:
|
||
result = subprocess.run(
|
||
[sys.executable, "-m", "langgraph", "--version"],
|
||
capture_output=True, text=True, timeout=10
|
||
)
|
||
if result.returncode == 0:
|
||
print(f"[OK] langgraph-cli OK: {result.stdout.strip() or result.stderr.strip()}")
|
||
else:
|
||
# Try via entry point script
|
||
import shutil
|
||
lg = shutil.which("langgraph")
|
||
if lg:
|
||
r2 = subprocess.run([lg, "--version"], capture_output=True, text=True, timeout=10)
|
||
if r2.returncode == 0:
|
||
print(f"[OK] langgraph dev CLI OK: {r2.stdout.strip()}")
|
||
else:
|
||
print(f"[WARN] langgraph CLI found but --version failed: {r2.stderr.strip()}")
|
||
else:
|
||
print("[FAIL] langgraph CLI not found on PATH — install: pip install 'langgraph-cli[inmem]'")
|
||
ok = False
|
||
except Exception as e:
|
||
print(f"[FAIL] langgraph CLI check error: {e}")
|
||
ok = False
|
||
|
||
return ok
|
||
|
||
|
||
def test_vivado():
|
||
config_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "env_config.json")
|
||
env = os.environ.copy()
|
||
vivado_bin = ""
|
||
|
||
if os.path.exists(config_path):
|
||
with open(config_path, encoding="utf-8") as f:
|
||
config = json.load(f)
|
||
vivado_bin = config.get("VIVADO_BIN_PATH", "").strip()
|
||
if vivado_bin:
|
||
env["PATH"] = vivado_bin + os.pathsep + env["PATH"]
|
||
|
||
# On Windows use the full path to vivado.bat to avoid shell PATH issues
|
||
if vivado_bin and (os.name == "nt" or sys.platform == "win32"):
|
||
cmd = [os.path.join(vivado_bin, "vivado.bat"), "-version"]
|
||
else:
|
||
cmd = ["vivado", "-version"]
|
||
|
||
try:
|
||
result = subprocess.run(cmd, capture_output=True, text=True, timeout=30, env=env)
|
||
if result.returncode == 0:
|
||
first_line = (result.stdout.strip().splitlines() or ["(no output)"])[0]
|
||
print(f"[OK] Vivado detected: {first_line}")
|
||
return True
|
||
else:
|
||
print(f"[FAIL] vivado -version non-zero exit: {result.stderr.strip()}")
|
||
return False
|
||
except FileNotFoundError:
|
||
print(f"[FAIL] vivado not found. CMD tried: {cmd}")
|
||
return False
|
||
except subprocess.TimeoutExpired:
|
||
print("[FAIL] vivado -version timed out (30s)")
|
||
return False
|
||
|
||
|
||
if __name__ == "__main__":
|
||
print("=" * 50)
|
||
print("LangGraph + Vivado smoke test")
|
||
print("=" * 50)
|
||
ok_lg = test_langgraph()
|
||
print("-" * 50)
|
||
print("langgraph-plan-review deps:")
|
||
ok_pr = test_langgraph_plan_review_deps()
|
||
print("-" * 50)
|
||
ok_vv = test_vivado()
|
||
print("=" * 50)
|
||
if ok_lg and ok_pr and ok_vv:
|
||
print("[PASS] All checks passed. LangGraph + Vivado + plan-review pipeline OK!")
|
||
sys.exit(0)
|
||
else:
|
||
print("[FAIL] Some checks failed. See above.")
|
||
sys.exit(1)
|
||
```
|
||
|
||
### 运行冒烟测试
|
||
```bash
|
||
conda run -n langgraph python smoke_test.py
|
||
```
|
||
|
||
- **全部通过**:向用户报告"环境配置完成,LangGraph + Vivado 链路闭环成功。"
|
||
- **有失败项**:读取具体错误,向用户说明原因(路径问题、包未安装等),并提供修复建议。
|
||
|
||
---
|
||
|
||
## 注意事项
|
||
|
||
- Windows 路径转换规则:`C:\Xilinx\Vivado\2023.2\bin` → `/c/Xilinx/Vivado/2023.2/bin`(首字母小写,冒号去掉,反斜杠换正斜杠)。
|
||
- `conda run -n langgraph vivado -version` 需要 PATH 在 conda 激活前已包含 Vivado bin 目录,若不行则用 `export PATH=... && conda run ...` 形式或直接用绝对路径调用。
|
||
- 本技能产生的文件:`env_config.json`、`smoke_test.py`(均在调用时的当前目录)。
|