@jterrazz/intelligence 1.2.0 → 1.4.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.
package/README.md CHANGED
@@ -5,16 +5,17 @@
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. By combining a composable prompt system, safe tool integration, and a ports-and-adapters architecture, it empowers developers to create reliable and maintainable AI-powered applications.
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.
9
9
 
10
10
  ---
11
11
 
12
- ## Why Use This Library?
12
+ ## Core Principles
13
13
 
14
- - **🤖 Build Predictable Agents**: Use the composable prompt library to ensure your agents have a consistent personality, tone, and behavior.
15
- - **🛠️ Integrate Tools Safely**: `SafeToolAdapter` provides built-in error handling, logging, and Zod-based schema validation for all your tools.
16
- - **🏗️ Stay Flexible**: The ports-and-adapters architecture makes it easy to swap out underlying models or frameworks (like LangChain) without rewriting your core logic.
17
- - **🎯 Get Type-Safe Responses**: Move beyond string parsing with `AIResponseParser`, which validates and types your model's output against a Zod schema.
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
+
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.
17
+
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.
18
19
 
19
20
  ## Installation
20
21
 
@@ -26,11 +27,11 @@ npm install @jterrazz/intelligence
26
27
 
27
28
  ## Quick Start
28
29
 
29
- Get your first agent running in under a minute. This example uses a preset to create a helpful Discord community animator.
30
+ Get your first agent running in minutes. This example creates a helpful agent for a Discord community.
30
31
 
31
32
  ```typescript
32
33
  import {
33
- ChatAgentAdapter,
34
+ AutonomousAgentAdapter,
34
35
  OpenRouterAdapter,
35
36
  SystemPromptAdapter,
36
37
  PROMPT_LIBRARY,
@@ -43,7 +44,7 @@ const model = new OpenRouterAdapter({
43
44
  });
44
45
 
45
46
  // 2. Create an agent using a preset prompt
46
- const agent = new ChatAgentAdapter('discord-bot', {
47
+ const agent = new AutonomousAgentAdapter('discord-bot', {
47
48
  model,
48
49
  systemPrompt: new SystemPromptAdapter(PROMPT_LIBRARY.PRESETS.COMMUNITY_ANIMATOR),
49
50
  });
@@ -55,277 +56,153 @@ console.log(response);
55
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?"
56
57
  ```
57
58
 
58
- ---
59
-
60
- ## Core Concepts
61
-
62
- ### 1. Composable Prompts
63
-
64
- Instead of writing monolithic prompts, the library provides a collection of composable string constants. Mix and match them to build a precise, fine-grained system prompt that defines your agent's behavior.
65
-
66
- - **`FOUNDATIONS`**: Core, non-negotiable rules (e.g., `PROMPT_LIBRARY.FOUNDATIONS.ETHICAL_CONDUCT`).
67
- - **`PERSONAS`**: The agent's identity and purpose (e.g., `PROMPT_LIBRARY.PERSONAS.EXPERT_ADVISOR`).
68
- - **`DOMAINS`**: The agent's area of expertise (e.g., `PROMPT_LIBRARY.DOMAINS.SOFTWARE_ENGINEERING`).
69
- - **`TONES`**: The emotional flavor of communication (e.g., `PROMPT_LIBRARY.TONES.PROFESSIONAL`).
70
- - **`FORMATS`**: The structural format of the output (e.g., `PROMPT_LIBRARY.FORMATS.JSON`).
71
- - **`LANGUAGES`**: The natural language for the response (e.g., `PROMPT_LIBRARY.LANGUAGES.ENGLISH_NATIVE`).
72
- - **`VERBOSITY`**: The level of detail in the response (e.g., `PROMPT_LIBRARY.VERBOSITY.DETAILED`).
73
- - **`RESPONSES`**: The strategic approach to responding (e.g., `PROMPT_LIBRARY.RESPONSES.ALWAYS_ENGAGE`).
74
-
75
- This approach makes agent behavior more predictable and easier to modify.
76
-
77
- ### 2. Safe Tool Integration
78
-
79
- The `SafeToolAdapter` is a wrapper for your functions that ensures they are executed safely.
80
-
81
- ```typescript
82
- import { SafeToolAdapter } from '@jterrazz/intelligence';
83
- import { z } from 'zod/v4';
84
-
85
- const weatherTool = new SafeToolAdapter(
86
- {
87
- name: 'get_weather',
88
- description: 'Get the current weather for a specific city.',
89
- execute: async ({ city }) => `The weather in ${city} is currently sunny.`,
90
- },
91
- {
92
- // Zod schema for automatic validation and type-safety
93
- schema: z.object({
94
- city: z.string().describe('The city name'),
95
- }),
96
- },
97
- );
98
- ```
99
-
100
- The adapter handles errors gracefully and integrates seamlessly with the agent, which will automatically provide the Zod schema to the underlying model.
101
-
102
- ### 3. Ports and Adapters Architecture
103
-
104
- The library is built on a hexagonal architecture.
105
-
106
- - **Ports (`/ports`)**: Define the contracts (interfaces) for core components like `Agent`, `Model`, and `Tool`.
107
- - **Adapters (`/adapters`)**: Provide concrete implementations. For example, `ChatAgentAdapter` is an adapter that uses LangChain, and `OpenRouterAdapter` is an adapter for the OpenRouter API.
108
-
109
- This separation of concerns means you can easily create your own adapters to support different models or services without changing the application's core logic.
110
-
111
- ```
112
- src/
113
- ├── ports/ # Abstract interfaces (the "what")
114
- └── adapters/ # Concrete implementations (the "how")
115
- ```
116
-
117
- ---
59
+ ## Creating Domain-Specific Agents
118
60
 
