Merge pull request #23 from JianFeeeee/feat/rename-and-prompt-convergence

refactor: 全面改名 HologramAgent + 提示词技术内容下沉 + 修 21 处乱码 + 回填数据完整性
This commit is contained in:
JianFeeeee
2026-10-22 21:04:34 +08:00
committed by GitHub
206 changed files with 418 additions and 303 deletions

View File

@ -1,4 +1,4 @@
# HomeAgent 主仓 CI。
# HologramAgent 主仓 CI。
#
# 设计原则:**CI 里跑的每一条命令,都是本地已实测通过的命令**。
# 不写「应该有用来试试」的步骤 —— 未验证的 CI 步骤会把假红灯变成常态,
@ -235,11 +235,11 @@ jobs:
#
# 取值依据(实测 2026-10-21,直连不带代理,非推测):
# https://gitcode.com/JianFeeeee/HologramAgent → 200 ← 当前用这个
# https://gitcode.com/JianFeeeee/HomeAgent → 301 ← 旧名,跳转到上面
# https://gitcode.com/JianFeeeee/HologramAgent → 301 ← 旧名,跳转到上面
# https://gitcode.com/JianFeeeee/hologramagentsdk → 200(SDK 仓,另一对象)
# https://gitcode.com/JianFeeeee/homeagentsdk → 404
#
# 背景:gitcode 侧镜像仓已由 HomeAgent 改名为 HologramAgent(与 GitHub
# 背景:gitcode 侧镜像仓已由 HologramAgent 改名为 HologramAgent(与 GitHub
# 主仓同名)。旧地址仍 301 跳转,跟随后也能到达,但走重定向 ⇒ 别再用它。
# 判定两仓同一对象:两地址 git ls-remote 的 refs 列表 md5 相同。
#
@ -263,7 +263,7 @@ jobs:
with:
# 必须取完整历史:镜像可能在任意旧提交上,快进需要共同祖先。
fetch-depth: 0
# ★ 改名(HomeAgent → HologramAgent)后的必然过渡态:gitcode 上的镜像仓
# ★ 改名(HologramAgent → HologramAgent)后的必然过渡态:gitcode 上的镜像仓
# 是**另一个账号下的独立仓库**,改 GitHub 仓名不会自动建出它。
# 若不在这里显式探测,缺少目标仓时只会得到 git 的原始报错
# ("repository not found" 混在 push 输出里),看不出是「仓没建」。

View File

@ -308,7 +308,7 @@ jobs:
[ "$PRE" = "true" ] && FLAGS+=(--prerelease)
gh release create "$TAG" \
--title "$TAG" \
--notes "HomeAgent $VERSION
--notes "HologramAgent $VERSION
产物清单与校验见 SHA256SUMS。
- \`hologramagent_${VERSION}_linux_amd64.tar.gz\` — 内核 + CLI + GUI 打包
@ -361,11 +361,11 @@ jobs:
#
# 取值依据(实测 2026-10-21,直连不带代理,非推测):
# https://gitcode.com/JianFeeeee/HologramAgent → 200 ← 当前用这个
# https://gitcode.com/JianFeeeee/HomeAgent → 301 ← 旧名,跳转到上面
# https://gitcode.com/JianFeeeee/HologramAgent → 301 ← 旧名,跳转到上面
# https://gitcode.com/JianFeeeee/hologramagentsdk → 200(SDK 仓,另一对象)
# https://gitcode.com/JianFeeeee/homeagentsdk → 404
#
# 背景:gitcode 侧镜像仓已由 HomeAgent 改名为 HologramAgent(与 GitHub
# 背景:gitcode 侧镜像仓已由 HologramAgent 改名为 HologramAgent(与 GitHub
# 主仓同名)。旧地址仍 301 跳转,跟随后也能到达,但走重定向 ⇒ 别再用它。
# 判定两仓同一对象:两地址 git ls-remote 的 refs 列表 md5 相同。
#
@ -390,7 +390,7 @@ jobs:
name: linux-amd64
path: dist
# ★ 前置检查:gitcode 镜像仓是否存在。
# 改名(HomeAgent → HologramAgent)后 gitcode 目标仓需要**人工新建**,
# 改名(HologramAgent → HologramAgent)后 gitcode 目标仓需要**人工新建**,
# 不探的话失败会埋在 push/curl 的原始输出里,看不出是「仓没建」。
# 语义:token 未配 = 可选项跳过(上一步);token 有但仓不存在 = 硬失败。
#

View File

@ -1,8 +1,8 @@
HomeAgent 是完全独立自研的新一代 Agent 框架。
HologramAgent 是完全独立自研的新一代 Agent 框架。
## 架构总览
HomeAgent 采用内核 + 插件双层架构:
HologramAgent 采用内核 + 插件双层架构:
```
外部输入(QQ/Web/CLI)

View File

