feat(agentic): add content generate command
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
5c5d9c33bf
commit
1fade56b17
3 changed files with 86 additions and 0 deletions
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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().
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue