@jterrazz/intelligence 1.6.1 → 2.0.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 (53) hide show
  1. package/README.md +199 -83
  2. package/dist/adapters/agents/{basic-agent.adapter.d.ts → chat-agent.adapter.d.ts} +6 -6
  3. package/dist/adapters/agents/{basic-agent.adapter.js → chat-agent.adapter.js} +37 -20
  4. package/dist/adapters/agents/chat-agent.adapter.js.map +1 -0
  5. package/dist/adapters/agents/{retryable-agent.adapter.d.ts → resilient-agent.adapter.d.ts} +4 -4
  6. package/dist/adapters/agents/{retryable-agent.adapter.js → resilient-agent.adapter.js} +8 -8
  7. package/dist/adapters/agents/resilient-agent.adapter.js.map +1 -0
  8. package/dist/adapters/agents/{autonomous-agent.adapter.d.ts → tool-agent.adapter.d.ts} +6 -6
  9. package/dist/adapters/agents/{autonomous-agent.adapter.js → tool-agent.adapter.js} +10 -10
  10. package/dist/adapters/agents/tool-agent.adapter.js.map +1 -0
  11. package/dist/adapters/models/openrouter-model.adapter.d.ts +17 -32
  12. package/dist/adapters/models/openrouter-model.adapter.js +84 -25
  13. package/dist/adapters/models/openrouter-model.adapter.js.map +1 -1
  14. package/dist/adapters/prompts/__tests__/presets.test.js +4 -4
  15. package/dist/adapters/prompts/__tests__/presets.test.js.map +1 -1
  16. package/dist/adapters/prompts/system-prompt.adapter.d.ts +2 -2
  17. package/dist/adapters/prompts/system-prompt.adapter.js +6 -6
  18. package/dist/adapters/prompts/system-prompt.adapter.js.map +1 -1
  19. package/dist/adapters/prompts/user-prompt.adapter.d.ts +2 -2
  20. package/dist/adapters/prompts/user-prompt.adapter.js +6 -6
  21. package/dist/adapters/prompts/user-prompt.adapter.js.map +1 -1
  22. package/dist/adapters/providers/openrouter-provider.adapter.d.ts +34 -0
  23. package/dist/adapters/providers/openrouter-provider.adapter.js +57 -0
  24. package/dist/adapters/providers/openrouter-provider.adapter.js.map +1 -0
  25. package/dist/adapters/tools/safe-tool.adapter.d.ts +2 -2
  26. package/dist/adapters/tools/safe-tool.adapter.js +6 -6
  27. package/dist/adapters/tools/safe-tool.adapter.js.map +1 -1
  28. package/dist/adapters/utils/__tests__/{ai-response-parser.test.js → structured-response-parser.test.js} +30 -30
  29. package/dist/adapters/utils/__tests__/structured-response-parser.test.js.map +1 -0
  30. package/dist/adapters/utils/{ai-response-parser-error.d.ts → structured-response-parser-error.d.ts} +2 -2
  31. package/dist/adapters/utils/{ai-response-parser-error.js → structured-response-parser-error.js} +9 -9
  32. package/dist/adapters/utils/structured-response-parser-error.js.map +1 -0
  33. package/dist/adapters/utils/{ai-response-parser.d.ts → structured-response-parser.d.ts} +1 -1
  34. package/dist/adapters/utils/{ai-response-parser.js → structured-response-parser.js} +13 -13
  35. package/dist/adapters/utils/structured-response-parser.js.map +1 -0
  36. package/dist/index.cjs +727 -342
  37. package/dist/index.d.ts +11 -8
  38. package/dist/index.js +29 -8
  39. package/dist/index.js.map +1 -1
  40. package/dist/ports/model.port.d.ts +30 -3
  41. package/dist/ports/model.port.js +1 -1
  42. package/dist/ports/model.port.js.map +1 -1
  43. package/dist/ports/provider.port.d.ts +13 -0
  44. package/dist/ports/provider.port.js +5 -0
  45. package/dist/ports/provider.port.js.map +1 -0
  46. package/package.json +11 -9
  47. package/dist/adapters/agents/autonomous-agent.adapter.js.map +0 -1
  48. package/dist/adapters/agents/basic-agent.adapter.js.map +0 -1
  49. package/dist/adapters/agents/retryable-agent.adapter.js.map +0 -1
  50. package/dist/adapters/utils/__tests__/ai-response-parser.test.js.map +0 -1
  51. package/dist/adapters/utils/ai-response-parser-error.js.map +0 -1
  52. package/dist/adapters/utils/ai-response-parser.js.map +0 -1
  53. /package/dist/adapters/utils/__tests__/{ai-response-parser.test.d.ts → structured-response-parser.test.d.ts} +0 -0
