@falai/agent 0.4.1 → 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 +464 -291
- 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 -12
- 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 +464 -291
- 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 -12
- 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 +674 -356
- 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 -13
- 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 -116
- package/dist/cjs/core/PreparationEngine.d.ts.map +0 -1
- package/dist/cjs/core/PreparationEngine.js +0 -353
- 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 -116
- package/dist/core/PreparationEngine.d.ts.map +0 -1
- package/dist/core/PreparationEngine.js +0 -349
- 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 -561
- package/src/core/PromptBuilder.ts +0 -617
- package/src/types/observation.ts +0 -29
- package/src/types/prompt.ts +0 -49
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Example: Streaming Responses
|
|
3
|
+
* Updated for v2 architecture with session state management
|
|
3
4
|
*
|
|
4
5
|
* This example demonstrates how to use the respondStream method
|
|
5
6
|
* to stream AI responses in real-time for better user experience
|
|
@@ -12,6 +13,7 @@ import {
|
|
|
12
13
|
AnthropicProvider,
|
|
13
14
|
OpenAIProvider,
|
|
14
15
|
GeminiProvider,
|
|
16
|
+
createSession,
|
|
15
17
|
} from "../src/index";
|
|
16
18
|
|
|
17
19
|
// Custom context type
|
|
@@ -70,9 +72,12 @@ async function streamingWithAnthropic() {
|
|
|
70
72
|
console.log("📤 Streaming response from Claude...\n");
|
|
71
73
|
console.log("Response: ");
|
|
72
74
|
|
|
73
|
-
//
|
|
75
|
+
// Initialize session state for streaming conversation
|
|
76
|
+
let session = createSession();
|
|
77
|
+
|
|
78
|
+
// Use respondStream for real-time streaming with session state
|
|
74
79
|
let fullMessage = "";
|
|
75
|
-
for await (const chunk of agent.respondStream({ history })) {
|
|
80
|
+
for await (const chunk of agent.respondStream({ history, session })) {
|
|
76
81
|
// chunk.delta contains the new text
|
|
77
82
|
// chunk.accumulated contains the full text so far
|
|
78
83
|
// chunk.done indicates if this is the final chunk
|
|
@@ -85,9 +90,14 @@ async function streamingWithAnthropic() {
|
|
|
85
90
|
if (chunk.done) {
|
|
86
91
|
console.log("\n\n✅ Stream complete!");
|
|
87
92
|
console.log(`\n📊 Metadata:`);
|
|
88
|
-
console.log(
|
|
89
|
-
|
|
93
|
+
console.log(
|
|
94
|
+
` - Route: ${chunk.session?.currentRoute?.title || "None"}`
|
|
95
|
+
);
|
|
96
|
+
console.log(` - Extracted:`, chunk.session?.extracted || "None");
|
|
90
97
|
console.log(` - Tool Calls: ${chunk.toolCalls?.length || 0}`);
|
|
98
|
+
|
|
99
|
+
// Update session with progress
|
|
100
|
+
session = chunk.session!;
|
|
91
101
|
}
|
|
92
102
|
}
|
|
93
103
|
} catch (error) {
|
|
@@ -131,13 +141,23 @@ async function streamingWithOpenAI() {
|
|
|
131
141
|
console.log("📤 Streaming response from OpenAI...\n");
|
|
132
142
|
console.log("Response: ");
|
|
133
143
|
|
|
134
|
-
|
|
144
|
+
// Initialize session state for streaming conversation
|
|
145
|
+
let session = createSession();
|
|
146
|
+
|
|
147
|
+
for await (const chunk of agent.respondStream({ history, session })) {
|
|
135
148
|
if (chunk.delta) {
|
|
136
149
|
process.stdout.write(chunk.delta);
|
|
137
150
|
}
|
|
138
151
|
|
|
139
152
|
if (chunk.done) {
|
|
140
153
|
console.log("\n\n✅ Stream complete!");
|
|
154
|
+
console.log(
|
|
155
|
+
` - Route: ${chunk.session?.currentRoute?.title || "None"}`
|
|
156
|
+
);
|
|
157
|
+
console.log(` - Extracted:`, chunk.session?.extracted || "None");
|
|
158
|
+
|
|
159
|
+
// Update session with progress
|
|
160
|
+
session = chunk.session!;
|
|
141
161
|
}
|
|
142
162
|
}
|
|
143
163
|
} catch (error) {
|
|
@@ -181,13 +201,23 @@ async function streamingWithGemini() {
|
|
|
181
201
|
console.log("📤 Streaming response from Gemini...\n");
|
|
182
202
|
console.log("Response: ");
|
|
183
203
|
|
|
184
|
-
|
|
204
|
+
// Initialize session state for streaming conversation
|
|
205
|
+
let session = createSession();
|
|
206
|
+
|
|
207
|
+
for await (const chunk of agent.respondStream({ history, session })) {
|
|
185
208
|
if (chunk.delta) {
|
|
186
209
|
process.stdout.write(chunk.delta);
|
|
187
210
|
}
|
|
188
211
|
|
|
189
212
|
if (chunk.done) {
|
|
190
213
|
console.log("\n\n✅ Stream complete!");
|
|
214
|
+
console.log(
|
|
215
|
+
` - Route: ${chunk.session?.currentRoute?.title || "None"}`
|
|
216
|
+
);
|
|
217
|
+
console.log(` - Extracted:`, chunk.session?.extracted || "None");
|
|
218
|
+
|
|
219
|
+
// Update session with progress
|
|
220
|
+
session = chunk.session!;
|
|
191
221
|
}
|
|
192
222
|
}
|
|
193
223
|
} catch (error) {
|
|
@@ -239,19 +269,24 @@ async function streamingWithRoutes() {
|
|
|
239
269
|
console.log("📤 Streaming response with route detection...\n");
|
|
240
270
|
console.log("Response: ");
|
|
241
271
|
|
|
242
|
-
|
|
272
|
+
// Initialize session state for streaming conversation
|
|
273
|
+
let session = createSession();
|
|
274
|
+
|
|
275
|
+
for await (const chunk of agent.respondStream({ history, session })) {
|
|
243
276
|
if (chunk.delta) {
|
|
244
277
|
process.stdout.write(chunk.delta);
|
|
245
278
|
}
|
|
246
279
|
|
|
247
280
|
if (chunk.done) {
|
|
248
281
|
console.log("\n\n✅ Stream complete!");
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
282
|
+
console.log(`\n📊 Metadata:`);
|
|
283
|
+
console.log(
|
|
284
|
+
` - Route: ${chunk.session?.currentRoute?.title || "None"}`
|
|
285
|
+
);
|
|
286
|
+
console.log(` - Extracted:`, chunk.session?.extracted || "None");
|
|
287
|
+
|
|
288
|
+
// Update session with progress
|
|
289
|
+
session = chunk.session!;
|
|
255
290
|
}
|
|
256
291
|
}
|
|
257
292
|
} catch (error) {
|
|
@@ -301,8 +336,12 @@ async function streamingWithAbortSignal() {
|
|
|
301
336
|
console.log("📤 Streaming response (will abort after 3s)...\n");
|
|
302
337
|
console.log("Response: ");
|
|
303
338
|
|
|
339
|
+
// Initialize session state for streaming conversation
|
|
340
|
+
let session = createSession();
|
|
341
|
+
|
|
304
342
|
for await (const chunk of agent.respondStream({
|
|
305
343
|
history,
|
|
344
|
+
session,
|
|
306
345
|
signal: abortController.signal,
|
|
307
346
|
})) {
|
|
308
347
|
if (chunk.delta) {
|
|
@@ -311,6 +350,15 @@ async function streamingWithAbortSignal() {
|
|
|
311
350
|
|
|
312
351
|
if (chunk.done) {
|
|
313
352
|
console.log("\n\n✅ Stream complete!");
|
|
353
|
+
console.log(`\n📊 Metadata:`);
|
|
354
|
+
console.log(
|
|
355
|
+
` - Route: ${chunk.session?.currentRoute?.title || "None"}`
|
|
356
|
+
);
|
|
357
|
+
console.log(` - Extracted:`, chunk.session?.extracted || "None");
|
|
358
|
+
|
|
359
|
+
// Update session with progress
|
|
360
|
+
session = chunk.session!;
|
|
361
|
+
|
|
314
362
|
clearTimeout(timeout);
|
|
315
363
|
}
|
|
316
364
|
}
|
package/examples/travel-agent.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Travel agent example
|
|
3
|
-
* Demonstrates
|
|
2
|
+
* Travel agent example with session state management
|
|
3
|
+
* Demonstrates data-driven conversations with schema extraction and state progression
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import {
|
|
@@ -10,6 +10,8 @@ import {
|
|
|
10
10
|
END_ROUTE,
|
|
11
11
|
EventSource,
|
|
12
12
|
createMessageEvent,
|
|
13
|
+
createSession,
|
|
14
|
+
type ToolContext,
|
|
13
15
|
} from "../src/index";
|
|
14
16
|
|
|
15
17
|
// Context type for travel agent
|
|
@@ -18,10 +20,27 @@ interface TravelContext {
|
|
|
18
20
|
customerName: string;
|
|
19
21
|
}
|
|
20
22
|
|
|
21
|
-
//
|
|
22
|
-
|
|
23
|
+
// Data extraction types for travel booking
|
|
24
|
+
interface FlightBookingData {
|
|
25
|
+
destination: string;
|
|
26
|
+
destinationCode?: string; // Enriched by tools
|
|
27
|
+
departureDate: string;
|
|
28
|
+
returnDate?: string;
|
|
29
|
+
passengers: number;
|
|
30
|
+
cabinClass: "economy" | "business" | "first";
|
|
31
|
+
urgency: "low" | "medium" | "high";
|
|
32
|
+
shouldSearchFlights?: boolean; // Action flag
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
interface BookingStatusData {
|
|
36
|
+
confirmationNumber: string;
|
|
37
|
+
email?: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Tools with data access
|
|
41
|
+
const getAvailableDestinations = defineTool(
|
|
23
42
|
"get_available_destinations",
|
|
24
|
-
async () => {
|
|
43
|
+
async ({ context }: ToolContext<TravelContext>) => {
|
|
25
44
|
return {
|
|
26
45
|
data: [
|
|
27
46
|
"Paris, France",
|
|
@@ -36,78 +55,124 @@ const getAvailableDestinations = defineTool<TravelContext, [], string[]>(
|
|
|
36
55
|
}
|
|
37
56
|
);
|
|
38
57
|
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
58
|
+
const lookupDestinationCode = defineTool(
|
|
59
|
+
"lookup_destination_code",
|
|
60
|
+
async ({
|
|
61
|
+
context,
|
|
62
|
+
extracted,
|
|
63
|
+
}: ToolContext<TravelContext, FlightBookingData>) => {
|
|
64
|
+
if (!extracted?.destination) {
|
|
65
|
+
return { data: undefined };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Simulate airport code lookup
|
|
69
|
+
const codes: Record<string, string> = {
|
|
70
|
+
"Paris, France": "CDG",
|
|
71
|
+
"Tokyo, Japan": "NRT",
|
|
72
|
+
"Bali, Indonesia": "DPS",
|
|
73
|
+
"New York, USA": "JFK",
|
|
74
|
+
};
|
|
75
|
+
|
|
46
76
|
return {
|
|
47
|
-
data:
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
],
|
|
77
|
+
data: undefined,
|
|
78
|
+
extractedUpdate: {
|
|
79
|
+
destinationCode: codes[extracted.destination],
|
|
80
|
+
},
|
|
52
81
|
};
|
|
53
82
|
},
|
|
54
83
|
{
|
|
55
|
-
description: "
|
|
84
|
+
description: "Convert destination name to airport code",
|
|
56
85
|
}
|
|
57
86
|
);
|
|
58
87
|
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
88
|
+
const searchFlights = defineTool(
|
|
89
|
+
"search_flights",
|
|
90
|
+
async ({
|
|
91
|
+
context,
|
|
92
|
+
extracted,
|
|
93
|
+
}: ToolContext<TravelContext, FlightBookingData>) => {
|
|
94
|
+
if (!extracted?.destination || !extracted?.departureDate) {
|
|
95
|
+
return { data: [] };
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Simulate flight search based on extracted data
|
|
99
|
+
const flights = [
|
|
100
|
+
`Flight 123 - ${extracted.departureDate}, 9:00 AM, $${
|
|
101
|
+
800 + Math.floor(Math.random() * 200)
|
|
102
|
+
}`,
|
|
103
|
+
`Flight 321 - ${extracted.departureDate}, 2:30 PM, $${
|
|
104
|
+
700 + Math.floor(Math.random() * 200)
|
|
105
|
+
}`,
|
|
106
|
+
`Flight 987 - ${extracted.departureDate}, 6:45 PM, $${
|
|
107
|
+
600 + Math.floor(Math.random() * 200)
|
|
108
|
+
}`,
|
|
109
|
+
];
|
|
110
|
+
|
|
66
111
|
return {
|
|
67
|
-
data:
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
112
|
+
data: flights,
|
|
113
|
+
extractedUpdate: {
|
|
114
|
+
shouldSearchFlights: false, // Clear the flag
|
|
115
|
+
},
|
|
71
116
|
};
|
|
72
117
|
},
|
|
73
118
|
{
|
|
74
|
-
description: "
|
|
119
|
+
description: "Search for flights based on extracted travel data",
|
|
75
120
|
}
|
|
76
121
|
);
|
|
77
122
|
|
|
78
|
-
const bookFlight = defineTool
|
|
123
|
+
const bookFlight = defineTool(
|
|
79
124
|
"book_flight",
|
|
80
|
-
async ({
|
|
125
|
+
async ({
|
|
126
|
+
context,
|
|
127
|
+
extracted,
|
|
128
|
+
}: ToolContext<TravelContext, FlightBookingData>) => {
|
|
129
|
+
if (!extracted) {
|
|
130
|
+
return { data: "Please provide flight details" };
|
|
131
|
+
}
|
|
132
|
+
|
|
81
133
|
const confirmationNumber = `TRV-${new Date()
|
|
82
134
|
.toISOString()
|
|
83
135
|
.slice(0, 10)
|
|
84
136
|
.replace(/-/g, "")}-001`;
|
|
137
|
+
|
|
85
138
|
return {
|
|
86
|
-
data: `Flight booked
|
|
139
|
+
data: `Flight booked for ${context.customerName} to ${extracted.destination}. Confirmation: ${confirmationNumber}`,
|
|
87
140
|
};
|
|
88
141
|
},
|
|
89
142
|
{
|
|
90
|
-
description: "Book a flight
|
|
143
|
+
description: "Book a flight using extracted travel data",
|
|
91
144
|
}
|
|
92
145
|
);
|
|
93
146
|
|
|
94
147
|
const getBookingStatus = defineTool<
|
|
95
148
|
TravelContext,
|
|
96
|
-
[
|
|
97
|
-
|
|
149
|
+
[],
|
|
150
|
+
{ status: string; details: string; notes?: string }
|
|
98
151
|
>(
|
|
99
152
|
"get_booking_status",
|
|
100
|
-
async (
|
|
153
|
+
async ({
|
|
154
|
+
context,
|
|
155
|
+
extracted,
|
|
156
|
+
}: ToolContext<TravelContext, BookingStatusData>) => {
|
|
157
|
+
if (!extracted?.confirmationNumber) {
|
|
158
|
+
return {
|
|
159
|
+
data: {
|
|
160
|
+
status: "Error",
|
|
161
|
+
details: "Please provide a confirmation number",
|
|
162
|
+
},
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
|
|
101
166
|
return {
|
|
102
167
|
data: {
|
|
103
168
|
status: "Confirmed",
|
|
104
|
-
details:
|
|
169
|
+
details: `Flight booking ${extracted.confirmationNumber} is confirmed.`,
|
|
105
170
|
notes: "Check-in opens 24 hours before departure.",
|
|
106
171
|
},
|
|
107
172
|
};
|
|
108
173
|
},
|
|
109
174
|
{
|
|
110
|
-
description: "Get booking status
|
|
175
|
+
description: "Get booking status using extracted confirmation number",
|
|
111
176
|
}
|
|
112
177
|
);
|
|
113
178
|
|
|
@@ -152,83 +217,108 @@ async function createTravelAgent() {
|
|
|
152
217
|
synonyms: ["insurance", "trip protection", "travel protection"],
|
|
153
218
|
});
|
|
154
219
|
|
|
155
|
-
// Create flight booking route
|
|
156
|
-
const flightBookingRoute = agent.createRoute({
|
|
220
|
+
// Create flight booking route with data extraction
|
|
221
|
+
const flightBookingRoute = agent.createRoute<FlightBookingData>({
|
|
157
222
|
title: "Book a Flight",
|
|
158
223
|
description:
|
|
159
224
|
"Helps the customer find and book a flight to their desired destination.",
|
|
160
225
|
conditions: ["The customer wants to book a flight"],
|
|
226
|
+
gatherSchema: {
|
|
227
|
+
type: "object",
|
|
228
|
+
properties: {
|
|
229
|
+
destination: {
|
|
230
|
+
type: "string",
|
|
231
|
+
description: "Travel destination",
|
|
232
|
+
},
|
|
233
|
+
destinationCode: {
|
|
234
|
+
type: "string",
|
|
235
|
+
description: "Airport code (enriched by tool)",
|
|
236
|
+
},
|
|
237
|
+
departureDate: {
|
|
238
|
+
type: "string",
|
|
239
|
+
description: "Departure date",
|
|
240
|
+
},
|
|
241
|
+
returnDate: {
|
|
242
|
+
type: "string",
|
|
243
|
+
description: "Return date (optional)",
|
|
244
|
+
},
|
|
245
|
+
passengers: {
|
|
246
|
+
type: "number",
|
|
247
|
+
minimum: 1,
|
|
248
|
+
maximum: 9,
|
|
249
|
+
description: "Number of passengers",
|
|
250
|
+
},
|
|
251
|
+
cabinClass: {
|
|
252
|
+
type: "string",
|
|
253
|
+
enum: ["economy", "business", "first"],
|
|
254
|
+
default: "economy",
|
|
255
|
+
description: "Cabin class preference",
|
|
256
|
+
},
|
|
257
|
+
urgency: {
|
|
258
|
+
type: "string",
|
|
259
|
+
enum: ["low", "medium", "high"],
|
|
260
|
+
default: "medium",
|
|
261
|
+
description: "Travel urgency level",
|
|
262
|
+
},
|
|
263
|
+
shouldSearchFlights: {
|
|
264
|
+
type: "boolean",
|
|
265
|
+
description: "Flag to trigger flight search",
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
required: ["destination", "departureDate", "passengers"],
|
|
269
|
+
},
|
|
161
270
|
});
|
|
162
271
|
|
|
163
|
-
// Build the route flow
|
|
164
|
-
const
|
|
272
|
+
// Build the route flow with data extraction and smart state progression
|
|
273
|
+
const askDestination = flightBookingRoute.initialState.transitionTo({
|
|
165
274
|
chatState: "Ask about the destination",
|
|
275
|
+
gather: ["destination"],
|
|
276
|
+
skipIf: (extracted) => !!extracted.destination,
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
const enrichDestination = askDestination.transitionTo({
|
|
280
|
+
toolState: lookupDestinationCode,
|
|
281
|
+
requiredData: ["destination"],
|
|
166
282
|
});
|
|
167
283
|
|
|
168
|
-
const
|
|
284
|
+
const askDates = enrichDestination.transitionTo({
|
|
169
285
|
chatState: "Ask about preferred travel dates",
|
|
286
|
+
gather: ["departureDate"],
|
|
287
|
+
skipIf: (extracted) => !!extracted.departureDate,
|
|
288
|
+
requiredData: ["destination"],
|
|
170
289
|
});
|
|
171
290
|
|
|
172
|
-
const
|
|
173
|
-
|
|
291
|
+
const askPassengers = askDates.transitionTo({
|
|
292
|
+
chatState: "Ask for number of passengers",
|
|
293
|
+
gather: ["passengers"],
|
|
294
|
+
skipIf: (extracted) => !!extracted.passengers,
|
|
295
|
+
requiredData: ["destination", "departureDate"],
|
|
174
296
|
});
|
|
175
297
|
|
|
176
|
-
const
|
|
298
|
+
const searchFlightsState = askPassengers.transitionTo({
|
|
299
|
+
toolState: searchFlights,
|
|
300
|
+
// Triggered when shouldSearchFlights flag is set by hook
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
const presentFlights = searchFlightsState.transitionTo({
|
|
177
304
|
chatState: "Present available flights and ask which one works for them",
|
|
178
305
|
});
|
|
179
306
|
|
|
180
307
|
// Happy path: customer selects a flight
|
|
181
|
-
const
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
"Collect passenger information and confirm booking details before proceeding",
|
|
185
|
-
},
|
|
186
|
-
"The customer selects a flight"
|
|
187
|
-
);
|
|
188
|
-
|
|
189
|
-
const t5 = t4.transitionTo(
|
|
190
|
-
{
|
|
191
|
-
toolState: bookFlight,
|
|
192
|
-
},
|
|
193
|
-
"The customer confirms the booking details"
|
|
194
|
-
);
|
|
195
|
-
|
|
196
|
-
const t6 = t5.transitionTo({
|
|
197
|
-
chatState: "Provide confirmation number and booking summary",
|
|
308
|
+
const confirmBooking = presentFlights.transitionTo({
|
|
309
|
+
chatState: "Confirm booking details before proceeding",
|
|
310
|
+
gather: ["cabinClass", "urgency"], // Additional optional data
|
|
198
311
|
});
|
|
199
312
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
// Alternative path: no flights work
|
|
203
|
-
const t7 = t3.transitionTo(
|
|
204
|
-
{
|
|
205
|
-
toolState: getAlternativeFlights,
|
|
206
|
-
},
|
|
207
|
-
"None of the flights work for the customer"
|
|
208
|
-
);
|
|
209
|
-
|
|
210
|
-
const t8 = t7.transitionTo({
|
|
211
|
-
chatState: "Present alternative flights and ask if any work",
|
|
313
|
+
const bookFlightState = confirmBooking.transitionTo({
|
|
314
|
+
toolState: bookFlight,
|
|
212
315
|
});
|
|
213
316
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
state: t4,
|
|
218
|
-
},
|
|
219
|
-
"The customer selects a flight"
|
|
220
|
-
);
|
|
221
|
-
|
|
222
|
-
// No alternative flights work either
|
|
223
|
-
const t9 = t8.transitionTo(
|
|
224
|
-
{
|
|
225
|
-
chatState:
|
|
226
|
-
"Suggest calling our office or visiting our website for more options",
|
|
227
|
-
},
|
|
228
|
-
"None of the alternative flights work either"
|
|
229
|
-
);
|
|
317
|
+
const provideConfirmation = bookFlightState.transitionTo({
|
|
318
|
+
chatState: "Provide confirmation number and booking summary",
|
|
319
|
+
});
|
|
230
320
|
|
|
231
|
-
|
|
321
|
+
provideConfirmation.transitionTo({ state: END_ROUTE });
|
|
232
322
|
|
|
233
323
|
// Add route-specific guidelines
|
|
234
324
|
flightBookingRoute.createGuideline({
|
|
@@ -244,45 +334,44 @@ async function createTravelAgent() {
|
|
|
244
334
|
"Inform them that visa requirements vary by destination and nationality, and suggest they check with the embassy or consulate",
|
|
245
335
|
});
|
|
246
336
|
|
|
247
|
-
// Create booking status route
|
|
248
|
-
const bookingStatusRoute = agent.createRoute({
|
|
337
|
+
// Create booking status route with data extraction
|
|
338
|
+
const bookingStatusRoute = agent.createRoute<BookingStatusData>({
|
|
249
339
|
title: "Check Booking Status",
|
|
250
340
|
description:
|
|
251
341
|
"Retrieves the customer's booking status and provides relevant information.",
|
|
252
342
|
conditions: ["The customer wants to check their booking status"],
|
|
343
|
+
gatherSchema: {
|
|
344
|
+
type: "object",
|
|
345
|
+
properties: {
|
|
346
|
+
confirmationNumber: {
|
|
347
|
+
type: "string",
|
|
348
|
+
description: "Booking confirmation number",
|
|
349
|
+
},
|
|
350
|
+
email: {
|
|
351
|
+
type: "string",
|
|
352
|
+
description: "Email address associated with booking (optional)",
|
|
353
|
+
},
|
|
354
|
+
},
|
|
355
|
+
required: ["confirmationNumber"],
|
|
356
|
+
},
|
|
253
357
|
});
|
|
254
358
|
|
|
255
|
-
const
|
|
359
|
+
const askConfirmation = bookingStatusRoute.initialState.transitionTo({
|
|
256
360
|
chatState: "Ask for the confirmation number or booking reference",
|
|
361
|
+
gather: ["confirmationNumber"],
|
|
362
|
+
skipIf: (extracted) => !!extracted.confirmationNumber,
|
|
257
363
|
});
|
|
258
364
|
|
|
259
|
-
const
|
|
365
|
+
const checkStatus = askConfirmation.transitionTo({
|
|
260
366
|
toolState: getBookingStatus,
|
|
367
|
+
requiredData: ["confirmationNumber"],
|
|
261
368
|
});
|
|
262
369
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
"Tell the customer that the booking could not be found and ask them to verify the confirmation number or call the office",
|
|
267
|
-
},
|
|
268
|
-
"The booking could not be found"
|
|
269
|
-
);
|
|
270
|
-
|
|
271
|
-
s1.transitionTo(
|
|
272
|
-
{
|
|
273
|
-
chatState:
|
|
274
|
-
"Provide the booking details and confirm everything is in order",
|
|
275
|
-
},
|
|
276
|
-
"The booking is confirmed and all details are correct"
|
|
277
|
-
);
|
|
370
|
+
const provideStatus = checkStatus.transitionTo({
|
|
371
|
+
chatState: "Provide booking status and relevant information",
|
|
372
|
+
});
|
|
278
373
|
|
|
279
|
-
|
|
280
|
-
{
|
|
281
|
-
chatState:
|
|
282
|
-
"Present the booking information and mention any issues or pending actions required",
|
|
283
|
-
},
|
|
284
|
-
"The booking has issues or requires customer action"
|
|
285
|
-
);
|
|
374
|
+
provideStatus.transitionTo({ state: END_ROUTE });
|
|
286
375
|
|
|
287
376
|
// Global guidelines
|
|
288
377
|
agent.createGuideline({
|
|
@@ -307,34 +396,78 @@ async function createTravelAgent() {
|
|
|
307
396
|
return agent;
|
|
308
397
|
}
|
|
309
398
|
|
|
310
|
-
// Example usage
|
|
399
|
+
// Example usage with session state
|
|
311
400
|
async function main() {
|
|
312
401
|
const agent = await createTravelAgent();
|
|
313
402
|
|
|
403
|
+
// Initialize session state
|
|
404
|
+
let session = createSession<FlightBookingData | BookingStatusData>();
|
|
405
|
+
|
|
314
406
|
// Simulate a conversation
|
|
315
407
|
const history = [
|
|
316
408
|
createMessageEvent(
|
|
317
409
|
EventSource.CUSTOMER,
|
|
318
|
-
"
|
|
319
|
-
"Hi, I want to book a flight to Paris"
|
|
410
|
+
"Alice",
|
|
411
|
+
"Hi, I want to book a flight to Paris next week with 2 passengers"
|
|
320
412
|
),
|
|
321
413
|
];
|
|
322
414
|
|
|
323
415
|
console.log("Agent:", agent.name);
|
|
324
416
|
console.log("Description:", agent.description);
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
417
|
+
|
|
418
|
+
// Turn 1 - Agent extracts data and starts booking flow
|
|
419
|
+
const response1 = await agent.respond({ history, session });
|
|
420
|
+
console.log("\n=== TURN 1 ===");
|
|
421
|
+
console.log("Agent:", response1.message);
|
|
422
|
+
console.log("Route:", response1.session?.currentRoute?.title);
|
|
423
|
+
console.log("State:", response1.session?.currentState?.id);
|
|
424
|
+
console.log("Extracted:", response1.session?.extracted);
|
|
425
|
+
|
|
426
|
+
// Session state updated with progress
|
|
427
|
+
session = response1.session!;
|
|
428
|
+
|
|
429
|
+
// Turn 2 - Continue with session state
|
|
430
|
+
if (response1.session?.currentRoute?.title === "Book a Flight") {
|
|
431
|
+
const history2 = [
|
|
432
|
+
...history,
|
|
433
|
+
createMessageEvent(EventSource.AI_AGENT, "Agent", response1.message),
|
|
434
|
+
createMessageEvent(EventSource.CUSTOMER, "Alice", "Economy class please"),
|
|
435
|
+
];
|
|
436
|
+
|
|
437
|
+
const response2 = await agent.respond({ history: history2, session });
|
|
438
|
+
console.log("\n=== TURN 2 ===");
|
|
439
|
+
console.log("Agent:", response2.message);
|
|
440
|
+
console.log("Updated extracted:", response2.session?.extracted);
|
|
441
|
+
console.log("Current state:", response2.session?.currentState?.id);
|
|
333
442
|
}
|
|
334
443
|
|
|
335
|
-
//
|
|
336
|
-
|
|
337
|
-
|
|
444
|
+
// Demonstrate booking status check
|
|
445
|
+
const statusHistory = [
|
|
446
|
+
createMessageEvent(
|
|
447
|
+
EventSource.CUSTOMER,
|
|
448
|
+
"Bob",
|
|
449
|
+
"Can you check my booking status? Confirmation number TRV-20251015-001"
|
|
450
|
+
),
|
|
451
|
+
];
|
|
452
|
+
|
|
453
|
+
let statusSession = createSession<BookingStatusData>();
|
|
454
|
+
const statusResponse = await agent.respond({
|
|
455
|
+
history: statusHistory,
|
|
456
|
+
session: statusSession,
|
|
457
|
+
});
|
|
458
|
+
console.log("\n=== BOOKING STATUS CHECK ===");
|
|
459
|
+
console.log("Agent:", statusResponse.message);
|
|
460
|
+
console.log("Route:", statusResponse.session?.currentRoute?.title);
|
|
461
|
+
console.log("Extracted:", statusResponse.session?.extracted);
|
|
462
|
+
|
|
463
|
+
// Show session state management benefits
|
|
464
|
+
console.log("\n=== SESSION STATE BENEFITS ===");
|
|
465
|
+
console.log("✅ Always-on routing - respects user intent changes");
|
|
466
|
+
console.log("✅ Data persistence - extracted data survives across turns");
|
|
467
|
+
console.log(
|
|
468
|
+
"✅ State progression - intelligent flow based on collected data"
|
|
469
|
+
);
|
|
470
|
+
console.log("✅ Context awareness - router sees current progress");
|
|
338
471
|
}
|
|
339
472
|
|
|
340
473
|
// Run if executed directly
|