@jterrazz/intelligence 1.0.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/README.md +111 -14
  2. package/dist/adapters/agents/chat-agent.adapter.d.ts +20 -26
  3. package/dist/adapters/agents/chat-agent.adapter.js +99 -129
  4. package/dist/adapters/agents/chat-agent.adapter.js.map +1 -1
  5. package/dist/adapters/agents/query-agent.adapter.d.ts +26 -0
  6. package/dist/adapters/agents/query-agent.adapter.js +303 -0
  7. package/dist/adapters/agents/query-agent.adapter.js.map +1 -0
  8. package/dist/adapters/models/openrouter-model.adapter.d.ts +16 -6
  9. package/dist/adapters/models/openrouter-model.adapter.js +7 -4
  10. package/dist/adapters/models/openrouter-model.adapter.js.map +1 -1
  11. package/dist/adapters/prompts/__tests__/__snapshots__/presets.test.ts.snap +73 -103
  12. package/dist/adapters/prompts/__tests__/presets.test.js +1 -1
  13. package/dist/adapters/prompts/__tests__/presets.test.js.map +1 -1
  14. package/dist/adapters/prompts/library/categories/domain.d.ts +8 -8
  15. package/dist/adapters/prompts/library/categories/domain.js +8 -8
  16. package/dist/adapters/prompts/library/categories/domain.js.map +1 -1
  17. package/dist/adapters/prompts/library/categories/format.d.ts +7 -6
  18. package/dist/adapters/prompts/library/categories/format.js +7 -6
  19. package/dist/adapters/prompts/library/categories/format.js.map +1 -1
  20. package/dist/adapters/prompts/library/categories/foundations.d.ts +11 -0
  21. package/dist/adapters/prompts/library/categories/foundations.js +12 -0
  22. package/dist/adapters/prompts/library/categories/foundations.js.map +1 -0
  23. package/dist/adapters/prompts/library/categories/language.d.ts +8 -8
  24. package/dist/adapters/prompts/library/categories/language.js +8 -8
  25. package/dist/adapters/prompts/library/categories/language.js.map +1 -1
  26. package/dist/adapters/prompts/library/categories/persona.d.ts +9 -8
  27. package/dist/adapters/prompts/library/categories/persona.js +9 -8
  28. package/dist/adapters/prompts/library/categories/persona.js.map +1 -1
  29. package/dist/adapters/prompts/library/categories/response.d.ts +9 -0
  30. package/dist/adapters/prompts/library/categories/response.js +10 -0
  31. package/dist/adapters/prompts/library/categories/response.js.map +1 -0
  32. package/dist/adapters/prompts/library/categories/tone.d.ts +5 -5
  33. package/dist/adapters/prompts/library/categories/tone.js +5 -5
  34. package/dist/adapters/prompts/library/categories/tone.js.map +1 -1
  35. package/dist/adapters/prompts/library/categories/verbosity.d.ts +3 -3
  36. package/dist/adapters/prompts/library/categories/verbosity.js +3 -3
  37. package/dist/adapters/prompts/library/categories/verbosity.js.map +1 -1
  38. package/dist/adapters/prompts/library/index.d.ts +50 -50
  39. package/dist/adapters/prompts/library/index.js +15 -17
  40. package/dist/adapters/prompts/library/index.js.map +1 -1
  41. package/dist/adapters/prompts/library/presets.d.ts +5 -5
  42. package/dist/adapters/prompts/library/presets.js +27 -33
  43. package/dist/adapters/prompts/library/presets.js.map +1 -1
  44. package/dist/adapters/prompts/system-prompt.adapter.d.ts +2 -2
  45. package/dist/adapters/prompts/system-prompt.adapter.js.map +1 -1
  46. package/dist/adapters/prompts/user-prompt.adapter.d.ts +2 -2
  47. package/dist/adapters/prompts/user-prompt.adapter.js.map +1 -1
  48. package/dist/adapters/tools/safe-tool.adapter.d.ts +2 -2
  49. package/dist/adapters/tools/safe-tool.adapter.js.map +1 -1
  50. package/dist/index.cjs +517 -258
  51. package/dist/index.d.ts +1 -0
  52. package/dist/index.js +1 -0
  53. package/dist/index.js.map +1 -1
  54. package/dist/ports/agent.port.d.ts +3 -3
  55. package/dist/ports/agent.port.js.map +1 -1
  56. package/dist/ports/model.port.d.ts +1 -1
  57. package/dist/ports/model.port.js.map +1 -1
  58. package/dist/ports/prompt.port.d.ts +1 -1
  59. package/dist/ports/prompt.port.js.map +1 -1
  60. package/dist/ports/tool.port.d.ts +1 -1
  61. package/dist/ports/tool.port.js.map +1 -1
  62. package/package.json +1 -1
  63. package/dist/adapters/prompts/library/categories/agent-logic.d.ts +0 -8
  64. package/dist/adapters/prompts/library/categories/agent-logic.js +0 -9
  65. package/dist/adapters/prompts/library/categories/agent-logic.js.map +0 -1
  66. package/dist/adapters/prompts/library/categories/agent-skills.d.ts +0 -8
  67. package/dist/adapters/prompts/library/categories/agent-skills.js +0 -9
  68. package/dist/adapters/prompts/library/categories/agent-skills.js.map +0 -1
  69. package/dist/adapters/prompts/library/categories/directives.d.ts +0 -9
  70. package/dist/adapters/prompts/library/categories/directives.js +0 -10
  71. 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
