Skip to content

Commit 69de0ad

Browse files
committed
chore(release): 更新版本至 0.8.4 并修复代码规范问题
1 parent 757c765 commit 69de0ad

File tree

30 files changed

+366
-202
lines changed

30 files changed

+366
-202
lines changed

.env.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/
22
ELECTRON_BUILDER_BINARIES_MIRROR=https://npmmirror.com/mirrors/electron-builder-binaries/
3+
PERO_VERSION=0.8.4

.github/workflows/build-electron.yml

Lines changed: 43 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -312,35 +312,51 @@ jobs:
312312
PeroCore-Electron/dist_electron/*.exe
313313
PeroCore-Portable-*.zip
314314
PeroCore-Browser-Extension.zip
315-
name: 'PeroCore ${{ github.ref_name }}'
315+
name: '萌动链接:PeroperoChat! ${{ github.ref_name }}'
316316
body: |
317-
## ${{ github.ref_name }} Release Notes
318-
319-
### Downloads
320-
- **Setup 安装版** (`.exe`): 推荐大多数用户使用,数据存储在系统用户目录
321-
- **Portable 便携版** (`.zip`): 解压即用,数据存储在程序目录下的 `data/` 文件夹中
322-
- **Browser Extension** (`.zip`): 浏览器扩展插件
323-
324-
### Architecture
325-
- Gateway embedded into Python backend (removed Go dependency)
326-
- Agent service refactored into 6 submodules
327-
- Build pipeline cleaned up (removed copy-gateway.js)
328-
329-
### Features
330-
- Auto-hide launcher after startup
331-
- 3D character system improvements
332-
- Pixel-style UI enhancements
333-
- **NEW: Portable version support**
334-
335-
### Stability
336-
- Fixed file:// URL format issue causing production build to not launch
337-
- Steam module lazy loading to prevent native crashes
338-
- Google Fonts localized for offline/China network support
339-
- Global exception handling improvements
340-
- TypeScript type fixes
341-
342-
Automated release by GitHub Actions
317+
## 🎉 ${{ github.ref_name }} 版本更新
318+
319+
> 萌动链接:PeroperoChat!是一款开源的 AI 桌面伴侣应用,集成本地大模型、3D 桌宠、Plugin 系统与多智能体框架。
320+
321+
---
322+
323+
### 📦 下载说明
324+
325+
| 文件 | 说明 | 推荐人群 |
326+
|------|------|----------|
327+
| `*-Setup-*.exe` | 安装版 | 普通用户,数据存储在系统用户目录 |
328+
| `PeroCore-Portable-*.zip` | 便携版(解压即用) | 随身携带或多设备使用,数据存储于 `data/` 文件夹 |
329+
| `PeroCore-Browser-Extension.zip` | 浏览器扩展 | 配合主程序在浏览器中使用 |
330+
331+
> ⚠️ Windows 可能弹出 SmartScreen 警告,点击"仍要运行"即可。本软件为开源项目,源码可在仓库中查阅。
332+
333+
---
334+
335+
### 🆕 本版本更新内容
336+
337+
#### ✨ 新特性
338+
- 请查阅本次 Commit 记录了解具体变更
339+
340+
#### 🐛 问题修复
341+
- 请查阅本次 Commit 记录了解具体变更
342+
343+
#### 🏗️ 架构优化
344+
- 请查阅本次 Commit 记录了解具体变更
345+
346+
---
347+
348+
### 🚀 快速开始
349+
350+
1. 下载并安装(安装版)或解压(便携版)
351+
2. 首次启动需同意《用户许可协议》
352+
3. 在启动器中配置 LLM API Key 后即可使用
353+
4. 详细使用文档请参阅 [项目 Wiki](https://github.com/${{ github.repository }}/wiki)
354+
355+
---
356+
357+
*由 GitHub Actions 自动构建发布 · 构建时间:${{ github.event.head_commit.timestamp }}*
343358
draft: false
344359
prerelease: false
345360
env:
346361
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
362+

backend/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "pero-backend"
3-
version = "0.8.3"
3+
version = "0.8.4"
44
description = "萌动链接:PeroperoChat! 后端服务"
55
requires-python = ">=3.10,<3.11"
66
dependencies = [

docs/STEAM_INTEGRATION_GUIDE.md

Lines changed: 70 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -32,30 +32,55 @@
3232

3333
为了确保资产加载的统一性,我们将对以下类型的资源进行联邦化管理。**注意:** 此处的“模型”指 Bedrock 3D 渲染资源(如 Rossi 形象),而非 AI 语言模型权重。
3434

35-
| 资产类型 (Type) | 物理位置 (Physical Path) | 说明 |
36-
| :--------------------- | :------------------------------ | :----------------------------------------- |
37-
| **3D 模型 (model_3d)** | `public/assets/3d/` | Bedrock 3D 模型文件夹 (含 `manifest.json`) |
38-
| **人设 (persona)** | `backend/services/mdp/(xxx...)` | 包含提示词组件、Agent 专属配置等 |
39-
| **插件 (plugin)** | `backend/nit_core/plugins/` | 具有独立功能的 Python 插件 |
40-
| **模组 (mod)** | `backend/mods/` | 用户自定义的功能扩展 |
41-
| **接口 (interface)** | `backend/interfaces/` | 系统核心接口定义与扩展 |
35+
| 资产类型 (Type) | 内置位置 (Official Path) | 标识文件 | 说明 |
36+
| :--- | :--- | :--- | :--- |
37+
| **人设 (persona)** | `@app/backend/services/mdp/agents/<name>/` | `asset.json` + `config.json` | 提示词、模式 Persona、碎碎念、头像 |
38+
| **插件 (plugin)** | `@app/backend/nit_core/plugins/<name>/` | `description.json` + `schema.json` | Python 插件入口 + OpenAI Tool 定义 |
39+
| **3D 模型 (model_3d)** | `@app/public/assets/3d/` | `manifest.json``.pero` | Bedrock 3D 模型,支持加密容器 |
40+
| **模组 (mod)** | `@app/backend/mods/<name>/` | `mod.toml` | 三层扩展体系 (EventBus/Pipeline/External) |
41+
42+
每种类型在用户覆盖层也有对应位置:`@data/custom/<type>/<name>/`
4243

4344
### 3.2 统一资产定义 (`asset.json`)
4445

45-
所有资产(无论是内置、本地还是创意工坊下载)均需在根目录包含一个 `manifest.json`(如果是 Bedrock 模型,则在现有 `manifest.json` 中嵌入元数据):
46+
新建资产的标准元数据文件为 `asset.json``AssetRegistry` 也兼容以下格式(按检测优先级排列):
47+
48+
| 优先级 | 文件名 | 适用类型 | 说明 |
49+
| :----- | :----- | :------- | :--- |
50+
| 1 | `asset.json` | 所有类型 | **标准格式**,新资产必须使用 |
51+
| 2 | `manifest.json` | model_3d | 兼容旧版 Bedrock 模型清单 |
52+
| 3 | `description.json` | plugin | 兼容现有插件格式(含 `entryPoint` 字段) |
53+
| 4 | `mod.toml` | mod | TOML 格式,从 `[mod]` section 读取 |
54+
55+
#### `asset.json` 标准格式
4656

4757
```json
4858
{
49-
"asset_id": "com.user.cute_pero_model",
50-
"type": "model_3d", // plugin | persona | model_3d | mod | interface
51-
"source": "workshop", // official | local | workshop
52-
"display_name": "超级可爱的 Pero 模型",
53-
"version": "1.0.2",
54-
"workshop_id": "123456789", // 仅当 source 为 workshop 时存在
55-
"config": {} // 特定资产配置
59+
"asset_id": "com.perocore.persona.pero",
60+
"type": "persona",
61+
"source": "official",
62+
"display_name": "Pero",
63+
"version": "1.0.0",
64+
"description": "看板娘Pero! 核心桌宠角色",
65+
"author": "PeroCore",
66+
"config": {
67+
"agent_id": "pero",
68+
"personas": ["work", "social", "group"],
69+
"social_enabled": true
70+
}
5671
}
5772
```
5873

74+
#### Asset ID 命名规范
75+
76+
采用反向域名格式:`<scope>.<type>.<name>`
77+
78+
| scope | 含义 | 示例 |
79+
| :---- | :--- | :--- |
80+
| `com.perocore` | 官方内置 | `com.perocore.persona.pero` |
81+
| `com.workshop` | 创意工坊 | `com.workshop.model.123456` |
82+
| `com.user` | 用户自定义 | `com.user.plugin.my_tool` |
83+
5984
---
6085

6186
## 4. 虚拟路径管理器 (Virtual Path Resolver)
@@ -90,7 +115,16 @@
90115

91116
### 4.3 资产注册表 (Asset Registry)
92117

93-
系统维护一个全局单例 `AssetRegistry`,负责扫描并注册所有可用资产。程序逻辑(如前端加载模型、后端加载人设)通过 `asset_id` 进行资源请求,由注册表根据虚拟路径解析出真实的物理地址。
118+
系统维护一个全局单例 `AssetRegistry` (`core/asset_registry.py`),负责扫描并注册所有可用资产。
119+
120+
**扫描顺序与冲突策略**:按 `official → workshop → local` 顺序扫描,**后者覆盖前者**(同 `asset_id` 时)。这意味着用户可以在 `@data/custom/` 中放置与官方同 ID 的资产来实现覆盖。
121+
122+
**关键 API**
123+
- `scan_all()` — 全量扫描所有来源目录
124+
- `get_asset(asset_id)` — 按 ID 检索已注册资产
125+
- `get_assets_by_type(type)` — 按类型查询所有资产
126+
127+
**代码位置**: [`asset_registry.py`](file:///c:/Users/Administrator/OneDrive/桌面/workspace/PeroCore/backend/core/asset_registry.py) | [`path_resolver.py`](file:///c:/Users/Administrator/OneDrive/桌面/workspace/PeroCore/backend/core/path_resolver.py)
94128

95129
---
96130

@@ -109,17 +143,23 @@
109143

110144
---
111145

112-
## 6. 后续行动计划 (Action Plan)
113-
114-
1. **[Backend] 虚拟路径适配**:
115-
- 实现 `core/path_resolver.py`,支持环境感知和逻辑路径转换。
116-
- 在 Python 端,识别 `sys.frozen` 或打包环境,动态调整 `@app` 路径。
117-
2. **[Backend] 资产加载重构**:
118-
-`MDPManager` (人设)、`PluginManager` (插件) 接入 `PathResolver`
119-
- 实现 `AssetRegistry` 统一管理 `backend/mods``backend/interfaces` 目录。
120-
3. **[Frontend] 模型加载适配**:
121-
- 更新 Bedrock 加载逻辑,支持从外部目录(如 `@workshop`)加载 3D 模型资产。
122-
4. **[DevOps] 目录规范化**:
123-
- 统一 `data` 目录入口,支持通过环境变量 `PERO_DATA_DIR` 迁移,为云同步做准备。
124-
5. **[Steam] 功能接入**:
125-
- 接入 Steamworks SDK 正式 App ID,测试 Overlay 弹出与云存档上传。
146+
## 6. 行动计划 (Action Plan)
147+
148+
### ✅ 已完成
149+
150+
1. **[Backend] 虚拟路径适配**: `core/path_resolver.py` 已实现,支持 `@app`/`@data`/`@workshop`/`@temp` 四个逻辑前缀,支持 `sys.frozen` 打包环境检测和 `PERO_DATA_DIR` 环境变量。
151+
2. **[Backend] AssetRegistry**: `core/asset_registry.py` 已实现全量扫描与冲突覆盖,支持 `asset.json``manifest.json``description.json``mod.toml` 四种元数据格式。
152+
3. **[Backend] 管理器接入**: `PluginManager``ModelManager` 均已通过 `get_asset_registry()` 查询资产,不再硬编码路径。
153+
4. **[Frontend] 模型联邦加载**: Electron 端 `assets.ts` 支持 `official`/`workshop`/`local` 三源扫描与 `asset://` 协议。
154+
5. **[DevOps] 目录规范**: `@data` 默认为 `@app/data`,可通过 `PERO_DATA_DIR` 环境变量迁移。
155+
6. **[Tool] PeroClawd!**: 资产创建工具已实现人设编辑器、插件工作台、3D 资产打包,含 `asset.json` 自动生成和 asset_id 规范校验。
156+
157+
### 🚧 进行中
158+
159+
7. **[Tool] PeroClawd! 资源管理器联动**: 将 PeroClawd! 的文件资源管理器与 `AssetRegistry` 的扫描逻辑对齐,实现从磁盘打开现有资产到工作台编辑的双向流程。
160+
8. **[Steam] 功能接入**: 接入 Steamworks SDK 正式 App ID (4457100),测试 Overlay 弹出与云存档上传。
161+
162+
### 📋 待规划
163+
164+
9. **[Tool] Mod 工作台**: 在 PeroClawd! 中新增 `mod.toml` 编辑器,覆盖三层扩展体系 (EventBus/Pipeline/External)。
165+
10. **[Workshop] 上传流程**: 从 PeroClawd! 直接发布资产到 Steam 创意工坊。

electron/main/services/tray.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,6 @@ export function createTray() {
4040

4141
try {
4242
const icon = nativeImage.createFromPath(iconPath)
43-
// 如需调整大小
44-
// icon.resize({ width: 16, height: 16 })
4543

4644
tray = new Tray(icon)
4745

electron/main/utils/env.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ if (isElectron) {
4040
} else if (!app.isPackaged) {
4141
// 开发模式:数据统一存放在项目的 backend/ 目录下
4242
// 这样 paths.data = {project}/backend/data/ 与 Python 后端数据位于同一目录
43-
const projectRoot = path.resolve(__dirname, '../../..') // dist-electron/main -> electron -> 项目根
43+
const projectRoot = path.resolve(__dirname, '../../..') // dist-electron/main -> electron -> 项目根
4444
appUserData = path.join(projectRoot, 'backend')
4545
console.log(`[Env] 开发模式,数据目录: ${appUserData}/data/`)
4646
} else {
@@ -75,7 +75,13 @@ export const isPortable = isElectron && isPackaged && detectPortableMode(appExe)
7575
* 用于 Logger 的双写:开发模式下日志同时存在项目目录 + 系统目录。
7676
*/
7777
export const systemUserData: string = isElectron
78-
? (() => { try { return require('electron').app.getPath('userData') } catch { return appUserData } })()
78+
? (() => {
79+
try {
80+
return require('electron').app.getPath('userData')
81+
} catch {
82+
return appUserData
83+
}
84+
})()
7985
: appUserData
8086

