fix(ax): resolve nested workspace discovery
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
4d278a5172
commit
dc6f2e2073
6 changed files with 139 additions and 15 deletions
|
|
@ -118,8 +118,8 @@ func (commands appCommandSet) check(_ core.Options) core.Result {
|
|||
|
||||
wsRoot := agentic.WorkspaceRoot()
|
||||
if fs.IsDir(wsRoot) {
|
||||
entries := core.PathGlob(core.JoinPath(wsRoot, "*"))
|
||||
core.Print(nil, " workspace: %s (%d entries)", wsRoot, len(entries))
|
||||
statusFiles := agentic.WorkspaceStatusPaths()
|
||||
core.Print(nil, " workspace: %s (%d workspaces)", wsRoot, len(statusFiles))
|
||||
} else {
|
||||
core.Print(nil, " workspace: %s (MISSING)", wsRoot)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,10 +4,12 @@ package main
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
agentpkg "dappco.re/go/agent"
|
||||
"dappco.re/go/agent/pkg/agentic"
|
||||
"dappco.re/go/core"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
|
@ -31,6 +33,35 @@ func withArgs(t *testing.T, args ...string) {
|
|||
})
|
||||
}
|
||||
|
||||
func captureStdout(t *testing.T, run func()) string {
|
||||
t.Helper()
|
||||
|
||||
old := os.Stdout
|
||||
reader, writer, err := os.Pipe()
|
||||
if err != nil {
|
||||
t.Fatalf("pipe stdout: %v", err)
|
||||
}
|
||||
os.Stdout = writer
|
||||
defer func() {
|
||||
os.Stdout = old
|
||||
}()
|
||||
|
||||
run()
|
||||
|
||||
if err := writer.Close(); err != nil {
|
||||
t.Fatalf("close writer: %v", err)
|
||||
}
|
||||
data, err := io.ReadAll(reader)
|
||||
if err != nil {
|
||||
t.Fatalf("read stdout: %v", err)
|
||||
}
|
||||
if err := reader.Close(); err != nil {
|
||||
t.Fatalf("close reader: %v", err)
|
||||
}
|
||||
|
||||
return string(data)
|
||||
}
|
||||
|
||||
func TestCommands_ApplyLogLevel_Good(t *testing.T) {
|
||||
defer core.SetLevel(core.LevelInfo)
|
||||
|
||||
|
|
@ -111,6 +142,26 @@ func TestCommands_Check_Good(t *testing.T) {
|
|||
assert.True(t, r.OK)
|
||||
}
|
||||
|
||||
func TestCommands_Check_Good_BranchWorkspaceCount(t *testing.T) {
|
||||
c := newTestCore(t)
|
||||
|
||||
ws := core.JoinPath(agentic.WorkspaceRoot(), "core", "go-io", "feature", "new-ui")
|
||||
assert.True(t, agentic.LocalFs().EnsureDir(agentic.WorkspaceRepoDir(ws)).OK)
|
||||
assert.True(t, agentic.LocalFs().EnsureDir(agentic.WorkspaceMetaDir(ws)).OK)
|
||||
assert.True(t, agentic.LocalFs().Write(core.JoinPath(ws, "status.json"), core.JSONMarshalString(agentic.WorkspaceStatus{
|
||||
Status: "running",
|
||||
Repo: "go-io",
|
||||
Agent: "codex",
|
||||
})).OK)
|
||||
|
||||
output := captureStdout(t, func() {
|
||||
r := c.Cli().Run("check")
|
||||
assert.True(t, r.OK)
|
||||
})
|
||||
|
||||
assert.Contains(t, output, "1 workspaces")
|
||||
}
|
||||
|
||||
func TestCommands_Env_Good(t *testing.T) {
|
||||
c := newTestCore(t)
|
||||
|
||||
|
|
|
|||
|
|
@ -19,23 +19,23 @@ func registerMCPService(c *core.Core) core.Result {
|
|||
return core.Result{Value: core.E("main.registerMCPService", "core is required", nil), OK: false}
|
||||
}
|
||||
|
||||
var subsystems []mcp.Subsystem
|
||||
var registeredSubsystems []mcp.Subsystem
|
||||
|
||||
if prep, ok := core.ServiceFor[*agentic.PrepSubsystem](c, "agentic"); ok {
|
||||
subsystems = append(subsystems, prep)
|
||||
if agenticSubsystem, ok := core.ServiceFor[*agentic.PrepSubsystem](c, "agentic"); ok {
|
||||
registeredSubsystems = append(registeredSubsystems, agenticSubsystem)
|
||||
}
|
||||
if mon, ok := core.ServiceFor[*monitor.Subsystem](c, "monitor"); ok {
|
||||
subsystems = append(subsystems, mon)
|
||||
if monitorSubsystem, ok := core.ServiceFor[*monitor.Subsystem](c, "monitor"); ok {
|
||||
registeredSubsystems = append(registeredSubsystems, monitorSubsystem)
|
||||
}
|
||||
if brn, ok := core.ServiceFor[*brain.DirectSubsystem](c, "brain"); ok {
|
||||
subsystems = append(subsystems, brn)
|
||||
if brainSubsystem, ok := core.ServiceFor[*brain.DirectSubsystem](c, "brain"); ok {
|
||||
registeredSubsystems = append(registeredSubsystems, brainSubsystem)
|
||||
}
|
||||
|
||||
svc, err := mcp.New(mcp.Options{
|
||||
Subsystems: subsystems,
|
||||
service, err := mcp.New(mcp.Options{
|
||||
Subsystems: registeredSubsystems,
|
||||
})
|
||||
if err != nil {
|
||||
return core.Result{Value: core.E("main.registerMCPService", "create mcp service", err), OK: false}
|
||||
}
|
||||
return core.Result{Value: svc, OK: true}
|
||||
return core.Result{Value: service, OK: true}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -614,6 +614,26 @@ func TestCommands_CmdStatus_Good_DeepWorkspace(t *testing.T) {
|
|||
assert.Contains(t, output, "core/go-io/task-5")
|
||||
}
|
||||
|
||||
func TestCommands_CmdStatus_Good_BranchWorkspace(t *testing.T) {
|
||||
s, _ := testPrepWithCore(t, nil)
|
||||
|
||||
ws := core.JoinPath(WorkspaceRoot(), "core", "go-io", "feature", "new-ui")
|
||||
fs.EnsureDir(WorkspaceRepoDir(ws))
|
||||
fs.EnsureDir(WorkspaceMetaDir(ws))
|
||||
fs.Write(core.JoinPath(ws, "status.json"), core.JSONMarshalString(WorkspaceStatus{
|
||||
Status: "completed",
|
||||
Repo: "go-io",
|
||||
Agent: "codex",
|
||||
}))
|
||||
|
||||
output := captureStdout(t, func() {
|
||||
r := s.cmdStatus(core.NewOptions())
|
||||
assert.True(t, r.OK)
|
||||
})
|
||||
|
||||
assert.Contains(t, output, "core/go-io/feature/new-ui")
|
||||
}
|
||||
|
||||
func TestCommands_CmdPrompt_Bad_MissingRepo(t *testing.T) {
|
||||
s, _ := testPrepWithCore(t, nil)
|
||||
r := s.cmdPrompt(core.NewOptions())
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ package agentic
|
|||
|
||||
import (
|
||||
"context"
|
||||
iofs "io/fs"
|
||||
"sort"
|
||||
"strconv"
|
||||
|
||||
core "dappco.re/go/core"
|
||||
|
|
@ -82,9 +84,47 @@ func HomeDir() string {
|
|||
}
|
||||
|
||||
func workspaceStatusPaths(wsRoot string) []string {
|
||||
old := core.PathGlob(core.JoinPath(wsRoot, "*", "status.json"))
|
||||
deep := core.PathGlob(core.JoinPath(wsRoot, "*", "*", "*", "status.json"))
|
||||
return append(old, deep...)
|
||||
if wsRoot == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var paths []string
|
||||
seen := make(map[string]bool)
|
||||
|
||||
var walk func(dir string, depth int)
|
||||
walk = func(dir string, depth int) {
|
||||
r := fs.List(dir)
|
||||
if !r.OK {
|
||||
return
|
||||
}
|
||||
|
||||
entries, ok := r.Value.([]iofs.DirEntry)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
statusPath := core.JoinPath(dir, "status.json")
|
||||
if fs.IsFile(statusPath) {
|
||||
if depth == 1 || depth == 3 || (fs.IsDir(core.JoinPath(dir, "repo")) && fs.IsDir(core.JoinPath(dir, ".meta"))) {
|
||||
if !seen[statusPath] {
|
||||
seen[statusPath] = true
|
||||
paths = append(paths, statusPath)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
for _, entry := range entries {
|
||||
if !entry.IsDir() {
|
||||
continue
|
||||
}
|
||||
walk(core.JoinPath(dir, entry.Name()), depth+1)
|
||||
}
|
||||
}
|
||||
|
||||
walk(wsRoot, 0)
|
||||
sort.Strings(paths)
|
||||
return paths
|
||||
}
|
||||
|
||||
// WorkspaceRepoDir returns the checked-out repo directory for a workspace.
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
core "dappco.re/go/core"
|
||||
)
|
||||
|
|
@ -65,6 +66,18 @@ func TestPaths_WorkspaceHelpers_Good(t *testing.T) {
|
|||
assert.Contains(t, WorkspaceLogFiles(wsDir), core.JoinPath(metaDir, "agent-codex.log"))
|
||||
}
|
||||
|
||||
func TestPaths_WorkspaceHelpers_Good_BranchNameWithSlash(t *testing.T) {
|
||||
t.Setenv("CORE_WORKSPACE", "/tmp/test-core")
|
||||
wsDir := core.JoinPath(WorkspaceRoot(), "core", "go-io", "feature", "new-ui")
|
||||
|
||||
require.True(t, fs.EnsureDir(WorkspaceRepoDir(wsDir)).OK)
|
||||
require.True(t, fs.EnsureDir(WorkspaceMetaDir(wsDir)).OK)
|
||||
require.True(t, fs.Write(WorkspaceStatusPath(wsDir), "{}").OK)
|
||||
|
||||
assert.Equal(t, "core/go-io/feature/new-ui", WorkspaceName(wsDir))
|
||||
assert.Contains(t, WorkspaceStatusPaths(), WorkspaceStatusPath(wsDir))
|
||||
}
|
||||
|
||||
func TestPaths_PlansRoot_Good(t *testing.T) {
|
||||
t.Setenv("CORE_WORKSPACE", "/tmp/test-core")
|
||||
assert.Equal(t, "/tmp/test-core/plans", PlansRoot())
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue