feat: complete P0/P1/P2 — WebUI SPA, OpenClaw sidecar+simulator, healthcheck auto-sched+perf

P0: WebUI重构
- 完整 SPA 仪表盘 (7标签页), //go:embed dashboard.html
P1: OpenClaw兼容 (三通道: SKILL.md / sidecar / simulator)
- Node.js 模拟进程统一加载任意 OpenClaw 插件
- JSON-RPC 2.0 over stdio 协议, go:embed 内嵌
P2: Healthcheck 优化
- 定时自动执行 (startAutoCheck, 30min)
- healthcheck_perf 性能监控工具

其他: agentcli/cmd 插件, integration_test, status.go,
      test_deepseek 清理, 多项 bug 修复
This commit is contained in:
root
2026-07-04 12:51:32 +08:00
parent 77e12f7329
commit fab58e709a
30 changed files with 4956 additions and 578 deletions

View File

@ -34,7 +34,7 @@ func newTestHandler(t *testing.T) (*Handler, *supervisor.Daemon) {
sup := supervisor.New(cfg)
sup.Start()
return NewHandler(sup, nil, nil, nil, cfg, nil, nil, nil, nil, nil, nil, events.NewBus()), sup
return NewHandler(sup, nil, nil, nil, cfg, nil, nil, nil, nil, nil, nil, events.NewBus(), nil), sup
}
func TestHandleStatus(t *testing.T) {
@ -138,7 +138,7 @@ func TestHandleKnowledgeSearch(t *testing.T) {
sup.Start()
defer sup.Shutdown()
h := NewHandler(sup, nil, nil, nil, cfg, nil, nil, ks, nil, nil, nil, events.NewBus())
h := NewHandler(sup, nil, nil, nil, cfg, nil, nil, ks, nil, nil, nil, events.NewBus(), nil)
req := httptest.NewRequest(http.MethodGet, "/api/v1/knowledge?q=test", nil)
w := httptest.NewRecorder()
@ -170,7 +170,7 @@ func TestHandleKnowledgeCreate(t *testing.T) {
sup.Start()
defer sup.Shutdown()
h := NewHandler(sup, nil, nil, nil, cfg, nil, nil, ks, nil, nil, nil, events.NewBus())
h := NewHandler(sup, nil, nil, nil, cfg, nil, nil, ks, nil, nil, nil, events.NewBus(), nil)
body := `{"name":"new_doc","content":"fresh content"}`
req := httptest.NewRequest(http.MethodPost, "/api/v1/knowledge", strings.NewReader(body))
@ -235,7 +235,7 @@ func TestHandleTrackerStats(t *testing.T) {
sup.Start()
defer sup.Shutdown()
h := NewHandler(sup, nil, nil, nil, cfg, nil, nil, nil, tr, nil, nil, events.NewBus())
h := NewHandler(sup, nil, nil, nil, cfg, nil, nil, nil, tr, nil, nil, events.NewBus(), nil)
req := httptest.NewRequest(http.MethodGet, "/api/v1/tracker", nil)
w := httptest.NewRecorder()
@ -415,7 +415,7 @@ func TestSettingsAPIFlow(t *testing.T) {
defer sup.Shutdown()
pluginReg := plugin.NewRegistry()
h := NewHandler(sup, nil, nil, nil, &types.Config{}, nil, nil, nil, nil, cfgReg, pluginReg, events.NewBus())
h := NewHandler(sup, nil, nil, nil, &types.Config{}, nil, nil, nil, nil, cfgReg, pluginReg, events.NewBus(), nil)
t.Run("GET_settings_lists_keys_and_plugins", func(t *testing.T) {
req := httptest.NewRequest(http.MethodGet, "/api/v1/settings", nil)
@ -522,7 +522,7 @@ func TestSettingsAPIFlow(t *testing.T) {
})
t.Run("settings_not_available_without_registry", func(t *testing.T) {
h2 := NewHandler(sup, nil, nil, nil, &types.Config{}, nil, nil, nil, nil, nil, nil, events.NewBus())
h2 := NewHandler(sup, nil, nil, nil, &types.Config{}, nil, nil, nil, nil, nil, nil, events.NewBus(), nil)
req := httptest.NewRequest(http.MethodGet, "/api/v1/settings", nil)
w := httptest.NewRecorder()
h2.handleSettings(w, req)
@ -548,7 +548,7 @@ func TestSettingsWithPluginRegistry(t *testing.T) {
defer sup.Shutdown()
pluginReg := plugin.NewRegistry()
h := NewHandler(sup, nil, nil, nil, &types.Config{}, nil, nil, nil, nil, cfgReg, pluginReg, events.NewBus())
h := NewHandler(sup, nil, nil, nil, &types.Config{}, nil, nil, nil, nil, cfgReg, pluginReg, events.NewBus(), nil)
req := httptest.NewRequest(http.MethodGet, "/api/v1/settings", nil)
w := httptest.NewRecorder()
@ -622,7 +622,7 @@ func TestHandleCompletionsEndToEnd(t *testing.T) {
sup.Start()
defer sup.Shutdown()
h := NewHandler(sup, nil, nil, nil, &types.Config{}, iom, nil, nil, nil, nil, nil, events.NewBus())
h := NewHandler(sup, nil, nil, nil, &types.Config{}, iom, nil, nil, nil, nil, nil, events.NewBus(), nil)
t.Run("POST_chat_completions_returns_echo", func(t *testing.T) {
body := `{"model":"test","messages":[{"role":"user","content":"你好"}]}`
@ -655,7 +655,7 @@ func TestHandleCompletionsEndToEnd(t *testing.T) {
})
t.Run("POST_chat_completions_no_iom_returns_503", func(t *testing.T) {
h2 := NewHandler(sup, nil, nil, nil, &types.Config{}, nil, nil, nil, nil, nil, nil, events.NewBus())
h2 := NewHandler(sup, nil, nil, nil, &types.Config{}, nil, nil, nil, nil, nil, nil, events.NewBus(), nil)
body := `{"messages":[{"role":"user","content":"hi"}]}`
req := httptest.NewRequest(http.MethodPost, "/v1/chat/completions", strings.NewReader(body))
req.Header.Set("Content-Type", "application/json")