Merge commit 'refs/tmp/gmain' into ci/boot-graph-tests

This commit is contained in:
JianFeeeee
2026-10-24 13:34:57 +08:00
300 changed files with 5310 additions and 939 deletions

View File

@ -1,4 +1,4 @@
# HomeAgent 主仓 CI。
# HologramAgent 主仓 CI。
#
# 设计原则:**CI 里跑的每一条命令,都是本地已实测通过的命令**。
# 不写「应该有用来试试」的步骤 —— 未验证的 CI 步骤会把假红灯变成常态,
@ -521,19 +521,124 @@ jobs:
csrc:
name: C infrastructure gates
runs-on: ubuntu-latest
timeout-minutes: 20
# 门禁本身实测 0~1 秒(csrc-lint/abi/headers/sanitize/cross 各自 <1s)。
# 这 15 分钟全部是给 apt-get 的余量 —— 卡死历来只发生在装包阶段。
timeout-minutes: 15
steps:
- uses: actions/checkout@v7
# clang 供双编译器告警对照;gcc-aarch64 供跨架构编译门禁。
# 门禁在缺工具时是显式 SKIP 而不是假通过,这里装齐以免静默降级。
- name: 安装 C 工具链
# ── 安装 C 工具链 ─────────────────────────────────────────────
#
# ★ 加固点(2026-10-22):实测两次该 job 卡死 20 分钟并超时,
# 而**本地同一门禁 0~1 秒全通过**(make check-csrc)。卡死点全在
# apt-get:ubuntu-latest runner 上 `apt-get update` 偶发挂住不返回,
# 既没有失败也没有进展,只能等 job 级 timeout。
#
# 三重加固:
# 1. 逐包检查是否已安装 —— runner 镜像通常自带 cmake/clang,
# 已装就跳过 apt-get(多数情况直接走这条,完全不碰网络)
# 2. 需要装时给 apt-get 加自身的超时与重试,让它**自己失败**,
# 而不是把整个 job 拖到 job 级 timeout(后者报错信息毫无指向性)
# 3. 装完立即 `command -v` 复核,缺工具就红 —— 见下方"缺工具即失败"
- name: 安装 C 工具链(已装则跳过)
# 120s(update) + 180s(install) = 300s,给 5 分钟正好;
# 超出说明 timeout 命令本身没生效,此时应当红而不是继续等。
timeout-minutes: 5
run: |
sudo apt-get update -qq
sudo apt-get install -y -qq cmake clang gcc-aarch64-linux-gnu
set -uo pipefail
# ★ 不再需要 gcc-aarch64-linux-gnu(2026-10-22)。
#
# 实测:装它要从源拉 10MB+ 的 cpp-13 等依赖,在 runner 上卡住超时
# (15:47:39 开始下 cpp-13-aarch64,180s 后仍未完成)。
# 而 csrc-cross 只需要 `-fsyntax-only`,clang 自带交叉前端即可:
# `clang --target=aarch64-linux-gnu` 会真的切到 aarch64 目标
# (__aarch64__ 宏生效、指针宽度按该架构算),足以暴露本门禁要抓的
# 架构问题。Makefile 的 csrc-cross 已按
# CC_ARM64 > clang --target > aarch64-gcc > SKIP 的优先级挑选。
need=""
command -v cmake >/dev/null || need="$need cmake"
command -v clang >/dev/null || need="$need clang"
# aarch64 的 libc 头(1.7MB,仅头文件,**不含编译器**)。
# 用它 + 已预装的 clang 交叉前端,替代 10MB+ 的完整交叉 GCC
# (实测那个会卡在下载 cpp-13-aarch64,180s 超时)。
[ -d /usr/aarch64-linux-gnu/include ] || need="$need libc6-dev-arm64-cross"
if [ -z "$need" ]; then
echo "✅ 依赖已存在,跳过 apt-get:$(command -v cmake clang | tr '\n' ' ')"
exit 0
fi
echo "需要安装:$need"
# ★ 2026-10-22 实测:加 Acquire::*Timeout=60 + Retries=3 之后仍然卡满
# 6 分钟 step 超时,且**日志里一个 apt 输出都没有** —— 因为 `-qq`
# 把一切静默了。卡死不可观测正是它拖满超时的原因:既看不到卡在哪个
# 源,也看不到到底在下载什么。
#
# 所以:
# · 去掉 `-qq`,保留可读进度(否则下次卡死仍然无从诊断)
# · 用 `timeout` 命令做外层硬超时 —— Acquire::Timeout 只管单个连接,
# 不管 apt 整体(源重试、DPkg 锁等待都不受它约束)
# · 失败后**不重试整段**:宁可红一次让人看见,也不要为偶发网络
# 抖动掩盖真实问题
APT_OPTS="-o Acquire::http::Timeout=30 -o Acquire::https::Timeout=30 -o Acquire::Retries=2"
# shellcheck disable=SC2086
if ! timeout 120 sudo apt-get $APT_OPTS update; then
echo "::error::apt-get update 超时/失败(120s)—— runner 网络或源不可用"
exit 1
fi
# shellcheck disable=SC2086
if ! timeout 180 sudo apt-get $APT_OPTS install -y --no-install-recommends $need; then
echo "::error::apt-get install 超时/失败(180s)需要安装:$need"
exit 1
fi
# ── 缺工具即失败(★ 这条是本次加固的核心)────────────────────
#
# 此前门禁在缺工具时打 `[SKIP] ... exit 0` —— **CI 照样变绿**。
# 那意味着:apt-get 悄悄失败(或将来有人删掉安装步骤)⇒ 五道门禁
# 全部跳过 ⇒ job 绿 ⇒ 让人以为 C 侧有门禁,实际一个都没跑。
#
# 静默降级比红更危险:红会有人修,绿没人看。
# 所以 CI 里显式要求工具必须在场,SKIP 视为失败。
- name: 确认 C 工具链齐备(缺则失败,不接受 SKIP)
run: |
set -euo pipefail
miss=""
for t in cmake clang; do
if command -v "$t" >/dev/null 2>&1; then
echo " ✅ $t: $(command -v "$t")"
else
echo " ❌ $t 缺失" >&2
miss="$miss $t"
fi
done
[ -z "$miss" ] || {
echo "::error::C 工具链缺失:$miss —— 缺工具时门禁会 SKIP 并 exit 0,等于假装通过"
exit 1
}
# ── 跑门禁 ──────────────────────────────────────────────────
# 门禁自身 0~1 秒,给它 5 分钟绰绰有余;超出说明是异常(不是慢)。
- name: make check-csrc
run: make check-csrc
timeout-minutes: 5
run: |
set -o pipefail
make check-csrc 2>&1 | tee /tmp/csrc.log
# ★ 二次确认:任何 [SKIP] 都视为失败。
#
# Makefile 里每道门禁在缺依赖时 `echo "[SKIP] ..."; exit 0`,
# 这在本机是合理的(开发者未必装了交叉工具链),但在 CI 里
# 就等于把"没验证"伪装成"通过"。上面那步已保证工具齐备,
# 这里再拦一次是为了覆盖将来新增门禁时漏配依赖的情况。
if grep -q '\[SKIP\]' /tmp/csrc.log; then
echo "::error::门禁出现 [SKIP],说明有检查没真正执行:"
grep '\[SKIP\]' /tmp/csrc.log >&2
echo "CI 里不接受 SKIP —— 要么装上依赖,要么明确从 check-csrc 摘掉这条。" >&2
exit 1
fi
echo "✅ 全部门禁实际执行,无 SKIP"
# ── 文档站构建(mkdocs,纯 Python,无外部依赖)──
docs:
@ -589,11 +694,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 相同。
#
@ -617,7 +722,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,3 +1,7 @@
# 门禁脚本需要 bash 的 PIPESTATUS(/bin/sh=dash 不支持)。
# 没有它就无法区分"编译器失败"与"head 成功" —— 实测会让门禁假通过。
SHELL := /bin/bash
.PHONY: test-gui all build build-plain build-cli build-gui clean install test run build-static build-linux-arm64 lint fmt sync-client-versions check-client-versions check-starmap-shared check-client-protocol csrc csrc-test csrc-lint csrc-abi csrc-headers csrc-sanitize csrc-cross csrc-fuzz check-csrc check-csrc-full
# HOMED_TAGS 默认带 onnxruntime:发行版**默认启用**本地向量空间(与
# deploy/packaging/build.sh 保持一致)。
@ -255,21 +259,71 @@ csrc-fuzz:
# C 侧的架构相关问题(endianness 假设、指针宽度、size_t vs int 宽度、
# -fsanitize 不可用)只有真的用目标编译器编一遍才会暴露。
# 与 deploy/packaging/build.sh 的 arm64 目标共用同一套 CC 变量。
#
# ## 为什么首选 clang --target,而不是 aarch64-linux-gnu-gcc(2026-10-22)
#
# 这道门禁只做 `-fsyntax-only`(不链接、不运行),而 clang 自带交叉前端:
# `clang --target=aarch64-linux-gnu` 会真的切到 aarch64 目标(`__aarch64__`
# 宏生效、指针宽度按该架构计算),足以暴露本门禁要抓的那类问题
# (endianness 假设、指针/size_t 宽度、不支持的 C 扩展)。
#
# 而装 `gcc-aarch64-linux-gnu` 需要从源拉 10MB+ 的 cpp-13 等依赖 ——
# 实测在 CI runner 上会卡住超时(见 .github/workflows/ci.yml 的加固说明)。
# 既然只需要语法层验证,就不该为它引入一个会卡死的下载依赖。
#
# 优先级:CC_ARM64(显式指定) > clang --target > aarch64-linux-gnu-gcc > SKIP
#
# ★ 宿主头泄漏陷阱(CI 实测):只加 -isystem 指向 aarch64 头还不够 ——
# 宿主 /usr/include/stdint.h 会先被找到,它再 include <bits/libc-header-start.h>
# (amd64 布局),aarch64 目标下必然找不到:
# /usr/include/stdint.h:26: fatal error: 'bits/libc-header-start.h' file not found
# 所以 clang-target 模式必须 -nostdinc 剃掉全部默认路径,再按
# 「clang 内建头 → aarch64 目标头」顺序加回(见下方 ARM64_INC)。
# explicit / cross-gcc 模式用编译器自带搜索路径,不传这些。
#
# ★ 两个假通过陷阱(实测踩到,勿删):
# 1. 显式 CC_ARM64 指向不存在的命令时,`cmd | head` 的退出码是 head 的(恒 0),
# command-not-found(127) 被吞 ⇒ 门禁显示"通过"。所以循环里改用 PIPESTATUS[0],
# 且对显式指定的编译器先做 command -v 校验。
# 2. 上述 PIPESTATUS 需要 bash;Make 默认 /bin/sh=dash 不支持(见文件顶 SHELL)。
.PHONY: csrc-cross
csrc-cross:
@echo "== C 侧交叉编译(linux/arm64)=="
@CC_ARM64=$${CC_ARM64:-aarch64-linux-gnu-gcc}; \
if ! command -v $$CC_ARM64 >/dev/null 2>&1; then \
echo " [SKIP] $$CC_ARM64 不存在(未装交叉工具链)"; exit 0; \
@ok=1; \
if [ -n "$${CC_ARM64:-}" ]; then \
if ! command -v "$$CC_ARM64" >/dev/null 2>&1; then \
echo " [FAIL] CC_ARM64=$$CC_ARM64 不存在"; exit 1; \
fi; \
ok=1; \
CC="$$CC_ARM64"; MODE="explicit"; \
elif command -v clang >/dev/null 2>&1; then \
CC="clang --target=aarch64-linux-gnu"; MODE="clang-target"; \
elif command -v aarch64-linux-gnu-gcc >/dev/null 2>&1; then \
CC="aarch64-linux-gnu-gcc"; MODE="cross-gcc"; \
else \
echo " [SKIP] 无 clang、无 aarch64-linux-gnu-gcc(未装任何交叉前端)"; exit 0; \
fi; \
\
ARM64_INC="-nostdinc -isystem $$(clang -print-resource-dir)/include"; \
for d in /usr/aarch64-linux-gnu/include /usr/include/aarch64-linux-gnu; do \
[ -d "$$d" ] && ARM64_INC="$$ARM64_INC -isystem $$d"; \
done; \
\
if [ "$$MODE" = "clang-target" ]; then \
printf '#include <string.h>\nint main(void){return 0;}\n' > /tmp/_archchk.c; \
if ! clang --target=aarch64-linux-gnu $$ARM64_INC -fsyntax-only /tmp/_archchk.c >/dev/null 2>&1; then \
echo " [SKIP] clang 交叉前端不可用(缺 aarch64 libc 头,装 libc6-dev-arm64-cross 即可)"; exit 0; \
fi; \
fi; \
\
EXTRA_INC=""; \
[ "$$MODE" = "clang-target" ] && EXTRA_INC="$$ARM64_INC"; \
for src in $(CSRC_SRCS); do \
if ! $$CC_ARM64 $(CSRC_CFLAGS) -Werror -fsyntax-only $$src 2>&1 | head -20; then \
ok=0; \
fi; \
$$CC $$EXTRA_INC $(CSRC_CFLAGS) -Werror -fsyntax-only $$src 2>&1 | head -20; \
rc=$${PIPESTATUS[0]}; \
if [ "$$rc" != "0" ]; then ok=0; fi; \
done; \
if [ "$$ok" = "1" ]; then \
echo " $$CC_ARM64: 0 告警、编译通过 ✓($(words $(CSRC_SRCS)) 个源文件)"; \
echo " $$CC [$$MODE]: 0 告警、编译通过 ✓($(words $(CSRC_SRCS)) 个源文件)"; \
else \
echo " [FAIL] arm64 交叉编译失败"; exit 1; \
fi

