From 394cb66311cf7d29893569e0389b99dbc7c0ab40 Mon Sep 17 00:00:00 2001 From: iven Date: Thu, 23 Apr 2026 13:13:40 +0800 Subject: [PATCH] =?UTF-8?q?fix(identity):=20=E9=87=8D=E6=9E=84=20agent=20?= =?UTF-8?q?=E5=91=BD=E5=90=8D=E6=A3=80=E6=B5=8B=E6=AD=A3=E5=88=99=20?= =?UTF-8?q?=E2=80=94=20=E8=A6=86=E7=9B=96"=E5=90=8D=E7=A7=B0=E6=94=B9?= =?UTF-8?q?=E4=B8=BA=E5=B0=8F=E8=8A=B3"=E7=AD=89=E8=A1=A8=E8=BE=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit detectAgentNameSuggestion 从固定正则改为 trigger+extract 两步法, 10 个 trigger 模式覆盖中文/英文常见命名表达,stopWords 过滤误匹配。 同时修复 streamStore content 类型处理和 RightPanel 重复事件监听。 --- desktop/src/components/RightPanel.tsx | 7 ++-- desktop/src/lib/cold-start-mapper.ts | 48 ++++++++++++++++++--------- desktop/src/store/chat/streamStore.ts | 5 +-- 3 files changed, 39 insertions(+), 21 deletions(-) diff --git a/desktop/src/components/RightPanel.tsx b/desktop/src/components/RightPanel.tsx index 6b3f820..d43f49d 100644 --- a/desktop/src/components/RightPanel.tsx +++ b/desktop/src/components/RightPanel.tsx @@ -181,20 +181,21 @@ export function RightPanel({ simpleMode = false }: RightPanelProps) { }, [currentAgent?.id]); // Listen for profile updates after conversations (fired after memory extraction completes) + // This single handler handles both userProfile refresh and clone name refresh useEffect(() => { - const handler = (e: Event) => { + const handler = async (e: Event) => { const detail = (e as CustomEvent).detail; if (detail?.agentId === currentAgent?.id && currentAgent?.id) { invoke('agent_get', { agentId: currentAgent.id }) .then(data => setUserProfile(data?.userProfile ?? null)) .catch(() => {}); // Refresh clones data so selectedClone (name, role, nickname, etc.) stays current - loadClones(); + await loadClones(); } }; window.addEventListener('zclaw:agent-profile-updated', handler); return () => window.removeEventListener('zclaw:agent-profile-updated', handler); - }, [currentAgent?.id]); + }, [currentAgent?.id, clones]); // Listen for Tauri identity update events (from Rust post_conversation_hook) // When agent name changes in soul.md, update AgentConfig.name and refresh panel diff --git a/desktop/src/lib/cold-start-mapper.ts b/desktop/src/lib/cold-start-mapper.ts index 4e6b1e7..0ede0bc 100644 --- a/desktop/src/lib/cold-start-mapper.ts +++ b/desktop/src/lib/cold-start-mapper.ts @@ -147,25 +147,41 @@ export function detectNameSuggestion(message: string): string | undefined { } /** - * Detect if user gives the agent a name (e.g., "叫你小马", "以后叫你小马", "你的名字是小马"). - * Returns the detected agent name or undefined. + * Detect if user gives the agent a name. + * Covers: "叫你小马", "你就叫小芳", "名称改为小芳", "名字叫小马", + * "改名为X", "起名X", "称呼你为X", English patterns, etc. */ export function detectAgentNameSuggestion(message: string): string | undefined { - if (!message) return undefined; - const patterns = [ - /叫你[""''「」]?(\S{1,8})[""''「」]?[吧。!]?/, - /你的名字[是为][""''「」]?(\S{1,8})[""''「」]?[。!]?/, - /以后叫你[""''「」]?(\S{1,8})[""''「」]?[吧。!]?/, - /给你起[个]?名[字]?(?:叫)?[""''「」]?(\S{1,8})[""''「」]?/, - /name you (\S{1,15})/i, - /call you (\S{1,15})/i, + if (!message || typeof message !== 'string') return undefined; + // Trigger phrases: the name appears RIGHT AFTER the matched trigger + const triggers = [ + /叫你\s*[""''「」]?/, // "叫你小马" + /你就叫\s*[""''「」]?/, // "你就叫小芳" + /你(?:以後|以后)?叫\s*[""''「」]?/, // "你叫小马" / "你以后叫小马" + /[名].{0,2}[为是叫成]\s*[""''「」]?/, // "名称改为" / "名字是" / "名称改成" + /改[名为称叫]\s*[""''「」]?/, // "改名为X" / "改名X" / "改称X" + /起[个]?名[字]?(?:叫)?\s*[""''「」]?/, // "起名X" / "起名叫X" + /称呼[你你].{0,2}[为是]\s*[""''「」]?/, // "称呼你为X" + /\bname you\s+/i, + /\bcall you\s+/i, + /\byour name\s+(?:is|should be)\s+/i, ]; - for (const pattern of patterns) { - const match = message.match(pattern); - if (match && match[1]) { - const name = match[1].replace(/[吧。!,、]/g, '').trim(); - if (name.length >= 1 && name.length <= 8) { - return name; + const stopWords = new Set([ + '你', '我', '他', '她', '它', '的', '了', '是', '在', '有', '不', + '也', '都', '还', '又', '这', '那', '什么', '怎么', '为什么', '可以', + '能', '会', '要', '想', '去', '来', '做', '说', '看', '好', '吧', + '呢', '啊', '哦', '嗯', '哈', '呀', '嘛', + ]); + for (const trigger of triggers) { + const m = message.match(trigger); + if (!m) continue; + // Extract 1-6 Chinese characters or word chars after the trigger + const rest = message.slice(m.index! + m[0].length); + const nameMatch = rest.match(/^[""''「」]?([一-鿿]{1,6}|\w{1,10})/); + if (nameMatch && nameMatch[1]) { + const raw = nameMatch[1].replace(/[吧。!,、呢啊了]+$/g, '').trim(); + if (raw.length >= 1 && raw.length <= 8 && !stopWords.has(raw)) { + return raw; } } } diff --git a/desktop/src/store/chat/streamStore.ts b/desktop/src/store/chat/streamStore.ts index 7de8482..065a814 100644 --- a/desktop/src/store/chat/streamStore.ts +++ b/desktop/src/store/chat/streamStore.ts @@ -386,8 +386,9 @@ function createCompleteHandler( log.warn('Failed to persist detected userName:', e); } } - // Detect agent name change (e.g. "叫你小马", "以后叫你小马") - const detectedAgentName = lastUserMsg ? detectAgentNameSuggestion(lastUserMsg.content) : undefined; + // Detect agent name change (e.g. "叫你小马", "以后叫你小马", "你就叫小马吧") + const lastContent = typeof lastUserMsg?.content === 'string' ? lastUserMsg.content : ''; + const detectedAgentName = lastContent ? detectAgentNameSuggestion(lastContent) : undefined; if (detectedAgentName && agentId) { try { const { useAgentStore } = await import('../agentStore');