From b2e58a1bb7d9b3c0391453b6b989f6cf50847a5d Mon Sep 17 00:00:00 2001 From: octo-patch Date: Thu, 9 Apr 2026 06:46:56 +0800 Subject: [PATCH 1/6] feat: add MiniMax-M2.7 as default model and update API endpoint - Add MiniMax-M2.7 as the recommended default chat model - Add MiniMax-M2.7-highspeed as a faster alternative - Update base URL to api.minimax.io (international) with note about api.minimaxi.com for China - Add model comparison table in documentation (both CN and EN) - Add API key registration link to MiniMax Open Platform --- .env.example | 13 ++++++++----- docs/en/guide/third-party-models.md | 20 +++++++++++++++----- docs/guide/third-party-models.md | 20 +++++++++++++++----- 3 files changed, 38 insertions(+), 15 deletions(-) diff --git a/.env.example b/.env.example index 99f367cc..c0007f24 100644 --- a/.env.example +++ b/.env.example @@ -1,12 +1,15 @@ # ============================================================ # MiniMax(直连 Anthropic 兼容接口) +# 海外用户: ANTHROPIC_BASE_URL=https://api.minimax.io/anthropic +# 国内用户: ANTHROPIC_BASE_URL=https://api.minimaxi.com/anthropic +# 可用模型: MiniMax-M2.7(默认)、MiniMax-M2.7-highspeed(更快) # ============================================================ -# ANTHROPIC_AUTH_TOKEN=your_token_here -# ANTHROPIC_BASE_URL=https://api.minimaxi.com/anthropic -# ANTHROPIC_MODEL=MiniMax-M2.7-highspeed -# ANTHROPIC_DEFAULT_SONNET_MODEL=MiniMax-M2.7-highspeed +# ANTHROPIC_AUTH_TOKEN=your_minimax_api_key_here +# ANTHROPIC_BASE_URL=https://api.minimax.io/anthropic +# ANTHROPIC_MODEL=MiniMax-M2.7 +# ANTHROPIC_DEFAULT_SONNET_MODEL=MiniMax-M2.7 # ANTHROPIC_DEFAULT_HAIKU_MODEL=MiniMax-M2.7-highspeed -# ANTHROPIC_DEFAULT_OPUS_MODEL=MiniMax-M2.7-highspeed +# ANTHROPIC_DEFAULT_OPUS_MODEL=MiniMax-M2.7 # API_TIMEOUT_MS=3000000 # ============================================================ diff --git a/docs/en/guide/third-party-models.md b/docs/en/guide/third-party-models.md index 66416c50..7cb3b3fb 100644 --- a/docs/en/guide/third-party-models.md +++ b/docs/en/guide/third-party-models.md @@ -172,18 +172,28 @@ CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 ### MiniMax (pre-configured in .env.example) +MiniMax provides an Anthropic-compatible API endpoint and can be connected directly without any proxy. Available models: + +| Model | Description | +|-------|-------------| +| `MiniMax-M2.7` | Default recommended, excellent overall performance | +| `MiniMax-M2.7-highspeed` | Faster responses, suitable for latency-sensitive use cases | + ```env -ANTHROPIC_AUTH_TOKEN=your_token_here -ANTHROPIC_BASE_URL=https://api.minimaxi.com/anthropic -ANTHROPIC_MODEL=MiniMax-M2.7-highspeed -ANTHROPIC_DEFAULT_SONNET_MODEL=MiniMax-M2.7-highspeed +ANTHROPIC_AUTH_TOKEN=your_minimax_api_key_here +# International users: api.minimax.io; China users may use api.minimaxi.com +ANTHROPIC_BASE_URL=https://api.minimax.io/anthropic +ANTHROPIC_MODEL=MiniMax-M2.7 +ANTHROPIC_DEFAULT_SONNET_MODEL=MiniMax-M2.7 ANTHROPIC_DEFAULT_HAIKU_MODEL=MiniMax-M2.7-highspeed -ANTHROPIC_DEFAULT_OPUS_MODEL=MiniMax-M2.7-highspeed +ANTHROPIC_DEFAULT_OPUS_MODEL=MiniMax-M2.7 API_TIMEOUT_MS=3000000 DISABLE_TELEMETRY=1 CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 ``` +> **Get API Key**: Visit [MiniMax Open Platform](https://platform.minimax.io) to register and obtain an API key. + --- ## Option 3: Other Proxy Tools diff --git a/docs/guide/third-party-models.md b/docs/guide/third-party-models.md index 1bc746a6..93b6ccdc 100644 --- a/docs/guide/third-party-models.md +++ b/docs/guide/third-party-models.md @@ -172,18 +172,28 @@ CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 ### MiniMax(已在 .env.example 中配置) +MiniMax 提供 Anthropic 兼容接口,支持直接接入,无需代理。可用模型: + +| 模型 | 说明 | +|------|------| +| `MiniMax-M2.7` | 默认推荐,综合性能优秀 | +| `MiniMax-M2.7-highspeed` | 响应更快,适合对速度有要求的场景 | + ```env -ANTHROPIC_AUTH_TOKEN=your_token_here -ANTHROPIC_BASE_URL=https://api.minimaxi.com/anthropic -ANTHROPIC_MODEL=MiniMax-M2.7-highspeed -ANTHROPIC_DEFAULT_SONNET_MODEL=MiniMax-M2.7-highspeed +ANTHROPIC_AUTH_TOKEN=your_minimax_api_key_here +# 海外用户使用 api.minimax.io,国内用户可改为 api.minimaxi.com +ANTHROPIC_BASE_URL=https://api.minimax.io/anthropic +ANTHROPIC_MODEL=MiniMax-M2.7 +ANTHROPIC_DEFAULT_SONNET_MODEL=MiniMax-M2.7 ANTHROPIC_DEFAULT_HAIKU_MODEL=MiniMax-M2.7-highspeed -ANTHROPIC_DEFAULT_OPUS_MODEL=MiniMax-M2.7-highspeed +ANTHROPIC_DEFAULT_OPUS_MODEL=MiniMax-M2.7 API_TIMEOUT_MS=3000000 DISABLE_TELEMETRY=1 CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 ``` +> **获取 API Key**:访问 [MiniMax 开放平台](https://platform.minimax.io) 注册并获取 API Key。 + --- ## 方式三:其他代理工具 From a143477969b70caa162de7d80dedb07859d0a70f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E5=91=98=E9=98=BF=E6=B1=9F=28Relakkes?= =?UTF-8?q?=29?= Date: Wed, 15 Apr 2026 21:54:44 +0800 Subject: [PATCH 2/6] =?UTF-8?q?ci(desktop):=20=E6=B7=BB=E5=8A=A0=E5=BC=80?= =?UTF-8?q?=E5=8F=91=E9=98=B6=E6=AE=B5=E6=A1=8C=E9=9D=A2=E7=AB=AF=E6=9E=84?= =?UTF-8?q?=E5=BB=BA=20workflow?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 支持在任意分支手动触发构建,产物上传为 GitHub Artifact 供下载测试。 Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/build-desktop-dev.yml | 201 ++++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 .github/workflows/build-desktop-dev.yml diff --git a/.github/workflows/build-desktop-dev.yml b/.github/workflows/build-desktop-dev.yml new file mode 100644 index 00000000..2d631ec1 --- /dev/null +++ b/.github/workflows/build-desktop-dev.yml @@ -0,0 +1,201 @@ +name: Build Desktop (Dev) + +# 开发阶段构建 — 不创建 Release,只上传 Artifacts 供下载测试 +on: + workflow_dispatch: + inputs: + platforms: + description: 'Build platforms' + required: true + default: 'all' + type: choice + options: + - all + - macos-arm64 + - macos-x64 + - windows-x64 + - linux-x64 + - linux-arm64 + +permissions: + contents: read + +concurrency: + group: build-desktop-dev-${{ github.ref }} + cancel-in-progress: true + +jobs: + # ── 动态生成构建矩阵 ────────────────────────────────────── + prepare: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.set-matrix.outputs.matrix }} + steps: + - id: set-matrix + run: | + ALL='[ + {"platform":"macos-latest","rust_target":"aarch64-apple-darwin","tauri_args":"--target aarch64-apple-darwin","bundles":"app,dmg","label":"macOS-ARM64","artifact_name":"desktop-macos-arm64","artifact_glob":"*.dmg"}, + {"platform":"macos-latest","rust_target":"x86_64-apple-darwin","tauri_args":"--target x86_64-apple-darwin","bundles":"app,dmg","label":"macOS-x64","artifact_name":"desktop-macos-x64","artifact_glob":"*.dmg"}, + {"platform":"windows-latest","rust_target":"x86_64-pc-windows-msvc","tauri_args":"","bundles":"nsis,msi","label":"Windows-x64","artifact_name":"desktop-windows-x64","artifact_glob":"*.exe"}, + {"platform":"ubuntu-22.04","rust_target":"x86_64-unknown-linux-gnu","tauri_args":"","bundles":"deb,appimage","label":"Linux-x64","artifact_name":"desktop-linux-x64","artifact_glob":"*.deb"}, + {"platform":"ubuntu-22.04-arm","rust_target":"aarch64-unknown-linux-gnu","tauri_args":"","bundles":"deb,appimage","label":"Linux-ARM64","artifact_name":"desktop-linux-arm64","artifact_glob":"*.deb"} + ]' + + SELECTED="${{ inputs.platforms }}" + if [ "$SELECTED" = "all" ]; then + echo "matrix={\"include\":$ALL}" >> "$GITHUB_OUTPUT" + else + echo "$ALL" | jq -c --arg sel "$SELECTED" \ + '{include: [.[] | select( + ($sel == "macos-arm64" and .label == "macOS-ARM64") or + ($sel == "macos-x64" and .label == "macOS-x64") or + ($sel == "windows-x64" and .label == "Windows-x64") or + ($sel == "linux-x64" and .label == "Linux-x64") or + ($sel == "linux-arm64" and .label == "Linux-ARM64") + )]}' >> "$GITHUB_OUTPUT" + fi + + # ── 构建 ──────────────────────────────────────────────────── + build: + needs: prepare + strategy: + fail-fast: false + matrix: ${{ fromJson(needs.prepare.outputs.matrix) }} + + runs-on: ${{ matrix.platform }} + name: Build (${{ matrix.label }}) + + steps: + - name: Checkout + uses: actions/checkout@v4 + + # ── 系统依赖 (Linux) ───────────────────────────────────── + - name: Install Linux dependencies + if: contains(matrix.platform, 'ubuntu') + run: | + sudo apt-get update + sudo apt-get install -y \ + build-essential curl wget file \ + libxdo-dev libssl-dev \ + libwebkit2gtk-4.1-dev \ + libayatana-appindicator3-dev \ + librsvg2-dev patchelf + + # ── Bun ────────────────────────────────────────────────── + - name: Setup Bun + uses: oven-sh/setup-bun@v2 + with: + bun-version: latest + + # ── Node.js ────────────────────────────────────────────── + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + + # ── Rust ───────────────────────────────────────────────── + - name: Setup Rust + uses: dtolnay/rust-toolchain@stable + with: + targets: ${{ matrix.rust_target }} + + - name: Rust cache + uses: swatinem/rust-cache@v2 + with: + workspaces: 'desktop/src-tauri -> target' + shared-key: ${{ matrix.rust_target }} + + # ── 安装依赖 ───────────────────────────────────────────── + - name: Install root dependencies + run: bun install + + - name: Install desktop dependencies + working-directory: desktop + run: bun install + + # ── 构建 sidecars ──────────────────────────────────────── + - name: Build sidecars + working-directory: desktop + env: + TAURI_ENV_TARGET_TRIPLE: ${{ matrix.rust_target }} + run: bun run build:sidecars + + # ── 构建 Tauri (无签名、无 updater) ────────────────────── + - name: Build Tauri app + working-directory: desktop + env: + TAURI_ENV_TARGET_TRIPLE: ${{ matrix.rust_target }} + run: | + # 开发构建: 禁用 updater artifacts (不需要签名密钥) + echo '{"bundle":{"createUpdaterArtifacts":false}}' > /tmp/dev-build.json + + ARGS=(bunx tauri build --bundles ${{ matrix.bundles }} --ci --config /tmp/dev-build.json) + + if [ -n "${{ matrix.tauri_args }}" ]; then + ARGS+=(${{ matrix.tauri_args }}) + fi + + "${ARGS[@]}" + shell: bash + + # ── 收集产物 ───────────────────────────────────────────── + - name: Collect artifacts + id: collect + shell: bash + run: | + BUNDLE_DIR="desktop/src-tauri/target/${{ matrix.rust_target }}/release/bundle" + FALLBACK_DIR="desktop/src-tauri/target/release/bundle" + + # 优先使用带 target 的路径 + if [ -d "$BUNDLE_DIR" ]; then + SEARCH_DIR="$BUNDLE_DIR" + else + SEARCH_DIR="$FALLBACK_DIR" + fi + + STAGING="desktop/build-artifacts/ci-${{ matrix.artifact_name }}" + mkdir -p "$STAGING" + + echo "Searching for artifacts in: $SEARCH_DIR" + if [ -d "$SEARCH_DIR" ]; then + find "$SEARCH_DIR" -type f \( \ + -name "*.dmg" -o -name "*.app" -o \ + -name "*.exe" -o -name "*.msi" -o \ + -name "*.deb" -o -name "*.AppImage" -o \ + -name "*.zip" \ + \) | while read -r f; do + echo " Copying: $(basename "$f")" + cp "$f" "$STAGING/" + done + fi + + echo "staging_dir=$STAGING" >> "$GITHUB_OUTPUT" + echo "=== Collected artifacts ===" + ls -lh "$STAGING/" 2>/dev/null || echo "(empty)" + + # ── 上传为 GitHub Artifact ─────────────────────────────── + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.artifact_name }} + path: ${{ steps.collect.outputs.staging_dir }} + retention-days: 7 + if-no-files-found: warn + + # ── 构建完成汇总 ──────────────────────────────────────────── + summary: + needs: build + runs-on: ubuntu-latest + if: always() + steps: + - name: Build summary + run: | + echo "## Desktop Dev Build Summary" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "| Platform | Status |" >> $GITHUB_STEP_SUMMARY + echo "|----------|--------|" >> $GITHUB_STEP_SUMMARY + echo "Branch: \`${{ github.ref_name }}\`" >> $GITHUB_STEP_SUMMARY + echo "Commit: \`${{ github.sha }}\`" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "📦 Artifacts are available for download from the **Artifacts** section above." >> $GITHUB_STEP_SUMMARY + echo "Artifacts will be retained for **7 days**." >> $GITHUB_STEP_SUMMARY From 5b2c4142775d841c83df5b11aa53020647b4d132 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E5=91=98=E9=98=BF=E6=B1=9F=28Relakkes?= =?UTF-8?q?=29?= Date: Wed, 15 Apr 2026 21:57:03 +0800 Subject: [PATCH 3/6] =?UTF-8?q?fix(ci):=20=E4=BF=AE=E5=A4=8D=20dev=20?= =?UTF-8?q?=E6=9E=84=E5=BB=BA=20workflow=20=E7=9F=A9=E9=98=B5=20JSON=20?= =?UTF-8?q?=E8=BE=93=E5=87=BA=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 多行 JSON 写入 GITHUB_OUTPUT 不被支持,改为用 jq -c 压缩成单行输出。 Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/build-desktop-dev.yml | 26 ++++++++++--------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/.github/workflows/build-desktop-dev.yml b/.github/workflows/build-desktop-dev.yml index 2d631ec1..54a08c0d 100644 --- a/.github/workflows/build-desktop-dev.yml +++ b/.github/workflows/build-desktop-dev.yml @@ -33,27 +33,21 @@ jobs: steps: - id: set-matrix run: | - ALL='[ - {"platform":"macos-latest","rust_target":"aarch64-apple-darwin","tauri_args":"--target aarch64-apple-darwin","bundles":"app,dmg","label":"macOS-ARM64","artifact_name":"desktop-macos-arm64","artifact_glob":"*.dmg"}, - {"platform":"macos-latest","rust_target":"x86_64-apple-darwin","tauri_args":"--target x86_64-apple-darwin","bundles":"app,dmg","label":"macOS-x64","artifact_name":"desktop-macos-x64","artifact_glob":"*.dmg"}, - {"platform":"windows-latest","rust_target":"x86_64-pc-windows-msvc","tauri_args":"","bundles":"nsis,msi","label":"Windows-x64","artifact_name":"desktop-windows-x64","artifact_glob":"*.exe"}, - {"platform":"ubuntu-22.04","rust_target":"x86_64-unknown-linux-gnu","tauri_args":"","bundles":"deb,appimage","label":"Linux-x64","artifact_name":"desktop-linux-x64","artifact_glob":"*.deb"}, - {"platform":"ubuntu-22.04-arm","rust_target":"aarch64-unknown-linux-gnu","tauri_args":"","bundles":"deb,appimage","label":"Linux-ARM64","artifact_name":"desktop-linux-arm64","artifact_glob":"*.deb"} - ]' + ALL='[{"platform":"macos-latest","rust_target":"aarch64-apple-darwin","tauri_args":"--target aarch64-apple-darwin","bundles":"app,dmg","label":"macOS-ARM64","artifact_name":"desktop-macos-arm64"},{"platform":"macos-latest","rust_target":"x86_64-apple-darwin","tauri_args":"--target x86_64-apple-darwin","bundles":"app,dmg","label":"macOS-x64","artifact_name":"desktop-macos-x64"},{"platform":"windows-latest","rust_target":"x86_64-pc-windows-msvc","tauri_args":"","bundles":"nsis,msi","label":"Windows-x64","artifact_name":"desktop-windows-x64"},{"platform":"ubuntu-22.04","rust_target":"x86_64-unknown-linux-gnu","tauri_args":"","bundles":"deb,appimage","label":"Linux-x64","artifact_name":"desktop-linux-x64"},{"platform":"ubuntu-22.04-arm","rust_target":"aarch64-unknown-linux-gnu","tauri_args":"","bundles":"deb,appimage","label":"Linux-ARM64","artifact_name":"desktop-linux-arm64"}]' SELECTED="${{ inputs.platforms }}" if [ "$SELECTED" = "all" ]; then - echo "matrix={\"include\":$ALL}" >> "$GITHUB_OUTPUT" + MATRIX=$(echo "$ALL" | jq -c '{include: .}') else - echo "$ALL" | jq -c --arg sel "$SELECTED" \ - '{include: [.[] | select( - ($sel == "macos-arm64" and .label == "macOS-ARM64") or - ($sel == "macos-x64" and .label == "macOS-x64") or - ($sel == "windows-x64" and .label == "Windows-x64") or - ($sel == "linux-x64" and .label == "Linux-x64") or - ($sel == "linux-arm64" and .label == "Linux-ARM64") - )]}' >> "$GITHUB_OUTPUT" + MATRIX=$(echo "$ALL" | jq -c --arg sel "$SELECTED" '{include: [.[] | select( + ($sel == "macos-arm64" and .label == "macOS-ARM64") or + ($sel == "macos-x64" and .label == "macOS-x64") or + ($sel == "windows-x64" and .label == "Windows-x64") or + ($sel == "linux-x64" and .label == "Linux-x64") or + ($sel == "linux-arm64" and .label == "Linux-ARM64") + )]}') fi + echo "matrix=$MATRIX" >> "$GITHUB_OUTPUT" # ── 构建 ──────────────────────────────────────────────────── build: From da95101aa728dce13bc39f858853180179f74aa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E5=91=98=E9=98=BF=E6=B1=9F=28Relakkes?= =?UTF-8?q?=29?= Date: Wed, 15 Apr 2026 22:16:09 +0800 Subject: [PATCH 4/6] =?UTF-8?q?fix(ci):=20=E8=A1=A5=E5=85=85=20dev=20?= =?UTF-8?q?=E6=9E=84=E5=BB=BA=20workflow=20=E7=9A=84=20adapters=20?= =?UTF-8?q?=E4=BE=9D=E8=B5=96=E5=AE=89=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/build-desktop-dev.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/build-desktop-dev.yml b/.github/workflows/build-desktop-dev.yml index 54a08c0d..9f42664c 100644 --- a/.github/workflows/build-desktop-dev.yml +++ b/.github/workflows/build-desktop-dev.yml @@ -107,6 +107,10 @@ jobs: working-directory: desktop run: bun install + - name: Install adapter dependencies + working-directory: adapters + run: bun install + # ── 构建 sidecars ──────────────────────────────────────── - name: Build sidecars working-directory: desktop From abf8e3f141149a6e79dfec7a2185b8bc2de6b0ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E5=91=98=E9=98=BF=E6=B1=9F=28Relakkes?= =?UTF-8?q?=29?= Date: Wed, 15 Apr 2026 22:40:32 +0800 Subject: [PATCH 5/6] =?UTF-8?q?fix(ci):=20artifact=20=E5=90=8D=E7=A7=B0?= =?UTF-8?q?=E5=8A=A0=E4=B8=8A=E4=BA=A7=E5=93=81=E5=90=8D=E5=92=8C=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/build-desktop-dev.yml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-desktop-dev.yml b/.github/workflows/build-desktop-dev.yml index 9f42664c..3fa0d949 100644 --- a/.github/workflows/build-desktop-dev.yml +++ b/.github/workflows/build-desktop-dev.yml @@ -33,7 +33,7 @@ jobs: steps: - id: set-matrix run: | - ALL='[{"platform":"macos-latest","rust_target":"aarch64-apple-darwin","tauri_args":"--target aarch64-apple-darwin","bundles":"app,dmg","label":"macOS-ARM64","artifact_name":"desktop-macos-arm64"},{"platform":"macos-latest","rust_target":"x86_64-apple-darwin","tauri_args":"--target x86_64-apple-darwin","bundles":"app,dmg","label":"macOS-x64","artifact_name":"desktop-macos-x64"},{"platform":"windows-latest","rust_target":"x86_64-pc-windows-msvc","tauri_args":"","bundles":"nsis,msi","label":"Windows-x64","artifact_name":"desktop-windows-x64"},{"platform":"ubuntu-22.04","rust_target":"x86_64-unknown-linux-gnu","tauri_args":"","bundles":"deb,appimage","label":"Linux-x64","artifact_name":"desktop-linux-x64"},{"platform":"ubuntu-22.04-arm","rust_target":"aarch64-unknown-linux-gnu","tauri_args":"","bundles":"deb,appimage","label":"Linux-ARM64","artifact_name":"desktop-linux-arm64"}]' + ALL='[{"platform":"macos-latest","rust_target":"aarch64-apple-darwin","tauri_args":"--target aarch64-apple-darwin","bundles":"app,dmg","label":"macOS-ARM64","artifact_name":"macos-arm64"},{"platform":"macos-latest","rust_target":"x86_64-apple-darwin","tauri_args":"--target x86_64-apple-darwin","bundles":"app,dmg","label":"macOS-x64","artifact_name":"macos-x64"},{"platform":"windows-latest","rust_target":"x86_64-pc-windows-msvc","tauri_args":"","bundles":"nsis,msi","label":"Windows-x64","artifact_name":"windows-x64"},{"platform":"ubuntu-22.04","rust_target":"x86_64-unknown-linux-gnu","tauri_args":"","bundles":"deb,appimage","label":"Linux-x64","artifact_name":"linux-x64"},{"platform":"ubuntu-22.04-arm","rust_target":"aarch64-unknown-linux-gnu","tauri_args":"","bundles":"deb,appimage","label":"Linux-ARM64","artifact_name":"linux-arm64"}]' SELECTED="${{ inputs.platforms }}" if [ "$SELECTED" = "all" ]; then @@ -63,6 +63,14 @@ jobs: - name: Checkout uses: actions/checkout@v4 + # ── 读取版本号 ─────────────────────────────────────────── + - name: Read version + id: version + shell: bash + run: | + VERSION=$(jq -r '.version' desktop/src-tauri/tauri.conf.json) + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + # ── 系统依赖 (Linux) ───────────────────────────────────── - name: Install Linux dependencies if: contains(matrix.platform, 'ubuntu') @@ -151,7 +159,7 @@ jobs: SEARCH_DIR="$FALLBACK_DIR" fi - STAGING="desktop/build-artifacts/ci-${{ matrix.artifact_name }}" + STAGING="desktop/build-artifacts/ci-Claude-Code-Haha-v${{ steps.version.outputs.version }}-${{ matrix.artifact_name }}" mkdir -p "$STAGING" echo "Searching for artifacts in: $SEARCH_DIR" @@ -175,7 +183,7 @@ jobs: - name: Upload artifacts uses: actions/upload-artifact@v4 with: - name: ${{ matrix.artifact_name }} + name: Claude-Code-Haha-v${{ steps.version.outputs.version }}-${{ matrix.artifact_name }} path: ${{ steps.collect.outputs.staging_dir }} retention-days: 7 if-no-files-found: warn From 1a07c2505997475442aae8ed8927b9e9e8fb81d4 Mon Sep 17 00:00:00 2001 From: xiaomingbusi Date: Thu, 16 Apr 2026 08:35:52 +0800 Subject: [PATCH 6/6] feat: fix companion randomization - support 18 species with rarity system --- src/buddy/companion.ts | 31 +++++++++++++++++++++++++++---- src/buddy/types.ts | 11 +++++++---- src/commands/buddy/buddy.tsx | 7 +++++-- 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/src/buddy/companion.ts b/src/buddy/companion.ts index 09c38386..52f3359f 100644 --- a/src/buddy/companion.ts +++ b/src/buddy/companion.ts @@ -7,6 +7,7 @@ import { RARITIES, RARITY_WEIGHTS, type Rarity, + type Species, SPECIES, STAT_NAMES, type StatName, @@ -121,13 +122,35 @@ export function companionUserId(): string { return config.oauthAccount?.accountUuid ?? config.userID ?? 'anon' } -// Regenerate bones from userId, merge with stored soul. Bones never persist -// so species renames and SPECIES-array edits can't break stored companions, -// and editing config.companion can't fake a rarity. +function storedAppearanceSeed(stored: { + appearanceSeed?: string + hatchedAt: number + name: string + personality: string +}): string { + return ( + stored.appearanceSeed ?? + `legacy:${stored.hatchedAt}:${stored.name}:${stored.personality}` + ) +} + +function applyStoredOverrides( + bones: CompanionBones, + stored: { speciesOverride?: Species }, +): CompanionBones { + return stored.speciesOverride + ? { ...bones, species: stored.speciesOverride } + : bones +} + +// Regenerate bones from the stored hatch seed, merge with the saved soul. +// Old configs without a seed get a deterministic legacy fallback so they stop +// changing every render without requiring users to re-hatch. export function getCompanion(): Companion | undefined { const stored = getGlobalConfig().companion if (!stored) return undefined - const { bones } = roll(companionUserId()) + const { bones: rolledBones } = rollWithSeed(storedAppearanceSeed(stored)) + const bones = applyStoredOverrides(rolledBones, stored) // bones last so stale bones fields in old-format configs get overridden return { ...stored, ...bones } } diff --git a/src/buddy/types.ts b/src/buddy/types.ts index 8f1c82aa..8f17b96f 100644 --- a/src/buddy/types.ts +++ b/src/buddy/types.ts @@ -118,10 +118,13 @@ export type Companion = CompanionBones & hatchedAt: number } -// What actually persists in config. Bones are regenerated from hash(userId) -// on every read so species renames don't break stored companions and users -// can't edit their way to a legendary. -export type StoredCompanion = CompanionSoul & { hatchedAt: number } +// What actually persists in config. The hatch seed locks in a companion's +// bones so the sprite/species stop changing between renders and restarts. +export type StoredCompanion = CompanionSoul & { + hatchedAt: number + appearanceSeed?: string + speciesOverride?: Species +} export const RARITY_WEIGHTS = { common: 60, diff --git a/src/commands/buddy/buddy.tsx b/src/commands/buddy/buddy.tsx index 56d7e9c9..235ce6c8 100644 --- a/src/commands/buddy/buddy.tsx +++ b/src/commands/buddy/buddy.tsx @@ -4,6 +4,7 @@ import type { LocalJSXCommandCall } from '../../types/command.js' import { getCompanion, roll, + rollWithSeed, companionUserId, } from '../../buddy/companion.js' import { renderSprite } from '../../buddy/sprites.js' @@ -73,8 +74,9 @@ function CompanionCard({ ) return } - // Hatch a new companion with a generated name - const { bones } = roll(companionUserId()) + // Hatch a new companion with a generated name and random seed + const appearanceSeed = `hatch:${Date.now()}:${Math.random().toString(36).slice(2)}` + const { bones } = rollWithSeed(appearanceSeed) const adjectives = [ 'Bright', 'Cozy', 'Swift', 'Calm', 'Wise', 'Bold', 'Fuzzy', 'Lucky', 'Snappy', 'Quirky', @@ -90,6 +92,7 @@ function CompanionCard({ name, personality: `A ${bones.rarity} ${bones.species} who loves debugging and hanging out.`, hatchedAt: Date.now(), + appearanceSeed, } saveGlobalConfig(c => ({ ...c, companion: soul })) onDone(