feat(agentic): expose workspace watch command
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
dbbc09b09c
commit
02aea97b7d
3 changed files with 59 additions and 0 deletions
|
|
@ -13,6 +13,9 @@ func (s *PrepSubsystem) registerWorkspaceCommands() {
|
|||
c.Command("workspace/list", core.Command{Description: "List all agent workspaces with status", Action: s.cmdWorkspaceList})
|
||||
c.Command("workspace/clean", core.Command{Description: "Remove completed/failed/blocked workspaces", Action: s.cmdWorkspaceClean})
|
||||
c.Command("workspace/dispatch", core.Command{Description: "Dispatch an agent to work on a repo task", Action: s.cmdWorkspaceDispatch})
|
||||
c.Command("workspace/watch", core.Command{Description: "Watch workspaces until they complete", Action: s.cmdWorkspaceWatch})
|
||||
c.Command("watch", core.Command{Description: "Watch workspaces until they complete", Action: s.cmdWorkspaceWatch})
|
||||
c.Command("agentic:watch", core.Command{Description: "Watch workspaces until they complete", Action: s.cmdWorkspaceWatch})
|
||||
}
|
||||
|
||||
func (s *PrepSubsystem) cmdWorkspaceList(_ core.Options) core.Result {
|
||||
|
|
@ -117,6 +120,27 @@ func (s *PrepSubsystem) cmdWorkspaceDispatch(options core.Options) core.Result {
|
|||
return core.Result{OK: true}
|
||||
}
|
||||
|
||||
func (s *PrepSubsystem) cmdWorkspaceWatch(options core.Options) core.Result {
|
||||
watchOptions := core.NewOptions(options.Items()...)
|
||||
if watchOptions.String("workspace") == "" && len(optionStringSliceValue(watchOptions, "workspaces")) == 0 {
|
||||
if workspace := optionStringValue(options, "_arg"); workspace != "" {
|
||||
watchOptions.Set("workspace", workspace)
|
||||
}
|
||||
}
|
||||
input := watchInputFromOptions(watchOptions)
|
||||
|
||||
_, output, err := s.watch(s.commandContext(), nil, input)
|
||||
if err != nil {
|
||||
core.Print(nil, "error: %v", err)
|
||||
return core.Result{Value: err, OK: false}
|
||||
}
|
||||
|
||||
core.Print(nil, "completed: %d", len(output.Completed))
|
||||
core.Print(nil, "failed: %d", len(output.Failed))
|
||||
core.Print(nil, "duration: %s", output.Duration)
|
||||
return core.Result{Value: output, OK: output.Success}
|
||||
}
|
||||
|
||||
func workspaceDispatchInputFromOptions(options core.Options) DispatchInput {
|
||||
dispatchOptions := core.NewOptions(options.Items()...)
|
||||
if dispatchOptions.String("repo") == "" {
|
||||
|
|
|
|||
|
|
@ -158,6 +158,38 @@ func TestCommandsworkspace_CmdWorkspaceDispatch_Ugly_AllFieldsSet(t *testing.T)
|
|||
assert.False(t, r.OK)
|
||||
}
|
||||
|
||||
func TestCommandsworkspace_CmdWorkspaceWatch_Good_ExplicitWorkspaceCompletes(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", root)
|
||||
|
||||
writeWatchStatus(root, "core/go-io/task-42", WorkspaceStatus{
|
||||
Status: "ready-for-review",
|
||||
Repo: "go-io",
|
||||
Agent: "codex",
|
||||
PRURL: "https://forge.lthn.ai/core/go-io/pulls/42",
|
||||
})
|
||||
|
||||
c := core.New()
|
||||
s := &PrepSubsystem{
|
||||
ServiceRuntime: core.NewServiceRuntime(c, AgentOptions{}),
|
||||
backoff: make(map[string]time.Time),
|
||||
failCount: make(map[string]int),
|
||||
}
|
||||
|
||||
r := s.cmdWorkspaceWatch(core.NewOptions(
|
||||
core.Option{Key: "workspace", Value: "core/go-io/task-42"},
|
||||
core.Option{Key: "poll_interval", Value: 1},
|
||||
core.Option{Key: "timeout", Value: 2},
|
||||
))
|
||||
assert.True(t, r.OK)
|
||||
|
||||
output, ok := r.Value.(WatchOutput)
|
||||
assert.True(t, ok)
|
||||
assert.True(t, output.Success)
|
||||
assert.Len(t, output.Completed, 1)
|
||||
assert.Equal(t, "core/go-io/task-42", output.Completed[0].Workspace)
|
||||
}
|
||||
|
||||
func TestCommandsworkspace_WorkspaceDispatchInputFromOptions_Good_MapsFullContract(t *testing.T) {
|
||||
input := workspaceDispatchInputFromOptions(core.NewOptions(
|
||||
core.Option{Key: "_arg", Value: "go-io"},
|
||||
|
|
|
|||
|
|
@ -658,6 +658,9 @@ func TestPrep_OnStartup_Good_RegistersGenerateCommand(t *testing.T) {
|
|||
assert.Contains(t, c.Commands(), "dispatch/sync")
|
||||
assert.Contains(t, c.Commands(), "agentic:plan")
|
||||
assert.Contains(t, c.Commands(), "prep-workspace")
|
||||
assert.Contains(t, c.Commands(), "watch")
|
||||
assert.Contains(t, c.Commands(), "workspace/watch")
|
||||
assert.Contains(t, c.Commands(), "agentic:watch")
|
||||
assert.Contains(t, c.Commands(), "brain/ingest")
|
||||
assert.Contains(t, c.Commands(), "brain/seed-memory")
|
||||
assert.Contains(t, c.Commands(), "brain/list")
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue