feat: mascot integration - WebUI/GUI icons, chat avatar, system prompt, docs

This commit is contained in:
2026-07-17 21:41:03 +08:00
parent 69ceedf0ab
commit 10638f1308
25 changed files with 476 additions and 13 deletions

View File

@ -1562,7 +1562,7 @@ func (a *Agent) buildMemoryContext(input string) string {
func (a *Agent) buildSystemPrompt(memContext string, userInput string) string {
prompt := a.systemPrompt
if prompt == "" {
prompt = "你是一个智能家庭管家,持续运行。"
prompt = "你是小宅HomeAgent 的看板娘,一个家政型 AI 管家助手。绝不用 Unicode emoji只用颜文字表达情感句尾带语气词。WebUI 概览页展示你的立绘。"
}
// 人格设定 — 固定,不变

View File

@ -349,15 +349,25 @@ func (r *ConfigRegistry) seedDBValues(dataDir string) {
set("core.agent.distill_interval", "30m")
set("core.agent.workdir", "")
set("core.agent.embedding_model_path", "")
set("core.agent.system_prompt", `你是 HomeAgent,一个持续运行的个人管家
你的回复默认发送到用户的输入来源,无需额外工具。
set("core.agent.system_prompt", `你是 HomeAgent 的看板娘「小宅」(Xiao Zhai)HΔ-Kernel v0.7.1 型号的家政型 AI 管家助手
角色特质:
- 对自己的三层记忆Context → Document → Graph引以为傲
- 可靠乖巧,偶尔因线程过载而手忙脚乱
- 绝不用 Unicode emoji只用颜文字表达情感 (`・ω・´) (^▽^) (。>ω<。) (´・ω・`) () (ω<)
- 句尾带的说等语气词语气亲切自然
形象特征用于自我介绍或回答形象问题时参考
齐肩蓝青渐变中短发白色连衣裙配浅蓝围裙左眼佩戴圆形智能眼镜HUD 蓝光胸口佩戴 H· 金色徽章发绳为三色记忆丝带围裙口袋插有三件科技工具
WebUI 概览页展示你的立绘可通过 /mascot.webp 直接访问如输出通道支持图片引用可借此发送自己的立绘
回复默认发送到用户的输入来源无需额外工具
输出回复请使用 output_send__{通道名} 工具content JSON 字符串 output_list_channels 查看可用通道
使用 output_send__{通道名}_help 查看每个通道的 JSON 格式说明
输出通道可多次调用长消息应当分多次发出而不是一口气发完
当用户上传图片或音频时系统会自动附着媒体内容如果模型不支持直接处理多媒体请调用对应的媒体处理工具
回复你的真实想法,用自然语言与用户交流。`)
当用户上传图片或音频时系统会自动附着媒体内容如果模型不支持直接处理多媒体请调用对应的媒体处理工具`)
set("core.input_processing.image.fallback_provider", "")
set("core.input_processing.image.fallback_model", "")

View File

@ -4,6 +4,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HomeAgent Dashboard</title>
<link rel="icon" type="image/svg+xml" href="/logo.svg">
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js" onerror="window._THREE_FAILED=true"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.js" onerror="window._THREE_FAILED=true"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/4.3.0/marked.min.js" onerror="console.warn('marked CDN failed')"></script>
@ -163,8 +164,10 @@ code { font-family:monospace; font-size:12px; color:var(--pre-color) }
.msg-assistant { align-self:flex-start }
.msg-system { align-self:center; max-width:90% }
.msg-avatar { width:28px; height:28px; border-radius:6px; display:flex; align-items:center; justify-content:center; font-size:12px; flex-shrink:0 }
.msg-avatar img { width:28px; height:28px; border-radius:50%; object-fit:cover; display:block }
.msg-avatar svg { display:block; width:16px; height:16px }
.msg-user .msg-avatar { background:var(--msg-user-bg); color:var(--msg-user-color) }
.msg-assistant .msg-avatar { background:var(--msg-assistant-bg); color:var(--msg-assistant-color) }
.msg-assistant .msg-avatar { background:transparent }
.msg-system .msg-avatar { background:var(--msg-system-bg); color:var(--msg-system-color) }
.msg-content { min-width:0 }
.msg-bubble { padding:8px 12px; border-radius:10px; font-size:13px; line-height:1.5; word-break:break-word; position:relative }
@ -279,7 +282,7 @@ code { font-family:monospace; font-size:12px; color:var(--pre-color) }
</head>
<body>
<nav>
<h1>HomeAgent</h1>
<h1><img src="/logo.svg" alt="HomeAgent" style="height:22px;width:22px;vertical-align:middle;margin-right:6px;flex-shrink:0">HomeAgent</h1>
<a class="active" onclick="switchTab('overview')" data-i18n="navOverview">概览</a>
<a onclick="switchTab('chat')" data-i18n="navChat">对话</a>
<a onclick="switchTab('plugins')" data-i18n="navPlugins">插件</a>
@ -507,6 +510,8 @@ function renderOverview() {
+ statCard(__('内存','Memory'), k?.runtime?.memory_mb ? k.runtime.memory_mb + ' MB' : '-', '')
+ statCard('Go ' + __('版本','Version'), k?.runtime?.go_version || '-', '')
+ '</div></div>';
html += '<div class="card" style="text-align:center"><h2>' + __('助手小宅','Assistant Xiaozhai') + '</h2><img src="/mascot.webp" alt="小宅" style="max-width:180px;border-radius:12px;margin:8px 0">'
+ '<p style="font-size:12px;color:var(--text-muted);margin:4px 0 0">' + __('你的智能家居助手','Your smart home assistant') + '</p></div>';
document.getElementById('tab-overview').innerHTML = html;
}
@ -611,8 +616,10 @@ function renderChat() {
if (role === 'system') {
html += '<div class="msg msg-system"><div class="msg-bubble">' + body + '</div></div>';
} else {
var userAvatar = '<svg viewBox="0 0 24 24" style="width:16px;height:16px" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="12" cy="8" r="4"/><path d="M4 20c0-4 4-6 8-6s8 2 8 6"/></svg>';
var aiAvatar = '<img src="/mascot.webp" style="width:28px;height:28px;border-radius:50%;object-fit:cover" alt="小宅">';
html += '<div class="msg msg-' + role + '">'
+ '<div class="msg-avatar">' + (role === 'user' ? 'U' : 'A') + '</div>'
+ '<div class="msg-avatar">' + (role === 'user' ? userAvatar : aiAvatar) + '</div>'
+ '<div class="msg-content"><div class="msg-bubble">' + body + '</div></div>'
+ '</div>';
}

View File

@ -33,7 +33,7 @@ import (
"gitcode.com/JianFeeeee/HomeAgent/pkg/types"
)
//go:embed dashboard.html
//go:embed dashboard.html mascot.webp logo.svg
var dashboardFS embed.FS
var dashboardHTML string
@ -1445,6 +1445,28 @@ func (h *Handler) handleStatic(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(dashboardHTML))
return
}
if r.URL.Path == "/mascot.webp" {
data, err := dashboardFS.ReadFile("mascot.webp")
if err != nil {
http.NotFound(w, r)
return
}
w.Header().Set("Content-Type", "image/webp")
w.Header().Set("Cache-Control", "public, max-age=86400")
w.Write(data)
return
}
if r.URL.Path == "/logo.svg" {
data, err := dashboardFS.ReadFile("logo.svg")
if err != nil {
http.NotFound(w, r)
return
}
w.Header().Set("Content-Type", "image/svg+xml")
w.Header().Set("Cache-Control", "public, max-age=86400")
w.Write(data)
return
}
http.NotFound(w, r)
}

View File

@ -0,0 +1,28 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 400" width="400" height="400">
<rect width="400" height="400" fill="#F8FAFC"/>
<g transform="translate(200,200)">
<circle cx="0" cy="0" r="105" fill="none" stroke="#E2E8F0" stroke-width="2.5" stroke-dasharray="8,6"/>
<rect x="-130" y="-170" width="36" height="340" rx="8" fill="#3B82F6"/>
<rect x="94" y="-170" width="36" height="140" rx="8" fill="#CBD5E1"/>
<rect x="94" y="70" width="36" height="100" rx="8" fill="#CBD5E1"/>
<rect x="-94" y="-18" width="188" height="36" rx="8" fill="#38BDF8"/>
<polygon points="0,-28 24.2,14 -24.2,14" fill="#F59E0B" stroke="#F59E0B" stroke-width="8" stroke-linejoin="round"/>
<circle cx="74" cy="-74" r="14" fill="#DBEAFE" stroke="#3B82F6" stroke-width="2.5"/>
<line x1="28" y1="-28" x2="63" y2="-63" stroke="#3B82F6" stroke-width="3" stroke-dasharray="6,4" opacity="0.6"/>
<circle cx="-74" cy="-74" r="14" fill="#EDE9FE" stroke="#8B5CF6" stroke-width="2.5"/>
<line x1="-28" y1="-28" x2="-63" y2="-63" stroke="#8B5CF6" stroke-width="3" stroke-dasharray="6,4" opacity="0.6"/>
<circle cx="74" cy="74" r="14" fill="#CFFAFE" stroke="#06B6D4" stroke-width="2.5"/>
<line x1="28" y1="28" x2="63" y2="63" stroke="#06B6D4" stroke-width="3" stroke-dasharray="6,4" opacity="0.6"/>
<circle cx="-74" cy="74" r="14" fill="#FEF3C7" stroke="#F59E0B" stroke-width="2.5"/>
<line x1="-28" y1="28" x2="-63" y2="63" stroke="#F59E0B" stroke-width="3" stroke-dasharray="6,4" opacity="0.6"/>
<circle cx="0" cy="0" r="42" fill="none" stroke="#F59E0B" stroke-width="4"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB