summaryrefslogtreecommitdiffhomepage
path: root/internal/tui/components
diff options
context:
space:
mode:
authorKujtim Hoxha <[email protected]>2025-03-24 11:47:39 +0100
committerKujtim Hoxha <[email protected]>2025-03-24 11:47:39 +0100
commit005b8ac16776512b2d4b1f22bd989da162ca1bad (patch)
treecfe0d1da344ac31a467f1bea788ce80c723cd980 /internal/tui/components
parente7258e38aeb46281fda474b8b7fcc3eee35edd9f (diff)
downloadopencode-005b8ac16776512b2d4b1f22bd989da162ca1bad.tar.gz
opencode-005b8ac16776512b2d4b1f22bd989da162ca1bad.zip
initial working agent
Diffstat (limited to 'internal/tui/components')
-rw-r--r--internal/tui/components/repl/messages.go75
-rw-r--r--internal/tui/components/repl/sessions.go31
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()