8187
export const paths = {

electron/main/utils/logger.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export type LogSource =
1919
class Logger {
2020
private static instance: Logger
2121
private logFile: string | null = null
22-
private secondaryLogFile: string | null = null // 开发模式下同时写入 %APPDATA%
22+
private secondaryLogFile: string | null = null // 开发模式下同时写入 %APPDATA%
2323

2424
// 隐藏模式 (降噪)
2525
// 优化: 组合正则以获得更好的性能
@@ -100,7 +100,7 @@ class Logger {
100100
// 动态获取路径,避免循环依赖
101101
// 注意: logger 在 env.ts 之前被加载,不能直接 import paths,需自行检测模式
102102
let primaryDir = ''
103-
let systemDir = '' // %APPDATA% 路径(用于开发模式双写)
103+
let systemDir = '' // %APPDATA% 路径(用于开发模式双写)
104104

105105
try {
106106
const { app } = require('electron')
@@ -115,7 +115,7 @@ class Logger {
115115
// 开发模式:主日志在 backend/data/logs/,同时写 %APPDATA% 副本
116116
const projectRoot = path.resolve(__dirname, '../../..')
117117
primaryDir = path.join(projectRoot, 'backend')
118-
systemDir = app.getPath('userData') // %APPDATA%/...
118+
systemDir = app.getPath('userData') // %APPDATA%/...
119119
} else {
120120
// 发行模式
121121
primaryDir = app.getPath('userData')
@@ -143,7 +143,10 @@ class Logger {
143143
fs.mkdirSync(sysLogDir, { recursive: true })
144144
}
145145
this.secondaryLogFile = path.join(sysLogDir, 'main.log')
146-
fs.writeFileSync(this.secondaryLogFile, `--- Log started at ${new Date().toISOString()} (dev secondary) ---\n`)
146+
fs.writeFileSync(
147+
this.secondaryLogFile,
148+
`--- Log started at ${new Date().toISOString()} (dev secondary) ---\n`
149+
)
147150
}
148151
} catch (e) {
149152
console.error('[Logger] 初始化日志文件失败:', e)

electron/main/windows/manager.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,10 @@ export class WindowManager {
162162
}
163163

164164
public hideLauncherWindow() {
165-
logger.info('Main', `hideLauncherWindow 被调用, 当前窗口状态: ${this.launcherWin ? '存在' : '不存在'}, 销毁状态: ${this.launcherWin?.isDestroyed()}`)
165+
logger.info(
166+
'Main',
167+
`hideLauncherWindow 被调用, 当前窗口状态: ${this.launcherWin ? '存在' : '不存在'}, 销毁状态: ${this.launcherWin?.isDestroyed()}`
168+
)
166169
if (this.launcherWin && !this.launcherWin.isDestroyed()) {
167170
this.launcherWin.hide()
168171
logger.info('Main', '已执行 launcherWin.hide()')

package.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "peropero-chat",
33
"private": true,
4-
"version": "0.8.3",
4+
"version": "0.8.4",
55
"description": "萌动链接:PeroperoChat!- 一个充满活力的 3D 桌面宠物应用",
66
"author": "YoKONCy",
77
"license": "Apache-2.0",
@@ -11,6 +11,11 @@
1111
},
1212
"main": "dist-electron/main/index.js",
1313
"scripts": {
14+
"sync-version": "node scripts/sync-version.js",
15+
"predev:electron": "npm run sync-version",
16+
"prebuild:electron": "npm run sync-version",
17+
"prebuild:steam": "npm run sync-version",
18+
"prebuild:portable": "npm run sync-version",
1419
"dev:electron": "concurrently -k \"tsc -p electron/tsconfig.json -w\" \"vite\" \"wait-on tcp:127.0.0.1:5173 && cross-env VITE_DEV_SERVER_URL=http://127.0.0.1:5173 electron .\"",
1520
"build:backend": "node scripts/build-backend.js",
1621
"build:docker": "vite build --mode docker",
@@ -175,6 +180,10 @@
175180
"!**/*.pdb",
176181
"!**/nit_core/plugins/social_adapter/NapCat"
177182
]
183+
},
184+
{
185+
"from": "public/Logo.png",
186+
"to": "Logo.png"
178187
}
179188
],
180189
"win": {

scripts/sync-version.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
const fs = require('fs')
2+
const path = require('path')
3+
4+
const envPath = path.join(__dirname, '../.env')
5+
const pkgPath = path.join(__dirname, '../package.json')
6+
const pyTomlPath = path.join(__dirname, '../backend/pyproject.toml')
7+
8+
let version = '0.8.3' // Default fallback
9+
10+
// 1. Read version from .env
11+
if (fs.existsSync(envPath)) {
12+
const envContent = fs.readFileSync(envPath, 'utf-8')
13+
// Match PERO_VERSION=x.y.z
14+
const match = envContent.match(/^PERO_VERSION\s*=\s*(.+)$/m)
15+
if (match) {
16+
version = match[1].replace(/['"]/g, '').trim()
17+
} else {
18+
console.log('[Version Sync] PERO_VERSION not found in .env, using default version:', version)
19+
}
20+
} else {
21+
console.log('[Version Sync] .env not found, using default version:', version)
22+
}
23+
24+
function updateVersion() {
25+
let updated = false
26+
27+
// 2. Update package.json
28+
if (fs.existsSync(pkgPath)) {
29+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'))
30+
if (pkg.version !== version) {
31+
pkg.version = version
32+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n')
33+
console.log(`[Version Sync] package.json updated to ${version}`)
34+
updated = true
35+
}
36+
}
37+
38+
// 3. Update backend/pyproject.toml
39+
if (fs.existsSync(pyTomlPath)) {
40+
let pyToml = fs.readFileSync(pyTomlPath, 'utf8')
41+
const replaced = pyToml.replace(/^version\s*=\s*".*"/m, `version = "${version}"`)
42+
if (pyToml !== replaced) {
43+
fs.writeFileSync(pyTomlPath, replaced)
44+
console.log(`[Version Sync] backend/pyproject.toml updated to ${version}`)
45+
updated = true
46+
}
47+
}
48+
49+
if (!updated) {
50+
console.log(`[Version Sync] All versions are already up-to-date (${version})`)
51+
}
52+
}
53+
54+
updateVersion()

0 commit comments

Comments
 (0)