119
- ## Recipes
61
+ 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.
120
62
 
121
- ### Recipe: Code Review Assistant
63
+ ### 1. Data Extraction Agent (`BasicAgentAdapter`)
122
64
 
123
- This recipe creates an agent that acts as an expert software engineer, providing detailed feedback on code.
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.
124
66
 
125
67
  ```typescript
126
68
  import {
127
- ChatAgentAdapter,
69
+ BasicAgentAdapter,
70
+ ModelPort,
128
71
  OpenRouterAdapter,
129
72
  SystemPromptAdapter,
130
73
  UserPromptAdapter,
131
74
  PROMPT_LIBRARY,
132
75
  } from '@jterrazz/intelligence';
133
-
76
+ import { z } from 'zod';
77
+
78
+ // 1. Define the output type for compile-time type-safety
79
+ interface Contact {
80
+ name: string;
81
+ email: string;
82
+ }
83
+
84
+ // 2. Create a specialized agent by extending BasicAgentAdapter
85
+ class ContactExtractorAgent extends BasicAgentAdapter<Contact> {
86
+ constructor(model: ModelPort) {
87
+ super('contact-extractor', {
88
+ 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,
97
+ 'You are an expert at extracting contact details from text.',
98
+ ),
99
+ });
100
+ }
101
+ }
102
+
103
+ // 3. Instantiate and use the agent
134
104
  const model = new OpenRouterAdapter({
135
105
  apiKey: process.env.OPENROUTER_API_KEY!,
136
106
  modelName: 'anthropic/claude-3.5-sonnet',
137
107
  });
108
+ const agent = new ContactExtractorAgent(model);
138
109
 
139
- // 1. Compose the system prompt from multiple parts (using rest arguments)
140
- const systemPrompt = new SystemPromptAdapter(
141
- PROMPT_LIBRARY.PERSONAS.EXPERT_ADVISOR,
142
- PROMPT_LIBRARY.DOMAINS.SOFTWARE_ENGINEERING,
143
- PROMPT_LIBRARY.TONES.PROFESSIONAL,
144
- PROMPT_LIBRARY.VERBOSITY.DETAILED,
145
- PROMPT_LIBRARY.FORMATS.MARKDOWN,
146
- PROMPT_LIBRARY.FOUNDATIONS.FACTUAL_ACCURACY,
147
- );
148
-
149
- // 2. Create the user request (using a single array)
150
- const userPrompt = new UserPromptAdapter([
151
- 'Please review this TypeScript code for best practices:',
152
- 'const x = (s) => s.trim();',
153
- ]);
154
-
155
- // 3. Configure and run the agent
156
- const agent = new ChatAgentAdapter('code-reviewer', {
157
- model,
158
- systemPrompt,
159
- });
160
-
161
- const response = await agent.run(userPrompt);
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));
162
112
 
163
- console.log(response);
113
+ console.log(contact);
114
+ // Output: { name: 'John Doe', email: 'john.doe@example.com' }
164
115
  ```
