Skip to content

Commit a8b1a0a

Browse files
committed
feat(dashboard): add comprehensive configuration editing UI
- Add EditModal component with support for multiple field types (text, number, boolean, select, multiselect, textarea, json) - Implement full CRUD operations for Models and Endpoints (add, edit, delete) - Add edit functionality for all configuration sections: * Prompt Guard (PII Detection, Jailbreak Detection) * Similarity Cache (Similarity BERT, Semantic Cache) * Intelligent Routing (In-tree/Out-tree Classifiers) * Tools Selection * Observability (Distributed Tracing) * Classification API - Add edit functionality for Categories (system prompt, reasoning settings) - Add edit functionality for Reasoning Families - Add model score management in Categories (add, edit, delete model scores) - Implement dynamic dropdowns populated from configuration: * Reasoning Family selection from configured reasoning families * Preferred Endpoints selection from configured endpoints * Model selection for category model scores - Add complete pricing configuration (currency, prompt/completion costs) - Add complete PII policy configuration (allow/block, 17 PII types) - Visualize all configuration fields (no JSON input required) - Fix docker-compose volume mount to allow config file writes (ro -> rw) - Remove deprecated fields (endpoint models, health_check_path, monitoring dashboard) - Improve UI/UX with better card layouts, icons, and visual feedback Backend changes: - Add POST /api/router/config/update endpoint for configuration updates - Add JSON to YAML conversion for config file writes Frontend changes: - Create reusable EditModal component with field validation - Update ConfigPage with comprehensive edit buttons and handlers - Add CSS styles for edit buttons, model scores, and multiselect fields - Improve endpoint display (separate address, port, weight) This enables full configuration management through the dashboard UI without manual YAML editing. Signed-off-by: bitliu <[email protected]>
1 parent f158057 commit a8b1a0a

File tree

7 files changed

+2810
-417
lines changed

7 files changed

+2810
-417
lines changed

dashboard/backend/main.go

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,83 @@ func configHandler(configPath string) http.HandlerFunc {
5959
}
6060
}
6161

