@jterrazz/intelligence 1.1.1 → 1.3.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 +65 -60
- package/dist/adapters/agents/{chat-agent.adapter.d.ts → autonomous-agent.adapter.d.ts} +4 -4
- package/dist/adapters/agents/{chat-agent.adapter.js → autonomous-agent.adapter.js} +16 -13
- package/dist/adapters/agents/autonomous-agent.adapter.js.map +1 -0
- package/dist/adapters/agents/basic-agent.adapter.d.ts +26 -0
- package/dist/adapters/agents/basic-agent.adapter.js +303 -0
- package/dist/adapters/agents/basic-agent.adapter.js.map +1 -0
- package/dist/adapters/agents/query-agent.adapter.d.ts +4 -4
- package/dist/adapters/agents/query-agent.adapter.js +6 -6
- package/dist/adapters/agents/query-agent.adapter.js.map +1 -1
- package/dist/adapters/models/openrouter-model.adapter.js +6 -0
- package/dist/adapters/models/openrouter-model.adapter.js.map +1 -1
- package/dist/adapters/prompts/__tests__/presets.test.js +4 -4
- package/dist/adapters/prompts/__tests__/presets.test.js.map +1 -1
- package/dist/adapters/prompts/library/categories/response.d.ts +1 -1
- package/dist/adapters/prompts/library/categories/response.js +1 -1
- package/dist/adapters/prompts/library/categories/response.js.map +1 -1
- package/dist/adapters/prompts/library/index.d.ts +3 -3
- package/dist/adapters/prompts/library/index.js +4 -4
- package/dist/adapters/prompts/library/index.js.map +1 -1
- package/dist/adapters/prompts/library/presets.js +4 -4
- package/dist/adapters/prompts/library/presets.js.map +1 -1
- package/dist/index.cjs +37 -28
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/adapters/agents/chat-agent.adapter.js.map +0 -1
package/README.md
CHANGED
|
@@ -30,22 +30,22 @@ Get your first agent running in under a minute. This example uses a preset to cr
|
|
|
30
30
|
|
|
31
31
|
```typescript
|
|
32
32
|
import {
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
AutonomousAgentAdapter,
|
|
34
|
+
OpenRouterAdapter,
|
|
35
35
|
SystemPromptAdapter,
|
|
36
|
-
|
|
36
|
+
PROMPT_LIBRARY,
|
|
37
37
|
} from '@jterrazz/intelligence';
|
|
38
38
|
|
|
39
39
|
// 1. Set up the model provider
|
|
40
|
-
const model = new
|
|
40
|
+
const model = new OpenRouterAdapter({
|
|
41
41
|
apiKey: process.env.OPENROUTER_API_KEY!, // Make sure to set this environment variable
|
|
42
42
|
modelName: 'anthropic/claude-3.5-sonnet',
|
|
43
43
|
});
|
|
44
44
|
|
|
45
45
|
// 2. Create an agent using a preset prompt
|
|
46
|
-
const agent = new
|
|
46
|
+
const agent = new AutonomousAgentAdapter('discord-bot', {
|
|
47
47
|
model,
|
|
48
|
-
systemPrompt: new SystemPromptAdapter(
|
|
48
|
+
systemPrompt: new SystemPromptAdapter(PROMPT_LIBRARY.PRESETS.COMMUNITY_ANIMATOR),
|
|
49
49
|
});
|
|
50
50
|
|
|
51
51
|
// 3. Run the agent
|
|
@@ -63,10 +63,14 @@ console.log(response);
|
|
|
63
63
|
|
|
64
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
65
|
|
|
66
|
-
- **`
|
|
67
|
-
- **`
|
|
68
|
-
- **`
|
|
69
|
-
- **`
|
|
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`).
|
|
70
74
|
|
|
71
75
|
This approach makes agent behavior more predictable and easier to modify.
|
|
72
76
|
|
|
@@ -100,7 +104,7 @@ The adapter handles errors gracefully and integrates seamlessly with the agent,
|
|
|
100
104
|
The library is built on a hexagonal architecture.
|
|
101
105
|
|
|
102
106
|
- **Ports (`/ports`)**: Define the contracts (interfaces) for core components like `Agent`, `Model`, and `Tool`.
|
|
103
|
-
- **Adapters (`/adapters`)**: Provide concrete implementations. For example, `
|
|
107
|
+
- **Adapters (`/adapters`)**: Provide concrete implementations. For example, `AutonomousAgentAdapter` is an adapter that uses LangChain, and `OpenRouterAdapter` is an adapter for the OpenRouter API.
|
|
104
108
|
|
|
105
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.
|
|
106
110
|
|
|
@@ -120,26 +124,26 @@ This recipe creates an agent that acts as an expert software engineer, providing
|
|
|
120
124
|
|
|
121
125
|
```typescript
|
|
122
126
|
import {
|
|
123
|
-
|
|
124
|
-
|
|
127
|
+
AutonomousAgentAdapter,
|
|
128
|
+
OpenRouterAdapter,
|
|
125
129
|
SystemPromptAdapter,
|
|
126
130
|
UserPromptAdapter,
|
|
127
|
-
|
|
131
|
+
PROMPT_LIBRARY,
|
|
128
132
|
} from '@jterrazz/intelligence';
|
|
129
133
|
|
|
130
|
-
const model = new
|
|
134
|
+
const model = new OpenRouterAdapter({
|
|
131
135
|
apiKey: process.env.OPENROUTER_API_KEY!,
|
|
132
136
|
modelName: 'anthropic/claude-3.5-sonnet',
|
|
133
137
|
});
|
|
134
138
|
|
|
135
139
|
// 1. Compose the system prompt from multiple parts (using rest arguments)
|
|
136
140
|
const systemPrompt = new SystemPromptAdapter(
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
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,
|
|
143
147
|
);
|
|
144
148
|
|
|
145
149
|
// 2. Create the user request (using a single array)
|
|
@@ -149,7 +153,7 @@ const userPrompt = new UserPromptAdapter([
|
|
|
149
153
|
]);
|
|
150
154
|
|
|
151
155
|
// 3. Configure and run the agent
|
|
152
|
-
const agent = new
|
|
156
|
+
const agent = new AutonomousAgentAdapter('code-reviewer', {
|
|
153
157
|
model,
|
|
154
158
|
systemPrompt,
|
|
155
159
|
});
|
|
@@ -159,34 +163,34 @@ const response = await agent.run(userPrompt);
|
|
|
159
163
|
console.log(response);
|
|
160
164
|
```
|
|
161
165
|
|
|
162
|
-
### Recipe: Simple Text Processor (
|
|
166
|
+
### Recipe: Simple Text Processor (BasicAgent)
|
|
163
167
|
|
|
164
|
-
This example shows how to use the simpler `
|
|
168
|
+
This example shows how to use the simpler `BasicAgentAdapter` for one-shot responses without tools.
|
|
165
169
|
|
|
166
170
|
```typescript
|
|
167
171
|
import {
|
|
168
|
-
|
|
169
|
-
|
|
172
|
+
BasicAgentAdapter,
|
|
173
|
+
OpenRouterAdapter,
|
|
170
174
|
SystemPromptAdapter,
|
|
171
175
|
UserPromptAdapter,
|
|
172
|
-
|
|
176
|
+
PROMPT_LIBRARY,
|
|
173
177
|
} from '@jterrazz/intelligence';
|
|
174
178
|
|
|
175
|
-
const model = new
|
|
179
|
+
const model = new OpenRouterAdapter({
|
|
176
180
|
apiKey: process.env.OPENROUTER_API_KEY!,
|
|
177
181
|
modelName: 'anthropic/claude-3.5-sonnet',
|
|
178
182
|
});
|
|
179
183
|
|
|
180
184
|
// 1. Create a simple system prompt for text processing
|
|
181
185
|
const systemPrompt = new SystemPromptAdapter(
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
186
|
+
PROMPT_LIBRARY.PERSONAS.EXPERT_ADVISOR,
|
|
187
|
+
PROMPT_LIBRARY.TONES.PROFESSIONAL,
|
|
188
|
+
PROMPT_LIBRARY.FORMATS.MARKDOWN,
|
|
185
189
|
'You are a helpful assistant that improves text clarity and grammar.',
|
|
186
190
|
);
|
|
187
191
|
|
|
188
|
-
// 2. Create a
|
|
189
|
-
const agent = new
|
|
192
|
+
// 2. Create a basic agent (no tools needed)
|
|
193
|
+
const agent = new BasicAgentAdapter('text-processor', {
|
|
190
194
|
model,
|
|
191
195
|
systemPrompt,
|
|
192
196
|
});
|
|
@@ -201,21 +205,21 @@ console.log(response);
|
|
|
201
205
|
// Expected output: A grammatically corrected and improved version of the text
|
|
202
206
|
```
|
|
203
207
|
|
|
204
|
-
### Recipe: Structured Data Extraction (
|
|
208
|
+
### Recipe: Structured Data Extraction (BasicAgent with Schema)
|
|
205
209
|
|
|
206
|
-
This example shows how to use `
|
|
210
|
+
This example shows how to use `BasicAgentAdapter` with schema parsing for structured responses.
|
|
207
211
|
|
|
208
212
|
```typescript
|
|
209
213
|
import {
|
|
210
|
-
|
|
211
|
-
|
|
214
|
+
BasicAgentAdapter,
|
|
215
|
+
OpenRouterAdapter,
|
|
212
216
|
SystemPromptAdapter,
|
|
213
217
|
UserPromptAdapter,
|
|
214
|
-
|
|
218
|
+
PROMPT_LIBRARY,
|
|
215
219
|
} from '@jterrazz/intelligence';
|
|
216
220
|
import { z } from 'zod/v4';
|
|
217
221
|
|
|
218
|
-
const model = new
|
|
222
|
+
const model = new OpenRouterAdapter({
|
|
219
223
|
apiKey: process.env.OPENROUTER_API_KEY!,
|
|
220
224
|
modelName: 'anthropic/claude-3.5-sonnet',
|
|
221
225
|
});
|
|
@@ -230,14 +234,14 @@ const extractionSchema = z.object({
|
|
|
230
234
|
|
|
231
235
|
// 2. Create a system prompt for data extraction
|
|
232
236
|
const systemPrompt = new SystemPromptAdapter(
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
237
|
+
PROMPT_LIBRARY.PERSONAS.EXPERT_ADVISOR,
|
|
238
|
+
PROMPT_LIBRARY.TONES.PROFESSIONAL,
|
|
239
|
+
PROMPT_LIBRARY.FORMATS.JSON,
|
|
236
240
|
'You extract contact information from text and return it as JSON.',
|
|
237
241
|
);
|
|
238
242
|
|
|
239
|
-
// 3. Create a
|
|
240
|
-
const agent = new
|
|
243
|
+
// 3. Create a basic agent with schema parsing
|
|
244
|
+
const agent = new BasicAgentAdapter('contact-extractor', {
|
|
241
245
|
model,
|
|
242
246
|
schema: extractionSchema,
|
|
243
247
|
systemPrompt,
|
|
@@ -262,11 +266,12 @@ This example shows how to give an agent a tool and have it respond to a user que
|
|
|
262
266
|
|
|
263
267
|
```typescript
|
|
264
268
|
import {
|
|
265
|
-
|
|
266
|
-
|
|
269
|
+
AutonomousAgentAdapter,
|
|
270
|
+
OpenRouterAdapter,
|
|
267
271
|
SafeToolAdapter,
|
|
268
272
|
SystemPromptAdapter,
|
|
269
|
-
|
|
273
|
+
UserPromptAdapter,
|
|
274
|
+
PROMPT_LIBRARY,
|
|
270
275
|
} from '@jterrazz/intelligence';
|
|
271
276
|
import { z } from 'zod/v4';
|
|
272
277
|
|
|
@@ -286,14 +291,14 @@ const weatherTool = new SafeToolAdapter(
|
|
|
286
291
|
);
|
|
287
292
|
|
|
288
293
|
// 2. Create an agent that knows how to use tools
|
|
289
|
-
const agent = new
|
|
294
|
+
const agent = new AutonomousAgentAdapter('weather-bot', {
|
|
290
295
|
model,
|
|
291
|
-
systemPrompt: new SystemPromptAdapter(
|
|
296
|
+
systemPrompt: new SystemPromptAdapter(PROMPT_LIBRARY.PRESETS.EMPATHETIC_SUPPORT_AGENT), // A good general-purpose preset
|
|
292
297
|
tools: [weatherTool], // Pass the tool instance directly
|
|
293
298
|
});
|
|
294
299
|
|
|
295
300
|
// 3. Run the agent with a user query that requires the tool
|
|
296
|
-
const response = await agent.run(
|
|
301
|
+
const response = await agent.run(new UserPromptAdapter("What's the weather like in Boston?"));
|
|
297
302
|
|
|
298
303
|
console.log(response);
|
|
299
304
|
// Expected output: "The weather in Boston is 75°F and sunny."
|
|
@@ -305,16 +310,16 @@ console.log(response);
|
|
|
305
310
|
|
|
306
311
|
### Core Components
|
|
307
312
|
|
|
308
|
-
| Class | Description
|
|
309
|
-
| ------------------------ |
|
|
310
|
-
| `
|
|
311
|
-
| `
|
|
312
|
-
| `OpenRouterModelAdapter` | An adapter for connecting to any model on the OpenRouter platform.
|
|
313
|
-
| `SafeToolAdapter` | A type-safe wrapper for creating tools with validation and error handling.
|
|
314
|
-
| `SystemPromptAdapter` | A simple adapter to generate a system prompt string from a prompt array.
|
|
315
|
-
| `UserPromptAdapter` | A simple adapter to generate a user prompt string from a prompt array.
|
|
316
|
-
| `AIResponseParser` | A utility to parse a model's string output into a typed object using Zod.
|
|
317
|
-
| `
|
|
313
|
+
| Class | Description |
|
|
314
|
+
| ------------------------ | ------------------------------------------------------------------------------- |
|
|
315
|
+
| `AutonomousAgentAdapter` | The main agent implementation. Runs prompts and coordinates tools autonomously. |
|
|
316
|
+
| `BasicAgentAdapter` | A basic 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. |
|
|
318
323
|
|
|
319
324
|
## Contributing
|
|
320
325
|
|
|
@@ -5,7 +5,7 @@ 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
|
|
8
|
+
export interface AutonomousAgentOptions<T = unknown> {
|
|
9
9
|
logger?: LoggerPort;
|
|
10
10
|
model: ModelPort;
|
|
11
11
|
schema?: z.ZodSchema<T>;
|
|
@@ -14,13 +14,13 @@ export interface ChatAgentOptions<T = unknown> {
|
|
|
14
14
|
verbose?: boolean;
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
|
-
* An
|
|
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
19
|
*/
|
|
20
|
-
export declare class
|
|
20
|
+
export declare class AutonomousAgentAdapter<T = unknown> implements AgentPort {
|
|
21
21
|
readonly name: string;
|
|
22
22
|
private readonly options;
|
|
23
|
-
constructor(name: string, options:
|
|
23
|
+
constructor(name: string, options: AutonomousAgentOptions<T>);
|
|
24
24
|
run(userPrompt?: PromptPort): Promise<null | string>;
|
|
25
25
|
private createExecutor;
|
|
26
26
|
private parseAgentOutput;
|
|
@@ -160,20 +160,20 @@ function _ts_generator(thisArg, body) {
|
|
|
160
160
|
import { ChatPromptTemplate } from '@langchain/core/prompts';
|
|
161
161
|
import { AgentExecutor, createStructuredChatAgent } from 'langchain/agents';
|
|
162
162
|
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. Any formatting guidelines within the <OBJECTIVE> section
|
|
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
164
|
/**
|
|
165
|
-
* An
|
|
165
|
+
* An autonomous agent that uses tools and a structured prompt to accomplish tasks.
|
|
166
166
|
* It can decide whether to respond or remain silent and supports schema-validated responses.
|
|
167
|
-
*/ export var
|
|
167
|
+
*/ export var AutonomousAgentAdapter = /*#__PURE__*/ function() {
|
|
168
168
|
"use strict";
|
|
169
|
-
function
|
|
170
|
-
_class_call_check(this,
|
|
169
|
+
function AutonomousAgentAdapter(name, options) {
|
|
170
|
+
_class_call_check(this, AutonomousAgentAdapter);
|
|
171
171
|
_define_property(this, "name", void 0);
|
|
172
172
|
_define_property(this, "options", void 0);
|
|
173
173
|
this.name = name;
|
|
174
174
|
this.options = options;
|
|
175
175
|
}
|
|
176
|
-
_create_class(
|
|
176
|
+
_create_class(AutonomousAgentAdapter, [
|
|
177
177
|
{
|
|
178
178
|
key: "run",
|
|
179
179
|
value: function run(userPrompt) {
|
|
@@ -213,6 +213,12 @@ var SYSTEM_PROMPT_TEMPLATE = '\n<OBJECTIVE>\n{mission_prompt}\n</OBJECTIVE>\n\n<
|
|
|
213
213
|
throw new Error('Agent returned an invalid result structure.');
|
|
214
214
|
}
|
|
215
215
|
agentResponse = this.parseAgentOutput(result.output);
|
|
216
|
+
if (!agentResponse) {
|
|
217
|
+
return [
|
|
218
|
+
2,
|
|
219
|
+
null
|
|
220
|
+
];
|
|
221
|
+
}
|
|
216
222
|
if (!agentResponse.shouldRespond) {
|
|
217
223
|
;
|
|
218
224
|
(_this_options_logger2 = this.options.logger) === null || _this_options_logger2 === void 0 ? void 0 : _this_options_logger2.info("[".concat(this.name, "] Agent chose to remain silent."), {
|
|
@@ -318,13 +324,10 @@ var SYSTEM_PROMPT_TEMPLATE = '\n<OBJECTIVE>\n{mission_prompt}\n</OBJECTIVE>\n\n<
|
|
|
318
324
|
shouldRespond: false
|
|
319
325
|
};
|
|
320
326
|
}
|
|
321
|
-
(_this_options_logger = this.options.logger) === null || _this_options_logger === void 0 ? void 0 : _this_options_logger.
|
|
327
|
+
(_this_options_logger = this.options.logger) === null || _this_options_logger === void 0 ? void 0 : _this_options_logger.error("[".concat(this.name, "] Agent output was missing 'RESPOND:' or 'SILENT:' prefix."), {
|
|
322
328
|
rawOutput: output
|
|
323
329
|
});
|
|
324
|
-
return
|
|
325
|
-
message: text,
|
|
326
|
-
shouldRespond: true
|
|
327
|
-
};
|
|
330
|
+
return null;
|
|
328
331
|
}
|
|
329
332
|
},
|
|
330
333
|
{
|
|
@@ -352,7 +355,7 @@ var SYSTEM_PROMPT_TEMPLATE = '\n<OBJECTIVE>\n{mission_prompt}\n</OBJECTIVE>\n\n<
|
|
|
352
355
|
}
|
|
353
356
|
}
|
|
354
357
|
]);
|
|
355
|
-
return
|
|
358
|
+
return AutonomousAgentAdapter;
|
|
356
359
|
}();
|
|
357
360
|
|
|
358
|
-
//# sourceMappingURL=
|
|
361
|
+
//# sourceMappingURL=autonomous-agent.adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/adapters/agents/autonomous-agent.adapter.ts"],"sourcesContent":["import { type LoggerPort } from '@jterrazz/logger';\nimport { ChatPromptTemplate } from '@langchain/core/prompts';\nimport { AgentExecutor, createStructuredChatAgent } from 'langchain/agents';\nimport { type 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';\nimport type { ToolPort } from '../../ports/tool.port.js';\n\nimport { AIResponseParser } from '../utils/ai-response-parser.js';\n\nimport type { SystemPromptAdapter } from '../prompts/system-prompt.adapter.js';\n\nexport interface AutonomousAgentOptions<T = unknown> {\n logger?: LoggerPort;\n model: ModelPort;\n schema?: z.ZodSchema<T>;\n systemPrompt: SystemPromptAdapter;\n tools: ToolPort[];\n verbose?: boolean;\n}\n\nconst 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`;\n\n/**\n * An autonomous agent that uses tools and a structured prompt to accomplish tasks.\n * It can decide whether to respond or remain silent and supports schema-validated responses.\n */\nexport class AutonomousAgentAdapter<T = unknown> implements AgentPort {\n constructor(\n public readonly name: string,\n private readonly options: AutonomousAgentOptions<T>,\n ) {}\n\n async run(userPrompt?: PromptPort): Promise<null | string> {\n this.options.logger?.debug(`[${this.name}] Starting chat execution.`);\n\n try {\n const executor = await this.createExecutor();\n const userInput = this.resolveUserInput(userPrompt);\n\n const result = await executor.invoke({ input: userInput });\n\n this.options.logger?.debug(`[${this.name}] Agent execution completed.`, {\n hasOutput: 'output' in result,\n });\n\n if (!result || typeof result.output !== 'string') {\n throw new Error('Agent returned an invalid result structure.');\n }\n\n const agentResponse = this.parseAgentOutput(result.output);\n\n if (!agentResponse) {\n return null;\n }\n\n if (!agentResponse.shouldRespond) {\n this.options.logger?.info(`[${this.name}] Agent chose to remain silent.`, {\n reason: agentResponse.reason,\n });\n return null;\n }\n\n const message = agentResponse.message ?? '';\n\n if (this.options.schema) {\n this.validateResponseContent(message, this.options.schema);\n this.options.logger?.info(\n `[${this.name}] Execution finished; response content validated.`,\n );\n } else {\n this.options.logger?.info(`[${this.name}] Execution finished.`);\n }\n\n return message;\n } catch (error) {\n this.options.logger?.error(`[${this.name}] Chat execution failed.`, {\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n return null;\n }\n }\n\n private async createExecutor(): Promise<AgentExecutor> {\n const model = this.options.model.getModel();\n const tools = this.options.tools.map((tool) => tool.getDynamicTool());\n\n const prompt = ChatPromptTemplate.fromMessages([\n [\n 'system',\n SYSTEM_PROMPT_TEMPLATE.replace(\n '{mission_prompt}',\n this.options.systemPrompt.generate(),\n ),\n ],\n ['human', '{input}'],\n ]);\n\n const agent = await createStructuredChatAgent({\n llm: model,\n prompt,\n tools,\n });\n\n return AgentExecutor.fromAgentAndTools({\n agent,\n tools,\n verbose: this.options.verbose,\n });\n }\n\n private parseAgentOutput(output: string): null | {\n message?: string;\n reason?: string;\n shouldRespond: boolean;\n } {\n const text = output.trim();\n\n const respondMatch = text.match(/^RESPOND:\\s*([\\s\\S]+)$/i);\n if (respondMatch) {\n return { message: respondMatch[1].trim(), shouldRespond: true };\n }\n\n const silentMatch = text.match(/^SILENT:\\s*([\\s\\S]+)$/i);\n if (silentMatch) {\n return { reason: silentMatch[1].trim(), shouldRespond: false };\n }\n\n this.options.logger?.error(\n `[${this.name}] Agent output was missing 'RESPOND:' or 'SILENT:' prefix.`,\n { rawOutput: output },\n );\n\n return null;\n }\n\n private resolveUserInput(userPrompt?: PromptPort): string {\n if (userPrompt) {\n return userPrompt.generate();\n }\n return 'Proceed with your instructions.';\n }\n\n private validateResponseContent<TResponse>(\n content: string,\n schema: z.ZodSchema<TResponse>,\n ): void {\n try {\n new AIResponseParser(schema).parse(content);\n } catch (error) {\n this.options.logger?.error(\n `[${this.name}] Failed to validate response content against schema.`,\n {\n error: error instanceof Error ? error.message : 'Unknown error',\n rawContent: content,\n },\n );\n throw new Error('Invalid response content from model.');\n }\n }\n}\n"],"names":["ChatPromptTemplate","AgentExecutor","createStructuredChatAgent","AIResponseParser","SYSTEM_PROMPT_TEMPLATE","AutonomousAgentAdapter","name","options","run","userPrompt","executor","userInput","result","agentResponse","message","error","logger","debug","createExecutor","resolveUserInput","invoke","input","hasOutput","output","Error","parseAgentOutput","shouldRespond","info","reason","schema","validateResponseContent","model","tools","prompt","agent","getModel","map","tool","getDynamicTool","fromMessages","replace","systemPrompt","generate","llm","fromAgentAndTools","verbose","text","trim","respondMatch","match","silentMatch","rawOutput","content","parse","rawContent"],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type LoggerPort } from '@jterrazz/logger';
|
|
2
|
+
import { type z } from 'zod/v4';
|
|
3
|
+
import { type AgentPort } from '../../ports/agent.port.js';
|
|
4
|
+
import type { ModelPort } from '../../ports/model.port.js';
|
|
5
|
+
import type { PromptPort } from '../../ports/prompt.port.js';
|
|
6
|
+
import type { SystemPromptAdapter } from '../prompts/system-prompt.adapter.js';
|
|
7
|
+
export interface BasicAgentOptions<T = string> {
|
|
8
|
+
logger?: LoggerPort;
|
|
9
|
+
model: ModelPort;
|
|
10
|
+
schema?: z.ZodSchema<T>;
|
|
11
|
+
systemPrompt: SystemPromptAdapter;
|
|
12
|
+
verbose?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* A basic agent for direct, one-shot interactions with a model.
|
|
16
|
+
* It supports optional response parsing against a Zod schema but does not use tools.
|
|
17
|
+
*/
|
|
18
|
+
export declare class BasicAgentAdapter<T = string> implements AgentPort {
|
|
19
|
+
readonly name: string;
|
|
20
|
+
private readonly options;
|
|
21
|
+
constructor(name: string, options: BasicAgentOptions<T>);
|
|
22
|
+
run(userPrompt?: PromptPort): Promise<null | string>;
|
|
23
|
+
private invokeModel;
|
|
24
|
+
private parseResponse;
|
|
25
|
+
private resolveUserInput;
|
|
26
|
+
}
|