@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
package/README.md CHANGED
@@ -34,7 +34,7 @@
34
34
  ### 🚀 **Production Ready**
35
35
 
36
36
  - **Robust Retry Logic** - Exponential backoff & backup models
37
- - **AI Provider Strategy** - Pluggable backends (Gemini, OpenAI, OpenRouter)
37
+ - **AI Provider Strategy** - Pluggable backends (Claude, Gemini, OpenAI, OpenRouter)
38
38
  - **Prompt Composition** - Sophisticated prompt building system
39
39
 
40
40
  </td>
@@ -87,8 +87,10 @@ Get up and running in 60 seconds:
87
87
  ```typescript
88
88
  import {
89
89
  Agent,
90
+ AnthropicProvider,
90
91
  GeminiProvider,
91
- OpenAIProvider, // or use OpenAI
92
+ OpenAIProvider,
93
+ OpenRouterProvider,
92
94
  createMessageEvent,
93
95
  EventSource,
94
96
  } from "@falai/agent";
@@ -101,15 +103,25 @@ interface SupportContext {
101
103
  }
102
104
 
103
105
  // 2️⃣ Create AI provider (choose one)
104
- const ai = new GeminiProvider({
105
- apiKey: process.env.GEMINI_API_KEY!,
106
- model: "models/gemini-2.5-flash",
106
+ const ai = new AnthropicProvider({
107
+ apiKey: process.env.ANTHROPIC_API_KEY!,
108
+ model: "claude-sonnet-4-5",
107
109
  });
108
110
 
109
- // Or use OpenAI:
111
+ // Or use other providers:
112
+ // const ai = new GeminiProvider({
113
+ // apiKey: process.env.GEMINI_API_KEY!,
114
+ // model: "models/gemini-2.5-flash",
115
+ // });
116
+
110
117
  // const ai = new OpenAIProvider({
111
118
  // apiKey: process.env.OPENAI_API_KEY!,
112
- // model: "gpt-5", // Required - specify your model
119
+ // model: "gpt-5",
120
+ // });
121
+
122
+ // const ai = new OpenRouterProvider({
123
+ // apiKey: process.env.OPENROUTER_API_KEY!,
124
+ // model: "anthropic/claude-sonnet-4-5", // Access to 200+ models
113
125
  // });
114
126
 
115
127
  // 3️⃣ Initialize your agent - two ways!
@@ -174,6 +186,36 @@ const response = await agent.respond({
174
186
  console.log(response.message); // 🎉 AI-powered response ready!
175
187
  ```
176
188
 
189
+ ### ⚡ Streaming Responses (NEW!)
190
+
191
+ Stream AI responses in real-time for better user experience:
192
+
193
+ ```typescript
194
+ // Use respondStream for real-time streaming
195
+ for await (const chunk of agent.respondStream({ history })) {
196
+ // chunk.delta contains the new text
197
+ process.stdout.write(chunk.delta);
198
+
199
+ if (chunk.done) {
200
+ // Stream complete - access final metadata
201
+ console.log("\n✅ Complete!");
202
+ console.log("Route:", chunk.route?.title);
203
+ console.log("Tool calls:", chunk.toolCalls?.length);
204
+ }
205
+ }
206
+ ```
207
+
208
+ **Benefits:**
209
+
210
+ - ✨ Real-time response generation
211
+ - 🎯 Better perceived performance
212
+ - 🛑 Cancellable with AbortSignal
213
+ - 📊 Access to route/state/tool information in final chunk
214
+
215
+ **Supported Providers:** All providers support streaming (Anthropic, OpenAI, Gemini, OpenRouter)
216
+
217
+ See [streaming-agent.ts](./examples/streaming-agent.ts) for complete examples.
218
+
177
219
  ---
178
220
 
179
221
  ## 📚 Documentation
@@ -287,20 +329,30 @@ const onboardingRoute = agent.createRoute({
287
329
  conditions: ["User is new and needs onboarding"],
288
330
  });
289
331
 
290
- // Build the flow
332
+ // Option 1: Step-by-step (clear and explicit)
291
333
  const askName = onboardingRoute.initialState.transitionTo({
292
334
  chatState: "Ask for user's full name",
293
335
  });
294
336
 
295
337
  const askEmail = askName.transitionTo({
296
338
  chatState: "Request email address",
297
- condition: "User provided their name",
298
339
  });
299
340
 
