@falai/agent 0.3.0 → 0.3.11

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 (114) hide show
  1. package/README.md +257 -24
  2. package/dist/cjs/core/Agent.d.ts +37 -0
  3. package/dist/cjs/core/Agent.d.ts.map +1 -1
  4. package/dist/cjs/core/Agent.js +167 -1
  5. package/dist/cjs/core/Agent.js.map +1 -1
  6. package/dist/cjs/core/DomainRegistry.d.ts +10 -0
  7. package/dist/cjs/core/DomainRegistry.d.ts.map +1 -1
  8. package/dist/cjs/core/DomainRegistry.js +25 -0
  9. package/dist/cjs/core/DomainRegistry.js.map +1 -1
  10. package/dist/cjs/core/PromptBuilder.d.ts +9 -1
  11. package/dist/cjs/core/PromptBuilder.d.ts.map +1 -1
  12. package/dist/cjs/core/PromptBuilder.js +49 -2
  13. package/dist/cjs/core/PromptBuilder.js.map +1 -1
  14. package/dist/cjs/core/Route.d.ts +16 -0
  15. package/dist/cjs/core/Route.d.ts.map +1 -1
  16. package/dist/cjs/core/Route.js +22 -0
  17. package/dist/cjs/core/Route.js.map +1 -1
  18. package/dist/cjs/index.d.ts +2 -0
  19. package/dist/cjs/index.d.ts.map +1 -1
  20. package/dist/cjs/index.js +3 -1
  21. package/dist/cjs/index.js.map +1 -1
  22. package/dist/cjs/providers/AnthropicProvider.d.ts +43 -0
  23. package/dist/cjs/providers/AnthropicProvider.d.ts.map +1 -0
  24. package/dist/cjs/providers/AnthropicProvider.js +328 -0
  25. package/dist/cjs/providers/AnthropicProvider.js.map +1 -0
  26. package/dist/cjs/providers/GeminiProvider.d.ts +4 -1
  27. package/dist/cjs/providers/GeminiProvider.d.ts.map +1 -1
  28. package/dist/cjs/providers/GeminiProvider.js +96 -0
  29. package/dist/cjs/providers/GeminiProvider.js.map +1 -1
  30. package/dist/cjs/providers/OpenAIProvider.d.ts +4 -1
  31. package/dist/cjs/providers/OpenAIProvider.d.ts.map +1 -1
  32. package/dist/cjs/providers/OpenAIProvider.js +115 -0
  33. package/dist/cjs/providers/OpenAIProvider.js.map +1 -1
  34. package/dist/cjs/providers/OpenRouterProvider.d.ts +4 -1
  35. package/dist/cjs/providers/OpenRouterProvider.d.ts.map +1 -1
  36. package/dist/cjs/providers/OpenRouterProvider.js +115 -0
  37. package/dist/cjs/providers/OpenRouterProvider.js.map +1 -1
  38. package/dist/cjs/providers/index.d.ts +13 -0
  39. package/dist/cjs/providers/index.d.ts.map +1 -0
  40. package/dist/cjs/providers/index.js +16 -0
  41. package/dist/cjs/providers/index.js.map +1 -0
  42. package/dist/cjs/types/ai.d.ts +28 -0
  43. package/dist/cjs/types/ai.d.ts.map +1 -1
  44. package/dist/cjs/types/route.d.ts +6 -0
  45. package/dist/cjs/types/route.d.ts.map +1 -1
  46. package/dist/core/Agent.d.ts +37 -0
  47. package/dist/core/Agent.d.ts.map +1 -1
  48. package/dist/core/Agent.js +167 -1
  49. package/dist/core/Agent.js.map +1 -1
  50. package/dist/core/DomainRegistry.d.ts +10 -0
  51. package/dist/core/DomainRegistry.d.ts.map +1 -1
  52. package/dist/core/DomainRegistry.js +25 -0
  53. package/dist/core/DomainRegistry.js.map +1 -1
  54. package/dist/core/PromptBuilder.d.ts +9 -1
  55. package/dist/core/PromptBuilder.d.ts.map +1 -1
  56. package/dist/core/PromptBuilder.js +49 -2
  57. package/dist/core/PromptBuilder.js.map +1 -1
  58. package/dist/core/Route.d.ts +16 -0
  59. package/dist/core/Route.d.ts.map +1 -1
  60. package/dist/core/Route.js +22 -0
  61. package/dist/core/Route.js.map +1 -1
  62. package/dist/index.d.ts +2 -0
  63. package/dist/index.d.ts.map +1 -1
  64. package/dist/index.js +1 -0
  65. package/dist/index.js.map +1 -1
  66. package/dist/providers/AnthropicProvider.d.ts +43 -0
  67. package/dist/providers/AnthropicProvider.d.ts.map +1 -0
  68. package/dist/providers/AnthropicProvider.js +321 -0
  69. package/dist/providers/AnthropicProvider.js.map +1 -0
  70. package/dist/providers/GeminiProvider.d.ts +4 -1
  71. package/dist/providers/GeminiProvider.d.ts.map +1 -1
  72. package/dist/providers/GeminiProvider.js +96 -0
  73. package/dist/providers/GeminiProvider.js.map +1 -1
  74. package/dist/providers/OpenAIProvider.d.ts +4 -1
  75. package/dist/providers/OpenAIProvider.d.ts.map +1 -1
  76. package/dist/providers/OpenAIProvider.js +115 -0
  77. package/dist/providers/OpenAIProvider.js.map +1 -1
  78. package/dist/providers/OpenRouterProvider.d.ts +4 -1
  79. package/dist/providers/OpenRouterProvider.d.ts.map +1 -1
  80. package/dist/providers/OpenRouterProvider.js +115 -0
  81. package/dist/providers/OpenRouterProvider.js.map +1 -1
  82. package/dist/providers/index.d.ts +13 -0
  83. package/dist/providers/index.d.ts.map +1 -0
  84. package/dist/providers/index.js +9 -0
  85. package/dist/providers/index.js.map +1 -0
  86. package/dist/types/ai.d.ts +28 -0
  87. package/dist/types/ai.d.ts.map +1 -1
  88. package/dist/types/route.d.ts +6 -0
  89. package/dist/types/route.d.ts.map +1 -1
  90. package/docs/API_REFERENCE.md +357 -2
  91. package/docs/CONSTRUCTOR_OPTIONS.md +178 -37
  92. package/docs/GETTING_STARTED.md +10 -2
  93. package/docs/PROVIDERS.md +139 -2
  94. package/examples/business-onboarding.ts +708 -0
  95. package/examples/declarative-agent.ts +1 -1
  96. package/examples/domain-scoping.ts +267 -0
  97. package/examples/healthcare-agent.ts +4 -4
  98. package/examples/openai-agent.ts +6 -4
  99. package/examples/rules-prohibitions.ts +258 -0
  100. package/examples/streaming-agent.ts +371 -0
  101. package/examples/travel-agent.ts +7 -4
  102. package/package.json +2 -1
  103. package/src/core/Agent.ts +220 -1
  104. package/src/core/DomainRegistry.ts +30 -0
  105. package/src/core/PromptBuilder.ts +70 -3
  106. package/src/core/Route.ts +28 -0
  107. package/src/index.ts +2 -0
  108. package/src/providers/AnthropicProvider.ts +467 -0
  109. package/src/providers/GeminiProvider.ts +135 -0
  110. package/src/providers/OpenAIProvider.ts +157 -0
  111. package/src/providers/OpenRouterProvider.ts +157 -0
  112. package/src/providers/index.ts +16 -0
  113. package/src/types/ai.ts +32 -0
  114. package/src/types/route.ts +6 -0
