feat(agentic): add dispatch lifecycle commands
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
dc9a81e101
commit
c55f4e4f5e
2 changed files with 100 additions and 0 deletions
|
|
@ -20,6 +20,9 @@ func (s *PrepSubsystem) registerCommands(ctx context.Context) {
|
|||
c.Command("run/task", core.Command{Description: "Run a single task end-to-end", Action: s.cmdRunTask})
|
||||
c.Command("run/orchestrator", core.Command{Description: "Run the queue orchestrator (standalone, no MCP)", Action: s.cmdOrchestrator})
|
||||
c.Command("dispatch", core.Command{Description: "Dispatch queued agents", Action: s.cmdDispatch})
|
||||
c.Command("dispatch/start", core.Command{Description: "Start the dispatch queue runner", Action: s.cmdDispatchStart})
|
||||
c.Command("dispatch/shutdown", core.Command{Description: "Freeze the dispatch queue gracefully", Action: s.cmdDispatchShutdown})
|
||||
c.Command("dispatch/shutdown-now", core.Command{Description: "Hard stop the dispatch queue and kill running agents", Action: s.cmdDispatchShutdownNow})
|
||||
c.Command("prep", core.Command{Description: "Prepare a workspace: clone repo, build prompt", Action: s.cmdPrep})
|
||||
c.Command("prep-workspace", core.Command{Description: "Prepare a workspace: clone repo, build prompt", Action: s.cmdPrep})
|
||||
c.Command("generate", core.Command{Description: "Generate content from a prompt using the platform content pipeline", Action: s.cmdGenerate})
|
||||
|
|
@ -110,6 +113,49 @@ func (s *PrepSubsystem) cmdDispatch(_ core.Options) core.Result {
|
|||
return s.runDispatchLoop("dispatch")
|
||||
}
|
||||
|
||||
func (s *PrepSubsystem) cmdDispatchStart(_ core.Options) core.Result {
|
||||
_, output, err := s.dispatchStart(s.commandContext(), nil, ShutdownInput{})
|
||||
if err != nil {
|
||||
core.Print(nil, "error: %v", err)
|
||||
return core.Result{Value: err, OK: false}
|
||||
}
|
||||
|
||||
if output.Message != "" {
|
||||
core.Print(nil, "%s", output.Message)
|
||||
}
|
||||
return core.Result{Value: output, OK: true}
|
||||
}
|
||||
|
||||
func (s *PrepSubsystem) cmdDispatchShutdown(_ core.Options) core.Result {
|
||||
_, output, err := s.shutdownGraceful(s.commandContext(), nil, ShutdownInput{})
|
||||
if err != nil {
|
||||
core.Print(nil, "error: %v", err)
|
||||
return core.Result{Value: err, OK: false}
|
||||
}
|
||||
|
||||
if output.Message != "" {
|
||||
core.Print(nil, "%s", output.Message)
|
||||
}
|
||||
return core.Result{Value: output, OK: true}
|
||||
}
|
||||
|
||||
func (s *PrepSubsystem) cmdDispatchShutdownNow(_ core.Options) core.Result {
|
||||
_, output, err := s.shutdownNow(s.commandContext(), nil, ShutdownInput{})
|
||||
if err != nil {
|
||||
core.Print(nil, "error: %v", err)
|
||||
return core.Result{Value: err, OK: false}
|
||||
}
|
||||
|
||||
if output.Message != "" {
|
||||
core.Print(nil, "%s", output.Message)
|
||||
}
|
||||
if output.Running > 0 || output.Queued > 0 {
|
||||
core.Print(nil, "running: %d", output.Running)
|
||||
core.Print(nil, "queued: %d", output.Queued)
|
||||
}
|
||||
return core.Result{Value: output, OK: true}
|
||||
}
|
||||
|
||||
func (s *PrepSubsystem) runDispatchLoop(label string) core.Result {
|
||||
ctx := s.commandContext()
|
||||
core.Print(nil, "core-agent %s running (pid %s)", label, core.Env("PID"))
|
||||
|
|
|
|||
|
|
@ -1146,6 +1146,57 @@ func TestCommands_CmdDispatch_Good_CancelledCtx(t *testing.T) {
|
|||
assert.True(t, r.OK)
|
||||
}
|
||||
|
||||
func TestCommands_CmdDispatchStart_Good(t *testing.T) {
|
||||
s, c := testPrepWithCore(t, nil)
|
||||
called := false
|
||||
c.Action("runner.start", func(_ context.Context, _ core.Options) core.Result {
|
||||
called = true
|
||||
return core.Result{OK: true}
|
||||
})
|
||||
|
||||
output := captureStdout(t, func() {
|
||||
r := s.cmdDispatchStart(core.NewOptions())
|
||||
assert.True(t, r.OK)
|
||||
})
|
||||
|
||||
assert.True(t, called)
|
||||
assert.Contains(t, output, "dispatch started")
|
||||
}
|
||||
|
||||
func TestCommands_CmdDispatchShutdown_Good(t *testing.T) {
|
||||
s, c := testPrepWithCore(t, nil)
|
||||
called := false
|
||||
c.Action("runner.stop", func(_ context.Context, _ core.Options) core.Result {
|
||||
called = true
|
||||
return core.Result{OK: true}
|
||||
})
|
||||
|
||||
output := captureStdout(t, func() {
|
||||
r := s.cmdDispatchShutdown(core.NewOptions())
|
||||
assert.True(t, r.OK)
|
||||
})
|
||||
|
||||
assert.True(t, called)
|
||||
assert.Contains(t, output, "queue frozen")
|
||||
}
|
||||
|
||||
func TestCommands_CmdDispatchShutdownNow_Good(t *testing.T) {
|
||||
s, c := testPrepWithCore(t, nil)
|
||||
called := false
|
||||
c.Action("runner.kill", func(_ context.Context, _ core.Options) core.Result {
|
||||
called = true
|
||||
return core.Result{OK: true}
|
||||
})
|
||||
|
||||
output := captureStdout(t, func() {
|
||||
r := s.cmdDispatchShutdownNow(core.NewOptions())
|
||||
assert.True(t, r.OK)
|
||||
})
|
||||
|
||||
assert.True(t, called)
|
||||
assert.Contains(t, output, "killed all agents")
|
||||
}
|
||||
|
||||
func TestCommands_ParseIntStr_Good(t *testing.T) {
|
||||
assert.Equal(t, 42, parseIntString("42"))
|
||||
assert.Equal(t, 123, parseIntString("issue-123"))
|
||||
|
|
@ -1166,6 +1217,9 @@ func TestCommands_RegisterCommands_Good_AllRegistered(t *testing.T) {
|
|||
assert.Contains(t, cmds, "run/task")
|
||||
assert.Contains(t, cmds, "run/orchestrator")
|
||||
assert.Contains(t, cmds, "dispatch")
|
||||
assert.Contains(t, cmds, "dispatch/start")
|
||||
assert.Contains(t, cmds, "dispatch/shutdown")
|
||||
assert.Contains(t, cmds, "dispatch/shutdown-now")
|
||||
assert.Contains(t, cmds, "prep")
|
||||
assert.Contains(t, cmds, "complete")
|
||||
assert.Contains(t, cmds, "scan")
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue