summaryrefslogtreecommitdiffhomepage
path: root/packages/tui/internal/app/app.go
diff options
context:
space:
mode:
authoradamdotdevin <[email protected]>2025-07-21 05:52:02 -0500
committeradamdotdevin <[email protected]>2025-07-21 05:52:11 -0500
commit8e8796507d9adcb89341dfe01ec499938611ebea (patch)
treea4d503f71eed1280a478b1adaf2037a88594eac3 /packages/tui/internal/app/app.go
parentcef5c295834760d9d3a57334f2e52bd528c66e68 (diff)
downloadopencode-8e8796507d9adcb89341dfe01ec499938611ebea.tar.gz
opencode-8e8796507d9adcb89341dfe01ec499938611ebea.zip
feat(tui): message history select with up/down arrows
Diffstat (limited to 'packages/tui/internal/app/app.go')
-rw-r--r--packages/tui/internal/app/app.go103
1 files changed, 22 insertions, 81 deletions
diff --git a/packages/tui/internal/app/app.go b/packages/tui/internal/app/app.go
index b73cfc3cd..a481cd101 100644
--- a/packages/tui/internal/app/app.go
+++ b/packages/tui/internal/app/app.go
@@ -6,7 +6,6 @@ import (
"path/filepath"
"sort"
"strings"
- "time"
"log/slog"
@@ -15,7 +14,6 @@ import (
"github.com/sst/opencode/internal/clipboard"
"github.com/sst/opencode/internal/commands"
"github.com/sst/opencode/internal/components/toast"
- "github.com/sst/opencode/internal/config"
"github.com/sst/opencode/internal/id"
"github.com/sst/opencode/internal/styles"
"github.com/sst/opencode/internal/theme"
@@ -35,7 +33,7 @@ type App struct {
StatePath string
Config *opencode.Config
Client *opencode.Client
- State *config.State
+ State *State
ModeIndex int
Mode *opencode.Mode
Provider *opencode.Provider
@@ -61,10 +59,7 @@ type ModelSelectedMsg struct {
}
type SessionClearedMsg struct{}
type CompactSessionMsg struct{}
-type SendMsg struct {
- Text string
- Attachments []opencode.FilePartInputParam
-}
+type SendPrompt = Prompt
type SetEditorContentMsg struct {
Text string
}
@@ -95,14 +90,14 @@ func New(
}
appStatePath := filepath.Join(appInfo.Path.State, "tui")
- appState, err := config.LoadState(appStatePath)
+ appState, err := LoadState(appStatePath)
if err != nil {
- appState = config.NewState()
- config.SaveState(appStatePath, appState)
+ appState = NewState()
+ SaveState(appStatePath, appState)
}
if appState.ModeModel == nil {
- appState.ModeModel = make(map[string]config.ModeModel)
+ appState.ModeModel = make(map[string]ModeModel)
}
if configInfo.Theme != "" {
@@ -127,7 +122,7 @@ func New(
mode = &modes[modeIndex]
if mode.Model.ModelID != "" {
- appState.ModeModel[mode.Name] = config.ModeModel{
+ appState.ModeModel[mode.Name] = ModeModel{
ProviderID: mode.Model.ProviderID,
ModelID: mode.Model.ModelID,
}
@@ -241,11 +236,7 @@ func (a *App) cycleMode(forward bool) (*App, tea.Cmd) {
}
a.State.Mode = a.Mode.Name
-
- return a, func() tea.Msg {
- a.SaveState()
- return nil
- }
+ return a, a.SaveState()
}
func (a *App) SwitchMode() (*App, tea.Cmd) {
@@ -346,7 +337,7 @@ func (a *App) InitializeProvider() tea.Cmd {
Model: *currentModel,
}))
if a.InitialPrompt != nil && *a.InitialPrompt != "" {
- cmds = append(cmds, util.CmdHandler(SendMsg{Text: *a.InitialPrompt}))
+ cmds = append(cmds, util.CmdHandler(SendPrompt{Text: *a.InitialPrompt}))
}
return tea.Sequence(cmds...)
}
@@ -370,7 +361,6 @@ func (a *App) IsBusy() bool {
if len(a.Messages) == 0 {
return false
}
-
lastMessage := a.Messages[len(a.Messages)-1]
if casted, ok := lastMessage.Info.(opencode.AssistantMessage); ok {
return casted.Time.Completed == 0
@@ -378,10 +368,13 @@ func (a *App) IsBusy() bool {
return false
}
-func (a *App) SaveState() {
- err := config.SaveState(a.StatePath, a.State)
- if err != nil {
- slog.Error("Failed to save state", "error", err)
+func (a *App) SaveState() tea.Cmd {
+ return func() tea.Msg {
+ err := SaveState(a.StatePath, a.State)
+ if err != nil {
+ slog.Error("Failed to save state", "error", err)
+ }
+ return nil
}
}
@@ -459,11 +452,7 @@ func (a *App) CreateSession(ctx context.Context) (*opencode.Session, error) {
return session, nil
}
-func (a *App) SendChatMessage(
- ctx context.Context,
- text string,
- attachments []opencode.FilePartInputParam,
-) (*App, tea.Cmd) {
+func (a *App) SendPrompt(ctx context.Context, prompt Prompt) (*App, tea.Cmd) {
var cmds []tea.Cmd
if a.Session.ID == "" {
session, err := a.CreateSession(ctx)
@@ -474,65 +463,18 @@ func (a *App) SendChatMessage(
cmds = append(cmds, util.CmdHandler(SessionCreatedMsg{Session: session}))
}
- message := opencode.UserMessage{
- ID: id.Ascending(id.Message),
- SessionID: a.Session.ID,
- Role: opencode.UserMessageRoleUser,
- Time: opencode.UserMessageTime{
- Created: float64(time.Now().UnixMilli()),
- },
- }
-
- parts := []opencode.PartUnion{opencode.TextPart{
- ID: id.Ascending(id.Part),
- MessageID: message.ID,
- SessionID: a.Session.ID,
- Type: opencode.TextPartTypeText,
- Text: text,
- }}
- if len(attachments) > 0 {
- for _, attachment := range attachments {
- parts = append(parts, opencode.FilePart{
- ID: id.Ascending(id.Part),
- MessageID: message.ID,
- SessionID: a.Session.ID,
- Type: opencode.FilePartTypeFile,
- Filename: attachment.Filename.Value,
- Mime: attachment.Mime.Value,
- URL: attachment.URL.Value,
- })
- }
- }
+ messageID := id.Ascending(id.Message)
+ message := prompt.ToMessage(messageID, a.Session.ID)
- a.Messages = append(a.Messages, Message{Info: message, Parts: parts})
+ a.Messages = append(a.Messages, message)
cmds = append(cmds, func() tea.Msg {
- partsParam := []opencode.SessionChatParamsPartUnion{}
- for _, part := range parts {
- switch casted := part.(type) {
- case opencode.TextPart:
- partsParam = append(partsParam, opencode.TextPartInputParam{
- ID: opencode.F(casted.ID),
- Type: opencode.F(opencode.TextPartInputType(casted.Type)),
- Text: opencode.F(casted.Text),
- })
- case opencode.FilePart:
- partsParam = append(partsParam, opencode.FilePartInputParam{
- ID: opencode.F(casted.ID),
- Mime: opencode.F(casted.Mime),
- Type: opencode.F(opencode.FilePartInputType(casted.Type)),
- URL: opencode.F(casted.URL),
- Filename: opencode.F(casted.Filename),
- })
- }
- }
-
_, err := a.Client.Session.Chat(ctx, a.Session.ID, opencode.SessionChatParams{
- Parts: opencode.F(partsParam),
- MessageID: opencode.F(message.ID),
ProviderID: opencode.F(a.Provider.ID),
ModelID: opencode.F(a.Model.ID),
Mode: opencode.F(a.Mode.Name),
+ MessageID: opencode.F(messageID),
+ Parts: opencode.F(message.ToSessionChatParams()),
})
if err != nil {
errormsg := fmt.Sprintf("failed to send message: %v", err)
@@ -557,7 +499,6 @@ func (a *App) Cancel(ctx context.Context, sessionID string) error {
_, err := a.Client.Session.Abort(ctx, sessionID)
if err != nil {
slog.Error("Failed to cancel session", "error", err)
- // status.Error(err.Error())
return err
}
return nil