62+
// updateConfigHandler updates the config.yaml file
63+
func updateConfigHandler(configPath string) http.HandlerFunc {
64+
return func(w http.ResponseWriter, r *http.Request) {
65+
// Only allow POST/PUT requests
66+
if r.Method != http.MethodPost && r.Method != http.MethodPut {
67+
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
68+
return
69+
}
70+
71+
// Read the request body
72+
var configData map[string]interface{}
73+
if err := json.NewDecoder(r.Body).Decode(&configData); err != nil {
74+
log.Printf("Error decoding request body: %v", err)
75+
http.Error(w, fmt.Sprintf("Invalid request body: %v", err), http.StatusBadRequest)
76+
return
77+
}
78+
79+
// Convert to YAML
80+
yamlData, err := yaml.Marshal(configData)
81+
if err != nil {
82+
log.Printf("Error marshaling config to YAML: %v", err)
83+
http.Error(w, fmt.Sprintf("Failed to convert config to YAML: %v", err), http.StatusInternalServerError)
84+
return
85+
}
86+
87+
// Write to file
88+
if err := os.WriteFile(configPath, yamlData, 0644); err != nil {
89+
log.Printf("Error writing config file: %v", err)
90+
http.Error(w, fmt.Sprintf("Failed to write config file: %v", err), http.StatusInternalServerError)
91+
return
92+
}
93+
94+
log.Printf("Configuration updated successfully")
95+
w.Header().Set("Content-Type", "application/json")
96+
w.WriteHeader(http.StatusOK)
97+
json.NewEncoder(w).Encode(map[string]string{"status": "success", "message": "Configuration updated successfully"})
98+
}
99+
}
100+
101+
// toolsDBHandler reads and serves the tools_db.json file
102+
func toolsDBHandler(configDir string) http.HandlerFunc {
103+
return func(w http.ResponseWriter, r *http.Request) {
104+
// Only allow GET requests
105+
if r.Method != http.MethodGet {
106+
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
107+
return
108+
}
109+
110+
// Construct the tools_db.json path
111+
toolsDBPath := filepath.Join(configDir, "tools_db.json")
112+
113+
// Read the tools database file
114+
data, err := os.ReadFile(toolsDBPath)
115+
if err != nil {
116+
log.Printf("Error reading tools_db.json: %v", err)
117+
http.Error(w, fmt.Sprintf("Failed to read tools database: %v", err), http.StatusInternalServerError)
118+
return
119+
}
120+
121+
// Parse JSON to validate it
122+
var tools interface{}
123+
if err := json.Unmarshal(data, &tools); err != nil {
124+
log.Printf("Error parsing tools_db.json: %v", err)
125+
http.Error(w, fmt.Sprintf("Failed to parse tools database: %v", err), http.StatusInternalServerError)
126+
return
127+
}
128+
129+
// Send response
130+
w.Header().Set("Content-Type", "application/json")
131+
if err := json.NewEncoder(w).Encode(tools); err != nil {
132+
log.Printf("Error encoding tools to JSON: %v", err)
133+
http.Error(w, fmt.Sprintf("Failed to encode tools: %v", err), http.StatusInternalServerError)
134+
return
135+
}
136+
}
137+
}
138+
62139
// newReverseProxy creates a reverse proxy to targetBase and strips the given prefix from the incoming path
63140
func newReverseProxy(targetBase, stripPrefix string, forwardAuth bool) (*httputil.ReverseProxy, error) {
64141
targetURL, err := url.Parse(targetBase)
@@ -213,6 +290,15 @@ func main() {
213290
mux.HandleFunc("/api/router/config/all", configHandler(absConfigPath))
214291
log.Printf("Config API endpoint registered: /api/router/config/all")
215292

293+
// Config update endpoint - update the config.yaml file
294+
mux.HandleFunc("/api/router/config/update", updateConfigHandler(absConfigPath))
295+
log.Printf("Config update API endpoint registered: /api/router/config/update")
296+
297+
// Tools DB endpoint - serve the tools_db.json
298+
configDir := filepath.Dir(absConfigPath)
299+
mux.HandleFunc("/api/tools-db", toolsDBHandler(configDir))
300+
log.Printf("Tools DB API endpoint registered: /api/tools-db")
301+
216302
// Router API proxy (forward Authorization) - MUST be registered before Grafana
217303
var routerAPIProxy *httputil.ReverseProxy
218304
if *routerAPI != "" {

dashboard/frontend/src/components/ConfigNav.tsx

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export type ConfigSection =
88
| 'intelligent-routing'
99
| 'tools-selection'
1010
| 'observability'
11+
| 'classification-api'
1112

1213
interface ConfigNavProps {
1314
activeSection: ConfigSection
@@ -18,39 +19,45 @@ const ConfigNav: React.FC<ConfigNavProps> = ({ activeSection, onSectionChange })
1819
const sections = [
1920
{
2021
id: 'models' as ConfigSection,
21-
icon: '🔌',
22-
title: 'Models & Endpoints',
23-
description: 'Model configurations and backend endpoints'
22+
icon: '🤖',
23+
title: 'Models',
24+
description: 'User defined models and endpoints'
2425
},
2526
{
2627
id: 'prompt-guard' as ConfigSection,
2728
icon: '🛡️',
2829
title: 'Prompt Guard',
29-
description: 'PII and jailbreak detection'
30+
description: 'PII and jailbreak ModernBERT detection'
3031
},
3132
{
3233
id: 'similarity-cache' as ConfigSection,
3334
icon: '⚡',
3435
title: 'Similarity Cache',
35-
description: 'Semantic caching configuration'
36+
description: 'Similarity BERT configuration'
3637
},
3738
{
3839
id: 'intelligent-routing' as ConfigSection,
39-
icon: '📊',
40+
icon: '🧠',
4041
title: 'Intelligent Routing',
41-
description: 'Categories and reasoning configuration'
42+
description: 'Classify BERT, categories & reasoning'
4243
},
4344
{
4445
id: 'tools-selection' as ConfigSection,
4546
icon: '🔧',
4647
title: 'Tools Selection',
47-
description: 'Tool auto-selection settings'
48+
description: 'Tools configuration and database'
4849
},
4950
{
5051
id: 'observability' as ConfigSection,
51-
icon: '📈',
52+
icon: '📊',
5253
title: 'Observability',
53-
description: 'Metrics and monitoring'
54+
description: 'Tracing and metrics'
55+
},
56+
{
57+
id: 'classification-api' as ConfigSection,
58+
icon: '🔌',
59+
title: 'Classification API',
60+
description: 'Batch classification settings'
5461
}
5562
]
5663

0 commit comments

Comments
 (0)