summaryrefslogtreecommitdiffhomepage
path: root/packages/tui/internal/components
diff options
context:
space:
mode:
Diffstat (limited to 'packages/tui/internal/components')
-rw-r--r--packages/tui/internal/components/chat/message.go24
-rw-r--r--packages/tui/internal/components/chat/messages.go66
2 files changed, 68 insertions, 22 deletions
diff --git a/packages/tui/internal/components/chat/message.go b/packages/tui/internal/components/chat/message.go
index 46dd02d14..eecfe2611 100644
--- a/packages/tui/internal/components/chat/message.go
+++ b/packages/tui/internal/components/chat/message.go
@@ -14,6 +14,7 @@ import (
"github.com/muesli/reflow/truncate"
"github.com/sst/opencode-sdk-go"
"github.com/sst/opencode/internal/app"
+ "github.com/sst/opencode/internal/commands"
"github.com/sst/opencode/internal/components/diff"
"github.com/sst/opencode/internal/styles"
"github.com/sst/opencode/internal/theme"
@@ -479,6 +480,8 @@ func renderToolDetails(
backgroundColor := t.BackgroundPanel()
borderColor := t.BackgroundPanel()
defaultStyle := styles.NewStyle().Background(backgroundColor).Width(width - 6).Render
+ baseStyle := styles.NewStyle().Background(backgroundColor).Foreground(t.Text()).Render
+ mutedStyle := styles.NewStyle().Background(backgroundColor).Foreground(t.TextMuted()).Render
permissionContent := ""
if permission.ID != "" {
@@ -602,14 +605,15 @@ func renderToolDetails(
}
}
case "bash":
- command := toolInputMap["command"].(string)
- body = fmt.Sprintf("```console\n$ %s\n", command)
- output := metadata["output"]
- if output != nil {
- body += ansi.Strip(fmt.Sprintf("%s", output))
+ if command, ok := toolInputMap["command"].(string); ok {
+ body = fmt.Sprintf("```console\n$ %s\n", command)
+ output := metadata["output"]
+ if output != nil {
+ body += ansi.Strip(fmt.Sprintf("%s", output))
+ }
+ body += "```"
+ body = util.ToMarkdown(body, width, backgroundColor)
}
- body += "```"
- body = util.ToMarkdown(body, width, backgroundColor)
case "webfetch":
if format, ok := toolInputMap["format"].(string); ok && result != nil {
body = *result
@@ -653,6 +657,12 @@ func renderToolDetails(
steps = append(steps, step)
}
body = strings.Join(steps, "\n")
+
+ body += "\n\n"
+ body += baseStyle(app.Keybind(commands.SessionChildCycleCommand)) +
+ mutedStyle(", ") +
+ baseStyle(app.Keybind(commands.SessionChildCycleReverseCommand)) +
+ mutedStyle(" navigate child sessions")
}
body = defaultStyle(body)
default:
diff --git a/packages/tui/internal/components/chat/messages.go b/packages/tui/internal/components/chat/messages.go
index 1c6bce904..109a734ad 100644
--- a/packages/tui/internal/components/chat/messages.go
+++ b/packages/tui/internal/components/chat/messages.go
@@ -180,6 +180,8 @@ func (m *messagesComponent) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.tail = true
return m, m.renderView()
}
+ case app.SessionSelectedMsg:
+ m.viewport.GotoBottom()
case app.MessageRevertedMsg:
if msg.Session.ID == m.app.Session.ID {
m.cache.Clear()
@@ -782,8 +784,17 @@ func (m *messagesComponent) renderHeader() string {
headerWidth := m.width
t := theme.CurrentTheme()
- base := styles.NewStyle().Foreground(t.Text()).Background(t.Background()).Render
- muted := styles.NewStyle().Foreground(t.TextMuted()).Background(t.Background()).Render
+ bgColor := t.Background()
+ borderColor := t.BackgroundElement()
+
+ isChildSession := m.app.Session.ParentID != ""
+ if isChildSession {
+ bgColor = t.BackgroundElement()
+ borderColor = t.Accent()
+ }
+
+ base := styles.NewStyle().Foreground(t.Text()).Background(bgColor).Render
+ muted := styles.NewStyle().Foreground(t.TextMuted()).Background(bgColor).Render
sessionInfo := ""
tokens := float64(0)
@@ -815,20 +826,44 @@ func (m *messagesComponent) renderHeader() string {
sessionInfoText := formatTokensAndCost(tokens, contextWindow, cost, isSubscriptionModel)
sessionInfo = styles.NewStyle().
Foreground(t.TextMuted()).
- Background(t.Background()).
+ Background(bgColor).
Render(sessionInfoText)
shareEnabled := m.app.Config.Share != opencode.ConfigShareDisabled
+
+ navHint := ""
+ if isChildSession {
+ navHint = base(" "+m.app.Keybind(commands.SessionChildCycleReverseCommand)) + muted(" back")
+ }
+
headerTextWidth := headerWidth
- if !shareEnabled {
- // +1 is to ensure there is always at least one space between header and session info
- headerTextWidth -= len(sessionInfoText) + 1
+ if isChildSession {
+ headerTextWidth -= lipgloss.Width(navHint)
+ } else if !shareEnabled {
+ headerTextWidth -= lipgloss.Width(sessionInfoText)
}
headerText := util.ToMarkdown(
"# "+m.app.Session.Title,
headerTextWidth,
- t.Background(),
+ bgColor,
)
+ if isChildSession {
+ headerText = layout.Render(
+ layout.FlexOptions{
+ Background: &bgColor,
+ Direction: layout.Row,
+ Justify: layout.JustifySpaceBetween,
+ Align: layout.AlignStretch,
+ Width: headerTextWidth,
+ },
+ layout.FlexItem{
+ View: headerText,
+ },
+ layout.FlexItem{
+ View: navHint,
+ },
+ )
+ }
var items []layout.FlexItem
if shareEnabled {
@@ -841,10 +876,9 @@ func (m *messagesComponent) renderHeader() string {
items = []layout.FlexItem{{View: headerText}, {View: sessionInfo}}
}
- background := t.Background()
headerRow := layout.Render(
layout.FlexOptions{
- Background: &background,
+ Background: &bgColor,
Direction: layout.Row,
Justify: layout.JustifySpaceBetween,
Align: layout.AlignStretch,
@@ -860,14 +894,14 @@ func (m *messagesComponent) renderHeader() string {
header := strings.Join(headerLines, "\n")
header = styles.NewStyle().
- Background(t.Background()).
+ Background(bgColor).
Width(headerWidth).
PaddingLeft(2).
PaddingRight(2).
BorderLeft(true).
BorderRight(true).
BorderBackground(t.Background()).
- BorderForeground(t.BackgroundElement()).
+ BorderForeground(borderColor).
BorderStyle(lipgloss.ThickBorder()).
Render(header)
@@ -914,7 +948,7 @@ func formatTokensAndCost(
formattedCost := fmt.Sprintf("$%.2f", cost)
return fmt.Sprintf(
- "%s/%d%% (%s)",
+ " %s/%d%% (%s)",
formattedTokens,
int(percentage),
formattedCost,
@@ -923,20 +957,22 @@ func formatTokensAndCost(
func (m *messagesComponent) View() string {
t := theme.CurrentTheme()
+ bgColor := t.Background()
+
if m.loading {
return lipgloss.Place(
m.width,
m.height,
lipgloss.Center,
lipgloss.Center,
- styles.NewStyle().Background(t.Background()).Render(""),
- styles.WhitespaceStyle(t.Background()),
+ styles.NewStyle().Background(bgColor).Render(""),
+ styles.WhitespaceStyle(bgColor),
)
}
viewport := m.viewport.View()
return styles.NewStyle().
- Background(t.Background()).
+ Background(bgColor).
Render(m.header + "\n" + viewport)
}