From 7d9354866afba52ba0419d004ad435ff1a45435e Mon Sep 17 00:00:00 2001 From: QAyong Date: Tue, 29 Sep 2026 03:34:07 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat(buddy):=20=E8=AE=BE=E7=BD=AE=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=20AI=20=E8=BA=AB=E4=BB=BD=EF=BC=8C=E5=8F=AF=E8=87=AA?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E8=81=8A=E5=A4=A9=E7=AA=97=E5=8F=A3=E7=9A=84?= =?UTF-8?q?=E5=A4=B4=E5=83=8F=E4=B8=8E=E5=90=8D=E7=A7=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 聊天窗口里 AI 回复上方的头像与名称此前是固定值(品牌头像 + Lexora Buddy)。 - 新增 desktop.agentProfile 配置(name / avatar / syncWithUserProfile),落盘为 [desktop.agent_profile] - 设置 → 外观 下新增「AI 身份」区块:可上传头像(≤2MB)、填写名称(≤30 字)、恢复默认 - 新增行内开关「同步用户头像与名称」:开启后照搬个人资料的解析结果(自定义头像或首字母圆 + 昵称),关闭后回到自定义/默认 - 聊天窗口与设置预览共用同一套解析(resolveUserProfile),两处渲染一致 - BuddyChatAgentIdentity 支持首字母头像分支,避免无头像时错误回退到品牌图标 - 新增单测:品牌兜底 / 自定义头像 / 首字母圆;既有 transcript 测试的 DesktopUi mock 同步补字段 - 新增 i18n:desktop.agent.*(中/英) --- .../electron/main/config/LexoraConfigStore.ts | 28 ++ .../__tests__/LexoraConfigStore.spec.ts | 5 + apps/buddy/electron/shared/desktopApi.ts | 10 +- .../electron/shared/desktopApiSchemas.ts | 7 + .../src/app/bootstrap/DesktopAppProvider.vue | 31 ++ apps/buddy/src/i18n/locales/en-US/app.ts | 14 + apps/buddy/src/i18n/locales/zh-CN/app.ts | 14 + apps/buddy/src/modules/settings/index.ts | 1 + .../pages/DesktopAppearanceSettingsView.vue | 13 +- .../src/modules/settings/settingsContext.ts | 10 +- .../app/DesktopAgentIdentitySettings.vue | 341 ++++++++++++++++++ .../transcript/BuddyChatAgentIdentity.vue | 25 +- .../__tests__/BuddyChatActivities.spec.ts | 1 + .../__tests__/BuddyChatAgentIdentity.spec.ts | 70 ++++ .../__tests__/BuddyChatMessageContent.spec.ts | 2 + .../__tests__/DesktopChatTranscript.spec.ts | 1 + apps/buddy/src/shared/ui/desktopUiContext.ts | 1 + 17 files changed, 568 insertions(+), 6 deletions(-) create mode 100644 apps/buddy/src/modules/settings/widgets/app/DesktopAgentIdentitySettings.vue create mode 100644 apps/buddy/src/modules/tasks/widgets/transcript/__tests__/BuddyChatAgentIdentity.spec.ts diff --git a/apps/buddy/electron/main/config/LexoraConfigStore.ts b/apps/buddy/electron/main/config/LexoraConfigStore.ts index 6637b64e..196203b6 100644 --- a/apps/buddy/electron/main/config/LexoraConfigStore.ts +++ b/apps/buddy/electron/main/config/LexoraConfigStore.ts @@ -64,6 +64,15 @@ const desktopConfigSchema = z.object({ device_name: '', avatar: '', }), + agent_profile: z.object({ + name: z.string().max(30).default(''), + avatar: z.string().max(DESKTOP_PROFILE_AVATAR_MAX_DATA_URL_LENGTH).default(''), + sync_with_user_profile: z.boolean().default(false), + }).passthrough().default({ + name: '', + avatar: '', + sync_with_user_profile: false, + }), developer_tools_enabled: z.boolean().default(false), language: z.enum(['zh-CN', 'en-US']).default('zh-CN'), launch_at_login: z.boolean().default(false), @@ -86,6 +95,7 @@ const desktopConfigSchema = z.object({ task_sidebar_pinned_items: [], task_sidebar: { collapsed: false, collapsed_sections: [], collapsed_spaces: [] }, profile: { user_name: '', device_name: '', avatar: '' }, + agent_profile: { name: '', avatar: '', sync_with_user_profile: false }, developer_tools_enabled: false, language: 'zh-CN', launch_at_login: false, @@ -312,6 +322,11 @@ function decodeConfig(value: unknown): LexoraConfig { deviceName: config.desktop.profile.device_name, avatar: config.desktop.profile.avatar, }, + agentProfile: { + name: config.desktop.agent_profile.name, + avatar: config.desktop.agent_profile.avatar, + syncWithUserProfile: config.desktop.agent_profile.sync_with_user_profile, + }, developerToolsEnabled: config.desktop.developer_tools_enabled, language: config.desktop.language, launchAtLogin: config.desktop.launch_at_login, @@ -363,6 +378,11 @@ function encodeConfig(config: LexoraConfig) { device_name: config.desktop.profile.deviceName, avatar: config.desktop.profile.avatar, }, + agent_profile: { + name: config.desktop.agentProfile.name, + avatar: config.desktop.agentProfile.avatar, + sync_with_user_profile: config.desktop.agentProfile.syncWithUserProfile, + }, developer_tools_enabled: config.desktop.developerToolsEnabled, language: config.desktop.language, launch_at_login: config.desktop.launchAtLogin, @@ -405,6 +425,10 @@ function mergeConfig(current: LexoraConfig, patch: LexoraConfigPatch): LexoraCon ...current.desktop.profile, ...patch.desktop?.profile, }, + agentProfile: { + ...current.desktop.agentProfile, + ...patch.desktop?.agentProfile, + }, }, pet: { ...current.pet, @@ -433,6 +457,10 @@ function mergeConfigFile(file: unknown, config: LexoraConfig): Record { deviceName: '', userName: '', }, + agentProfile: { + avatar: '', + name: '', + syncWithUserProfile: false, + }, sidebarCollapsed: false, theme: 'dark', }) diff --git a/apps/buddy/electron/shared/desktopApi.ts b/apps/buddy/electron/shared/desktopApi.ts index f9e117f4..811dbe58 100644 --- a/apps/buddy/electron/shared/desktopApi.ts +++ b/apps/buddy/electron/shared/desktopApi.ts @@ -99,6 +99,12 @@ export interface DesktopUserProfileConfig { avatar: string } +export interface DesktopAgentProfileConfig { + name: string + avatar: string + syncWithUserProfile: boolean +} + export interface DesktopAppInfo { runtimeProfile: BuddyRuntimeProfile isPackaged: boolean @@ -181,6 +187,7 @@ export interface LexoraConfig { updateNotificationsEnabled: boolean notifyWhenFocused: boolean profile: DesktopUserProfileConfig + agentProfile: DesktopAgentProfileConfig pluginAuthor: string sidebarCollapsed: boolean theme: 'system' | 'light' | 'dark' @@ -196,10 +203,11 @@ export interface LexoraConfigPatch { runtime?: Partial browser?: Partial proxy?: LexoraConfig['proxy'] - desktop?: Partial> & { + desktop?: Partial> & { chat?: Partial taskSidebar?: Partial profile?: Partial + agentProfile?: Partial } pet?: Partial } diff --git a/apps/buddy/electron/shared/desktopApiSchemas.ts b/apps/buddy/electron/shared/desktopApiSchemas.ts index abc356e8..18ee70d5 100644 --- a/apps/buddy/electron/shared/desktopApiSchemas.ts +++ b/apps/buddy/electron/shared/desktopApiSchemas.ts @@ -46,6 +46,12 @@ const desktopUserProfilePatchSchema = z.object({ avatar: z.string().max(DESKTOP_PROFILE_AVATAR_MAX_DATA_URL_LENGTH).optional(), }).strict() +const desktopAgentProfilePatchSchema = z.object({ + name: z.string().max(30).optional(), + avatar: z.string().max(DESKTOP_PROFILE_AVATAR_MAX_DATA_URL_LENGTH).optional(), + syncWithUserProfile: z.boolean().optional(), +}).strict() + export const feedbackIssueInputSchema = z.object({ feedback: z.string().max(4_000), }).strict() @@ -75,6 +81,7 @@ export const lexoraConfigPatchSchema: z.ZodType = z.object({ taskSidebarPinnedItems: taskSidebarPinnedItemsSchema.optional(), taskSidebar: taskSidebarPreferencesSchema.optional(), profile: desktopUserProfilePatchSchema.optional(), + agentProfile: desktopAgentProfilePatchSchema.optional(), developerToolsEnabled: z.boolean().optional(), pluginAuthor: extensionAuthorSchema.optional(), language: z.enum(['zh-CN', 'en-US']).optional(), diff --git a/apps/buddy/src/app/bootstrap/DesktopAppProvider.vue b/apps/buddy/src/app/bootstrap/DesktopAppProvider.vue index 14624c75..89bce327 100644 --- a/apps/buddy/src/app/bootstrap/DesktopAppProvider.vue +++ b/apps/buddy/src/app/bootstrap/DesktopAppProvider.vue @@ -1,4 +1,5 @@ diff --git a/apps/buddy/src/modules/settings/settingsContext.ts b/apps/buddy/src/modules/settings/settingsContext.ts index 5e531e6a..4ec7897d 100644 --- a/apps/buddy/src/modules/settings/settingsContext.ts +++ b/apps/buddy/src/modules/settings/settingsContext.ts @@ -1,4 +1,4 @@ -import type { DesktopAppInfo, DesktopBrowserApi } from '@buddy-electron/shared/desktopApi' +import type { DesktopAgentProfileConfig, DesktopAppInfo, DesktopBrowserApi, DesktopUserProfileConfig } from '@buddy-electron/shared/desktopApi' import type { BuddyCapabilities } from '@buddy-shared/platform' import type { Ref } from 'vue' import type { ApplicationSettings, ShortcutSettings } from './contracts' @@ -19,6 +19,14 @@ export interface SettingsContext { applicationSettings: ApplicationSettings dataSettings: DesktopDataSettingsCapability platformCapabilities: Readonly> + profile: { + config: Readonly> + update: (patch: Partial) => Promise + } + agentProfile: { + config: Readonly> + update: (patch: Partial) => Promise + } providerSettings: ModelProvidersStore ready: Promise openTask: (conversationId: string) => Promise diff --git a/apps/buddy/src/modules/settings/widgets/app/DesktopAgentIdentitySettings.vue b/apps/buddy/src/modules/settings/widgets/app/DesktopAgentIdentitySettings.vue new file mode 100644 index 00000000..c8961a92 --- /dev/null +++ b/apps/buddy/src/modules/settings/widgets/app/DesktopAgentIdentitySettings.vue @@ -0,0 +1,341 @@ + + + + + diff --git a/apps/buddy/src/modules/tasks/widgets/transcript/BuddyChatAgentIdentity.vue b/apps/buddy/src/modules/tasks/widgets/transcript/BuddyChatAgentIdentity.vue index 9338011c..0799c6d3 100644 --- a/apps/buddy/src/modules/tasks/widgets/transcript/BuddyChatAgentIdentity.vue +++ b/apps/buddy/src/modules/tasks/widgets/transcript/BuddyChatAgentIdentity.vue @@ -1,26 +1,34 @@ @@ -50,6 +58,17 @@ const { t } = useBuddyI18n(() => props.language) object-fit: cover; } +.buddy-chat-agent-identity__initials { + display: grid; + width: 100%; + height: 100%; + place-items: center; + color: var(--buddy-text-on-accent); + font-size: calc(var(--buddy-chat-avatar-size) * 0.45); + font-weight: 600; + line-height: 1; +} + .buddy-chat-agent-identity__name { min-width: 0; color: var(--buddy-chat-agent-name-color); diff --git a/apps/buddy/src/modules/tasks/widgets/transcript/__tests__/BuddyChatActivities.spec.ts b/apps/buddy/src/modules/tasks/widgets/transcript/__tests__/BuddyChatActivities.spec.ts index 7faa2339..f63de588 100644 --- a/apps/buddy/src/modules/tasks/widgets/transcript/__tests__/BuddyChatActivities.spec.ts +++ b/apps/buddy/src/modules/tasks/widgets/transcript/__tests__/BuddyChatActivities.spec.ts @@ -512,6 +512,7 @@ function mountTurn(nodes: ChatAgentTurnNode[], status: ChatAgentTurn['status'] = isDark: shallowRef(false), appSidebarCollapsed: shallowRef(false), chat: shallowRef({ outlinePosition: 'top-right', permissionMode: 'policy_approval', welcome: 'random' }), + agentIdentity: shallowRef({ avatar: '', avatarColor: null, initials: null, name: '' }), }) useProvideChatContent({ canPreviewFile: () => false, previewFile: () => {}, writeClipboardText: async () => {} }) return () => h(NMessageProvider, null, { default: () => [ diff --git a/apps/buddy/src/modules/tasks/widgets/transcript/__tests__/BuddyChatAgentIdentity.spec.ts b/apps/buddy/src/modules/tasks/widgets/transcript/__tests__/BuddyChatAgentIdentity.spec.ts new file mode 100644 index 00000000..2238227b --- /dev/null +++ b/apps/buddy/src/modules/tasks/widgets/transcript/__tests__/BuddyChatAgentIdentity.spec.ts @@ -0,0 +1,70 @@ +// @vitest-environment jsdom +import type { Ref } from 'vue' +import { describe, expect, it } from 'vitest' +import { createApp, h, nextTick, shallowRef } from 'vue' +import { useProvideDesktopUi } from '@/shared/ui/desktopUiContext' +import { BRAND_ASSET_URLS } from '@/shared/branding/brandAssets' +import BuddyChatAgentIdentity from '../BuddyChatAgentIdentity.vue' + +interface AgentIdentityInput { + avatar: string + avatarColor: string | null + initials: string | null + name: string +} + +function render(agentIdentity: Ref) { + const root = document.createElement('div') + const app = createApp({ + setup() { + useProvideDesktopUi({ + language: shallowRef('zh-CN'), + isDark: shallowRef(false), + sidebarCollapsed: shallowRef(false), + chat: shallowRef({ outlinePosition: 'top-right', permissionMode: 'policy_approval', welcome: 'random' }), + agentIdentity, + }) + return () => h(BuddyChatAgentIdentity, { language: 'zh-CN' }) + }, + }) + app.mount(root) + return { app, root } +} + +function identity(overrides: Partial = {}): AgentIdentityInput { + return { avatar: '', avatarColor: null, initials: null, name: '', ...overrides } +} + +describe('buddyChatAgentIdentity', () => { + it('falls back to the brand avatar and default name', async () => { + const { app, root } = render(shallowRef(identity())) + await nextTick() + + expect(root.querySelector('img')?.getAttribute('src')).toBe(BRAND_ASSET_URLS.chatAvatar) + expect(root.querySelector('.buddy-chat-agent-identity__name')?.textContent.trim()).toBe('Lexora Buddy') + + app.unmount() + }) + + it('renders the configured agent name and avatar', async () => { + const { app, root } = render(shallowRef(identity({ avatar: 'data:image/png;base64,abc', name: '小助手' }))) + await nextTick() + + expect(root.querySelector('img')?.getAttribute('src')).toBe('data:image/png;base64,abc') + expect(root.querySelector('.buddy-chat-agent-identity__name')?.textContent.trim()).toBe('小助手') + + app.unmount() + }) + + it('mirrors the profile initials avatar when syncing with the user profile', async () => { + const { app, root } = render(shallowRef(identity({ avatarColor: '#4a72b0', initials: 'AQ', name: 'Ayong Q' }))) + await nextTick() + + expect(root.querySelector('img')).toBeNull() + expect(root.querySelector('.buddy-chat-agent-identity__initials')?.textContent.trim()).toBe('AQ') + expect(root.querySelector('.buddy-chat-agent-identity__avatar')?.getAttribute('style')).toContain('rgb(74, 114, 176)') + expect(root.querySelector('.buddy-chat-agent-identity__name')?.textContent.trim()).toBe('Ayong Q') + + app.unmount() + }) +}) diff --git a/apps/buddy/src/modules/tasks/widgets/transcript/__tests__/BuddyChatMessageContent.spec.ts b/apps/buddy/src/modules/tasks/widgets/transcript/__tests__/BuddyChatMessageContent.spec.ts index 21b56063..3070ce14 100644 --- a/apps/buddy/src/modules/tasks/widgets/transcript/__tests__/BuddyChatMessageContent.spec.ts +++ b/apps/buddy/src/modules/tasks/widgets/transcript/__tests__/BuddyChatMessageContent.spec.ts @@ -86,6 +86,7 @@ describe('buddyChatMessageContent', () => { isDark: shallowRef(false), appSidebarCollapsed: shallowRef(false), chat: shallowRef({ outlinePosition: 'top-right', permissionMode: 'policy_approval', welcome: 'random' }), + agentIdentity: shallowRef({ avatar: '', avatarColor: null, initials: null, name: '' }), }) useProvideChatContent({ canPreviewFile, @@ -225,6 +226,7 @@ function renderContent(message: LocalMessage, isDark = false) { isDark: shallowRef(isDark), appSidebarCollapsed: shallowRef(false), chat: shallowRef({ outlinePosition: 'top-right', permissionMode: 'policy_approval', welcome: 'random' }), + agentIdentity: shallowRef({ avatar: '', avatarColor: null, initials: null, name: '' }), }) return () => h(BuddyChatMessageContent, { language: 'zh-CN', diff --git a/apps/buddy/src/modules/tasks/widgets/transcript/__tests__/DesktopChatTranscript.spec.ts b/apps/buddy/src/modules/tasks/widgets/transcript/__tests__/DesktopChatTranscript.spec.ts index 53a9a36f..ec3f592c 100644 --- a/apps/buddy/src/modules/tasks/widgets/transcript/__tests__/DesktopChatTranscript.spec.ts +++ b/apps/buddy/src/modules/tasks/widgets/transcript/__tests__/DesktopChatTranscript.spec.ts @@ -97,6 +97,7 @@ function mountTranscript(loadOutlineMessages: () => Promise h(DesktopChatTranscript, props.value) }, diff --git a/apps/buddy/src/shared/ui/desktopUiContext.ts b/apps/buddy/src/shared/ui/desktopUiContext.ts index ca58d46b..0d872f34 100644 --- a/apps/buddy/src/shared/ui/desktopUiContext.ts +++ b/apps/buddy/src/shared/ui/desktopUiContext.ts @@ -8,6 +8,7 @@ interface DesktopUiContext { isDark: Readonly> chat: Readonly>> appSidebarCollapsed: Readonly> + agentIdentity: Readonly> } const [useProvideDesktopUi, injectDesktopUi] = createInjectionState( From 156ae9afeb9b476e5e75121e6ff6a9506ee9858b Mon Sep 17 00:00:00 2001 From: QAyong Date: Tue, 29 Sep 2026 16:39:04 +0800 Subject: [PATCH 2/2] docs: add AI identity settings preview --- pr-assets/ai-identity-demo.png | Bin 0 -> 19898 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 pr-assets/ai-identity-demo.png diff --git a/pr-assets/ai-identity-demo.png b/pr-assets/ai-identity-demo.png new file mode 100644 index 0000000000000000000000000000000000000000..e42171d3a5addb1916cade6915105c2fe40154e7 GIT binary patch literal 19898 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ñTPTx_JACsfAf9TRZN7_b-qS_^FCu{pr~y8#wD{ksqB;%b(d zI^p2kvXf7XRxICsd>8o0pa#R`z%xbkraR}EPvucI)KY9#5&hLA!qqC$>9S@u*bE6{ zVDScA$bP0l+XkK=g74S literal 0 HcmV?d00001