@falai/agent 0.4.1 → 0.5.1
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 +55 -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 +77 -0
- package/dist/cjs/types/session.d.ts.map +1 -0
- package/dist/cjs/types/session.js +146 -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 +55 -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 +77 -0
- package/dist/types/session.d.ts.map +1 -0
- package/dist/types/session.js +138 -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 +329 -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 +668 -356
- package/src/core/Events.ts +12 -2
- package/src/core/PersistenceManager.ts +81 -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 +219 -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,14 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Example: Using Redis for Persistence
|
|
2
|
+
* Example: Using Redis for Persistence with Session State
|
|
3
3
|
*
|
|
4
4
|
* Fast, in-memory persistence perfect for:
|
|
5
5
|
* - High-throughput applications
|
|
6
|
-
* - Session caching
|
|
6
|
+
* - Session caching with extracted data
|
|
7
7
|
* - Real-time chat applications
|
|
8
8
|
* - Temporary conversation storage
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
Agent,
|
|
13
|
+
GeminiProvider,
|
|
14
|
+
RedisAdapter,
|
|
15
|
+
createMessageEvent,
|
|
16
|
+
EventSource,
|
|
17
|
+
MessageEventData,
|
|
18
|
+
Event,
|
|
19
|
+
} from "../src/index";
|
|
12
20
|
// @ts-ignore
|
|
13
21
|
import Redis from "ioredis";
|
|
14
22
|
|
|
@@ -25,65 +33,427 @@ import Redis from "ioredis";
|
|
|
25
33
|
* 3. Run this example
|
|
26
34
|
*/
|
|
27
35
|
|
|
36
|
+
interface ChatContext {
|
|
37
|
+
userId: string;
|
|
38
|
+
userName: string;
|
|
39
|
+
chatType: "support" | "sales" | "general";
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
interface SupportTicketData {
|
|
43
|
+
issue: string;
|
|
44
|
+
category: "technical" | "billing" | "account" | "other";
|
|
45
|
+
priority: "low" | "medium" | "high";
|
|
46
|
+
description: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
28
49
|
async function example() {
|
|
29
50
|
// Initialize Redis client
|
|
30
51
|
const redis = new Redis();
|
|
31
52
|
|
|
53
|
+
const userId = "user_123";
|
|
54
|
+
|
|
32
55
|
// Create agent with Redis persistence
|
|
33
|
-
const agent = new Agent({
|
|
34
|
-
name: "
|
|
35
|
-
description: "Fast, real-time
|
|
56
|
+
const agent = new Agent<ChatContext>({
|
|
57
|
+
name: "Support Assistant",
|
|
58
|
+
description: "Fast, real-time support assistant",
|
|
59
|
+
goal: "Help users resolve issues quickly",
|
|
36
60
|
ai: new GeminiProvider({
|
|
37
61
|
apiKey: process.env.GEMINI_API_KEY!,
|
|
38
62
|
model: "models/gemini-2.0-flash-exp",
|
|
39
63
|
}),
|
|
64
|
+
context: {
|
|
65
|
+
userId,
|
|
66
|
+
userName: "Alice",
|
|
67
|
+
chatType: "support",
|
|
68
|
+
},
|
|
40
69
|
// ✨ Redis adapter with custom options
|
|
41
70
|
persistence: {
|
|
42
71
|
adapter: new RedisAdapter({
|
|
43
72
|
redis,
|
|
44
|
-
keyPrefix: "
|
|
73
|
+
keyPrefix: "support:", // Custom prefix
|
|
45
74
|
sessionTTL: 24 * 60 * 60, // 24 hours
|
|
46
75
|
messageTTL: 7 * 24 * 60 * 60, // 7 days
|
|
47
76
|
}),
|
|
48
|
-
autoSave: true,
|
|
49
|
-
userId
|
|
77
|
+
autoSave: true, // Auto-save session state
|
|
78
|
+
userId,
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// Create support ticket route with data gathering
|
|
83
|
+
const ticketRoute = agent.createRoute<SupportTicketData>({
|
|
84
|
+
title: "Create Support Ticket",
|
|
85
|
+
description: "Help user create and track support tickets",
|
|
86
|
+
conditions: [
|
|
87
|
+
"User needs help with an issue",
|
|
88
|
+
"User wants to report a problem",
|
|
89
|
+
"User mentions support, help, or issue",
|
|
90
|
+
],
|
|
91
|
+
gatherSchema: {
|
|
92
|
+
type: "object",
|
|
93
|
+
properties: {
|
|
94
|
+
issue: {
|
|
95
|
+
type: "string",
|
|
96
|
+
description: "Brief summary of the issue",
|
|
97
|
+
},
|
|
98
|
+
category: {
|
|
99
|
+
type: "string",
|
|
100
|
+
enum: ["technical", "billing", "account", "other"],
|
|
101
|
+
description: "Issue category",
|
|
102
|
+
},
|
|
103
|
+
priority: {
|
|
104
|
+
type: "string",
|
|
105
|
+
enum: ["low", "medium", "high"],
|
|
106
|
+
default: "medium",
|
|
107
|
+
description: "Issue priority",
|
|
108
|
+
},
|
|
109
|
+
description: {
|
|
110
|
+
type: "string",
|
|
111
|
+
description: "Detailed description of the issue",
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
required: ["issue", "category", "description"],
|
|
50
115
|
},
|
|
51
116
|
});
|
|
52
117
|
|
|
118
|
+
// State flow
|
|
119
|
+
ticketRoute.initialState
|
|
120
|
+
.transitionTo({
|
|
121
|
+
chatState: "Ask what the issue is",
|
|
122
|
+
gather: ["issue", "category"],
|
|
123
|
+
skipIf: (data) => !!data.issue && !!data.category,
|
|
124
|
+
})
|
|
125
|
+
.transitionTo({
|
|
126
|
+
chatState: "Ask for priority",
|
|
127
|
+
gather: ["priority"],
|
|
128
|
+
skipIf: (data) => !!data.priority,
|
|
129
|
+
requiredData: ["issue", "category"],
|
|
130
|
+
})
|
|
131
|
+
.transitionTo({
|
|
132
|
+
chatState: "Ask for detailed description",
|
|
133
|
+
gather: ["description"],
|
|
134
|
+
skipIf: (data) => !!data.description,
|
|
135
|
+
requiredData: ["issue", "category"],
|
|
136
|
+
})
|
|
137
|
+
.transitionTo({
|
|
138
|
+
chatState: "Confirm and create ticket",
|
|
139
|
+
requiredData: ["issue", "category", "description"],
|
|
140
|
+
});
|
|
141
|
+
|
|
53
142
|
const persistence = agent.getPersistenceManager();
|
|
54
143
|
if (!persistence) return;
|
|
55
144
|
|
|
56
|
-
// Create session
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
145
|
+
// Create session with state support
|
|
146
|
+
const { sessionData, sessionState } =
|
|
147
|
+
await persistence.createSessionWithState<SupportTicketData>({
|
|
148
|
+
userId,
|
|
149
|
+
agentName: "Support Assistant",
|
|
150
|
+
initialData: {
|
|
151
|
+
priority: "medium", // Default priority
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
console.log("✨ Session created in Redis:", sessionData.id);
|
|
156
|
+
console.log("📊 Initial state:", {
|
|
157
|
+
extracted: sessionState.extracted,
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
// Turn 1: User provides issue
|
|
161
|
+
const history: Event<MessageEventData>[] = [];
|
|
162
|
+
let session = sessionState;
|
|
163
|
+
|
|
164
|
+
const message1 = createMessageEvent(
|
|
165
|
+
EventSource.CUSTOMER,
|
|
166
|
+
"Alice",
|
|
167
|
+
"I can't log into my account, it's a technical issue and it's urgent!"
|
|
168
|
+
);
|
|
169
|
+
history.push(message1);
|
|
170
|
+
|
|
171
|
+
const response1 = await agent.respond({
|
|
172
|
+
history,
|
|
173
|
+
session,
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
console.log("\n--- Turn 1 ---");
|
|
177
|
+
console.log("🤖 Agent:", response1.message);
|
|
178
|
+
console.log("📊 Extracted data:", response1.session?.extracted);
|
|
179
|
+
|
|
180
|
+
// Save messages
|
|
181
|
+
await persistence.saveMessage({
|
|
182
|
+
sessionId: sessionData.id,
|
|
183
|
+
role: "user",
|
|
184
|
+
content: message1.data.message,
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
await persistence.saveMessage({
|
|
188
|
+
sessionId: sessionData.id,
|
|
189
|
+
role: "agent",
|
|
190
|
+
content: response1.message,
|
|
191
|
+
route: response1.session?.currentRoute?.id,
|
|
192
|
+
state: response1.session?.currentState?.id,
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
session = response1.session!;
|
|
196
|
+
|
|
197
|
+
// Turn 2: Provide more details
|
|
198
|
+
history.push(
|
|
199
|
+
createMessageEvent(
|
|
200
|
+
EventSource.AI_AGENT,
|
|
201
|
+
"Support Assistant",
|
|
202
|
+
response1.message
|
|
203
|
+
)
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
const message2 = createMessageEvent(
|
|
207
|
+
EventSource.CUSTOMER,
|
|
208
|
+
"Alice",
|
|
209
|
+
"I keep getting 'Invalid credentials' error even though I reset my password"
|
|
210
|
+
);
|
|
211
|
+
history.push(message2);
|
|
212
|
+
|
|
213
|
+
const response2 = await agent.respond({
|
|
214
|
+
history,
|
|
215
|
+
session,
|
|
61
216
|
});
|
|
62
217
|
|
|
63
|
-
console.log("
|
|
218
|
+
console.log("\n--- Turn 2 ---");
|
|
219
|
+
console.log("🤖 Agent:", response2.message);
|
|
220
|
+
console.log("📊 Extracted data:", response2.session?.extracted);
|
|
64
221
|
|
|
65
|
-
// Save a message
|
|
66
222
|
await persistence.saveMessage({
|
|
67
|
-
sessionId:
|
|
223
|
+
sessionId: sessionData.id,
|
|
68
224
|
role: "user",
|
|
69
|
-
content:
|
|
225
|
+
content: message2.data.message,
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
await persistence.saveMessage({
|
|
229
|
+
sessionId: sessionData.id,
|
|
230
|
+
role: "agent",
|
|
231
|
+
content: response2.message,
|
|
70
232
|
});
|
|
71
233
|
|
|
72
|
-
// Load
|
|
73
|
-
|
|
74
|
-
|
|
234
|
+
// Load session state from Redis (demonstrates persistence)
|
|
235
|
+
console.log("\n--- Loading Session from Redis ---");
|
|
236
|
+
const loadedSession = await persistence.loadSessionState<SupportTicketData>(
|
|
237
|
+
sessionData.id
|
|
238
|
+
);
|
|
239
|
+
|
|
240
|
+
console.log("📥 Loaded session:", {
|
|
241
|
+
currentRoute: loadedSession?.currentRoute?.title,
|
|
242
|
+
extracted: loadedSession?.extracted,
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
// Get messages
|
|
246
|
+
const messages = await persistence.getSessionMessages(sessionData.id);
|
|
247
|
+
console.log(`\n💬 ${messages.length} messages in session`);
|
|
75
248
|
|
|
76
249
|
// Complete session
|
|
77
|
-
await persistence.completeSession(
|
|
250
|
+
await persistence.completeSession(sessionData.id);
|
|
78
251
|
console.log("✅ Session completed");
|
|
79
252
|
|
|
80
253
|
// Cleanup
|
|
81
254
|
await redis.quit();
|
|
82
255
|
}
|
|
83
256
|
|
|
257
|
+
/**
|
|
258
|
+
* Advanced Example: High-Throughput Chat with Session State
|
|
259
|
+
*/
|
|
260
|
+
async function highThroughputExample() {
|
|
261
|
+
const redis = new Redis();
|
|
262
|
+
|
|
263
|
+
interface QuickChatData {
|
|
264
|
+
topic: string;
|
|
265
|
+
sentiment: "positive" | "neutral" | "negative";
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const agent = new Agent({
|
|
269
|
+
name: "Chat Bot",
|
|
270
|
+
description: "Fast chat responses",
|
|
271
|
+
ai: new GeminiProvider({
|
|
272
|
+
apiKey: process.env.GEMINI_API_KEY!,
|
|
273
|
+
model: "models/gemini-2.0-flash-exp",
|
|
274
|
+
}),
|
|
275
|
+
persistence: {
|
|
276
|
+
adapter: new RedisAdapter({
|
|
277
|
+
redis,
|
|
278
|
+
keyPrefix: "chat:",
|
|
279
|
+
sessionTTL: 60 * 60, // 1 hour for quick chats
|
|
280
|
+
}),
|
|
281
|
+
autoSave: true,
|
|
282
|
+
userId: "user_456",
|
|
283
|
+
},
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
// Simple chat route that extracts topic and sentiment
|
|
287
|
+
const chatRoute = agent.createRoute<QuickChatData>({
|
|
288
|
+
title: "General Chat",
|
|
289
|
+
gatherSchema: {
|
|
290
|
+
type: "object",
|
|
291
|
+
properties: {
|
|
292
|
+
topic: {
|
|
293
|
+
type: "string",
|
|
294
|
+
description: "Main topic of conversation",
|
|
295
|
+
},
|
|
296
|
+
sentiment: {
|
|
297
|
+
type: "string",
|
|
298
|
+
enum: ["positive", "neutral", "negative"],
|
|
299
|
+
description: "User's sentiment",
|
|
300
|
+
},
|
|
301
|
+
},
|
|
302
|
+
required: ["topic", "sentiment"],
|
|
303
|
+
},
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
chatRoute.initialState.transitionTo({
|
|
307
|
+
chatState: "Chat and extract topic/sentiment",
|
|
308
|
+
gather: ["topic", "sentiment"],
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
const persistence = agent.getPersistenceManager()!;
|
|
312
|
+
|
|
313
|
+
// Create session
|
|
314
|
+
const { sessionData, sessionState } =
|
|
315
|
+
await persistence.createSessionWithState<QuickChatData>({
|
|
316
|
+
userId: "user_456",
|
|
317
|
+
agentName: "Chat Bot",
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
// Quick chat interaction
|
|
321
|
+
const response = await agent.respond({
|
|
322
|
+
history: [
|
|
323
|
+
createMessageEvent(
|
|
324
|
+
EventSource.CUSTOMER,
|
|
325
|
+
"User",
|
|
326
|
+
"I'm loving the new features you added!"
|
|
327
|
+
),
|
|
328
|
+
],
|
|
329
|
+
session: sessionState,
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
console.log("🤖 Response:", response.message);
|
|
333
|
+
console.log("📊 Extracted:", response.session?.extracted);
|
|
334
|
+
console.log("💾 Session state cached in Redis!");
|
|
335
|
+
|
|
336
|
+
await redis.quit();
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Session Recovery Example
|
|
341
|
+
* Shows how to resume conversations from Redis
|
|
342
|
+
*/
|
|
343
|
+
async function sessionRecoveryExample() {
|
|
344
|
+
const redis = new Redis();
|
|
345
|
+
|
|
346
|
+
interface OrderData {
|
|
347
|
+
productId: string;
|
|
348
|
+
quantity: number;
|
|
349
|
+
shippingAddress: string;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
const agent = new Agent({
|
|
353
|
+
name: "Order Assistant",
|
|
354
|
+
ai: new GeminiProvider({
|
|
355
|
+
apiKey: process.env.GEMINI_API_KEY!,
|
|
356
|
+
model: "models/gemini-2.0-flash-exp",
|
|
357
|
+
}),
|
|
358
|
+
persistence: {
|
|
359
|
+
adapter: new RedisAdapter({ redis }),
|
|
360
|
+
autoSave: true,
|
|
361
|
+
userId: "user_789",
|
|
362
|
+
},
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
const orderRoute = agent.createRoute<OrderData>({
|
|
366
|
+
title: "Place Order",
|
|
367
|
+
gatherSchema: {
|
|
368
|
+
type: "object",
|
|
369
|
+
properties: {
|
|
370
|
+
productId: { type: "string" },
|
|
371
|
+
quantity: { type: "number", minimum: 1 },
|
|
372
|
+
shippingAddress: { type: "string" },
|
|
373
|
+
},
|
|
374
|
+
required: ["productId", "quantity", "shippingAddress"],
|
|
375
|
+
},
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
orderRoute.initialState
|
|
379
|
+
.transitionTo({
|
|
380
|
+
chatState: "Ask what to order",
|
|
381
|
+
gather: ["productId", "quantity"],
|
|
382
|
+
})
|
|
383
|
+
.transitionTo({
|
|
384
|
+
chatState: "Ask for shipping address",
|
|
385
|
+
gather: ["shippingAddress"],
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
const persistence = agent.getPersistenceManager()!;
|
|
389
|
+
|
|
390
|
+
// Start a new session
|
|
391
|
+
const { sessionData, sessionState } =
|
|
392
|
+
await persistence.createSessionWithState<OrderData>({
|
|
393
|
+
userId: "user_789",
|
|
394
|
+
agentName: "Order Assistant",
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
const sessionId = sessionData.id;
|
|
398
|
+
|
|
399
|
+
console.log("✨ New order session:", sessionId);
|
|
400
|
+
|
|
401
|
+
// First interaction
|
|
402
|
+
const response1 = await agent.respond({
|
|
403
|
+
history: [
|
|
404
|
+
createMessageEvent(
|
|
405
|
+
EventSource.CUSTOMER,
|
|
406
|
+
"User",
|
|
407
|
+
"I want to order product ABC123, 2 units"
|
|
408
|
+
),
|
|
409
|
+
],
|
|
410
|
+
session: sessionState,
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
console.log("🤖 Response:", response1.message);
|
|
414
|
+
console.log("📊 Extracted so far:", response1.session?.extracted);
|
|
415
|
+
|
|
416
|
+
// --- Simulate user disconnecting and reconnecting ---
|
|
417
|
+
console.log("\n--- User Reconnects ---");
|
|
418
|
+
|
|
419
|
+
// Load session from Redis
|
|
420
|
+
const recoveredSession = await persistence.loadSessionState<OrderData>(
|
|
421
|
+
sessionId
|
|
422
|
+
);
|
|
423
|
+
|
|
424
|
+
console.log("📥 Recovered session state:", {
|
|
425
|
+
currentRoute: recoveredSession?.currentRoute?.title,
|
|
426
|
+
extracted: recoveredSession?.extracted,
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
// Load message history
|
|
430
|
+
const history = await persistence.loadSessionHistory(sessionId);
|
|
431
|
+
console.log(`📜 Loaded ${history.length} messages from history`);
|
|
432
|
+
|
|
433
|
+
// Continue conversation
|
|
434
|
+
history.push(
|
|
435
|
+
createMessageEvent(
|
|
436
|
+
EventSource.CUSTOMER,
|
|
437
|
+
"User",
|
|
438
|
+
"Ship to 123 Main St, New York"
|
|
439
|
+
)
|
|
440
|
+
);
|
|
441
|
+
|
|
442
|
+
const response2 = await agent.respond({
|
|
443
|
+
history,
|
|
444
|
+
session: recoveredSession!,
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
console.log("🤖 Response:", response2.message);
|
|
448
|
+
console.log("📊 Final extracted data:", response2.session?.extracted);
|
|
449
|
+
console.log("✅ Order complete with recovered session!");
|
|
450
|
+
|
|
451
|
+
await redis.quit();
|
|
452
|
+
}
|
|
453
|
+
|
|
84
454
|
// Run the example
|
|
85
455
|
if (require.main === module) {
|
|
86
456
|
example().catch(console.error);
|
|
87
457
|
}
|
|
88
458
|
|
|
89
|
-
export { example };
|
|
459
|
+
export { example, highThroughputExample, sessionRecoveryExample };
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Rules & Prohibitions Example
|
|
3
|
+
* Updated for v2 architecture with session state management
|
|
3
4
|
*
|
|
4
5
|
* Demonstrates how to use rules and prohibitions to control agent behavior
|
|
5
6
|
* in different conversation routes (e.g., WhatsApp bot with different styles)
|
|
6
7
|
*/
|
|
7
8
|
|
|
8
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
Agent,
|
|
11
|
+
createMessageEvent,
|
|
12
|
+
EventSource,
|
|
13
|
+
createSession,
|
|
14
|
+
} from "../src/index";
|
|
9
15
|
import { AnthropicProvider } from "../src/providers";
|
|
10
16
|
|
|
11
17
|
// Initialize AI provider
|
|
@@ -137,11 +143,17 @@ async function demonstrateRulesAndProhibitions() {
|
|
|
137
143
|
),
|
|
138
144
|
];
|
|
139
145
|
|
|
140
|
-
|
|
141
|
-
|
|
146
|
+
// Initialize session state for multi-turn conversation
|
|
147
|
+
let session = createSession();
|
|
148
|
+
|
|
149
|
+
const response1 = await agent.respond({ history: history1, session });
|
|
150
|
+
console.log(`Route: ${response1.session?.currentRoute?.title}`);
|
|
142
151
|
console.log(`Response: ${response1.message}`);
|
|
143
152
|
console.log(`Expected: Short, direct, max 1 emoji\n`);
|
|
144
153
|
|
|
154
|
+
// Update session with progress
|
|
155
|
+
session = response1.session!;
|
|
156
|
+
|
|
145
157
|
// Example 2: Sales Consultation - Should be engaging and value-focused
|
|
146
158
|
console.log("2️⃣ Sales Consultation Route (conversational, value-first)");
|
|
147
159
|
const history2 = [
|
|
@@ -152,11 +164,14 @@ async function demonstrateRulesAndProhibitions() {
|
|
|
152
164
|
),
|
|
153
165
|
];
|
|
154
166
|
|
|
155
|
-
const response2 = await agent.respond({ history: history2 });
|
|
156
|
-
console.log(`Route: ${response2.
|
|
167
|
+
const response2 = await agent.respond({ history: history2, session });
|
|
168
|
+
console.log(`Route: ${response2.session?.currentRoute?.title}`);
|
|
157
169
|
console.log(`Response: ${response2.message}`);
|
|
158
170
|
console.log(`Expected: Ask about needs, show value before price\n`);
|
|
159
171
|
|
|
172
|
+
// Update session again
|
|
173
|
+
session = response2.session!;
|
|
174
|
+
|
|
160
175
|
// Example 3: Technical Support - Should be detailed and step-by-step
|
|
161
176
|
console.log("3️⃣ Technical Support Route (detailed, step-by-step)");
|
|
162
177
|
const history3 = [
|
|
@@ -167,11 +182,14 @@ async function demonstrateRulesAndProhibitions() {
|
|
|
167
182
|
),
|
|
168
183
|
];
|
|
169
184
|
|
|
170
|
-
const response3 = await agent.respond({ history: history3 });
|
|
171
|
-
console.log(`Route: ${response3.
|
|
185
|
+
const response3 = await agent.respond({ history: history3, session });
|
|
186
|
+
console.log(`Route: ${response3.session?.currentRoute?.title}`);
|
|
172
187
|
console.log(`Response: ${response3.message}`);
|
|
173
188
|
console.log(`Expected: Clear steps, simple language, patient\n`);
|
|
174
189
|
|
|
190
|
+
// Update session again
|
|
191
|
+
session = response3.session!;
|
|
192
|
+
|
|
175
193
|
// Example 4: Emergency Support - Should be calm and action-oriented
|
|
176
194
|
console.log("4️⃣ Emergency Support Route (urgent, professional)");
|
|
177
195
|
const history4 = [
|
|
@@ -182,19 +200,22 @@ async function demonstrateRulesAndProhibitions() {
|
|
|
182
200
|
),
|
|
183
201
|
];
|
|
184
202
|
|
|
185
|
-
const response4 = await agent.respond({ history: history4 });
|
|
186
|
-
console.log(`Route: ${response4.
|
|
203
|
+
const response4 = await agent.respond({ history: history4, session });
|
|
204
|
+
console.log(`Route: ${response4.session?.currentRoute?.title}`);
|
|
187
205
|
console.log(`Response: ${response4.message}`);
|
|
188
206
|
console.log(`Expected: Acknowledge urgency, no emojis, concrete steps\n`);
|
|
189
207
|
|
|
208
|
+
// Update session again
|
|
209
|
+
session = response4.session!;
|
|
210
|
+
|
|
190
211
|
// Example 5: General Chat - Should be friendly and casual
|
|
191
212
|
console.log("5️⃣ General Chat Route (friendly, casual)");
|
|
192
213
|
const history5 = [
|
|
193
214
|
createMessageEvent(EventSource.CUSTOMER, "Eve", "Hey! How's it going?"),
|
|
194
215
|
];
|
|
195
216
|
|
|
196
|
-
const response5 = await agent.respond({ history: history5 });
|
|
197
|
-
console.log(`Route: ${response5.
|
|
217
|
+
const response5 = await agent.respond({ history: history5, session });
|
|
218
|
+
console.log(`Route: ${response5.session?.currentRoute?.title}`);
|
|
198
219
|
console.log(`Response: ${response5.message}`);
|
|
199
220
|
console.log(`Expected: Friendly, emojis, mirrors customer tone\n`);
|
|
200
221
|
}
|