@falai/agent 0.3.11 → 0.3.12

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.
Files changed (71) hide show
  1. package/README.md +92 -0
  2. package/dist/adapters/PrismaAdapter.d.ts +115 -0
  3. package/dist/adapters/PrismaAdapter.d.ts.map +1 -0
  4. package/dist/adapters/PrismaAdapter.js +331 -0
  5. package/dist/adapters/PrismaAdapter.js.map +1 -0
  6. package/dist/adapters/index.d.ts +6 -0
  7. package/dist/adapters/index.d.ts.map +1 -0
  8. package/dist/adapters/index.js +5 -0
  9. package/dist/adapters/index.js.map +1 -0
  10. package/dist/cjs/adapters/PrismaAdapter.d.ts +115 -0
  11. package/dist/cjs/adapters/PrismaAdapter.d.ts.map +1 -0
  12. package/dist/cjs/adapters/PrismaAdapter.js +335 -0
  13. package/dist/cjs/adapters/PrismaAdapter.js.map +1 -0
  14. package/dist/cjs/adapters/index.d.ts +6 -0
  15. package/dist/cjs/adapters/index.d.ts.map +1 -0
  16. package/dist/cjs/adapters/index.js +9 -0
  17. package/dist/cjs/adapters/index.js.map +1 -0
  18. package/dist/cjs/core/Agent.d.ts +10 -0
  19. package/dist/cjs/core/Agent.d.ts.map +1 -1
  20. package/dist/cjs/core/Agent.js +23 -0
  21. package/dist/cjs/core/Agent.js.map +1 -1
  22. package/dist/cjs/core/PersistenceManager.d.ts +77 -0
  23. package/dist/cjs/core/PersistenceManager.d.ts.map +1 -0
  24. package/dist/cjs/core/PersistenceManager.js +153 -0
  25. package/dist/cjs/core/PersistenceManager.js.map +1 -0
  26. package/dist/cjs/index.d.ts +4 -0
  27. package/dist/cjs/index.d.ts.map +1 -1
  28. package/dist/cjs/index.js +6 -1
  29. package/dist/cjs/index.js.map +1 -1
  30. package/dist/cjs/types/agent.d.ts +3 -0
  31. package/dist/cjs/types/agent.d.ts.map +1 -1
  32. package/dist/cjs/types/agent.js.map +1 -1
  33. package/dist/cjs/types/index.d.ts +1 -0
  34. package/dist/cjs/types/index.d.ts.map +1 -1
  35. package/dist/cjs/types/persistence.d.ts +194 -0
  36. package/dist/cjs/types/persistence.d.ts.map +1 -0
  37. package/dist/cjs/types/persistence.js +7 -0
  38. package/dist/cjs/types/persistence.js.map +1 -0
  39. package/dist/core/Agent.d.ts +10 -0
  40. package/dist/core/Agent.d.ts.map +1 -1
  41. package/dist/core/Agent.js +23 -0
  42. package/dist/core/Agent.js.map +1 -1
  43. package/dist/core/PersistenceManager.d.ts +77 -0
  44. package/dist/core/PersistenceManager.d.ts.map +1 -0
  45. package/dist/core/PersistenceManager.js +149 -0
  46. package/dist/core/PersistenceManager.js.map +1 -0
  47. package/dist/index.d.ts +4 -0
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +3 -0
  50. package/dist/index.js.map +1 -1
  51. package/dist/types/agent.d.ts +3 -0
  52. package/dist/types/agent.d.ts.map +1 -1
  53. package/dist/types/agent.js.map +1 -1
  54. package/dist/types/index.d.ts +1 -0
  55. package/dist/types/index.d.ts.map +1 -1
  56. package/dist/types/persistence.d.ts +194 -0
  57. package/dist/types/persistence.d.ts.map +1 -0
  58. package/dist/types/persistence.js +6 -0
  59. package/dist/types/persistence.js.map +1 -0
  60. package/docs/PERSISTENCE.md +419 -0
  61. package/examples/prisma-persistence.ts +313 -0
  62. package/examples/prisma-schema.example.prisma +74 -0
  63. package/package.json +9 -1
  64. package/src/adapters/PrismaAdapter.ts +510 -0
  65. package/src/adapters/index.ts +10 -0
  66. package/src/core/Agent.ts +31 -0
  67. package/src/core/PersistenceManager.ts +222 -0
  68. package/src/index.ts +21 -0
  69. package/src/types/agent.ts +3 -0
  70. package/src/types/index.ts +14 -0
  71. package/src/types/persistence.ts +234 -0
