name: genkit-test description: "Validate AI generation packages with a chat UI and API backend" version: 1 vars: project_name: "" service_name: "ai-gateway" app_name: "chat-ui" feature_slug: "ai-chat" steps: # --- Infrastructure --- create-project: action: api method: POST endpoint: /project body: name: "{{ .vars.project_name }}" description: "Genkit validation: AI chat with text and image generation" outputs: - project_id: .data.name - domain: .data.domain add-service: description: Add AI gateway service depends_on: [create-project] action: api method: POST endpoint: "/projects/{{ .outputs.create-project.project_id }}/components" body: type: service name: "{{ .vars.service_name }}" add-ui: description: Add React chat UI depends_on: [create-project] action: api method: POST endpoint: "/projects/{{ .outputs.create-project.project_id }}/components" body: type: app-react name: "{{ .vars.app_name }}" wait-init: depends_on: [add-service, add-ui] action: wait_pipeline project_id: "{{ .outputs.create-project.project_id }}" max_attempts: 120 poll_interval: 5 # --- SDLC: Build AI Endpoints --- create-feature: depends_on: [wait-init] action: api method: POST endpoint: "/projects/{{ .outputs.create-project.project_id }}/sdlc/features" body: slug: "{{ .vars.feature_slug }}" title: "AI Generation Endpoints" implement-ai: description: "Agent implements text and image generation endpoints" depends_on: [create-feature] action: api method: POST endpoint: "/projects/{{ .outputs.create-project.project_id }}/builds" body: prompt: | /implement-feature {{ .vars.feature_slug }} --requirements ' Use pkg/textgen and pkg/mediagen to create AI generation endpoints. Environment variables available: LAOZHANG_API_KEY, GEMINI_API_KEY Endpoints to implement: 1. GET /health/providers - Check AI provider connectivity - Initialize textgen.Manager with ProductionConfig - Return provider names and health status 2. POST /chat - Text generation Request: {"message": "string", "system_prompt": "string (optional)"} - Use textgen.Manager.GenerateText() - Return: {"response": "string", "provider": "string"} 3. POST /generate-image - Image generation Request: {"prompt": "string"} - Use mediagen.Manager.GenerateImage() - Return: {"image_base64": "string", "provider": "string"} Use ProductionConfig for both managers (LaoZhang primary, Gemini fallback). Handle errors gracefully with proper HTTP status codes. ' auto_commit: true auto_push: true git_clone_url: "https://git.threesix.ai/jordan/{{ .outputs.create-project.project_id }}.git" outputs: - build_id: .data.task_id wait-build: description: Wait for agent code generation depends_on: [implement-ai] action: wait_build build_id: "{{ .outputs.implement-ai.build_id }}" max_attempts: 120 poll_interval: 5 wait-deploy: depends_on: [wait-build] action: wait_pipeline project_id: "{{ .outputs.create-project.project_id }}" max_attempts: 120 poll_interval: 5 # --- Verification --- verify-service-health: description: "Verify the AI service is running" depends_on: [wait-deploy] action: shell command: | DOMAIN="{{ .outputs.create-project.domain }}" SERVICE_NAME="{{ .vars.service_name }}" HEALTH=$(curl -s "https://$DOMAIN/api/$SERVICE_NAME/health" | jq -r '.data.status // .status // empty') if [ "$HEALTH" == "healthy" ] || [ "$HEALTH" == "ok" ]; then echo "Service healthy" exit 0 else echo "Service not healthy: $HEALTH" curl -s "https://$DOMAIN/api/$SERVICE_NAME/health" | jq . exit 1 fi verify-provider-health: description: "Verify AI providers are accessible" depends_on: [verify-service-health] on_error: continue action: shell command: | DOMAIN="{{ .outputs.create-project.domain }}" SERVICE_NAME="{{ .vars.service_name }}" echo "Checking provider health..." RESP=$(curl -s "https://$DOMAIN/api/$SERVICE_NAME/health/providers") echo "$RESP" | jq . # Check if we got any provider info (success even if some providers are down) if echo "$RESP" | jq -e '.data // .providers // .' > /dev/null 2>&1; then echo "Provider health endpoint working" exit 0 else echo "Provider health check failed" exit 1 fi verify-text-generation: description: "Test text generation endpoint" depends_on: [verify-provider-health] on_error: continue action: shell command: | DOMAIN="{{ .outputs.create-project.domain }}" SERVICE_NAME="{{ .vars.service_name }}" echo "Testing text generation..." RESP=$(curl -s -X POST "https://$DOMAIN/api/$SERVICE_NAME/chat" \ -H "Content-Type: application/json" \ -d '{"message": "What is 2+2? Reply with just the number."}') echo "$RESP" | jq . # Check if we got a response RESPONSE=$(echo "$RESP" | jq -r '.response // .data.response // .text // empty') if [ -n "$RESPONSE" ]; then echo "Text generation working: $RESPONSE" exit 0 else echo "Text generation failed" exit 1 fi verify-image-generation: description: "Test image generation endpoint" depends_on: [verify-text-generation] on_error: continue action: shell command: | DOMAIN="{{ .outputs.create-project.domain }}" SERVICE_NAME="{{ .vars.service_name }}" echo "Testing image generation..." RESP=$(curl -s -X POST "https://$DOMAIN/api/$SERVICE_NAME/generate-image" \ -H "Content-Type: application/json" \ -d '{"prompt": "a simple red circle on white background"}') # Check if we got base64 image data IMAGE=$(echo "$RESP" | jq -r '.image_base64 // .data.image_base64 // .image // empty') if [ -n "$IMAGE" ] && [ ${#IMAGE} -gt 100 ]; then echo "Image generation working (got ${#IMAGE} chars of base64)" exit 0 else echo "Image generation failed or returned empty" echo "$RESP" | jq . exit 1 fi teardown: - action: api method: DELETE endpoint: "/project/{{ .outputs.create-project.project_id }}"