165
116
 
166
- ### Recipe: Simple Text Processor (QueryAgent)
117
+ ### 2. Autonomous Agent with a Custom Tool (`AutonomousAgentAdapter`)
167
118
 
168
- This example shows how to use the simpler `QueryAgentAdapter` for one-shot responses without tools.
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.
169
120
 
170
121
  ```typescript
171
122
  import {
172
- QueryAgentAdapter,
123
+ AutonomousAgentAdapter,
124
+ ModelPort,
173
125
  OpenRouterAdapter,
126
+ SafeToolAdapter,
174
127
  SystemPromptAdapter,
175
128
  UserPromptAdapter,
176
- PROMPT_LIBRARY,
177
129
  } from '@jterrazz/intelligence';
178
-
179
- const model = new OpenRouterAdapter({
180
- apiKey: process.env.OPENROUTER_API_KEY!,
181
- modelName: 'anthropic/claude-3.5-sonnet',
182
- });
183
-
184
- // 1. Create a simple system prompt for text processing
185
- const systemPrompt = new SystemPromptAdapter(
186
- PROMPT_LIBRARY.PERSONAS.EXPERT_ADVISOR,
187
- PROMPT_LIBRARY.TONES.PROFESSIONAL,
188
- PROMPT_LIBRARY.FORMATS.MARKDOWN,
189
- 'You are a helpful assistant that improves text clarity and grammar.',
190
- );
191
-
192
- // 2. Create a query agent (no tools needed)
193
- const agent = new QueryAgentAdapter('text-processor', {
194
- model,
195
- systemPrompt,
130
+ import { z } from 'zod';
131
+
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
+ }
139
+
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({
143
+ name: 'get_weather',
144
+ description: 'Gets the current weather for a specified city.',
145
+ schema: z.object({ city: z.string().describe('The name of the city') }),
146
+ 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.
149
+ if (city.toLowerCase() === 'paris') {
150
+ return JSON.stringify({
151
+ city: 'Paris',
152
+ temperature: 25,
153
+ conditions: 'sunny',
154
+ forecast: 'clear skies for the next 24 hours',
155
+ });
156
+ }
157
+ return `Sorry, I don't have weather information for ${city}.`;
158
+ },
196
159
  });
197
160
 
198
- // 3. Run a simple query
199
- const userPrompt = new UserPromptAdapter(
200
- 'Please improve this text: "Me and john was going to store yesterday"',
201
- );
202
- const response = await agent.run(userPrompt);
203
-
204
- console.log(response);
205
- // Expected output: A grammatically corrected and improved version of the text
206
- ```
207
-
208
- ### Recipe: Structured Data Extraction (QueryAgent with Schema)
209
-
210
- This example shows how to use `QueryAgentAdapter` with schema parsing for structured responses.
211
-
212
- ```typescript
213
- import {
214
- QueryAgentAdapter,
215
- OpenRouterAdapter,
216
- SystemPromptAdapter,
217
- UserPromptAdapter,
218
- PROMPT_LIBRARY,
219
- } from '@jterrazz/intelligence';
220
- import { z } from 'zod/v4';
221
-
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) {
164
+ super('weather-assistant', {
165
+ model,
166
+ 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(
175
+ '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.',
177
+ ),
178
+ });
179
+ }
180
+ }
181
+
182
+ // 4. Instantiate and use the agent
222
183
  const model = new OpenRouterAdapter({
223
184
  apiKey: process.env.OPENROUTER_API_KEY!,
224
185
  modelName: 'anthropic/claude-3.5-sonnet',
225
186
  });