@ -2,7 +2,7 @@
name: commondev-discipline
description: commondev 主管式多仓库开发流水线的使用与开发纪律。当你要为某个工程开一条分支、把工程派给一个下属 agent、或用 pi 拉起执行 agent 干活时必读。核心动作:为每个工程对话新建驻留式子 agent 并把该工程的一对通道划给它(否则所有工程都挤在根 agent 上)。**git 托管平台的操作(Gitea/GitHub/GitLab)不在插件里,而在本文** —— 用 enc_shell + 保存的凭据调 curl/CLI 完成。也含 hmap 插件开发与部署纪律。
version: 2.0.0
author: HomeAgent
author: HologramAgent
---
# commondev 纪律(主管模式 · 工程对话 · 平台操作)
@ -176,7 +176,7 @@ enc_shell(command="curl -s -X POST -H \"Authorization: token @{t}\" -H 'Content-
| 角色 | 是谁 | 干什么 |
|---|---|---|
| **人** | 老板 | 只与主管对接 |
| **主管** | 你(长期驻留的 HomeAgent 主 agent) | 拆任务、**定义判据**、复审、决定合入 |
| **主管** | 你(长期驻留的 HologramAgent 主 agent) | 拆任务、**定义判据**、复审、决定合入 |
| **执行 agent** | 按工程拉起的一个 pi / dsh 实例 | 在某棵工作树里干活 |
| **commondev 插件** | 外部独立插件 | 仓库/凭据/分支/PR/测试,全部机械化操作 |

View File

@ -2,5 +2,5 @@
"name": "commondev-discipline",
"description": "commondev 主管式多仓库开发流水线的使用与开发纪律:为每个工程对话新建驻留子并划入其通道、投递必须落同一 session、复核必须含变异阶段;以及 hmap 插件开发纪律(plg.json、SDK 版本、产物形态、Serial/ParallelSafe、外部插件能力边界、凭据与孤儿清理)",
"version": "1.0.0",
"author": "HomeAgent"
"author": "HologramAgent"
}

View File

