check server is running before running command
This commit is contained in:
commit
8f8b6288ac
3 changed files with 91 additions and 25 deletions
|
@ -223,3 +223,10 @@ func (c *Client) Delete(ctx context.Context, req *DeleteRequest) error {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) Heartbeat(ctx context.Context) error {
|
||||||
|
if err := c.do(ctx, http.MethodHead, "/", nil, nil); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
58
cmd/cmd.go
58
cmd/cmd.go
|
@ -10,7 +10,9 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -425,7 +427,6 @@ func generateInteractive(cmd *cobra.Command, model string) error {
|
||||||
usage()
|
usage()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
usage()
|
usage()
|
||||||
continue
|
continue
|
||||||
|
@ -519,6 +520,54 @@ func RunServer(_ *cobra.Command, _ []string) error {
|
||||||
return server.Serve(ln)
|
return server.Serve(ln)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func startMacApp(client *api.Client) error {
|
||||||
|
exe, err := os.Executable()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
link, err := os.Readlink(exe)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !strings.Contains(link, "Ollama.app") {
|
||||||
|
return fmt.Errorf("could not find ollama app")
|
||||||
|
}
|
||||||
|
path := strings.Split(link, "Ollama.app")
|
||||||
|
if err := exec.Command("/usr/bin/open", "-a", path[0]+"Ollama.app").Run(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// wait for the server to start
|
||||||
|
timeout := time.After(5 * time.Second)
|
||||||
|
tick := time.Tick(500 * time.Millisecond)
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-timeout:
|
||||||
|
return errors.New("timed out waiting for server to start")
|
||||||
|
case <-tick:
|
||||||
|
if err := client.Heartbeat(context.Background()); err == nil {
|
||||||
|
return nil // server has started
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkServerHeartbeat(_ *cobra.Command, _ []string) error {
|
||||||
|
client := api.NewClient()
|
||||||
|
if err := client.Heartbeat(context.Background()); err != nil {
|
||||||
|
if !strings.Contains(err.Error(), "connection refused") {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if runtime.GOOS == "darwin" {
|
||||||
|
if err := startMacApp(client); err != nil {
|
||||||
|
return fmt.Errorf("could not connect to ollama app, is it running?")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("could not connect to ollama server, run 'ollama serve' to start it")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func NewCLI() *cobra.Command {
|
func NewCLI() *cobra.Command {
|
||||||
log.SetFlags(log.LstdFlags | log.Lshortfile)
|
log.SetFlags(log.LstdFlags | log.Lshortfile)
|
||||||
|
|
||||||
|
@ -537,6 +586,7 @@ func NewCLI() *cobra.Command {
|
||||||
Use: "create MODEL",
|
Use: "create MODEL",
|
||||||
Short: "Create a model from a Modelfile",
|
Short: "Create a model from a Modelfile",
|
||||||
Args: cobra.MinimumNArgs(1),
|
Args: cobra.MinimumNArgs(1),
|
||||||
|
PreRunE: checkServerHeartbeat,
|
||||||
RunE: CreateHandler,
|
RunE: CreateHandler,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -546,6 +596,7 @@ func NewCLI() *cobra.Command {
|
||||||
Use: "run MODEL [PROMPT]",
|
Use: "run MODEL [PROMPT]",
|
||||||
Short: "Run a model",
|
Short: "Run a model",
|
||||||
Args: cobra.MinimumNArgs(1),
|
Args: cobra.MinimumNArgs(1),
|
||||||
|
PreRunE: checkServerHeartbeat,
|
||||||
RunE: RunHandler,
|
RunE: RunHandler,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -562,6 +613,7 @@ func NewCLI() *cobra.Command {
|
||||||
Use: "pull MODEL",
|
Use: "pull MODEL",
|
||||||
Short: "Pull a model from a registry",
|
Short: "Pull a model from a registry",
|
||||||
Args: cobra.MinimumNArgs(1),
|
Args: cobra.MinimumNArgs(1),
|
||||||
|
PreRunE: checkServerHeartbeat,
|
||||||
RunE: PullHandler,
|
RunE: PullHandler,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -571,6 +623,7 @@ func NewCLI() *cobra.Command {
|
||||||
Use: "push MODEL",
|
Use: "push MODEL",
|
||||||
Short: "Push a model to a registry",
|
Short: "Push a model to a registry",
|
||||||
Args: cobra.MinimumNArgs(1),
|
Args: cobra.MinimumNArgs(1),
|
||||||
|
PreRunE: checkServerHeartbeat,
|
||||||
RunE: PushHandler,
|
RunE: PushHandler,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -580,6 +633,7 @@ func NewCLI() *cobra.Command {
|
||||||
Use: "list",
|
Use: "list",
|
||||||
Aliases: []string{"ls"},
|
Aliases: []string{"ls"},
|
||||||
Short: "List models",
|
Short: "List models",
|
||||||
|
PreRunE: checkServerHeartbeat,
|
||||||
RunE: ListHandler,
|
RunE: ListHandler,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -587,6 +641,7 @@ func NewCLI() *cobra.Command {
|
||||||
Use: "cp",
|
Use: "cp",
|
||||||
Short: "Copy a model",
|
Short: "Copy a model",
|
||||||
Args: cobra.MinimumNArgs(2),
|
Args: cobra.MinimumNArgs(2),
|
||||||
|
PreRunE: checkServerHeartbeat,
|
||||||
RunE: CopyHandler,
|
RunE: CopyHandler,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -594,6 +649,7 @@ func NewCLI() *cobra.Command {
|
||||||
Use: "rm",
|
Use: "rm",
|
||||||
Short: "Remove a model",
|
Short: "Remove a model",
|
||||||
Args: cobra.MinimumNArgs(1),
|
Args: cobra.MinimumNArgs(1),
|
||||||
|
PreRunE: checkServerHeartbeat,
|
||||||
RunE: DeleteHandler,
|
RunE: DeleteHandler,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -318,6 +318,9 @@ func Serve(ln net.Listener) error {
|
||||||
r.GET("/", func(c *gin.Context) {
|
r.GET("/", func(c *gin.Context) {
|
||||||
c.String(http.StatusOK, "Ollama is running")
|
c.String(http.StatusOK, "Ollama is running")
|
||||||
})
|
})
|
||||||
|
r.HEAD("/", func(c *gin.Context) {
|
||||||
|
c.Status(http.StatusOK)
|
||||||
|
})
|
||||||
|
|
||||||
r.POST("/api/pull", PullModelHandler)
|
r.POST("/api/pull", PullModelHandler)
|
||||||
r.POST("/api/generate", GenerateHandler)
|
r.POST("/api/generate", GenerateHandler)
|
||||||
|
|
Loading…
Reference in a new issue