@falai/agent 0.6.8 → 0.7.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.
- package/README.md +62 -59
- package/dist/adapters/MemoryAdapter.js +2 -2
- package/dist/adapters/MemoryAdapter.js.map +1 -1
- package/dist/adapters/MongoAdapter.js +2 -2
- package/dist/adapters/MongoAdapter.js.map +1 -1
- package/dist/adapters/OpenSearchAdapter.js +7 -7
- package/dist/adapters/OpenSearchAdapter.js.map +1 -1
- package/dist/adapters/PostgreSQLAdapter.js +9 -9
- package/dist/adapters/PostgreSQLAdapter.js.map +1 -1
- package/dist/adapters/PrismaAdapter.js +3 -3
- package/dist/adapters/PrismaAdapter.js.map +1 -1
- package/dist/adapters/RedisAdapter.js +2 -2
- package/dist/adapters/RedisAdapter.js.map +1 -1
- package/dist/adapters/SQLiteAdapter.d.ts +3 -3
- package/dist/adapters/SQLiteAdapter.d.ts.map +1 -1
- package/dist/adapters/SQLiteAdapter.js +11 -11
- package/dist/adapters/SQLiteAdapter.js.map +1 -1
- package/dist/adapters/index.d.ts +1 -1
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/cjs/adapters/MemoryAdapter.js +2 -2
- package/dist/cjs/adapters/MemoryAdapter.js.map +1 -1
- package/dist/cjs/adapters/MongoAdapter.js +2 -2
- package/dist/cjs/adapters/MongoAdapter.js.map +1 -1
- package/dist/cjs/adapters/OpenSearchAdapter.js +7 -7
- package/dist/cjs/adapters/OpenSearchAdapter.js.map +1 -1
- package/dist/cjs/adapters/PostgreSQLAdapter.js +9 -9
- package/dist/cjs/adapters/PostgreSQLAdapter.js.map +1 -1
- package/dist/cjs/adapters/PrismaAdapter.js +3 -3
- package/dist/cjs/adapters/PrismaAdapter.js.map +1 -1
- package/dist/cjs/adapters/RedisAdapter.js +2 -2
- package/dist/cjs/adapters/RedisAdapter.js.map +1 -1
- package/dist/cjs/adapters/SQLiteAdapter.d.ts +3 -3
- package/dist/cjs/adapters/SQLiteAdapter.d.ts.map +1 -1
- package/dist/cjs/adapters/SQLiteAdapter.js +11 -11
- package/dist/cjs/adapters/SQLiteAdapter.js.map +1 -1
- package/dist/cjs/adapters/index.d.ts +1 -1
- package/dist/cjs/adapters/index.d.ts.map +1 -1
- package/dist/cjs/constants/index.d.ts +4 -4
- package/dist/cjs/constants/index.js +5 -5
- package/dist/cjs/core/Agent.d.ts +22 -22
- package/dist/cjs/core/Agent.d.ts.map +1 -1
- package/dist/cjs/core/Agent.js +160 -152
- package/dist/cjs/core/Agent.js.map +1 -1
- package/dist/cjs/core/Events.d.ts +6 -6
- package/dist/cjs/core/Events.d.ts.map +1 -1
- package/dist/cjs/core/PersistenceManager.d.ts +13 -13
- package/dist/cjs/core/PersistenceManager.d.ts.map +1 -1
- package/dist/cjs/core/PersistenceManager.js +24 -24
- package/dist/cjs/core/PersistenceManager.js.map +1 -1
- package/dist/cjs/core/ResponseEngine.d.ts +3 -8
- package/dist/cjs/core/ResponseEngine.d.ts.map +1 -1
- package/dist/cjs/core/ResponseEngine.js +8 -8
- package/dist/cjs/core/ResponseEngine.js.map +1 -1
- package/dist/cjs/core/Route.d.ts +17 -17
- package/dist/cjs/core/Route.d.ts.map +1 -1
- package/dist/cjs/core/Route.js +33 -33
- package/dist/cjs/core/Route.js.map +1 -1
- package/dist/cjs/core/RoutingEngine.d.ts +30 -30
- package/dist/cjs/core/RoutingEngine.d.ts.map +1 -1
- package/dist/cjs/core/RoutingEngine.js +192 -192
- package/dist/cjs/core/RoutingEngine.js.map +1 -1
- package/dist/cjs/core/Step.d.ts +72 -0
- package/dist/cjs/core/Step.d.ts.map +1 -0
- package/dist/cjs/core/Step.js +150 -0
- package/dist/cjs/core/Step.js.map +1 -0
- package/dist/cjs/core/ToolExecutor.d.ts +5 -5
- package/dist/cjs/core/ToolExecutor.d.ts.map +1 -1
- package/dist/cjs/core/ToolExecutor.js +8 -8
- package/dist/cjs/core/ToolExecutor.js.map +1 -1
- package/dist/cjs/core/Transition.d.ts +14 -14
- package/dist/cjs/core/Transition.d.ts.map +1 -1
- package/dist/cjs/core/Transition.js +48 -19
- package/dist/cjs/core/Transition.js.map +1 -1
- package/dist/cjs/index.d.ts +7 -7
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +8 -8
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/agent.d.ts +8 -8
- package/dist/cjs/types/agent.d.ts.map +1 -1
- package/dist/cjs/types/ai.d.ts +2 -2
- package/dist/cjs/types/ai.d.ts.map +1 -1
- package/dist/cjs/types/history.d.ts +3 -3
- package/dist/cjs/types/history.d.ts.map +1 -1
- package/dist/cjs/types/index.d.ts +1 -1
- package/dist/cjs/types/index.d.ts.map +1 -1
- package/dist/cjs/types/persistence.d.ts +5 -5
- package/dist/cjs/types/persistence.d.ts.map +1 -1
- package/dist/cjs/types/route.d.ts +57 -52
- package/dist/cjs/types/route.d.ts.map +1 -1
- package/dist/cjs/types/session.d.ts +27 -27
- package/dist/cjs/types/session.d.ts.map +1 -1
- package/dist/cjs/types/session.js +48 -50
- package/dist/cjs/types/session.js.map +1 -1
- package/dist/cjs/types/tool.d.ts +13 -13
- package/dist/cjs/types/tool.d.ts.map +1 -1
- package/dist/cjs/utils/id.d.ts +8 -3
- package/dist/cjs/utils/id.d.ts.map +1 -1
- package/dist/cjs/utils/id.js +16 -7
- package/dist/cjs/utils/id.js.map +1 -1
- package/dist/constants/index.d.ts +4 -4
- package/dist/constants/index.js +4 -4
- package/dist/core/Agent.d.ts +22 -22
- package/dist/core/Agent.d.ts.map +1 -1
- package/dist/core/Agent.js +162 -154
- package/dist/core/Agent.js.map +1 -1
- package/dist/core/Events.d.ts +6 -6
- package/dist/core/Events.d.ts.map +1 -1
- package/dist/core/PersistenceManager.d.ts +13 -13
- package/dist/core/PersistenceManager.d.ts.map +1 -1
- package/dist/core/PersistenceManager.js +25 -25
- package/dist/core/PersistenceManager.js.map +1 -1
- package/dist/core/ResponseEngine.d.ts +3 -8
- package/dist/core/ResponseEngine.d.ts.map +1 -1
- package/dist/core/ResponseEngine.js +8 -8
- package/dist/core/ResponseEngine.js.map +1 -1
- package/dist/core/Route.d.ts +17 -17
- package/dist/core/Route.d.ts.map +1 -1
- package/dist/core/Route.js +33 -33
- package/dist/core/Route.js.map +1 -1
- package/dist/core/RoutingEngine.d.ts +30 -30
- package/dist/core/RoutingEngine.d.ts.map +1 -1
- package/dist/core/RoutingEngine.js +193 -193
- package/dist/core/RoutingEngine.js.map +1 -1
- package/dist/core/Step.d.ts +72 -0
- package/dist/core/Step.d.ts.map +1 -0
- package/dist/core/Step.js +146 -0
- package/dist/core/Step.js.map +1 -0
- package/dist/core/ToolExecutor.d.ts +5 -5
- package/dist/core/ToolExecutor.d.ts.map +1 -1
- package/dist/core/ToolExecutor.js +8 -8
- package/dist/core/ToolExecutor.js.map +1 -1
- package/dist/core/Transition.d.ts +14 -14
- package/dist/core/Transition.d.ts.map +1 -1
- package/dist/core/Transition.js +48 -19
- package/dist/core/Transition.js.map +1 -1
- package/dist/index.d.ts +7 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/types/agent.d.ts +8 -8
- package/dist/types/agent.d.ts.map +1 -1
- package/dist/types/ai.d.ts +2 -2
- package/dist/types/ai.d.ts.map +1 -1
- package/dist/types/history.d.ts +3 -3
- package/dist/types/history.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/persistence.d.ts +5 -5
- package/dist/types/persistence.d.ts.map +1 -1
- package/dist/types/route.d.ts +57 -52
- package/dist/types/route.d.ts.map +1 -1
- package/dist/types/session.d.ts +27 -27
- package/dist/types/session.d.ts.map +1 -1
- package/dist/types/session.js +44 -46
- package/dist/types/session.js.map +1 -1
- package/dist/types/tool.d.ts +13 -13
- package/dist/types/tool.d.ts.map +1 -1
- package/dist/utils/id.d.ts +8 -3
- package/dist/utils/id.d.ts.map +1 -1
- package/dist/utils/id.js +14 -6
- package/dist/utils/id.js.map +1 -1
- package/docs/ADAPTERS.md +21 -21
- package/docs/AGENT.md +57 -55
- package/docs/API_REFERENCE.md +218 -220
- package/docs/ARCHITECTURE.md +99 -104
- package/docs/CONTEXT_MANAGEMENT.md +81 -88
- package/docs/DOCS.md +18 -18
- package/docs/DOMAINS.md +16 -16
- package/docs/EXAMPLES.md +43 -43
- package/docs/GETTING_STARTED.md +60 -63
- package/docs/PERSISTENCE.md +66 -70
- package/docs/PROVIDERS.md +2 -2
- package/docs/README.md +6 -6
- package/docs/ROUTES.md +218 -220
- package/docs/STEPS.md +883 -0
- package/examples/business-onboarding.ts +84 -81
- package/examples/company-qna-agent.ts +68 -67
- package/examples/custom-database-persistence.ts +87 -89
- package/examples/declarative-agent.ts +32 -32
- package/examples/domain-scoping.ts +18 -18
- package/examples/extracted-data-modification.ts +92 -97
- package/examples/healthcare-agent.ts +89 -91
- package/examples/openai-agent.ts +29 -32
- package/examples/opensearch-persistence.ts +43 -45
- package/examples/persistent-onboarding.ts +65 -66
- package/examples/prisma-persistence.ts +108 -112
- package/examples/prisma-schema.example.prisma +3 -3
- package/examples/redis-persistence.ts +67 -73
- package/examples/route-transitions.ts +71 -47
- package/examples/rules-prohibitions.ts +28 -28
- package/examples/streaming-agent.ts +24 -24
- package/examples/travel-agent.ts +94 -109
- package/package.json +1 -1
- package/src/adapters/MemoryAdapter.ts +3 -3
- package/src/adapters/MongoAdapter.ts +3 -3
- package/src/adapters/OpenSearchAdapter.ts +8 -8
- package/src/adapters/PostgreSQLAdapter.ts +10 -10
- package/src/adapters/PrismaAdapter.ts +4 -4
- package/src/adapters/RedisAdapter.ts +3 -3
- package/src/adapters/SQLiteAdapter.ts +15 -15
- package/src/adapters/index.ts +1 -1
- package/src/constants/index.ts +4 -4
- package/src/core/Agent.ts +210 -206
- package/src/core/Events.ts +12 -12
- package/src/core/PersistenceManager.ts +32 -36
- package/src/core/ResponseEngine.ts +11 -17
- package/src/core/Route.ts +55 -49
- package/src/core/RoutingEngine.ts +244 -252
- package/src/core/Step.ts +197 -0
- package/src/core/ToolExecutor.ts +11 -11
- package/src/core/Transition.ts +72 -26
- package/src/index.ts +8 -8
- package/src/types/agent.ts +8 -8
- package/src/types/ai.ts +2 -2
- package/src/types/history.ts +3 -3
- package/src/types/index.ts +1 -1
- package/src/types/persistence.ts +6 -6
- package/src/types/route.ts +77 -61
- package/src/types/session.ts +75 -78
- package/src/types/tool.ts +17 -17
- package/src/utils/id.ts +15 -6
- package/dist/cjs/core/State.d.ts +0 -72
- package/dist/cjs/core/State.d.ts.map +0 -1
- package/dist/cjs/core/State.js +0 -148
- package/dist/cjs/core/State.js.map +0 -1
- package/dist/core/State.d.ts +0 -72
- package/dist/core/State.d.ts.map +0 -1
- package/dist/core/State.js +0 -144
- package/dist/core/State.js.map +0 -1
- package/docs/STATES.md +0 -888
- package/src/core/State.ts +0 -212
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Example: Modifying
|
|
2
|
+
* Example: Modifying Collected data with Tools and Hooks
|
|
3
3
|
*
|
|
4
4
|
* This demonstrates:
|
|
5
5
|
* 1. Schema-first data extraction with JSON Schema
|
|
6
|
-
* 2. Tools that modify
|
|
6
|
+
* 2. Tools that modify collected data (validation, enrichment)
|
|
7
7
|
* 3. Lifecycle hooks for data validation and business logic
|
|
8
|
-
* 4. Data-driven
|
|
8
|
+
* 4. Data-driven step flows with code-based logic (skipIf, requires)
|
|
9
9
|
* 5. Three-phase pipeline: PREPARATION → ROUTING → RESPONSE
|
|
10
10
|
*/
|
|
11
11
|
|
|
@@ -14,14 +14,14 @@ import {
|
|
|
14
14
|
createSession,
|
|
15
15
|
EventSource,
|
|
16
16
|
createMessageEvent,
|
|
17
|
-
|
|
17
|
+
END_ROUTE,
|
|
18
18
|
OpenAIProvider,
|
|
19
19
|
} from "../src";
|
|
20
20
|
import type { Event } from "../src/types";
|
|
21
21
|
import type { ToolRef } from "../src/types/tool";
|
|
22
22
|
|
|
23
23
|
// ==============================================================================
|
|
24
|
-
// CONTEXT &
|
|
24
|
+
// CONTEXT & COLLECTED DATA TYPES
|
|
25
25
|
// ==============================================================================
|
|
26
26
|
|
|
27
27
|
interface FlightBookingContext {
|
|
@@ -59,8 +59,8 @@ const enrichDestinationTool: ToolRef<
|
|
|
59
59
|
name: "Enrich Destination",
|
|
60
60
|
description: "Convert city names to IATA airport codes",
|
|
61
61
|
handler: async (context) => {
|
|
62
|
-
const {
|
|
63
|
-
const destination = (
|
|
62
|
+
const { data } = context;
|
|
63
|
+
const destination = (data as Partial<FlightData>)?.destination;
|
|
64
64
|
|
|
65
65
|
if (!destination) {
|
|
66
66
|
return { data: undefined };
|
|
@@ -81,7 +81,7 @@ const enrichDestinationTool: ToolRef<
|
|
|
81
81
|
|
|
82
82
|
return {
|
|
83
83
|
data: undefined,
|
|
84
|
-
|
|
84
|
+
dataUpdate: {
|
|
85
85
|
destinationCode,
|
|
86
86
|
} as Partial<FlightData>,
|
|
87
87
|
};
|
|
@@ -95,8 +95,8 @@ const validateDateTool: ToolRef<FlightBookingContext, [], void, FlightData> = {
|
|
|
95
95
|
description:
|
|
96
96
|
"Parse relative dates (today, tomorrow) to ISO format and validate",
|
|
97
97
|
handler: async (context) => {
|
|
98
|
-
const {
|
|
99
|
-
const departureDate = (
|
|
98
|
+
const { data } = context;
|
|
99
|
+
const departureDate = (data as Partial<FlightData>)?.departureDate;
|
|
100
100
|
|
|
101
101
|
if (!departureDate) {
|
|
102
102
|
return { data: undefined };
|
|
@@ -133,7 +133,7 @@ const validateDateTool: ToolRef<FlightBookingContext, [], void, FlightData> = {
|
|
|
133
133
|
|
|
134
134
|
return {
|
|
135
135
|
data: undefined,
|
|
136
|
-
|
|
136
|
+
dataUpdate: {
|
|
137
137
|
departureDateParsed: parsedDate,
|
|
138
138
|
} as Partial<FlightData>,
|
|
139
139
|
};
|
|
@@ -144,10 +144,10 @@ const validateDateTool: ToolRef<FlightBookingContext, [], void, FlightData> = {
|
|
|
144
144
|
const searchFlightsTool: ToolRef<FlightBookingContext, [], void, FlightData> = {
|
|
145
145
|
id: "search_flights",
|
|
146
146
|
name: "Search Flights",
|
|
147
|
-
description: "Search for available flights based on
|
|
147
|
+
description: "Search for available flights based on collected data",
|
|
148
148
|
handler: async (context) => {
|
|
149
|
-
const {
|
|
150
|
-
const flightData =
|
|
149
|
+
const { data } = context;
|
|
150
|
+
const flightData = data as Partial<FlightData>;
|
|
151
151
|
|
|
152
152
|
if (!flightData?.destinationCode || !flightData?.departureDateParsed) {
|
|
153
153
|
console.log("[Tool] Cannot search flights: missing required data");
|
|
@@ -179,7 +179,7 @@ const searchFlightsTool: ToolRef<FlightBookingContext, [], void, FlightData> = {
|
|
|
179
179
|
contextUpdate: {
|
|
180
180
|
availableFlights: flights,
|
|
181
181
|
},
|
|
182
|
-
|
|
182
|
+
dataUpdate: {
|
|
183
183
|
shouldSearchFlights: false, // Clear the flag to prevent re-execution
|
|
184
184
|
} as Partial<FlightData>,
|
|
185
185
|
};
|
|
@@ -192,8 +192,8 @@ const bookFlightTool: ToolRef<FlightBookingContext, [], void, FlightData> = {
|
|
|
192
192
|
name: "Book Flight",
|
|
193
193
|
description: "Finalize the flight booking",
|
|
194
194
|
handler: async (context) => {
|
|
195
|
-
const {
|
|
196
|
-
const flightData =
|
|
195
|
+
const { data } = context;
|
|
196
|
+
const flightData = data as Partial<FlightData>;
|
|
197
197
|
console.log("[Tool] Booking flight with data:", flightData);
|
|
198
198
|
// Simulate booking API call
|
|
199
199
|
return { data: undefined };
|
|
@@ -204,49 +204,44 @@ const bookFlightTool: ToolRef<FlightBookingContext, [], void, FlightData> = {
|
|
|
204
204
|
// LIFECYCLE HOOKS: Data Validation & Business Logic (RESPONSE Phase)
|
|
205
205
|
// ==============================================================================
|
|
206
206
|
|
|
207
|
-
async function
|
|
208
|
-
|
|
209
|
-
|
|
207
|
+
async function onDataUpdate(
|
|
208
|
+
data: Record<string, unknown>,
|
|
209
|
+
previousData: Record<string, unknown>
|
|
210
210
|
): Promise<Record<string, unknown>> {
|
|
211
|
-
console.log("[Hook]
|
|
212
|
-
console.log(" Previous:",
|
|
213
|
-
console.log(" New:",
|
|
211
|
+
console.log("[Hook] onDataUpdate called");
|
|
212
|
+
console.log(" Previous:", previousData);
|
|
213
|
+
console.log(" New:", data);
|
|
214
214
|
|
|
215
215
|
// Example: Validate passenger count
|
|
216
|
-
const passengers =
|
|
216
|
+
const passengers = data.passengers as number | undefined;
|
|
217
217
|
if (typeof passengers === "number") {
|
|
218
218
|
if (passengers < 1) {
|
|
219
219
|
console.warn("[Hook] Invalid passengers count, setting to 1");
|
|
220
|
-
|
|
220
|
+
data.passengers = 1;
|
|
221
221
|
}
|
|
222
222
|
if (passengers > 9) {
|
|
223
223
|
console.warn("[Hook] Too many passengers, capping at 9");
|
|
224
|
-
|
|
224
|
+
data.passengers = 9;
|
|
225
225
|
}
|
|
226
226
|
}
|
|
227
227
|
|
|
228
228
|
// Example: Normalize cabin class
|
|
229
|
-
const cabinClass =
|
|
229
|
+
const cabinClass = data.cabinClass as string | undefined;
|
|
230
230
|
if (typeof cabinClass === "string") {
|
|
231
|
-
|
|
231
|
+
data.cabinClass = cabinClass.toLowerCase();
|
|
232
232
|
}
|
|
233
233
|
|
|
234
234
|
// Example: Auto-trigger flight search when we have enough data
|
|
235
|
-
const hasDestination =
|
|
236
|
-
const hasDate =
|
|
235
|
+
const hasDestination = data.destinationCode || data.destination;
|
|
236
|
+
const hasDate = data.departureDateParsed || data.departureDate;
|
|
237
237
|
const hasPassengers = typeof passengers === "number";
|
|
238
238
|
|
|
239
|
-
if (
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
hasPassengers &&
|
|
243
|
-
!extracted.shouldSearchFlights
|
|
244
|
-
) {
|
|
245
|
-
console.log("[Hook] All required data gathered, triggering flight search");
|
|
246
|
-
extracted.shouldSearchFlights = true;
|
|
239
|
+
if (hasDestination && hasDate && hasPassengers && !data.shouldSearchFlights) {
|
|
240
|
+
console.log("[Hook] All required data collected, triggering flight search");
|
|
241
|
+
data.shouldSearchFlights = true;
|
|
247
242
|
}
|
|
248
243
|
|
|
249
|
-
return
|
|
244
|
+
return data;
|
|
250
245
|
}
|
|
251
246
|
|
|
252
247
|
// ==============================================================================
|
|
@@ -263,7 +258,7 @@ const agent = new Agent<FlightBookingContext>({
|
|
|
263
258
|
}),
|
|
264
259
|
context: {},
|
|
265
260
|
hooks: {
|
|
266
|
-
|
|
261
|
+
onDataUpdate, // Validation & enrichment hook
|
|
267
262
|
},
|
|
268
263
|
});
|
|
269
264
|
|
|
@@ -275,7 +270,7 @@ const bookingRoute = agent.createRoute<FlightData>({
|
|
|
275
270
|
"User wants to book a flight",
|
|
276
271
|
"User mentions flying, traveling, or booking",
|
|
277
272
|
],
|
|
278
|
-
|
|
273
|
+
schema: {
|
|
279
274
|
type: "object",
|
|
280
275
|
properties: {
|
|
281
276
|
destination: {
|
|
@@ -313,65 +308,65 @@ const bookingRoute = agent.createRoute<FlightData>({
|
|
|
313
308
|
},
|
|
314
309
|
});
|
|
315
310
|
|
|
316
|
-
//
|
|
317
|
-
const
|
|
318
|
-
|
|
319
|
-
|
|
311
|
+
// Step 1: Collect destination
|
|
312
|
+
const collectDestination = bookingRoute.initialStep.nextStep({
|
|
313
|
+
instructions: "Ask where they want to fly",
|
|
314
|
+
collect: ["destination"],
|
|
320
315
|
skipIf: (data) => !!data.destination,
|
|
321
316
|
});
|
|
322
317
|
|
|
323
|
-
//
|
|
324
|
-
const enrichDestination =
|
|
325
|
-
|
|
326
|
-
|
|
318
|
+
// Step 2: Enrich destination (tool execution)
|
|
319
|
+
const enrichDestination = collectDestination.nextStep({
|
|
320
|
+
tool: enrichDestinationTool,
|
|
321
|
+
requires: ["destination"],
|
|
327
322
|
});
|
|
328
323
|
|
|
329
|
-
//
|
|
330
|
-
const
|
|
331
|
-
|
|
332
|
-
|
|
324
|
+
// Step 3: Collect date
|
|
325
|
+
const collectDate = enrichDestination.nextStep({
|
|
326
|
+
instructions: "Ask when they want to depart",
|
|
327
|
+
collect: ["departureDate"],
|
|
333
328
|
skipIf: (data) => !!data.departureDate,
|
|
334
329
|
});
|
|
335
330
|
|
|
336
|
-
//
|
|
337
|
-
const validateDate =
|
|
338
|
-
|
|
339
|
-
|
|
331
|
+
// Step 4: Validate/parse date (tool execution)
|
|
332
|
+
const validateDate = collectDate.nextStep({
|
|
333
|
+
tool: validateDateTool,
|
|
334
|
+
requires: ["departureDate"],
|
|
340
335
|
});
|
|
341
336
|
|
|
342
|
-
//
|
|
343
|
-
const
|
|
344
|
-
|
|
345
|
-
|
|
337
|
+
// Step 5: Collect passengers
|
|
338
|
+
const collectPassengers = validateDate.nextStep({
|
|
339
|
+
instructions: "Ask how many passengers",
|
|
340
|
+
collect: ["passengers"],
|
|
346
341
|
skipIf: (data) => !!data.passengers,
|
|
347
342
|
});
|
|
348
343
|
|
|
349
|
-
//
|
|
350
|
-
const searchFlights =
|
|
351
|
-
|
|
352
|
-
// This
|
|
353
|
-
// The hook automatically sets this flag when all data is
|
|
344
|
+
// Step 6: Search flights (triggered by hook setting shouldSearchFlights)
|
|
345
|
+
const searchFlights = collectPassengers.nextStep({
|
|
346
|
+
tool: searchFlightsTool,
|
|
347
|
+
// This step is entered when shouldSearchFlights is true
|
|
348
|
+
// The hook automatically sets this flag when all data is collected
|
|
354
349
|
});
|
|
355
350
|
|
|
356
|
-
//
|
|
357
|
-
const presentResults = searchFlights.
|
|
358
|
-
|
|
351
|
+
// Step 7: Present results
|
|
352
|
+
const presentResults = searchFlights.nextStep({
|
|
353
|
+
instructions: "Present available flights to the user",
|
|
359
354
|
});
|
|
360
355
|
|
|
361
|
-
//
|
|
362
|
-
const confirmBooking = presentResults.
|
|
363
|
-
|
|
364
|
-
|
|
356
|
+
// Step 8: Confirm booking
|
|
357
|
+
const confirmBooking = presentResults.nextStep({
|
|
358
|
+
instructions: "Ask user to confirm the booking",
|
|
359
|
+
requires: ["destinationCode", "departureDateParsed", "passengers"],
|
|
365
360
|
});
|
|
366
361
|
|
|
367
|
-
//
|
|
368
|
-
const finalizeBooking = confirmBooking.
|
|
369
|
-
|
|
362
|
+
// Step 9: Finalize booking
|
|
363
|
+
const finalizeBooking = confirmBooking.nextStep({
|
|
364
|
+
tool: bookFlightTool,
|
|
370
365
|
condition: "User confirms the booking",
|
|
371
366
|
});
|
|
372
367
|
|
|
373
|
-
//
|
|
374
|
-
finalizeBooking.
|
|
368
|
+
// Step 10: End of conversation
|
|
369
|
+
finalizeBooking.nextStep({ step: END_ROUTE });
|
|
375
370
|
|
|
376
371
|
// ==============================================================================
|
|
377
372
|
// USAGE EXAMPLE: Three-Phase Pipeline Demonstration
|
|
@@ -393,12 +388,12 @@ async function main() {
|
|
|
393
388
|
|
|
394
389
|
console.log("\n=== RESPONSE ===");
|
|
395
390
|
console.log("Message:", response.message);
|
|
396
|
-
console.log("
|
|
391
|
+
console.log("Data:", response.session?.data);
|
|
397
392
|
console.log("Context:", agent["context"]);
|
|
398
393
|
|
|
399
394
|
if (response.isRouteComplete) {
|
|
400
395
|
console.log("\n✅ Flight booking complete!");
|
|
401
|
-
await sendBookingConfirmation(response.session?.
|
|
396
|
+
await sendBookingConfirmation(response.session?.data);
|
|
402
397
|
}
|
|
403
398
|
|
|
404
399
|
/*
|
|
@@ -406,14 +401,14 @@ async function main() {
|
|
|
406
401
|
* 1. AI extracts: { destination: "Paris", departureDate: "tomorrow", passengers: 2 }
|
|
407
402
|
* 2. Hook validates passengers ✓
|
|
408
403
|
* 3. Hook detects all data present, sets shouldSearchFlights: true
|
|
409
|
-
* 4.
|
|
410
|
-
* - Skips
|
|
404
|
+
* 4. Step machine:
|
|
405
|
+
* - Skips collectDestination (has destination)
|
|
411
406
|
* - Runs enrichDestination tool → adds destinationCode: "CDG"
|
|
412
|
-
* - Skips
|
|
407
|
+
* - Skips collectDate (has departureDate)
|
|
413
408
|
* - Runs validateDate tool → adds departureDateParsed: "2025-10-16"
|
|
414
|
-
* - Skips
|
|
409
|
+
* - Skips collectPassengers (has passengers)
|
|
415
410
|
* - Runs searchFlights tool → updates context with flights, clears flag
|
|
416
|
-
* - Enters presentResults
|
|
411
|
+
* - Enters presentResults step
|
|
417
412
|
* 5. AI generates response with flight options
|
|
418
413
|
*/
|
|
419
414
|
}
|
|
@@ -446,30 +441,30 @@ async function sendBookingConfirmation(data: Partial<FlightData> | undefined) {
|
|
|
446
441
|
* - Type-safe extraction throughout the conversation
|
|
447
442
|
* - Predictable data structure every time
|
|
448
443
|
*
|
|
449
|
-
* 2. CODE-BASED
|
|
450
|
-
* - Use TypeScript functions (skipIf,
|
|
451
|
-
* - Deterministic flow based on
|
|
452
|
-
* - No fuzzy LLM interpretation of
|
|
444
|
+
* 2. CODE-BASED STEP LOGIC
|
|
445
|
+
* - Use TypeScript functions (skipIf, requires) instead of LLM conditions
|
|
446
|
+
* - Deterministic flow based on collected data
|
|
447
|
+
* - No fuzzy LLM interpretation of step logic
|
|
453
448
|
*
|
|
454
|
-
* 3. TOOLS ENRICH
|
|
455
|
-
* - Tools modify
|
|
449
|
+
* 3. TOOLS ENRICH COLLECTED DATA (PREPARATION Phase)
|
|
450
|
+
* - Tools modify collected data via `dataUpdate`
|
|
456
451
|
* - Great for: validation, enrichment, normalization, computed fields
|
|
457
452
|
* - Execute before AI sees the conversation
|
|
458
453
|
*
|
|
459
454
|
* 4. LIFECYCLE HOOKS (RESPONSE Phase)
|
|
460
|
-
* -
|
|
455
|
+
* - onDataUpdate runs after each data extraction
|
|
461
456
|
* - Cross-cutting logic: validation, business rules, auto-triggering
|
|
462
|
-
* - Return modified
|
|
457
|
+
* - Return modified collected data
|
|
463
458
|
*
|
|
464
459
|
* 5. THREE-PHASE PIPELINE
|
|
465
460
|
* - PREPARATION: Tools execute and enrich context/data
|
|
466
|
-
* - ROUTING: AI scores routes based on current
|
|
461
|
+
* - ROUTING: AI scores routes based on current step
|
|
467
462
|
* - RESPONSE: AI generates message with schema-enforced extraction
|
|
468
463
|
*
|
|
469
|
-
* 6. SESSION
|
|
470
|
-
* -
|
|
464
|
+
* 6. SESSION STEP MANAGEMENT
|
|
465
|
+
* - Collected data persists across conversation turns
|
|
471
466
|
* - Always-on routing respects user intent changes
|
|
472
|
-
* -
|
|
467
|
+
* - Step recovery enables conversation resumption
|
|
473
468
|
*/
|
|
474
469
|
|
|
475
470
|
if (require.main === module) {
|