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		app.Logger.Info("Starting termai...")
 40		zone.NewGlobal()
 41		tui := tea.NewProgram(
 42			tui.New(app),
 43			tea.WithAltScreen(),
 44			tea.WithMouseCellMotion(),
 45		)
 46		app.Logger.Info("Setting up subscriptions...")
 47		ch, unsub := setupSubscriptions(app)
 48		defer unsub()
 49
 50		go func() {
 51			// Set this up once
 52			agent.GetMcpTools(ctx)
 53			for msg := range ch {
 54				tui.Send(msg)
 55			}
 56		}()
 57		if _, err := tui.Run(); err != nil {
 58			return err
 59		}
 60		return nil
 61	},
 62}
 63
 64func setupSubscriptions(app *app.App) (chan tea.Msg, func()) {
 65	ch := make(chan tea.Msg)
 66	wg := sync.WaitGroup{}
 67	ctx, cancel := context.WithCancel(app.Context)
 68
 69	{
 70		sub := app.Logger.Subscribe(ctx)
 71		wg.Add(1)
 72		go func() {
 73			for ev := range sub {
 74				ch <- ev
 75			}
 76			wg.Done()
 77		}()
 78	}
 79	{
 80		sub := app.Sessions.Subscribe(ctx)
 81		wg.Add(1)
 82		go func() {
 83			for ev := range sub {
 84				ch <- ev
 85			}
 86			wg.Done()
 87		}()
 88	}
 89	{
 90		sub := app.Messages.Subscribe(ctx)
 91		wg.Add(1)
 92		go func() {
 93			for ev := range sub {
 94				ch <- ev
 95			}
 96			wg.Done()
 97		}()
 98	}
 99	{
100		sub := app.Permissions.Subscribe(ctx)
101		wg.Add(1)
102		go func() {
103			for ev := range sub {
104				ch <- ev
105			}
106			wg.Done()
107		}()
108	}
109	return ch, func() {
110		cancel()
111		wg.Wait()
112		close(ch)
113	}
114}
115
116func Execute() {
117	err := rootCmd.Execute()
118	if err != nil {
119		os.Exit(1)
120	}
121}
122
123func init() {
124	rootCmd.Flags().BoolP("help", "h", false, "Help")
125	rootCmd.Flags().BoolP("debug", "d", false, "Help")
126}