summaryrefslogtreecommitdiffhomepage
path: root/packages/tui/internal/app
diff options
context:
space:
mode:
authorspoons-and-mirrors <[email protected]>2025-08-12 22:21:57 +0200
committerGitHub <[email protected]>2025-08-12 16:21:57 -0400
commit81583cddbdd588fa3eb9e3e15ea70909ce1b4b93 (patch)
treeae32dc2bc337d569647c4f5af14abecffde6cf65 /packages/tui/internal/app
parentd16ae1fc4e6732dfb0d497f389f10c5ab04c253a (diff)
downloadopencode-81583cddbdd588fa3eb9e3e15ea70909ce1b4b93.tar.gz
opencode-81583cddbdd588fa3eb9e3e15ea70909ce1b4b93.zip
refactor(agent-modal): revamped UI/UX for the agent modal (#1838)
Co-authored-by: Dax Raad <[email protected]> Co-authored-by: Dax <[email protected]>
Diffstat (limited to 'packages/tui/internal/app')
-rw-r--r--packages/tui/internal/app/app.go44
-rw-r--r--packages/tui/internal/app/state.go43
2 files changed, 86 insertions, 1 deletions
diff --git a/packages/tui/internal/app/app.go b/packages/tui/internal/app/app.go
index 47520257d..345726483 100644
--- a/packages/tui/internal/app/app.go
+++ b/packages/tui/internal/app/app.go
@@ -71,9 +71,11 @@ type ModelSelectedMsg struct {
Provider opencode.Provider
Model opencode.Model
}
+
type AgentSelectedMsg struct {
- Agent opencode.Agent
+ AgentName string
}
+
type SessionClearedMsg struct{}
type CompactSessionMsg struct{}
type SendPrompt = Prompt
@@ -272,6 +274,7 @@ func (a *App) cycleMode(forward bool) (*App, tea.Cmd) {
}
a.State.Agent = a.Agent().Name
+ a.State.UpdateAgentUsage(a.Agent().Name)
return a, a.SaveState()
}
@@ -316,6 +319,45 @@ func (a *App) CycleRecentModel() (*App, tea.Cmd) {
return a, toast.NewErrorToast("Recent model not found")
}
+func (a *App) SwitchToAgent(agentName string) (*App, tea.Cmd) {
+ // Find the agent index by name
+ for i, agent := range a.Agents {
+ if agent.Name == agentName {
+ a.AgentIndex = i
+ break
+ }
+ }
+
+ // Set up model for the new agent
+ modelID := a.Agent().Model.ModelID
+ providerID := a.Agent().Model.ProviderID
+ if modelID == "" {
+ if model, ok := a.State.AgentModel[a.Agent().Name]; ok {
+ modelID = model.ModelID
+ providerID = model.ProviderID
+ }
+ }
+
+ if modelID != "" {
+ for _, provider := range a.Providers {
+ if provider.ID == providerID {
+ a.Provider = &provider
+ for _, model := range provider.Models {
+ if model.ID == modelID {
+ a.Model = &model
+ break
+ }
+ }
+ break
+ }
+ }
+ }
+
+ a.State.Agent = a.Agent().Name
+ a.State.UpdateAgentUsage(agentName)
+ return a, a.SaveState()
+}
+
// findModelByFullID finds a model by its full ID in the format "provider/model"
func findModelByFullID(
providers []opencode.Provider,
diff --git a/packages/tui/internal/app/state.go b/packages/tui/internal/app/state.go
index 283cbd15e..0e4010bec 100644
--- a/packages/tui/internal/app/state.go
+++ b/packages/tui/internal/app/state.go
@@ -16,6 +16,11 @@ type ModelUsage struct {
LastUsed time.Time `toml:"last_used"`
}
+type AgentUsage struct {
+ AgentName string `toml:"agent_name"`
+ LastUsed time.Time `toml:"last_used"`
+}
+
type AgentModel struct {
ProviderID string `toml:"provider_id"`
ModelID string `toml:"model_id"`
@@ -29,6 +34,7 @@ type State struct {
Model string `toml:"model"`
Agent string `toml:"agent"`
RecentlyUsedModels []ModelUsage `toml:"recently_used_models"`
+ RecentlyUsedAgents []AgentUsage `toml:"recently_used_agents"`
MessagesRight bool `toml:"messages_right"`
SplitDiff bool `toml:"split_diff"`
MessageHistory []Prompt `toml:"message_history"`
@@ -42,6 +48,7 @@ func NewState() *State {
Agent: "build",
AgentModel: make(map[string]AgentModel),
RecentlyUsedModels: make([]ModelUsage, 0),
+ RecentlyUsedAgents: make([]AgentUsage, 0),
MessageHistory: make([]Prompt, 0),
}
}
@@ -83,6 +90,42 @@ func (s *State) RemoveModelFromRecentlyUsed(providerID, modelID string) {
}
}
+// UpdateAgentUsage updates the recently used agents list with the specified agent
+func (s *State) UpdateAgentUsage(agentName string) {
+ now := time.Now()
+
+ // Check if this agent is already in the list
+ for i, usage := range s.RecentlyUsedAgents {
+ if usage.AgentName == agentName {
+ s.RecentlyUsedAgents[i].LastUsed = now
+ usage := s.RecentlyUsedAgents[i]
+ copy(s.RecentlyUsedAgents[1:i+1], s.RecentlyUsedAgents[0:i])
+ s.RecentlyUsedAgents[0] = usage
+ return
+ }
+ }
+
+ newUsage := AgentUsage{
+ AgentName: agentName,
+ LastUsed: now,
+ }
+
+ // Prepend to slice and limit to last 20 entries
+ s.RecentlyUsedAgents = append([]AgentUsage{newUsage}, s.RecentlyUsedAgents...)
+ if len(s.RecentlyUsedAgents) > 20 {
+ s.RecentlyUsedAgents = s.RecentlyUsedAgents[:20]
+ }
+}
+
+func (s *State) RemoveAgentFromRecentlyUsed(agentName string) {
+ for i, usage := range s.RecentlyUsedAgents {
+ if usage.AgentName == agentName {
+ s.RecentlyUsedAgents = append(s.RecentlyUsedAgents[:i], s.RecentlyUsedAgents[i+1:]...)
+ return
+ }
+ }
+}
+
func (s *State) AddPromptToHistory(prompt Prompt) {
s.MessageHistory = append([]Prompt{prompt}, s.MessageHistory...)
if len(s.MessageHistory) > 50 {