@ -1,16 +1,16 @@
---
name: knowledge-base
description: 按分类树检索 HomeAgent 知识库。当需要查阅项目知识、架构约定、历史决策,或用户提到"知识库/knowledge/知识库有哪些/这个项目的约定是什么"时使用。支持树形导航、分类内检索、以图搜知识。
description: 按分类树检索 HologramAgent 知识库。当需要查阅项目知识、架构约定、历史决策,或用户提到"知识库/knowledge/知识库有哪些/这个项目的约定是什么"时使用。支持树形导航、分类内检索、以图搜知识。
version: 1.1.0
author: HomeAgent
author: HologramAgent
---
## Usage
先看树定位分类,再做定向检索。接口由 HomeAgent 的 `kbtree` 插件提供,
先看树定位分类,再做定向检索。接口由 HologramAgent 的 `kbtree` 插件提供,
只读、需 token。详见下方"接入"。
HomeAgent 知识库按**分类树**组织(`tech/go/并发`、`life/sleep` …)。
HologramAgent 知识库按**分类树**组织(`tech/go/并发`、`life/sleep` …)。
### 何时用
@ -102,7 +102,7 @@ curl -s -H "$AUTH" "$BASE/search?q=goroutine&limit=5"
若知识条目挂了图片,它在**多模态统一空间**里有向量,能被图片本身检索到。
前提是宿主已接入多模态向量 provider(否则只是记录了媒体,不参与召回)。
判断是否就绪:HomeAgent 自身的知识库接口会返回稠密路状态
判断是否就绪:HologramAgent 自身的知识库接口会返回稠密路状态
(`dense.enabled` / `dense.ready` / `dense.total`)。若为未启用,
**不要承诺"能以图搜"**。
@ -132,13 +132,13 @@ curl -s -H "$AUTH" "$BASE/search?q=goroutine&limit=5"
- **分类不存在返回 404**,并在 `categories` 字段里附上现有分类 —— 用它自查
拼写。
- **`items=0` 只是不要正文**,`total_count` 仍准确,可用于判断规模。
- **本服务只读**。写方法返回 405。要写知识请用 HomeAgent 主 agent 的
- **本服务只读**。写方法返回 405。要写知识请用 HologramAgent 主 agent 的
`knowledge_create`(或 WebUI 界面),不要试图绕过它直接写这个接口。
- 知识名里不能有 `..`、空格(会被规范成 `_`)、点开头的段。
### 写入
本服务不提供写入。若你在 HomeAgent 主 agent 内部,写入用内核工具:
本服务不提供写入。若你在 HologramAgent 主 agent 内部,写入用内核工具:
```
knowledge_create name="tech/go/调度" content="正文..."

View File

@ -1,5 +1,5 @@
#!/usr/bin/env bash
# kbtree 客户端:按分类树检索 HomeAgent 知识库。
# kbtree 客户端:按分类树检索 HologramAgent 知识库。
#
# 由 knowledge-base skill 调用(agent 读 SKILL.md 后按需调本脚本)。
# 也可人工使用:
@ -88,7 +88,7 @@ if ! (exec 3<>"/dev/tcp/${HOSTPORT%%:*}/${HOSTPORT##*:}") 2>/dev/null; then
cat >&2 <<EOF
kbtree: 连不上 $BASE(端口未监听)。
最常见原因——**服务还没上线**。kbtree 是 HomeAgent 的内置插件,
最常见原因——**服务还没上线**。kbtree 是 HologramAgent 的内置插件,
需要二进制里含它才会启动。若 homed 是在合入该插件之前构建/部署的,
就一直没有这个服务。上线后验证:

View File

@ -1,6 +1,6 @@
{
"name": "knowledge-base",
"description": "按分类树检索 HomeAgent 知识库:树形导航、分类内检索、以图搜知识",
"description": "按分类树检索 HologramAgent 知识库:树形导航、分类内检索、以图搜知识",
"version": "1.1.0",
"author": "HomeAgent"
"author": "HologramAgent"
}

View File

@ -1,4 +1,4 @@
# HomeAgent GUI 设计说明与外部借鉴
# HologramAgent GUI 设计说明与外部借鉴
本文件记录 GUI(`cmd/gui`)在设计过程中**明确借鉴的外部实现**,以及本仓自行做出的设计决策。
@ -12,11 +12,11 @@
### PiDeck(`C:\Users\21989\AppData\Local\Programs\PiDeck`)
**PiDeck 是本机安装的一个第三方 Electron 应用**(其前端依赖
`@deepseek-ai/dsh-web-frontend`)。HomeAgent GUI 在交互设计上参考了它的以下
`@deepseek-ai/dsh-web-frontend`)。HologramAgent GUI 在交互设计上参考了它的以下
做法。参考方式为**阅读其打包产物 `app.asar` 中的 CSS 实现**,理解其设计意图后
在 HomeAgent 的样式体系中独立重写 —— 未复制其代码,也未使用其资源文件。
在 HologramAgent 的样式体系中独立重写 —— 未复制其代码,也未使用其资源文件。
| 借鉴项 | PiDeck 的实现 | HomeAgent 的落地 | 动机 |
| 借鉴项 | PiDeck 的实现 | HologramAgent 的落地 | 动机 |
|---|---|---|---|
| **加载 / 思考动画** | `@keyframes _dsh-state-dot-chase`(三点透明度递减 `1 → .6 → .35 → .15`)与 `tool-activity-dot`(上浮 + 缩放) | `renderer/style.css` 的 `haDots` / `haDotFloat` | 旧实现是 `border + rotate` 的经典 spinner。旋转语义上暗示"在加载某个确定的东西",而 agent 思考本身没有进度可转;且在 15px 的消息气泡里转圈糊成一团 |
| **运行态呼吸光晕** | `.turn-row--running:before` —— 一层几乎看不见的 accent 底色(`color-mix(... 3%)`)以 `2.2s` 周期做 `opacity: 0 → 1 → 0` 呼吸 | `.msg-bubble.msg-running::before` | 单看气泡里的几个点,视线要缩到一小块;光晕铺在整条消息上,余光就能感知"agent 正在回" |
@ -24,20 +24,20 @@
| **组合键处理** | ——(PiDeck 为 Web 应用,不涉及系统级输入注入) | —— | —— |
**关于分组卡的规则差异**:PiDeck 的分组策略我们理解为"折叠成组",
HomeAgent 额外加了一条规则 —— **只有 1 个工具时保持单卡**(组卡没意义,
HologramAgent 额外加了一条规则 —— **只有 1 个工具时保持单卡**(组卡没意义,
反而多一层点击)。这是本地决策,不是 PiDeck 的做法。
---
## 本仓自行做出的设计(未借鉴)
以下几项与 PiDeck 无关,是为 HomeAgent 自身场景做的决定:
以下几项与 PiDeck 无关,是为 HologramAgent 自身场景做的决定:
- **SSE 取代 EventSource**:需要自定义 `X-API-Key` 与 `Last-Event-ID` 请求头,
浏览器原生 `EventSource` 不支持。
- **增量聊天渲染**(`applyIncrementalChatRender`):按 `data-msgkey` 复用 DOM
节点。性能问题由本仓实测定位(旧实现 200 条消息单次全量重建 235ms)。
- **设备令牌注入**(`isDeviceTokenPath` / `deviceApiKey`):HomeAgent 服务端
- **设备令牌注入**(`isDeviceTokenPath` / `deviceApiKey`):HologramAgent 服务端
`/api/v1/device/` 命名空间下并存两套鉴权(`requireAPI` 认 cookie、
`requireToken` 只认 `X-API-Key`),需要客户端主动带令牌。
- **静默启动的"创建后隐藏"**:不创建窗口会导致渲染进程不启动(SSE、设备桥

View File

@ -166,7 +166,7 @@ check(
// ── 5) 页面不得再引用公网 CDN ───────────────────────────────────────
//
// 与服务端 starmap_vendor_test.go 同一判据(那里钉 WebUI,这里钉 GUI)。
// HomeAgent 支持离线/内网部署,而前端有 4 个硬依赖在公网上时,
// HologramAgent 支持离线/内网部署,而前端有 4 个硬依赖在公网上时,
// 断网/出口受限环境下星图必坏、且用户无从修复。
const htmlSrc = readFileSync(join(here, "renderer", "index.html"), "utf8");

View File

@ -185,7 +185,7 @@ async function adoptSlSession(url) {
}
// 带 Electron cookie jar 的 fetch(跟随外部网关 302 → login 域 → 回跳,最多 6 跳),
// 使 POST /api/v1/login 真正触达内层 HomeAgent 并取回 homeagent_session。
// 使 POST /api/v1/login 真正触达内层 HologramAgent 并取回 homeagent_session。
async function sessionFetch(initUrl, opts) {
const { session } = require("electron");
let url = initUrl;
@ -430,7 +430,7 @@ function createWindow(show = true) {
height: 860,
minWidth: 900,
minHeight: 600,
title: "HomeAgent",
title: "HologramAgent",
frame: false,
show: false, // 一律先不显示,由 ready-to-show 决定
icon: path.join(__dirname, "icon.ico"),
@ -806,7 +806,7 @@ ipcMain.handle("webui:openLogin", (_, { url, username, password }) => {
parent: mainWindow,
modal: true,
autoHideMenuBar: true,
title: "HomeAgent - 网关联机登录",
title: "HologramAgent - 网关联机登录",
webPreferences: { contextIsolation: true, nodeIntegration: false },
});
const u = encodeURIComponent(username || "");
@ -1456,7 +1456,7 @@ async function connectDeviceBridgeOnce(cfg) {
op: "hello",
device: {
device_id: deviceBridgeId,
name: "HomeAgent GUI",
name: "HologramAgent GUI",
kind: "computer",
authorized: authorized,
caps: [
@ -1986,8 +1986,8 @@ function executeHomeagentCmd(capability, reqId) {
const h = Math.min(parseInt(area.height || 600, 10) - 40, 560);
const html = /<\/?[a-z][\s\S]*>/i.test(raw)
? raw
: "<div style='font-family:sans-serif;display:flex;flex-direction:column;justify-content:center;align-items:center;height:100%;padding:24px;box-sizing:border-box'><h1 style='margin:0 0 16px;color:#ff7fac'>HomeAgent</h1><p style='font-size:16px;line-height:1.6;white-space:pre-wrap;word-break:break-all'>" +
String(raw || "HomeAgent 远程屏幕提示").replace(/</g, "&lt;") +
: "<div style='font-family:sans-serif;display:flex;flex-direction:column;justify-content:center;align-items:center;height:100%;padding:24px;box-sizing:border-box'><h1 style='margin:0 0 16px;color:#ff7fac'>HologramAgent</h1><p style='font-size:16px;line-height:1.6;white-space:pre-wrap;word-break:break-all'>" +
String(raw || "HologramAgent 远程屏幕提示").replace(/</g, "&lt;") +
"</p></div>";
try {
if (screensueWin && !screensueWin.isDestroyed()) screensueWin.destroy();
@ -1999,7 +1999,7 @@ function executeHomeagentCmd(capability, reqId) {
alwaysOnTop: true,
frame: false,
resizable: true,
title: "HomeAgent · screensue",
title: "HologramAgent · screensue",
webPreferences: { nodeIntegration: false, contextIsolation: true },
});
screensueWin.setAlwaysOnTop(true, "screen-saver");
@ -3223,7 +3223,7 @@ async function setDeviceAuthorized(authorized) {
op: "hello",
device: {
device_id: deviceBridgeId,
name: "HomeAgent GUI",
name: "HologramAgent GUI",
kind: "computer",
authorized: !!authorized,
caps: [
@ -3291,7 +3291,7 @@ function buildTrayMenuTemplate() {
const electron = require("electron");
const TMenu = electron.Menu;
const tpl = [];
tpl.push({ label: "HomeAgent", enabled: true });
tpl.push({ label: "HologramAgent", enabled: true });
tpl.push({ type: "separator" });
// 远程连接状态(缓存避免每次读文件)
const connLabel = trayConnCache.connLabel || "未连接";
@ -3404,7 +3404,7 @@ function initTray() {
img = nImg.createEmpty();
}
tray = new Tray(img);
tray.setToolTip("HomeAgent - 个人智能管家");
tray.setToolTip("HologramAgent - 个人智能管家");
rebuildTrayMenu();
tray.on("double-click", () => showMainWindow());
console.log("[tray] READY: " + (tray ? "tray-created" : "null"));
@ -3525,7 +3525,7 @@ app.whenReady().then(async () => {
// 「启动时不显示主窗口,驻留托盘后台运行」,但主进程从来没读过它 ——
// whenReady 无条件 createWindow(),于是必然弹窗。
//
// 实测(本机,prefs.silentStart=true):窗口标题 HomeAgent 照样出现。
// 实测(本机,prefs.silentStart=true):窗口标题 HologramAgent 照样出现。
//
// 与 applyAutoLaunch 里的 openAsHidden 是两回事:那个是告诉 OS「开机自启
// 时如何启动」(仅 Windows/macOS 生效),这里是本进程自己决定要不要显示,
@ -3605,7 +3605,7 @@ let notifSeq = 0;
ipcMain.handle("notify:show", (_, payload) => {
try {
const p = payload || {};
const title = String(p.title || "HomeAgent");
const title = String(p.title || "HologramAgent");
const body = String(p.body || "");
if (!body) return { ok: false, error: "empty body" };
if (!Notification.isSupported()) return { ok: false, error: "unsupported" };
@ -3721,10 +3721,10 @@ function saveGuiPrefs(p) {
}
// Electron LoginItem 写入的注册表项名是「electron.app.<exe 名>」。
// 产物改名过(HomeAgent.exe → homeagent-gui.exe)就会多出一条旧项,
// 产物改名过(HologramAgent.exe → homeagent-gui.exe)就会多出一条旧项,
// 且 setLoginItemSettings 不会清理它们 ⇒ 开机启动两次同一个 exe。
// 实测本机 Run 键里确实同时存在:
// electron.app.HomeAgent = "E:\program\homeagent\...\homeagent-gui.exe"
// electron.app.HologramAgent = "E:\program\homeagent\...\homeagent-gui.exe"
// electron.app.homeagent-gui = E:\program\homeagent\...\homeagent-gui.exe
// 两条指向同一 exe,所以表面看是两个自启动,实际是同一份的重复。
//

View File

@ -3,7 +3,7 @@
"version": "1.4.0",
"author": "JianFeeeee <jianfeeeee@homeagent.local>",
"homepage": "https://github.com/JianFeeeee/HologramAgent",
"description": "HomeAgent Desktop GUI - Multi-connection management dashboard",
"description": "HologramAgent Desktop GUI - Multi-connection management dashboard",
"main": "main.js",
"scripts": {
"start": "electron . --no-sandbox",
@ -25,7 +25,7 @@
},
"build": {
"appId": "com.homeagent.gui",
"productName": "HomeAgent",
"productName": "HologramAgent",
"linux": {
"target": [
"deb",

View File

@ -741,7 +741,7 @@ async function api(p, o) {
// 从服务端发现设备网关地址(自动链接的权威来源)。
//
// 失败不报错:老版本 HomeAgent 没有这个端点,回退到本地推导即可
// 失败不报错:老版本 HologramAgent 没有这个端点,回退到本地推导即可
// (见 renderDeviceChannel 里的 state.discoveredGateway || 旧口径)。
//
// 优先 url_portal(门户同源形态):GUI 主进程连 WS 走系统解析器,
@ -1083,7 +1083,7 @@ async function refreshAll() {
// 服务端列表未含本机(可能离线),仍展示本地状态
state.devices.push({
device_id: dbinfo.deviceId,
name: "HomeAgent GUI",
name: "HologramAgent GUI",
kind: "computer",
authorized: dbinfo.authorized,
online: false,
@ -1555,7 +1555,7 @@ function renderOverview() {
b.commit && b.commit !== "unknown" ? String(b.commit).slice(0, 7) : "";
return (
"v" + escHtml(v) +
'<div class="stat-sub">' + escHtml(b.kernel_name || "HomeAgent") +
'<div class="stat-sub">' + escHtml(b.kernel_name || "HologramAgent") +
(sha ? " · " + escHtml(sha) : "") + "</div>"
);
})(),
@ -1819,8 +1819,8 @@ function buildChatLayout() {
"</h2>" +
"<p>" +
__(
"连接 HomeAgent 服务端后即可开始对话。请在设置中添加后端连接。",
"Connect to a HomeAgent server to start chatting. Add a backend connection in Settings.",
"连接 HologramAgent 服务端后即可开始对话。请在设置中添加后端连接。",
"Connect to a HologramAgent server to start chatting. Add a backend connection in Settings.",
) +
"</p>" +
'<button class="btn btn-primary" onclick="goSettingsConn()">' +
@ -1853,7 +1853,7 @@ function buildChatLayout() {
if (state.messages.length === 0) {
html +=
'<div class="empty-state" style="flex:1;display:flex;align-items:center;justify-content:center"><p>' +
__("开始与您的 HomeAgent 聊天吧", "Start chatting with your HomeAgent") +
__("开始与您的 HologramAgent 聊天吧", "Start chatting with your HologramAgent") +
"</p></div>";
}
html +=
@ -2229,7 +2229,7 @@ function renderChat() {
if (msgs.length === 0) {
html =
'<div class="empty-state" style="flex:1;display:flex;align-items:center;justify-content:center"><p>' +
__("开始与您的 HomeAgent 聊天吧", "Start chatting with your HomeAgent") +
__("开始与您的 HologramAgent 聊天吧", "Start chatting with your HologramAgent") +
"</p></div>";
} else {
msgs.forEach((m, i) => {
@ -5963,7 +5963,7 @@ function renderGuiPrefs() {
sw(
"autoLaunch",
__("开机自启", "Auto launch on start"),
__("登录后自动启动 HomeAgent(静默)", "Start silently at login"),
__("登录后自动启动 HologramAgent(静默)", "Start silently at login"),
"saveGuiPrefs('autoLaunch', this.checked)",
) +
sw(
@ -6041,7 +6041,7 @@ function renderConnSection() {
"</h3>" +
"<label>" +
__("名称", "Name") +
'</label><input id="conn-name" placeholder="My HomeAgent">' +
'</label><input id="conn-name" placeholder="My HologramAgent">' +
"<label>" +
__("连接类型", "Type") +
'</label><select id="conn-type" onchange="toggleConnType()">' +
@ -6734,7 +6734,7 @@ async function connectFetchSSE(url) {
String(p.content || "").slice(0, 40);
notifyTurnOnce(
_sig,
"HomeAgent",
"HologramAgent",
String(p.content || "").slice(0, 160) || __("(空回复)", "(empty reply)"),
);
endChatTurn();
@ -7329,8 +7329,8 @@ function renderDevices() {
html +=
'<p style="color:var(--text-muted)">' +
__(
"暂无设备接入。设备通过 WebSocket 连接到设备网关(默认经 HomeAgent 反代到 devices.<基域名>,或直连 127.0.0.1:9890/api/v1/device/ws),携带 token 后 hello 登记、bind 授权。",
"No devices yet. Devices connect via WebSocket (proxied by HomeAgent at devices.<base-domain>, or directly 127.0.0.1:9890/api/v1/device/ws), hello to register, bind to authorize.",
"暂无设备接入。设备通过 WebSocket 连接到设备网关(默认经 HologramAgent 反代到 devices.<基域名>,或直连 127.0.0.1:9890/api/v1/device/ws),携带 token 后 hello 登记、bind 授权。",
"No devices yet. Devices connect via WebSocket (proxied by HologramAgent at devices.<base-domain>, or directly 127.0.0.1:9890/api/v1/device/ws), hello to register, bind to authorize.",
) +
"</p>";
} else {

View File

@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>HomeAgent</title>
<title>HologramAgent</title>
<link rel="icon" type="image/svg+xml" href="icon.svg" />
<link rel="stylesheet" href="style.css" />
<!--
@ -11,7 +11,7 @@
为什么(与服务端 webui 插件同一条理由,见
internal/plugins/webui/starmap_vendor_test.go 的注释):
HomeAgent 明确支持离线/内网部署,而前端原本有 4 个硬依赖在公网上
HologramAgent 明确支持离线/内网部署,而前端原本有 4 个硬依赖在公网上
(cdnjs/jsdelivr)。真实现象是「服务端 curl 同一批 URL 返回 200,
但用户点星图看到『3D 星图不可用(CDN 加载失败)』」——不是服务端的问题,
是客户端访问不到公共 CDN(内网/出口受限/断网)。
@ -108,7 +108,7 @@
<div id="app">
<!-- 左侧图标栏:主页=对话,其余为二级页面 -->
<aside class="rail" id="rail">
<div class="rail-logo"><img src="icon.svg" alt="HomeAgent" /></div>
<div class="rail-logo"><img src="icon.svg" alt="HologramAgent" /></div>
<button
class="rail-btn active"
id="rail-chat"
@ -318,7 +318,7 @@
<div class="main">
<div class="topbar">
<h1>HomeAgent</h1>
<h1>HologramAgent</h1>
<span
class="conn-indicator"
id="conn-indicator"

View File

@ -6,7 +6,7 @@
// 文案写着「启动时不显示主窗口,驻留托盘后台运行」,但主进程从来没读过它
// —— whenReady 无条件 createWindow(),于是必然弹窗。
//
// 实测(本机,prefs.silentStart=true):窗口标题 HomeAgent 照样出现。
// 实测(本机,prefs.silentStart=true):窗口标题 HologramAgent 照样出现。
//
// 本判据钉住三件事:
// 1. whenReady 真的读 silentStart 并据此决定 show

View File

@ -296,7 +296,7 @@ func (s *MockServer) handlePlugins(w http.ResponseWriter, r *http.Request) {
func (s *MockServer) handleChatHistory(w http.ResponseWriter, r *http.Request) {
writeJSON(w, []ChatMessage{
{Role: "user", Content: "你好"},
{Role: "assistant", Content: "你好!我是 HomeAgent,有什么可以帮你的?"},
{Role: "assistant", Content: "你好!我是 HologramAgent,有什么可以帮你的?"},
{Role: "user", Content: "测试消息"},
{Role: "assistant", Content: "这是模拟后端的测试回复,GUI 连接正常 ✅"},
})
@ -361,7 +361,7 @@ func (s *MockServer) handleChatEvents(w http.ResponseWriter, r *http.Request) {
func (s *MockServer) handleMemoryGraph(w http.ResponseWriter, r *http.Request) {
writeJSON(w, map[string]interface{}{
"nodes": []map[string]interface{}{
{"id": "1", "label": "HomeAgent", "group": "system"},
{"id": "1", "label": "HologramAgent", "group": "system"},
{"id": "2", "label": "GUI 测试", "group": "user"},
},
"edges": []map[string]interface{}{
@ -511,7 +511,7 @@ func main() {
server.registerRoutes(mux)
addr := ":9099"
log.Printf("=== HomeAgent Mock Server ====")
log.Printf("=== HologramAgent Mock Server ====")
log.Printf("监听地址: http://0.0.0.0%s", addr)
log.Printf("API 基础路径: http://0.0.0.0%s/api/v1/", addr)
log.Printf("SSE 端点: http://0.0.0.0%s/api/v1/chat/events", addr)

View File

@ -349,7 +349,7 @@ func (s *MockServer) handleDeviceWS(w http.ResponseWriter, r *http.Request) {
ws.WriteJSON(client.CmdMsg{
Op: "cmd",
ReqID: "test_2_clipboardsue_" + fmt.Sprintf("%d", time.Now().UnixMilli()),
Command: "homeagent-clipboardsue HomeAgent远程测试_" + fmt.Sprintf("%d", time.Now().UnixMilli()),
Command: "homeagent-clipboardsue HologramAgent远程测试_" + fmt.Sprintf("%d", time.Now().UnixMilli()),
CmdType: "homeagent",
})
@ -404,7 +404,7 @@ func (s *MockServer) handleDeviceWS(w http.ResponseWriter, r *http.Request) {
ws.WriteJSON(client.CmdMsg{
Op: "cmd",
ReqID: "test_6_screensue_" + fmt.Sprintf("%d", time.Now().UnixMilli()),
Command: `homeagent-screensue 10 <!DOCTYPE html><html><head><meta charset="utf-8"><style>body{background:linear-gradient(135deg,#667eea,#764ba2);color:white;font-family:sans-serif;padding:30px;margin:0}h1{font-size:32px;text-shadow:0 2px 8px rgba(0,0,0,0.3)}.card{background:rgba(255,255,255,0.15);border-radius:12px;padding:20px;margin:12px 0;backdrop-filter:blur(8px)}.badge{display:inline-block;background:#4ade80;color:#000;padding:3px 10px;border-radius:16px;font-weight:bold}</style></head><body><h1>HomeAgent GUI 全量测试</h1><div class="card"><h2>能力测试结果</h2><table border="1" cellpadding="6" style="border-collapse:collapse;width:100%"><tr><th>能力</th><th>结果</th></tr><tr><td>screensee 截图</td><td><span class="badge">通过</span></td></tr><tr><td>clipboard 读写</td><td><span class="badge">通过</span></td></tr><tr><td>computeruse 操控</td><td><span class="badge">通过</span></td></tr><tr><td>speakeruse TTS</td><td><span class="badge">通过</span></td></tr><tr><td>screensue 渲染</td><td><span class="badge">通过</span></td></tr></table></div><p style="text-align:center;color:rgba(255,255,255,0.7)">2026-08-23 19:50</p></body></html>`,
Command: `homeagent-screensue 10 <!DOCTYPE html><html><head><meta charset="utf-8"><style>body{background:linear-gradient(135deg,#667eea,#764ba2);color:white;font-family:sans-serif;padding:30px;margin:0}h1{font-size:32px;text-shadow:0 2px 8px rgba(0,0,0,0.3)}.card{background:rgba(255,255,255,0.15);border-radius:12px;padding:20px;margin:12px 0;backdrop-filter:blur(8px)}.badge{display:inline-block;background:#4ade80;color:#000;padding:3px 10px;border-radius:16px;font-weight:bold}</style></head><body><h1>HologramAgent GUI 全量测试</h1><div class="card"><h2>能力测试结果</h2><table border="1" cellpadding="6" style="border-collapse:collapse;width:100%"><tr><th>能力</th><th>结果</th></tr><tr><td>screensee 截图</td><td><span class="badge">通过</span></td></tr><tr><td>clipboard 读写</td><td><span class="badge">通过</span></td></tr><tr><td>computeruse 操控</td><td><span class="badge">通过</span></td></tr><tr><td>speakeruse TTS</td><td><span class="badge">通过</span></td></tr><tr><td>screensue 渲染</td><td><span class="badge">通过</span></td></tr></table></div><p style="text-align:center;color:rgba(255,255,255,0.7)">2026-08-23 19:50</p></body></html>`,
CmdType: "homeagent",
})

