diff --git a/packages/cue/src/examples/control-flows/branch.ts b/packages/cue/src/examples/control-flows/branch.ts new file mode 100644 index 0000000..07bb5cc --- /dev/null +++ b/packages/cue/src/examples/control-flows/branch.ts @@ -0,0 +1,64 @@ +import { Cue } from '../../../src/cue'; +import { z } from 'zod'; +import { log, monitorCue } from './utils/logger'; + +// Create branch workflow +const createBranchWorkflow = () => { + // Define blocks + const greaterThanBlock = Cue.createBlock({ + id: 'greater-than', + inputSchema: z.number(), + outputSchema: z.string(), + execute: async ({ inputData }) => { + const result = `Number ${inputData} is greater than 10`; + log('Greater than block executed', { input: inputData, result }); + return result; + }, + }); + + const lessThanBlock = Cue.createBlock({ + id: 'less-than', + inputSchema: z.number(), + outputSchema: z.string(), + execute: async ({ inputData }) => { + const result = `Number ${inputData} is less than or equal to 10`; + log('Less than block executed', { input: inputData, result }); + return result; + }, + }); + + const cue = Cue.createCue({ + id: 'branch-workflow', + inputSchema: z.number(), + outputSchema: z.string(), + }); + + // Create conditional branches + cue.branch([ + [async ({ inputData }) => inputData > 10, greaterThanBlock], + [async ({ inputData }) => inputData <= 10, lessThanBlock], + ]); + + return cue; +}; + +// Example usage +const main = async () => { + try { + const workflow = createBranchWorkflow(); + const unsubscribeMain = monitorCue(workflow); + + // Test with different numbers + const results = await Promise.all([ + workflow.start(5), // Should use lessThanBlock + workflow.start(15), // Should use greaterThanBlock + ]); + + log('Final results:', results); + unsubscribeMain(); + } catch (error) { + console.error('Error:', error); + } +}; + +main(); diff --git a/packages/cue/src/examples/control-flows/loops/dountil.ts b/packages/cue/src/examples/control-flows/loops/dountil.ts new file mode 100644 index 0000000..bdedba9 --- /dev/null +++ b/packages/cue/src/examples/control-flows/loops/dountil.ts @@ -0,0 +1,49 @@ +import { Cue } from '../../../../src/cue'; +import { z } from 'zod'; +import { log, monitorCue } from '../utils/logger'; + +// Create do-until workflow +const createDoUntilWorkflow = () => { + // Define block + const counterBlock = Cue.createBlock({ + id: 'counter', + inputSchema: z.number(), + outputSchema: z.number(), + execute: async ({ inputData }) => { + const result = inputData + 1; + log('Counter block executed', { input: inputData, result }); + return result; + }, + }); + + const cue = Cue.createCue({ + id: 'dountil-workflow', + inputSchema: z.number(), + outputSchema: z.number(), + }); + + // Execute block until condition becomes true + cue.dountil( + counterBlock, + async ({ inputData }) => inputData >= 5 // Stop when number reaches or exceeds 5 + ); + + return cue; +}; + +// Example usage +const main = async () => { + try { + const workflow = createDoUntilWorkflow(); + const unsubscribeMain = monitorCue(workflow); + + const result = await workflow.start(1); // Start from 1 + + log('Final result:', result); + unsubscribeMain(); + } catch (error) { + console.error('Error:', error); + } +}; + +main(); diff --git a/packages/cue/src/examples/control-flows/loops/dowhile.ts b/packages/cue/src/examples/control-flows/loops/dowhile.ts new file mode 100644 index 0000000..be3df28 --- /dev/null +++ b/packages/cue/src/examples/control-flows/loops/dowhile.ts @@ -0,0 +1,49 @@ +import { Cue } from '../../../../src/cue'; +import { z } from 'zod'; +import { log, monitorCue } from '../utils/logger'; + +// Create do-while workflow +const createDoWhileWorkflow = () => { + // Define block + const counterBlock = Cue.createBlock({ + id: 'counter', + inputSchema: z.number(), + outputSchema: z.number(), + execute: async ({ inputData }) => { + const result = inputData + 1; + log('Counter block executed', { input: inputData, result }); + return result; + }, + }); + + const cue = Cue.createCue({ + id: 'dowhile-workflow', + inputSchema: z.number(), + outputSchema: z.number(), + }); + + // Execute block while condition is true + cue.dowhile( + counterBlock, + async ({ inputData }) => inputData < 5 // Continue while number is less than 5 + ); + + return cue; +}; + +// Example usage +const main = async () => { + try { + const workflow = createDoWhileWorkflow(); + const unsubscribeMain = monitorCue(workflow); + + const result = await workflow.start(1); // Start from 1 + + log('Final result:', result); + unsubscribeMain(); + } catch (error) { + console.error('Error:', error); + } +}; + +main(); diff --git a/packages/cue/src/examples/control-flows/loops/foreach.ts b/packages/cue/src/examples/control-flows/loops/foreach.ts new file mode 100644 index 0000000..a50ee76 --- /dev/null +++ b/packages/cue/src/examples/control-flows/loops/foreach.ts @@ -0,0 +1,46 @@ +import { Cue } from '../../../../src/cue'; +import { z } from 'zod'; +import { log, monitorCue } from '../utils/logger'; + +// Create foreach workflow +const createForEachWorkflow = () => { + // Define block + const processItemBlock = Cue.createBlock({ + id: 'process-item', + inputSchema: z.number(), + outputSchema: z.number(), + execute: async ({ inputData }) => { + const result = inputData * 3; + log('Process item block executed', { input: inputData, result }); + return result; + }, + }); + + const cue = Cue.createCue({ + id: 'foreach-workflow', + inputSchema: z.array(z.number()), + outputSchema: z.array(z.number()), + }); + + // Process each item in the array + cue.foreach(processItemBlock); + + return cue; +}; + +// Example usage +const main = async () => { + try { + const workflow = createForEachWorkflow(); + const unsubscribeMain = monitorCue(workflow); + + const result = await workflow.start([1, 2, 3, 4, 5]); + + log('Final result:', result); + unsubscribeMain(); + } catch (error) { + console.error('Error:', error); + } +}; + +main(); diff --git a/packages/cue/src/examples/control-flows/map.ts b/packages/cue/src/examples/control-flows/map.ts new file mode 100644 index 0000000..5b7b2bc --- /dev/null +++ b/packages/cue/src/examples/control-flows/map.ts @@ -0,0 +1,82 @@ +import { Cue } from '../../cue'; +import { z } from 'zod'; +import { log, monitorCue } from './utils/logger'; + +// Create mapping workflow +const createMappingWorkflow = () => { + // Define blocks + const multiplyBlock = Cue.createBlock({ + id: 'multiply', + inputSchema: z.number(), + outputSchema: z.object({ + original: z.number(), + multiplied: z.number(), + }), + execute: async ({ inputData }) => { + const result = { + original: inputData, + multiplied: inputData * 2, + }; + log('Multiply block executed', { input: inputData, result }); + return result; + }, + }); + + const addBlock = Cue.createBlock({ + id: 'add', + inputSchema: z.object({ + value: z.number(), + increment: z.number(), + }), + outputSchema: z.number(), + execute: async ({ inputData }) => { + const result = inputData.value + inputData.increment; + log('Add block executed', { input: inputData, result }); + return result; + }, + }); + + const cue = Cue.createCue({ + id: 'mapping-workflow', + inputSchema: z.number(), + outputSchema: z.number(), + }); + + // Chain blocks with mapping + cue + .then(multiplyBlock) + .map({ + value: { + block: multiplyBlock, + path: 'multiplied', + }, + increment: { + value: 5, + schema: z.number(), + }, + }) + .then(addBlock); + + return cue; +}; + +// Example usage +const main = async () => { + try { + const workflow = createMappingWorkflow(); + const unsubscribeMain = monitorCue(workflow); + + const result = await workflow.start(3); // Input: 3 + // Expected flow: + // 1. multiplyBlock: 3 -> { original: 3, multiplied: 6 } + // 2. map: { value: 6, increment: 5 } + // 3. addBlock: 6 + 5 -> 11 + + log('Final result:', result); + unsubscribeMain(); + } catch (error) { + console.error('Error:', error); + } +}; + +main(); diff --git a/packages/cue/src/examples/control-flows/parallel.ts b/packages/cue/src/examples/control-flows/parallel.ts new file mode 100644 index 0000000..0a696d2 --- /dev/null +++ b/packages/cue/src/examples/control-flows/parallel.ts @@ -0,0 +1,60 @@ +import { Cue } from '../../../src/cue'; +import { z } from 'zod'; +import { log, monitorCue } from './utils/logger'; + +// Create parallel workflow +const createParallelWorkflow = () => { + // Define blocks + const squareBlock = Cue.createBlock({ + id: 'square', + inputSchema: z.number(), + outputSchema: z.number(), + execute: async ({ inputData }) => { + const result = inputData * inputData; + log('Square block executed', { input: inputData, result }); + return result; + }, + }); + + const cubeBlock = Cue.createBlock({ + id: 'cube', + inputSchema: z.number(), + outputSchema: z.number(), + execute: async ({ inputData }) => { + const result = inputData * inputData * inputData; + log('Cube block executed', { input: inputData, result }); + return result; + }, + }); + + const cue = Cue.createCue({ + id: 'parallel-workflow', + inputSchema: z.number(), + outputSchema: z.object({ + square: z.number(), + cube: z.number(), + }), + }); + + // Execute blocks in parallel + cue.parallel([squareBlock, cubeBlock]); + + return cue; +}; + +// Example usage +const main = async () => { + try { + const workflow = createParallelWorkflow(); + const unsubscribeMain = monitorCue(workflow); + + const result = await workflow.start(5); + + log('Final result:', result); + unsubscribeMain(); + } catch (error) { + console.error('Error:', error); + } +}; + +main(); diff --git a/packages/cue/src/examples/control-flows/sequential.ts b/packages/cue/src/examples/control-flows/sequential.ts new file mode 100644 index 0000000..05a29ca --- /dev/null +++ b/packages/cue/src/examples/control-flows/sequential.ts @@ -0,0 +1,60 @@ +import { Cue } from '../../../src/cue'; +import { z } from 'zod'; +import { log, monitorCue } from './utils/logger'; + +// Create sequential workflow +const createSequentialWorkflow = () => { + // Define blocks + const addBlock = Cue.createBlock({ + id: 'add', + inputSchema: z.object({ a: z.number(), b: z.number() }), + outputSchema: z.number(), + execute: async ({ inputData }) => { + const result = inputData.a + inputData.b; + log('Add block executed', { input: inputData, result }); + return result; + }, + }); + + const multiplyBlock = Cue.createBlock({ + id: 'multiply', + inputSchema: z.number(), + outputSchema: z.number(), + execute: async ({ inputData }) => { + const result = inputData * 2; + log('Multiply block executed', { input: inputData, result }); + return result; + }, + }); + + const cue = Cue.createCue({ + id: 'sequential-workflow', + inputSchema: z.object({ a: z.number(), b: z.number() }), + outputSchema: z.number(), + }); + + // Chain blocks sequentially + cue.then(addBlock).then(multiplyBlock); + + return cue; +}; + +// Example usage +const main = async () => { + try { + const workflow = createSequentialWorkflow(); + const unsubscribeMain = monitorCue(workflow); + + const result = await workflow.start({ + a: 5, + b: 3, + }); + + log('Final result:', result); + unsubscribeMain(); + } catch (error) { + console.error('Error:', error); + } +}; + +main(); diff --git a/packages/cue/src/examples/control-flows/suspend-resume.ts b/packages/cue/src/examples/control-flows/suspend-resume.ts new file mode 100644 index 0000000..38093b1 --- /dev/null +++ b/packages/cue/src/examples/control-flows/suspend-resume.ts @@ -0,0 +1,94 @@ +import { Cue } from '../../cue'; +import { z } from 'zod'; +import { log, monitorCue } from './utils/logger'; + +// Create a simple suspend/resume workflow +const createSimpleWorkflow = () => { + // Simple block that can be suspended + const suspendBlock = Cue.createBlock({ + id: 'suspend', + inputSchema: z.object({ + value: z.number(), + }), + outputSchema: z.number(), + execute: async ({ inputData, suspend }) => { + log('Block suspending', { input: inputData }); + await suspend(inputData); + return inputData.value * 2; + }, + }); + + // Create the workflow + const cue = Cue.createCue({ + id: 'simple-workflow', + inputSchema: z.object({ + value: z.number(), + }), + outputSchema: z.number(), + }); + + // Add the block to the workflow + cue.then(suspendBlock); + + return cue; +}; + +// Example usage +const main = async () => { + try { + console.log('Starting workflow...'); + const workflow = createSimpleWorkflow(); + const unsubscribe = monitorCue(workflow); + + // Start workflow + const result = await workflow.start({ + value: 10, + }); + + console.log('Workflow started with result:', result); + + if (result.status === 'suspended' && result.steps.suspend) { + const suspendedStep = result.steps.suspend; + log('Workflow suspended', result); + console.log('--------------------------------'); + console.log('Suspended step info:', { + status: suspendedStep.status, + output: suspendedStep.output, + suspendedPath: suspendedStep.suspendedPath, + }); + console.log('--------------------------------'); + + // Resume after delay + setTimeout(async () => { + try { + console.log('--------------------------------Resuming workflow...'); + const resumeResult = await workflow.resume({ + block: 'suspend', + resumeData: suspendedStep.output, + }); + log('Workflow completed', resumeResult); + } catch (error: any) { + console.error('Resume error:', error); + if (error && typeof error === 'object') { + console.error('Error details:', { + name: error.name, + message: error.message, + stack: error.stack, + }); + } + } + }, 6000); + } + + // Keep the process alive + setTimeout(() => { + console.log('Cleaning up...'); + unsubscribe(); + }, 7000); + } catch (error) { + console.error('Error:', error); + } +}; + +// Execute main function +main().catch(console.error); diff --git a/packages/cue/src/examples/control-flows/utils/logger.ts b/packages/cue/src/examples/control-flows/utils/logger.ts new file mode 100644 index 0000000..9c7b71f --- /dev/null +++ b/packages/cue/src/examples/control-flows/utils/logger.ts @@ -0,0 +1,26 @@ +export const log = (message: string, data?: any) => { + console.log(`\n[${new Date().toISOString()}] ${message}`); + if (data) { + console.log(JSON.stringify(data, null, 2)); + } +}; + +export const monitorCue = (cue: any) => { + // Monitor overall Cue status + cue.watch((event: any) => { + log(`Cue Status Update: ${event.type}`, event.data); + }); + + // Monitor block results + const unsubscribe = cue.store.subscribe((state: any) => { + const lastLog = state.logs[state.logs.length - 1]; + if (lastLog?.logType === 'BlockStatusUpdate') { + log(`Block ${lastLog.blockId} Status: ${lastLog.blockStatus}`, { + result: lastLog.blockResult, + executionPath: state.executionPath, + }); + } + }); + + return unsubscribe; +};