@@ -40,9 +40,17 @@ Adds an agent capability. Returns `this` for chaining.
40
40
 
41
41
  Creates an observation for disambiguation.
42
42
 
43
- ##### `addDomain<TName, TDomain>(name: TName, domainObject: TDomain): this`
43
+ ##### `addDomain<TName, TDomain>(name: TName, domainObject: TDomain): void`
44
44
 
45
- Registers a domain with tools/methods. Returns `this` for chaining.
45
+ Registers a domain with tools/methods.
46
+
47
+ ##### `getDomainsForRoute(routeId: string): Record<string, Record<string, unknown>>`
48
+
49
+ Gets allowed domains for a specific route by ID. Returns filtered domains based on route's `domains` property, or all domains if route has no restrictions.
50
+
51
+ ##### `getDomainsForRouteByTitle(routeTitle: string): Record<string, Record<string, unknown>>`
52
+
53
+ Gets allowed domains for a specific route by title. Returns filtered domains based on route's `domains` property, or all domains if route has no restrictions.
46
54
 
47
55
  ##### `respond(input: RespondInput<TContext>): Promise<RespondOutput>`
48
56
 
@@ -101,6 +109,107 @@ if (response.route?.title === END_ROUTE) {
101
109
  }
102
110
  ```
103
111
 
112
+ ##### `respondStream(input: RespondInput<TContext>): AsyncGenerator<StreamChunk>`
113
+
114
+ Generates an AI response as a real-time stream for better user experience. Provides the same structured output as `respond()` but delivers it incrementally.
115
+
116
+ ```typescript
117
+ interface StreamChunk {
118
+ /** The incremental text delta */
119
+ delta: string;
120
+ /** Full accumulated text so far */
121
+ accumulated: string;
122
+ /** Whether this is the final chunk */
123
+ done: boolean;
124
+ /** Route chosen by the agent (only in final chunk) */
125
+ route?: { id: string; title: string };
126
+ /** Current state within the route (only in final chunk) */
127
+ state?: { id: string; description?: string };
128
+ /** Tool calls requested by the agent (only in final chunk) */
129
+ toolCalls?: Array<{
130
+ toolName: string;
131
+ arguments: Record<string, unknown>;
132
+ }>;
133
+ }
134
+ ```
135
+
136
+ **Key Features:**
137
+
138
+ - 🌊 Real-time streaming for better perceived performance
139
+ - 📊 Access to route, state, and tool information in final chunk
140
+ - 🛑 Cancellable with AbortSignal
141
+ - ✅ Supported by all providers (Anthropic, OpenAI, Gemini, OpenRouter)
142
+
143
+ **Example:**
144
+
145
+ ```typescript
146
+ // Basic streaming
147
+ for await (const chunk of agent.respondStream({ history })) {
148
+ if (chunk.delta) {
149
+ // Display incremental text to user
150
+ process.stdout.write(chunk.delta);
151
+ }
152
+
153
+ if (chunk.done) {
154
+ console.log("\n✅ Complete!");
155
+ // Access final metadata
156
+ if (chunk.route) {
157
+ console.log("Route:", chunk.route.title);
158
+ }
159
+ if (chunk.toolCalls) {
160
+ console.log("Tool calls:", chunk.toolCalls.length);
161
+ }
162
+ }
163
+ }
164
+ ```
165
+
166
+ **With Cancellation:**
167
+
168
+ ```typescript
169
+ const abortController = new AbortController();
170
+
171
+ // Cancel after 5 seconds
172
+ setTimeout(() => abortController.abort(), 5000);
173
+
174
+ try {
175
+ for await (const chunk of agent.respondStream({
176
+ history,
177
+ signal: abortController.signal,
178
+ })) {
179
+ console.log(chunk.delta);
180
+ }
181
+ } catch (error) {
182
+ if (error.name === "AbortError") {
183
+ console.log("Stream cancelled");
184
+ }
185
+ }
186
+ ```
187
+
188
+ **Collecting Full Response:**
189
+
190
+ ```typescript
191
+ let fullMessage = "";
192
+ let finalChunk;
193
+
194
+ for await (const chunk of agent.respondStream({ history })) {
195
+ fullMessage += chunk.delta;
196
+ if (chunk.done) {
197
+ finalChunk = chunk;
198
+ }
199
+ }
200
+
201
+ // Save to database
202
+ await db.agentMessages.create({
203
+ sessionId: session.id,
204
+ role: "agent",
205
+ content: fullMessage,
206
+ route: finalChunk.route?.title,
207
+ toolCalls: finalChunk.toolCalls || [],
208
+ });
209
+ ```
210
+
211
+ **See Also:** [streaming-agent.ts](../examples/streaming-agent.ts) for comprehensive examples.
212
+
104
213
  #### Properties
105
214
 
106
215
  ##### `name: string`
@@ -136,6 +245,9 @@ interface RouteOptions {
136
245
  description?: string; // Route description
137
246
  conditions?: string[]; // Conditions that activate this route
138
247
  guidelines?: Guideline[]; // Initial guidelines for this route
248
+ domains?: string[]; // Domain names allowed in this route (undefined = all domains)
249
+ rules?: string[]; // Absolute rules the agent MUST follow in this route
250
+ prohibitions?: string[]; // Absolute prohibitions the agent MUST NEVER do in this route
139
251
  }
140
252
  ```