View File

@ -240,7 +240,7 @@ internal/
├── config/ SQLite 配置中心
├── events/ 事件总线
└── internal/lua/adapters/ 10 个 LLM 协议适配器脚本
外部插件开发见 [homeagentsdk](https://github.com/JianFeeeee/homeagentsdk) 仓库,使用 `hmapdev` 工具链开发,参考 `example/` 目录下的 Go 和 Lua 示例
外部插件开发见 [hologramagentsdk](https://github.com/JianFeeeee/hologramagentsdk) 仓库,使用 `hmapdev` 工具链开发,参考 `example/` 目录下的 Go 和 Lua 示例
```
## 项目状态
@ -318,7 +318,7 @@ internal/
> inline/small **30.4µs**、frame/small 51.5µs、inline/large 767µs、frame/large 398µs。
> 保留原文不修改,以免伪造历史。
**v1.1.1** — 多模态贯通**插件边界**。v1.1.0 让记忆系统支持了二进制多媒体节点,但那条链路只对内核自己开放;本版打通到插件与模型。公开 SDK 新增媒体字段与三个媒体注入接口(配套 [SDK v1.1.0](https://github.com/JianFeeeee/homeagentsdk/tree/v1.1.0),整条 1.1.x 线共用),内核实现对应四个 RPC。桥接层此前在**静默裁字段**:插件交进来的 `Confidence`/类型/`SentenceText` 全被丢弃、`Doc` 只留三个字段、`Remove` 不解引用(媒体永久算「被引用」,GC 收不掉)。`processTextInput`/`processMediaInput` 归一成一条 `processInput`,媒体路径由此获得它一直缺的去重、`no_memory`、通道 `Cleaner`、中断语义、`EventRawInput`。修掉三处真实缺陷:**用户发的图从来没出现在 WebUI 聊天记录里**(媒体路径发布 map 而订阅方断言 string)、**`memory_commit` 的 `sentence_text` 从未暴露给模型**(而它是媒体绑定链的必经环节)、**`PluginSDK` 两处并发竞态**(`-race` 实测 11 处,插件重载瞬间偶发 nil 解引用崩溃)。
**v1.1.1** — 多模态贯通**插件边界**。v1.1.0 让记忆系统支持了二进制多媒体节点,但那条链路只对内核自己开放;本版打通到插件与模型。公开 SDK 新增媒体字段与三个媒体注入接口(配套 [SDK v1.1.0](https://github.com/JianFeeeee/hologramagentsdk/tree/v1.1.0),整条 1.1.x 线共用),内核实现对应四个 RPC。桥接层此前在**静默裁字段**:插件交进来的 `Confidence`/类型/`SentenceText` 全被丢弃、`Doc` 只留三个字段、`Remove` 不解引用(媒体永久算「被引用」,GC 收不掉)。`processTextInput`/`processMediaInput` 归一成一条 `processInput`,媒体路径由此获得它一直缺的去重、`no_memory`、通道 `Cleaner`、中断语义、`EventRawInput`。修掉三处真实缺陷:**用户发的图从来没出现在 WebUI 聊天记录里**(媒体路径发布 map 而订阅方断言 string)、**`memory_commit` 的 `sentence_text` 从未暴露给模型**(而它是媒体绑定链的必经环节)、**`PluginSDK` 两处并发竞态**(`-race` 实测 11 处,插件重载瞬间偶发 nil 解引用崩溃)。
**v1.1.0** — 记忆系统支持**二进制多媒体节点**。内容寻址媒体存储(CAS + SQLite 元数据 + 磁盘 blob,`Get` always 重校 digest),贯通 L0(上下文事件)/L2(文档)/L3(图谱句子)三层,引用计数式 GC(有引用者绝不删)。视觉模型生成的描述文本是持久语义记忆,blob 只是可被容量 GC 淘汰的缓存。
@ -326,7 +326,7 @@ internal/
**v0.9.0** — C ABI v2:外部插件 Stage 回调支持写回(`invoke_stage` 增加 result 输出,插件可在 OnInput/AfterToolcall/PostAction 修改 RawMessage/LLMText/ToolResults 等并同步回内核),ABI 版本随内核 minor 对齐(v0.9.x → ABIVersion=2,`version_min=1` 向后兼容旧插件)。同步修复工具循环 zen 兼容补位误伤首轮 system 上下文的问题。配套 SDK 提供增强版 sanitizer 示例(坏 UTF-8/U+FFFD/ANSI 转义全链路清洗)。**该 ABI 已随 v1.0.0 退场。**
**v0.8.0** — 核心可用,插件系统增强。内置 20+ 插件,外部插件开发见 [homeagentsdk](https://github.com/JianFeeeee/homeagentsdk) 仓库。新增输入通道 `NoMemory`/`Cleaner`、`ChannelDef`、插件禁用/启用系统(CLI + WebUI),`plugindev` 工具链完成 C ABI `ChannelDef` 传递。
**v0.8.0** — 核心可用,插件系统增强。内置 20+ 插件,外部插件开发见 [hologramagentsdk](https://github.com/JianFeeeee/hologramagentsdk) 仓库。新增输入通道 `NoMemory`/`Cleaner`、`ChannelDef`、插件禁用/启用系统(CLI + WebUI),`plugindev` 工具链完成 C ABI `ChannelDef` 传递。
## 文档
@ -385,7 +385,7 @@ make install # 安装到系统
**通过网络提供服务时也要向使用者提供源码**(§13 Remote Network Interaction)。
即:任何人把改过的 HologramAgent 对外提供网络服务,都必须让该服务的使用者拿到改动后的源码。
插件与本项目通过公开 [homeagentsdk](https://github.com/JianFeeeee/homeagentsdk) 静态链接
插件与本项目通过公开 [hologramagentsdk](https://github.com/JianFeeeee/hologramagentsdk) 静态链接
(SDK 源码会进入插件二进制),但那个仓**以 MIT 发布**——MIT 是宽松许可,拿到授权的代码不继承
本项目的 AGPL。因此**外部插件不是本项目的衍生作品**,作者可自行选择许可(含闭源、商业、私有),
既不必同许可、也不受 §13 网络条款约束。第三方插件生态的安全与活跃正建立在这条之上。

View File

@ -221,7 +221,7 @@ internal/
├── config/ SQLite config center
├── events/ Event bus
└── internal/lua/adapters/ 10 LLM protocol adapter scripts
External plugin development: see [homeagentsdk](https://github.com/JianFeeeee/homeagentsdk) repo, use `hmapdev` toolchain, refer to Go and Lua examples in `example/`
External plugin development: see [hologramagentsdk](https://github.com/JianFeeeee/hologramagentsdk) repo, use `hmapdev` toolchain, refer to Go and Lua examples in `example/`
```
## Project Status
@ -323,7 +323,7 @@ External plugin development: see [homeagentsdk](https://github.com/JianFeeeee/ho
**v1.1.1** — Multimodal reaches the **plugin boundary**. v1.1.0 gave the memory system binary
multimedia nodes, but that path was open only to the kernel itself; this release opens it to
plugins and the model. The public SDK gains media fields and three media injection methods
(paired with [SDK v1.1.0](https://github.com/JianFeeeee/homeagentsdk/tree/v1.1.0),
(paired with [SDK v1.1.0](https://github.com/JianFeeeee/hologramagentsdk/tree/v1.1.0),
shared by the whole 1.1.x line), and the kernel implements the four matching RPCs. The bridge
layer had been **silently dropping fields**: `Confidence`/types/`SentenceText` handed in by a
plugin were discarded, `Doc` kept only three fields, and `Remove` never released references
@ -346,7 +346,7 @@ semantic memory; the blob is only a cache that capacity GC may evict.
**v0.9.0** — C ABI v2: external plugin Stage callbacks can now write back (`invoke_stage` gained a result out-param; plugins may mutate RawMessage/LLMText/ToolResults etc. in OnInput/AfterToolcall/PostAction and have them synced to the core). ABI version now tracks core minor releases (v0.9.x → ABIVersion=2, `version_min=1` keeps old plugins loadable). Also fixes the tool-loop zen-compat placeholder that wrongly fired on first-turn system context tail. The SDK ships an enhanced sanitizer example (bad-UTF-8 / U+FFFD / ANSI-escape scrub across the whole pipeline). **This ABI retired with v1.0.0.**
**v0.8.0** — Core is functional, plugin system enhanced. 20+ built-in plugins. External plugin development via [homeagentsdk](https://github.com/JianFeeeee/homeagentsdk) repo. Added input channel `NoMemory`/`Cleaner`, `ChannelDef`, plugin disable/enable system (CLI + WebUI), `plugindev` toolchain C ABI `ChannelDef` support.
**v0.8.0** — Core is functional, plugin system enhanced. 20+ built-in plugins. External plugin development via [hologramagentsdk](https://github.com/JianFeeeee/hologramagentsdk) repo. Added input channel `NoMemory`/`Cleaner`, `ChannelDef`, plugin disable/enable system (CLI + WebUI), `plugindev` toolchain C ABI `ChannelDef` support.
## Documentation
@ -408,7 +408,7 @@ with it over a network** (§13, Remote Network Interaction). Anyone running a mo
as a network service therefore has to make the modified source available to that service's users.
Plugins are **statically linked** against this project through the public
[homeagentsdk](https://github.com/JianFeeeee/homeagentsdk) (the SDK source ends up inside the
[hologramagentsdk](https://github.com/JianFeeeee/hologramagentsdk) (the SDK source ends up inside the
plugin binary), but that repository is released under **MIT** — a permissive license, so code
received under it does **not** inherit this project's AGPL. External plugins are therefore **not
derivative works of this project**: authors pick their own license (closed-source, commercial or

View File

@ -111,5 +111,5 @@ Core functionality is operational. Plugin system and SDK are ready for independe
- Built-in plugins (13): webui / cli / agentcli / cfgmgr / healthcheck / kbtree / multimodal / pluginmgr / clawhubadapter / remotedevice / skillmgr / seemedia / seq
- Criterion: **a plugin stays built-in only if it requires internal-SDK-only capabilities**; everything else ships as an .hmap external plugin (see ARCHITECTURE)
- External plugin examples ([homeagentsdk](https://github.com/JianFeeeee/homeagentsdk) repo `example/`, both Go and Lua types): qq / files / a2a / ai_image / bili / browser / calendar / editdoc / memo / music / ocr / rss / sanitizer / weather / luademo
- External plugin examples ([hologramagentsdk](https://github.com/JianFeeeee/hologramagentsdk) repo `example/`, both Go and Lua types): qq / files / a2a / ai_image / bili / browser / calendar / editdoc / memo / music / ocr / rss / sanitizer / weather / luademo
- Distribution: `.hmap` plugin package format, installable via WebUI

View File

@ -8,13 +8,20 @@
All external interaction capabilities of HologramAgent comes from plugins. Plugins interact with the kernel through `PluginSDK` (Go API).
**SDK Repository**: Plugin development tools, template code, and example plugins are hosted in the [homeagentsdk](https://github.com/JianFeeeee/homeagentsdk) repository.
**SDK Repository**: Plugin development tools, template code, and example plugins are hosted in the [hologramagentsdk](https://github.com/JianFeeeee/hologramagentsdk) repository.
```bash
git clone https://github.com/JianFeeeee/homeagentsdk.git
cd homeagentsdk
git clone https://github.com/JianFeeeee/hologramagentsdk.git
cd hologramagentsdk
```
> **The repo name and the module path are two different things.** The repository
> was renamed to `hologramagentsdk` in Oct 2026, but the `go.mod` of every
> **published tag** (v1.3.0 and earlier) still declares
> `module github.com/JianFeeeee/homeagentsdk`, so `import` / `go.mod` keep using
> the old module path (as in the examples below). Once the SDK ships a tag with
> the new module name, the core repo and new plugins can migrate together.
Each plugin implements a three-method interface:
```go
@ -48,7 +55,7 @@ plugin types, and producing `.hmap` plugin bundles (the tool is named after that
### Installation
```bash
cd homeagentsdk/tools/hmapdev
cd hologramagentsdk/tools/hmapdev
go build -o hmapdev
# Add hmapdev to PATH or use directly
# Prebuilt binaries also ship as release assets (hmapdev_linux_amd64, ...)
@ -844,31 +851,31 @@ Internal: records are stored in SQLite `disabled_plugins` table (`name`, `disabl
## 7. Example Plugin Reference
### SDK Repository Examples (`homeagentsdk/example/`)
### SDK Repository Examples (`hologramagentsdk/example/`)
| Example | Type | Features |
|---------|------|----------|
| [weather](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/weather) | Go | Weather queries (wttr.in); demonstrates NoMemory/Cleaner/stage hooks/channels/text memory |
| [luademo](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/luademo) | Lua | Full-featured Lua example covering the whole v0.8.0 Lua SDK surface |
| [qq](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/qq) | Go | NapCat OneBot integration, 24 tools, full input/output channel wiring |
| [memo](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/memo) | Go | Memo management, PreAction injection + timed interrupt dual reminder |
| [files](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/files) | Go | File system operations, 4 write modes, sandbox isolation |
| [browser](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/browser) | Go | Web search + HTTP fetch (SSRF) + Chromium render (merged from web/webfetch) |
| [bili](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/bili) | Go | Bilibili video download (yt-dlp) |
| [editdoc](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/editdoc) | Go | Office document editing and format conversion |
| [a2a](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/a2a) | Go | Agent-to-Agent protocol |
| [ocr](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/ocr) | Go | Offline text recognition (Tesseract) |
| [sanitizer](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/sanitizer) | Go | Output sanitizer filter |
| [calendar](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/calendar) | Go | Calendar management |
| [rss](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/rss) | Go | RSS subscriptions |
| [ai_image](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/ai_image) | Go | AI image generation |
| [music](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/music) | Go | Music playback |
| [vikunja](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/vikunja) | Go | Vikunja task management (projects/tasks/labels CRUD) |
| [vanblog](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/vanblog) | Go | VanBlog publishing and management |
| [deepsearch](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/deepsearch) | Go | Multi-round deep search (progressive focus + cited summary) |
| [acp](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/acp) | Go | Agent Client Protocol (external editors/IDEs drive this agent) |
| [recoverydiag](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/recoverydiag) | Go | Five-part fault diagnosis (triage / sqlite check / log signatures / diff / ranked conclusions); core plugin of failback mode |
| [plugindev](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/plugindev) | Go | Plugin scaffolding: generate, build, install — lets the agent develop plugins itself |
| [weather](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/weather) | Go | Weather queries (wttr.in); demonstrates NoMemory/Cleaner/stage hooks/channels/text memory |
| [luademo](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/luademo) | Lua | Full-featured Lua example covering the whole v0.8.0 Lua SDK surface |
| [qq](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/qq) | Go | NapCat OneBot integration, 24 tools, full input/output channel wiring |
| [memo](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/memo) | Go | Memo management, PreAction injection + timed interrupt dual reminder |
| [files](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/files) | Go | File system operations, 4 write modes, sandbox isolation |
| [browser](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/browser) | Go | Web search + HTTP fetch (SSRF) + Chromium render (merged from web/webfetch) |
| [bili](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/bili) | Go | Bilibili video download (yt-dlp) |
| [editdoc](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/editdoc) | Go | Office document editing and format conversion |
| [a2a](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/a2a) | Go | Agent-to-Agent protocol |
| [ocr](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/ocr) | Go | Offline text recognition (Tesseract) |
| [sanitizer](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/sanitizer) | Go | Output sanitizer filter |
| [calendar](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/calendar) | Go | Calendar management |
| [rss](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/rss) | Go | RSS subscriptions |
| [ai_image](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/ai_image) | Go | AI image generation |
| [music](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/music) | Go | Music playback |
| [vikunja](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/vikunja) | Go | Vikunja task management (projects/tasks/labels CRUD) |
| [vanblog](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/vanblog) | Go | VanBlog publishing and management |
| [deepsearch](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/deepsearch) | Go | Multi-round deep search (progressive focus + cited summary) |
| [acp](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/acp) | Go | Agent Client Protocol (external editors/IDEs drive this agent) |
| [recoverydiag](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/recoverydiag) | Go | Five-part fault diagnosis (triage / sqlite check / log signatures / diff / ranked conclusions); core plugin of failback mode |
| [plugindev](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/plugindev) | Go | Plugin scaffolding: generate, build, install — lets the agent develop plugins itself |
### Built-in Plugins
@ -903,4 +910,4 @@ Internal: records are stored in SQLite `disabled_plugins` table (`name`, `disabl
*Want to understand the project goals? See [OVERVIEW.md](OVERVIEW.md).*
*Want to understand the architecture? See [ARCHITECTURE.md](ARCHITECTURE.md).*
*SDK repository and development tools? See [homeagentsdk](https://github.com/JianFeeeee/homeagentsdk).*
*SDK repository and development tools? See [hologramagentsdk](https://github.com/JianFeeeee/hologramagentsdk).*

View File

@ -10,7 +10,17 @@ HologramAgent 的认知架构由三个核心子系统构成:事件循环(eve
**阶段管道(StageHost)** 管理两类注册:工具定义(ToolDef)与阶段处理器(StageHandler)。ToolDef 包含 `NoMemory bool` 和 `Cleaner func(string) string` 两个可选的记忆控制字段:`NoMemory=true` 时工具输出不参与向量化/jieba/蒸馏计算(原文保留);`Cleaner` 在输出进入计算层前执行过滤(如提取 JSON 的 `content` 字段)。两者均不修改原文,只影响计算层输入。`RegisterTool` 拒绝同名注册,推断工具所属插件名,并维护工具到插件的映射表 `toolPlugins`。`RegisterStage` 将处理器追加至对应阶段的处理器列表。触发阶段执行时(`RunStage`),**所有已注册处理器通过 goroutine 并行执行**,共享同一 `*StageContext` 实例(通过 `sync.RWMutex` 保护并发访问)。单个处理器的 panic 被独立恢复,不影响其他处理器。短路语义通过检查 `ctx.Response != nil` 实现——任一阶段处理器可设置此值提前终止当前链路。工具执行 `ExecuteTool` 内置 panic 恢复与栈追踪记录。`UnregisterPluginTools` 在插件热重载时移除对应工具集。
**上下文窗口(RelevanceContext)** 维护一个按时间排序的事件列表。`Append` 在录入前经 `textForVector` 聚合工具输出:按 `NoMemory` 跳过、`Cleaner` 过滤(插件为各自工具注册的清洗函数,如 QQ 外置插件剥离工具调用模板),最后经 `CleanText` 做基本空白规范化,再通过三分支向量策略(agent 事件用 Response,用户事件用 Input,cold_storage 用 Input+Response)计算嵌入向量。`Prune` 在事件数超过 `topK` 时触发,**无条件保护最近 10 条事件不被裁剪**(recency bias),对剩余候选事件计算与当前输入的 CosineSimilarity,按评分降序保留 `topK - 10` 条(下限为 0),之后按时间戳重排序。裁剪出的事件中,过滤掉 `agentcli` 和 `terminal` 来源后,其余通过 `docStore.ContextToDoc` 归档至 Document 层,保留原始时间戳。持久化采用 5 秒防抖写入磁盘 JSON 文件。
**上下文窗口(RelevanceContext)** 维护一个按时间排序的事件列表。`Append` 在录入前经 `textForVector` 聚合工具输出:按 `NoMemory` 跳过、`Cleaner` 过滤(插件为各自工具注册的清洗函数),最后经 `CleanText` 做基本空白规范化,再通过三分支向量策略(agent 事件用 Response,用户事件用 Input,cold_storage 用 Input+Response)计算嵌入向量。`Prune` 在事件数超过 `topK` 时触发,**无条件保护最近 10 条事件不被裁剪**(recency bias),对剩余候选事件计算与当前输入的 CosineSimilarity,按评分降序保留 `topK - 10` 条(下限为 0),之后按时间戳重排序。裁剪出的事件通过 `docStore.ContextToDoc` **迁移**至 Document 层:事件连同它持有的块一起下沉,保留原始时间戳与完整正文。持久化采用 5 秒防抖写入磁盘 JSON 文件。
> ★ **哪些事件不该进 L2,由插件自己声明,内核不认插件名**。
>
> 旧版这里写的是「过滤掉 `agentcli` 和 `terminal` 来源后归档」——那是在内核里
> 硬编码插件行为,已废除。正确姿势是插件在注册时就声明:
> - `ToolDef.NoMemory` / `ToolDef.Cleaner`:工具输出不进计算层
> - `ChannelDef.NoMemory` / `ChannelDef.Cleaner`:该通道的输入不进计算层
> - `InjectOptions.NoMemory`:本次注入不参与记忆
>
> 内核只消费这些**声明**(已由 `textForVector` 实现),不认识任何具体插件。
**工具定义聚合自五个来源**:IOManager 注册的插件工具;StageHost 注册的 SDK 插件工具;Indexer 提供的记忆索引工具;内置条件工具(依据 memory / knowledge / docStore / social / pluginReg / providerManager 等模块的非空状态选择性添加,包括记忆操作、知识检索、文档查询、社交网络、插件重载、子代理生成、输出通道工具、LLM 源切换等);以及按 `pendingMedia` 状态添加的媒体处理工具。`buildToolDefs()` 在每次 process 周期中重新聚合所有这些来源。
@ -83,35 +93,64 @@ eventLoop() → processTextInput()
## 三层记忆
### 记忆块是唯一载体,层是持有关系
三层不是三种数据结构,而是**同一批记忆块的三层持有关系**:
```
记忆块 MemoryBlock(union)
├─ 文本块:负载在 Text
└─ 媒体块:负载在 Data(配 MIME/宽高/尺寸)
↑ 同一个块 ID 在 context → doc → graph 全程不变
↑ 块自带 vector + fingerprint:向量只算一次,跨层复用
```
| 层 | 承载单元 | 与模型的关系 | 容量 | 流动性 |
|---|---|---|---|---|
| **L1 Context** | 事件(内联正文 + 块) | **直接投喂**(进 system prompt 时序) | 最近 n 条 / 上限 m 条 | 超限时按相似度迁出 |
| **L2 Document** | 事件(内联正文 + 块) | **不直接投喂**(需召回才进 L1) | 无上限 | 冷到阈值后蒸馏进 L3 |
| **L3 Graph** | 三元组(节点 + 关系边),节点即记忆块 | 不投喂(经召回进入 L1) | 持久 | 不流出 |
★ **L1 与 L2 结构完全同构**,唯一区别是「是否被直接投喂给模型」。
L2 不是 L1 的摘要层,也不是另一种数据形态——它就是同样的事件 + 同样的块,只是不直接进模型视野。
★ **正文(含多媒体正文)内联在块里**:文本块的 `Text` 就是正文,媒体块的 `Data` 就是字节。
不存在「块 + 外部正文」的分离形态,也不存在靠渲染字符串承载原文的路径。
事件是块的容器,不是块的替代品。
★ **任何一层都不压缩**。视图(检索摘要、给模型看的渲染)可以是压缩的,但视图不是记忆。
### 记忆流转
```
① Context (工作窗口)
① Context (工作窗口 — 直接投喂)
RelevanceContext — 内存 events[] + JSON持久化
每条事件:Timestamp / Source / Input / Response(完整) / ToolsUsed / ToolResults / Blocks
Append: 每次输入, CleanText → 三分支向量(textForVector)
agent事件→Response, 用户事件→Input, cold_storage→Input+Response
向量层级:统一多模态空间(主,带 fingerprint)→ StaticEmbedder 词嵌入 → TF-IDF(回退)
Prune: DenseCosine(仅同指纹才比较)→ 退化 StaticEmbedder CosineSimilarity;保留 topK + 最近10条
├── 保留 → timeline → 按时间排序 → system prompt
└── 低分 → Document 层归档 (原始时间戳)
└── 低分 → Document 层归档(迁移:事件连同块一起下沉,时间戳与正文不变)
Save: 5s debounce 写盘
↓ Prune 归档 ↑ LLM 主动召回
↓ Prune 归档(迁移) ↑ 召回(迁回)
② Document (文件记忆)
DocStore — JSON文件 + 稠密向量(统一多模态空间;dense_fp 须与当前空间同指纹,不符即重算;兜底: StaticEmbedder / TF-IDF InvertedIndex)
② Document (文件记忆 — 不直接投喂,结构与 L1 同构)
DocStore — 每篇文档 = 检索元数据 + 事件列表(内联正文 + 块)
写入: Prune归档 / doc_commit / Graph快照(syncGraphToDocs)
读取:
├── 自动注入: Query(input, top3) → 同一向量空间下相似度摘要 → 【相关记忆文档】→ system prompt (只读)
└── LLM主动: doc_query → Consume(读取并删除)
→ 逐条 context.Append{Timestamp: d.CreatedAt, Source: "cold_storage"}
→ 文档以原始时间戳写入 context 时间线, 从 docStore 删除
├── 自动预填充: Query(input, top3) → 同一向量空间下相似度摘要 → 【相关记忆文档】→ system prompt (只读,不动层)
└── LLM主动: doc_query → Consume(取走)
→ 逐条按各自原始时间戳把事件插回 L1 时序
→ 块随事件迁回(同一块 ID,向量不重算),L2 不再持有
冷化: FindColdDocs(72h, ≤2次访问) → docToTriples → Graph
↓ 冷文档蒸馏 ↑ 自动召回
③ Graph (图数据库)
SQLite — entities + relations 表
③ Graph (图数据库 — 顶层仍是三元组,节点即记忆块)
SQLite — memory_blocks(节点) + memory_block_edges(边)
三元组 = 【节点】【关系边】【节点】;putTripleBlocksTx 落为 src --edge_type--> dst
写入: memory_commit / 冷文档蒸馏 / Pipeline 规则蒸馏 / memory_merge
读取:
├── 自动召回: Indexer.BuildContext(input)
@ -174,21 +213,33 @@ eventLoop() → processTextInput()
- 向量化前统一经 `CleanText` 去模版噪声
- 三分支 `textForVector`:agent 事件用 Response、用户事件用 Input、cold_storage 用 Input+Response
- 预训练词嵌入 `StaticEmbedder` → CosineSimilarity,模型不可用时自动回退 TF-IDF
- 保护最近 10 条记录免于淘汰,超出部分按相关性排序归档到文档记忆
- 归档事件以原始时间戳写入文档记忆,后续 `doc_query` 召回时按原始时间戳插回时序
- 保护最近 10 条记录免于淘汰,超出部分按相关性排序**迁移**到文档记忆
- 迁移是事件**连同它持有的块**一起下沉,时间戳与正文不变;源事件清空块(同一块不同时留两层)
### Document 层
`internal/memory/document/document.go` — `Store`
- 消费即删模式:`doc_query` 检索到后删除
- 双路召回:与 Context 共享的 StaticEmbedder 语义向量搜索 + jieba 关键词提取(模型未加载时回退 char-bigram TF-IDF)
**与 Context 同构,只是不直接投喂给模型**:
- 每篇文档 = 检索元数据(`ID`/`Summary`/`Vector`/`DenseVec`/`DenseFP`/`AccessCount`)
+ **事件列表**(内联正文 + 块)
- 正文内联在块里:文本块的 `Text` 是正文,媒体块的 `Data` 是字节
- `Doc.Content` 只是**渲染视图**(供摘要/人工阅读/SDK 兼容),不是原文载体
- 自动预填充:与 Context 共享的向量空间做相似度检索 → 摘要进 system prompt(**只读**,不动层)
- 主动召回:`doc_query` 取走后,**逐条按各自原始时间戳**把事件插回 L1 时序,块随事件迁回
- 冷化:`FindColdDocs(72h, ≤2次访问)` → `docToTriples` → Graph
### Graph 层
`internal/memory/graph.go` — `GraphDB`
- SQLite WAL 模式,两张表(驱动:mattn/go-sqlite3,CGo)
- `Commit(triples)` — UPSERT entities + INSERT relations
- `Recall(keywords, depth)` — 关键词 LIKE 搜索 + BFS 遍历
**顶层结构仍是三元组,变的是节点的物理表示**:
- SQLite WAL 模式(驱动:mattn/go-sqlite3,CGo)
- `memory_blocks`(节点,带 vector + fingerprint + modality)+ `memory_block_edges`(边)
- 三元组 = 【节点】【关系边】【节点】:`putTripleBlocksTx` 落为 `src --edge_type--> dst`
- `entities` / `relations` 旧表是**存量过渡路径**,逐步退场(退场的是节点存储,不是三元组概念)
- `Commit(triples)` — 写入时直接块化为节点 + 边
- `Recall(keywords, depth)` — 关键词检索 + BFS 遍历
### 记忆工具(LLM 可直接调用)

View File

@ -24,12 +24,20 @@ CLI 需要终端面板时,**订阅事件总线**(`EventTerminalOutput` + `Ev
自己攒视图,而不是去读内核里的某个状态组件。内核只提供事件总线与插件注册面——
新增一类能力不需要改内核,也不会在核心里堆出第二套业务真相。
**三层记忆架构** — 通过分级存储策略管理 Agent 长周期运行中的信息留存:
- **Context 层**:内存中预训练词嵌入评分的事件窗口(StaticEmbedder 词向量 → CosineSimilarity,TF-IDF 回退),实时维护最近上下文,低相关性事件自动下沉到下一层
- **Document 层**:JSON 文件 + TF-IDF 向量索引的临时记忆,支持显式提交和隐式归档,冷数据蒸馏到 Graph
- **Graph 层**:SQLite 图数据库,持久化实体(entities)和关系(relations),BFS 遍历召回,蒸馏管道从对话中提取三元组
**三层记忆架构** — 三层不是三种数据结构,而是**同一批记忆块的三层持有关系**:
- **Context 层(L1,直接投喂)**:内存中预训练词嵌入评分的事件窗口(StaticEmbedder 词向量 → CosineSimilarity,TF-IDF 回退),实时维护最近上下文,低相关性事件自动下沉到下一层
- **Document 层(L2,不直接投喂)**:与 L1 **结构同构**——同样的事件 + 同样的块,只是不直接进模型视野;支持显式提交和隐式归档,冷数据蒸馏到 Graph
- **Graph 层(L3,持久)**:SQLite 图数据库,**顶层仍是三元组**(节点 + 关系边),但节点从 `entities` 表升级为 `memory_blocks`;BFS 遍历召回,蒸馏管道从对话中提取三元组
三层递进:上下文 → 冷归档 → 长期图记忆,构成从短期到持久的信息衰减与整合管道。
★ **L1 与 L2 唯一区别是「是否被直接投喂给模型」**:L2 不是 L1 的摘要层,也不是
另一种数据形态。召回 = 把事件(连同它持有的块)从“不投喂”的持有层**迁回**“投喂”的持有层。
★ **正文(含多媒体正文)内联在块里**:文本块的 `Text` 是正文,媒体块的 `Data` 是字节。
不存在「块 + 外部正文」的分离形态。**任何一层都不压缩** —— 视图(检索摘要、渲染结果)
可以是压缩的,但视图不是记忆。
三层流动:上下文 → 冷归档 → 长期图记忆,构成从短期到持久的信息衰减与整合管道;
每一次都是**迁移**(块 ID 与向量不变,只换持有层),不是复制。
**媒体记忆(v1.2.0 起:一等记忆块)** — 图片/音频不是附属物,而是记忆的一等节点:
- **内容寻址存储(CAS)**:digest 寻址,元数据在 SQLite、blob 在磁盘(两级分桶),相同字节只存一份,
@ -101,5 +109,5 @@ CLI 需要终端面板时,**订阅事件总线**(`EventTerminalOutput` + `Ev
- 内置插件(13 个):webui / cli / agentcli / cfgmgr / healthcheck / kbtree / multimodal / pluginmgr / clawhubadapter / remotedevice / skillmgr / seemedia / seq
- 判定标准:**只有必须使用内部 SDK 能力(公开 SDK 没有的接口面)的插件才内置**,其余一律外置为 .hmap 插件(详见 ARCHITECTURE「内置插件的判定标准」)
- 外部插件示例([homeagentsdk](https://github.com/JianFeeeee/homeagentsdk) 仓库 `example/`,含 Go 和 Lua 两种类型):qq / files / a2a / ai_image / bili / browser / calendar / editdoc / memo / music / ocr / rss / sanitizer / weather / luademo
- 外部插件示例([hologramagentsdk](https://github.com/JianFeeeee/hologramagentsdk) 仓库 `example/`,含 Go 和 Lua 两种类型):qq / files / a2a / ai_image / bili / browser / calendar / editdoc / memo / music / ocr / rss / sanitizer / weather / luademo
- 打包分发:`.hmap` 插件包格式,通过 WebUI 安装

View File

@ -9,13 +9,19 @@
HologramAgent 的所有外部交互能力都来自插件。插件通过 `PluginSDK`(Go API)与内核交互。
**SDK 仓库**:插件开发工具、模板代码和示例插件统一托管在
[homeagentsdk](https://github.com/JianFeeeee/homeagentsdk) 仓库。
[hologramagentsdk](https://github.com/JianFeeeee/hologramagentsdk) 仓库。
```bash
git clone https://github.com/JianFeeeee/homeagentsdk.git
cd homeagentsdk
git clone https://github.com/JianFeeeee/hologramagentsdk.git
cd hologramagentsdk
```
> **仓名与 module 路径不是一回事**:仓 2026-10 已改名为 `hologramagentsdk`,
> 但**已发布 tag(v1.3.0 及更早)的 go.mod 里 module 仍是**
> `github.com/JianFeeeee/homeagentsdk`,所以 `import` 与 `go.mod` 里继续写旧
> module 路径(下面示例即如此)。等 SDK 发新 tag 把 module 改成新名后,
> 主仓与新插件再一起改 import。
每个插件实现一个三方法接口:
```go
@ -49,7 +55,7 @@ type Plugin interface {
### 安装
```bash
cd homeagentsdk/tools/hmapdev
cd hologramagentsdk/tools/hmapdev
go build -o hmapdev
# 将 hmapdev 加入 PATH 或直接使用
# 也可从 SDK 的 release 附件下载预编译二进制(hmapdev_linux_amd64 等)
@ -830,31 +836,31 @@ pmgr.ReloadPlugins() // 重载所有插件
## 七、示例插件参考
### SDK 仓库示例(`homeagentsdk/example/`)
### SDK 仓库示例(`hologramagentsdk/example/`)
| 示例 | 类型 | 特点 |
|------|------|------|
| [weather](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/weather) | Go | 天气查询(wttr.in),演示 NoMemory/Cleaner/阶段钩子/通道/文本记忆 |
| [luademo](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/luademo) | Lua | Lua 全功能示例,覆盖 v0.8.0 Lua SDK 全部 API 面 |
| [qq](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/qq) | Go | NapCat OneBot 对接,24 个工具,输入/输出通道完整对接 |
| [memo](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/memo) | Go | 备忘管理,PreAction 注入 + 定时打断双提醒 |
| [files](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/files) | Go | 文件系统操作,4 种写入模式,沙箱隔离 |
| [browser](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/browser) | Go | 网络搜索、网页抓取(SSRF)、浏览器渲染(合并自 web/webfetch) |
| [bili](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/bili) | Go | B 站视频下载(yt-dlp) |
| [editdoc](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/editdoc) | Go | Office 文档编辑与格式转换 |
| [a2a](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/a2a) | Go | Agent-to-Agent 协议 |
| [ocr](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/ocr) | Go | 离线文字识别(Tesseract) |
| [sanitizer](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/sanitizer) | Go | 输出清洗过滤器 |
| [calendar](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/calendar) | Go | 日历管理 |
| [rss](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/rss) | Go | RSS 订阅 |
| [ai_image](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/ai_image) | Go | AI 图片生成 |
| [music](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/music) | Go | 音乐播放 |
| [vikunja](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/vikunja) | Go | Vikunja 任务管理对接(项目/任务/标签 CRUD) |
| [vanblog](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/vanblog) | Go | VanBlog 博客发布与管理 |
| [deepsearch](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/deepsearch) | Go | 多轮深度检索(逐层聚焦 + 引用汇总) |
| [acp](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/acp) | Go | Agent Client Protocol 对接(外部编辑器/IDE 驱动本 agent) |
| [recoverydiag](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/recoverydiag) | Go | 故障诊断五件套(分诊/sqlite 校验/日志签名/diff/结论排序),failback 模式的核心插件 |
| [plugindev](https://github.com/JianFeeeee/homeagentsdk/tree/main/example/plugindev) | Go | 插件脚手架:生成工程、构建、安装,供 agent 自助开发插件 |
| [weather](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/weather) | Go | 天气查询(wttr.in),演示 NoMemory/Cleaner/阶段钩子/通道/文本记忆 |
| [luademo](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/luademo) | Lua | Lua 全功能示例,覆盖 v0.8.0 Lua SDK 全部 API 面 |
| [qq](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/qq) | Go | NapCat OneBot 对接,24 个工具,输入/输出通道完整对接 |
| [memo](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/memo) | Go | 备忘管理,PreAction 注入 + 定时打断双提醒 |
| [files](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/files) | Go | 文件系统操作,4 种写入模式,沙箱隔离 |
| [browser](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/browser) | Go | 网络搜索、网页抓取(SSRF)、浏览器渲染(合并自 web/webfetch) |
| [bili](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/bili) | Go | B 站视频下载(yt-dlp) |
| [editdoc](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/editdoc) | Go | Office 文档编辑与格式转换 |
| [a2a](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/a2a) | Go | Agent-to-Agent 协议 |
| [ocr](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/ocr) | Go | 离线文字识别(Tesseract) |
| [sanitizer](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/sanitizer) | Go | 输出清洗过滤器 |
| [calendar](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/calendar) | Go | 日历管理 |
| [rss](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/rss) | Go | RSS 订阅 |
| [ai_image](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/ai_image) | Go | AI 图片生成 |
| [music](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/music) | Go | 音乐播放 |
| [vikunja](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/vikunja) | Go | Vikunja 任务管理对接(项目/任务/标签 CRUD) |
| [vanblog](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/vanblog) | Go | VanBlog 博客发布与管理 |
| [deepsearch](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/deepsearch) | Go | 多轮深度检索(逐层聚焦 + 引用汇总) |
| [acp](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/acp) | Go | Agent Client Protocol 对接(外部编辑器/IDE 驱动本 agent) |
| [recoverydiag](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/recoverydiag) | Go | 故障诊断五件套(分诊/sqlite 校验/日志签名/diff/结论排序),failback 模式的核心插件 |
| [plugindev](https://github.com/JianFeeeee/hologramagentsdk/tree/main/example/plugindev) | Go | 插件脚手架:生成工程、构建、安装,供 agent 自助开发插件 |
### 内置插件
@ -884,4 +890,4 @@ pmgr.ReloadPlugins() // 重载所有插件
*了解项目整体目标?查看 [OVERVIEW.md](OVERVIEW.md)。*
*了解技术架构?查看 [ARCHITECTURE.md](ARCHITECTURE.md)。*
*SDK 仓库与开发工具?查看 [homeagentsdk](https://github.com/JianFeeeee/homeagentsdk)。*
*SDK 仓库与开发工具?查看 [hologramagentsdk](https://github.com/JianFeeeee/hologramagentsdk)。*

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',

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