Go API server + Preact UI + Claude Code adapter. - App-centric model (ideas, not repos) - AgentProvider interface for multi-agent support - K8s pod lifecycle for sandboxed agent sessions - Gitea integration (create repos, push branches) - WebSocket streaming for live session output - Woodpecker CI/CD pipelines (kaniko build + kubectl deploy)
76 lines
1.8 KiB
Go
76 lines
1.8 KiB
Go
package claudecode
|
|
|
|
import "strings"
|
|
|
|
type Milestone struct {
|
|
Label string `json:"label"`
|
|
Status string `json:"status"` // "done", "active", "pending"
|
|
}
|
|
|
|
type ProgressTracker struct {
|
|
filesSeen map[string]bool
|
|
milestones []Milestone
|
|
}
|
|
|
|
func NewProgressTracker() *ProgressTracker {
|
|
return &ProgressTracker{
|
|
filesSeen: make(map[string]bool),
|
|
milestones: []Milestone{
|
|
{Label: "Setting up project", Status: "active"},
|
|
{Label: "Creating data models", Status: "pending"},
|
|
{Label: "Building UI components", Status: "pending"},
|
|
{Label: "Adding styling and polish", Status: "pending"},
|
|
{Label: "Final checks", Status: "pending"},
|
|
},
|
|
}
|
|
}
|
|
|
|
func (pt *ProgressTracker) Milestones() []Milestone {
|
|
cp := make([]Milestone, len(pt.milestones))
|
|
copy(cp, pt.milestones)
|
|
return cp
|
|
}
|
|
|
|
func (pt *ProgressTracker) ProcessLine(line string) {
|
|
lower := strings.ToLower(line)
|
|
|
|
if strings.Contains(lower, "\"tool\":\"write\"") || strings.Contains(lower, "\"tool\":\"create\"") {
|
|
pt.advanceTo(0)
|
|
}
|
|
|
|
if containsAny(lower, "model", "schema", "database", "migration", "struct", "type ") {
|
|
pt.advanceTo(1)
|
|
}
|
|
|
|
if containsAny(lower, "component", "page", "route", "template", "html", "tsx", "jsx", "vue") {
|
|
pt.advanceTo(2)
|
|
}
|
|
|
|
if containsAny(lower, "css", "style", "tailwind", "theme", "color", "font", "layout") {
|
|
pt.advanceTo(3)
|
|
}
|
|
|
|
if containsAny(lower, "test", "readme", "done", "complete", "finish", "final") {
|
|
pt.advanceTo(4)
|
|
}
|
|
}
|
|
|
|
func (pt *ProgressTracker) advanceTo(idx int) {
|
|
for i := range pt.milestones {
|
|
if i < idx {
|
|
pt.milestones[i].Status = "done"
|
|
} else if i == idx {
|
|
pt.milestones[i].Status = "active"
|
|
}
|
|
}
|
|
}
|
|
|
|
func containsAny(s string, substrs ...string) bool {
|
|
for _, sub := range substrs {
|
|
if strings.Contains(s, sub) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|