View File

@ -1,7 +1,7 @@
{
"app": {
"bundleName": "com.example.homeagent",
"vendor": "HomeAgent",
"vendor": "HologramAgent",
"versionCode": 1004000,
"versionName": "1.4.0",
// 分层图标:前景是字形,背景(沉淀色)在 base/ 与 dark/ 各一份,随系统主题切换。

View File

@ -2,7 +2,7 @@
"string": [
{
"name": "app_name",
"value": "HomeAgent"
"value": "HologramAgent"
}
]
}

View File

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

View File

Before

Width:  |  Height:  |  Size: 989 B

After

Width:  |  Height:  |  Size: 989 B

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 988 B

After

Width:  |  Height:  |  Size: 988 B

View File

@ -1,7 +1,7 @@
{
"name": "entry",
"version": "1.0.0",
"description": "HomeAgent HarmonyOS client entry module",
"description": "HologramAgent HarmonyOS client entry module",
"main": "",
"author": "",
"license": "Apache-2.0",

View File

@ -45,7 +45,7 @@ export function applyChatSse(ev: SseEvent, sink: ChatStreamSink): void {
const frameType: string = frame['type'] as string ?? '';
const type: string = ev.event.length > 0 ? ev.event : frameType;
// 诊断只记事件类型(内容可能含隐私,不落盘)
hilog.debug(0x0000, 'HomeAgent', 'sse %{public}s', type);
hilog.debug(0x0000, 'HologramAgent', 'sse %{public}s', type);
if (type === 'agent_output') {
const content: string = payload['content'] as string ?? '';

View File

@ -10,7 +10,7 @@ export class DeviceBridgeClient {
private url: string = '';
private token: string = '';
private deviceId: string = '';
private name: string = 'HomeAgent OHOS';
private name: string = 'HologramAgent OHOS';
private kind: string = 'phone';
private caps: string[] = [];
private hostname: string = 'ohos';
@ -237,7 +237,7 @@ export class DeviceBridgeClient {
// 为何不报错回去:这些 op 不要求回执(服务端 pushToDevice 不等
// device→server 的应答),回一个错误帧反而会被当成未知帧处理。
if (op.length > 0) {
hilog.debug(0x0000, 'HomeAgent', 'device bridge: 忽略不支持的 op %{public}s', op);
hilog.debug(0x0000, 'HologramAgent', 'device bridge: 忽略不支持的 op %{public}s', op);
}
return;
}

View File

@ -30,7 +30,7 @@ function ensureBridgeStateTracking(): void {
*
* 网关改造为子域反代后位于 devices.<基域名>,而基域名与子域标签都是**服务端
* 配置**,客户端拼不出来。正常路径是先调 discoverGateway() 问服务端;
* 本函数只在「服务端没有发现端点」(老版本 HomeAgent)时兜底,
* 本函数只在「服务端没有发现端点」(老版本 HologramAgent)时兜底,
* 保留旧部署的可用性。
*/
export function deviceGatewayUrl(base: string): string {

View File

@ -216,7 +216,7 @@ class StatusStore {
if (build !== undefined && build !== null) {
const bVer: string = build['version'] as string ?? '';
const bCommit: string = build['commit'] as string ?? '';
const bName: string = build['kernel_name'] as string ?? 'HomeAgent';
const bName: string = build['kernel_name'] as string ?? 'HologramAgent';
const bSdk: string = build['sdk_compatible'] as string ?? '';
const bTime: string = build['build_time'] as string ?? '';
lic = build['license'] as string ?? '';

View File

@ -11,11 +11,11 @@ import { ApiError } from './ApiClient';
* 约定:
* - UI 只显示 userMessage() 返回的短句(人话、可行动、不含技术细节);
* - 技术细节(原始 message / HTTP 状态码 / 响应体)只写进 hilog,
* 通过 `hdc shell hilog | grep HomeAgent` 排查,不进 UI。
* 通过 `hdc shell hilog | grep HologramAgent` 排查,不进 UI。
*/
const DOMAIN: number = 0xA0A0;
const TAG: string = 'HomeAgent';
const TAG: string = 'HologramAgent';
/** 网络类错误的统一提示:不暴露主机名、端口、curl 错误码。 */
const MSG_UNREACHABLE: string = '连接不上后端服务,请检查网络与服务地址';

View File

@ -208,7 +208,7 @@ export struct ConnectionsPane {
.fontSize(12)
.fontColor(this.palette().textSecondary)
.margin({ bottom: 10 })
TextInput({ placeholder: '名称 (如 HomeAgent)', text: this.editName })
TextInput({ placeholder: '名称 (如 HologramAgent)', text: this.editName })
.height(36).fontSize(13).fontColor(this.palette().textPrimary)
.placeholderColor(this.palette().textMuted).backgroundColor(this.palette().bgInput)
.borderRadius(RADIUS_SM).border({ width: 1, color: this.palette().border })

View File

@ -69,7 +69,7 @@ export struct DeviceLocalPane {
}) {
PlainCard({ caption: '基本信息' }) {
DeviceKvRow({ label: '设备 ID', value: this.deviceId.length > 0 ? this.deviceId : '未注册' })
DeviceKvRow({ label: '名称', value: 'HomeAgent OHOS' })
DeviceKvRow({ label: '名称', value: 'HologramAgent OHOS' })
DeviceKvRow({ label: '类型', value: 'phone' })
}

View File

@ -48,7 +48,7 @@ export struct GradientBackground {
// 只处理本地沙箱文件;http(s) 背景图不是本应用的场景(设置页只给图库选择)
const path: string = src.startsWith('file://') ? src.substring(7) : src;
if (!path.startsWith('/')) {
hilog.error(0x0000, 'HomeAgent', 'bg: unsupported source');
hilog.error(0x0000, 'HologramAgent', 'bg: unsupported source');
this.bgPixel = undefined;
return;
}
@ -59,11 +59,11 @@ export struct GradientBackground {
await srcObj.release();
fileIo.closeSync(f);
this.bgPixel = pm;
hilog.info(0x0000, 'HomeAgent', 'bg decoded ok');
hilog.info(0x0000, 'HologramAgent', 'bg decoded ok');
} catch (e) {
// 失败必须留痕:否则表现就是"设置了但没生效",无从定位
const err = e as BusinessError;
hilog.error(0x0000, 'HomeAgent', 'bg decode failed code=%{public}d', err.code as number);
hilog.error(0x0000, 'HologramAgent', 'bg decode failed code=%{public}d', err.code as number);
this.bgPixel = undefined;
}
}

View File

@ -21,7 +21,7 @@ function storedThemeMode(): string {
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
console.info('[HomeAgent] ability onCreate');
console.info('[HologramAgent] ability onCreate');
const sysDark: boolean =
this.context.config?.colorMode === ConfigurationConstant.ColorMode.COLOR_MODE_DARK;
// Seed the OS color state first, then resolve the persisted mode.
@ -33,7 +33,7 @@ export default class EntryAbility extends UIAbility {
onDestroy(): void {
stopForegroundBridge();
console.info('[HomeAgent] ability onDestroy');
console.info('[HologramAgent] ability onDestroy');
}
/** System dark/light switch — re-resolve when mode is 'system'. */
@ -75,7 +75,7 @@ export default class EntryAbility extends UIAbility {
onWindowStageCreate(windowStage: window.WindowStage): void {
const startUI = (): void => {
windowStage.loadContent('pages/Index', () => {
console.info('[HomeAgent] main page loaded');
console.info('[HologramAgent] main page loaded');
});
};
@ -99,21 +99,21 @@ export default class EntryAbility extends UIAbility {
// 全屏沉浸:内容延伸到状态栏和导航栏区域
win.setWindowLayoutFullScreen(true);
} catch (e) {
console.warn('[HomeAgent] setWindowLayoutFullScreen failed: ' + (e as Error).message);
console.warn('[HologramAgent] setWindowLayoutFullScreen failed: ' + (e as Error).message);
}
connStore.init(this.context).then(async () => {
const cur = connStore.getCurrentConnection();
if (cur !== null) {
apiClient.setConnection(cur);
}
console.info('[HomeAgent] connStore initialized');
console.info('[HologramAgent] connStore initialized');
// init 之后持久化的主题模式才可读,这里按存量设置重新解析并刷新系统栏
this.reapplyStoredTheme();
this.applySystemBar();
startForegroundBridge(this.context);
startUI();
}).catch((e: Error) => {
console.error('[HomeAgent] connStore init failed: ' + e.message);
console.error('[HologramAgent] connStore init failed: ' + e.message);
startUI();
});
});
@ -129,16 +129,16 @@ export default class EntryAbility extends UIAbility {
}
onWindowStageDestroy(): void {
console.info('[HomeAgent] ability onWindowStageDestroy');
console.info('[HologramAgent] ability onWindowStageDestroy');
}
onForeground(): void {
startForegroundBridge(this.context);
console.info('[HomeAgent] ability onForeground');
console.info('[HologramAgent] ability onForeground');
}
onBackground(): void {
stopForegroundBridge();
console.info('[HomeAgent] ability onBackground');
console.info('[HologramAgent] ability onBackground');
}
}

View File

@ -207,7 +207,7 @@ export function normalizeBaseUrl(raw: string): string {
export function defaultConnection(): ConnectionConfig {
const c: ConnectionConfig = {
id: '',
name: 'HomeAgent',
name: 'HologramAgent',
url: '',
apiKey: '',
type: 'webui',

View File

@ -2,7 +2,7 @@
"module": {
"name": "entry",
"type": "entry",
"description": "HomeAgent client entry module",
"description": "HologramAgent client entry module",
"mainElement": "EntryAbility",
"deviceTypes": [
"phone",
@ -31,7 +31,7 @@
{
"name": "EntryAbility",
"srcEntry": "./ets/entryability/EntryAbility.ets",
"description": "HomeAgent main entry",
"description": "HologramAgent main entry",
"icon": "$media:layered_image",
"label": "$string:app_name",
// 启动页图标用透明底字形,配合随主题切换的 start_window_background,

View File

@ -2,7 +2,7 @@
"string": [
{
"name": "app_name",
"value": "HomeAgent"
"value": "HologramAgent"
},
{
"name": "read_pasteboard_reason",

View File

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Some files were not shown because too many files have changed in this diff Show More