@falai/agent 0.1.0-alpha2 → 0.1.0-alpha3

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 (59) hide show
  1. package/README.md +106 -0
  2. package/dist/cjs/src/core/BatchExecutor.d.ts +353 -0
  3. package/dist/cjs/src/core/BatchExecutor.d.ts.map +1 -0
  4. package/dist/cjs/src/core/BatchExecutor.js +842 -0
  5. package/dist/cjs/src/core/BatchExecutor.js.map +1 -0
  6. package/dist/cjs/src/core/BatchPromptBuilder.d.ts +86 -0
  7. package/dist/cjs/src/core/BatchPromptBuilder.d.ts.map +1 -0
  8. package/dist/cjs/src/core/BatchPromptBuilder.js +201 -0
  9. package/dist/cjs/src/core/BatchPromptBuilder.js.map +1 -0
  10. package/dist/cjs/src/core/ResponseModal.d.ts +34 -0
  11. package/dist/cjs/src/core/ResponseModal.d.ts.map +1 -1
  12. package/dist/cjs/src/core/ResponseModal.js +460 -34
  13. package/dist/cjs/src/core/ResponseModal.js.map +1 -1
  14. package/dist/cjs/src/index.d.ts +2 -0
  15. package/dist/cjs/src/index.d.ts.map +1 -1
  16. package/dist/cjs/src/index.js +7 -1
  17. package/dist/cjs/src/index.js.map +1 -1
  18. package/dist/cjs/src/types/agent.d.ts +9 -1
  19. package/dist/cjs/src/types/agent.d.ts.map +1 -1
  20. package/dist/cjs/src/types/route.d.ts +98 -0
  21. package/dist/cjs/src/types/route.d.ts.map +1 -1
  22. package/dist/src/core/BatchExecutor.d.ts +353 -0
  23. package/dist/src/core/BatchExecutor.d.ts.map +1 -0
  24. package/dist/src/core/BatchExecutor.js +837 -0
  25. package/dist/src/core/BatchExecutor.js.map +1 -0
  26. package/dist/src/core/BatchPromptBuilder.d.ts +86 -0
  27. package/dist/src/core/BatchPromptBuilder.d.ts.map +1 -0
  28. package/dist/src/core/BatchPromptBuilder.js +197 -0
  29. package/dist/src/core/BatchPromptBuilder.js.map +1 -0
  30. package/dist/src/core/ResponseModal.d.ts +34 -0
  31. package/dist/src/core/ResponseModal.d.ts.map +1 -1
  32. package/dist/src/core/ResponseModal.js +460 -34
  33. package/dist/src/core/ResponseModal.js.map +1 -1
  34. package/dist/src/index.d.ts +2 -0
  35. package/dist/src/index.d.ts.map +1 -1
  36. package/dist/src/index.js +2 -0
  37. package/dist/src/index.js.map +1 -1
  38. package/dist/src/types/agent.d.ts +9 -1
  39. package/dist/src/types/agent.d.ts.map +1 -1
  40. package/dist/src/types/route.d.ts +98 -0
  41. package/dist/src/types/route.d.ts.map +1 -1
  42. package/docs/api/overview.md +124 -0
  43. package/docs/architecture/multi-step-execution.md +243 -0
  44. package/docs/core/ai-integration/prompt-composition.md +135 -0
  45. package/docs/core/ai-integration/response-processing.md +146 -0
  46. package/docs/core/conversation-flows/data-collection.md +143 -0
  47. package/docs/core/conversation-flows/step-transitions.md +132 -0
  48. package/docs/core/conversation-flows/steps.md +112 -0
  49. package/docs/core/error-handling.md +193 -0
  50. package/docs/guides/getting-started/README.md +102 -0
  51. package/docs/guides/migration/README.md +23 -0
  52. package/docs/guides/migration/multi-step-execution.md +303 -0
  53. package/package.json +4 -2
  54. package/src/core/BatchExecutor.ts +1156 -0
  55. package/src/core/BatchPromptBuilder.ts +275 -0
  56. package/src/core/ResponseModal.ts +605 -35
  57. package/src/index.ts +2 -0
  58. package/src/types/agent.ts +9 -1
  59. package/src/types/route.ts +119 -0