@@ -0,0 +1,313 @@
1
+ /**
2
+ * Example: Using Prisma ORM for Persistence
3
+ *
4
+ * This example shows how to use @falai/agent with Prisma for automatic
5
+ * session and message persistence - as easy as using an AI provider!
6
+ */
7
+
8
+ import {
9
+ Agent,
10
+ GeminiProvider,
11
+ PrismaAdapter,
12
+ createMessageEvent,
13
+ EventSource,
14
+ } from "../src/index";
15
+
16
+ // @ts-ignore
17
+ import { PrismaClient } from "@prisma/client";
18
+
19
+ /**
20
+ * Setup Steps:
21
+ *
22
+ * 1. Install dependencies:
23
+ * npm install prisma @prisma/client
24
+ *
25
+ * 2. Initialize Prisma:
26
+ * npx prisma init
27
+ *
28
+ * 3. Copy schema from examples/prisma-schema.example.prisma
29
+ * to your prisma/schema.prisma file
30
+ *
31
+ * 4. Generate Prisma client:
32
+ * npx prisma generate
33
+ *
34
+ * 5. Run migrations:
35
+ * npx prisma migrate dev --name init
36
+ */
37
+
38
+ // Example context type
39
+ interface ConversationContext {
40
+ userId: string;
41
+ sessionId: string;
42
+ userName: string;
43
+ preferences: {
44
+ language: string;
45
+ theme: string;
46
+ };
47
+ }
48
+
49
+ async function example() {
50
+ // Initialize Prisma client
51
+ const prisma = new PrismaClient();
52
+
53
+ const userId = "user_123";
54
+
55
+ /**
56
+ * Create Agent with Persistence - Simple Provider Pattern! ✨
57
+ */
58
+ const agent = new Agent<ConversationContext>({
59
+ name: "Shopping Assistant",
60
+ description: "A helpful shopping assistant",
61
+ ai: new GeminiProvider({
62
+ apiKey: process.env.GEMINI_API_KEY!,
63
+ model: "models/gemini-2.0-flash-exp",
64
+ }),
65
+ context: {
66
+ userId,
67
+ sessionId: "", // Will be set when we create/load a session
68
+ userName: "Alice",
69
+ preferences: {
70
+ language: "en",
71
+ theme: "light",
72
+ },
73
+ },
74
+ // ✨ Just pass the adapter - that's it!
75
+ persistence: {
76
+ adapter: new PrismaAdapter({ prisma }),
77
+ autoSave: true,
78
+ userId,
79
+ },
80
+ });
81
+
82
+ /**
83
+ * Get persistence manager from agent
84
+ */
85
+ const persistence = agent.getPersistenceManager();
86
+
87
+ if (!persistence) {
88
+ throw new Error("Persistence not configured");
89
+ }
90
+
91
+ /**
92
+ * Create or find a session
93
+ */
94
+ let session = await persistence.findActiveSession(userId);
95
+
96
+ if (!session) {
97
+ session = await persistence.createSession({
98
+ userId,
99
+ agentName: "Shopping Assistant",
100
+ initialData: {
101
+ language: "en",
102
+ theme: "light",
103
+ },
104
+ });
105
+ console.log("✨ Created new session:", session.id);
106
+ } else {
107
+ console.log("📂 Found active session:", session.id);
108
+ }
109
+
110
+ // Update context with session ID
111
+ await agent.updateContext({
112
+ sessionId: session.id,
113
+ } as Partial<ConversationContext>);
114
+
115
+ /**
116
+ * Load conversation history
117
+ */
118
+ const history = await persistence.loadSessionHistory(session.id);
119
+ console.log(`📜 Loaded ${history.length} messages from history`);
120
+
121
+ /**
122
+ * Send a message
123
+ */
124
+ const userMessage = createMessageEvent(
125
+ EventSource.CUSTOMER,
126
+ "Alice",
127
+ "I'm looking for a winter jacket"
128
+ );
129
+
130
+ // Save user message
131
+ await persistence.saveMessage({
132
+ sessionId: session.id,
133
+ userId,
134
+ role: "user",
135
+ content: "I'm looking for a winter jacket",
136
+ event: userMessage,
137
+ });
138
+
139
+ history.push(userMessage);
140
+
141
+ // Generate agent response
142
+ const response = await agent.respond({ history });
143
+ console.log("🤖 Agent:", response.message);
144
+
145
+ // Save agent message
146
+ await persistence.saveMessage({
147
+ sessionId: session.id,
148
+ userId,
149
+ role: "agent",
150
+ content: response.message,
151
+ route: response.route?.id,
152
+ state: response.state?.id,
153
+ toolCalls: response.toolCalls,
154
+ });
155
+
156
+ /**
157
+ * Query sessions and messages
158
+ */
159
+ const userSessions = await persistence.getUserSessions(userId);
160
+ console.log(`👤 User has ${userSessions.length} total sessions`);
161
+
162
+ const messages = await persistence.getSessionMessages(session.id);
163
+ console.log(`💬 Session has ${messages.length} messages`);
164
+
165
+ /**
166
+ * Complete the session
167
+ */
168
+ await persistence.completeSession(session.id);
169
+ console.log("✅ Session completed");
170
+
171
+ /**
172
+ * Cleanup
173
+ */
174
+ await prisma.$disconnect();
175
+ }
176
+
177
+ /**
178
+ * Advanced Example: Using with Lifecycle Hooks
179
+ */
180
+ async function advancedExample() {
181
+ const prisma = new PrismaClient();
182
+ const userId = "user_123";
183
+
184
+ const agent = new Agent<ConversationContext>({
185
+ name: "Smart Assistant",
186
+ description: "An intelligent assistant with persistent state",
187
+ ai: new GeminiProvider({
188
+ apiKey: process.env.GEMINI_API_KEY!,
189
+ model: "models/gemini-2.0-flash-exp",
190
+ }),
191
+ context: {
192
+ userId,
193
+ sessionId: "",
194
+ userName: "Alice",
195
+ preferences: {
196
+ language: "en",
197
+ theme: "light",
198
+ },
199
+ },
200
+ // Lifecycle hooks for automatic context sync
201
+ hooks: {
202
+ // Load fresh context before each response
203
+ beforeRespond: async (currentContext) => {
204
+ const persistence = agent.getPersistenceManager();
205
+ if (!persistence) return currentContext;
206
+
207
+ const freshSession = await persistence.getSession(
208
+ currentContext.sessionId
209
+ );
210
+ return {
211
+ ...currentContext,
212
+ preferences:
213
+ (
214
+ freshSession?.collectedData as {
215
+ preferences?: typeof currentContext.preferences;
216
+ }
217
+ )?.preferences || currentContext.preferences,
218
+ };
219
+ },
220
+ // Automatically persist context updates
221
+ onContextUpdate: async (newContext) => {
222
+ const persistence = agent.getPersistenceManager();
223
+ if (!persistence) return;
224
+
225
+ await persistence.updateCollectedData(newContext.sessionId, {
226
+ preferences: newContext.preferences,
227
+ });
228
+ },
229
+ },
230
+ // ✨ Same simple adapter pattern!
231
+ persistence: {
232
+ adapter: new PrismaAdapter({ prisma }),
233
+ autoSave: true,
234
+ userId,
235
+ },
236
+ });
237
+
238
+ // Create a session
239
+ const persistence = agent.getPersistenceManager();
240
+ const session = await persistence!.createSession({
241
+ userId,
242
+ agentName: "Smart Assistant",
243
+ });
244
+
245
+ await agent.updateContext({
246
+ sessionId: session.id,
247
+ } as Partial<ConversationContext>);
248
+
249
+ // Now context updates are automatically persisted!
250
+ await agent.updateContext({
251
+ preferences: {
252
+ language: "es",
253
+ theme: "dark",
254
+ },
255
+ } as Partial<ConversationContext>);
256
+
257
+ console.log("🎉 Context updates automatically saved to database!");
258
+
259
+ await prisma.$disconnect();
260
+ }
261
+
262
+ /**
263
+ * Minimal Example - Quick Start
264
+ */
265
+ async function quickStart() {
266
+ const prisma = new PrismaClient();
267
+
268
+ // That's it! Just create the adapter and pass it
269
+ const agent = new Agent({
270
+ name: "My Agent",
271
+ description: "A helpful assistant",
272
+ ai: new GeminiProvider({
273
+ apiKey: process.env.GEMINI_API_KEY!,
274
+ model: "models/gemini-2.5-flash",
275
+ }),
276
+ persistence: {
277
+ adapter: new PrismaAdapter({ prisma }), // ✨ Simple!
278
+ userId: "user_123",
279
+ },
280
+ });
281
+
282
+ // Get persistence manager
283
+ const persistence = agent.getPersistenceManager();
284
+ if (!persistence) return;
285
+
286
+ // Create session
287
+ const session = await persistence.createSession({
288
+ userId: "user_123",
289
+ agentName: "My Agent",
290
+ });
291
+
292
+ // Load history and respond
293
+ const history = await persistence.loadSessionHistory(session.id);
294
+ const response = await agent.respond({ history });
295
+
296
+ // Save message
297
+ await persistence.saveMessage({
298
+ sessionId: session.id,
299
+ role: "agent",
300
+ content: response.message,
301
+ });
302
+
303
+ console.log("✅ Done! Messages automatically saved to Prisma.");
304
+
305
+ await prisma.$disconnect();
306
+ }
307
+
308
+ // Run the example
309
+ if (require.main === module) {
310
+ example().catch(console.error);
311
+ }
312
+
313
+ export { example, advancedExample, quickStart };
@@ -0,0 +1,74 @@
1
+ // This is an example Prisma schema file for @falai/agent persistence
2
+ // Copy and adapt this to your needs
3
+
4
+ datasource db {
5
+ provider = "postgresql" // or "mysql", "sqlite", "sqlserver", "mongodb"
6
+ url = env("DATABASE_URL")
7
+ }
8
+
9
+ generator client {
10
+ provider = "prisma-client-js"
11
+ }
12
+
13
+ // Agent Session model
14
+ // Stores conversation session state
15
+ model AgentSession {
16
+ id String @id @default(cuid())
17
+ userId String? @map("user_id")
18
+ agentName String? @map("agent_name")
19
+ status String @default("active") // "active" | "completed" | "abandoned"
20
+ currentRoute String? @map("current_route")
21
+ currentState String? @map("current_state")
22
+ collectedData Json? @map("collected_data")
23
+ messageCount Int @default(0) @map("message_count")
24
+ lastMessageAt DateTime? @map("last_message_at")
25
+ completedAt DateTime? @map("completed_at")
26
+ createdAt DateTime @default(now()) @map("created_at")
27
+ updatedAt DateTime @updatedAt @map("updated_at")
28
+
29
+ // Relations
30
+ messages AgentMessage[]
31
+
32
+ @@index([userId])
33
+ @@index([status])
34
+ @@index([userId, status])
35
+ @@map("agent_sessions")
36
+ }
37
+
38
+ // Agent Message model
39
+ // Stores individual messages in a conversation
40
+ model AgentMessage {
41
+ id String @id @default(cuid())
42
+ sessionId String @map("session_id")
43
+ userId String? @map("user_id")
44
+ role String // "user" | "agent" | "system"
45
+ content String @db.Text
46
+ route String?
47
+ state String?
48
+ toolCalls Json? @map("tool_calls")
49
+ event Json? // Optional: store full event data
50
+ createdAt DateTime @default(now()) @map("created_at")
51
+
52
+ // Relations
53
+ session AgentSession @relation(fields: [sessionId], references: [id], onDelete: Cascade)
54
+
55
+ @@index([sessionId])
56
+ @@index([userId])
57
+ @@index([sessionId, createdAt])
58
+ @@map("agent_messages")
59
+ }
60
+
61
+ // Alternative: If you want different table names, you can customize:
62
+ //
63
+ // model ConversationSession {
64
+ // id String @id @default(cuid())
65
+ // ...
66
+ // @@map("conversations")
67
+ // }
68
+ //
69
+ // model ChatMessage {
70
+ // id String @id @default(cuid())
71
+ // ...
72
+ // @@map("chat_messages")
73
+ // }
74
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@falai/agent",
3
- "version": "0.3.11",
3
+ "version": "0.3.12",
4
4
  "description": "Standalone, strongly-typed AI Agent framework with route DSL and AI provider strategy",
5
5
  "type": "module",
6
6
  "main": "./dist/cjs/index.js",
@@ -80,5 +80,13 @@
80
80
  "@anthropic-ai/sdk": "^0.65.0",
81
81
  "@google/genai": "^0.3.0",
82
82
  "openai": "^6.3.0"
83
+ },
84
+ "peerDependencies": {
85
+ "@prisma/client": "^5.0.0 || ^6.0.0"
86
+ },
87
+ "peerDependenciesMeta": {
88
+ "@prisma/client": {
89
+ "optional": true
90
+ }
83
91
  }
84
92
  }