feat: RoutingWorkflow + LLM Router + Memory Activity
ci / test (push) Successful in 2m12s

- Add RoutingWorkflow: generic state machine executor for WorkflowSpec
- Add LLM Router: natural language → WorkflowSpec generation
- Add RetrieveMemoryActivity: query poimen-memory for context
- Add activities: AnalyzeCode, SecurityScan, GenerateReport, Notify, etc.
- Add agent-prompts/router: LLM prompt documentation
- Extend starter with --route flag for routing workflows
- Remove orchestrator job (trigger via API/message instead)
- Clean up: move docs to Desktop, add .gitignore for *.md
This commit is contained in:
Test
2026-09-02 19:21:53 -07:00
parent 5a465b145c
commit a0e64224a7
74 changed files with 3950 additions and 12421 deletions
+305
View File
@@ -0,0 +1,305 @@
package routing
import (
"encoding/json"
"testing"
)
func TestParseIntentResponse(t *testing.T) {
tests := []struct {
name string
response string
wantErr bool
validate func(*testing.T, *Intent)
}{
{
name: "basic intent",
response: `{
"activities": ["CloneRepoActivity", "AnalyzeCodeActivity"],
"parameters": {"repo": "https://github.com/test/repo"},
"isCron": false,
"workflowName": "analyze-repo"
}`,
wantErr: false,
validate: func(t *testing.T, intent *Intent) {
if len(intent.Activities) != 2 {
t.Errorf("expected 2 activities, got %d", len(intent.Activities))
}
if intent.Activities[0] != "CloneRepoActivity" {
t.Errorf("expected CloneRepoActivity first, got %s", intent.Activities[0])
}
if intent.IsCron {
t.Error("expected isCron=false")
}
},
},
{
name: "cron intent",
response: `{
"activities": ["CloneRepoActivity", "SecurityScanActivity"],
"parameters": {"repo": "https://github.com/test/repo"},
"isCron": true,
"cronSchedule": "0 2 * * *",
"cronTimezone": "America/New_York",
"workflowName": "daily-security-scan"
}`,
wantErr: false,
validate: func(t *testing.T, intent *Intent) {
if !intent.IsCron {
t.Error("expected isCron=true")
}
if intent.CronSchedule != "0 2 * * *" {
t.Errorf("expected cron schedule '0 2 * * *', got %s", intent.CronSchedule)
}
if intent.CronTimezone != "America/New_York" {
t.Errorf("expected timezone 'America/New_York', got %s", intent.CronTimezone)
}
},
},
{
name: "with markdown code block",
response: "```json\n{\"activities\": [\"CloneRepoActivity\"], \"parameters\": {}, \"isCron\": false}\n```",
wantErr: false,
validate: func(t *testing.T, intent *Intent) {
if len(intent.Activities) != 1 {
t.Errorf("expected 1 activity, got %d", len(intent.Activities))
}
},
},
{
name: "defaults applied",
response: `{"activities": ["CloneRepoActivity"], "parameters": {}}`,
wantErr: false,
validate: func(t *testing.T, intent *Intent) {
if intent.CronTimezone != "UTC" {
t.Errorf("expected default timezone UTC, got %s", intent.CronTimezone)
}
if intent.ErrorHandling != "retry" {
t.Errorf("expected default errorHandling 'retry', got %s", intent.ErrorHandling)
}
if intent.WorkflowName != "generated-workflow" {
t.Errorf("expected default workflowName, got %s", intent.WorkflowName)
}
},
},
{
name: "invalid json",
response: "this is not json",
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
intent, err := parseIntentResponse(tt.response)
if tt.wantErr {
if err == nil {
t.Error("expected error, got nil")
}
return
}
if err != nil {
t.Errorf("unexpected error: %v", err)
return
}
if tt.validate != nil {
tt.validate(t, intent)
}
})
}
}
func TestBuildSpec(t *testing.T) {
// Load knowledge base
kb, err := LoadKnowledgeBaseFromDefaultPath()
if err != nil {
t.Fatalf("failed to load knowledge base: %v", err)
}
router := &LLMRouter{
knowledgeBase: kb,
}
intent := &Intent{
Activities: []string{"CloneRepoActivity", "AnalyzeCodeActivity", "SecurityScanActivity"},
Parameters: map[string]interface{}{"repo": "https://github.com/test/repo", "branch": "main"},
WorkflowName: "test-workflow",
ErrorHandling: "retry",
}
input := LLMRouterInput{
Message: "Analyze repo for security",
Context: map[string]interface{}{},
}
spec, err := router.buildSpec(intent, input)
if err != nil {
t.Fatalf("buildSpec failed: %v", err)
}
// Validate spec
if spec.Name != "test-workflow" {
t.Errorf("expected name 'test-workflow', got %s", spec.Name)
}
if len(spec.States) < 3 {
t.Errorf("expected at least 3 states, got %d", len(spec.States))
}
// First state should be CloneRepoActivity
if spec.States[0].Resource != "CloneRepoActivity" {
t.Errorf("expected first state to be CloneRepoActivity, got %s", spec.States[0].Resource)
}
// Last activity state should have End=true
lastActivityIdx := len(spec.States) - 1
if spec.States[lastActivityIdx].Type == StateTypeFail {
lastActivityIdx--
}
if !spec.States[lastActivityIdx].End {
t.Error("expected last activity state to have End=true")
}
// Check retry policy on flaky activity (AnalyzeCodeActivity)
for _, state := range spec.States {
if state.Resource == "AnalyzeCodeActivity" {
if state.Retry == nil {
t.Error("expected retry policy on flaky activity")
} else if state.Retry.MaxAttempts != 3 {
t.Errorf("expected 3 max attempts for flaky activity, got %d", state.Retry.MaxAttempts)
}
if len(state.Catch) == 0 {
t.Error("expected catch clause on flaky activity")
}
}
}
}
func TestBuildCronSpec(t *testing.T) {
kb, err := LoadKnowledgeBaseFromDefaultPath()
if err != nil {
t.Fatalf("failed to load knowledge base: %v", err)
}
router := &LLMRouter{
knowledgeBase: kb,
}
intent := &Intent{
Activities: []string{"CloneRepoActivity", "SecurityScanActivity"},
Parameters: map[string]interface{}{"repo": "https://github.com/test/repo"},
IsCron: true,
CronSchedule: "0 2 * * *",
CronTimezone: "UTC",
WorkflowName: "daily-scan",
}
input := LLMRouterInput{
Message: "Run security scan daily at 2 AM",
}
cronSpec, err := router.buildCronSpec(intent, input)
if err != nil {
t.Fatalf("buildCronSpec failed: %v", err)
}
if cronSpec.Type != "CronWorkflow" {
t.Errorf("expected type 'CronWorkflow', got %s", cronSpec.Type)
}
if cronSpec.Schedule != "0 2 * * *" {
t.Errorf("expected schedule '0 2 * * *', got %s", cronSpec.Schedule)
}
if cronSpec.Timezone != "UTC" {
t.Errorf("expected timezone 'UTC', got %s", cronSpec.Timezone)
}
if !cronSpec.EnableHistory {
t.Error("expected EnableHistory=true")
}
}
func TestBuildParameters(t *testing.T) {
kb, err := LoadKnowledgeBaseFromDefaultPath()
if err != nil {
t.Fatalf("failed to load knowledge base: %v", err)
}
router := &LLMRouter{
knowledgeBase: kb,
}
// Test first activity (CloneRepoActivity) - should use input references
cloneAct := kb.GetActivity("CloneRepoActivity")
intent := &Intent{
Activities: []string{"CloneRepoActivity", "AnalyzeCodeActivity"},
Parameters: map[string]interface{}{"repo": "https://github.com/test/repo"},
}
params := router.buildParameters(cloneAct, intent, 0)
if params["repo"] != "https://github.com/test/repo" {
t.Errorf("expected repo from parameters, got %v", params["repo"])
}
// Test second activity (AnalyzeCodeActivity) - should reference previous output
analyzeAct := kb.GetActivity("AnalyzeCodeActivity")
params = router.buildParameters(analyzeAct, intent, 1)
if params["path"] != "${CloneRepoActivity.output.path}" {
t.Errorf("expected JSONPath reference to CloneRepoActivity.output.path, got %v", params["path"])
}
}
func TestBuildRetryPolicy(t *testing.T) {
kb, err := LoadKnowledgeBaseFromDefaultPath()
if err != nil {
t.Fatalf("failed to load knowledge base: %v", err)
}
router := &LLMRouter{
knowledgeBase: kb,
}
// Flaky activity with retry error handling
analyzeAct := kb.GetActivity("AnalyzeCodeActivity")
intent := &Intent{ErrorHandling: "retry"}
policy := router.buildRetryPolicy(analyzeAct, intent)
if policy.MaxAttempts != 3 {
t.Errorf("expected 3 max attempts for flaky activity, got %d", policy.MaxAttempts)
}
if policy.BackoffRate != 2.0 {
t.Errorf("expected backoff rate 2.0, got %f", policy.BackoffRate)
}
// Fail-fast error handling
intent = &Intent{ErrorHandling: "fail-fast"}
policy = router.buildRetryPolicy(analyzeAct, intent)
if policy.MaxAttempts != 1 {
t.Errorf("expected 1 max attempt for fail-fast, got %d", policy.MaxAttempts)
}
}
func TestIntentJSONMarshal(t *testing.T) {
intent := &Intent{
Activities: []string{"CloneRepoActivity"},
Parameters: map[string]interface{}{"repo": "https://test"},
IsCron: true,
CronSchedule: "0 * * * *",
CronTimezone: "UTC",
WorkflowName: "test",
ErrorHandling: "retry",
}
data, err := json.Marshal(intent)
if err != nil {
t.Fatalf("marshal failed: %v", err)
}
var decoded Intent
if err := json.Unmarshal(data, &decoded); err != nil {
t.Fatalf("unmarshal failed: %v", err)
}
if decoded.CronSchedule != intent.CronSchedule {
t.Errorf("expected schedule %s, got %s", intent.CronSchedule, decoded.CronSchedule)
}
}