- Dashboard: tools, agents status, updates, quick actions - Studio: central chat + agents/workflows sidebar (Ctrl+S toggle) - Shell: terminal + AI assistant panel side-by-side (Ctrl+A toggle) - Config: profile, API keys, terminal/starship settings in 2 columns - New red/rose color scheme (#E8364F → #FF6B8A → #FFB3C6) - Animated header with visual tab bar and pulse loading - Remove old chat.go, agents.go, workflow_tab.go (merged into studio.go) - All tests pass, build clean 💘 Generated with Crush Assisted-by: GLM-5.1 via Crush <crush@charm.land>
109 lines
2.6 KiB
Go
109 lines
2.6 KiB
Go
package tui
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
tea "github.com/charmbracelet/bubbletea"
|
|
"github.com/muyue/muyue/internal/config"
|
|
"github.com/muyue/muyue/internal/installer"
|
|
"github.com/muyue/muyue/internal/orchestrator"
|
|
"github.com/muyue/muyue/internal/workflow"
|
|
)
|
|
|
|
func startInstallCmd(cfg *config.MuyueConfig, tools []string, index int) tea.Cmd {
|
|
return tea.Cmd(func() tea.Msg {
|
|
inst := installer.New(cfg)
|
|
result := inst.InstallTool(tools[index])
|
|
|
|
if index+1 < len(tools) {
|
|
return installBatchMsg{
|
|
result: result,
|
|
tools: tools,
|
|
index: index,
|
|
config: cfg,
|
|
}
|
|
}
|
|
return installCompleteMsg{results: []installer.InstallResult{result}}
|
|
})
|
|
}
|
|
|
|
func sendAIMessage(orch *orchestrator.Orchestrator, input string) tea.Cmd {
|
|
return tea.Cmd(func() tea.Msg {
|
|
if orch == nil {
|
|
return aiErrMsg{err: fmt.Errorf("orchestrator not configured")}
|
|
}
|
|
resp, err := orch.Send(input)
|
|
if err != nil {
|
|
return aiErrMsg{err: err}
|
|
}
|
|
return aiResponseMsg{content: resp}
|
|
})
|
|
}
|
|
|
|
func startWorkflowCmd(orch *orchestrator.Orchestrator, goal string) tea.Cmd {
|
|
return tea.Cmd(func() tea.Msg {
|
|
resp, err := orch.StartWorkflow(goal)
|
|
if err != nil {
|
|
return aiErrMsg{err: err}
|
|
}
|
|
return aiResponseMsg{content: resp}
|
|
})
|
|
}
|
|
|
|
func workflowChatCmd(orch *orchestrator.Orchestrator, input string) tea.Cmd {
|
|
return tea.Cmd(func() tea.Msg {
|
|
wf := orch.Workflow
|
|
switch wf.Phase {
|
|
case workflow.PhaseGathering:
|
|
resp, err := orch.AnswerQuestion(input)
|
|
if err != nil {
|
|
return aiErrMsg{err: err}
|
|
}
|
|
return aiResponseMsg{content: resp}
|
|
case workflow.PhaseReviewing:
|
|
approved, feedback := workflow.ParseApproval(input)
|
|
resp, err := orch.ReviewPlan(approved, feedback)
|
|
if err != nil {
|
|
return aiErrMsg{err: err}
|
|
}
|
|
return aiResponseMsg{content: resp}
|
|
default:
|
|
resp, err := orch.Send(input)
|
|
if err != nil {
|
|
return aiErrMsg{err: err}
|
|
}
|
|
return aiResponseMsg{content: resp}
|
|
}
|
|
})
|
|
}
|
|
|
|
func generatePlanCmd(orch *orchestrator.Orchestrator) tea.Cmd {
|
|
return tea.Cmd(func() tea.Msg {
|
|
resp, err := orch.GeneratePlan()
|
|
if err != nil {
|
|
return aiErrMsg{err: err}
|
|
}
|
|
return aiResponseMsg{content: resp}
|
|
})
|
|
}
|
|
|
|
func reviewPlanCmd(orch *orchestrator.Orchestrator, approved bool, feedback string) tea.Cmd {
|
|
return tea.Cmd(func() tea.Msg {
|
|
resp, err := orch.ReviewPlan(approved, feedback)
|
|
if err != nil {
|
|
return aiErrMsg{err: err}
|
|
}
|
|
return aiResponseMsg{content: resp}
|
|
})
|
|
}
|
|
|
|
func continueWorkflowCmd(orch *orchestrator.Orchestrator, output string) tea.Cmd {
|
|
return tea.Cmd(func() tea.Msg {
|
|
resp, err := orch.ContinueExecution(output)
|
|
if err != nil {
|
|
return aiErrMsg{err: err}
|
|
}
|
|
return aiResponseMsg{content: resp}
|
|
})
|
|
}
|