@@ -0,0 +1,275 @@
1
+ /**
2
+ * BatchPromptBuilder - Combines multiple Step prompts into a single coherent prompt
3
+ *
4
+ * Responsible for building a combined prompt for batch execution of multiple Steps
5
+ * in a single LLM call.
6
+ *
7
+ * **Validates: Requirements 4.1, 4.2, 4.3, 4.4**
8
+ */
9
+
10
+ import type { StepOptions } from '../types/route';
11
+ import type { AgentOptions } from '../types/agent';
12
+ import type { SessionState } from '../types/session';
13
+ import type { Event } from '../types/history';
14
+ import type { Route } from './Route';
15
+ import { render, createTemplateContext } from '../utils/template';
16
+ import { PromptComposer } from './PromptComposer';
17
+
18
+ /**
19
+ * Parameters for building a batch prompt
20
+ */
21
+ export interface BuildBatchPromptParams<TContext, TData> {
22
+ /** Steps included in this batch */
23
+ steps: StepOptions<TContext, TData>[];
24
+ /** The route containing the steps */
25
+ route: Route<TContext, TData>;
26
+ /** Conversation history */
27
+ history: Event[];
28
+ /** Agent context */
29
+ context: TContext;
30
+ /** Current session state */
31
+ session: SessionState<TData>;
32
+ /** Agent options for identity/personality */
33
+ agentOptions: AgentOptions<TContext, TData>;
34
+ }
35
+
36
+ /**
37
+ * Result of building a batch prompt
38
+ */
39
+ export interface BatchPromptResult {
40
+ /** The combined prompt string */
41
+ prompt: string;
42
+ /** All collect fields from all steps in the batch */
43
+ collectFields: string[];
44
+ /** Number of steps included in the prompt */
45
+ stepCount: number;
46
+ }
47
+
48
+ /**
49
+ * BatchPromptBuilder class - builds combined prompts for batch execution
50
+ *
51
+ * Combines multiple Step prompts into a single coherent prompt that:
52
+ * - Preserves the intent of each Step's individual prompt
53
+ * - Includes data collection instructions for all collect fields
54
+ * - Produces a single LLM call regardless of the number of Steps
55
+ *
56
+ * **Validates: Requirements 4.1, 4.2, 4.3, 4.4**
57
+ */
58
+ export class BatchPromptBuilder<TContext = unknown, TData = unknown> {
59
+ /**
60
+ * Build a combined prompt for a batch of Steps
61
+ *
62
+ * @param params - Parameters for building the batch prompt
63
+ * @returns BatchPromptResult with the combined prompt and metadata
64
+ *
65
+ * **Validates: Requirements 4.1, 4.2, 4.3, 4.4**
66
+ */
67
+ async buildBatchPrompt(params: BuildBatchPromptParams<TContext, TData>): Promise<BatchPromptResult> {
68
+ const { steps, route, history, context, session, agentOptions } = params;
69
+
70
+ // Create template context for rendering
71
+ const templateContext = createTemplateContext<TContext, TData>({
72
+ context,
73
+ data: session.data,
74
+ session,
75
+ history,
76
+ });
77
+
78
+ // Collect all collect fields from all steps
79
+ const collectFields: string[] = [];
80
+ for (const step of steps) {
81
+ if (step.collect && step.collect.length > 0) {
82
+ for (const field of step.collect) {
83
+ const fieldStr = String(field);
84
+ if (!collectFields.includes(fieldStr)) {
85
+ collectFields.push(fieldStr);
86
+ }
87
+ }
88
+ }
89
+ }
90
+
91
+ // Build the combined prompt using PromptComposer for consistency
92
+ const composer = new PromptComposer<TContext, TData>(templateContext);
93
+
94
+ // Add agent meta information
95
+ await composer.addAgentMeta(agentOptions);
96
+
97
+ // Add route-specific identity/personality if available
98
+ if (route.identity) {
99
+ const identity = await render(route.identity, templateContext);
100
+ if (identity) {
101
+ await composer.addInstruction(`**Route Identity:** ${identity}`);
102
+ }
103
+ }
104
+
105
+ if (route.personality) {
106
+ const personality = await render(route.personality, templateContext);
107
+ if (personality) {
108
+ await composer.addInstruction(`**Route Personality:** ${personality}`);
109
+ }
110
+ }
111
+
112
+ // Add knowledge base if available
113
+ await composer.addKnowledgeBase(agentOptions.knowledgeBase, route.getKnowledgeBase());
114
+
115
+ // Add glossary terms
116
+ const allTerms = [...(agentOptions.terms || []), ...route.getTerms()];
117
+ await composer.addGlossary(allTerms);
118
+
119
+ // Add guidelines
120
+ const allGuidelines = [...(agentOptions.guidelines || []), ...route.getGuidelines()];
121
+ await composer.addGuidelines(allGuidelines);
122
+
123
+ // Add interaction history
124
+ await composer.addInteractionHistory(history, 'Recent conversation context:');
125
+
126
+ // Build the step sections
127
+ const stepSections = await this.buildStepSections(steps, templateContext);
128
+
129
+ // Add the conversation flow section
130
+ if (steps.length > 1) {
131
+ await composer.addInstruction(
132
+ `## Current Conversation Flow\n\n` +
133
+ `You are handling multiple aspects of this conversation in a single response.\n\n` +
134
+ stepSections
135
+ );
136
+ } else if (steps.length === 1) {
137
+ await composer.addInstruction(
138
+ `## Current Step\n\n` +
139
+ stepSections
140
+ );
141
+ }
142
+
143
+ // Add data collection section if there are fields to collect
144
+ if (collectFields.length > 0) {
145
+ const collectionSection = this.buildDataCollectionSection(collectFields, agentOptions);
146
+ await composer.addInstruction(collectionSection);
147
+ }
148
+
149
+ // Add response format instructions
150
+ const responseFormat = this.buildResponseFormatSection(collectFields);
151
+ await composer.addInstruction(responseFormat);
152
+
153
+ // Build the final prompt
154
+ const prompt = await composer.build();
155
+
156
+ return {
157
+ prompt,
158
+ collectFields,
159
+ stepCount: steps.length,
160
+ };
161
+ }
162
+
163
+ /**
164
+ * Build the step sections of the prompt
165
+ *
166
+ * @param steps - Steps to include in the prompt
167
+ * @param templateContext - Template context for rendering
168
+ * @returns Formatted step sections string
169
+ */
170
+ private async buildStepSections(
171
+ steps: StepOptions<TContext, TData>[],
172
+ templateContext: ReturnType<typeof createTemplateContext<TContext, TData>>
173
+ ): Promise<string> {
174
+ const sections: string[] = [];
175
+
176
+ for (let i = 0; i < steps.length; i++) {
177
+ const step = steps[i];
178
+ const stepNumber = i + 1;
179
+
180
+ // Build step header
181
+ const description = step.description || `Step ${stepNumber}`;
182
+ let section = `### Step ${stepNumber}: ${description}\n`;
183
+
184
+ // Render and add step prompt if available
185
+ if (step.prompt) {
186
+ const renderedPrompt = await render(step.prompt, templateContext);
187
+ if (renderedPrompt) {
188
+ section += `\n${renderedPrompt}\n`;
189
+ }
190
+ }
191
+
192
+ // Add collect fields for this step if any
193
+ if (step.collect && step.collect.length > 0) {
194
+ const collectList = step.collect.map(f => `\`${String(f)}\``).join(', ');
195
+ section += `\n**Collect:** ${collectList}\n`;
196
+ }
197
+
198
+ sections.push(section);
199
+ }
200
+
201
+ return sections.join('\n');
202
+ }
203
+
204
+ /**
205
+ * Build the data collection section of the prompt
206
+ *
207
+ * @param collectFields - Fields to collect from the response
208
+ * @param agentOptions - Agent options containing schema information
209
+ * @returns Formatted data collection section string
210
+ */
211
+ private buildDataCollectionSection(
212
+ collectFields: string[],
213
+ agentOptions: AgentOptions<TContext, TData>
214
+ ): string {
215
+ const lines: string[] = [
216
+ '## Data Collection',
217
+ '',
218
+ 'Extract the following information from your response:',
219
+ ''
220
+ ];
221
+
222
+ // Get schema information if available
223
+ const schema = agentOptions.schema;
224
+
225
+ for (const field of collectFields) {
226
+ let fieldDescription = field;
227
+
228
+ // Try to get field type/description from schema
229
+ if (schema?.properties && schema.properties[field]) {
230
+ const fieldSchema = schema.properties[field] as Record<string, unknown>;
231
+ const rawType = fieldSchema.type;
232
+ const rawDescription = fieldSchema.description;
233
+
234
+ // Safely convert to string, handling objects and primitives
235
+ const type = typeof rawType === 'string' ? rawType : 'string';
236
+ const description = typeof rawDescription === 'string' ? rawDescription : '';
237
+
238
+ if (description) {
239
+ fieldDescription = `${field} (${type}): ${description}`;
240
+ } else {
241
+ fieldDescription = `${field} (${type})`;
242
+ }
243
+ }
244
+
245
+ lines.push(`- ${fieldDescription}`);
246
+ }
247
+
248
+ return lines.join('\n');
249
+ }
250
+
251
+ /**
252
+ * Build the response format section of the prompt
253
+ *
254
+ * @param collectFields - Fields to collect from the response
255
+ * @returns Formatted response format section string
256
+ */
257
+ private buildResponseFormatSection(collectFields: string[]): string {
258
+ const lines: string[] = [
259
+ '## Response Format',
260
+ '',
261
+ 'Return JSON with:',
262
+ '- `message`: Your response to the user'
263
+ ];
264
+
265
+ if (collectFields.length > 0) {
266
+ lines.push('');
267
+ lines.push('Include the following collected fields as top-level properties:');
268
+ for (const field of collectFields) {
269
+ lines.push(`- \`${field}\``);
270
+ }
271
+ }
272
+
273
+ return lines.join('\n');
274
+ }
275
+ }