feat(agentic): add content generate command

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Virgil 2026-04-01 10:40:28 +00:00
parent 5c5d9c33bf
commit 1fade56b17
3 changed files with 86 additions and 0 deletions

View file

@ -20,6 +20,7 @@ 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("prep", 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})
c.Command("status", core.Command{Description: "List agent workspace statuses", Action: s.cmdStatus})
c.Command("prompt", core.Command{Description: "Build and display an agent prompt for a repo", Action: s.cmdPrompt})
c.Command("extract", core.Command{Description: "Extract a workspace template to a directory", Action: s.cmdExtract})
@ -150,6 +151,50 @@ func (s *PrepSubsystem) cmdPrep(options core.Options) core.Result {
return core.Result{OK: true}
}
func (s *PrepSubsystem) cmdGenerate(options core.Options) core.Result {
prompt := optionStringValue(options, "prompt", "_arg")
if prompt == "" {
core.Print(nil, "usage: core-agent generate --prompt=\"Draft a release note\" [--provider=claude] [--config='{\"max_tokens\":4000}']")
return core.Result{Value: core.E("agentic.cmdGenerate", "prompt is required", nil), OK: false}
}
result := s.handleContentGenerate(s.commandContext(), core.NewOptions(
core.Option{Key: "prompt", Value: prompt},
core.Option{Key: "provider", Value: options.String("provider")},
core.Option{Key: "config", Value: options.String("config")},
))
if !result.OK {
err := commandResultError("agentic.cmdGenerate", result)
core.Print(nil, "error: %v", err)
return core.Result{Value: err, OK: false}
}
output, ok := result.Value.(ContentGenerateOutput)
if !ok {
err := core.E("agentic.cmdGenerate", "invalid content generate output", nil)
core.Print(nil, "error: %v", err)
return core.Result{Value: err, OK: false}
}
if output.Result.Provider != "" {
core.Print(nil, "provider: %s", output.Result.Provider)
}
if output.Result.Model != "" {
core.Print(nil, "model: %s", output.Result.Model)
}
if output.Result.Status != "" {
core.Print(nil, "status: %s", output.Result.Status)
}
if output.Result.Content != "" {
core.Print(nil, "content: %s", output.Result.Content)
}
if output.Result.InputTokens > 0 || output.Result.OutputTokens > 0 {
core.Print(nil, "tokens: %d in / %d out", output.Result.InputTokens, output.Result.OutputTokens)
}
return core.Result{OK: true}
}
func (s *PrepSubsystem) cmdStatus(_ core.Options) core.Result {
workspaceRoot := WorkspaceRoot()
filesystem := s.Core().Fs()

View file

@ -690,6 +690,35 @@ func TestCommands_CmdPrompt_Good_DefaultTask(t *testing.T) {
assert.True(t, r.OK)
}
func TestCommands_CmdGenerate_Bad_MissingPrompt(t *testing.T) {
s, _ := testPrepWithCore(t, nil)
r := s.cmdGenerate(core.NewOptions())
assert.False(t, r.OK)
}
func TestCommands_CmdGenerate_Good(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, "/v1/content/generate", r.URL.Path)
assert.Equal(t, http.MethodPost, r.Method)
_, _ = w.Write([]byte(`{"data":{"id":"gen_1","provider":"claude","model":"claude-3.7-sonnet","content":"Release notes draft","input_tokens":12,"output_tokens":48,"status":"completed"}}`))
}))
defer server.Close()
s := testPrepWithPlatformServer(t, server, "secret-token")
output := captureStdout(t, func() {
r := s.cmdGenerate(core.NewOptions(
core.Option{Key: "_arg", Value: "Draft a release note"},
core.Option{Key: "provider", Value: "claude"},
))
assert.True(t, r.OK)
})
assert.Contains(t, output, "provider: claude")
assert.Contains(t, output, "model: claude-3.7-sonnet")
assert.Contains(t, output, "status: completed")
assert.Contains(t, output, "content: Release notes draft")
}
func TestCommands_CmdExtract_Good(t *testing.T) {
s, _ := testPrepWithCore(t, nil)
target := core.JoinPath(t.TempDir(), "extract-test")

View file

@ -570,6 +570,18 @@ func TestPrep_OnStartup_Good_RegistersPlatformCommandAlias(t *testing.T) {
assert.Contains(t, c.Commands(), "fleet/events")
}
func TestPrep_OnStartup_Good_RegistersGenerateCommand(t *testing.T) {
t.Setenv("CORE_WORKSPACE", t.TempDir())
t.Setenv("CORE_AGENT_DISPATCH", "")
c := core.New(core.WithOption("name", "test"))
s := NewPrep()
s.ServiceRuntime = core.NewServiceRuntime(c, AgentOptions{})
require.True(t, s.OnStartup(context.Background()).OK)
assert.Contains(t, c.Commands(), "generate")
}
func TestPrep_OnStartup_Bad(t *testing.T) {
// OnStartup with nil ServiceRuntime — panics because
// registerCommands calls s.Core().Command().