187
+ const agent = new WeatherAssistantAgent(model);
226
188
 
227
- // 1. Define the response schema
228
- const extractionSchema = z.object({
229
- name: z.string(),
230
- email: z.string().email(),
231
- phone: z.string().optional(),
232
- company: z.string().optional(),
233
- });
234
-
235
- // 2. Create a system prompt for data extraction
236
- const systemPrompt = new SystemPromptAdapter(
237
- PROMPT_LIBRARY.PERSONAS.EXPERT_ADVISOR,
238
- PROMPT_LIBRARY.TONES.PROFESSIONAL,
239
- PROMPT_LIBRARY.FORMATS.JSON,
240
- 'You extract contact information from text and return it as JSON.',
241
- );
242
-
243
- // 3. Create a query agent with schema parsing
244
- const agent = new QueryAgentAdapter('contact-extractor', {
245
- model,
246
- schema: extractionSchema,
247
- systemPrompt,
248
- });
249
-
250
- // 4. Run the query
251
- const userPrompt = new UserPromptAdapter(
252
- 'Extract contact info: "Hi, I\'m John Doe from TechCorp. Email me at john@techcorp.com or call 555-1234"',
253
- );
254
- const response = await agent.run(userPrompt);
255
-
256
- // 5. Get both raw response and parsed data
257
- console.log('Raw response:', response);
258
- const parsedData = agent.getLastParsedResult();
259
- console.log('Parsed data:', parsedData);
260
- // Expected: { name: "John Doe", email: "john@techcorp.com", phone: "555-1234", company: "TechCorp" }
261
- ```
262
-
263
- ### Recipe: Weather Bot with Tools
264
-
265
- This example shows how to give an agent a tool and have it respond to a user query.
266
-
267
- ```typescript
268
- import {
269
- ChatAgentAdapter,
270
- OpenRouterAdapter,
271
- SafeToolAdapter,
272
- SystemPromptAdapter,
273
- UserPromptAdapter,
274
- PROMPT_LIBRARY,
275
- } from '@jterrazz/intelligence';
276
- import { z } from 'zod/v4';
277
-
278
- // Assume 'model' is already configured
279
-
280
- // 1. Define the tool
281
- const weatherTool = new SafeToolAdapter(
282
- {
283
- name: 'get_weather',
284
- description: 'Get the current weather for a location.',
285
- execute: async ({ city }) => {
286
- // In a real app, you would fetch from a weather API here
287
- return `The weather in ${city} is 75°F and sunny.`;
288
- },
289
- },
290
- { schema: z.object({ city: z.string().describe('City name') }) },
291
- );
292
-
293
- // 2. Create an agent that knows how to use tools
294
- const agent = new ChatAgentAdapter('weather-bot', {
295
- model,
296
- systemPrompt: new SystemPromptAdapter(PROMPT_LIBRARY.PRESETS.EMPATHETIC_SUPPORT_AGENT), // A good general-purpose preset
297
- tools: [weatherTool], // Pass the tool instance directly
298
- });
299
-
300
- // 3. Run the agent with a user query that requires the tool
301
- const response = await agent.run(new UserPromptAdapter("What's the weather like in Boston?"));
189
+ const response = await agent.run(new UserPromptAdapter("What's the weather like in Paris?"));
302
190
 
303
191
  console.log(response);
