mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-11-01 23:07:30 +00:00
## ① 全面改名 HomeAgent → HologramAgent
仓库已改名,但代码与文档里仍有大量旧名。本次按"用户能看到的优先"全量替换:
- 用户可见:登录页标题/页脚、默认人格第一句、CLI 状态输出、启动日志、
plugin_install 的工具描述、AI 图片插件的 User-Agent
- 文档与脚本:README、assets/docs、docs/zh、deploy/*.sh、.github/workflows
- 鸿蒙工程:cmd/ohos/HomeAgent → cmd/ohos/HologramAgent(git mv)
目录内的 module/app 描述同步;**证书路径原样保留**
(default_HomeAgent_xxx.cer/p7b/p12 是签名材料的实际文件名,改了会找不到证书)
- 插件元数据:plugin.json 的 author
★ 必须保持原样的两处(改了会坏):
· legacySeededPromptSignature = "你是 HomeAgent 的看板娘「小宅」…"
—— 那是识别历史播种人格卡的**原文锚点**,改了就识别不出旧数据
· 公开 SDK 的 ProxyAuthHomeAgent = "homeagent"
—— 那是 SDK 契约里的值,属独立仓库,本仓不改
## ② 修 21 处乱码(U+FFFD)
这些是历史编辑留下的编码破坏,全在注释里,例如:
「赌注重下���遍」→「赌注重下一遍」
「「不��滤」」 →「「不过滤」」
「**待��退场**」→「**待退场**」
★ 保留 providers/chineseclip/tokenizer.go 里的 2 处:那是**故意**用
U+FFFD 演示"非法 UTF-8 字节被归一成 U+FFFD",不是乱码。
## ③ 提示词技术内容下沉(用户:技术性内容应该收敛到 skill 与 -help 中)
实测系统提示词 2309 字,其中两段几乎全是**模型无法据以行动的实现细节**:
【工具执行顺序】1272 字(ParallelSafe 声明、批内降级、batchRunnable 判据…)
【三层记忆】 1069 字(L1/L2/L3 编号、消费式删除、向量空间、指纹…)
收敛后 **2309 → 1723 字(-25%)**,保留的全是"模型据此做什么不同的事":
工具顺序:默认并行 / 不要依赖先后 / 同通道保序 / 写类工具可能串行
三层记忆:时序里能看最近 / doc_query 把历史事件按原始时间戳插回时序 /
关系用 memory_recall / 成文知识用 knowledge_search
判断口径写进判据:新加一段提示词前先问"模型会据此做什么不同的事",
答不上来就该进 skill 或工具描述。
## 判据
prompt_memory_test.go 新增 2 条:
- TestSystemPromptHasNoImplementationJargon
黑名单:ParallelSafe / batchRunnable / 消费式 / DenseCosine / fingerprint /
向量空间 / 批内降级 / 自激
- TestSystemPromptStaysCompact:上限 2000 字(当前 1723)
变异:把 "ParallelSafe 声明、批内降级" 加回工具顺序段 ⇒ 第一条立刻红。
## 验证
- go build ./... / go vet ./... 干净
- go test ./... -count=1:58 包 0 失败
- make check-client-versions:客户端与内核版本一致
360 lines
12 KiB
HTML
360 lines
12 KiB
HTML
<!doctype html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||
<title>HologramAgent</title>
|
||
<link rel="icon" type="image/svg+xml" href="icon.svg" />
|
||
<link rel="stylesheet" href="style.css" />
|
||
<!--
|
||
第三方库全部本地化(renderer/vendor/),不引用任何公网 CDN。
|
||
|
||
为什么(与服务端 webui 插件同一条理由,见
|
||
internal/plugins/webui/starmap_vendor_test.go 的注释):
|
||
HologramAgent 明确支持离线/内网部署,而前端原本有 4 个硬依赖在公网上
|
||
(cdnjs/jsdelivr)。真实现象是「服务端 curl 同一批 URL 返回 200,
|
||
但用户点星图看到『3D 星图不可用(CDN 加载失败)』」——不是服务端的问题,
|
||
是客户端访问不到公共 CDN(内网/出口受限/断网)。
|
||
换 CDN 只是把同一个赌注重下一遍。
|
||
|
||
★ 版本与 internal/plugins/webui/static/ 下那四个文件一致(同样是
|
||
three r128 / marked 4.3.0 / DOMPurify 3.2.4),两端保持一致,
|
||
由 vendor-align.test.mjs 钉住。
|
||
|
||
★ DOMPurify 从 CDN 挪到本地还修掉了一个**安全边界**:
|
||
它加载失败时 renderMd() 会回退到手写正则剥 <script>/on*=/javascript:,
|
||
那不是完备的 HTML sanitizer,而它渲染的是**模型输出与记忆文本**
|
||
(都算不可信输入)。净化器必须可用,不能有降级路径。
|
||
-->
|
||
<script src="vendor/three.min.js"></script>
|
||
<script src="vendor/OrbitControls.js"></script>
|
||
<script src="vendor/marked.min.js"></script>
|
||
<script src="vendor/purify.min.js"></script>
|
||
<script>
|
||
// 本地依赖缺失时的可见报错:宁可显式说「本地库缺失」,
|
||
// 也不要静默退化(静默退化的症状是星图空白/markdown 变纯文本,
|
||
// 用户看不出是打包漏了文件)。
|
||
if (!window.THREE) window._THREE_FAILED = true;
|
||
if (typeof marked === "undefined")
|
||
console.error("[vendor] marked.min.js 缺失:Markdown 将退化为纯文本");
|
||
if (typeof DOMPurify === "undefined")
|
||
console.error(
|
||
"[vendor] purify.min.js 缺失:Markdown 净化不可用(不应发生,库已本地化)",
|
||
);
|
||
</script>
|
||
</head>
|
||
<body>
|
||
<div id="bg-layer"></div>
|
||
|
||
<div class="titlebar" id="titlebar">
|
||
<div class="titlebar-controls">
|
||
<button
|
||
class="tb-btn"
|
||
id="tb-min"
|
||
title="最小化"
|
||
onclick="window.homeagent && homeagent.win.minimize()"
|
||
>
|
||
<svg
|
||
viewBox="0 0 24 24"
|
||
width="14"
|
||
height="14"
|
||
fill="none"
|
||
stroke="currentColor"
|
||
stroke-width="1.6"
|
||
stroke-linecap="round"
|
||
>
|
||
<line x1="4" y1="12" x2="20" y2="12" />
|
||
</svg>
|
||
</button>
|
||
<button
|
||
class="tb-btn"
|
||
id="tb-max"
|
||
title="最大化"
|
||
onclick="window.homeagent && homeagent.win.toggleMaximize()"
|
||
>
|
||
<svg
|
||
viewBox="0 0 24 24"
|
||
width="13"
|
||
height="13"
|
||
fill="none"
|
||
stroke="currentColor"
|
||
stroke-width="1.6"
|
||
stroke-linecap="round"
|
||
>
|
||
<rect x="5" y="5" width="14" height="14" rx="1.5" />
|
||
</svg>
|
||
</button>
|
||
<button
|
||
class="tb-btn tb-close"
|
||
id="tb-close"
|
||
title="关闭"
|
||
onclick="window.homeagent && homeagent.win.close()"
|
||
>
|
||
<svg
|
||
viewBox="0 0 24 24"
|
||
width="14"
|
||
height="14"
|
||
fill="none"
|
||
stroke="currentColor"
|
||
stroke-width="1.6"
|
||
stroke-linecap="round"
|
||
>
|
||
<path d="M6 6l12 12M18 6L6 18" />
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="app">
|
||
<!-- 左侧图标栏:主页=对话,其余为二级页面 -->
|
||
<aside class="rail" id="rail">
|
||
<div class="rail-logo"><img src="icon.svg" alt="HologramAgent" /></div>
|
||
<button
|
||
class="rail-btn active"
|
||
id="rail-chat"
|
||
onclick="switchView('chat')"
|
||
title="对话"
|
||
>
|
||
<svg
|
||
viewBox="0 0 24 24"
|
||
fill="none"
|
||
stroke="currentColor"
|
||
stroke-width="2"
|
||
stroke-linecap="round"
|
||
stroke-linejoin="round"
|
||
>
|
||
<path
|
||
d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"
|
||
/>
|
||
</svg>
|
||
</button>
|
||
<button
|
||
class="rail-btn"
|
||
id="rail-overview"
|
||
onclick="switchView('overview')"
|
||
title="概览"
|
||
>
|
||
<svg
|
||
viewBox="0 0 24 24"
|
||
fill="none"
|
||
stroke="currentColor"
|
||
stroke-width="2"
|
||
stroke-linecap="round"
|
||
stroke-linejoin="round"
|
||
>
|
||
<path d="M22 12h-4l-3 9L9 3l-3 9H2" />
|
||
</svg>
|
||
</button>
|
||
<button
|
||
class="rail-btn"
|
||
id="rail-plugins"
|
||
onclick="switchView('plugins')"
|
||
title="插件"
|
||
>
|
||
<svg
|
||
viewBox="0 0 24 24"
|
||
fill="none"
|
||
stroke="currentColor"
|
||
stroke-width="2"
|
||
stroke-linecap="round"
|
||
stroke-linejoin="round"
|
||
>
|
||
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" />
|
||
</svg>
|
||
</button>
|
||
<button
|
||
class="rail-btn"
|
||
id="rail-adapters"
|
||
onclick="switchView('adapters')"
|
||
title="适配器"
|
||
>
|
||
<svg
|
||
viewBox="0 0 24 24"
|
||
fill="none"
|
||
stroke="currentColor"
|
||
stroke-width="2"
|
||
stroke-linecap="round"
|
||
stroke-linejoin="round"
|
||
>
|
||
<path
|
||
d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4"
|
||
/>
|
||
</svg>
|
||
</button>
|
||
<button
|
||
class="rail-btn"
|
||
id="rail-kernel"
|
||
onclick="switchView('kernel')"
|
||
title="内核"
|
||
>
|
||
<svg
|
||
viewBox="0 0 24 24"
|
||
fill="none"
|
||
stroke="currentColor"
|
||
stroke-width="2"
|
||
stroke-linecap="round"
|
||
stroke-linejoin="round"
|
||
>
|
||
<rect x="4" y="4" width="16" height="16" rx="2" />
|
||
<rect x="9" y="9" width="6" height="6" />
|
||
<path
|
||
d="M9 1v4M15 1v4M9 19v4M15 19v4M1 9h4M1 15h4M19 9h4M19 15h4"
|
||
/>
|
||
</svg>
|
||
</button>
|
||
<button
|
||
class="rail-btn"
|
||
id="rail-devices"
|
||
onclick="switchView('devices')"
|
||
title="设备"
|
||
>
|
||
<svg
|
||
viewBox="0 0 24 24"
|
||
fill="none"
|
||
stroke="currentColor"
|
||
stroke-width="2"
|
||
stroke-linecap="round"
|
||
stroke-linejoin="round"
|
||
>
|
||
<circle cx="7" cy="7" r="3" />
|
||
<circle cx="17" cy="17" r="3" />
|
||
<circle cx="17" cy="7" r="3" />
|
||
<path d="M7 7h7a3 3 0 0 1 3 3v4" />
|
||
</svg>
|
||
</button>
|
||
<div class="rail-spacer"></div>
|
||
<button
|
||
class="rail-btn"
|
||
id="rail-persona"
|
||
onclick="switchView('persona')"
|
||
title="人设"
|
||
>
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7">
|
||
<circle cx="12" cy="8" r="4" />
|
||
<path d="M4 21c0-4 3.6-6 8-6s8 2 8 6" />
|
||
</svg>
|
||
</button>
|
||
<button
|
||
class="rail-btn"
|
||
id="rail-proxy"
|
||
onclick="switchView('proxy')"
|
||
title="反代"
|
||
>
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7">
|
||
<path d="M4 8h16M4 16h16" />
|
||
<circle cx="8" cy="8" r="2" />
|
||
<circle cx="16" cy="16" r="2" />
|
||
</svg>
|
||
</button>
|
||
<button
|
||
class="rail-btn"
|
||
id="rail-settings"
|
||
onclick="switchView('settings')"
|
||
title="设置"
|
||
>
|
||
<svg
|
||
viewBox="0 0 24 24"
|
||
fill="none"
|
||
stroke="currentColor"
|
||
stroke-width="2"
|
||
stroke-linecap="round"
|
||
stroke-linejoin="round"
|
||
>
|
||
<circle cx="12" cy="12" r="3" />
|
||
<path
|
||
d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"
|
||
/>
|
||
</svg>
|
||
</button>
|
||
<button
|
||
class="rail-btn"
|
||
onclick="toggleTheme()"
|
||
title="切换亮色/暗色模式"
|
||
id="theme-btn"
|
||
>
|
||
<svg
|
||
viewBox="0 0 24 24"
|
||
width="15"
|
||
height="15"
|
||
fill="none"
|
||
stroke="currentColor"
|
||
stroke-width="2"
|
||
stroke-linecap="round"
|
||
>
|
||
<path d="M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z" />
|
||
</svg>
|
||
</button>
|
||
<div class="palette-pop" id="palette-pop" title="外观"></div>
|
||
<button
|
||
class="rail-btn"
|
||
onclick="toggleAppearance()"
|
||
id="palette-btn"
|
||
title="外观:主题色 / 背景图"
|
||
>
|
||
<svg
|
||
viewBox="0 0 24 24"
|
||
width="15"
|
||
height="15"
|
||
fill="none"
|
||
stroke="currentColor"
|
||
stroke-width="2"
|
||
stroke-linecap="round"
|
||
stroke-linejoin="round"
|
||
>
|
||
<path
|
||
d="M12 22a10 10 0 1 1 10-10c0 2.2-1.8 4-4 4h-2a3 3 0 0 0-3 3c0 1.1.9 2 2 2 1.4 0 2.5-1.1 3.6-2.1C19.3 18.5 20 20 21.5 20.5A1 1 0 0 0 22 19c0-4-3.6-7-10-7-5.5 0-9 3.8-9 9z"
|
||
/>
|
||
<circle cx="7.5" cy="10.5" r="1" />
|
||
<circle cx="12" cy="7.5" r="1" />
|
||
<circle cx="16.5" cy="10.5" r="1" />
|
||
</svg>
|
||
</button>
|
||
<span
|
||
class="conn-dot dot-gray"
|
||
id="rail-conn-dot"
|
||
title="连接状态"
|
||
></span>
|
||
</aside>
|
||
|
||
<div class="main">
|
||
<div class="topbar">
|
||
<h1>HologramAgent</h1>
|
||
<span
|
||
class="conn-indicator"
|
||
id="conn-indicator"
|
||
onclick="goSettingsConn()"
|
||
title="点击管理后端连接"
|
||
>
|
||
<span class="status-dot dot-gray" id="conn-dot"></span>
|
||
<span id="conn-name-display">未连接</span>
|
||
<span style="font-size: 10px; margin-left: 4px; opacity: 0.6"
|
||
>▼</span
|
||
>
|
||
</span>
|
||
<div class="spacer"></div>
|
||
<button class="lang-btn" onclick="toggleLang()" id="lang-btn">
|
||
EN
|
||
</button>
|
||
</div>
|
||
|
||
<div class="container">
|
||
<div id="view-chat" class="view active"></div>
|
||
<div id="view-overview" class="view"></div>
|
||
<div id="view-plugins" class="view"></div>
|
||
<div id="view-adapters" class="view"></div>
|
||
<div id="view-kernel" class="view"></div>
|
||
<div id="view-devices" class="view"></div>
|
||
<div id="view-settings" class="view"></div>
|
||
<div id="view-persona" class="view"></div>
|
||
<div id="view-proxy" class="view"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="toast" class="toast"></div>
|
||
<div id="confirm-overlay" class="confirm-overlay"></div>
|
||
|
||
<script src="app.js"></script>
|
||
</body>
|
||
</html>
|