@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
JavaScript
;
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
});