refactor(agentic): replace core path helpers

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Virgil 2026-04-02 08:58:17 +00:00
parent 165db215a2
commit 4c6296c1c1
7 changed files with 61 additions and 24 deletions

View file

@ -88,14 +88,14 @@ func parseForgeArgs(options core.Options) (org, repo string, num int64) {
num, _ = strconv.ParseInt(v, 10, 64)
}
if orgResult := core.ValidateName(org); orgResult.OK {
org = orgResult.Value.(string)
if validatedOrg, ok := validateName(org); ok {
org = validatedOrg
} else {
org = ""
}
if repoResult := core.ValidateName(repo); repoResult.OK {
repo = repoResult.Value.(string)
if validatedRepo, ok := validateName(repo); ok {
repo = validatedRepo
} else {
repo = ""
}
@ -504,13 +504,12 @@ func (s *PrepSubsystem) cmdRepoList(options core.Options) core.Result {
if org == "" {
org = "core"
}
orgResult := core.ValidateName(org)
if !orgResult.OK {
err, _ := orgResult.Value.(error)
validatedOrg, ok := validateName(org)
if !ok {
core.Print(nil, "usage: core-agent repo list [--org=core]")
return core.Result{Value: core.E("agentic.cmdRepoList", "invalid org name", err), OK: false}
return core.Result{Value: core.E("agentic.cmdRepoList", "invalid org name", nil), OK: false}
}
org = orgResult.Value.(string)
org = validatedOrg
repos, err := s.forge.Repos.ListOrgRepos(ctx, org)
if err != nil {
core.Print(nil, "error: %v", err)

View file

@ -316,7 +316,7 @@ func messageRoot() string {
}
func messagePath(workspace string) string {
return core.JoinPath(messageRoot(), core.Concat(core.SanitisePath(workspace), ".json"))
return core.JoinPath(messageRoot(), core.Concat(pathKey(workspace), ".json"))
}
func readWorkspaceMessages(workspace string) ([]AgentMessage, error) {

View file

@ -4,6 +4,10 @@ package agentic
import (
"context"
"crypto/rand"
"encoding/hex"
"strconv"
"sync/atomic"
"time"
core "dappco.re/go/core"
@ -152,6 +156,8 @@ type PlanListOutput struct {
const planListDefaultLimit = 20
var planIDCounter atomic.Uint64
// result := c.Action("plan.create").Run(ctx, core.NewOptions(
//
// core.Option{Key: "title", Value: "AX RFC follow-up"},
@ -354,7 +360,7 @@ func (s *PrepSubsystem) planCreate(_ context.Context, _ *mcp.CallToolRequest, in
return nil, PlanCreateOutput{}, core.E("planCreate", "objective is required", nil)
}
id := core.ID()
id := planID()
plan := Plan{
ID: id,
Slug: planSlugValue(input.Slug, input.Title, id),
@ -558,8 +564,7 @@ func (s *PrepSubsystem) planList(_ context.Context, _ *mcp.CallToolRequest, inpu
}
func planPath(dir, id string) string {
safe := core.SanitisePath(id)
return core.JoinPath(dir, core.Concat(safe, ".json"))
return core.JoinPath(dir, core.Concat(pathKey(id), ".json"))
}
func planPhasesValue(options core.Options, keys ...string) []Phase {
@ -710,6 +715,20 @@ func phaseCriteriaValue(values ...any) []string {
return nil
}
func planID() string {
counter := planIDCounter.Add(1)
suffix := planRandomHex()
return core.Concat("id-", strconv.FormatUint(counter, 10), "-", suffix)
}
func planRandomHex() string {
bytes := make([]byte, 3)
if _, err := rand.Read(bytes); err != nil {
return "000000"
}
return hex.EncodeToString(bytes)
}
func planTaskSliceValue(value any) []PlanTask {
switch typed := value.(type) {
case []PlanTask:

View file

@ -522,19 +522,17 @@ func workspaceDir(org, repo string, input PrepInput) (string, error) {
// r := workspaceDirResult("core", "go-io", PrepInput{Issue: 15})
// if r.OK { workspaceDir := r.Value.(string) }
func workspaceDirResult(org, repo string, input PrepInput) core.Result {
orgName := core.ValidateName(org)
if !orgName.OK {
err, _ := orgName.Value.(error)
return core.Result{Value: core.E("workspaceDir", "invalid org name", err), OK: false}
orgName, ok := validateName(org)
if !ok {
return core.Result{Value: core.E("workspaceDir", "invalid org name", nil), OK: false}
}
repoName := core.ValidateName(repo)
if !repoName.OK {
err, _ := repoName.Value.(error)
return core.Result{Value: core.E("workspaceDir", "invalid repo name", err), OK: false}
repoName, ok := validateName(repo)
if !ok {
return core.Result{Value: core.E("workspaceDir", "invalid repo name", nil), OK: false}
}
base := core.JoinPath(WorkspaceRoot(), orgName.Value.(string), repoName.Value.(string))
base := core.JoinPath(WorkspaceRoot(), orgName, repoName)
switch {
case input.PR > 0:
return core.Result{Value: core.JoinPath(base, core.Sprintf("pr-%d", input.PR)), OK: true}

View file

@ -2,6 +2,27 @@
package agentic
import core "dappco.re/go/core"
func validateName(text string) (string, bool) {
name := core.Trim(text)
if name == "" || name == "." || name == ".." {
return "", false
}
if core.Contains(name, "/") || core.Contains(name, "\\") {
return "", false
}
return name, true
}
func pathKey(text string) string {
safe := core.PathBase(core.Trim(text))
if safe == "." || safe == ".." || safe == "" {
return "invalid"
}
return safe
}
func sanitiseBranchSlug(text string, max int) string {
out := make([]rune, 0, len(text))
for _, r := range text {

View file

@ -916,7 +916,7 @@ func sessionCacheRoot() string {
}
func sessionCachePath(sessionID string) string {
return core.JoinPath(sessionCacheRoot(), core.Concat(core.SanitisePath(sessionID), ".json"))
return core.JoinPath(sessionCacheRoot(), core.Concat(pathKey(sessionID), ".json"))
}
func readSessionCache(sessionID string) (*Session, error) {

View file

@ -339,7 +339,7 @@ func stateRoot() string {
}
func statePath(planSlug string) string {
return core.JoinPath(stateRoot(), core.Concat(core.SanitisePath(planSlug), ".json"))
return core.JoinPath(stateRoot(), core.Concat(pathKey(planSlug), ".json"))
}
func readPlanStates(planSlug string) ([]WorkspaceState, error) {