94 lines
2.5 KiB
Go
94 lines
2.5 KiB
Go
package action
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/rockliang/poimen/workflows/action/llm"
|
|
"github.com/rockliang/poimen/workflows/prompts"
|
|
"github.com/rockliang/poimen/workflows/statemachine"
|
|
"go.temporal.io/sdk/activity"
|
|
)
|
|
|
|
// ImplementerInput is input to ImplementerActivity.
|
|
type ImplementerInput struct {
|
|
Config statemachine.OrchestratorConfig
|
|
TaskID string
|
|
WorktreePath string
|
|
Lessons string // "known errors — do not repeat" section
|
|
}
|
|
|
|
// ImplementerOutput is the output of ImplementerActivity.
|
|
type ImplementerOutput struct {
|
|
Success bool
|
|
Changes string // summary of changes made
|
|
}
|
|
|
|
// ImplementerActivity calls the Implementer LLM to implement the task.
|
|
func ImplementerActivity(ctx context.Context, in ImplementerInput) (ImplementerOutput, error) {
|
|
// Record heartbeat
|
|
activity.RecordHeartbeat(ctx, "starting implementer for "+in.TaskID)
|
|
|
|
// Get LLM client
|
|
client, err := llm.NewClient()
|
|
if err != nil {
|
|
return ImplementerOutput{}, fmt.Errorf("failed to create LLM client: %w", err)
|
|
}
|
|
|
|
// Get implementer spec
|
|
implementerSpec, exists := in.Config.RolePrompts["implementer"]
|
|
if !exists {
|
|
return ImplementerOutput{}, fmt.Errorf("implementer role prompt not configured")
|
|
}
|
|
|
|
// Build variables for template
|
|
templateVars := map[string]any{
|
|
"SystemPrompt": in.Config.SystemPrompt,
|
|
"Task": in.TaskID,
|
|
"WorktreePath": in.WorktreePath,
|
|
}
|
|
|
|
// Inject lessons if provided
|
|
if in.Lessons != "" {
|
|
templateVars["Lessons"] = in.Lessons
|
|
}
|
|
|
|
// Render template
|
|
var templateContent string
|
|
if implementerSpec.RawTemplate != "" {
|
|
templateContent = implementerSpec.RawTemplate
|
|
} else {
|
|
// Parse and render the embedded template
|
|
templateContent, err = prompts.Render(implementerSpec.TemplateRef, templateVars)
|
|
if err != nil {
|
|
return ImplementerOutput{}, fmt.Errorf("failed to render implementer template: %w", err)
|
|
}
|
|
}
|
|
|
|
// Call LLM
|
|
messages := []llm.MessageParam{
|
|
{
|
|
Role: "user",
|
|
Content: templateContent,
|
|
},
|
|
}
|
|
|
|
response, err := client.CreateMessage(ctx, llm.MessageInput{
|
|
Model: implementerSpec.Model,
|
|
SystemPrompt: in.Config.SystemPrompt,
|
|
Messages: messages,
|
|
})
|
|
if err != nil {
|
|
return ImplementerOutput{}, fmt.Errorf("implementer LLM call failed: %w", err)
|
|
}
|
|
|
|
// Record progress
|
|
activity.RecordHeartbeat(ctx, "implementer completed for "+in.TaskID)
|
|
|
|
// Return success (in full implementation would parse response and execute tool calls)
|
|
return ImplementerOutput{
|
|
Success: true,
|
|
Changes: response,
|
|
}, nil
|
|
}
|