141
253
 
@@ -151,6 +263,18 @@ Adds a guideline specific to this route. Returns `this` for chaining.
151
263
 
152
264
  Returns all guidelines for this route.
153
265
 
266
+ ##### `getDomains(): string[] | undefined`
267
+
268
+ Returns allowed domain names for this route. Returns `undefined` if all domains are allowed, or an array of domain names if restricted.
269
+
270
+ ##### `getRules(): string[]`
271
+
272
+ Returns the rules that must be followed in this route.
273
+
274
+ ##### `getProhibitions(): string[]`
275
+
276
+ Returns the prohibitions that must never be done in this route.
277
+
154
278
  ##### `getRef(): RouteRef`
155
279
 
156
280
  Returns a reference to this route.
@@ -216,6 +340,7 @@ interface TransitionResult {
216
340
  **Example:**
217
341
 
218
342
  ```typescript
343
+ // Approach 1: Step-by-step (ideal for complex flows with branching)
219
344
  const t0 = route.initialState.transitionTo({
220
345
  chatState: "Ask for user name",
221
346
  });
@@ -224,9 +349,30 @@ const t1 = t0.transitionTo({
224
349
  chatState: "Ask for email",
225
350
  });
226
351
 
352
+ const t2 = t1.transitionTo({
353
+ chatState: "Confirm details",
354
+ });
355
+
227
356
  // Access state properties
228
357
  console.log(t1.id); // State ID
229
358
  console.log(t1.routeId); // Route ID
359
+
360
+ // Use saved references for branching
361
+ t1.transitionTo(
362
+ { chatState: "Handle invalid email" },
363
+ "Email validation failed"
364
+ );
365
+
366
+ // Approach 2: Fluent chaining (elegant for linear flows)
367
+ route.initialState
368
+ .transitionTo({ chatState: "Ask for user name" })
369
+ .transitionTo({ chatState: "Ask for email" })
370
+ .transitionTo({ chatState: "Confirm details" })
371
+ .transitionTo({ state: END_ROUTE });
372
+
373
+ // Both approaches are equivalent - choose based on your needs:
374
+ // - Use step-by-step for complex flows with conditional branches
375
+ // - Use chaining for simple linear flows for conciseness
230
376
  ```
231
377
 
232
378
  ##### `addGuideline(guideline: Guideline): void`
@@ -289,6 +435,117 @@ Observation description (readonly).
289
435
 
290
436
  ---
291
437
 
438
+ ### `DomainRegistry`
439
+
440
+ Registry for organizing agent tools and methods by domain.
441
+
442
+ #### Methods
443
+
444
+ ##### `register<TDomain>(name: string, domain: TDomain): void`
445
+
446
+ Registers a new domain with its tools/methods. Throws error if domain name already exists.
447
+
448
+ ##### `get<TDomain>(name: string): TDomain | undefined`
449
+
450
+ Gets a registered domain by name. Returns `undefined` if not found.
451
+
452
+ ##### `has(name: string): boolean`
453
+
454
+ Checks if a domain is registered.
455
+
456
+ ##### `all(): Record<string, Record<string, unknown>>`
457
+
458
+ Returns all registered domains as a single object.
459
+
460
+ ##### `getFiltered(allowedNames?: string[]): Record<string, Record<string, unknown>>`
461
+
462
+ Returns filtered domains by names. If `allowedNames` is `undefined`, returns all domains.
463
+
464
+ **Example:**
465
+
466
+ ```typescript
467
+ const registry = new DomainRegistry();
468
+
469
+ registry.register("payment", {
470
+ processPayment: async (amount: number) => {
471
+ /* ... */
472
+ },
473
+ });
474
+
475
+ registry.register("shipping", {
476
+ calculateShipping: (zipCode: string) => {
477
+ /* ... */
478
+ },
479
+ });
480
+
481
+ // Get specific domains
482
+ const filtered = registry.getFiltered(["payment"]); // Only payment domain
483
+
484
+ // Get all domains
485
+ const all = registry.getFiltered(); // payment + shipping
486
+ ```
487
+
488
+ ##### `getDomainNames(): string[]`
489
+
490
+ Returns list of all registered domain names.
491
+
492
+ ---
493
+
494
+ ### `AnthropicProvider`
495
+
496
+ AI provider implementation for Anthropic (Claude models).
497
+
498
+ #### Constructor
499
+
500
+ ```typescript
501
+ new AnthropicProvider(options: AnthropicProviderOptions)
502
+
503
+ interface AnthropicProviderOptions {
504
+ apiKey: string;
505
+ model: string; // Required: e.g., "claude-sonnet-4-5"
506
+ backupModels?: string[]; // Fallback models
507
+ config?: Partial<Omit<MessageCreateParamsNonStreaming, "model" | "messages" | "max_tokens">>;
508
+ retryConfig?: {
509
+ timeout?: number; // Default: 60000ms
510
+ retries?: number; // Default: 3
511
+ };
512
+ }
513
+ ```
514
+
515
+ **Note:** `model` is required for AnthropicProvider. Available models include:
516
+
517
+ - `claude-sonnet-4-5` - Latest Claude Sonnet 4.5 (most capable)
518
+ - `claude-opus-4-1` - Claude Opus 4.1 (powerful for complex tasks)
519
+ - `claude-sonnet-4-0` - Claude Sonnet 4.0 (stable, production-ready)
520
+
521
+ #### Methods
522
+
523
+ ##### `generateMessage<TContext>(input: GenerateMessageInput<TContext>): Promise<GenerateMessageOutput>`
524
+
525
+ Generates a message with retry logic and backup models using Anthropic's API.
526
+
527
+ **Example:**
528
+
529
+ ```typescript
530
+ import { AnthropicProvider } from "@falai/agent";
531
+
532
+ const provider = new AnthropicProvider({
533
+ apiKey: process.env.ANTHROPIC_API_KEY!,
534
+ model: "claude-sonnet-4-5",
535
+ backupModels: ["claude-opus-4-1", "claude-sonnet-4-0"],
536
+ config: {
537
+ temperature: 0.7,
538
+ top_p: 0.9,
539
+ },
540
+ retryConfig: {
541
+ timeout: 60000,
542
+ retries: 3,
543
+ },
544
+ });
545
+ ```
546
+
547
+ ---
548
+
292
549
  ### `GeminiProvider`
293
550
 
294
551
  AI provider implementation for Google Gemini.
@@ -317,6 +574,104 @@ Generates a message with retry logic and backup models.
317
574
 
318
575
  ---
319
576
 
577
+ ### `OpenAIProvider`
578
+
579
+ AI provider implementation for OpenAI (GPT models).
580
+
581
+ #### Constructor
582
+
583
+ ```typescript
584
+ new OpenAIProvider(options: OpenAIProviderOptions)
585
+
586
+ interface OpenAIProviderOptions {
587
+ apiKey: string;
588
+ model: string; // Required: e.g., "gpt-4o", "gpt-5"
589
+ backupModels?: string[]; // Fallback models
590
+ retryConfig?: {
591
+ timeout?: number; // Default: 60000ms
592
+ retries?: number; // Default: 3
593
+ };
594
+ }
595
+ ```
596
+
597
+ **Note:** Unlike GeminiProvider, `model` is required for OpenAIProvider. Choose from available OpenAI models like "gpt-4o", "gpt-5", "gpt-4-turbo", etc.
598
+
599
+ #### Methods
600
+
601
+ ##### `generateMessage<TContext>(input: GenerateMessageInput<TContext>): Promise<GenerateMessageOutput>`
602
+
603
+ Generates a message with retry logic and backup models using OpenAI's API.
604
+
605
+ **Example:**
606
+
607
+ ```typescript
608
+ import { OpenAIProvider } from "@falai/agent";
609
+
610
+ const provider = new OpenAIProvider({
611
+ apiKey: process.env.OPENAI_API_KEY!,
612
+ model: "gpt-5",
613
+ backupModels: ["gpt-4o", "gpt-4-turbo"],
614
+ retryConfig: {
615
+ timeout: 60000,
616
+ retries: 3,
617
+ },
618
+ });
619
+ ```
620
+
621
+ ---
622
+
623
+ ### `OpenRouterProvider`
624
+
625
+ AI provider implementation for OpenRouter (access to 200+ models).
626
+
627
+ #### Constructor
628
+
629
+ ```typescript
630
+ new OpenRouterProvider(options: OpenRouterProviderOptions)
631
+
632
+ interface OpenRouterProviderOptions {
633
+ apiKey: string;
634
+ model: string; // Required: e.g., "openai/gpt-5", "anthropic/claude-sonnet-4-5"
635
+ backupModels?: string[]; // Fallback models
636
+ siteUrl?: string; // Optional: your app URL for OpenRouter rankings
637
+ siteName?: string; // Optional: your app name for OpenRouter rankings
638
+ retryConfig?: {
639
+ timeout?: number; // Default: 60000ms
640
+ retries?: number; // Default: 3
641
+ };
642
+ }
643
+ ```
644
+
645
+ **Note:** OpenRouter provides access to models from multiple providers. Model names follow the format `provider/model-name` (e.g., "openai/gpt-5", "anthropic/claude-sonnet-4-5", "google/gemini-pro").
646
+
647
+ #### Methods
648
+
649
+ ##### `generateMessage<TContext>(input: GenerateMessageInput<TContext>): Promise<GenerateMessageOutput>`
650
+
651
+ Generates a message with retry logic and backup models using OpenRouter's API.
652
+
653
+ **Example:**
654
+
655
+ ```typescript
656
+ import { OpenRouterProvider } from "@falai/agent";
657
+
658
+ const provider = new OpenRouterProvider({
659
+ apiKey: process.env.OPENROUTER_API_KEY!,
660
+ model: "openai/gpt-5",
661
+ backupModels: ["anthropic/claude-sonnet-4-5", "google/gemini-pro"],
662
+ siteUrl: "https://yourapp.com",
663
+ siteName: "Your App Name",
664
+ retryConfig: {
665
+ timeout: 60000,
666
+ retries: 3,
667
+ },
668
+ });
669
+ ```
670
+
671
+ **See Also:** [Providers Guide](./PROVIDERS.md) for detailed provider comparison and configuration examples.
672
+
673
+ ---
674
+
320
675
  ### `PromptBuilder`
321
676
 
322
677
  Constructs prompts for AI generation.