@falai/agent 0.9.0-alpha-1 → 0.9.0-alpha-2
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 +34 -22
- package/dist/cjs/src/core/Agent.d.ts +52 -24
- package/dist/cjs/src/core/Agent.d.ts.map +1 -1
- package/dist/cjs/src/core/Agent.js +266 -39
- package/dist/cjs/src/core/Agent.js.map +1 -1
- package/dist/cjs/src/core/PersistenceManager.d.ts.map +1 -1
- package/dist/cjs/src/core/PersistenceManager.js +48 -25
- package/dist/cjs/src/core/PersistenceManager.js.map +1 -1
- package/dist/cjs/src/core/PromptComposer.d.ts +1 -1
- package/dist/cjs/src/core/PromptComposer.d.ts.map +1 -1
- package/dist/cjs/src/core/PromptComposer.js.map +1 -1
- package/dist/cjs/src/core/ResponseEngine.d.ts +13 -12
- package/dist/cjs/src/core/ResponseEngine.d.ts.map +1 -1
- package/dist/cjs/src/core/ResponseEngine.js +4 -4
- package/dist/cjs/src/core/ResponseEngine.js.map +1 -1
- package/dist/cjs/src/core/ResponsePipeline.d.ts +66 -38
- package/dist/cjs/src/core/ResponsePipeline.d.ts.map +1 -1
- package/dist/cjs/src/core/ResponsePipeline.js +71 -3
- package/dist/cjs/src/core/ResponsePipeline.js.map +1 -1
- package/dist/cjs/src/core/Route.d.ts +24 -5
- package/dist/cjs/src/core/Route.d.ts.map +1 -1
- package/dist/cjs/src/core/Route.js +45 -1
- package/dist/cjs/src/core/Route.js.map +1 -1
- package/dist/cjs/src/core/RoutingEngine.d.ts +31 -6
- package/dist/cjs/src/core/RoutingEngine.d.ts.map +1 -1
- package/dist/cjs/src/core/RoutingEngine.js +113 -9
- package/dist/cjs/src/core/RoutingEngine.js.map +1 -1
- package/dist/cjs/src/core/SessionManager.d.ts +14 -4
- package/dist/cjs/src/core/SessionManager.d.ts.map +1 -1
- package/dist/cjs/src/core/SessionManager.js +25 -5
- package/dist/cjs/src/core/SessionManager.js.map +1 -1
- package/dist/cjs/src/core/Step.d.ts +10 -10
- package/dist/cjs/src/core/Step.d.ts.map +1 -1
- package/dist/cjs/src/core/Step.js.map +1 -1
- package/dist/cjs/src/core/ToolExecutor.d.ts +4 -2
- package/dist/cjs/src/core/ToolExecutor.d.ts.map +1 -1
- package/dist/cjs/src/core/ToolExecutor.js +13 -3
- package/dist/cjs/src/core/ToolExecutor.js.map +1 -1
- package/dist/cjs/src/types/agent.d.ts +41 -21
- package/dist/cjs/src/types/agent.d.ts.map +1 -1
- package/dist/cjs/src/types/agent.js.map +1 -1
- package/dist/cjs/src/types/index.d.ts +1 -1
- package/dist/cjs/src/types/index.d.ts.map +1 -1
- package/dist/cjs/src/types/index.js.map +1 -1
- package/dist/cjs/src/types/persistence.d.ts +0 -1
- package/dist/cjs/src/types/persistence.d.ts.map +1 -1
- package/dist/cjs/src/types/route.d.ts +22 -16
- package/dist/cjs/src/types/route.d.ts.map +1 -1
- package/dist/cjs/src/types/session.d.ts +6 -11
- package/dist/cjs/src/types/session.d.ts.map +1 -1
- package/dist/cjs/src/types/tool.d.ts +12 -6
- package/dist/cjs/src/types/tool.d.ts.map +1 -1
- package/dist/cjs/src/utils/session.d.ts +2 -2
- package/dist/cjs/src/utils/session.d.ts.map +1 -1
- package/dist/cjs/src/utils/session.js +6 -26
- package/dist/cjs/src/utils/session.js.map +1 -1
- package/dist/src/core/Agent.d.ts +52 -24
- package/dist/src/core/Agent.d.ts.map +1 -1
- package/dist/src/core/Agent.js +266 -39
- package/dist/src/core/Agent.js.map +1 -1
- package/dist/src/core/PersistenceManager.d.ts.map +1 -1
- package/dist/src/core/PersistenceManager.js +48 -25
- package/dist/src/core/PersistenceManager.js.map +1 -1
- package/dist/src/core/PromptComposer.d.ts +1 -1
- package/dist/src/core/PromptComposer.d.ts.map +1 -1
- package/dist/src/core/PromptComposer.js.map +1 -1
- package/dist/src/core/ResponseEngine.d.ts +13 -12
- package/dist/src/core/ResponseEngine.d.ts.map +1 -1
- package/dist/src/core/ResponseEngine.js +4 -4
- package/dist/src/core/ResponseEngine.js.map +1 -1
- package/dist/src/core/ResponsePipeline.d.ts +66 -38
- package/dist/src/core/ResponsePipeline.d.ts.map +1 -1
- package/dist/src/core/ResponsePipeline.js +71 -3
- package/dist/src/core/ResponsePipeline.js.map +1 -1
- package/dist/src/core/Route.d.ts +24 -5
- package/dist/src/core/Route.d.ts.map +1 -1
- package/dist/src/core/Route.js +45 -1
- package/dist/src/core/Route.js.map +1 -1
- package/dist/src/core/RoutingEngine.d.ts +31 -6
- package/dist/src/core/RoutingEngine.d.ts.map +1 -1
- package/dist/src/core/RoutingEngine.js +113 -9
- package/dist/src/core/RoutingEngine.js.map +1 -1
- package/dist/src/core/SessionManager.d.ts +14 -4
- package/dist/src/core/SessionManager.d.ts.map +1 -1
- package/dist/src/core/SessionManager.js +25 -5
- package/dist/src/core/SessionManager.js.map +1 -1
- package/dist/src/core/Step.d.ts +10 -10
- package/dist/src/core/Step.d.ts.map +1 -1
- package/dist/src/core/Step.js.map +1 -1
- package/dist/src/core/ToolExecutor.d.ts +4 -2
- package/dist/src/core/ToolExecutor.d.ts.map +1 -1
- package/dist/src/core/ToolExecutor.js +13 -3
- package/dist/src/core/ToolExecutor.js.map +1 -1
- package/dist/src/types/agent.d.ts +41 -21
- package/dist/src/types/agent.d.ts.map +1 -1
- package/dist/src/types/agent.js.map +1 -1
- package/dist/src/types/index.d.ts +1 -1
- package/dist/src/types/index.d.ts.map +1 -1
- package/dist/src/types/index.js.map +1 -1
- package/dist/src/types/persistence.d.ts +0 -1
- package/dist/src/types/persistence.d.ts.map +1 -1
- package/dist/src/types/route.d.ts +22 -16
- package/dist/src/types/route.d.ts.map +1 -1
- package/dist/src/types/session.d.ts +6 -11
- package/dist/src/types/session.d.ts.map +1 -1
- package/dist/src/types/tool.d.ts +12 -6
- package/dist/src/types/tool.d.ts.map +1 -1
- package/dist/src/utils/session.d.ts +2 -2
- package/dist/src/utils/session.d.ts.map +1 -1
- package/dist/src/utils/session.js +6 -26
- package/dist/src/utils/session.js.map +1 -1
- package/docs/README.md +3 -3
- package/docs/api/README.md +35 -4
- package/docs/api/overview.md +166 -12
- package/docs/core/agent/README.md +162 -17
- package/docs/core/agent/context-management.md +39 -15
- package/docs/core/agent/session-management.md +49 -16
- package/docs/core/ai-integration/prompt-composition.md +38 -14
- package/docs/core/ai-integration/response-processing.md +28 -17
- package/docs/core/conversation-flows/data-collection.md +103 -25
- package/docs/core/conversation-flows/route-dsl.md +45 -22
- package/docs/core/conversation-flows/routes.md +74 -18
- package/docs/core/conversation-flows/step-transitions.md +3 -3
- package/docs/core/conversation-flows/steps.md +39 -15
- package/docs/core/routing/intelligent-routing.md +18 -9
- package/docs/core/tools/tool-definition.md +8 -8
- package/docs/core/tools/tool-execution.md +26 -26
- package/docs/core/tools/tool-scoping.md +5 -5
- package/docs/guides/getting-started/README.md +54 -32
- package/examples/advanced-patterns/knowledge-based-agent.ts +37 -28
- package/examples/advanced-patterns/persistent-onboarding.ts +70 -41
- package/examples/advanced-patterns/route-lifecycle-hooks.ts +28 -2
- package/examples/advanced-patterns/streaming-responses.ts +28 -23
- package/examples/ai-providers/anthropic-integration.ts +40 -33
- package/examples/ai-providers/openai-integration.ts +25 -25
- package/examples/conversation-flows/completion-transitions.ts +36 -32
- package/examples/core-concepts/basic-agent.ts +76 -78
- package/examples/core-concepts/schema-driven-extraction.ts +20 -16
- package/examples/core-concepts/session-management.ts +65 -53
- package/examples/integrations/database-integration.ts +49 -34
- package/examples/integrations/healthcare-integration.ts +96 -91
- package/examples/integrations/search-integration.ts +79 -82
- package/examples/integrations/server-session-management.ts +25 -17
- package/examples/persistence/database-persistence.ts +61 -45
- package/examples/persistence/memory-sessions.ts +52 -63
- package/examples/persistence/redis-persistence.ts +81 -95
- package/examples/tools/basic-tools.ts +73 -62
- package/examples/tools/data-enrichment-tools.ts +52 -44
- package/package.json +1 -1
- package/src/core/Agent.ts +418 -128
- package/src/core/PersistenceManager.ts +51 -27
- package/src/core/PromptComposer.ts +1 -1
- package/src/core/ResponseEngine.ts +21 -19
- package/src/core/ResponsePipeline.ts +174 -59
- package/src/core/Route.ts +58 -6
- package/src/core/RoutingEngine.ts +174 -27
- package/src/core/SessionManager.ts +32 -8
- package/src/core/Step.ts +20 -12
- package/src/core/ToolExecutor.ts +19 -5
- package/src/types/agent.ts +46 -23
- package/src/types/index.ts +2 -0
- package/src/types/persistence.ts +0 -1
- package/src/types/route.ts +22 -16
- package/src/types/session.ts +6 -12
- package/src/types/tool.ts +15 -9
- package/src/utils/session.ts +6 -31
|
@@ -64,8 +64,20 @@ async function example() {
|
|
|
64
64
|
|
|
65
65
|
const userId = "user_123";
|
|
66
66
|
|
|
67
|
+
// Define support ticket schema
|
|
68
|
+
const supportTicketSchema = {
|
|
69
|
+
type: "object",
|
|
70
|
+
properties: {
|
|
71
|
+
issue: { type: "string" },
|
|
72
|
+
category: { type: "string", enum: ["technical", "billing", "account", "other"] },
|
|
73
|
+
priority: { type: "string", enum: ["low", "medium", "high"] },
|
|
74
|
+
description: { type: "string" },
|
|
75
|
+
},
|
|
76
|
+
required: ["issue", "category", "priority", "description"],
|
|
77
|
+
};
|
|
78
|
+
|
|
67
79
|
// Create agent with Redis persistence
|
|
68
|
-
const agent = new Agent<ChatContext>({
|
|
80
|
+
const agent = new Agent<ChatContext, SupportTicketData>({
|
|
69
81
|
name: "Support Assistant",
|
|
70
82
|
description: "Fast, real-time support assistant",
|
|
71
83
|
goal: "Help users resolve issues quickly",
|
|
@@ -78,6 +90,8 @@ async function example() {
|
|
|
78
90
|
userName: "Alice",
|
|
79
91
|
chatType: "support",
|
|
80
92
|
},
|
|
93
|
+
// NEW: Agent-level schema
|
|
94
|
+
schema: supportTicketSchema,
|
|
81
95
|
// ✨ Redis adapter with custom options
|
|
82
96
|
persistence: {
|
|
83
97
|
adapter: new RedisAdapter<ChatContext>({
|
|
@@ -92,7 +106,7 @@ async function example() {
|
|
|
92
106
|
});
|
|
93
107
|
|
|
94
108
|
// Create support ticket route with data collecting
|
|
95
|
-
const ticketRoute = agent.createRoute
|
|
109
|
+
const ticketRoute = agent.createRoute({
|
|
96
110
|
title: "Create Support Ticket",
|
|
97
111
|
description: "Help user create and track support tickets",
|
|
98
112
|
conditions: [
|
|
@@ -100,31 +114,10 @@ async function example() {
|
|
|
100
114
|
"User wants to report a problem",
|
|
101
115
|
"User mentions support, help, or issue",
|
|
102
116
|
],
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
type: "string",
|
|
108
|
-
description: "Brief summary of the issue",
|
|
109
|
-
},
|
|
110
|
-
category: {
|
|
111
|
-
type: "string",
|
|
112
|
-
enum: ["technical", "billing", "account", "other"],
|
|
113
|
-
description: "Issue category",
|
|
114
|
-
},
|
|
115
|
-
priority: {
|
|
116
|
-
type: "string",
|
|
117
|
-
enum: ["low", "medium", "high"],
|
|
118
|
-
default: "medium",
|
|
119
|
-
description: "Issue priority",
|
|
120
|
-
},
|
|
121
|
-
description: {
|
|
122
|
-
type: "string",
|
|
123
|
-
description: "Detailed description of the issue",
|
|
124
|
-
},
|
|
125
|
-
},
|
|
126
|
-
required: ["issue", "category", "description"],
|
|
127
|
-
},
|
|
117
|
+
// NEW: Required fields for route completion
|
|
118
|
+
requiredFields: ["issue", "category", "description"],
|
|
119
|
+
// NEW: Optional fields that enhance the experience
|
|
120
|
+
optionalFields: ["priority"],
|
|
128
121
|
});
|
|
129
122
|
|
|
130
123
|
// Step flow
|
|
@@ -156,9 +149,9 @@ async function example() {
|
|
|
156
149
|
console.log("✨ Session ready:", agent.session.id);
|
|
157
150
|
|
|
158
151
|
// Set initial data
|
|
159
|
-
await agent.session.setData
|
|
152
|
+
await agent.session.setData({ priority: "medium" });
|
|
160
153
|
|
|
161
|
-
console.log("📊 Initial data:", agent.session.getData
|
|
154
|
+
console.log("📊 Initial data:", agent.session.getData());
|
|
162
155
|
|
|
163
156
|
// Turn 1: User provides issue
|
|
164
157
|
console.log("\n--- Turn 1 ---");
|
|
@@ -177,11 +170,11 @@ async function example() {
|
|
|
177
170
|
console.log("🤖 Agent:", response1.message);
|
|
178
171
|
|
|
179
172
|
await agent.session.addMessage("assistant", response1.message);
|
|
180
|
-
console.log("📊 Collected data:", agent.session.getData
|
|
173
|
+
console.log("📊 Collected data:", agent.session.getData());
|
|
181
174
|
|
|
182
175
|
// Turn 2: Provide more details
|
|
183
176
|
console.log("\n--- Turn 2 ---");
|
|
184
|
-
|
|
177
|
+
|
|
185
178
|
await agent.session.addMessage(
|
|
186
179
|
"user",
|
|
187
180
|
"I keep getting 'Invalid credentials' error even though I reset my password",
|
|
@@ -193,20 +186,20 @@ async function example() {
|
|
|
193
186
|
});
|
|
194
187
|
|
|
195
188
|
console.log("🤖 Agent:", response2.message);
|
|
196
|
-
console.log("📊 Collected data:", agent.session.getData
|
|
189
|
+
console.log("📊 Collected data:", agent.session.getData());
|
|
197
190
|
|
|
198
191
|
await agent.session.addMessage("assistant", response2.message);
|
|
199
192
|
|
|
200
193
|
if (response2.isRouteComplete) {
|
|
201
194
|
console.log("\n✅ Support ticket route complete!");
|
|
202
|
-
await fileSupportTicket(agent.session.getData
|
|
195
|
+
await fileSupportTicket(agent.session.getData() as SupportTicketData);
|
|
203
196
|
}
|
|
204
197
|
|
|
205
198
|
// Demonstrate session recovery with new agent instance
|
|
206
199
|
console.log("\n--- Session Recovery Example ---");
|
|
207
200
|
const sessionId = agent.session.id;
|
|
208
|
-
|
|
209
|
-
const recoveredAgent = new Agent<ChatContext>({
|
|
201
|
+
|
|
202
|
+
const recoveredAgent = new Agent<ChatContext, SupportTicketData>({
|
|
210
203
|
name: "Support Assistant",
|
|
211
204
|
provider: new GeminiProvider({
|
|
212
205
|
apiKey: process.env.GEMINI_API_KEY!,
|
|
@@ -217,6 +210,8 @@ async function example() {
|
|
|
217
210
|
userName: "Alice",
|
|
218
211
|
chatType: "support",
|
|
219
212
|
},
|
|
213
|
+
// NEW: Agent-level schema (same as original agent)
|
|
214
|
+
schema: supportTicketSchema,
|
|
220
215
|
persistence: {
|
|
221
216
|
adapter: new RedisAdapter<ChatContext>({
|
|
222
217
|
redis,
|
|
@@ -230,7 +225,7 @@ async function example() {
|
|
|
230
225
|
});
|
|
231
226
|
|
|
232
227
|
// Recreate the same route on recovered agent
|
|
233
|
-
recoveredAgent.createRoute
|
|
228
|
+
recoveredAgent.createRoute({
|
|
234
229
|
title: "Create Support Ticket",
|
|
235
230
|
description: "Help user create and track support tickets",
|
|
236
231
|
conditions: [
|
|
@@ -238,31 +233,16 @@ async function example() {
|
|
|
238
233
|
"User wants to report a problem",
|
|
239
234
|
"User mentions support, help, or issue",
|
|
240
235
|
],
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
category: {
|
|
246
|
-
type: "string",
|
|
247
|
-
enum: ["technical", "billing", "account", "other"],
|
|
248
|
-
description: "Issue category",
|
|
249
|
-
},
|
|
250
|
-
priority: {
|
|
251
|
-
type: "string",
|
|
252
|
-
enum: ["low", "medium", "high"],
|
|
253
|
-
default: "medium",
|
|
254
|
-
description: "Issue priority",
|
|
255
|
-
},
|
|
256
|
-
description: { type: "string", description: "Detailed description of the issue" },
|
|
257
|
-
},
|
|
258
|
-
required: ["issue", "category", "description"],
|
|
259
|
-
},
|
|
236
|
+
// NEW: Required fields for route completion
|
|
237
|
+
requiredFields: ["issue", "category", "description"],
|
|
238
|
+
// NEW: Optional fields that enhance the experience
|
|
239
|
+
optionalFields: ["priority"],
|
|
260
240
|
});
|
|
261
241
|
|
|
262
242
|
console.log("📥 Recovered session:", {
|
|
263
243
|
sessionId: recoveredAgent.session.id,
|
|
264
244
|
historyLength: recoveredAgent.session.getHistory().length,
|
|
265
|
-
data: recoveredAgent.session.getData
|
|
245
|
+
data: recoveredAgent.session.getData(),
|
|
266
246
|
});
|
|
267
247
|
|
|
268
248
|
console.log("✅ Session recovery complete!");
|
|
@@ -278,15 +258,27 @@ async function example() {
|
|
|
278
258
|
async function highThroughputExample() {
|
|
279
259
|
const redis = new Redis();
|
|
280
260
|
|
|
281
|
-
|
|
261
|
+
// Define quick chat schema
|
|
262
|
+
const quickChatSchema = {
|
|
263
|
+
type: "object",
|
|
264
|
+
properties: {
|
|
265
|
+
topic: { type: "string" },
|
|
266
|
+
sentiment: { type: "string", enum: ["positive", "neutral", "negative"] },
|
|
267
|
+
},
|
|
268
|
+
required: ["topic", "sentiment"],
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
const agent = new Agent<unknown, QuickChatData>({
|
|
282
272
|
name: "Chat Bot",
|
|
283
273
|
description: "Fast chat responses",
|
|
284
274
|
provider: new GeminiProvider({
|
|
285
275
|
apiKey: process.env.GEMINI_API_KEY!,
|
|
286
276
|
model: "models/gemini-2.5-flash",
|
|
287
277
|
}),
|
|
278
|
+
// NEW: Agent-level schema
|
|
279
|
+
schema: quickChatSchema,
|
|
288
280
|
persistence: {
|
|
289
|
-
adapter: new RedisAdapter<
|
|
281
|
+
adapter: new RedisAdapter<unknown>({
|
|
290
282
|
redis,
|
|
291
283
|
keyPrefix: "chat:",
|
|
292
284
|
sessionTTL: 60 * 60, // 1 hour for quick chats
|
|
@@ -297,23 +289,10 @@ async function highThroughputExample() {
|
|
|
297
289
|
});
|
|
298
290
|
|
|
299
291
|
// Simple chat route that extracts topic and sentiment
|
|
300
|
-
const chatRoute = agent.createRoute
|
|
292
|
+
const chatRoute = agent.createRoute({
|
|
301
293
|
title: "General Chat",
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
properties: {
|
|
305
|
-
topic: {
|
|
306
|
-
type: "string",
|
|
307
|
-
description: "Main topic of conversation",
|
|
308
|
-
},
|
|
309
|
-
sentiment: {
|
|
310
|
-
type: "string",
|
|
311
|
-
enum: ["positive", "neutral", "negative"],
|
|
312
|
-
description: "User's sentiment",
|
|
313
|
-
},
|
|
314
|
-
},
|
|
315
|
-
required: ["topic", "sentiment"],
|
|
316
|
-
},
|
|
294
|
+
// NEW: Required fields for route completion
|
|
295
|
+
requiredFields: ["topic", "sentiment"],
|
|
317
296
|
});
|
|
318
297
|
|
|
319
298
|
chatRoute.initialStep
|
|
@@ -334,13 +313,13 @@ async function highThroughputExample() {
|
|
|
334
313
|
});
|
|
335
314
|
|
|
336
315
|
console.log("🤖 Response:", response.message);
|
|
337
|
-
console.log("📊 Data:", agent.session.getData
|
|
316
|
+
console.log("📊 Data:", agent.session.getData());
|
|
338
317
|
|
|
339
318
|
await agent.session.addMessage("assistant", response.message);
|
|
340
319
|
|
|
341
320
|
if (response.isRouteComplete) {
|
|
342
321
|
console.log("\n✅ Chat analytics route complete!");
|
|
343
|
-
await logChatAnalytics(agent.session.getData
|
|
322
|
+
await logChatAnalytics(agent.session.getData() as QuickChatData);
|
|
344
323
|
}
|
|
345
324
|
|
|
346
325
|
console.log("💾 Session automatically saved to Redis!");
|
|
@@ -355,30 +334,36 @@ async function highThroughputExample() {
|
|
|
355
334
|
async function sessionRecoveryExample() {
|
|
356
335
|
const redis = new Redis();
|
|
357
336
|
|
|
358
|
-
|
|
337
|
+
// Define order schema
|
|
338
|
+
const orderSchema = {
|
|
339
|
+
type: "object",
|
|
340
|
+
properties: {
|
|
341
|
+
productId: { type: "string" },
|
|
342
|
+
quantity: { type: "number", minimum: 1 },
|
|
343
|
+
shippingAddress: { type: "string" },
|
|
344
|
+
},
|
|
345
|
+
required: ["productId", "quantity", "shippingAddress"],
|
|
346
|
+
};
|
|
347
|
+
|
|
348
|
+
const agent = new Agent<unknown, OrderData>({
|
|
359
349
|
name: "Order Assistant",
|
|
360
350
|
provider: new GeminiProvider({
|
|
361
351
|
apiKey: process.env.GEMINI_API_KEY!,
|
|
362
352
|
model: "models/gemini-2.5-flash",
|
|
363
353
|
}),
|
|
354
|
+
// NEW: Agent-level schema
|
|
355
|
+
schema: orderSchema,
|
|
364
356
|
persistence: {
|
|
365
|
-
adapter: new RedisAdapter<
|
|
357
|
+
adapter: new RedisAdapter<unknown>({ redis }),
|
|
366
358
|
autoSave: true,
|
|
367
359
|
userId: "user_789",
|
|
368
360
|
},
|
|
369
361
|
});
|
|
370
362
|
|
|
371
|
-
const orderRoute = agent.createRoute
|
|
363
|
+
const orderRoute = agent.createRoute({
|
|
372
364
|
title: "Place Order",
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
properties: {
|
|
376
|
-
productId: { type: "string" },
|
|
377
|
-
quantity: { type: "number", minimum: 1 },
|
|
378
|
-
shippingAddress: { type: "string" },
|
|
379
|
-
},
|
|
380
|
-
required: ["productId", "quantity", "shippingAddress"],
|
|
381
|
-
},
|
|
365
|
+
// NEW: Required fields for route completion
|
|
366
|
+
requiredFields: ["productId", "quantity", "shippingAddress"],
|
|
382
367
|
});
|
|
383
368
|
|
|
384
369
|
orderRoute.initialStep
|
|
@@ -404,7 +389,7 @@ async function sessionRecoveryExample() {
|
|
|
404
389
|
});
|
|
405
390
|
|
|
406
391
|
console.log("🤖 Response:", response1.message);
|
|
407
|
-
console.log("📊 Data so far:", agent.session.getData
|
|
392
|
+
console.log("📊 Data so far:", agent.session.getData());
|
|
408
393
|
|
|
409
394
|
await agent.session.addMessage("assistant", response1.message);
|
|
410
395
|
|
|
@@ -412,24 +397,25 @@ async function sessionRecoveryExample() {
|
|
|
412
397
|
console.log("\n--- User Reconnects ---");
|
|
413
398
|
|
|
414
399
|
// Create new agent instance with same sessionId (simulates reconnection)
|
|
415
|
-
const reconnectedAgent = new Agent<OrderData>({
|
|
400
|
+
const reconnectedAgent = new Agent<unknown, OrderData>({
|
|
416
401
|
name: "Order Assistant",
|
|
417
402
|
provider: new GeminiProvider({
|
|
418
403
|
apiKey: process.env.GEMINI_API_KEY!,
|
|
419
404
|
model: "models/gemini-2.5-flash",
|
|
420
405
|
}),
|
|
406
|
+
// NEW: Agent-level schema (same as original agent)
|
|
407
|
+
schema: orderSchema,
|
|
421
408
|
persistence: {
|
|
422
|
-
adapter: new RedisAdapter<
|
|
409
|
+
adapter: new RedisAdapter<unknown>({ redis }),
|
|
423
410
|
autoSave: true,
|
|
424
411
|
},
|
|
425
412
|
sessionId, // Same sessionId - will load existing session
|
|
426
|
-
routes: [orderRoute],
|
|
427
413
|
});
|
|
428
414
|
|
|
429
415
|
console.log("📥 Recovered session:", {
|
|
430
416
|
sessionId: reconnectedAgent.session.id,
|
|
431
417
|
historyLength: reconnectedAgent.session.getHistory().length,
|
|
432
|
-
data: reconnectedAgent.session.getData
|
|
418
|
+
data: reconnectedAgent.session.getData(),
|
|
433
419
|
});
|
|
434
420
|
|
|
435
421
|
// Continue conversation
|
|
@@ -440,13 +426,13 @@ async function sessionRecoveryExample() {
|
|
|
440
426
|
});
|
|
441
427
|
|
|
442
428
|
console.log("🤖 Response:", response2.message);
|
|
443
|
-
console.log("📊 Final collected data:", reconnectedAgent.session.getData
|
|
429
|
+
console.log("📊 Final collected data:", reconnectedAgent.session.getData());
|
|
444
430
|
|
|
445
431
|
await reconnectedAgent.session.addMessage("assistant", response2.message);
|
|
446
432
|
|
|
447
433
|
if (response2.isRouteComplete) {
|
|
448
434
|
console.log("\n✅ Order placement complete!");
|
|
449
|
-
await processOrder(reconnectedAgent.session.getData
|
|
435
|
+
await processOrder(reconnectedAgent.session.getData() as OrderData);
|
|
450
436
|
}
|
|
451
437
|
|
|
452
438
|
console.log("✅ Order complete with recovered session!");
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* and integration with conversation flows.
|
|
7
7
|
*
|
|
8
8
|
* Key concepts:
|
|
9
|
-
* - Tool definition with Tool<TContext, TArgs, TResult
|
|
9
|
+
* - Tool definition with Tool<TContext, TData, TArgs, TResult> interface
|
|
10
10
|
* - Tool context and parameters
|
|
11
11
|
* - Tool execution in conversation flows
|
|
12
12
|
* - Error handling in tools
|
|
@@ -36,7 +36,7 @@ interface SearchData {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
// Example 1: Simple Calculator Tool
|
|
39
|
-
const calculatorTool: Tool<unknown, [], string
|
|
39
|
+
const calculatorTool: Tool<unknown, UnifiedToolData, [], string> = {
|
|
40
40
|
id: "calculator",
|
|
41
41
|
name: "Math Calculator",
|
|
42
42
|
description: "Evaluate mathematical expressions and return results",
|
|
@@ -51,8 +51,7 @@ const calculatorTool: Tool<unknown, [], string, CalculatorData> = {
|
|
|
51
51
|
required: ["expression"],
|
|
52
52
|
},
|
|
53
53
|
handler: ({ data }) => {
|
|
54
|
-
|
|
55
|
-
if (!calcData?.expression) {
|
|
54
|
+
if (!data?.expression) {
|
|
56
55
|
throw new Error("No expression provided");
|
|
57
56
|
}
|
|
58
57
|
|
|
@@ -60,22 +59,22 @@ const calculatorTool: Tool<unknown, [], string, CalculatorData> = {
|
|
|
60
59
|
// Simple expression evaluation (in production, use a safe math library)
|
|
61
60
|
// WARNING: eval is unsafe - use a proper math evaluation library in production
|
|
62
61
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
63
|
-
const result = eval(
|
|
62
|
+
const result = eval(data.expression);
|
|
64
63
|
|
|
65
64
|
if (typeof result !== "number" || isNaN(result)) {
|
|
66
65
|
throw new Error("Invalid calculation result");
|
|
67
66
|
}
|
|
68
67
|
|
|
69
68
|
return {
|
|
70
|
-
data: `The result of ${
|
|
69
|
+
data: `The result of ${data.expression} is ${result}`,
|
|
71
70
|
dataUpdate: {
|
|
72
71
|
result,
|
|
73
|
-
operation:
|
|
72
|
+
operation: data.expression,
|
|
74
73
|
},
|
|
75
74
|
};
|
|
76
75
|
} catch (error) {
|
|
77
76
|
throw new Error(
|
|
78
|
-
`Error calculating ${
|
|
77
|
+
`Error calculating ${data.expression}: ${
|
|
79
78
|
error instanceof Error ? error.message : "Unknown error"
|
|
80
79
|
}`
|
|
81
80
|
);
|
|
@@ -84,7 +83,7 @@ const calculatorTool: Tool<unknown, [], string, CalculatorData> = {
|
|
|
84
83
|
};
|
|
85
84
|
|
|
86
85
|
// Example 2: Weather Tool with External API Simulation
|
|
87
|
-
const weatherTool: Tool<unknown, [], string
|
|
86
|
+
const weatherTool: Tool<unknown, UnifiedToolData, [], string> = {
|
|
88
87
|
id: "get_weather",
|
|
89
88
|
name: "Weather Lookup",
|
|
90
89
|
description: "Get current weather and forecast for a location",
|
|
@@ -96,8 +95,7 @@ const weatherTool: Tool<unknown, [], string, WeatherData> = {
|
|
|
96
95
|
required: ["location"],
|
|
97
96
|
},
|
|
98
97
|
handler: async ({ data }) => {
|
|
99
|
-
|
|
100
|
-
if (!weatherData?.location) {
|
|
98
|
+
if (!data?.location) {
|
|
101
99
|
throw new Error("No location provided");
|
|
102
100
|
}
|
|
103
101
|
|
|
@@ -127,14 +125,14 @@ const weatherTool: Tool<unknown, [], string, WeatherData> = {
|
|
|
127
125
|
},
|
|
128
126
|
};
|
|
129
127
|
|
|
130
|
-
const weather = mockWeather[
|
|
128
|
+
const weather = mockWeather[data.location] || {
|
|
131
129
|
temp: 70,
|
|
132
130
|
condition: "Unknown",
|
|
133
131
|
forecast: "Weather data unavailable",
|
|
134
132
|
};
|
|
135
133
|
|
|
136
134
|
return {
|
|
137
|
-
data: `Weather in ${
|
|
135
|
+
data: `Weather in ${data.location}: ${weather.temp}°F and ${weather.condition}. ${weather.forecast}`,
|
|
138
136
|
dataUpdate: {
|
|
139
137
|
temperature: weather.temp,
|
|
140
138
|
condition: weather.condition,
|
|
@@ -145,7 +143,7 @@ const weatherTool: Tool<unknown, [], string, WeatherData> = {
|
|
|
145
143
|
};
|
|
146
144
|
|
|
147
145
|
// Example 3: Search Tool with Multiple Results
|
|
148
|
-
const searchTool: Tool<unknown, [], string
|
|
146
|
+
const searchTool: Tool<unknown, UnifiedToolData, [], string> = {
|
|
149
147
|
id: "web_search",
|
|
150
148
|
name: "Web Search",
|
|
151
149
|
description: "Search the web for information on a given query",
|
|
@@ -157,8 +155,7 @@ const searchTool: Tool<unknown, [], string, SearchData> = {
|
|
|
157
155
|
required: ["query"],
|
|
158
156
|
},
|
|
159
157
|
handler: async ({ data }) => {
|
|
160
|
-
|
|
161
|
-
if (!searchData?.query) {
|
|
158
|
+
if (!data?.query) {
|
|
162
159
|
throw new Error("No search query provided");
|
|
163
160
|
}
|
|
164
161
|
|
|
@@ -187,15 +184,15 @@ const searchTool: Tool<unknown, [], string, SearchData> = {
|
|
|
187
184
|
],
|
|
188
185
|
};
|
|
189
186
|
|
|
190
|
-
const results = mockResults[
|
|
191
|
-
`Search results for "${
|
|
187
|
+
const results = mockResults[data.query.toLowerCase()] || [
|
|
188
|
+
`Search results for "${data.query}"`,
|
|
192
189
|
"This is a simulated search result",
|
|
193
190
|
"In a real implementation, this would connect to a search API",
|
|
194
191
|
"Such as Google Custom Search, Bing Web Search, or Elasticsearch",
|
|
195
192
|
];
|
|
196
193
|
|
|
197
194
|
return {
|
|
198
|
-
data: `Search results for "${
|
|
195
|
+
data: `Search results for "${data.query}":\n${results
|
|
199
196
|
.map((r, i) => `${i + 1}. ${r}`)
|
|
200
197
|
.join("\n")}`,
|
|
201
198
|
dataUpdate: {
|
|
@@ -209,9 +206,9 @@ const searchTool: Tool<unknown, [], string, SearchData> = {
|
|
|
209
206
|
// Example 4: Tool that Modifies Context (Advanced)
|
|
210
207
|
const updatePreferencesTool: Tool<
|
|
211
208
|
{ preferences?: { theme: string; language: string } },
|
|
209
|
+
UnifiedToolData,
|
|
212
210
|
[],
|
|
213
|
-
string
|
|
214
|
-
{ theme?: string; language?: string }
|
|
211
|
+
string
|
|
215
212
|
> = {
|
|
216
213
|
id: "update_preferences",
|
|
217
214
|
name: "Update Preferences",
|
|
@@ -242,29 +239,54 @@ const updatePreferencesTool: Tool<
|
|
|
242
239
|
},
|
|
243
240
|
};
|
|
244
241
|
|
|
242
|
+
// Define unified data schema for all tool interactions
|
|
243
|
+
interface UnifiedToolData extends CalculatorData, WeatherData, SearchData {
|
|
244
|
+
theme?: string;
|
|
245
|
+
language?: string;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const unifiedToolSchema = {
|
|
249
|
+
type: "object",
|
|
250
|
+
properties: {
|
|
251
|
+
// Calculator fields
|
|
252
|
+
expression: { type: "string" },
|
|
253
|
+
result: { type: "number" },
|
|
254
|
+
operation: { type: "string" },
|
|
255
|
+
// Weather fields
|
|
256
|
+
location: { type: "string" },
|
|
257
|
+
temperature: { type: "number" },
|
|
258
|
+
condition: { type: "string" },
|
|
259
|
+
forecast: { type: "string" },
|
|
260
|
+
// Search fields
|
|
261
|
+
query: { type: "string" },
|
|
262
|
+
results: { type: "array", items: { type: "string" } },
|
|
263
|
+
source: { type: "string" },
|
|
264
|
+
// Preferences fields
|
|
265
|
+
theme: { type: "string", enum: ["light", "dark"] },
|
|
266
|
+
language: { type: "string", enum: ["en", "es", "fr"] },
|
|
267
|
+
},
|
|
268
|
+
};
|
|
269
|
+
|
|
245
270
|
// Create agent with tools
|
|
246
|
-
const agent = new Agent<{ preferences?: { theme: string; language: string } }>({
|
|
271
|
+
const agent = new Agent<{ preferences?: { theme: string; language: string } }, UnifiedToolData>({
|
|
247
272
|
name: "ToolBot",
|
|
248
273
|
description: "An agent demonstrating various tool capabilities",
|
|
249
274
|
provider: new GeminiProvider({
|
|
250
275
|
apiKey: process.env.GEMINI_API_KEY!,
|
|
251
276
|
model: "models/gemini-2.5-flash",
|
|
252
277
|
}),
|
|
278
|
+
// NEW: Agent-level schema
|
|
279
|
+
schema: unifiedToolSchema,
|
|
253
280
|
});
|
|
254
281
|
|
|
255
282
|
// Create routes that use different tools
|
|
256
|
-
agent.createRoute
|
|
283
|
+
agent.createRoute({
|
|
257
284
|
title: "Calculator",
|
|
258
285
|
description: "Mathematical calculations",
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
result: { type: "number" },
|
|
264
|
-
operation: { type: "string" },
|
|
265
|
-
},
|
|
266
|
-
required: ["expression"],
|
|
267
|
-
},
|
|
286
|
+
// NEW: Required fields for route completion
|
|
287
|
+
requiredFields: ["expression"],
|
|
288
|
+
// NEW: Optional fields that enhance the experience
|
|
289
|
+
optionalFields: ["result", "operation"],
|
|
268
290
|
steps: [
|
|
269
291
|
{
|
|
270
292
|
id: "get_expression",
|
|
@@ -283,19 +305,13 @@ agent.createRoute<CalculatorData>({
|
|
|
283
305
|
],
|
|
284
306
|
});
|
|
285
307
|
|
|
286
|
-
agent.createRoute
|
|
308
|
+
agent.createRoute({
|
|
287
309
|
title: "Weather",
|
|
288
310
|
description: "Weather information",
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
temperature: { type: "number" },
|
|
294
|
-
condition: { type: "string" },
|
|
295
|
-
forecast: { type: "string" },
|
|
296
|
-
},
|
|
297
|
-
required: ["location"],
|
|
298
|
-
},
|
|
311
|
+
// NEW: Required fields for route completion
|
|
312
|
+
requiredFields: ["location"],
|
|
313
|
+
// NEW: Optional fields that enhance the experience
|
|
314
|
+
optionalFields: ["temperature", "condition", "forecast"],
|
|
299
315
|
steps: [
|
|
300
316
|
{
|
|
301
317
|
id: "get_location",
|
|
@@ -314,18 +330,13 @@ agent.createRoute<WeatherData>({
|
|
|
314
330
|
],
|
|
315
331
|
});
|
|
316
332
|
|
|
317
|
-
agent.createRoute
|
|
333
|
+
agent.createRoute({
|
|
318
334
|
title: "Web Search",
|
|
319
335
|
description: "Information search",
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
results: { type: "array", items: { type: "string" } },
|
|
325
|
-
source: { type: "string" },
|
|
326
|
-
},
|
|
327
|
-
required: ["query"],
|
|
328
|
-
},
|
|
336
|
+
// NEW: Required fields for route completion
|
|
337
|
+
requiredFields: ["query"],
|
|
338
|
+
// NEW: Optional fields that enhance the experience
|
|
339
|
+
optionalFields: ["results", "source"],
|
|
329
340
|
steps: [
|
|
330
341
|
{
|
|
331
342
|
id: "get_query",
|
|
@@ -371,7 +382,7 @@ async function demonstrateBasicTools() {
|
|
|
371
382
|
console.log("Bot:", calcResponse.message);
|
|
372
383
|
console.log(
|
|
373
384
|
"Calculated result:",
|
|
374
|
-
|
|
385
|
+
calcResponse.session?.data?.result
|
|
375
386
|
);
|
|
376
387
|
console.log();
|
|
377
388
|
|
|
@@ -383,9 +394,9 @@ async function demonstrateBasicTools() {
|
|
|
383
394
|
});
|
|
384
395
|
console.log("Bot:", weatherResponse.message);
|
|
385
396
|
console.log("Weather data:", {
|
|
386
|
-
temperature: (weatherResponse.session?.data as Partial<
|
|
397
|
+
temperature: (weatherResponse.session?.data as Partial<UnifiedToolData>)
|
|
387
398
|
?.temperature,
|
|
388
|
-
condition: (weatherResponse.session?.data as Partial<
|
|
399
|
+
condition: (weatherResponse.session?.data as Partial<UnifiedToolData>)
|
|
389
400
|
?.condition,
|
|
390
401
|
});
|
|
391
402
|
console.log();
|
|
@@ -404,7 +415,7 @@ async function demonstrateBasicTools() {
|
|
|
404
415
|
console.log("Bot:", searchResponse.message);
|
|
405
416
|
console.log(
|
|
406
417
|
"Search results count:",
|
|
407
|
-
(searchResponse.session?.data as Partial<
|
|
418
|
+
(searchResponse.session?.data as Partial<UnifiedToolData>)?.results?.length
|
|
408
419
|
);
|
|
409
420
|
}
|
|
410
421
|
|
|
@@ -453,15 +464,15 @@ async function demonstrateToolDataFlow() {
|
|
|
453
464
|
console.log("1. Initial calculation:");
|
|
454
465
|
console.log(
|
|
455
466
|
" User input collected:",
|
|
456
|
-
(response1.session?.data as Partial<
|
|
467
|
+
(response1.session?.data as Partial<UnifiedToolData>)?.expression
|
|
457
468
|
);
|
|
458
469
|
console.log(
|
|
459
470
|
" Tool result:",
|
|
460
|
-
(response1.session?.data as Partial<
|
|
471
|
+
(response1.session?.data as Partial<UnifiedToolData>)?.result
|
|
461
472
|
);
|
|
462
473
|
console.log(
|
|
463
474
|
" Operation stored:",
|
|
464
|
-
(response1.session?.data as Partial<
|
|
475
|
+
(response1.session?.data as Partial<UnifiedToolData>)?.operation
|
|
465
476
|
);
|
|
466
477
|
|
|
467
478
|
// Follow up question using previous result
|
|
@@ -475,7 +486,7 @@ async function demonstrateToolDataFlow() {
|
|
|
475
486
|
console.log("\n2. Follow-up calculation:");
|
|
476
487
|
console.log(
|
|
477
488
|
" Previous result available:",
|
|
478
|
-
(response2.session?.data as Partial<
|
|
489
|
+
(response2.session?.data as Partial<UnifiedToolData>)?.result
|
|
479
490
|
);
|
|
480
491
|
console.log(" Bot response:", response2.message);
|
|
481
492
|
}
|
|
@@ -486,7 +497,7 @@ function demonstrateToolPatterns() {
|
|
|
486
497
|
|
|
487
498
|
console.log("1. Basic Tool Pattern:");
|
|
488
499
|
console.log(`
|
|
489
|
-
const myTool: Tool<ContextType, [], ResultType
|
|
500
|
+
const myTool: Tool<ContextType, DataType, [], ResultType> = {
|
|
490
501
|
id: "tool_name", // Unique identifier
|
|
491
502
|
description: "What this tool does", // AI uses this to decide when to call
|
|
492
503
|
parameters: { // JSON Schema for tool parameters
|