@jterrazz/intelligence 1.0.0 → 1.1.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 +111 -14
- package/dist/adapters/agents/chat-agent.adapter.d.ts +20 -26
- package/dist/adapters/agents/chat-agent.adapter.js +99 -129
- package/dist/adapters/agents/chat-agent.adapter.js.map +1 -1
- package/dist/adapters/agents/query-agent.adapter.d.ts +26 -0
- package/dist/adapters/agents/query-agent.adapter.js +303 -0
- package/dist/adapters/agents/query-agent.adapter.js.map +1 -0
- package/dist/adapters/models/openrouter-model.adapter.d.ts +16 -6
- package/dist/adapters/models/openrouter-model.adapter.js +7 -4
- package/dist/adapters/models/openrouter-model.adapter.js.map +1 -1
- package/dist/adapters/prompts/__tests__/__snapshots__/presets.test.ts.snap +73 -103
- package/dist/adapters/prompts/__tests__/presets.test.js +1 -1
- package/dist/adapters/prompts/__tests__/presets.test.js.map +1 -1
- package/dist/adapters/prompts/library/categories/domain.d.ts +8 -8
- package/dist/adapters/prompts/library/categories/domain.js +8 -8
- package/dist/adapters/prompts/library/categories/domain.js.map +1 -1
- package/dist/adapters/prompts/library/categories/format.d.ts +7 -6
- package/dist/adapters/prompts/library/categories/format.js +7 -6
- package/dist/adapters/prompts/library/categories/format.js.map +1 -1
- package/dist/adapters/prompts/library/categories/foundations.d.ts +9 -0
- package/dist/adapters/prompts/library/categories/foundations.js +10 -0
- package/dist/adapters/prompts/library/categories/foundations.js.map +1 -0
- package/dist/adapters/prompts/library/categories/language.d.ts +8 -8
- package/dist/adapters/prompts/library/categories/language.js +8 -8
- package/dist/adapters/prompts/library/categories/language.js.map +1 -1
- package/dist/adapters/prompts/library/categories/persona.d.ts +8 -8
- package/dist/adapters/prompts/library/categories/persona.js +8 -8
- package/dist/adapters/prompts/library/categories/persona.js.map +1 -1
- package/dist/adapters/prompts/library/categories/response.d.ts +9 -0
- package/dist/adapters/prompts/library/categories/response.js +10 -0
- package/dist/adapters/prompts/library/categories/response.js.map +1 -0
- package/dist/adapters/prompts/library/categories/tone.d.ts +5 -5
- package/dist/adapters/prompts/library/categories/tone.js +5 -5
- package/dist/adapters/prompts/library/categories/tone.js.map +1 -1
- package/dist/adapters/prompts/library/categories/verbosity.d.ts +3 -3
- package/dist/adapters/prompts/library/categories/verbosity.js +3 -3
- package/dist/adapters/prompts/library/categories/verbosity.js.map +1 -1
- package/dist/adapters/prompts/library/index.d.ts +53 -56
- package/dist/adapters/prompts/library/index.js +15 -17
- package/dist/adapters/prompts/library/index.js.map +1 -1
- package/dist/adapters/prompts/library/presets.d.ts +5 -5
- package/dist/adapters/prompts/library/presets.js +27 -33
- package/dist/adapters/prompts/library/presets.js.map +1 -1
- package/dist/adapters/prompts/system-prompt.adapter.d.ts +2 -2
- package/dist/adapters/prompts/system-prompt.adapter.js.map +1 -1
- package/dist/adapters/prompts/user-prompt.adapter.d.ts +2 -2
- package/dist/adapters/prompts/user-prompt.adapter.js.map +1 -1
- package/dist/adapters/tools/safe-tool.adapter.d.ts +2 -2
- package/dist/adapters/tools/safe-tool.adapter.js.map +1 -1
- package/dist/index.cjs +514 -258
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/ports/agent.port.d.ts +3 -3
- package/dist/ports/agent.port.js.map +1 -1
- package/dist/ports/model.port.d.ts +1 -1
- package/dist/ports/model.port.js.map +1 -1
- package/dist/ports/prompt.port.d.ts +1 -1
- package/dist/ports/prompt.port.js.map +1 -1
- package/dist/ports/tool.port.d.ts +1 -1
- package/dist/ports/tool.port.js.map +1 -1
- package/package.json +1 -1
- package/dist/adapters/prompts/library/categories/agent-logic.d.ts +0 -8
- package/dist/adapters/prompts/library/categories/agent-logic.js +0 -9
- package/dist/adapters/prompts/library/categories/agent-logic.js.map +0 -1
- package/dist/adapters/prompts/library/categories/agent-skills.d.ts +0 -8
- package/dist/adapters/prompts/library/categories/agent-skills.js +0 -9
- package/dist/adapters/prompts/library/categories/agent-skills.js.map +0 -1
- package/dist/adapters/prompts/library/categories/directives.d.ts +0 -9
- package/dist/adapters/prompts/library/categories/directives.js +0 -10
- package/dist/adapters/prompts/library/categories/directives.js.map +0 -1
package/README.md
CHANGED
|
@@ -43,11 +43,10 @@ const model = new OpenRouterModelAdapter({
|
|
|
43
43
|
});
|
|
44
44
|
|
|
45
45
|
// 2. Create an agent using a preset prompt
|
|
46
|
-
const agent = new ChatAgentAdapter(
|
|
47
|
-
|
|
48
|
-
new SystemPromptAdapter(PROMPTS.PRESETS.DISCORD_COMMUNITY_ANIMATOR),
|
|
49
|
-
|
|
50
|
-
);
|
|
46
|
+
const agent = new ChatAgentAdapter('discord-bot', {
|
|
47
|
+
model,
|
|
48
|
+
systemPrompt: new SystemPromptAdapter(PROMPTS.PRESETS.DISCORD_COMMUNITY_ANIMATOR),
|
|
49
|
+
});
|
|
51
50
|
|
|
52
51
|
// 3. Run the agent
|
|
53
52
|
const response = await agent.run();
|
|
@@ -150,13 +149,113 @@ const userPrompt = new UserPromptAdapter([
|
|
|
150
149
|
]);
|
|
151
150
|
|
|
152
151
|
// 3. Configure and run the agent
|
|
153
|
-
const agent = new ChatAgentAdapter('code-reviewer',
|
|
152
|
+
const agent = new ChatAgentAdapter('code-reviewer', {
|
|
153
|
+
model,
|
|
154
|
+
systemPrompt,
|
|
155
|
+
});
|
|
154
156
|
|
|
155
157
|
const response = await agent.run(userPrompt);
|
|
156
158
|
|
|
157
159
|
console.log(response);
|
|
158
160
|
```
|
|
159
161
|
|
|
162
|
+
### Recipe: Simple Text Processor (QueryAgent)
|
|
163
|
+
|
|
164
|
+
This example shows how to use the simpler `QueryAgentAdapter` for one-shot responses without tools.
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
import {
|
|
168
|
+
QueryAgentAdapter,
|
|
169
|
+
OpenRouterModelAdapter,
|
|
170
|
+
SystemPromptAdapter,
|
|
171
|
+
UserPromptAdapter,
|
|
172
|
+
PROMPTS,
|
|
173
|
+
} from '@jterrazz/intelligence';
|
|
174
|
+
|
|
175
|
+
const model = new OpenRouterModelAdapter({
|
|
176
|
+
apiKey: process.env.OPENROUTER_API_KEY!,
|
|
177
|
+
modelName: 'anthropic/claude-3.5-sonnet',
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
// 1. Create a simple system prompt for text processing
|
|
181
|
+
const systemPrompt = new SystemPromptAdapter(
|
|
182
|
+
PROMPTS.PERSONA.EXPERT_ADVISOR,
|
|
183
|
+
PROMPTS.TONE.PROFESSIONAL,
|
|
184
|
+
PROMPTS.FORMAT.MARKDOWN,
|
|
185
|
+
'You are a helpful assistant that improves text clarity and grammar.',
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
// 2. Create a query agent (no tools needed)
|
|
189
|
+
const agent = new QueryAgentAdapter('text-processor', {
|
|
190
|
+
model,
|
|
191
|
+
systemPrompt,
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
// 3. Run a simple query
|
|
195
|
+
const userPrompt = new UserPromptAdapter(
|
|
196
|
+
'Please improve this text: "Me and john was going to store yesterday"',
|
|
197
|
+
);
|
|
198
|
+
const response = await agent.run(userPrompt);
|
|
199
|
+
|
|
200
|
+
console.log(response);
|
|
201
|
+
// Expected output: A grammatically corrected and improved version of the text
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Recipe: Structured Data Extraction (QueryAgent with Schema)
|
|
205
|
+
|
|
206
|
+
This example shows how to use `QueryAgentAdapter` with schema parsing for structured responses.
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
import {
|
|
210
|
+
QueryAgentAdapter,
|
|
211
|
+
OpenRouterModelAdapter,
|
|
212
|
+
SystemPromptAdapter,
|
|
213
|
+
UserPromptAdapter,
|
|
214
|
+
PROMPTS,
|
|
215
|
+
} from '@jterrazz/intelligence';
|
|
216
|
+
import { z } from 'zod/v4';
|
|
217
|
+
|
|
218
|
+
const model = new OpenRouterModelAdapter({
|
|
219
|
+
apiKey: process.env.OPENROUTER_API_KEY!,
|
|
220
|
+
modelName: 'anthropic/claude-3.5-sonnet',
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
// 1. Define the response schema
|
|
224
|
+
const extractionSchema = z.object({
|
|
225
|
+
name: z.string(),
|
|
226
|
+
email: z.string().email(),
|
|
227
|
+
phone: z.string().optional(),
|
|
228
|
+
company: z.string().optional(),
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
// 2. Create a system prompt for data extraction
|
|
232
|
+
const systemPrompt = new SystemPromptAdapter(
|
|
233
|
+
PROMPTS.PERSONA.EXPERT_ADVISOR,
|
|
234
|
+
PROMPTS.TONE.PROFESSIONAL,
|
|
235
|
+
PROMPTS.FORMAT.JSON,
|
|
236
|
+
'You extract contact information from text and return it as JSON.',
|
|
237
|
+
);
|
|
238
|
+
|
|
239
|
+
// 3. Create a query agent with schema parsing
|
|
240
|
+
const agent = new QueryAgentAdapter('contact-extractor', {
|
|
241
|
+
model,
|
|
242
|
+
schema: extractionSchema,
|
|
243
|
+
systemPrompt,
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
// 4. Run the query
|
|
247
|
+
const userPrompt = new UserPromptAdapter(
|
|
248
|
+
'Extract contact info: "Hi, I\'m John Doe from TechCorp. Email me at john@techcorp.com or call 555-1234"',
|
|
249
|
+
);
|
|
250
|
+
const response = await agent.run(userPrompt);
|
|
251
|
+
|
|
252
|
+
// 5. Get both raw response and parsed data
|
|
253
|
+
console.log('Raw response:', response);
|
|
254
|
+
const parsedData = agent.getLastParsedResult();
|
|
255
|
+
console.log('Parsed data:', parsedData);
|
|
256
|
+
// Expected: { name: "John Doe", email: "john@techcorp.com", phone: "555-1234", company: "TechCorp" }
|
|
257
|
+
```
|
|
258
|
+
|
|
160
259
|
### Recipe: Weather Bot with Tools
|
|
161
260
|
|
|
162
261
|
This example shows how to give an agent a tool and have it respond to a user query.
|
|
@@ -187,14 +286,11 @@ const weatherTool = new SafeToolAdapter(
|
|
|
187
286
|
);
|
|
188
287
|
|
|
189
288
|
// 2. Create an agent that knows how to use tools
|
|
190
|
-
const agent = new ChatAgentAdapter(
|
|
191
|
-
|
|
192
|
-
new SystemPromptAdapter(PROMPTS.PRESETS.EMPATHETIC_SUPPORT_AGENT), // A good general-purpose preset
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
tools: [weatherTool], // Pass the tool instance directly
|
|
196
|
-
},
|
|
197
|
-
);
|
|
289
|
+
const agent = new ChatAgentAdapter('weather-bot', {
|
|
290
|
+
model,
|
|
291
|
+
systemPrompt: new SystemPromptAdapter(PROMPTS.PRESETS.EMPATHETIC_SUPPORT_AGENT), // A good general-purpose preset
|
|
292
|
+
tools: [weatherTool], // Pass the tool instance directly
|
|
293
|
+
});
|
|
198
294
|
|
|
199
295
|
// 3. Run the agent with a user query that requires the tool
|
|
200
296
|
const response = await agent.run({ generate: () => "What's the weather like in Boston?" });
|
|
@@ -212,6 +308,7 @@ console.log(response);
|
|
|
212
308
|
| Class | Description |
|
|
213
309
|
| ------------------------ | -------------------------------------------------------------------------- |
|
|
214
310
|
| `ChatAgentAdapter` | The main agent implementation. Runs prompts and coordinates tools. |
|
|
311
|
+
| `QueryAgentAdapter` | A simpler agent for one-shot responses without tools or complex logic. |
|
|
215
312
|
| `OpenRouterModelAdapter` | An adapter for connecting to any model on the OpenRouter platform. |
|
|
216
313
|
| `SafeToolAdapter` | A type-safe wrapper for creating tools with validation and error handling. |
|
|
217
314
|
| `SystemPromptAdapter` | A simple adapter to generate a system prompt string from a prompt array. |
|
|
@@ -1,35 +1,29 @@
|
|
|
1
1
|
import { type LoggerPort } from '@jterrazz/logger';
|
|
2
|
-
import { z } from 'zod/v4';
|
|
3
|
-
import type
|
|
4
|
-
import type {
|
|
5
|
-
import type {
|
|
6
|
-
import type {
|
|
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 { ToolPort } from '../../ports/tool.port.js';
|
|
7
7
|
import type { SystemPromptAdapter } from '../prompts/system-prompt.adapter.js';
|
|
8
|
-
export
|
|
9
|
-
export interface ChatAgentOptions {
|
|
8
|
+
export interface ChatAgentOptions<T = unknown> {
|
|
10
9
|
logger?: LoggerPort;
|
|
11
|
-
model:
|
|
12
|
-
|
|
10
|
+
model: ModelPort;
|
|
11
|
+
schema?: z.ZodSchema<T>;
|
|
12
|
+
systemPrompt: SystemPromptAdapter;
|
|
13
|
+
tools: ToolPort[];
|
|
14
|
+
verbose?: boolean;
|
|
13
15
|
}
|
|
14
|
-
declare const AgentResponseSchema: z.ZodObject<{
|
|
15
|
-
message: z.ZodOptional<z.ZodString>;
|
|
16
|
-
reason: z.ZodOptional<z.ZodString>;
|
|
17
|
-
shouldRespond: z.ZodBoolean;
|
|
18
|
-
}, z.core.$strip>;
|
|
19
16
|
/**
|
|
20
|
-
*
|
|
17
|
+
* An advanced agent that uses tools and a structured prompt to engage in conversational chat.
|
|
18
|
+
* It can decide whether to respond or remain silent and supports schema-validated responses.
|
|
21
19
|
*/
|
|
22
|
-
export declare class ChatAgentAdapter implements
|
|
23
|
-
|
|
24
|
-
private readonly
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
constructor(name: string, systemPrompt: SystemPromptAdapter, options: ChatAgentOptions);
|
|
28
|
-
run(userPrompt?: Prompt): Promise<null | string>;
|
|
20
|
+
export declare class ChatAgentAdapter<T = unknown> implements AgentPort {
|
|
21
|
+
readonly name: string;
|
|
22
|
+
private readonly options;
|
|
23
|
+
constructor(name: string, options: ChatAgentOptions<T>);
|
|
24
|
+
run(userPrompt?: PromptPort): Promise<null | string>;
|
|
29
25
|
private createExecutor;
|
|
30
|
-
private
|
|
31
|
-
private handleResponse;
|
|
32
|
-
private parseAgentResponse;
|
|
26
|
+
private parseAgentOutput;
|
|
33
27
|
private resolveUserInput;
|
|
28
|
+
private validateResponseContent;
|
|
34
29
|
}
|
|
35
|
-
export {};
|
|
@@ -66,10 +66,6 @@ function _instanceof(left, right) {
|
|
|
66
66
|
return left instanceof right;
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
|
-
function _type_of(obj) {
|
|
70
|
-
"@swc/helpers - typeof";
|
|
71
|
-
return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
|
|
72
|
-
}
|
|
73
69
|
function _ts_generator(thisArg, body) {
|
|
74
70
|
var f, y, t, _ = {
|
|
75
71
|
label: 0,
|
|
@@ -161,89 +157,95 @@ function _ts_generator(thisArg, body) {
|
|
|
161
157
|
};
|
|
162
158
|
}
|
|
163
159
|
}
|
|
164
|
-
import { ChatPromptTemplate
|
|
160
|
+
import { ChatPromptTemplate } from '@langchain/core/prompts';
|
|
165
161
|
import { AgentExecutor, createStructuredChatAgent } from 'langchain/agents';
|
|
166
|
-
import { z } from 'zod/v4';
|
|
167
162
|
import { AIResponseParser } from '../utils/ai-response-parser.js';
|
|
168
|
-
|
|
169
|
-
var AgentResponseSchema = z.object({
|
|
170
|
-
message: z.string().optional(),
|
|
171
|
-
reason: z.string().optional(),
|
|
172
|
-
shouldRespond: z["boolean"]()
|
|
173
|
-
});
|
|
174
|
-
// LangChain-specific framework rules (internal to this adapter)
|
|
175
|
-
var LANGCHAIN_FRAMEWORK_RULES = '\n<AGENT_FRAMEWORK>\nYou are a chat agent piloted by the LangChain framework.\n\nYou have access to the following tools: {tools}\nTool names: {tool_names}\nAgent scratchpad: {agent_scratchpad}\n\nWhen you want to provide your final response, you MUST format it exactly like this:\n\n```json\n{{"action": "Final Answer", "action_input": {{"shouldRespond": false, "reason": "<your reason>"}}}}\n```\n\nOR \n\n```json\n{{"action": "Final Answer", "action_input": {{"shouldRespond": true, "message": "<your response message>"}}}}\n```\n\n"shouldRespond" set to true means the message will be sent to the user.\n"shouldRespond" set to false means the message will not be sent to the user.\n\nALWAYS use this exact format with markdown code blocks and the action/action_input structure.\n</AGENT_FRAMEWORK>';
|
|
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 (like message templates) apply ONLY to the content that goes inside the "RESPOND: " part of your final answer.\n\nYou 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. The input must start with "RESPOND: " or "SILENT: ".\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</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';
|
|
176
164
|
/**
|
|
177
|
-
*
|
|
165
|
+
* An advanced agent that uses tools and a structured prompt to engage in conversational chat.
|
|
166
|
+
* It can decide whether to respond or remain silent and supports schema-validated responses.
|
|
178
167
|
*/ export var ChatAgentAdapter = /*#__PURE__*/ function() {
|
|
179
168
|
"use strict";
|
|
180
|
-
function ChatAgentAdapter(name,
|
|
169
|
+
function ChatAgentAdapter(name, options) {
|
|
181
170
|
_class_call_check(this, ChatAgentAdapter);
|
|
182
|
-
_define_property(this, "executorPromise", void 0);
|
|
183
|
-
_define_property(this, "logger", void 0);
|
|
184
171
|
_define_property(this, "name", void 0);
|
|
185
|
-
_define_property(this, "
|
|
172
|
+
_define_property(this, "options", void 0);
|
|
186
173
|
this.name = name;
|
|
187
|
-
this.
|
|
188
|
-
this.responseParser = new AIResponseParser(AgentResponseSchema);
|
|
189
|
-
this.executorPromise = this.createExecutor(systemPrompt, options);
|
|
174
|
+
this.options = options;
|
|
190
175
|
}
|
|
191
176
|
_create_class(ChatAgentAdapter, [
|
|
192
177
|
{
|
|
193
178
|
key: "run",
|
|
194
179
|
value: function run(userPrompt) {
|
|
195
180
|
return _async_to_generator(function() {
|
|
196
|
-
var
|
|
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;
|
|
197
182
|
return _ts_generator(this, function(_state) {
|
|
198
183
|
switch(_state.label){
|
|
199
184
|
case 0:
|
|
185
|
+
(_this_options_logger = this.options.logger) === null || _this_options_logger === void 0 ? void 0 : _this_options_logger.debug("[".concat(this.name, "] Starting chat execution."));
|
|
186
|
+
_state.label = 1;
|
|
187
|
+
case 1:
|
|
200
188
|
_state.trys.push([
|
|
201
|
-
|
|
202
|
-
|
|
189
|
+
1,
|
|
190
|
+
4,
|
|
203
191
|
,
|
|
204
|
-
|
|
192
|
+
5
|
|
205
193
|
]);
|
|
206
194
|
return [
|
|
207
195
|
4,
|
|
208
|
-
this.
|
|
196
|
+
this.createExecutor()
|
|
209
197
|
];
|
|
210
|
-
case
|
|
198
|
+
case 2:
|
|
211
199
|
executor = _state.sent();
|
|
212
|
-
|
|
200
|
+
userInput = this.resolveUserInput(userPrompt);
|
|
213
201
|
return [
|
|
214
202
|
4,
|
|
215
203
|
executor.invoke({
|
|
216
|
-
input:
|
|
204
|
+
input: userInput
|
|
217
205
|
})
|
|
218
206
|
];
|
|
219
|
-
case
|
|
207
|
+
case 3:
|
|
220
208
|
result = _state.sent();
|
|
221
|
-
(
|
|
222
|
-
|
|
223
|
-
hasOutput: 'output' in result,
|
|
224
|
-
hasUserPrompt: !!userPrompt,
|
|
225
|
-
outputType: _type_of(result.output)
|
|
209
|
+
(_this_options_logger1 = this.options.logger) === null || _this_options_logger1 === void 0 ? void 0 : _this_options_logger1.debug("[".concat(this.name, "] Agent execution completed."), {
|
|
210
|
+
hasOutput: 'output' in result
|
|
226
211
|
});
|
|
227
|
-
if (!result || typeof result.output
|
|
228
|
-
throw new Error('Agent returned invalid result structure');
|
|
212
|
+
if (!result || typeof result.output !== 'string') {
|
|
213
|
+
throw new Error('Agent returned an invalid result structure.');
|
|
214
|
+
}
|
|
215
|
+
agentResponse = this.parseAgentOutput(result.output);
|
|
216
|
+
if (!agentResponse.shouldRespond) {
|
|
217
|
+
;
|
|
218
|
+
(_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."), {
|
|
219
|
+
reason: agentResponse.reason
|
|
220
|
+
});
|
|
221
|
+
return [
|
|
222
|
+
2,
|
|
223
|
+
null
|
|
224
|
+
];
|
|
225
|
+
}
|
|
226
|
+
message = (_agentResponse_message = agentResponse.message) !== null && _agentResponse_message !== void 0 ? _agentResponse_message : '';
|
|
227
|
+
if (this.options.schema) {
|
|
228
|
+
;
|
|
229
|
+
this.validateResponseContent(message, this.options.schema);
|
|
230
|
+
(_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."));
|
|
231
|
+
} else {
|
|
232
|
+
;
|
|
233
|
+
(_this_options_logger4 = this.options.logger) === null || _this_options_logger4 === void 0 ? void 0 : _this_options_logger4.info("[".concat(this.name, "] Execution finished."));
|
|
229
234
|
}
|
|
230
|
-
response = this.parseAgentResponse(result.output);
|
|
231
235
|
return [
|
|
232
236
|
2,
|
|
233
|
-
|
|
237
|
+
message
|
|
234
238
|
];
|
|
235
|
-
case
|
|
239
|
+
case 4:
|
|
236
240
|
error = _state.sent();
|
|
237
|
-
(
|
|
238
|
-
|
|
239
|
-
error: _instanceof(error, Error) ? error.message : 'Unknown error',
|
|
240
|
-
userPrompt: userPrompt ? 'Prompt object' : 'none'
|
|
241
|
+
(_this_options_logger5 = this.options.logger) === null || _this_options_logger5 === void 0 ? void 0 : _this_options_logger5.error("[".concat(this.name, "] Chat execution failed."), {
|
|
242
|
+
error: _instanceof(error, Error) ? error.message : 'Unknown error'
|
|
241
243
|
});
|
|
242
244
|
return [
|
|
243
245
|
2,
|
|
244
246
|
null
|
|
245
247
|
];
|
|
246
|
-
case
|
|
248
|
+
case 5:
|
|
247
249
|
return [
|
|
248
250
|
2
|
|
249
251
|
];
|
|
@@ -254,31 +256,32 @@ var LANGCHAIN_FRAMEWORK_RULES = '\n<AGENT_FRAMEWORK>\nYou are a chat agent pilot
|
|
|
254
256
|
},
|
|
255
257
|
{
|
|
256
258
|
key: "createExecutor",
|
|
257
|
-
value: function createExecutor(
|
|
259
|
+
value: function createExecutor() {
|
|
258
260
|
return _async_to_generator(function() {
|
|
259
|
-
var model,
|
|
261
|
+
var model, tools, prompt, agent;
|
|
260
262
|
return _ts_generator(this, function(_state) {
|
|
261
263
|
switch(_state.label){
|
|
262
264
|
case 0:
|
|
263
|
-
model = options.model.getModel();
|
|
264
|
-
|
|
265
|
-
dynamicTools = options.tools.map(function(tool) {
|
|
265
|
+
model = this.options.model.getModel();
|
|
266
|
+
tools = this.options.tools.map(function(tool) {
|
|
266
267
|
return tool.getDynamicTool();
|
|
267
268
|
});
|
|
268
|
-
// Combine LangChain framework rules with user-provided system prompts
|
|
269
|
-
systemPromptText = "".concat(LANGCHAIN_FRAMEWORK_RULES, "\n\n").concat(systemPrompt.generate());
|
|
270
|
-
systemTemplate = SystemMessagePromptTemplate.fromTemplate(systemPromptText);
|
|
271
|
-
humanTemplate = HumanMessagePromptTemplate.fromTemplate('{input}');
|
|
272
269
|
prompt = ChatPromptTemplate.fromMessages([
|
|
273
|
-
|
|
274
|
-
|
|
270
|
+
[
|
|
271
|
+
'system',
|
|
272
|
+
SYSTEM_PROMPT_TEMPLATE.replace('{mission_prompt}', this.options.systemPrompt.generate())
|
|
273
|
+
],
|
|
274
|
+
[
|
|
275
|
+
'human',
|
|
276
|
+
'{input}'
|
|
277
|
+
]
|
|
275
278
|
]);
|
|
276
279
|
return [
|
|
277
280
|
4,
|
|
278
281
|
createStructuredChatAgent({
|
|
279
282
|
llm: model,
|
|
280
283
|
prompt: prompt,
|
|
281
|
-
tools:
|
|
284
|
+
tools: tools
|
|
282
285
|
})
|
|
283
286
|
];
|
|
284
287
|
case 1:
|
|
@@ -287,98 +290,65 @@ var LANGCHAIN_FRAMEWORK_RULES = '\n<AGENT_FRAMEWORK>\nYou are a chat agent pilot
|
|
|
287
290
|
2,
|
|
288
291
|
AgentExecutor.fromAgentAndTools({
|
|
289
292
|
agent: agent,
|
|
290
|
-
tools:
|
|
293
|
+
tools: tools,
|
|
294
|
+
verbose: this.options.verbose
|
|
291
295
|
})
|
|
292
296
|
];
|
|
293
297
|
}
|
|
294
298
|
});
|
|
295
|
-
})();
|
|
299
|
+
}).call(this);
|
|
296
300
|
}
|
|
297
301
|
},
|
|
298
302
|
{
|
|
299
|
-
key: "
|
|
300
|
-
value: function
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
if (
|
|
305
|
-
return
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
if (codeBlockMatch) {
|
|
310
|
-
var content = codeBlockMatch[1].trim();
|
|
311
|
-
try {
|
|
312
|
-
var parsed = JSON.parse(content);
|
|
313
|
-
if (parsed.action === 'Final Answer' && parsed.action_input) {
|
|
314
|
-
return JSON.stringify(parsed.action_input);
|
|
315
|
-
}
|
|
316
|
-
} catch (e) {
|
|
317
|
-
// Fall through to return original content
|
|
318
|
-
}
|
|
319
|
-
return content;
|
|
303
|
+
key: "parseAgentOutput",
|
|
304
|
+
value: function parseAgentOutput(output) {
|
|
305
|
+
var _this_options_logger;
|
|
306
|
+
var text = output.trim();
|
|
307
|
+
var respondMatch = text.match(/^RESPOND:\s*([\s\S]+)$/i);
|
|
308
|
+
if (respondMatch) {
|
|
309
|
+
return {
|
|
310
|
+
message: respondMatch[1].trim(),
|
|
311
|
+
shouldRespond: true
|
|
312
|
+
};
|
|
320
313
|
}
|
|
321
|
-
|
|
322
|
-
if (
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
}
|
|
314
|
+
var silentMatch = text.match(/^SILENT:\s*([\s\S]+)$/i);
|
|
315
|
+
if (silentMatch) {
|
|
316
|
+
return {
|
|
317
|
+
reason: silentMatch[1].trim(),
|
|
318
|
+
shouldRespond: false
|
|
319
|
+
};
|
|
327
320
|
}
|
|
328
|
-
|
|
321
|
+
(_this_options_logger = this.options.logger) === null || _this_options_logger === void 0 ? void 0 : _this_options_logger.warn("[".concat(this.name, "] Agent output was missing 'RESPOND:' or 'SILENT:' prefix. Treating as a direct response."), {
|
|
322
|
+
rawOutput: output
|
|
323
|
+
});
|
|
324
|
+
return {
|
|
325
|
+
message: text,
|
|
326
|
+
shouldRespond: true
|
|
327
|
+
};
|
|
329
328
|
}
|
|
330
329
|
},
|
|
331
330
|
{
|
|
332
|
-
key: "
|
|
333
|
-
value: function
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
var _this_logger1;
|
|
337
|
-
(_this_logger1 = this.logger) === null || _this_logger1 === void 0 ? void 0 : _this_logger1.info('Agent responding with message', {
|
|
338
|
-
agentName: this.name
|
|
339
|
-
});
|
|
340
|
-
return response.message;
|
|
341
|
-
}
|
|
342
|
-
if (!response.shouldRespond) {
|
|
343
|
-
var _this_logger2;
|
|
344
|
-
(_this_logger2 = this.logger) === null || _this_logger2 === void 0 ? void 0 : _this_logger2.info('Agent chose not to respond', {
|
|
345
|
-
agentName: this.name,
|
|
346
|
-
reason: response.reason
|
|
347
|
-
});
|
|
348
|
-
return null;
|
|
331
|
+
key: "resolveUserInput",
|
|
332
|
+
value: function resolveUserInput(userPrompt) {
|
|
333
|
+
if (userPrompt) {
|
|
334
|
+
return userPrompt.generate();
|
|
349
335
|
}
|
|
350
|
-
|
|
351
|
-
agentName: this.name,
|
|
352
|
-
response: response
|
|
353
|
-
});
|
|
354
|
-
return null;
|
|
336
|
+
return 'Proceed with your instructions.';
|
|
355
337
|
}
|
|
356
338
|
},
|
|
357
339
|
{
|
|
358
|
-
key: "
|
|
359
|
-
value: function
|
|
340
|
+
key: "validateResponseContent",
|
|
341
|
+
value: function validateResponseContent(content, schema) {
|
|
360
342
|
try {
|
|
361
|
-
|
|
362
|
-
var processedOutput = this.extractActionInput(output);
|
|
363
|
-
return this.responseParser.parse(processedOutput);
|
|
343
|
+
new AIResponseParser(schema).parse(content);
|
|
364
344
|
} catch (error) {
|
|
365
|
-
var
|
|
366
|
-
(
|
|
367
|
-
agentName: this.name,
|
|
345
|
+
var _this_options_logger;
|
|
346
|
+
(_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."), {
|
|
368
347
|
error: _instanceof(error, Error) ? error.message : 'Unknown error',
|
|
369
|
-
|
|
348
|
+
rawContent: content
|
|
370
349
|
});
|
|
371
|
-
throw new Error('Invalid
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
},
|
|
375
|
-
{
|
|
376
|
-
key: "resolveUserInput",
|
|
377
|
-
value: function resolveUserInput(userPrompt) {
|
|
378
|
-
if (!userPrompt) {
|
|
379
|
-
return 'Please analyze the current situation and respond if appropriate.';
|
|
350
|
+
throw new Error('Invalid response content from model.');
|
|
380
351
|
}
|
|
381
|
-
return userPrompt.generate();
|
|
382
352
|
}
|
|
383
353
|
}
|
|
384
354
|
]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/adapters/agents/chat-agent.adapter.ts"],"sourcesContent":["import { type LoggerPort } from '@jterrazz/logger';\nimport {\n ChatPromptTemplate,\n HumanMessagePromptTemplate,\n SystemMessagePromptTemplate,\n} from '@langchain/core/prompts';\nimport { AgentExecutor, createStructuredChatAgent } from 'langchain/agents';\nimport { z } from 'zod/v4';\n\nimport type { Agent } from '../../ports/agent.port.js';\nimport type { Model } from '../../ports/model.port.js';\nimport type { Prompt } from '../../ports/prompt.port.js';\nimport type { Tool } 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 type AgentResponse = z.infer<typeof AgentResponseSchema>;\n\nexport interface ChatAgentOptions {\n logger?: LoggerPort;\n model: Model;\n tools: Tool[];\n}\n\n// Schema for agent responses\nconst AgentResponseSchema = z.object({\n message: z.string().optional(),\n reason: z.string().optional(),\n shouldRespond: z.boolean(),\n});\n\n// LangChain-specific framework rules (internal to this adapter)\nconst LANGCHAIN_FRAMEWORK_RULES = `\n<AGENT_FRAMEWORK>\nYou are a chat agent piloted by the LangChain framework.\n\nYou have access to the following tools: {tools}\nTool names: {tool_names}\nAgent scratchpad: {agent_scratchpad}\n\nWhen you want to provide your final response, you MUST format it exactly like this:\n\n\\`\\`\\`json\n{{\"action\": \"Final Answer\", \"action_input\": {{\"shouldRespond\": false, \"reason\": \"<your reason>\"}}}}\n\\`\\`\\`\n\nOR \n\n\\`\\`\\`json\n{{\"action\": \"Final Answer\", \"action_input\": {{\"shouldRespond\": true, \"message\": \"<your response message>\"}}}}\n\\`\\`\\`\n\n\"shouldRespond\" set to true means the message will be sent to the user.\n\"shouldRespond\" set to false means the message will not be sent to the user.\n\nALWAYS use this exact format with markdown code blocks and the action/action_input structure.\n</AGENT_FRAMEWORK>`;\n\n/**\n * Chat agent adapter that provides structured chat capabilities with optional responses\n */\nexport class ChatAgentAdapter implements Agent {\n private readonly executorPromise: Promise<AgentExecutor>;\n private readonly logger?: LoggerPort;\n private readonly name: string;\n private readonly responseParser: AIResponseParser<AgentResponse>;\n\n constructor(name: string, systemPrompt: SystemPromptAdapter, options: ChatAgentOptions) {\n this.name = name;\n this.logger = options.logger;\n this.responseParser = new AIResponseParser(AgentResponseSchema);\n this.executorPromise = this.createExecutor(systemPrompt, options);\n }\n\n async run(userPrompt?: Prompt): Promise<null | string> {\n try {\n const executor = await this.executorPromise;\n const input = this.resolveUserInput(userPrompt);\n const result = await executor.invoke({ input });\n\n this.logger?.debug('Agent execution result', {\n agentName: this.name,\n hasOutput: 'output' in result,\n hasUserPrompt: !!userPrompt,\n outputType: typeof result.output,\n });\n\n if (!result || typeof result.output === 'undefined') {\n throw new Error('Agent returned invalid result structure');\n }\n\n const response = this.parseAgentResponse(result.output);\n return this.handleResponse(response);\n } catch (error) {\n this.logger?.error('Error running chat agent', {\n agentName: this.name,\n error: error instanceof Error ? error.message : 'Unknown error',\n userPrompt: userPrompt ? 'Prompt object' : 'none',\n });\n return null;\n }\n }\n\n private async createExecutor(\n systemPrompt: SystemPromptAdapter,\n options: ChatAgentOptions,\n ): Promise<AgentExecutor> {\n const model = options.model.getModel();\n\n // Convert Tool instances to DynamicTool instances\n const dynamicTools = options.tools.map((tool) => tool.getDynamicTool());\n\n // Combine LangChain framework rules with user-provided system prompts\n const systemPromptText = `${LANGCHAIN_FRAMEWORK_RULES}\\n\\n${systemPrompt.generate()}`;\n const systemTemplate = SystemMessagePromptTemplate.fromTemplate(systemPromptText);\n const humanTemplate = HumanMessagePromptTemplate.fromTemplate('{input}');\n\n const prompt = ChatPromptTemplate.fromMessages([systemTemplate, humanTemplate]);\n\n const agent = await createStructuredChatAgent({\n llm: model,\n prompt,\n tools: dynamicTools,\n });\n\n return AgentExecutor.fromAgentAndTools({\n agent,\n tools: dynamicTools,\n });\n }\n\n private extractActionInput(output: unknown): string {\n if (typeof output === 'object' && output !== null) {\n return JSON.stringify(output);\n }\n\n if (typeof output !== 'string') {\n return String(output);\n }\n\n // Check for LangChain's action/action_input format first\n const codeBlockMatch = output.match(/```(?:json)?\\s*([\\s\\S]*?)```/i);\n if (codeBlockMatch) {\n const content = codeBlockMatch[1].trim();\n try {\n const parsed = JSON.parse(content);\n if (parsed.action === 'Final Answer' && parsed.action_input) {\n return JSON.stringify(parsed.action_input);\n }\n } catch {\n // Fall through to return original content\n }\n return content;\n }\n\n // Fallback: Look for \"Final Answer:\" pattern\n if (output.includes('Final Answer:')) {\n const actionInputMatch = output.match(/Final Answer:\\s*([\\s\\S]*?)$/i);\n if (actionInputMatch) {\n return actionInputMatch[1].trim();\n }\n }\n\n return output;\n }\n\n private handleResponse(response: AgentResponse): null | string {\n if (response.shouldRespond && response.message) {\n this.logger?.info('Agent responding with message', { agentName: this.name });\n return response.message;\n }\n\n if (!response.shouldRespond) {\n this.logger?.info('Agent chose not to respond', {\n agentName: this.name,\n reason: response.reason,\n });\n return null;\n }\n\n this.logger?.error('Invalid agent response state', { agentName: this.name, response });\n return null;\n }\n\n private parseAgentResponse(output: unknown): AgentResponse {\n try {\n // Handle LangChain's action/action_input format\n const processedOutput = this.extractActionInput(output);\n return this.responseParser.parse(processedOutput);\n } catch (error) {\n this.logger?.error('Failed to parse agent response', {\n agentName: this.name,\n error: error instanceof Error ? error.message : 'Unknown error',\n rawOutput: output,\n });\n throw new Error('Invalid agent response format');\n }\n }\n\n private resolveUserInput(userPrompt?: Prompt): string {\n if (!userPrompt) {\n return 'Please analyze the current situation and respond if appropriate.';\n }\n\n return userPrompt.generate();\n }\n}\n"],"names":["ChatPromptTemplate","HumanMessagePromptTemplate","SystemMessagePromptTemplate","AgentExecutor","createStructuredChatAgent","z","AIResponseParser","AgentResponseSchema","object","message","string","optional","reason","shouldRespond","boolean","LANGCHAIN_FRAMEWORK_RULES","ChatAgentAdapter","name","systemPrompt","options","executorPromise","logger","responseParser","createExecutor","run","userPrompt","executor","input","result","response","error","resolveUserInput","invoke","debug","agentName","hasOutput","hasUserPrompt","outputType","output","Error","parseAgentResponse","handleResponse","model","dynamicTools","systemPromptText","systemTemplate","humanTemplate","prompt","agent","getModel","tools","map","tool","getDynamicTool","generate","fromTemplate","fromMessages","llm","fromAgentAndTools","extractActionInput","JSON","stringify","String","codeBlockMatch","match","content","trim","parsed","parse","action","action_input","includes","actionInputMatch","info","processedOutput","rawOutput"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/adapters/agents/chat-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 ChatAgentOptions<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. Any formatting guidelines within the <OBJECTIVE> section (like message templates) apply ONLY to the content that goes inside the \"RESPOND: \" part of your final answer.\n\nYou 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. The input must start with \"RESPOND: \" or \"SILENT: \".\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</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 advanced agent that uses tools and a structured prompt to engage in conversational chat.\n * It can decide whether to respond or remain silent and supports schema-validated responses.\n */\nexport class ChatAgentAdapter<T = unknown> implements AgentPort {\n constructor(\n public readonly name: string,\n private readonly options: ChatAgentOptions<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.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): {\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?.warn(\n `[${this.name}] Agent output was missing 'RESPOND:' or 'SILENT:' prefix. Treating as a direct response.`,\n { rawOutput: output },\n );\n\n return { message: text, shouldRespond: true };\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","ChatAgentAdapter","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","warn","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 QueryAgentOptions<T = string> {
|
|
8
|
+
logger?: LoggerPort;
|
|
9
|
+
model: ModelPort;
|
|
10
|
+
schema?: z.ZodSchema<T>;
|
|
11
|
+
systemPrompt: SystemPromptAdapter;
|
|
12
|
+
verbose?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* A simple 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 QueryAgentAdapter<T = string> implements AgentPort {
|
|
19
|
+
readonly name: string;
|
|
20
|
+
private readonly options;
|
|
21
|
+
constructor(name: string, options: QueryAgentOptions<T>);
|
|
22
|
+
run(userPrompt?: PromptPort): Promise<null | string>;
|
|
23
|
+
private invokeModel;
|
|
24
|
+
private parseResponse;
|
|
25
|
+
private resolveUserInput;
|
|
26
|
+
}
|