jsfe 0.2.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +418 -43
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -16,7 +16,7 @@ npm i jsfe
16
16
 
17
17
  ## Usage
18
18
 
19
- ```typescript
19
+ ```javascript
20
20
  import { WorkflowEngine } from "jsfe";
21
21
 
22
22
  // 1. Create the engine
@@ -36,8 +36,220 @@ const engine = new WorkflowEngine(
36
36
  // 2. Initialize a session for each user
37
37
  const sessionContext = engine.initSession(yourLogger, 'user-123', 'session-456');
38
38
 
39
- // 3. Process user input and assistant responses
40
- const result = await engine.updateActivity(contextEntry, sessionContext);
39
+ // 3. Plug-in the engine to process User message
40
+ const userEntry = {
41
+ role: 'user',
42
+ content: 'I need help with my account',
43
+ };
44
+ const result = await engine.updateActivity(userEntry, sessionContext);
45
+ if (result) {
46
+ // Intent detected and handled no need to proceed to normal response generation
47
+ return result;
48
+ }
49
+
50
+ // 4. Call your normal Generate reply process as usual
51
+ const reply = await yourConversationalReply(input);
52
+
53
+ // 5. Update the engine's context with the generated reply
54
+ const assistantEntry = {
55
+ role: 'assistant',
56
+ content: 'I can help you with your account. What specific issue are you experiencing?',
57
+ };
58
+ await engine.updateActivity(assistantEntry, sessionContext);
59
+
60
+ // Return the generated reply to the user
61
+ return reply;
62
+ ```
63
+
64
+ ## Engine Initialization Parameters
65
+
66
+ The WorkflowEngine constructor accepts the following parameters in order, each serving a specific purpose in the engine's operation:
67
+
68
+ **1. hostLogger** (Logger | null)
69
+ - **Purpose**: Primary logging interface for the host application
70
+ - **Requirements**: Must support `.debug()`, `.info()`, `.warn()`, `.error()` methods
71
+ - **Usage**: Engine uses this for all operational logging and debugging output
72
+ - **Example**: Winston, or custom logger implementation
73
+ - **Nullable**: Can be `null` to disable host application logging
74
+
75
+ **2. aiCallback** (Function)
76
+ - **Purpose**: AI communication function for intent detection and response generation
77
+ - **Signature**: `async (systemInstruction: string, userMessage: string) => string`
78
+ - **Integration**: Engine calls this function when AI analysis is needed
79
+ - **Requirements**: Must return AI response as string, handle errors gracefully
80
+ - **Details**: See dedicated AI Callback Function section below
81
+
82
+ **3. flowsMenu** (FlowDefinition[])
83
+ - **Purpose**: Array of available workflow definitions
84
+ - **Content**: All workflows that the engine can detect and execute
85
+ - **Validation**: Engine validates flow structure during initialization
86
+ - **Requirements**: Each flow must have valid id, name, description, and steps
87
+
88
+ **4. toolsRegistry** (ToolDefinition[])
89
+ - **Purpose**: Array of external tool definitions for CALL-TOOL steps
90
+ - **Content**: HTTP APIs, local functions, and mock tools available to workflows
91
+ - **Validation**: Parameter schemas validated against OpenAI Function Calling Standard
92
+ - **Security**: Tools define their own security levels and authentication requirements
93
+
94
+ **5. APPROVED_FUNCTIONS** (Map<string, Function>)
95
+ - **Purpose**: Secure registry of pre-approved local JavaScript functions
96
+ - **Security**: Only functions in this map can be executed by local-type tools
97
+ - **Format**: `Map` where keys are function names and values are the actual functions
98
+ - **Validation**: Functions must match tool definitions in toolsRegistry
99
+
100
+ **6. globalVariables** (Record<string, unknown>, optional)
101
+ - **Purpose**: Session-wide variables accessible to all workflows
102
+ - **Scope**: Available to all flows in the session via variable interpolation
103
+ - **Security**: Safe sharing of host application data with workflows
104
+ - **Examples**: User ID, session ID, application configuration, environmental data
105
+
106
+ **7. validateOnInit** (boolean, optional)
107
+ - **Purpose**: Enable comprehensive flow and tool validation during initialization
108
+ - **Default**: `true` - recommended for development and production
109
+ - **Performance**: Set to `false` only in high-performance scenarios with pre-validated flows
110
+ - **Output**: Detailed validation reports with errors, warnings, and success metrics
111
+
112
+ **8. language** (string, optional)
113
+ - **Purpose**: User's preferred language for localized messages and prompts
114
+ - **Format**: ISO language code ('en', 'es', 'fr', 'de', etc.)
115
+ - **Default**: 'en' if not specified
116
+ - **Usage**: Engine selects appropriate prompt_xx properties from flow definitions
117
+
118
+ **9. messageRegistry** (MessageRegistry, optional)
119
+ - **Purpose**: Custom message templates for engine-generated user messages
120
+ - **Format**: Multi-language message registry with customizable system messages
121
+ - **Override**: Allows customization of built-in engine messages
122
+ - **Localization**: Supports multiple languages with fallback to default messages
123
+
124
+ **10. guidanceConfig** (GuidanceConfig, optional)
125
+ - **Purpose**: Configuration for user guidance and help messages
126
+ - **Features**: Controls how and when the engine provides user assistance
127
+ - **Modes**: Append, prepend, template, or none for guidance integration
128
+ - **Context**: Different guidance for general vs. payment/financial workflows
129
+
130
+ ### AI Callback Function
131
+
132
+ The `aiCallback` parameter provides the engine access to your AI system for intent detection and workflow triggering. Here's a minimal implementation example:
133
+
134
+ ```javascript
135
+ // Minimal AI callback implementation
136
+ async function aiCallback(systemInstruction, userMessage) {
137
+ try {
138
+ const response = await fetch("https://api.openai.com/v1/chat/completions", {
139
+ method: "POST",
140
+ headers: {
141
+ "Content-Type": "application/json",
142
+ "Authorization": `Bearer ${YOUR_OPENAI_API_KEY}`
143
+ },
144
+ body: JSON.stringify({
145
+ model: "gpt-4o-mini",
146
+ messages: [
147
+ { role: "system", content: systemInstruction },
148
+ { role: "user", content: userMessage }
149
+ ],
150
+ temperature: 0.1,
151
+ max_tokens: 200
152
+ })
153
+ });
154
+
155
+ if (!response.ok) {
156
+ throw new Error(`AI API request failed: ${response.status} ${response.statusText}`);
157
+ }
158
+
159
+ const data = await response.json();
160
+ return data.choices[0].message.content.trim();
161
+
162
+ } catch (error) {
163
+ throw new Error(`AI communication failed: ${error.message}`);
164
+ }
165
+ }
166
+ ```
167
+
168
+ **AI Callback Interface:**
169
+ - **Input**: `systemInstruction` (string), `userMessage` (string)
170
+ - **Output**: AI response as a string
171
+ - **Purpose**: Analyzes user input to detect workflow intents and generate responses
172
+ - **Integration**: The engine calls this function when it needs AI analysis for intent detection
173
+
174
+ **How the Engine Generates Input Arguments:**
175
+ - **`systemInstruction`**: Dynamically generated by the engine based on:
176
+ - Available flow definitions and their descriptions
177
+ - Current session context and active flows
178
+ - Current conversation state and collected variables
179
+ - **`userMessage`**: Intelligently composed by the engine, including:
180
+ - The actual user input/prompt
181
+ - Relevant contextual information from the conversation
182
+ - Session state and variables needed for intent analysis
183
+
184
+ Both parameters are carefully engineered by the engine to work together for optimal intent detection. The engine automatically constructs comprehensive, context-aware prompts that provide the AI with all necessary information for accurate workflow selection and response generation. Your aiCallback implementation only needs to send these pre-constructed arguments to your AI service and return the response.
185
+
186
+ **Alternative AI Services:**
187
+ You can integrate any AI service (Claude, Gemini, local LLMs, etc.) by implementing this same interface. The engine only requires a function that takes system instructions and user input, then returns an AI response.
188
+
189
+ ### Core Registries
190
+
191
+ The engine operates through four primary registries that define its capabilities:
192
+
193
+ #### 1. **Flows Registry** - Workflow Definitions
194
+ ```javascript
195
+ const flowsMenu = [
196
+ {
197
+ id: "payment-workflow",
198
+ name: "ProcessPayment",
199
+ prompt: "Process a payment",
200
+ description: "Handle payment processing with validation",
201
+ steps: [
202
+ { type: "SAY", value: "Let's process your payment." },
203
+ { type: "SAY-GET", variable: "amount", value: "Enter amount:" },
204
+ { type: "CALL-TOOL", tool: "PaymentProcessor", args: {...} }
205
+ ]
206
+ }
207
+ ];
208
+ ```
209
+
210
+ #### 2. **Tools Registry** - External Integrations
211
+ ```javascript
212
+ const toolsRegistry = [
213
+ {
214
+ id: "PaymentProcessor",
215
+ name: "Process Payment",
216
+ description: "Processes financial transactions securely",
217
+ parameters: { /* OpenAI Function Calling Standard Schema */ },
218
+ implementation: {
219
+ type: "local", // or "http" for REST APIs
220
+ function: "processPayment",
221
+ timeout: 10000
222
+ },
223
+ security: {
224
+ requiresAuth: true,
225
+ auditLevel: "critical",
226
+ dataClassification: "financial"
227
+ }
228
+ }
229
+ ];
230
+ ```
231
+
232
+ #### 3. **Approved Functions Registry** - Secure Local Functions
233
+ ```javascript
234
+ const APPROVED_FUNCTIONS = new Map();
235
+
236
+ // Define secure local functions
237
+ async function processPayment(args) {
238
+ // Secure payment processing logic
239
+ return { transactionId: "...", status: "success" };
240
+ }
241
+
242
+ // Register approved functions
243
+ APPROVED_FUNCTIONS.set('processPayment', processPayment);
244
+ ```
245
+
246
+ #### 4. **Global Variables** - Secure Sharing of Local Data
247
+ ```javascript
248
+ const globalVariables = {
249
+ caller_id: "(555) 123-4567",
250
+ caller_name: "John Doe",
251
+ thread_id: "conversation-123"
252
+ };
41
253
  ```
42
254
 
43
255
  ### Session Management
@@ -58,35 +270,12 @@ interface ContextEntry {
58
270
  role: 'user' | 'assistant' | 'system' | 'tool'; // Message role type
59
271
  content: string | Record<string, unknown>; // Message content (text, object, etc.)
60
272
  timestamp: number; // Unix timestamp in milliseconds
61
- stepId?: string; // Optional: Associated flow step ID
62
- toolName?: string; // Optional: Tool name for tool messages
273
+ stepId?: string; // Optional: Used by the system when a Step calls a Tool
274
+ toolName?: string; // Optional: Used by the system to record Tool result into the chat context
63
275
  metadata?: Record<string, unknown>; // Optional: Additional context data
64
276
  }
65
277
  ```
66
278
 
67
- ### Example Usage
68
-
69
- ```typescript
70
- // User message
71
- const userEntry = {
72
- role: 'user',
73
- content: 'I need help with my account',
74
- timestamp: Date.now()
75
- };
76
- // Process the message
77
- await engine.updateActivity(userEntry, sessionContext);
78
-
79
- // Assistant response
80
- const assistantEntry = {
81
- role: 'assistant',
82
- content: 'I can help you with your account. What specific issue are you experiencing?',
83
- timestamp: Date.now(),
84
- stepId: 'greeting-step'
85
- };
86
- // Process the message
87
- await engine.updateActivity(assistantEntry, sessionContext);
88
- ```
89
-
90
279
  ## Architecture Overview
91
280
 
92
281
  ### Stack-of-Stacks Design
@@ -100,25 +289,38 @@ The Flow Engine implements a sophisticated "stack-of-stacks" architecture that a
100
289
  - Automatic stack switching for flow interruption/resumption
101
290
  - Proper isolation between different workflow contexts
102
291
 
103
- 2. **Flow Frame Structure**
292
+ 2. **Flow Frame Structure (Runtime Execution Context)**
104
293
  Each flow execution maintains a complete context frame:
105
294
  ```typescript
106
- {
107
- flowName: string, // Human-readable flow name
108
- flowId: string, // Unique flow identifier
109
- flowVersion: string, // Flow version for compatibility
110
- flowStepsStack: [...], // Remaining steps (reversed)
111
- contextStack: [...], // Complete interaction history
112
- inputStack: [...], // Current input context
113
- variables: {}, // Unified variable storage
114
- transaction: TransactionObj, // Audit and transaction tracking
115
- userId: string, // User identifier
116
- startTime: number, // Flow start timestamp
117
- pendingVariable: string, // Variable awaiting user input
118
- lastSayMessage: string, // Last SAY step output
119
- pendingInterruption: {} // Interruption state management
295
+ interface FlowFrame {
296
+ flowName: string; // Human-readable flow name (from FlowDefinition.name)
297
+ flowId: string; // Unique flow identifier (from FlowDefinition.id)
298
+ flowVersion: string; // Flow version for compatibility (from FlowDefinition.version)
299
+ flowStepsStack: FlowStep[]; // Remaining steps (reversed for efficient pop)
300
+ contextStack: ContextEntry[]; // Complete interaction history with role info
301
+ inputStack: unknown[]; // Current input context for step execution
302
+ variables: Record<string, unknown>; // Unified variable storage (shared across sub-flows)
303
+ transaction: TransactionObj; // Comprehensive transaction and audit tracking
304
+ userId: string; // User identifier for this flow session
305
+ startTime: number; // Flow start timestamp for timing analysis
306
+ pendingVariable?: string; // Variable name awaiting user input (SAY-GET steps)
307
+ lastSayMessage?: string; // Last SAY step output for context
308
+ pendingInterruption?: Record<string, unknown>; // Interruption state management
309
+ accumulatedMessages?: string[]; // Accumulated SAY messages for batching
310
+ parentTransaction?: string; // Parent transaction ID for sub-flow tracking
311
+ justResumed?: boolean; // Flag indicating flow was just resumed
120
312
  }
121
313
  ```
314
+
315
+ **Technical Implementation Details:**
316
+ - **Flow Identity**: `flowName`, `flowId`, `flowVersion` are copied from the FlowDefinition
317
+ - **Dynamic Properties**: Flow `prompt`, `description`, and localized prompts are accessed dynamically from FlowDefinition
318
+ - **flowStepsStack**: Steps stored in reverse order for efficient pop operations
319
+ - **contextStack**: Enhanced with role information for complete conversation context
320
+ - **variables**: Flat storage shared across sub-flows for seamless data passing
321
+ - **accumulatedMessages**: SAY steps are batched for efficient output
322
+ - **justResumed**: Helps engine provide appropriate resumption messages
323
+ ```
122
324
 
123
325
  3. **Helper Function Architecture**
124
326
  All stack operations go through centralized helper functions:
@@ -127,6 +329,179 @@ The Flow Engine implements a sophisticated "stack-of-stacks" architecture that a
127
329
  - `pushToCurrentStack(engine, frame)`: Adds flow to active stack
128
330
  - `popFromCurrentStack(engine)`: Removes flow from active stack
129
331
 
332
+ 4. **Tool Definition Structure (Runtime Integration Context)**
333
+ Tools provide external capabilities with comprehensive security and validation:
334
+ ```typescript
335
+ interface ToolDefinition {
336
+ id: string; // Unique tool identifier
337
+ name: string; // Human-readable tool name
338
+ description: string; // Tool functionality description
339
+
340
+ parameters?: { // OpenAI Function Calling Standard schema
341
+ type: string; // Parameter type structure
342
+ properties?: Record<string, PropertySchema>; // Parameter validation rules
343
+ required?: string[]; // Required parameter names
344
+ additionalProperties?: boolean; // Additional parameter handling
345
+ };
346
+
347
+ implementation?: { // Execution configuration
348
+ type: 'local' | 'http'; // Implementation type
349
+ function?: string; // Local function name (APPROVED_FUNCTIONS)
350
+ url?: string; // HTTP endpoint with {param} placeholders
351
+ method?: HttpMethod; // HTTP method
352
+ pathParams?: string[]; // URL parameter substitution
353
+ queryParams?: string[]; // Query string parameters
354
+ responseMapping?: MappingConfig; // Response transformation config
355
+ timeout?: number; // Request timeout
356
+ retries?: number; // Retry attempts
357
+ };
358
+
359
+ security?: { // Security controls
360
+ rateLimit?: { // Rate limiting configuration
361
+ requests: number; // Max requests per window
362
+ window: number; // Time window in milliseconds
363
+ };
364
+ };
365
+ apiKey?: string; // Authentication token
366
+ riskLevel?: 'low' | 'medium' | 'high'; // Security classification
367
+ }
368
+ ```
369
+
370
+ **Technical Implementation Details:**
371
+ - **Parameter Validation**: JSON Schema validation with ajv for type safety
372
+ - **Local Function Execution**: Secure execution through APPROVED_FUNCTIONS registry
373
+ - **HTTP Integration**: Full REST API support with authentication and retries
374
+ - **Response Mapping**: Declarative transformation without code injection
375
+ - **Security Controls**: Rate limiting, risk classification, audit logging
376
+ - **Error Handling**: Automatic retry logic and graceful degradation
377
+
378
+ 5. **Response Mapping Configuration (MappingConfig Interface)**
379
+ The comprehensive response mapping system supports multiple transformation types:
380
+ ```typescript
381
+ export type MappingConfig =
382
+ | JsonPathMappingConfig
383
+ | ObjectMappingConfig
384
+ | ArrayMappingConfig
385
+ | TemplateMappingConfig
386
+ | ConditionalMappingConfig
387
+ | PathConfig
388
+ | string
389
+ | Record<string, unknown>;
390
+
391
+ // JSONPath-based field extraction and transformation
392
+ export type JsonPathMappingConfig = {
393
+ type: 'jsonPath';
394
+ mappings: Record<string, {
395
+ path: string; // JSONPath expression for data extraction
396
+ transform?: ValueTransformConfig; // Optional value transformation
397
+ fallback?: unknown; // Fallback value if path not found
398
+ }>;
399
+ strict?: boolean; // Strict mode validation
400
+ };
401
+
402
+ // Object structure mapping with nested support
403
+ export type ObjectMappingConfig = {
404
+ type: 'object';
405
+ mappings: Record<string, string | PathConfig | MappingConfig | object>;
406
+ strict?: boolean; // Strict mode validation
407
+ };
408
+
409
+ // Array processing with filtering, sorting, and pagination
410
+ export type ArrayMappingConfig = {
411
+ type: 'array';
412
+ source?: string; // Source array path
413
+ filter?: ConditionConfig; // Filtering conditions
414
+ itemMapping?: MappingConfig; // Per-item transformation
415
+ sort?: { field: string; order?: 'asc' | 'desc' }; // Sorting configuration
416
+ offset?: number; // Pagination offset
417
+ limit?: number; // Pagination limit
418
+ fallback?: unknown[]; // Fallback array if source not found
419
+ };
420
+
421
+ // Template-based string generation with variable substitution
422
+ export type TemplateMappingConfig = {
423
+ type: 'template';
424
+ template: string; // Template string with {{variable}} placeholders
425
+ dataPath?: string; // Optional path to resolve template data from
426
+ };
427
+
428
+ // Conditional logic-based mapping selection
429
+ export type ConditionalMappingConfig = {
430
+ type: 'conditional';
431
+ conditions: Array<{
432
+ if: ConditionConfig; // Condition evaluation
433
+ then: MappingConfig; // Mapping to apply if condition true
434
+ }>;
435
+ else?: MappingConfig; // Default mapping if no conditions match
436
+ };
437
+
438
+ // Path-based value extraction with transformation
439
+ export type PathConfig = {
440
+ path: string; // Data path for extraction
441
+ transform?: ValueTransformConfig; // Optional value transformation
442
+ fallback?: unknown; // Fallback value if path not found
443
+ };
444
+
445
+ // Comprehensive value transformation system with 25+ transform types
446
+ export interface ValueTransformConfig {
447
+ type: 'parseInt' | 'parseFloat' | 'toLowerCase' | 'toUpperCase' | 'trim' |
448
+ 'replace' | 'concat' | 'regex' | 'date' | 'default' | 'conditional' |
449
+ 'substring' | 'split' | 'join' | 'abs' | 'round' | 'floor' | 'ceil' |
450
+ 'template' | 'sum' | 'average' | 'count' | 'min' | 'max' | 'multiply' |
451
+ 'divide' | 'percentage' | 'add' | 'subtract' | 'currentYear' |
452
+ 'yearDifference' | 'handlebars' | 'custom';
453
+
454
+ // Common transformation parameters
455
+ fallback?: unknown; // Default value for failed transforms
456
+ prefix?: string; // String prefix for concat operations
457
+ suffix?: string; // String suffix for concat operations
458
+ pattern?: string; // Regex pattern for replace/match operations
459
+ replacement?: string; // Replacement string for regex operations
460
+ template?: string; // Template string for template transforms
461
+ value?: unknown; // Static value for default transforms
462
+
463
+ // Mathematical operation parameters
464
+ precision?: number; // Decimal precision for rounding operations
465
+ divisor?: number; // Divisor for division/percentage operations
466
+ multiplier?: number; // Multiplier for multiplication operations
467
+ addend?: number; // Value to add for addition operations
468
+ subtrahend?: number; // Value to subtract for subtraction operations
469
+
470
+ // Array and aggregation parameters
471
+ field?: string; // Field name for array aggregations
472
+ delimiter?: string; // Delimiter for join/split operations
473
+ index?: number; // Array index for element selection
474
+
475
+ // Conditional and date parameters
476
+ condition?: ConditionConfig; // Condition for conditional transforms
477
+ fromYear?: number; // Start year for year difference calculations
478
+ dataPath?: string; // Path for accessing context data
479
+ }
480
+
481
+ // Flexible condition evaluation system
482
+ export interface ConditionConfig {
483
+ field: string; // Field path for evaluation
484
+ operator: 'equals' | 'eq' | 'notEquals' | 'ne' | 'contains' | 'exists' |
485
+ 'notExists' | 'greaterThan' | 'gt' | 'lessThan' | 'lt' |
486
+ 'greaterThanOrEqual' | 'gte' | 'lessThanOrEqual' | 'lte' |
487
+ 'startsWith' | 'endsWith' | 'matches' | 'in' | 'hasLength' |
488
+ 'isArray' | 'isObject' | 'isString' | 'isNumber';
489
+ value?: unknown; // Comparison value for operators
490
+ }
491
+ ```
492
+
493
+ **Response Mapping Technical Features:**
494
+ - **Type Safety**: Full TypeScript interface definitions with validation
495
+ - **Declarative Configuration**: No code injection - pure JSON configuration
496
+ - **Comprehensive Transforms**: 25+ built-in transformation types
497
+ - **Mathematical Operations**: Arithmetic, statistical, and precision control
498
+ - **Date Processing**: Dynamic date calculations and formatting
499
+ - **Template System**: Handlebars-style variable substitution with array iteration
500
+ - **Conditional Logic**: Complex branching and filtering capabilities
501
+ - **Array Processing**: Filtering, sorting, pagination, and aggregation
502
+ - **Path Resolution**: JSONPath support with fallback handling
503
+ - **Security**: Complete input sanitization and validation
504
+
130
505
  ## Features & Capabilities
131
506
 
132
507
  ### Flow Execution Modes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jsfe",
3
- "version": "0.2.0",
3
+ "version": "0.5.0",
4
4
  "description": "TypeScript workflow engine for conversational/automation apps: multi-flow orchestration, interrupt/resume, stack-based control, robust errors, and flexible tool/REST integration.",
5
5
  "license": "MIT",
6
6
  "author": "Ron Pinkas",