@jterrazz/intelligence 1.3.0 → 1.4.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.
@@ -1 +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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"}
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 { 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<TOutput = string> {\n logger?: LoggerPort;\n model: ModelPort;\n schema?: z.ZodSchema<TOutput>;\n systemPrompt: SystemPromptAdapter;\n tools: ToolPort[];\n verbose?: boolean;\n}\n\nconst SYSTEM_PROMPT_TEMPLATE = `\n<OBJECTIVE>\n{mission_prompt}\n</OBJECTIVE>\n\n<GLOBAL_WRAPPER_OUTPUT_FORMAT>\nCRITICAL: The format instructions in this section are the ONLY valid way to structure your response. Your entire response MUST be a single JSON markdown code block. Any formatting guidelines within the <OBJECTIVE> section apply ONLY to the content inside the \"RESPOND:\" part of your final \"action_input\".\n\nREQUIRED: You have two ways to respond:\n\n1. **Call a tool** to gather information. For this, you MUST output a JSON blob with the tool's name and its input.\n *Valid tool names are: {tool_names}*\n \\`\\`\\`json\n {{\n \"action\": \"tool_name_to_use\",\n \"action_input\": \"the input for the tool, or an empty object {{}} if no input is needed\"\n }}\n \\`\\`\\`\n\n2. **Provide the Final Answer** once you have enough information. For this, you MUST output a JSON blob with the \"Final Answer\" action.\n The \"action_input\" for a \"Final Answer\" MUST be a string that begins with either \"RESPOND: \" for a message or \"SILENT: \" for no message. This prefix is a literal part of the output string and MUST NOT be omitted.\n - To send a message:\n \\`\\`\\`json\n {{\n \"action\": \"Final Answer\",\n \"action_input\": \"RESPOND: <your response message>\"\n }}\n \\`\\`\\`\n - To stay silent:\n \\`\\`\\`json\n {{\n \"action\": \"Final Answer\",\n \"action_input\": \"SILENT: <your reason for staying silent>\"\n }}\n \\`\\`\\`\n\n YOU MUST ALWAYS INCLUDE \"RESPOND:\" OR \"SILENT:\" IN YOUR FINAL ANSWER'S \"action_input\". FAILURE TO DO SO WILL CAUSE AN ERROR.\n\n{schema_format}\n</OUTPUT_FORMAT>\n\n<EXECUTION_CONTEXT>\nThis is internal data for your reference.\n\n<TOOLS>\n{tools}\n</TOOLS>\n\n<WORKING_MEMORY>\nThis is your internal thought process and previous tool usage.\n{agent_scratchpad}\n</WORKING_MEMORY>\n</EXECUTION_CONTEXT>\n`;\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 * @template TOutput - The TypeScript type of the output\n */\nexport class AutonomousAgentAdapter<TOutput = string> implements AgentPort<PromptPort, TOutput> {\n constructor(\n public readonly name: string,\n private readonly options: AutonomousAgentOptions<TOutput>,\n ) {}\n\n async run(input?: PromptPort): Promise<null | TOutput> {\n this.options.logger?.debug(`[${this.name}] Starting chat execution.`);\n\n try {\n const executor = await this.createExecutor();\n const userInput = this.resolveUserInput(input);\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 const validatedResponse = this.validateResponseContent(\n message,\n this.options.schema,\n );\n\n this.options.logger?.info(\n `[${this.name}] Execution finished; response content validated.`,\n );\n return validatedResponse;\n } else {\n this.options.logger?.info(`[${this.name}] Execution finished.`);\n // When no schema is provided, we assume TOutput is string (default), so message is the result\n return message as TOutput;\n }\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 // Add schema format instructions if schema is provided\n let schemaFormatInstructions = '';\n if (this.options.schema) {\n const jsonSchema = z.toJSONSchema(this.options.schema);\n const isPrimitiveType = ['boolean', 'integer', 'number', 'string'].includes(\n jsonSchema.type as string,\n );\n const jsonSchemaString = JSON.stringify(jsonSchema, null, 2)\n .replace(/{/g, '{{')\n .replace(/}/g, '}}');\n\n if (isPrimitiveType) {\n schemaFormatInstructions = `\n\nSCHEMA VALIDATION: When providing a \"RESPOND:\" answer, the content after \"RESPOND: \" must be a ${jsonSchema.type} value that matches this schema:\n\n\\`\\`\\`json\n${jsonSchemaString}\n\\`\\`\\`\n\nExample format:\n\\`\\`\\`json\n{{\n \"action\": \"Final Answer\",\n \"action_input\": \"RESPOND: your ${jsonSchema.type} value here\"\n}}\n\\`\\`\\`\n\nDo not wrap the ${jsonSchema.type} value in JSON - just provide the raw value after \"RESPOND: \".`;\n } else {\n schemaFormatInstructions = `\n\nSCHEMA VALIDATION: When providing a \"RESPOND:\" answer, the content after \"RESPOND: \" must be valid JSON that matches this exact schema:\n\n\\`\\`\\`json\n${jsonSchemaString}\n\\`\\`\\`\n\nExample format:\n\\`\\`\\`json\n{{\n \"action\": \"Final Answer\",\n \"action_input\": \"RESPOND: {{\\\\\"field1\\\\\": \\\\\"value1\\\\\", \\\\\"field2\\\\\": \\\\\"value2\\\\\"}}\"\n}}\n\\`\\`\\`\n`;\n }\n }\n\n const prompt = ChatPromptTemplate.fromMessages([\n [\n 'system',\n SYSTEM_PROMPT_TEMPLATE.replace(\n '{mission_prompt}',\n this.options.systemPrompt.generate(),\n ).replace('{schema_format}', schemaFormatInstructions),\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(input?: PromptPort): string {\n if (input) {\n return input.generate();\n }\n return 'Proceed with your instructions.';\n }\n\n private validateResponseContent<TResponse>(\n content: string,\n schema: z.ZodSchema<TResponse>,\n ): TResponse {\n try {\n return 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","z","AIResponseParser","SYSTEM_PROMPT_TEMPLATE","AutonomousAgentAdapter","name","options","run","input","executor","userInput","result","agentResponse","message","validatedResponse","error","logger","debug","createExecutor","resolveUserInput","invoke","hasOutput","output","Error","parseAgentOutput","shouldRespond","info","reason","schema","validateResponseContent","model","tools","schemaFormatInstructions","jsonSchema","isPrimitiveType","jsonSchemaString","prompt","agent","getModel","map","tool","getDynamicTool","toJSONSchema","includes","type","JSON","stringify","replace","fromMessages","systemPrompt","generate","llm","fromAgentAndTools","verbose","text","trim","respondMatch","match","silentMatch","rawOutput","content","parse","rawContent"],"mappings":"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"}
@@ -1,25 +1,26 @@
1
1
  import { type LoggerPort } from '@jterrazz/logger';
2
- import { type z } from 'zod/v4';
2
+ import { z } from 'zod/v4';
3
3
  import { type AgentPort } from '../../ports/agent.port.js';
4
4
  import type { ModelPort } from '../../ports/model.port.js';
5
5
  import type { PromptPort } from '../../ports/prompt.port.js';
6
6
  import type { SystemPromptAdapter } from '../prompts/system-prompt.adapter.js';
7
- export interface BasicAgentOptions<T = string> {
7
+ export interface BasicAgentOptions<TOutput = string> {
8
8
  logger?: LoggerPort;
9
9
  model: ModelPort;
10
- schema?: z.ZodSchema<T>;
10
+ schema?: z.ZodSchema<TOutput>;
11
11
  systemPrompt: SystemPromptAdapter;
12
12
  verbose?: boolean;
13
13
  }
14
14
  /**
15
15
  * A basic agent for direct, one-shot interactions with a model.
16
16
  * It supports optional response parsing against a Zod schema but does not use tools.
17
+ * @template TOutput - The TypeScript type of the output
17
18
  */
18
- export declare class BasicAgentAdapter<T = string> implements AgentPort {
19
+ export declare class BasicAgentAdapter<TOutput = string> implements AgentPort<PromptPort, TOutput> {
19
20
  readonly name: string;
20
21
  private readonly options;
21
- constructor(name: string, options: BasicAgentOptions<T>);
22
- run(userPrompt?: PromptPort): Promise<null | string>;
22
+ constructor(name: string, options: BasicAgentOptions<TOutput>);
23
+ run(input?: PromptPort): Promise<null | TOutput>;
23
24
  private invokeModel;
24
25
  private parseResponse;
25
26
  private resolveUserInput;
@@ -157,10 +157,12 @@ function _ts_generator(thisArg, body) {
157
157
  };
158
158
  }
159
159
  }
160
+ import { z } from 'zod/v4';
160
161
  import { AIResponseParser } from '../utils/ai-response-parser.js';
161
162
  /**
162
163
  * A basic agent for direct, one-shot interactions with a model.
163
164
  * It supports optional response parsing against a Zod schema but does not use tools.
165
+ * @template TOutput - The TypeScript type of the output
164
166
  */ export var BasicAgentAdapter = /*#__PURE__*/ function() {
165
167
  "use strict";
166
168
  function BasicAgentAdapter(name, options) {
@@ -173,9 +175,9 @@ import { AIResponseParser } from '../utils/ai-response-parser.js';
173
175
  _create_class(BasicAgentAdapter, [
174
176
  {
175
177
  key: "run",
176
- value: function run(userPrompt) {
178
+ value: function run(input) {
177
179
  return _async_to_generator(function() {
178
- var _this_options_logger, content, _this_options_logger1, _this_options_logger2, error, _this_options_logger3;
180
+ var _this_options_logger, content, _this_options_logger1, parsedResponse, _this_options_logger2, error, _this_options_logger3;
179
181
  return _ts_generator(this, function(_state) {
180
182
  switch(_state.label){
181
183
  case 0:
@@ -190,21 +192,30 @@ import { AIResponseParser } from '../utils/ai-response-parser.js';
190
192
  ]);
191
193
  return [
192
194
  4,
193
- this.invokeModel(userPrompt)
195
+ this.invokeModel(input)
194
196
  ];
195
197
  case 2:
196
198
  content = _state.sent();
197
199
  if (this.options.schema) {
198
200
  ;
199
- this.parseResponse(content, this.options.schema);
201
+ parsedResponse = this.parseResponse(content, this.options.schema);
200
202
  (_this_options_logger1 = this.options.logger) === null || _this_options_logger1 === void 0 ? void 0 : _this_options_logger1.info("[".concat(this.name, "] Execution finished and response parsed."));
203
+ return [
204
+ 2,
205
+ parsedResponse
206
+ ];
201
207
  } else {
202
208
  ;
203
209
  (_this_options_logger2 = this.options.logger) === null || _this_options_logger2 === void 0 ? void 0 : _this_options_logger2.info("[".concat(this.name, "] Execution finished."));
210
+ // When no schema is provided, we assume TOutput is string (default), so content is the result
211
+ return [
212
+ 2,
213
+ content
214
+ ];
204
215
  }
205
216
  return [
206
- 2,
207
- content
217
+ 3,
218
+ 4
208
219
  ];
209
220
  case 3:
210
221
  error = _state.sent();
@@ -226,14 +237,29 @@ import { AIResponseParser } from '../utils/ai-response-parser.js';
226
237
  },
227
238
  {
228
239
  key: "invokeModel",
229
- value: function invokeModel(userPrompt) {
240
+ value: function invokeModel(input) {
230
241
  return _async_to_generator(function() {
231
- var _this_options_logger, userInput, systemMessage, messages, _this_options_logger1, response, content;
242
+ var _this_options_logger, userInput, systemMessage, jsonSchema, isPrimitiveType, messages, _this_options_logger1, response, content;
232
243
  return _ts_generator(this, function(_state) {
233
244
  switch(_state.label){
234
245
  case 0:
235
- userInput = this.resolveUserInput(userPrompt);
246
+ userInput = this.resolveUserInput(input);
236
247
  systemMessage = this.options.systemPrompt.generate();
248
+ // Add schema definition to system prompt if schema is provided
249
+ if (this.options.schema) {
250
+ jsonSchema = z.toJSONSchema(this.options.schema);
251
+ isPrimitiveType = [
252
+ 'boolean',
253
+ 'integer',
254
+ 'number',
255
+ 'string'
256
+ ].includes(jsonSchema.type);
257
+ if (isPrimitiveType) {
258
+ systemMessage += "\n\n<OUTPUT_FORMAT>\nYou must respond with a ".concat(jsonSchema.type, " value that matches this schema:\n\n```json\n").concat(JSON.stringify(jsonSchema, null, 2), "\n```\n\nYour response should be only the ").concat(jsonSchema.type, " value, without any JSON wrapping or additional text.\n</OUTPUT_FORMAT>");
259
+ } else {
260
+ systemMessage += "\n\n<OUTPUT_FORMAT>\nYou must respond with valid JSON that matches this exact schema:\n\n```json\n".concat(JSON.stringify(jsonSchema, null, 2), "\n```\n\nYour response must be parseable JSON that validates against this schema. Do not include any text outside the JSON.\n</OUTPUT_FORMAT>");
261
+ }
262
+ }
237
263
  messages = [
238
264
  {
239
265
  content: systemMessage,
@@ -276,7 +302,7 @@ import { AIResponseParser } from '../utils/ai-response-parser.js';
276
302
  key: "parseResponse",
277
303
  value: function parseResponse(content, schema) {
278
304
  try {
279
- new AIResponseParser(schema).parse(content);
305
+ return new AIResponseParser(schema).parse(content);
280
306
  } catch (error) {
281
307
  var _this_options_logger;
282
308
  (_this_options_logger = this.options.logger) === null || _this_options_logger === void 0 ? void 0 : _this_options_logger.error("[".concat(this.name, "] Failed to parse model response."), {
@@ -289,9 +315,9 @@ import { AIResponseParser } from '../utils/ai-response-parser.js';
289
315
  },
290
316
  {
291
317
  key: "resolveUserInput",
292
- value: function resolveUserInput(userPrompt) {
293
- if (userPrompt) {
294
- return userPrompt.generate();
318
+ value: function resolveUserInput(input) {
319
+ if (input) {
320
+ return input.generate();
295
321
  }
296
322
  return 'Proceed with your instructions.';
297
323
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/adapters/agents/basic-agent.adapter.ts"],"sourcesContent":["import { type LoggerPort } from '@jterrazz/logger';\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';\n\nimport { AIResponseParser } from '../utils/ai-response-parser.js';\n\nimport type { SystemPromptAdapter } from '../prompts/system-prompt.adapter.js';\n\nexport interface BasicAgentOptions<T = string> {\n logger?: LoggerPort;\n model: ModelPort;\n schema?: z.ZodSchema<T>;\n systemPrompt: SystemPromptAdapter;\n verbose?: boolean;\n}\n\n/**\n * A basic agent for direct, one-shot interactions with a model.\n * It supports optional response parsing against a Zod schema but does not use tools.\n */\nexport class BasicAgentAdapter<T = string> implements AgentPort {\n constructor(\n public readonly name: string,\n private readonly options: BasicAgentOptions<T>,\n ) {}\n\n async run(userPrompt?: PromptPort): Promise<null | string> {\n this.options.logger?.debug(`[${this.name}] Starting query execution.`);\n\n try {\n const content = await this.invokeModel(userPrompt);\n\n if (this.options.schema) {\n this.parseResponse(content, this.options.schema);\n this.options.logger?.info(`[${this.name}] Execution finished and response parsed.`);\n } else {\n this.options.logger?.info(`[${this.name}] Execution finished.`);\n }\n\n return content;\n } catch (error) {\n this.options.logger?.error(`[${this.name}] Execution failed.`, {\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n return null;\n }\n }\n\n private async invokeModel(userPrompt?: PromptPort): Promise<string> {\n const userInput = this.resolveUserInput(userPrompt);\n const systemMessage = this.options.systemPrompt.generate();\n\n const messages = [\n { content: systemMessage, role: 'system' as const },\n { content: userInput, role: 'user' as const },\n ];\n\n this.options.logger?.debug(`[${this.name}] Invoking model...`, {\n hasSchema: !!this.options.schema,\n });\n\n if (this.options.verbose) {\n this.options.logger?.info(`[${this.name}] Sending messages to model...`, {\n messages,\n });\n }\n\n const response = await this.options.model.getModel().invoke(messages);\n const { content } = response;\n\n if (typeof content !== 'string') {\n throw new Error('Model returned a non-string content type.');\n }\n\n return content;\n }\n\n private parseResponse<TResponse>(content: string, schema: z.ZodSchema<TResponse>): void {\n try {\n new AIResponseParser(schema).parse(content);\n } catch (error) {\n this.options.logger?.error(`[${this.name}] Failed to parse model response.`, {\n error: error instanceof Error ? error.message : 'Unknown error',\n rawContent: content,\n });\n throw new Error('Invalid response format from model.');\n }\n }\n\n private resolveUserInput(userPrompt?: PromptPort): string {\n if (userPrompt) {\n return userPrompt.generate();\n }\n return 'Proceed with your instructions.';\n }\n}\n"],"names":["AIResponseParser","BasicAgentAdapter","name","options","run","userPrompt","content","error","logger","debug","invokeModel","schema","parseResponse","info","Error","message","userInput","systemMessage","messages","response","resolveUserInput","systemPrompt","generate","role","hasSchema","verbose","model","getModel","invoke","parse","rawContent"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/adapters/agents/basic-agent.adapter.ts"],"sourcesContent":["import { type LoggerPort } from '@jterrazz/logger';\nimport { z } from 'zod/v4';\n\nimport { type AgentPort } from '../../ports/agent.port.js';\nimport type { ModelPort } from '../../ports/model.port.js';\nimport type { PromptPort } from '../../ports/prompt.port.js';\n\nimport { AIResponseParser } from '../utils/ai-response-parser.js';\n\nimport type { SystemPromptAdapter } from '../prompts/system-prompt.adapter.js';\n\nexport interface BasicAgentOptions<TOutput = string> {\n logger?: LoggerPort;\n model: ModelPort;\n schema?: z.ZodSchema<TOutput>;\n systemPrompt: SystemPromptAdapter;\n verbose?: boolean;\n}\n\n/**\n * A basic agent for direct, one-shot interactions with a model.\n * It supports optional response parsing against a Zod schema but does not use tools.\n * @template TOutput - The TypeScript type of the output\n */\nexport class BasicAgentAdapter<TOutput = string> implements AgentPort<PromptPort, TOutput> {\n constructor(\n public readonly name: string,\n private readonly options: BasicAgentOptions<TOutput>,\n ) {}\n\n async run(input?: PromptPort): Promise<null | TOutput> {\n this.options.logger?.debug(`[${this.name}] Starting query execution.`);\n\n try {\n const content = await this.invokeModel(input);\n\n if (this.options.schema) {\n const parsedResponse = this.parseResponse(content, this.options.schema);\n this.options.logger?.info(`[${this.name}] Execution finished and response parsed.`);\n return parsedResponse;\n } else {\n this.options.logger?.info(`[${this.name}] Execution finished.`);\n // When no schema is provided, we assume TOutput is string (default), so content is the result\n return content as TOutput;\n }\n } catch (error) {\n this.options.logger?.error(`[${this.name}] Execution failed.`, {\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n return null;\n }\n }\n\n private async invokeModel(input?: PromptPort): Promise<string> {\n const userInput = this.resolveUserInput(input);\n let systemMessage = this.options.systemPrompt.generate();\n\n // Add schema definition to system prompt if schema is provided\n if (this.options.schema) {\n const jsonSchema = z.toJSONSchema(this.options.schema);\n const isPrimitiveType = ['boolean', 'integer', 'number', 'string'].includes(\n jsonSchema.type as string,\n );\n\n if (isPrimitiveType) {\n systemMessage += `\\n\\n<OUTPUT_FORMAT>\nYou must respond with a ${jsonSchema.type} value that matches this schema:\n\n\\`\\`\\`json\n${JSON.stringify(jsonSchema, null, 2)}\n\\`\\`\\`\n\nYour response should be only the ${jsonSchema.type} value, without any JSON wrapping or additional text.\n</OUTPUT_FORMAT>`;\n } else {\n systemMessage += `\\n\\n<OUTPUT_FORMAT>\nYou must respond with valid JSON that matches this exact schema:\n\n\\`\\`\\`json\n${JSON.stringify(jsonSchema, null, 2)}\n\\`\\`\\`\n\nYour response must be parseable JSON that validates against this schema. Do not include any text outside the JSON.\n</OUTPUT_FORMAT>`;\n }\n }\n\n const messages = [\n { content: systemMessage, role: 'system' as const },\n { content: userInput, role: 'user' as const },\n ];\n\n this.options.logger?.debug(`[${this.name}] Invoking model...`, {\n hasSchema: !!this.options.schema,\n });\n\n if (this.options.verbose) {\n this.options.logger?.info(`[${this.name}] Sending messages to model...`, {\n messages,\n });\n }\n\n const response = await this.options.model.getModel().invoke(messages);\n const { content } = response;\n\n if (typeof content !== 'string') {\n throw new Error('Model returned a non-string content type.');\n }\n\n return content;\n }\n\n private parseResponse<TResponse>(content: string, schema: z.ZodSchema<TResponse>): TResponse {\n try {\n return new AIResponseParser(schema).parse(content);\n } catch (error) {\n this.options.logger?.error(`[${this.name}] Failed to parse model response.`, {\n error: error instanceof Error ? error.message : 'Unknown error',\n rawContent: content,\n });\n throw new Error('Invalid response format from model.');\n }\n }\n\n private resolveUserInput(input?: PromptPort): string {\n if (input) {\n return input.generate();\n }\n return 'Proceed with your instructions.';\n }\n}\n"],"names":["z","AIResponseParser","BasicAgentAdapter","name","options","run","input","content","parsedResponse","error","logger","debug","invokeModel","schema","parseResponse","info","Error","message","userInput","systemMessage","jsonSchema","isPrimitiveType","messages","response","resolveUserInput","systemPrompt","generate","toJSONSchema","includes","type","JSON","stringify","role","hasSchema","verbose","model","getModel","invoke","parse","rawContent"],"mappings":"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"}
package/dist/index.cjs CHANGED
@@ -627,10 +627,11 @@ function _ts_generator$2(thisArg, body) {
627
627
  };
628
628
  }
629
629
  }
630
- 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';
630
+ var SYSTEM_PROMPT_TEMPLATE = '\n<OBJECTIVE>\n{mission_prompt}\n</OBJECTIVE>\n\n<GLOBAL_WRAPPER_OUTPUT_FORMAT>\nCRITICAL: The format instructions in this section are the ONLY valid way to structure your response. Your entire response MUST be a single JSON markdown code block. Any formatting guidelines within the <OBJECTIVE> section apply ONLY to the content inside the "RESPOND:" part of your final "action_input".\n\nREQUIRED: You have two ways to respond:\n\n1. **Call a tool** to gather information. For this, you MUST output a JSON blob with the tool\'s name and its input.\n *Valid tool names are: {tool_names}*\n ```json\n {{\n "action": "tool_name_to_use",\n "action_input": "the input for the tool, or an empty object {{}} if no input is needed"\n }}\n ```\n\n2. **Provide the Final Answer** once you have enough information. For this, you MUST output a JSON blob with the "Final Answer" action.\n The "action_input" for a "Final Answer" MUST be a string that begins with either "RESPOND: " for a message or "SILENT: " for no message. This prefix is a literal part of the output string and MUST NOT be omitted.\n - To send a message:\n ```json\n {{\n "action": "Final Answer",\n "action_input": "RESPOND: <your response message>"\n }}\n ```\n - To stay silent:\n ```json\n {{\n "action": "Final Answer",\n "action_input": "SILENT: <your reason for staying silent>"\n }}\n ```\n\n YOU MUST ALWAYS INCLUDE "RESPOND:" OR "SILENT:" IN YOUR FINAL ANSWER\'S "action_input". FAILURE TO DO SO WILL CAUSE AN ERROR.\n\n{schema_format}\n</OUTPUT_FORMAT>\n\n<EXECUTION_CONTEXT>\nThis is internal data for your reference.\n\n<TOOLS>\n{tools}\n</TOOLS>\n\n<WORKING_MEMORY>\nThis is your internal thought process and previous tool usage.\n{agent_scratchpad}\n</WORKING_MEMORY>\n</EXECUTION_CONTEXT>\n';
631
631
  /**
632
632
  * An autonomous agent that uses tools and a structured prompt to accomplish tasks.
633
633
  * It can decide whether to respond or remain silent and supports schema-validated responses.
634
+ * @template TOutput - The TypeScript type of the output
634
635
  */ var AutonomousAgentAdapter = /*#__PURE__*/ function() {
635
636
  function AutonomousAgentAdapter(name, options) {
636
637
  _class_call_check$5(this, AutonomousAgentAdapter);
@@ -642,9 +643,9 @@ var SYSTEM_PROMPT_TEMPLATE = '\n<OBJECTIVE>\n{mission_prompt}\n</OBJECTIVE>\n\n<
642
643
  _create_class$5(AutonomousAgentAdapter, [
643
644
  {
644
645
  key: "run",
645
- value: function run(userPrompt) {
646
+ value: function run(input) {
646
647
  return _async_to_generator$2(function() {
647
- 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;
648
+ var _this_options_logger, _this_options_logger1, executor, userInput, result, agentResponse, _this_options_logger2, _agentResponse_message, message, _this_options_logger3, validatedResponse, _this_options_logger4, error, _this_options_logger5;
648
649
  return _ts_generator$2(this, function(_state) {
649
650
  switch(_state.label){
650
651
  case 0:
@@ -663,7 +664,7 @@ var SYSTEM_PROMPT_TEMPLATE = '\n<OBJECTIVE>\n{mission_prompt}\n</OBJECTIVE>\n\n<
663
664
  ];
664
665
  case 2:
665
666
  executor = _state.sent();
666
- userInput = this.resolveUserInput(userPrompt);
667
+ userInput = this.resolveUserInput(input);
667
668
  return [
668
669
  4,
669
670
  executor.invoke({
@@ -696,15 +697,20 @@ var SYSTEM_PROMPT_TEMPLATE = '\n<OBJECTIVE>\n{mission_prompt}\n</OBJECTIVE>\n\n<
696
697
  }
697
698
  message = (_agentResponse_message = agentResponse.message) !== null && _agentResponse_message !== void 0 ? _agentResponse_message : '';
698
699
  if (this.options.schema) {
699
- this.validateResponseContent(message, this.options.schema);
700
+ validatedResponse = this.validateResponseContent(message, this.options.schema);
700
701
  (_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."));
702
+ return [
703
+ 2,
704
+ validatedResponse
705
+ ];
701
706
  } else {
702
707
  (_this_options_logger4 = this.options.logger) === null || _this_options_logger4 === void 0 ? void 0 : _this_options_logger4.info("[".concat(this.name, "] Execution finished."));
708
+ // When no schema is provided, we assume TOutput is string (default), so message is the result
709
+ return [
710
+ 2,
711
+ message
712
+ ];
703
713
  }
704
- return [
705
- 2,
706
- message
707
- ];
708
714
  case 4:
709
715
  error = _state.sent();
710
716
  (_this_options_logger5 = this.options.logger) === null || _this_options_logger5 === void 0 ? void 0 : _this_options_logger5.error("[".concat(this.name, "] Chat execution failed."), {
@@ -727,7 +733,7 @@ var SYSTEM_PROMPT_TEMPLATE = '\n<OBJECTIVE>\n{mission_prompt}\n</OBJECTIVE>\n\n<
727
733
  key: "createExecutor",
728
734
  value: function createExecutor() {
729
735
  return _async_to_generator$2(function() {
730
- var model, tools, prompt, agent;
736
+ var model, tools, schemaFormatInstructions, jsonSchema, isPrimitiveType, jsonSchemaString, prompt, agent;
731
737
  return _ts_generator$2(this, function(_state) {
732
738
  switch(_state.label){
733
739
  case 0:
@@ -735,10 +741,27 @@ var SYSTEM_PROMPT_TEMPLATE = '\n<OBJECTIVE>\n{mission_prompt}\n</OBJECTIVE>\n\n<
735
741
  tools = this.options.tools.map(function(tool) {
736
742
  return tool.getDynamicTool();
737
743
  });
744
+ // Add schema format instructions if schema is provided
745
+ schemaFormatInstructions = '';
746
+ if (this.options.schema) {
747
+ jsonSchema = v4.z.toJSONSchema(this.options.schema);
748
+ isPrimitiveType = [
749
+ 'boolean',
750
+ 'integer',
751
+ 'number',
752
+ 'string'
753
+ ].includes(jsonSchema.type);
754
+ jsonSchemaString = JSON.stringify(jsonSchema, null, 2).replace(/{/g, '{{').replace(/}/g, '}}');
755
+ if (isPrimitiveType) {
756
+ schemaFormatInstructions = '\n\nSCHEMA VALIDATION: When providing a "RESPOND:" answer, the content after "RESPOND: " must be a '.concat(jsonSchema.type, " value that matches this schema:\n\n```json\n").concat(jsonSchemaString, '\n```\n\nExample format:\n```json\n{{\n "action": "Final Answer",\n "action_input": "RESPOND: your ').concat(jsonSchema.type, ' value here"\n}}\n```\n\nDo not wrap the ').concat(jsonSchema.type, ' value in JSON - just provide the raw value after "RESPOND: ".');
757
+ } else {
758
+ schemaFormatInstructions = '\n\nSCHEMA VALIDATION: When providing a "RESPOND:" answer, the content after "RESPOND: " must be valid JSON that matches this exact schema:\n\n```json\n'.concat(jsonSchemaString, '\n```\n\nExample format:\n```json\n{{\n "action": "Final Answer",\n "action_input": "RESPOND: {{\\"field1\\": \\"value1\\", \\"field2\\": \\"value2\\"}}"\n}}\n```\n');
759
+ }
760
+ }
738
761
  prompt = prompts.ChatPromptTemplate.fromMessages([
739
762
  [
740
763
  'system',
741
- SYSTEM_PROMPT_TEMPLATE.replace('{mission_prompt}', this.options.systemPrompt.generate())
764
+ SYSTEM_PROMPT_TEMPLATE.replace('{mission_prompt}', this.options.systemPrompt.generate()).replace('{schema_format}', schemaFormatInstructions)
742
765
  ],
743
766
  [
744
767
  'human',
@@ -795,9 +818,9 @@ var SYSTEM_PROMPT_TEMPLATE = '\n<OBJECTIVE>\n{mission_prompt}\n</OBJECTIVE>\n\n<
795
818
  },
796
819
  {
797
820
  key: "resolveUserInput",
798
- value: function resolveUserInput(userPrompt) {
799
- if (userPrompt) {
800
- return userPrompt.generate();
821
+ value: function resolveUserInput(input) {
822
+ if (input) {
823
+ return input.generate();
801
824
  }
802
825
  return 'Proceed with your instructions.';
803
826
  }
@@ -806,7 +829,7 @@ var SYSTEM_PROMPT_TEMPLATE = '\n<OBJECTIVE>\n{mission_prompt}\n</OBJECTIVE>\n\n<
806
829
  key: "validateResponseContent",
807
830
  value: function validateResponseContent(content, schema) {
808
831
  try {
809
- new AIResponseParser(schema).parse(content);
832
+ return new AIResponseParser(schema).parse(content);
810
833
  } catch (error) {
811
834
  var _this_options_logger;
812
835
  (_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."), {
@@ -982,6 +1005,7 @@ function _ts_generator$1(thisArg, body) {
982
1005
  /**
983
1006
  * A basic agent for direct, one-shot interactions with a model.
984
1007
  * It supports optional response parsing against a Zod schema but does not use tools.
1008
+ * @template TOutput - The TypeScript type of the output
985
1009
  */ var BasicAgentAdapter = /*#__PURE__*/ function() {
986
1010
  function BasicAgentAdapter(name, options) {
987
1011
  _class_call_check$4(this, BasicAgentAdapter);
@@ -993,9 +1017,9 @@ function _ts_generator$1(thisArg, body) {
993
1017
  _create_class$4(BasicAgentAdapter, [
994
1018
  {
995
1019
  key: "run",
996
- value: function run(userPrompt) {
1020
+ value: function run(input) {
997
1021
  return _async_to_generator$1(function() {
998
- var _this_options_logger, content, _this_options_logger1, _this_options_logger2, error, _this_options_logger3;
1022
+ var _this_options_logger, content, _this_options_logger1, parsedResponse, _this_options_logger2, error, _this_options_logger3;
999
1023
  return _ts_generator$1(this, function(_state) {
1000
1024
  switch(_state.label){
1001
1025
  case 0:
@@ -1010,20 +1034,25 @@ function _ts_generator$1(thisArg, body) {
1010
1034
  ]);
1011
1035
  return [
1012
1036
  4,
1013
- this.invokeModel(userPrompt)
1037
+ this.invokeModel(input)
1014
1038
  ];
1015
1039
  case 2:
1016
1040
  content = _state.sent();
1017
1041
  if (this.options.schema) {
1018
- this.parseResponse(content, this.options.schema);
1042
+ parsedResponse = this.parseResponse(content, this.options.schema);
1019
1043
  (_this_options_logger1 = this.options.logger) === null || _this_options_logger1 === void 0 ? void 0 : _this_options_logger1.info("[".concat(this.name, "] Execution finished and response parsed."));
1044
+ return [
1045
+ 2,
1046
+ parsedResponse
1047
+ ];
1020
1048
  } else {
1021
1049
  (_this_options_logger2 = this.options.logger) === null || _this_options_logger2 === void 0 ? void 0 : _this_options_logger2.info("[".concat(this.name, "] Execution finished."));
1050
+ // When no schema is provided, we assume TOutput is string (default), so content is the result
1051
+ return [
1052
+ 2,
1053
+ content
1054
+ ];
1022
1055
  }
1023
- return [
1024
- 2,
1025
- content
1026
- ];
1027
1056
  case 3:
1028
1057
  error = _state.sent();
1029
1058
  (_this_options_logger3 = this.options.logger) === null || _this_options_logger3 === void 0 ? void 0 : _this_options_logger3.error("[".concat(this.name, "] Execution failed."), {
@@ -1044,14 +1073,29 @@ function _ts_generator$1(thisArg, body) {
1044
1073
  },
1045
1074
  {
1046
1075
  key: "invokeModel",
1047
- value: function invokeModel(userPrompt) {
1076
+ value: function invokeModel(input) {
1048
1077
  return _async_to_generator$1(function() {
1049
- var _this_options_logger, userInput, systemMessage, messages, _this_options_logger1, response, content;
1078
+ var _this_options_logger, userInput, systemMessage, jsonSchema, isPrimitiveType, messages, _this_options_logger1, response, content;
1050
1079
  return _ts_generator$1(this, function(_state) {
1051
1080
  switch(_state.label){
1052
1081
  case 0:
1053
- userInput = this.resolveUserInput(userPrompt);
1082
+ userInput = this.resolveUserInput(input);
1054
1083
  systemMessage = this.options.systemPrompt.generate();
1084
+ // Add schema definition to system prompt if schema is provided
1085
+ if (this.options.schema) {
1086
+ jsonSchema = v4.z.toJSONSchema(this.options.schema);
1087
+ isPrimitiveType = [
1088
+ 'boolean',
1089
+ 'integer',
1090
+ 'number',
1091
+ 'string'
1092
+ ].includes(jsonSchema.type);
1093
+ if (isPrimitiveType) {
1094
+ systemMessage += "\n\n<OUTPUT_FORMAT>\nYou must respond with a ".concat(jsonSchema.type, " value that matches this schema:\n\n```json\n").concat(JSON.stringify(jsonSchema, null, 2), "\n```\n\nYour response should be only the ").concat(jsonSchema.type, " value, without any JSON wrapping or additional text.\n</OUTPUT_FORMAT>");
1095
+ } else {
1096
+ systemMessage += "\n\n<OUTPUT_FORMAT>\nYou must respond with valid JSON that matches this exact schema:\n\n```json\n".concat(JSON.stringify(jsonSchema, null, 2), "\n```\n\nYour response must be parseable JSON that validates against this schema. Do not include any text outside the JSON.\n</OUTPUT_FORMAT>");
1097
+ }
1098
+ }
1055
1099
  messages = [
1056
1100
  {
1057
1101
  content: systemMessage,
@@ -1093,7 +1137,7 @@ function _ts_generator$1(thisArg, body) {
1093
1137
  key: "parseResponse",
1094
1138
  value: function parseResponse(content, schema) {
1095
1139
  try {
1096
- new AIResponseParser(schema).parse(content);
1140
+ return new AIResponseParser(schema).parse(content);
1097
1141
  } catch (error) {
1098
1142
  var _this_options_logger;
1099
1143
  (_this_options_logger = this.options.logger) === null || _this_options_logger === void 0 ? void 0 : _this_options_logger.error("[".concat(this.name, "] Failed to parse model response."), {
@@ -1106,9 +1150,9 @@ function _ts_generator$1(thisArg, body) {
1106
1150
  },
1107
1151
  {
1108
1152
  key: "resolveUserInput",
1109
- value: function resolveUserInput(userPrompt) {
1110
- if (userPrompt) {
1111
- return userPrompt.generate();
1153
+ value: function resolveUserInput(input) {
1154
+ if (input) {
1155
+ return input.generate();
1112
1156
  }
1113
1157
  return 'Proceed with your instructions.';
1114
1158
  }
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- export { AutonomousAgentAdapter } from './adapters/agents/autonomous-agent.adapter.js';
2
- export { BasicAgentAdapter } from './adapters/agents/basic-agent.adapter.js';
1
+ export { AutonomousAgentAdapter, type AutonomousAgentOptions, } from './adapters/agents/autonomous-agent.adapter.js';
2
+ export { BasicAgentAdapter, type BasicAgentOptions, } from './adapters/agents/basic-agent.adapter.js';
3
3
  export { OpenRouterModelAdapter as OpenRouterAdapter } from './adapters/models/openrouter-model.adapter.js';
4
4
  export { PROMPT_LIBRARY } from './adapters/prompts/library/index.js';
5
5
  export { SystemPromptAdapter } from './adapters/prompts/system-prompt.adapter.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export { AutonomousAgentAdapter } from './adapters/agents/autonomous-agent.adapter.js';\nexport { BasicAgentAdapter } from './adapters/agents/basic-agent.adapter.js';\nexport { OpenRouterModelAdapter as OpenRouterAdapter } from './adapters/models/openrouter-model.adapter.js';\nexport { PROMPT_LIBRARY } from './adapters/prompts/library/index.js';\nexport { SystemPromptAdapter } from './adapters/prompts/system-prompt.adapter.js';\nexport { UserPromptAdapter } from './adapters/prompts/user-prompt.adapter.js';\nexport { SafeToolAdapter } from './adapters/tools/safe-tool.adapter.js';\nexport { AIResponseParser } from './adapters/utils/ai-response-parser.js';\n\nexport * from './ports/agent.port.js';\nexport * from './ports/model.port.js';\nexport * from './ports/prompt.port.js';\nexport * from './ports/tool.port.js';\n"],"names":["AutonomousAgentAdapter","BasicAgentAdapter","OpenRouterModelAdapter","OpenRouterAdapter","PROMPT_LIBRARY","SystemPromptAdapter","UserPromptAdapter","SafeToolAdapter","AIResponseParser"],"mappings":"AAAA,SAASA,sBAAsB,QAAQ,gDAAgD;AACvF,SAASC,iBAAiB,QAAQ,2CAA2C;AAC7E,SAASC,0BAA0BC,iBAAiB,QAAQ,gDAAgD;AAC5G,SAASC,cAAc,QAAQ,sCAAsC;AACrE,SAASC,mBAAmB,QAAQ,8CAA8C;AAClF,SAASC,iBAAiB,QAAQ,4CAA4C;AAC9E,SAASC,eAAe,QAAQ,wCAAwC;AACxE,SAASC,gBAAgB,QAAQ,yCAAyC;AAE1E,cAAc,wBAAwB;AACtC,cAAc,wBAAwB;AACtC,cAAc,yBAAyB;AACvC,cAAc,uBAAuB"}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export {\n AutonomousAgentAdapter,\n type AutonomousAgentOptions,\n} from './adapters/agents/autonomous-agent.adapter.js';\nexport {\n BasicAgentAdapter,\n type BasicAgentOptions,\n} from './adapters/agents/basic-agent.adapter.js';\nexport { OpenRouterModelAdapter as OpenRouterAdapter } from './adapters/models/openrouter-model.adapter.js';\nexport { PROMPT_LIBRARY } from './adapters/prompts/library/index.js';\nexport { SystemPromptAdapter } from './adapters/prompts/system-prompt.adapter.js';\nexport { UserPromptAdapter } from './adapters/prompts/user-prompt.adapter.js';\nexport { SafeToolAdapter } from './adapters/tools/safe-tool.adapter.js';\nexport { AIResponseParser } from './adapters/utils/ai-response-parser.js';\n\nexport * from './ports/agent.port.js';\nexport * from './ports/model.port.js';\nexport * from './ports/prompt.port.js';\nexport * from './ports/tool.port.js';\n"],"names":["AutonomousAgentAdapter","BasicAgentAdapter","OpenRouterModelAdapter","OpenRouterAdapter","PROMPT_LIBRARY","SystemPromptAdapter","UserPromptAdapter","SafeToolAdapter","AIResponseParser"],"mappings":"AAAA,SACIA,sBAAsB,QAEnB,gDAAgD;AACvD,SACIC,iBAAiB,QAEd,2CAA2C;AAClD,SAASC,0BAA0BC,iBAAiB,QAAQ,gDAAgD;AAC5G,SAASC,cAAc,QAAQ,sCAAsC;AACrE,SAASC,mBAAmB,QAAQ,8CAA8C;AAClF,SAASC,iBAAiB,QAAQ,4CAA4C;AAC9E,SAASC,eAAe,QAAQ,wCAAwC;AACxE,SAASC,gBAAgB,QAAQ,yCAAyC;AAE1E,cAAc,wBAAwB;AACtC,cAAc,wBAAwB;AACtC,cAAc,yBAAyB;AACvC,cAAc,uBAAuB"}
@@ -1,11 +1,13 @@
1
1
  import type { PromptPort } from './prompt.port.js';
2
2
  /**
3
- * Port for chat agents
3
+ * Port for chat agents with generic input and output types
4
+ * @template TInput - The type of input parameters the agent accepts
5
+ * @template TOutput - The type of output the agent returns
4
6
  */
5
- export interface AgentPort {
7
+ export interface AgentPort<TInput = PromptPort, TOutput = string> {
6
8
  /**
7
- * Run the agent with optional user prompt and return optional response
8
- * @param userPrompt - The user prompt to process
9
+ * Run the agent with optional input and return optional response
10
+ * @param input - The input to process
9
11
  */
10
- run(userPrompt?: PromptPort): Promise<null | string>;
12
+ run(input?: TInput): Promise<null | TOutput>;
11
13
  }
@@ -1,5 +1,7 @@
1
1
  /**
2
- * Port for chat agents
2
+ * Port for chat agents with generic input and output types
3
+ * @template TInput - The type of input parameters the agent accepts
4
+ * @template TOutput - The type of output the agent returns
3
5
  */ export { };
4
6
 
5
7
  //# sourceMappingURL=agent.port.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/ports/agent.port.ts"],"sourcesContent":["import type { PromptPort } from './prompt.port.js';\n\n/**\n * Port for chat agents\n */\nexport interface AgentPort {\n /**\n * Run the agent with optional user prompt and return optional response\n * @param userPrompt - The user prompt to process\n */\n run(userPrompt?: PromptPort): Promise<null | string>;\n}\n"],"names":[],"mappings":"AAEA;;CAEC,GACD,WAMC"}
1
+ {"version":3,"sources":["../../src/ports/agent.port.ts"],"sourcesContent":["import type { PromptPort } from './prompt.port.js';\n\n/**\n * Port for chat agents with generic input and output types\n * @template TInput - The type of input parameters the agent accepts\n * @template TOutput - The type of output the agent returns\n */\nexport interface AgentPort<TInput = PromptPort, TOutput = string> {\n /**\n * Run the agent with optional input and return optional response\n * @param input - The input to process\n */\n run(input?: TInput): Promise<null | TOutput>;\n}\n"],"names":[],"mappings":"AAEA;;;;CAIC,GACD,WAMC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@jterrazz/intelligence",
3
3
  "author": "Jean-Baptiste Terrazzoni <contact@jterrazz.com>",
4
- "version": "1.3.0",
4
+ "version": "1.4.1",
5
5
  "exports": {
6
6
  ".": {
7
7
  "require": "./dist/index.cjs",
@@ -24,10 +24,10 @@
24
24
  },
25
25
  "dependencies": {
26
26
  "@jterrazz/logger": "^1.3.4",
27
- "@langchain/community": "^0.3.46",
28
- "@langchain/core": "^0.3.58",
29
- "@langchain/openai": "^0.5.13",
30
- "zod": "^3.25.65"
27
+ "@langchain/community": "^0.3.47",
28
+ "@langchain/core": "^0.3.61",
29
+ "@langchain/openai": "^0.5.15",
30
+ "zod": "^3.25.67"
31
31
  },
32
32
  "publishConfig": {
33
33
  "registry": "https://registry.npmjs.org/"
@@ -1,26 +0,0 @@
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
- }