diff --git a/apps/desktop/electron/electron-env.d.ts b/apps/desktop/electron/electron-env.d.ts index c92ef48a..006b28f0 100644 --- a/apps/desktop/electron/electron-env.d.ts +++ b/apps/desktop/electron/electron-env.d.ts @@ -68,6 +68,7 @@ interface SkillAddResult { interface ProfileData { profileId: string | undefined name: string | undefined + style: string | undefined userContent: string | undefined } @@ -106,6 +107,7 @@ interface ElectronAPI { profile: { get: () => Promise updateName: (name: string) => Promise + updateStyle: (style: string) => Promise updateUser: (content: string) => Promise } } diff --git a/apps/desktop/electron/ipc/profile.ts b/apps/desktop/electron/ipc/profile.ts index ed30130f..d6dd4dac 100644 --- a/apps/desktop/electron/ipc/profile.ts +++ b/apps/desktop/electron/ipc/profile.ts @@ -25,6 +25,7 @@ function getDefaultAgent() { export interface ProfileData { profileId: string | undefined name: string | undefined + style: string | undefined userContent: string | undefined } @@ -41,6 +42,7 @@ export function registerProfileIpcHandlers(): void { return { profileId: undefined, name: undefined, + style: undefined, userContent: undefined, } } @@ -48,6 +50,7 @@ export function registerProfileIpcHandlers(): void { return { profileId: agent.getProfileId(), name: agent.getAgentName(), + style: agent.getAgentStyle(), userContent: agent.getUserContent(), } }) @@ -88,4 +91,20 @@ export function registerProfileIpcHandlers(): void { return { ok: true } }) + + /** + * Update agent communication style. + */ + ipcMain.handle('profile:updateStyle', async (_event, style: string) => { + const agent = getDefaultAgent() + if (!agent) { + return { error: 'No agent available' } + } + + agent.setAgentStyle(style) + // Reload system prompt to apply changes immediately + agent.reloadSystemPrompt() + + return { ok: true, style } + }) } diff --git a/apps/desktop/electron/preload.ts b/apps/desktop/electron/preload.ts index e0afbf9a..73152aad 100644 --- a/apps/desktop/electron/preload.ts +++ b/apps/desktop/electron/preload.ts @@ -40,9 +40,14 @@ export interface SkillInfo { export interface ProfileData { profileId: string | undefined name: string | undefined + style: string | undefined userContent: string | undefined } +// Available style options +export const AGENT_STYLES = ['concise', 'warm', 'playful', 'professional'] as const +export type AgentStyle = (typeof AGENT_STYLES)[number] + // ============================================================================ // Expose typed API to Renderer process // ============================================================================ @@ -95,6 +100,7 @@ const electronAPI = { profile: { get: (): Promise => ipcRenderer.invoke('profile:get'), updateName: (name: string) => ipcRenderer.invoke('profile:updateName', name), + updateStyle: (style: string) => ipcRenderer.invoke('profile:updateStyle', style), updateUser: (content: string) => ipcRenderer.invoke('profile:updateUser', content), }, } diff --git a/apps/desktop/src/components/agent-settings-dialog.tsx b/apps/desktop/src/components/agent-settings-dialog.tsx index 3f44d548..5414a7c2 100644 --- a/apps/desktop/src/components/agent-settings-dialog.tsx +++ b/apps/desktop/src/components/agent-settings-dialog.tsx @@ -12,7 +12,15 @@ import { Input } from '@multica/ui/components/ui/input' import { Textarea } from '@multica/ui/components/ui/textarea' import { Label } from '@multica/ui/components/ui/label' import { HugeiconsIcon } from '@hugeicons/react' -import { Loading03Icon } from '@hugeicons/core-free-icons' +import { Loading03Icon, Tick02Icon } from '@hugeicons/core-free-icons' + +// Style options with labels +const STYLE_OPTIONS = [ + { value: 'concise', label: 'Concise', description: 'Brief and to the point' }, + { value: 'warm', label: 'Warm', description: 'Friendly and approachable' }, + { value: 'playful', label: 'Playful', description: 'Fun and lighthearted' }, + { value: 'professional', label: 'Professional', description: 'Formal and business-like' }, +] as const interface AgentSettingsDialogProps { open: boolean @@ -23,8 +31,8 @@ export function AgentSettingsDialog({ open, onOpenChange }: AgentSettingsDialogP const [loading, setLoading] = useState(false) const [saving, setSaving] = useState(false) const [name, setName] = useState('') + const [style, setStyle] = useState('concise') const [userContent, setUserContent] = useState('') - const [profileId, setProfileId] = useState() // Load profile data when dialog opens useEffect(() => { @@ -37,8 +45,8 @@ export function AgentSettingsDialog({ open, onOpenChange }: AgentSettingsDialogP setLoading(true) try { const data = await window.electronAPI.profile.get() - setProfileId(data.profileId) setName(data.name ?? '') + setStyle(data.style ?? 'concise') setUserContent(data.userContent ?? '') } catch (err) { console.error('Failed to load profile:', err) @@ -52,6 +60,8 @@ export function AgentSettingsDialog({ open, onOpenChange }: AgentSettingsDialogP try { // Update name if changed await window.electronAPI.profile.updateName(name) + // Update style + await window.electronAPI.profile.updateStyle(style) // Update user content await window.electronAPI.profile.updateUser(userContent) onOpenChange(false) @@ -68,7 +78,7 @@ export function AgentSettingsDialog({ open, onOpenChange }: AgentSettingsDialogP Edit Agent - Customize your agent's name and personal settings. + Customize your agent's name, style and personal settings. @@ -78,13 +88,6 @@ export function AgentSettingsDialog({ open, onOpenChange }: AgentSettingsDialogP ) : (
- {/* Profile ID (read-only) */} - {profileId && ( -
- Profile: {profileId} -
- )} - {/* Name */}
@@ -96,6 +99,35 @@ export function AgentSettingsDialog({ open, onOpenChange }: AgentSettingsDialogP />
+ {/* Style */} +
+ +
+ {STYLE_OPTIONS.map((option) => ( + + ))} +
+
+ {/* User Content */}
@@ -107,7 +139,7 @@ export function AgentSettingsDialog({ open, onOpenChange }: AgentSettingsDialogP value={userContent} onChange={(e) => setUserContent(e.target.value)} placeholder="- I'm a frontend developer - I prefer TypeScript - Please respond in Chinese" - className="min-h-[160px] font-mono text-sm" + className="min-h-[120px] font-mono text-sm" />