@falai/agent 0.1.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.
Files changed (129) hide show
  1. package/README.md +516 -0
  2. package/dist/constants/index.d.ts +5 -0
  3. package/dist/constants/index.d.ts.map +1 -0
  4. package/dist/constants/index.js +5 -0
  5. package/dist/constants/index.js.map +1 -0
  6. package/dist/core/Agent.d.ts +98 -0
  7. package/dist/core/Agent.d.ts.map +1 -0
  8. package/dist/core/Agent.js +248 -0
  9. package/dist/core/Agent.js.map +1 -0
  10. package/dist/core/DomainRegistry.d.ts +26 -0
  11. package/dist/core/DomainRegistry.d.ts.map +1 -0
  12. package/dist/core/DomainRegistry.js +41 -0
  13. package/dist/core/DomainRegistry.js.map +1 -0
  14. package/dist/core/Events.d.ts +19 -0
  15. package/dist/core/Events.d.ts.map +1 -0
  16. package/dist/core/Events.js +79 -0
  17. package/dist/core/Events.js.map +1 -0
  18. package/dist/core/Observation.d.ts +24 -0
  19. package/dist/core/Observation.d.ts.map +1 -0
  20. package/dist/core/Observation.js +35 -0
  21. package/dist/core/Observation.js.map +1 -0
  22. package/dist/core/PromptBuilder.d.ts +121 -0
  23. package/dist/core/PromptBuilder.d.ts.map +1 -0
  24. package/dist/core/PromptBuilder.js +339 -0
  25. package/dist/core/PromptBuilder.js.map +1 -0
  26. package/dist/core/Route.d.ts +46 -0
  27. package/dist/core/Route.d.ts.map +1 -0
  28. package/dist/core/Route.js +113 -0
  29. package/dist/core/Route.js.map +1 -0
  30. package/dist/core/State.d.ts +50 -0
  31. package/dist/core/State.d.ts.map +1 -0
  32. package/dist/core/State.js +110 -0
  33. package/dist/core/State.js.map +1 -0
  34. package/dist/core/Tool.d.ts +31 -0
  35. package/dist/core/Tool.d.ts.map +1 -0
  36. package/dist/core/Tool.js +33 -0
  37. package/dist/core/Tool.js.map +1 -0
  38. package/dist/core/Transition.d.ts +32 -0
  39. package/dist/core/Transition.d.ts.map +1 -0
  40. package/dist/core/Transition.js +59 -0
  41. package/dist/core/Transition.js.map +1 -0
  42. package/dist/index.d.ts +34 -0
  43. package/dist/index.d.ts.map +1 -0
  44. package/dist/index.js +26 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/providers/GeminiProvider.d.ts +40 -0
  47. package/dist/providers/GeminiProvider.d.ts.map +1 -0
  48. package/dist/providers/GeminiProvider.js +126 -0
  49. package/dist/providers/GeminiProvider.js.map +1 -0
  50. package/dist/providers/OpenAIProvider.d.ts +42 -0
  51. package/dist/providers/OpenAIProvider.d.ts.map +1 -0
  52. package/dist/providers/OpenAIProvider.js +164 -0
  53. package/dist/providers/OpenAIProvider.js.map +1 -0
  54. package/dist/providers/OpenRouterProvider.d.ts +46 -0
  55. package/dist/providers/OpenRouterProvider.d.ts.map +1 -0
  56. package/dist/providers/OpenRouterProvider.js +171 -0
  57. package/dist/providers/OpenRouterProvider.js.map +1 -0
  58. package/dist/types/agent.d.ts +105 -0
  59. package/dist/types/agent.d.ts.map +1 -0
  60. package/dist/types/agent.js +18 -0
  61. package/dist/types/agent.js.map +1 -0
  62. package/dist/types/ai.d.ts +78 -0
  63. package/dist/types/ai.d.ts.map +1 -0
  64. package/dist/types/ai.js +5 -0
  65. package/dist/types/ai.js.map +1 -0
  66. package/dist/types/history.d.ts +112 -0
  67. package/dist/types/history.d.ts.map +1 -0
  68. package/dist/types/history.js +34 -0
  69. package/dist/types/history.js.map +1 -0
  70. package/dist/types/index.d.ts +14 -0
  71. package/dist/types/index.d.ts.map +1 -0
  72. package/dist/types/index.js +7 -0
  73. package/dist/types/index.js.map +1 -0
  74. package/dist/types/observation.d.ts +25 -0
  75. package/dist/types/observation.d.ts.map +1 -0
  76. package/dist/types/observation.js +5 -0
  77. package/dist/types/observation.js.map +1 -0
  78. package/dist/types/prompt.d.ts +46 -0
  79. package/dist/types/prompt.d.ts.map +1 -0
  80. package/dist/types/prompt.js +16 -0
  81. package/dist/types/prompt.js.map +1 -0
  82. package/dist/types/route.d.ts +59 -0
  83. package/dist/types/route.d.ts.map +1 -0
  84. package/dist/types/route.js +5 -0
  85. package/dist/types/route.js.map +1 -0
  86. package/dist/types/tool.d.ts +46 -0
  87. package/dist/types/tool.d.ts.map +1 -0
  88. package/dist/types/tool.js +5 -0
  89. package/dist/types/tool.js.map +1 -0
  90. package/dist/utils/retry.d.ts +13 -0
  91. package/dist/utils/retry.d.ts.map +1 -0
  92. package/dist/utils/retry.js +70 -0
  93. package/dist/utils/retry.js.map +1 -0
  94. package/docs/API_REFERENCE.md +517 -0
  95. package/docs/CONSTRUCTOR_OPTIONS.md +256 -0
  96. package/docs/CONTRIBUTING.md +481 -0
  97. package/docs/GETTING_STARTED.md +328 -0
  98. package/docs/PROVIDERS.md +472 -0
  99. package/docs/PUBLISHING.md +174 -0
  100. package/docs/README.md +68 -0
  101. package/docs/STRUCTURE.md +32 -0
  102. package/examples/declarative-agent.ts +217 -0
  103. package/examples/healthcare-agent.ts +283 -0
  104. package/examples/openai-agent.ts +167 -0
  105. package/examples/travel-agent.ts +342 -0
  106. package/package.json +73 -0
  107. package/src/constants/index.ts +5 -0
  108. package/src/core/Agent.ts +307 -0
  109. package/src/core/DomainRegistry.ts +50 -0
  110. package/src/core/Events.ts +101 -0
  111. package/src/core/Observation.ts +46 -0
  112. package/src/core/PromptBuilder.ts +511 -0
  113. package/src/core/Route.ts +136 -0
  114. package/src/core/State.ts +153 -0
  115. package/src/core/Tool.ts +54 -0
  116. package/src/core/Transition.ts +66 -0
  117. package/src/index.ts +83 -0
  118. package/src/providers/GeminiProvider.ts +220 -0
  119. package/src/providers/OpenAIProvider.ts +272 -0
  120. package/src/providers/OpenRouterProvider.ts +282 -0
  121. package/src/types/agent.ts +112 -0
  122. package/src/types/ai.ts +85 -0
  123. package/src/types/history.ts +125 -0
  124. package/src/types/index.ts +56 -0
  125. package/src/types/observation.ts +27 -0
  126. package/src/types/prompt.ts +49 -0
  127. package/src/types/route.ts +68 -0
  128. package/src/types/tool.ts +53 -0
  129. package/src/utils/retry.ts +96 -0
