Files
HomeAgent/internal/sdk/status.go
JianFeeeee 5aaae93367 feat(healthcheck): 内核状态快照报出内核版本号与 ONNX 模型启用状态
healthcheck_kernel 此前没有任何「ONNX 模型是否在用」的信息,只报「向量可用/不可用」,
分不清「统一多模态空间已加载」与「退回到词嵌入/TF-IDF 路径」;人格卡要求
「版本以运行时快照为准」,也缺一个可查字段(build.version 早就在,但没人知道)。

- KernelStatus 新增 onnx 段:enabled / provider / dim / fingerprint / modalities / reason。
  判据取 Loaded()(provider 真正打开且元数据合法),**不是**「配置里写了 provider」
  —— 后者在模型缺失 / 运行时缺失时也为真,报出去就是假绿。
- 未启用时 reason 给**具体原因**:未配置(说明会走回退路径)/ 打开失败的具体错误。
  homed 把「配置的 provider 名」与「打开失败原因」透传给 Agent,仅供状态报告。
- ProviderAdapter 新增 Modalities()(可选能力,按接口断言取用,不改公开契约)。
- healthcheck_kernel 的工具描述同步说明它回答这两件事。

**顺带修一个真实 panic**:collectKernelStatus 的 knowledge 是**接口**参数,
(*knowledge.Store)(nil) 塞进接口后 `ks != nil` 仍为真 → 调 List() 直接 panic,
而 healthcheck_kernel 正是走这条路径(panic 发生在工具 goroutine 里)。
GetKernelStatus 改为先按具体指针判空、再赋给接口;并加刻画测试钉住这个成因
(一旦不再 panic 说明参数形状已变,守卫与该测试应同步删除)。

验证:单测 4 例(已启用 / 打开失败 / 未配置 / 未加载)+ 刻画测试;
隔离实例 E2E 7/7:正例 provider=chineseclip → enabled=true、dim=512、模态 2;
反例 provider=nonexistent → enabled=false 且 reason 含具体错误与 provider 名,
真实对话仍通。
2026-09-12 14:56:25 +08:00

144 lines
4.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package sdk
// StatusAPI provides a snapshot of the kernel runtime status.
type StatusAPI interface {
GetKernelStatus() *KernelStatus
}
// KernelStatus is the aggregated runtime snapshot of all kernel subsystems.
type KernelStatus struct {
Uptime string `json:"uptime"`
StartTime string `json:"start_time"`
// Build 是内核自身的版本与构建信息。
//
// 为何需要:此前 WebUI 展示的“版本”取自 `sdk.SDKVersion`,那是 **SDK 仓
// meta.Version 的硬编码值**;而 `-ldflags` 注入的是内核的
// `internal/meta.Version`——两条链完全不相交。于是:
// - 构建时注入的真实版本号、commit、构建时间全部丢失
// - 两仲版本号碰巧相等时看不出问题,一旦不等就报错版本;
// - 无法回答“现网跑的是哪个 commit 构出来的”。
Build BuildStatus `json:"build"`
AgentID string `json:"agent_id"`
Plugins []PluginInfo `json:"plugins"`
Tools []ToolDef `json:"tools"`
Channels []ChannelInfo `json:"channels"`
Memory MemoryStatus `json:"memory"`
Knowledge KnowledgeStatus `json:"knowledge"`
Documents DocumentStatus `json:"documents"`
TextMemory TextMemoryStatus `json:"text_memory"`
Social SocialStatus `json:"social"`
LLM LLMStatus `json:"llm"`
Context ContextStatus `json:"context"`
Runtime RuntimeStatus `json:"runtime"`
// ONNX 报告统一多模态向量空间ONNX 模型)是否**真的在用**。
//
// 为何单列:内核的向量能力是三层降级(统一多模态空间 → 词嵌入 → TF-IDF
// 只报「向量可用/不可用」分不清「ONNX 模型已加载」与「退回了纯文本路径」。
// 模型缺失 / 运行时缺失 / provider 打开失败时这里是 enabled=false + reason。
ONNX ONNXStatus `json:"onnx"`
Tracker TrackerStatus `json:"tracker"`
}
// ONNXStatus 是统一多模态向量空间ONNX 模型)的启用状态与身份。
type ONNXStatus struct {
// Enabled 是 provider 真正打开且元数据合法(不是「配置里写了 provider」
Enabled bool `json:"enabled"`
// Provider 是配置指定的 provider 名(如 chineseclip / qwen3vl / http
Provider string `json:"provider,omitempty"`
Dim int `json:"dim,omitempty"`
Fingerprint string `json:"fingerprint,omitempty"`
Modalities []string `json:"modalities,omitempty"`
// Reason 是未启用时的原因(未配置 / 打开失败的具体错误 / 其它)。
Reason string `json:"reason,omitempty"`
}
type PluginInfo struct {
Name string `json:"name"`
Loaded bool `json:"loaded"`
}
type ChannelInfo struct {
Name string `json:"name"`
Type string `json:"type"`
Ready bool `json:"ready"`
}
type MemoryStatus struct {
Available bool `json:"available"`
EntityCount int `json:"entity_count"`
RelationCount int `json:"relation_count"`
EntityTypes int `json:"entity_types"`
}
type KnowledgeStatus struct {
Available bool `json:"available"`
ItemCount int `json:"item_count"`
Items []string `json:"items,omitempty"`
}
type DocumentStatus struct {
Available bool `json:"available"`
DocCount int `json:"doc_count"`
VectorCount int `json:"vector_count"`
}
type TextMemoryStatus struct {
Available bool `json:"available"`
FileCount int `json:"file_count"`
}
type SocialStatus struct {
Available bool `json:"available"`
PersonCount int `json:"person_count"`
}
type LLMStatus struct {
Available bool `json:"available"`
Provider string `json:"provider,omitempty"`
Sources int `json:"sources,omitempty"`
}
type ContextStatus struct {
EventCount int `json:"event_count,omitempty"`
}
type RuntimeStatus struct {
Goroutines int `json:"goroutines"`
MemoryMB int64 `json:"memory_mb"`
GoVersion string `json:"go_version"`
}
// BuildStatus 是内核二进制的构建身份,全部来自 `internal/meta`
// (由 -ldflags 在构建时注入,未注入时为源码默认值/unknown
type BuildStatus struct {
// Version 是内核语义版本(如 1.0.0)。
Version string `json:"version"`
// Commit 是构建时的 Git 短 hash未注入为 unknown。
Commit string `json:"commit"`
// BuildTime 是 UTC 构建时间;未注入为 unknown。
BuildTime string `json:"build_time"`
// SDKCompatible 是本内核可兼容的最高 SDK 版本。
// 插件用旧 SDK 编译时靠它判断能不能加载。
SDKCompatible string `json:"sdk_compatible"`
// KernelName 是内核名HomeAgent
KernelName string `json:"kernel_name"`
// SourceURL 是本次构建对应的源码地址。AGPL-3.0 §13 要求:向使用者提供网络
// 服务时,要给他们拿到 Corresponding Source 的机会——WebUI 状态页会把它渲染成
// 可见链接,所以**修改后对外部署的分支必须把这个值改指向自己的源码仓库**。
SourceURL string `json:"source_url,omitempty"`
}
type TrackerStatus struct {
Available bool `json:"available"`
Dir string `json:"dir,omitempty"`
}