2023-12-27 00:03:45 +00:00
|
|
|
package lifecycle
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
"log"
|
|
|
|
"log/slog"
|
2024-02-15 22:58:29 +00:00
|
|
|
"os"
|
2024-02-16 23:33:16 +00:00
|
|
|
"os/signal"
|
|
|
|
"syscall"
|
2023-12-27 00:03:45 +00:00
|
|
|
|
|
|
|
"github.com/jmorganca/ollama/app/store"
|
|
|
|
"github.com/jmorganca/ollama/app/tray"
|
|
|
|
)
|
|
|
|
|
|
|
|
func Run() {
|
|
|
|
InitLogging()
|
|
|
|
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
var done chan int
|
|
|
|
|
|
|
|
t, err := tray.NewTray()
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalf("Failed to start: %s", err)
|
|
|
|
}
|
|
|
|
callbacks := t.GetCallbacks()
|
|
|
|
|
2024-02-16 23:33:16 +00:00
|
|
|
signals := make(chan os.Signal, 1)
|
|
|
|
signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM)
|
|
|
|
|
2023-12-27 00:03:45 +00:00
|
|
|
go func() {
|
|
|
|
slog.Debug("starting callback loop")
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-callbacks.Quit:
|
2024-02-16 23:33:16 +00:00
|
|
|
slog.Debug("quit called")
|
|
|
|
t.Quit()
|
|
|
|
case <-signals:
|
|
|
|
slog.Debug("shutting down due to signal")
|
2023-12-27 00:03:45 +00:00
|
|
|
t.Quit()
|
|
|
|
case <-callbacks.Update:
|
|
|
|
err := DoUpgrade(cancel, done)
|
|
|
|
if err != nil {
|
|
|
|
slog.Warn(fmt.Sprintf("upgrade attempt failed: %s", err))
|
|
|
|
}
|
|
|
|
case <-callbacks.ShowLogs:
|
|
|
|
ShowLogs()
|
|
|
|
case <-callbacks.DoFirstUse:
|
|
|
|
err := GetStarted()
|
|
|
|
if err != nil {
|
|
|
|
slog.Warn(fmt.Sprintf("Failed to launch getting started shell: %s", err))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
// Are we first use?
|
|
|
|
if !store.GetFirstTimeRun() {
|
|
|
|
slog.Debug("First time run")
|
|
|
|
err = t.DisplayFirstUseNotification()
|
|
|
|
if err != nil {
|
|
|
|
slog.Debug(fmt.Sprintf("XXX failed to display first use notification %v", err))
|
|
|
|
}
|
|
|
|
store.SetFirstTimeRun(true)
|
|
|
|
} else {
|
|
|
|
slog.Debug("Not first time, skipping first run notification")
|
|
|
|
}
|
|
|
|
|
|
|
|
if IsServerRunning(ctx) {
|
2024-02-15 22:58:29 +00:00
|
|
|
slog.Info("Detected another instance of ollama running, exiting")
|
|
|
|
os.Exit(1)
|
2023-12-27 00:03:45 +00:00
|
|
|
} else {
|
|
|
|
done, err = SpawnServer(ctx, CLIName)
|
|
|
|
if err != nil {
|
|
|
|
// TODO - should we retry in a backoff loop?
|
|
|
|
// TODO - should we pop up a warning and maybe add a menu item to view application logs?
|
|
|
|
slog.Error(fmt.Sprintf("Failed to spawn ollama server %s", err))
|
|
|
|
done = make(chan int, 1)
|
|
|
|
done <- 1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
StartBackgroundUpdaterChecker(ctx, t.UpdateAvailable)
|
|
|
|
|
|
|
|
t.Run()
|
|
|
|
cancel()
|
|
|
|
slog.Info("Waiting for ollama server to shutdown...")
|
|
|
|
if done != nil {
|
|
|
|
<-done
|
|
|
|
}
|
|
|
|
slog.Info("Ollama app exiting")
|
|
|
|
}
|