feat(tui): handle --model and --prompt flags

This commit is contained in:
adamdottv
2025-07-08 05:50:10 -05:00
parent 6100a77b85
commit ea96ead346
4 changed files with 117 additions and 86 deletions

View File

@@ -9,6 +9,7 @@ import (
"strings"
tea "github.com/charmbracelet/bubbletea/v2"
flag "github.com/spf13/pflag"
"github.com/sst/opencode-sdk-go"
"github.com/sst/opencode-sdk-go/option"
"github.com/sst/opencode/internal/app"
@@ -23,6 +24,10 @@ func main() {
version = "v" + Version
}
var model *string = flag.String("model", "", "model to begin with")
var prompt *string = flag.String("prompt", "", "prompt to begin with")
flag.Parse()
url := os.Getenv("OPENCODE_SERVER")
appInfoStr := os.Getenv("OPENCODE_APP_INFO")
@@ -65,7 +70,7 @@ func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
app_, err := app.New(ctx, version, appInfo, httpClient)
app_, err := app.New(ctx, version, appInfo, httpClient, model, prompt)
if err != nil {
panic(err)
}

View File

@@ -17,7 +17,6 @@ require (
github.com/muesli/termenv v0.16.0
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3
github.com/sst/opencode-sdk-go v0.1.0-alpha.8
github.com/tidwall/gjson v1.14.4
rsc.io/qr v0.2.0
)
@@ -50,6 +49,7 @@ require (
github.com/sosodev/duration v1.3.1 // indirect
github.com/speakeasy-api/openapi-overlay v0.9.0 // indirect
github.com/spf13/cobra v1.9.1 // indirect
github.com/tidwall/gjson v1.14.4 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
github.com/tidwall/sjson v1.2.5 // indirect

View File

@@ -32,6 +32,8 @@ type App struct {
Session *opencode.Session
Messages []opencode.MessageUnion
Commands commands.CommandRegistry
InitialModel *string
InitialPrompt *string
}
type SessionSelectedMsg = *opencode.Session
@@ -58,6 +60,8 @@ func New(
version string,
appInfo opencode.App,
httpClient *opencode.Client,
model *string,
prompt *string,
) (*App, error) {
util.RootPath = appInfo.Path.Root
util.CwdPath = appInfo.Path.Cwd
@@ -118,6 +122,8 @@ func New(
Session: &opencode.Session{},
Messages: []opencode.MessageUnion{},
Commands: commands.LoadFromConfig(configInfo),
InitialModel: model,
InitialPrompt: prompt,
}
return app, nil
@@ -141,7 +147,6 @@ func (a *App) Key(commandName commands.CommandName) string {
}
func (a *App) InitializeProvider() tea.Cmd {
return func() tea.Msg {
providersResponse, err := a.Client.Config.Providers(context.Background())
if err != nil {
slog.Error("Failed to list providers", "error", err)
@@ -195,11 +200,36 @@ func (a *App) InitializeProvider() tea.Cmd {
currentModel = defaultModel
}
return ModelSelectedMsg{
var initialProvider *opencode.Provider
var initialModel *opencode.Model
if a.InitialModel != nil && *a.InitialModel != "" {
splits := strings.Split(*a.InitialModel, "/")
for _, provider := range providers {
if provider.ID == splits[0] {
initialProvider = &provider
for _, model := range provider.Models {
if model.ID == splits[1] {
initialModel = &model
}
}
}
}
}
if initialProvider != nil && initialModel != nil {
currentProvider = initialProvider
currentModel = initialModel
}
var cmds []tea.Cmd
cmds = append(cmds, util.CmdHandler(ModelSelectedMsg{
Provider: *currentProvider,
Model: *currentModel,
}))
if a.InitialPrompt != nil && *a.InitialPrompt != "" {
cmds = append(cmds, util.CmdHandler(SendMsg{Text: *a.InitialPrompt}))
}
}
return tea.Sequence(cmds...)
}
func getDefaultModel(

View File

@@ -64,7 +64,7 @@ func (m *editorComponent) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return m, tea.Batch(cmds...)
}
case dialog.ThemeSelectedMsg:
m.textarea = createTextArea(&m.textarea)
m.textarea = m.resetTextareaStyles()
m.spinner = createSpinner()
return m, tea.Batch(m.spinner.Tick, m.textarea.Focus())
case dialog.CompletionSelectedMsg:
@@ -306,13 +306,13 @@ func (m *editorComponent) getSubmitKeyText() string {
return m.app.Commands[commands.InputSubmitCommand].Keys()[0]
}
func createTextArea(existing *textarea.Model) textarea.Model {
func (m *editorComponent) resetTextareaStyles() textarea.Model {
t := theme.CurrentTheme()
bgColor := t.BackgroundElement()
textColor := t.Text()
textMutedColor := t.TextMuted()
ta := textarea.New()
ta := m.textarea
ta.Styles.Blurred.Base = styles.NewStyle().Foreground(textColor).Background(bgColor).Lipgloss()
ta.Styles.Blurred.CursorLine = styles.NewStyle().Background(bgColor).Lipgloss()
@@ -337,17 +337,6 @@ func createTextArea(existing *textarea.Model) textarea.Model {
Background(t.Secondary()).
Lipgloss()
ta.Styles.Cursor.Color = t.Primary()
ta.Prompt = " "
ta.ShowLineNumbers = false
ta.CharLimit = -1
if existing != nil {
ta.SetValue(existing.Value())
// ta.SetWidth(existing.Width())
ta.SetHeight(existing.Height())
}
return ta
}
@@ -367,12 +356,19 @@ func createSpinner() spinner.Model {
func NewEditorComponent(app *app.App) EditorComponent {
s := createSpinner()
ta := createTextArea(nil)
return &editorComponent{
ta := textarea.New()
ta.Prompt = " "
ta.ShowLineNumbers = false
ta.CharLimit = -1
m := &editorComponent{
app: app,
textarea: ta,
spinner: s,
interruptKeyInDebounce: false,
}
m.resetTextareaStyles()
return m
}