1package ollama
2
3import (
4 "context"
5 "fmt"
6 "os/exec"
7 "syscall"
8 "time"
9)
10
11var processManager = &ProcessManager{}
12
13// StartService starts the Ollama service if not already running
14func StartService(ctx context.Context) error {
15 if IsRunning(ctx) {
16 return nil // Already running
17 }
18
19 if !IsInstalled() {
20 return fmt.Errorf("Ollama is not installed")
21 }
22
23 processManager.mu.Lock()
24 defer processManager.mu.Unlock()
25
26 // Set up cleanup on first use
27 processManager.setupOnce.Do(func() {
28 setupCleanup()
29 })
30
31 // Start Ollama service
32 cmd := exec.CommandContext(ctx, "ollama", "serve")
33 cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
34
35 if err := cmd.Start(); err != nil {
36 return fmt.Errorf("failed to start Ollama service: %w", err)
37 }
38
39 processManager.ollamaProcess = cmd
40 processManager.crushStartedOllama = true
41
42 // Wait for service to be ready
43 startTime := time.Now()
44 for time.Since(startTime) < ServiceStartTimeout {
45 if IsRunning(ctx) {
46 return nil
47 }
48 time.Sleep(100 * time.Millisecond)
49 }
50
51 return fmt.Errorf("Ollama service did not start within %v", ServiceStartTimeout)
52}
53
54// EnsureRunning ensures Ollama service is running, starting it if necessary
55func EnsureRunning(ctx context.Context) error {
56 // Always ensure cleanup is set up, even if Ollama was already running
57 processManager.setupOnce.Do(func() {
58 setupCleanup()
59 })
60 return StartService(ctx)
61}
62
63// EnsureModelLoaded ensures a model is loaded, loading it if necessary
64func EnsureModelLoaded(ctx context.Context, modelName string) error {
65 if err := EnsureRunning(ctx); err != nil {
66 return err
67 }
68
69 running, err := IsModelRunning(ctx, modelName)
70 if err != nil {
71 return fmt.Errorf("failed to check if model is running: %w", err)
72 }
73
74 if running {
75 return nil // Already loaded
76 }
77
78 // Load the model
79 loadCtx, cancel := context.WithTimeout(ctx, ModelLoadTimeout)
80 defer cancel()
81
82 if err := LoadModel(loadCtx, modelName); err != nil {
83 return fmt.Errorf("failed to load model %s: %w", modelName, err)
84 }
85
86 return nil
87}