package/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
  [![NPM Version](https://img.shields.io/npm/v/@jterrazz/intelligence.svg)](https://www.npmjs.com/package/@jterrazz/intelligence)
6
6
  [![License](https://img.shields.io/npm/l/@jterrazz/intelligence.svg)](./LICENSE)
7
7
 
8
- `@jterrazz/intelligence` provides a clean, structured, and extensible foundation for building sophisticated AI agents. It's designed to help you create reliable and maintainable AI-powered applications by focusing on composability and type safety.
8
+ `@jterrazz/intelligence` provides a clean, structured, and extensible foundation for building sophisticated AI agents. Built on the **Vercel AI SDK** with **OpenRouter** support, it's designed to help you create reliable and maintainable AI-powered applications by focusing on composability, type safety, and resilience.
9
9
 
10
10
  ---
11
11
 
@@ -13,10 +13,12 @@
13
13
 
14
14
  - **Composable Prompts**: Instead of monolithic prompts, the library offers a collection of constants. Mix and match them to build a precise system prompt that defines your agent's behavior, personality, and output format.
15
15
 
16
- - **Safe, Typed Tools**: A `SafeToolAdapter` provides built-in error handling and Zod-based schema validation for any tool you create. This ensures that tool inputs are valid and that your agent can gracefully handle execution errors.
16
+ - **Safe, Typed Tools**: A `SafeTool` provides built-in error handling and Zod-based schema validation for any tool you create. This ensures that tool inputs are valid and that your agent can gracefully handle execution errors.
17
17
 
18
18
  - **Ports & Adapters Architecture**: The library uses a hexagonal architecture to separate core logic from implementation details. This makes it easy to swap out underlying models or services (e.g., switching from OpenAI to Anthropic) without rewriting your application.
19
19
 
20
+ - **Structured Outputs**: Leverages both prompt-based schema instructions and OpenRouter's official structured outputs for reliable, validated responses.
21
+
20
22
  ## Installation
21
23
 
22
24
  ```bash
@@ -25,127 +27,140 @@ npm install @jterrazz/intelligence
25
27
 
26
28
  ---
27
29
 
30
+ ## Agent Types
31
+
32
+ ### 🗣️ **ChatAgent**
33
+
34
+ For conversational AI and text generation with optional schema validation. Perfect for chatbots, content generation, and structured data extraction.
35
+
36
+ ### 🛡️ **ResilientAgent**
37
+
38
+ A decorator that adds retry logic to any agent for fault-tolerant execution. Wraps other agents to handle transient failures gracefully.
39
+
40
+ ### 🔧 **ToolAgent**
41
+
42
+ For complex workflows requiring external tools and function calling. Can reason about when to use tools and provide structured responses.
43
+
44
+ ---
45
+
28
46
  ## Quick Start
29
47
 
30
- Get your first agent running in minutes. This example creates a helpful agent for a Discord community.
48
+ Get your first agent running in minutes. This example creates a helpful conversational agent.
31
49
 
32
50
  ```typescript
33
- import {
34
- AutonomousAgentAdapter,
35
- OpenRouterAdapter,
36
- SystemPromptAdapter,
37
- PROMPT_LIBRARY,
38
- } from '@jterrazz/intelligence';
51
+ import { ChatAgent, OpenRouterProvider, SystemPrompt, PROMPTS } from '@jterrazz/intelligence';
39
52
 
40
53
  // 1. Set up the model provider
41
- const model = new OpenRouterAdapter({
54
+ const provider = new OpenRouterProvider({
42
55
  apiKey: process.env.OPENROUTER_API_KEY!, // Make sure to set this environment variable
43
- modelName: 'anthropic/claude-3.5-sonnet',
44
56
  });
45
57
 
46
- // 2. Create an agent using a preset prompt
47
- const agent = new AutonomousAgentAdapter('discord-bot', {
58
+ // 2. Get a model instance
59
+ const model = provider.getModel('anthropic/claude-sonnet-4');
60
+
61
+ // 3. Create a conversational agent
62
+ const agent = new ChatAgent('helpful-assistant', {
48
63
  model,
49
- systemPrompt: new SystemPromptAdapter(PROMPT_LIBRARY.PRESETS.COMMUNITY_ANIMATOR),
64
+ systemPrompt: new SystemPrompt(PROMPTS.PRESETS.HELPFUL_ASSISTANT),
50
65
  });
51
66
 
52
- // 3. Run the agent
67
+ // 4. Run the agent
53
68
  const response = await agent.run();
54
69
 
55
70
  console.log(response);
56
- // Output might be: "Hello, community! I'm here to help with any questions and keep the good vibes flowing. What's on your mind today?"
71
+ // Output: "Hello! I'm here to help you with any questions or tasks you might have. What can I assist you with today?"
57
72
  ```
58
73
 
59
74
  ## Creating Domain-Specific Agents
60
75
 
61
76
  The most powerful feature of `@jterrazz/intelligence` is its ability to create specialized, reusable agents. By extending the base adapters, you can encapsulate an agent's logic, prompts, and tools into a clean, type-safe class.
62
77
 
63
- ### 1. Data Extraction Agent (`BasicAgentAdapter`)
78
+ ### 1. Data Extraction Agent (`ChatAgent`)
64
79
 
65
- Use `BasicAgentAdapter` for simpler, one-shot tasks where you need a structured response but don't require complex tool use. This example creates a reusable agent to extract contact information.
80
+ Use `ChatAgent` for structured data extraction and conversational tasks. This example creates a reusable agent to extract contact information with full type safety.
66
81
 
67
82
  ```typescript
68
83
  import {
69
- BasicAgentAdapter,
70
- ModelPort,
71
- OpenRouterAdapter,
72
- SystemPromptAdapter,
73
- UserPromptAdapter,
74
- PROMPT_LIBRARY,
84
+ ChatAgent,
85
+ OpenRouterProvider,
86
+ SystemPrompt,
87
+ UserPrompt,
88
+ PROMPTS,
75
89
  } from '@jterrazz/intelligence';
76
90
  import { z } from 'zod';
77
91
 
78
- // 1. Define the output type for compile-time type-safety
79
- interface Contact {
80
- name: string;
81
- email: string;
82
- }
92
+ // 1. Define the output schema for both compile-time and runtime validation
93
+ const contactSchema = z.object({
94
+ name: z.string().describe('The full name of the person'),
95
+ email: z.string().email().describe('The email address'),
96
+ phone: z.string().optional().describe('Phone number if available'),
97
+ });
98
+
99
+ type Contact = z.infer<typeof contactSchema>;
100
+
101
+ // 2. Create a specialized agent by extending ChatAgent
102
+ class ContactExtractorAgent extends ChatAgent<Contact> {
103
+ constructor(provider: OpenRouterProvider) {
104
+ const model = provider.getModel('anthropic/claude-sonnet-4');
83
105
 
84
- // 2. Create a specialized agent by extending BasicAgentAdapter
85
- class ContactExtractorAgent extends BasicAgentAdapter<Contact> {
86
- constructor(model: ModelPort) {
87
106
  super('contact-extractor', {
88
107
  model,
89
- // Define the schema for runtime validation and type inference
90
- schema: z.object({
91
- name: z.string().describe('The full name of the person'),
92
- email: z.string().email().describe('The email address'),
93
- }),
94
- // Compose the system prompt from the library
95
- systemPrompt: new SystemPromptAdapter(
96
- PROMPT_LIBRARY.FORMATS.JSON,
108
+ schema: contactSchema, // Enables structured outputs + runtime validation
109
+ systemPrompt: new SystemPrompt(
97
110
  'You are an expert at extracting contact details from text.',
111
+ 'Always extract the most complete information available.',
98
112
  ),
99
113
  });
100
114
  }
101
115
  }
102
116
 
103
117
  // 3. Instantiate and use the agent
104
- const model = new OpenRouterAdapter({
118
+ const provider = new OpenRouterProvider({
105
119
  apiKey: process.env.OPENROUTER_API_KEY!,
106
- modelName: 'anthropic/claude-3.5-sonnet',
107
120
  });
108
- const agent = new ContactExtractorAgent(model);
121
+ const agent = new ContactExtractorAgent(provider);
109
122
 
110
- const text = 'Say hi to John Doe, you can reach him at john.doe@example.com.';
111
- const contact = await agent.run(new UserPromptAdapter(text));
123
+ const text =
124
+ 'Say hi to John Doe, you can reach him at john.doe@example.com or call (555) 123-4567.';
125
+ const contact = await agent.run(new UserPrompt(text));
112
126
 
113
127
  console.log(contact);
114
- // Output: { name: 'John Doe', email: 'john.doe@example.com' }
128
+ // Output: { name: 'John Doe', email: 'john.doe@example.com', phone: '(555) 123-4567' }
115
129
  ```
116
130
 
117
- ### 2. Autonomous Agent with a Custom Tool (`AutonomousAgentAdapter`)
131
+ ### 2. Tool-Enabled Agent (`ToolAgent`)
118
132
 
119
- Use `AutonomousAgentAdapter` when you need an agent that can reason and use tools to accomplish a task. This example creates a weather assistant that uses a tool and returns a structured JSON response.
133
+ Use `ToolAgent` when you need an agent that can reason and use tools to accomplish complex tasks. This example creates a weather assistant.
120
134
 
121
135
  ```typescript
122
136
  import {
123
- AutonomousAgentAdapter,
124
- ModelPort,
125
- OpenRouterAdapter,
126
- SafeToolAdapter,
127
- SystemPromptAdapter,
128
- UserPromptAdapter,
137
+ ToolAgent,
138
+ OpenRouterProvider,
139
+ SafeTool,
140
+ SystemPrompt,
141
+ UserPrompt,
129
142
  } from '@jterrazz/intelligence';
130
143
  import { z } from 'zod';
131
144
 
132
- // 1. Define the agent's final output type
133
- interface WeatherReport {
134
- city: string;
135
- temperature: number;
136
- conditions: string;
137
- forecast: string;
138
- }
145
+ // 1. Define the agent's final output schema
146
+ const weatherReportSchema = z.object({
147
+ city: z.string(),
148
+ temperature: z.number(),
149
+ conditions: z.string(),
150
+ forecast: z.string(),
151
+ });
139
152
 
140
- // 2. Define a tool. Its `execute` function should return a string,
141
- // as the agent will process this output to formulate a final answer.
142
- const weatherTool = new SafeToolAdapter({
153
+ type WeatherReport = z.infer<typeof weatherReportSchema>;
154
+
155
+ // 2. Create a weather tool
156
+ const weatherTool = new SafeTool({
143
157
  name: 'get_weather',
144
158
  description: 'Gets the current weather for a specified city.',
145
- schema: z.object({ city: z.string().describe('The name of the city') }),
159
+ schema: z.object({
160
+ city: z.string().describe('The name of the city'),
161
+ }),
146
162
  execute: async ({ city }) => {
147
- // In a real app, you would call a weather API here.
148
- // The tool returns raw data, often as a JSON string.
163
+ // In a real app, you would call a weather API here
149
164
  if (city.toLowerCase() === 'paris') {
150
165
  return JSON.stringify({
151
166
  city: 'Paris',
@@ -158,44 +173,145 @@ const weatherTool = new SafeToolAdapter({
158
173
  },
159
174
  });
160
175
 
161
- // 3. Create a specialized agent that uses the tool and has a structured output
162
- class WeatherAssistantAgent extends AutonomousAgentAdapter<WeatherReport> {
163
- constructor(model: ModelPort) {
176
+ // 3. Create a specialized tool agent
177
+ class WeatherAssistantAgent extends ToolAgent<WeatherReport> {
178
+ constructor(provider: OpenRouterProvider) {
179
+ const model = provider.getModel('anthropic/claude-sonnet-4');
180
+
164
181
  super('weather-assistant', {
165
182
  model,
166
183
  tools: [weatherTool],
167
- // This schema defines the agent's FINAL output structure
168
- schema: z.object({
169
- city: z.string(),
170
- temperature: z.number(),
171
- conditions: z.string(),
172
- forecast: z.string(),
173
- }),
174
- systemPrompt: new SystemPromptAdapter(
184
+ schema: weatherReportSchema, // Structured output for the final response
185
+ systemPrompt: new SystemPrompt(
175
186
  'You are a helpful weather assistant.',
176
- 'You must use the provided tools to get weather information and then respond with a structured JSON object.',
187
+ 'Use the available tools to get weather information, then provide a complete weather report.',
177
188
  ),
178
189
  });
179
190
  }
180
191
  }
181
192
 
182
193
  // 4. Instantiate and use the agent
183
- const model = new OpenRouterAdapter({
194
+ const provider = new OpenRouterProvider({
184
195
  apiKey: process.env.OPENROUTER_API_KEY!,
185
- modelName: 'anthropic/claude-3.5-sonnet',
186
196
  });
187
- const agent = new WeatherAssistantAgent(model);
197
+ const agent = new WeatherAssistantAgent(provider);
188
198
 
189
- const response = await agent.run(new UserPromptAdapter("What's the weather like in Paris?"));
199
+ const response = await agent.run(new UserPrompt("What's the weather like in Paris?"));
190
200
 
191
201
  console.log(response);
192
202
  // Output: { city: 'Paris', temperature: 25, conditions: 'sunny', forecast: 'clear skies for the next 24 hours' }
193
203
  ```
194
204
 
205
+ ### 3. Resilient Agent (`ResilientAgent`)
206
+
207
+ Use `ResilientAgent` to add retry logic and fault tolerance to any existing agent. Perfect for production environments where reliability is crucial.
208
+
209
+ ```typescript
210
+ import {
211
+ ChatAgent,
212
+ ResilientAgent,
213
+ OpenRouterProvider,
214
+ SystemPrompt,
215
+ UserPrompt,
216
+ } from '@jterrazz/intelligence';
217
+ import { z } from 'zod';
218
+
219
+ // 1. Create a base agent
220
+ const provider = new OpenRouterProvider({
221
+ apiKey: process.env.OPENROUTER_API_KEY!,
222
+ });
223
+
224
+ const model = provider.getModel('anthropic/claude-sonnet-4');
225
+
226
+ const baseAgent = new ChatAgent('sentiment-analyzer', {
227
+ model,
228
+ schema: z.object({
229
+ sentiment: z.enum(['positive', 'negative', 'neutral']),
230
+ confidence: z.number().min(0).max(1),
231
+ }),
232
+ systemPrompt: new SystemPrompt(
233
+ 'You are a sentiment analysis expert.',
234
+ 'Analyze the sentiment of the given text and provide your confidence level.',
235
+ ),
236
+ });
237
+
238
+ // 2. Wrap with resilient behavior
239
+ const resilientAgent = new ResilientAgent(baseAgent, {
240
+ retries: 3, // Will retry up to 3 times on failure
241
+ });
242
+
243
+ // 3. Use the resilient agent - it will automatically retry on failures
244
+ const result = await resilientAgent.run(new UserPrompt('I absolutely love this new feature!'));
245
+
246
+ console.log(result);
247
+ // Output: { sentiment: 'positive', confidence: 0.95 }
248
+ console.log(resilientAgent.name);
249
+ // Output: "Resilient(sentiment-analyzer)"
250
+ ```
251
+
252
+ ## Advanced Configuration
253
+
254
+ ### Model Configuration
255
+
256
+ Customize model behavior with detailed configuration options:
257
+
258
+ ```typescript
259
+ const provider = new OpenRouterProvider({
260
+ apiKey: process.env.OPENROUTER_API_KEY!,
261
+ metadata: {
262
+ application: 'My AI App',
263
+ website: 'https://myapp.com',
264
+ },
265
+ });
266
+
267
+ // Configure model-specific settings
268
+ const model = provider.getModel('anthropic/claude-sonnet-4', {
269
+ maxTokens: 100000,
270
+ reasoning: {
271
+ effort: 'high', // Use high reasoning effort for complex tasks
272
+ exclude: true, // Exclude reasoning from the response
273
+ },
274
+ });
275
+ ```
276
+
277
+ ### Combining Agents
278
+
279
+ Create powerful workflows by combining different agent types:
280
+
281
+ ```typescript
282
+ // Create a pipeline: Chat Agent → Tool Agent → Resilient wrapper
283
+ const extractor = new ChatAgent('data-extractor', {
284
+ /* ... */
285
+ });
286
+ const processor = new ToolAgent('data-processor', {
287
+ /* ... */
288
+ });
289
+ const resilientProcessor = new ResilientAgent(processor, { retries: 3 });
290
+
291
+ // Use them in sequence
292
+ const rawData = await extractor.run(userInput);
293
+ const processedData = await resilientProcessor.run(rawData);
294
+ ```
295
+
195
296
  ## Development
196
297
 
197
298
  - **Linting**: `npm run lint`
198
299
  - **Testing**: `npm run test`
300
+ - **Building**: `npm run build`
301
+
302
+ ## Architecture
303
+
304
+ The library follows **Clean Architecture** principles:
305
+
306
+ - **Ports**: Define interfaces for models, agents, tools, and prompts
307
+ - **Adapters**: Implement the ports for specific providers (OpenRouter, tools, etc.)
308
+ - **Domain Logic**: Core agent behavior independent of external dependencies
309
+
310
+ This makes the library:
311
+
312
+ - **Testable**: Easy to mock dependencies and test business logic
313
+ - **Extensible**: Simple to add new model providers or agent types
314
+ - **Maintainable**: Clear separation between domain logic and infrastructure
199
315
 
200
316
  ## Contributing
201
317
 
@@ -3,23 +3,23 @@ import { z } from 'zod/v4';
3
3
  import { type AgentPort } from '../../ports/agent.port.js';
4
4
  import type { ModelPort } from '../../ports/model.port.js';
5
5
  import type { PromptPort } from '../../ports/prompt.port.js';
6
- import type { SystemPromptAdapter } from '../prompts/system-prompt.adapter.js';
7
- export interface BasicAgentOptions<TOutput = string> {
6
+ import type { SystemPrompt } from '../prompts/system-prompt.adapter.js';
7
+ export interface ChatAgentOptions<TOutput = string> {
8
8
  logger?: LoggerPort;
9
9
  model: ModelPort;
10
10
  schema?: z.ZodSchema<TOutput>;
11
- systemPrompt: SystemPromptAdapter;
11
+ systemPrompt: SystemPrompt;
12
12
  verbose?: boolean;
13
13
  }
14
14
  /**
15
- * A basic agent for direct, one-shot interactions with a model.
15
+ * A conversational agent for direct, one-shot interactions with a model.
16
16
  * It supports optional response parsing against a Zod schema but does not use tools.
17
17
  * @template TOutput - The TypeScript type of the output
18
18
  */
19
- export declare class BasicAgentAdapter<TOutput = string> implements AgentPort<PromptPort, TOutput> {
19
+ export declare class ChatAgent<TOutput = string> implements AgentPort<PromptPort, TOutput> {
20
20
  readonly name: string;
21
21
  private readonly options;
22
- constructor(name: string, options: BasicAgentOptions<TOutput>);
22
+ constructor(name: string, options: ChatAgentOptions<TOutput>);
23
23
  run(input?: PromptPort): Promise<null | TOutput>;
24
24
  private invokeModel;
25
25
  private parseResponse;
@@ -157,22 +157,23 @@ function _ts_generator(thisArg, body) {
157
157
  };
158
158
  }
159
159
  }
160
+ import { generateText } from 'ai';
160
161
  import { z } from 'zod/v4';
161
- import { AIResponseParser } from '../utils/ai-response-parser.js';
162
+ import { StructuredResponseParser } from '../utils/structured-response-parser.js';
162
163
  /**
163
- * A basic agent for direct, one-shot interactions with a model.
164
+ * A conversational agent for direct, one-shot interactions with a model.
164
165
  * It supports optional response parsing against a Zod schema but does not use tools.
165
166
  * @template TOutput - The TypeScript type of the output
166
- */ export var BasicAgentAdapter = /*#__PURE__*/ function() {
167
+ */ export var ChatAgent = /*#__PURE__*/ function() {
167
168
  "use strict";
168
- function BasicAgentAdapter(name, options) {
169
- _class_call_check(this, BasicAgentAdapter);
169
+ function ChatAgent(name, options) {
170
+ _class_call_check(this, ChatAgent);
170
171
  _define_property(this, "name", void 0);
171
172
  _define_property(this, "options", void 0);
172
173
  this.name = name;
173
174
  this.options = options;
174
175
  }
175
- _create_class(BasicAgentAdapter, [
176
+ _create_class(ChatAgent, [
176
177
  {
177
178
  key: "run",
178
179
  value: function run(input) {
@@ -213,7 +214,6 @@ import { AIResponseParser } from '../utils/ai-response-parser.js';
213
214
  (_this_options_logger2 = this.options.logger) === null || _this_options_logger2 === void 0 ? void 0 : _this_options_logger2.debug('Execution finished', {
214
215
  agent: this.name
215
216
  });
216
- // When no schema is provided, we assume TOutput is string (default), so content is the result
217
217
  return [
218
218
  2,
219
219
  content
@@ -227,7 +227,8 @@ import { AIResponseParser } from '../utils/ai-response-parser.js';
227
227
  error = _state.sent();
228
228
  (_this_options_logger3 = this.options.logger) === null || _this_options_logger3 === void 0 ? void 0 : _this_options_logger3.error('Execution failed', {
229
229
  agent: this.name,
230
- error: _instanceof(error, Error) ? error.message : 'Unknown error'
230
+ error: _instanceof(error, Error) ? error.message : 'Unknown error',
231
+ errorStack: _instanceof(error, Error) ? error.stack : undefined
231
232
  });
232
233
  return [
233
234
  2,
@@ -246,13 +247,12 @@ import { AIResponseParser } from '../utils/ai-response-parser.js';
246
247
  key: "invokeModel",
247
248
  value: function invokeModel(input) {
248
249
  return _async_to_generator(function() {
249
- var _this_options_logger, userInput, systemMessage, jsonSchema, isPrimitiveType, messages, _this_options_logger1, response, content;
250
+ var _this_options_logger, userInput, systemMessage, jsonSchema, isPrimitiveType, messages, _this_options_logger1, generateConfig, jsonSchema1, text;
250
251
  return _ts_generator(this, function(_state) {
251
252
  switch(_state.label){
252
253
  case 0:
253
254
  userInput = this.resolveUserInput(input);
254
255
  systemMessage = this.options.systemPrompt.generate();
255
- // Add schema definition to system prompt if schema is provided
256
256
  if (this.options.schema) {
257
257
  jsonSchema = z.toJSONSchema(this.options.schema);
258
258
  isPrimitiveType = [
@@ -288,19 +288,36 @@ import { AIResponseParser } from '../utils/ai-response-parser.js';
288
288
  messages: messages
289
289
  });
290
290
  }
291
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
292
+ generateConfig = {
293
+ messages: messages,
294
+ model: this.options.model.getVercelModel()
295
+ };
296
+ // Prepare structured outputs configuration for better schema validation when schema is provided
297
+ // NOTE: OpenRouter supports structured outputs, but @openrouter/ai-sdk-provider (v0.7.3)
298
+ // doesn't pass through responseFormat parameter yet. Currently relies on prompt-based instructions.
299
+ // Once provider support is added, this will provide stronger guarantees than prompts alone.
300
+ // See: https://openrouter.ai/docs/features/structured-outputs
301
+ if (this.options.schema) {
302
+ jsonSchema1 = z.toJSONSchema(this.options.schema);
303
+ generateConfig.responseFormat = {
304
+ json_schema: {
305
+ name: 'response',
306
+ schema: jsonSchema1,
307
+ strict: true
308
+ },
309
+ type: 'json_schema'
310
+ };
311
+ }
291
312
  return [
292
313
  4,
293
- this.options.model.getModel().invoke(messages)
314
+ generateText(generateConfig)
294
315
  ];
295
316
  case 1:
296
- response = _state.sent();
297
- content = response.content;
298
- if (typeof content !== 'string') {
299
- throw new Error('Model returned a non-string content type.');
300
- }
317
+ text = _state.sent().text;
301
318
  return [
302
319
  2,
303
- content
320
+ text
304
321
  ];
305
322
  }
306
323
  });
@@ -311,7 +328,7 @@ import { AIResponseParser } from '../utils/ai-response-parser.js';
311
328
  key: "parseResponse",
312
329
  value: function parseResponse(content, schema) {
313
330
  try {
314
- return new AIResponseParser(schema).parse(content);
331
+ return new StructuredResponseParser(schema).parse(content);
315
332
  } catch (error) {
316
333
  var _this_options_logger;
317
334
  (_this_options_logger = this.options.logger) === null || _this_options_logger === void 0 ? void 0 : _this_options_logger.error('Failed to parse model response.', {
@@ -333,7 +350,7 @@ import { AIResponseParser } from '../utils/ai-response-parser.js';
333
350
  }
334
351
  }
335
352
  ]);
336
- return BasicAgentAdapter;
353
+ return ChatAgent;
337
354
  }();
338
355
 
339
- //# sourceMappingURL=basic-agent.adapter.js.map
356
+ //# sourceMappingURL=chat-agent.adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/adapters/agents/chat-agent.adapter.ts"],"sourcesContent":["import { type LoggerPort } from '@jterrazz/logger';\nimport { generateText } from 'ai';\nimport { z } from 'zod/v4';\n\nimport { type AgentPort } from '../../ports/agent.port.js';\nimport type { ModelPort } from '../../ports/model.port.js';\nimport type { PromptPort } from '../../ports/prompt.port.js';\n\nimport { StructuredResponseParser } from '../utils/structured-response-parser.js';\n\nimport type { SystemPrompt } from '../prompts/system-prompt.adapter.js';\n\nexport interface ChatAgentOptions<TOutput = string> {\n logger?: LoggerPort;\n model: ModelPort;\n schema?: z.ZodSchema<TOutput>;\n systemPrompt: SystemPrompt;\n verbose?: boolean;\n}\n\n/**\n * A conversational agent for direct, one-shot interactions with a model.\n * It supports optional response parsing against a Zod schema but does not use tools.\n * @template TOutput - The TypeScript type of the output\n */\nexport class ChatAgent<TOutput = string> implements AgentPort<PromptPort, TOutput> {\n constructor(\n public readonly name: string,\n private readonly options: ChatAgentOptions<TOutput>,\n ) {}\n\n async run(input?: PromptPort): Promise<null | TOutput> {\n this.options.logger?.debug('Starting query execution', { agent: this.name });\n\n try {\n const content = await this.invokeModel(input);\n\n if (this.options.schema) {\n const parsedResponse = this.parseResponse(content, this.options.schema);\n\n this.options.logger?.debug('Execution finished and response parsed', {\n agent: this.name,\n });\n\n return parsedResponse;\n } else {\n this.options.logger?.debug('Execution finished', { agent: this.name });\n\n return content as TOutput;\n }\n } catch (error) {\n this.options.logger?.error('Execution failed', {\n agent: this.name,\n error: error instanceof Error ? error.message : 'Unknown error',\n errorStack: error instanceof Error ? error.stack : undefined,\n });\n return null;\n }\n }\n\n private async invokeModel(input?: PromptPort): Promise<string> {\n const userInput = this.resolveUserInput(input);\n let systemMessage = this.options.systemPrompt.generate();\n\n if (this.options.schema) {\n const jsonSchema = z.toJSONSchema(this.options.schema);\n const isPrimitiveType = ['boolean', 'integer', 'number', 'string'].includes(\n jsonSchema.type as string,\n );\n\n if (isPrimitiveType) {\n systemMessage += `\\n\\n<OUTPUT_FORMAT>\nYou must respond with a ${jsonSchema.type} value that matches this schema:\n\n\\`\\`\\`json\n${JSON.stringify(jsonSchema, null, 2)}\n\\`\\`\\`\n\nYour response should be only the ${jsonSchema.type} value, without any JSON wrapping or additional text.\n</OUTPUT_FORMAT>`;\n } else {\n systemMessage += `\\n\\n<OUTPUT_FORMAT>\nYou must respond with valid JSON that matches this JSON schema description:\n\n\\`\\`\\`json\n${JSON.stringify(jsonSchema, null, 2)}\n\\`\\`\\`\n\nYour response must be parseable JSON that validates against this schema. Do not include any text outside the JSON.\n</OUTPUT_FORMAT>`;\n }\n }\n\n const messages = [\n { content: systemMessage, role: 'system' as const },\n { content: userInput, role: 'user' as const },\n ];\n\n this.options.logger?.debug('Invoking model...', {\n agent: this.name,\n hasSchema: !!this.options.schema,\n });\n\n if (this.options.verbose) {\n this.options.logger?.debug('Sending messages to model...', {\n agent: this.name,\n messages,\n });\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const generateConfig: any = {\n messages,\n model: this.options.model.getVercelModel(),\n };\n\n // Prepare structured outputs configuration for better schema validation when schema is provided\n // NOTE: OpenRouter supports structured outputs, but @openrouter/ai-sdk-provider (v0.7.3)\n // doesn't pass through responseFormat parameter yet. Currently relies on prompt-based instructions.\n // Once provider support is added, this will provide stronger guarantees than prompts alone.\n // See: https://openrouter.ai/docs/features/structured-outputs\n if (this.options.schema) {\n const jsonSchema = z.toJSONSchema(this.options.schema);\n generateConfig.responseFormat = {\n json_schema: {\n name: 'response',\n schema: jsonSchema,\n strict: true,\n },\n type: 'json_schema',\n };\n }\n\n const { text } = await generateText(generateConfig);\n\n return text;\n }\n\n private parseResponse<TResponse>(content: string, schema: z.ZodSchema<TResponse>): TResponse {\n try {\n return new StructuredResponseParser(schema).parse(content);\n } catch (error) {\n this.options.logger?.error('Failed to parse model response.', {\n agent: this.name,\n error: error instanceof Error ? error.message : 'Unknown error',\n rawContent: content,\n });\n throw new Error('Invalid response format from model.');\n }\n }\n\n private resolveUserInput(input?: PromptPort): string {\n if (input) {\n return input.generate();\n }\n return 'Proceed with your instructions.';\n }\n}\n"],"names":["generateText","z","StructuredResponseParser","ChatAgent","name","options","run","input","content","parsedResponse","error","logger","debug","agent","invokeModel","schema","parseResponse","Error","message","errorStack","stack","undefined","userInput","systemMessage","jsonSchema","isPrimitiveType","messages","generateConfig","text","resolveUserInput","systemPrompt","generate","toJSONSchema","includes","type","JSON","stringify","role","hasSchema","verbose","model","getVercelModel","responseFormat","json_schema","strict","parse","rawContent"],"mappings":"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"}
@@ -1,20 +1,20 @@
1
1
  import { type LoggerPort } from '@jterrazz/logger';
2
2
  import { type AgentPort } from '../../ports/agent.port.js';
3
3
  import type { PromptPort } from '../../ports/prompt.port.js';
4
- export interface RetryableAgentAdapterOptions {
4
+ export interface ResilientAgentOptions {
5
5
  logger?: LoggerPort;
6
6
  retries?: number;
7
7
  }
8
8
  /**
9
- * A decorator agent that adds retry logic to an existing agent.
9
+ * A decorator agent that adds retry logic to an existing agent for resilient execution.
10
10
  * @template TInput - The TypeScript type of the input
11
11
  * @template TOutput - The TypeScript type of the output
12
12
  */
13
- export declare class RetryableAgentAdapter<TInput = PromptPort, TOutput = string> implements AgentPort<TInput, TOutput> {
13
+ export declare class ResilientAgent<TInput = PromptPort, TOutput = string> implements AgentPort<TInput, TOutput> {
14
14
  private readonly agent;
15
15
  readonly name: string;
16
16
  private readonly logger?;
17
17
  private readonly retries;
18
- constructor(agent: AgentPort<TInput, TOutput>, options?: RetryableAgentAdapterOptions);
18
+ constructor(agent: AgentPort<TInput, TOutput>, options?: ResilientAgentOptions);
19
19
  run(input?: TInput): Promise<null | TOutput>;
20
20
  }
@@ -158,25 +158,25 @@ function _ts_generator(thisArg, body) {
158
158
  }
159
159
  }
160
160
  /**
161
- * A decorator agent that adds retry logic to an existing agent.
161
+ * A decorator agent that adds retry logic to an existing agent for resilient execution.
162
162
  * @template TInput - The TypeScript type of the input
163
163
  * @template TOutput - The TypeScript type of the output
164
- */ export var RetryableAgentAdapter = /*#__PURE__*/ function() {
164
+ */ export var ResilientAgent = /*#__PURE__*/ function() {
165
165
  "use strict";
166
- function RetryableAgentAdapter(agent) {
166
+ function ResilientAgent(agent) {
167
167
  var options = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
168
- _class_call_check(this, RetryableAgentAdapter);
168
+ _class_call_check(this, ResilientAgent);
169
169
  _define_property(this, "agent", void 0);
170
170
  _define_property(this, "name", void 0);
171
171
  _define_property(this, "logger", void 0);
172
172
  _define_property(this, "retries", void 0);
173
173
  this.agent = agent;
174
174
  var logger = options.logger, _options_retries = options.retries, retries = _options_retries === void 0 ? 1 : _options_retries;
175
- this.name = "Retryable(".concat(agent.name, ")");
175
+ this.name = "Resilient(".concat(agent.name, ")");
176
176
  this.logger = logger;
177
177
  this.retries = retries;
178
178
  }
179
- _create_class(RetryableAgentAdapter, [
179
+ _create_class(ResilientAgent, [
180
180
  {
181
181
  key: "run",
182
182
  value: function run(input) {
@@ -257,7 +257,7 @@ function _ts_generator(thisArg, body) {
257
257
  }
258
258
  }
259
259
  ]);
260
- return RetryableAgentAdapter;
260
+ return ResilientAgent;
261
261
  }();
262
262
 
263
- //# sourceMappingURL=retryable-agent.adapter.js.map
263
+ //# sourceMappingURL=resilient-agent.adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/adapters/agents/resilient-agent.adapter.ts"],"sourcesContent":["import { type LoggerPort } from '@jterrazz/logger';\n\nimport { type AgentPort } from '../../ports/agent.port.js';\nimport type { PromptPort } from '../../ports/prompt.port.js';\n\nexport interface ResilientAgentOptions {\n logger?: LoggerPort;\n retries?: number;\n}\n\n/**\n * A decorator agent that adds retry logic to an existing agent for resilient execution.\n * @template TInput - The TypeScript type of the input\n * @template TOutput - The TypeScript type of the output\n */\nexport class ResilientAgent<TInput = PromptPort, TOutput = string>\n implements AgentPort<TInput, TOutput>\n{\n public readonly name: string;\n private readonly logger?: LoggerPort;\n private readonly retries: number;\n\n constructor(\n private readonly agent: AgentPort<TInput, TOutput>,\n options: ResilientAgentOptions = {},\n ) {\n const { logger, retries = 1 } = options;\n this.name = `Resilient(${agent.name})`;\n this.logger = logger;\n this.retries = retries;\n }\n\n async run(input?: TInput): Promise<null | TOutput> {\n const maxAttempts = this.retries + 1;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n this.logger?.debug(`Attempt ${attempt} of ${maxAttempts}`, { agent: this.name });\n const result = await this.agent.run(input);\n\n if (result !== null) {\n this.logger?.debug(`Attempt ${attempt} of ${maxAttempts} succeeded`, {\n agent: this.name,\n });\n return result;\n }\n\n this.logger?.debug(\n `Attempt ${attempt} of ${maxAttempts} failed: agent returned null`,\n { agent: this.name },\n );\n } catch (error) {\n this.logger?.debug(`Attempt ${attempt} of ${maxAttempts} failed with an error`, {\n agent: this.name,\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n }\n }\n\n this.logger?.error(`All ${maxAttempts} attempts failed`, { agent: this.name });\n return null;\n }\n}\n"],"names":["ResilientAgent","agent","options","name","logger","retries","run","input","maxAttempts","attempt","result","error","debug","Error","message"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAUA;;;;CAIC,GACD,OAAO,IAAA,AAAMA,+BAAN;;aAAMA,eAQL,AAAiBC,KAAiC;YAClDC,UAAAA,iEAAiC,CAAC;gCAT7BF;;QAGT,uBAAgBG,QAAhB,KAAA;QACA,uBAAiBC,UAAjB,KAAA;QACA,uBAAiBC,WAAjB,KAAA;aAGqBJ,QAAAA;QAGjB,IAAQG,SAAwBF,QAAxBE,2BAAwBF,QAAhBG,SAAAA,wCAAU;QAC1B,IAAI,CAACF,IAAI,GAAG,AAAC,aAAuB,OAAXF,MAAME,IAAI,EAAC;QACpC,IAAI,CAACC,MAAM,GAAGA;QACd,IAAI,CAACC,OAAO,GAAGA;;kBAdVL;;YAiBHM,KAAAA;mBAAN,SAAMA,IAAIC,KAAc;;wBA2BpB,cA1BMC,aAEGC,SAED,eAUA,eATMC,QAGF,eAUCC,OACL;;;;gCAnBFH,cAAc,IAAI,CAACH,OAAO,GAAG;gCAE1BI,UAAU;;;qCAAGA,CAAAA,WAAWD,WAAU;;;;;;;;;;;;iCAEnC,gBAAA,IAAI,CAACJ,MAAM,cAAX,oCAAA,cAAaQ,KAAK,CAAC,AAAC,WAAwBJ,OAAdC,SAAQ,QAAkB,OAAZD,cAAe;oCAAEP,OAAO,IAAI,CAACE,IAAI;gCAAC;gCAC/D;;oCAAM,IAAI,CAACF,KAAK,CAACK,GAAG,CAACC;;;gCAA9BG,SAAS;gCAEf,IAAIA,WAAW,MAAM;;qCACjB,gBAAA,IAAI,CAACN,MAAM,cAAX,oCAAA,cAAaQ,KAAK,CAAC,AAAC,WAAwBJ,OAAdC,SAAQ,QAAkB,OAAZD,aAAY,eAAa;wCACjEP,OAAO,IAAI,CAACE,IAAI;oCACpB;oCACA;;wCAAOO;;gCACX;iCAEA,gBAAA,IAAI,CAACN,MAAM,cAAX,oCAAA,cAAaQ,KAAK,CACd,AAAC,WAAwBJ,OAAdC,SAAQ,QAAkB,OAAZD,aAAY,iCACrC;oCAAEP,OAAO,IAAI,CAACE,IAAI;gCAAC;;;;;;gCAElBQ;iCACL,gBAAA,IAAI,CAACP,MAAM,cAAX,oCAAA,cAAaQ,KAAK,CAAC,AAAC,WAAwBJ,OAAdC,SAAQ,QAAkB,OAAZD,aAAY,0BAAwB;oCAC5EP,OAAO,IAAI,CAACE,IAAI;oCAChBQ,OAAOA,AAAK,YAALA,OAAiBE,SAAQF,MAAMG,OAAO,GAAG;gCACpD;;;;;;gCApBsCL;;;;;;iCAwB9C,eAAA,IAAI,CAACL,MAAM,cAAX,mCAAA,aAAaO,KAAK,CAAC,AAAC,OAAkB,OAAZH,aAAY,qBAAmB;oCAAEP,OAAO,IAAI,CAACE,IAAI;gCAAC;gCAC5E;;oCAAO;;;;gBACX;;;;WA9CSH;IA+CZ"}