fix(agentic): run language-specific workspace prep
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
24bb3b26c6
commit
c75911be67
2 changed files with 154 additions and 0 deletions
|
|
@ -544,6 +544,9 @@ func (s *PrepSubsystem) prepWorkspace(ctx context.Context, _ *mcp.CallToolReques
|
|||
}
|
||||
|
||||
s.cloneWorkspaceDeps(ctx, workspaceDir, repoDir, input.Org)
|
||||
if err := s.runWorkspaceLanguagePrep(ctx, workspaceDir, repoDir); err != nil {
|
||||
return nil, PrepOutput{}, err
|
||||
}
|
||||
|
||||
docsDir := core.JoinPath(workspaceDir, ".core", "reference", "docs")
|
||||
if !fs.IsDir(docsDir) {
|
||||
|
|
@ -696,6 +699,39 @@ func (s *PrepSubsystem) buildPrompt(ctx context.Context, input PrepInput, branch
|
|||
return b.String(), memories, consumers
|
||||
}
|
||||
|
||||
// runWorkspaceLanguagePrep installs repository dependencies before the agent starts.
|
||||
//
|
||||
// _ = s.runWorkspaceLanguagePrep(ctx, "/srv/.core/workspace/core/go-io/task-42", "/srv/Code/core/go-io")
|
||||
func (s *PrepSubsystem) runWorkspaceLanguagePrep(ctx context.Context, workspaceDir, repoDir string) error {
|
||||
process := s.Core().Process()
|
||||
|
||||
if fs.IsFile(core.JoinPath(repoDir, "go.mod")) {
|
||||
if result := process.RunIn(ctx, repoDir, "go", "mod", "download"); !result.OK {
|
||||
return core.E("prepWorkspace", "go mod download failed", nil)
|
||||
}
|
||||
}
|
||||
|
||||
if fs.IsFile(core.JoinPath(repoDir, "go.mod")) && (fs.IsFile(core.JoinPath(workspaceDir, "go.work")) || fs.IsFile(core.JoinPath(repoDir, "go.work"))) {
|
||||
if result := process.RunIn(ctx, repoDir, "go", "work", "sync"); !result.OK {
|
||||
return core.E("prepWorkspace", "go work sync failed", nil)
|
||||
}
|
||||
}
|
||||
|
||||
if fs.IsFile(core.JoinPath(repoDir, "composer.json")) {
|
||||
if result := process.RunIn(ctx, repoDir, "composer", "install"); !result.OK {
|
||||
return core.E("prepWorkspace", "composer install failed", nil)
|
||||
}
|
||||
}
|
||||
|
||||
if fs.IsFile(core.JoinPath(repoDir, "package.json")) {
|
||||
if result := process.RunIn(ctx, repoDir, "npm", "install"); !result.OK {
|
||||
return core.E("prepWorkspace", "npm install failed", nil)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *PrepSubsystem) getIssueBody(ctx context.Context, org, repo string, issue int) string {
|
||||
idx := core.Sprintf("%d", issue)
|
||||
iss, err := s.forge.Issues.Get(ctx, forge.Params{"owner": org, "repo": repo, "index": idx})
|
||||
|
|
|
|||
|
|
@ -6,12 +6,14 @@ import (
|
|||
"context"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
core "dappco.re/go/core"
|
||||
"dappco.re/go/core/forge"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// --- Shutdown ---
|
||||
|
|
@ -115,6 +117,122 @@ func TestPrep_FindConsumersList_Bad_NoGoWork(t *testing.T) {
|
|||
assert.Empty(t, list)
|
||||
}
|
||||
|
||||
func writeFakeLanguageCommand(t *testing.T, dir, name, logPath string, exitCode int) {
|
||||
t.Helper()
|
||||
|
||||
script := core.Concat(
|
||||
"#!/bin/sh\n",
|
||||
"printf '%s %s\\n' '",
|
||||
name,
|
||||
"' \"$*\" >> '",
|
||||
logPath,
|
||||
"'\n",
|
||||
"exit ",
|
||||
core.Sprint(exitCode),
|
||||
"\n",
|
||||
)
|
||||
require.True(t, fs.WriteMode(core.JoinPath(dir, name), script, 0755).OK)
|
||||
}
|
||||
|
||||
// --- runWorkspaceLanguagePrep ---
|
||||
|
||||
func TestPrep_RunWorkspaceLanguagePrep_Good_Polyglot(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
binDir := core.JoinPath(root, "bin")
|
||||
require.True(t, fs.EnsureDir(binDir).OK)
|
||||
|
||||
logPath := core.JoinPath(root, "commands.log")
|
||||
writeFakeLanguageCommand(t, binDir, "go", logPath, 0)
|
||||
writeFakeLanguageCommand(t, binDir, "composer", logPath, 0)
|
||||
writeFakeLanguageCommand(t, binDir, "npm", logPath, 0)
|
||||
|
||||
oldPath := os.Getenv("PATH")
|
||||
t.Setenv("PATH", core.Concat(binDir, ":", oldPath))
|
||||
|
||||
workspaceDir := core.JoinPath(root, "workspace")
|
||||
repoDir := core.JoinPath(root, "repo")
|
||||
require.True(t, fs.EnsureDir(workspaceDir).OK)
|
||||
require.True(t, fs.EnsureDir(repoDir).OK)
|
||||
require.True(t, fs.Write(core.JoinPath(repoDir, "go.mod"), "module example.com/test\n").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(repoDir, "composer.json"), "{}").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(repoDir, "package.json"), "{}").OK)
|
||||
require.True(t, fs.Write(core.JoinPath(workspaceDir, "go.work"), "go 1.22\n").OK)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
backoff: make(map[string]time.Time),
|
||||
failCount: make(map[string]int),
|
||||
}
|
||||
|
||||
err := s.runWorkspaceLanguagePrep(context.Background(), workspaceDir, repoDir)
|
||||
require.NoError(t, err)
|
||||
|
||||
logResult := fs.Read(logPath)
|
||||
require.True(t, logResult.OK)
|
||||
assert.Equal(t, "go mod download\ngo work sync\ncomposer install\nnpm install\n", logResult.Value.(string))
|
||||
}
|
||||
|
||||
func TestPrep_RunWorkspaceLanguagePrep_Bad_NoLanguageManifests(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
binDir := core.JoinPath(root, "bin")
|
||||
require.True(t, fs.EnsureDir(binDir).OK)
|
||||
|
||||
logPath := core.JoinPath(root, "commands.log")
|
||||
writeFakeLanguageCommand(t, binDir, "go", logPath, 0)
|
||||
writeFakeLanguageCommand(t, binDir, "composer", logPath, 0)
|
||||
writeFakeLanguageCommand(t, binDir, "npm", logPath, 0)
|
||||
|
||||
oldPath := os.Getenv("PATH")
|
||||
t.Setenv("PATH", core.Concat(binDir, ":", oldPath))
|
||||
|
||||
workspaceDir := core.JoinPath(root, "workspace")
|
||||
repoDir := core.JoinPath(root, "repo")
|
||||
require.True(t, fs.EnsureDir(workspaceDir).OK)
|
||||
require.True(t, fs.EnsureDir(repoDir).OK)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
backoff: make(map[string]time.Time),
|
||||
failCount: make(map[string]int),
|
||||
}
|
||||
|
||||
err := s.runWorkspaceLanguagePrep(context.Background(), workspaceDir, repoDir)
|
||||
require.NoError(t, err)
|
||||
|
||||
logResult := fs.Read(logPath)
|
||||
assert.False(t, logResult.OK)
|
||||
}
|
||||
|
||||
func TestPrep_RunWorkspaceLanguagePrep_Ugly_CommandFailure(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
binDir := core.JoinPath(root, "bin")
|
||||
require.True(t, fs.EnsureDir(binDir).OK)
|
||||
|
||||
logPath := core.JoinPath(root, "commands.log")
|
||||
writeFakeLanguageCommand(t, binDir, "go", logPath, 0)
|
||||
writeFakeLanguageCommand(t, binDir, "composer", logPath, 1)
|
||||
writeFakeLanguageCommand(t, binDir, "npm", logPath, 0)
|
||||
|
||||
oldPath := os.Getenv("PATH")
|
||||
t.Setenv("PATH", core.Concat(binDir, ":", oldPath))
|
||||
|
||||
workspaceDir := core.JoinPath(root, "workspace")
|
||||
repoDir := core.JoinPath(root, "repo")
|
||||
require.True(t, fs.EnsureDir(workspaceDir).OK)
|
||||
require.True(t, fs.EnsureDir(repoDir).OK)
|
||||
require.True(t, fs.Write(core.JoinPath(repoDir, "composer.json"), "{}").OK)
|
||||
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}),
|
||||
backoff: make(map[string]time.Time),
|
||||
failCount: make(map[string]int),
|
||||
}
|
||||
|
||||
err := s.runWorkspaceLanguagePrep(context.Background(), workspaceDir, repoDir)
|
||||
require.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "composer install failed")
|
||||
}
|
||||
|
||||
// --- pullWikiContent ---
|
||||
|
||||
func TestPrep_PullWikiContent_Good_WithPages(t *testing.T) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue