mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-11-01 14:57:38 +00:00
批 1,不含 SDK 仓与目录改名。 - go.mod 第 1 行 module 路径 - 366 个 .go 文件的完整前缀 github.com/JianFeeeee/HomeAgent 机械替换 (857 处,仅完整前缀;展示名/注释里的 HomeAgent 字样留给批 5) - 未改:third_party 目录名、SDK 自身 go.mod module、go.mod replace 目标、 homed/waiter 可执行名、.hmap 后缀
142 lines
4.7 KiB
Go
142 lines
4.7 KiB
Go
// Package kernelmod 是内核模块的**注册表**(用户设计的 core)。
|
||
//
|
||
// ## 用户的设计意图(原话)
|
||
//
|
||
// > 模块应该在 /modelname/ 独立文件夹下,根目录只有 core.go,
|
||
// > core 内有一个注册表注册各个模块,各个模块通过该注册表得知内核有哪些模块,
|
||
// > 从而声明对其他模块的依赖,注意注册表中的模块列表是乱序的,
|
||
// > 只是为了向模块展示内核注册了哪些模块
|
||
//
|
||
// ## 目录形状
|
||
//
|
||
// internal/kernelmod/
|
||
// ├── core.go ← 本文件:注册表(+ 唯一的 import 清单)
|
||
// ├── facilities.go ← 设施名常量(模块间的协议)
|
||
// ├── config/mod.go ← 每个模块一个独立文件夹
|
||
// ├── kernelapi/mod.go
|
||
// ├── lua/mod.go
|
||
// ├── llm/mod.go
|
||
// ├── memory/mod.go
|
||
// ├── supervisor/mod.go
|
||
// ├── tracker/mod.go
|
||
// ├── textmem/mod.go
|
||
// ├── docstore/mod.go
|
||
// ├── knowledge/{migration,store}.go
|
||
// ├── multimodal/mod.go
|
||
// ├── onnx/mod.go
|
||
// ├── stagehost/mod.go
|
||
// └── agent/mod.go
|
||
//
|
||
// ## 职责边界(刻意做窄)
|
||
//
|
||
// 本文件**只做两件事**:
|
||
//
|
||
// · `Register(m)` —— 模块在 init() 里自注册
|
||
// · `Registered()` —— 返回已注册模块(**乱序**,仅供查询"内核有哪些模块")
|
||
//
|
||
// 它**不做**依赖解析/分层/执行 —— 那些是 `internal/kernelboot` 的事。
|
||
// 分开的理由:注册表是"名册",分层器是"调度器"。混在一起会让
|
||
// "只想知道有哪些模块"的人被迫拉进整个调度逻辑。
|
||
//
|
||
// ## ★ 为什么列表是"乱序",以及这为什么是对的
|
||
//
|
||
// 注册顺序取决于 **Go 的 init() 执行顺序**(由 import 图决定,
|
||
// 规范未定义跨包的**具体**顺序)。若把注册顺序当成"可信的启动顺序",
|
||
// 那就是**隐式顺序依赖** —— 正是本设计要消灭的东西(§1 的病 A)。
|
||
//
|
||
// 所以 `Registered()` **刻意不排序**,并明确"顺序无意义":
|
||
//
|
||
// · 模块只能用它回答"内核注册了哪些模块"
|
||
// · **不能**用它推断先后 —— 先后只由 Requires/Provides 决定
|
||
//
|
||
// ★ 分层器(kernelboot.Build)内部会按名字排序以保证**结果可复现**,
|
||
// 那是分层器的实现细节,与"注册表乱序"不矛盾。
|
||
//
|
||
// ## ★ 关于下面那份 import 清单(为什么必须有,且它是**唯一**的一处)
|
||
//
|
||
// Go 要求"包被 import 才会编译进来"。模块各自在 init() 里注册,
|
||
// 但**必须有东西把它们引进来** —— 这就是下面那些空白导入。
|
||
//
|
||
// 为什么不能省(也解释了一个真实的 Go 约束):
|
||
//
|
||
// core.go 想 import lua/ ⇒ core → lua → core(lua 要调 Register)
|
||
// ⇒ **循环导入**,Go 禁止
|
||
//
|
||
// 解法:注册表 API 放在**本包**、模块 import 本包(单向),
|
||
// 而"把它们引进来"的清单只能放在**本包之外** —— 见
|
||
// `internal/kernelmod/all/all.go`(只做 import,无逻辑)。
|
||
//
|
||
// ⇒ 加模块 = **加一个文件夹 + 在 all.go 加一行**(唯一的一处编辑)。
|
||
package kernelmod
|
||
|
||
import (
|
||
"sync"
|
||
|
||
"github.com/JianFeeeee/HologramAgent/internal/kernelboot"
|
||
)
|
||
|
||
var (
|
||
mu sync.Mutex
|
||
list []kernelboot.Module
|
||
seen = map[string]bool{}
|
||
dups []string
|
||
)
|
||
|
||
// Register 由模块在自己的 init() 里调用。
|
||
//
|
||
// 重复注册同名模块会被**记录**(不 panic):panic 发生在 init 阶段,
|
||
// 栈信息对使用者毫无意义(他只想知道哪个模块重名)。由 Registered 报出。
|
||
func Register(m kernelboot.Module) {
|
||
if m == nil {
|
||
return
|
||
}
|
||
mu.Lock()
|
||
defer mu.Unlock()
|
||
name := m.Name()
|
||
if seen[name] {
|
||
dups = append(dups, name)
|
||
return
|
||
}
|
||
seen[name] = true
|
||
list = append(list, m)
|
||
}
|
||
|
||
// Registered 返回全部已注册模块。
|
||
//
|
||
// ★ **顺序无意义**(见包注释):它取决于 init() 执行顺序。
|
||
// 只用它回答"内核注册了哪些模块",**不要**用它推断先后。
|
||
func Registered() []kernelboot.Module {
|
||
mu.Lock()
|
||
defer mu.Unlock()
|
||
out := make([]kernelboot.Module, len(list))
|
||
copy(out, list)
|
||
return out
|
||
}
|
||
|
||
// Duplicates 返回重复注册的模块名(诊断用)。
|
||
func Duplicates() []string {
|
||
mu.Lock()
|
||
defer mu.Unlock()
|
||
out := make([]string, len(dups))
|
||
copy(out, dups)
|
||
return out
|
||
}
|
||
|
||
// Names 返回已注册模块名(诊断用;顺序同 Registered,无意义)。
|
||
func Names() []string {
|
||
mu.Lock()
|
||
defer mu.Unlock()
|
||
out := make([]string, 0, len(list))
|
||
for _, m := range list {
|
||
out = append(out, m.Name())
|
||
}
|
||
return out
|
||
}
|
||
|
||
// IsRegistered 报告某模块是否已注册(模块可用它判断依赖是否存在)。
|
||
func IsRegistered(name string) bool {
|
||
mu.Lock()
|
||
defer mu.Unlock()
|
||
return seen[name]
|
||
}
|