From b094cb85cd2c721d140095665a9ccf09768dff6f Mon Sep 17 00:00:00 2001 From: Joywayer Date: Fri, 29 May 2026 09:03:13 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20rust?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/copilot-instructions.md | 2 +- claude-dev-stack/.env | 43 +++++++++++++++++++++++++++++++++ windows-dev-stack/deploy.ps1 | 36 ++++++++++++++++++--------- 3 files changed, 68 insertions(+), 13 deletions(-) create mode 100644 claude-dev-stack/.env diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 9609411..54ae7d5 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -24,4 +24,4 @@ rtk gain --history # Per-command savings history rtk discover # Find missed rtk opportunities rtk proxy # Run raw (no filtering) but track usage ``` - + \ No newline at end of file diff --git a/claude-dev-stack/.env b/claude-dev-stack/.env new file mode 100644 index 0000000..6632a6f --- /dev/null +++ b/claude-dev-stack/.env @@ -0,0 +1,43 @@ +# ============================================================= +# Claude Dev Stack 配置文件 +# 复制为 .env 并按需填写 +# ============================================================= + +# ── Claude / API 配置 ──────────────────────────────────────── +# 推荐:灵眸 AI(国内直连,无需代理)https://docs.lmuai.com/docs/tools/claude-code +ANTHROPIC_AUTH_TOKEN=sk-ccaf8169bce7c735dfa1f021ec326b3904842dfd50e1ae817c3417017e0d8ee0 +ANTHROPIC_BASE_URL=https://api.lmuai.com + +# 备选:Anthropic 官方 API Key(海外直连) +# ANTHROPIC_API_KEY= +# ANTHROPIC_BASE_URL=https://api.anthropic.com + +# 备选:DeepSeek 兼容接口 +# ANTHROPIC_API_KEY= +# ANTHROPIC_BASE_URL=https://api.deepseek.com/anthropic + +# 默认使用的模型 +# 灵眸可选:claude-opus-4-7 | claude-sonnet-4-6 | claude-sonnet-4-5 | claude-haiku-4-5 +# DeepSeek可选:deepseek-v4-pro +CLAUDE_MODEL=claude-sonnet-4-6 + +# ── WSL2 ──────────────────────────────────────────────────── +# WSL2 发行版名称(wsl --list 查看已安装发行版) +WSL_DISTRO=Ubuntu + +# 设为 true 可跳过 WSL2 安装步骤(已安装时使用) +SKIP_WSL_INSTALL=false + +# ── Unity MCP ─────────────────────────────────────────────── +# unity-mcp-server 自动克隆至 WSL2 ~/.mcp-servers/unity-mcp-server/ +# Unity Plugin 需手动通过 Package Manager 安装: +# https://github.com/AnkleBreaker-Studio/unity-mcp-plugin.git +# (无需额外配置) + +# ── Rust / Token Killer ────────────────────────────────────── +# (暂无需配置,预留扩展用) +# CARGO_REGISTRY_MIRROR=https://rsproxy.cn/ + +# ── Docker 镜像加速(可选)────────────────────────────────── +# 若 WSL2 内需要 Docker,可配置国内加速镜像(逗号分隔) +# DOCKER_REGISTRY_MIRRORS=https://docker.m.daocloud.io,https://hub-mirror.c.163.com diff --git a/windows-dev-stack/deploy.ps1 b/windows-dev-stack/deploy.ps1 index 8a0efb5..95ab49a 100644 --- a/windows-dev-stack/deploy.ps1 +++ b/windows-dev-stack/deploy.ps1 @@ -103,13 +103,18 @@ function Refresh-Path { # ────────────────────────────────────────────────────────────── function Install-Winget { param([string]$Id, [string]$DisplayName) - $wg = Get-Command winget -ErrorAction SilentlyContinue - if (-not $wg) { + # pwsh (Core) 里 winget 不在 PATH,尝试固定路径 + $wgPath = (Get-Command winget -ErrorAction SilentlyContinue)?.Source + if (-not $wgPath) { + $wgPath = "$env:LOCALAPPDATA\Microsoft\WindowsApps\winget.exe" + if (-not (Test-Path $wgPath)) { $wgPath = $null } + } + if (-not $wgPath) { Write-Warn "未找到 winget,请手动安装 $DisplayName" return $false } Write-Info "winget install $Id ..." - winget install --id $Id --silent --accept-source-agreements --accept-package-agreements 2>&1 | Out-Null + & $wgPath install --id $Id --silent --accept-source-agreements --accept-package-agreements 2>&1 | Out-Null Refresh-Path return $true } @@ -576,7 +581,12 @@ if ($cargoCmd) { Write-OK "Rust 已安装: $($rustcVer.Trim())" } else { # 检查 winget 是否已记录安装(避免重复安装时阻塞) - $wgList = winget list --id Rustlang.Rustup --accept-source-agreements 2>&1 | Out-String + $wgPath = (Get-Command winget -ErrorAction SilentlyContinue)?.Source + if (-not $wgPath) { + $fallback = "$env:LOCALAPPDATA\Microsoft\WindowsApps\winget.exe" + if (Test-Path $fallback) { $wgPath = $fallback } + } + $wgList = if ($wgPath) { & $wgPath list --id Rustlang.Rustup --accept-source-agreements 2>&1 | Out-String } else { "" } if ($wgList -match "Rustlang.Rustup") { Write-Info "rustup 已安装,但当前会话 PATH 未更新。已将 $cargoBin 加入 PATH" # rustup 首次运行会初始化 stable 工具链 @@ -586,14 +596,16 @@ if ($cargoCmd) { } else { Write-Info "通过 winget 安装 Rust (rustup)..." $ok = Install-Winget "Rustlang.Rustup" "Rustup" - if (Test-Path $cargoBin) { $env:Path = "$cargoBin;$env:Path" } - Refresh-Path - $cargoCmd = Get-Command cargo -ErrorAction SilentlyContinue - if ($cargoCmd) { - Write-OK "Rust 安装完成: $(& rustc --version 2>&1)" - } else { - Write-Warn "Rust 安装后未找到 cargo,请关闭并重开终端后继续" - Write-Warn " 或手动安装:https://rustup.rs" + if ($ok) { + if (Test-Path $cargoBin) { $env:Path = "$cargoBin;$env:Path" } + Refresh-Path + $cargoCmd = Get-Command cargo -ErrorAction SilentlyContinue + if ($cargoCmd) { + Write-OK "Rust 安装完成: $(& rustc --version 2>&1)" + } else { + Write-Warn "Rust 安装后未找到 cargo,请关闭并重开终端后继续" + Write-Warn " 或手动安装:https://rustup.rs" + } } } } From be82a4eb7098fa2088026ee3e49dc110d4edfcfa Mon Sep 17 00:00:00 2001 From: Joywayer Date: Fri, 29 May 2026 09:22:34 +0800 Subject: [PATCH 2/2] copilot mcp --- windows-dev-stack/README.md | 12 ++++----- windows-dev-stack/deploy.ps1 | 48 ++++++++++++++++++++++++++++++++++-- 2 files changed, 52 insertions(+), 8 deletions(-) diff --git a/windows-dev-stack/README.md b/windows-dev-stack/README.md index 3ed8828..85c57af 100644 --- a/windows-dev-stack/README.md +++ b/windows-dev-stack/README.md @@ -85,12 +85,12 @@ gh auth login `deploy.ps1` 自动写入以下客户端的 MCP 配置: -| 客户端 | 配置文件 | -|--------|---------| -| Claude Desktop | `%APPDATA%\Claude\claude_desktop_config.json` | -| Cursor | `%USERPROFILE%\.cursor\mcp.json` | -| Windsurf | `%APPDATA%\Windsurf\mcp_config.json` | -| VS Code | `%APPDATA%\Code\User\mcp.json` | +| 客户端 | 配置文件 / 方式 | +|--------|----------------| +| Claude Desktop | `%APPDATA%\Claude\claude_desktop_config.json`(`mcpServers` 格式) | +| Cursor | `%USERPROFILE%\.cursor\mcp.json`(`mcpServers` 格式) | +| Windsurf | `%APPDATA%\Windsurf\mcp_config.json`(`mcpServers` 格式) | +| **VS Code Copilot Agent** | `%APPDATA%\Code\User\settings.json` → `mcp.servers`(VS Code 专用格式) | | Claude Code CLI | `claude mcp add --scope user`(写入用户级 MCP) | --- diff --git a/windows-dev-stack/deploy.ps1 b/windows-dev-stack/deploy.ps1 index 95ab49a..a5106e1 100644 --- a/windows-dev-stack/deploy.ps1 +++ b/windows-dev-stack/deploy.ps1 @@ -155,6 +155,50 @@ function Merge-McpConfig { Write-OK "$Label -> $ConfigFile" } +# ────────────────────────────────────────────────────────────── +# 辅助:写入 VS Code settings.json 中的 mcp.servers(VS Code 专用格式) +# VS Code Copilot Agent 读取 settings.json -> "mcp" -> "servers" +# 而非 mcp.json 中的 "mcpServers"(那是 Claude Desktop / Cursor 格式) +# ────────────────────────────────────────────────────────────── +function Merge-VsCodeMcpSettings { + param( + [string] $ServerName, + [hashtable] $Entry, + [string] $Label + ) + $settingsFile = "$env:APPDATA\Code\User\settings.json" + $dir = Split-Path $settingsFile + if (-not (Test-Path $dir)) { New-Item -ItemType Directory -Path $dir -Force | Out-Null } + + function ConvertTo-OrderedHashtable($obj) { + if ($obj -is [System.Management.Automation.PSCustomObject]) { + $h = [ordered]@{} + foreach ($p in $obj.PSObject.Properties) { $h[$p.Name] = ConvertTo-OrderedHashtable $p.Value } + return $h + } elseif ($obj -is [System.Collections.IEnumerable] -and $obj -isnot [string]) { + return @($obj | ForEach-Object { ConvertTo-OrderedHashtable $_ }) + } + return $obj + } + + $cfg = [ordered]@{} + if (Test-Path $settingsFile) { + try { + $raw = Get-Content $settingsFile -Raw | ConvertFrom-Json + $cfg = ConvertTo-OrderedHashtable $raw + } catch { + Write-Warn "settings.json 解析失败,将新建 mcp 节点:$_" + } + } + + if (-not $cfg.ContainsKey("mcp")) { $cfg["mcp"] = [ordered]@{} } + if (-not $cfg["mcp"].ContainsKey("servers")) { $cfg["mcp"]["servers"] = [ordered]@{} } + $cfg["mcp"]["servers"][$ServerName] = $Entry + + $cfg | ConvertTo-Json -Depth 15 | Set-Content $settingsFile -Encoding UTF8 + Write-OK "$Label -> $settingsFile [mcp.servers.$ServerName]" +} + # ══════════════════════════════════════════════════════════════ # Step 1: Node.js LTS # ══════════════════════════════════════════════════════════════ @@ -450,7 +494,7 @@ if ($unityEntry) { Merge-McpConfig "$env:USERPROFILE\.cursor\mcp.json" $unityMcpEntry "Cursor" $wsDirC = if (Test-Path "$env:APPDATA\Windsurf") { "$env:APPDATA\Windsurf" } else { "$env:USERPROFILE\.codeium\windsurf" } Merge-McpConfig "$wsDirC\mcp_config.json" $unityMcpEntry "Windsurf" - Merge-McpConfig "$env:APPDATA\Code\User\mcp.json" $unityMcpEntry "VS Code" + Merge-VsCodeMcpSettings "unity-mcp" $unityMcpEntry "VS Code Copilot Agent (Unity MCP)" # Claude Code CLI(Windows) if (Get-Command claude -ErrorAction SilentlyContinue) { & claude mcp remove unity-mcp --scope user 2>&1 | Out-Null @@ -498,7 +542,7 @@ if (-not (Test-Path $godotSrcDir)) { Merge-McpConfig "$env:USERPROFILE\.cursor\mcp.json" $godotMcpEntry "Cursor (Godot)" "godot-mcp-pro" $wsDirG = if (Test-Path "$env:APPDATA\Windsurf") { "$env:APPDATA\Windsurf" } else { "$env:USERPROFILE\.codeium\windsurf" } Merge-McpConfig "$wsDirG\mcp_config.json" $godotMcpEntry "Windsurf (Godot)" "godot-mcp-pro" - Merge-McpConfig "$env:APPDATA\Code\User\mcp.json" $godotMcpEntry "VS Code (Godot)" "godot-mcp-pro" + Merge-VsCodeMcpSettings "godot-mcp-pro" $godotMcpEntry "VS Code Copilot Agent (Godot MCP Pro)" if (Get-Command claude -ErrorAction SilentlyContinue) { & claude mcp remove godot-mcp-pro --scope user 2>&1 | Out-Null & claude mcp add --scope user godot-mcp-pro node $godotEntry 2>&1 | Out-Null