Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions cmd/ax/harness.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ func setHarnessWorkDir() error {
if dir == "" {
return nil
}
if err := os.MkdirAll(dir, 0755); err != nil {
return fmt.Errorf("create harness working directory %q: %w", dir, err)
}
if err := os.Chdir(dir); err != nil {
return fmt.Errorf("set harness working directory %q: %w", dir, err)
}
Expand Down
12 changes: 8 additions & 4 deletions cmd/ax/harness_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,14 @@ func TestSetHarnessWorkDir(t *testing.T) {
}
})

t.Run("missing directory returns an error", func(t *testing.T) {
t.Setenv("AX_HARNESS_WORKDIR", filepath.Join(t.TempDir(), "does-not-exist"))
if err := setHarnessWorkDir(); err == nil {
t.Error("expected an error for a missing directory, got nil")
t.Run("missing directory is created", func(t *testing.T) {
dir := filepath.Join(t.TempDir(), "created", "workdir")
t.Setenv("AX_HARNESS_WORKDIR", dir)
if err := setHarnessWorkDir(); err != nil {
t.Fatalf("setHarnessWorkDir: %v", err)
}
if _, err := os.Stat(dir); err != nil {
t.Errorf("working directory %q was not created: %v", dir, err)
}
})
}
Expand Down
3 changes: 3 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,9 @@ func (c *Config) Validate() error {
}

func AXAssetsDir() (string, error) {
if dir := os.Getenv("AX_DURABLE_DIR"); dir != "" {
return filepath.Join(dir, ".ax"), nil
}
home, err := os.UserHomeDir()
if err != nil {
return "", fmt.Errorf("resolving home directory: %w", err)
Expand Down
31 changes: 31 additions & 0 deletions internal/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
package config

import (
"os"
"path/filepath"
"strings"
"testing"

Expand Down Expand Up @@ -345,3 +347,32 @@ func TestValidate_SkillsSelectionOneof(t *testing.T) {
}
})
}

func TestAXAssetsDir(t *testing.T) {
t.Run("durable-dir env roots the .ax tree on the volume", func(t *testing.T) {
t.Setenv("AX_DURABLE_DIR", "/mnt/durable")
got, err := AXAssetsDir()
if err != nil {
t.Fatalf("AXAssetsDir: %v", err)
}
want := filepath.Join("/mnt/durable", ".ax")
if got != want {
t.Errorf("AXAssetsDir() = %q, want %q", got, want)
}
})
t.Run("unset roots under the home directory", func(t *testing.T) {
t.Setenv("AX_DURABLE_DIR", "")
home, err := os.UserHomeDir()
if err != nil {
t.Skipf("no home directory: %v", err)
}
got, err := AXAssetsDir()
if err != nil {
t.Fatalf("AXAssetsDir: %v", err)
}
want := filepath.Join(home, ".ax")
if got != want {
t.Errorf("AXAssetsDir() = %q, want %q", got, want)
}
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -159,12 +159,12 @@ func cloudLocation() string {
return defaultLocation
}

// DefaultStateDir returns the default resume-cursor directory, ~/.ax/antigravityinteractions/cursors,
// used when a caller does not set StateDir explicitly. It lives outside the
// agent's working directory on purpose: the working directory is the agent's
// operating surface (it reads and edits files there), so AX's internal state is
// kept separate to avoid the agent seeing or clobbering it. New still requires a
// non-empty StateDir; callers apply this default.
// DefaultStateDir returns the default resume-cursor directory,
// <AXAssetsDir>/antigravityinteractions/cursors, used when a caller does not set
// StateDir explicitly. Locally that is ~/.ax/...; on a substrate actor
// AX_DURABLE_DIR points AXAssetsDir at a durable volume (e.g. /durable/.ax), kept
// outside the agent's working directory so the agent does not see or modify it.
// New still requires a non-empty StateDir; callers apply this default.
func DefaultStateDir() (string, error) {
axDir, err := config.AXAssetsDir()
if err != nil {
Expand Down
12 changes: 11 additions & 1 deletion manifests/ax-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -97,16 +97,26 @@ spec:
- name: GOOGLE_CLOUD_PROJECT
value: "${GOOGLE_CLOUD_PROJECT}"
- name: AX_HARNESS_WORKDIR
value: "/workspace"
value: "/durable/workspace"
- name: AX_DURABLE_DIR
value: "/durable"
# Content of manifests/ax.yaml
- name: AX_CONFIG_CONTENT
value: "${AX_CONFIG_CONTENT}"
readyz:
httpGet:
path: /readyz
port: 8081
volumeMounts:
- name: durable
mountPath: /durable
volumes:
- name: durable
durableDir: {}
snapshotsConfig:
location: gs://${AX_SNAPSHOTS_BUCKET}/axinteractions/
onPause: Data
onCommit: Data
---

# ---------------------------------------------------------------------------
Expand Down
Loading