@falai/agent 0.6.3 → 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 -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 +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
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
import {
|
|
14
14
|
Agent,
|
|
15
15
|
defineTool,
|
|
16
|
-
|
|
16
|
+
END_STATE,
|
|
17
17
|
EventSource,
|
|
18
18
|
createMessageEvent,
|
|
19
19
|
OpenAIProvider,
|
|
@@ -563,7 +563,7 @@ async function createBusinessOnboardingAgent(
|
|
|
563
563
|
condition: "User confirmed everything is okay",
|
|
564
564
|
});
|
|
565
565
|
|
|
566
|
-
completion.transitionTo({ state:
|
|
566
|
+
completion.transitionTo({ state: END_STATE });
|
|
567
567
|
|
|
568
568
|
// ==================== Alternative: Sequential Steps ====================
|
|
569
569
|
// For simpler linear flows, you can use the new sequential steps approach:
|
|
@@ -619,7 +619,7 @@ async function createBusinessOnboardingAgent(
|
|
|
619
619
|
chatState: "Thank you for your feedback! It helps us improve. 🙏",
|
|
620
620
|
condition: "User provided feedback",
|
|
621
621
|
})
|
|
622
|
-
.transitionTo({ state:
|
|
622
|
+
.transitionTo({ state: END_STATE });
|
|
623
623
|
|
|
624
624
|
// ==================== Global Guidelines ====================
|
|
625
625
|
|
|
@@ -722,15 +722,31 @@ async function main() {
|
|
|
722
722
|
try {
|
|
723
723
|
// Initialize session state for multi-turn conversation
|
|
724
724
|
let session = createSession<OnboardingData>();
|
|
725
|
+
agent.setCurrentSession(session);
|
|
725
726
|
|
|
726
|
-
const response = await agent.respond({ history
|
|
727
|
+
const response = await agent.respond({ history });
|
|
727
728
|
console.log("Agent:", response.message);
|
|
728
729
|
console.log("\nRoute:", response.session?.currentRoute?.title);
|
|
729
|
-
|
|
730
|
+
|
|
731
|
+
// After the conversation, you can get the extracted data
|
|
732
|
+
const extractedData = agent.getExtractedData<OnboardingData>();
|
|
733
|
+
console.log("Extracted:", extractedData);
|
|
730
734
|
|
|
731
735
|
// Update session with progress
|
|
732
736
|
session = response.session!;
|
|
733
737
|
|
|
738
|
+
// You can also pass the session to the agent constructor
|
|
739
|
+
// const agentWithSession = await createBusinessOnboardingAgent("user_123", "Alice", "session_456", {}, session);
|
|
740
|
+
// const response2 = await agentWithSession.respond({ history });
|
|
741
|
+
|
|
742
|
+
if (response.isRouteComplete) {
|
|
743
|
+
console.log("\n✅ Onboarding route complete!");
|
|
744
|
+
// Here you would typically save the complete data to your database
|
|
745
|
+
await processOnboardingData(agent.getExtractedData());
|
|
746
|
+
} else {
|
|
747
|
+
console.log("\n⏳ Onboarding route in progress...");
|
|
748
|
+
}
|
|
749
|
+
|
|
734
750
|
console.log("\n✅ Session state benefits:");
|
|
735
751
|
console.log(" - Data extraction tracked across turns");
|
|
736
752
|
console.log(" - State progression managed automatically");
|
|
@@ -741,6 +757,31 @@ async function main() {
|
|
|
741
757
|
}
|
|
742
758
|
}
|
|
743
759
|
|
|
760
|
+
/**
|
|
761
|
+
* Mock function to process completed onboarding data
|
|
762
|
+
* @param data - The complete onboarding data
|
|
763
|
+
*/
|
|
764
|
+
async function processOnboardingData(data: Partial<OnboardingData>) {
|
|
765
|
+
console.log("\n" + "=".repeat(60));
|
|
766
|
+
console.log("🚀 Processing Completed Onboarding Data...");
|
|
767
|
+
console.log("=".repeat(60));
|
|
768
|
+
console.log("Received data:", JSON.stringify(data, null, 2));
|
|
769
|
+
|
|
770
|
+
// Example: Save to a database
|
|
771
|
+
console.log("\n💾 Saving to database...");
|
|
772
|
+
await new Promise((resolve) => setTimeout(resolve, 1000)); // Simulate async operation
|
|
773
|
+
console.log(" - Business Info:", data.business?.businessName);
|
|
774
|
+
console.log(" - Contact Info:", data.contact?.website);
|
|
775
|
+
console.log(" - Location Info:", data.location?.address);
|
|
776
|
+
|
|
777
|
+
// Example: Triggering a welcome email
|
|
778
|
+
console.log("\n📧 Sending welcome email...");
|
|
779
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
780
|
+
console.log(` - Email sent to user associated with the account.`);
|
|
781
|
+
|
|
782
|
+
console.log("\n✨ Onboarding processing complete!");
|
|
783
|
+
}
|
|
784
|
+
|
|
744
785
|
// Run if executed directly
|
|
745
786
|
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
746
787
|
main().catch(console.error);
|
|
@@ -15,6 +15,8 @@ import {
|
|
|
15
15
|
EventSource,
|
|
16
16
|
createMessageEvent,
|
|
17
17
|
EventKind,
|
|
18
|
+
END_STATE,
|
|
19
|
+
OpenAIProvider,
|
|
18
20
|
} from "../src";
|
|
19
21
|
import type { Event } from "../src/types";
|
|
20
22
|
import type { ToolRef } from "../src/types/tool";
|
|
@@ -54,6 +56,12 @@ interface CompanyContext {
|
|
|
54
56
|
}>;
|
|
55
57
|
}
|
|
56
58
|
|
|
59
|
+
interface FeedbackData {
|
|
60
|
+
rating?: number;
|
|
61
|
+
comments?: string;
|
|
62
|
+
contactPermission?: boolean;
|
|
63
|
+
}
|
|
64
|
+
|
|
57
65
|
// ==============================================================================
|
|
58
66
|
// TOOLS: Context Enrichment (PREPARATION Phase)
|
|
59
67
|
// ==============================================================================
|
|
@@ -138,7 +146,10 @@ const agent = new Agent<CompanyContext>({
|
|
|
138
146
|
"I'm here to help you learn about Acme Corp, our products, and policies",
|
|
139
147
|
personality:
|
|
140
148
|
"Friendly, helpful, and knowledgeable. Always professional but approachable.",
|
|
141
|
-
ai:
|
|
149
|
+
ai: new OpenAIProvider({
|
|
150
|
+
apiKey: process.env.OPENAI_API_KEY || "test-key",
|
|
151
|
+
model: "gpt-5o-mini",
|
|
152
|
+
}),
|
|
142
153
|
|
|
143
154
|
// Initialize with company knowledge
|
|
144
155
|
context: {
|
|
@@ -325,6 +336,57 @@ const fallbackRoute = agent.createRoute({
|
|
|
325
336
|
|
|
326
337
|
// Initial state is enough for fallback conversations
|
|
327
338
|
|
|
339
|
+
// Route 7: Collect Feedback (Stateful Example)
|
|
340
|
+
const feedbackRoute = agent.createRoute<FeedbackData>({
|
|
341
|
+
title: "Collect Feedback",
|
|
342
|
+
description: "Collect user feedback about their experience",
|
|
343
|
+
conditions: ["User wants to leave feedback", "User seems satisfied or upset"],
|
|
344
|
+
extractionSchema: {
|
|
345
|
+
type: "object",
|
|
346
|
+
properties: {
|
|
347
|
+
rating: {
|
|
348
|
+
type: "number",
|
|
349
|
+
description: "A rating from 1 to 5",
|
|
350
|
+
minimum: 1,
|
|
351
|
+
maximum: 5,
|
|
352
|
+
},
|
|
353
|
+
comments: { type: "string", description: "Open-ended feedback" },
|
|
354
|
+
contactPermission: {
|
|
355
|
+
type: "boolean",
|
|
356
|
+
description: "Permission to contact the user for more details",
|
|
357
|
+
},
|
|
358
|
+
},
|
|
359
|
+
required: ["rating", "comments"],
|
|
360
|
+
},
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
feedbackRoute.initialState
|
|
364
|
+
.transitionTo({
|
|
365
|
+
id: "ask_rating",
|
|
366
|
+
chatState:
|
|
367
|
+
"I'd love to hear your feedback. On a scale of 1 to 5, how would you rate your experience with me today?",
|
|
368
|
+
gather: ["rating"],
|
|
369
|
+
})
|
|
370
|
+
.transitionTo({
|
|
371
|
+
id: "ask_comments",
|
|
372
|
+
chatState:
|
|
373
|
+
"Thanks for the rating! Do you have any specific comments or suggestions?",
|
|
374
|
+
gather: ["comments"],
|
|
375
|
+
requiredData: ["rating"],
|
|
376
|
+
})
|
|
377
|
+
.transitionTo({
|
|
378
|
+
id: "ask_permission",
|
|
379
|
+
chatState:
|
|
380
|
+
"Thank you for the detailed feedback. Would it be okay if our team contacted you for more details?",
|
|
381
|
+
gather: ["contactPermission"],
|
|
382
|
+
requiredData: ["comments"],
|
|
383
|
+
})
|
|
384
|
+
.transitionTo({
|
|
385
|
+
id: "thank_you",
|
|
386
|
+
chatState: "Thank you for your valuable feedback!",
|
|
387
|
+
})
|
|
388
|
+
.transitionTo({ state: END_STATE });
|
|
389
|
+
|
|
328
390
|
// ==============================================================================
|
|
329
391
|
// USAGE EXAMPLES: Three-Phase Pipeline Demonstration
|
|
330
392
|
// ==============================================================================
|
|
@@ -439,6 +501,50 @@ async function exampleConversations() {
|
|
|
439
501
|
console.log("User: How much does it cost?");
|
|
440
502
|
console.log("AI:", resp2.message);
|
|
441
503
|
// AI understands "it" refers to Acme Widget from context
|
|
504
|
+
|
|
505
|
+
// =========================================================================
|
|
506
|
+
// Example 6: Stateful feedback collection
|
|
507
|
+
// =========================================================================
|
|
508
|
+
console.log("\n=== EXAMPLE 6: Stateful Feedback Collection ===");
|
|
509
|
+
const feedbackHistory: Event[] = [
|
|
510
|
+
createMessageEvent(
|
|
511
|
+
EventSource.CUSTOMER,
|
|
512
|
+
"User",
|
|
513
|
+
"This was very helpful, I want to leave some feedback."
|
|
514
|
+
),
|
|
515
|
+
];
|
|
516
|
+
|
|
517
|
+
const feedbackResponse = await agent.respond({
|
|
518
|
+
history: feedbackHistory,
|
|
519
|
+
session,
|
|
520
|
+
});
|
|
521
|
+
console.log("AI:", feedbackResponse.message);
|
|
522
|
+
console.log("Route:", feedbackResponse.session?.currentRoute?.title);
|
|
523
|
+
|
|
524
|
+
if (feedbackResponse.isRouteComplete) {
|
|
525
|
+
console.log("\n✅ Feedback collection complete!");
|
|
526
|
+
await processFeedback(agent.getExtractedData(feedbackResponse.session?.id));
|
|
527
|
+
} else {
|
|
528
|
+
console.log("\n⏳ Feedback collection in progress...");
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
/**
|
|
533
|
+
* Mock function to process collected feedback.
|
|
534
|
+
* @param data The feedback data collected from the user.
|
|
535
|
+
*/
|
|
536
|
+
async function processFeedback(data: Partial<FeedbackData>) {
|
|
537
|
+
console.log("\n" + "=".repeat(60));
|
|
538
|
+
console.log("Processing user feedback...");
|
|
539
|
+
console.log("=".repeat(60));
|
|
540
|
+
console.log("Rating:", data.rating);
|
|
541
|
+
console.log("Comments:", data.comments);
|
|
542
|
+
console.log("Permission to contact:", data.contactPermission);
|
|
543
|
+
|
|
544
|
+
// Here you would typically save this to a database or send it to a support system.
|
|
545
|
+
await new Promise((resolve) => setTimeout(resolve, 500)); // Simulate async operation
|
|
546
|
+
console.log("Feedback logged successfully!");
|
|
547
|
+
console.log("=".repeat(60));
|
|
442
548
|
}
|
|
443
549
|
|
|
444
550
|
// ==============================================================================
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
SessionState,
|
|
20
20
|
MessageEventData,
|
|
21
21
|
Event,
|
|
22
|
+
END_STATE,
|
|
22
23
|
} from "../src/index";
|
|
23
24
|
|
|
24
25
|
/**
|
|
@@ -32,6 +33,7 @@ interface CustomDatabaseSession {
|
|
|
32
33
|
currentState?: string;
|
|
33
34
|
collectedData?: {
|
|
34
35
|
extracted?: Record<string, unknown>;
|
|
36
|
+
extractedByRoute?: Record<string, Partial<unknown>>;
|
|
35
37
|
routeHistory?: unknown[];
|
|
36
38
|
currentRouteTitle?: string;
|
|
37
39
|
currentStateDescription?: string;
|
|
@@ -193,7 +195,13 @@ async function example() {
|
|
|
193
195
|
id: "confirm_details",
|
|
194
196
|
chatState: "Confirm all details",
|
|
195
197
|
requiredData: ["fullName", "email", "companyName"],
|
|
196
|
-
})
|
|
198
|
+
})
|
|
199
|
+
.transitionTo({
|
|
200
|
+
id: "complete_onboarding",
|
|
201
|
+
chatState:
|
|
202
|
+
"Thank you! Your account is set up. You will receive a confirmation email shortly.",
|
|
203
|
+
})
|
|
204
|
+
.transitionTo({ state: END_STATE });
|
|
197
205
|
|
|
198
206
|
/**
|
|
199
207
|
* Create or load session from your custom database
|
|
@@ -234,6 +242,11 @@ async function example() {
|
|
|
234
242
|
: undefined,
|
|
235
243
|
extracted:
|
|
236
244
|
(dbSession.collectedData?.extracted as Partial<OnboardingData>) || {},
|
|
245
|
+
extractedByRoute:
|
|
246
|
+
(dbSession.collectedData?.extractedByRoute as Record<
|
|
247
|
+
string,
|
|
248
|
+
Partial<OnboardingData>
|
|
249
|
+
>) || {},
|
|
237
250
|
routeHistory:
|
|
238
251
|
(dbSession.collectedData
|
|
239
252
|
?.routeHistory as SessionState<OnboardingData>["routeHistory"]) || [],
|
|
@@ -373,6 +386,14 @@ async function example() {
|
|
|
373
386
|
|
|
374
387
|
console.log("💾 Session saved to database");
|
|
375
388
|
|
|
389
|
+
// Check for route completion
|
|
390
|
+
if (response2.isRouteComplete) {
|
|
391
|
+
console.log("\n✅ Onboarding Complete!");
|
|
392
|
+
// In a real app, you would now trigger the next steps,
|
|
393
|
+
// like sending a welcome email, creating an account, etc.
|
|
394
|
+
await processOnboarding(response2.session?.extracted);
|
|
395
|
+
}
|
|
396
|
+
|
|
376
397
|
/**
|
|
377
398
|
* Demonstrate session recovery
|
|
378
399
|
*/
|
|
@@ -404,6 +425,11 @@ async function example() {
|
|
|
404
425
|
extracted:
|
|
405
426
|
(reloadedDbSession.collectedData?.extracted as Partial<OnboardingData>) ||
|
|
406
427
|
{},
|
|
428
|
+
extractedByRoute:
|
|
429
|
+
(reloadedDbSession.collectedData?.extractedByRoute as Record<
|
|
430
|
+
string,
|
|
431
|
+
Partial<OnboardingData>
|
|
432
|
+
>) || {},
|
|
407
433
|
routeHistory:
|
|
408
434
|
(reloadedDbSession.collectedData
|
|
409
435
|
?.routeHistory as SessionState<OnboardingData>["routeHistory"]) || [],
|
|
@@ -429,6 +455,23 @@ async function example() {
|
|
|
429
455
|
console.log("\n✅ Example complete!");
|
|
430
456
|
}
|
|
431
457
|
|
|
458
|
+
/**
|
|
459
|
+
* Mock function to simulate processing the completed onboarding data.
|
|
460
|
+
* @param data - The collected onboarding data.
|
|
461
|
+
*/
|
|
462
|
+
async function processOnboarding(data: Partial<OnboardingData> | undefined) {
|
|
463
|
+
console.log("\n🚀 Processing onboarding data...");
|
|
464
|
+
// Simulate creating a user account
|
|
465
|
+
console.log(
|
|
466
|
+
` - Creating account for ${data?.fullName} at ${data?.companyName}`
|
|
467
|
+
);
|
|
468
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
469
|
+
// Simulate sending a welcome email
|
|
470
|
+
console.log(` - Sending welcome email to ${data?.email}`);
|
|
471
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
472
|
+
console.log("✨ Onboarding processed successfully!");
|
|
473
|
+
}
|
|
474
|
+
|
|
432
475
|
/**
|
|
433
476
|
* Advanced Example: With validation hooks
|
|
434
477
|
*/
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
type Guideline,
|
|
22
22
|
type Capability,
|
|
23
23
|
type RouteOptions,
|
|
24
|
+
END_STATE,
|
|
24
25
|
} from "../src/index";
|
|
25
26
|
|
|
26
27
|
// Context type
|
|
@@ -45,24 +46,22 @@ interface LabData {
|
|
|
45
46
|
}
|
|
46
47
|
|
|
47
48
|
// Define tools with custom IDs (optional - IDs are deterministic by default)
|
|
48
|
-
const getInsuranceProviders = defineTool<HealthcareContext, [], string[]>(
|
|
49
|
-
"get_insurance_providers",
|
|
50
|
-
async () => {
|
|
49
|
+
const getInsuranceProviders = defineTool<HealthcareContext, [], string[]>({
|
|
50
|
+
name: "get_insurance_providers",
|
|
51
|
+
handler: async () => {
|
|
51
52
|
return { data: ["MegaCare Insurance", "HealthFirst", "WellnessPlus"] };
|
|
52
53
|
},
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
);
|
|
54
|
+
id: "healthcare_insurance_providers", // Custom ID for persistence
|
|
55
|
+
description: "Retrieves list of accepted insurance providers",
|
|
56
|
+
});
|
|
58
57
|
|
|
59
58
|
const getAvailableSlots = defineTool<
|
|
60
59
|
HealthcareContext,
|
|
61
60
|
[],
|
|
62
61
|
{ date: string; time: string }[]
|
|
63
|
-
>(
|
|
64
|
-
"get_available_slots",
|
|
65
|
-
async () => {
|
|
62
|
+
>({
|
|
63
|
+
name: "get_available_slots",
|
|
64
|
+
handler: async () => {
|
|
66
65
|
return {
|
|
67
66
|
data: [
|
|
68
67
|
{ date: "2025-10-20", time: "10:00 AM" },
|
|
@@ -71,19 +70,17 @@ const getAvailableSlots = defineTool<
|
|
|
71
70
|
],
|
|
72
71
|
};
|
|
73
72
|
},
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
);
|
|
73
|
+
id: "healthcare_available_slots", // Custom ID
|
|
74
|
+
description: "Gets available appointment slots",
|
|
75
|
+
});
|
|
79
76
|
|
|
80
77
|
const getLabResults = defineTool<
|
|
81
78
|
HealthcareContext,
|
|
82
79
|
[],
|
|
83
80
|
{ report: string; status: string }
|
|
84
|
-
>(
|
|
85
|
-
"get_lab_results",
|
|
86
|
-
async ({ context, extracted }) => {
|
|
81
|
+
>({
|
|
82
|
+
name: "get_lab_results",
|
|
83
|
+
handler: async ({ context, extracted }) => {
|
|
87
84
|
// Tools can now access extracted data
|
|
88
85
|
const labData = extracted as Partial<LabData>;
|
|
89
86
|
if (labData?.testType) {
|
|
@@ -102,19 +99,13 @@ const getLabResults = defineTool<
|
|
|
102
99
|
},
|
|
103
100
|
};
|
|
104
101
|
},
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
109
|
-
);
|
|
102
|
+
id: "healthcare_lab_results", // Custom ID
|
|
103
|
+
description: "Retrieves patient lab results",
|
|
104
|
+
});
|
|
110
105
|
|
|
111
|
-
const scheduleAppointment = defineTool<
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
{ confirmation: string }
|
|
115
|
-
>(
|
|
116
|
-
"schedule_appointment",
|
|
117
|
-
async ({ context, extracted }) => {
|
|
106
|
+
const scheduleAppointment = defineTool<HealthcareContext>({
|
|
107
|
+
name: "schedule_appointment",
|
|
108
|
+
handler: async ({ context, extracted }) => {
|
|
118
109
|
// Tools can access extracted appointment data
|
|
119
110
|
const appointment = extracted as Partial<AppointmentData>;
|
|
120
111
|
if (!appointment?.preferredDate || !appointment?.preferredTime) {
|
|
@@ -127,11 +118,9 @@ const scheduleAppointment = defineTool<
|
|
|
127
118
|
},
|
|
128
119
|
};
|
|
129
120
|
},
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
}
|
|
134
|
-
);
|
|
121
|
+
id: "healthcare_schedule_appointment",
|
|
122
|
+
description: "Schedules patient appointments",
|
|
123
|
+
});
|
|
135
124
|
|
|
136
125
|
// Declarative configuration
|
|
137
126
|
const terms: Term[] = [
|
|
@@ -226,6 +215,36 @@ const routes: RouteOptions[] = [
|
|
|
226
215
|
enabled: true,
|
|
227
216
|
},
|
|
228
217
|
],
|
|
218
|
+
// NEW: Use sequential steps for a linear booking flow
|
|
219
|
+
steps: [
|
|
220
|
+
{
|
|
221
|
+
id: "ask_appointment_type",
|
|
222
|
+
chatState:
|
|
223
|
+
"What type of appointment do you need? (checkup, consultation, or followup)",
|
|
224
|
+
gather: ["appointmentType"],
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
id: "ask_date_time",
|
|
228
|
+
chatState: "When would you like to come in?",
|
|
229
|
+
gather: ["preferredDate", "preferredTime"],
|
|
230
|
+
requiredData: ["appointmentType"],
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
id: "ask_symptoms",
|
|
234
|
+
chatState: "Are you experiencing any symptoms?",
|
|
235
|
+
gather: ["symptoms"],
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
id: "confirm_appointment",
|
|
239
|
+
toolState: scheduleAppointment,
|
|
240
|
+
requiredData: ["preferredDate", "preferredTime"],
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
id: "final_confirmation",
|
|
244
|
+
chatState:
|
|
245
|
+
"Your appointment is confirmed. You will receive a notification shortly.",
|
|
246
|
+
},
|
|
247
|
+
],
|
|
229
248
|
},
|
|
230
249
|
{
|
|
231
250
|
id: "route_check_lab_results", // Custom ID
|
|
@@ -266,7 +285,7 @@ const routes: RouteOptions[] = [
|
|
|
266
285
|
conditions: ["Patient asks general healthcare questions"],
|
|
267
286
|
// No extractionSchema - stateless Q&A
|
|
268
287
|
},
|
|
269
|
-
];
|
|
288
|
+
] as RouteOptions[];
|
|
270
289
|
|
|
271
290
|
// Create the fully configured agent
|
|
272
291
|
const agent = new Agent<HealthcareContext>({
|
|
@@ -342,6 +361,14 @@ async function main() {
|
|
|
342
361
|
|
|
343
362
|
// Session tracks the appointment booking progress
|
|
344
363
|
console.log("Current state:", response2.session?.currentState?.id);
|
|
364
|
+
|
|
365
|
+
// Check for route completion
|
|
366
|
+
if (response2.isRouteComplete && response2.session) {
|
|
367
|
+
console.log("\n✅ Appointment scheduling complete!");
|
|
368
|
+
await sendAppointmentConfirmation(
|
|
369
|
+
agent.getExtractedData(response2.session.id) as AppointmentData
|
|
370
|
+
);
|
|
371
|
+
}
|
|
345
372
|
}
|
|
346
373
|
|
|
347
374
|
// Note: Custom IDs ensure consistency across server restarts
|
|
@@ -352,6 +379,22 @@ async function main() {
|
|
|
352
379
|
// - State recovery for resuming conversations
|
|
353
380
|
}
|
|
354
381
|
|
|
382
|
+
/**
|
|
383
|
+
* Mock function to send an appointment confirmation.
|
|
384
|
+
* @param data - The appointment data.
|
|
385
|
+
*/
|
|
386
|
+
async function sendAppointmentConfirmation(data: AppointmentData) {
|
|
387
|
+
console.log("\n" + "=".repeat(60));
|
|
388
|
+
console.log("🚀 Sending Appointment Confirmation...");
|
|
389
|
+
console.log("=".repeat(60));
|
|
390
|
+
console.log("Appointment Details:", JSON.stringify(data, null, 2));
|
|
391
|
+
console.log(
|
|
392
|
+
` - Sending confirmation to patient for ${data.preferredDate} at ${data.preferredTime}.`
|
|
393
|
+
);
|
|
394
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
395
|
+
console.log("✨ Confirmation sent!");
|
|
396
|
+
}
|
|
397
|
+
|
|
355
398
|
// Uncomment to run:
|
|
356
399
|
// main().catch(console.error);
|
|
357
400
|
|
|
@@ -17,6 +17,8 @@ import {
|
|
|
17
17
|
createMessageEvent,
|
|
18
18
|
EventSource,
|
|
19
19
|
createSession,
|
|
20
|
+
END_STATE,
|
|
21
|
+
defineTool,
|
|
20
22
|
} from "../src/index";
|
|
21
23
|
import { OpenRouterProvider } from "../src/providers";
|
|
22
24
|
|
|
@@ -102,11 +104,55 @@ agent.createRoute({
|
|
|
102
104
|
domains: ["scraping"], // ✅ Only scraping tools available
|
|
103
105
|
});
|
|
104
106
|
|
|
105
|
-
|
|
107
|
+
const scheduleEventTool = defineTool({
|
|
108
|
+
id: "scheduleEvent",
|
|
109
|
+
name: "scheduleEvent",
|
|
110
|
+
description: "Schedules an event in the calendar",
|
|
111
|
+
handler: async ({ extracted }) => {
|
|
112
|
+
const { title, date, description } = extracted as {
|
|
113
|
+
title: string;
|
|
114
|
+
date: string;
|
|
115
|
+
description: string;
|
|
116
|
+
};
|
|
117
|
+
console.log(`[Calendar] Scheduling event: ${title} on ${date}`);
|
|
118
|
+
return { data: { eventId: "evt_123", success: true } };
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
agent.createRoute<{ title: string; date: string; description: string }>({
|
|
106
123
|
title: "Schedule Meeting",
|
|
107
124
|
description: "Book and manage appointments",
|
|
108
125
|
conditions: ["User wants to schedule, view, or cancel events"],
|
|
109
126
|
domains: ["calendar"], // ✅ Only calendar tools available
|
|
127
|
+
extractionSchema: {
|
|
128
|
+
type: "object",
|
|
129
|
+
properties: {
|
|
130
|
+
title: { type: "string" },
|
|
131
|
+
date: { type: "string" },
|
|
132
|
+
description: { type: "string" },
|
|
133
|
+
},
|
|
134
|
+
required: ["title", "date"],
|
|
135
|
+
},
|
|
136
|
+
steps: [
|
|
137
|
+
{
|
|
138
|
+
chatState: "What is the title of the meeting?",
|
|
139
|
+
gather: ["title"],
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
chatState: "When would you like to schedule it?",
|
|
143
|
+
gather: ["date"],
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
chatState: "Any description for the meeting?",
|
|
147
|
+
gather: ["description"],
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
toolState: scheduleEventTool,
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
chatState: "The meeting has been scheduled.",
|
|
154
|
+
},
|
|
155
|
+
],
|
|
110
156
|
});
|
|
111
157
|
|
|
112
158
|
agent.createRoute({
|
|
@@ -137,11 +183,11 @@ async function demonstrateScoping() {
|
|
|
137
183
|
// Example 1: Data Collection route - only scraping tools available
|
|
138
184
|
console.log("1️⃣ Example: User wants to scrape data");
|
|
139
185
|
const history1 = [
|
|
140
|
-
createMessageEvent(
|
|
141
|
-
EventSource.CUSTOMER,
|
|
142
|
-
"Alice",
|
|
143
|
-
"Can you scrape the homepage of example.com?"
|
|
144
|
-
),
|
|
186
|
+
createMessageEvent({
|
|
187
|
+
source: EventSource.CUSTOMER,
|
|
188
|
+
participantName: "Alice",
|
|
189
|
+
message: "Can you scrape the homepage of example.com?",
|
|
190
|
+
}),
|
|
145
191
|
];
|
|
146
192
|
|
|
147
193
|
// Initialize session state for multi-turn conversation
|
|
@@ -158,11 +204,11 @@ async function demonstrateScoping() {
|
|
|
158
204
|
// Example 2: Schedule Meeting route - only calendar tools available
|
|
159
205
|
console.log("2️⃣ Example: User wants to schedule a meeting");
|
|
160
206
|
const history2 = [
|
|
161
|
-
createMessageEvent(
|
|
162
|
-
EventSource.CUSTOMER,
|
|
163
|
-
"Bob",
|
|
164
|
-
"Schedule a meeting for tomorrow at 2pm"
|
|
165
|
-
),
|
|
207
|
+
createMessageEvent({
|
|
208
|
+
source: EventSource.CUSTOMER,
|
|
209
|
+
participantName: "Bob",
|
|
210
|
+
message: "Schedule a meeting for tomorrow at 2pm",
|
|
211
|
+
}),
|
|
166
212
|
];
|
|
167
213
|
|
|
168
214
|
const response2 = await agent.respond({ history: history2, session });
|
|
@@ -170,17 +216,27 @@ async function demonstrateScoping() {
|
|
|
170
216
|
console.log(`Available tools in this route: calendar only`);
|
|
171
217
|
console.log(`Response: ${response2.message}\n`);
|
|
172
218
|
|
|
219
|
+
if (response2.isRouteComplete) {
|
|
220
|
+
console.log("\n✅ Meeting scheduling complete!");
|
|
221
|
+
await sendMeetingInvite(
|
|
222
|
+
agent.getExtractedData(response2.session?.id) as {
|
|
223
|
+
title: string;
|
|
224
|
+
date: string;
|
|
225
|
+
}
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
|
|
173
229
|
// Update session again
|
|
174
230
|
session = response2.session!;
|
|
175
231
|
|
|
176
232
|
// Example 3: Customer Support route - NO tools available
|
|
177
233
|
console.log("3️⃣ Example: User has a general question");
|
|
178
234
|
const history3 = [
|
|
179
|
-
createMessageEvent(
|
|
180
|
-
EventSource.CUSTOMER,
|
|
181
|
-
"Charlie",
|
|
182
|
-
"What are your business hours?"
|
|
183
|
-
),
|
|
235
|
+
createMessageEvent({
|
|
236
|
+
source: EventSource.CUSTOMER,
|
|
237
|
+
participantName: "Charlie",
|
|
238
|
+
message: "What are your business hours?",
|
|
239
|
+
}),
|
|
184
240
|
];
|
|
185
241
|
|
|
186
242
|
const response3 = await agent.respond({ history: history3, session });
|
|
@@ -194,11 +250,11 @@ async function demonstrateScoping() {
|
|
|
194
250
|
// Example 4: Admin Support route - ALL tools available (for demo purposes)
|
|
195
251
|
console.log("4️⃣ Example: Admin needs full access");
|
|
196
252
|
const history4 = [
|
|
197
|
-
createMessageEvent(
|
|
198
|
-
EventSource.CUSTOMER,
|
|
199
|
-
"Admin",
|
|
200
|
-
"I need to generate a report and process a refund"
|
|
201
|
-
),
|
|
253
|
+
createMessageEvent({
|
|
254
|
+
source: EventSource.CUSTOMER,
|
|
255
|
+
participantName: "Admin",
|
|
256
|
+
message: "I need to generate a report and process a refund",
|
|
257
|
+
}),
|
|
202
258
|
];
|
|
203
259
|
|
|
204
260
|
const response4 = await agent.respond({ history: history4, session });
|
|
@@ -288,6 +344,20 @@ console.log(
|
|
|
288
344
|
)}`
|
|
289
345
|
);
|
|
290
346
|
|
|
347
|
+
/**
|
|
348
|
+
* Mock function to send a meeting invite.
|
|
349
|
+
* @param data - The meeting data.
|
|
350
|
+
*/
|
|
351
|
+
async function sendMeetingInvite(data: { title: string; date: string }) {
|
|
352
|
+
console.log("\n" + "=".repeat(60));
|
|
353
|
+
console.log("🚀 Sending Meeting Invite...");
|
|
354
|
+
console.log("=".repeat(60));
|
|
355
|
+
console.log("Meeting Details:", JSON.stringify(data, null, 2));
|
|
356
|
+
console.log(` - Sending invite for "${data.title}" on ${data.date}.`);
|
|
357
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
358
|
+
console.log("✨ Invite sent!");
|
|
359
|
+
}
|
|
360
|
+
|
|
291
361
|
// Run demonstration
|
|
292
362
|
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
293
363
|
demonstrateScoping().catch(console.error);
|