Skip to content

Commit 7404b07

Browse files
Frank Guoclaude
andcommitted
Fix CI: global model cache, project-local daemon runtime
Model GGUF cache returns to ~/.cache/rekal/nomic/ (same binary across all projects, avoids per-test decompression that caused CI timeouts). Daemon socket and PID remain project-local at .rekal/nomic/. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent f15bd1b commit 7404b07

5 files changed

Lines changed: 21 additions & 21 deletions

File tree

cmd/rekal/cli/init.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,7 @@ imported into the local data DB automatically.`,
123123
}
124124

125125
// Pre-decompress nomic model so first query is fast.
126-
nomicCacheDir := filepath.Join(rekalDir, "nomic")
127-
if err := nomic.WarmCache(nomicCacheDir); err != nil {
126+
if err := nomic.WarmCache(); err != nil {
128127
fmt.Fprintf(cmd.ErrOrStderr(), "rekal: warning: nomic cache warm failed: %v\n", err)
129128
}
130129

cmd/rekal/cli/nomic/client.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
package nomic
44

5-
import "path/filepath"
6-
75
// Client provides nomic embeddings, transparently using the daemon when
86
// available or falling back to in-process embedding.
97
type Client struct {
@@ -27,8 +25,7 @@ func NewClient(gitRoot string) (*Client, error) {
2725
}
2826

2927
// No daemon running — fall back to in-process and spawn one for next time.
30-
cacheDir := filepath.Join(gitRoot, ".rekal", "nomic")
31-
embedder, err := NewEmbedder(cacheDir)
28+
embedder, err := NewEmbedder()
3229
if err != nil {
3330
return nil, err
3431
}

cmd/rekal/cli/nomic/daemon.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ func readMsg(conn net.Conn, v interface{}) error {
8989
// RunDaemon runs the nomic embedding daemon. It loads the model once, listens
9090
// on a Unix socket, and exits after idleTimeout of inactivity.
9191
func RunDaemon(gitRoot string) error {
92-
dir, err := nomicDir(gitRoot)
92+
_, err := nomicDir(gitRoot)
9393
if err != nil {
9494
return err
9595
}
@@ -114,7 +114,7 @@ func RunDaemon(gitRoot string) error {
114114
}
115115

116116
// Load model.
117-
embedder, err := NewEmbedder(dir)
117+
embedder, err := NewEmbedder()
118118
if err != nil {
119119
return fmt.Errorf("nomic daemon: load model: %w", err)
120120
}

cmd/rekal/cli/nomic/nomic_cgo.go

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -48,18 +48,23 @@ type Embedder struct {
4848
nEmbd int
4949
}
5050

51-
// WarmCache pre-decompresses the model GGUF into the given directory
51+
// WarmCache pre-decompresses the model GGUF into the global cache
5252
// so the first query doesn't pay decompression cost.
53-
func WarmCache(cacheDir string) error {
54-
_, err := cachedModelPath(cacheDir)
53+
func WarmCache() error {
54+
_, err := cachedModelPath()
5555
return err
5656
}
5757

5858
// cachedModelPath returns the path to a cached decompressed GGUF file,
5959
// creating it if it doesn't exist or the content hash has changed.
60-
// cacheDir is the directory to store the cached file (e.g. .rekal/nomic/).
61-
func cachedModelPath(cacheDir string) (string, error) {
62-
dir := cacheDir
60+
// The cache is global (~/.cache/rekal/nomic/) since the model binary
61+
// is the same across all projects.
62+
func cachedModelPath() (string, error) {
63+
cacheDir, err := os.UserCacheDir()
64+
if err != nil {
65+
return "", fmt.Errorf("nomic: cache dir: %w", err)
66+
}
67+
dir := filepath.Join(cacheDir, "rekal", "nomic")
6368
if err := os.MkdirAll(dir, 0o755); err != nil {
6469
return "", fmt.Errorf("nomic: create cache dir: %w", err)
6570
}
@@ -101,14 +106,13 @@ func cachedModelPath(cacheDir string) (string, error) {
101106
return cached, nil
102107
}
103108

104-
// NewEmbedder loads the embedded model, using a cached decompressed file
105-
// in cacheDir. cacheDir is the directory for the cached GGUF (e.g. .rekal/nomic/).
106-
func NewEmbedder(cacheDir string) (*Embedder, error) {
109+
// NewEmbedder loads the embedded model, using a cached decompressed file when available.
110+
func NewEmbedder() (*Embedder, error) {
107111
if !Supported() {
108112
return nil, ErrNotSupported
109113
}
110114

111-
modelPath, err := cachedModelPath(cacheDir)
115+
modelPath, err := cachedModelPath()
112116
if err != nil {
113117
return nil, err
114118
}
@@ -125,7 +129,7 @@ func NewEmbedder(cacheDir string) (*Embedder, error) {
125129
if handle == nil {
126130
// Cache may be corrupt — remove and retry once.
127131
os.Remove(modelPath) //nolint:errcheck
128-
modelPath, err = cachedModelPath(cacheDir)
132+
modelPath, err = cachedModelPath()
129133
if err != nil {
130134
return nil, err
131135
}

cmd/rekal/cli/nomic/nomic_nocgo.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@ func Supported() bool {
1515
}
1616

1717
// WarmCache is a no-op on unsupported platforms.
18-
func WarmCache(_ string) error {
18+
func WarmCache() error {
1919
return nil
2020
}
2121

2222
// Embedder is a stub on unsupported platforms.
2323
type Embedder struct{}
2424

2525
// NewEmbedder always returns ErrNotSupported on unsupported platforms.
26-
func NewEmbedder(_ string) (*Embedder, error) {
26+
func NewEmbedder() (*Embedder, error) {
2727
return nil, ErrNotSupported
2828
}
2929

0 commit comments

Comments
 (0)