@jterrazz/intelligence 1.4.3 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/agents/autonomous-agent.adapter.js +2 -2
- package/dist/adapters/agents/autonomous-agent.adapter.js.map +1 -1
- package/dist/adapters/agents/basic-agent.adapter.js +1 -1
- package/dist/adapters/agents/basic-agent.adapter.js.map +1 -1
- package/dist/adapters/agents/retryable-agent.adapter.d.ts +20 -0
- package/dist/adapters/agents/retryable-agent.adapter.js +254 -0
- package/dist/adapters/agents/retryable-agent.adapter.js.map +1 -0
- package/dist/adapters/models/openrouter-model.adapter.js +1 -1
- package/dist/adapters/models/openrouter-model.adapter.js.map +1 -1
- package/dist/index.cjs +4 -4
- package/dist/ports/agent.port.d.ts +4 -0
- package/dist/ports/agent.port.js.map +1 -1
- package/package.json +2 -1
|
@@ -295,9 +295,9 @@ var SYSTEM_PROMPT_TEMPLATE = '\n<OBJECTIVE>\n{mission_prompt}\n</OBJECTIVE>\n\n<
|
|
|
295
295
|
].includes(jsonSchema.type);
|
|
296
296
|
jsonSchemaString = JSON.stringify(jsonSchema, null, 2).replace(/{/g, '{{').replace(/}/g, '}}');
|
|
297
297
|
if (isPrimitiveType) {
|
|
298
|
-
schemaFormatInstructions = '\n\nSCHEMA VALIDATION: When providing a "RESPOND:" answer, the content after "RESPOND: " must be a '.concat(jsonSchema.type, " value that matches this schema:\n\n```json\n").concat(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: ".');
|
|
298
|
+
schemaFormatInstructions = '\n\nSCHEMA VALIDATION: When providing a "RESPOND:" answer, the content after "RESPOND: " must be a '.concat(jsonSchema.type, " value that matches this schema description:\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: ".');
|
|
299
299
|
} else {
|
|
300
|
-
schemaFormatInstructions = '\n\nSCHEMA VALIDATION: When providing a "RESPOND:" answer, the content after "RESPOND: " must be valid JSON that matches this
|
|
300
|
+
schemaFormatInstructions = '\n\nSCHEMA VALIDATION: When providing a "RESPOND:" answer, the content after "RESPOND: " must be valid JSON that matches this JSON schema description:\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');
|
|
301
301
|
}
|
|
302
302
|
}
|
|
303
303
|
prompt = ChatPromptTemplate.fromMessages([
|
|
@@ -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 { 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
|
+
{"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 description:\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 JSON schema description:\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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"}
|
|
@@ -257,7 +257,7 @@ import { AIResponseParser } from '../utils/ai-response-parser.js';
|
|
|
257
257
|
if (isPrimitiveType) {
|
|
258
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
259
|
} else {
|
|
260
|
-
systemMessage += "\n\n<OUTPUT_FORMAT>\nYou must respond with valid JSON that matches this
|
|
260
|
+
systemMessage += "\n\n<OUTPUT_FORMAT>\nYou must respond with valid JSON that matches this JSON schema description:\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
261
|
}
|
|
262
262
|
}
|
|
263
263
|
messages = [
|
|
@@ -1 +1 @@
|
|
|
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
|
|
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 JSON schema description:\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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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type LoggerPort } from '@jterrazz/logger';
|
|
2
|
+
import { type AgentPort } from '../../ports/agent.port.js';
|
|
3
|
+
import type { PromptPort } from '../../ports/prompt.port.js';
|
|
4
|
+
export interface RetryableAgentAdapterOptions {
|
|
5
|
+
logger?: LoggerPort;
|
|
6
|
+
retries?: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* A decorator agent that adds retry logic to an existing agent.
|
|
10
|
+
* @template TInput - The TypeScript type of the input
|
|
11
|
+
* @template TOutput - The TypeScript type of the output
|
|
12
|
+
*/
|
|
13
|
+
export declare class RetryableAgentAdapter<TInput = PromptPort, TOutput = string> implements AgentPort<TInput, TOutput> {
|
|
14
|
+
private readonly agent;
|
|
15
|
+
readonly name: string;
|
|
16
|
+
private readonly logger?;
|
|
17
|
+
private readonly retries;
|
|
18
|
+
constructor(agent: AgentPort<TInput, TOutput>, options?: RetryableAgentAdapterOptions);
|
|
19
|
+
run(input?: TInput): Promise<null | TOutput>;
|
|
20
|
+
}
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
|
|
2
|
+
try {
|
|
3
|
+
var info = gen[key](arg);
|
|
4
|
+
var value = info.value;
|
|
5
|
+
} catch (error) {
|
|
6
|
+
reject(error);
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
if (info.done) {
|
|
10
|
+
resolve(value);
|
|
11
|
+
} else {
|
|
12
|
+
Promise.resolve(value).then(_next, _throw);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function _async_to_generator(fn) {
|
|
16
|
+
return function() {
|
|
17
|
+
var self = this, args = arguments;
|
|
18
|
+
return new Promise(function(resolve, reject) {
|
|
19
|
+
var gen = fn.apply(self, args);
|
|
20
|
+
function _next(value) {
|
|
21
|
+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
|
|
22
|
+
}
|
|
23
|
+
function _throw(err) {
|
|
24
|
+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
|
|
25
|
+
}
|
|
26
|
+
_next(undefined);
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function _class_call_check(instance, Constructor) {
|
|
31
|
+
if (!(instance instanceof Constructor)) {
|
|
32
|
+
throw new TypeError("Cannot call a class as a function");
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function _defineProperties(target, props) {
|
|
36
|
+
for(var i = 0; i < props.length; i++){
|
|
37
|
+
var descriptor = props[i];
|
|
38
|
+
descriptor.enumerable = descriptor.enumerable || false;
|
|
39
|
+
descriptor.configurable = true;
|
|
40
|
+
if ("value" in descriptor) descriptor.writable = true;
|
|
41
|
+
Object.defineProperty(target, descriptor.key, descriptor);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function _create_class(Constructor, protoProps, staticProps) {
|
|
45
|
+
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
|
|
46
|
+
if (staticProps) _defineProperties(Constructor, staticProps);
|
|
47
|
+
return Constructor;
|
|
48
|
+
}
|
|
49
|
+
function _define_property(obj, key, value) {
|
|
50
|
+
if (key in obj) {
|
|
51
|
+
Object.defineProperty(obj, key, {
|
|
52
|
+
value: value,
|
|
53
|
+
enumerable: true,
|
|
54
|
+
configurable: true,
|
|
55
|
+
writable: true
|
|
56
|
+
});
|
|
57
|
+
} else {
|
|
58
|
+
obj[key] = value;
|
|
59
|
+
}
|
|
60
|
+
return obj;
|
|
61
|
+
}
|
|
62
|
+
function _instanceof(left, right) {
|
|
63
|
+
if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
|
|
64
|
+
return !!right[Symbol.hasInstance](left);
|
|
65
|
+
} else {
|
|
66
|
+
return left instanceof right;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function _ts_generator(thisArg, body) {
|
|
70
|
+
var f, y, t, _ = {
|
|
71
|
+
label: 0,
|
|
72
|
+
sent: function() {
|
|
73
|
+
if (t[0] & 1) throw t[1];
|
|
74
|
+
return t[1];
|
|
75
|
+
},
|
|
76
|
+
trys: [],
|
|
77
|
+
ops: []
|
|
78
|
+
}, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
79
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() {
|
|
80
|
+
return this;
|
|
81
|
+
}), g;
|
|
82
|
+
function verb(n) {
|
|
83
|
+
return function(v) {
|
|
84
|
+
return step([
|
|
85
|
+
n,
|
|
86
|
+
v
|
|
87
|
+
]);
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function step(op) {
|
|
91
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
92
|
+
while(g && (g = 0, op[0] && (_ = 0)), _)try {
|
|
93
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
94
|
+
if (y = 0, t) op = [
|
|
95
|
+
op[0] & 2,
|
|
96
|
+
t.value
|
|
97
|
+
];
|
|
98
|
+
switch(op[0]){
|
|
99
|
+
case 0:
|
|
100
|
+
case 1:
|
|
101
|
+
t = op;
|
|
102
|
+
break;
|
|
103
|
+
case 4:
|
|
104
|
+
_.label++;
|
|
105
|
+
return {
|
|
106
|
+
value: op[1],
|
|
107
|
+
done: false
|
|
108
|
+
};
|
|
109
|
+
case 5:
|
|
110
|
+
_.label++;
|
|
111
|
+
y = op[1];
|
|
112
|
+
op = [
|
|
113
|
+
0
|
|
114
|
+
];
|
|
115
|
+
continue;
|
|
116
|
+
case 7:
|
|
117
|
+
op = _.ops.pop();
|
|
118
|
+
_.trys.pop();
|
|
119
|
+
continue;
|
|
120
|
+
default:
|
|
121
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
|
|
122
|
+
_ = 0;
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
|
|
126
|
+
_.label = op[1];
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
if (op[0] === 6 && _.label < t[1]) {
|
|
130
|
+
_.label = t[1];
|
|
131
|
+
t = op;
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
if (t && _.label < t[2]) {
|
|
135
|
+
_.label = t[2];
|
|
136
|
+
_.ops.push(op);
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
if (t[2]) _.ops.pop();
|
|
140
|
+
_.trys.pop();
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
op = body.call(thisArg, _);
|
|
144
|
+
} catch (e) {
|
|
145
|
+
op = [
|
|
146
|
+
6,
|
|
147
|
+
e
|
|
148
|
+
];
|
|
149
|
+
y = 0;
|
|
150
|
+
} finally{
|
|
151
|
+
f = t = 0;
|
|
152
|
+
}
|
|
153
|
+
if (op[0] & 5) throw op[1];
|
|
154
|
+
return {
|
|
155
|
+
value: op[0] ? op[1] : void 0,
|
|
156
|
+
done: true
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* A decorator agent that adds retry logic to an existing agent.
|
|
162
|
+
* @template TInput - The TypeScript type of the input
|
|
163
|
+
* @template TOutput - The TypeScript type of the output
|
|
164
|
+
*/ export var RetryableAgentAdapter = /*#__PURE__*/ function() {
|
|
165
|
+
"use strict";
|
|
166
|
+
function RetryableAgentAdapter(agent) {
|
|
167
|
+
var options = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
|
|
168
|
+
_class_call_check(this, RetryableAgentAdapter);
|
|
169
|
+
_define_property(this, "agent", void 0);
|
|
170
|
+
_define_property(this, "name", void 0);
|
|
171
|
+
_define_property(this, "logger", void 0);
|
|
172
|
+
_define_property(this, "retries", void 0);
|
|
173
|
+
this.agent = agent;
|
|
174
|
+
var logger = options.logger, _options_retries = options.retries, retries = _options_retries === void 0 ? 1 : _options_retries;
|
|
175
|
+
this.name = "Retryable(".concat(agent.name, ")");
|
|
176
|
+
this.logger = logger;
|
|
177
|
+
this.retries = retries;
|
|
178
|
+
}
|
|
179
|
+
_create_class(RetryableAgentAdapter, [
|
|
180
|
+
{
|
|
181
|
+
key: "run",
|
|
182
|
+
value: function run(input) {
|
|
183
|
+
return _async_to_generator(function() {
|
|
184
|
+
var _this_logger, maxAttempts, attempt, _this_logger1, _this_logger2, result, _this_logger3, error, _this_logger4;
|
|
185
|
+
return _ts_generator(this, function(_state) {
|
|
186
|
+
switch(_state.label){
|
|
187
|
+
case 0:
|
|
188
|
+
maxAttempts = this.retries + 1;
|
|
189
|
+
attempt = 1;
|
|
190
|
+
_state.label = 1;
|
|
191
|
+
case 1:
|
|
192
|
+
if (!(attempt <= maxAttempts)) return [
|
|
193
|
+
3,
|
|
194
|
+
6
|
|
195
|
+
];
|
|
196
|
+
_state.label = 2;
|
|
197
|
+
case 2:
|
|
198
|
+
_state.trys.push([
|
|
199
|
+
2,
|
|
200
|
+
4,
|
|
201
|
+
,
|
|
202
|
+
5
|
|
203
|
+
]);
|
|
204
|
+
(_this_logger1 = this.logger) === null || _this_logger1 === void 0 ? void 0 : _this_logger1.debug("[".concat(this.name, "] Attempt ").concat(attempt, " of ").concat(maxAttempts, "."));
|
|
205
|
+
return [
|
|
206
|
+
4,
|
|
207
|
+
this.agent.run(input)
|
|
208
|
+
];
|
|
209
|
+
case 3:
|
|
210
|
+
result = _state.sent();
|
|
211
|
+
if (result !== null) {
|
|
212
|
+
;
|
|
213
|
+
(_this_logger3 = this.logger) === null || _this_logger3 === void 0 ? void 0 : _this_logger3.info("[".concat(this.name, "] Attempt ").concat(attempt, " of ").concat(maxAttempts, " succeeded."));
|
|
214
|
+
return [
|
|
215
|
+
2,
|
|
216
|
+
result
|
|
217
|
+
];
|
|
218
|
+
}
|
|
219
|
+
(_this_logger2 = this.logger) === null || _this_logger2 === void 0 ? void 0 : _this_logger2.warn("[".concat(this.name, "] Attempt ").concat(attempt, " of ").concat(maxAttempts, " failed: agent returned null."));
|
|
220
|
+
return [
|
|
221
|
+
3,
|
|
222
|
+
5
|
|
223
|
+
];
|
|
224
|
+
case 4:
|
|
225
|
+
error = _state.sent();
|
|
226
|
+
(_this_logger4 = this.logger) === null || _this_logger4 === void 0 ? void 0 : _this_logger4.warn("[".concat(this.name, "] Attempt ").concat(attempt, " of ").concat(maxAttempts, " failed with an error."), {
|
|
227
|
+
error: _instanceof(error, Error) ? error.message : 'Unknown error'
|
|
228
|
+
});
|
|
229
|
+
return [
|
|
230
|
+
3,
|
|
231
|
+
5
|
|
232
|
+
];
|
|
233
|
+
case 5:
|
|
234
|
+
attempt++;
|
|
235
|
+
return [
|
|
236
|
+
3,
|
|
237
|
+
1
|
|
238
|
+
];
|
|
239
|
+
case 6:
|
|
240
|
+
(_this_logger = this.logger) === null || _this_logger === void 0 ? void 0 : _this_logger.error("[".concat(this.name, "] All ").concat(maxAttempts, " attempts failed."));
|
|
241
|
+
return [
|
|
242
|
+
2,
|
|
243
|
+
null
|
|
244
|
+
];
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
}).call(this);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
]);
|
|
251
|
+
return RetryableAgentAdapter;
|
|
252
|
+
}();
|
|
253
|
+
|
|
254
|
+
//# sourceMappingURL=retryable-agent.adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/adapters/agents/retryable-agent.adapter.ts"],"sourcesContent":["import { type LoggerPort } from '@jterrazz/logger';\n\nimport { type AgentPort } from '../../ports/agent.port.js';\nimport type { PromptPort } from '../../ports/prompt.port.js';\n\nexport interface RetryableAgentAdapterOptions {\n logger?: LoggerPort;\n retries?: number;\n}\n\n/**\n * A decorator agent that adds retry logic to an existing agent.\n * @template TInput - The TypeScript type of the input\n * @template TOutput - The TypeScript type of the output\n */\nexport class RetryableAgentAdapter<TInput = PromptPort, TOutput = string>\n implements AgentPort<TInput, TOutput>\n{\n public readonly name: string;\n private readonly logger?: LoggerPort;\n private readonly retries: number;\n\n constructor(\n private readonly agent: AgentPort<TInput, TOutput>,\n options: RetryableAgentAdapterOptions = {},\n ) {\n const { logger, retries = 1 } = options;\n this.name = `Retryable(${agent.name})`;\n this.logger = logger;\n this.retries = retries;\n }\n\n async run(input?: TInput): Promise<null | TOutput> {\n const maxAttempts = this.retries + 1;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n this.logger?.debug(`[${this.name}] Attempt ${attempt} of ${maxAttempts}.`);\n const result = await this.agent.run(input);\n\n if (result !== null) {\n this.logger?.info(\n `[${this.name}] Attempt ${attempt} of ${maxAttempts} succeeded.`,\n );\n return result;\n }\n\n this.logger?.warn(\n `[${this.name}] Attempt ${attempt} of ${maxAttempts} failed: agent returned null.`,\n );\n } catch (error) {\n this.logger?.warn(\n `[${this.name}] Attempt ${attempt} of ${maxAttempts} failed with an error.`,\n {\n error: error instanceof Error ? error.message : 'Unknown error',\n },\n );\n }\n }\n\n this.logger?.error(`[${this.name}] All ${maxAttempts} attempts failed.`);\n return null;\n }\n}\n"],"names":["RetryableAgentAdapter","agent","options","name","logger","retries","run","input","maxAttempts","attempt","result","error","debug","info","warn","Error","message"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAUA;;;;CAIC,GACD,OAAO,IAAA,AAAMA,sCAAN;;aAAMA,sBAQL,AAAiBC,KAAiC;YAClDC,UAAAA,iEAAwC,CAAC;gCATpCF;;QAGT,uBAAgBG,QAAhB,KAAA;QACA,uBAAiBC,UAAjB,KAAA;QACA,uBAAiBC,WAAjB,KAAA;aAGqBJ,QAAAA;QAGjB,IAAQG,SAAwBF,QAAxBE,2BAAwBF,QAAhBG,SAAAA,wCAAU;QAC1B,IAAI,CAACF,IAAI,GAAG,AAAC,aAAuB,OAAXF,MAAME,IAAI,EAAC;QACpC,IAAI,CAACC,MAAM,GAAGA;QACd,IAAI,CAACC,OAAO,GAAGA;;kBAdVL;;YAiBHM,KAAAA;mBAAN,SAAMA,IAAIC,KAAc;;wBA4BpB,cA3BMC,aAEGC,SAED,eAUA,eATMC,QAGF,eASCC,OACL;;;;gCAlBFH,cAAc,IAAI,CAACH,OAAO,GAAG;gCAE1BI,UAAU;;;qCAAGA,CAAAA,WAAWD,WAAU;;;;;;;;;;;;iCAEnC,gBAAA,IAAI,CAACJ,MAAM,cAAX,oCAAA,cAAaQ,KAAK,CAAC,AAAC,IAAyBH,OAAtB,IAAI,CAACN,IAAI,EAAC,cAA0BK,OAAdC,SAAQ,QAAkB,OAAZD,aAAY;gCACxD;;oCAAM,IAAI,CAACP,KAAK,CAACK,GAAG,CAACC;;;gCAA9BG,SAAS;gCAEf,IAAIA,WAAW,MAAM;;qCACjB,gBAAA,IAAI,CAACN,MAAM,cAAX,oCAAA,cAAaS,IAAI,CACb,AAAC,IAAyBJ,OAAtB,IAAI,CAACN,IAAI,EAAC,cAA0BK,OAAdC,SAAQ,QAAkB,OAAZD,aAAY;oCAExD;;wCAAOE;;gCACX;iCAEA,gBAAA,IAAI,CAACN,MAAM,cAAX,oCAAA,cAAaU,IAAI,CACb,AAAC,IAAyBL,OAAtB,IAAI,CAACN,IAAI,EAAC,cAA0BK,OAAdC,SAAQ,QAAkB,OAAZD,aAAY;;;;;;gCAEnDG;iCACL,gBAAA,IAAI,CAACP,MAAM,cAAX,oCAAA,cAAaU,IAAI,CACb,AAAC,IAAyBL,OAAtB,IAAI,CAACN,IAAI,EAAC,cAA0BK,OAAdC,SAAQ,QAAkB,OAAZD,aAAY,2BACpD;oCACIG,OAAOA,AAAK,YAALA,OAAiBI,SAAQJ,MAAMK,OAAO,GAAG;gCACpD;;;;;;gCApBkCP;;;;;;iCAyB9C,eAAA,IAAI,CAACL,MAAM,cAAX,mCAAA,aAAaO,KAAK,CAAC,AAAC,IAAqBH,OAAlB,IAAI,CAACL,IAAI,EAAC,UAAoB,OAAZK,aAAY;gCACrD;;oCAAO;;;;gBACX;;;;WA/CSR;IAgDZ"}
|
|
@@ -64,7 +64,7 @@ import { ChatOpenAI } from '@langchain/openai';
|
|
|
64
64
|
'X-Title': config.metadata.application
|
|
65
65
|
})
|
|
66
66
|
},
|
|
67
|
-
maxTokens: (_config_maxTokens = config.maxTokens) !== null && _config_maxTokens !== void 0 ? _config_maxTokens :
|
|
67
|
+
maxTokens: (_config_maxTokens = config.maxTokens) !== null && _config_maxTokens !== void 0 ? _config_maxTokens : 256000,
|
|
68
68
|
modelKwargs: {
|
|
69
69
|
reasoning: {
|
|
70
70
|
effort: 'high',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/adapters/models/openrouter-model.adapter.ts"],"sourcesContent":["import type { BaseLanguageModel } from '@langchain/core/language_models/base';\nimport { ChatOpenAI } from '@langchain/openai';\n\nimport type { ModelPort } from '../../ports/model.port.js';\n\nexport interface OpenRouterConfig {\n /**\n * OpenRouter API key\n */\n apiKey: string;\n /**\n * The maximum number of tokens to generate\n */\n maxTokens?: number;\n /**\n * Optional metadata for request headers\n */\n metadata?: OpenRouterMetadata;\n /**\n * The model to use (e.g., 'google/gemini-2.5-flash-preview-05-20:thinking')\n */\n modelName: string;\n}\n\nexport interface OpenRouterMetadata {\n /**\n * Application title for X-Title header\n */\n application?: string;\n /**\n * Website URL for HTTP-Referer header\n */\n website?: string;\n}\n\n/**\n * OpenRouter adapter that provides access to various models through OpenRouter's API\n */\nexport class OpenRouterModelAdapter implements ModelPort {\n private readonly model: BaseLanguageModel;\n\n constructor(config: OpenRouterConfig) {\n this.model = new ChatOpenAI({\n configuration: {\n baseURL: 'https://openrouter.ai/api/v1',\n defaultHeaders: {\n ...(config.metadata?.website && {\n 'HTTP-Referer': config.metadata.website,\n }),\n ...(config.metadata?.application && { 'X-Title': config.metadata.application }),\n },\n },\n maxTokens: config.maxTokens ??
|
|
1
|
+
{"version":3,"sources":["../../../src/adapters/models/openrouter-model.adapter.ts"],"sourcesContent":["import type { BaseLanguageModel } from '@langchain/core/language_models/base';\nimport { ChatOpenAI } from '@langchain/openai';\n\nimport type { ModelPort } from '../../ports/model.port.js';\n\nexport interface OpenRouterConfig {\n /**\n * OpenRouter API key\n */\n apiKey: string;\n /**\n * The maximum number of tokens to generate\n */\n maxTokens?: number;\n /**\n * Optional metadata for request headers\n */\n metadata?: OpenRouterMetadata;\n /**\n * The model to use (e.g., 'google/gemini-2.5-flash-preview-05-20:thinking')\n */\n modelName: string;\n}\n\nexport interface OpenRouterMetadata {\n /**\n * Application title for X-Title header\n */\n application?: string;\n /**\n * Website URL for HTTP-Referer header\n */\n website?: string;\n}\n\n/**\n * OpenRouter adapter that provides access to various models through OpenRouter's API\n */\nexport class OpenRouterModelAdapter implements ModelPort {\n private readonly model: BaseLanguageModel;\n\n constructor(config: OpenRouterConfig) {\n this.model = new ChatOpenAI({\n configuration: {\n baseURL: 'https://openrouter.ai/api/v1',\n defaultHeaders: {\n ...(config.metadata?.website && {\n 'HTTP-Referer': config.metadata.website,\n }),\n ...(config.metadata?.application && { 'X-Title': config.metadata.application }),\n },\n },\n maxTokens: config.maxTokens ?? 256_000,\n modelKwargs: {\n reasoning: {\n effort: 'high',\n exclude: true,\n },\n },\n modelName: config.modelName,\n openAIApiKey: config.apiKey,\n });\n }\n\n getModel(): BaseLanguageModel {\n return this.model;\n }\n}\n"],"names":["ChatOpenAI","OpenRouterModelAdapter","config","model","configuration","baseURL","defaultHeaders","metadata","website","application","maxTokens","modelKwargs","reasoning","effort","exclude","modelName","openAIApiKey","apiKey","getModel"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,SAASA,UAAU,QAAQ,oBAAoB;AAkC/C;;CAEC,GACD,OAAO,IAAA,AAAMC,uCAAN;;aAAMA,uBAGGC,MAAwB;gCAH3BD;YAQWC,kBAGAA;QAVpB,uBAAiBC,SAAjB,KAAA;YAamBD;QAVf,IAAI,CAACC,KAAK,GAAG,IAAIH,WAAW;YACxBI,eAAe;gBACXC,SAAS;gBACTC,gBAAgB,mBACRJ,EAAAA,mBAAAA,OAAOK,QAAQ,cAAfL,uCAAAA,iBAAiBM,OAAO,KAAI;oBAC5B,gBAAgBN,OAAOK,QAAQ,CAACC,OAAO;gBAC3C,GACIN,EAAAA,oBAAAA,OAAOK,QAAQ,cAAfL,wCAAAA,kBAAiBO,WAAW,KAAI;oBAAE,WAAWP,OAAOK,QAAQ,CAACE,WAAW;gBAAC;YAErF;YACAC,WAAWR,CAAAA,oBAAAA,OAAOQ,SAAS,cAAhBR,+BAAAA,oBAAoB;YAC/BS,aAAa;gBACTC,WAAW;oBACPC,QAAQ;oBACRC,SAAS;gBACb;YACJ;YACAC,WAAWb,OAAOa,SAAS;YAC3BC,cAAcd,OAAOe,MAAM;QAC/B;;kBAvBKhB;;YA0BTiB,KAAAA;mBAAAA,SAAAA;gBACI,OAAO,IAAI,CAACf,KAAK;YACrB;;;WA5BSF;IA6BZ"}
|
package/dist/index.cjs
CHANGED
|
@@ -766,9 +766,9 @@ var SYSTEM_PROMPT_TEMPLATE = '\n<OBJECTIVE>\n{mission_prompt}\n</OBJECTIVE>\n\n<
|
|
|
766
766
|
].includes(jsonSchema.type);
|
|
767
767
|
jsonSchemaString = JSON.stringify(jsonSchema, null, 2).replace(/{/g, '{{').replace(/}/g, '}}');
|
|
768
768
|
if (isPrimitiveType) {
|
|
769
|
-
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: ".');
|
|
769
|
+
schemaFormatInstructions = '\n\nSCHEMA VALIDATION: When providing a "RESPOND:" answer, the content after "RESPOND: " must be a '.concat(jsonSchema.type, " value that matches this schema description:\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: ".');
|
|
770
770
|
} else {
|
|
771
|
-
schemaFormatInstructions = '\n\nSCHEMA VALIDATION: When providing a "RESPOND:" answer, the content after "RESPOND: " must be valid JSON that matches this
|
|
771
|
+
schemaFormatInstructions = '\n\nSCHEMA VALIDATION: When providing a "RESPOND:" answer, the content after "RESPOND: " must be valid JSON that matches this JSON schema description:\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');
|
|
772
772
|
}
|
|
773
773
|
}
|
|
774
774
|
prompt = prompts.ChatPromptTemplate.fromMessages([
|
|
@@ -1106,7 +1106,7 @@ function _ts_generator$1(thisArg, body) {
|
|
|
1106
1106
|
if (isPrimitiveType) {
|
|
1107
1107
|
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>");
|
|
1108
1108
|
} else {
|
|
1109
|
-
systemMessage += "\n\n<OUTPUT_FORMAT>\nYou must respond with valid JSON that matches this
|
|
1109
|
+
systemMessage += "\n\n<OUTPUT_FORMAT>\nYou must respond with valid JSON that matches this JSON schema description:\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>");
|
|
1110
1110
|
}
|
|
1111
1111
|
}
|
|
1112
1112
|
messages = [
|
|
@@ -1237,7 +1237,7 @@ function _object_spread(target) {
|
|
|
1237
1237
|
'X-Title': config.metadata.application
|
|
1238
1238
|
})
|
|
1239
1239
|
},
|
|
1240
|
-
maxTokens: (_config_maxTokens = config.maxTokens) !== null && _config_maxTokens !== void 0 ? _config_maxTokens :
|
|
1240
|
+
maxTokens: (_config_maxTokens = config.maxTokens) !== null && _config_maxTokens !== void 0 ? _config_maxTokens : 256000,
|
|
1241
1241
|
modelKwargs: {
|
|
1242
1242
|
reasoning: {
|
|
1243
1243
|
effort: 'high',
|
|
@@ -5,6 +5,10 @@ import type { PromptPort } from './prompt.port.js';
|
|
|
5
5
|
* @template TOutput - The type of output the agent returns
|
|
6
6
|
*/
|
|
7
7
|
export interface AgentPort<TInput = PromptPort, TOutput = string> {
|
|
8
|
+
/**
|
|
9
|
+
* A descriptive name for the agent, used for logging and identification.
|
|
10
|
+
*/
|
|
11
|
+
readonly name: string;
|
|
8
12
|
/**
|
|
9
13
|
* Run the agent with optional input and return optional response
|
|
10
14
|
* @param input - The input to process
|
|
@@ -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 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,
|
|
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 * A descriptive name for the agent, used for logging and identification.\n */\n readonly name: string;\n\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,WAWC"}
|
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.
|
|
4
|
+
"version": "1.5.0",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
7
7
|
"require": "./dist/index.cjs",
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"@langchain/community": "^0.3.47",
|
|
28
28
|
"@langchain/core": "^0.3.61",
|
|
29
29
|
"@langchain/openai": "^0.5.15",
|
|
30
|
+
"ai": "^4.3.16",
|
|
30
31
|
"jsonrepair": "^3.12.0",
|
|
31
32
|
"zod": "^3.25.67"
|
|
32
33
|
},
|