package main import ( "context" "encoding/json" "log/slog" "os" "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" "github.com/sst/opencode/internal/clipboard" "github.com/sst/opencode/internal/tui" "github.com/sst/opencode/internal/util" ) var Version = "dev" func main() { version := Version if version != "dev" && !strings.HasPrefix(Version, "v") { 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") var appInfo opencode.App err := json.Unmarshal([]byte(appInfoStr), &appInfo) if err != nil { slog.Error("Failed to unmarshal app info", "error", err) os.Exit(1) } httpClient := opencode.NewClient( option.WithBaseURL(url), ) apiHandler := util.NewAPILogHandler(httpClient, "tui", slog.LevelDebug) logger := slog.New(apiHandler) slog.SetDefault(logger) slog.Debug("TUI launched", "app", appInfo) go func() { err = clipboard.Init() if err != nil { slog.Error("Failed to initialize clipboard", "error", err) } }() // Create main context for the application ctx, cancel := context.WithCancel(context.Background()) defer cancel() app_, err := app.New(ctx, version, appInfo, httpClient, model, prompt) if err != nil { panic(err) } program := tea.NewProgram( tui.NewModel(app_), tea.WithAltScreen(), tea.WithKeyboardEnhancements(), tea.WithMouseCellMotion(), ) go func() { stream := httpClient.Event.ListStreaming(ctx) for stream.Next() { evt := stream.Current().AsUnion() program.Send(evt) } if err := stream.Err(); err != nil { slog.Error("Error streaming events", "error", err) program.Send(err) } }() // Run the TUI result, err := program.Run() if err != nil { slog.Error("TUI error", "error", err) } slog.Info("TUI exited", "result", result) }