praisonai 1.2.1 → 1.2.2

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 (45) hide show
  1. package/dist/cache/index.d.ts +78 -0
  2. package/dist/cache/index.js +235 -0
  3. package/dist/db/postgres.d.ts +84 -0
  4. package/dist/db/postgres.js +266 -0
  5. package/dist/db/redis.d.ts +109 -0
  6. package/dist/db/redis.js +307 -0
  7. package/dist/db/sqlite.d.ts +66 -0
  8. package/dist/db/sqlite.js +339 -0
  9. package/dist/events/index.d.ts +84 -0
  10. package/dist/events/index.js +153 -0
  11. package/dist/index.d.ts +11 -0
  12. package/dist/index.js +84 -1
  13. package/dist/integrations/index.d.ts +7 -0
  14. package/dist/integrations/index.js +26 -0
  15. package/dist/integrations/observability/base.d.ts +123 -0
  16. package/dist/integrations/observability/base.js +183 -0
  17. package/dist/integrations/observability/index.d.ts +8 -0
  18. package/dist/integrations/observability/index.js +29 -0
  19. package/dist/integrations/observability/langfuse.d.ts +32 -0
  20. package/dist/integrations/observability/langfuse.js +174 -0
  21. package/dist/integrations/vector/base.d.ts +110 -0
  22. package/dist/integrations/vector/base.js +158 -0
  23. package/dist/integrations/vector/chroma.d.ts +25 -0
  24. package/dist/integrations/vector/chroma.js +143 -0
  25. package/dist/integrations/vector/index.d.ts +14 -0
  26. package/dist/integrations/vector/index.js +37 -0
  27. package/dist/integrations/vector/pinecone.d.ts +28 -0
  28. package/dist/integrations/vector/pinecone.js +172 -0
  29. package/dist/integrations/vector/qdrant.d.ts +25 -0
  30. package/dist/integrations/vector/qdrant.js +146 -0
  31. package/dist/integrations/vector/weaviate.d.ts +30 -0
  32. package/dist/integrations/vector/weaviate.js +206 -0
  33. package/dist/integrations/voice/base.d.ts +76 -0
  34. package/dist/integrations/voice/base.js +168 -0
  35. package/dist/integrations/voice/index.d.ts +6 -0
  36. package/dist/integrations/voice/index.js +26 -0
  37. package/dist/knowledge/graph-rag.d.ts +125 -0
  38. package/dist/knowledge/graph-rag.js +289 -0
  39. package/dist/knowledge/index.d.ts +2 -0
  40. package/dist/knowledge/index.js +18 -0
  41. package/dist/knowledge/reranker.d.ts +86 -0
  42. package/dist/knowledge/reranker.js +196 -0
  43. package/dist/workflows/yaml-parser.d.ts +48 -0
  44. package/dist/workflows/yaml-parser.js +304 -0
  45. package/package.json +1 -1
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Reranker - Rerank search results for improved relevance
3
+ * Inspired by mastra's rerank module
4
+ */
5
+ export interface RerankResult {
6
+ id: string;
7
+ score: number;
8
+ content: string;
9
+ metadata?: Record<string, any>;
10
+ originalRank: number;
11
+ newRank: number;
12
+ }
13
+ export interface RerankConfig {
14
+ model?: string;
15
+ topK?: number;
16
+ threshold?: number;
17
+ }
18
+ /**
19
+ * Abstract base class for rerankers
20
+ */
21
+ export declare abstract class BaseReranker {
22
+ readonly name: string;
23
+ constructor(name: string);
24
+ abstract rerank(query: string, documents: Array<{
25
+ id: string;
26
+ content: string;
27
+ metadata?: Record<string, any>;
28
+ }>, config?: RerankConfig): Promise<RerankResult[]>;
29
+ }
30
+ /**
31
+ * Cohere Reranker - Uses Cohere's rerank API
32
+ */
33
+ export declare class CohereReranker extends BaseReranker {
34
+ private apiKey;
35
+ private model;
36
+ constructor(config?: {
37
+ apiKey?: string;
38
+ model?: string;
39
+ });
40
+ rerank(query: string, documents: Array<{
41
+ id: string;
42
+ content: string;
43
+ metadata?: Record<string, any>;
44
+ }>, config?: RerankConfig): Promise<RerankResult[]>;
45
+ }
46
+ /**
47
+ * Cross-Encoder Reranker - Uses sentence similarity for reranking
48
+ * This is a simple implementation using cosine similarity
49
+ */
50
+ export declare class CrossEncoderReranker extends BaseReranker {
51
+ private embedFn?;
52
+ constructor(config?: {
53
+ embedFn?: (texts: string[]) => Promise<number[][]>;
54
+ });
55
+ rerank(query: string, documents: Array<{
56
+ id: string;
57
+ content: string;
58
+ metadata?: Record<string, any>;
59
+ }>, config?: RerankConfig): Promise<RerankResult[]>;
60
+ private keywordRerank;
61
+ private cosineSimilarity;
62
+ }
63
+ /**
64
+ * LLM Reranker - Uses an LLM to score relevance
65
+ */
66
+ export declare class LLMReranker extends BaseReranker {
67
+ private generateFn;
68
+ constructor(config: {
69
+ generateFn: (prompt: string) => Promise<string>;
70
+ });
71
+ rerank(query: string, documents: Array<{
72
+ id: string;
73
+ content: string;
74
+ metadata?: Record<string, any>;
75
+ }>, config?: RerankConfig): Promise<RerankResult[]>;
76
+ }
77
+ export declare function createCohereReranker(config?: {
78
+ apiKey?: string;
79
+ model?: string;
80
+ }): CohereReranker;
81
+ export declare function createCrossEncoderReranker(config?: {
82
+ embedFn?: (texts: string[]) => Promise<number[][]>;
83
+ }): CrossEncoderReranker;
84
+ export declare function createLLMReranker(config: {
85
+ generateFn: (prompt: string) => Promise<string>;
86
+ }): LLMReranker;
@@ -0,0 +1,196 @@
1
+ "use strict";
2
+ /**
3
+ * Reranker - Rerank search results for improved relevance
4
+ * Inspired by mastra's rerank module
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.LLMReranker = exports.CrossEncoderReranker = exports.CohereReranker = exports.BaseReranker = void 0;
8
+ exports.createCohereReranker = createCohereReranker;
9
+ exports.createCrossEncoderReranker = createCrossEncoderReranker;
10
+ exports.createLLMReranker = createLLMReranker;
11
+ /**
12
+ * Abstract base class for rerankers
13
+ */
14
+ class BaseReranker {
15
+ constructor(name) {
16
+ this.name = name;
17
+ }
18
+ }
19
+ exports.BaseReranker = BaseReranker;
20
+ /**
21
+ * Cohere Reranker - Uses Cohere's rerank API
22
+ */
23
+ class CohereReranker extends BaseReranker {
24
+ constructor(config = {}) {
25
+ super('CohereReranker');
26
+ this.apiKey = config.apiKey || process.env.COHERE_API_KEY || '';
27
+ this.model = config.model || 'rerank-english-v3.0';
28
+ }
29
+ async rerank(query, documents, config) {
30
+ if (!this.apiKey) {
31
+ throw new Error('Cohere API key required for reranking');
32
+ }
33
+ const response = await fetch('https://api.cohere.ai/v1/rerank', {
34
+ method: 'POST',
35
+ headers: {
36
+ 'Authorization': `Bearer ${this.apiKey}`,
37
+ 'Content-Type': 'application/json'
38
+ },
39
+ body: JSON.stringify({
40
+ model: config?.model || this.model,
41
+ query,
42
+ documents: documents.map(d => d.content),
43
+ top_n: config?.topK || documents.length,
44
+ return_documents: true
45
+ })
46
+ });
47
+ if (!response.ok) {
48
+ const error = await response.text();
49
+ throw new Error(`Cohere rerank error: ${response.status} - ${error}`);
50
+ }
51
+ const data = await response.json();
52
+ const threshold = config?.threshold || 0;
53
+ return (data.results || [])
54
+ .filter((r) => r.relevance_score >= threshold)
55
+ .map((r, newRank) => ({
56
+ id: documents[r.index].id,
57
+ score: r.relevance_score,
58
+ content: documents[r.index].content,
59
+ metadata: documents[r.index].metadata,
60
+ originalRank: r.index,
61
+ newRank
62
+ }));
63
+ }
64
+ }
65
+ exports.CohereReranker = CohereReranker;
66
+ /**
67
+ * Cross-Encoder Reranker - Uses sentence similarity for reranking
68
+ * This is a simple implementation using cosine similarity
69
+ */
70
+ class CrossEncoderReranker extends BaseReranker {
71
+ constructor(config = {}) {
72
+ super('CrossEncoderReranker');
73
+ this.embedFn = config.embedFn;
74
+ }
75
+ async rerank(query, documents, config) {
76
+ if (!this.embedFn) {
77
+ // Fallback to simple keyword matching
78
+ return this.keywordRerank(query, documents, config);
79
+ }
80
+ // Get embeddings for query and all documents
81
+ const texts = [query, ...documents.map(d => d.content)];
82
+ const embeddings = await this.embedFn(texts);
83
+ const queryEmbedding = embeddings[0];
84
+ const docEmbeddings = embeddings.slice(1);
85
+ // Calculate similarity scores
86
+ const scores = docEmbeddings.map((docEmb, i) => ({
87
+ index: i,
88
+ score: this.cosineSimilarity(queryEmbedding, docEmb)
89
+ }));
90
+ // Sort by score descending
91
+ scores.sort((a, b) => b.score - a.score);
92
+ const threshold = config?.threshold || 0;
93
+ const topK = config?.topK || documents.length;
94
+ return scores
95
+ .filter(s => s.score >= threshold)
96
+ .slice(0, topK)
97
+ .map((s, newRank) => ({
98
+ id: documents[s.index].id,
99
+ score: s.score,
100
+ content: documents[s.index].content,
101
+ metadata: documents[s.index].metadata,
102
+ originalRank: s.index,
103
+ newRank
104
+ }));
105
+ }
106
+ keywordRerank(query, documents, config) {
107
+ const queryTerms = query.toLowerCase().split(/\s+/);
108
+ const scores = documents.map((doc, i) => {
109
+ const content = doc.content.toLowerCase();
110
+ let score = 0;
111
+ for (const term of queryTerms) {
112
+ if (content.includes(term)) {
113
+ score += 1;
114
+ }
115
+ }
116
+ // Normalize by query length
117
+ score = score / queryTerms.length;
118
+ return { index: i, score };
119
+ });
120
+ scores.sort((a, b) => b.score - a.score);
121
+ const threshold = config?.threshold || 0;
122
+ const topK = config?.topK || documents.length;
123
+ return scores
124
+ .filter(s => s.score >= threshold)
125
+ .slice(0, topK)
126
+ .map((s, newRank) => ({
127
+ id: documents[s.index].id,
128
+ score: s.score,
129
+ content: documents[s.index].content,
130
+ metadata: documents[s.index].metadata,
131
+ originalRank: s.index,
132
+ newRank
133
+ }));
134
+ }
135
+ cosineSimilarity(a, b) {
136
+ const dot = a.reduce((sum, x, i) => sum + x * b[i], 0);
137
+ const normA = Math.sqrt(a.reduce((sum, x) => sum + x * x, 0));
138
+ const normB = Math.sqrt(b.reduce((sum, x) => sum + x * x, 0));
139
+ return dot / (normA * normB);
140
+ }
141
+ }
142
+ exports.CrossEncoderReranker = CrossEncoderReranker;
143
+ /**
144
+ * LLM Reranker - Uses an LLM to score relevance
145
+ */
146
+ class LLMReranker extends BaseReranker {
147
+ constructor(config) {
148
+ super('LLMReranker');
149
+ this.generateFn = config.generateFn;
150
+ }
151
+ async rerank(query, documents, config) {
152
+ const scores = [];
153
+ // Score each document
154
+ for (let i = 0; i < documents.length; i++) {
155
+ const doc = documents[i];
156
+ const prompt = `Rate the relevance of the following document to the query on a scale of 0 to 10.
157
+ Query: ${query}
158
+ Document: ${doc.content.slice(0, 500)}
159
+
160
+ Respond with only a number between 0 and 10.`;
161
+ try {
162
+ const response = await this.generateFn(prompt);
163
+ const score = parseFloat(response.trim()) / 10;
164
+ scores.push({ index: i, score: isNaN(score) ? 0 : Math.min(1, Math.max(0, score)) });
165
+ }
166
+ catch {
167
+ scores.push({ index: i, score: 0 });
168
+ }
169
+ }
170
+ scores.sort((a, b) => b.score - a.score);
171
+ const threshold = config?.threshold || 0;
172
+ const topK = config?.topK || documents.length;
173
+ return scores
174
+ .filter(s => s.score >= threshold)
175
+ .slice(0, topK)
176
+ .map((s, newRank) => ({
177
+ id: documents[s.index].id,
178
+ score: s.score,
179
+ content: documents[s.index].content,
180
+ metadata: documents[s.index].metadata,
181
+ originalRank: s.index,
182
+ newRank
183
+ }));
184
+ }
185
+ }
186
+ exports.LLMReranker = LLMReranker;
187
+ // Factory functions
188
+ function createCohereReranker(config) {
189
+ return new CohereReranker(config);
190
+ }
191
+ function createCrossEncoderReranker(config) {
192
+ return new CrossEncoderReranker(config);
193
+ }
194
+ function createLLMReranker(config) {
195
+ return new LLMReranker(config);
196
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * YAML Workflow Parser
3
+ * Parse YAML workflow definitions into executable workflows
4
+ */
5
+ import { Workflow } from './index';
6
+ export interface YAMLWorkflowDefinition {
7
+ name: string;
8
+ description?: string;
9
+ version?: string;
10
+ steps: YAMLStepDefinition[];
11
+ metadata?: Record<string, any>;
12
+ }
13
+ export interface YAMLStepDefinition {
14
+ name: string;
15
+ type: 'agent' | 'tool' | 'condition' | 'parallel' | 'loop';
16
+ agent?: string;
17
+ tool?: string;
18
+ input?: string | Record<string, any>;
19
+ output?: string;
20
+ condition?: string;
21
+ onError?: 'fail' | 'skip' | 'retry';
22
+ maxRetries?: number;
23
+ timeout?: number;
24
+ steps?: YAMLStepDefinition[];
25
+ loopCondition?: string;
26
+ maxIterations?: number;
27
+ }
28
+ export interface ParsedWorkflow {
29
+ workflow: Workflow;
30
+ definition: YAMLWorkflowDefinition;
31
+ errors: string[];
32
+ }
33
+ /**
34
+ * Parse YAML string into workflow definition
35
+ */
36
+ export declare function parseYAMLWorkflow(yamlContent: string): YAMLWorkflowDefinition;
37
+ /**
38
+ * Create executable workflow from YAML definition
39
+ */
40
+ export declare function createWorkflowFromYAML(definition: YAMLWorkflowDefinition, agents?: Record<string, any>, tools?: Record<string, any>): ParsedWorkflow;
41
+ /**
42
+ * Load workflow from YAML file
43
+ */
44
+ export declare function loadWorkflowFromFile(filePath: string, agents?: Record<string, any>, tools?: Record<string, any>): Promise<ParsedWorkflow>;
45
+ /**
46
+ * Validate YAML workflow definition
47
+ */
48
+ export declare function validateWorkflowDefinition(definition: YAMLWorkflowDefinition): string[];
@@ -0,0 +1,304 @@
1
+ "use strict";
2
+ /**
3
+ * YAML Workflow Parser
4
+ * Parse YAML workflow definitions into executable workflows
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || (function () {
23
+ var ownKeys = function(o) {
24
+ ownKeys = Object.getOwnPropertyNames || function (o) {
25
+ var ar = [];
26
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
+ return ar;
28
+ };
29
+ return ownKeys(o);
30
+ };
31
+ return function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ })();
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ exports.parseYAMLWorkflow = parseYAMLWorkflow;
41
+ exports.createWorkflowFromYAML = createWorkflowFromYAML;
42
+ exports.loadWorkflowFromFile = loadWorkflowFromFile;
43
+ exports.validateWorkflowDefinition = validateWorkflowDefinition;
44
+ const index_1 = require("./index");
45
+ /**
46
+ * Parse YAML string into workflow definition
47
+ */
48
+ function parseYAMLWorkflow(yamlContent) {
49
+ // Simple YAML parser for workflow definitions
50
+ // For production, use js-yaml package
51
+ const lines = yamlContent.split('\n');
52
+ const result = {
53
+ name: '',
54
+ steps: []
55
+ };
56
+ let currentStep = null;
57
+ let indent = 0;
58
+ for (const line of lines) {
59
+ const trimmed = line.trim();
60
+ if (!trimmed || trimmed.startsWith('#'))
61
+ continue;
62
+ const currentIndent = line.search(/\S/);
63
+ // Parse key-value pairs
64
+ const colonIndex = trimmed.indexOf(':');
65
+ if (colonIndex === -1)
66
+ continue;
67
+ const key = trimmed.substring(0, colonIndex).trim();
68
+ const value = trimmed.substring(colonIndex + 1).trim();
69
+ if (currentIndent === 0) {
70
+ // Top-level keys
71
+ if (key === 'name')
72
+ result.name = value;
73
+ else if (key === 'description')
74
+ result.description = value;
75
+ else if (key === 'version')
76
+ result.version = value;
77
+ else if (key === 'steps') {
78
+ // Steps array starts
79
+ indent = currentIndent;
80
+ }
81
+ }
82
+ else if (trimmed.startsWith('- name:')) {
83
+ // New step
84
+ if (currentStep && currentStep.name) {
85
+ result.steps.push(currentStep);
86
+ }
87
+ currentStep = {
88
+ name: value,
89
+ type: 'agent'
90
+ };
91
+ }
92
+ else if (currentStep) {
93
+ // Step properties
94
+ if (key === 'type')
95
+ currentStep.type = value;
96
+ else if (key === 'agent')
97
+ currentStep.agent = value;
98
+ else if (key === 'tool')
99
+ currentStep.tool = value;
100
+ else if (key === 'input')
101
+ currentStep.input = value;
102
+ else if (key === 'output')
103
+ currentStep.output = value;
104
+ else if (key === 'condition')
105
+ currentStep.condition = value;
106
+ else if (key === 'onError')
107
+ currentStep.onError = value;
108
+ else if (key === 'maxRetries')
109
+ currentStep.maxRetries = parseInt(value);
110
+ else if (key === 'timeout')
111
+ currentStep.timeout = parseInt(value);
112
+ else if (key === 'loopCondition')
113
+ currentStep.loopCondition = value;
114
+ else if (key === 'maxIterations')
115
+ currentStep.maxIterations = parseInt(value);
116
+ }
117
+ }
118
+ // Add last step
119
+ if (currentStep && currentStep.name) {
120
+ result.steps.push(currentStep);
121
+ }
122
+ return result;
123
+ }
124
+ /**
125
+ * Create executable workflow from YAML definition
126
+ */
127
+ function createWorkflowFromYAML(definition, agents = {}, tools = {}) {
128
+ const errors = [];
129
+ const workflow = new index_1.Workflow(definition.name);
130
+ for (const stepDef of definition.steps) {
131
+ try {
132
+ const stepConfig = createStepConfig(stepDef, agents, tools, errors);
133
+ if (stepConfig) {
134
+ workflow.addStep(stepConfig);
135
+ }
136
+ }
137
+ catch (error) {
138
+ errors.push(`Error creating step ${stepDef.name}: ${error.message}`);
139
+ }
140
+ }
141
+ return { workflow, definition, errors };
142
+ }
143
+ function createStepConfig(stepDef, agents, tools, errors) {
144
+ const { name, type, agent, tool, onError, maxRetries, timeout, condition } = stepDef;
145
+ let execute;
146
+ switch (type) {
147
+ case 'agent':
148
+ if (!agent) {
149
+ errors.push(`Step ${name}: agent type requires 'agent' field`);
150
+ return null;
151
+ }
152
+ const agentInstance = agents[agent];
153
+ if (!agentInstance) {
154
+ errors.push(`Step ${name}: agent '${agent}' not found`);
155
+ return null;
156
+ }
157
+ execute = async (input) => {
158
+ if (typeof agentInstance.chat === 'function') {
159
+ return agentInstance.chat(typeof input === 'string' ? input : JSON.stringify(input));
160
+ }
161
+ return agentInstance(input);
162
+ };
163
+ break;
164
+ case 'tool':
165
+ if (!tool) {
166
+ errors.push(`Step ${name}: tool type requires 'tool' field`);
167
+ return null;
168
+ }
169
+ const toolInstance = tools[tool];
170
+ if (!toolInstance) {
171
+ errors.push(`Step ${name}: tool '${tool}' not found`);
172
+ return null;
173
+ }
174
+ execute = async (input) => {
175
+ if (typeof toolInstance.execute === 'function') {
176
+ return toolInstance.execute(input);
177
+ }
178
+ if (typeof toolInstance.run === 'function') {
179
+ return toolInstance.run(input);
180
+ }
181
+ return toolInstance(input);
182
+ };
183
+ break;
184
+ case 'condition':
185
+ execute = async (input, context) => {
186
+ // Evaluate condition and return input or skip
187
+ if (condition) {
188
+ // Simple condition evaluation
189
+ const result = evaluateCondition(condition, input, context);
190
+ return result ? input : null;
191
+ }
192
+ return input;
193
+ };
194
+ break;
195
+ default:
196
+ execute = async (input) => input;
197
+ }
198
+ return {
199
+ name,
200
+ execute,
201
+ onError,
202
+ maxRetries,
203
+ timeout,
204
+ condition: condition ? (context) => evaluateCondition(condition, null, context) : undefined
205
+ };
206
+ }
207
+ function evaluateCondition(condition, input, context) {
208
+ // Simple condition evaluation
209
+ // Supports: "result.success", "input.length > 0", etc.
210
+ try {
211
+ // Create a safe evaluation context
212
+ const evalContext = {
213
+ input,
214
+ context,
215
+ result: context?.get?.('lastResult'),
216
+ ...context?.metadata
217
+ };
218
+ // Simple expression evaluation
219
+ if (condition.includes('===')) {
220
+ const [left, right] = condition.split('===').map(s => s.trim());
221
+ return getNestedValue(evalContext, left) === parseValue(right);
222
+ }
223
+ if (condition.includes('!==')) {
224
+ const [left, right] = condition.split('!==').map(s => s.trim());
225
+ return getNestedValue(evalContext, left) !== parseValue(right);
226
+ }
227
+ if (condition.includes('>')) {
228
+ const [left, right] = condition.split('>').map(s => s.trim());
229
+ return getNestedValue(evalContext, left) > parseValue(right);
230
+ }
231
+ if (condition.includes('<')) {
232
+ const [left, right] = condition.split('<').map(s => s.trim());
233
+ return getNestedValue(evalContext, left) < parseValue(right);
234
+ }
235
+ // Boolean check
236
+ return !!getNestedValue(evalContext, condition);
237
+ }
238
+ catch {
239
+ return false;
240
+ }
241
+ }
242
+ function getNestedValue(obj, path) {
243
+ return path.split('.').reduce((current, key) => current?.[key], obj);
244
+ }
245
+ function parseValue(value) {
246
+ value = value.trim();
247
+ if (value === 'true')
248
+ return true;
249
+ if (value === 'false')
250
+ return false;
251
+ if (value === 'null')
252
+ return null;
253
+ if (value.startsWith('"') && value.endsWith('"'))
254
+ return value.slice(1, -1);
255
+ if (value.startsWith("'") && value.endsWith("'"))
256
+ return value.slice(1, -1);
257
+ const num = Number(value);
258
+ if (!isNaN(num))
259
+ return num;
260
+ return value;
261
+ }
262
+ /**
263
+ * Load workflow from YAML file
264
+ */
265
+ async function loadWorkflowFromFile(filePath, agents = {}, tools = {}) {
266
+ const fs = await Promise.resolve().then(() => __importStar(require('fs/promises')));
267
+ const content = await fs.readFile(filePath, 'utf-8');
268
+ const definition = parseYAMLWorkflow(content);
269
+ return createWorkflowFromYAML(definition, agents, tools);
270
+ }
271
+ /**
272
+ * Validate YAML workflow definition
273
+ */
274
+ function validateWorkflowDefinition(definition) {
275
+ const errors = [];
276
+ if (!definition.name) {
277
+ errors.push('Workflow must have a name');
278
+ }
279
+ if (!definition.steps || definition.steps.length === 0) {
280
+ errors.push('Workflow must have at least one step');
281
+ }
282
+ const stepNames = new Set();
283
+ for (const step of definition.steps) {
284
+ if (!step.name) {
285
+ errors.push('Each step must have a name');
286
+ }
287
+ else if (stepNames.has(step.name)) {
288
+ errors.push(`Duplicate step name: ${step.name}`);
289
+ }
290
+ else {
291
+ stepNames.add(step.name);
292
+ }
293
+ if (!step.type) {
294
+ errors.push(`Step ${step.name}: must have a type`);
295
+ }
296
+ if (step.type === 'agent' && !step.agent) {
297
+ errors.push(`Step ${step.name}: agent type requires 'agent' field`);
298
+ }
299
+ if (step.type === 'tool' && !step.tool) {
300
+ errors.push(`Step ${step.name}: tool type requires 'tool' field`);
301
+ }
302
+ }
303
+ return errors;
304
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "praisonai",
3
- "version": "1.2.1",
3
+ "version": "1.2.2",
4
4
  "description": "PraisonAI TypeScript AI Agents Framework - Node.js, npm, and Javascript AI Agents Framework",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",