@falai/agent 0.6.3 → 0.6.5
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 -29
- 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 +113 -26
- 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/ResponseEngine.d.ts +1 -1
- package/dist/cjs/core/ResponseEngine.d.ts.map +1 -1
- package/dist/cjs/core/ResponseEngine.js +4 -1
- package/dist/cjs/core/ResponseEngine.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 +116 -41
- package/dist/cjs/core/RoutingEngine.js.map +1 -1
- package/dist/cjs/core/State.d.ts +18 -6
- package/dist/cjs/core/State.d.ts.map +1 -1
- package/dist/cjs/core/State.js +30 -7
- 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 +13 -2
- package/dist/cjs/types/session.d.ts.map +1 -1
- package/dist/cjs/types/session.js +28 -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 +113 -26
- 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/ResponseEngine.d.ts +1 -1
- package/dist/core/ResponseEngine.d.ts.map +1 -1
- package/dist/core/ResponseEngine.js +4 -1
- package/dist/core/ResponseEngine.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 +116 -41
- package/dist/core/RoutingEngine.js.map +1 -1
- package/dist/core/State.d.ts +18 -6
- package/dist/core/State.d.ts.map +1 -1
- package/dist/core/State.js +31 -8
- 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 +13 -2
- package/dist/types/session.d.ts.map +1 -1
- package/dist/types/session.js +28 -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 +140 -24
- package/src/core/Events.ts +73 -10
- package/src/core/ResponseEngine.ts +6 -0
- package/src/core/Route.ts +8 -4
- package/src/core/RoutingEngine.ts +154 -43
- package/src/core/State.ts +45 -12
- 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 +47 -7
- package/src/utils/logger.ts +19 -0
|
@@ -9,7 +9,14 @@
|
|
|
9
9
|
* 5. Three-phase pipeline: PREPARATION → ROUTING → RESPONSE
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
Agent,
|
|
14
|
+
createSession,
|
|
15
|
+
EventSource,
|
|
16
|
+
createMessageEvent,
|
|
17
|
+
END_STATE,
|
|
18
|
+
OpenAIProvider,
|
|
19
|
+
} from "../src";
|
|
13
20
|
import type { Event } from "../src/types";
|
|
14
21
|
import type { ToolRef } from "../src/types/tool";
|
|
15
22
|
|
|
@@ -179,6 +186,20 @@ const searchFlightsTool: ToolRef<FlightBookingContext, [], void, FlightData> = {
|
|
|
179
186
|
},
|
|
180
187
|
};
|
|
181
188
|
|
|
189
|
+
// Tool 4: Book the flight
|
|
190
|
+
const bookFlightTool: ToolRef<FlightBookingContext, [], void, FlightData> = {
|
|
191
|
+
id: "book_flight",
|
|
192
|
+
name: "Book Flight",
|
|
193
|
+
description: "Finalize the flight booking",
|
|
194
|
+
handler: async (context) => {
|
|
195
|
+
const { extracted } = context;
|
|
196
|
+
const flightData = extracted as Partial<FlightData>;
|
|
197
|
+
console.log("[Tool] Booking flight with data:", flightData);
|
|
198
|
+
// Simulate booking API call
|
|
199
|
+
return { data: undefined };
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
|
|
182
203
|
// ==============================================================================
|
|
183
204
|
// LIFECYCLE HOOKS: Data Validation & Business Logic (RESPONSE Phase)
|
|
184
205
|
// ==============================================================================
|
|
@@ -236,7 +257,10 @@ const agent = new Agent<FlightBookingContext>({
|
|
|
236
257
|
name: "Flight Booking Agent",
|
|
237
258
|
goal: "Help users book flights efficiently",
|
|
238
259
|
description: "I help you find and book flights",
|
|
239
|
-
ai:
|
|
260
|
+
ai: new OpenAIProvider({
|
|
261
|
+
apiKey: process.env.OPENAI_API_KEY || "your-api-key-here",
|
|
262
|
+
model: "gpt-5o-mini",
|
|
263
|
+
}),
|
|
240
264
|
context: {},
|
|
241
265
|
hooks: {
|
|
242
266
|
onExtractedUpdate, // Validation & enrichment hook
|
|
@@ -334,6 +358,21 @@ const presentResults = searchFlights.transitionTo({
|
|
|
334
358
|
chatState: "Present available flights to the user",
|
|
335
359
|
});
|
|
336
360
|
|
|
361
|
+
// State 8: Confirm booking
|
|
362
|
+
const confirmBooking = presentResults.transitionTo({
|
|
363
|
+
chatState: "Ask user to confirm the booking",
|
|
364
|
+
requiredData: ["destinationCode", "departureDateParsed", "passengers"],
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
// State 9: Finalize booking
|
|
368
|
+
const finalizeBooking = confirmBooking.transitionTo({
|
|
369
|
+
toolState: bookFlightTool,
|
|
370
|
+
condition: "User confirms the booking",
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
// State 10: End of conversation
|
|
374
|
+
finalizeBooking.transitionTo({ state: END_STATE });
|
|
375
|
+
|
|
337
376
|
// ==============================================================================
|
|
338
377
|
// USAGE EXAMPLE: Three-Phase Pipeline Demonstration
|
|
339
378
|
// ==============================================================================
|
|
@@ -357,6 +396,11 @@ async function main() {
|
|
|
357
396
|
console.log("Extracted:", response.session?.extracted);
|
|
358
397
|
console.log("Context:", agent["context"]);
|
|
359
398
|
|
|
399
|
+
if (response.isRouteComplete) {
|
|
400
|
+
console.log("\n✅ Flight booking complete!");
|
|
401
|
+
await sendBookingConfirmation(response.session?.extracted);
|
|
402
|
+
}
|
|
403
|
+
|
|
360
404
|
/*
|
|
361
405
|
* Expected flow:
|
|
362
406
|
* 1. AI extracts: { destination: "Paris", departureDate: "tomorrow", passengers: 2 }
|
|
@@ -374,6 +418,24 @@ async function main() {
|
|
|
374
418
|
*/
|
|
375
419
|
}
|
|
376
420
|
|
|
421
|
+
/**
|
|
422
|
+
* Mock function to send a booking confirmation.
|
|
423
|
+
* @param data - The flight booking data.
|
|
424
|
+
*/
|
|
425
|
+
async function sendBookingConfirmation(data: Partial<FlightData> | undefined) {
|
|
426
|
+
console.log("\n" + "=".repeat(60));
|
|
427
|
+
console.log("🚀 Sending Booking Confirmation...");
|
|
428
|
+
console.log("=".repeat(60));
|
|
429
|
+
console.log("Booking Details:", JSON.stringify(data, null, 2));
|
|
430
|
+
console.log(
|
|
431
|
+
` - Sending confirmation for flight to ${data?.destinationCode} on ${
|
|
432
|
+
data?.departureDateParsed ?? ""
|
|
433
|
+
}.`
|
|
434
|
+
);
|
|
435
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
436
|
+
console.log("✨ Confirmation sent!");
|
|
437
|
+
}
|
|
438
|
+
|
|
377
439
|
// ==============================================================================
|
|
378
440
|
// KEY TAKEAWAYS: Architecture Principles Demonstrated
|
|
379
441
|
// ==============================================================================
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
Agent,
|
|
8
8
|
defineTool,
|
|
9
9
|
AnthropicProvider,
|
|
10
|
-
|
|
10
|
+
END_STATE,
|
|
11
11
|
EventSource,
|
|
12
12
|
createMessageEvent,
|
|
13
13
|
createSession,
|
|
@@ -213,7 +213,7 @@ async function createHealthcareAgent() {
|
|
|
213
213
|
});
|
|
214
214
|
|
|
215
215
|
confirmation.transitionTo({
|
|
216
|
-
state:
|
|
216
|
+
state: END_STATE,
|
|
217
217
|
condition: "Appointment booked successfully",
|
|
218
218
|
});
|
|
219
219
|
|
|
@@ -232,7 +232,7 @@ async function createHealthcareAgent() {
|
|
|
232
232
|
chatState:
|
|
233
233
|
"Ask the patient to call the office to schedule an appointment",
|
|
234
234
|
})
|
|
235
|
-
.transitionTo({ state:
|
|
235
|
+
.transitionTo({ state: END_STATE });
|
|
236
236
|
|
|
237
237
|
schedulingRoute.createGuideline({
|
|
238
238
|
condition: "The patient says their visit is urgent",
|
|
@@ -291,7 +291,7 @@ async function createHealthcareAgent() {
|
|
|
291
291
|
chatState: "Present the lab results and explain what they mean",
|
|
292
292
|
});
|
|
293
293
|
|
|
294
|
-
presentResults.transitionTo({ state:
|
|
294
|
+
presentResults.transitionTo({ state: END_STATE });
|
|
295
295
|
|
|
296
296
|
labResultsRoute.createGuideline({
|
|
297
297
|
condition:
|
|
@@ -383,9 +383,66 @@ async function main() {
|
|
|
383
383
|
|
|
384
384
|
// Update session again
|
|
385
385
|
session = response2.session!;
|
|
386
|
+
|
|
387
|
+
// Turn 3: Patient provides final details
|
|
388
|
+
const history3 = [
|
|
389
|
+
...history2,
|
|
390
|
+
createMessageEvent(EventSource.AI_AGENT, "Agent", response2.message),
|
|
391
|
+
createMessageEvent(
|
|
392
|
+
EventSource.CUSTOMER,
|
|
393
|
+
"Patient",
|
|
394
|
+
"Tuesday at 2 PM works for me."
|
|
395
|
+
),
|
|
396
|
+
];
|
|
397
|
+
|
|
398
|
+
const response3 = await agent.respond({ history: history3, session });
|
|
399
|
+
console.log("\nPatient: Tuesday at 2 PM works for me.");
|
|
400
|
+
console.log("Agent:", response3.message);
|
|
401
|
+
console.log("Updated extracted:", response3.session?.extracted);
|
|
402
|
+
console.log("Current state:", response3.session?.currentState?.id);
|
|
403
|
+
|
|
404
|
+
// Check for route completion
|
|
405
|
+
if (response3.isRouteComplete) {
|
|
406
|
+
console.log("\n✅ Appointment scheduling complete!");
|
|
407
|
+
await sendAppointmentReminder(
|
|
408
|
+
agent.getExtractedData(
|
|
409
|
+
response3.session?.id
|
|
410
|
+
) as unknown as AppointmentData
|
|
411
|
+
);
|
|
412
|
+
}
|
|
386
413
|
}
|
|
387
414
|
}
|
|
388
415
|
|
|
416
|
+
/**
|
|
417
|
+
* Mock function to send an appointment reminder.
|
|
418
|
+
* @param data - The appointment data.
|
|
419
|
+
*/
|
|
420
|
+
async function sendAppointmentReminder(data: AppointmentData) {
|
|
421
|
+
console.log("\n" + "=".repeat(60));
|
|
422
|
+
console.log("🚀 Sending Appointment Reminder...");
|
|
423
|
+
console.log("=".repeat(60));
|
|
424
|
+
console.log("Appointment Details:", JSON.stringify(data, null, 2));
|
|
425
|
+
console.log(
|
|
426
|
+
` - Sending reminder for ${data.appointmentReason} on ${data.preferredDate} at ${data.preferredTime}.`
|
|
427
|
+
);
|
|
428
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
429
|
+
console.log("✨ Reminder sent!");
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Mock function to log a patient inquiry about lab results.
|
|
434
|
+
* @param data - The lab results data.
|
|
435
|
+
*/
|
|
436
|
+
async function logPatientInquiry(data: LabResultsData) {
|
|
437
|
+
console.log("\n" + "=".repeat(60));
|
|
438
|
+
console.log("📝 Logging Patient Inquiry...");
|
|
439
|
+
console.log("=".repeat(60));
|
|
440
|
+
console.log("Inquiry Details:", JSON.stringify(data, null, 2));
|
|
441
|
+
console.log(` - Logging inquiry for ${data.testType} results.`);
|
|
442
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
443
|
+
console.log("✨ Inquiry logged!");
|
|
444
|
+
}
|
|
445
|
+
|
|
389
446
|
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
390
447
|
main().catch(console.error);
|
|
391
448
|
}
|
package/examples/openai-agent.ts
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
createMessageEvent,
|
|
11
11
|
EventSource,
|
|
12
12
|
createSession,
|
|
13
|
-
|
|
13
|
+
END_STATE,
|
|
14
14
|
} from "../src/index";
|
|
15
15
|
|
|
16
16
|
// Custom context type
|
|
@@ -151,7 +151,7 @@ async function main() {
|
|
|
151
151
|
"Present the weather information in a friendly way with temperature and condition",
|
|
152
152
|
});
|
|
153
153
|
|
|
154
|
-
showWeather.transitionTo({ state:
|
|
154
|
+
showWeather.transitionTo({ state: END_STATE });
|
|
155
155
|
|
|
156
156
|
// Example conversation with session state management
|
|
157
157
|
console.log("🤖 Starting OpenAI Agent Example\n");
|
|
@@ -191,6 +191,14 @@ async function main() {
|
|
|
191
191
|
// Update session with progress
|
|
192
192
|
session = response.session!;
|
|
193
193
|
|
|
194
|
+
// Check for route completion
|
|
195
|
+
if (response.isRouteComplete) {
|
|
196
|
+
console.log("\n✅ Weather route complete!");
|
|
197
|
+
await logWeatherRequest(
|
|
198
|
+
agent.getExtractedData(session.id) as WeatherData
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
|
|
194
202
|
console.log("\n✨ Session state benefits:");
|
|
195
203
|
console.log(" ✅ Data extraction tracked across turns");
|
|
196
204
|
console.log(" ✅ State progression managed automatically");
|
|
@@ -203,6 +211,20 @@ async function main() {
|
|
|
203
211
|
}
|
|
204
212
|
}
|
|
205
213
|
|
|
214
|
+
/**
|
|
215
|
+
* Mock function to log the weather request for analytics.
|
|
216
|
+
* @param data - The weather data from the completed route.
|
|
217
|
+
*/
|
|
218
|
+
async function logWeatherRequest(data: WeatherData) {
|
|
219
|
+
console.log("\n" + "=".repeat(60));
|
|
220
|
+
console.log("📊 Logging Weather Request for Analytics...");
|
|
221
|
+
console.log("=".repeat(60));
|
|
222
|
+
console.log("Request Details:", JSON.stringify(data, null, 2));
|
|
223
|
+
console.log(` - Logging request for location: ${data.location}`);
|
|
224
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
225
|
+
console.log("✨ Request logged!");
|
|
226
|
+
}
|
|
227
|
+
|
|
206
228
|
// Run if executed directly
|
|
207
229
|
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
208
230
|
main().catch(console.error);
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
EventSource,
|
|
17
17
|
MessageEventData,
|
|
18
18
|
Event,
|
|
19
|
+
END_STATE,
|
|
19
20
|
} from "../src/index";
|
|
20
21
|
// @ts-ignore
|
|
21
22
|
import { Client } from "@opensearch-project/opensearch";
|
|
@@ -157,7 +158,8 @@ async function example() {
|
|
|
157
158
|
.transitionTo({
|
|
158
159
|
chatState: "Propose solution and close complaint",
|
|
159
160
|
requiredData: ["category", "description"],
|
|
160
|
-
})
|
|
161
|
+
})
|
|
162
|
+
.transitionTo({ state: END_STATE });
|
|
161
163
|
|
|
162
164
|
const persistence = agent.getPersistenceManager();
|
|
163
165
|
if (!persistence) return;
|
|
@@ -239,6 +241,13 @@ async function example() {
|
|
|
239
241
|
content: response2.message,
|
|
240
242
|
});
|
|
241
243
|
|
|
244
|
+
if (response2.isRouteComplete) {
|
|
245
|
+
console.log("\n✅ Complaint route complete!");
|
|
246
|
+
await createSupportTicket(
|
|
247
|
+
agent.getExtractedData(session.id) as ComplaintData
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
|
|
242
251
|
// Load session from OpenSearch
|
|
243
252
|
console.log("\n--- Loading Session from OpenSearch ---");
|
|
244
253
|
const loadedSession = await persistence.loadSessionState<ComplaintData>(
|
|
@@ -471,6 +480,22 @@ async function timeSeriesExample() {
|
|
|
471
480
|
}
|
|
472
481
|
}
|
|
473
482
|
|
|
483
|
+
/**
|
|
484
|
+
* Mock function to create a support ticket.
|
|
485
|
+
* @param data - The complaint data from the completed route.
|
|
486
|
+
*/
|
|
487
|
+
async function createSupportTicket(data: ComplaintData) {
|
|
488
|
+
console.log("\n" + "=".repeat(60));
|
|
489
|
+
console.log("🎫 Creating Support Ticket...");
|
|
490
|
+
console.log("=".repeat(60));
|
|
491
|
+
console.log("Ticket Details:", JSON.stringify(data, null, 2));
|
|
492
|
+
console.log(
|
|
493
|
+
` - Creating ticket for category: ${data.category} with severity: ${data.severity}`
|
|
494
|
+
);
|
|
495
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
496
|
+
console.log("✨ Ticket created successfully!");
|
|
497
|
+
}
|
|
498
|
+
|
|
474
499
|
// Run the example
|
|
475
500
|
if (require.main === module) {
|
|
476
501
|
example().catch(console.error);
|
|
@@ -7,7 +7,8 @@ import {
|
|
|
7
7
|
Agent,
|
|
8
8
|
defineTool,
|
|
9
9
|
GeminiProvider,
|
|
10
|
-
|
|
10
|
+
END_STATE,
|
|
11
|
+
END_STATE_ID,
|
|
11
12
|
EventSource,
|
|
12
13
|
createMessageEvent,
|
|
13
14
|
createSession,
|
|
@@ -269,24 +270,20 @@ async function createPersistentOnboardingAgent(sessionId: string) {
|
|
|
269
270
|
});
|
|
270
271
|
|
|
271
272
|
// State 1: Gather business name and description
|
|
272
|
-
const gatherBusinessInfo = onboardingRoute.initialState.transitionTo(
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
"Need to collect basic business information first"
|
|
280
|
-
);
|
|
273
|
+
const gatherBusinessInfo = onboardingRoute.initialState.transitionTo({
|
|
274
|
+
chatState: "Ask for business name and a brief description",
|
|
275
|
+
gather: ["businessName", "businessDescription"],
|
|
276
|
+
skipIf: (extracted) =>
|
|
277
|
+
!!extracted.businessName && !!extracted.businessDescription,
|
|
278
|
+
condition: "Need to collect basic business information first",
|
|
279
|
+
});
|
|
281
280
|
|
|
282
281
|
// State 2: Save business info (tool execution)
|
|
283
|
-
const saveBusiness = gatherBusinessInfo.transitionTo(
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
"Business name and description provided, save to database"
|
|
289
|
-
);
|
|
282
|
+
const saveBusiness = gatherBusinessInfo.transitionTo({
|
|
283
|
+
toolState: saveBusinessInfo,
|
|
284
|
+
requiredData: ["businessName", "businessDescription"],
|
|
285
|
+
condition: "Business name and description provided, save to database",
|
|
286
|
+
});
|
|
290
287
|
|
|
291
288
|
// State 3: Gather industry
|
|
292
289
|
const gatherIndustry = saveBusiness.transitionTo({
|
|
@@ -319,7 +316,7 @@ async function createPersistentOnboardingAgent(sessionId: string) {
|
|
|
319
316
|
chatState: "Summarize all collected information and ask for confirmation",
|
|
320
317
|
});
|
|
321
318
|
|
|
322
|
-
confirm.transitionTo({ state:
|
|
319
|
+
confirm.transitionTo({ state: END_STATE });
|
|
323
320
|
|
|
324
321
|
// Guidelines
|
|
325
322
|
onboardingRoute.createGuideline({
|
|
@@ -438,6 +435,15 @@ async function main() {
|
|
|
438
435
|
console.log("🤖 Bot:", response1.message);
|
|
439
436
|
console.log("📊 Extracted after turn 1:", response1.session?.extracted);
|
|
440
437
|
console.log("📊 Route:", response1.session?.currentRoute?.title);
|
|
438
|
+
|
|
439
|
+
// Check route completion after turn 1
|
|
440
|
+
console.log("🔍 Route Completion Check (Turn 1):");
|
|
441
|
+
if (response1.isRouteComplete) {
|
|
442
|
+
console.log(" ✅ Route completed after turn 1!");
|
|
443
|
+
} else {
|
|
444
|
+
console.log(" ⏳ Route still in progress after turn 1");
|
|
445
|
+
}
|
|
446
|
+
|
|
441
447
|
console.log();
|
|
442
448
|
|
|
443
449
|
// Update session with progress
|
|
@@ -461,6 +467,15 @@ async function main() {
|
|
|
461
467
|
const response2 = await agent.respond({ history: history2, session });
|
|
462
468
|
console.log("🤖 Bot:", response2.message);
|
|
463
469
|
console.log("📊 Extracted after turn 2:", response2.session?.extracted);
|
|
470
|
+
|
|
471
|
+
// Check route completion after turn 2
|
|
472
|
+
console.log("🔍 Route Completion Check (Turn 2):");
|
|
473
|
+
if (response2.isRouteComplete) {
|
|
474
|
+
console.log(" ✅ Route completed after turn 2!");
|
|
475
|
+
} else {
|
|
476
|
+
console.log(" ⏳ Route still in progress after turn 2");
|
|
477
|
+
}
|
|
478
|
+
|
|
464
479
|
console.log();
|
|
465
480
|
|
|
466
481
|
// Update session again
|
|
@@ -480,8 +495,43 @@ async function main() {
|
|
|
480
495
|
const response3 = await agent.respond({ history: history3, session });
|
|
481
496
|
console.log("🤖 Bot:", response3.message);
|
|
482
497
|
console.log("📊 Extracted after turn 3:", response3.session?.extracted);
|
|
498
|
+
|
|
499
|
+
// Check route completion after turn 3
|
|
500
|
+
console.log("🔍 Route Completion Check (Turn 3):");
|
|
501
|
+
if (response3.isRouteComplete) {
|
|
502
|
+
console.log(" ✅ Route completed after turn 3!");
|
|
503
|
+
} else {
|
|
504
|
+
console.log(" ⏳ Route still in progress after turn 3");
|
|
505
|
+
}
|
|
506
|
+
|
|
483
507
|
console.log();
|
|
484
508
|
|
|
509
|
+
// Update session again
|
|
510
|
+
session = response3.session!;
|
|
511
|
+
|
|
512
|
+
// Turn 4: User provides contact email, completing the flow
|
|
513
|
+
console.log("📱 Turn 4: User provides contact email");
|
|
514
|
+
const history4 = [
|
|
515
|
+
...history3,
|
|
516
|
+
createMessageEvent(EventSource.AI_AGENT, "Agent", response3.message),
|
|
517
|
+
createMessageEvent(
|
|
518
|
+
EventSource.CUSTOMER,
|
|
519
|
+
"Alice",
|
|
520
|
+
"Our contact email is contact@techflow.ai"
|
|
521
|
+
),
|
|
522
|
+
];
|
|
523
|
+
const response4 = await agent.respond({ history: history4, session });
|
|
524
|
+
console.log("🤖 Bot:", response4.message);
|
|
525
|
+
console.log("📊 Extracted after turn 4:", response4.session?.extracted);
|
|
526
|
+
|
|
527
|
+
// Check for route completion
|
|
528
|
+
if (response4.isRouteComplete) {
|
|
529
|
+
console.log("\n✅ Onboarding complete!");
|
|
530
|
+
await finalizeOnboarding(
|
|
531
|
+
agent.getExtractedData(response4.session?.id) as unknown as OnboardingData
|
|
532
|
+
);
|
|
533
|
+
}
|
|
534
|
+
|
|
485
535
|
// Verify persistence
|
|
486
536
|
console.log("=== PERSISTENCE VERIFICATION ===");
|
|
487
537
|
const finalSession = await db.sessions.findById(sessionId);
|
|
@@ -529,6 +579,22 @@ async function main() {
|
|
|
529
579
|
* - No more LLM interpretation of state logic
|
|
530
580
|
*/
|
|
531
581
|
|
|
582
|
+
/**
|
|
583
|
+
* Mock function to finalize the onboarding process.
|
|
584
|
+
* @param data - The complete onboarding data.
|
|
585
|
+
*/
|
|
586
|
+
async function finalizeOnboarding(data: OnboardingData) {
|
|
587
|
+
console.log("\n" + "=".repeat(60));
|
|
588
|
+
console.log("🚀 Finalizing Onboarding...");
|
|
589
|
+
console.log("=".repeat(60));
|
|
590
|
+
console.log("Onboarding Details:", JSON.stringify(data, null, 2));
|
|
591
|
+
console.log(` - Sending welcome email to ${data.contactEmail}...`);
|
|
592
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
593
|
+
console.log(" - Scheduling follow-up call...");
|
|
594
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
595
|
+
console.log("✨ Onboarding finalized!");
|
|
596
|
+
}
|
|
597
|
+
|
|
532
598
|
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
533
599
|
main().catch(console.error);
|
|
534
600
|
}
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
PrismaAdapter,
|
|
12
12
|
createMessageEvent,
|
|
13
13
|
EventSource,
|
|
14
|
-
|
|
14
|
+
END_STATE,
|
|
15
15
|
} from "../src/index";
|
|
16
16
|
|
|
17
17
|
// @ts-ignore
|
|
@@ -57,6 +57,21 @@ interface FlightBookingData {
|
|
|
57
57
|
cabinClass: "economy" | "premium" | "business" | "first";
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
// Extracted data type for onboarding
|
|
61
|
+
interface OnboardingData {
|
|
62
|
+
fullName: string;
|
|
63
|
+
email: string;
|
|
64
|
+
phoneNumber: string;
|
|
65
|
+
country: string;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Extracted data type for contact form
|
|
69
|
+
interface ContactFormData {
|
|
70
|
+
name: string;
|
|
71
|
+
email: string;
|
|
72
|
+
message: string;
|
|
73
|
+
}
|
|
74
|
+
|
|
60
75
|
async function example() {
|
|
61
76
|
// Initialize Prisma client
|
|
62
77
|
const prisma = new PrismaClient();
|
|
@@ -166,6 +181,8 @@ async function example() {
|
|
|
166
181
|
requiredData: ["destination", "departureDate", "passengers", "cabinClass"],
|
|
167
182
|
});
|
|
168
183
|
|
|
184
|
+
confirmBooking.transitionTo({ state: END_STATE });
|
|
185
|
+
|
|
169
186
|
/**
|
|
170
187
|
* Get persistence manager from agent
|
|
171
188
|
*/
|
|
@@ -305,6 +322,13 @@ async function example() {
|
|
|
305
322
|
|
|
306
323
|
session = response2.session!;
|
|
307
324
|
|
|
325
|
+
if (response2.isRouteComplete) {
|
|
326
|
+
console.log("\n✅ Flight booking complete!");
|
|
327
|
+
await sendFlightConfirmation(
|
|
328
|
+
agent.getExtractedData(session.id) as FlightBookingData
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
|
|
308
332
|
/**
|
|
309
333
|
* Load session state from database (demonstrates persistence)
|
|
310
334
|
*/
|
|
@@ -356,13 +380,6 @@ async function advancedExample() {
|
|
|
356
380
|
};
|
|
357
381
|
}
|
|
358
382
|
|
|
359
|
-
interface OnboardingData {
|
|
360
|
-
fullName: string;
|
|
361
|
-
email: string;
|
|
362
|
-
phoneNumber: string;
|
|
363
|
-
country: string;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
383
|
const agent = new Agent<UserContext>({
|
|
367
384
|
name: "Onboarding Assistant",
|
|
368
385
|
description: "Help new users get started",
|
|
@@ -447,7 +464,8 @@ async function advancedExample() {
|
|
|
447
464
|
})
|
|
448
465
|
.transitionTo({
|
|
449
466
|
chatState: "Confirm and complete onboarding",
|
|
450
|
-
})
|
|
467
|
+
})
|
|
468
|
+
.transitionTo({ state: END_STATE });
|
|
451
469
|
|
|
452
470
|
const persistence = agent.getPersistenceManager()!;
|
|
453
471
|
|
|
@@ -481,6 +499,13 @@ async function advancedExample() {
|
|
|
481
499
|
content: response.message,
|
|
482
500
|
});
|
|
483
501
|
|
|
502
|
+
if (response.isRouteComplete) {
|
|
503
|
+
console.log("\n✅ Onboarding complete!");
|
|
504
|
+
await sendOnboardingEmail(
|
|
505
|
+
agent.getExtractedData(sessionData.id) as OnboardingData
|
|
506
|
+
);
|
|
507
|
+
}
|
|
508
|
+
|
|
484
509
|
console.log("✅ Session state automatically saved to database!");
|
|
485
510
|
|
|
486
511
|
await prisma.$disconnect();
|
|
@@ -492,12 +517,6 @@ async function advancedExample() {
|
|
|
492
517
|
async function quickStart() {
|
|
493
518
|
const prisma = new PrismaClient();
|
|
494
519
|
|
|
495
|
-
interface ContactFormData {
|
|
496
|
-
name: string;
|
|
497
|
-
email: string;
|
|
498
|
-
message: string;
|
|
499
|
-
}
|
|
500
|
-
|
|
501
520
|
const agent = new Agent({
|
|
502
521
|
name: "Support Agent",
|
|
503
522
|
ai: new GeminiProvider({
|
|
@@ -532,7 +551,8 @@ async function quickStart() {
|
|
|
532
551
|
})
|
|
533
552
|
.transitionTo({
|
|
534
553
|
chatState: "Confirm submission",
|
|
535
|
-
})
|
|
554
|
+
})
|
|
555
|
+
.transitionTo({ state: END_STATE });
|
|
536
556
|
|
|
537
557
|
const persistence = agent.getPersistenceManager()!;
|
|
538
558
|
|
|
@@ -557,11 +577,65 @@ async function quickStart() {
|
|
|
557
577
|
|
|
558
578
|
console.log("✅ Response:", response.message);
|
|
559
579
|
console.log("📊 Extracted:", response.session?.extracted);
|
|
580
|
+
|
|
581
|
+
if (response.isRouteComplete) {
|
|
582
|
+
console.log("\n✅ Contact form submitted!");
|
|
583
|
+
await logContactForm(
|
|
584
|
+
agent.getExtractedData(sessionData.id) as ContactFormData
|
|
585
|
+
);
|
|
586
|
+
}
|
|
587
|
+
|
|
560
588
|
console.log("💾 Session state auto-saved to Prisma!");
|
|
561
589
|
|
|
562
590
|
await prisma.$disconnect();
|
|
563
591
|
}
|
|
564
592
|
|
|
593
|
+
/**
|
|
594
|
+
* Mock function to send a flight confirmation email.
|
|
595
|
+
* @param data - The flight booking data.
|
|
596
|
+
*/
|
|
597
|
+
async function sendFlightConfirmation(
|
|
598
|
+
data: Partial<FlightBookingData> | undefined
|
|
599
|
+
) {
|
|
600
|
+
console.log("\n" + "=".repeat(60));
|
|
601
|
+
console.log("🚀 Sending Flight Confirmation...");
|
|
602
|
+
console.log("=".repeat(60));
|
|
603
|
+
console.log("Booking Details:", JSON.stringify(data, null, 2));
|
|
604
|
+
console.log(
|
|
605
|
+
` - Sending confirmation for ${data?.passengers} passengers to ${data?.destination}.`
|
|
606
|
+
);
|
|
607
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
608
|
+
console.log("✨ Confirmation sent!");
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
/**
|
|
612
|
+
* Mock function to send an onboarding email.
|
|
613
|
+
* @param data - The onboarding data.
|
|
614
|
+
*/
|
|
615
|
+
async function sendOnboardingEmail(data: Partial<OnboardingData> | undefined) {
|
|
616
|
+
console.log("\n" + "=".repeat(60));
|
|
617
|
+
console.log("🚀 Sending Onboarding Email...");
|
|
618
|
+
console.log("=".repeat(60));
|
|
619
|
+
console.log("Onboarding Details:", JSON.stringify(data, null, 2));
|
|
620
|
+
console.log(` - Sending welcome email to ${data?.email}.`);
|
|
621
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
622
|
+
console.log("✨ Email sent!");
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
/**
|
|
626
|
+
* Mock function to log a contact form submission.
|
|
627
|
+
* @param data - The contact form data.
|
|
628
|
+
*/
|
|
629
|
+
async function logContactForm(data: Partial<ContactFormData> | undefined) {
|
|
630
|
+
console.log("\n" + "=".repeat(60));
|
|
631
|
+
console.log("📝 Logging Contact Form Submission...");
|
|
632
|
+
console.log("=".repeat(60));
|
|
633
|
+
console.log("Submission Details:", JSON.stringify(data, null, 2));
|
|
634
|
+
console.log(` - Logging message from ${data?.name}.`);
|
|
635
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
636
|
+
console.log("✨ Submission logged!");
|
|
637
|
+
}
|
|
638
|
+
|
|
565
639
|
// Run the example
|
|
566
640
|
if (require.main === module) {
|
|
567
641
|
example().catch(console.error);
|