- 'discord-bot',
48
- new SystemPromptAdapter(PROMPTS.PRESETS.DISCORD_COMMUNITY_ANIMATOR),
49
- { model },
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', systemPrompt, { model });
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
- 'weather-bot',
192
- new SystemPromptAdapter(PROMPTS.PRESETS.EMPATHETIC_SUPPORT_AGENT), // A good general-purpose preset
193
- {
194
- model,
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 { Agent } from '../../ports/agent.port.js';
4
- import type { Model } from '../../ports/model.port.js';
5
- import type { Prompt } from '../../ports/prompt.port.js';
6
- import type { Tool } from '../../ports/tool.port.js';
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 type AgentResponse = z.infer<typeof AgentResponseSchema>;
9
- export interface ChatAgentOptions {
8
+ export interface ChatAgentOptions<T = unknown> {
10
9
  logger?: LoggerPort;
11
- model: Model;
12
- tools: Tool[];
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
- * Chat agent adapter that provides structured chat capabilities with optional responses
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 Agent {
23
- private readonly executorPromise;
24
- private readonly logger?;
25
- private readonly name;
26
- private readonly responseParser;
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 extractActionInput;
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, HumanMessagePromptTemplate, SystemMessagePromptTemplate } from '@langchain/core/prompts';
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
- // Schema for agent responses
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
- * Chat agent adapter that provides structured chat capabilities with optional responses
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, systemPrompt, options) {
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, "responseParser", void 0);
172
+ _define_property(this, "options", void 0);
186
173
  this.name = name;
187
- this.logger = options.logger;
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 _this_logger, executor, input, result, response, error, _this_logger1;
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
- 0,
202
- 3,
189
+ 1,
190
+ 4,
203
191
  ,
204
- 4
192
+ 5
205
193
  ]);
206
194
  return [
207
195
  4,
208
- this.executorPromise
196
+ this.createExecutor()
209
197
  ];
210
- case 1:
198
+ case 2:
211
199
  executor = _state.sent();
212
- input = this.resolveUserInput(userPrompt);
200
+ userInput = this.resolveUserInput(userPrompt);
213
201
  return [
214
202
  4,
215
203
  executor.invoke({
216
- input: input
204
+ input: userInput
217
205
  })
218
206
  ];
219
- case 2:
207
+ case 3:
220
208
  result = _state.sent();
221
- (_this_logger = this.logger) === null || _this_logger === void 0 ? void 0 : _this_logger.debug('Agent execution result', {
222
- agentName: this.name,
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 === 'undefined') {
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
- this.handleResponse(response)
237
+ message
234
238
  ];
235
- case 3:
239
+ case 4:
236
240
  error = _state.sent();
237
- (_this_logger1 = this.logger) === null || _this_logger1 === void 0 ? void 0 : _this_logger1.error('Error running chat agent', {
238
- agentName: this.name,
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 4:
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(systemPrompt, options) {
259
+ value: function createExecutor() {
258
260
  return _async_to_generator(function() {
259
- var model, dynamicTools, systemPromptText, systemTemplate, humanTemplate, prompt, agent;
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
- // Convert Tool instances to DynamicTool instances
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
- systemTemplate,
274
- humanTemplate
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: dynamicTools
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: dynamicTools
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: "extractActionInput",
300
- value: function extractActionInput(output) {
301
- if ((typeof output === "undefined" ? "undefined" : _type_of(output)) === 'object' && output !== null) {
302
- return JSON.stringify(output);
303
- }
304
- if (typeof output !== 'string') {
305
- return String(output);
306
- }
307
- // Check for LangChain's action/action_input format first
308
- var codeBlockMatch = output.match(/```(?:json)?\s*([\s\S]*?)```/i);
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
- // Fallback: Look for "Final Answer:" pattern
322
- if (output.includes('Final Answer:')) {
323
- var actionInputMatch = output.match(/Final Answer:\s*([\s\S]*?)$/i);
324
- if (actionInputMatch) {
325
- return actionInputMatch[1].trim();
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
- return output;
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: "handleResponse",
333
- value: function handleResponse(response) {
334
- var _this_logger;
335
- if (response.shouldRespond && response.message) {
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
- (_this_logger = this.logger) === null || _this_logger === void 0 ? void 0 : _this_logger.error('Invalid agent response state', {
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: "parseAgentResponse",
359
- value: function parseAgentResponse(output) {
340
+ key: "validateResponseContent",
341
+ value: function validateResponseContent(content, schema) {
360
342
  try {
361
- // Handle LangChain's action/action_input format
362
- var processedOutput = this.extractActionInput(output);
363
- return this.responseParser.parse(processedOutput);
343
+ new AIResponseParser(schema).parse(content);
364
344
  } catch (error) {
365
- var _this_logger;
366
- (_this_logger = this.logger) === null || _this_logger === void 0 ? void 0 : _this_logger.error('Failed to parse agent response', {
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
- rawOutput: output
348
+ rawContent: content
370
349
  });
371
- throw new Error('Invalid agent response format');
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
+ }