From 6a1225a6b77dd729ebab9f403aeebc3b69ebfdbb Mon Sep 17 00:00:00 2001 From: xmanrui <841206367@qq.com> Date: Tue, 23 Jun 2026 12:59:20 +0800 Subject: [PATCH] Validate identity emoji values --- app/api/agent-activity/route.ts | 20 ++++++++++++++++---- app/api/config/route.ts | 15 +++++++++++++-- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/app/api/agent-activity/route.ts b/app/api/agent-activity/route.ts index da03019..ae29af0 100644 --- a/app/api/agent-activity/route.ts +++ b/app/api/agent-activity/route.ts @@ -29,6 +29,17 @@ function normalizeIdentityValue(rawValue: string): string | null { return value || null } +function isEmojiLike(value: string): boolean { + return /\p{Extended_Pictographic}/u.test(value) || /[\u{1F1E6}-\u{1F1FF}]{2}/u.test(value) +} + +function normalizeIdentityEmoji(rawEmoji: unknown): string | null { + if (typeof rawEmoji !== 'string') return null + const emoji = normalizeIdentityValue(rawEmoji) + if (!emoji || !isEmojiLike(emoji)) return null + return emoji +} + type SessionsIndex = Record type CronStoreJob = { id: string @@ -1015,7 +1026,7 @@ export async function GET() { const emojiLine = identityRaw.split(/\r?\n/).find((line) => /\*\*Emoji:\*\*/.test(line)) const m = emojiLine?.match(/\*\*Emoji:\*\*\s*(.*)$/) if (m) { - const emoji = normalizeIdentityValue(m[1]) + const emoji = normalizeIdentityEmoji(m[1]) if (emoji) agentJsonEmoji = emoji } } catch { /* ignore */ } @@ -1028,8 +1039,9 @@ export async function GET() { try { const raw = await fs.readFile(agentJsonPath, 'utf8') const parsed = JSON.parse(raw) - if (typeof parsed?.emoji === 'string' && parsed.emoji.trim()) { - agentJsonEmoji = parsed.emoji.trim() + const emoji = normalizeIdentityEmoji(parsed?.emoji) + if (emoji) { + agentJsonEmoji = emoji } } catch { /* ignore */ } } @@ -1130,7 +1142,7 @@ export async function GET() { agents.push({ agentId: agent.id, name: agent.name || agent.id, - emoji: agentJsonEmoji || agent.identity?.emoji || agent.emoji || '🤖', + emoji: agentJsonEmoji || normalizeIdentityEmoji(agent.identity?.emoji) || normalizeIdentityEmoji(agent.emoji) || '🤖', state, lastActive, subagents, diff --git a/app/api/config/route.ts b/app/api/config/route.ts index 25c7537..d0a40f5 100644 --- a/app/api/config/route.ts +++ b/app/api/config/route.ts @@ -251,6 +251,17 @@ function normalizeIdentityName(rawName: string): string | null { return name || null; } +function isEmojiLike(value: string): boolean { + return /\p{Extended_Pictographic}/u.test(value) || /[\u{1F1E6}-\u{1F1FF}]{2}/u.test(value); +} + +function normalizeIdentityEmoji(rawEmoji: unknown): string | null { + if (typeof rawEmoji !== "string") return null; + const emoji = normalizeIdentityName(rawEmoji); + if (!emoji || !isEmojiLike(emoji)) return null; + return emoji; +} + // 从 IDENTITY.md 读取机器人名字 function readIdentityEmoji(agentId: string, agentDir?: string, workspace?: string): string | null { const candidates = [ @@ -267,7 +278,7 @@ function readIdentityEmoji(agentId: string, agentDir?: string, workspace?: strin const emojiLine = content.split(/\r?\n/).find((line) => /\*\*Emoji:\*\*/.test(line)); const match = emojiLine?.match(/\*\*Emoji:\*\*\s*(.*)$/); if (match) { - const emoji = normalizeIdentityName(match[1]); + const emoji = normalizeIdentityEmoji(match[1]); if (emoji) return emoji; } } catch {} @@ -400,7 +411,7 @@ export async function GET() { const identityName = readIdentityName(id, agent.agentDir, agent.workspace); const name = identityName || agent.name || id; const identityEmoji = readIdentityEmoji(id, agent.agentDir, agent.workspace); - const emoji = identityEmoji || agent.identity?.emoji || agent.emoji || "🤖"; + const emoji = identityEmoji || normalizeIdentityEmoji(agent.identity?.emoji) || normalizeIdentityEmoji(agent.emoji) || "🤖"; const model = normalizeModelRef(agent.model, defaultModel); // 查找绑定的平台