diff --git a/.changeset/witty-ideas-flow.md b/.changeset/witty-ideas-flow.md
new file mode 100644
index 00000000..3bba43a5
--- /dev/null
+++ b/.changeset/witty-ideas-flow.md
@@ -0,0 +1,15 @@
+---
+"@promptx/desktop": patch
+---
+feat: 角色/工具详情面板添加导出按钮,支持 v1 和 v2 角色导出
+
+- 角色和工具详情面板右上角新增导出按钮(非 system 资源可见)
+- 后端 resources:download 支持 version 参数,v2 角色正确定位 ~/.rolex/roles/ 目录
+- v2 角色导出的 ZIP 以 roleId 为顶层目录,确保导入时还原正确 ID
+- 添加 i18n 键:export / exportSuccess / exportFailed(中英文)
+
+fix: macOS 上 AgentX 对话时子进程不再显示 Dock 图标
+
+- macOS 启动时检测 Electron Helper 二进制(LSUIElement=true),用于 spawn 子进程
+- buildOptions 和 AgentXService 的 MCP server 在 macOS 上优先使用 Helper 二进制
+- 所有 spawn 调用添加 windowsHide: true
diff --git a/CENSUS_PARSER_FIX.md b/CENSUS_PARSER_FIX.md
new file mode 100644
index 00000000..a9effaca
--- /dev/null
+++ b/CENSUS_PARSER_FIX.md
@@ -0,0 +1,214 @@
+# Census.list 文本解析器修复
+
+## 问题描述
+
+用户报告在角色页面看不到组织,尽管通过 `directory` 操作可以看到两个组织:
+1. rolex (RoleX) - 系统组织
+2. 火花堆栈人工智能有限公司 - 用户创建的组织
+
+## 根本原因
+
+RoleX 1.1.0 的 `census.list` 返回的是**文本格式**的输出,而不是 JSON 结构化数据。原代码期望的是 JSON 格式,导致解析失败。
+
+### census.list 输出格式示例
+
+```
+rolex (RoleX)
+ nuwa (女娲, nvwa) — individual-manager, organization-manager, position-manager
+
+火花堆栈人工智能有限公司
+ Node全栈工程师 — Node全栈工程师岗位
+ 测试工程师 — 测试工程师岗位
+ AI系统架构师 — AI系统架构师岗位
+ UI设计师 — UI设计师岗位
+ 产品经理 — 产品经理岗位
+```
+
+## 解决方案
+
+### 1. 添加文本解析器
+
+在 `RolexBridge.js` 中添加 `_parseCensusOutput()` 方法,将文本格式转换为结构化 JSON:
+
+```javascript
+_parseCensusOutput(text) {
+ const result = {
+ roles: [],
+ organizations: []
+ }
+
+ // 解析逻辑:
+ // 1. 识别组织行(无缩进)
+ // 2. 识别角色行(有缩进,描述包含 manager 等关键词)
+ // 3. 识别职位行(有缩进,描述是职位说明)
+
+ return result
+}
+```
+
+### 2. 区分角色和职位
+
+**关键判断逻辑:**
+- **角色**:描述包含多个逗号分隔的职位,或包含 "manager"、"individual"、"organization"、"position" 等关键词
+- **职位**:描述是职位说明文本(如"Node全栈工程师岗位")
+
+### 3. 输出结构
+
+```json
+{
+ "roles": [
+ {
+ "name": "nuwa",
+ "org": "rolex (RoleX)",
+ "position": "individual-manager"
+ }
+ ],
+ "organizations": [
+ {
+ "name": "rolex (RoleX)",
+ "members": [
+ {
+ "name": "nuwa",
+ "position": "individual-manager"
+ }
+ ],
+ "positions": []
+ },
+ {
+ "name": "火花堆栈人工智能有限公司",
+ "members": [],
+ "positions": [
+ {
+ "name": "Node全栈工程师",
+ "description": "Node全栈工程师岗位"
+ },
+ ...
+ ]
+ }
+ ]
+}
+```
+
+## 文件改动
+
+### 1. `packages/core/src/rolex/RolexBridge.js`
+- 修改 `directory()` 方法,调用 `_parseCensusOutput()` 解析文本
+- 添加 `_parseCensusOutput()` 私有方法
+
+### 2. `apps/desktop/src/main/windows/ResourceListWindow.ts`
+- 移除 `rolex:directory` handler 中的 `JSON.parse()`
+- 移除 `resources:getV2RoleData` handler 中的 `JSON.parse()`
+
+### 3. `apps/desktop/src/view/pages/roles-window/index.tsx`
+- 移除前端的 `JSON.parse()`
+
+## 测试结果
+
+### 解析前(错误)
+```
+角色列表包含职位定义:
+- nuwa
+- Node全栈工程师 ❌ 这是职位,不是角色
+- 测试工程师 ❌ 这是职位,不是角色
+...
+```
+
+### 解析后(正确)
+```
+角色列表:
+- nuwa (rolex (RoleX) - individual-manager) ✅
+
+组织列表:
+- rolex (RoleX)
+ 成员: nuwa [individual-manager] ✅
+
+- 火花堆栈人工智能有限公司
+ 职位: Node全栈工程师, 测试工程师, ... ✅
+ 成员: (空,因为还没有任命角色到职位)
+```
+
+## 为什么看不到"火花堆栈人工智能有限公司"组织?
+
+**原因:该组织没有成员!**
+
+虽然组织定义了 5 个职位,但还没有任命任何角色到这些职位。树状列表只显示**有成员的组织**。
+
+## 如何让组织显示在列表中?
+
+需要任命角色到职位:
+
+```javascript
+// 1. 创建一个新角色(或使用现有角色)
+// 假设已有角色 "alice"
+
+// 2. 任命角色到职位
+{
+ "operation": "require",
+ "role": "nuwa",
+ "orgName": "火花堆栈人工智能有限公司",
+ "position": "Node全栈工程师",
+ "individual": "alice"
+}
+```
+
+任命后,`census.list` 输出会变成:
+
+```
+火花堆栈人工智能有限公司
+ alice — Node全栈工程师
+ Node全栈工程师 — Node全栈工程师岗位
+ ...
+```
+
+此时解析器会识别:
+- `alice` 是角色(因为描述是职位名称,不是职位说明)
+- `Node全栈工程师` 是职位定义
+
+## 下一步
+
+1. **重启 PromptX Desktop**
+2. **打开角色窗口**
+3. **切换到 V2 Rolex 标签**
+4. **应该能看到 "rolex (RoleX)" 组织,展开后看到 nuwa**
+5. **任命角色到"火花堆栈人工智能有限公司"的职位**
+6. **刷新后应该能看到该组织**
+
+## 调试命令
+
+### 查看解析后的目录数据
+```javascript
+window.electronAPI?.invoke("rolex:directory", {}).then(result => {
+ console.log('Directory:', result.data)
+ console.log('Organizations:', result.data.organizations)
+ console.log('Roles:', result.data.roles)
+})
+```
+
+### 查看原始 census.list 输出
+通过 MCP action 工具:
+```json
+{
+ "role": "nuwa",
+ "operation": "directory"
+}
+```
+
+## 注意事项
+
+1. **职位 vs 角色**:census.list 中同时包含职位定义和角色任命,需要正确区分
+2. **空组织**:没有成员的组织不会显示在树状列表中(这是设计行为)
+3. **组织名称**:包含括号的组织名称(如 "rolex (RoleX)")会被完整保留
+4. **多职位角色**:如果角色担任多个职位,只显示第一个职位
+
+## 已知限制
+
+1. **解析启发式**:使用关键词判断是否为角色,可能在某些边缘情况下误判
+2. **职位描述格式**:假设职位描述不包含逗号和 manager 等关键词
+3. **文本格式依赖**:依赖 census.list 的固定文本格式,如果 RoleX 更新格式可能需要调整解析器
+
+## 改进建议
+
+如果 RoleX 未来提供结构化 API(返回 JSON),应该:
+1. 优先使用结构化 API
+2. 保留文本解析器作为后备方案
+3. 添加版本检测逻辑
diff --git a/ORGANIZATION_API_GUIDE.md b/ORGANIZATION_API_GUIDE.md
new file mode 100644
index 00000000..d1b34f71
--- /dev/null
+++ b/ORGANIZATION_API_GUIDE.md
@@ -0,0 +1,314 @@
+# 角色组织架构 API 使用指南
+
+## 概述
+
+PromptX 集成了 RoleX 1.1.0,支持完整的组织架构管理功能。本文档介绍如何获取和管理角色的组织架构信息。
+
+## 1. 获取组织目录(Directory)
+
+### 方法:`directory()`
+
+获取整个社会目录,包含所有角色和组织的信息。
+
+```javascript
+const { RolexActionDispatcher } = require('@promptx/core').rolex
+const dispatcher = new RolexActionDispatcher()
+
+// 获取完整的组织目录
+const directoryResult = await dispatcher.dispatch('directory', {})
+
+// directory 返回的是 JSON 字符串,需要解析
+const directory = JSON.parse(directoryResult)
+
+console.log(directory)
+// 输出结构:
+// {
+// roles: [
+// { name: "角色ID", org: "组织名称", position: "职位名称" },
+// ...
+// ],
+// organizations: [
+// { name: "组织名称", charter: "组织章程", members: [...] },
+// ...
+// ]
+// }
+```
+
+### 从目录中查找特定角色的组织信息
+
+```javascript
+const directory = JSON.parse(directoryResult)
+
+// 查找角色的组织信息
+const roleId = "nuwa"
+const roleEntry = directory.roles?.find(r => r.name === roleId)
+
+if (roleEntry && roleEntry.org) {
+ const orgName = roleEntry.org
+ const position = roleEntry.position
+
+ // 查找组织详情
+ const org = directory.organizations?.find(o => o.name === orgName)
+
+ console.log(`角色 ${roleId} 属于组织 ${orgName}`)
+ console.log(`职位:${position}`)
+ console.log(`组织章程:${org?.charter}`)
+ console.log(`组织成员:`, org?.members)
+} else {
+ console.log(`角色 ${roleId} 未加入任何组织`)
+}
+```
+
+## 2. 组织管理操作
+
+### 2.1 创建组织(Synthesize)
+
+```javascript
+// 创建新组织
+await dispatcher.dispatch('synthesize', {
+ role: 'founder-role-id', // 创建者角色ID
+ name: 'MyOrganization', // 组织名称
+ charter: '组织章程内容' // 组织章程
+})
+```
+
+### 2.2 定义组织章程(Charter)
+
+```javascript
+// 为组织定义或更新章程
+await dispatcher.dispatch('charter', {
+ role: 'admin-role-id',
+ orgName: 'MyOrganization',
+ content: '更新后的组织章程内容'
+})
+```
+
+### 2.3 解散组织(Dissolve)
+
+```javascript
+// 解散组织
+await dispatcher.dispatch('dissolve', {
+ role: 'admin-role-id',
+ orgName: 'MyOrganization'
+})
+```
+
+## 3. 职位管理操作
+
+### 3.1 设立职位(Charge)
+
+```javascript
+// 在组织中设立新职位
+await dispatcher.dispatch('charge', {
+ role: 'admin-role-id',
+ orgName: 'MyOrganization',
+ position: 'Engineer', // 职位名称
+ procedure: '职位职责描述' // 职位流程/职责
+})
+```
+
+### 3.2 任命角色到职位(Require)
+
+```javascript
+// 任命角色到特定职位
+await dispatcher.dispatch('require', {
+ role: 'admin-role-id',
+ orgName: 'MyOrganization',
+ position: 'Engineer',
+ individual: 'target-role-id' // 被任命的角色ID
+})
+```
+
+### 3.3 撤销职位(Abolish)
+
+```javascript
+// 撤销组织中的职位
+await dispatcher.dispatch('abolish', {
+ role: 'admin-role-id',
+ orgName: 'MyOrganization',
+ position: 'Engineer'
+})
+```
+
+## 4. 在前端获取组织信息
+
+### 4.1 通过 IPC 调用
+
+```typescript
+// 在 Electron 渲染进程中
+const result = await window.electronAPI?.invoke('resources:getV2RoleData', {
+ roleId: 'nuwa'
+})
+
+if (result?.success) {
+ const { identity, focus, directory } = result
+
+ // directory 已经是解析后的对象
+ const roleEntry = directory?.roles?.find(r => r.name === 'nuwa')
+ const orgName = roleEntry?.org
+ const position = roleEntry?.position
+ const org = orgName ? directory?.organizations?.find(o => o.name === orgName) : null
+
+ console.log('组织信息:', {
+ orgName,
+ position,
+ charter: org?.charter,
+ members: org?.members
+ })
+}
+```
+
+### 4.2 使用 React Hook
+
+```typescript
+// 在 React 组件中使用
+function MyComponent({ roleId }: { roleId: string }) {
+ const [orgInfo, setOrgInfo] = useState(null)
+
+ useEffect(() => {
+ const loadOrgInfo = async () => {
+ const result = await window.electronAPI?.invoke('resources:getV2RoleData', {
+ roleId
+ })
+
+ if (result?.success && result.directory) {
+ const roleEntry = result.directory.roles?.find(r => r.name === roleId)
+ if (roleEntry?.org) {
+ const org = result.directory.organizations?.find(
+ o => o.name === roleEntry.org
+ )
+ setOrgInfo({
+ orgName: roleEntry.org,
+ position: roleEntry.position,
+ org
+ })
+ }
+ }
+ }
+
+ loadOrgInfo()
+ }, [roleId])
+
+ return (
+
+ {orgInfo ? (
+ <>
+
组织:{orgInfo.orgName}
+
职位:{orgInfo.position}
+
章程:{orgInfo.org?.charter}
+ >
+ ) : (
+
未加入任何组织
+ )}
+
+ )
+}
+```
+
+## 5. 完整示例:组织管理流程
+
+```javascript
+const { RolexActionDispatcher } = require('@promptx/core').rolex
+const dispatcher = new RolexActionDispatcher()
+
+async function organizationExample() {
+ // 1. 创建组织
+ await dispatcher.dispatch('synthesize', {
+ role: 'founder',
+ name: 'TechCorp',
+ charter: '致力于技术创新的组织'
+ })
+
+ // 2. 设立职位
+ await dispatcher.dispatch('charge', {
+ role: 'founder',
+ orgName: 'TechCorp',
+ position: 'CTO',
+ procedure: '负责技术战略和团队管理'
+ })
+
+ await dispatcher.dispatch('charge', {
+ role: 'founder',
+ orgName: 'TechCorp',
+ position: 'Engineer',
+ procedure: '负责产品开发和维护'
+ })
+
+ // 3. 任命角色到职位
+ await dispatcher.dispatch('require', {
+ role: 'founder',
+ orgName: 'TechCorp',
+ position: 'CTO',
+ individual: 'alice'
+ })
+
+ await dispatcher.dispatch('require', {
+ role: 'founder',
+ orgName: 'TechCorp',
+ position: 'Engineer',
+ individual: 'bob'
+ })
+
+ // 4. 查看组织结构
+ const directoryResult = await dispatcher.dispatch('directory', {})
+ const directory = JSON.parse(directoryResult)
+
+ const org = directory.organizations?.find(o => o.name === 'TechCorp')
+ console.log('TechCorp 组织结构:', org)
+
+ // 5. 查看特定角色的组织信息
+ const aliceEntry = directory.roles?.find(r => r.name === 'alice')
+ console.log('Alice 的组织信息:', {
+ org: aliceEntry?.org,
+ position: aliceEntry?.position
+ })
+}
+```
+
+## 6. 数据结构说明
+
+### Directory 结构
+
+```typescript
+interface Directory {
+ roles: Array<{
+ name: string // 角色ID
+ org?: string // 所属组织名称(可选)
+ position?: string // 在组织中的职位(可选)
+ }>
+ organizations: Array<{
+ name: string // 组织名称
+ charter?: string // 组织章程
+ members?: Array<{ // 成员列表
+ name: string // 成员角色ID
+ position: string // 职位
+ }>
+ }>
+}
+```
+
+## 7. 注意事项
+
+1. **V2 角色专属**:组织架构功能仅适用于 RoleX V2 角色,V1 角色不支持
+2. **权限管理**:某些操作(如解散组织、撤销职位)可能需要特定权限
+3. **数据持久化**:组织信息存储在 RoleX SQLite 数据库中(`~/.rolex/rolex.db`)
+4. **字符串格式**:`directory()` 返回的是 JSON 字符串,需要使用 `JSON.parse()` 解析
+
+## 8. 相关文件
+
+- **后端 API**:`packages/core/src/rolex/RolexBridge.js`
+- **前端组件**:`apps/desktop/src/view/pages/roles-window/components/RoleDetailPanel.tsx`
+- **IPC Handler**:`apps/desktop/src/main/windows/ResourceListWindow.ts` (line 984-1011)
+- **MCP 工具**:`packages/mcp-server/src/tools/action.ts`
+
+## 9. 相关操作列表
+
+| 操作 | 方法 | 说明 |
+|------|------|------|
+| 获取目录 | `directory()` | 获取所有角色和组织信息 |
+| 创建组织 | `synthesize(name, charter)` | 创建新组织 |
+| 定义章程 | `charter(orgName, content)` | 定义或更新组织章程 |
+| 解散组织 | `dissolve(orgName)` | 解散组织 |
+| 设立职位 | `charge(orgName, position, procedure)` | 在组织中设立职位 |
+| 任命角色 | `require(orgName, position, individual)` | 任命角色到职位 |
+| 撤销职位 | `abolish(orgName, position)` | 撤销组织中的职位 |
diff --git a/ROLEX_UPGRADE_GUIDE.md b/ROLEX_UPGRADE_GUIDE.md
new file mode 100644
index 00000000..bb38a4e4
--- /dev/null
+++ b/ROLEX_UPGRADE_GUIDE.md
@@ -0,0 +1,257 @@
+# PromptX RoleX v2 升级到 1.1.0 指南
+
+## 当前状态
+
+- **RoleX 版本**: 1.1.0
+- **问题**: v2 角色列表显示 0 个角色
+- **原因**: RoleX 1.1.0 使用 SQLite 数据库存储,需要重新初始化
+
+## 升级步骤
+
+### 1. 备份现有数据(可选)
+
+如果你有重要的 v2 角色数据,先备份:
+
+```bash
+# 备份旧的 RoleX 数据
+cp -r ~/.rolex ~/.rolex.backup.$(date +%Y%m%d)
+```
+
+### 2. 清理旧数据
+
+RoleX 1.1.0 使用全新的数据库存储,旧的文件系统数据不兼容。建议清理:
+
+```bash
+# 删除旧的 RoleX 数据(会删除所有 v2 角色)
+rm -rf ~/.rolex
+
+# 或者只删除数据库文件,保留 roles 目录作为参考
+rm -f ~/.rolex/rolex.db
+```
+
+**注意**: 这会删除所有现有的 v2 角色数据。如果需要保留,请先备份。
+
+### 3. 重新初始化 RoleX
+
+RoleX 1.1.0 会在首次运行时自动调用 `genesis()` 创建初始世界。
+
+当前代码已经包含了 genesis 调用(RolexBridge.js line 98):
+
+```javascript
+await this.rolex.genesis()
+```
+
+### 4. 验证升级
+
+重新启动 PromptX Desktop 应用,然后:
+
+1. 打开角色窗口
+2. 切换到 "RoleX" 标签
+3. 应该能看到初始角色(如 nuwa)
+
+### 5. 检查日志
+
+查看日志确认初始化成功:
+
+```bash
+tail -f ~/.promptx/logs/promptx-$(date +%Y-%m-%d).log | grep -i rolex
+```
+
+应该看到类似的日志:
+
+```
+[RolexBridge] Initializing RoleX...
+[RolexBridge] Creating platform...
+[RolexBridge] Creating Rolex instance...
+[RolexBridge] Running genesis...
+[RolexBridge] RoleX initialized successfully
+[RolexBridge] Census result: [...]
+[RolexBridge] Found X V2 roles from database
+```
+
+## 已知问题和解决方案
+
+### 问题 1: Census 返回空数组
+
+**症状**: 日志显示 `[RolexBridge] Census result:` 后面是空的
+
+**原因**:
+1. genesis() 可能没有正确执行
+2. 或者 census.list 返回格式不符合预期
+
+**解决方案**:
+
+检查 census.list 的返回格式。根据 RoleX 源码分析,census.list 应该返回 `CensusEntry[]` 数组:
+
+```typescript
+interface CensusEntry {
+ id?: string;
+ name: string;
+ tag?: string;
+}
+```
+
+当前代码(RolexBridge.js line 349-366)已经处理了这个格式。
+
+### 问题 2: 数据库权限问题
+
+**症状**: 初始化失败,提示数据库错误
+
+**解决方案**:
+
+```bash
+# 确保目录权限正确
+chmod 755 ~/.rolex
+chmod 644 ~/.rolex/rolex.db
+```
+
+### 问题 3: Node.js 版本不兼容
+
+**症状**: SQLite 相关错误
+
+**要求**: Node.js 22+ 或 Bun
+
+**解决方案**: 升级 Node.js 或使用 Bun
+
+## 代码修改总结
+
+已完成的修改(在 `packages/core/src/rolex/RolexBridge.js`):
+
+1. ✅ **localPlatform 配置** (line 91)
+ ```javascript
+ this.platform = localPlatform({ dataDir: this.rolexRoot })
+ ```
+
+2. ✅ **Rolex.create()** (line 94)
+ ```javascript
+ this.rolex = await Rolex.create(this.platform)
+ ```
+
+3. ✅ **genesis() 调用** (line 98)
+ ```javascript
+ await this.rolex.genesis()
+ ```
+
+4. ✅ **listV2Roles() 数据库查询** (line 339-410)
+ - 使用 `rolex.direct('!census.list')` 查询
+ - 降级方案使用 `platform.repository.runtime`
+
+## 测试步骤
+
+### 1. 重新构建
+
+```bash
+cd /e/Users/DF/Desktop/11111/PromptX
+pnpm build:core
+pnpm build:desktop
+```
+
+### 2. 启动应用
+
+启动 PromptX Desktop 应用
+
+### 3. 检查角色列表
+
+1. 打开角色窗口
+2. 切换到 "RoleX" 标签
+3. 应该看到至少 1 个角色(nuwa)
+
+### 4. 测试 census.list
+
+在应用中激活 nuwa 角色,然后执行:
+
+```javascript
+// 通过 MCP 或直接调用
+await rolex.direct('!census.list')
+```
+
+应该返回类似:
+
+```json
+[
+ {
+ "id": "nuwa",
+ "name": "Nuwa",
+ "tag": null
+ }
+]
+```
+
+## 如果仍然没有角色
+
+### 调试步骤
+
+1. **检查 genesis 是否执行**
+
+查看日志中是否有 "Running genesis" 和 "RoleX initialized successfully"
+
+2. **手动查询数据库**
+
+```bash
+# 如果有 sqlite3 命令
+sqlite3 ~/.rolex/rolex.db "SELECT * FROM nodes WHERE name='individual';"
+```
+
+3. **检查 bootstrap 配置**
+
+确认 localPlatform 配置中包含 bootstrap:
+
+```javascript
+this.platform = localPlatform({
+ dataDir: this.rolexRoot,
+ bootstrap: ['npm:@rolexjs/genesis'] // 添加这一行
+})
+```
+
+4. **强制重新初始化**
+
+```bash
+# 删除数据库
+rm -f ~/.rolex/rolex.db
+
+# 重启应用,会重新运行 genesis
+```
+
+## 迁移现有角色(可选)
+
+如果你有旧的 v2 角色需要迁移到 1.1.0:
+
+### 方案 1: 手动重建
+
+1. 导出旧角色的 Feature 内容
+2. 使用 `!individual.born` 重新创建
+3. 使用 `!individual.train` 添加技能
+
+### 方案 2: 使用 ResourceX
+
+1. 将旧角色打包为 ResourceX 资源
+2. 使用 `!prototype.summon` 导入
+
+## 提交更改
+
+完成升级后,提交代码:
+
+```bash
+cd /e/Users/DF/Desktop/11111/PromptX
+git add packages/core/src/rolex/RolexBridge.js
+git commit -m "feat(core): complete RoleX 1.1.0 migration
+
+- Use Rolex.create() instead of new Rolex()
+- Add genesis() call for world initialization
+- Update listV2Roles() to query from database via census.list
+- Fix localPlatform configuration with dataDir object"
+```
+
+## 参考文档
+
+- RoleX 1.1.0 源码分析: `RoleX-Analysis-Phase*.md`
+- RoleX GitHub: https://github.com/Deepractice/RoleX
+- Genesis 包: `@rolexjs/genesis`
+
+## 需要帮助?
+
+如果升级过程中遇到问题:
+
+1. 检查日志文件: `~/.promptx/logs/promptx-*.log`
+2. 查看 RoleX 数据目录: `~/.rolex/`
+3. 确认 Node.js 版本: `node --version` (需要 22+)
diff --git a/ROLEX_UPGRADE_QUICK.md b/ROLEX_UPGRADE_QUICK.md
new file mode 100644
index 00000000..39721e0d
--- /dev/null
+++ b/ROLEX_UPGRADE_QUICK.md
@@ -0,0 +1,113 @@
+# RoleX v2 升级到 1.1.0 - 快速指南
+
+## 🎯 核心问题
+
+RoleX 1.1.0 使用 SQLite 数据库存储,不再使用文件系统。需要重新初始化。
+
+## ⚡ 快速升级步骤
+
+### 1. 清理旧数据
+
+```bash
+# 删除旧的 RoleX 数据库(会清空所有 v2 角色)
+rm -f ~/.rolex/rolex.db
+
+# 或者完全重置(推荐)
+rm -rf ~/.rolex
+```
+
+**⚠️ 警告**: 这会删除所有现有的 v2 角色。如需保留,请先备份:
+```bash
+cp -r ~/.rolex ~/.rolex.backup
+```
+
+### 2. 重启应用
+
+重新启动 PromptX Desktop 应用。
+
+应用会自动:
+1. 创建新的 SQLite 数据库
+2. 运行 `genesis()` 初始化世界
+3. 创建 Nuwa 种子角色
+
+### 3. 验证
+
+打开角色窗口 → 切换到 "RoleX" 标签 → 应该看到 **nuwa** 角色
+
+## 🔧 已完成的代码修改
+
+所有必要的代码修改已完成:
+
+1. ✅ **添加 bootstrap 配置** - 注册 Genesis 原型
+2. ✅ **使用 Rolex.create()** - 替代 new Rolex()
+3. ✅ **调用 genesis()** - 初始化世界
+4. ✅ **数据库查询** - 使用 census.list 查询角色
+
+## 📋 检查清单
+
+- [ ] 删除旧数据库: `rm -f ~/.rolex/rolex.db`
+- [ ] 重启 PromptX Desktop
+- [ ] 打开角色窗口
+- [ ] 切换到 "RoleX" 标签
+- [ ] 确认看到 nuwa 角色
+
+## 🐛 故障排除
+
+### 问题: 仍然显示 0 个角色
+
+**解决方案 1**: 完全重置
+```bash
+rm -rf ~/.rolex
+# 重启应用
+```
+
+**解决方案 2**: 检查日志
+```bash
+tail -f ~/.promptx/logs/promptx-$(date +%Y-%m-%d).log | grep -i rolex
+```
+
+应该看到:
+```
+[RolexBridge] Running genesis...
+[RolexBridge] RoleX initialized successfully
+[RolexBridge] Found X V2 roles from database
+```
+
+### 问题: Genesis 失败
+
+**可能原因**: Node.js 版本过低
+
+**解决方案**: 确保 Node.js 22+ 或使用 Bun
+```bash
+node --version # 应该 >= 22
+```
+
+## 📝 提交更改
+
+```bash
+git add packages/core/src/rolex/RolexBridge.js
+git commit -m "feat(core): complete RoleX 1.1.0 migration with bootstrap config"
+```
+
+## 🎓 关键变化
+
+| 项目 | 0.11.0 | 1.1.0 |
+|------|--------|-------|
+| 存储 | 文件系统 (`~/.rolex/roles/`) | SQLite 数据库 (`~/.rolex/rolex.db`) |
+| 初始化 | `bootstrap()` | `genesis()` |
+| 实例化 | `new Rolex(platform)` | `await Rolex.create(platform)` |
+| Platform | `localPlatform(path)` | `localPlatform({ dataDir, bootstrap })` |
+| 角色查询 | 文件系统扫描 | 数据库查询 (`census.list`) |
+
+## ✨ 新功能
+
+- **Genesis 系统**: 自动创建初始世界和 Nuwa 角色
+- **Census 查询**: 统一的实体查询接口
+- **数据库存储**: 更高效的数据管理
+- **原型系统**: 支持角色模板和复用
+
+## 📚 参考
+
+- 详细升级指南: `ROLEX_UPGRADE_GUIDE.md`
+- RoleX 源码分析: `RoleX-Analysis-Phase*.md`
+- RoleX GitHub: https://github.com/Deepractice/RoleX
diff --git a/V2_ROLE_TREE_CHANGES.md b/V2_ROLE_TREE_CHANGES.md
new file mode 100644
index 00000000..cdd90f45
--- /dev/null
+++ b/V2_ROLE_TREE_CHANGES.md
@@ -0,0 +1,213 @@
+# V2 角色树状列表和数据修复
+
+## 改动概述
+
+本次更新主要解决两个问题:
+1. V2 角色列表改为树状结构,按组织分组显示
+2. 修复 V2 角色详细页的数据显示问题(适配 RoleX 1.1.0 数据库架构)
+
+## 文件改动
+
+### 1. 新增文件
+
+#### `apps/desktop/src/view/pages/roles-window/components/RoleTreeListPanel.tsx`
+- 新的树状角色列表组件
+- 支持按组织分组显示 V2 角色
+- 显示组织章程、职位信息
+- 可展开/折叠组织节点
+- 独立角色单独分组显示
+- V1 角色保持平面列表显示
+
+**主要特性:**
+- 组织节点显示:组织名称、章程、成员数量
+- 角色节点显示:角色名称、职位标签、来源标签、描述
+- 树状缩进和连接线视觉效果
+- 支持搜索和筛选
+
+### 2. 修改文件
+
+#### `apps/desktop/src/view/pages/roles-window/index.tsx`
+**改动:**
+- 导入 `RoleTreeListPanel` 替代 `RoleListPanel`
+- 添加 `organizations` 状态管理
+- 修改 `loadRoles` 函数,增加组织目录数据加载:
+ ```typescript
+ // 加载组织目录信息
+ const directoryResult = await window.electronAPI?.invoke("rolex:directory", {})
+ // 更新角色的组织信息(org, position)
+ // 设置组织列表
+ ```
+- 将组织数据传递给 `RoleTreeListPanel`
+
+#### `apps/desktop/src/view/pages/roles-window/components/RoleDetailPanel.tsx`
+**改动:**
+- 修复 `V2GoalsTab` 组件,适配 RoleX 1.1.0 的 `focus()` 输出格式
+- RoleX 1.1.0 的 `focus()` 返回文本格式而非结构化数据
+- 改为直接显示原始文本输出(使用 `` 标签)
+
+**修改前:**
+```typescript
+const current = data?.focus?.current // 期望结构化数据
+const otherGoals: any[] = data?.focus?.otherGoals || []
+```
+
+**修改后:**
+```typescript
+const focusText = data?.focus // 直接使用文本输出
+// 使用 标签显示格式化文本
+```
+
+#### `apps/desktop/src/main/windows/ResourceListWindow.ts`
+**改动:**
+- 添加 `rolex:directory` IPC handler
+- 调用 `RolexActionDispatcher.dispatch('directory', {})` 获取组织目录
+- 返回解析后的 JSON 数据
+
+```typescript
+ipcMain.handle('rolex:directory', async (_evt) => {
+ const dispatcher = new RolexActionDispatcher()
+ const directoryResult = await dispatcher.dispatch('directory', {})
+ const directory = typeof directoryResult === 'string'
+ ? JSON.parse(directoryResult)
+ : directoryResult
+ return { success: true, data: directory }
+})
+```
+
+#### `apps/desktop/src/i18n/locales/en.json`
+**改动:**
+- 添加 `roles.filters.independent`: "Independent Roles"
+
+#### `apps/desktop/src/i18n/locales/zh-CN.json`
+**改动:**
+- 添加 `roles.filters.independent`: "独立角色"
+
+## 数据结构
+
+### RoleItem 扩展
+```typescript
+type RoleItem = {
+ id: string
+ name: string
+ description?: string
+ type: "role"
+ source?: string
+ version?: "v1" | "v2"
+ org?: string // 新增:所属组织
+ position?: string // 新增:在组织中的职位
+}
+```
+
+### OrganizationNode
+```typescript
+type OrganizationNode = {
+ name: string
+ charter?: string
+ roles: RoleItem[]
+}
+```
+
+### Directory 结构(来自 RoleX)
+```typescript
+interface Directory {
+ roles: Array<{
+ name: string // 角色ID
+ org?: string // 所属组织
+ position?: string // 职位
+ }>
+ organizations: Array<{
+ name: string // 组织名称
+ charter?: string // 组织章程
+ members?: Array<{
+ name: string // 成员角色ID
+ position: string // 职位
+ }>
+ }>
+}
+```
+
+## UI 效果
+
+### V2 角色列表(树状结构)
+```
+┌─ 组织A (3)
+│ ├─ 角色1 [CTO]
+│ ├─ 角色2 [Engineer]
+│ └─ 角色3 [Designer]
+├─ 组织B (2)
+│ ├─ 角色4 [Manager]
+│ └─ 角色5 [Developer]
+└─ 独立角色 (2)
+ ├─ 角色6
+ └─ 角色7
+```
+
+### V1 角色列表(平面列表)
+```
+- 角色A
+- 角色B
+- 角色C
+```
+
+## API 调用流程
+
+### 加载角色列表
+1. `window.electronAPI?.getGroupedResources()` - 获取基础角色数据
+2. `window.electronAPI?.invoke("rolex:directory", {})` - 获取组织目录
+3. 合并数据:将组织信息(org, position)添加到角色对象
+4. 构建组织节点列表
+
+### 加载角色详情
+1. `window.electronAPI?.invoke("resources:getV2RoleData", { roleId })` - 获取角色详细数据
+2. 返回:`{ identity, focus, directory }`
+3. `focus` 是文本格式的当前目标输出
+4. `directory` 包含组织结构信息
+
+## 兼容性
+
+- ✅ V1 角色:保持原有平面列表显示
+- ✅ V2 角色(无组织):显示在"独立角色"分组
+- ✅ V2 角色(有组织):显示在对应组织节点下
+- ✅ 搜索和筛选:在所有模式下正常工作
+- ✅ V2 功能禁用时:自动切换到 V1 模式
+
+## 测试建议
+
+1. **树状列表测试**
+ - 创建多个组织和角色
+ - 验证组织节点展开/折叠
+ - 验证角色的组织和职位标签显示
+ - 测试搜索功能
+
+2. **数据显示测试**
+ - 查看有目标的 V2 角色的 Goals 标签
+ - 查看有组织的 V2 角色的 Organization 标签
+ - 验证 Identity 文本正确显示
+
+3. **边界情况测试**
+ - 无组织的 V2 角色
+ - 无目标的 V2 角色
+ - 空组织
+ - V1/V2 混合场景
+
+## 后续优化建议
+
+1. **Focus 数据解析**
+ - 可以考虑在后端解析 focus 文本输出为结构化数据
+ - 提取目标名称、计划、任务列表等信息
+ - 提供更友好的 UI 展示
+
+2. **组织管理功能**
+ - 添加创建组织的 UI
+ - 添加设立职位的 UI
+ - 添加任命角色的 UI
+
+3. **性能优化**
+ - 大量角色时的虚拟滚动
+ - 组织节点的懒加载
+ - 缓存组织目录数据
+
+4. **视觉优化**
+ - 组织节点的图标和颜色主题
+ - 更丰富的职位标签样式
+ - 组织层级的视觉连接线
diff --git a/V2_ROLE_TREE_TEST_GUIDE.md b/V2_ROLE_TREE_TEST_GUIDE.md
new file mode 100644
index 00000000..cfe7911c
--- /dev/null
+++ b/V2_ROLE_TREE_TEST_GUIDE.md
@@ -0,0 +1,226 @@
+# V2 角色树状列表测试指南
+
+## 测试前准备
+
+1. 确保已启用 V2 功能(设置 → 服务器配置 → 启用 V2 功能)
+2. 确保有一些 V2 角色存在
+3. 重启 PromptX Desktop
+
+## 测试步骤
+
+### 1. 基础显示测试
+
+**测试树状列表显示:**
+1. 打开角色窗口
+2. 切换到 "V2 Rolex" 标签
+3. 验证:
+ - [ ] 如果有组织,应该看到组织节点(带 Building2 图标)
+ - [ ] 组织节点显示组织名称和成员数量
+ - [ ] 组织节点可以展开/折叠(点击查看)
+ - [ ] 展开后显示该组织下的所有角色
+ - [ ] 角色显示职位标签(紫色)
+ - [ ] 无组织的角色显示在"独立角色"分组下
+
+**测试 V1 角色显示:**
+1. 切换到 "V1 DPML" 标签
+2. 验证:
+ - [ ] V1 角色保持平面列表显示(无树状结构)
+ - [ ] 所有 V1 角色正常显示
+
+### 2. 创建测试组织和角色
+
+使用 MCP action 工具或 AgentX 对话创建测试数据:
+
+```javascript
+// 1. 创建组织
+{
+ "operation": "synthesize",
+ "role": "nuwa",
+ "name": "TechCorp",
+ "charter": "致力于技术创新的组织"
+}
+
+// 2. 设立职位
+{
+ "operation": "charge",
+ "role": "nuwa",
+ "orgName": "TechCorp",
+ "position": "CTO",
+ "procedure": "负责技术战略"
+}
+
+{
+ "operation": "charge",
+ "role": "nuwa",
+ "orgName": "TechCorp",
+ "position": "Engineer",
+ "procedure": "负责产品开发"
+}
+
+// 3. 创建新角色(如果需要)
+// 使用 nuwa 角色创建新的 V2 角色
+
+// 4. 任命角色到职位
+{
+ "operation": "require",
+ "role": "nuwa",
+ "orgName": "TechCorp",
+ "position": "CTO",
+ "individual": "alice" // 替换为实际角色ID
+}
+```
+
+### 3. 刷新并验证
+
+1. 关闭并重新打开角色窗口(或重启应用)
+2. 验证:
+ - [ ] 看到 "TechCorp" 组织节点
+ - [ ] 组织节点显示成员数量
+ - [ ] 展开后看到被任命的角色
+ - [ ] 角色显示对应的职位标签(如 "CTO")
+
+### 4. 角色详情测试
+
+**测试组织信息显示:**
+1. 选择一个有组织的 V2 角色
+2. 点击 "Organization" 标签
+3. 验证:
+ - [ ] 显示组织名称
+ - [ ] 显示角色的职位
+ - [ ] 显示组织成员列表
+
+**测试目标信息显示:**
+1. 选择一个有目标的 V2 角色
+2. 点击 "Goals" 标签
+3. 验证:
+ - [ ] 显示当前目标的文本输出
+ - [ ] 文本格式正确(使用等宽字体)
+ - [ ] 如果没有目标,显示"暂无活跃目标"
+
+**测试身份信息显示:**
+1. 点击 "Overview" 标签
+2. 验证:
+ - [ ] 显示角色描述
+ - [ ] 显示角色身份文本(identity)
+
+**测试结构信息显示:**
+1. 点击 "Structure" 标签
+2. 验证:
+ - [ ] 显示四个层级:Persona、Knowledge、Voice、Experience
+ - [ ] 可以展开查看各层级的文件
+ - [ ] 可以点击文件查看内容
+
+### 5. 搜索和筛选测试
+
+**测试搜索功能:**
+1. 在搜索框输入角色名称
+2. 验证:
+ - [ ] 只显示匹配的角色
+ - [ ] 组织节点根据是否有匹配角色显示/隐藏
+ - [ ] 清空搜索后恢复所有角色
+
+**测试来源筛选:**
+1. 点击不同的来源筛选按钮(All/System/Plaza/User)
+2. 验证:
+ - [ ] 只显示对应来源的角色
+ - [ ] 组织节点根据筛选结果更新
+
+### 6. 边界情况测试
+
+**测试无组织角色:**
+1. 创建一个新的 V2 角色但不加入任何组织
+2. 验证:
+ - [ ] 角色显示在"独立角色"分组下
+ - [ ] 点击角色查看详情正常
+
+**测试空组织:**
+1. 创建一个组织但不任命任何角色
+2. 验证:
+ - [ ] 组织节点显示成员数量为 0
+ - [ ] 展开后显示为空
+
+**测试混合场景:**
+1. 同时有 V1 和 V2 角色
+2. 验证:
+ - [ ] 切换 V1/V2 标签正常工作
+ - [ ] 数据不会混淆
+
+### 7. 性能测试
+
+**测试大量角色:**
+1. 如果有大量角色(>50个)
+2. 验证:
+ - [ ] 列表滚动流畅
+ - [ ] 展开/折叠响应及时
+ - [ ] 搜索响应快速
+
+## 常见问题排查
+
+### 问题1:看不到组织节点
+**可能原因:**
+- 没有创建组织
+- 角色没有被任命到组织
+- 需要刷新数据
+
+**解决方法:**
+1. 使用 action 工具创建组织和任命角色
+2. 关闭并重新打开角色窗口
+3. 检查后端日志是否有错误
+
+### 问题2:角色详情显示不正确
+**可能原因:**
+- RoleX 数据库数据格式问题
+- 后端 API 返回数据格式不匹配
+
+**解决方法:**
+1. 检查浏览器控制台是否有错误
+2. 查看后端日志
+3. 验证 `resources:getV2RoleData` 返回的数据结构
+
+### 问题3:树状列表不显示
+**可能原因:**
+- 组件导入错误
+- 构建失败
+
+**解决方法:**
+1. 重新构建:`pnpm --filter @promptx/desktop build`
+2. 检查构建日志是否有错误
+3. 重启应用
+
+## 调试技巧
+
+### 查看组织目录数据
+在浏览器控制台执行:
+```javascript
+window.electronAPI?.invoke("rolex:directory", {}).then(console.log)
+```
+
+### 查看角色详细数据
+```javascript
+window.electronAPI?.invoke("resources:getV2RoleData", { roleId: "nuwa" }).then(console.log)
+```
+
+### 查看所有角色数据
+```javascript
+window.electronAPI?.getGroupedResources().then(console.log)
+```
+
+## 预期结果
+
+✅ **成功标准:**
+1. V2 角色按组织分组显示
+2. 组织节点可以展开/折叠
+3. 角色显示职位标签
+4. 角色详情页正确显示组织、目标、身份信息
+5. 搜索和筛选功能正常
+6. V1 角色保持原有显示方式
+7. 性能流畅,无明显卡顿
+
+## 反馈
+
+如果发现问题,请记录:
+1. 问题描述
+2. 复现步骤
+3. 预期行为 vs 实际行为
+4. 浏览器控制台错误信息
+5. 后端日志(如果有)
diff --git a/V2_STRUCTURE_TAB_DATABASE_MIGRATION.md b/V2_STRUCTURE_TAB_DATABASE_MIGRATION.md
new file mode 100644
index 00000000..76b3b4ff
--- /dev/null
+++ b/V2_STRUCTURE_TAB_DATABASE_MIGRATION.md
@@ -0,0 +1,124 @@
+# V2 Structure Tab Database Migration
+
+## 问题
+V2 角色详情页的"结构"标签页仍在从文件系统读取 identity 数据(`~/.rolex/roles//identity/*.feature`),但 RoleX 1.1.0 已将所有数据迁移到 SQLite 数据库。
+
+## 解决方案
+
+### 1. 后端改动
+
+**文件**: `apps/desktop/src/main/windows/ResourceListWindow.ts`
+
+添加新的 IPC handler `rolex:getIdentityNodes`:
+
+```typescript
+ipcMain.handle('rolex:getIdentityNodes', async (_evt, payload: { roleId: string }) => {
+ try {
+ const { RolexBridge } = require('@promptx/core')
+ const bridge = RolexBridge.getInstance()
+ const identityData = await bridge.identity(payload.roleId)
+ return { success: true, data: identityData }
+ } catch (error: any) {
+ return { success: false, message: error?.message }
+ }
+})
+```
+
+这个 handler 调用 `RolexBridge.identity(roleId)`,它内部会:
+1. 激活角色:`await this.rolex.activate(roleId)`
+2. 获取身份投影:`return role.project()`
+3. 返回包含 identity 节点的结构化数据
+
+### 2. 前端改动
+
+**文件**: `apps/desktop/src/view/pages/roles-window/components/RoleDetailPanel.tsx`
+
+完全重写 `V2StructureTab` 组件:
+
+#### 主要变化:
+
+1. **数据加载**:
+ - 旧:调用 `resources:listV2RoleFiles` 获取文件列表
+ - 新:调用 `rolex:getIdentityNodes` 获取数据库节点
+
+2. **数据结构**:
+ - 旧:`files: string[]` (文件名数组)
+ - 新:`nodes: any[]` (节点对象数组,包含 id, name, information)
+
+3. **分类逻辑**:
+ - 旧:根据文件名模式 (`.knowledge.`, `.voice.`, `.experience.`)
+ - 新:根据节点的 name 或 id 包含的关键词
+
+4. **内容查看**:
+ - 旧:点击文件后调用 `resources:readV2RoleFile` 读取文件内容
+ - 新:直接显示节点的 `information` 字段(Gherkin Feature 内容)
+
+5. **编辑功能**:
+ - 旧:支持编辑和保存(调用 `resources:saveV2RoleFile`)
+ - 新:只读模式(数据库节点不支持 UI 直接编辑)
+
+## 数据流
+
+```
+用户点击"结构"标签
+ ↓
+V2StructureTab 调用 rolex:getIdentityNodes
+ ↓
+IPC handler 调用 RolexBridge.identity(roleId)
+ ↓
+RolexBridge 调用 role.project()
+ ↓
+RoleX 从 SQLite 数据库查询 identity 节点
+ ↓
+返回节点数组 [{ id, name, information, ... }]
+ ↓
+前端按类别显示节点
+ ↓
+用户点击节点查看 Gherkin 内容
+```
+
+## RoleX 1.1.0 数据库架构
+
+根据 RoleX 分析文档:
+
+- **nodes 表**:存储所有节点
+ - `id`: 节点唯一标识
+ - `name`: 节点名称
+ - `information`: Gherkin Feature 格式的内容
+ - `prototype`: 原型引用
+
+- **identity 节点**:角色的身份结构
+ - persona: 人格特征
+ - knowledge: 知识库
+ - voice: 语音风格
+ - experience: 经验记录
+
+## 测试建议
+
+1. 打开一个 V2 角色的详情页
+2. 切换到"结构"标签
+3. 验证显示了 4 个层级(persona, knowledge, voice, experience)
+4. 点击展开每个层级,查看节点列表
+5. 点击节点,查看 Gherkin Feature 内容
+6. 确认内容是从数据库加载的(不是文件系统)
+
+## 注意事项
+
+1. **只读模式**:当前实现将所有节点设为只读。如果需要编辑功能,需要:
+ - 添加新的 IPC handler 调用 RoleX API 更新节点
+ - 在前端恢复编辑和保存逻辑
+
+2. **节点分类**:当前使用简单的关键词匹配。如果 RoleX 提供了更明确的节点类型标识,应该使用那个。
+
+3. **错误处理**:如果角色没有 identity 数据,会显示空列表。可以考虑添加更友好的提示。
+
+## 相关文件
+
+- `packages/core/src/rolex/RolexBridge.js` - identity() 方法
+- `apps/desktop/src/main/windows/ResourceListWindow.ts` - IPC handlers
+- `apps/desktop/src/view/pages/roles-window/components/RoleDetailPanel.tsx` - V2StructureTab
+
+## 提交
+
+Commit: d869209
+Message: "fix(core): migrate V2 role Structure tab from filesystem to database"
diff --git a/apps/desktop/src/i18n/locales/en.json b/apps/desktop/src/i18n/locales/en.json
index cadab941..1df513f0 100644
--- a/apps/desktop/src/i18n/locales/en.json
+++ b/apps/desktop/src/i18n/locales/en.json
@@ -53,7 +53,9 @@
"activate": "Set as active",
"activated": "Configuration activated",
"deleted": "Configuration deleted",
- "saved": "Configuration saved"
+ "saved": "Configuration saved",
+ "anthropicOnly": "Anthropic format only",
+ "openaiNotSupported": "OpenAI protocol endpoints are not supported"
},
"skills": {
"title": "Skills Configuration",
@@ -419,7 +421,8 @@
"all": "All",
"system": "System",
"plaza": "Plaza",
- "user": "User"
+ "user": "User",
+ "independent": "Independent Roles"
},
"activate": "Activate",
"empty": "No roles found",
@@ -690,6 +693,7 @@
},
"rename": {
"placeholder": "Enter conversation name",
+ "cancel": "Cancel",
"saving": "Saving...",
"save": "Save"
},
@@ -768,5 +772,40 @@
"toolPrompt": "What tools are available?"
}
}
+ },
+ "notifications": {
+ "button": "Notifications",
+ "title": "Notifications",
+ "unreadCount": "{{count}} unread notification",
+ "unreadCount_other": "{{count}} unread notifications",
+ "allRead": "All notifications read",
+ "markAllRead": "Mark all as read",
+ "markRead": "Mark as read",
+ "empty": "No notifications",
+ "time": {
+ "justNow": "Just now",
+ "minutesAgo": "{{count}} minute ago",
+ "minutesAgo_other": "{{count}} minutes ago",
+ "hoursAgo": "{{count}} hour ago",
+ "hoursAgo_other": "{{count}} hours ago",
+ "daysAgo": "{{count}} day ago",
+ "daysAgo_other": "{{count}} days ago"
+ },
+ "welcome": {
+ "title": "Welcome to PromptX!",
+ "content": "Thank you for using PromptX. Explore roles, tools, and AgentX to enhance your AI experience."
+ },
+ "update": {
+ "title": "New Features Available",
+ "content": "Check out the latest updates: RoleX lifecycle management, improved UI, and more!"
+ },
+ "updateV220": {
+ "title": "v2.2.0 Update Released",
+ "content": "New notification center, AgentX config with preset & OpenAI protocol detection, RoleX core upgraded from v0.11.0 to v1.3.0, fixed conversation rename bug, fixed Windows Git link issue. V2 role import/export/delete features temporarily disabled."
+ },
+ "rolexUpgrade": {
+ "title": "RoleX (V2) Architecture Upgrade",
+ "content": "Existing V2 roles need to be upgraded. Please activate Nuwa and ask her to upgrade and migrate your roles to continue using them."
+ }
}
}
diff --git a/apps/desktop/src/i18n/locales/en.json.bak b/apps/desktop/src/i18n/locales/en.json.bak
new file mode 100644
index 00000000..8af143f1
--- /dev/null
+++ b/apps/desktop/src/i18n/locales/en.json.bak
@@ -0,0 +1,776 @@
+{
+ "settings": {
+ "title": "Settings",
+ "subtitle": "Customize your PromptX experience",
+ "tabs": {
+ "system": "System",
+ "agentx": "AgentX",
+ "remote": "Remote Access"
+ },
+ "language": {
+ "title": "Language",
+ "description": "Choose your preferred language",
+ "english": "English",
+ "chinese": "简体中文"
+ },
+ "agentx": {
+ "title": "AgentX Configuration",
+ "description": "Configure AgentX AI assistant API connection",
+ "apiKey": {
+ "label": "API Key",
+ "placeholder": "sk-ant-...",
+ "description": "Your AgentX API Key"
+ },
+ "baseUrl": {
+ "label": "API Base URL",
+ "placeholder": "https://api.anthropic.com",
+ "description": "API server address, defaults to Anthropic official endpoint"
+ },
+ "model": {
+ "label": "Model",
+ "placeholder": "claude-opus-4-5-20251101",
+ "description": "Model name to use"
+ },
+ "testConnection": "Test Connection",
+ "testing": "Testing...",
+ "testSuccess": "Connection successful!",
+ "testFailed": "Connection failed",
+ "save": "Save Configuration",
+ "saving": "Saving...",
+ "saveSuccess": "AgentX configuration saved successfully",
+ "saveFailed": "Failed to save AgentX configuration",
+ "windowsGitWarning": {
+ "text": "AgentX requires Git to be installed on Windows.",
+ "link": "Download Git for Windows"
+ },
+ "profiles": {
+ "empty": "No configurations yet. Add one to get started.",
+ "add": "Add Configuration",
+ "addTitle": "Add Configuration",
+ "editTitle": "Edit Configuration",
+ "name": "Name",
+ "active": "Active",
+ "activate": "Set as active",
+ "activated": "Configuration activated",
+ "deleted": "Configuration deleted",
+ "saved": "Configuration saved",
+ "anthropicOnly": "Anthropic format only",
+ "openaiNotSupported": "OpenAI protocol endpoints are not supported"
+ },
+ "skills": {
+ "title": "Skills Configuration",
+ "description": "Manage enabled Skills that will be used for all AgentX conversations",
+ "empty": "No available Skills",
+ "emptyHint": "Click 'Add Skill' to import your first skill",
+ "refresh": "Refresh",
+ "save": "Save",
+ "saving": "Saving...",
+ "addSkill": "Add Skill",
+ "importing": "Importing...",
+ "loadError": "Failed to load Skills",
+ "saveSuccess": "Skills configuration saved",
+ "saveError": "Failed to save Skills configuration",
+ "importSuccess": "Skill \"{{name}}\" imported successfully",
+ "importError": "Failed to import Skill",
+ "invalidStructure": "Invalid skill package: SKILL.md not found in the zip",
+ "deleteConfirm": "Are you sure you want to delete skill \"{{name}}\"?",
+ "deleteSuccess": "Skill \"{{name}}\" deleted successfully",
+ "deleteError": "Failed to delete Skill",
+ "delete": "Delete"
+ }
+ },
+ "autoStart": {
+ "title": "Auto Start",
+ "description": "Launch PromptX automatically when computer starts",
+ "enable": "Enable auto start"
+ },
+ "webAccess": {
+ "title": "Remote Access",
+ "description": "Enable LAN access to PromptX via browser, supports multiple sessions",
+ "port": {
+ "label": "HTTP Port",
+ "description": "Web service port, default 5201"
+ },
+ "toggle": "Enable Remote Access",
+ "enabled": "Remote access enabled",
+ "disabled": "Remote access disabled",
+ "enableFailed": "Failed to enable",
+ "disableFailed": "Failed to disable",
+ "copyUrl": "URL copied",
+ "qrHint": "Scan to access on phone or other devices"
+ },
+ "server": {
+ "title": "Server Configuration",
+ "description": "Configure server host, port and debug settings",
+ "host": {
+ "label": "Server Host",
+ "placeholder": "127.0.0.1",
+ "description": "Host address for the server to listen on, e.g. 127.0.0.1"
+ },
+ "port": {
+ "label": "Server Port",
+ "placeholder": "5203",
+ "description": "Port for the server to listen on, range 1-65535"
+ },
+ "debug": {
+ "label": "Debug Mode",
+ "description": "Output more log information for troubleshooting"
+ },
+ "enableV2": {
+ "label": "Enable V2 Features (RoleX)",
+ "description": "Enable RoleX role lifecycle management: role creation, goal management, and organization features"
+ },
+ "save": "Save Configuration",
+ "saving": "Saving...",
+ "reset": "Reset to Default"
+ },
+ "mcp": {
+ "title": "MCP Configuration",
+ "description": "Configure Model Context Protocol servers",
+ "add": "Add Server",
+ "edit": "Edit Server",
+ "empty": "No MCP servers configured",
+ "emptyHint": "Click 'Add Server' to add your first MCP server",
+ "dialogDescription": "Configure the MCP server with JSON format",
+ "fields": {
+ "name": "Server Name",
+ "namePlaceholder": "e.g., my-mcp-server",
+ "config": "Configuration (JSON)",
+ "configHint": "Stdio: {command, args, env} | HTTP/SSE: {type, url}",
+ "enabled": "Enable this server"
+ },
+ "save": "Save",
+ "saving": "Saving...",
+ "cancel": "Cancel",
+ "saveSuccess": "MCP configuration saved successfully",
+ "saveFailed": "Failed to save MCP configuration",
+ "loadError": "Failed to load MCP servers",
+ "validation": {
+ "nameRequired": "Server name is required",
+ "commandOrUrlRequired": "Either 'command' (stdio) or 'url' (http/sse) is required",
+ "typeRequired": "The 'type' field is required when using 'url' (http or sse)",
+ "invalidJson": "Invalid JSON format",
+ "invalidConfig": "Invalid configuration",
+ "duplicate": "A server with this name already exists"
+ },
+ "builtin": "Built-in",
+ "cannotDeleteBuiltin": "Cannot delete built-in server",
+ "cannotDisableBuiltin": "Cannot disable built-in server"
+ },
+ "skills": {
+ "title": "Skills Configuration",
+ "description": "Manage and configure AI skills"
+ }
+ },
+
+ "logs": {
+ "title": "Application Logs",
+ "subtitle": "View and manage application logs",
+ "management": "Logs Management",
+ "description": "View, filter, and manage application logs",
+ "search": {
+ "placeholder": "Search logs..."
+ },
+ "filters": {
+ "all": "All",
+ "normal": "Normal",
+ "error": "Error",
+ "clearDate": "Clear"
+ },
+ "list": {
+ "title": "Log Files",
+ "count": "Log Files ({{count}})",
+ "empty": "No logs found"
+ },
+ "viewer": {
+ "selectPrompt": "Select a log file to view its content",
+ "loading": "Loading...",
+ "empty": "Log is empty"
+ },
+ "actions": {
+ "clearAll": "Clear All",
+ "delete": "Delete"
+ },
+ "messages": {
+ "loadFailed": "Failed to load logs",
+ "readFailed": "Failed to read log",
+ "deleteFailed": "Failed to delete log",
+ "deleteSuccess": "Log deleted successfully",
+ "deleteConfirm": "Delete log file: {{name}}?",
+ "clearAllConfirm": "Are you sure you want to delete ALL log files?",
+ "clearSuccess": "Cleared {{count}} log files",
+ "clearFailed": "Failed to clear logs"
+ }
+ },
+ "resources": {
+ "comingSoon": {
+ "title": "Coming Soon",
+ "description": "Agent Shop is under construction, stay tuned",
+ "badge": "Coming Soon"
+ },
+ "banner": {
+ "title": "Share Your Creations",
+ "subtitle": "Discover and share roles & tools with the community",
+ "publishRole": "Publish Role",
+ "publishTool": "Publish Tool"
+ },
+ "search": {
+ "placeholder": "Search resources / roles / tools"
+ },
+ "import": {
+ "title": "Import Resource",
+ "description": "Import a role or tool from a file ",
+ "button": "Import Resource",
+ "methods": {
+ "file": "File Import",
+ "url": "URL Import (Coming Soon)"
+ },
+ "fields": {
+ "resourceType": "Resource Type",
+ "zipFile": "ZIP File",
+ "browse": "Browse",
+ "upload": "Upload",
+ "customId": "Custom ID (Optional)",
+ "customIdPlaceholder": "Leave empty to use original ID",
+ "customIdHint": "The ID will be used as the folder name",
+ "customName": "Custom Name (Optional)",
+ "customNamePlaceholder": "Display name for the resource",
+ "customDescription": "Custom Description (Optional)",
+ "customDescriptionPlaceholder": "Brief description of the resource"
+ },
+ "actions": {
+ "cancel": "Cancel",
+ "import": "Import",
+ "importing": "Importing..."
+ },
+ "messages": {
+ "selectFile": "Please select a file",
+ "importSuccess": "Resource imported successfully",
+ "importFailed": "Failed to import resource",
+ "invalidStructure": "Invalid resource structure",
+ "fileNotFound": "File not found",
+ "resourceExists": "Resource exists",
+ "resourceExistsMessage": "Resource \"{{id}}\" already exists. Overwrite?",
+ "cancelled": "Operation cancelled"
+ },
+ "urlComingSoon": "URL import feature is coming soon..."
+ },
+ "cards": {
+ "roles": {
+ "title": "Roles",
+ "description": "Number of activatable roles"
+ },
+ "tools": {
+ "title": "Tools",
+ "description": "Number of executable tools"
+ },
+ "sources": {
+ "title": "Sources",
+ "description": "Resource count by source"
+ }
+ },
+ "filters": {
+ "type": "Type:",
+ "source": "Source:",
+ "all": "All",
+ "roles": "Roles",
+ "tools": "Tools",
+ "system": "System",
+ "user": "User"
+ },
+ "actions": {
+ "edit": "Edit",
+ "download": "Download",
+ "delete": "Delete",
+ "use": "Use",
+ "export": "Export",
+ "exportSuccess": "Exported successfully",
+ "exportFailed": "Export failed"
+ },
+ "messages": {
+ "loadFailed": "Failed to load resources",
+ "searchFailed": "Search failed",
+ "downloadSuccess": "Saved to: {{path}}",
+ "downloadFailed": "Download failed",
+ "deleteConfirm": "Confirm delete {{type}} \"{{name}}\"? This action cannot be undone.",
+ "deleteSuccess": "Deleted successfully",
+ "deleteFailed": "Delete failed",
+ "deleteOnlyUser": "Only user resources can be deleted (system/project cannot be deleted)",
+ "noMore": "No more items :-I",
+ "editOnlyUser": "Only user resources can be edited "
+ },
+ "types": {
+ "role": "Role",
+ "tool": "Tool"
+ },
+ "editor": {
+ "title": "Edit {{type}}: {{name}}",
+ "fields": {
+ "name": "Name",
+ "description": "Description",
+ "namePlaceholder": "Enter resource name",
+ "descriptionPlaceholder": "Enter resource description"
+ },
+ "fileList": "File List",
+ "editFile": "Edit: {{file}}",
+ "selectFile": "Please select a file",
+ "fileContent": "File content...",
+ "selectFilePrompt": "Please select a file to edit from the left",
+ "buttons": {
+ "saveResourceInfo": "Save Resource Info",
+ "saveFile": "Save File",
+ "close": "Close",
+ "saving": "Saving...",
+ "copyPrompt": "Copy Prompt",
+ "copySuccess": "Prompt copied to clipboard"
+ },
+ "messages": {
+ "loadFilesFailed": "Failed to load file list",
+ "readFileFailed": "Failed to read file",
+ "editorOpenFailed": "Failed to open editor",
+ "saveFailed": "Save failed",
+ "saveSuccess": "Saved successfully",
+ "resourceInfoSaveSuccess": "Resource info saved successfully",
+ "saveResourceInfoFailed": "Failed to save resource info",
+ "onlyUserEditable": "Only user resources can be edited (system/project are read-only)",
+ "loading": "Loading...",
+ "loadingFileContent": "Loading file content..."
+ },
+ "tabs": {
+ "editor": "Editor",
+ "preview": "Preview"
+ },
+ "preview": {
+ "loading": "Loading preview...",
+ "empty": "No preview content",
+ "failed": "Failed to load preview"
+ },
+ "readOnly": "⚠️ This resource is in read-only mode ({{source}})"
+ }
+ },
+ "tray": {
+ "tooltip": "PromptX Desktop",
+ "status": {
+ "running": "Running",
+ "stopped": "Stopped",
+ "starting": "Starting...",
+ "stopping": "Stopping...",
+ "error": "Error",
+ "unknown": "Unknown"
+ },
+ "menu": {
+ "status": "Status: {{status}}",
+ "startServer": "Start Server",
+ "stopServer": "Stop Server",
+ "toggleServer": "Toggle Server",
+ "copyAddress": "Copy Server Address",
+ "openMainWindow": "Open Main Window",
+ "manageResources": "Manage Resources",
+ "showLogs": "Show Logs",
+ "settings": "Settings...",
+ "checkUpdates": "Check for Updates...",
+ "checkingUpdates": "Checking for Updates...",
+ "downloadUpdate": "Download Update ({{version}})",
+ "downloading": "Downloading... {{percent}}%",
+ "installUpdate": "Install Update ({{version}})",
+ "retryUpdate": "Retry Update Check",
+ "about": "About PromptX",
+ "quit": "Quit PromptX"
+ },
+ "windows": {
+ "logs": "PromptX Logs",
+ "settings": "PromptX Settings"
+ }
+ },
+ "messages": {
+ "autoStartEnabled": "Auto start enabled successfully",
+ "autoStartDisabled": "Auto start disabled successfully",
+ "autoStartError": "Failed to toggle auto start",
+ "configSaved": "Configuration saved successfully",
+ "configSaveError": "Failed to save configuration",
+ "configReset": "Configuration reset to default",
+ "configResetError": "Failed to reset configuration",
+ "loadError": "Failed to load settings, please try again",
+ "languageChanged": "Language changed successfully",
+ "restartRequired": "Restart Required",
+ "restartDescription": "Server configuration has been saved. The application needs to restart for changes to take effect.",
+ "restartNow": "Restart Now",
+ "restartLater": "Later",
+ "restartError": "Failed to restart application"
+ },
+ "sidebar": {
+ "agentx": "AgentX Chat",
+ "resources": "Agent Shop",
+ "roles":"Roles",
+ "tools":"Tools",
+ "logs": "Logs",
+ "settings": "Settings",
+ "update": "Check for Updates"
+ },
+ "roles": {
+ "search": {
+ "placeholder": "Search roles..."
+ },
+ "stats": {
+ "total": "Total Roles",
+ "system": "System Roles",
+ "user": "User Roles"
+ },
+ "filters": {
+ "source": "Source:",
+ "all": "All",
+ "system": "System",
+ "plaza": "Plaza",
+ "user": "User",
+ "independent": "Independent Roles"
+ },
+ "activate": "Activate",
+ "empty": "No roles found",
+ "noDescription": "No description available",
+ "detail": {
+ "description": "Description",
+ "createRole":"Create Role",
+ "close": "Close",
+ "editRole": "Edit Role",
+ "editRoleName": "Name",
+ "uploadAvatar": "Upload Avatar",
+ "structure": "Structure",
+ "memory": "Memory",
+ "architecture": "DPML Layer Architecture (Three-Layer Architecture, On-Demand Loading)",
+ "memoryEmpty": "No memory data available",
+ "selectRole": "Select a role to view details",
+ "overview": "Overview",
+ "structure": "Structure",
+ "prompt": "Role Prompt",
+ "rolePrompt": "Role Prompt",
+ "promptLoading": "Loading prompt...",
+ "promptError": "Failed to load prompt",
+ "promptLoadError": "Failed to load prompt",
+ "roleFile": "Role Definition",
+ "personalityLayer": "Personality Layer",
+ "personalityDesc": "Defines thinking patterns and cognitive traits",
+ "principleLayer": "Principle Layer",
+ "principleDesc": "Defines workflows and execution standards",
+ "knowledgeLayer": "Knowledge Layer",
+ "knowledgeDesc": "Defines domain expertise and professional knowledge",
+ "noFiles": "No files",
+ "loadingFiles": "Loading files...",
+ "loadFilesFailed": "Failed to load file list",
+ "systemRoleReadOnly": "Built-in system roles cannot be viewed",
+ "fileContent": "File Content",
+ "loadingContent": "Loading content...",
+ "loadContentFailed": "Failed to load content",
+ "readOnly": "Read-only",
+ "save": "Save",
+ "saving": "Saving...",
+ "saveSuccess": "Saved successfully",
+ "saveFailed": "Failed to save",
+ "close": "Close",
+ "goals": "Goals",
+ "organization": "Organization",
+ "identity": "Identity",
+ "currentGoal": "Current Goal",
+ "noGoals": "No active goals",
+ "goalPlan": "Execution Plan",
+ "goalTasks": "Tasks",
+ "noTasks": "No tasks",
+ "noOrganization": "Not in any organization",
+ "orgPosition": "Position",
+ "orgMembers": "Members",
+ "taskPending": "Pending",
+ "taskInProgress": "In Progress",
+ "taskCompleted": "Completed",
+ "loadingData": "Loading...",
+ "v2PersonaLayer": "Persona",
+ "v2PersonaDesc": "Core personality and behavioral traits",
+ "v2KnowledgeLayer": "Knowledge",
+ "v2KnowledgeDesc": "Domain knowledge and professional expertise",
+ "v2VoiceLayer": "Voice",
+ "v2VoiceDesc": "Language style and communication patterns",
+ "v2ExperienceLayer": "Experience",
+ "v2ExperienceDesc": "Accumulated experience from practice"
+ },
+ "memory": {
+ "overview": "Overview",
+ "engrams": "Engrams",
+ "network": "Network",
+ "cues": "Cues",
+ "engramCount": "Engrams",
+ "cueCount": "Cues",
+ "connections": "Connections",
+ "lastActive": "Last Active",
+ "topCues": "Top Cues",
+ "noMemoryData": "No memory data available",
+ "loading": "Loading...",
+ "type": "Type",
+ "strength": "Strength",
+ "schema": "Schema",
+ "search": "Search...",
+ "page": "Page",
+ "clickToExplore": "Click to explore",
+ "recallFrequency": "Recall Frequency",
+ "weight": "Weight",
+ "edit": "Edit",
+ "delete": "Delete",
+ "save": "Save",
+ "cancel": "Cancel",
+ "confirmDelete": "Are you sure?",
+ "deleteCue": "Delete Cue",
+ "typeAtomic": "Atomic",
+ "typeLink": "Link",
+ "typePattern": "Pattern",
+ "allTypes": "All"
+ },
+ "messages": {
+ "loadFailed": "Failed to load roles",
+ "activateSuccess": "Role \"{{name}}\" activated successfully",
+ "activateFailed": "Failed to activate role",
+ "activatePrompt": "Activate role {{name}}",
+ "deleteConfirm": "Delete role \"{{name}}\"? This cannot be undone.",
+ "deleteSuccess": "Role \"{{name}}\" deleted successfully",
+ "deleteFailed": "Failed to delete role",
+ "deleteOnlyUser": "Only user-created roles can be deleted"
+ }
+ },
+ "tools": {
+ "search": {
+ "placeholder": "Search tools..."
+ },
+ "stats": {
+ "total": "Total Tools",
+ "system": "System Tools",
+ "user": "User Tools"
+ },
+ "filters": {
+ "source": "Source:",
+ "all": "All",
+ "system": "System",
+ "plaza": "Plaza",
+ "user": "User"
+ },
+ "execute": "Execute",
+ "empty": "No tools found",
+ "noDescription": "No description available",
+ "detail": {
+ "description": "Description",
+ "parameters": "Parameters",
+ "parametersPlaceholder": "{\"key\": \"value\"}",
+ "parametersHint": "Optional. Enter JSON parameters for tool execution.",
+ "result": "Execution Result",
+ "close": "Close",
+ "overview": "Overview",
+ "test": "Test",
+ "configure": "Configure",
+ "logs": "Logs",
+ "install": "Install Tool",
+ "output": "Output",
+ "outputEmpty": "Run a test to see output here...",
+ "runTest": "Run Test",
+ "envVars": "Environment Variables",
+ "noEnvVars": "No environment variables configured",
+ "noLogs": "No execution logs available",
+ "selectTool": "Select a tool to view details",
+ "deleteTool": "Delete Tool",
+ "tags": "Tags",
+ "manual": "Documentation",
+ "info": "Tool Info",
+ "source": "Source",
+ "execSuccess": "Execution succeeded",
+ "execFailed": "Execution failed",
+ "paramsHint": "Enter JSON parameters for tool execution. Leave {} for no parameters.",
+ "executing": "Executing...",
+ "execNoOutput": "Execution completed with no output",
+ "toolFiles": "Tool Files",
+ "noFiles": "No tool files found",
+ "readOnly": "Read-only",
+ "loadingFile": "Loading file...",
+ "paramSchema": "Parameter Schema",
+ "execHistory": "Execution History",
+ "clearLogs": "Clear Logs",
+ "formMode": "Form",
+ "edit": "Edit",
+ "save": "Save",
+ "cancel": "Cancel",
+ "editInfo": "Edit Info",
+ "editName": "Tool Name",
+ "editDescription": "Tool Description",
+ "namePlaceholder": "Enter tool name",
+ "descriptionPlaceholder": "Enter tool description",
+ "createTool": "Create Tool"
+ },
+ "messages": {
+ "loadFailed": "Failed to load tools",
+ "executeSuccess": "Tool \"{{name}}\" executed successfully",
+ "executeFailed": "Failed to execute tool",
+ "invalidParams": "Invalid JSON parameters",
+ "deleteOnlyUser": "Only user-created tools can be deleted",
+ "deleteConfirm": "Are you sure you want to delete tool \"{{name}}\"? This cannot be undone.",
+ "deleteSuccess": "Tool \"{{name}}\" deleted successfully",
+ "deleteFailed": "Failed to delete tool",
+ "saveSuccess": "File saved successfully",
+ "saveFailed": "Failed to save file",
+ "updateSuccess": "Tool info updated successfully",
+ "updateFailed": "Failed to update tool info",
+ "updateOnlyUser": "Only user-created tools can be edited"
+ }
+ },
+ "update": {
+ "title": "Software Update",
+ "description": "Check for and install software updates",
+ "currentVersion": "Current Version",
+ "checkNow": "Check Now",
+ "checking": "Checking...",
+ "upToDate": "You're up to date!",
+ "upToDateMessage": "You're running the latest version",
+ "newVersion": "New Version Available",
+ "download": "Download",
+ "downloading": "Downloading...",
+ "downloadComplete": "Download complete",
+ "readyToInstall": "Update ready to install",
+ "installNow": "Install Now",
+ "releaseNotes": "What's New",
+ "checkFailed": "Failed to check for updates",
+ "downloadFailed": "Failed to download update",
+ "installFailed": "Failed to install update",
+ "errorMessage": "An error occurred while checking for updates"
+ },
+ "datePicker": {
+ "placeholder": "Select date",
+ "selectDate": "Select Date",
+ "clear": "Clear"
+ },
+ "agentxUI": {
+ "chat": {
+ "placeholder": "Type a message...",
+ "toolbar": {
+ "emoji": "Emoji",
+ "file": "File",
+ "save": "Save conversation"
+ },
+ "status": {
+ "thinking": "Thinking",
+ "responding": "Responding",
+ "planning": "Planning",
+ "executing": "Executing",
+ "error": "Error",
+ "idle": "Idle",
+ "queued": "Queued",
+ "processing": "Processing"
+ },
+ "messageCount": "{{count}} message",
+ "messageCount_other": "{{count}} messages",
+ "actions": {
+ "stop": "Stop",
+ "send": "Send (Enter)",
+ "remove": "Remove",
+ "download": "Download",
+ "removeImage": "Remove image",
+ "escToStop": "esc to stop",
+ "copy": "Copy",
+ "regenerate": "Regenerate",
+ "like": "Like",
+ "dislike": "Dislike"
+ },
+ "empty": {
+ "title": "No conversation selected",
+ "description": "Select a conversation or start a new one"
+ },
+ "dropToSend": "Drop to send",
+ "errors": {
+ "maxAttachments": "Maximum {{max}} attachments allowed",
+ "fileTooLarge": "{{name}} exceeds the {{max}} size limit",
+ "fileTypeNotAccepted": "{{name}} is not a supported file type"
+ }
+ },
+ "conversations": {
+ "title": "Conversations",
+ "new": "New conversation",
+ "search": "Search conversations...",
+ "empty": {
+ "title": "No conversations yet",
+ "description": "Start a new conversation to begin",
+ "action": "New conversation"
+ },
+ "rename": {
+ "placeholder": "Enter conversation name",
+ "cancel": "Cancel",
+ "saving": "Saving...",
+ "save": "Save"
+ },
+ "delete": {
+ "confirm": "Are you sure you want to delete \"{{name}}\"?",
+ "cancel": "Cancel",
+ "confirm_button": "Delete",
+ "deleting": "Deleting..."
+ },
+ "actions": {
+ "rename": "Rename",
+ "delete": "Delete"
+ },
+ "status": {
+ "online": "Online",
+ "offline": "Offline"
+ },
+ "untitled": "Untitled"
+ },
+ "messages": {
+ "empty": {
+ "title": "No messages",
+ "description": "Start the conversation by sending a message"
+ }
+ },
+ "tool": {
+ "status": {
+ "planning": "Planning...",
+ "executing": "Executing...",
+ "completed": "Completed",
+ "error": "Error"
+ }
+ },
+ "sidebar": {
+ "expand": "Expand sidebar",
+ "collapse": "Collapse sidebar"
+ },
+ "list": {
+ "empty": {
+ "description": "Get started by creating a new item"
+ }
+ },
+ "time": {
+ "justNow": "Just now",
+ "unknown": "Unknown",
+ "minAgo": "1 min ago",
+ "minsAgo": "{{count}} mins ago",
+ "hourAgo": "1 hour ago",
+ "hoursAgo": "{{count}} hours ago",
+ "dayAgo": "1 day ago",
+ "daysAgo": "{{count}} days ago"
+ },
+ "mobile": {
+ "search": "Search..."
+ },
+ "page": {
+ "notConfigured": {
+ "title": "AgentX Not Configured",
+ "description": "Please configure your AgentX API Key in Settings to use AgentX.",
+ "hint": "Settings → AgentX Configuration → Enter API Key → Save"
+ },
+ "connectionError": "Connection Error",
+ "connecting": "Connecting to AgentX..."
+ },
+ "welcome": {
+ "tagline": "PromptX, Making AI Accessible",
+ "inputPlaceholder": "Ask me anything...",
+ "presets": {
+ "luban": "Activate Luban to build tools",
+ "lubanPrompt": "Activate Luban, I want to build a tool",
+ "nuwa": "Activate Nuwa to create roles",
+ "nuwaPrompt": "Activate Nuwa, I want to create a role",
+ "role": "Explore available roles",
+ "rolePrompt": "What roles are available?",
+ "tool": "Explore available tools",
+ "toolPrompt": "What tools are available?"
+ }
+ }
+ }
+}
diff --git a/apps/desktop/src/i18n/locales/zh-CN.json b/apps/desktop/src/i18n/locales/zh-CN.json
index fee51d7a..7bc628af 100644
--- a/apps/desktop/src/i18n/locales/zh-CN.json
+++ b/apps/desktop/src/i18n/locales/zh-CN.json
@@ -53,7 +53,9 @@
"activate": "设为当前",
"activated": "已切换配置",
"deleted": "配置已删除",
- "saved": "配置已保存"
+ "saved": "配置已保存",
+ "anthropicOnly": "仅支持 Anthropic 格式",
+ "openaiNotSupported": "暂不支持 OpenAI 协议的端点"
},
"skills": {
"title": "Skills 配置",
@@ -418,7 +420,8 @@
"all": "全部",
"system": "系统",
"plaza": "广场",
- "user": "用户"
+ "user": "用户",
+ "independent": "独立角色"
},
"activate": "激活",
"empty": "暂无角色",
@@ -687,6 +690,7 @@
},
"rename": {
"placeholder": "输入对话名称",
+ "cancel": "取消",
"saving": "保存中...",
"save": "保存"
},
@@ -765,5 +769,40 @@
"toolPrompt": "有哪些可用的工具?"
}
}
+ },
+ "notifications": {
+ "button": "通知",
+ "title": "通知中心",
+ "unreadCount": "{{count}} 条未读通知",
+ "unreadCount_other": "{{count}} 条未读通知",
+ "allRead": "所有通知已读",
+ "markAllRead": "全部标为已读",
+ "markRead": "标为已读",
+ "empty": "暂无通知",
+ "time": {
+ "justNow": "刚刚",
+ "minutesAgo": "{{count}} 分钟前",
+ "minutesAgo_other": "{{count}} 分钟前",
+ "hoursAgo": "{{count}} 小时前",
+ "hoursAgo_other": "{{count}} 小时前",
+ "daysAgo": "{{count}} 天前",
+ "daysAgo_other": "{{count}} 天前"
+ },
+ "welcome": {
+ "title": "欢迎使用 PromptX!",
+ "content": "感谢使用 PromptX。探索角色、工具和 AgentX,提升您的 AI 体验。"
+ },
+ "update": {
+ "title": "新功能上线",
+ "content": "查看最新更新:RoleX 生命周期管理、界面优化等更多功能!"
+ },
+ "updateV220": {
+ "title": "v2.2.0 版本更新",
+ "content": "新增通知中心、AgentX 配置增加预设与 OpenAI 协议识别功能、V2 RoleX 内核从 v0.11.0 更新到 v1.3.0、修复对话重命名后无效的 bug、修复 Windows 平台点击 Git 链接无响应的 bug。V2 的角色导入导出与删除功能暂时下架。"
+ },
+ "rolexUpgrade": {
+ "title": "RoleX(V2)架构升级",
+ "content": "原有 V2 角色需要升级。请激活女娲,让女娲进行升级与迁移才能继续使用。"
+ }
}
}
diff --git a/apps/desktop/src/main/index.ts b/apps/desktop/src/main/index.ts
index 4b97f6a4..0bbd365c 100644
--- a/apps/desktop/src/main/index.ts
+++ b/apps/desktop/src/main/index.ts
@@ -69,6 +69,7 @@ class PromptXDesktopApp {
this.setupLanguageIPC()
this.setupLogsIPC()
this.setupDialogIPC()
+ this.setupShellIPC()
this.setupAgentXIPC()
this.setupWebAccessIPC()
@@ -566,6 +567,34 @@ class PromptXDesktopApp {
})
}
+ private setupShellIPC(): void {
+ // 打开外部链接 - 在新的 Electron 窗口中打开
+ ipcMain.handle('shell:openExternal', async (_event, url: string) => {
+ try {
+ const { BrowserWindow } = await import('electron')
+
+ // 创建新的浏览器窗口
+ const browserWindow = new BrowserWindow({
+ width: 1200,
+ height: 800,
+ webPreferences: {
+ nodeIntegration: false,
+ contextIsolation: true,
+ },
+ title: 'Browser',
+ })
+
+ // 加载 URL
+ await browserWindow.loadURL(url)
+
+ logger.info('Opened URL in Electron browser window:', url)
+ } catch (error) {
+ logger.error('Failed to open URL in browser window:', String(error))
+ throw error
+ }
+ })
+ }
+
private setupAgentXIPC(): void {
// 获取 AgentX 服务器 URL
ipcMain.handle('agentx:getServerUrl', () => {
diff --git a/apps/desktop/src/main/windows/ResourceListWindow.ts b/apps/desktop/src/main/windows/ResourceListWindow.ts
index 71006644..dccc9dec 100644
--- a/apps/desktop/src/main/windows/ResourceListWindow.ts
+++ b/apps/desktop/src/main/windows/ResourceListWindow.ts
@@ -1000,8 +1000,7 @@ export class ResourceListWindow {
// 获取组织目录
let directory = null
try {
- const dirResult = await dispatcher.dispatch('directory', { role: payload.roleId })
- directory = typeof dirResult === 'string' ? JSON.parse(dirResult) : dirResult
+ directory = await dispatcher.dispatch('directory', { role: payload.roleId })
} catch { /* no organizations */ }
return { success: true, identity, focus, directory }
@@ -1010,6 +1009,24 @@ export class ResourceListWindow {
}
})
+ // 获取 RoleX 组织目录
+ ipcMain.handle('rolex:directory', async (_evt) => {
+ try {
+ const core = await import('@promptx/core')
+ const coreExports = (core as any).default || core
+ const { RolexActionDispatcher } = (coreExports as any).rolex
+ const dispatcher = new RolexActionDispatcher()
+
+ // directory() 现在返回结构化的 JSON 数据
+ const directory = await dispatcher.dispatch('directory', {})
+
+ return { success: true, data: directory }
+ } catch (error: any) {
+ console.error('Failed to get directory:', error)
+ return { success: false, message: error?.message }
+ }
+ })
+
// V2 角色文件列表(~/.rolex/roles//identity/)
ipcMain.handle('resources:listV2RoleFiles', async (_evt, payload: { roleId: string }) => {
try {
@@ -1056,6 +1073,49 @@ export class ResourceListWindow {
}
})
+ // V2 角色身份结构(从数据库读取)
+ ipcMain.handle('rolex:getIdentityNodes', async (_evt, payload: { roleId: string }) => {
+ try {
+ const core = require('@promptx/core')
+ const bridge = core.rolex.getRolexBridge()
+ const identityText = await bridge.identity(payload.roleId)
+ console.log('[rolex:getIdentityNodes] roleId:', payload.roleId)
+ console.log('[rolex:getIdentityNodes] identityText type:', typeof identityText)
+
+ // Parse the text into structured nodes
+ const nodes: any[] = []
+ if (typeof identityText === 'string') {
+ // Split by ## markers to find top-level nodes
+ const sections = identityText.split(/\n## \[/)
+ for (let i = 1; i < sections.length; i++) {
+ const section = sections[i]
+ // Extract node type and id from [type] (id)
+ const match = section.match(/^([^\]]+)\]\s*\(([^)]+)\)/)
+ if (match) {
+ const nodeType = match[1].trim()
+ const nodeId = match[2].trim()
+ // Extract the content (everything after the first line until next ## or end)
+ const contentMatch = section.match(/\n([\s\S]*?)(?=\n## \[|$)/)
+ const content = contentMatch ? contentMatch[1].trim() : ''
+
+ nodes.push({
+ id: nodeId,
+ name: nodeId,
+ type: nodeType,
+ information: content
+ })
+ }
+ }
+ }
+
+ console.log('[rolex:getIdentityNodes] Parsed nodes:', nodes.length)
+ return { success: true, data: nodes }
+ } catch (error: any) {
+ console.error('[rolex:getIdentityNodes] Error:', error)
+ return { success: false, message: error?.message }
+ }
+ })
+
// 获取角色头像(profile.png/jpg/jpeg/webp)→ base64 data URL
ipcMain.handle('resources:getRoleAvatar', async (_evt, payload: { id: string; source?: string }) => {
try {
diff --git a/apps/desktop/src/preload/index.ts b/apps/desktop/src/preload/index.ts
index c05a3a42..8a6d004d 100644
--- a/apps/desktop/src/preload/index.ts
+++ b/apps/desktop/src/preload/index.ts
@@ -174,7 +174,7 @@ contextBridge.exposeInMainWorld('electronAPI', {
},
// Shell API
shell: {
- openExternal: (url: string) => shell.openExternal(url),
+ openExternal: (url: string) => ipcRenderer.invoke('shell:openExternal', url),
},
// System info
platform: process.platform,
diff --git a/apps/desktop/src/view/components/agentx-ui/components/container/AgentList.tsx b/apps/desktop/src/view/components/agentx-ui/components/container/AgentList.tsx
index d8671a80..cd4e931c 100644
--- a/apps/desktop/src/view/components/agentx-ui/components/container/AgentList.tsx
+++ b/apps/desktop/src/view/components/agentx-ui/components/container/AgentList.tsx
@@ -194,7 +194,7 @@ export function AgentList({
const items: ListPaneItem[] = React.useMemo(() => {
return images.map((img) => ({
id: img.imageId,
- title: firstMessages[img.imageId] || img.name || t("agentxUI.conversations.untitled"),
+ title: img.name || firstMessages[img.imageId] || t("agentxUI.conversations.untitled"),
trailing: (
handleDialogClose(false)}
disabled={isRenaming}
>
- Cancel
+ {t("agentxUI.conversations.rename.cancel")}