@@ -0,0 +1,342 @@
1
+ /**
2
+ * Travel agent example (abridged from Python version)
3
+ * Demonstrates route DSL, tools, and guidelines
4
+ */
5
+
6
+ import {
7
+ Agent,
8
+ defineTool,
9
+ GeminiProvider,
10
+ END_ROUTE,
11
+ EventSource,
12
+ createMessageEvent,
13
+ } from "../src/index";
14
+
15
+ // Context type for travel agent
16
+ interface TravelContext {
17
+ customerId: string;
18
+ customerName: string;
19
+ }
20
+
21
+ // Tools
22
+ const getAvailableDestinations = defineTool<TravelContext, [], string[]>(
23
+ "get_available_destinations",
24
+ async () => {
25
+ return {
26
+ data: [
27
+ "Paris, France",
28
+ "Tokyo, Japan",
29
+ "Bali, Indonesia",
30
+ "New York, USA",
31
+ ],
32
+ };
33
+ },
34
+ {
35
+ description: "Get list of available travel destinations",
36
+ }
37
+ );
38
+
39
+ const getAvailableFlights = defineTool<
40
+ TravelContext,
41
+ [destination: string],
42
+ string[]
43
+ >(
44
+ "get_available_flights",
45
+ async (_context, destination) => {
46
+ return {
47
+ data: [
48
+ "Flight 123 - June 15, 9:00 AM, $850",
49
+ "Flight 321 - June 16, 2:30 PM, $720",
50
+ "Flight 987 - June 17, 6:45 PM, $680",
51
+ ],
52
+ };
53
+ },
54
+ {
55
+ description: "Get available flights for a destination",
56
+ }
57
+ );
58
+
59
+ const getAlternativeFlights = defineTool<
60
+ TravelContext,
61
+ [destination: string],
62
+ string[]
63
+ >(
64
+ "get_alternative_flights",
65
+ async (_context, destination) => {
66
+ return {
67
+ data: [
68
+ "Flight 485 - June 25, 11:00 AM, $920",
69
+ "Flight 516 - July 2, 4:15 PM, $780",
70
+ ],
71
+ };
72
+ },
73
+ {
74
+ description: "Get alternative flight options with different dates",
75
+ }
76
+ );
77
+
78
+ const bookFlight = defineTool<TravelContext, [flightDetails: string], string>(
79
+ "book_flight",
80
+ async ({ context }, flightDetails) => {
81
+ const confirmationNumber = `TRV-${new Date()
82
+ .toISOString()
83
+ .slice(0, 10)
84
+ .replace(/-/g, "")}-001`;
85
+ return {
86
+ data: `Flight booked: ${flightDetails} for ${context.customerName}. Confirmation number: ${confirmationNumber}`,
87
+ };
88
+ },
89
+ {
90
+ description: "Book a flight with the provided details",
91
+ }
92
+ );
93
+
94
+ const getBookingStatus = defineTool<
95
+ TravelContext,
96
+ [confirmationNumber: string],
97
+ object
98
+ >(
99
+ "get_booking_status",
100
+ async (_context, confirmationNumber) => {
101
+ return {
102
+ data: {
103
+ status: "Confirmed",
104
+ details: "Flight to Paris on June 15, 9:00 AM. Seat 12A assigned.",
105
+ notes: "Check-in opens 24 hours before departure.",
106
+ },
107
+ };
108
+ },
109
+ {
110
+ description: "Get booking status by confirmation number",
111
+ }
112
+ );
113
+
114
+ // Initialize agent
115
+ async function createTravelAgent() {
116
+ const provider = new GeminiProvider({
117
+ apiKey: process.env.GEMINI_API_KEY || "test-key",
118
+ model: "models/gemini-2.0-flash-exp",
119
+ retryConfig: {
120
+ timeout: 60000,
121
+ retries: 3,
122
+ },
123
+ });
124
+
125
+ const agent = new Agent<TravelContext>({
126
+ name: "Walker",
127
+ description:
128
+ "A knowledgeable travel agent who helps book flights, answer travel questions, and manage reservations.",
129
+ goal: "Help customers book travel and manage their reservations",
130
+ ai: provider,
131
+ context: {
132
+ customerId: "test-123",
133
+ customerName: "Test Customer",
134
+ },
135
+ });
136
+
137
+ // Add domain glossary
138
+ agent.createTerm({
139
+ name: "Office Phone Number",
140
+ description:
141
+ "The phone number of our travel agency office, at +1-800-TRAVEL-1",
142
+ synonyms: ["contact number", "customer service number", "support line"],
143
+ });
144
+
145
+ agent.createTerm({
146
+ name: "Travel Insurance",
147
+ description:
148
+ "An optional service that provides coverage for trip cancellations, medical emergencies, lost luggage, and other travel-related issues.",
149
+ synonyms: ["insurance", "trip protection", "travel protection"],
150
+ });
151
+
152
+ // Create flight booking route
153
+ const flightBookingRoute = agent.createRoute({
154
+ title: "Book a Flight",
155
+ description:
156
+ "Helps the customer find and book a flight to their desired destination.",
157
+ conditions: ["The customer wants to book a flight"],
158
+ });
159
+
160
+ // Build the route flow
161
+ const t0 = flightBookingRoute.initialState.transitionTo({
162
+ chatState: "Ask about the destination",
163
+ });
164
+
165
+ const t1 = t0.target.transitionTo({
166
+ chatState: "Ask about preferred travel dates",
167
+ });
168
+
169
+ const t2 = t1.target.transitionTo({
170
+ toolState: getAvailableFlights,
171
+ });
172
+
173
+ const t3 = t2.target.transitionTo({
174
+ chatState: "Present available flights and ask which one works for them",
175
+ });
176
+
177
+ // Happy path: customer selects a flight
178
+ const t4 = t3.target.transitionTo(
179
+ {
180
+ chatState:
181
+ "Collect passenger information and confirm booking details before proceeding",
182
+ },
183
+ "The customer selects a flight"
184
+ );
185
+
186
+ const t5 = t4.target.transitionTo(
187
+ {
188
+ toolState: bookFlight,
189
+ },
190
+ "The customer confirms the booking details"
191
+ );
192
+
193
+ const t6 = t5.target.transitionTo({
194
+ chatState: "Provide confirmation number and booking summary",
195
+ });
196
+
197
+ t6.target.transitionTo({ state: END_ROUTE });
198
+
199
+ // Alternative path: no flights work
200
+ const t7 = t3.target.transitionTo(
201
+ {
202
+ toolState: getAlternativeFlights,
203
+ },
204
+ "None of the flights work for the customer"
205
+ );
206
+
207
+ const t8 = t7.target.transitionTo({
208
+ chatState: "Present alternative flights and ask if any work",
209
+ });
210
+
211
+ // Link back to happy path
212
+ t8.target.transitionTo(
213
+ {
214
+ state: t4.target,
215
+ },
216
+ "The customer selects a flight"
217
+ );
218
+
219
+ // No alternative flights work either
220
+ const t9 = t8.target.transitionTo(
221
+ {
222
+ chatState:
223
+ "Suggest calling our office or visiting our website for more options",
224
+ },
225
+ "None of the alternative flights work either"
226
+ );
227
+
228
+ t9.target.transitionTo({ state: END_ROUTE });
229
+
230
+ // Add route-specific guidelines
231
+ flightBookingRoute.createGuideline({
232
+ condition:
233
+ "The customer mentions they need to travel urgently or it's an emergency",
234
+ action:
235
+ "Direct them to call our office immediately for priority booking assistance",
236
+ });
237
+
238
+ flightBookingRoute.createGuideline({
239
+ condition: "The customer asks about visa requirements",
240
+ action:
241
+ "Inform them that visa requirements vary by destination and nationality, and suggest they check with the embassy or consulate",
242
+ });
243
+
244
+ // Create booking status route
245
+ const bookingStatusRoute = agent.createRoute({
246
+ title: "Check Booking Status",
247
+ description:
248
+ "Retrieves the customer's booking status and provides relevant information.",
249
+ conditions: ["The customer wants to check their booking status"],
250
+ });
251
+
252
+ const s0 = bookingStatusRoute.initialState.transitionTo({
253
+ chatState: "Ask for the confirmation number or booking reference",
254
+ });
255
+
256
+ const s1 = s0.target.transitionTo({
257
+ toolState: getBookingStatus,
258
+ });
259
+
260
+ s1.target.transitionTo(
261
+ {
262
+ chatState:
263
+ "Tell the customer that the booking could not be found and ask them to verify the confirmation number or call the office",
264
+ },
265
+ "The booking could not be found"
266
+ );
267
+
268
+ s1.target.transitionTo(
269
+ {
270
+ chatState:
271
+ "Provide the booking details and confirm everything is in order",
272
+ },
273
+ "The booking is confirmed and all details are correct"
274
+ );
275
+
276
+ s1.target.transitionTo(
277
+ {
278
+ chatState:
279
+ "Present the booking information and mention any issues or pending actions required",
280
+ },
281
+ "The booking has issues or requires customer action"
282
+ );
283
+
284
+ // Global guidelines
285
+ agent.createGuideline({
286
+ condition: "The customer asks about travel insurance",
287
+ action:
288
+ "Explain our travel insurance options, coverage details, and pricing, then offer to add it to their booking",
289
+ });
290
+
291
+ agent.createGuideline({
292
+ condition: "The customer asks to speak with a human agent",
293
+ action:
294
+ "Provide the office phone number and office hours, and offer to help them with anything else in the meantime",
295
+ });
296
+
297
+ agent.createGuideline({
298
+ condition:
299
+ "The customer inquires about something that has nothing to do with travel",
300
+ action:
301
+ "Kindly tell them you cannot assist with off-topic inquiries - do not engage with their request.",
302
+ });
303
+
304
+ return agent;
305
+ }
306
+
307
+ // Example usage
308
+ async function main() {
309
+ const agent = await createTravelAgent();
310
+
311
+ // Simulate a conversation
312
+ const history = [
313
+ createMessageEvent(
314
+ EventSource.CUSTOMER,
315
+ "Customer",
316
+ "Hi, I want to book a flight to Paris"
317
+ ),
318
+ ];
319
+
320
+ console.log("Agent:", agent.name);
321
+ console.log("Description:", agent.description);
322
+ console.log("\nRoutes:", agent.getRoutes().length);
323
+ console.log("Terms:", agent.getTerms().length);
324
+ console.log("Guidelines:", agent.getGuidelines().length);
325
+
326
+ // Print route structure
327
+ const routes = agent.getRoutes();
328
+ for (const route of routes) {
329
+ console.log("\n" + route.describe());
330
+ }
331
+
332
+ // Generate response (would need valid API key)
333
+ // const response = await agent.respond({ history });
334
+ // console.log('\nAgent response:', response.message);
335
+ }
336
+
337
+ // Run if executed directly
338
+ if (import.meta.url === `file://${process.argv[1]}`) {
339
+ main().catch(console.error);
340
+ }
341
+
342
+ export { createTravelAgent };
package/package.json ADDED
@@ -0,0 +1,73 @@
1
+ {
2
+ "name": "@falai/agent",
3
+ "version": "0.1.0",
4
+ "description": "Standalone, strongly-typed AI Agent framework with route DSL and AI provider strategy",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "src",
17
+ "docs",
18
+ "examples",
19
+ "README.md",
20
+ "LICENSE"
21
+ ],
22
+ "publishConfig": {
23
+ "access": "public"
24
+ },
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "https://github.com/gusnips/falai.git"
28
+ },
29
+ "bugs": {
30
+ "url": "https://github.com/gusnips/falai/issues"
31
+ },
32
+ "homepage": "https://github.com/gusnips/falai#readme",
33
+ "scripts": {
34
+ "build": "tsc",
35
+ "dev": "tsc --watch",
36
+ "typecheck": "tsc --noEmit",
37
+ "lint": "eslint src/**/*.ts",
38
+ "lint:fix": "eslint src/**/*.ts --fix",
39
+ "clean": "rm -rf dist",
40
+ "prebuild": "npm run clean",
41
+ "prepublishOnly": "npm run lint && npm run typecheck && npm run build",
42
+ "release:patch": "npm version patch && npm publish",
43
+ "release:minor": "npm version minor && npm publish",
44
+ "release:major": "npm version major && npm publish",
45
+ "release": "npm publish",
46
+ "test": "echo \"Error: no test specified\" && exit 1"
47
+ },
48
+ "keywords": [
49
+ "ai",
50
+ "agent",
51
+ "typescript",
52
+ "conversational-ai",
53
+ "gemini",
54
+ "llm",
55
+ "chatbot",
56
+ "framework",
57
+ "routes",
58
+ "dsl"
59
+ ],
60
+ "author": "Gustavo Salomé <gusnips>",
61
+ "license": "MIT",
62
+ "devDependencies": {
63
+ "@types/node": "^20.11.0",
64
+ "@eslint/js": "^9.17.0",
65
+ "eslint": "^9.17.0",
66
+ "typescript": "^5.3.3",
67
+ "typescript-eslint": "^8.18.2"
68
+ },
69
+ "dependencies": {
70
+ "@google/genai": "^0.3.0",
71
+ "openai": "^6.3.0"
72
+ }
73
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Special marker to end a route/journey
3
+ */
4
+
5
+ export const END_ROUTE = Symbol("END_ROUTE");