diff --git a/src/templates/feature-dev.ts b/src/templates/feature-dev.ts new file mode 100644 index 000000000..1f89e0e27 --- /dev/null +++ b/src/templates/feature-dev.ts @@ -0,0 +1,63 @@ +import { Context } from '@agentworkforce/relay'; + +export interface Plan { + strategy: string; + reasoning: string; +} + +export interface DeveloperOutput { + decisions: string[]; + implementationDetails: string; +} + +export interface ReviewerOutput { + deviations: string[]; + approved: boolean; +} + +export const featureDevTemplate = { + async run(requirements: string, initialContext?: Record): Promise<{ + plan: Plan; + development: DeveloperOutput; + review: ReviewerOutput; + }> { + const ctx = new Context(initialContext); + ctx.set('requirements', requirements); + + const plan = await this.planner(ctx); + ctx.set('plan', plan); + + const development = await this.developer(ctx); + ctx.set('development', development); + + const review = await this.reviewer(ctx); + + return { plan, development, review }; + }, + + async planner(context: Context): Promise { + const requirements = context.get('requirements') as string; + return { + strategy: `Implement ${requirements}`, + reasoning: 'Detailed reasoning based on requirements.' + }; + }, + + async developer(context: Context): Promise { + const plan = context.get('plan') as Plan; + return { + decisions: [`Following strategy: ${plan.strategy}`], + implementationDetails: 'Code changes made according to plan.' + }; + }, + + async reviewer(context: Context): Promise { + const plan = context.get('plan') as Plan; + const development = context.get('development') as DeveloperOutput; + const deviations: string[] = []; + if (!development.decisions.some(d => d.includes(plan.strategy))) { + deviations.push('Implementation deviates from plan strategy'); + } + return { deviations, approved: deviations.length === 0 }; + } +}; diff --git a/src/templates/review-loop.ts b/src/templates/review-loop.ts new file mode 100644 index 000000000..89f3f9511 --- /dev/null +++ b/src/templates/review-loop.ts @@ -0,0 +1,41 @@ +import { LoopStep, Step, StepContext } from '@agentworkforce/relay'; + +export interface ReviewStepOutput { + passed: boolean; + feedback?: string; +} + +export interface AddressFeedbackInput { + code: string; + feedback: string; +} + +export interface AddressFeedbackOutput { + code: string; +} + +export interface ReviewLoopConfig { + maxIterations?: number; +} + +export function createReviewLoop( + reviewStep: Step, + addressFeedbackStep: Step, + config: ReviewLoopConfig = {} +): Step<{ code: string }, { finalCode: string; iterations: number }> { + const maxIterations = config.maxIterations ?? 5; + + return new LoopStep<{ code: string }, { finalCode: string; iterations: number }>({ + steps: [reviewStep, addressFeedbackStep], + while: (ctx: StepContext) => { + const reviewOut = ctx.getStepOutput(reviewStep) as ReviewStepOutput; + return !reviewOut.passed; + }, + maxLoops: maxIterations, + finalize: (ctx: StepContext) => { + const addressOut = ctx.getStepOutput(addressFeedbackStep) as AddressFeedbackOutput | undefined; + const finalCode = addressOut?.code ?? ctx.input.code; + return { finalCode, iterations: ctx.iterationCount }; + }, + }); +} diff --git a/src/workflow/types.ts b/src/workflow/types.ts new file mode 100644 index 000000000..1a0f95945 --- /dev/null +++ b/src/workflow/types.ts @@ -0,0 +1,21 @@ +export interface StepContext { + data: Record; + metadata?: Record; + history?: string[]; +} + +export interface WorkflowStep { + name: string; + execute(context: StepContext): Promise | StepContext; +} + +export interface LoopStep extends WorkflowStep { + condition: (context: StepContext) => boolean | Promise; + steps: WorkflowStep[]; + maxIterations?: number; +} + +export interface Workflow { + name: string; + steps: WorkflowStep[]; +}