mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-09-21 09:28:14 +00:00
## WebUI 版本链路修复 问题:handler.go:949 报的是 sdk.SDKVersion,那条链最终指向 SDK 仓 meta.Version 的硬编码值,与 -ldflags 注入的内核版本 完全不相交。构建时间、commit hash 全部丢失。 dashboard.html 兜底值是 '0.1.0'——碰巧版本号相等时不显眼, 一旦不等就报错。 修复: - KernelStatus 新增 BuildStatus 字段(Version/Commit/BuildTime/SDKCompatible/KernelName) 取自 internal/meta(-ldflags 注入点),与接口冻结无关(KernelStatus 只在 internal/sdk) - /api/v1/status 改用 meta.Version,另加 sdk_version 字段暴露 SDK 版本 - dashboard.html 概览卡显示 HomeAgent vX.Y.Z + commit/日期/SDK 兼容版本, 去掉 || '0.1.0' 误导性兜底 ## Windows 交叉编译修复 问题:internal/plugin/dynamic_proc_windows.go(Part 1 的桩,610e9d0)只定义了 tryLoadProc,但平台中立的 registry.go 还在调 loadProc / closeProcHost——这两个 函数只在 dynamic_proc_unix.go 里。Windows 下整个 homed 从 Part 1 起编译不过。 plan.md §12.5 声称「Windows 只做了交叉编译,无真机验证」——实际是连编译都没通过。 修复:dynamic_proc_unix.go / dynamic_proc_windows.go 合并为平台中立的 dynamic_proc.go(文件内无任何平台专属调用,proc 包内部通过 shmalloc_* / evtfd_* / shmpass_* / procattr_* 各自带构建标签处理差异)。 ## 发布脚本三处回归修复 deploy/packaging/build.sh(从 package/build.sh 移到 deploy/packaging/ 后): 1. PROJECT_ROOT 少一层目录(.. → ../..),产物落进 deploy/build/ 而非根目录 2. initconfig 从未被构建,但 installer.nsi 和 package-linux.sh 都引用它 3. GO 兜底路径指向 /home/jianf/go1.26.5(陈旧硬编码)改为 command -v go 4. electron-builder --config package.json 校验整个文件导致 devDependencies 被判为 unknown property,去掉 --config 让它从 build 键读配置 deploy/packaging/package-linux.sh: 1. build_go() 补上 initconfig 构建步骤 2. GO 兜底路径同步修复 知识库 3 条重写 + 1 条新增: - homeagent_identity:v0.9.0 C ABI → v1.0.0 子进程 - homeagent_architecture:全篇重写为子进程架构(三面通信、Supervisor 台账、 崩溃自愈、权限三道闸) - homeagent_recent_updates:在 v0.9.0 前插入 v1.0.0 主线摘要 - changelog_v1.0.0(新建):6 类缺陷消除、架构、实测、已知限制、迁移指引
220 lines
5.2 KiB
Go
220 lines
5.2 KiB
Go
package core
|
||
|
||
import (
|
||
"fmt"
|
||
"runtime"
|
||
"time"
|
||
|
||
agentIO "gitcode.com/JianFeeeee/HomeAgent/internal/agent/io"
|
||
"gitcode.com/JianFeeeee/HomeAgent/internal/memory"
|
||
"gitcode.com/JianFeeeee/HomeAgent/internal/memory/document"
|
||
"gitcode.com/JianFeeeee/HomeAgent/internal/memory/social"
|
||
"gitcode.com/JianFeeeee/HomeAgent/internal/memory/text"
|
||
"gitcode.com/JianFeeeee/HomeAgent/internal/meta"
|
||
"gitcode.com/JianFeeeee/HomeAgent/internal/plugin"
|
||
sdk "gitcode.com/JianFeeeee/HomeAgent/internal/sdk"
|
||
"gitcode.com/JianFeeeee/HomeAgent/internal/tracker"
|
||
)
|
||
|
||
// StatusProvider 内核状态查询接口。插件通过此接口查看内核运行动态。
|
||
type StatusProvider interface {
|
||
GetKernelStatus() *KernelStatus
|
||
}
|
||
|
||
// 状态 DTO 使用内置 SDK 的中立类型,保证与插件层解耦。
|
||
type KernelStatus = sdk.KernelStatus
|
||
type PluginInfo = sdk.PluginInfo
|
||
type ChannelInfo = sdk.ChannelInfo
|
||
type MemoryStatus = sdk.MemoryStatus
|
||
type KnowledgeStatus = sdk.KnowledgeStatus
|
||
type DocumentStatus = sdk.DocumentStatus
|
||
type TextMemoryStatus = sdk.TextMemoryStatus
|
||
type SocialStatus = sdk.SocialStatus
|
||
type LLMStatus = sdk.LLMStatus
|
||
type ContextStatus = sdk.ContextStatus
|
||
type RuntimeStatus = sdk.RuntimeStatus
|
||
type TrackerStatus = sdk.TrackerStatus
|
||
type BuildStatus = sdk.BuildStatus
|
||
|
||
func channelInfoFromIO(ch agentIO.ChannelInfo) ChannelInfo {
|
||
return ChannelInfo{
|
||
Name: ch.Name,
|
||
Type: fmt.Sprintf("%d", ch.Type),
|
||
Ready: true,
|
||
}
|
||
}
|
||
|
||
// collectKernelStatus 聚合内核各子系统状态快照。
|
||
// 接收所有子系统引用(均为可选——nil 表示不可用),返回统一的状态报告。
|
||
func collectKernelStatus(
|
||
startTime time.Time,
|
||
agentID string,
|
||
providerName string,
|
||
sourceCount int,
|
||
stageHost *StageHost,
|
||
iom *agentIO.IOManager,
|
||
pluginReg *plugin.Registry,
|
||
memDB *memory.GraphDB,
|
||
ks interface{ List() []string },
|
||
docStore *document.Store,
|
||
textMem *text.Memory,
|
||
socialStore *social.SocialStore,
|
||
trk *tracker.Tracker,
|
||
) *KernelStatus {
|
||
status := &KernelStatus{
|
||
Uptime: time.Since(startTime).Round(time.Second).String(),
|
||
StartTime: startTime.Format(time.RFC3339),
|
||
AgentID: agentID,
|
||
// 构建身份取自内核自己的 meta(-ldflags 注入点),
|
||
// 而非 SDK 仓的硬编码版本。
|
||
Build: BuildStatus{
|
||
Version: meta.Version,
|
||
Commit: meta.Commit,
|
||
BuildTime: meta.BuildTime,
|
||
SDKCompatible: meta.SDKCompatibleVersion,
|
||
KernelName: meta.KernelName,
|
||
},
|
||
Runtime: RuntimeStatus{
|
||
Goroutines: runtime.NumGoroutine(),
|
||
GoVersion: runtime.Version(),
|
||
},
|
||
LLM: LLMStatus{
|
||
Available: providerName != "",
|
||
Provider: providerName,
|
||
Sources: sourceCount,
|
||
},
|
||
}
|
||
|
||
// Plugins
|
||
if pluginReg != nil {
|
||
names := pluginReg.List()
|
||
for _, n := range names {
|
||
status.Plugins = append(status.Plugins, PluginInfo{Name: n, Loaded: true})
|
||
}
|
||
}
|
||
|
||
// Tools
|
||
if stageHost != nil {
|
||
status.Tools = stageHost.GetToolDefs()
|
||
}
|
||
|
||
// Channels
|
||
if iom != nil {
|
||
for _, ch := range iom.ListChannels() {
|
||
status.Channels = append(status.Channels, channelInfoFromIO(ch))
|
||
}
|
||
}
|
||
|
||
// Graph memory
|
||
if memDB != nil {
|
||
status.Memory.Available = true
|
||
if info, err := memDB.Introspect(); err == nil {
|
||
if ec, ok := info["entity_count"].(int); ok {
|
||
status.Memory.EntityCount = ec
|
||
}
|
||
if rc, ok := info["relation_count"].(int); ok {
|
||
status.Memory.RelationCount = rc
|
||
}
|
||
if et, ok := info["entity_type_count"].(int); ok {
|
||
status.Memory.EntityTypes = et
|
||
}
|
||
}
|
||
}
|
||
|
||
// Knowledge
|
||
if ks != nil {
|
||
status.Knowledge.Available = true
|
||
status.Knowledge.Items = ks.List()
|
||
status.Knowledge.ItemCount = len(status.Knowledge.Items)
|
||
}
|
||
|
||
// Documents
|
||
if docStore != nil {
|
||
status.Documents.Available = true
|
||
stats := docStore.Stats()
|
||
if dc, ok := stats["doc_count"].(int); ok {
|
||
status.Documents.DocCount = dc
|
||
}
|
||
if vc, ok := stats["vector_count"].(int); ok {
|
||
status.Documents.VectorCount = vc
|
||
}
|
||
}
|
||
|
||
// Text memory
|
||
if textMem != nil {
|
||
status.TextMemory.Available = true
|
||
status.TextMemory.FileCount = textMem.FileCount()
|
||
}
|
||
|
||
// Social
|
||
if socialStore != nil {
|
||
status.Social.Available = true
|
||
if persons, err := socialStore.ListPersons(); err == nil {
|
||
status.Social.PersonCount = len(persons)
|
||
}
|
||
}
|
||
|
||
|
||
// Tracker
|
||
if trk != nil {
|
||
status.Tracker.Available = true
|
||
status.Tracker.Dir = trk.MergeDir()
|
||
}
|
||
|
||
// Memory
|
||
var m runtime.MemStats
|
||
runtime.ReadMemStats(&m)
|
||
status.Runtime.MemoryMB = int64(m.Alloc / 1024 / 1024)
|
||
|
||
return status
|
||
}
|
||
|
||
// GetKernelStatus 返回 Agent 驱动的内核状态快照。
|
||
func (a *Agent) GetKernelStatus() *KernelStatus {
|
||
providerName := ""
|
||
sourceCount := 0
|
||
if a.providerManager != nil {
|
||
sourceCount = len(a.providerManager.List())
|
||
}
|
||
if a.provider != nil {
|
||
providerName = a.provider.Name()
|
||
}
|
||
|
||
var textMem *text.Memory
|
||
if a.textMem != nil {
|
||
textMem = a.textMem
|
||
}
|
||
|
||
var socialStore *social.SocialStore
|
||
if a.social != nil {
|
||
socialStore = a.social
|
||
}
|
||
|
||
|
||
var trk *tracker.Tracker
|
||
if a.tracker != nil {
|
||
trk = a.tracker
|
||
}
|
||
|
||
ks := collectKernelStatus(
|
||
a.startTime,
|
||
string(a.id),
|
||
providerName,
|
||
sourceCount,
|
||
a.stageHost,
|
||
a.io,
|
||
a.pluginReg,
|
||
a.memory,
|
||
a.knowledge,
|
||
a.docStore,
|
||
textMem,
|
||
socialStore,
|
||
trk,
|
||
)
|
||
|
||
return ks
|
||
}
|
||
|
||
var _ StatusProvider = (*Agent)(nil)
|
||
var _ sdk.StatusAPI = (*Agent)(nil)
|