UNPKG

@candoa/workflows

Version:

Type-safe workflow SDK for Candoa with Copilot-friendly syntax. Define chat workflows with triggers, actions, and type safety.

421 lines (415 loc) 11.7 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name2 in all) __defProp(target, name2, { get: all[name2], enumerable: true }); }; 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 __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var src_exports = {}; __export(src_exports, { addTags: () => addTags, buildWorkflowContext: () => buildWorkflowContext, collectEmail: () => collectEmail, collectFirstName: () => collectFirstName, collectLastName: () => collectLastName, conditional: () => conditional, createTask: () => createTask, createTrigger: () => createTrigger, extractWorkflowMetrics: () => extractWorkflowMetrics, handoffToHuman: () => handoffToHuman, name: () => name, prepareWorkflowForDatabase: () => prepareWorkflowForDatabase, saveToContact: () => saveToContact, sendEmail: () => sendEmail, sendMessage: () => sendMessage, serializeWorkflow: () => serializeWorkflow, setVariable: () => setVariable, updateWorkflowStats: () => updateWorkflowStats, validateWorkflow: () => validateWorkflow, validateWorkflowCompatibility: () => validateWorkflowCompatibility, version: () => version, wait: () => wait, workflow: () => workflow }); module.exports = __toCommonJS(src_exports); // src/workflow.ts var WorkflowWithTriggerImpl = class { constructor(name2, config, triggerType) { this.name = name2; this.config = config; this.triggerType = triggerType; } /** * Defines the actions to execute when the trigger fires * @param actions List of workflow actions to execute in sequence * @returns Complete workflow definition */ use(...actions) { return { name: this.name, config: this.config, trigger: { type: this.triggerType }, actions }; } }; var WorkflowBuilderImpl = class { constructor(name2, config = {}) { this.name = name2; this.config = config; } /** * Defines the trigger that will start this workflow * @param trigger The event type that triggers this workflow * @returns Builder with trigger set, ready for actions */ on(trigger) { return new WorkflowWithTriggerImpl(this.name, this.config, trigger); } }; function workflow(name2, config = {}) { return new WorkflowBuilderImpl(name2, config); } function createTrigger(type, conditions) { return { type, conditions }; } function validateWorkflow(workflowDef) { const errors = []; if (!workflowDef.name || workflowDef.name.trim().length === 0) { errors.push("Workflow name is required"); } if (!workflowDef.trigger?.type) { errors.push("Workflow trigger is required"); } if (!workflowDef.actions || workflowDef.actions.length === 0) { errors.push("Workflow must have at least one action"); } workflowDef.actions?.forEach((action, index) => { if (!action.type) { errors.push(`Action at index ${index} is missing type`); } if (!action.params) { errors.push(`Action at index ${index} is missing params`); } }); return errors; } function serializeWorkflow(workflowDef) { return { name: workflowDef.name, description: workflowDef.config.description, trigger: workflowDef.trigger, actions: workflowDef.actions, version: "1.0", createdAt: (/* @__PURE__ */ new Date()).toISOString(), // Add fields that would be useful for the Candoa platform enabled: true, metadata: { sdk_version: "0.1.0", triggers_count: 1, actions_count: workflowDef.actions.length } }; } // src/database-utils.ts function prepareWorkflowForDatabase(workflowDef, projectId) { return { name: workflowDef.name, projectId, workflowData: { // Core workflow definition name: workflowDef.name, description: workflowDef.config.description, trigger: workflowDef.trigger, actions: workflowDef.actions, // Metadata for the platform metadata: { version: "1.0", enabled: true, sdk_version: "0.1.0", // Analytics fields triggers_count: 1, actions_count: workflowDef.actions.length, // Execution tracking last_executed: null, execution_count: 0, success_count: 0, error_count: 0, // Integration settings integrations: { handoff: true, // Integrates with automated handoff contacts: true, // Can create/update contacts conversations: true, // Works with conversation system tasks: true, // Can create tasks emails: true // Can send emails }, // Permissions access_levels: ["AI_AGENT", "AI_COPILOT"], // Created timestamp created_at: (/* @__PURE__ */ new Date()).toISOString() } } }; } function buildWorkflowContext(params) { const { conversationId, contactData = {}, messageHistory = [], triggerData = {} } = params; return { // Conversation context conversationId: conversationId || "", conversation_history_count: messageHistory.length, user_questions_count: messageHistory.filter( (msg) => msg.role === "user" && msg.content.includes("?") ).length, // Contact context (matches your contact schema) contactId: contactData.id || "", firstName: contactData.firstName || contactData.name?.split(" ")[0] || "", lastName: contactData.lastName || contactData.name?.split(" ")[1] || "", email: contactData.email || "", phone: contactData.phoneNumber || "", company: contactData.company || "", // Trigger-specific context ...triggerData, // Timestamp context timestamp: (/* @__PURE__ */ new Date()).toISOString(), date: (/* @__PURE__ */ new Date()).toLocaleDateString(), time: (/* @__PURE__ */ new Date()).toLocaleTimeString() }; } function validateWorkflowCompatibility(workflowDef) { const warnings = []; const errors = []; const supportedTriggers = [ "chat.started", "chat.ended", "message.received", "intent.detected", "sentiment.negative", "payment.failed", "user.signup", "custom.event" ]; if (!supportedTriggers.includes(workflowDef.trigger.type)) { errors.push(`Unsupported trigger type: ${workflowDef.trigger.type}`); } const supportedActions = [ "collect_first_name", "collect_last_name", "collect_email", "save_to_contact", "send_message", "send_email", "handoff_to_human", "create_task", "add_tags", "wait", "set_variable", "conditional" ]; for (const action of workflowDef.actions) { if (!supportedActions.includes(action.type)) { warnings.push(`Action type '${action.type}' may not be fully supported`); } if (action.type === "save_to_contact") { const validFields = ["firstName", "lastName", "email", "phone", "company"]; const field = action.params.field; if (!validFields.includes(field)) { errors.push( `Invalid contact field '${field}'. Valid fields: ${validFields.join(", ")}` ); } } } if (workflowDef.actions.length > 20) { warnings.push( "Workflow has many actions - consider breaking it into smaller workflows" ); } const hasWait = workflowDef.actions.some((action) => action.type === "wait"); if (hasWait) { warnings.push( "Workflow contains wait actions - ensure your system supports delayed execution" ); } return { isValid: errors.length === 0, warnings, errors }; } function extractWorkflowMetrics(workflowDef, executionResult) { return { workflow_name: workflowDef.name, trigger_type: workflowDef.trigger.type, actions_count: workflowDef.actions.length, actions_completed: executionResult.actionsCompleted, execution_time_ms: executionResult.executionTime, success: executionResult.success, error: executionResult.error, timestamp: (/* @__PURE__ */ new Date()).toISOString() }; } function updateWorkflowStats(currentWorkflowData, wasSuccessful) { return { ...currentWorkflowData, metadata: { ...currentWorkflowData.metadata, last_executed: (/* @__PURE__ */ new Date()).toISOString(), execution_count: (currentWorkflowData.metadata.execution_count || 0) + 1, success_count: wasSuccessful ? (currentWorkflowData.metadata.success_count || 0) + 1 : currentWorkflowData.metadata.success_count || 0, error_count: !wasSuccessful ? (currentWorkflowData.metadata.error_count || 0) + 1 : currentWorkflowData.metadata.error_count || 0 } }; } // src/actions.ts function collectFirstName(params) { return { type: "collect_first_name", params: { prompt: params.prompt, errorMessage: params.errorMessage || "I didn't catch that. Could you please tell me your first name?", maxRetries: params.maxRetries || 3 } }; } function collectLastName(params) { return { type: "collect_last_name", params: { prompt: params.prompt, errorMessage: params.errorMessage || "Could you please tell me your last name?", maxRetries: params.maxRetries || 3 } }; } function collectEmail(params) { return { type: "collect_email", params: { prompt: params.prompt, errorMessage: params.errorMessage || "Please provide a valid email address.", maxRetries: params.maxRetries || 3 } }; } function saveToContact(params) { return { type: "save_to_contact", params }; } function sendMessage(params) { return { type: "send_message", params: { message: params.message, delay: params.delay || 0 } }; } function setVariable(params) { return { type: "set_variable", params }; } function conditional(params) { return { type: "conditional", params }; } function wait(params) { return { type: "wait", params: { duration: params.duration, unit: params.unit || "seconds" } }; } function handoffToHuman(params) { return { type: "handoff_to_human", params: { reason: params.reason || "User requested human assistance" } }; } function sendEmail(params) { return { type: "send_email", params }; } function createTask(params) { return { type: "create_task", params: { title: params.title, description: params.description || "", assignee: params.assignee || "" } }; } function addTags(params) { return { type: "add_tags", params: { tags: params.tags, target: params.target || "conversation" } }; } // src/index.ts var version = "0.1.0"; var name = "@candoa/workflows"; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { addTags, buildWorkflowContext, collectEmail, collectFirstName, collectLastName, conditional, createTask, createTrigger, extractWorkflowMetrics, handoffToHuman, name, prepareWorkflowForDatabase, saveToContact, sendEmail, sendMessage, serializeWorkflow, setVariable, updateWorkflowStats, validateWorkflow, validateWorkflowCompatibility, version, wait, workflow });