304
- // Expected output: "The weather in Boston is 75°F and sunny."
192
+ // Output: { city: 'Paris', temperature: 25, conditions: 'sunny', forecast: 'clear skies for the next 24 hours' }
305
193
  ```
306
194
 
307
- ---
308
-
309
- ## API Reference
310
-
311
- ### Core Components
195
+ ## Development
312
196
 
313
- | Class | Description |
314
- | ------------------------ | -------------------------------------------------------------------------- |
315
- | `ChatAgentAdapter` | The main agent implementation. Runs prompts and coordinates tools. |
316
- | `QueryAgentAdapter` | A simpler agent for one-shot responses without tools or complex logic. |
317
- | `OpenRouterModelAdapter` | An adapter for connecting to any model on the OpenRouter platform. |
318
- | `SafeToolAdapter` | A type-safe wrapper for creating tools with validation and error handling. |
319
- | `SystemPromptAdapter` | A simple adapter to generate a system prompt string from a prompt array. |
320
- | `UserPromptAdapter` | A simple adapter to generate a user prompt string from a prompt array. |
321
- | `AIResponseParser` | A utility to parse a model's string output into a typed object using Zod. |
322
- | `PROMPT_LIBRARY` | A frozen object containing the entire composable prompt library. |
197
+ - **Linting**: `npm run lint`
198
+ - **Testing**: `npm run test`
323
199
 
324
200
  ## Contributing
325
201
 
326
- Contributions are welcome! Please feel free to submit a Pull Request.
202
+ Contributions are welcome! Please feel free to open an issue or submit a pull request.
203
+
204
+ ---
327
205
 
328
- ## Author
206
+ ## License
329
207
 
330
- - Jean-Baptiste Terrazzoni ([@jterrazz](https://github.com/jterrazz))
331
- - Email: contact@jterrazz.com
208
+ This project is licensed under the [MIT License](./LICENSE).
@@ -1,27 +1,28 @@
1
1
  import { type LoggerPort } from '@jterrazz/logger';
2
- import { type z } from 'zod/v4';
2
+ 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
6
  import type { ToolPort } from '../../ports/tool.port.js';
7
7
  import type { SystemPromptAdapter } from '../prompts/system-prompt.adapter.js';
8
- export interface ChatAgentOptions<T = unknown> {
8
+ export interface AutonomousAgentOptions<TOutput = string> {
9
9
  logger?: LoggerPort;
10
10
  model: ModelPort;
11
- schema?: z.ZodSchema<T>;
11
+ schema?: z.ZodSchema<TOutput>;
12
12
  systemPrompt: SystemPromptAdapter;
13
13
  tools: ToolPort[];
14
14
  verbose?: boolean;
15
15
  }
16
16
  /**
17
- * An advanced agent that uses tools and a structured prompt to engage in conversational chat.
17
+ * An autonomous agent that uses tools and a structured prompt to accomplish tasks.
18
18
  * It can decide whether to respond or remain silent and supports schema-validated responses.
19
+ * @template TOutput - The TypeScript type of the output
19
20
  */
20
- export declare class ChatAgentAdapter<T = unknown> implements AgentPort {
21
+ export declare class AutonomousAgentAdapter<TOutput = string> implements AgentPort<PromptPort, TOutput> {
21
22
  readonly name: string;
22
23
  private readonly options;
23
- constructor(name: string, options: ChatAgentOptions<T>);
24
- run(userPrompt?: PromptPort): Promise<null | string>;
24
+ constructor(name: string, options: AutonomousAgentOptions<TOutput>);
25
+ run(input?: PromptPort): Promise<null | TOutput>;
25
26
  private createExecutor;
26
27
  private parseAgentOutput;
27
28
  private resolveUserInput;
@@ -159,26 +159,28 @@ function _ts_generator(thisArg, body) {
159
159
  }
160
160
  import { ChatPromptTemplate } from '@langchain/core/prompts';
161
161
  import { AgentExecutor, createStructuredChatAgent } from 'langchain/agents';
162
+ import { z } from 'zod/v4';
162
163
  import { AIResponseParser } from '../utils/ai-response-parser.js';
163
- var SYSTEM_PROMPT_TEMPLATE = '\n<OBJECTIVE>\n{mission_prompt}\n</OBJECTIVE>\n\n<OUTPUT_FORMAT>\nCRITICAL: The format instructions in this section are the ONLY valid way to structure your response. Your entire response MUST be a single JSON markdown code block. Any formatting guidelines within the <OBJECTIVE> section apply ONLY to the content inside the "RESPOND:" part of your final "action_input".\n\nREQUIRED: You have two ways to respond:\n\n1. **Call a tool** to gather information. For this, you MUST output a JSON blob with the tool\'s name and its input.\n *Valid tool names are: {tool_names}*\n ```json\n {{\n "action": "tool_name_to_use",\n "action_input": "the input for the tool, or an empty object {{}} if no input is needed"\n }}\n ```\n\n2. **Provide the Final Answer** once you have enough information. For this, you MUST output a JSON blob with the "Final Answer" action.\n The "action_input" for a "Final Answer" MUST be a string that begins with either "RESPOND: " for a message or "SILENT: " for no message. This prefix is a literal part of the output string and MUST NOT be omitted.\n - To send a message:\n ```json\n {{\n "action": "Final Answer",\n "action_input": "RESPOND: <your response message>"\n }}\n ```\n - To stay silent:\n ```json\n {{\n "action": "Final Answer",\n "action_input": "SILENT: <your reason for staying silent>"\n }}\n ```\n\n YOU MUST ALWAYS INCLUDE "RESPOND:" OR "SILENT:" IN YOUR FINAL ANSWER\'S "action_input". FAILURE TO DO SO WILL CAUSE AN ERROR.\n</OUTPUT_FORMAT>\n\n<EXECUTION_CONTEXT>\nThis is internal data for your reference.\n\n<TOOLS>\n{tools}\n</TOOLS>\n\n<WORKING_MEMORY>\nThis is your internal thought process and previous tool usage.\n{agent_scratchpad}\n</WORKING_MEMORY>\n</EXECUTION_CONTEXT>\n';
164
+ var SYSTEM_PROMPT_TEMPLATE = '\n<OBJECTIVE>\n{mission_prompt}\n</OBJECTIVE>\n\n<GLOBAL_WRAPPER_OUTPUT_FORMAT>\nCRITICAL: The format instructions in this section are the ONLY valid way to structure your response. Your entire response MUST be a single JSON markdown code block. Any formatting guidelines within the <OBJECTIVE> section apply ONLY to the content inside the "RESPOND:" part of your final "action_input".\n\nREQUIRED: You have two ways to respond:\n\n1. **Call a tool** to gather information. For this, you MUST output a JSON blob with the tool\'s name and its input.\n *Valid tool names are: {tool_names}*\n ```json\n {{\n "action": "tool_name_to_use",\n "action_input": "the input for the tool, or an empty object {{}} if no input is needed"\n }}\n ```\n\n2. **Provide the Final Answer** once you have enough information. For this, you MUST output a JSON blob with the "Final Answer" action.\n The "action_input" for a "Final Answer" MUST be a string that begins with either "RESPOND: " for a message or "SILENT: " for no message. This prefix is a literal part of the output string and MUST NOT be omitted.\n - To send a message:\n ```json\n {{\n "action": "Final Answer",\n "action_input": "RESPOND: <your response message>"\n }}\n ```\n - To stay silent:\n ```json\n {{\n "action": "Final Answer",\n "action_input": "SILENT: <your reason for staying silent>"\n }}\n ```\n\n YOU MUST ALWAYS INCLUDE "RESPOND:" OR "SILENT:" IN YOUR FINAL ANSWER\'S "action_input". FAILURE TO DO SO WILL CAUSE AN ERROR.\n\n{schema_format}\n</OUTPUT_FORMAT>\n\n<EXECUTION_CONTEXT>\nThis is internal data for your reference.\n\n<TOOLS>\n{tools}\n</TOOLS>\n\n<WORKING_MEMORY>\nThis is your internal thought process and previous tool usage.\n{agent_scratchpad}\n</WORKING_MEMORY>\n</EXECUTION_CONTEXT>\n';
164
165
  /**
165
- * An advanced agent that uses tools and a structured prompt to engage in conversational chat.
166
+ * An autonomous agent that uses tools and a structured prompt to accomplish tasks.
166
167
  * It can decide whether to respond or remain silent and supports schema-validated responses.
167
- */ export var ChatAgentAdapter = /*#__PURE__*/ function() {
168
+ * @template TOutput - The TypeScript type of the output
169
+ */ export var AutonomousAgentAdapter = /*#__PURE__*/ function() {
168
170
  "use strict";
169
- function ChatAgentAdapter(name, options) {
170
- _class_call_check(this, ChatAgentAdapter);
171
+ function AutonomousAgentAdapter(name, options) {
172
+ _class_call_check(this, AutonomousAgentAdapter);
171
173
  _define_property(this, "name", void 0);
172
174
  _define_property(this, "options", void 0);
173
175
  this.name = name;
174
176
  this.options = options;
175
177
  }
176
- _create_class(ChatAgentAdapter, [
178
+ _create_class(AutonomousAgentAdapter, [
177
179
  {
178
180
  key: "run",
179
- value: function run(userPrompt) {
181
+ value: function run(input) {
180
182
  return _async_to_generator(function() {
181
- var _this_options_logger, _this_options_logger1, executor, userInput, result, agentResponse, _this_options_logger2, _agentResponse_message, message, _this_options_logger3, _this_options_logger4, error, _this_options_logger5;
183
+ var _this_options_logger, _this_options_logger1, executor, userInput, result, agentResponse, _this_options_logger2, _agentResponse_message, message, _this_options_logger3, validatedResponse, _this_options_logger4, error, _this_options_logger5;
182
184
  return _ts_generator(this, function(_state) {
183
185
  switch(_state.label){
184
186
  case 0:
@@ -197,7 +199,7 @@ var SYSTEM_PROMPT_TEMPLATE = '\n<OBJECTIVE>\n{mission_prompt}\n</OBJECTIVE>\n\n<
197
199
  ];
198
200
  case 2:
199
201
  executor = _state.sent();
200
- userInput = this.resolveUserInput(userPrompt);
202
+ userInput = this.resolveUserInput(input);
201
203
  return [
202
204
  4,
203
205
  executor.invoke({
@@ -232,15 +234,24 @@ var SYSTEM_PROMPT_TEMPLATE = '\n<OBJECTIVE>\n{mission_prompt}\n</OBJECTIVE>\n\n<
232
234
  message = (_agentResponse_message = agentResponse.message) !== null && _agentResponse_message !== void 0 ? _agentResponse_message : '';
233
235
  if (this.options.schema) {
234
236
  ;
235
- this.validateResponseContent(message, this.options.schema);
237
+ validatedResponse = this.validateResponseContent(message, this.options.schema);
236
238
  (_this_options_logger3 = this.options.logger) === null || _this_options_logger3 === void 0 ? void 0 : _this_options_logger3.info("[".concat(this.name, "] Execution finished; response content validated."));
239
+ return [
240
+ 2,
241
+ validatedResponse
242
+ ];
237
243
  } else {
238
244
  ;
239
245
  (_this_options_logger4 = this.options.logger) === null || _this_options_logger4 === void 0 ? void 0 : _this_options_logger4.info("[".concat(this.name, "] Execution finished."));
246
+ // When no schema is provided, we assume TOutput is string (default), so message is the result
247
+ return [
248
+ 2,
249
+ message
250
+ ];
240
251
  }
241
252
  return [
242
- 2,
243
- message
253
+ 3,
254
+ 5
244
255
  ];
245
256
  case 4:
246
257
  error = _state.sent();
@@ -264,7 +275,7 @@ var SYSTEM_PROMPT_TEMPLATE = '\n<OBJECTIVE>\n{mission_prompt}\n</OBJECTIVE>\n\n<
264
275
  key: "createExecutor",
265
276
  value: function createExecutor() {
266
277
  return _async_to_generator(function() {
267
- var model, tools, prompt, agent;
278
+ var model, tools, schemaFormatInstructions, jsonSchema, isPrimitiveType, prompt, agent;
268
279
  return _ts_generator(this, function(_state) {
269
280
  switch(_state.label){
270
281
  case 0:
@@ -272,10 +283,27 @@ var SYSTEM_PROMPT_TEMPLATE = '\n<OBJECTIVE>\n{mission_prompt}\n</OBJECTIVE>\n\n<
272
283
  tools = this.options.tools.map(function(tool) {
273
284
  return tool.getDynamicTool();
274
285
  });
286
+ // Add schema format instructions if schema is provided
287
+ schemaFormatInstructions = '';
288
+ if (this.options.schema) {
289
+ jsonSchema = z.toJSONSchema(this.options.schema);
290
+ console.log(jsonSchema.type);
291
+ isPrimitiveType = [
292
+ 'boolean',
293
+ 'integer',
294
+ 'number',
295
+ 'string'
296
+ ].includes(jsonSchema.type);
297
+ if (isPrimitiveType) {
298
+ schemaFormatInstructions = '\n\nSCHEMA VALIDATION: When providing a "RESPOND:" answer, the content after "RESPOND: " must be a '.concat(jsonSchema.type, " value that matches this schema:\n\n```json\n").concat(JSON.stringify(jsonSchema, null, 2), '\n```\n\nExample format:\n```json\n{{\n "action": "Final Answer",\n "action_input": "RESPOND: your ').concat(jsonSchema.type, ' value here"\n}}\n```\n\nDo not wrap the ').concat(jsonSchema.type, ' value in JSON - just provide the raw value after "RESPOND: ".');
299
+ } else {
300
+ schemaFormatInstructions = '\n\nSCHEMA VALIDATION: When providing a "RESPOND:" answer, the content after "RESPOND: " must be valid JSON that matches this exact schema:\n\n```json\n'.concat(JSON.stringify(jsonSchema, null, 2).replace(/{/g, '{{').replace(/}/g, '}}'), '\n```\n\nExample format:\n```json\n{{\n "action": "Final Answer",\n "action_input": "RESPOND: {{\\"field1\\": \\"value1\\", \\"field2\\": \\"value2\\"}}"\n}}\n```\n');
301
+ }
302
+ }
275
303
  prompt = ChatPromptTemplate.fromMessages([
276
304
  [
277
305
  'system',
278
- SYSTEM_PROMPT_TEMPLATE.replace('{mission_prompt}', this.options.systemPrompt.generate())
306
+ SYSTEM_PROMPT_TEMPLATE.replace('{mission_prompt}', this.options.systemPrompt.generate()).replace('{schema_format}', schemaFormatInstructions)
279
307
  ],
280
308
  [
281
309
  'human',
@@ -332,9 +360,9 @@ var SYSTEM_PROMPT_TEMPLATE = '\n<OBJECTIVE>\n{mission_prompt}\n</OBJECTIVE>\n\n<
332
360
  },
333
361
  {
334
362
  key: "resolveUserInput",
335
- value: function resolveUserInput(userPrompt) {
336
- if (userPrompt) {
337
- return userPrompt.generate();
363
+ value: function resolveUserInput(input) {
364
+ if (input) {
365
+ return input.generate();
338
366
  }
339
367
  return 'Proceed with your instructions.';
340
368
  }
@@ -343,7 +371,7 @@ var SYSTEM_PROMPT_TEMPLATE = '\n<OBJECTIVE>\n{mission_prompt}\n</OBJECTIVE>\n\n<
343
371
  key: "validateResponseContent",
344
372
  value: function validateResponseContent(content, schema) {
345
373
  try {
346
- new AIResponseParser(schema).parse(content);
374
+ return new AIResponseParser(schema).parse(content);
347
375
  } catch (error) {
348
376
  var _this_options_logger;
349
377
  (_this_options_logger = this.options.logger) === null || _this_options_logger === void 0 ? void 0 : _this_options_logger.error("[".concat(this.name, "] Failed to validate response content against schema."), {
@@ -355,7 +383,7 @@ var SYSTEM_PROMPT_TEMPLATE = '\n<OBJECTIVE>\n{mission_prompt}\n</OBJECTIVE>\n\n<
355
383
  }
356
384
  }
357
385
  ]);
358
- return ChatAgentAdapter;
386
+ return AutonomousAgentAdapter;
359
387
  }();
360
388
 
361
- //# sourceMappingURL=chat-agent.adapter.js.map
389
+ //# sourceMappingURL=autonomous-agent.adapter.js.map