300
341
  const confirmDetails = askEmail.transitionTo({
301
342
  chatState: "Confirm all details before proceeding",
302
343
  });
303
344
 
345
+ confirmDetails.transitionTo({ state: END_ROUTE });
346
+
347
+ // Option 2: Fluent chaining (concise and elegant)
348
+ onboardingRoute.initialState
349
+ .transitionTo({ chatState: "Ask for user's full name" })
350
+ .transitionTo({ chatState: "Request email address" })
351
+ .transitionTo({ chatState: "Confirm all details before proceeding" })
352
+ .transitionTo({ state: END_ROUTE });
353
+
354
+ // Both approaches work identically - choose what fits your style!
355
+
304
356
  // Add guidelines dynamically (can also be in route options)
305
357
  onboardingRoute.createGuideline({
306
358
  condition: "User provides invalid email",
@@ -308,17 +360,127 @@ onboardingRoute.createGuideline({
308
360
  enabled: true,
309
361
  tags: ["validation"],
310
362
  });
363
+ ```
364
+
365
+ ### 📜 Rules & Prohibitions Per Route
366
+
367
+ Control agent behavior and communication style for each route:
311
368
 
312
- // Happy path completion
313
- confirmDetails.transitionTo({
314
- chatState: "Welcome message and next steps",
315
- condition: "User confirms details",
369
+ ```typescript
370
+ // WhatsApp support bot with different styles per route
371
+ agent.createRoute({
372
+ title: "Quick Support",
373
+ description: "Fast answers for common questions",
374
+ conditions: ["User has a simple question"],
375
+ rules: [
376
+ "Keep messages extremely short (1-2 lines maximum)",
377
+ "Use bullet points for lists",
378
+ "Maximum 1 emoji per message 👍",
379
+ "Be direct and to the point",
380
+ ],
381
+ prohibitions: [
382
+ "Never send long paragraphs",
383
+ "Do not over-explain",
384
+ "Never use more than 2 emojis",
385
+ ],
316
386
  });
317
387
 
318
- // End the route
319
- confirmDetails.transitionTo({ state: END_ROUTE });
388
+ agent.createRoute({
389
+ title: "Sales Consultation",
390
+ description: "Help customer discover needs",
391
+ conditions: ["User is interested in buying"],
392
+ rules: [
393
+ "Ask open-ended questions to discover needs",
394
+ "Use storytelling when presenting solutions",
395
+ "Present value before mentioning price",
396
+ ],
397
+ prohibitions: [
398
+ "Never talk about price before showing value",
399
+ "Do not pressure or push",
400
+ "Avoid technical jargon",
401
+ ],
402
+ });
403
+
404
+ agent.createRoute({
405
+ title: "Emergency Support",
406
+ description: "Handle urgent issues",
407
+ conditions: ["Customer is frustrated", "Urgent issue"],
408
+ rules: [
409
+ "Acknowledge the urgency immediately",
410
+ "Express empathy and understanding",
411
+ "Set clear expectations on resolution time",
412
+ ],
413
+ prohibitions: [
414
+ "Never downplay the customer's concern",
415
+ "Do not use emojis (keep it professional)",
416
+ 'Never say "calm down"',
417
+ ],
418
+ });
320
419
  ```
321
420
 
421
+ **Use Cases:**
422
+
423
+ - 📱 Different message styles per channel (WhatsApp, email, chat)
424
+ - 🎭 Context-specific tone and behavior
425
+ - 🎨 Brand consistency across routes
426
+ - ⚡ Automatic enforcement without manual checking
427
+
428
+ ### 🔐 Domain Scoping for Security
429
+
430
+ Restrict which tools are available in each route:
431
+
432
+ ```typescript
433
+ // Register different tool domains
434
+ agent.addDomain("payment", {
435
+ processPayment: async (amount: number) => {
436
+ /* ... */
437
+ },
438
+ refund: async (txId: string) => {
439
+ /* ... */
440
+ },
441
+ });
442
+
443
+ agent.addDomain("calendar", {
444
+ scheduleEvent: async (date: Date, title: string) => {
445
+ /* ... */
446
+ },
447
+ });
448
+
449
+ agent.addDomain("analytics", {
450
+ trackEvent: async (name: string) => {
451
+ /* ... */
452
+ },
453
+ });
454
+
455
+ // Route 1: Customer Support - NO access to payment tools
456
+ agent.createRoute({
457
+ title: "Customer Support",
458
+ description: "Answer general questions",
459
+ domains: [], // 🔒 No tools (conversation only)
460
+ });
461
+
462
+ // Route 2: Checkout - ONLY payment and analytics
463
+ agent.createRoute({
464
+ title: "Checkout Process",
465
+ description: "Process purchases",
466
+ domains: ["payment", "analytics"], // 🔒 Limited access
467
+ });
468
+
469
+ // Route 3: Admin - ALL tools available
470
+ agent.createRoute({
471
+ title: "Admin Support",
472
+ description: "Full system access",
473
+ // domains not specified = all domains available
474
+ });
475
+ ```
476
+
477
+ **Benefits:**
478
+
479
+ - 🔒 Prevent unauthorized tool calls
480
+ - ⚡ Improve AI performance (reduced decision space)
481
+ - 📋 Clear documentation of route capabilities
482
+ - 🛡️ Security by design
483
+
322
484
  ### 🔀 Disambiguation with Observations
323
485
 
324
486
  Handle ambiguous user intent gracefully - declaratively or programmatically:
@@ -496,9 +658,27 @@ const event = createMessageEvent(
496
658
 
497
659
  ### ⚙️ Advanced Configuration
498
660
 
499
- Fine-tune AI provider behavior - works with both Gemini and OpenAI:
661
+ Fine-tune AI provider behavior - works with all providers:
500
662
 
501
663
  ```typescript
664
+ // Anthropic (Claude) configuration
665
+ const anthropicProvider = new AnthropicProvider({
666
+ apiKey: process.env.ANTHROPIC_API_KEY!,
667
+ model: "claude-sonnet-4-5", // Primary model
668
+ backupModels: [
669
+ "claude-opus-4-1", // Backup if primary fails
670
+ "claude-sonnet-4-0", // Stable fallback
671
+ ],
672
+ config: {
673
+ temperature: 0.7,
674
+ top_p: 0.9,
675
+ },
676
+ retryConfig: {
677
+ timeout: 60000, // 60s timeout
678
+ retries: 3, // 3 attempts with exponential backoff
679
+ },
680
+ });
681
+
502
682
  // Gemini configuration
503
683
  const geminiProvider = new GeminiProvider({
504
684
  apiKey: process.env.GEMINI_API_KEY!,
@@ -508,8 +688,8 @@ const geminiProvider = new GeminiProvider({
508
688
  "models/gemini-2.0-flash",
509
689
  ],
510
690
  retryConfig: {
511
- timeout: 60000, // 60s timeout
512
- retries: 3, // 3 attempts with exponential backoff
691
+ timeout: 60000,
692
+ retries: 3,
513
693
  },
514
694
  });
515
695
 
@@ -523,6 +703,19 @@ const openaiProvider = new OpenAIProvider({
523
703
  retries: 3,
524
704
  },
525
705
  });
706
+
707
+ // OpenRouter configuration (access to 200+ models)
708
+ const openrouterProvider = new OpenRouterProvider({
709
+ apiKey: process.env.OPENROUTER_API_KEY!,
710
+ model: "anthropic/claude-sonnet-4-5",
711
+ backupModels: ["openai/gpt-5", "google/gemini-2.5-flash"],
712
+ siteUrl: "https://yourapp.com",
713
+ siteName: "Your App Name",
714
+ retryConfig: {
715
+ timeout: 60000,
716
+ retries: 3,
717
+ },
718
+ });
526
719
  ```
527
720
 
528
721
  ---
@@ -538,6 +731,16 @@ const openaiProvider = new OpenAIProvider({
538
731
  - 🔗 Route references by title in observations
539
732
  - ➕ Dynamic additions after construction
540
733
 
734
+ ### ⚡ [Streaming Responses](./examples/streaming-agent.ts) **(NEW!)**
735
+
736
+ **Real-time streaming responses for better UX:**
737
+
738
+ - 🌊 Stream responses from all providers (Anthropic, OpenAI, Gemini, OpenRouter)
739
+ - 📡 Real-time text generation with `respondStream`
740
+ - 🛑 Cancellable streams with AbortSignal
741
+ - 📊 Access route, state, and tool information
742
+ - 🎯 5 comprehensive examples covering different use cases
743
+
541
744
  ### 💾 [Persistent Onboarding Agent](./examples/persistent-onboarding.ts)
542
745
 
543
746
  **Multi-turn conversation with state persistence:**
@@ -548,6 +751,17 @@ const openaiProvider = new OpenAIProvider({
548
751
  - 🔧 Two approaches: lifecycle hooks vs context provider
549
752
  - 📝 Complete onboarding flow across multiple turns
550
753
 
754
+ ### 🏢 [Business Onboarding](./examples/business-onboarding.ts)
755
+
756
+ **Production-ready business onboarding with advanced patterns:**
757
+
758
+ - 🎯 Real-world multi-step business setup flow
759
+ - 🔀 Complex branching logic (physical vs online business)
760
+ - 🔄 Tools with `contextUpdate` for automatic state management
761
+ - 🔗 Both step-by-step and fluent chaining approaches
762
+ - 🎨 Lifecycle hooks for agent caching and persistence
763
+ - 📊 Dynamic route creation based on collected data
764
+
551
765
  ### 🌍 [Travel Booking Agent](./examples/travel-agent.ts)
552
766
 
553
767
  A complete travel agent implementation featuring:
@@ -568,15 +782,34 @@ Healthcare-focused agent demonstrating:
568
782
  - 🔐 Sensitive data handling
569
783
  - ⚠️ Urgent case prioritization
570
784
 
571
- ### 🌐 [OpenAI Agent](./examples/openai-agent.ts)
785
+ ### 🌐 Multiple Provider Examples
572
786
 
573
- Using OpenAI provider instead of Gemini:
787
+ See how different AI providers work:
574
788
 
575
- - 🤖 OpenAI GPT-4o integration
576
- - 🔄 Backup model configuration
577
- - ⚙️ Custom retry settings
789
+ - **[OpenAI Agent](./examples/openai-agent.ts)** - GPT-5 integration
790
+ - **[Healthcare Agent](./examples/healthcare-agent.ts)** - Claude 3.5 Sonnet
791
+ - **[Travel Agent](./examples/travel-agent.ts)** - OpenRouter with backup models
792
+ - 🔄 All with backup model configuration and retry settings
578
793
  - 🌤️ Weather checking example
579
794
 
795
+ ### 🔐 [Domain Scoping](./examples/domain-scoping.ts)
796
+
797
+ Control tool access per route for security and clarity:
798
+
799
+ - 🔒 Restrict which tools are available in each route
800
+ - 🎯 Prevent unauthorized tool calls
801
+ - ⚡ Improve AI performance by reducing decision space
802
+ - 📋 Clear documentation of route capabilities
803
+
804
+ ### 📜 [Rules & Prohibitions](./examples/rules-prohibitions.ts)
805
+
806
+ Control agent behavior and communication style per route:
807
+
808
+ - ✅ Define absolute rules the agent must follow
809
+ - ❌ Set prohibitions for what agent must never do
810
+ - 💬 Different communication styles per route
811
+ - 🎨 Perfect for multi-channel bots (WhatsApp, email, chat)
812
+
580
813
  ---
581
814
 
582
815
  ## 🏗️ Architecture
@@ -585,7 +818,7 @@ Using OpenAI provider instead of Gemini:
585
818
  src/
586
819
  ├── types/ # Type definitions (strongly typed contracts)
587
820
  ├── core/ # Core framework (Agent, Route, State, Tools, etc.)
588
- ├── providers/ # AI providers (Gemini with retry/backup logic)
821
+ ├── providers/ # AI providers (Anthropic, Gemini, OpenAI, OpenRouter)
589
822
  ├── utils/ # Utilities (retry, timeout, helpers)
590
823
  ├── constants/ # Constants (END_ROUTE, symbols)
591
824
  └── index.ts # Public API exports
@@ -70,6 +70,31 @@ export declare class Agent<TContext = unknown> {
70
70
  * @internal
71
71
  */
72
72
  private getContext;
73
+ /**
74
+ * Generate a response based on history and context as a stream
75
+ */
76
+ respondStream(params: {
77
+ history: Event[];
78
+ state?: StateRef;
79
+ contextOverride?: Partial<TContext>;
80
+ signal?: AbortSignal;
81
+ }): AsyncGenerator<{
82
+ delta: string;
83
+ accumulated: string;
84
+ done: boolean;
85
+ route?: {
86
+ id: string;
87
+ title: string;
88
+ } | null;
89
+ state?: {
90
+ id: string;
91
+ description?: string;
92
+ } | null;
93
+ toolCalls?: Array<{
94
+ toolName: string;
95
+ arguments: Record<string, unknown>;
96
+ }>;
97
+ }>;
73
98
  /**
74
99
  * Generate a response based on history and context
75
100
  */
@@ -117,5 +142,17 @@ export declare class Agent<TContext = unknown> {
117
142
  * Get the domain registry
118
143
  */
119
144
  getDomainRegistry(): DomainRegistry;
145
+ /**
146
+ * Get allowed domains for a specific route
147
+ * @param routeId - Route ID to check
148
+ * @returns Filtered domains object, or all domains if route has no restrictions
149
+ */
150
+ getDomainsForRoute(routeId: string): Record<string, Record<string, unknown>>;
151
+ /**
152
+ * Get allowed domains for a specific route by title
153
+ * @param routeTitle - Route title to check
154
+ * @returns Filtered domains object, or all domains if route has no restrictions
155
+ */
156
+ getDomainsForRouteByTitle(routeTitle: string): Record<string, Record<string, unknown>>;
120
157
  }
121
158
  //# sourceMappingURL=Agent.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Agent.d.ts","sourceRoot":"","sources":["../../../src/core/Agent.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Agent.d.ts","sourceRoot":"","sources":["../../../src/core/Agent.ts"],"names":[],"mappings":"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"}
@@ -171,6 +171,136 @@ class Agent {
171
171
  // Otherwise return the stored context
172
172
  return this.context;
173
173
  }
174
+ /**
175
+ * Generate a response based on history and context as a stream
176
+ */
177
+ async *respondStream(params) {
178
+ const { history, contextOverride, signal } = params;
179
+ // Get current context (may fetch from provider)
180
+ let currentContext = await this.getContext();
181
+ // Call beforeRespond hook if configured
182
+ if (this.options.hooks?.beforeRespond && currentContext !== undefined) {
183
+ currentContext = await this.options.hooks.beforeRespond(currentContext);
184
+ // Update stored context with the result from beforeRespond
185
+ this.context = currentContext;
186
+ }
187
+ // Merge context with override
188
+ const effectiveContext = {
189
+ ...currentContext,
190
+ ...contextOverride,
191
+ };
192
+ // Build prompt (same as respond method)
193
+ const promptBuilder = new PromptBuilder_1.PromptBuilder();
194
+ // Add agent identity
195
+ if (this.options.description) {
196
+ promptBuilder.addAgentIdentity({
197
+ name: this.options.name,
198
+ description: this.options.description,
199
+ });
200
+ }
201
+ // Add interaction history
202
+ promptBuilder.addInteractionHistoryForMessageGeneration(history);
203
+ // Add glossary
204
+ if (this.terms.length > 0) {
205
+ promptBuilder.addGlossary(this.terms);
206
+ }
207
+ // Add guidelines (convert to GuidelineMatch format, filter enabled only)
208
+ const enabledGuidelines = this.guidelines.filter((g) => g.enabled !== false);
209
+ if (enabledGuidelines.length > 0) {
210
+ const guidelineMatches = enabledGuidelines.map((g) => ({
211
+ guideline: g,
212
+ }));
213
+ promptBuilder.addGuidelinesForMessageGeneration(guidelineMatches);
214
+ }
215
+ // Add capabilities
216
+ if (this.capabilities.length > 0) {
217
+ promptBuilder.addCapabilitiesForMessageGeneration(this.capabilities);
218
+ }
219
+ // Add observations
220
+ if (this.observations.length > 0) {
221
+ const observationsWithRoutes = this.observations
222
+ .map((obs) => ({
223
+ description: obs.description,
224
+ routes: obs.getRoutes().map((routeRef) => {
225
+ const route = this.routes.find((r) => r.id === routeRef.id);
226
+ return { title: route?.title || routeRef.id };
227
+ }),
228
+ }))
229
+ .filter((obs) => obs.routes.length > 0);
230
+ if (observationsWithRoutes.length > 0) {
231
+ promptBuilder.addObservations(observationsWithRoutes);
232
+ }
233
+ }
234
+ // Add active routes with their rules and prohibitions
235
+ if (this.routes.length > 0) {
236
+ promptBuilder.addActiveRoutes(this.routes.map((r) => ({
237
+ title: r.title,
238
+ description: r.description,
239
+ conditions: r.conditions,
240
+ domains: r.getDomains(),
241
+ rules: r.getRules(),
242
+ prohibitions: r.getProhibitions(),
243
+ })));
244
+ }
245
+ // Add domains (tools) information if any domains are registered
246
+ const allDomains = this.domainRegistry.all();
247
+ if (Object.keys(allDomains).length > 0) {
248
+ promptBuilder.addDomains(allDomains);
249
+ }
250
+ // Add JSON response schema instructions
251
+ promptBuilder.addJsonResponseSchema();
252
+ // Build final prompt
253
+ const prompt = promptBuilder.build();
254
+ // Generate message stream using AI provider with JSON mode enabled
255
+ const stream = this.options.ai.generateMessageStream({
256
+ prompt,
257
+ history,
258
+ context: effectiveContext,
259
+ signal,
260
+ parameters: {
261
+ jsonMode: true,
262
+ },
263
+ });
264
+ // Stream chunks to caller
265
+ for await (const chunk of stream) {
266
+ // Extract route and state from structured response on final chunk
267
+ let route = null;
268
+ let state = null;
269
+ let toolCalls;
270
+ if (chunk.done && chunk.structured) {
271
+ // Find route by title
272
+ if (chunk.structured.route) {
273
+ const foundRoute = this.routes.find((r) => r.title === chunk.structured?.route);
274
+ if (foundRoute) {
275
+ route = {
276
+ id: foundRoute.id,
277
+ title: foundRoute.title,
278
+ };
279
+ }
280
+ }
281
+ // Create state reference if provided
282
+ if (chunk.structured.state) {
283
+ state = {
284
+ id: "dynamic_state",
285
+ description: chunk.structured.state,
286
+ };
287
+ }
288
+ // Extract tool calls
289
+ if (chunk.structured.toolCalls &&
290
+ chunk.structured.toolCalls.length > 0) {
291
+ toolCalls = chunk.structured.toolCalls;
292
+ }
293
+ }
294
+ yield {
295
+ delta: chunk.delta,
296
+ accumulated: chunk.accumulated,
297
+ done: chunk.done,
298
+ route: route || undefined,
299
+ state: state || undefined,
300
+ toolCalls,
301
+ };
302
+ }
303
+ }
174
304
  /**
175
305
  * Generate a response based on history and context
176
306
  */
@@ -231,14 +361,22 @@ class Agent {
231
361
  promptBuilder.addObservations(observationsWithRoutes);
232
362
  }
233
363
  }
234
- // Add active routes
364
+ // Add active routes with their rules and prohibitions
235
365
  if (this.routes.length > 0) {
236
366
  promptBuilder.addActiveRoutes(this.routes.map((r) => ({
237
367
  title: r.title,
238
368
  description: r.description,
239
369
  conditions: r.conditions,
370
+ domains: r.getDomains(),
371
+ rules: r.getRules(),
372
+ prohibitions: r.getProhibitions(),
240
373
  })));
241
374
  }
375
+ // Add domains (tools) information if any domains are registered
376
+ const allDomains = this.domainRegistry.all();
377
+ if (Object.keys(allDomains).length > 0) {
378
+ promptBuilder.addDomains(allDomains);
379
+ }
242
380
  // Add JSON response schema instructions
243
381
  promptBuilder.addJsonResponseSchema();
244
382
  // Build final prompt
@@ -327,6 +465,34 @@ class Agent {
327
465
  getDomainRegistry() {
328
466
  return this.domainRegistry;
329
467
  }
468
+ /**
469
+ * Get allowed domains for a specific route
470
+ * @param routeId - Route ID to check
471
+ * @returns Filtered domains object, or all domains if route has no restrictions
472
+ */
473
+ getDomainsForRoute(routeId) {
474
+ const route = this.routes.find((r) => r.id === routeId);
475
+ if (!route) {
476
+ // Route not found, return all domains
477
+ return this.domainRegistry.all();
478
+ }
479
+ const allowedDomains = route.getDomains();
480
+ return this.domainRegistry.getFiltered(allowedDomains);
481
+ }
482
+ /**
483
+ * Get allowed domains for a specific route by title
484
+ * @param routeTitle - Route title to check
485
+ * @returns Filtered domains object, or all domains if route has no restrictions
486
+ */
487
+ getDomainsForRouteByTitle(routeTitle) {
488
+ const route = this.routes.find((r) => r.title === routeTitle);
489
+ if (!route) {
490
+ // Route not found, return all domains
491
+ return this.domainRegistry.all();
492
+ }
493
+ const allowedDomains = route.getDomains();
494
+ return this.domainRegistry.getFiltered(allowedDomains);
495
+ }
330
496
  }
331
497
  exports.Agent = Agent;
332
498
  //# sourceMappingURL=Agent.js.map