173d857dbb
- Add GET /api/claude/sessions/{session_id}/builder API for structure view
- Load builder session tags and snippets by Claude session ID
- Implement structure view in dashboard: shows tag selections and snippet details
- Add LoadSettings to persist LLM config changes across restarts
- Settings are now loaded from database on startup
Co-Authored-By: Claude <noreply@anthropic.com>
166 lines
4.2 KiB
Go
166 lines
4.2 KiB
Go
package handlers
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"prompt-generator/internal/db"
|
|
"prompt-generator/internal/models"
|
|
)
|
|
|
|
func GetClaudeSessions(w http.ResponseWriter, r *http.Request) {
|
|
projectName := r.URL.Query().Get("project_name")
|
|
if projectName == "" {
|
|
fail(w, 400, "project_name 参数必填")
|
|
return
|
|
}
|
|
|
|
rows, err := db.DB.Query(`
|
|
SELECT session_id, COUNT(*) as prompt_count, MAX(created_at) as last_time
|
|
FROM prompts
|
|
WHERE project_name=?
|
|
GROUP BY session_id
|
|
ORDER BY last_time DESC
|
|
LIMIT 50
|
|
`, projectName)
|
|
if err != nil {
|
|
fail(w, 500, "查询失败")
|
|
return
|
|
}
|
|
defer rows.Close()
|
|
|
|
var sessions []map[string]interface{}
|
|
for rows.Next() {
|
|
var sessionID string
|
|
var count int
|
|
var lastTime string
|
|
if err := rows.Scan(&sessionID, &count, &lastTime); err != nil {
|
|
continue
|
|
}
|
|
sessions = append(sessions, map[string]interface{}{
|
|
"session_id": sessionID,
|
|
"prompt_count": count,
|
|
"last_time": lastTime,
|
|
})
|
|
}
|
|
if sessions == nil {
|
|
sessions = []map[string]interface{}{}
|
|
}
|
|
success(w, sessions)
|
|
}
|
|
|
|
// GetBuilderSessionByClaudeSession looks up a builder session by claude_session_id
|
|
func GetBuilderSessionByClaudeSession(w http.ResponseWriter, r *http.Request) {
|
|
sessionID := r.PathValue("session_id")
|
|
if sessionID == "" {
|
|
fail(w, 400, "session_id 必填")
|
|
return
|
|
}
|
|
|
|
var s models.BuilderSession
|
|
err := db.DB.QueryRow("SELECT id, title, project_name, final_prompt, claude_session_id, created_at, updated_at FROM builder_sessions WHERE claude_session_id=?", sessionID).
|
|
Scan(&s.ID, &s.Title, &s.ProjectName, &s.FinalPrompt, &s.ClaudeSessionID, &s.CreatedAt, &s.UpdatedAt)
|
|
if err != nil {
|
|
// Not found is not an error
|
|
success(w, nil)
|
|
return
|
|
}
|
|
|
|
// Load tags with details
|
|
tags := []map[string]interface{}{}
|
|
tagRows, err := db.DB.Query(`
|
|
SELECT bst.tag_id, bst.tag_option_id, t.name, to2.label, to2.constraint_text
|
|
FROM builder_session_tags bst
|
|
JOIN tags t ON t.id = bst.tag_id
|
|
JOIN tag_options to2 ON to2.id = bst.tag_option_id
|
|
WHERE bst.builder_session_id=?`, s.ID)
|
|
if err == nil {
|
|
for tagRows.Next() {
|
|
var tagID, optionID int64
|
|
var tagName, optionLabel, constraintText string
|
|
if err := tagRows.Scan(&tagID, &optionID, &tagName, &optionLabel, &constraintText); err == nil {
|
|
tags = append(tags, map[string]interface{}{
|
|
"tag_id": tagID,
|
|
"tag_option_id": optionID,
|
|
"tag_name": tagName,
|
|
"option_label": optionLabel,
|
|
"constraint_text": constraintText,
|
|
})
|
|
}
|
|
}
|
|
tagRows.Close()
|
|
}
|
|
|
|
// Load snippets with details
|
|
snippets := []map[string]interface{}{}
|
|
snippetRows, err := db.DB.Query(`
|
|
SELECT bss.snippet_id, s.name, s.content, s.category, bss.sort_order
|
|
FROM builder_session_snippets bss
|
|
JOIN snippets s ON s.id = bss.snippet_id
|
|
WHERE bss.builder_session_id=?
|
|
ORDER BY bss.sort_order`, s.ID)
|
|
if err == nil {
|
|
for snippetRows.Next() {
|
|
var snippetID int64
|
|
var name, content, category string
|
|
var sortOrder int
|
|
if err := snippetRows.Scan(&snippetID, &name, &content, &category, &sortOrder); err == nil {
|
|
snippets = append(snippets, map[string]interface{}{
|
|
"snippet_id": snippetID,
|
|
"name": name,
|
|
"content": content,
|
|
"category": category,
|
|
"sort_order": sortOrder,
|
|
})
|
|
}
|
|
}
|
|
snippetRows.Close()
|
|
}
|
|
|
|
success(w, map[string]interface{}{
|
|
"session": s,
|
|
"tags": tags,
|
|
"snippets": snippets,
|
|
})
|
|
}
|
|
|
|
func GetClaudePrompts(w http.ResponseWriter, r *http.Request) {
|
|
sessionID := r.PathValue("session_id")
|
|
if sessionID == "" {
|
|
fail(w, 400, "session_id 必填")
|
|
return
|
|
}
|
|
|
|
rows, err := db.DB.Query(`
|
|
SELECT id, session_id, project_name, prompt, created_at
|
|
FROM prompts
|
|
WHERE session_id=?
|
|
ORDER BY created_at DESC
|
|
LIMIT 10
|
|
`, sessionID)
|
|
if err != nil {
|
|
fail(w, 500, "查询失败")
|
|
return
|
|
}
|
|
defer rows.Close()
|
|
|
|
var prompts []map[string]interface{}
|
|
for rows.Next() {
|
|
var id int64
|
|
var sid, pname, prompt, createdAt string
|
|
if err := rows.Scan(&id, &sid, &pname, &prompt, &createdAt); err != nil {
|
|
continue
|
|
}
|
|
prompts = append(prompts, map[string]interface{}{
|
|
"id": id,
|
|
"session_id": sid,
|
|
"project": pname,
|
|
"prompt": prompt,
|
|
"created_at": createdAt,
|
|
})
|
|
}
|
|
if prompts == nil {
|
|
prompts = []map[string]interface{}{}
|
|
}
|
|
success(w, prompts)
|
|
}
|