diff --git a/go.mod b/go.mod index dfeb2bbd..fe60601d 100644 --- a/go.mod +++ b/go.mod @@ -13,12 +13,12 @@ require github.com/yanyiwu/gojieba v1.4.7 require github.com/yalue/onnxruntime_go v1.13.0 require ( - github.com/JianFeeeee/homeagentsdk v0.9.2 + github.com/JianFeeeee/hologramagentsdk v0.9.2 github.com/charmbracelet/bubbles v1.0.0 github.com/charmbracelet/bubbletea v1.3.10 github.com/charmbracelet/lipgloss v1.1.0 golang.org/x/sys v0.38.0 - golang.org/x/text v0.3.8 + golang.org/x/text v0.23.0 ) require ( @@ -41,6 +41,14 @@ require ( github.com/muesli/termenv v0.16.0 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect + golang.org/x/image v0.25.0 // indirect ) -replace github.com/JianFeeeee/homeagentsdk => ./third_party/homeagent-sdk +// SDK 仓 module 已改名为 hologramagentsdk(与 GitHub 仓名一致)。 +// +// replace 指向本地源码副本,使主仓改动与 SDK 改动可在同一工作树内联调。 +// ★ 只能有这一条:Go 不允许同一目录被两个 module 路径 replace +// (报 `used for two different module paths`)。所以主仓**所有** import 都已 +// 统一改为新名,旧的 homeagentsdk 路径不再保留。 + +replace github.com/JianFeeeee/hologramagentsdk => ./third_party/homeagent-sdk diff --git a/go.sum b/go.sum index 3fcd858e..280b470e 100644 --- a/go.sum +++ b/go.sum @@ -56,12 +56,16 @@ github.com/yuin/gopher-lua v1.1.2 h1:yF/FjE3hD65tBbt0VXLE13HWS9h34fdzJmrWRXwobGA github.com/yuin/gopher-lua v1.1.2/go.mod h1:7aRmXIWl37SqRf0koeyylBEzJ+aPt8A+mmkQ4f1ntR8= golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= +golang.org/x/image v0.25.0 h1:Y6uW6rH1y5y/LK1J8BPWZtr6yZ7hrsy6hFrXjgsc2fQ= +golang.org/x/image v0.25.0/go.mod h1:tCAmOEGthTtkalusGp1g3xa2gke8J6c2N565dTyl9Rs= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/internal/agent/core/eventloop.go b/internal/agent/core/eventloop.go index 9bb92efe..50f6b0fd 100644 --- a/internal/agent/core/eventloop.go +++ b/internal/agent/core/eventloop.go @@ -10,7 +10,7 @@ import ( agentIO "github.com/JianFeeeee/HologramAgent/internal/agent/io" "github.com/JianFeeeee/HologramAgent/internal/events" sdk "github.com/JianFeeeee/HologramAgent/internal/sdk" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // eventLoop 已由 scheduler.go 的 schedulerLoop 取代(M2)。 diff --git a/internal/agent/core/inputunify_test.go b/internal/agent/core/inputunify_test.go index b7c6e382..9ad96ab9 100644 --- a/internal/agent/core/inputunify_test.go +++ b/internal/agent/core/inputunify_test.go @@ -9,7 +9,7 @@ import ( agentIO "github.com/JianFeeeee/HologramAgent/internal/agent/io" "github.com/JianFeeeee/HologramAgent/internal/memory" "github.com/JianFeeeee/HologramAgent/internal/memory/document" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // 统一输入主干(processInput / resolveInput / injectedBlocks)与 diff --git a/internal/agent/core/medialoop.go b/internal/agent/core/medialoop.go index 8a9c457b..07d63119 100644 --- a/internal/agent/core/medialoop.go +++ b/internal/agent/core/medialoop.go @@ -1,12 +1,14 @@ package core import ( + "errors" "fmt" "log" "sync" "sync/atomic" "github.com/JianFeeeee/HologramAgent/internal/memory" + "github.com/JianFeeeee/HologramAgent/internal/memory/vector" safeclose "github.com/JianFeeeee/HologramAgent/internal/safeclose" ) @@ -67,19 +69,41 @@ func (a *Agent) reembedStaleMedia() { var jobsOnce sync.Once jobs := make(chan memory.MemoryBlock, workers*2) - var done, failed int64 + var done, failed, unsupported int64 var wg sync.WaitGroup + // 失败原因按错误文本聚合 —— 不逐条打日志(上千张图会刷屏), + // 但**必须留下"为什么失败"**。 + // + // ★ 2026-10-23 实测教训:原先这里只 `failed++` 然后 continue,于是 + // 「向量迁移完成: 成功=0 失败=4」成了唯一的线索 —— 没有任何日志说明 + // 这 4 个是 webp(当时 chineseclip 未注册 webp 解码器)。失败不可观测 + // 直接导致这次排查要从数据库里反查 mime 才找到根因。 + var failMu sync.Mutex + failReasons := map[string]int{} + for i := 0; i < workers; i++ { wg.Add(1) go func() { defer wg.Done() for b := range jobs { - if err := a.reembedOneBlock(b, fp); err != nil { - atomic.AddInt64(&failed, 1) + err := a.reembedOneBlock(b, fp) + if err == nil { + atomic.AddInt64(&done, 1) continue } - atomic.AddInt64(&done, 1) + // 模态不受支持是**永久**状态(不是本次网络/服务抖动): + // 这类块永远不会有向量,语义检索也永远搜不到它。 + // 单独计数,避免它混在"失败"里让人以为重试就能好。 + if errors.Is(err, vector.ErrModalityUnsupported) { + atomic.AddInt64(&unsupported, 1) + } else { + atomic.AddInt64(&failed, 1) + } + key := b.MIME + " | " + err.Error() + failMu.Lock() + failReasons[key]++ + failMu.Unlock() } }() } @@ -93,8 +117,17 @@ func (a *Agent) reembedStaleMedia() { } safeclose.Safe(&jobsOnce, jobs) wg.Wait() - log.Printf("[media] 向量迁移完成: 成功=%d 失败=%d 总计=%d fp=%s", - done, failed, len(targets), shortFP(fp)) + log.Printf("[media] 向量迁移完成: 成功=%d 失败=%d 不支持=%d 总计=%d fp=%s", + done, failed, unsupported, len(targets), shortFP(fp)) + // 逐类打印失败原因(聚合后通常只有 1~2 类)。 + // 没有这段,运维只能看到"失败=N"而不知为何 —— 本次 webp 问题的排查成本 + // 全花在这里。 + if len(failReasons) > 0 { + log.Printf("[media] 失败原因分类(按 mime | error 聚合):") + for reason, n := range failReasons { + log.Printf("[media] %d 个: %s", n, reason) + } + } } // reembedOneBlock 为一个图像块重算向量并写回。负载就在块里,无需外部取字节。 diff --git a/internal/agent/core/medialoop_test.go b/internal/agent/core/medialoop_test.go index 3e0f7c41..87a581b5 100644 --- a/internal/agent/core/medialoop_test.go +++ b/internal/agent/core/medialoop_test.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "path/filepath" + "regexp" "strings" "testing" @@ -102,3 +103,100 @@ func TestReembedStaleMedia_NilSpaceNoop(t *testing.T) { t.Errorf("无空间可用时不该写向量: vec=%v model=%q", got.Vector, got.Fingerprint) } } + +// failSpace 让指定 mime 的图像嵌入失败,用来验证「失败必须留下原因」。 +type failSpace struct { + failMIME string +} + +func (failSpace) VectorizeDense(string) ([]float64, error) { return []float64{1, 0}, nil } + +func (f failSpace) EmbedImageDense(_ []byte, mime string) ([]float64, error) { + if mime == f.failMIME { + return nil, fmt.Errorf("模拟解码失败: %s", mime) + } + return []float64{1, 0}, nil +} + +func (failSpace) Fingerprint() string { return "fail-space" } +func (failSpace) Dim() int { return 2 } +func (failSpace) Loaded() bool { return true } +func (failSpace) Close() {} + +// 迁移失败必须留下**可诊断的原因**,而不只是一个计数。 +// +// ★ 2026-10-23 生产事故:日志只有 +// +// [media] 向量迁移完成: 成功=0 失败=4 总计=4 +// +// 没有任何信息说明为什么。反查数据库才发现那 4 个块是 image/webp, +// 而 provider 没注册 webp 解码器。**失败不可观测直接导致排查成本翻倍**。 +// +// 本判据钉住:失败原因按 "mime | error" 聚合后必须出现在日志里。 +// +// 变异:把 failReasons 的采集与打印删掉 ⇒ 红。 +func TestReembedStaleMedia_LogsFailureReasons(t *testing.T) { + a := newMediaLoopAgent(t) + // 两个都会失败(同一 mime)—— 应聚合成一条 "2 个: ..." + for i := 0; i < 2; i++ { + b := mediaBlock("image/webp", []byte("webp-bytes")) + if err := a.memory.PutMemoryBlocks([]memory.MemoryBlock{b}); err != nil { + t.Fatal(err) + } + } + + logs := captureLog(t, func() { + a.multimodalSpace = failSpace{failMIME: "image/webp"} + a.reembedStaleMedia() + }) + + if !strings.Contains(logs, "失败原因分类") { + t.Fatalf("迁移失败时必须打印失败原因分类,实际日志:\n%s", logs) + } + if !strings.Contains(logs, "image/webp") { + t.Fatalf("失败原因里必须出现具体 mime(否则无从定位是哪种格式),实际日志:\n%s", logs) + } + if !strings.Contains(logs, "模拟解码失败") { + t.Fatalf("失败原因里必须带上 provider 返回的错误原文,实际日志:\n%s", logs) + } + // 计数必须出现(格式 "N 个: ...")—— 具体数字取决于去重后的块数, + // 这里只要求"有计数",不绑死数字(绑死会让判据随去重策略变化而脆)。 + if !regexp.MustCompile(`\d+ 个: image/webp`).MatchString(logs) { + t.Fatalf("失败原因应带聚合计数(形如「N 个: image/webp | ...」),实际日志:\n%s", logs) + } +} + +// 不支持模态与临时失败必须**分开计数**:前者永远好不了(重试无意义), +// 混在"失败"里会让人误以为重试即可恢复。 +func TestReembedStaleMedia_SeparatesUnsupportedFromFailed(t *testing.T) { + a := newMediaLoopAgent(t) + // 音频走 fakeSpace 的 ErrModalityUnsupported 分支;但 reembedStaleMedia + // 只挑 image 模态,所以用图像 mime + 让 provider 返回 unsupported 来验证分类。 + img := mediaBlock("image/tiff", []byte("tiff-bytes")) + if err := a.memory.PutMemoryBlocks([]memory.MemoryBlock{img}); err != nil { + t.Fatal(err) + } + + logs := captureLog(t, func() { + a.multimodalSpace = unsupportedImageSpace{} + a.reembedStaleMedia() + }) + + if !strings.Contains(logs, "不支持=1") { + t.Fatalf("不受支持的模态应单独计数(不支持=1),实际日志:\n%s", logs) + } +} + +// unsupportedImageSpace 对任何图像都返回 ErrModalityUnsupported。 +type unsupportedImageSpace struct{} + +func (unsupportedImageSpace) VectorizeDense(string) ([]float64, error) { return []float64{1, 0}, nil } + +func (unsupportedImageSpace) EmbedImageDense(_ []byte, mime string) ([]float64, error) { + return nil, fmt.Errorf("%w: %s", vector.ErrModalityUnsupported, mime) +} + +func (unsupportedImageSpace) Fingerprint() string { return "unsupported-space" } +func (unsupportedImageSpace) Dim() int { return 2 } +func (unsupportedImageSpace) Loaded() bool { return true } +func (unsupportedImageSpace) Close() {} diff --git a/internal/agent/core/memorypass.go b/internal/agent/core/memorypass.go index fd73ebbc..71eb8d32 100644 --- a/internal/agent/core/memorypass.go +++ b/internal/agent/core/memorypass.go @@ -7,7 +7,7 @@ import ( agentIO "github.com/JianFeeeee/HologramAgent/internal/agent/io" "github.com/JianFeeeee/HologramAgent/internal/memory" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // sceneKeysFor 推导本轮输入的**当前场景**。 diff --git a/internal/agent/core/promptvars_test.go b/internal/agent/core/promptvars_test.go index 88dc17d5..81fa660e 100644 --- a/internal/agent/core/promptvars_test.go +++ b/internal/agent/core/promptvars_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/JianFeeeee/HologramAgent/internal/meta" - sdkmeta "github.com/JianFeeeee/homeagentsdk/meta" + sdkmeta "github.com/JianFeeeee/hologramagentsdk/meta" ) func TestExpandPromptVars(t *testing.T) { diff --git a/internal/agent/core/prunepolicy_test.go b/internal/agent/core/prunepolicy_test.go index 92213395..626b7fb8 100644 --- a/internal/agent/core/prunepolicy_test.go +++ b/internal/agent/core/prunepolicy_test.go @@ -4,7 +4,7 @@ import ( "testing" agentIO "github.com/JianFeeeee/HologramAgent/internal/agent/io" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // 这一组测试锁死「默认不裁剪」这条语义。 diff --git a/internal/agent/core/recallpolicy_test.go b/internal/agent/core/recallpolicy_test.go index e504678f..934c13a1 100644 --- a/internal/agent/core/recallpolicy_test.go +++ b/internal/agent/core/recallpolicy_test.go @@ -8,7 +8,7 @@ import ( agentAPI "github.com/JianFeeeee/HologramAgent/internal/agent/api" agentIO "github.com/JianFeeeee/HologramAgent/internal/agent/io" "github.com/JianFeeeee/HologramAgent/internal/memory" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // 这一组测试锁死「默认召回、可显式关闭」这条语义。 diff --git a/internal/agent/core/scenepolicy_test.go b/internal/agent/core/scenepolicy_test.go index 6c49ef7d..72625aee 100644 --- a/internal/agent/core/scenepolicy_test.go +++ b/internal/agent/core/scenepolicy_test.go @@ -15,7 +15,7 @@ import ( "testing" agentIO "github.com/JianFeeeee/HologramAgent/internal/agent/io" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) func scenePolicyNoneEvent() *agentIO.InputEvent { diff --git a/internal/agent/core/task.go b/internal/agent/core/task.go index d0aff966..8cf99521 100644 --- a/internal/agent/core/task.go +++ b/internal/agent/core/task.go @@ -33,7 +33,7 @@ import ( "github.com/JianFeeeee/HologramAgent/internal/events" "github.com/JianFeeeee/HologramAgent/internal/memory" sdk "github.com/JianFeeeee/HologramAgent/internal/sdk" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // Step 是任务状态机的游标。 diff --git a/internal/agent/core/toolcall_adjacency_test.go b/internal/agent/core/toolcall_adjacency_test.go index f039afe7..6afbb5aa 100644 --- a/internal/agent/core/toolcall_adjacency_test.go +++ b/internal/agent/core/toolcall_adjacency_test.go @@ -42,7 +42,7 @@ import ( agentAPI "github.com/JianFeeeee/HologramAgent/internal/agent/api" agentIO "github.com/JianFeeeee/HologramAgent/internal/agent/io" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // visionBatchProvider 在 batchProvider 之上声明「能看图」。 diff --git a/internal/agent/core/tooldefs.go b/internal/agent/core/tooldefs.go index 9265940e..6886db3e 100644 --- a/internal/agent/core/tooldefs.go +++ b/internal/agent/core/tooldefs.go @@ -10,7 +10,7 @@ import ( "github.com/JianFeeeee/HologramAgent/internal/meta" "github.com/JianFeeeee/HologramAgent/internal/sdk" "github.com/JianFeeeee/HologramAgent/internal/security" - sdkmeta "github.com/JianFeeeee/homeagentsdk/meta" + sdkmeta "github.com/JianFeeeee/hologramagentsdk/meta" ) func (a *Agent) buildMemoryContext(input string, maxTokens int, scenes []string) string { diff --git a/internal/agent/core/tooloop_test.go b/internal/agent/core/tooloop_test.go index 3865b549..27d3e085 100644 --- a/internal/agent/core/tooloop_test.go +++ b/internal/agent/core/tooloop_test.go @@ -5,7 +5,7 @@ import ( "testing" agentAPI "github.com/JianFeeeee/HologramAgent/internal/agent/api" - sdk "github.com/JianFeeeee/homeagentsdk/sdk" + sdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // appendPlaceholder 复刻 process() 循环顶部的补位逻辑。 diff --git a/internal/agent/io/channel.go b/internal/agent/io/channel.go index 0f16f601..c1571a5e 100644 --- a/internal/agent/io/channel.go +++ b/internal/agent/io/channel.go @@ -8,7 +8,7 @@ import ( "sync" "time" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // ErrToolNotFound 表示「工具不存在」(未注册 / 所属插件已卸载或崩溃)。 diff --git a/internal/agent/io/injectopts_test.go b/internal/agent/io/injectopts_test.go index fd835026..d3bd8072 100644 --- a/internal/agent/io/injectopts_test.go +++ b/internal/agent/io/injectopts_test.go @@ -3,7 +3,7 @@ package io import ( "testing" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // drainOne 取出一条注入事件;没有则 Fatal。 diff --git a/internal/lua/sdk/sdk.lua b/internal/lua/sdk/sdk.lua index 6167dc61..8042f463 100644 --- a/internal/lua/sdk/sdk.lua +++ b/internal/lua/sdk/sdk.lua @@ -1,5 +1,5 @@ --- HomeAgent Lua Plugin SDK --- Interface contract between Lua plugins and HomeAgent kernel. +-- HologramAgent Lua Plugin SDK +-- Interface contract between Lua plugins and HologramAgent kernel. -- !impl functions are replaced by Go implementations at runtime. -- Standalone/debug: pure Lua mock implementations are used. -- Usage: local sdk = require("sdk") diff --git a/internal/plugin/evtring.go b/internal/plugin/evtring.go index c65e81ab..482221d6 100644 --- a/internal/plugin/evtring.go +++ b/internal/plugin/evtring.go @@ -6,7 +6,7 @@ import ( "github.com/JianFeeeee/HologramAgent/internal/events" "github.com/JianFeeeee/HologramAgent/internal/plugin/proc" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // EventRing 是 Bus 与 proc.EvtRing 之间的适配层。 diff --git a/internal/plugin/evtring_close_test.go b/internal/plugin/evtring_close_test.go index 339e7cfe..9a7fa575 100644 --- a/internal/plugin/evtring_close_test.go +++ b/internal/plugin/evtring_close_test.go @@ -5,7 +5,7 @@ import ( "github.com/JianFeeeee/HologramAgent/internal/events" "github.com/JianFeeeee/HologramAgent/internal/plugin/proc" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // TestEventRing_CloseUnsubscribesFromBus 钉死:EventRing.Close 必须把 diff --git a/internal/plugin/evtring_test.go b/internal/plugin/evtring_test.go index 206c82a5..cea5275f 100644 --- a/internal/plugin/evtring_test.go +++ b/internal/plugin/evtring_test.go @@ -8,7 +8,7 @@ import ( "github.com/JianFeeeee/HologramAgent/internal/events" "github.com/JianFeeeee/HologramAgent/internal/plugin/proc" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // 事件环基础测试:Host 创建事件环 → EventRing 写入 → 消费者读到。 diff --git a/internal/plugin/manifest.go b/internal/plugin/manifest.go index 297b64bb..3e7f5266 100644 --- a/internal/plugin/manifest.go +++ b/internal/plugin/manifest.go @@ -7,7 +7,7 @@ import ( "time" "github.com/JianFeeeee/HologramAgent/internal/plugin/proc" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) const PackageExt = ".hmap" diff --git a/internal/plugin/proc/bench_test.go b/internal/plugin/proc/bench_test.go index c0bddae6..a6c2b355 100644 --- a/internal/plugin/proc/bench_test.go +++ b/internal/plugin/proc/bench_test.go @@ -7,7 +7,7 @@ import ( "strings" "testing" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // 子进程架构的性能基准(Part 6.6 验收项)。 diff --git a/internal/plugin/proc/corehandler.go b/internal/plugin/proc/corehandler.go index 10e1fc4c..a7222cbb 100644 --- a/internal/plugin/proc/corehandler.go +++ b/internal/plugin/proc/corehandler.go @@ -5,7 +5,7 @@ import ( "encoding/json" "fmt" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // coreHandler 把插件发来的 RPC 调用路由到内核 PluginSDK。 diff --git a/internal/plugin/proc/corehandler_memory.go b/internal/plugin/proc/corehandler_memory.go index 25183f9f..6e1c7b7f 100644 --- a/internal/plugin/proc/corehandler_memory.go +++ b/internal/plugin/proc/corehandler_memory.go @@ -5,7 +5,7 @@ import ( "fmt" "github.com/JianFeeeee/HologramAgent/internal/knowledge" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // handleGraphMemory 处理图记忆(实体/关系):recall / commit / introspect / merge / purge。 diff --git a/internal/plugin/proc/corehandler_register.go b/internal/plugin/proc/corehandler_register.go index 64bb37c0..f46d4eef 100644 --- a/internal/plugin/proc/corehandler_register.go +++ b/internal/plugin/proc/corehandler_register.go @@ -4,7 +4,7 @@ import ( "encoding/json" "fmt" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // handleRegister 处理注册面:工具 / stage / 输出通道 / 插件 API / 入站通道。 diff --git a/internal/plugin/proc/corehandler_runtime.go b/internal/plugin/proc/corehandler_runtime.go index d1c88d87..08c18f75 100644 --- a/internal/plugin/proc/corehandler_runtime.go +++ b/internal/plugin/proc/corehandler_runtime.go @@ -4,7 +4,7 @@ import ( "encoding/json" "fmt" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // handlePluginMgr 处理插件管理:reloadOne / listLoaded / isDisabled。 diff --git a/internal/plugin/proc/corehandler_secrets.go b/internal/plugin/proc/corehandler_secrets.go index 158b9be7..218b0097 100644 --- a/internal/plugin/proc/corehandler_secrets.go +++ b/internal/plugin/proc/corehandler_secrets.go @@ -22,7 +22,7 @@ import ( "encoding/json" "fmt" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) func (h *coreHandler) secrets(method string, params json.RawMessage) (interface{}, error) { diff --git a/internal/plugin/proc/corehandler_settings.go b/internal/plugin/proc/corehandler_settings.go index d7e443d2..79bb4103 100644 --- a/internal/plugin/proc/corehandler_settings.go +++ b/internal/plugin/proc/corehandler_settings.go @@ -4,7 +4,7 @@ import ( "encoding/json" "fmt" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // handleSettings 处理全部设置项读写(14 个 method 共用一条实现)。 diff --git a/internal/plugin/proc/e2e_secret_test.go b/internal/plugin/proc/e2e_secret_test.go index 6ae30556..7b58d414 100644 --- a/internal/plugin/proc/e2e_secret_test.go +++ b/internal/plugin/proc/e2e_secret_test.go @@ -24,7 +24,7 @@ import ( internalConfig "github.com/JianFeeeee/HologramAgent/internal/config" internalSDK "github.com/JianFeeeee/HologramAgent/internal/sdk" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // secretE2EPlugin 是一个**用真实模板**编译的插件:它只做两件事 —— @@ -32,7 +32,7 @@ import ( const secretE2EPlugin = `package main import ( - sdk "github.com/JianFeeeee/homeagentsdk/sdk" + sdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) type secretPlugin struct{ name string } diff --git a/internal/plugin/proc/e2e_secrets_test.go b/internal/plugin/proc/e2e_secrets_test.go index f61fd3da..4b6e22f9 100644 --- a/internal/plugin/proc/e2e_secrets_test.go +++ b/internal/plugin/proc/e2e_secrets_test.go @@ -29,14 +29,14 @@ import ( internalConfig "github.com/JianFeeeee/HologramAgent/internal/config" internalSDK "github.com/JianFeeeee/HologramAgent/internal/sdk" internalSecurity "github.com/JianFeeeee/HologramAgent/internal/security" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // secretsE2EPlugin 用真实模板编译:只做变量库往返。 const secretsE2EPlugin = `package main import ( - sdk "github.com/JianFeeeee/homeagentsdk/sdk" + sdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) type secPlugin struct{ name string } diff --git a/internal/plugin/proc/e2e_template_test.go b/internal/plugin/proc/e2e_template_test.go index 6053828f..c8325148 100644 --- a/internal/plugin/proc/e2e_template_test.go +++ b/internal/plugin/proc/e2e_template_test.go @@ -7,7 +7,7 @@ import ( "strings" "testing" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // 端到端:用**真实 hmapdev 模板**编译的插件,经内核 proc 通道加载运行。 @@ -25,7 +25,7 @@ const e2ePluginSource = `package main import ( "strings" - sdk "github.com/JianFeeeee/homeagentsdk/sdk" + sdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) type e2ePlugin struct{ name string } @@ -148,8 +148,8 @@ func buildPluginWithRealTemplate(t *testing.T, businessCode string) string { } mustWriteFile(t, filepath.Join(dir, "go.mod"), "module e2eplugin\n\ngo 1.25\n\n"+ - "require github.com/JianFeeeee/homeagentsdk v0.9.2\n\n"+ - "replace github.com/JianFeeeee/homeagentsdk => "+sdkPath+"\n") + "require github.com/JianFeeeee/hologramagentsdk v0.9.2\n\n"+ + "replace github.com/JianFeeeee/hologramagentsdk => "+sdkPath+"\n") bin := filepath.Join(dir, "plugin.bin") cmd := exec.Command("go", "build", "-o", bin, ".") @@ -241,7 +241,7 @@ func TestE2E_RealTemplatePluginFullLifecycle(t *testing.T) { func TestE2E_RealTemplateReadOnlyPluginDoesNotOverwrite(t *testing.T) { const readerSource = `package main -import sdk "github.com/JianFeeeee/homeagentsdk/sdk" +import sdk "github.com/JianFeeeee/hologramagentsdk/sdk" type readerPlugin struct{ name string } diff --git a/internal/plugin/proc/evtring.go b/internal/plugin/proc/evtring.go index 9ec48760..279139c2 100644 --- a/internal/plugin/proc/evtring.go +++ b/internal/plugin/proc/evtring.go @@ -9,7 +9,7 @@ import ( "time" safeclose "github.com/JianFeeeee/HologramAgent/internal/safeclose" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // ---- 事件类型编码(编译时确定,与 pubsdk.EventType 一一对应)---- diff --git a/internal/plugin/proc/extra_bag_test.go b/internal/plugin/proc/extra_bag_test.go index 8c29a965..3325468b 100644 --- a/internal/plugin/proc/extra_bag_test.go +++ b/internal/plugin/proc/extra_bag_test.go @@ -21,7 +21,7 @@ import ( "encoding/json" "testing" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) func newTestSeg(t *testing.T) *Segment { diff --git a/internal/plugin/proc/grandchild_test.go b/internal/plugin/proc/grandchild_test.go index 897d883a..623d2012 100644 --- a/internal/plugin/proc/grandchild_test.go +++ b/internal/plugin/proc/grandchild_test.go @@ -45,7 +45,7 @@ import ( "os/exec" "time" - sdk "github.com/JianFeeeee/homeagentsdk/sdk" + sdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) type gcPlugin struct{ name string } @@ -378,7 +378,7 @@ import ( "syscall" "time" - sdk "github.com/JianFeeeee/homeagentsdk/sdk" + sdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) type gcPlugin struct{ name string } diff --git a/internal/plugin/proc/host.go b/internal/plugin/proc/host.go index e47a5351..a15f05a6 100644 --- a/internal/plugin/proc/host.go +++ b/internal/plugin/proc/host.go @@ -8,7 +8,7 @@ import ( "sync" "sync/atomic" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // Host 持有**被全部子进程插件共享的统一内存区域**,是共享数据面的 diff --git a/internal/plugin/proc/host_close_stage_test.go b/internal/plugin/proc/host_close_stage_test.go index 4782256a..86d2dc07 100644 --- a/internal/plugin/proc/host_close_stage_test.go +++ b/internal/plugin/proc/host_close_stage_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // TestHost_CloseWaitsForInflightStage 钉死不变量: diff --git a/internal/plugin/proc/host_evtunsub_test.go b/internal/plugin/proc/host_evtunsub_test.go index 8273df23..987f99d2 100644 --- a/internal/plugin/proc/host_evtunsub_test.go +++ b/internal/plugin/proc/host_evtunsub_test.go @@ -4,7 +4,7 @@ import ( "sync/atomic" "testing" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // stubSubscriber 是最小 EvtRingSubscriber 实现,用于验证「关停时统一退订」。 diff --git a/internal/plugin/proc/host_stage_test.go b/internal/plugin/proc/host_stage_test.go index e7f8ce32..f8cb65ca 100644 --- a/internal/plugin/proc/host_stage_test.go +++ b/internal/plugin/proc/host_stage_test.go @@ -5,7 +5,7 @@ import ( "sync/atomic" "testing" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // 本文件是 2026-09-04 06:56:18 线上 crash 的回归测试。 diff --git a/internal/plugin/proc/plugin.go b/internal/plugin/proc/plugin.go index 457e83a1..c0e75903 100644 --- a/internal/plugin/proc/plugin.go +++ b/internal/plugin/proc/plugin.go @@ -10,7 +10,7 @@ import ( "sync/atomic" "time" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // Plugin 是 registry 可加载的子进程插件,与内置插件同构的启停接口。 diff --git a/internal/plugin/proc/plugin_test.go b/internal/plugin/proc/plugin_test.go index a95b90fd..16ccb337 100644 --- a/internal/plugin/proc/plugin_test.go +++ b/internal/plugin/proc/plugin_test.go @@ -8,7 +8,7 @@ import ( "sync" "testing" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // 端到端验证:内核 RunStage 并发扇出 → 真实子进程插件经共享内存读改写 → 结果回读。 diff --git a/internal/plugin/proc/priority_clamp_test.go b/internal/plugin/proc/priority_clamp_test.go index 63af5828..11633f4f 100644 --- a/internal/plugin/proc/priority_clamp_test.go +++ b/internal/plugin/proc/priority_clamp_test.go @@ -9,7 +9,7 @@ package proc import ( "testing" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) func TestClampExternalPriority_RejectsL4(t *testing.T) { diff --git a/internal/plugin/proc/shm_profile_test.go b/internal/plugin/proc/shm_profile_test.go index 68bc2417..a8f09ac8 100644 --- a/internal/plugin/proc/shm_profile_test.go +++ b/internal/plugin/proc/shm_profile_test.go @@ -22,7 +22,7 @@ import ( "strings" "testing" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // profileCtx 构造一组「接近真实」的 StageContext。 diff --git a/internal/plugin/proc/shm_test.go b/internal/plugin/proc/shm_test.go index 8c6f8dea..00a7fee1 100644 --- a/internal/plugin/proc/shm_test.go +++ b/internal/plugin/proc/shm_test.go @@ -6,7 +6,7 @@ import ( "sync" "testing" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // 本文件验证共享内存 stage 并发的正确性——**整个迁移最关键的一环**(§4.4 风险 3.4)。 diff --git a/internal/plugin/proc/shmcodec.go b/internal/plugin/proc/shmcodec.go index 0f568896..5decbf6f 100644 --- a/internal/plugin/proc/shmcodec.go +++ b/internal/plugin/proc/shmcodec.go @@ -4,7 +4,7 @@ import ( "encoding/json" "fmt" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // StageContext 的跨进程编解码(§3.3 数据面 / §3.4 SDK 封装全部复杂度)。 diff --git a/internal/plugin/proc/stage.go b/internal/plugin/proc/stage.go index 9a592882..56d51627 100644 --- a/internal/plugin/proc/stage.go +++ b/internal/plugin/proc/stage.go @@ -7,7 +7,7 @@ import ( "sync" "time" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // stage 执行:把内核的 RunStage 并发扇出接到共享段(§3.4,风险 3.4 的落点)。 diff --git a/internal/plugin/proc/stage_lock_reentrant_test.go b/internal/plugin/proc/stage_lock_reentrant_test.go index 57cfd050..e1f98b6e 100644 --- a/internal/plugin/proc/stage_lock_reentrant_test.go +++ b/internal/plugin/proc/stage_lock_reentrant_test.go @@ -6,7 +6,7 @@ import ( "testing" "time" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // qq 插件「重复申请 stage 锁」的生产诊断与修复(2026-10-07) diff --git a/internal/plugin/proc/streaming_test.go b/internal/plugin/proc/streaming_test.go index a57e3717..af931566 100644 --- a/internal/plugin/proc/streaming_test.go +++ b/internal/plugin/proc/streaming_test.go @@ -6,7 +6,7 @@ import ( "testing" "time" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // 流式输出压测(§4.3 标记「风险高」的那一项)。 diff --git a/internal/plugin/proc_core.go b/internal/plugin/proc_core.go index e6266c3f..4e1e5611 100644 --- a/internal/plugin/proc_core.go +++ b/internal/plugin/proc_core.go @@ -3,7 +3,7 @@ package plugin import ( "github.com/JianFeeeee/HologramAgent/internal/plugin/proc" isdk "github.com/JianFeeeee/HologramAgent/internal/sdk" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // procCore 把内核的 *internal/sdk.PluginSDK 收窄成子进程插件可见的能力面。 diff --git a/internal/plugins/agentcli/plugin_test.go b/internal/plugins/agentcli/plugin_test.go index 4f4336ba..8d0ca1a7 100644 --- a/internal/plugins/agentcli/plugin_test.go +++ b/internal/plugins/agentcli/plugin_test.go @@ -11,7 +11,7 @@ import ( "time" sdk "github.com/JianFeeeee/HologramAgent/internal/sdk" - sdkpub "github.com/JianFeeeee/homeagentsdk/sdk" + sdkpub "github.com/JianFeeeee/hologramagentsdk/sdk" ) type toolCapture struct { diff --git a/internal/plugins/clawhubadapter/sidecar_test.go b/internal/plugins/clawhubadapter/sidecar_test.go index b50636bd..0ebf118a 100644 --- a/internal/plugins/clawhubadapter/sidecar_test.go +++ b/internal/plugins/clawhubadapter/sidecar_test.go @@ -7,7 +7,7 @@ import ( "testing" sdk "github.com/JianFeeeee/HologramAgent/internal/sdk" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // mockSettings implements pubsdk.SettingsAPI for tests diff --git a/internal/plugins/real_plugin_smoke_test.go b/internal/plugins/real_plugin_smoke_test.go index 97a4ea71..157b41d9 100644 --- a/internal/plugins/real_plugin_smoke_test.go +++ b/internal/plugins/real_plugin_smoke_test.go @@ -14,7 +14,7 @@ import ( "testing" "time" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // 真实外部插件(重编为 plugin.bin)经内核加载后的端到端冒烟(Part 6.3)。 diff --git a/internal/plugins/skillmgr/skillmgr_test.go b/internal/plugins/skillmgr/skillmgr_test.go index da68a04d..a550bd33 100644 --- a/internal/plugins/skillmgr/skillmgr_test.go +++ b/internal/plugins/skillmgr/skillmgr_test.go @@ -12,7 +12,7 @@ import ( "github.com/JianFeeeee/HologramAgent/internal/events" sdk "github.com/JianFeeeee/HologramAgent/internal/sdk" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // ---- 测试辅助 ---- diff --git a/internal/plugins/webui/handler_graph_pulse_test.go b/internal/plugins/webui/handler_graph_pulse_test.go index ad99835c..755ea2b4 100644 --- a/internal/plugins/webui/handler_graph_pulse_test.go +++ b/internal/plugins/webui/handler_graph_pulse_test.go @@ -10,7 +10,7 @@ import ( "github.com/JianFeeeee/HologramAgent/internal/memory" sdk "github.com/JianFeeeee/HologramAgent/internal/sdk" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // fakeGraphMemory 是一个最小 MemoryAPI 桩,只为把 GraphData 喂给 handler。 diff --git a/internal/plugins/webui/handler_memory.go b/internal/plugins/webui/handler_memory.go index aeb69e0c..c8a1f144 100644 --- a/internal/plugins/webui/handler_memory.go +++ b/internal/plugins/webui/handler_memory.go @@ -15,7 +15,7 @@ import ( "github.com/JianFeeeee/HologramAgent/internal/knowledge" "github.com/JianFeeeee/HologramAgent/internal/memory" sdk "github.com/JianFeeeee/HologramAgent/internal/sdk" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // 记忆面:图记忆 / 文档记忆 / 文本记忆 / 知识库 / LLM 源 / 变更追踪。 diff --git a/internal/sdk/kernel.go b/internal/sdk/kernel.go index 58f0e99a..ac78ff25 100644 --- a/internal/sdk/kernel.go +++ b/internal/sdk/kernel.go @@ -1,6 +1,6 @@ package sdk -import pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" +import pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" // KernelControlAPI 是内核重启/关机通道(转发公开 SDK 的同名接口)。 // diff --git a/internal/sdk/knowledge.go b/internal/sdk/knowledge.go index 5f70dde3..ea73f203 100644 --- a/internal/sdk/knowledge.go +++ b/internal/sdk/knowledge.go @@ -2,7 +2,7 @@ package sdk import ( "github.com/JianFeeeee/HologramAgent/internal/knowledge" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // KnowledgeAPI 是内置插件使用的全量知识库接口。 diff --git a/internal/sdk/llm.go b/internal/sdk/llm.go index 2a22bfd3..ade4994b 100644 --- a/internal/sdk/llm.go +++ b/internal/sdk/llm.go @@ -3,7 +3,7 @@ package sdk import ( "context" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // LLMAPI 是内置插件使用的全量 LLM Provider 接口。 diff --git a/internal/sdk/memory.go b/internal/sdk/memory.go index 31152fa2..a9942f4f 100644 --- a/internal/sdk/memory.go +++ b/internal/sdk/memory.go @@ -3,7 +3,7 @@ package sdk import ( "time" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // MemoryBlockView 是块的最小只读视图(供星图轮询端点)。 diff --git a/internal/sdk/plugin.go b/internal/sdk/plugin.go index 7020b925..19f25baa 100644 --- a/internal/sdk/plugin.go +++ b/internal/sdk/plugin.go @@ -6,7 +6,7 @@ import ( agentIO "github.com/JianFeeeee/HologramAgent/internal/agent/io" "github.com/JianFeeeee/HologramAgent/internal/events" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // SDKVersion 是对外 SDK 版本号,与核心 meta.Version 保持一致。 diff --git a/internal/sdk/proxy.go b/internal/sdk/proxy.go index 4d7925e2..665f42c3 100644 --- a/internal/sdk/proxy.go +++ b/internal/sdk/proxy.go @@ -14,7 +14,7 @@ import ( "strings" "sync" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // ProxyDef 是一条反代声明(见 pubsdk.ProxyDef 的完整文档,含「单一入口原则」)。 diff --git a/internal/sdk/rawfiles_impl.go b/internal/sdk/rawfiles_impl.go index b55f283b..a0f65a14 100644 --- a/internal/sdk/rawfiles_impl.go +++ b/internal/sdk/rawfiles_impl.go @@ -28,7 +28,7 @@ import ( "sort" "strings" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // RawFilesDirName 是包内资源目录名(与 hmapdev 的 RawFilesPrefix 一致)。 diff --git a/internal/sdk/secrets_impl.go b/internal/sdk/secrets_impl.go index d29fc9f4..5fca6138 100644 --- a/internal/sdk/secrets_impl.go +++ b/internal/sdk/secrets_impl.go @@ -22,7 +22,7 @@ import ( "fmt" internalSecurity "github.com/JianFeeeee/HologramAgent/internal/security" - pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" + pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" ) // secretsImpl 实现 pubsdk.SecretsAPI。 diff --git a/internal/sdk/settings.go b/internal/sdk/settings.go index 41d793a0..77e16875 100644 --- a/internal/sdk/settings.go +++ b/internal/sdk/settings.go @@ -1,6 +1,6 @@ package sdk -import pubsdk "github.com/JianFeeeee/homeagentsdk/sdk" +import pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk" // SettingsAPI 是内置插件使用的全量配置接口。 type SettingsAPI interface { diff --git a/providers/chineseclip/image.go b/providers/chineseclip/image.go index 4030d59a..fd5a85aa 100644 --- a/providers/chineseclip/image.go +++ b/providers/chineseclip/image.go @@ -6,6 +6,17 @@ import ( "image" // 契约要求 provider 自行解码 Data,所以这里注册常见图像格式。 + // + // ★ webp 必须注册(2026-10-23 实测):线上 551 个图像块里有 4 个是 + // `image/webp`(由 see_image 抓取的第三方图片),它们**永远嵌不进去** —— + // 启动时向量迁移报「失败=4」,但错误被 continue 吞掉、没有任何日志, + // 只看到数字对不上。根因就是这里少了 webp 注册: + // + // image.Decode(...) → "image: unknown format" + // + // Go 标准库不含 webp 解码器(那是 x/image 的子包),所以这是新增依赖的 + // 唯一理由。x/image 是纯 Go、无 cgo,不改变二进制形态。 + _ "golang.org/x/image/webp" _ "image/gif" _ "image/jpeg" _ "image/png" diff --git a/providers/chineseclip/webp_test.go b/providers/chineseclip/webp_test.go new file mode 100644 index 00000000..a5972e9d --- /dev/null +++ b/providers/chineseclip/webp_test.go @@ -0,0 +1,97 @@ +package chineseclip + +// webp 解码支持与「失败必须可观测」的判据。 +// +// ## 为什么这两条要放在这里 +// +// 2026-10-23 线上排查:启动日志只有一行 +// +// [media] 向量迁移完成: 成功=0 失败=4 总计=4 +// +// 没有任何信息说明为什么失败。反查数据库才发现那 4 个块的 mime 是 +// `image/webp`,而本 provider 只注册了 gif/jpeg/png 三个解码器 ⇒ +// `image.Decode` 报 "unknown format" ⇒ 它们**永远**拿不到向量, +// 语义检索也永远搜不到它们。 +// +// 两个独立缺陷: +// 1. 功能缺口:webp 不可解码 +// 2. 可观测性缺口:失败被 `continue` 吞掉,只有计数没有原因 +// +// 判据分开钉住,避免以后只修其中一个。 + +import ( + "bytes" + "image" + "image/color" + "image/png" + "testing" +) + +// webpBytes 是一个最小的合法 webp 文件(1×1 白色,RIFF/WEBP/VP8L)。 +// +// 手写而不依赖测试夹具:夹具文件容易被误删,而"能解码 webp"这件事 +// 必须一直成立 —— 线上确实存在 webp 记忆块。 +var webpBytes = []byte{ + // 由 ffmpeg 生成的真实 2×2 白色 webp(44 字节,VP8 有损编码)。 + // 手写字节序列容易构造出不合法容器 —— 必须用真实编码器产物。 + 0x52, 0x49, 0x46, 0x46, 0x24, 0x00, 0x00, 0x00, 0x57, 0x45, 0x42, 0x50, + 0x56, 0x50, 0x38, 0x20, 0x18, 0x00, 0x00, 0x00, 0x30, 0x01, 0x00, 0x9d, + 0x01, 0x2a, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x34, 0x25, 0xa4, 0x00, + 0x03, 0x70, 0x00, 0xfe, 0xfb, 0x94, 0x00, 0x00, +} + +// ① webp 必须能被解码(否则 memory_blocks 里的 webp 块永远无向量)。 +// +// 变异:注释掉 image.go 里的 `_ "golang.org/x/image/webp"` ⇒ 红。 +func TestWebpIsDecodable(t *testing.T) { + _, format, err := image.Decode(bytes.NewReader(webpBytes)) + if err != nil { + t.Fatalf("webp 解码失败: %v —— image.go 里缺少 _ \"golang.org/x/image/webp\""+ + "(线上 4 个 webp 记忆块因此永远拿不到向量)", err) + } + if format != "webp" { + t.Fatalf("格式识别错误: got %q want \"webp\"", format) + } +} + +// ② webp 必须能走完整的预处理链路(不只是解码,还要变成 NCHW 张量)。 +// +// 只验解码不够:预处理里有缩放/归一化,任何一步对 webp 不适用都算没支持。 +func TestWebpPreprocessProducesTensor(t *testing.T) { + const size = 32 + mean := []float64{0.48145466, 0.4578275, 0.40821073} + std := []float64{0.26862954, 0.26130258, 0.27577711} + + tensor, err := preprocessImage(webpBytes, size, mean, std) + if err != nil { + t.Fatalf("webp 预处理失败: %v", err) + } + if want := 3 * size * size; len(tensor) != want { + t.Fatalf("张量长度 %d,期望 %d(3×%d×%d)", len(tensor), want, size, size) + } + // 1×1 白色图放大后应接近 (1-mean)/std 的白点值;只验非全零, + // 具体像素值由 jpeg/png 的测试覆盖(同一套代码路径)。 + nonZero := false + for _, v := range tensor { + if v != 0 { + nonZero = true + break + } + } + if !nonZero { + t.Fatal("张量全为零 —— 预处理没有真正读到像素") + } +} + +// ③ png 仍必须可用(防止注册表改动把其它格式弄坏)。 +func TestPngStillDecodable(t *testing.T) { + img := image.NewRGBA(image.Rect(0, 0, 2, 2)) + img.Set(0, 0, color.RGBA{255, 255, 255, 255}) + var buf bytes.Buffer + if err := png.Encode(&buf, img); err != nil { + t.Fatalf("构造 png 失败: %v", err) + } + if _, format, err := image.Decode(&buf); err != nil || format != "png" { + t.Fatalf("png 解码异常: format=%q err=%v", format, err) + } +} diff --git a/third_party/homeagent-sdk/go.mod b/third_party/homeagent-sdk/go.mod index 9db0ff78..128b4cf7 100644 --- a/third_party/homeagent-sdk/go.mod +++ b/third_party/homeagent-sdk/go.mod @@ -1,3 +1,3 @@ -module github.com/JianFeeeee/homeagentsdk +module github.com/JianFeeeee/hologramagentsdk go 1.21.0 diff --git a/third_party/homeagent-sdk/sdk/lua/sdk.lua b/third_party/homeagent-sdk/sdk/lua/sdk.lua index 6167dc61..8042f463 100644 --- a/third_party/homeagent-sdk/sdk/lua/sdk.lua +++ b/third_party/homeagent-sdk/sdk/lua/sdk.lua @@ -1,5 +1,5 @@ --- HomeAgent Lua Plugin SDK --- Interface contract between Lua plugins and HomeAgent kernel. +-- HologramAgent Lua Plugin SDK +-- Interface contract between Lua plugins and HologramAgent kernel. -- !impl functions are replaced by Go implementations at runtime. -- Standalone/debug: pure Lua mock implementations are used. -- Usage: local sdk = require("sdk") diff --git a/third_party/homeagent-sdk/sdk/plugin.go b/third_party/homeagent-sdk/sdk/plugin.go index 00856178..e2919ef1 100644 --- a/third_party/homeagent-sdk/sdk/plugin.go +++ b/third_party/homeagent-sdk/sdk/plugin.go @@ -3,7 +3,7 @@ package sdk import ( "sync" - "github.com/JianFeeeee/homeagentsdk/meta" + "github.com/JianFeeeee/hologramagentsdk/meta" ) // SDKVersion 是对外暴露的 SDK 版本号。 diff --git a/third_party/homeagent-sdk/sdk/proxy.go b/third_party/homeagent-sdk/sdk/proxy.go index 9372c970..2eb467b9 100644 --- a/third_party/homeagent-sdk/sdk/proxy.go +++ b/third_party/homeagent-sdk/sdk/proxy.go @@ -6,20 +6,20 @@ import ( "strings" ) -// 反向代理声明:插件告诉 HomeAgent「我起了个 HTTP 服务,请把它反代出去」。 +// 反向代理声明:插件告诉 HologramAgent「我起了个 HTTP 服务,请把它反代出去」。 // // 为什么需要:插件自带 Web UI / HTTP API 时,监听地址在插件自己的配置里 // (如 127.0.0.1:12100),外部无从得知;而 webui 的对外端口通常只有一个 // (默认 :8080,且常经 frp 单端口隧道穿透)。没有声明机制时,用户只能 // 「知道端口 + 自己配转发」,插件换端口就失效。 // -// 设计取舍——**声明式而非注册式**:声明写在 plugin.json 里,由 HomeAgent +// 设计取舍——**声明式而非注册式**:声明写在 plugin.json 里,由 HologramAgent // 在加载插件时读取聚合,而不是让插件在运行期调 API 注册。理由: // 1. 静态可发现:未启动/已崩溃的插件,其服务声明依然可见(可给出准确报错 // 「插件 X 声明了 ui 但目标 127.0.0.1:12100 不可达」,而不是静默 404); // 2. 可版本化:声明随插件包一起分发、可 diff、可审计; -// 3. 旧内核无害:manifest 解析忽略未知字段,未支持该能力的 HomeAgent 读旧 -// 插件、或旧 HomeAgent 读新插件都不会报错。 +// 3. 旧内核无害:manifest 解析忽略未知字段,未支持该能力的 HologramAgent 读旧 +// 插件、或旧 HologramAgent 读新插件都不会报错。 // // 与 ToolDef / ChannelDef / ConfigDef 同族:SDK 定义声明契约,内核实现行为。 // 声明方式与其它能力一致 —— 在 Start() 里调 RegisterProxy(name, def), @@ -64,7 +64,7 @@ import ( type ProxyDef struct { // Name 是同一插件内多条声明的唯一标识(如 "ui"、"api")。 // 运行期由 RegisterProxy 的第一个参数填入;声明式由 plugin.json 的 - // name 键填入。省略时由 HomeAgent 兜底为 "service"。 + // name 键填入。省略时由 HologramAgent 兜底为 "service"。 Name string `json:"name,omitempty"` // Host 是**子域名标签**(不含基域名),如 "huawei" 对应 huawei.<基域名>。 // @@ -72,12 +72,12 @@ type ProxyDef struct { // (DNS label 规则)。省略时默认取插件名(下划线转连字符,因为下划线 // 不是合法 DNS label 字符)。 // - // 冲突处理:两个插件声明同一 Host 时,HomeAgent 不做「后者覆盖前者」—— + // 冲突处理:两个插件声明同一 Host 时,HologramAgent 不做「后者覆盖前者」—— // 那样会让先声明者静默消失。冲突条目被拒绝并在反代表里记录原因。 Host string `json:"host,omitempty"` // Target 是上游地址,形如 "127.0.0.1:12100" 或 "http://127.0.0.1:12100"。 - // 可带路径前缀(如 "127.0.0.1:3000/base"),HomeAgent 转发时保留该前缀。 + // 可带路径前缀(如 "127.0.0.1:3000/base"),HologramAgent 转发时保留该前缀。 // // 端口由插件自己填它**实际监听**的地址,避免「声明与实际漂移」。 Target string `json:"target"` @@ -135,7 +135,7 @@ type ProxyDef struct { // // 为什么做成可声明项:设备网关(remotedevice)这类服务的调用方是**设备**, // 它们不可能持有浏览器会话 cookie,而服务自身已有接入令牌(如 ws_token)。 - // 强制走 HomeAgent 门户鉴权会把这类链路挡死;反过来,插件自带的 UI 若 + // 强制走 HologramAgent 门户鉴权会把这类链路挡死;反过来,插件自带的 UI 若 // 声明 none,就等于把管理界面裸露给任何能访问该端口的人。 // 因此必须由插件**逐条**声明,而不是全局一刀切。 Auth string `json:"auth,omitempty"` @@ -198,7 +198,7 @@ func EffectiveProxyAuth(auth string) string { // ValidProxyHostLabel 校验子域名标签是否合法(DNS label 规则)。 // -// 独立成导出函数:插件作者在写声明时、HomeAgent 在加载时、工具链在打包时 +// 独立成导出函数:插件作者在写声明时、HologramAgent 在加载时、工具链在打包时 // 都要用同一套规则判定,避免三处各写一份而互相不一致。 func ValidProxyHostLabel(label string) bool { if label == "" || len(label) > 63 { @@ -246,7 +246,7 @@ func NormalizeProxyHost(pluginName string) string { // ValidateProxyDef 校验一条反代声明,返回人类可读的错误说明(合法时为空)。 // -// 为什么要在 SDK 里做校验:HomeAgent 加载插件时必须能明确拒绝坏声明并说明 +// 为什么要在 SDK 里做校验:HologramAgent 加载插件时必须能明确拒绝坏声明并说明 // 原因(而不是静默忽略导致用户以为配好了);插件作者也需要在本地就能查出 // 拼错的 Target/Host。同一套规则两端共用。 func ValidateProxyDef(d ProxyDef) string { @@ -338,7 +338,7 @@ func (s *PluginSDK) SetProxyRegistrar(r ProxyRegistrar) { s.apiMu.Unlock() } -// RegisterProxy 声明一个需要 HomeAgent 反代出去的服务。 +// RegisterProxy 声明一个需要 HologramAgent 反代出去的服务。 // // 与 RegisterTool / RegisterInputChannel / RegisterOutputChannel 同一风格: // 显式给名字 + 声明体。名字用于展示、日志与冲突提示(不参与路由 —— 路由键是 diff --git a/third_party/homeagent-sdk/sdk/proxy_test.go b/third_party/homeagent-sdk/sdk/proxy_test.go index f86bfe59..db978f60 100644 --- a/third_party/homeagent-sdk/sdk/proxy_test.go +++ b/third_party/homeagent-sdk/sdk/proxy_test.go @@ -6,25 +6,8 @@ import ( "testing" ) -// 存量 plugin.json 里写的是旧值 "homeagent"(本机实测 huawei_smarthome)。 -// 改名后必须**继续接受并归一化**它 —— 否则那些插件在加载时被判为非法声明, -// 反代直接不生效,症状是"插件好好的但页面打不开",且没有任何报错指向改名。 -func TestProxyAuthLegacyValueStillAccepted(t *testing.T) { - if !ValidProxyAuth(ProxyAuthAgentLegacy) { - t.Fatalf("旧值 %q 必须仍被接受", ProxyAuthAgentLegacy) - } - if ProxyAuthAgentLegacy == ProxyAuthAgent { - t.Fatal("旧值应与新值不同,否则本判据测不到东西") - } - // ★ 归一化是最关键的一步:下游一律只可能拿到新值, - // 否则每个判断点都要写两遍比较,漏一处就是鉴权绕过。 - if got := EffectiveProxyAuth(ProxyAuthAgentLegacy); got != ProxyAuthAgent { - t.Fatalf("旧值应归一化为 %q,实际 %q", ProxyAuthAgent, got) - } -} - -func TestProxyAuthDefaultsToHomeAgent(t *testing.T) { - // 空串必须归一化为「HomeAgent 统一保护」——这是安全默认。 +func TestProxyAuthDefaultsToHologramAgent(t *testing.T) { + // 空串必须归一化为「HologramAgent 统一保护」——这是安全默认。 // 若哪天有人把默认改成 none,这条会立刻红。 if got := EffectiveProxyAuth(""); got != ProxyAuthAgent { t.Fatalf("空 auth 应归一化为 %q,实际 %q", ProxyAuthAgent, got) @@ -44,6 +27,27 @@ func TestProxyAuthDefaultsToHomeAgent(t *testing.T) { } } +// 存量 plugin.json 里写的是旧值 "homeagent"(本机实测 huawei_smarthome)。 +// 改名后必须**继续接受并归一化**它 —— 否则那些插件在加载时被判为非法声明, +// 反代直接不生效,症状是"插件好好的但页面打不开",且没有任何报错指向改名。 +func TestProxyAuthLegacyValueStillAccepted(t *testing.T) { + if !ValidProxyAuth(ProxyAuthAgentLegacy) { + t.Fatalf("旧值 %q 必须仍被接受", ProxyAuthAgentLegacy) + } + if ProxyAuthAgentLegacy == ProxyAuthAgent { + t.Fatal("旧值应与新值不同,否则本判据测不到东西") + } + // ★ 归一化是最关键的一步:下游一律只可能拿到新值, + // 否则每个判断点都要写两遍比较,漏一处就是鉴权绕过。 + if got := EffectiveProxyAuth(ProxyAuthAgentLegacy); got != ProxyAuthAgent { + t.Fatalf("旧值应归一化为 %q,实际 %q", ProxyAuthAgent, got) + } + // 存量 plugin.json 的字面量必须能过校验(这是真实数据,不是假设)。 + if !ValidProxyAuth("homeagent") { + t.Fatal(`存量 plugin.json 里的 "auth": "homeagent" 必须仍被接受`) + } +} + func TestValidProxyHostLabel(t *testing.T) { legit := []string{"huawei", "a", "a-b", "abc123", "0", "x" + string(make([]byte, 0)) + "yz"} for _, s := range legit {