fix(ax): align remaining comments with AX principles
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
326c046d4e
commit
06ae13d92b
17 changed files with 42 additions and 142 deletions
|
|
@ -1,7 +1,5 @@
|
|||
// SPDX-License-Identifier: EUPL-1.2
|
||||
|
||||
// Workspace CLI commands registered by the agentic service during OnStartup.
|
||||
|
||||
package agentic
|
||||
|
||||
import (
|
||||
|
|
@ -10,8 +8,6 @@ import (
|
|||
core "dappco.re/go/core"
|
||||
)
|
||||
|
||||
// c.Command("workspace/list", core.Command{Description: "List all agent workspaces with status", Action: s.cmdWorkspaceList})
|
||||
// c.Command("workspace/dispatch", core.Command{Description: "Dispatch an agent to work on a repo task", Action: s.cmdWorkspaceDispatch})
|
||||
func (s *PrepSubsystem) registerWorkspaceCommands() {
|
||||
c := s.Core()
|
||||
c.Command("workspace/list", core.Command{Description: "List all agent workspaces with status", Action: s.cmdWorkspaceList})
|
||||
|
|
@ -94,6 +90,7 @@ func (s *PrepSubsystem) cmdWorkspaceClean(options core.Options) core.Result {
|
|||
return core.Result{OK: true}
|
||||
}
|
||||
|
||||
// input := DispatchInput{Repo: "go-io", Task: "Fix the failing tests", Issue: 12}
|
||||
func (s *PrepSubsystem) cmdWorkspaceDispatch(options core.Options) core.Result {
|
||||
repo := options.String("_arg")
|
||||
if repo == "" {
|
||||
|
|
@ -101,8 +98,6 @@ func (s *PrepSubsystem) cmdWorkspaceDispatch(options core.Options) core.Result {
|
|||
return core.Result{Value: core.E("agentic.cmdWorkspaceDispatch", "repo is required", nil), OK: false}
|
||||
}
|
||||
|
||||
// Call dispatch directly — CLI is an explicit user action,
|
||||
// not gated by the frozen-queue entitlement.
|
||||
input := DispatchInput{
|
||||
Repo: repo,
|
||||
Task: options.String("task"),
|
||||
|
|
|
|||
|
|
@ -1,10 +1,5 @@
|
|||
// SPDX-License-Identifier: EUPL-1.2
|
||||
|
||||
// Workspace dependency cloning.
|
||||
// Reads the repo's go.mod, finds Core ecosystem modules, clones them into
|
||||
// the workspace alongside ./repo, and builds a go.work that includes them all.
|
||||
// This gives the agent a complete, buildable workspace without needing go.work=off.
|
||||
|
||||
package agentic
|
||||
|
||||
import (
|
||||
|
|
@ -137,7 +132,7 @@ func parseCoreDeps(gomod string) []coreDep {
|
|||
|
||||
// forgeSSHURL builds the Forge SSH clone URL for a repo.
|
||||
//
|
||||
// forgeSSHURL("core", "go-io") → "ssh://git@forge.lthn.ai:2223/core/go-io.git"
|
||||
// forgeSSHURL("core", "go-io") → "ssh://git@forge.lthn.ai:2223/core/go-io.git"
|
||||
func forgeSSHURL(org, repo string) string {
|
||||
return core.Concat("ssh://git@forge.lthn.ai:2223/", org, "/", repo, ".git")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,15 +12,11 @@ import (
|
|||
"github.com/modelcontextprotocol/go-sdk/mcp"
|
||||
)
|
||||
|
||||
// workspaceTracker is the interface runner.Service satisfies.
|
||||
// Uses *WorkspaceStatus from agentic — runner imports agentic for the type.
|
||||
type workspaceTracker interface {
|
||||
TrackWorkspace(name string, status any)
|
||||
}
|
||||
|
||||
// DispatchInput is the input for agentic_dispatch.
|
||||
//
|
||||
// input := agentic.DispatchInput{Repo: "go-io", Task: "Fix the failing tests", Agent: "codex", Issue: 15}
|
||||
// input := agentic.DispatchInput{Repo: "go-io", Task: "Fix the failing tests", Agent: "codex", Issue: 15}
|
||||
type DispatchInput struct {
|
||||
Repo string `json:"repo"` // Target repo (e.g. "go-io")
|
||||
Org string `json:"org,omitempty"` // Forge org (default "core")
|
||||
|
|
@ -37,9 +33,7 @@ type DispatchInput struct {
|
|||
DryRun bool `json:"dry_run,omitempty"` // Preview without executing
|
||||
}
|
||||
|
||||
// DispatchOutput is the output for agentic_dispatch.
|
||||
//
|
||||
// out := agentic.DispatchOutput{Success: true, Agent: "codex", Repo: "go-io", WorkspaceDir: ".core/workspace/core/go-io/task-15"}
|
||||
// out := agentic.DispatchOutput{Success: true, Agent: "codex", Repo: "go-io", WorkspaceDir: ".core/workspace/core/go-io/task-15"}
|
||||
type DispatchOutput struct {
|
||||
Success bool `json:"success"`
|
||||
Agent string `json:"agent"`
|
||||
|
|
@ -58,7 +52,6 @@ func (s *PrepSubsystem) registerDispatchTool(server *mcp.Server) {
|
|||
}
|
||||
|
||||
// command, args, err := agentCommand("codex:review", "Review the last 2 commits via git diff HEAD~2")
|
||||
// Supports model variants: "gemini", "gemini:flash", "codex", "claude", "claude:haiku".
|
||||
func agentCommand(agent, prompt string) (string, []string, error) {
|
||||
commandResult := agentCommandResult(agent, prompt)
|
||||
if !commandResult.OK {
|
||||
|
|
@ -157,8 +150,6 @@ func agentCommandResult(agent, prompt string) core.Result {
|
|||
}
|
||||
}
|
||||
|
||||
// defaultDockerImage is the container image for agent dispatch.
|
||||
// Override via AGENT_DOCKER_IMAGE env var.
|
||||
const defaultDockerImage = "core-dev"
|
||||
|
||||
// command, args := containerCommand("local", "codex", []string{"exec", "--oss"}, "/srv/.core/workspace/core/go-io/task-5/repo", "/srv/.core/workspace/core/go-io/task-5/.meta")
|
||||
|
|
@ -248,8 +239,7 @@ func detectFinalStatus(repoDir string, exitCode int, processStatus string) (stri
|
|||
return "completed", ""
|
||||
}
|
||||
|
||||
// trackFailureRate detects fast consecutive failures and applies backoff.
|
||||
// Returns true if backoff was triggered.
|
||||
// backoff := s.trackFailureRate("codex", "failed", time.Now().Add(-30*time.Second))
|
||||
func (s *PrepSubsystem) trackFailureRate(agent, status string, startedAt time.Time) bool {
|
||||
pool := baseAgent(agent)
|
||||
if status == "failed" {
|
||||
|
|
@ -270,7 +260,7 @@ func (s *PrepSubsystem) trackFailureRate(agent, status string, startedAt time.Ti
|
|||
return false
|
||||
}
|
||||
|
||||
// startIssueTracking starts a Forge stopwatch on the workspace's issue.
|
||||
// s.startIssueTracking("/srv/.core/workspace/core/go-io/task-5")
|
||||
func (s *PrepSubsystem) startIssueTracking(workspaceDir string) {
|
||||
if s.forge == nil {
|
||||
return
|
||||
|
|
@ -287,7 +277,7 @@ func (s *PrepSubsystem) startIssueTracking(workspaceDir string) {
|
|||
s.forge.Issues.StartStopwatch(context.Background(), org, workspaceStatus.Repo, int64(workspaceStatus.Issue))
|
||||
}
|
||||
|
||||
// stopIssueTracking stops a Forge stopwatch on the workspace's issue.
|
||||
// s.stopIssueTracking("/srv/.core/workspace/core/go-io/task-5")
|
||||
func (s *PrepSubsystem) stopIssueTracking(workspaceDir string) {
|
||||
if s.forge == nil {
|
||||
return
|
||||
|
|
@ -361,10 +351,7 @@ func (s *PrepSubsystem) onAgentComplete(agent, workspaceDir, outputFile string,
|
|||
|
||||
s.broadcastComplete(agent, workspaceDir, finalStatus)
|
||||
|
||||
// Run completion pipeline via PerformAsync for successful agents.
|
||||
// Gets ActionTaskStarted/Completed broadcasts + WaitGroup integration for graceful shutdown.
|
||||
//
|
||||
// c.PerformAsync("agentic.complete", options) → runs agent.completion Task in background
|
||||
// c.PerformAsync("agentic.complete", core.NewOptions(core.Option{Key: "workspace", Value: workspaceDir}))
|
||||
if finalStatus == "completed" && s.ServiceRuntime != nil {
|
||||
s.Core().PerformAsync("agentic.complete", core.NewOptions(
|
||||
core.Option{Key: "workspace", Value: workspaceDir},
|
||||
|
|
@ -432,10 +419,8 @@ type completionProcess interface {
|
|||
Output() string
|
||||
}
|
||||
|
||||
// agentCompletionMonitor waits for a spawned process to finish, then finalises the workspace.
|
||||
//
|
||||
// monitor := &agentCompletionMonitor{service: s, agent: "codex", workspaceDir: workspaceDir, outputFile: outputFile, process: proc}
|
||||
// s.Core().Action("agentic.monitor.core.go-io.task-5", monitor.run)
|
||||
// monitor := &agentCompletionMonitor{service: s, agent: "codex", workspaceDir: workspaceDir, outputFile: outputFile, process: proc}
|
||||
// s.Core().Action("agentic.monitor.core.go-io.task-5", monitor.run)
|
||||
type agentCompletionMonitor struct {
|
||||
service *PrepSubsystem
|
||||
agent string
|
||||
|
|
|
|||
|
|
@ -9,9 +9,7 @@ import (
|
|||
core "dappco.re/go/core"
|
||||
)
|
||||
|
||||
// DispatchSyncInput is the input for a synchronous (blocking) task run.
|
||||
//
|
||||
// input := agentic.DispatchSyncInput{Repo: "go-crypt", Agent: "codex:gpt-5.3-codex-spark", Task: "fix it", Issue: 7}
|
||||
// input := agentic.DispatchSyncInput{Repo: "go-crypt", Agent: "codex:gpt-5.3-codex-spark", Task: "fix it", Issue: 7}
|
||||
type DispatchSyncInput struct {
|
||||
Org string
|
||||
Repo string
|
||||
|
|
@ -20,10 +18,8 @@ type DispatchSyncInput struct {
|
|||
Issue int
|
||||
}
|
||||
|
||||
// DispatchSyncResult is the output of a synchronous task run.
|
||||
//
|
||||
// if result.OK { core.Print(nil, "done: %s", result.Status) }
|
||||
// if !result.OK { core.Print(nil, "%v", result.Error) }
|
||||
// if result.OK { core.Print(nil, "done: %s", result.Status) }
|
||||
// if !result.OK { core.Print(nil, "%v", result.Error) }
|
||||
type DispatchSyncResult struct {
|
||||
OK bool
|
||||
Status string
|
||||
|
|
@ -31,10 +27,7 @@ type DispatchSyncResult struct {
|
|||
PRURL string
|
||||
}
|
||||
|
||||
// DispatchSync preps a workspace, spawns the agent directly (no queue, no concurrency check),
|
||||
// and blocks until the agent completes.
|
||||
//
|
||||
// result := prep.DispatchSync(ctx, input)
|
||||
// result := prep.DispatchSync(ctx, input)
|
||||
func (s *PrepSubsystem) DispatchSync(ctx context.Context, input DispatchSyncInput) DispatchSyncResult {
|
||||
// Prep workspace
|
||||
prepInput := PrepInput{
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import (
|
|||
"github.com/modelcontextprotocol/go-sdk/mcp"
|
||||
)
|
||||
|
||||
// input := agentic.EpicInput{Repo: "go-scm", Title: "Port agentic plans", Tasks: []string{"Read PHP flow", "Implement Go MCP tools"}}
|
||||
type EpicInput struct {
|
||||
Repo string `json:"repo"` // Target repo (e.g. "go-scm")
|
||||
Org string `json:"org,omitempty"` // Forge org (default "core")
|
||||
|
|
@ -22,7 +21,6 @@ type EpicInput struct {
|
|||
Template string `json:"template,omitempty"` // Prompt template for dispatch (default "coding")
|
||||
}
|
||||
|
||||
// out := agentic.EpicOutput{Success: true, EpicNumber: 42, EpicURL: "https://forge.example/core/go-scm/issues/42"}
|
||||
type EpicOutput struct {
|
||||
Success bool `json:"success"`
|
||||
EpicNumber int `json:"epic_number"`
|
||||
|
|
@ -31,7 +29,6 @@ type EpicOutput struct {
|
|||
Dispatched int `json:"dispatched,omitempty"`
|
||||
}
|
||||
|
||||
// child := agentic.ChildRef{Number: 43, Title: "Implement plan list", URL: "https://forge.example/core/go-scm/issues/43"}
|
||||
type ChildRef struct {
|
||||
Number int `json:"number"`
|
||||
Title string `json:"title"`
|
||||
|
|
|
|||
|
|
@ -9,14 +9,12 @@ import (
|
|||
"github.com/modelcontextprotocol/go-sdk/mcp"
|
||||
)
|
||||
|
||||
// input := agentic.MirrorInput{Repo: "go-io", DryRun: true, MaxFiles: 50}
|
||||
type MirrorInput struct {
|
||||
Repo string `json:"repo,omitempty"` // Specific repo, or empty for all
|
||||
DryRun bool `json:"dry_run,omitempty"` // Preview without pushing
|
||||
MaxFiles int `json:"max_files,omitempty"` // Max files per PR (default 50, CodeRabbit limit)
|
||||
}
|
||||
|
||||
// out := agentic.MirrorOutput{Success: true, Count: 1, Synced: []agentic.MirrorSync{{Repo: "go-io"}}}
|
||||
type MirrorOutput struct {
|
||||
Success bool `json:"success"`
|
||||
Synced []MirrorSync `json:"synced"`
|
||||
|
|
@ -24,7 +22,6 @@ type MirrorOutput struct {
|
|||
Count int `json:"count"`
|
||||
}
|
||||
|
||||
// sync := agentic.MirrorSync{Repo: "go-io", CommitsAhead: 3, FilesChanged: 12}
|
||||
type MirrorSync struct {
|
||||
Repo string `json:"repo"`
|
||||
CommitsAhead int `json:"commits_ahead"`
|
||||
|
|
|
|||
|
|
@ -10,10 +10,8 @@ import (
|
|||
"github.com/modelcontextprotocol/go-sdk/mcp"
|
||||
)
|
||||
|
||||
// Plan represents an implementation plan for agent work.
|
||||
//
|
||||
// plan := &Plan{ID: "id-1-a3f2b1", Title: "Migrate Core", Status: "draft", Objective: "..."}
|
||||
// r := writePlanResult(PlansRoot(), plan)
|
||||
// plan := &Plan{ID: "id-1-a3f2b1", Title: "Migrate Core", Status: "draft", Objective: "..."}
|
||||
// r := writePlanResult(PlansRoot(), plan)
|
||||
type Plan struct {
|
||||
ID string `json:"id"`
|
||||
Title string `json:"title"`
|
||||
|
|
@ -28,9 +26,7 @@ type Plan struct {
|
|||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
// Phase represents a phase within an implementation plan.
|
||||
//
|
||||
// phase := agentic.Phase{Number: 1, Name: "Migrate strings", Status: "in_progress"}
|
||||
// phase := agentic.Phase{Number: 1, Name: "Migrate strings", Status: "in_progress"}
|
||||
type Phase struct {
|
||||
Number int `json:"number"`
|
||||
Name string `json:"name"`
|
||||
|
|
@ -40,7 +36,6 @@ type Phase struct {
|
|||
Notes string `json:"notes,omitempty"`
|
||||
}
|
||||
|
||||
// input := agentic.PlanCreateInput{Title: "Migrate pkg/agentic", Objective: "Use Core primitives everywhere"}
|
||||
type PlanCreateInput struct {
|
||||
Title string `json:"title"`
|
||||
Objective string `json:"objective"`
|
||||
|
|
@ -50,25 +45,21 @@ type PlanCreateInput struct {
|
|||
Notes string `json:"notes,omitempty"`
|
||||
}
|
||||
|
||||
// out := agentic.PlanCreateOutput{Success: true, ID: "id-1-a3f2b1"}
|
||||
type PlanCreateOutput struct {
|
||||
Success bool `json:"success"`
|
||||
ID string `json:"id"`
|
||||
Path string `json:"path"`
|
||||
}
|
||||
|
||||
// input := agentic.PlanReadInput{ID: "id-1-a3f2b1"}
|
||||
type PlanReadInput struct {
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
// out := agentic.PlanReadOutput{Success: true, Plan: agentic.Plan{ID: "id-1-a3f2b1"}}
|
||||
type PlanReadOutput struct {
|
||||
Success bool `json:"success"`
|
||||
Plan Plan `json:"plan"`
|
||||
}
|
||||
|
||||
// input := agentic.PlanUpdateInput{ID: "id-1-a3f2b1", Status: "verified"}
|
||||
type PlanUpdateInput struct {
|
||||
ID string `json:"id"`
|
||||
Status string `json:"status,omitempty"`
|
||||
|
|
@ -79,30 +70,25 @@ type PlanUpdateInput struct {
|
|||
Agent string `json:"agent,omitempty"`
|
||||
}
|
||||
|
||||
// out := agentic.PlanUpdateOutput{Success: true, Plan: agentic.Plan{Status: "verified"}}
|
||||
type PlanUpdateOutput struct {
|
||||
Success bool `json:"success"`
|
||||
Plan Plan `json:"plan"`
|
||||
}
|
||||
|
||||
// input := agentic.PlanDeleteInput{ID: "id-1-a3f2b1"}
|
||||
type PlanDeleteInput struct {
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
// out := agentic.PlanDeleteOutput{Success: true, Deleted: "id-1-a3f2b1"}
|
||||
type PlanDeleteOutput struct {
|
||||
Success bool `json:"success"`
|
||||
Deleted string `json:"deleted"`
|
||||
}
|
||||
|
||||
// input := agentic.PlanListInput{Repo: "go-io", Status: "ready"}
|
||||
type PlanListInput struct {
|
||||
Status string `json:"status,omitempty"`
|
||||
Repo string `json:"repo,omitempty"`
|
||||
}
|
||||
|
||||
// out := agentic.PlanListOutput{Success: true, Count: 2, Plans: []agentic.Plan{{ID: "id-1-a3f2b1"}}}
|
||||
type PlanListOutput struct {
|
||||
Success bool `json:"success"`
|
||||
Count int `json:"count"`
|
||||
|
|
|
|||
|
|
@ -10,9 +10,7 @@ import (
|
|||
"github.com/modelcontextprotocol/go-sdk/mcp"
|
||||
)
|
||||
|
||||
// CreatePRInput is the input for agentic_create_pr.
|
||||
//
|
||||
// input := agentic.CreatePRInput{Workspace: "core/go-io/task-42", Title: "Fix watcher panic"}
|
||||
// input := agentic.CreatePRInput{Workspace: "core/go-io/task-42", Title: "Fix watcher panic"}
|
||||
type CreatePRInput struct {
|
||||
Workspace string `json:"workspace"` // workspace name (e.g. "core/go-io/task-42")
|
||||
Title string `json:"title,omitempty"` // PR title (default: task description)
|
||||
|
|
@ -21,9 +19,7 @@ type CreatePRInput struct {
|
|||
DryRun bool `json:"dry_run,omitempty"` // preview without creating
|
||||
}
|
||||
|
||||
// CreatePROutput is the output for agentic_create_pr.
|
||||
//
|
||||
// out := agentic.CreatePROutput{Success: true, PRURL: "https://forge.example/core/go-io/pulls/12", PRNum: 12}
|
||||
// out := agentic.CreatePROutput{Success: true, PRURL: "https://forge.example/core/go-io/pulls/12", PRNum: 12}
|
||||
type CreatePROutput struct {
|
||||
Success bool `json:"success"`
|
||||
PRURL string `json:"pr_url,omitempty"`
|
||||
|
|
@ -177,9 +173,7 @@ func (s *PrepSubsystem) commentOnIssue(ctx context.Context, org, repo string, is
|
|||
s.forge.Issues.CreateComment(ctx, org, repo, int64(issue), comment)
|
||||
}
|
||||
|
||||
// ListPRsInput is the input for agentic_list_prs.
|
||||
//
|
||||
// input := agentic.ListPRsInput{Org: "core", Repo: "go-io", State: "open", Limit: 10}
|
||||
// input := agentic.ListPRsInput{Org: "core", Repo: "go-io", State: "open", Limit: 10}
|
||||
type ListPRsInput struct {
|
||||
Org string `json:"org,omitempty"` // forge org (default "core")
|
||||
Repo string `json:"repo,omitempty"` // specific repo, or empty for all
|
||||
|
|
@ -187,18 +181,14 @@ type ListPRsInput struct {
|
|||
Limit int `json:"limit,omitempty"` // max results (default 20)
|
||||
}
|
||||
|
||||
// ListPRsOutput is the output for agentic_list_prs.
|
||||
//
|
||||
// out := agentic.ListPRsOutput{Success: true, Count: 2, PRs: []agentic.PRInfo{{Repo: "go-io", Number: 12}}}
|
||||
// out := agentic.ListPRsOutput{Success: true, Count: 2, PRs: []agentic.PRInfo{{Repo: "go-io", Number: 12}}}
|
||||
type ListPRsOutput struct {
|
||||
Success bool `json:"success"`
|
||||
Count int `json:"count"`
|
||||
PRs []PRInfo `json:"prs"`
|
||||
}
|
||||
|
||||
// PRInfo represents a pull request.
|
||||
//
|
||||
// pr := agentic.PRInfo{Repo: "go-io", Number: 12, Title: "Migrate pkg/fs", Branch: "agent/migrate-fs"}
|
||||
// pr := agentic.PRInfo{Repo: "go-io", Number: 12, Title: "Migrate pkg/fs", Branch: "agent/migrate-fs"}
|
||||
type PRInfo struct {
|
||||
Repo string `json:"repo"`
|
||||
Number int `json:"number"`
|
||||
|
|
|
|||
|
|
@ -208,11 +208,8 @@ func (s *PrepSubsystem) OnShutdown(ctx context.Context) core.Result {
|
|||
return core.Result{OK: true}
|
||||
}
|
||||
|
||||
// hydrateWorkspaces scans disk and populates the workspace Registry on startup.
|
||||
// Keyed by workspace name (relative path from workspace root).
|
||||
//
|
||||
// s.hydrateWorkspaces()
|
||||
// s.workspaces.Names() // ["core/go-io/task-5", "ws-blocked", ...]
|
||||
// s.hydrateWorkspaces()
|
||||
// s.workspaces.Names() // ["core/go-io/task-5", "ws-blocked", ...]
|
||||
func (s *PrepSubsystem) hydrateWorkspaces() {
|
||||
if s.workspaces == nil {
|
||||
s.workspaces = core.NewRegistry[*WorkspaceStatus]()
|
||||
|
|
@ -509,12 +506,8 @@ func (s *PrepSubsystem) prepWorkspace(ctx context.Context, _ *mcp.CallToolReques
|
|||
return nil, out, nil
|
||||
}
|
||||
|
||||
// copyRepoSpecs copies RFC spec files from the plans repo into the workspace specs/ folder.
|
||||
// Maps repo name to plans directory: go-io → core/go/io, agent → core/agent, core-bio → core/php/bio.
|
||||
// Preserves subdirectory structure so sub-package specs land in specs/{pkg}/RFC.md.
|
||||
//
|
||||
// s.copyRepoSpecs("/tmp/workspace", "go-io") // copies plans/core/go/io/**/RFC*.md → /tmp/workspace/specs/
|
||||
// s.copyRepoSpecs("/tmp/workspace", "core-bio") // copies plans/core/php/bio/**/RFC*.md → /tmp/workspace/specs/
|
||||
// s.copyRepoSpecs("/tmp/workspace", "go-io") // copies plans/core/go/io/**/RFC*.md → /tmp/workspace/specs/
|
||||
// s.copyRepoSpecs("/tmp/workspace", "core-bio") // copies plans/core/php/bio/**/RFC*.md → /tmp/workspace/specs/
|
||||
func (s *PrepSubsystem) copyRepoSpecs(workspaceDir, repo string) {
|
||||
fs := (&core.Fs{}).NewUnrestricted()
|
||||
|
||||
|
|
@ -570,22 +563,17 @@ func (s *PrepSubsystem) copyRepoSpecs(workspaceDir, repo string) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestPrepWorkspace exposes prepWorkspace for CLI testing.
|
||||
//
|
||||
// _, out, err := prep.TestPrepWorkspace(ctx, input)
|
||||
// _, out, err := prep.TestPrepWorkspace(ctx, input)
|
||||
func (s *PrepSubsystem) TestPrepWorkspace(ctx context.Context, input PrepInput) (*mcp.CallToolResult, PrepOutput, error) {
|
||||
return s.prepWorkspace(ctx, nil, input)
|
||||
}
|
||||
|
||||
// TestBuildPrompt exposes buildPrompt for CLI testing.
|
||||
//
|
||||
// prompt, memories, consumers := prep.TestBuildPrompt(ctx, input, "dev", repoPath)
|
||||
// prompt, memories, consumers := prep.TestBuildPrompt(ctx, input, "dev", repoPath)
|
||||
func (s *PrepSubsystem) TestBuildPrompt(ctx context.Context, input PrepInput, branch, repoPath string) (string, int, int) {
|
||||
return s.buildPrompt(ctx, input, branch, repoPath)
|
||||
}
|
||||
|
||||
// buildPrompt assembles all context into a single prompt string.
|
||||
// Context is gathered from: persona, flow, issue, brain, consumers, git log, wiki, plan.
|
||||
// prompt, memories, consumers := prep.buildPrompt(ctx, input, "dev", "/srv/repos/go-io")
|
||||
func (s *PrepSubsystem) buildPrompt(ctx context.Context, input PrepInput, branch, repoPath string) (string, int, int) {
|
||||
b := core.NewBuilder()
|
||||
memories := 0
|
||||
|
|
|
|||
|
|
@ -8,9 +8,7 @@ import (
|
|||
"github.com/modelcontextprotocol/go-sdk/mcp"
|
||||
)
|
||||
|
||||
// RemoteDispatchInput dispatches a task to a remote core-agent over HTTP.
|
||||
//
|
||||
// input := agentic.RemoteDispatchInput{Host: "charon", Repo: "go-io", Task: "Run the review queue"}
|
||||
// input := agentic.RemoteDispatchInput{Host: "charon", Repo: "go-io", Task: "Run the review queue"}
|
||||
type RemoteDispatchInput struct {
|
||||
Host string `json:"host"` // Remote agent host (e.g. "charon", "10.69.69.165:9101")
|
||||
Repo string `json:"repo"` // Target repo
|
||||
|
|
@ -22,9 +20,7 @@ type RemoteDispatchInput struct {
|
|||
Variables map[string]string `json:"variables,omitempty"` // Template variables
|
||||
}
|
||||
|
||||
// RemoteDispatchOutput is the response from a remote dispatch.
|
||||
//
|
||||
// out := agentic.RemoteDispatchOutput{Success: true, Host: "charon", Repo: "go-io", Agent: "claude:opus"}
|
||||
// out := agentic.RemoteDispatchOutput{Success: true, Host: "charon", Repo: "go-io", Agent: "claude:opus"}
|
||||
type RemoteDispatchOutput struct {
|
||||
Success bool `json:"success"`
|
||||
Host string `json:"host"`
|
||||
|
|
@ -165,7 +161,7 @@ func (s *PrepSubsystem) dispatchRemote(ctx context.Context, _ *mcp.CallToolReque
|
|||
return nil, output, nil
|
||||
}
|
||||
|
||||
// resolveHost maps friendly names to addresses.
|
||||
// addr := resolveHost("charon") // "10.69.69.165:9101"
|
||||
func resolveHost(host string) string {
|
||||
aliases := map[string]string{
|
||||
"charon": "10.69.69.165:9101",
|
||||
|
|
@ -184,7 +180,7 @@ func resolveHost(host string) string {
|
|||
return host
|
||||
}
|
||||
|
||||
// remoteToken gets the auth token for a remote agent.
|
||||
// token := remoteToken("charon")
|
||||
func remoteToken(host string) string {
|
||||
envKey := core.Sprintf("AGENT_TOKEN_%s", core.Upper(host))
|
||||
if token := core.Env(envKey); token != "" {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
// SPDX-License-Identifier: EUPL-1.2
|
||||
|
||||
// MCP remote client helpers.
|
||||
// HTTP transport functions are in transport.go (the ONE net/http file).
|
||||
|
||||
package agentic
|
||||
|
|
|
|||
|
|
@ -8,12 +8,10 @@ import (
|
|||
"github.com/modelcontextprotocol/go-sdk/mcp"
|
||||
)
|
||||
|
||||
// input := agentic.RemoteStatusInput{Host: "charon"}
|
||||
type RemoteStatusInput struct {
|
||||
Host string `json:"host"` // Remote agent host (e.g. "charon")
|
||||
}
|
||||
|
||||
// out := agentic.RemoteStatusOutput{Success: true, Host: "charon"}
|
||||
type RemoteStatusOutput struct {
|
||||
Success bool `json:"success"`
|
||||
Host string `json:"host"`
|
||||
|
|
|
|||
|
|
@ -9,9 +9,7 @@ import (
|
|||
"github.com/modelcontextprotocol/go-sdk/mcp"
|
||||
)
|
||||
|
||||
// ResumeInput is the input for agentic_resume.
|
||||
//
|
||||
// input := agentic.ResumeInput{Workspace: "core/go-scm/task-42", Answer: "Use the existing queue config"}
|
||||
// input := agentic.ResumeInput{Workspace: "core/go-scm/task-42", Answer: "Use the existing queue config"}
|
||||
type ResumeInput struct {
|
||||
Workspace string `json:"workspace"` // workspace name (e.g. "core/go-scm/task-42")
|
||||
Answer string `json:"answer,omitempty"` // answer to the blocked question (written to ANSWER.md)
|
||||
|
|
@ -19,9 +17,7 @@ type ResumeInput struct {
|
|||
DryRun bool `json:"dry_run,omitempty"` // preview without executing
|
||||
}
|
||||
|
||||
// ResumeOutput is the output for agentic_resume.
|
||||
//
|
||||
// out := agentic.ResumeOutput{Success: true, Workspace: "core/go-scm/task-42", Agent: "codex"}
|
||||
// out := agentic.ResumeOutput{Success: true, Workspace: "core/go-scm/task-42", Agent: "codex"}
|
||||
type ResumeOutput struct {
|
||||
Success bool `json:"success"`
|
||||
Workspace string `json:"workspace"`
|
||||
|
|
|
|||
|
|
@ -10,21 +10,18 @@ import (
|
|||
"github.com/modelcontextprotocol/go-sdk/mcp"
|
||||
)
|
||||
|
||||
// input := agentic.ScanInput{Org: "core", Labels: []string{"agentic", "bug"}, Limit: 20}
|
||||
type ScanInput struct {
|
||||
Org string `json:"org,omitempty"`
|
||||
Labels []string `json:"labels,omitempty"`
|
||||
Limit int `json:"limit,omitempty"`
|
||||
}
|
||||
|
||||
// out := agentic.ScanOutput{Success: true, Count: 1, Issues: []agentic.ScanIssue{{Repo: "go-io", Number: 12}}}
|
||||
type ScanOutput struct {
|
||||
Success bool `json:"success"`
|
||||
Count int `json:"count"`
|
||||
Issues []ScanIssue `json:"issues"`
|
||||
}
|
||||
|
||||
// issue := agentic.ScanIssue{Repo: "go-io", Number: 12, Title: "Replace fmt.Errorf"}
|
||||
type ScanIssue struct {
|
||||
Repo string `json:"repo"`
|
||||
Number int `json:"number"`
|
||||
|
|
|
|||
|
|
@ -9,10 +9,8 @@ import (
|
|||
"github.com/modelcontextprotocol/go-sdk/mcp"
|
||||
)
|
||||
|
||||
// input := agentic.ShutdownInput{}
|
||||
type ShutdownInput struct{}
|
||||
|
||||
// out := agentic.ShutdownOutput{Success: true, Running: 3, Message: "draining"}
|
||||
type ShutdownOutput struct {
|
||||
Success bool `json:"success"`
|
||||
Running int `json:"running"`
|
||||
|
|
|
|||
|
|
@ -10,9 +10,7 @@ import (
|
|||
"github.com/modelcontextprotocol/go-sdk/mcp"
|
||||
)
|
||||
|
||||
// WatchInput is the input for agentic_watch.
|
||||
//
|
||||
// input := agentic.WatchInput{Workspaces: []string{"core/go-io/task-42"}, PollInterval: 5, Timeout: 600}
|
||||
// input := agentic.WatchInput{Workspaces: []string{"core/go-io/task-42"}, PollInterval: 5, Timeout: 600}
|
||||
type WatchInput struct {
|
||||
// Workspaces to watch. If empty, watches all running/queued workspaces.
|
||||
Workspaces []string `json:"workspaces,omitempty"`
|
||||
|
|
@ -22,9 +20,7 @@ type WatchInput struct {
|
|||
Timeout int `json:"timeout,omitempty"`
|
||||
}
|
||||
|
||||
// WatchOutput is the result when all watched workspaces complete.
|
||||
//
|
||||
// out := agentic.WatchOutput{Success: true, Completed: []agentic.WatchResult{{Workspace: "core/go-io/task-42", Status: "completed"}}}
|
||||
// out := agentic.WatchOutput{Success: true, Completed: []agentic.WatchResult{{Workspace: "core/go-io/task-42", Status: "completed"}}}
|
||||
type WatchOutput struct {
|
||||
Success bool `json:"success"`
|
||||
Completed []WatchResult `json:"completed"`
|
||||
|
|
@ -32,9 +28,7 @@ type WatchOutput struct {
|
|||
Duration string `json:"duration"`
|
||||
}
|
||||
|
||||
// WatchResult describes one completed workspace.
|
||||
//
|
||||
// result := agentic.WatchResult{Workspace: "core/go-io/task-42", Agent: "codex", Repo: "go-io", Status: "completed"}
|
||||
// result := agentic.WatchResult{Workspace: "core/go-io/task-42", Agent: "codex", Repo: "go-io", Status: "completed"}
|
||||
type WatchResult struct {
|
||||
Workspace string `json:"workspace"`
|
||||
Agent string `json:"agent"`
|
||||
|
|
@ -208,7 +202,7 @@ func (s *PrepSubsystem) findActiveWorkspaces() []string {
|
|||
return active
|
||||
}
|
||||
|
||||
// resolveWorkspaceDir converts a workspace name to full path.
|
||||
// dir := s.resolveWorkspaceDir("core/go-io/task-42")
|
||||
func (s *PrepSubsystem) resolveWorkspaceDir(workspaceName string) string {
|
||||
if core.PathIsAbs(workspaceName) {
|
||||
return workspaceName
|
||||
|
|
|
|||
|
|
@ -66,8 +66,8 @@ func Register(coreApp *core.Core) core.Result {
|
|||
|
||||
// c.Action("runner.dispatch").Run(ctx, core.NewOptions(
|
||||
//
|
||||
// core.Option{Key: "repo", Value: "go-io"},
|
||||
// core.Option{Key: "agent", Value: "codex"},
|
||||
// core.Option{Key: "repo", Value: "go-io"},
|
||||
// core.Option{Key: "agent", Value: "codex"},
|
||||
//
|
||||
// ))
|
||||
// c.Action("runner.status").Run(ctx, core.NewOptions())
|
||||
|
|
@ -393,9 +393,7 @@ type AgentNotification struct {
|
|||
Limit int `json:"limit"`
|
||||
}
|
||||
|
||||
// WorkspaceQuery is the QUERY type for workspace lookups.
|
||||
//
|
||||
// result := c.QUERY(runner.WorkspaceQuery{Status: "running"})
|
||||
// result := c.QUERY(runner.WorkspaceQuery{Status: "running"})
|
||||
type WorkspaceQuery struct {
|
||||
Name string
|
||||
Status string
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue