UNPKG

@relayplane/sdk

Version:

RelayPlane SDK - Local-first AI workflow engine for building multi-step AI workflows

1,323 lines (1,308 loc) 190 kB
import { randomUUID } from 'crypto'; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, { get: (a, b) => (typeof require !== "undefined" ? require : a)[b] }) : x)(function(x) { if (typeof require !== "undefined") return require.apply(this, arguments); throw Error('Dynamic require of "' + x + '" is not supported'); }); var __commonJS = (cb, mod) => function __require2() { return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); // ../engine/dist/types/errors.js var require_errors = __commonJS({ "../engine/dist/types/errors.js"(exports$1) { Object.defineProperty(exports$1, "__esModule", { value: true }); exports$1.TemplateError = exports$1.TimeoutError = exports$1.ProviderError = exports$1.StepExecutionError = exports$1.WorkflowDependencyError = exports$1.WorkflowDefinitionError = exports$1.WorkflowError = void 0; exports$1.isWorkflowError = isWorkflowError; exports$1.isWorkflowDefinitionError = isWorkflowDefinitionError; exports$1.isStepExecutionError = isStepExecutionError; exports$1.isProviderError = isProviderError; exports$1.isTimeoutError = isTimeoutError; var WorkflowError = class _WorkflowError extends Error { cause; /** * Creates a new WorkflowError. * * @param message - Human-readable error message * @param cause - Optional underlying error that caused this error */ constructor(message, cause) { super(message); this.cause = cause; this.name = "WorkflowError"; Object.setPrototypeOf(this, _WorkflowError.prototype); } }; exports$1.WorkflowError = WorkflowError; var WorkflowDefinitionError = class _WorkflowDefinitionError extends WorkflowError { constructor(message, cause) { super(message, cause); this.name = "WorkflowDefinitionError"; Object.setPrototypeOf(this, _WorkflowDefinitionError.prototype); } }; exports$1.WorkflowDefinitionError = WorkflowDefinitionError; var WorkflowDependencyError = class _WorkflowDependencyError extends WorkflowDefinitionError { constructor(message, cause) { super(message, cause); this.name = "WorkflowDependencyError"; Object.setPrototypeOf(this, _WorkflowDependencyError.prototype); } }; exports$1.WorkflowDependencyError = WorkflowDependencyError; var StepExecutionError = class _StepExecutionError extends WorkflowError { stepName; workflowName; attempts; /** * Creates a new StepExecutionError. * * @param stepName - Name of the step that failed * @param workflowName - Name of the workflow being executed * @param message - Human-readable error message * @param attempts - Number of execution attempts made * @param cause - Optional underlying error */ constructor(stepName, workflowName, message, attempts = 1, cause) { super(message, cause); this.stepName = stepName; this.workflowName = workflowName; this.attempts = attempts; this.name = "StepExecutionError"; Object.setPrototypeOf(this, _StepExecutionError.prototype); } }; exports$1.StepExecutionError = StepExecutionError; var ProviderError = class _ProviderError extends WorkflowError { provider; /** * Creates a new ProviderError. * * @param provider - Name of the provider (e.g., "openai", "anthropic") * @param message - Human-readable error message * @param cause - Optional underlying provider error */ constructor(provider, message, cause) { super(message, cause); this.provider = provider; this.name = "ProviderError"; Object.setPrototypeOf(this, _ProviderError.prototype); } }; exports$1.ProviderError = ProviderError; var TimeoutError = class _TimeoutError extends WorkflowError { timeoutMs; /** * Creates a new TimeoutError. * * @param message - Human-readable error message * @param timeoutMs - The timeout value that was exceeded * @param cause - Optional underlying error */ constructor(message, timeoutMs, cause) { super(message, cause); this.timeoutMs = timeoutMs; this.name = "TimeoutError"; Object.setPrototypeOf(this, _TimeoutError.prototype); } }; exports$1.TimeoutError = TimeoutError; var TemplateError = class _TemplateError extends WorkflowError { template; /** * Creates a new TemplateError. * * @param message - Human-readable error message * @param template - The template string that failed * @param cause - Optional underlying error */ constructor(message, template, cause) { super(message, cause); this.template = template; this.name = "TemplateError"; Object.setPrototypeOf(this, _TemplateError.prototype); } }; exports$1.TemplateError = TemplateError; function isWorkflowError(error) { return error instanceof WorkflowError; } function isWorkflowDefinitionError(error) { return error instanceof WorkflowDefinitionError; } function isStepExecutionError(error) { return error instanceof StepExecutionError; } function isProviderError(error) { return error instanceof ProviderError; } function isTimeoutError(error) { return error instanceof TimeoutError; } } }); // ../engine/dist/types/index.js var require_types = __commonJS({ "../engine/dist/types/index.js"(exports$1) { Object.defineProperty(exports$1, "__esModule", { value: true }); exports$1.isTimeoutError = exports$1.isProviderError = exports$1.isStepExecutionError = exports$1.isWorkflowDefinitionError = exports$1.isWorkflowError = exports$1.TemplateError = exports$1.TimeoutError = exports$1.ProviderError = exports$1.StepExecutionError = exports$1.WorkflowDependencyError = exports$1.WorkflowDefinitionError = exports$1.WorkflowError = void 0; var errors_1 = require_errors(); Object.defineProperty(exports$1, "WorkflowError", { enumerable: true, get: function() { return errors_1.WorkflowError; } }); Object.defineProperty(exports$1, "WorkflowDefinitionError", { enumerable: true, get: function() { return errors_1.WorkflowDefinitionError; } }); Object.defineProperty(exports$1, "WorkflowDependencyError", { enumerable: true, get: function() { return errors_1.WorkflowDependencyError; } }); Object.defineProperty(exports$1, "StepExecutionError", { enumerable: true, get: function() { return errors_1.StepExecutionError; } }); Object.defineProperty(exports$1, "ProviderError", { enumerable: true, get: function() { return errors_1.ProviderError; } }); Object.defineProperty(exports$1, "TimeoutError", { enumerable: true, get: function() { return errors_1.TimeoutError; } }); Object.defineProperty(exports$1, "TemplateError", { enumerable: true, get: function() { return errors_1.TemplateError; } }); Object.defineProperty(exports$1, "isWorkflowError", { enumerable: true, get: function() { return errors_1.isWorkflowError; } }); Object.defineProperty(exports$1, "isWorkflowDefinitionError", { enumerable: true, get: function() { return errors_1.isWorkflowDefinitionError; } }); Object.defineProperty(exports$1, "isStepExecutionError", { enumerable: true, get: function() { return errors_1.isStepExecutionError; } }); Object.defineProperty(exports$1, "isProviderError", { enumerable: true, get: function() { return errors_1.isProviderError; } }); Object.defineProperty(exports$1, "isTimeoutError", { enumerable: true, get: function() { return errors_1.isTimeoutError; } }); } }); // ../engine/dist/validation/dag.js var require_dag = __commonJS({ "../engine/dist/validation/dag.js"(exports$1) { Object.defineProperty(exports$1, "__esModule", { value: true }); exports$1.validateAndSort = validateAndSort; exports$1.topologicalSort = topologicalSort; exports$1.detectCycles = detectCycles; var errors_1 = require_errors(); function validateAndSort(workflow) { if (!workflow.workflowName || workflow.workflowName.trim() === "") { throw new errors_1.WorkflowDefinitionError("Workflow name must be a non-empty string"); } if (!Array.isArray(workflow.steps) || workflow.steps.length === 0) { throw new errors_1.WorkflowDefinitionError("Workflow must have at least one step"); } validateUniqueStepNames(workflow.steps); validateDependencies(workflow.steps); return topologicalSort(workflow.steps); } function validateUniqueStepNames(steps) { const stepNames = /* @__PURE__ */ new Set(); const duplicates = []; for (const step of steps) { if (!step.stepName || step.stepName.trim() === "") { throw new errors_1.WorkflowDefinitionError("All steps must have a non-empty stepName"); } if (stepNames.has(step.stepName)) { duplicates.push(step.stepName); } else { stepNames.add(step.stepName); } } if (duplicates.length > 0) { throw new errors_1.WorkflowDefinitionError(`Duplicate step names found: ${duplicates.join(", ")}`); } } function validateDependencies(steps) { const stepNames = new Set(steps.map((s) => s.stepName)); for (const step of steps) { if (!step.model || step.model.trim() === "") { throw new errors_1.WorkflowDefinitionError(`Step "${step.stepName}" is missing required field "model"`); } if (step.dependsOn && step.dependsOn.length > 0) { for (const dependency of step.dependsOn) { if (dependency === step.stepName) { throw new errors_1.WorkflowDefinitionError(`Step "${step.stepName}" cannot depend on itself`); } if (!stepNames.has(dependency)) { throw new errors_1.WorkflowDefinitionError(`Step "${step.stepName}" depends on unknown step "${dependency}"`); } } } } } function topologicalSort(steps) { const stepMap = /* @__PURE__ */ new Map(); const inDegree = /* @__PURE__ */ new Map(); const dependents = /* @__PURE__ */ new Map(); for (const step of steps) { stepMap.set(step.stepName, step); inDegree.set(step.stepName, 0); dependents.set(step.stepName, /* @__PURE__ */ new Set()); } for (const step of steps) { if (step.dependsOn && step.dependsOn.length > 0) { inDegree.set(step.stepName, step.dependsOn.length); for (const dependency of step.dependsOn) { const depSet = dependents.get(dependency); if (depSet) { depSet.add(step.stepName); } } } } const queue = []; for (const [stepName, degree] of inDegree.entries()) { if (degree === 0) { queue.push(stepName); } } const sorted = []; const visited = /* @__PURE__ */ new Set(); while (queue.length > 0) { const currentName = queue.shift(); const currentStep = stepMap.get(currentName); sorted.push(currentStep); visited.add(currentName); const deps = dependents.get(currentName); if (deps) { for (const dependentName of deps) { const degree = inDegree.get(dependentName) - 1; inDegree.set(dependentName, degree); if (degree === 0) { queue.push(dependentName); } } } } if (sorted.length !== steps.length) { const unvisited = steps.filter((s) => !visited.has(s.stepName)).map((s) => s.stepName); const cycle = findCycle(steps, unvisited); throw new errors_1.WorkflowDependencyError(`Circular dependency detected: ${cycle.join(" \u2192 ")}`); } return sorted; } function findCycle(steps, unvisited) { const stepMap = new Map(steps.map((s) => [s.stepName, s])); const visiting = /* @__PURE__ */ new Set(); const visited = /* @__PURE__ */ new Set(); const path2 = []; function dfs(stepName) { if (visiting.has(stepName)) { return true; } if (visited.has(stepName)) { return false; } visiting.add(stepName); path2.push(stepName); const step = stepMap.get(stepName); if (step?.dependsOn) { for (const dep of step.dependsOn) { if (dfs(dep)) { return true; } } } visiting.delete(stepName); visited.add(stepName); path2.pop(); return false; } for (const startNode of unvisited) { if (dfs(startNode)) { return [...path2, startNode]; } } return unvisited; } function detectCycles(steps) { try { topologicalSort(steps); return false; } catch (error) { if (error instanceof errors_1.WorkflowDependencyError) { return true; } throw error; } } } }); // ../engine/dist/utils/uuid.js var require_uuid = __commonJS({ "../engine/dist/utils/uuid.js"(exports$1) { Object.defineProperty(exports$1, "__esModule", { value: true }); exports$1.generateUUID = generateUUID; exports$1.generateRunId = generateRunId; function generateUUID() { return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => { const r = Math.random() * 16 | 0; const v = c === "x" ? r : r & 3 | 8; return v.toString(16); }); } function generateRunId(prefix = "run") { return `${prefix}_${generateUUID()}`; } } }); // ../engine/dist/execution/context.js var require_context = __commonJS({ "../engine/dist/execution/context.js"(exports$1) { Object.defineProperty(exports$1, "__esModule", { value: true }); exports$1.ExecutionContextImpl = void 0; var uuid_1 = require_uuid(); var ExecutionContextImpl = class { runId; workflowName; startTime; endTime; initialInput; stepOutputs; logs; options; finalized = false; /** * Creates a new execution context for a workflow run. * * @param workflow - The workflow being executed * @param initialInput - Input provided by the user * @param options - Runtime options for this execution * @param runId - Optional custom run ID (generated if not provided) */ constructor(workflow, initialInput, options = {}, runId) { this.runId = runId || (0, uuid_1.generateRunId)(); this.workflowName = workflow.workflowName; this.startTime = (/* @__PURE__ */ new Date()).toISOString(); this.initialInput = initialInput; this.stepOutputs = /* @__PURE__ */ new Map(); this.logs = []; this.options = options; } /** * Stores the output of a completed step. * * @param stepName - Name of the step * @param output - Output value from the step * @throws {Error} If context is already finalized */ setOutput(stepName, output) { if (this.finalized) { throw new Error("Cannot set output on finalized context"); } this.stepOutputs.set(stepName, output); } /** * Retrieves the output of a previously executed step. * * @param stepName - Name of the step * @returns Output value, or undefined if step hasn't executed */ getOutput(stepName) { return this.stepOutputs.get(stepName); } /** * Checks if a step has been executed and has output. * * @param stepName - Name of the step * @returns True if step has output stored */ hasOutput(stepName) { return this.stepOutputs.has(stepName); } /** * Appends a step execution log to the context. * * @param log - Step execution log entry * @throws {Error} If context is already finalized */ appendLog(log) { if (this.finalized) { throw new Error("Cannot append log to finalized context"); } this.logs.push(log); } /** * Gets all execution logs in order. * * @returns Array of step execution logs */ getLogs() { return [...this.logs]; } /** * Gets the number of steps that have been executed. * * @returns Number of logs */ getStepCount() { return this.logs.length; } /** * Finalizes the context by setting the end time. * * After finalization, no more outputs or logs can be added. */ finalize() { if (!this.finalized) { this.endTime = (/* @__PURE__ */ new Date()).toISOString(); this.finalized = true; } } /** * Checks if the context has been finalized. * * @returns True if finalized */ isFinalized() { return this.finalized; } /** * Gets the total duration of the workflow run in milliseconds. * * @returns Duration in ms, or undefined if not finalized */ getDuration() { if (!this.endTime) { return void 0; } return new Date(this.endTime).getTime() - new Date(this.startTime).getTime(); } /** * Creates a summary object of the execution context. * * @returns Summary object with key metrics */ getSummary() { return { runId: this.runId, workflowName: this.workflowName, startTime: this.startTime, endTime: this.endTime, duration: this.getDuration(), stepCount: this.logs.length, outputCount: this.stepOutputs.size, finalized: this.finalized }; } }; exports$1.ExecutionContextImpl = ExecutionContextImpl; } }); // ../engine/dist/utils/interpolate.js var require_interpolate = __commonJS({ "../engine/dist/utils/interpolate.js"(exports$1) { Object.defineProperty(exports$1, "__esModule", { value: true }); exports$1.interpolate = interpolate; exports$1.hasTemplateVariables = hasTemplateVariables; exports$1.interpolateValue = interpolateValue; var errors_1 = require_errors(); function interpolate(template, context) { if (typeof template !== "string") { return template; } const pattern = /\{\{([^}]+)\}\}/g; let result = template; const matches = Array.from(template.matchAll(pattern)); for (const match of matches) { const fullMatch = match[0]; const expression = match[1].trim(); try { const value = resolveExpression(expression, context); const replacement = formatValue(value); result = result.replace(fullMatch, replacement); } catch (error) { if (error instanceof errors_1.TemplateError) { throw error; } throw new errors_1.TemplateError(`Failed to resolve template variable "${fullMatch}": ${error instanceof Error ? error.message : String(error)}`, fullMatch); } } return result; } function resolveExpression(expression, context) { const parts = expression.split("."); if (parts.length < 2) { throw new errors_1.TemplateError(`Invalid template expression "${expression}". Expected format: "stepName.output[.field]"`, `{{${expression}}}`); } const stepName = parts[0]; const accessor = parts[1]; if (!context.has(stepName)) { throw new errors_1.TemplateError(`Cannot resolve template variable "{{${expression}}}": step "${stepName}" not found or has not executed yet`, `{{${expression}}}`); } let value = context.get(stepName); let startIndex = 2; if (stepName === "input") { startIndex = 1; } else { if (accessor !== "output") { throw new errors_1.TemplateError(`Invalid template expression "${expression}". Second part must be "output"`, `{{${expression}}}`); } } for (let i = startIndex; i < parts.length; i++) { const prop = parts[i]; if (value === null || value === void 0) { throw new errors_1.TemplateError(`Cannot access property "${prop}" in "{{${expression}}}": parent value is ${value}`, `{{${expression}}}`); } if (typeof value !== "object") { throw new errors_1.TemplateError(`Cannot access property "${prop}" in "{{${expression}}}": parent is not an object`, `{{${expression}}}`); } if (!(prop in value)) { throw new errors_1.TemplateError(`Cannot access property "${prop}" in "{{${expression}}}": property does not exist`, `{{${expression}}}`); } value = value[prop]; } return value; } function formatValue(value) { if (value === null || value === void 0) { return ""; } if (typeof value === "string") { return value; } if (typeof value === "number" || typeof value === "boolean") { return String(value); } if (typeof value === "object") { return JSON.stringify(value); } return String(value); } function hasTemplateVariables(str) { if (typeof str !== "string") { return false; } return /\{\{[^}]+\}\}/.test(str); } function interpolateValue(value, context) { if (typeof value === "string") { return interpolate(value, context); } if (Array.isArray(value)) { return value.map((item) => interpolateValue(item, context)); } if (value !== null && typeof value === "object") { const result = {}; for (const [key, val] of Object.entries(value)) { result[key] = interpolateValue(val, context); } return result; } return value; } } }); // ../engine/dist/execution/input-resolver.js var require_input_resolver = __commonJS({ "../engine/dist/execution/input-resolver.js"(exports$1) { Object.defineProperty(exports$1, "__esModule", { value: true }); exports$1.resolveStepInput = resolveStepInput; exports$1.areDependenciesReady = areDependenciesReady; var interpolate_1 = require_interpolate(); function resolveStepInput(step, context) { const interpolationContext = /* @__PURE__ */ new Map(); if (context.initialInput !== void 0 && context.initialInput !== null) { interpolationContext.set("input", context.initialInput); } for (const [stepName, output] of context.stepOutputs.entries()) { interpolationContext.set(stepName, output); } let baseInput; if (step.input !== void 0) { baseInput = step.input; } else if (step.prompt !== void 0) { baseInput = step.prompt; } else { baseInput = context.initialInput; } const resolvedInput = (0, interpolate_1.interpolateValue)(baseInput, interpolationContext); if (step.dependsOn && step.dependsOn.length > 0) { const dependencies = {}; for (const depName of step.dependsOn) { const depOutput = context.getOutput(depName); if (depOutput !== void 0) { dependencies[depName] = depOutput; } } return { input: resolvedInput, dependencies }; } return resolvedInput; } function areDependenciesReady(step, context) { if (!step.dependsOn || step.dependsOn.length === 0) { return true; } return step.dependsOn.every((depName) => context.hasOutput(depName)); } } }); // ../engine/dist/execution/retry.js var require_retry = __commonJS({ "../engine/dist/execution/retry.js"(exports$1) { Object.defineProperty(exports$1, "__esModule", { value: true }); exports$1.calculateBackoff = calculateBackoff; exports$1.sleep = sleep; exports$1.isRecoverableError = isRecoverableError; function calculateBackoff(attempt, baseDelay = 1e3, jitterFactor = 0.2) { const exponentialDelay = baseDelay * Math.pow(2, attempt); const jitter = 1 + (Math.random() * 2 - 1) * jitterFactor; return Math.floor(exponentialDelay * jitter); } function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } function isRecoverableError(error) { if (!error) { return false; } const errorType = error.type || error.error?.type; if (errorType === "RateLimitError" || errorType === "rate_limit_exceeded") { return true; } if (errorType === "TimeoutError" || errorType === "timeout") { return true; } if (errorType === "NetworkError" || errorType === "ECONNRESET" || errorType === "ETIMEDOUT") { return true; } if (error.statusCode >= 500 && error.statusCode < 600) { return true; } const message = (error.message || "").toLowerCase(); if (message.includes("timeout") || message.includes("rate limit") || message.includes("503")) { return true; } return false; } } }); // ../engine/dist/execution/executor.js var require_executor = __commonJS({ "../engine/dist/execution/executor.js"(exports$1) { Object.defineProperty(exports$1, "__esModule", { value: true }); exports$1.executeStep = executeStep; exports$1.validateStepExecution = validateStepExecution; var errors_1 = require_errors(); var input_resolver_1 = require_input_resolver(); var retry_1 = require_retry(); var DEFAULT_STEP_TIMEOUT = 12e4; function createTimeout(ms, stepName) { return new Promise((_, reject) => { setTimeout(() => { reject(new errors_1.TimeoutError(`Step "${stepName}" timed out after ${ms}ms`, ms)); }, ms); }); } async function executeStep(step, context, adapterExecutor) { const startTime = Date.now(); const startedAt = (/* @__PURE__ */ new Date()).toISOString(); const maxRetries = step.retry?.maxRetries ?? 0; const baseBackoff = step.retry?.backoffMs ?? 1e3; const timeout = step.timeout ?? DEFAULT_STEP_TIMEOUT; let lastError; let attempts = 0; while (attempts <= maxRetries) { attempts++; try { const resolvedInput = (0, input_resolver_1.resolveStepInput)(step, context); const adapterPromise = adapterExecutor({ model: step.model, input: resolvedInput, schema: step.schema, stepName: step.stepName, workflowName: context.workflowName, stepMetadata: step.metadata }); const result = await Promise.race([ adapterPromise, createTimeout(timeout, step.stepName) ]); if (result.success) { const finishedAt2 = (/* @__PURE__ */ new Date()).toISOString(); const durationMs2 = Date.now() - startTime; return { stepName: step.stepName, model: step.model, startedAt, finishedAt: finishedAt2, durationMs: durationMs2, success: true, output: result.output, attempts, tokensIn: result.tokensIn, tokensOut: result.tokensOut }; } lastError = result.error; if (!(0, retry_1.isRecoverableError)(lastError) || attempts > maxRetries) { break; } const delay = (0, retry_1.calculateBackoff)(attempts - 1, baseBackoff); await (0, retry_1.sleep)(delay); } catch (error) { if (error instanceof errors_1.TimeoutError) { lastError = { type: "TimeoutError", message: error.message, timeoutMs: error.timeoutMs }; break; } lastError = { type: "UnexpectedError", message: error instanceof Error ? error.message : String(error), raw: error }; if (!(0, retry_1.isRecoverableError)(error) || attempts > maxRetries) { break; } const delay = (0, retry_1.calculateBackoff)(attempts - 1, baseBackoff); await (0, retry_1.sleep)(delay); } } const finishedAt = (/* @__PURE__ */ new Date()).toISOString(); const durationMs = Date.now() - startTime; return { stepName: step.stepName, model: step.model, startedAt, finishedAt, durationMs, success: false, error: lastError || { type: "UnknownError", message: "Step failed with unknown error" }, attempts }; } function validateStepExecution(step, context) { if (!step.stepName || !step.model) { throw new errors_1.StepExecutionError(step.stepName || "unknown", context.workflowName, "Step is missing required fields (stepName or model)", 0); } if (step.dependsOn && step.dependsOn.length > 0) { for (const depName of step.dependsOn) { if (!context.hasOutput(depName)) { throw new errors_1.StepExecutionError(step.stepName, context.workflowName, `Step "${step.stepName}" depends on "${depName}" which has not been executed`, 0); } } } } } }); // ../engine/dist/execution/condition-evaluator.js var require_condition_evaluator = __commonJS({ "../engine/dist/execution/condition-evaluator.js"(exports$1) { Object.defineProperty(exports$1, "__esModule", { value: true }); exports$1.evaluateCondition = evaluateCondition; exports$1.validateCondition = validateCondition; function evaluateCondition(condition, context) { const conditionContext = buildConditionContext(context); try { const evaluator = new Function("input", "steps", `"use strict"; return (${condition});`); const result = evaluator(conditionContext.input, conditionContext.steps); return { shouldExecute: Boolean(result) }; } catch (error) { return { shouldExecute: false, error: `Condition evaluation failed: ${error instanceof Error ? error.message : String(error)}` }; } } function buildConditionContext(context) { const steps = {}; for (const [stepName, output] of context.stepOutputs.entries()) { steps[stepName] = { output }; } return { input: context.initialInput, steps }; } function validateCondition(condition) { try { new Function("input", "steps", `"use strict"; return (${condition});`); return true; } catch (error) { throw new Error(`Invalid condition expression: ${error instanceof Error ? error.message : String(error)}`); } } } }); // ../engine/dist/runner/runner.js var require_runner = __commonJS({ "../engine/dist/runner/runner.js"(exports$1) { Object.defineProperty(exports$1, "__esModule", { value: true }); exports$1.WorkflowRunner = void 0; exports$1.runWorkflow = runWorkflow2; var dag_1 = require_dag(); var context_1 = require_context(); var executor_1 = require_executor(); var condition_evaluator_1 = require_condition_evaluator(); var WorkflowRunner = class { /** * Adapter executor function to use for all steps. */ adapterExecutor; /** * Creates a new WorkflowRunner instance. * * @param adapterExecutor - Function that executes adapter calls */ constructor(adapterExecutor) { this.adapterExecutor = adapterExecutor; } /** * Executes a complete workflow from start to finish. * * This method: * 1. Validates the workflow DAG structure * 2. Topologically sorts steps based on dependencies * 3. Initializes execution context * 4. Executes each step sequentially in dependency order * 5. Handles step failures (aborts on first failure) * 6. Aggregates results into a WorkflowRunResult * * @param workflow - The workflow definition to execute * @param initialInput - Initial input to provide to the workflow * @param options - Optional runtime configuration * @returns Complete workflow execution result with all step logs * * @example * ```typescript * const workflow: WorkflowDefinition = { * workflowName: 'greeting', * steps: [ * { stepName: 'greet', model: 'gpt-4o', prompt: 'Say hello' } * ] * }; * * const result = await runner.run(workflow, {}); * console.log(result.finalOutput); * ``` */ async run(workflow, initialInput, options = {}) { let sortedSteps; try { sortedSteps = (0, dag_1.validateAndSort)(workflow); } catch (error) { const runId = this.generateRunId(); const startedAt = (/* @__PURE__ */ new Date()).toISOString(); const finishedAt = (/* @__PURE__ */ new Date()).toISOString(); return { runId, workflowName: workflow.workflowName, startedAt, finishedAt, success: false, steps: [] // Store validation error information }; } const context = new context_1.ExecutionContextImpl(workflow, initialInput, options); const executionLevels = this.groupStepsByLevel(sortedSteps); let aborted = false; for (const levelSteps of executionLevels) { if (aborted) break; const stepPromises = []; for (const step of levelSteps) { stepPromises.push(this.executeStepWithCondition(step, context)); } const results = await Promise.all(stepPromises); for (const { step, log, skipped } of results) { if (skipped) { context.appendLog(log); context.setOutput(step.stepName, void 0); continue; } context.appendLog(log); if (log.success) { context.setOutput(step.stepName, log.output); } else { aborted = true; break; } } } context.finalize(); const result = { runId: context.runId, workflowName: context.workflowName, startedAt: context.startTime, finishedAt: context.endTime, success: this.isWorkflowSuccessful(context), steps: context.logs, finalOutput: this.getFinalOutput(sortedSteps, context) }; return result; } /** * Generates a unique run ID. * Uses a simple timestamp-based approach for the MVP. * * @returns Unique run identifier */ generateRunId() { return `run_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`; } /** * Determines if the workflow executed successfully. * A workflow is successful if all steps executed and succeeded. * * @param context - Execution context * @returns True if workflow completed successfully */ isWorkflowSuccessful(context) { return context.logs.length > 0 && context.logs.every((log) => log.success); } /** * Gets the final output of the workflow. * The final output is the output of the last step in execution order. * * @param sortedSteps - Steps in topological order * @param context - Execution context * @returns Output from the final step, or undefined if no steps or last step failed */ getFinalOutput(sortedSteps, context) { if (sortedSteps.length === 0 || context.logs.length === 0) { return void 0; } const lastLog = context.logs[context.logs.length - 1]; return lastLog.success ? lastLog.output : void 0; } /** * Groups steps by execution level for parallel execution. * Steps at the same level have no dependencies on each other and can run in parallel. * * @param sortedSteps - Topologically sorted steps * @returns Array of step arrays, where each inner array can be executed in parallel */ groupStepsByLevel(sortedSteps) { if (sortedSteps.length === 0) return []; const levels = []; const stepLevel = /* @__PURE__ */ new Map(); for (const step of sortedSteps) { let level = 0; if (step.dependsOn && step.dependsOn.length > 0) { for (const depName of step.dependsOn) { const depLevel = stepLevel.get(depName) ?? 0; level = Math.max(level, depLevel + 1); } } stepLevel.set(step.stepName, level); while (levels.length <= level) { levels.push([]); } levels[level].push(step); } return levels; } /** * Executes a step with condition evaluation. * * @param step - Step to execute * @param context - Execution context * @returns Execution result with step, log, and skipped flag */ async executeStepWithCondition(step, context) { try { (0, executor_1.validateStepExecution)(step, context); } catch (error) { const log2 = { stepName: step.stepName, model: step.model, startedAt: (/* @__PURE__ */ new Date()).toISOString(), finishedAt: (/* @__PURE__ */ new Date()).toISOString(), durationMs: 0, success: false, error: { type: "ValidationError", message: error instanceof Error ? error.message : String(error) }, attempts: 0 }; return { step, log: log2, skipped: false }; } if (step.condition) { const conditionResult = (0, condition_evaluator_1.evaluateCondition)(step.condition, context); if (conditionResult.error) { const log2 = { stepName: step.stepName, model: step.model, startedAt: (/* @__PURE__ */ new Date()).toISOString(), finishedAt: (/* @__PURE__ */ new Date()).toISOString(), durationMs: 0, success: false, error: { type: "ConditionError", message: conditionResult.error }, attempts: 0 }; return { step, log: log2, skipped: false }; } if (!conditionResult.shouldExecute) { const log2 = { stepName: step.stepName, model: step.model, startedAt: (/* @__PURE__ */ new Date()).toISOString(), finishedAt: (/* @__PURE__ */ new Date()).toISOString(), durationMs: 0, success: true, // Skipped steps are considered successful output: void 0, attempts: 0, skipped: true, skipReason: `Condition "${step.condition}" evaluated to false` }; return { step, log: log2, skipped: true }; } } const log = await (0, executor_1.executeStep)(step, context, this.adapterExecutor); return { step, log, skipped: false }; } }; exports$1.WorkflowRunner = WorkflowRunner; async function runWorkflow2(workflow, initialInput, adapterExecutor, options) { const runner = new WorkflowRunner(adapterExecutor); return runner.run(workflow, initialInput, options); } } }); // ../engine/dist/telemetry/tracer.js var require_tracer = __commonJS({ "../engine/dist/telemetry/tracer.js"(exports$1) { Object.defineProperty(exports$1, "__esModule", { value: true }); exports$1.createSpan = createSpan; exports$1.endSpan = endSpan; exports$1.addChildSpan = addChildSpan; exports$1.setSpanAttribute = setSpanAttribute; exports$1.generateTraceId = generateTraceId; exports$1.generateSpanId = generateSpanId; exports$1.createTraceContext = createTraceContext; exports$1.formatTraceparent = formatTraceparent; exports$1.parseTraceparent = parseTraceparent; exports$1.flattenSpans = flattenSpans; exports$1.totalDuration = totalDuration; exports$1.countSpans = countSpans; function createSpan(name, attributes = {}) { return { name, startTime: (/* @__PURE__ */ new Date()).toISOString(), status: "ok", attributes, children: [] }; } function endSpan(span, status = "ok", errorMessage) { span.endTime = (/* @__PURE__ */ new Date()).toISOString(); span.durationMs = new Date(span.endTime).getTime() - new Date(span.startTime).getTime(); span.status = status; if (errorMessage) { span.errorMessage = errorMessage; } } function addChildSpan(parent, child) { parent.children.push(child); } function setSpanAttribute(span, key, value) { span.attributes[key] = value; } function generateTraceId() { const bytes = new Uint8Array(16); if (typeof crypto !== "undefined" && crypto.getRandomValues) { crypto.getRandomValues(bytes); } else { for (let i = 0; i < 16; i++) { bytes[i] = Math.floor(Math.random() * 256); } } return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join(""); } function generateSpanId() { const bytes = new Uint8Array(8); if (typeof crypto !== "undefined" && crypto.getRandomValues) { crypto.getRandomValues(bytes); } else { for (let i = 0; i < 8; i++) { bytes[i] = Math.floor(Math.random() * 256); } } return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join(""); } function createTraceContext(parentContext) { return { traceId: parentContext?.traceId || generateTraceId(), spanId: generateSpanId(), parentSpanId: parentContext?.spanId }; } function formatTraceparent(context) { return `00-${context.traceId}-${context.spanId}-01`; } function parseTraceparent(traceparent) { const parts = traceparent.split("-"); if (parts.length !== 4 || parts[0] !== "00") { return void 0; } const [, traceId, spanId] = parts; if (traceId.length !== 32 || spanId.length !== 16) { return void 0; } return { traceId, spanId, parentSpanId: spanId // Use the parsed span as parent }; } function flattenSpans(span) { const result = [span]; for (const child of span.children) { result.push(...flattenSpans(child)); } return result; } function totalDuration(span) { return span.durationMs || 0; } function countSpans(span) { let count = 1; for (const child of span.children) { count += countSpans(child); } return count; } } }); // ../engine/dist/telemetry/index.js var require_telemetry = __commonJS({ "../engine/dist/telemetry/index.js"(exports$1) { Object.defineProperty(exports$1, "__esModule", { value: true }); exports$1.countSpans = exports$1.totalDuration = exports$1.flattenSpans = exports$1.parseTraceparent = exports$1.formatTraceparent = exports$1.createTraceContext = exports$1.generateSpanId = exports$1.generateTraceId = exports$1.setSpanAttribute = exports$1.addChildSpan = exports$1.endSpan = exports$1.createSpan = void 0; var tracer_1 = require_tracer(); Object.defineProperty(exports$1, "createSpan", { enumerable: true, get: function() { return tracer_1.createSpan; } }); Object.defineProperty(exports$1, "endSpan", { enumerable: true, get: function() { return tracer_1.endSpan; } }); Object.defineProperty(exports$1, "addChildSpan", { enumerable: true, get: function() { return tracer_1.addChildSpan; } }); Object.defineProperty(exports$1, "setSpanAttribute", { enumerable: true, get: function() { return tracer_1.setSpanAttribute; } }); Object.defineProperty(exports$1, "generateTraceId", { enumerable: true, get: function() { return tracer_1.generateTraceId; } }); Object.defineProperty(exports$1, "generateSpanId", { enumerable: true, get: function() { return tracer_1.generateSpanId; } }); Object.defineProperty(exports$1, "createTraceContext", { enumerable: true, get: function() { return tracer_1.createTraceContext; } }); Object.defineProperty(exports$1, "formatTraceparent", { enumerable: true, get: function() { return tracer_1.formatTraceparent; } }); Object.defineProperty(exports$1, "parseTraceparent", { enumerable: true, get: function() { return tracer_1.parseTraceparent; } }); Object.defineProperty(exports$1, "flattenSpans", { enumerable: true, get: function() { return tracer_1.flattenSpans; } }); Object.defineProperty(exports$1, "totalDuration", { enumerable: true, get: function() { return tracer_1.totalDuration; } }); Object.defineProperty(exports$1, "countSpans", { enumerable: true, get: function() { return tracer_1.countSpans; } }); } }); // ../engine/dist/index.js var require_dist = __commonJS({ "../engine/dist/index.js"(exports$1) { var __createBinding = exports$1 && exports$1.__createBinding || (Object.create ? (function(o, m, k, k2) { if (k2 === void 0) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === void 0) k2 = k; o[k2] = m[k]; })); var __exportStar = exports$1 && exports$1.__exportStar || function(m, exports2) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports2, p)) __createBinding(exports2, m, p); }; Object.defineProperty(exports$1, "__esModule", { value: true }); exports$1.runWorkflow = exports$1.WorkflowRunner = exports$1.generateRunId = exports$1.generateUUID = exports$1.hasTemplateVariables = exports$1.interpolateValue = exports$1.interpolate = exports$1.validateCondition = exports$1.evaluateCondition = exports$1.isRecoverableError = exports$1.sleep = exports$1.calculateBackoff = exports$1.areDependenciesReady = exports$1.resolveStepInput = exports$1.validateStepExecution = exports$1.executeStep = exports$1.ExecutionContextImpl = exports$1.detectCycles = exports$1.topologicalSort = exports$1.validateAndSort = void 0; __exportStar(require_types(), exports$1); var dag_1 = require_dag(); Object.defineProperty(exports$1, "validateAndSort", { enumerable: true, get: function() { return dag_1.validateAndSort; } }); Object.defineProperty(exports$1, "topologicalSort", { enumerable: true, get: function() { return dag_1.topologicalSort; } }); Object.defineProperty(exports$1, "detectCycles", { enumerable: true, get: function() { return dag_1.detectCycles; } }); var context_1 = require_context(); Object.defineProperty(exports$1, "ExecutionContextImpl", { enumerable: true, get: function() { return context_1.ExecutionContextImpl; } }); var executor_1 = require_executor(); Object.defineProperty(exports$1, "executeStep", { enumerable: true, get: function() { return executor_1.executeStep; } }); Object.defineProperty(exports$1, "validateStepExecution", { enumerable: true, get: function() { return executor_1.validateStepExecution; } }); var input_resolver_1 = require_input_resolver(); Object.defineProperty(exports$1, "resolveStepInput", { enumerable: true, get: function() { return input_resolver_1.resolveStepInput; } }); Object.defineProperty(exports$1, "areDependenciesRe