feat(ui): M4 — agent activity, knowledge search, audit, correlation grouping
Some checks failed
ci / build-test (push) Has been cancelled
ci / docker-build (push) Has been cancelled

Add three new pages completing the control-room web UI:
- Agent activity: polls /agent-activity every 5s, filterable by type/agent
- Knowledge search: FTS over /knowledge/search with snippet + entity links
- Audit trail: browseable audit log with actor/action/entity filters

Enhanced live events page with correlation-id clustering (Groups toggle).
Added fetchAgentActivity/searchKnowledge/fetchAudit to the API client.
11 nav items now cover all planned control-room views.
This commit is contained in:
2026-07-08 17:02:09 +02:00
parent cff05c0768
commit 2908b0a377
162 changed files with 7857 additions and 553 deletions

View File

@@ -1835,10 +1835,6 @@ func (s *Server) QueryMetrics(ctx context.Context, req gen.QueryMetricsRequestOb
if req.Params.EntityId == nil || *req.Params.EntityId == "" {
return nil, fmt.Errorf("%w: entity_id is required", domain.ErrInvalidInput)
}
if req.Params.Metric == nil || len(*req.Params.Metric) == 0 {
return nil, fmt.Errorf("%w: metric is required", domain.ErrInvalidInput)
}
entityID, err := s.resolveEntityID(ctx, *req.Params.EntityId)
if err != nil {
return nil, err
@@ -1853,8 +1849,33 @@ func (s *Server) QueryMetrics(ctx context.Context, req gen.QueryMetricsRequestOb
to = *req.Params.To
}
var metricNames []string
if req.Params.Metric != nil && len(*req.Params.Metric) > 0 {
metricNames = *req.Params.Metric
} else {
// metric omitted: report every metric recorded for this entity in range.
rows, err := s.pool.Query(ctx, `
SELECT DISTINCT metric FROM metric_samples
WHERE entity_id = $1 AND ts >= $2 AND ts <= $3
ORDER BY metric`, entityID, from, to)
if err != nil {
return nil, err
}
for rows.Next() {
var name string
if err := rows.Scan(&name); err != nil {
rows.Close()
return nil, err
}
metricNames = append(metricNames, name)
}
if err := rows.Err(); err != nil {
return nil, err
}
}
items := []gen.MetricSeries{}
for _, metricName := range *req.Params.Metric {
for _, metricName := range metricNames {
series := gen.MetricSeries{
EntityId: entityID.String(),
Metric: metricName,
@@ -1953,14 +1974,14 @@ func (s *Server) GetTrends(ctx context.Context, req gen.GetTrendsRequestObject)
f, _ := slopeNum.Float64Value()
t.Slope = float32Ptr(float32(f.Float64))
if f.Float64 > 0.01 {
t.Direction = gen.Improving
t.Direction = gen.TrendDirectionImproving
} else if f.Float64 < -0.01 {
t.Direction = gen.Degrading
t.Direction = gen.TrendDirectionDegrading
} else {
t.Direction = gen.Stable
t.Direction = gen.TrendDirectionStable
}
} else {
t.Direction = gen.Unknown
t.Direction = gen.TrendDirectionUnknown
}
items = append(items, t)
}