diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 08ca8c19e..ba05e9cfe 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -57,7 +57,9 @@ jobs:
run: pnpm run installRuntime:win:${{ matrix.arch }}
- name: Build Windows
- run: pnpm run build:win:${{ matrix.arch }}
+ run: |
+ pnpm run build
+ pnpm exec electron-builder --win --${{ matrix.arch }} --publish=never
env:
VITE_GITHUB_CLIENT_ID: ${{ secrets.DC_GITHUB_CLIENT_ID }}
VITE_GITHUB_CLIENT_SECRET: ${{ secrets.DC_GITHUB_CLIENT_SECRET }}
@@ -111,7 +113,9 @@ jobs:
# run: pnpm run installRuntime:linux:${{ matrix.arch }}
- name: Build Linux
- run: pnpm run build:linux:${{ matrix.arch }}
+ run: |
+ pnpm run build
+ pnpm exec electron-builder --linux --${{ matrix.arch }} --publish=never
env:
VITE_GITHUB_CLIENT_ID: ${{ secrets.DC_GITHUB_CLIENT_ID }}
VITE_GITHUB_CLIENT_SECRET: ${{ secrets.DC_GITHUB_CLIENT_SECRET }}
@@ -166,7 +170,9 @@ jobs:
run: pnpm run installRuntime:mac:${{ matrix.arch }}
- name: Build Mac
- run: pnpm run build:mac:${{ matrix.arch }}
+ run: |
+ pnpm run build
+ pnpm exec electron-builder --mac --${{ matrix.arch }} --publish=never
env:
CSC_LINK: ${{ secrets.DEEPCHAT_CSC_LINK }}
CSC_KEY_PASSWORD: ${{ secrets.DEEPCHAT_CSC_KEY_PASS }}
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 1209a9066..8065fdda9 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -1,45 +1,341 @@
-name: Create Release
+name: Release
on:
workflow_dispatch:
inputs:
- workflow_id:
- description: 'Build workflow run ID to use for artifacts'
+ tag:
+ description: 'Release tag (e.g. v0.5.5 v0.5.6-beta.1)'
required: true
type: string
- prerelease:
- description: 'Is this a prerelease?'
- required: true
- type: boolean
- default: false
+ push:
+ tags:
+ - v*.*.*
+
+permissions:
+ contents: write
jobs:
- create-release:
+ resolve-tag:
runs-on: ubuntu-latest
+ outputs:
+ tag: ${{ steps.resolve.outputs.tag }}
+ sha: ${{ steps.resolve.outputs.sha }}
steps:
- - name: Download artifacts from workflow
- uses: dawidd6/action-download-artifact@v6
+ - name: Resolve tag
+ id: resolve
+ uses: actions/github-script@v7
with:
- workflow_conclusion: success
- run_id: ${{ github.event.inputs.workflow_id }}
- path: artifacts
+ script: |
+ const isDispatch = context.eventName === 'workflow_dispatch'
+ const tag = isDispatch
+ ? context.payload.inputs?.tag
+ : context.ref.replace('refs/tags/', '')
+ if (!tag) {
+ core.setFailed('Tag is required')
+ return
+ }
+
+ const owner = context.repo.owner
+ const repo = context.repo.repo
+ const refName = `tags/${tag}`
+
+ const resolveTagSha = async (refData) => {
+ let sha = refData.object.sha
+ if (refData.object.type === 'tag') {
+ const tagObj = await github.rest.git.getTag({
+ owner,
+ repo,
+ tag_sha: sha
+ })
+ sha = tagObj.data.object.sha
+ }
+ return sha
+ }
+
+ if (isDispatch) {
+ try {
+ const { data } = await github.rest.git.getRef({
+ owner,
+ repo,
+ ref: refName
+ })
+ const sha = await resolveTagSha(data)
+ core.setOutput('sha', sha)
+ } catch (error) {
+ const sha = context.sha
+ await github.rest.git.createRef({
+ owner,
+ repo,
+ ref: `refs/${refName}`,
+ sha
+ })
+ core.setOutput('sha', sha)
+ }
+ } else {
+ try {
+ const { data } = await github.rest.git.getRef({
+ owner,
+ repo,
+ ref: refName
+ })
+ const sha = await resolveTagSha(data)
+ core.setOutput('sha', sha)
+ } catch (error) {
+ core.setFailed(`Tag ${tag} not found`)
+ return
+ }
+ }
+
+ core.setOutput('tag', tag)
+
+ build-windows:
+ needs: resolve-tag
+ runs-on: windows-latest
+ strategy:
+ matrix:
+ arch: [x64]
+ include:
+ - arch: x64
+ platform: win-x64
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ ref: ${{ needs.resolve-tag.outputs.sha }}
+ fetch-depth: 1
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: '22.13.1'
- - name: List downloaded artifacts
- run: find artifacts -type f | sort
+ - name: Setup pnpm
+ uses: pnpm/action-setup@v2
+ with:
+ version: 10.12.1
+
+ - name: Install dependencies
+ run: pnpm install
+
+ - name: Configure pnpm workspace for Windows ${{ matrix.arch }}
+ run: pnpm run install:sharp
+ env:
+ TARGET_OS: win32
+ TARGET_ARCH: ${{ matrix.arch }}
+
+ - name: Install dependencies
+ run: pnpm install
+ env:
+ npm_config_build_from_source: true
+ npm_config_platform: win32
+ npm_config_arch: ${{ matrix.arch }}
+
+ - name: Install Node Runtime
+ run: pnpm run installRuntime:win:${{ matrix.arch }}
+
+ - name: Build Windows
+ run: |
+ pnpm run build
+ pnpm exec electron-builder --win --${{ matrix.arch }} --publish=never
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ VITE_GITHUB_CLIENT_ID: ${{ secrets.DC_GITHUB_CLIENT_ID }}
+ VITE_GITHUB_CLIENT_SECRET: ${{ secrets.DC_GITHUB_CLIENT_SECRET }}
+ VITE_GITHUB_REDIRECT_URI: ${{ secrets.DC_GITHUB_REDIRECT_URI }}
+ VITE_PROVIDER_DB_URL: ${{ secrets.CDN_PROVIDER_DB_URL }}
+
+ - name: Upload artifacts
+ uses: actions/upload-artifact@v4
+ with:
+ name: deepchat-${{ matrix.platform }}
+ path: |
+ dist/*
+ !dist/win-unpacked
+ !dist/win-arm64-unpacked
+
+ build-linux:
+ needs: resolve-tag
+ runs-on: ubuntu-22.04
+ strategy:
+ matrix:
+ arch: [x64]
+ include:
+ - arch: x64
+ platform: linux-x64
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ ref: ${{ needs.resolve-tag.outputs.sha }}
+ fetch-depth: 1
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: '22.13.1'
+
+ - name: Setup pnpm
+ uses: pnpm/action-setup@v2
+ with:
+ version: 10.12.1
+
+ - name: Install dependencies
+ run: pnpm install
+
+ - name: Configure pnpm workspace for Linux ${{ matrix.arch }}
+ run: pnpm run install:sharp
+ env:
+ TARGET_OS: linux
+ TARGET_ARCH: ${{ matrix.arch }}
+
+ - name: Install dependencies
+ run: pnpm install
+
+ - name: Build Linux
+ run: |
+ pnpm run build
+ pnpm exec electron-builder --linux --${{ matrix.arch }} --publish=never
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ VITE_GITHUB_CLIENT_ID: ${{ secrets.DC_GITHUB_CLIENT_ID }}
+ VITE_GITHUB_CLIENT_SECRET: ${{ secrets.DC_GITHUB_CLIENT_SECRET }}
+ VITE_GITHUB_REDIRECT_URI: ${{ secrets.DC_GITHUB_REDIRECT_URI }}
+ VITE_PROVIDER_DB_URL: ${{ secrets.CDN_PROVIDER_DB_URL }}
+
+ - name: Upload artifacts
+ uses: actions/upload-artifact@v4
+ with:
+ name: deepchat-${{ matrix.platform }}
+ path: |
+ dist/*
+ !dist/linux-unpacked
+
+ build-mac:
+ needs: resolve-tag
+ runs-on: macos-15
+ strategy:
+ matrix:
+ arch: [x64, arm64]
+ include:
+ - arch: x64
+ platform: mac-x64
+ - arch: arm64
+ platform: mac-arm64
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ ref: ${{ needs.resolve-tag.outputs.sha }}
+ fetch-depth: 1
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: '22.13.1'
+
+ - name: Setup pnpm
+ uses: pnpm/action-setup@v2
+ with:
+ version: 10.12.1
+
+ - name: Install dependencies
+ run: pnpm install
+
+ - name: Configure pnpm workspace for macOS ${{ matrix.arch }}
+ run: pnpm run install:sharp
+ env:
+ TARGET_OS: darwin
+ TARGET_ARCH: ${{ matrix.arch }}
+
+ - name: Install dependencies
+ run: pnpm install
+
+ - name: Install Node Runtime
+ run: pnpm run installRuntime:mac:${{ matrix.arch }}
+
+ - name: Build Mac
+ run: |
+ pnpm run build
+ pnpm exec electron-builder --mac --${{ matrix.arch }} --publish=never
+ env:
+ CSC_LINK: ${{ secrets.DEEPCHAT_CSC_LINK }}
+ CSC_KEY_PASSWORD: ${{ secrets.DEEPCHAT_CSC_KEY_PASS }}
+ DEEPCHAT_APPLE_NOTARY_USERNAME: ${{ secrets.DEEPCHAT_APPLE_NOTARY_USERNAME }}
+ DEEPCHAT_APPLE_NOTARY_TEAM_ID: ${{ secrets.DEEPCHAT_APPLE_NOTARY_TEAM_ID }}
+ DEEPCHAT_APPLE_NOTARY_PASSWORD: ${{ secrets.DEEPCHAT_APPLE_NOTARY_PASSWORD }}
+ build_for_release: '2'
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ VITE_GITHUB_CLIENT_ID: ${{ secrets.DC_GITHUB_CLIENT_ID }}
+ VITE_GITHUB_CLIENT_SECRET: ${{ secrets.DC_GITHUB_CLIENT_SECRET }}
+ VITE_GITHUB_REDIRECT_URI: ${{ secrets.DC_GITHUB_REDIRECT_URI }}
+ NODE_OPTIONS: '--max-old-space-size=4096'
+ VITE_PROVIDER_DB_URL: ${{ secrets.CDN_PROVIDER_DB_URL }}
+
+ - name: Upload artifacts
+ uses: actions/upload-artifact@v4
+ with:
+ name: deepchat-${{ matrix.platform }}
+ path: |
+ dist/*
+ !dist/mac/*
+ !dist/mac-arm64/*
+
+ release:
+ needs:
+ - resolve-tag
+ - build-windows
+ - build-linux
+ - build-mac
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ ref: ${{ needs.resolve-tag.outputs.sha }}
+ fetch-depth: 1
- name: Get version number
id: get_version
run: |
- VERSION_FILE=$(find artifacts/deepchat-linux-x64 -name "DeepChat-*.tar.gz" | head -n 1)
- if [ -n "$VERSION_FILE" ]; then
- VERSION=$(echo $VERSION_FILE | grep -o 'DeepChat-[0-9]\+\.[0-9]\+\.[0-9]\+' | sed 's/DeepChat-//')
- echo "version=$VERSION" >> $GITHUB_OUTPUT
- echo "Found version: $VERSION"
+ VERSION=$(node -p "require('./package.json').version")
+ TAG="${{ needs.resolve-tag.outputs.tag }}"
+ if [ "v$VERSION" != "$TAG" ]; then
+ echo "Error: tag $TAG does not match package.json version v$VERSION"
+ exit 1
+ fi
+ if echo "$VERSION" | grep -qE '-(beta|alpha)\.[0-9]+$'; then
+ echo "prerelease=true" >> $GITHUB_OUTPUT
else
- echo "Error: DeepChat tar.gz file not found"
+ echo "prerelease=false" >> $GITHUB_OUTPUT
+ fi
+ echo "version=$VERSION" >> $GITHUB_OUTPUT
+
+ - name: Build release notes from CHANGELOG
+ run: |
+ VERSION="${{ steps.get_version.outputs.version }}"
+ CHANGELOG="CHANGELOG.md"
+ if [ ! -f "$CHANGELOG" ]; then
+ echo "Error: CHANGELOG.md not found"
+ exit 1
+ fi
+ NORMALIZED_CHANGELOG="$(mktemp)"
+ perl -pe 's/\x{FF08}/(/g; s/\x{FF09}/)/g; s/\r$//' "$CHANGELOG" > "$NORMALIZED_CHANGELOG"
+ HEADER_REGEX="^##[[:space:]]+v${VERSION}[[:space:]]*\\([0-9]{4}-[0-9]{2}-[0-9]{2}\\)[[:space:]]*$"
+ if ! grep -Eq "$HEADER_REGEX" "$NORMALIZED_CHANGELOG"; then
+ echo "Error: Changelog entry not found for v${VERSION}"
+ exit 1
+ fi
+ awk -v ver="v${VERSION}" '
+ $0 ~ "^##[[:space:]]+" ver "[[:space:]]*\\(" { in_section = 1 }
+ in_section && $0 ~ "^##[[:space:]]+" && $0 !~ "^##[[:space:]]+" ver "[[:space:]]*\\(" { exit }
+ in_section { print }
+ ' "$NORMALIZED_CHANGELOG" > release_notes.md
+ if [ ! -s release_notes.md ]; then
+ echo "Error: Release notes are empty for v${VERSION}"
exit 1
fi
+ - name: Download build artifacts
+ uses: actions/download-artifact@v4
+ with:
+ path: artifacts
+
- name: Prepare release assets
run: |
mkdir -p release_assets
@@ -49,33 +345,67 @@ jobs:
cp artifacts/deepchat-win-x64/*.exe release_assets/ 2>/dev/null || true
cp artifacts/deepchat-win-x64/*.msi release_assets/ 2>/dev/null || true
cp artifacts/deepchat-win-x64/*.zip release_assets/ 2>/dev/null || true
+ cp artifacts/deepchat-win-x64/*.yml release_assets/ 2>/dev/null || true
+ cp artifacts/deepchat-win-x64/*.blockmap release_assets/ 2>/dev/null || true
fi
- # Process Windows arm64 artifacts
- #if [ -d "artifacts/deepchat-win-arm64" ]; then
- # cp artifacts/deepchat-win-arm64/*.exe release_assets/ 2>/dev/null || true
- # cp artifacts/deepchat-win-arm64/*.msi release_assets/ 2>/dev/null || true
- # cp artifacts/deepchat-win-arm64/*.zip release_assets/ 2>/dev/null || true
- #fi
-
# Process Linux x64 artifacts
if [ -d "artifacts/deepchat-linux-x64" ]; then
cp artifacts/deepchat-linux-x64/*.AppImage release_assets/ 2>/dev/null || true
cp artifacts/deepchat-linux-x64/*.deb release_assets/ 2>/dev/null || true
cp artifacts/deepchat-linux-x64/*.rpm release_assets/ 2>/dev/null || true
cp artifacts/deepchat-linux-x64/*.tar.gz release_assets/ 2>/dev/null || true
+ cp artifacts/deepchat-linux-x64/*.yml release_assets/ 2>/dev/null || true
+ cp artifacts/deepchat-linux-x64/*.blockmap release_assets/ 2>/dev/null || true
fi
# Process Mac x64 artifacts
if [ -d "artifacts/deepchat-mac-x64" ]; then
cp artifacts/deepchat-mac-x64/*.dmg release_assets/ 2>/dev/null || true
cp artifacts/deepchat-mac-x64/*.zip release_assets/ 2>/dev/null || true
+ cp artifacts/deepchat-mac-x64/*.blockmap release_assets/ 2>/dev/null || true
fi
# Process Mac arm64 artifacts
if [ -d "artifacts/deepchat-mac-arm64" ]; then
cp artifacts/deepchat-mac-arm64/*.dmg release_assets/ 2>/dev/null || true
cp artifacts/deepchat-mac-arm64/*.zip release_assets/ 2>/dev/null || true
+ cp artifacts/deepchat-mac-arm64/*.blockmap release_assets/ 2>/dev/null || true
+ fi
+
+ merge_mac_yml() {
+ local name="$1"
+ local x64="artifacts/deepchat-mac-x64/$name"
+ local arm64="artifacts/deepchat-mac-arm64/$name"
+ if [ -f "$x64" ] && [ -f "$arm64" ]; then
+ ruby -ryaml -e '
+ x64 = YAML.load_file(ARGV[0]) || {}
+ arm = YAML.load_file(ARGV[1]) || {}
+ merged = x64.dup
+ merged["version"] ||= arm["version"]
+ merged["releaseDate"] ||= arm["releaseDate"]
+ merged["releaseNotes"] ||= arm["releaseNotes"]
+ merged["path"] ||= arm["path"]
+ merged["sha512"] ||= arm["sha512"]
+ files = []
+ files.concat(x64["files"]) if x64["files"].is_a?(Array)
+ files.concat(arm["files"]) if arm["files"].is_a?(Array)
+ merged["files"] = files.uniq { |f| f["url"] }
+ File.write(ARGV[2], merged.to_yaml)
+ ' "$x64" "$arm64" "release_assets/$name"
+ elif [ -f "$x64" ]; then
+ cp "$x64" "release_assets/$name"
+ elif [ -f "$arm64" ]; then
+ cp "$arm64" "release_assets/$name"
+ fi
+ }
+
+ merge_mac_yml latest-mac.yml
+ merge_mac_yml beta-mac.yml
+
+ if [ -z "$(ls -A release_assets)" ]; then
+ echo "Error: No release assets found"
+ exit 1
fi
ls -la release_assets/
@@ -83,51 +413,12 @@ jobs:
- name: Create Draft Release
uses: softprops/action-gh-release@v1
with:
- tag_name: v${{ steps.get_version.outputs.version }}
+ tag_name: ${{ needs.resolve-tag.outputs.tag }}
name: DeepChat V${{ steps.get_version.outputs.version }}
draft: true
- prerelease: ${{ github.event.inputs.prerelease }}
+ prerelease: ${{ steps.get_version.outputs.prerelease == 'true' }}
files: |
release_assets/*
- body: |
- # 🚀 DeepChat ${{ steps.get_version.outputs.version }} 正式发布 | 重新定义你的 AI 对话体验!
- —— 不再是简单的 ChatBot,而是你的自然语言 Agent 工具🌟
-
- 🔥 为什么选择 DeepChat?
-
- ✅ **商业友好**:基于原版 [Apache License 2.0](https://github.com/ThinkInAIXYZ/deepchat/blob/main/LICENSE) 开源,无任何协议外的额外约束,面向开源。
- ✅ **开箱即用**:极简配置,即刻开启你的智能对话之旅。
- ✅ **极致灵活**:自由切换模型,自定义模型源,满足你多样化的对话和探索需求。
- ✅ **体验绝佳**:LaTeX 公式渲染、代码高亮、Markdown 支持,模型对话从未如此顺畅。
- ✅ **持续进化**:我们倾听用户反馈,不断迭代更新,为你带来更卓越的 AI 对话体验。
-
- 📥 立即体验未来
-
- 💬 反馈有礼:欢迎提交你的宝贵建议,加入 VIP 用户社群,与我们一同塑造 DeepChat 的未来!
-
-
- 🎮 加入 Discord 社区:[https://discord.gg/6RBatENX](https://discord.gg/6RBatENX)
-
- ---
-
- # 🚀 DeepChat ${{ steps.get_version.outputs.version }} Official Release | Redefine Your AI Conversation Experience!
- —— Not just a simple ChatBot, but your natural language Agent tool 🌟
-
- 🔥 Why Choose DeepChat?
-
- ✅ **Business-Friendly**: Open source under [Apache License 2.0](https://github.com/ThinkInAIXYZ/deepchat/blob/main/LICENSE), with no additional constraints beyond the license, truly open source.
- ✅ **Ready to Use**: Minimal configuration, start your intelligent conversation journey immediately.
- ✅ **Ultra Flexible**: Freely switch models, customize model sources, meet your diverse conversation and exploration needs.
- ✅ **Excellent Experience**: LaTeX formula rendering, code highlighting, Markdown support, model conversations have never been smoother.
- ✅ **Continuous Evolution**: We listen to user feedback, continuously iterate and update, bringing you an even better AI conversation experience.
-
- 📥 Experience the Future Now
-
- 💬 Feedback Welcome: We welcome your valuable suggestions, join the user community, and shape the future of DeepChat together!
-
-
-
- 🎮 Join Discord Community: [https://discord.gg/6RBatENX](https://discord.gg/6RBatENX)
-
+ body_path: release_notes.md
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 000000000..cc73e0d7c
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,18 @@
+# Changelog
+
+## v0.5.6-beta.1 (2025-12-23)
+- Markdown 优化,修复列表元素异常
+- 修复 Ollama 视觉模型图片格式
+- Improved Markdown rendering, fixed list element issues
+- Fixed Ollama vision model image format
+
+## v0.5.5 (2025-12-19)
+- 全新 Yo Browser 功能,让你的模型畅游网络
+- All-new Yo Browser lets your model roam the web
+
+## v0.5.3 (2025-12-13)
+- 优化 ACP 体验,增加 ACP 调试能力
+- 增加了自定义软件字体能力
+- add acp process warmup and debug panel
+- add font settings
+- add Hebrew (he-IL) Translation
diff --git a/docs/rebrand-guide.md b/docs/rebrand-guide.md
index eb9f1bc2d..6ac09de52 100644
--- a/docs/rebrand-guide.md
+++ b/docs/rebrand-guide.md
@@ -86,7 +86,6 @@ This script will automatically replace brand information in the following files:
- `package.json` - Package configuration
- `electron-builder.yml` - Build configuration
-- `electron-builder-macx64.yml` - macOS x64 build configuration
- `src/main/index.ts` - Main process configuration
- `src/main/presenter/upgradePresenter/index.ts` - Update service configuration
- `src/renderer/src/i18n/*/about.json` - Internationalization files
@@ -343,7 +342,6 @@ node scripts/rebrand.js
- `package.json` - 包配置
- `electron-builder.yml` - 构建配置
-- `electron-builder-macx64.yml` - macOS x64 构建配置
- `src/main/index.ts` - 主进程配置
- `src/main/presenter/upgradePresenter/index.ts` - 更新服务配置
- `src/renderer/src/i18n/*/about.json` - 国际化文件
diff --git a/electron-builder-macx64.yml b/electron-builder-macx64.yml
deleted file mode 100644
index beb6a7b84..000000000
--- a/electron-builder-macx64.yml
+++ /dev/null
@@ -1,83 +0,0 @@
-appId: com.wefonk.deepchat
-productName: DeepChat
-directories:
- buildResources: build
-files:
- - '!**/.claude/*'
- - '!**/.github/*'
- - '!**/.cursor/*'
- - '!**/.vscode/*'
- - '!src/*'
- - '!test/*'
- - '!docs/*'
- - '!electron.vite.config.{js,ts,mjs,cjs}'
- - '!{.eslintignore,.eslintrc.cjs,.prettierignore,.prettierrc.yaml,dev-app-update.yml,CHANGELOG.md,README.md}'
- - '!{.env,.env.*,.npmrc,pnpm-lock.yaml}'
- - '!{tsconfig.json,tsconfig.node.json,tsconfig.app.json}'
- - '!keys/*'
- - '!scripts/*'
- - '!.github/*'
- - '!electron-builder.yml'
- - '!electron-builder-macx64.yml'
- - '!test/*'
- - '!*.config.ts'
- - '!*.config.js'
- - '!**/{LICENSE,LICENSE.txt,*.LICENSE.txt,NOTICE.txt,README.md,CHANGELOG.md,CONTRIBUTING.md,CONTRIBUTING.zh.md,README.zh.md,README.jp.md}'
- - '!**/{.DS_Store,Thumbs.db}'
- - '!*.md'
-asarUnpack:
- - '**/node_modules/sharp/**/*'
- - '**/node_modules/@img/**/*'
-extraResources:
- - from: ./runtime/
- to: app.asar.unpacked/runtime
- filter: ['**/*']
- - from: ./resources/cdn/
- to: app.asar.unpacked/resources/cdn
- filter: ['**/*']
-afterSign: scripts/notarize.js
-afterPack: scripts/afterPack.js
-electronLanguages:
- - zh-CN
- - zh-TW
- - zh-HK
- - en-US
- - ja-JP
- - ko-KR
- - fr-FR
- - ru-RU
- - ja
- - ru
- - zh_CN
- - zh_TW
- - zh_HK
- - en
- - ko
- - fr
- - fa-IR
- - fa
- - pt-BR
- - pt
- - da-DK
- - da
- - he-IL
- - he
-mac:
- entitlementsInherit: build/entitlements.mac.plist
- extendInfo:
- - NSCameraUsageDescription: Application requests access to the device's camera.
- - NSMicrophoneUsageDescription: Application requests access to the device's microphone.
- - NSDocumentsFolderUsageDescription: Application requests access to the user's Documents folder.
- - NSDownloadsFolderUsageDescription: Application requests access to the user's Downloads folder.
- gatekeeperAssess: false
- category: public.app-category.utilities
- target:
- - target: dmg
- arch: x64
- - target: zip
- arch: x64
- artifactName: ${name}-${version}-mac-${arch}.${ext}
-npmRebuild: true
-publish:
- provider: generic
- url: https://cdn.deepchatai.cn/upgrade/
diff --git a/electron-builder.yml b/electron-builder.yml
index 93c31acbb..3b2ace778 100644
--- a/electron-builder.yml
+++ b/electron-builder.yml
@@ -18,7 +18,6 @@ files:
- '!{.env,.env.*,.npmrc,pnpm-lock.yaml}'
- '!{tsconfig.json,tsconfig.node.json,tsconfig.app.json}'
- '!electron-builder.yml'
- - '!electron-builder-macx64.yml'
- '!test/*'
- '!*.config.ts'
- '!*.config.js'
@@ -84,9 +83,7 @@ mac:
category: public.app-category.utilities
target:
- target: dmg
- arch: arm64
- target: zip
- arch: arm64
artifactName: ${name}-${version}-mac-${arch}.${ext}
linux:
target:
@@ -99,5 +96,6 @@ linux:
- x-scheme-handler/deepchat
npmRebuild: true
publish:
- provider: generic
- url: https://cdn.deepchatai.cn/upgrade/
+ provider: github
+ owner: ThinkInAIXYZ
+ repo: deepchat
diff --git a/package.json b/package.json
index e1bbee87f..dacadd5e2 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "DeepChat",
- "version": "0.5.5",
+ "version": "0.5.6-beta.1",
"description": "DeepChat,一个简单易用的AI客户端",
"main": "./out/main/index.js",
"author": "ThinkInAIXYZ",
@@ -38,7 +38,7 @@
"install:sharp": "node scripts/install-sharp-for-platform.js",
"build:mac": "pnpm run build && electron-builder --mac",
"build:mac:arm64": "pnpm run build && electron-builder --mac --arm64",
- "build:mac:x64": "pnpm run build && electron-builder -c electron-builder-macx64.yml --mac --x64 ",
+ "build:mac:x64": "pnpm run build && electron-builder --mac --x64",
"build:linux": "pnpm run build && electron-builder --linux",
"build:linux:x64": "pnpm run build && electron-builder --linux --x64",
"build:linux:arm64": "pnpm run build && electron-builder --linux --arm64",
diff --git a/scripts/rebrand.js b/scripts/rebrand.js
index 797ce4984..1e1731c31 100644
--- a/scripts/rebrand.js
+++ b/scripts/rebrand.js
@@ -122,34 +122,6 @@ function updateElectronBuilder(config) {
}
}
-// 更新 electron-builder-macx64.yml
-function updateElectronBuilderMacX64(config) {
- const builderPath = path.join(PROJECT_ROOT, 'electron-builder-macx64.yml')
-
- if (!fs.existsSync(builderPath)) {
- return // 文件不存在则跳过
- }
-
- try {
- let content = fs.readFileSync(builderPath, 'utf8')
-
- // 替换 appId
- content = content.replace(/appId: .+/, `appId: ${config.app.appId}`)
-
- // 替换 productName
- content = content.replace(/productName: .+/, `productName: ${config.app.productName}`)
-
- // 替换 publish URL
- if (config.update && config.update.baseUrl) {
- content = content.replace(/url: https:\/\/cdn\.deepchatai\.cn\/upgrade\//, `url: ${config.update.baseUrl}`)
- }
-
- fs.writeFileSync(builderPath, content, 'utf8')
- success('已更新 electron-builder-macx64.yml')
- } catch (err) {
- error(`更新 electron-builder-macx64.yml 失败: ${err.message}`)
- }
-}
// 更新主进程中的 app user model ID
function updateMainIndex(config) {
@@ -480,7 +452,6 @@ function main() {
// 执行替换
updatePackageJson(config)
updateElectronBuilder(config)
- updateElectronBuilderMacX64(config)
updateMainIndex(config)
updateUpgradePresenter(config)
updateI18nFiles(config)
diff --git a/src/main/presenter/configPresenter/index.ts b/src/main/presenter/configPresenter/index.ts
index 86c03b1b6..25b329a98 100644
--- a/src/main/presenter/configPresenter/index.ts
+++ b/src/main/presenter/configPresenter/index.ts
@@ -73,7 +73,7 @@ interface IAppSettings {
floatingButtonEnabled?: boolean // Whether floating button is enabled
default_system_prompt?: string // Default system prompt
webContentLengthLimit?: number // Web content truncation length limit, default 3000 characters
- updateChannel?: string // Update channel: 'stable' | 'canary'
+ updateChannel?: string // Update channel: 'stable' | 'beta'
fontFamily?: string // Custom UI font
codeFontFamily?: string // Custom code font
[key: string]: unknown // Allow arbitrary keys, using unknown type instead of any
@@ -1475,7 +1475,12 @@ export class ConfigPresenter implements IConfigPresenter {
// 获取更新渠道
getUpdateChannel(): string {
- return this.getSetting('updateChannel') || 'stable'
+ const raw = this.getSetting('updateChannel') || 'stable'
+ const channel = raw === 'stable' || raw === 'beta' ? raw : 'beta'
+ if (channel !== raw) {
+ this.setSetting('updateChannel', channel)
+ }
+ return channel
}
// 设置更新渠道
diff --git a/src/main/presenter/upgradePresenter/index.ts b/src/main/presenter/upgradePresenter/index.ts
index 9d9584eb1..737dc5a0e 100644
--- a/src/main/presenter/upgradePresenter/index.ts
+++ b/src/main/presenter/upgradePresenter/index.ts
@@ -8,13 +8,22 @@ import {
import { eventBus, SendTarget } from '@/eventbus'
import { UPDATE_EVENTS, WINDOW_EVENTS } from '@/events'
import electronUpdater from 'electron-updater'
-import axios from 'axios'
-import { compare } from 'compare-versions'
+import type { UpdateInfo } from 'electron-updater'
import fs from 'fs'
import path from 'path'
const { autoUpdater } = electronUpdater
+const GITHUB_OWNER = 'ThinkInAIXYZ'
+const GITHUB_REPO = 'deepchat'
+const UPDATE_CHANNEL_STABLE = 'stable'
+const UPDATE_CHANNEL_BETA = 'beta'
+
+type ReleaseNoteItem = {
+ version?: string | null
+ note?: string | null
+}
+
// 版本信息接口
interface VersionInfo {
version: string
@@ -24,26 +33,41 @@ interface VersionInfo {
downloadUrl: string
}
-// 获取平台和架构信息
-const getPlatformInfo = () => {
- const platform = process.platform
- const arch = process.arch
- let platformString = ''
-
- if (platform === 'win32') {
- platformString = arch === 'arm64' ? 'winarm' : 'winx64'
- } else if (platform === 'darwin') {
- platformString = arch === 'arm64' ? 'macarm' : 'macx64'
- } else if (platform === 'linux') {
- platformString = arch === 'arm64' ? 'linuxarm' : 'linuxx64'
- }
+const normalizeUpdateChannel = (channel?: string): 'stable' | 'beta' => {
+ return channel === UPDATE_CHANNEL_BETA ? UPDATE_CHANNEL_BETA : UPDATE_CHANNEL_STABLE
+}
- return platformString
+const formatTagVersion = (version: string): string => {
+ return version.startsWith('v') ? version : `v${version}`
}
-// 获取版本检查的基础URL
-const getVersionCheckBaseUrl = () => {
- return 'https://cdn.deepchatai.cn'
+const buildReleaseUrl = (version: string): string => {
+ return `https://github.com/${GITHUB_OWNER}/${GITHUB_REPO}/releases/tag/${formatTagVersion(version)}`
+}
+
+const formatReleaseNotes = (notes?: string | ReleaseNoteItem[] | null): string => {
+ if (!notes) return ''
+ if (typeof notes === 'string') return notes
+ if (!Array.isArray(notes)) return String(notes)
+ const blocks = notes
+ .map((note) => {
+ const title = note.version ? `## ${note.version}` : ''
+ const body = note.note ?? ''
+ return [title, body].filter(Boolean).join('\n')
+ })
+ .filter((entry) => entry.length > 0)
+ return blocks.join('\n\n')
+}
+
+const toVersionInfo = (info: UpdateInfo): VersionInfo => {
+ const releaseUrl = buildReleaseUrl(info.version)
+ return {
+ version: info.version,
+ releaseDate: info.releaseDate || '',
+ releaseNotes: formatReleaseNotes(info.releaseNotes),
+ githubUrl: releaseUrl,
+ downloadUrl: releaseUrl
+ }
}
// 获取自动更新状态文件路径
@@ -57,8 +81,8 @@ export class UpgradePresenter implements IUpgradePresenter {
private _progress: UpdateProgress | null = null
private _error: string | null = null
private _versionInfo: VersionInfo | null = null
- private _baseUrl: string
private _lastCheckTime: number = 0 // 上次检查更新的时间戳
+ private _lastCheckType?: string
private _updateMarkerPath: string
private _previousUpdateFailed: boolean = false // 标记上次更新是否失败
private _configPresenter: IConfigPresenter // 配置presenter
@@ -66,7 +90,6 @@ export class UpgradePresenter implements IUpgradePresenter {
constructor(configPresenter: IConfigPresenter) {
this._configPresenter = configPresenter
- this._baseUrl = getVersionCheckBaseUrl()
this._updateMarkerPath = getUpdateMarkerFilePath()
// 配置自动更新
@@ -98,18 +121,33 @@ export class UpgradePresenter implements IUpgradePresenter {
this._lock = false
this._status = 'not-available'
eventBus.sendToRenderer(UPDATE_EVENTS.STATUS_CHANGED, SendTarget.ALL_WINDOWS, {
- status: this._status
+ status: this._status,
+ type: this._lastCheckType
})
})
// 有可用更新
autoUpdater.on('update-available', (info) => {
console.log('检测到新版本', info)
- this._status = 'available'
+ this._versionInfo = toVersionInfo(info)
- // 重要:这里不再使用info中的信息更新this._versionInfo
- // 而是确保使用之前从versionUrl获取的原始信息
- console.log('使用已保存的版本信息:', this._versionInfo)
+ if (this._previousUpdateFailed) {
+ console.log('上次更新失败,本次不进行自动更新,改为手动更新')
+ this._status = 'error'
+ this._error = '自动更新可能不稳定,请手动下载更新'
+ eventBus.sendToRenderer(UPDATE_EVENTS.STATUS_CHANGED, SendTarget.ALL_WINDOWS, {
+ status: this._status,
+ error: this._error,
+ info: this._versionInfo
+ })
+ return
+ }
+
+ this._status = 'available'
+ eventBus.sendToRenderer(UPDATE_EVENTS.STATUS_CHANGED, SendTarget.ALL_WINDOWS, {
+ status: this._status,
+ info: this._versionInfo
+ })
// 检测到更新后自动开始下载
this.startDownloadUpdate()
})
@@ -137,6 +175,10 @@ export class UpgradePresenter implements IUpgradePresenter {
this._lock = false
this._status = 'downloaded'
+ if (!this._versionInfo) {
+ this._versionInfo = toVersionInfo(info)
+ }
+
// 写入更新标记文件
this.writeUpdateMarker(this._versionInfo?.version || info.version)
@@ -250,83 +292,17 @@ export class UpgradePresenter implements IUpgradePresenter {
try {
this._status = 'checking'
+ this._lastCheckType = type
eventBus.sendToRenderer(UPDATE_EVENTS.STATUS_CHANGED, SendTarget.ALL_WINDOWS, {
status: this._status
})
- // 首先获取版本信息文件
- const platformString = getPlatformInfo()
- const rawChannel = this._configPresenter.getUpdateChannel()
- const updateChannel = rawChannel === 'canary' ? 'canary' : 'upgrade' // Sanitize channel
- const randomId = Math.floor(Date.now() / 3600000) // Timestamp truncated to hour
- const versionPath = updateChannel
- const versionUrl = `${this._baseUrl}/${versionPath}/${platformString}.json?noCache=${randomId}`
- console.log('versionUrl', versionUrl)
- const response = await axios.get(versionUrl, { timeout: 60000 }) // Add network timeout
- const remoteVersion = response.data
- const currentVersion = app.getVersion()
-
- // 保存完整的远程版本信息到内存中,作为唯一的标准信息源
- this._versionInfo = {
- version: remoteVersion.version,
- releaseDate: remoteVersion.releaseDate,
- releaseNotes: remoteVersion.releaseNotes,
- githubUrl: remoteVersion.githubUrl,
- downloadUrl: remoteVersion.downloadUrl
- }
-
- console.log('cache versionInfo:', this._versionInfo)
+ const updateChannel = normalizeUpdateChannel(this._configPresenter.getUpdateChannel())
+ autoUpdater.allowPrerelease = updateChannel === UPDATE_CHANNEL_BETA
+ autoUpdater.channel = updateChannel === UPDATE_CHANNEL_BETA ? UPDATE_CHANNEL_BETA : 'latest'
- // 更新上次检查时间
+ await autoUpdater.checkForUpdates()
this._lastCheckTime = Date.now()
-
- // 比较版本号
- if (compare(remoteVersion.version, currentVersion, '>')) {
- // 有新版本
-
- // 如果上次更新失败,这次不再尝试自动更新,直接进入错误状态让用户手动更新
- if (this._previousUpdateFailed) {
- console.log('上次更新失败,本次不进行自动更新,改为手动更新')
- this._status = 'error'
- this._error = '自动更新可能不稳定,请手动下载更新'
-
- eventBus.sendToRenderer(UPDATE_EVENTS.STATUS_CHANGED, SendTarget.ALL_WINDOWS, {
- status: this._status,
- error: this._error,
- info: this._versionInfo
- })
- return
- }
-
- // 设置自动更新的URL
- const autoUpdateUrl =
- updateChannel === 'canary'
- ? `${this._baseUrl}/canary/${platformString}`
- : `${this._baseUrl}/upgrade/v${remoteVersion.version}/${platformString}`
- console.log('设置自动更新URL:', autoUpdateUrl)
- autoUpdater.setFeedURL(autoUpdateUrl)
-
- try {
- // 使用electron-updater检查更新,但不自动下载
- await autoUpdater.checkForUpdates()
- } catch (err) {
- console.error('自动更新检查失败,回退到手动更新', err)
- // 如果自动更新失败,回退到手动更新
- this._status = 'available'
-
- eventBus.sendToRenderer(UPDATE_EVENTS.STATUS_CHANGED, SendTarget.ALL_WINDOWS, {
- status: this._status,
- info: this._versionInfo // 使用已保存的版本信息
- })
- }
- } else {
- // 没有新版本
- this._status = 'not-available'
- eventBus.sendToRenderer(UPDATE_EVENTS.STATUS_CHANGED, SendTarget.ALL_WINDOWS, {
- status: this._status,
- type
- })
- }
} catch (error: Error | unknown) {
this._status = 'error'
this._error = error instanceof Error ? error.message : String(error)
@@ -355,13 +331,14 @@ export class UpgradePresenter implements IUpgradePresenter {
}
async goDownloadUpgrade(type: 'github' | 'netdisk'): Promise {
+ const fallbackUrl = `https://github.com/${GITHUB_OWNER}/${GITHUB_REPO}/releases`
if (type === 'github') {
- const url = this._versionInfo?.githubUrl
+ const url = this._versionInfo?.githubUrl || fallbackUrl
if (url) {
shell.openExternal(url)
}
} else if (type === 'netdisk') {
- const url = this._versionInfo?.downloadUrl
+ const url = this._versionInfo?.downloadUrl || fallbackUrl
if (url) {
shell.openExternal(url)
}
diff --git a/src/renderer/settings/components/AboutUsSettings.vue b/src/renderer/settings/components/AboutUsSettings.vue
index 5d008ec8e..f88225443 100644
--- a/src/renderer/settings/components/AboutUsSettings.vue
+++ b/src/renderer/settings/components/AboutUsSettings.vue
@@ -57,8 +57,8 @@
{{ t('about.stableChannel') }}
-
- {{ t('about.canaryChannel') }}
+
+ {{ t('about.betaChannel') }}
diff --git a/src/renderer/src/i18n/da-DK/about.json b/src/renderer/src/i18n/da-DK/about.json
index 3b15f1a33..b035590f7 100644
--- a/src/renderer/src/i18n/da-DK/about.json
+++ b/src/renderer/src/i18n/da-DK/about.json
@@ -1,5 +1,5 @@
{
- "canaryChannel": "Intern testversion",
+ "betaChannel": "Beta",
"checkUpdateButton": "Tjek for opdateringer",
"description": "DeepChat er en tværplatform AI-klient, der har til formål at gøre det nemmere for flere mennesker at bruge AI.",
"deviceInfo": {
diff --git a/src/renderer/src/i18n/en-US/about.json b/src/renderer/src/i18n/en-US/about.json
index c4a66a843..3a2ebc9aa 100644
--- a/src/renderer/src/i18n/en-US/about.json
+++ b/src/renderer/src/i18n/en-US/about.json
@@ -15,5 +15,5 @@
"checkUpdateButton": "Check for Updates",
"updateChannel": "Update Channel",
"stableChannel": "Stable",
- "canaryChannel": "Canary"
+ "betaChannel": "Beta"
}
diff --git a/src/renderer/src/i18n/fa-IR/about.json b/src/renderer/src/i18n/fa-IR/about.json
index 77b59e799..b3a7c107e 100644
--- a/src/renderer/src/i18n/fa-IR/about.json
+++ b/src/renderer/src/i18n/fa-IR/about.json
@@ -15,5 +15,5 @@
"checkUpdateButton": "بررسی بهروزرسانی",
"updateChannel": "کانال بهروزرسانی",
"stableChannel": "پایدار",
- "canaryChannel": "کاناری"
+ "betaChannel": "Beta"
}
diff --git a/src/renderer/src/i18n/fr-FR/about.json b/src/renderer/src/i18n/fr-FR/about.json
index c5d9af7d9..d77768bb0 100644
--- a/src/renderer/src/i18n/fr-FR/about.json
+++ b/src/renderer/src/i18n/fr-FR/about.json
@@ -15,5 +15,5 @@
"checkUpdateButton": "Vérifier les mises à jour",
"updateChannel": "Canal de mise à jour",
"stableChannel": "Stable",
- "canaryChannel": "Canary"
+ "betaChannel": "Beta"
}
diff --git a/src/renderer/src/i18n/he-IL/about.json b/src/renderer/src/i18n/he-IL/about.json
index 03e17c5bb..2626806ca 100644
--- a/src/renderer/src/i18n/he-IL/about.json
+++ b/src/renderer/src/i18n/he-IL/about.json
@@ -15,5 +15,5 @@
"checkUpdateButton": "בדוק עדכונים",
"updateChannel": "ערוץ עדכון",
"stableChannel": "יציב (Stable)",
- "canaryChannel": "קנרית (Canary)"
+ "betaChannel": "Beta"
}
diff --git a/src/renderer/src/i18n/ja-JP/about.json b/src/renderer/src/i18n/ja-JP/about.json
index e4ce28faa..da646cdc0 100644
--- a/src/renderer/src/i18n/ja-JP/about.json
+++ b/src/renderer/src/i18n/ja-JP/about.json
@@ -7,7 +7,7 @@
"checkUpdateButton": "アップデートを確認",
"updateChannel": "アップデートチャンネル",
"stableChannel": "安定版",
- "canaryChannel": "テスト版",
+ "betaChannel": "Beta",
"deviceInfo": {
"title": "デバイス情報",
"platform": "プラットフォーム",
diff --git a/src/renderer/src/i18n/ko-KR/about.json b/src/renderer/src/i18n/ko-KR/about.json
index 114506c81..ef1666753 100644
--- a/src/renderer/src/i18n/ko-KR/about.json
+++ b/src/renderer/src/i18n/ko-KR/about.json
@@ -7,7 +7,7 @@
"checkUpdateButton": "업데이트 확인",
"updateChannel": "업데이트 채널",
"stableChannel": "안정 버전",
- "canaryChannel": "테스트 버전",
+ "betaChannel": "Beta",
"deviceInfo": {
"title": "장치 정보",
"platform": "플랫폼",
diff --git a/src/renderer/src/i18n/pt-BR/about.json b/src/renderer/src/i18n/pt-BR/about.json
index e1e02d593..433bfc7a2 100644
--- a/src/renderer/src/i18n/pt-BR/about.json
+++ b/src/renderer/src/i18n/pt-BR/about.json
@@ -15,5 +15,5 @@
"checkUpdateButton": "Verificar Atualizações",
"updateChannel": "Canal de Atualização",
"stableChannel": "Estável",
- "canaryChannel": "Canary"
+ "betaChannel": "Beta"
}
diff --git a/src/renderer/src/i18n/ru-RU/about.json b/src/renderer/src/i18n/ru-RU/about.json
index 04db38aef..ac4af0d6d 100644
--- a/src/renderer/src/i18n/ru-RU/about.json
+++ b/src/renderer/src/i18n/ru-RU/about.json
@@ -7,7 +7,7 @@
"checkUpdateButton": "Проверить обновления",
"updateChannel": "Канал обновлений",
"stableChannel": "Стабильный",
- "canaryChannel": "Канареечный",
+ "betaChannel": "Beta",
"deviceInfo": {
"title": "Сведения об устройстве",
"platform": "Платформа",
diff --git a/src/renderer/src/i18n/zh-CN/about.json b/src/renderer/src/i18n/zh-CN/about.json
index 88f9bfc1d..092dc8273 100644
--- a/src/renderer/src/i18n/zh-CN/about.json
+++ b/src/renderer/src/i18n/zh-CN/about.json
@@ -7,7 +7,7 @@
"checkUpdateButton": "检查更新",
"updateChannel": "更新渠道",
"stableChannel": "正式版",
- "canaryChannel": "内测版",
+ "betaChannel": "内测版",
"deviceInfo": {
"title": "设备信息",
"platform": "平台",
diff --git a/src/renderer/src/i18n/zh-HK/about.json b/src/renderer/src/i18n/zh-HK/about.json
index 091bf17e5..317079238 100644
--- a/src/renderer/src/i18n/zh-HK/about.json
+++ b/src/renderer/src/i18n/zh-HK/about.json
@@ -7,7 +7,7 @@
"checkUpdateButton": "檢查更新",
"updateChannel": "更新頻道",
"stableChannel": "正式版",
- "canaryChannel": "測試版",
+ "betaChannel": "内测版",
"deviceInfo": {
"title": "設備信息",
"platform": "平台",
diff --git a/src/renderer/src/i18n/zh-TW/about.json b/src/renderer/src/i18n/zh-TW/about.json
index 80ccdb87e..515c09a40 100644
--- a/src/renderer/src/i18n/zh-TW/about.json
+++ b/src/renderer/src/i18n/zh-TW/about.json
@@ -7,7 +7,7 @@
"checkUpdateButton": "檢查更新",
"updateChannel": "更新頻道",
"stableChannel": "正式版",
- "canaryChannel": "測試版",
+ "betaChannel": "内测版",
"deviceInfo": {
"title": "裝置資訊",
"platform": "平台",