@falai/agent 0.4.0 → 0.5.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 +21 -74
- package/dist/cjs/core/Agent.d.ts +22 -29
- package/dist/cjs/core/Agent.d.ts.map +1 -1
- package/dist/cjs/core/Agent.js +465 -275
- package/dist/cjs/core/Agent.js.map +1 -1
- package/dist/cjs/core/Events.d.ts +10 -1
- package/dist/cjs/core/Events.d.ts.map +1 -1
- package/dist/cjs/core/Events.js +3 -2
- package/dist/cjs/core/Events.js.map +1 -1
- package/dist/cjs/core/PersistenceManager.d.ts +19 -0
- package/dist/cjs/core/PersistenceManager.d.ts.map +1 -1
- package/dist/cjs/core/PersistenceManager.js +57 -0
- package/dist/cjs/core/PersistenceManager.js.map +1 -1
- package/dist/cjs/core/PromptComposer.d.ts +24 -0
- package/dist/cjs/core/PromptComposer.d.ts.map +1 -0
- package/dist/cjs/core/PromptComposer.js +127 -0
- package/dist/cjs/core/PromptComposer.js.map +1 -0
- package/dist/cjs/core/ResponseEngine.d.ts +19 -0
- package/dist/cjs/core/ResponseEngine.d.ts.map +1 -0
- package/dist/cjs/core/ResponseEngine.js +51 -0
- package/dist/cjs/core/ResponseEngine.js.map +1 -0
- package/dist/cjs/core/Route.d.ts +18 -12
- package/dist/cjs/core/Route.d.ts.map +1 -1
- package/dist/cjs/core/Route.js +15 -9
- package/dist/cjs/core/Route.js.map +1 -1
- package/dist/cjs/core/RoutingEngine.d.ts +38 -0
- package/dist/cjs/core/RoutingEngine.d.ts.map +1 -0
- package/dist/cjs/core/RoutingEngine.js +110 -0
- package/dist/cjs/core/RoutingEngine.js.map +1 -0
- package/dist/cjs/core/State.d.ts +15 -4
- package/dist/cjs/core/State.d.ts.map +1 -1
- package/dist/cjs/core/State.js +21 -2
- package/dist/cjs/core/State.js.map +1 -1
- package/dist/cjs/core/ToolExecutor.d.ts +29 -0
- package/dist/cjs/core/ToolExecutor.d.ts.map +1 -0
- package/dist/cjs/core/ToolExecutor.js +73 -0
- package/dist/cjs/core/ToolExecutor.js.map +1 -0
- package/dist/cjs/core/Transition.d.ts +5 -5
- package/dist/cjs/core/Transition.d.ts.map +1 -1
- package/dist/cjs/core/Transition.js.map +1 -1
- package/dist/cjs/index.d.ts +6 -8
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +8 -10
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/providers/AnthropicProvider.d.ts.map +1 -1
- package/dist/cjs/providers/AnthropicProvider.js +10 -13
- package/dist/cjs/providers/AnthropicProvider.js.map +1 -1
- package/dist/cjs/providers/GeminiProvider.d.ts.map +1 -1
- package/dist/cjs/providers/GeminiProvider.js +12 -8
- package/dist/cjs/providers/GeminiProvider.js.map +1 -1
- package/dist/cjs/providers/OpenAIProvider.d.ts.map +1 -1
- package/dist/cjs/providers/OpenAIProvider.js +10 -53
- package/dist/cjs/providers/OpenAIProvider.js.map +1 -1
- package/dist/cjs/providers/OpenRouterProvider.d.ts.map +1 -1
- package/dist/cjs/providers/OpenRouterProvider.js +10 -53
- package/dist/cjs/providers/OpenRouterProvider.js.map +1 -1
- package/dist/cjs/types/agent.d.ts +13 -9
- package/dist/cjs/types/agent.d.ts.map +1 -1
- package/dist/cjs/types/ai.d.ts +8 -2
- package/dist/cjs/types/ai.d.ts.map +1 -1
- package/dist/cjs/types/history.d.ts +8 -0
- package/dist/cjs/types/history.d.ts.map +1 -1
- package/dist/cjs/types/index.d.ts +0 -3
- package/dist/cjs/types/index.d.ts.map +1 -1
- package/dist/cjs/types/index.js +1 -3
- package/dist/cjs/types/index.js.map +1 -1
- package/dist/cjs/types/route.d.ts +39 -4
- package/dist/cjs/types/route.d.ts.map +1 -1
- package/dist/cjs/types/routing.d.ts +16 -0
- package/dist/cjs/types/routing.d.ts.map +1 -0
- package/dist/cjs/types/routing.js +3 -0
- package/dist/cjs/types/routing.js.map +1 -0
- package/dist/cjs/types/schema.d.ts +22 -0
- package/dist/cjs/types/schema.d.ts.map +1 -0
- package/dist/cjs/types/schema.js +3 -0
- package/dist/cjs/types/schema.js.map +1 -0
- package/dist/cjs/types/session.d.ts +72 -0
- package/dist/cjs/types/session.d.ts.map +1 -0
- package/dist/cjs/types/session.js +140 -0
- package/dist/cjs/types/session.js.map +1 -0
- package/dist/cjs/types/tool.d.ts +11 -5
- package/dist/cjs/types/tool.d.ts.map +1 -1
- package/dist/cjs/utils/id.d.ts +0 -5
- package/dist/cjs/utils/id.d.ts.map +1 -1
- package/dist/cjs/utils/id.js +0 -10
- package/dist/cjs/utils/id.js.map +1 -1
- package/dist/cjs/utils/schema.d.ts +17 -0
- package/dist/cjs/utils/schema.d.ts.map +1 -0
- package/dist/cjs/utils/schema.js +32 -0
- package/dist/cjs/utils/schema.js.map +1 -0
- package/dist/core/Agent.d.ts +22 -29
- package/dist/core/Agent.d.ts.map +1 -1
- package/dist/core/Agent.js +465 -275
- package/dist/core/Agent.js.map +1 -1
- package/dist/core/Events.d.ts +10 -1
- package/dist/core/Events.d.ts.map +1 -1
- package/dist/core/Events.js +3 -2
- package/dist/core/Events.js.map +1 -1
- package/dist/core/PersistenceManager.d.ts +19 -0
- package/dist/core/PersistenceManager.d.ts.map +1 -1
- package/dist/core/PersistenceManager.js +57 -0
- package/dist/core/PersistenceManager.js.map +1 -1
- package/dist/core/PromptComposer.d.ts +24 -0
- package/dist/core/PromptComposer.d.ts.map +1 -0
- package/dist/core/PromptComposer.js +123 -0
- package/dist/core/PromptComposer.js.map +1 -0
- package/dist/core/ResponseEngine.d.ts +19 -0
- package/dist/core/ResponseEngine.d.ts.map +1 -0
- package/dist/core/ResponseEngine.js +47 -0
- package/dist/core/ResponseEngine.js.map +1 -0
- package/dist/core/Route.d.ts +18 -12
- package/dist/core/Route.d.ts.map +1 -1
- package/dist/core/Route.js +15 -9
- package/dist/core/Route.js.map +1 -1
- package/dist/core/RoutingEngine.d.ts +38 -0
- package/dist/core/RoutingEngine.d.ts.map +1 -0
- package/dist/core/RoutingEngine.js +106 -0
- package/dist/core/RoutingEngine.js.map +1 -0
- package/dist/core/State.d.ts +15 -4
- package/dist/core/State.d.ts.map +1 -1
- package/dist/core/State.js +21 -2
- package/dist/core/State.js.map +1 -1
- package/dist/core/ToolExecutor.d.ts +29 -0
- package/dist/core/ToolExecutor.d.ts.map +1 -0
- package/dist/core/ToolExecutor.js +69 -0
- package/dist/core/ToolExecutor.js.map +1 -0
- package/dist/core/Transition.d.ts +5 -5
- package/dist/core/Transition.d.ts.map +1 -1
- package/dist/core/Transition.js.map +1 -1
- package/dist/index.d.ts +6 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -5
- package/dist/index.js.map +1 -1
- package/dist/providers/AnthropicProvider.d.ts.map +1 -1
- package/dist/providers/AnthropicProvider.js +10 -13
- package/dist/providers/AnthropicProvider.js.map +1 -1
- package/dist/providers/GeminiProvider.d.ts.map +1 -1
- package/dist/providers/GeminiProvider.js +12 -8
- package/dist/providers/GeminiProvider.js.map +1 -1
- package/dist/providers/OpenAIProvider.d.ts.map +1 -1
- package/dist/providers/OpenAIProvider.js +10 -53
- package/dist/providers/OpenAIProvider.js.map +1 -1
- package/dist/providers/OpenRouterProvider.d.ts.map +1 -1
- package/dist/providers/OpenRouterProvider.js +10 -53
- package/dist/providers/OpenRouterProvider.js.map +1 -1
- package/dist/types/agent.d.ts +13 -9
- package/dist/types/agent.d.ts.map +1 -1
- package/dist/types/ai.d.ts +8 -2
- package/dist/types/ai.d.ts.map +1 -1
- package/dist/types/history.d.ts +8 -0
- package/dist/types/history.d.ts.map +1 -1
- package/dist/types/index.d.ts +0 -3
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +0 -1
- package/dist/types/index.js.map +1 -1
- package/dist/types/route.d.ts +39 -4
- package/dist/types/route.d.ts.map +1 -1
- package/dist/types/routing.d.ts +16 -0
- package/dist/types/routing.d.ts.map +1 -0
- package/dist/types/routing.js +2 -0
- package/dist/types/routing.js.map +1 -0
- package/dist/types/schema.d.ts +22 -0
- package/dist/types/schema.d.ts.map +1 -0
- package/dist/types/schema.js +2 -0
- package/dist/types/schema.js.map +1 -0
- package/dist/types/session.d.ts +72 -0
- package/dist/types/session.d.ts.map +1 -0
- package/dist/types/session.js +132 -0
- package/dist/types/session.js.map +1 -0
- package/dist/types/tool.d.ts +11 -5
- package/dist/types/tool.d.ts.map +1 -1
- package/dist/utils/id.d.ts +0 -5
- package/dist/utils/id.d.ts.map +1 -1
- package/dist/utils/id.js +0 -9
- package/dist/utils/id.js.map +1 -1
- package/dist/utils/schema.d.ts +17 -0
- package/dist/utils/schema.d.ts.map +1 -0
- package/dist/utils/schema.js +27 -0
- package/dist/utils/schema.js.map +1 -0
- package/docs/ADAPTERS.md +83 -3
- package/docs/API_REFERENCE.md +95 -104
- package/docs/ARCHITECTURE.md +284 -286
- package/docs/CONSTRUCTOR_OPTIONS.md +192 -135
- package/docs/CONTEXT_MANAGEMENT.md +311 -28
- package/docs/CONTRIBUTING.md +1 -1
- package/docs/DOMAINS.md +61 -0
- package/docs/GETTING_STARTED.md +177 -88
- package/docs/PERSISTENCE.md +170 -23
- package/docs/README.md +7 -10
- package/examples/business-onboarding.ts +21 -9
- package/examples/company-qna-agent.ts +508 -0
- package/examples/declarative-agent.ts +143 -26
- package/examples/domain-scoping.ts +31 -10
- package/examples/extracted-data-modification.ts +415 -0
- package/examples/healthcare-agent.ts +194 -90
- package/examples/openai-agent.ts +67 -25
- package/examples/opensearch-persistence.ts +455 -151
- package/examples/persistent-onboarding.ts +162 -96
- package/examples/prisma-persistence.ts +371 -125
- package/examples/redis-persistence.ts +393 -23
- package/examples/rules-prohibitions.ts +32 -11
- package/examples/streaming-agent.ts +61 -13
- package/examples/travel-agent.ts +266 -133
- package/package.json +1 -1
- package/src/core/Agent.ts +679 -332
- package/src/core/Events.ts +12 -2
- package/src/core/PersistenceManager.ts +83 -0
- package/src/core/PromptComposer.ts +143 -0
- package/src/core/ResponseEngine.ts +82 -0
- package/src/core/Route.ts +32 -17
- package/src/core/RoutingEngine.ts +165 -0
- package/src/core/State.ts +55 -15
- package/src/core/ToolExecutor.ts +117 -0
- package/src/core/Transition.ts +5 -5
- package/src/index.ts +12 -21
- package/src/providers/AnthropicProvider.ts +10 -13
- package/src/providers/GeminiProvider.ts +12 -8
- package/src/providers/OpenAIProvider.ts +10 -56
- package/src/providers/OpenRouterProvider.ts +10 -56
- package/src/types/agent.ts +16 -10
- package/src/types/ai.ts +6 -2
- package/src/types/history.ts +8 -0
- package/src/types/index.ts +0 -11
- package/src/types/route.ts +41 -5
- package/src/types/routing.ts +18 -0
- package/src/types/schema.ts +23 -0
- package/src/types/session.ts +207 -0
- package/src/types/tool.ts +29 -7
- package/src/utils/id.ts +0 -10
- package/src/utils/schema.ts +32 -0
- package/dist/cjs/core/ConditionEvaluator.d.ts +0 -72
- package/dist/cjs/core/ConditionEvaluator.d.ts.map +0 -1
- package/dist/cjs/core/ConditionEvaluator.js +0 -272
- package/dist/cjs/core/ConditionEvaluator.js.map +0 -1
- package/dist/cjs/core/Observation.d.ts +0 -24
- package/dist/cjs/core/Observation.d.ts.map +0 -1
- package/dist/cjs/core/Observation.js +0 -39
- package/dist/cjs/core/Observation.js.map +0 -1
- package/dist/cjs/core/PreparationEngine.d.ts +0 -105
- package/dist/cjs/core/PreparationEngine.d.ts.map +0 -1
- package/dist/cjs/core/PreparationEngine.js +0 -320
- package/dist/cjs/core/PreparationEngine.js.map +0 -1
- package/dist/cjs/core/PromptBuilder.d.ts +0 -136
- package/dist/cjs/core/PromptBuilder.d.ts.map +0 -1
- package/dist/cjs/core/PromptBuilder.js +0 -421
- package/dist/cjs/core/PromptBuilder.js.map +0 -1
- package/dist/cjs/types/observation.d.ts +0 -27
- package/dist/cjs/types/observation.d.ts.map +0 -1
- package/dist/cjs/types/observation.js +0 -6
- package/dist/cjs/types/observation.js.map +0 -1
- package/dist/cjs/types/prompt.d.ts +0 -46
- package/dist/cjs/types/prompt.d.ts.map +0 -1
- package/dist/cjs/types/prompt.js +0 -19
- package/dist/cjs/types/prompt.js.map +0 -1
- package/dist/core/ConditionEvaluator.d.ts +0 -72
- package/dist/core/ConditionEvaluator.d.ts.map +0 -1
- package/dist/core/ConditionEvaluator.js +0 -268
- package/dist/core/ConditionEvaluator.js.map +0 -1
- package/dist/core/Observation.d.ts +0 -24
- package/dist/core/Observation.d.ts.map +0 -1
- package/dist/core/Observation.js +0 -35
- package/dist/core/Observation.js.map +0 -1
- package/dist/core/PreparationEngine.d.ts +0 -105
- package/dist/core/PreparationEngine.d.ts.map +0 -1
- package/dist/core/PreparationEngine.js +0 -316
- package/dist/core/PreparationEngine.js.map +0 -1
- package/dist/core/PromptBuilder.d.ts +0 -136
- package/dist/core/PromptBuilder.d.ts.map +0 -1
- package/dist/core/PromptBuilder.js +0 -417
- package/dist/core/PromptBuilder.js.map +0 -1
- package/dist/types/observation.d.ts +0 -27
- package/dist/types/observation.d.ts.map +0 -1
- package/dist/types/observation.js +0 -5
- package/dist/types/observation.js.map +0 -1
- package/dist/types/prompt.d.ts +0 -46
- package/dist/types/prompt.d.ts.map +0 -1
- package/dist/types/prompt.js +0 -16
- package/dist/types/prompt.js.map +0 -1
- package/docs/STRUCTURE.md +0 -58
- package/src/core/ConditionEvaluator.ts +0 -381
- package/src/core/Observation.ts +0 -47
- package/src/core/PreparationEngine.ts +0 -500
- package/src/core/PromptBuilder.ts +0 -617
- package/src/types/observation.ts +0 -29
- package/src/types/prompt.ts +0 -49
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Example: Using Prisma ORM for Persistence
|
|
2
|
+
* Example: Using Prisma ORM for Persistence with Session State
|
|
3
3
|
*
|
|
4
4
|
* This example shows how to use @falai/agent with Prisma for automatic
|
|
5
|
-
* session
|
|
5
|
+
* session state persistence - with the new data-driven architecture!
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import {
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
PrismaAdapter,
|
|
12
12
|
createMessageEvent,
|
|
13
13
|
EventSource,
|
|
14
|
+
createSession,
|
|
14
15
|
} from "../src/index";
|
|
15
16
|
|
|
16
17
|
// @ts-ignore
|
|
@@ -38,14 +39,24 @@ import { PrismaClient } from "@prisma/client";
|
|
|
38
39
|
// Example context type
|
|
39
40
|
interface ConversationContext {
|
|
40
41
|
userId: string;
|
|
41
|
-
sessionId: string;
|
|
42
42
|
userName: string;
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
currentBooking?: {
|
|
44
|
+
destination?: string;
|
|
45
|
+
departureDate?: string;
|
|
46
|
+
returnDate?: string;
|
|
47
|
+
passengers?: number;
|
|
46
48
|
};
|
|
47
49
|
}
|
|
48
50
|
|
|
51
|
+
// Extracted data type for flight booking
|
|
52
|
+
interface FlightBookingData {
|
|
53
|
+
destination: string;
|
|
54
|
+
departureDate: string;
|
|
55
|
+
returnDate?: string;
|
|
56
|
+
passengers: number;
|
|
57
|
+
cabinClass: "economy" | "premium" | "business" | "first";
|
|
58
|
+
}
|
|
59
|
+
|
|
49
60
|
async function example() {
|
|
50
61
|
// Initialize Prisma client
|
|
51
62
|
const prisma = new PrismaClient();
|
|
@@ -53,32 +64,103 @@ async function example() {
|
|
|
53
64
|
const userId = "user_123";
|
|
54
65
|
|
|
55
66
|
/**
|
|
56
|
-
* Create Agent with Persistence -
|
|
67
|
+
* Create Agent with Persistence - New Session-Based Pattern! ✨
|
|
57
68
|
*/
|
|
58
69
|
const agent = new Agent<ConversationContext>({
|
|
59
|
-
name: "
|
|
60
|
-
description: "A helpful
|
|
70
|
+
name: "Travel Assistant",
|
|
71
|
+
description: "A helpful travel booking assistant",
|
|
72
|
+
goal: "Help users book flights with ease",
|
|
61
73
|
ai: new GeminiProvider({
|
|
62
74
|
apiKey: process.env.GEMINI_API_KEY!,
|
|
63
75
|
model: "models/gemini-2.0-flash-exp",
|
|
64
76
|
}),
|
|
65
77
|
context: {
|
|
66
78
|
userId,
|
|
67
|
-
sessionId: "", // Will be set when we create/load a session
|
|
68
79
|
userName: "Alice",
|
|
69
|
-
preferences: {
|
|
70
|
-
language: "en",
|
|
71
|
-
theme: "light",
|
|
72
|
-
},
|
|
73
80
|
},
|
|
74
81
|
// ✨ Just pass the adapter - that's it!
|
|
75
82
|
persistence: {
|
|
76
83
|
adapter: new PrismaAdapter({ prisma }),
|
|
77
|
-
autoSave: true,
|
|
84
|
+
autoSave: true, // Auto-saves session state after each response
|
|
78
85
|
userId,
|
|
79
86
|
},
|
|
80
87
|
});
|
|
81
88
|
|
|
89
|
+
/**
|
|
90
|
+
* Create a route with data extraction schema
|
|
91
|
+
*/
|
|
92
|
+
const flightRoute = agent.createRoute<FlightBookingData>({
|
|
93
|
+
title: "Book a Flight",
|
|
94
|
+
description: "Help user book a flight ticket",
|
|
95
|
+
conditions: [
|
|
96
|
+
"User wants to book a flight",
|
|
97
|
+
"User mentions travel, flying, or booking tickets",
|
|
98
|
+
],
|
|
99
|
+
gatherSchema: {
|
|
100
|
+
type: "object",
|
|
101
|
+
properties: {
|
|
102
|
+
destination: {
|
|
103
|
+
type: "string",
|
|
104
|
+
description: "Destination city or airport",
|
|
105
|
+
},
|
|
106
|
+
departureDate: {
|
|
107
|
+
type: "string",
|
|
108
|
+
description: "Departure date (YYYY-MM-DD)",
|
|
109
|
+
},
|
|
110
|
+
returnDate: {
|
|
111
|
+
type: "string",
|
|
112
|
+
description: "Return date (YYYY-MM-DD)",
|
|
113
|
+
},
|
|
114
|
+
passengers: {
|
|
115
|
+
type: "number",
|
|
116
|
+
minimum: 1,
|
|
117
|
+
maximum: 9,
|
|
118
|
+
description: "Number of passengers",
|
|
119
|
+
},
|
|
120
|
+
cabinClass: {
|
|
121
|
+
type: "string",
|
|
122
|
+
enum: ["economy", "premium", "business", "first"],
|
|
123
|
+
default: "economy",
|
|
124
|
+
description: "Cabin class preference",
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
required: ["destination", "departureDate", "passengers", "cabinClass"],
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
// State flow with smart data gathering
|
|
132
|
+
const askDestination = flightRoute.initialState.transitionTo({
|
|
133
|
+
chatState: "Ask where they want to fly",
|
|
134
|
+
gather: ["destination"],
|
|
135
|
+
skipIf: (extracted) => !!extracted.destination,
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
const askDates = askDestination.transitionTo({
|
|
139
|
+
chatState: "Ask about travel dates",
|
|
140
|
+
gather: ["departureDate", "returnDate"],
|
|
141
|
+
skipIf: (extracted) => !!extracted.departureDate,
|
|
142
|
+
requiredData: ["destination"],
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
const askPassengers = askDates.transitionTo({
|
|
146
|
+
chatState: "Ask how many passengers",
|
|
147
|
+
gather: ["passengers"],
|
|
148
|
+
skipIf: (extracted) => !!extracted.passengers,
|
|
149
|
+
requiredData: ["destination", "departureDate"],
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
const askCabinClass = askPassengers.transitionTo({
|
|
153
|
+
chatState: "Ask about cabin class preference",
|
|
154
|
+
gather: ["cabinClass"],
|
|
155
|
+
skipIf: (extracted) => !!extracted.cabinClass,
|
|
156
|
+
requiredData: ["destination", "departureDate", "passengers"],
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
const confirmBooking = askCabinClass.transitionTo({
|
|
160
|
+
chatState: "Present options and confirm booking details",
|
|
161
|
+
requiredData: ["destination", "departureDate", "passengers", "cabinClass"],
|
|
162
|
+
});
|
|
163
|
+
|
|
82
164
|
/**
|
|
83
165
|
* Get persistence manager from agent
|
|
84
166
|
*/
|
|
@@ -89,83 +171,156 @@ async function example() {
|
|
|
89
171
|
}
|
|
90
172
|
|
|
91
173
|
/**
|
|
92
|
-
* Create or find a session
|
|
174
|
+
* Create or find a session - New Pattern!
|
|
93
175
|
*/
|
|
94
|
-
let
|
|
95
|
-
|
|
96
|
-
if (!session) {
|
|
97
|
-
session = await persistence.createSession({
|
|
176
|
+
let sessionResult =
|
|
177
|
+
await persistence.createSessionWithState<FlightBookingData>({
|
|
98
178
|
userId,
|
|
99
|
-
agentName: "
|
|
179
|
+
agentName: "Travel Assistant",
|
|
100
180
|
initialData: {
|
|
101
|
-
|
|
102
|
-
theme: "light",
|
|
181
|
+
cabinClass: "economy", // Default value
|
|
103
182
|
},
|
|
104
183
|
});
|
|
105
|
-
console.log("✨ Created new session:", session.id);
|
|
106
|
-
} else {
|
|
107
|
-
console.log("📂 Found active session:", session.id);
|
|
108
|
-
}
|
|
109
184
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
185
|
+
let session = sessionResult.sessionState;
|
|
186
|
+
const dbSessionId = sessionResult.sessionData.id;
|
|
187
|
+
|
|
188
|
+
console.log("✨ Created new session:", dbSessionId);
|
|
189
|
+
console.log("📊 Initial session state:", {
|
|
190
|
+
currentRoute: session.currentRoute,
|
|
191
|
+
extracted: session.extracted,
|
|
192
|
+
});
|
|
114
193
|
|
|
115
194
|
/**
|
|
116
195
|
* Load conversation history
|
|
117
196
|
*/
|
|
118
|
-
const history = await persistence.loadSessionHistory(
|
|
197
|
+
const history = await persistence.loadSessionHistory(dbSessionId);
|
|
119
198
|
console.log(`📜 Loaded ${history.length} messages from history`);
|
|
120
199
|
|
|
121
200
|
/**
|
|
122
|
-
*
|
|
201
|
+
* Turn 1: User provides multiple fields at once
|
|
123
202
|
*/
|
|
124
|
-
|
|
203
|
+
console.log("\n--- Turn 1 ---");
|
|
204
|
+
const userMessage1 = createMessageEvent(
|
|
125
205
|
EventSource.CUSTOMER,
|
|
126
206
|
"Alice",
|
|
127
|
-
"I
|
|
207
|
+
"I want to fly to Paris on June 15 with 2 people"
|
|
128
208
|
);
|
|
129
209
|
|
|
210
|
+
history.push(userMessage1);
|
|
211
|
+
|
|
212
|
+
const response1 = await agent.respond({
|
|
213
|
+
history,
|
|
214
|
+
session, // Pass session state
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
console.log("🤖 Agent:", response1.message);
|
|
218
|
+
console.log("📊 Session state after turn 1:", {
|
|
219
|
+
currentRoute: response1.session?.currentRoute?.title,
|
|
220
|
+
currentState: response1.session?.currentState?.id,
|
|
221
|
+
extracted: response1.session?.extracted,
|
|
222
|
+
});
|
|
223
|
+
|
|
130
224
|
// Save user message
|
|
131
225
|
await persistence.saveMessage({
|
|
132
|
-
sessionId:
|
|
226
|
+
sessionId: dbSessionId,
|
|
133
227
|
userId,
|
|
134
228
|
role: "user",
|
|
135
|
-
content:
|
|
136
|
-
event:
|
|
229
|
+
content: userMessage1.data.message,
|
|
230
|
+
event: userMessage1,
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
// Save agent message (session state is auto-saved by Agent!)
|
|
234
|
+
await persistence.saveMessage({
|
|
235
|
+
sessionId: dbSessionId,
|
|
236
|
+
userId,
|
|
237
|
+
role: "agent",
|
|
238
|
+
content: response1.message,
|
|
239
|
+
route: response1.session?.currentRoute?.id,
|
|
240
|
+
state: response1.session?.currentState?.id,
|
|
137
241
|
});
|
|
138
242
|
|
|
139
|
-
|
|
243
|
+
// Update session for next turn
|
|
244
|
+
session = response1.session!;
|
|
140
245
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
246
|
+
/**
|
|
247
|
+
* Turn 2: User changes their mind
|
|
248
|
+
*/
|
|
249
|
+
console.log("\n--- Turn 2 ---");
|
|
250
|
+
const userMessage2 = createMessageEvent(
|
|
251
|
+
EventSource.CUSTOMER,
|
|
252
|
+
"Alice",
|
|
253
|
+
"Actually, make that Tokyo instead, and premium class"
|
|
254
|
+
);
|
|
255
|
+
|
|
256
|
+
history.push(
|
|
257
|
+
createMessageEvent(
|
|
258
|
+
EventSource.AI_AGENT,
|
|
259
|
+
"Travel Assistant",
|
|
260
|
+
response1.message
|
|
261
|
+
)
|
|
262
|
+
);
|
|
263
|
+
history.push(userMessage2);
|
|
264
|
+
|
|
265
|
+
const response2 = await agent.respond({
|
|
266
|
+
history,
|
|
267
|
+
session, // Pass updated session
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
console.log("🤖 Agent:", response2.message);
|
|
271
|
+
console.log("📊 Session state after turn 2:", {
|
|
272
|
+
currentRoute: response2.session?.currentRoute?.title,
|
|
273
|
+
currentState: response2.session?.currentState?.id,
|
|
274
|
+
extracted: response2.session?.extracted,
|
|
275
|
+
});
|
|
144
276
|
|
|
145
|
-
// Save
|
|
277
|
+
// Save messages
|
|
146
278
|
await persistence.saveMessage({
|
|
147
|
-
sessionId:
|
|
279
|
+
sessionId: dbSessionId,
|
|
280
|
+
userId,
|
|
281
|
+
role: "user",
|
|
282
|
+
content: userMessage2.data.message,
|
|
283
|
+
event: userMessage2,
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
await persistence.saveMessage({
|
|
287
|
+
sessionId: dbSessionId,
|
|
148
288
|
userId,
|
|
149
289
|
role: "agent",
|
|
150
|
-
content:
|
|
151
|
-
route:
|
|
152
|
-
state:
|
|
153
|
-
|
|
290
|
+
content: response2.message,
|
|
291
|
+
route: response2.session?.currentRoute?.id,
|
|
292
|
+
state: response2.session?.currentState?.id,
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
session = response2.session!;
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Load session state from database (demonstrates persistence)
|
|
299
|
+
*/
|
|
300
|
+
console.log("\n--- Loading Session from Database ---");
|
|
301
|
+
const loadedSession = await persistence.loadSessionState<FlightBookingData>(
|
|
302
|
+
dbSessionId
|
|
303
|
+
);
|
|
304
|
+
|
|
305
|
+
console.log("📥 Loaded session state:", {
|
|
306
|
+
currentRoute: loadedSession?.currentRoute?.title,
|
|
307
|
+
currentState: loadedSession?.currentState?.id,
|
|
308
|
+
extracted: loadedSession?.extracted,
|
|
154
309
|
});
|
|
155
310
|
|
|
156
311
|
/**
|
|
157
312
|
* Query sessions and messages
|
|
158
313
|
*/
|
|
159
314
|
const userSessions = await persistence.getUserSessions(userId);
|
|
160
|
-
console.log(
|
|
315
|
+
console.log(`\n👤 User has ${userSessions.length} total sessions`);
|
|
161
316
|
|
|
162
|
-
const messages = await persistence.getSessionMessages(
|
|
317
|
+
const messages = await persistence.getSessionMessages(dbSessionId);
|
|
163
318
|
console.log(`💬 Session has ${messages.length} messages`);
|
|
164
319
|
|
|
165
320
|
/**
|
|
166
321
|
* Complete the session
|
|
167
322
|
*/
|
|
168
|
-
await persistence.completeSession(
|
|
323
|
+
await persistence.completeSession(dbSessionId);
|
|
169
324
|
console.log("✅ Session completed");
|
|
170
325
|
|
|
171
326
|
/**
|
|
@@ -175,59 +330,67 @@ async function example() {
|
|
|
175
330
|
}
|
|
176
331
|
|
|
177
332
|
/**
|
|
178
|
-
* Advanced Example:
|
|
333
|
+
* Advanced Example: Session State with Lifecycle Hooks
|
|
179
334
|
*/
|
|
180
335
|
async function advancedExample() {
|
|
181
336
|
const prisma = new PrismaClient();
|
|
182
|
-
const userId = "
|
|
337
|
+
const userId = "user_456";
|
|
183
338
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
339
|
+
interface UserContext {
|
|
340
|
+
userId: string;
|
|
341
|
+
userName: string;
|
|
342
|
+
preferences: {
|
|
343
|
+
currency: string;
|
|
344
|
+
language: string;
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
interface OnboardingData {
|
|
349
|
+
fullName: string;
|
|
350
|
+
email: string;
|
|
351
|
+
phoneNumber: string;
|
|
352
|
+
country: string;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
const agent = new Agent<UserContext>({
|
|
356
|
+
name: "Onboarding Assistant",
|
|
357
|
+
description: "Help new users get started",
|
|
187
358
|
ai: new GeminiProvider({
|
|
188
359
|
apiKey: process.env.GEMINI_API_KEY!,
|
|
189
360
|
model: "models/gemini-2.0-flash-exp",
|
|
190
361
|
}),
|
|
191
362
|
context: {
|
|
192
363
|
userId,
|
|
193
|
-
|
|
194
|
-
userName: "Alice",
|
|
364
|
+
userName: "Bob",
|
|
195
365
|
preferences: {
|
|
366
|
+
currency: "USD",
|
|
196
367
|
language: "en",
|
|
197
|
-
theme: "light",
|
|
198
368
|
},
|
|
199
369
|
},
|
|
200
|
-
// Lifecycle hooks for
|
|
370
|
+
// Lifecycle hooks for session state enrichment
|
|
201
371
|
hooks: {
|
|
202
|
-
//
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
)?.preferences || currentContext.preferences,
|
|
218
|
-
};
|
|
372
|
+
// Enrich extracted data before saving
|
|
373
|
+
onExtractedUpdate: async (extracted, previous) => {
|
|
374
|
+
console.log("🔄 Extracted data updated:", { extracted, previous });
|
|
375
|
+
|
|
376
|
+
// Normalize phone numbers
|
|
377
|
+
if (extracted.phoneNumber) {
|
|
378
|
+
extracted.phoneNumber = extracted.phoneNumber.replace(/\D/g, "");
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// Validate email
|
|
382
|
+
if (extracted.email && !extracted.email.includes("@")) {
|
|
383
|
+
console.warn("⚠️ Invalid email detected");
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
return extracted;
|
|
219
387
|
},
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
await persistence.updateCollectedData(newContext.sessionId, {
|
|
226
|
-
preferences: newContext.preferences,
|
|
227
|
-
});
|
|
388
|
+
|
|
389
|
+
// Update context when session state changes
|
|
390
|
+
onContextUpdate: async (newContext, oldContext) => {
|
|
391
|
+
console.log("🔄 Context updated:", { newContext, oldContext });
|
|
228
392
|
},
|
|
229
393
|
},
|
|
230
|
-
// ✨ Same simple adapter pattern!
|
|
231
394
|
persistence: {
|
|
232
395
|
adapter: new PrismaAdapter({ prisma }),
|
|
233
396
|
autoSave: true,
|
|
@@ -235,26 +398,79 @@ async function advancedExample() {
|
|
|
235
398
|
},
|
|
236
399
|
});
|
|
237
400
|
|
|
238
|
-
// Create
|
|
239
|
-
const
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
401
|
+
// Create onboarding route
|
|
402
|
+
const onboardingRoute = agent.createRoute<OnboardingData>({
|
|
403
|
+
title: "User Onboarding",
|
|
404
|
+
description: "Collect user information for account setup",
|
|
405
|
+
gatherSchema: {
|
|
406
|
+
type: "object",
|
|
407
|
+
properties: {
|
|
408
|
+
fullName: { type: "string" },
|
|
409
|
+
email: { type: "string" },
|
|
410
|
+
phoneNumber: { type: "string" },
|
|
411
|
+
country: { type: "string" },
|
|
412
|
+
},
|
|
413
|
+
required: ["fullName", "email", "country"],
|
|
414
|
+
},
|
|
243
415
|
});
|
|
244
416
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
417
|
+
onboardingRoute.initialState
|
|
418
|
+
.transitionTo({
|
|
419
|
+
chatState: "Welcome and ask for name",
|
|
420
|
+
gather: ["fullName"],
|
|
421
|
+
skipIf: (data) => !!data.fullName,
|
|
422
|
+
})
|
|
423
|
+
.transitionTo({
|
|
424
|
+
chatState: "Ask for email",
|
|
425
|
+
gather: ["email"],
|
|
426
|
+
skipIf: (data) => !!data.email,
|
|
427
|
+
})
|
|
428
|
+
.transitionTo({
|
|
429
|
+
chatState: "Ask for phone number (optional)",
|
|
430
|
+
gather: ["phoneNumber"],
|
|
431
|
+
})
|
|
432
|
+
.transitionTo({
|
|
433
|
+
chatState: "Ask for country",
|
|
434
|
+
gather: ["country"],
|
|
435
|
+
skipIf: (data) => !!data.country,
|
|
436
|
+
})
|
|
437
|
+
.transitionTo({
|
|
438
|
+
chatState: "Confirm and complete onboarding",
|
|
439
|
+
});
|
|
248
440
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
441
|
+
const persistence = agent.getPersistenceManager()!;
|
|
442
|
+
|
|
443
|
+
// Create session with state
|
|
444
|
+
const { sessionData, sessionState } =
|
|
445
|
+
await persistence.createSessionWithState<OnboardingData>({
|
|
446
|
+
userId,
|
|
447
|
+
agentName: "Onboarding Assistant",
|
|
448
|
+
});
|
|
256
449
|
|
|
257
|
-
console.log("
|
|
450
|
+
console.log("✨ Created onboarding session:", sessionData.id);
|
|
451
|
+
|
|
452
|
+
// Simulate conversation
|
|
453
|
+
const history = [];
|
|
454
|
+
let session = sessionState;
|
|
455
|
+
|
|
456
|
+
const response = await agent.respond({
|
|
457
|
+
history: [
|
|
458
|
+
createMessageEvent(EventSource.CUSTOMER, "Bob", "Hi, I'm new here!"),
|
|
459
|
+
],
|
|
460
|
+
session,
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
console.log("🤖 Agent:", response.message);
|
|
464
|
+
console.log("📊 Extracted so far:", response.session?.extracted);
|
|
465
|
+
|
|
466
|
+
await persistence.saveMessage({
|
|
467
|
+
sessionId: sessionData.id,
|
|
468
|
+
userId,
|
|
469
|
+
role: "agent",
|
|
470
|
+
content: response.message,
|
|
471
|
+
});
|
|
472
|
+
|
|
473
|
+
console.log("✅ Session state automatically saved to database!");
|
|
258
474
|
|
|
259
475
|
await prisma.$disconnect();
|
|
260
476
|
}
|
|
@@ -265,42 +481,72 @@ async function advancedExample() {
|
|
|
265
481
|
async function quickStart() {
|
|
266
482
|
const prisma = new PrismaClient();
|
|
267
483
|
|
|
268
|
-
|
|
484
|
+
interface ContactFormData {
|
|
485
|
+
name: string;
|
|
486
|
+
email: string;
|
|
487
|
+
message: string;
|
|
488
|
+
}
|
|
489
|
+
|
|
269
490
|
const agent = new Agent({
|
|
270
|
-
name: "
|
|
271
|
-
description: "A helpful assistant",
|
|
491
|
+
name: "Support Agent",
|
|
272
492
|
ai: new GeminiProvider({
|
|
273
493
|
apiKey: process.env.GEMINI_API_KEY!,
|
|
274
|
-
model: "models/gemini-2.
|
|
494
|
+
model: "models/gemini-2.0-flash-exp",
|
|
275
495
|
}),
|
|
276
496
|
persistence: {
|
|
277
|
-
adapter: new PrismaAdapter({ prisma }),
|
|
278
|
-
userId: "
|
|
497
|
+
adapter: new PrismaAdapter({ prisma }),
|
|
498
|
+
userId: "user_789",
|
|
499
|
+
autoSave: true, // ✨ Automatically saves session state!
|
|
279
500
|
},
|
|
280
501
|
});
|
|
281
502
|
|
|
282
|
-
//
|
|
283
|
-
const
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
503
|
+
// Create a simple contact form route
|
|
504
|
+
const contactRoute = agent.createRoute<ContactFormData>({
|
|
505
|
+
title: "Contact Form",
|
|
506
|
+
gatherSchema: {
|
|
507
|
+
type: "object",
|
|
508
|
+
properties: {
|
|
509
|
+
name: { type: "string" },
|
|
510
|
+
email: { type: "string" },
|
|
511
|
+
message: { type: "string" },
|
|
512
|
+
},
|
|
513
|
+
required: ["name", "email", "message"],
|
|
514
|
+
},
|
|
290
515
|
});
|
|
291
516
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
517
|
+
contactRoute.initialState
|
|
518
|
+
.transitionTo({
|
|
519
|
+
chatState: "Collect all information",
|
|
520
|
+
gather: ["name", "email", "message"],
|
|
521
|
+
})
|
|
522
|
+
.transitionTo({
|
|
523
|
+
chatState: "Confirm submission",
|
|
524
|
+
});
|
|
295
525
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
526
|
+
const persistence = agent.getPersistenceManager()!;
|
|
527
|
+
|
|
528
|
+
// Create session with state support
|
|
529
|
+
const { sessionData, sessionState } =
|
|
530
|
+
await persistence.createSessionWithState<ContactFormData>({
|
|
531
|
+
userId: "user_789",
|
|
532
|
+
agentName: "Support Agent",
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
// Chat!
|
|
536
|
+
const response = await agent.respond({
|
|
537
|
+
history: [
|
|
538
|
+
createMessageEvent(
|
|
539
|
+
EventSource.CUSTOMER,
|
|
540
|
+
"User",
|
|
541
|
+
"I need help, my name is John and my email is john@example.com"
|
|
542
|
+
),
|
|
543
|
+
],
|
|
544
|
+
session: sessionState,
|
|
301
545
|
});
|
|
302
546
|
|
|
303
|
-
console.log("✅
|
|
547
|
+
console.log("✅ Response:", response.message);
|
|
548
|
+
console.log("📊 Extracted:", response.session?.extracted);
|
|
549
|
+
console.log("💾 Session state auto-saved to Prisma!");
|
|
304
550
|
|
|
305
551
|
await prisma.$disconnect();
|
|
306
552
|
}
|