root.go

  1package cmd
  2
  3import (
  4	"context"
  5	"os"
  6	"sync"
  7
  8	tea "github.com/charmbracelet/bubbletea"
  9	"github.com/kujtimiihoxha/termai/internal/app"
 10	"github.com/kujtimiihoxha/termai/internal/config"
 11	"github.com/kujtimiihoxha/termai/internal/db"
 12	"github.com/kujtimiihoxha/termai/internal/llm/agent"
 13	"github.com/kujtimiihoxha/termai/internal/tui"
 14	zone "github.com/lrstanley/bubblezone"
 15	"github.com/spf13/cobra"
 16)
 17
 18var rootCmd = &cobra.Command{
 19	Use:   "termai",
 20	Short: "A terminal ai assistant",
 21	Long:  `A terminal ai assistant`,
 22	RunE: func(cmd *cobra.Command, args []string) error {
 23		if cmd.Flag("help").Changed {
 24			cmd.Help()
 25			return nil
 26		}
 27		debug, _ := cmd.Flags().GetBool("debug")
 28		err := config.Load(debug)
 29		if err != nil {
 30			return err
 31		}
 32		conn, err := db.Connect()
 33		if err != nil {
 34			return err
 35		}
 36		ctx := context.Background()
 37
 38		app := app.New(ctx, conn)
 39		defer app.Close()
 40		app.Logger.Info("Starting termai...")
 41		zone.NewGlobal()
 42		tui := tea.NewProgram(
 43			tui.New(app),
 44			tea.WithAltScreen(),
 45			tea.WithMouseCellMotion(),
 46		)
 47		app.Logger.Info("Setting up subscriptions...")
 48		ch, unsub := setupSubscriptions(app)
 49		defer unsub()
 50
 51		go func() {
 52			// Set this up once
 53			agent.GetMcpTools(ctx, app.Permissions)
 54			for msg := range ch {
 55				tui.Send(msg)
 56			}
 57		}()
 58		if _, err := tui.Run(); err != nil {
 59			return err
 60		}
 61		return nil
 62	},
 63}
 64
 65func setupSubscriptions(app *app.App) (chan tea.Msg, func()) {
 66	ch := make(chan tea.Msg)
 67	wg := sync.WaitGroup{}
 68	ctx, cancel := context.WithCancel(app.Context)
 69
 70	{
 71		sub := app.Logger.Subscribe(ctx)
 72		wg.Add(1)
 73		go func() {
 74			for ev := range sub {
 75				ch <- ev
 76			}
 77			wg.Done()
 78		}()
 79	}
 80	{
 81		sub := app.Sessions.Subscribe(ctx)
 82		wg.Add(1)
 83		go func() {
 84			for ev := range sub {
 85				ch <- ev
 86			}
 87			wg.Done()
 88		}()
 89	}
 90	{
 91		sub := app.Messages.Subscribe(ctx)
 92		wg.Add(1)
 93		go func() {
 94			for ev := range sub {
 95				ch <- ev
 96			}
 97			wg.Done()
 98		}()
 99	}
100	{
101		sub := app.Permissions.Subscribe(ctx)
102		wg.Add(1)
103		go func() {
104			for ev := range sub {
105				ch <- ev
106			}
107			wg.Done()
108		}()
109	}
110	return ch, func() {
111		cancel()
112		wg.Wait()
113		close(ch)
114	}
115}
116
117func Execute() {
118	err := rootCmd.Execute()
119	if err != nil {
120		os.Exit(1)
121	}
122}
123
124func init() {
125	rootCmd.Flags().BoolP("help", "h", false, "Help")
126	rootCmd.Flags().BoolP("debug", "d", false, "Help")
127}