mirror of
https://github.com/ollama/ollama.git
synced 2026-04-17 15:53:27 +02:00
launch/opencode: detect curl installed opencode at ~/.opencode/bin (#15197)
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
@@ -19,12 +20,34 @@ type OpenCode struct{}
|
||||
|
||||
func (o *OpenCode) String() string { return "OpenCode" }
|
||||
|
||||
// findOpenCode returns the opencode binary path, checking PATH first then the
|
||||
// curl installer location (~/.opencode/bin) which may not be on PATH yet.
|
||||
func findOpenCode() (string, bool) {
|
||||
if p, err := exec.LookPath("opencode"); err == nil {
|
||||
return p, true
|
||||
}
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return "", false
|
||||
}
|
||||
name := "opencode"
|
||||
if runtime.GOOS == "windows" {
|
||||
name = "opencode.exe"
|
||||
}
|
||||
fallback := filepath.Join(home, ".opencode", "bin", name)
|
||||
if _, err := os.Stat(fallback); err == nil {
|
||||
return fallback, true
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
func (o *OpenCode) Run(model string, args []string) error {
|
||||
if _, err := exec.LookPath("opencode"); err != nil {
|
||||
opencodePath, ok := findOpenCode()
|
||||
if !ok {
|
||||
return fmt.Errorf("opencode is not installed, install from https://opencode.ai")
|
||||
}
|
||||
|
||||
cmd := exec.Command("opencode", args...)
|
||||
cmd := exec.Command(opencodePath, args...)
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -771,6 +772,40 @@ func TestLookupCloudModelLimit(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestFindOpenCode(t *testing.T) {
|
||||
t.Run("fallback to ~/.opencode/bin", func(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
setTestHome(t, tmpDir)
|
||||
|
||||
// Ensure opencode is not on PATH
|
||||
t.Setenv("PATH", tmpDir)
|
||||
|
||||
// Without the fallback binary, findOpenCode should fail
|
||||
if _, ok := findOpenCode(); ok {
|
||||
t.Fatal("findOpenCode should fail when binary is not on PATH or in fallback location")
|
||||
}
|
||||
|
||||
// Create a fake binary at the curl install fallback location
|
||||
binDir := filepath.Join(tmpDir, ".opencode", "bin")
|
||||
os.MkdirAll(binDir, 0o755)
|
||||
name := "opencode"
|
||||
if runtime.GOOS == "windows" {
|
||||
name = "opencode.exe"
|
||||
}
|
||||
fakeBin := filepath.Join(binDir, name)
|
||||
os.WriteFile(fakeBin, []byte("#!/bin/sh\n"), 0o755)
|
||||
|
||||
// Now findOpenCode should succeed via fallback
|
||||
path, ok := findOpenCode()
|
||||
if !ok {
|
||||
t.Fatal("findOpenCode should succeed with fallback binary")
|
||||
}
|
||||
if path != fakeBin {
|
||||
t.Errorf("findOpenCode = %q, want %q", path, fakeBin)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestOpenCodeModels_NoConfig(t *testing.T) {
|
||||
o := &OpenCode{}
|
||||
tmpDir := t.TempDir()
|
||||
|
||||
@@ -92,8 +92,8 @@ var integrationSpecs = []*IntegrationSpec{
|
||||
Description: "Anomaly's open-source coding agent",
|
||||
Install: IntegrationInstallSpec{
|
||||
CheckInstalled: func() bool {
|
||||
_, err := exec.LookPath("opencode")
|
||||
return err == nil
|
||||
_, ok := findOpenCode()
|
||||
return ok
|
||||
},
|
||||
URL: "https://opencode.ai",
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user