diff options
| author | Kujtim Hoxha <[email protected]> | 2025-03-24 11:47:39 +0100 |
|---|---|---|
| committer | Kujtim Hoxha <[email protected]> | 2025-03-24 11:47:39 +0100 |
| commit | 005b8ac16776512b2d4b1f22bd989da162ca1bad (patch) | |
| tree | cfe0d1da344ac31a467f1bea788ce80c723cd980 /internal/tui/components | |
| parent | e7258e38aeb46281fda474b8b7fcc3eee35edd9f (diff) | |
| download | opencode-005b8ac16776512b2d4b1f22bd989da162ca1bad.tar.gz opencode-005b8ac16776512b2d4b1f22bd989da162ca1bad.zip | |
initial working agent
Diffstat (limited to 'internal/tui/components')
| -rw-r--r-- | internal/tui/components/repl/messages.go | 75 | ||||
| -rw-r--r-- | internal/tui/components/repl/sessions.go | 31 |
2 files changed, 99 insertions, 7 deletions
diff --git a/internal/tui/components/repl/messages.go b/internal/tui/components/repl/messages.go index 9d95d98f5..feddf7bf6 100644 --- a/internal/tui/components/repl/messages.go +++ b/internal/tui/components/repl/messages.go @@ -1,22 +1,33 @@ package repl import ( + "github.com/charmbracelet/bubbles/key" + "github.com/charmbracelet/bubbles/viewport" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" "github.com/kujtimiihoxha/termai/internal/app" "github.com/kujtimiihoxha/termai/internal/message" "github.com/kujtimiihoxha/termai/internal/pubsub" "github.com/kujtimiihoxha/termai/internal/session" + "github.com/kujtimiihoxha/termai/internal/tui/layout" ) +type MessagesCmp interface { + tea.Model + layout.Focusable + layout.Bordered + layout.Sizeable + layout.Bindings +} + type messagesCmp struct { app *app.App messages []message.Message session session.Session -} - -func (m *messagesCmp) Init() tea.Cmd { - return nil + viewport viewport.Model + width int + height int + focused bool } func (m *messagesCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) { @@ -25,6 +36,12 @@ func (m *messagesCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) { if msg.Type == pubsub.CreatedEvent { m.messages = append(m.messages, msg.Payload) } + case pubsub.Event[session.Session]: + if msg.Type == pubsub.UpdatedEvent { + if m.session.ID == msg.Payload.ID { + m.session = msg.Payload + } + } case SelectedSessionMsg: m.session, _ = m.app.Sessions.Get(msg.SessionID) m.messages, _ = m.app.Messages.List(m.session.ID) @@ -40,7 +57,55 @@ func (i *messagesCmp) View() string { return lipgloss.JoinVertical(lipgloss.Top, stringMessages...) } -func NewMessagesCmp(app *app.App) tea.Model { +// BindingKeys implements MessagesCmp. +func (m *messagesCmp) BindingKeys() []key.Binding { + return []key.Binding{} +} + +// Blur implements MessagesCmp. +func (m *messagesCmp) Blur() tea.Cmd { + m.focused = false + return nil +} + +// BorderText implements MessagesCmp. +func (m *messagesCmp) BorderText() map[layout.BorderPosition]string { + title := m.session.Title + if len(title) > 20 { + title = title[:20] + "..." + } + return map[layout.BorderPosition]string{ + layout.TopLeftBorder: title, + } +} + +// Focus implements MessagesCmp. +func (m *messagesCmp) Focus() tea.Cmd { + m.focused = true + return nil +} + +// GetSize implements MessagesCmp. +func (m *messagesCmp) GetSize() (int, int) { + return m.width, m.height +} + +// IsFocused implements MessagesCmp. +func (m *messagesCmp) IsFocused() bool { + return m.focused +} + +// SetSize implements MessagesCmp. +func (m *messagesCmp) SetSize(width int, height int) { + m.width = width + m.height = height +} + +func (m *messagesCmp) Init() tea.Cmd { + return nil +} + +func NewMessagesCmp(app *app.App) MessagesCmp { return &messagesCmp{ app: app, messages: []message.Message{}, diff --git a/internal/tui/components/repl/sessions.go b/internal/tui/components/repl/sessions.go index 44c870021..5d2411fb6 100644 --- a/internal/tui/components/repl/sessions.go +++ b/internal/tui/components/repl/sessions.go @@ -2,6 +2,7 @@ package repl import ( "fmt" + "strings" "github.com/charmbracelet/bubbles/key" "github.com/charmbracelet/bubbles/list" @@ -82,7 +83,7 @@ func (i *sessionsCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) { items[i] = listItem{ id: s.ID, title: s.Title, - desc: fmt.Sprintf("Tokens: %d, Cost: %.2f", s.PromptTokens+s.CompletionTokens, s.Cost), + desc: formatTokensAndCost(s.PromptTokens+s.CompletionTokens, s.Cost), } } return i, i.list.SetItems(items) @@ -94,7 +95,7 @@ func (i *sessionsCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) { s := item.(listItem) if s.id == msg.Payload.ID { s.title = msg.Payload.Title - s.desc = fmt.Sprintf("Tokens: %d, Cost: %.2f", msg.Payload.PromptTokens+msg.Payload.CompletionTokens, msg.Payload.Cost) + s.desc = formatTokensAndCost(msg.Payload.PromptTokens+msg.Payload.CompletionTokens, msg.Payload.Cost) items[idx] = s break } @@ -169,6 +170,32 @@ func (i *sessionsCmp) BindingKeys() []key.Binding { return append(layout.KeyMapToSlice(i.list.KeyMap), sessionKeyMapValue.Select) } +func formatTokensAndCost(tokens int64, cost float64) string { + // Format tokens in human-readable format (e.g., 110K, 1.2M) + var formattedTokens string + switch { + case tokens >= 1_000_000: + formattedTokens = fmt.Sprintf("%.1fM", float64(tokens)/1_000_000) + case tokens >= 1_000: + formattedTokens = fmt.Sprintf("%.1fK", float64(tokens)/1_000) + default: + formattedTokens = fmt.Sprintf("%d", tokens) + } + + // Remove .0 suffix if present + if strings.HasSuffix(formattedTokens, ".0K") { + formattedTokens = strings.Replace(formattedTokens, ".0K", "K", 1) + } + if strings.HasSuffix(formattedTokens, ".0M") { + formattedTokens = strings.Replace(formattedTokens, ".0M", "M", 1) + } + + // Format cost with $ symbol and 2 decimal places + formattedCost := fmt.Sprintf("$%.2f", cost) + + return fmt.Sprintf("Tokens: %s, Cost: %s", formattedTokens, formattedCost) +} + func NewSessionsCmp(app *app.App) SessionsCmp { listDelegate := list.NewDefaultDelegate() defaultItemStyle := list.NewDefaultItemStyles() |
