@falai/agent 0.6.2 → 0.6.4
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.
- package/README.md +89 -56
- package/dist/cjs/constants/index.d.ts +6 -1
- package/dist/cjs/constants/index.d.ts.map +1 -1
- package/dist/cjs/constants/index.js +8 -3
- package/dist/cjs/constants/index.js.map +1 -1
- package/dist/cjs/core/Agent.d.ts +22 -0
- package/dist/cjs/core/Agent.d.ts.map +1 -1
- package/dist/cjs/core/Agent.js +108 -21
- package/dist/cjs/core/Agent.js.map +1 -1
- package/dist/cjs/core/Events.d.ts +13 -0
- package/dist/cjs/core/Events.d.ts.map +1 -1
- package/dist/cjs/core/Events.js +28 -14
- package/dist/cjs/core/Events.js.map +1 -1
- package/dist/cjs/core/Route.d.ts.map +1 -1
- package/dist/cjs/core/Route.js +4 -4
- package/dist/cjs/core/Route.js.map +1 -1
- package/dist/cjs/core/RoutingEngine.d.ts +6 -1
- package/dist/cjs/core/RoutingEngine.d.ts.map +1 -1
- package/dist/cjs/core/RoutingEngine.js +112 -37
- package/dist/cjs/core/RoutingEngine.js.map +1 -1
- package/dist/cjs/core/State.d.ts +15 -5
- package/dist/cjs/core/State.d.ts.map +1 -1
- package/dist/cjs/core/State.js +24 -5
- package/dist/cjs/core/State.js.map +1 -1
- package/dist/cjs/core/Tool.d.ts +8 -1
- package/dist/cjs/core/Tool.d.ts.map +1 -1
- package/dist/cjs/core/Tool.js +25 -28
- package/dist/cjs/core/Tool.js.map +1 -1
- package/dist/cjs/core/Transition.js +1 -1
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +3 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/agent.d.ts +5 -0
- package/dist/cjs/types/agent.d.ts.map +1 -1
- package/dist/cjs/types/agent.js.map +1 -1
- package/dist/cjs/types/route.d.ts +7 -1
- package/dist/cjs/types/route.d.ts.map +1 -1
- package/dist/cjs/types/session.d.ts +12 -1
- package/dist/cjs/types/session.d.ts.map +1 -1
- package/dist/cjs/types/session.js +26 -5
- package/dist/cjs/types/session.js.map +1 -1
- package/dist/cjs/utils/logger.d.ts +10 -0
- package/dist/cjs/utils/logger.d.ts.map +1 -0
- package/dist/cjs/utils/logger.js +23 -0
- package/dist/cjs/utils/logger.js.map +1 -0
- package/dist/constants/index.d.ts +6 -1
- package/dist/constants/index.d.ts.map +1 -1
- package/dist/constants/index.js +6 -1
- package/dist/constants/index.js.map +1 -1
- package/dist/core/Agent.d.ts +22 -0
- package/dist/core/Agent.d.ts.map +1 -1
- package/dist/core/Agent.js +108 -21
- package/dist/core/Agent.js.map +1 -1
- package/dist/core/Events.d.ts +13 -0
- package/dist/core/Events.d.ts.map +1 -1
- package/dist/core/Events.js +28 -14
- package/dist/core/Events.js.map +1 -1
- package/dist/core/Route.d.ts.map +1 -1
- package/dist/core/Route.js +4 -4
- package/dist/core/Route.js.map +1 -1
- package/dist/core/RoutingEngine.d.ts +6 -1
- package/dist/core/RoutingEngine.d.ts.map +1 -1
- package/dist/core/RoutingEngine.js +112 -37
- package/dist/core/RoutingEngine.js.map +1 -1
- package/dist/core/State.d.ts +15 -5
- package/dist/core/State.d.ts.map +1 -1
- package/dist/core/State.js +25 -6
- package/dist/core/State.js.map +1 -1
- package/dist/core/Tool.d.ts +8 -1
- package/dist/core/Tool.d.ts.map +1 -1
- package/dist/core/Tool.js +25 -28
- package/dist/core/Tool.js.map +1 -1
- package/dist/core/Transition.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/types/agent.d.ts +5 -0
- package/dist/types/agent.d.ts.map +1 -1
- package/dist/types/agent.js.map +1 -1
- package/dist/types/route.d.ts +7 -1
- package/dist/types/route.d.ts.map +1 -1
- package/dist/types/session.d.ts +12 -1
- package/dist/types/session.d.ts.map +1 -1
- package/dist/types/session.js +26 -5
- package/dist/types/session.js.map +1 -1
- package/dist/utils/logger.d.ts +10 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +17 -0
- package/dist/utils/logger.js.map +1 -0
- package/docs/{CONSTRUCTOR_OPTIONS.md → AGENT.md} +79 -7
- package/docs/API_REFERENCE.md +309 -18
- package/docs/ARCHITECTURE.md +1 -1
- package/docs/DOCS.md +46 -22
- package/docs/GETTING_STARTED.md +1 -1
- package/docs/README.md +13 -5
- package/docs/ROUTES.md +743 -0
- package/docs/STATES.md +798 -0
- package/examples/business-onboarding.ts +46 -5
- package/examples/company-qna-agent.ts +107 -1
- package/examples/custom-database-persistence.ts +44 -1
- package/examples/declarative-agent.ts +80 -37
- package/examples/domain-scoping.ts +91 -21
- package/examples/extracted-data-modification.ts +64 -2
- package/examples/healthcare-agent.ts +61 -4
- package/examples/openai-agent.ts +24 -2
- package/examples/opensearch-persistence.ts +26 -1
- package/examples/persistent-onboarding.ts +84 -18
- package/examples/prisma-persistence.ts +90 -16
- package/examples/redis-persistence.ts +89 -17
- package/examples/rules-prohibitions.ts +300 -139
- package/examples/streaming-agent.ts +60 -0
- package/examples/travel-agent.ts +66 -24
- package/package.json +3 -2
- package/src/constants/index.ts +6 -1
- package/src/core/Agent.ts +135 -21
- package/src/core/Events.ts +73 -10
- package/src/core/Route.ts +8 -4
- package/src/core/RoutingEngine.ts +150 -39
- package/src/core/State.ts +35 -10
- package/src/core/Tool.ts +67 -10
- package/src/core/Transition.ts +1 -1
- package/src/index.ts +1 -1
- package/src/types/agent.ts +5 -0
- package/src/types/route.ts +10 -1
- package/src/types/session.ts +42 -6
- package/src/utils/logger.ts +19 -0
package/docs/API_REFERENCE.md
CHANGED
|
@@ -16,7 +16,7 @@ Main agent class for managing conversational AI.
|
|
|
16
16
|
new Agent<TContext>(options: AgentOptions<TContext>)
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
See [
|
|
19
|
+
See [Agent](./AGENT.md) for full details.
|
|
20
20
|
|
|
21
21
|
#### Methods
|
|
22
22
|
|
|
@@ -48,6 +48,70 @@ Gets allowed domains for a specific route by ID. Returns filtered domains based
|
|
|
48
48
|
|
|
49
49
|
Gets allowed domains for a specific route by title. Returns filtered domains based on route's `domains` property, or all domains if route has no restrictions.
|
|
50
50
|
|
|
51
|
+
##### `getExtractedData<TExtracted>(routeId?): Partial<TExtracted>`
|
|
52
|
+
|
|
53
|
+
Gets the extracted data from current session, optionally for a specific route.
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
// Option 1: Using current session (set with setCurrentSession)
|
|
57
|
+
agent.setCurrentSession(session);
|
|
58
|
+
const extracted = agent.getExtractedData(); // Uses current session
|
|
59
|
+
|
|
60
|
+
// Option 2: Get data for specific route
|
|
61
|
+
const routeData = agent.getExtractedData("onboarding"); // Route-specific data
|
|
62
|
+
|
|
63
|
+
// Option 3: From response (with current session set)
|
|
64
|
+
const response = await agent.respond({ history });
|
|
65
|
+
const extracted = agent.getExtractedData(); // Uses current session
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**Parameters:**
|
|
69
|
+
|
|
70
|
+
- `routeId` (optional): Route ID to get data for. If not provided, returns current route data.
|
|
71
|
+
|
|
72
|
+
**Returns:** The extracted data from the current session
|
|
73
|
+
|
|
74
|
+
**Note:** Returns empty object if no current session is set.
|
|
75
|
+
|
|
76
|
+
##### `setCurrentSession(session): void`
|
|
77
|
+
|
|
78
|
+
Sets the current session for convenience methods. Once set, methods like `getExtractedData()` don't need the session parameter.
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
// Set current session
|
|
82
|
+
agent.setCurrentSession(session);
|
|
83
|
+
|
|
84
|
+
// Now methods use the current session automatically
|
|
85
|
+
const extracted = agent.getExtractedData();
|
|
86
|
+
// Get extracted data for route
|
|
87
|
+
const routeData = agent.getExtractedData("onboarding");
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**Parameters:**
|
|
91
|
+
|
|
92
|
+
- `session`: Session state to use as current session
|
|
93
|
+
|
|
94
|
+
##### `getCurrentSession(): SessionState | undefined`
|
|
95
|
+
|
|
96
|
+
Gets the currently set session.
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
const current = agent.getCurrentSession();
|
|
100
|
+
if (current) {
|
|
101
|
+
console.log("Current session:", current.id);
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**Returns:** Current session or undefined if none set
|
|
106
|
+
|
|
107
|
+
##### `clearCurrentSession(): void`
|
|
108
|
+
|
|
109
|
+
Clears the current session.
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
agent.clearCurrentSession();
|
|
113
|
+
```
|
|
114
|
+
|
|
51
115
|
##### `respond(input: RespondInput<TContext>): Promise<RespondOutput>`
|
|
52
116
|
|
|
53
117
|
Generates an AI response with session state management, data extraction, and intelligent routing.
|
|
@@ -70,6 +134,13 @@ interface RespondOutput {
|
|
|
70
134
|
toolName: string;
|
|
71
135
|
arguments: Record<string, unknown>;
|
|
72
136
|
}>;
|
|
137
|
+
/**
|
|
138
|
+
* NEW: Indicates if the current route has reached END_STATE
|
|
139
|
+
* When true, all required data has been collected and the route is complete.
|
|
140
|
+
* Your application should handle this appropriately (e.g., process collected data,
|
|
141
|
+
* show completion UI, start a new route, etc.)
|
|
142
|
+
*/
|
|
143
|
+
isRouteComplete?: boolean;
|
|
73
144
|
}
|
|
74
145
|
```
|
|
75
146
|
|
|
@@ -86,6 +157,7 @@ interface RespondOutput {
|
|
|
86
157
|
- Tracks current route, state, and extracted data across turns
|
|
87
158
|
- Enables "I changed my mind" scenarios with context-aware routing
|
|
88
159
|
- Automatically merges new extracted data with existing session data
|
|
160
|
+
- **Per-route data preservation** - Extracted data is organized by route ID, allowing users to switch routes without losing progress
|
|
89
161
|
|
|
90
162
|
**Example with Persistence Adapters:**
|
|
91
163
|
|
|
@@ -99,9 +171,21 @@ const { sessionData, sessionState } =
|
|
|
99
171
|
agentName: "Travel Agent",
|
|
100
172
|
});
|
|
101
173
|
|
|
174
|
+
// Option 1: Set current session for convenience
|
|
175
|
+
agent.setCurrentSession(sessionState);
|
|
176
|
+
|
|
102
177
|
const response = await agent.respond({
|
|
103
178
|
history,
|
|
104
|
-
session: sessionState, //
|
|
179
|
+
// session: sessionState, // No longer required!
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
// Use convenience methods without passing session
|
|
183
|
+
const extracted = agent.getExtractedData();
|
|
184
|
+
|
|
185
|
+
// Option 2: Still pass session explicitly if preferred
|
|
186
|
+
const response2 = await agent.respond({
|
|
187
|
+
history,
|
|
188
|
+
session: sessionState,
|
|
105
189
|
});
|
|
106
190
|
```
|
|
107
191
|
|
|
@@ -178,6 +262,101 @@ await yourDb.messages.create({
|
|
|
178
262
|
});
|
|
179
263
|
```
|
|
180
264
|
|
|
265
|
+
**Handling Route Completion:**
|
|
266
|
+
|
|
267
|
+
When a route reaches its END_STATE transition (all required data collected), the response includes `isRouteComplete: true`:
|
|
268
|
+
|
|
269
|
+
```typescript
|
|
270
|
+
const response = await agent.respond({
|
|
271
|
+
history,
|
|
272
|
+
session,
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
if (response.isRouteComplete) {
|
|
276
|
+
// Route is complete! All data has been collected
|
|
277
|
+
console.log("✅ Route completed!");
|
|
278
|
+
|
|
279
|
+
// Get all the collected data
|
|
280
|
+
const collectedData = agent.getExtractedData(response.session!);
|
|
281
|
+
console.log("Collected data:", collectedData);
|
|
282
|
+
|
|
283
|
+
// Handle completion in your application:
|
|
284
|
+
// - Save the collected data to your database
|
|
285
|
+
// - Trigger business logic (e.g., create booking, send email)
|
|
286
|
+
// - Show completion UI to user
|
|
287
|
+
// - Start a new route or conversation
|
|
288
|
+
|
|
289
|
+
await processCompletedData(collectedData);
|
|
290
|
+
|
|
291
|
+
// Optional: Show a custom completion message
|
|
292
|
+
return "Thank you! Your information has been saved.";
|
|
293
|
+
} else {
|
|
294
|
+
// Normal flow - route still in progress
|
|
295
|
+
return response.message;
|
|
296
|
+
}
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
**Example: Onboarding Flow**
|
|
300
|
+
|
|
301
|
+
```typescript
|
|
302
|
+
// Onboarding route with skipIf logic for pre-filled data
|
|
303
|
+
const onboardingRoute = agent.createRoute<OnboardingData>({
|
|
304
|
+
id: "onboarding",
|
|
305
|
+
title: "User Onboarding",
|
|
306
|
+
extractionSchema: ONBOARDING_SCHEMA,
|
|
307
|
+
initialData: existingUserData, // Pre-fill with existing data
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
// Build states with skipIf conditions
|
|
311
|
+
const welcome = onboardingRoute.initialState.transitionTo({
|
|
312
|
+
id: "ask_name",
|
|
313
|
+
chatState: "What's your name?",
|
|
314
|
+
gather: ["name"],
|
|
315
|
+
skipIf: (data) => !!data.name, // Skip if name already collected
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
const askEmail = welcome.transitionTo({
|
|
319
|
+
id: "ask_email",
|
|
320
|
+
chatState: "What's your email?",
|
|
321
|
+
gather: ["email"],
|
|
322
|
+
skipIf: (data) => !!data.email, // Skip if email already collected
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
const complete = askEmail.transitionTo({
|
|
326
|
+
id: "complete",
|
|
327
|
+
chatState: "All done! Thank you.",
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
complete.transitionTo({ state: END_STATE });
|
|
331
|
+
|
|
332
|
+
// Option 1: Set current session for convenience
|
|
333
|
+
agent.setCurrentSession(session);
|
|
334
|
+
|
|
335
|
+
const response = await agent.respond({ history });
|
|
336
|
+
|
|
337
|
+
if (response.isRouteComplete) {
|
|
338
|
+
// If all data was pre-filled, the route completes immediately!
|
|
339
|
+
// The routing engine recursively skips all states and reaches END_STATE
|
|
340
|
+
const data = agent.getExtractedData(); // No need to pass session!
|
|
341
|
+
await saveUserProfile(data);
|
|
342
|
+
return "Profile updated successfully!";
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// Get route-specific data if needed
|
|
346
|
+
const onboardingData = agent.getExtractedDataForRoute("onboarding");
|
|
347
|
+
const bookingData = agent.getExtractedDataForRoute("booking");
|
|
348
|
+
|
|
349
|
+
return response.message;
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
**Important Notes:**
|
|
353
|
+
|
|
354
|
+
- `isRouteComplete` is `true` when the route reaches an `END_STATE` transition
|
|
355
|
+
- The `message` will be empty (`""`) when `isRouteComplete` is `true`
|
|
356
|
+
- You should check `isRouteComplete` and handle completion appropriately
|
|
357
|
+
- If all states are skipped (due to `skipIf` conditions), the route can complete immediately on entry
|
|
358
|
+
- Use `agent.getExtractedData(session)` to retrieve all collected data
|
|
359
|
+
|
|
181
360
|
See also: [Custom Database Integration Example](../examples/custom-database-persistence.ts)
|
|
182
361
|
|
|
183
362
|
##### `respondStream(input: RespondInput<TContext>): AsyncGenerator<StreamChunk>`
|
|
@@ -192,15 +371,18 @@ interface StreamChunk {
|
|
|
192
371
|
accumulated: string;
|
|
193
372
|
/** Whether this is the final chunk */
|
|
194
373
|
done: boolean;
|
|
195
|
-
/**
|
|
196
|
-
|
|
197
|
-
/** Current state within the route (only in final chunk) */
|
|
198
|
-
state?: { id: string; description?: string };
|
|
374
|
+
/** Updated session state (includes extracted data, current route/state) */
|
|
375
|
+
session?: SessionState;
|
|
199
376
|
/** Tool calls requested by the agent (only in final chunk) */
|
|
200
377
|
toolCalls?: Array<{
|
|
201
378
|
toolName: string;
|
|
202
379
|
arguments: Record<string, unknown>;
|
|
203
380
|
}>;
|
|
381
|
+
/**
|
|
382
|
+
* Indicates if the current route has reached END_STATE (only in final chunk)
|
|
383
|
+
* When true, all required data has been collected and the route is complete.
|
|
384
|
+
*/
|
|
385
|
+
isRouteComplete?: boolean;
|
|
204
386
|
}
|
|
205
387
|
```
|
|
206
388
|
|
|
@@ -215,7 +397,7 @@ interface StreamChunk {
|
|
|
215
397
|
|
|
216
398
|
```typescript
|
|
217
399
|
// Basic streaming
|
|
218
|
-
for await (const chunk of agent.respondStream({ history })) {
|
|
400
|
+
for await (const chunk of agent.respondStream({ history, session })) {
|
|
219
401
|
if (chunk.delta) {
|
|
220
402
|
// Display incremental text to user
|
|
221
403
|
process.stdout.write(chunk.delta);
|
|
@@ -223,9 +405,17 @@ for await (const chunk of agent.respondStream({ history })) {
|
|
|
223
405
|
|
|
224
406
|
if (chunk.done) {
|
|
225
407
|
console.log("\n✅ Complete!");
|
|
226
|
-
|
|
227
|
-
if
|
|
228
|
-
|
|
408
|
+
|
|
409
|
+
// Check if route is complete
|
|
410
|
+
if (chunk.isRouteComplete) {
|
|
411
|
+
console.log("🎉 Route completed!");
|
|
412
|
+
const data = agent.getExtractedData(chunk.session!);
|
|
413
|
+
await handleCompletion(data);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// Access session state
|
|
417
|
+
if (chunk.session?.currentRoute) {
|
|
418
|
+
console.log("Route:", chunk.session.currentRoute.title);
|
|
229
419
|
}
|
|
230
420
|
if (chunk.toolCalls) {
|
|
231
421
|
console.log("Tool calls:", chunk.toolCalls.length);
|
|
@@ -330,11 +520,28 @@ interface RouteOptions<TExtracted = unknown> {
|
|
|
330
520
|
|
|
331
521
|
// NEW: Pre-populate extracted data when entering route
|
|
332
522
|
initialData?: Partial<TExtracted>;
|
|
523
|
+
|
|
524
|
+
// NEW: Configure the initial state
|
|
525
|
+
initialState?: {
|
|
526
|
+
id?: string; // Custom ID for the initial state
|
|
527
|
+
chatState?: string; // Description for the initial state
|
|
528
|
+
gather?: string[]; // Fields to gather in the initial state
|
|
529
|
+
skipIf?: (extracted: Partial<TExtracted>) => boolean; // Skip condition
|
|
530
|
+
requiredData?: string[]; // Required data prerequisites
|
|
531
|
+
};
|
|
532
|
+
|
|
533
|
+
// NEW: Sequential steps for simple linear flows
|
|
534
|
+
steps?: TransitionSpec<unknown, TExtracted>[];
|
|
333
535
|
}
|
|
334
536
|
```
|
|
335
537
|
|
|
336
538
|
**Note on IDs:** Route IDs are deterministic by default, generated from the title using a hash function. This ensures consistency across server restarts. You can provide a custom ID if you need specific control over the identifier.
|
|
337
539
|
|
|
540
|
+
**Initial State Configuration:** You can configure the initial state in two ways:
|
|
541
|
+
|
|
542
|
+
1. Using `initialState` option when creating the route
|
|
543
|
+
2. Using `route.initialState.configure()` method after route creation
|
|
544
|
+
|
|
338
545
|
#### Methods
|
|
339
546
|
|
|
340
547
|
##### `createGuideline(guideline: Guideline): this`
|
|
@@ -361,6 +568,8 @@ Returns the prohibitions that must never be done in this route.
|
|
|
361
568
|
|
|
362
569
|
Returns a reference to this route.
|
|
363
570
|
|
|
571
|
+
**Note:** Routes no longer have a `getExtractedData()` method. Use `agent.getExtractedData()` or `agent.getExtractedDataForRoute(routeId)` instead.
|
|
572
|
+
|
|
364
573
|
##### `describe(): string`
|
|
365
574
|
|
|
366
575
|
Generates a description of this route's structure.
|
|
@@ -403,7 +612,7 @@ Creates a transition from this state and returns a chainable result.
|
|
|
403
612
|
interface TransitionSpec<TExtracted = unknown> {
|
|
404
613
|
chatState?: string; // Transition to a chat interaction
|
|
405
614
|
toolState?: ToolRef; // Transition to execute a tool
|
|
406
|
-
state?: StateRef | symbol; // Transition to specific state or
|
|
615
|
+
state?: StateRef | symbol; // Transition to specific state or END_STATE
|
|
407
616
|
|
|
408
617
|
// NEW: Data extraction fields for this state
|
|
409
618
|
gather?: string[];
|
|
@@ -492,7 +701,7 @@ flightRoute.initialState
|
|
|
492
701
|
.transitionTo({
|
|
493
702
|
chatState: "Present available flights",
|
|
494
703
|
})
|
|
495
|
-
.transitionTo({ state:
|
|
704
|
+
.transitionTo({ state: END_STATE });
|
|
496
705
|
|
|
497
706
|
// Use with session state
|
|
498
707
|
let session = createSession<FlightData>();
|
|
@@ -504,6 +713,36 @@ console.log(response.session?.extracted); // { destination: "Paris", ... }
|
|
|
504
713
|
|
|
505
714
|
Adds a guideline specific to this state.
|
|
506
715
|
|
|
716
|
+
##### `configure(config): this`
|
|
717
|
+
|
|
718
|
+
Configure the state properties after creation. Useful for overriding initial state configuration. Returns `this` for chaining.
|
|
719
|
+
|
|
720
|
+
```typescript
|
|
721
|
+
// Configure initial state after route creation
|
|
722
|
+
route.initialState.configure({
|
|
723
|
+
description: "Welcome! Let's get started",
|
|
724
|
+
gatherFields: ["name", "email"],
|
|
725
|
+
skipIf: (extracted) => !!extracted.name && !!extracted.email,
|
|
726
|
+
requiredData: [],
|
|
727
|
+
});
|
|
728
|
+
|
|
729
|
+
// Or configure any state
|
|
730
|
+
const askName = route.initialState.transitionTo({ chatState: "Ask for name" });
|
|
731
|
+
askName.configure({
|
|
732
|
+
gatherFields: ["firstName", "lastName"],
|
|
733
|
+
});
|
|
734
|
+
```
|
|
735
|
+
|
|
736
|
+
**Parameters:**
|
|
737
|
+
|
|
738
|
+
- `config`: Configuration object with optional properties:
|
|
739
|
+
- `description?: string` - State description
|
|
740
|
+
- `gatherFields?: string[]` - Fields to gather in this state
|
|
741
|
+
- `skipIf?: (extracted: Partial<TExtracted>) => boolean` - Skip condition function
|
|
742
|
+
- `requiredData?: string[]` - Required data prerequisites
|
|
743
|
+
|
|
744
|
+
**Returns:** `this` for method chaining
|
|
745
|
+
|
|
507
746
|
#### Properties
|
|
508
747
|
|
|
509
748
|
##### `id: string`
|
|
@@ -1531,9 +1770,19 @@ interface SessionState<TExtracted = Record<string, unknown>> {
|
|
|
1531
1770
|
enteredAt: Date;
|
|
1532
1771
|
};
|
|
1533
1772
|
|
|
1534
|
-
/**
|
|
1773
|
+
/**
|
|
1774
|
+
* Data extracted during the current route
|
|
1775
|
+
* Convenience reference to extractedByRoute[currentRoute.id]
|
|
1776
|
+
*/
|
|
1535
1777
|
extracted: Partial<TExtracted>;
|
|
1536
1778
|
|
|
1779
|
+
/**
|
|
1780
|
+
* Extracted data organized by route ID
|
|
1781
|
+
* Preserves data when switching between routes
|
|
1782
|
+
* Format: { "routeId": { ...extractedData } }
|
|
1783
|
+
*/
|
|
1784
|
+
extractedByRoute: Record<string, Partial<unknown>>;
|
|
1785
|
+
|
|
1537
1786
|
/** History of routes visited in this session */
|
|
1538
1787
|
routeHistory: Array<{
|
|
1539
1788
|
routeId: string;
|
|
@@ -1554,11 +1803,26 @@ interface SessionState<TExtracted = Record<string, unknown>> {
|
|
|
1554
1803
|
**Key Features:**
|
|
1555
1804
|
|
|
1556
1805
|
- **`id`** - Optional session identifier that persists across database operations
|
|
1557
|
-
- **`extracted`** - Type-safe data collected via `extractionSchema`
|
|
1806
|
+
- **`extracted`** - Type-safe data collected via `extractionSchema` for the **current route**
|
|
1807
|
+
- **`extractedByRoute`** - **NEW:** Per-route data map that preserves extracted data when switching routes
|
|
1558
1808
|
- **`currentRoute`** / **`currentState`** - Track conversation position
|
|
1559
1809
|
- **`routeHistory`** - Full audit trail of route transitions
|
|
1560
1810
|
- **`metadata`** - Custom data (timestamps, user info, etc.)
|
|
1561
1811
|
|
|
1812
|
+
**Per-Route Data Preservation:**
|
|
1813
|
+
|
|
1814
|
+
When users switch routes (e.g., "Actually, I want to book a hotel instead"), the framework automatically:
|
|
1815
|
+
|
|
1816
|
+
- Saves current route's `extracted` data to `extractedByRoute[routeId]`
|
|
1817
|
+
- Loads the new route's data from `extractedByRoute[newRouteId]` (if resuming)
|
|
1818
|
+
- Keeps `extracted` as a convenient reference to the current route's data
|
|
1819
|
+
|
|
1820
|
+
This allows users to:
|
|
1821
|
+
|
|
1822
|
+
- Switch routes without losing progress
|
|
1823
|
+
- Resume incomplete routes where they left off
|
|
1824
|
+
- Access historical data from previous routes via `session.extractedByRoute["route_id"]`
|
|
1825
|
+
|
|
1562
1826
|
**Usage:**
|
|
1563
1827
|
|
|
1564
1828
|
```typescript
|
|
@@ -1818,16 +2082,43 @@ All IDs are generated deterministically using a hash function of their content (
|
|
|
1818
2082
|
|
|
1819
2083
|
## Constants
|
|
1820
2084
|
|
|
1821
|
-
### `
|
|
2085
|
+
### `END_STATE`
|
|
1822
2086
|
|
|
1823
|
-
Symbol marking the end of a conversation route.
|
|
2087
|
+
Symbol marking the end of a conversation route. Use this when building routes to mark where they should end.
|
|
1824
2088
|
|
|
1825
2089
|
```typescript
|
|
1826
|
-
import {
|
|
2090
|
+
import { END_STATE } from "@falai/agent";
|
|
1827
2091
|
|
|
1828
|
-
|
|
2092
|
+
const thankYou = askEmail.transitionTo({
|
|
2093
|
+
chatState: "Thank you for your information!",
|
|
2094
|
+
});
|
|
2095
|
+
|
|
2096
|
+
// Mark the end of the route
|
|
2097
|
+
thankYou.transitionTo({ state: END_STATE });
|
|
2098
|
+
```
|
|
2099
|
+
|
|
2100
|
+
### `END_STATE_ID`
|
|
2101
|
+
|
|
2102
|
+
String constant representing END_STATE for runtime comparisons. When a route completes, `currentState.id` is set to this value.
|
|
2103
|
+
|
|
2104
|
+
```typescript
|
|
2105
|
+
import { END_STATE_ID } from "@falai/agent";
|
|
2106
|
+
|
|
2107
|
+
const response = await agent.respond({ history, session });
|
|
2108
|
+
|
|
2109
|
+
// Method 1: Using isRouteComplete (recommended)
|
|
2110
|
+
if (response.isRouteComplete) {
|
|
2111
|
+
console.log("Route completed!");
|
|
2112
|
+
}
|
|
2113
|
+
|
|
2114
|
+
// Method 2: Using END_STATE_ID constant
|
|
2115
|
+
if (response.session?.currentState?.id === END_STATE_ID) {
|
|
2116
|
+
console.log("Route completed!");
|
|
2117
|
+
}
|
|
1829
2118
|
```
|
|
1830
2119
|
|
|
2120
|
+
**Note:** Both methods are equivalent. Use `isRouteComplete` for simplicity, or `END_STATE_ID` for consistency with how you build routes.
|
|
2121
|
+
|
|
1831
2122
|
---
|
|
1832
2123
|
|
|
1833
2124
|
## Enums
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -158,7 +158,7 @@ If you don't provide an ID, one is automatically generated from the route ID and
|
|
|
158
158
|
1. **Code filters first**: `skipIf` and `requiredData` filter out invalid states deterministically
|
|
159
159
|
2. **AI selects best state**: From valid candidates, AI evaluates text conditions to choose optimal state
|
|
160
160
|
3. **Combined decision**: Single AI call handles both route selection AND state selection (no extra calls!)
|
|
161
|
-
4. **Completion detection**: When all states are skipped and `
|
|
161
|
+
4. **Completion detection**: When all states are skipped and `END_STATE` is reached, route is marked complete
|
|
162
162
|
|
|
163
163
|
```typescript
|
|
164
164
|
// The AI sees:
|
package/docs/DOCS.md
CHANGED
|
@@ -9,6 +9,7 @@ Complete index of all `@falai/agent` documentation.
|
|
|
9
9
|
Start here if you're new to the framework:
|
|
10
10
|
|
|
11
11
|
### [Getting Started Guide](./GETTING_STARTED.md)
|
|
12
|
+
|
|
12
13
|
Build your first AI agent in 5 minutes with step-by-step instructions.
|
|
13
14
|
|
|
14
15
|
**Topics:** Installation, first agent, basic routes, data extraction, session state
|
|
@@ -20,16 +21,19 @@ Build your first AI agent in 5 minutes with step-by-step instructions.
|
|
|
20
21
|
Essential guides for understanding how the framework works:
|
|
21
22
|
|
|
22
23
|
### [Architecture](./ARCHITECTURE.md)
|
|
24
|
+
|
|
23
25
|
Design principles, philosophy, and how the framework works under the hood.
|
|
24
26
|
|
|
25
27
|
**Topics:** Schema-first extraction, session state, code-based logic, state machines, deterministic IDs
|
|
26
28
|
|
|
27
|
-
### [
|
|
29
|
+
### [Agent](./AGENT.md)
|
|
30
|
+
|
|
28
31
|
Comprehensive guide to agent configuration patterns.
|
|
29
32
|
|
|
30
33
|
**Topics:** Declarative vs fluent API, terms, guidelines, capabilities, routes, initialization patterns
|
|
31
34
|
|
|
32
35
|
### [Context Management](./CONTEXT_MANAGEMENT.md)
|
|
36
|
+
|
|
33
37
|
Session state, lifecycle hooks, and persistent conversations.
|
|
34
38
|
|
|
35
39
|
**Topics:** Session state, lifecycle hooks, context updates, multi-turn conversations, persistence patterns
|
|
@@ -40,27 +44,44 @@ Session state, lifecycle hooks, and persistent conversations.
|
|
|
40
44
|
|
|
41
45
|
Deep dives into specific features:
|
|
42
46
|
|
|
47
|
+
### [Routes Guide](./ROUTES.md)
|
|
48
|
+
|
|
49
|
+
Complete guide to creating and managing conversational routes.
|
|
50
|
+
|
|
51
|
+
**Topics:** Route creation, initial state configuration, data extraction, sequential steps, security, branching logic
|
|
52
|
+
|
|
53
|
+
### [States Guide](./STATES.md)
|
|
54
|
+
|
|
55
|
+
Complete guide to creating and managing states in conversational flows.
|
|
56
|
+
|
|
57
|
+
**Topics:** State types, transitions, data gathering, state logic, skip conditions, configuration, advanced patterns
|
|
58
|
+
|
|
43
59
|
### [API Reference](./API_REFERENCE.md)
|
|
60
|
+
|
|
44
61
|
Complete API documentation for all classes, methods, and types.
|
|
45
62
|
|
|
46
63
|
**Topics:** Agent class, Route class, State class, defineTool, providers, all APIs
|
|
47
64
|
|
|
48
65
|
### [AI Providers](./PROVIDERS.md)
|
|
66
|
+
|
|
49
67
|
Guide to AI provider configuration and usage.
|
|
50
68
|
|
|
51
69
|
**Topics:** Anthropic (Claude), OpenAI (GPT), Google (Gemini), OpenRouter, custom providers, backup models, retry logic
|
|
52
70
|
|
|
53
71
|
### [Domain Organization](./DOMAINS.md)
|
|
72
|
+
|
|
54
73
|
Optional tool security and organization.
|
|
55
74
|
|
|
56
75
|
**Topics:** Domain-based security, tool scoping, route isolation, preventing unauthorized access
|
|
57
76
|
|
|
58
77
|
### [Persistence Guide](./PERSISTENCE.md)
|
|
78
|
+
|
|
59
79
|
Database integration and session persistence.
|
|
60
80
|
|
|
61
81
|
**Topics:** Persistence adapters, auto-save, session management, lifecycle integration, custom adapters
|
|
62
82
|
|
|
63
83
|
### [Database Adapters](./ADAPTERS.md)
|
|
84
|
+
|
|
64
85
|
Detailed comparison and configuration for all database adapters.
|
|
65
86
|
|
|
66
87
|
**Topics:** Prisma, Redis, MongoDB, PostgreSQL, SQLite, OpenSearch, Memory adapter, custom adapters
|
|
@@ -72,12 +93,15 @@ Detailed comparison and configuration for all database adapters.
|
|
|
72
93
|
Real-world code examples:
|
|
73
94
|
|
|
74
95
|
### [Examples Guide](./EXAMPLES.md)
|
|
96
|
+
|
|
75
97
|
Comprehensive guide to all 15+ production-ready examples.
|
|
76
98
|
|
|
77
99
|
**Topics:** Learning path, use case guide, code examples, quick reference
|
|
78
100
|
|
|
79
101
|
### [Example Files](../examples/)
|
|
102
|
+
|
|
80
103
|
Browse the `/examples` directory for runnable code:
|
|
104
|
+
|
|
81
105
|
- [Business Onboarding](../examples/business-onboarding.ts) - Complex multi-step workflows
|
|
82
106
|
- [Travel Agent](../examples/travel-agent.ts) - Session state & data extraction
|
|
83
107
|
- [Healthcare Agent](../examples/healthcare-agent.ts) - Security & validation
|
|
@@ -93,11 +117,13 @@ Browse the `/examples` directory for runnable code:
|
|
|
93
117
|
Help improve the framework:
|
|
94
118
|
|
|
95
119
|
### [Contributing Guide](./CONTRIBUTING.md)
|
|
120
|
+
|
|
96
121
|
How to contribute code, documentation, and report issues.
|
|
97
122
|
|
|
98
123
|
**Topics:** Development setup, code style, pull requests, bug reports
|
|
99
124
|
|
|
100
125
|
### [Publishing Guide](./PUBLISHING.md)
|
|
126
|
+
|
|
101
127
|
Internal guide for maintainers on publishing releases.
|
|
102
128
|
|
|
103
129
|
**Topics:** Release process, versioning, npm publishing, changelog
|
|
@@ -112,7 +138,9 @@ Internal guide for maintainers on publishing releases.
|
|
|
112
138
|
|
|
113
139
|
- **Build my first agent** → [Getting Started](./GETTING_STARTED.md)
|
|
114
140
|
- **Understand the design** → [Architecture](./ARCHITECTURE.md)
|
|
115
|
-
- **Configure my agent** → [
|
|
141
|
+
- **Configure my agent** → [Agent](./AGENT.md)
|
|
142
|
+
- **Create conversational flows** → [Routes Guide](./ROUTES.md)
|
|
143
|
+
- **Manage states** → [States Guide](./STATES.md)
|
|
116
144
|
- **Persist conversations** → [Persistence Guide](./PERSISTENCE.md)
|
|
117
145
|
- **Add tool security** → [Domain Organization](./DOMAINS.md)
|
|
118
146
|
- **See real examples** → [Examples Guide](./EXAMPLES.md)
|
|
@@ -124,45 +152,57 @@ Internal guide for maintainers on publishing releases.
|
|
|
124
152
|
### By Topic
|
|
125
153
|
|
|
126
154
|
**Architecture & Design:**
|
|
155
|
+
|
|
127
156
|
- [Architecture Guide](./ARCHITECTURE.md)
|
|
128
157
|
- [How It Works](../README.md#-how-it-works)
|
|
129
158
|
|
|
130
159
|
**Agent Configuration:**
|
|
131
|
-
|
|
160
|
+
|
|
161
|
+
- [Agent](./AGENT.md)
|
|
132
162
|
- [Context Management](./CONTEXT_MANAGEMENT.md)
|
|
133
163
|
- [Getting Started](./GETTING_STARTED.md)
|
|
134
164
|
|
|
135
165
|
**Routes & State Machines:**
|
|
166
|
+
|
|
167
|
+
- [Routes Guide](./ROUTES.md) - Complete guide to routes
|
|
168
|
+
- [States Guide](./STATES.md) - Complete guide to states
|
|
136
169
|
- [API Reference - Routes](./API_REFERENCE.md#route)
|
|
170
|
+
- [API Reference - States](./API_REFERENCE.md#state)
|
|
137
171
|
- [Architecture - State Machines](./ARCHITECTURE.md#state-machines)
|
|
138
172
|
- [Examples - Complex Flows](./EXAMPLES.md#-real-world-applications)
|
|
139
173
|
|
|
140
174
|
**Tools & Domains:**
|
|
175
|
+
|
|
141
176
|
- [Domain Organization](./DOMAINS.md)
|
|
142
177
|
- [API Reference - defineTool](./API_REFERENCE.md#definetool)
|
|
143
178
|
- [Examples - Domain Scoping](./EXAMPLES.md#-domain-scoping)
|
|
144
179
|
|
|
145
180
|
**Data Extraction:**
|
|
181
|
+
|
|
146
182
|
- [Architecture - Schema-First](./ARCHITECTURE.md#schema-first-data-extraction)
|
|
147
183
|
- [API Reference - extractionSchema](./API_REFERENCE.md#extractionschema)
|
|
148
184
|
- [Examples - Travel Agent](./EXAMPLES.md#-travel-agent)
|
|
149
185
|
|
|
150
186
|
**Session State:**
|
|
187
|
+
|
|
151
188
|
- [Context Management](./CONTEXT_MANAGEMENT.md)
|
|
152
189
|
- [Architecture - Session State](./ARCHITECTURE.md#session-state-management)
|
|
153
190
|
- [API Reference - createSession](./API_REFERENCE.md#createsession)
|
|
154
191
|
|
|
155
192
|
**Persistence:**
|
|
193
|
+
|
|
156
194
|
- [Persistence Guide](./PERSISTENCE.md)
|
|
157
195
|
- [Database Adapters](./ADAPTERS.md)
|
|
158
196
|
- [Examples - Prisma](./EXAMPLES.md#-prisma-persistence)
|
|
159
197
|
|
|
160
198
|
**AI Providers:**
|
|
199
|
+
|
|
161
200
|
- [AI Providers Guide](./PROVIDERS.md)
|
|
162
201
|
- [API Reference - Providers](./API_REFERENCE.md#providers)
|
|
163
202
|
- [Examples - Multiple Providers](./EXAMPLES.md#-provider-examples)
|
|
164
203
|
|
|
165
204
|
**Streaming:**
|
|
205
|
+
|
|
166
206
|
- [API Reference - respondStream](./API_REFERENCE.md#respondstream)
|
|
167
207
|
- [Examples - Streaming](./EXAMPLES.md#-streaming-responses)
|
|
168
208
|
|
|
@@ -173,32 +213,15 @@ Internal guide for maintainers on publishing releases.
|
|
|
173
213
|
All documentation follows these conventions:
|
|
174
214
|
|
|
175
215
|
### Code Examples
|
|
216
|
+
|
|
176
217
|
All code examples are TypeScript and can be copy-pasted directly.
|
|
177
218
|
|
|
178
219
|
### Links
|
|
220
|
+
|
|
179
221
|
- Internal docs use relative links: `[Text](./FILE.md)`
|
|
180
222
|
- Examples use relative links: `[Text](../examples/file.ts)`
|
|
181
223
|
- External links use full URLs
|
|
182
224
|
|
|
183
|
-
### File Structure
|
|
184
|
-
```
|
|
185
|
-
docs/
|
|
186
|
-
├── INDEX.md # This file - documentation index
|
|
187
|
-
├── README.md # Docs overview and quick links
|
|
188
|
-
├── GETTING_STARTED.md # Beginner tutorial
|
|
189
|
-
├── ARCHITECTURE.md # Design principles
|
|
190
|
-
├── API_REFERENCE.md # Complete API docs
|
|
191
|
-
├── CONSTRUCTOR_OPTIONS.md # Configuration patterns
|
|
192
|
-
├── CONTEXT_MANAGEMENT.md # Session state & hooks
|
|
193
|
-
├── PERSISTENCE.md # Database integration
|
|
194
|
-
├── ADAPTERS.md # Database adapter guide
|
|
195
|
-
├── DOMAINS.md # Tool security
|
|
196
|
-
├── PROVIDERS.md # AI provider guide
|
|
197
|
-
├── EXAMPLES.md # Examples guide
|
|
198
|
-
├── CONTRIBUTING.md # How to contribute
|
|
199
|
-
└── PUBLISHING.md # Release guide (maintainers)
|
|
200
|
-
```
|
|
201
|
-
|
|
202
225
|
---
|
|
203
226
|
|
|
204
227
|
## 🔍 Search Tips
|
|
@@ -211,6 +234,7 @@ docs/
|
|
|
211
234
|
4. **Search the [API Reference](./API_REFERENCE.md)** for specific APIs
|
|
212
235
|
|
|
213
236
|
**Common searches:**
|
|
237
|
+
|
|
214
238
|
- "How do I..." → [Getting Started](./GETTING_STARTED.md)
|
|
215
239
|
- "What is..." → [Architecture](./ARCHITECTURE.md)
|
|
216
240
|
- "Example of..." → [Examples Guide](./EXAMPLES.md)
|
package/docs/GETTING_STARTED.md
CHANGED
|
@@ -417,7 +417,7 @@ new GeminiProvider({
|
|
|
417
417
|
|
|
418
418
|
## What's Next?
|
|
419
419
|
|
|
420
|
-
- 📚 Read the [
|
|
420
|
+
- 📚 Read the [Agent Guide](./AGENT.md)
|
|
421
421
|
- 🔍 Check the [API Reference](./API_REFERENCE.md)
|
|
422
422
|
- 🏗️ Understand the [Architecture](./ARCHITECTURE.md)
|
|
423
423
|
- 🎯 Explore [Examples](../examples/)
|