Skip to content
This repository was archived by the owner on Sep 18, 2025. It is now read-only.

Commit f463ce6

Browse files
committed
improve status message handling
1 parent 57a2210 commit f463ce6

File tree

10 files changed

+140
-84
lines changed

10 files changed

+140
-84
lines changed

cmd/root.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,16 @@ func setupSubscriptions(app *app.App) (chan tea.Msg, func()) {
107107
wg.Done()
108108
}()
109109
}
110+
{
111+
sub := app.Status.Subscribe(ctx)
112+
wg.Add(1)
113+
go func() {
114+
for ev := range sub {
115+
ch <- ev
116+
}
117+
wg.Done()
118+
}()
119+
}
110120
return ch, func() {
111121
cancel()
112122
wg.Wait()

internal/app/services.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ import (
1111
"github.com/kujtimiihoxha/termai/internal/lsp/watcher"
1212
"github.com/kujtimiihoxha/termai/internal/message"
1313
"github.com/kujtimiihoxha/termai/internal/permission"
14+
"github.com/kujtimiihoxha/termai/internal/pubsub"
1415
"github.com/kujtimiihoxha/termai/internal/session"
16+
"github.com/kujtimiihoxha/termai/internal/tui/util"
1517
)
1618

1719
type App struct {
@@ -25,6 +27,7 @@ type App struct {
2527

2628
Logger logging.Interface
2729

30+
Status *pubsub.Broker[util.InfoMsg]
2831
ceanups []func()
2932
}
3033

@@ -43,6 +46,7 @@ func New(ctx context.Context, conn *sql.DB) *App {
4346
Messages: messages,
4447
Permissions: permission.Default,
4548
Logger: log,
49+
Status: pubsub.NewBroker[util.InfoMsg](),
4650
LSPClients: make(map[string]*lsp.Client),
4751
}
4852

internal/llm/agent/agent.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ import (
1515
"github.com/kujtimiihoxha/termai/internal/llm/provider"
1616
"github.com/kujtimiihoxha/termai/internal/llm/tools"
1717
"github.com/kujtimiihoxha/termai/internal/message"
18+
"github.com/kujtimiihoxha/termai/internal/pubsub"
19+
"github.com/kujtimiihoxha/termai/internal/tui/util"
1820
)
1921

2022
type Agent interface {
@@ -92,9 +94,24 @@ func (c *agent) processEvent(
9294
assistantMsg.AppendContent(event.Content)
9395
return c.Messages.Update(*assistantMsg)
9496
case provider.EventError:
97+
// TODO: remove when realease
9598
log.Println("error", event.Error)
99+
c.App.Status.Publish(pubsub.UpdatedEvent, util.InfoMsg{
100+
Type: util.InfoTypeError,
101+
Msg: event.Error.Error(),
102+
})
96103
return event.Error
97-
104+
case provider.EventWarning:
105+
c.App.Status.Publish(pubsub.UpdatedEvent, util.InfoMsg{
106+
Type: util.InfoTypeWarn,
107+
Msg: event.Info,
108+
})
109+
return nil
110+
case provider.EventInfo:
111+
c.App.Status.Publish(pubsub.UpdatedEvent, util.InfoMsg{
112+
Type: util.InfoTypeInfo,
113+
Msg: event.Info,
114+
})
98115
case provider.EventComplete:
99116
assistantMsg.SetToolCalls(event.Response.ToolCalls)
100117
assistantMsg.AddFinish(event.Response.FinishReason)

internal/llm/provider/anthropic.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,8 @@ func (a *anthropicProvider) StreamResponse(ctx context.Context, messages []messa
149149

150150
// Inform user we're retrying with attempt number
151151
eventChan <- ProviderEvent{
152-
Type: EventContentDelta,
153-
Content: fmt.Sprintf("\n\n[Retrying due to rate limit... attempt %d of %d]\n\n", attempts, maxRetries),
152+
Type: EventWarning,
153+
Info: fmt.Sprintf("[Retrying due to rate limit... attempt %d of %d]", attempts, maxRetries),
154154
}
155155

156156
// Calculate backoff with exponential backoff and jitter
@@ -380,4 +380,3 @@ func (a *anthropicProvider) convertToAnthropicMessages(messages []message.Messag
380380

381381
return anthropicMessages
382382
}
383-

internal/llm/provider/provider.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ const (
1717
EventContentStop EventType = "content_stop"
1818
EventComplete EventType = "complete"
1919
EventError EventType = "error"
20+
EventWarning EventType = "warning"
21+
EventInfo EventType = "info"
2022
)
2123

2224
type TokenUsage struct {
@@ -40,6 +42,9 @@ type ProviderEvent struct {
4042
ToolCall *message.ToolCall
4143
Error error
4244
Response *ProviderResponse
45+
46+
// Used for giving users info on e.x retry
47+
Info string
4348
}
4449

4550
type Provider interface {

internal/tui/components/core/status.go

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,9 @@ import (
1313
)
1414

1515
type statusCmp struct {
16-
err error
17-
info string
18-
width int
19-
messageTTL time.Duration
16+
info *util.InfoMsg
17+
width int
18+
messageTTL time.Duration
2019
}
2120

2221
// clearMessageCmd is a command that clears status messages after a timeout
@@ -34,17 +33,12 @@ func (m statusCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
3433
switch msg := msg.(type) {
3534
case tea.WindowSizeMsg:
3635
m.width = msg.Width
37-
case util.ErrorMsg:
38-
m.err = msg
39-
m.info = ""
4036
return m, m.clearMessageCmd()
4137
case util.InfoMsg:
42-
m.info = string(msg)
43-
m.err = nil
38+
m.info = &msg
4439
return m, m.clearMessageCmd()
4540
case util.ClearStatusMsg:
46-
m.info = ""
47-
m.err = nil
41+
m.info = nil
4842
}
4943
return m, nil
5044
}
@@ -56,25 +50,25 @@ var (
5650

5751
func (m statusCmp) View() string {
5852
status := styles.Padded.Background(styles.Grey).Foreground(styles.Text).Render("? help")
59-
60-
if m.err != nil {
61-
status += styles.Regular.Padding(0, 1).
62-
Background(styles.Red).
63-
Foreground(styles.Text).
64-
Width(m.availableFooterMsgWidth()).
65-
Render(m.err.Error())
66-
} else if m.info != "" {
67-
status += styles.Padded.
53+
if m.info != nil {
54+
infoStyle := styles.Padded.
6855
Foreground(styles.Base).
69-
Background(styles.Green).
70-
Width(m.availableFooterMsgWidth()).
71-
Render(m.info)
56+
Width(m.availableFooterMsgWidth())
57+
switch m.info.Type {
58+
case util.InfoTypeInfo:
59+
infoStyle = infoStyle.Background(styles.Blue)
60+
case util.InfoTypeWarn:
61+
infoStyle = infoStyle.Background(styles.Peach)
62+
case util.InfoTypeError:
63+
infoStyle = infoStyle.Background(styles.Red)
64+
}
65+
status += infoStyle.Render(m.info.Msg)
7266
} else {
7367
status += styles.Padded.
7468
Foreground(styles.Base).
7569
Background(styles.LightGrey).
7670
Width(m.availableFooterMsgWidth()).
77-
Render(m.info)
71+
Render("")
7872
}
7973
status += m.model()
8074
status += versionWidget

0 commit comments

Comments
 (0)