import { Context, Effect, Layer, Ref } from 'effect'; import { AgentService } from '../agent/service'; import type { Workflow } from './manager'; export interface WorkflowService { addWorkflow(name: string, config: Omit): Effect.Effect; getWorkflow(name: string): Effect.Effect; listWorkflows(): Effect.Effect; hasWorkflow(name: string): Effect.Effect; clear(): Effect.Effect; } export const WorkflowService = Context.GenericTag('WorkflowService'); export const WorkflowServiceLive = Layer.effect( WorkflowService, Effect.gen(function* () { const workflowsRef = yield* Ref.make(new Map()); const agentService = yield* AgentService; const validateWorkflowAgents = (name: string, workflow: Workflow): Effect.Effect => Effect.gen(function* () { const defaultAgent = yield* agentService.getAgentOptional(workflow.defaultAgent); if (!defaultAgent) { yield* Effect.sync(() => { console.warn( `[Workflow] Default agent "${workflow.defaultAgent}" not found in workflow "${name}"` ); }); } yield* Effect.forEach(workflow.agents, (agentId) => Effect.gen(function* () { const agent = yield* agentService.getAgentOptional(agentId); if (!agent) { yield* Effect.sync(() => { console.warn( `[Workflow] Agent "${agentId}" referenced in workflow "${name}" not found` ); }); } }) ); }); const service: WorkflowService = { addWorkflow: (name, config) => Effect.gen(function* () { const workflow: Workflow = { name, ...config }; yield* Ref.update(workflowsRef, (workflows) => { const next = new Map(workflows); next.set(name, workflow); return next; }); yield* validateWorkflowAgents(name, workflow); }), getWorkflow: (name) => Effect.map(Ref.get(workflowsRef), (workflows) => workflows.get(name)), listWorkflows: () => Effect.map(Ref.get(workflowsRef), (workflows) => Array.from(workflows.keys())), hasWorkflow: (name) => Effect.map(Ref.get(workflowsRef), (workflows) => workflows.has(name)), clear: () => Ref.set(workflowsRef, new Map()), }; return service; }) ); export type { Workflow } from './manager';