@jterrazz/intelligence 1.0.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.
Files changed (80) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +229 -0
  3. package/dist/adapters/agents/chat-agent.adapter.d.ts +35 -0
  4. package/dist/adapters/agents/chat-agent.adapter.js +388 -0
  5. package/dist/adapters/agents/chat-agent.adapter.js.map +1 -0
  6. package/dist/adapters/models/openrouter-model.adapter.d.ts +28 -0
  7. package/dist/adapters/models/openrouter-model.adapter.js +80 -0
  8. package/dist/adapters/models/openrouter-model.adapter.js.map +1 -0
  9. package/dist/adapters/prompts/__tests__/__snapshots__/presets.test.ts.snap +150 -0
  10. package/dist/adapters/prompts/__tests__/presets.test.d.ts +1 -0
  11. package/dist/adapters/prompts/__tests__/presets.test.js +31 -0
  12. package/dist/adapters/prompts/__tests__/presets.test.js.map +1 -0
  13. package/dist/adapters/prompts/library/categories/agent-logic.d.ts +8 -0
  14. package/dist/adapters/prompts/library/categories/agent-logic.js +9 -0
  15. package/dist/adapters/prompts/library/categories/agent-logic.js.map +1 -0
  16. package/dist/adapters/prompts/library/categories/agent-skills.d.ts +8 -0
  17. package/dist/adapters/prompts/library/categories/agent-skills.js +9 -0
  18. package/dist/adapters/prompts/library/categories/agent-skills.js.map +1 -0
  19. package/dist/adapters/prompts/library/categories/directives.d.ts +9 -0
  20. package/dist/adapters/prompts/library/categories/directives.js +10 -0
  21. package/dist/adapters/prompts/library/categories/directives.js.map +1 -0
  22. package/dist/adapters/prompts/library/categories/domain.d.ts +11 -0
  23. package/dist/adapters/prompts/library/categories/domain.js +12 -0
  24. package/dist/adapters/prompts/library/categories/domain.js.map +1 -0
  25. package/dist/adapters/prompts/library/categories/format.d.ts +9 -0
  26. package/dist/adapters/prompts/library/categories/format.js +10 -0
  27. package/dist/adapters/prompts/library/categories/format.js.map +1 -0
  28. package/dist/adapters/prompts/library/categories/language.d.ts +11 -0
  29. package/dist/adapters/prompts/library/categories/language.js +12 -0
  30. package/dist/adapters/prompts/library/categories/language.js.map +1 -0
  31. package/dist/adapters/prompts/library/categories/persona.d.ts +11 -0
  32. package/dist/adapters/prompts/library/categories/persona.js +12 -0
  33. package/dist/adapters/prompts/library/categories/persona.js.map +1 -0
  34. package/dist/adapters/prompts/library/categories/tone.d.ts +9 -0
  35. package/dist/adapters/prompts/library/categories/tone.js +10 -0
  36. package/dist/adapters/prompts/library/categories/tone.js.map +1 -0
  37. package/dist/adapters/prompts/library/categories/verbosity.d.ts +8 -0
  38. package/dist/adapters/prompts/library/categories/verbosity.js +9 -0
  39. package/dist/adapters/prompts/library/categories/verbosity.js.map +1 -0
  40. package/dist/adapters/prompts/library/index.d.ts +66 -0
  41. package/dist/adapters/prompts/library/index.js +28 -0
  42. package/dist/adapters/prompts/library/index.js.map +1 -0
  43. package/dist/adapters/prompts/library/presets.d.ts +17 -0
  44. package/dist/adapters/prompts/library/presets.js +51 -0
  45. package/dist/adapters/prompts/library/presets.js.map +1 -0
  46. package/dist/adapters/prompts/system-prompt.adapter.d.ts +9 -0
  47. package/dist/adapters/prompts/system-prompt.adapter.js +57 -0
  48. package/dist/adapters/prompts/system-prompt.adapter.js.map +1 -0
  49. package/dist/adapters/prompts/user-prompt.adapter.d.ts +9 -0
  50. package/dist/adapters/prompts/user-prompt.adapter.js +57 -0
  51. package/dist/adapters/prompts/user-prompt.adapter.js.map +1 -0
  52. package/dist/adapters/tools/safe-tool.adapter.d.ts +27 -0
  53. package/dist/adapters/tools/safe-tool.adapter.js +283 -0
  54. package/dist/adapters/tools/safe-tool.adapter.js.map +1 -0
  55. package/dist/adapters/utils/__tests__/ai-response-parser.test.d.ts +1 -0
  56. package/dist/adapters/utils/__tests__/ai-response-parser.test.js +249 -0
  57. package/dist/adapters/utils/__tests__/ai-response-parser.test.js.map +1 -0
  58. package/dist/adapters/utils/ai-response-parser-error.d.ts +8 -0
  59. package/dist/adapters/utils/ai-response-parser-error.js +136 -0
  60. package/dist/adapters/utils/ai-response-parser-error.js.map +1 -0
  61. package/dist/adapters/utils/ai-response-parser.d.ts +56 -0
  62. package/dist/adapters/utils/ai-response-parser.js +334 -0
  63. package/dist/adapters/utils/ai-response-parser.js.map +1 -0
  64. package/dist/index.cjs +1461 -0
  65. package/dist/index.d.ts +11 -0
  66. package/dist/index.js +13 -0
  67. package/dist/index.js.map +1 -0
  68. package/dist/ports/agent.port.d.ts +11 -0
  69. package/dist/ports/agent.port.js +5 -0
  70. package/dist/ports/agent.port.js.map +1 -0
  71. package/dist/ports/model.port.d.ts +10 -0
  72. package/dist/ports/model.port.js +5 -0
  73. package/dist/ports/model.port.js.map +1 -0
  74. package/dist/ports/prompt.port.d.ts +9 -0
  75. package/dist/ports/prompt.port.js +5 -0
  76. package/dist/ports/prompt.port.js.map +1 -0
  77. package/dist/ports/tool.port.d.ts +11 -0
  78. package/dist/ports/tool.port.js +5 -0
  79. package/dist/ports/tool.port.js.map +1 -0
  80. package/package.json +35 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Jean-Baptiste Terrazzoni <contact@jterrazz.com>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,229 @@
1
+ # @jterrazz/intelligence
2
+
3
+ **A composable, type-safe, and framework-agnostic AI agent library for TypeScript.**
4
+
5
+ [![NPM Version](https://img.shields.io/npm/v/@jterrazz/intelligence.svg)](https://www.npmjs.com/package/@jterrazz/intelligence)
6
+ [![License](https://img.shields.io/npm/l/@jterrazz/intelligence.svg)](./LICENSE)
7
+
8
+ `@jterrazz/intelligence` provides a clean, structured, and extensible foundation for building sophisticated AI agents. By combining a composable prompt system, safe tool integration, and a ports-and-adapters architecture, it empowers developers to create reliable and maintainable AI-powered applications.
9
+
10
+ ---
11
+
12
+ ## Why Use This Library?
13
+
14
+ - **🤖 Build Predictable Agents**: Use the composable prompt library to ensure your agents have a consistent personality, tone, and behavior.
15
+ - **🛠️ Integrate Tools Safely**: `SafeToolAdapter` provides built-in error handling, logging, and Zod-based schema validation for all your tools.
16
+ - **🏗️ Stay Flexible**: The ports-and-adapters architecture makes it easy to swap out underlying models or frameworks (like LangChain) without rewriting your core logic.
17
+ - **🎯 Get Type-Safe Responses**: Move beyond string parsing with `AIResponseParser`, which validates and types your model's output against a Zod schema.
18
+
19
+ ## Installation
20
+
21
+ ```bash
22
+ npm install @jterrazz/intelligence
23
+ ```
24
+
25
+ ---
26
+
27
+ ## Quick Start
28
+
29
+ Get your first agent running in under a minute. This example uses a preset to create a helpful Discord community animator.
30
+
31
+ ```typescript
32
+ import {
33
+ ChatAgentAdapter,
34
+ OpenRouterModelAdapter,
35
+ SystemPromptAdapter,
36
+ PROMPTS,
37
+ } from '@jterrazz/intelligence';
38
+
39
+ // 1. Set up the model provider
40
+ const model = new OpenRouterModelAdapter({
41
+ apiKey: process.env.OPENROUTER_API_KEY!, // Make sure to set this environment variable
42
+ modelName: 'anthropic/claude-3.5-sonnet',
43
+ });
44
+
45
+ // 2. Create an agent using a preset prompt
46
+ const agent = new ChatAgentAdapter(
47
+ 'discord-bot',
48
+ new SystemPromptAdapter(PROMPTS.PRESETS.DISCORD_COMMUNITY_ANIMATOR),
49
+ { model },
50
+ );
51
+
52
+ // 3. Run the agent
53
+ const response = await agent.run();
54
+
55
+ console.log(response);
56
+ // Output might be: "Hello, community! I'm here to help with any questions and keep the good vibes flowing. What's on your mind today?"
57
+ ```
58
+
59
+ ---
60
+
61
+ ## Core Concepts
62
+
63
+ ### 1. Composable Prompts
64
+
65
+ Instead of writing monolithic prompts, the library provides a collection of composable string constants. Mix and match them to build a precise, fine-grained system prompt that defines your agent's behavior.
66
+
67
+ - **`PERSONA`**: Who the agent is (e.g., `EXPERT_ADVISOR`).
68
+ - **`TONE`**: How the agent communicates (e.g., `PROFESSIONAL`, `EMPATHETIC`).
69
+ - **`FORMAT`** How the agent structures its response (e.g., `MARKDOWN`, `JSON`).
70
+ - **`DIRECTIVES`**: Core rules the agent must follow (e.g., `BE_SAFE`, `BE_FACTUAL`).
71
+
72
+ This approach makes agent behavior more predictable and easier to modify.
73
+
74
+ ### 2. Safe Tool Integration
75
+
76
+ The `SafeToolAdapter` is a wrapper for your functions that ensures they are executed safely.
77
+
78
+ ```typescript
79
+ import { SafeToolAdapter } from '@jterrazz/intelligence';
80
+ import { z } from 'zod/v4';
81
+
82
+ const weatherTool = new SafeToolAdapter(
83
+ {
84
+ name: 'get_weather',
85
+ description: 'Get the current weather for a specific city.',
86
+ execute: async ({ city }) => `The weather in ${city} is currently sunny.`,
87
+ },
88
+ {
89
+ // Zod schema for automatic validation and type-safety
90
+ schema: z.object({
91
+ city: z.string().describe('The city name'),
92
+ }),
93
+ },
94
+ );
95
+ ```
96
+
97
+ The adapter handles errors gracefully and integrates seamlessly with the agent, which will automatically provide the Zod schema to the underlying model.
98
+
99
+ ### 3. Ports and Adapters Architecture
100
+
101
+ The library is built on a hexagonal architecture.
102
+
103
+ - **Ports (`/ports`)**: Define the contracts (interfaces) for core components like `Agent`, `Model`, and `Tool`.
104
+ - **Adapters (`/adapters`)**: Provide concrete implementations. For example, `ChatAgentAdapter` is an adapter that uses LangChain, and `OpenRouterModelAdapter` is an adapter for the OpenRouter API.
105
+
106
+ This separation of concerns means you can easily create your own adapters to support different models or services without changing the application's core logic.
107
+
108
+ ```
109
+ src/
110
+ ├── ports/ # Abstract interfaces (the "what")
111
+ └── adapters/ # Concrete implementations (the "how")
112
+ ```
113
+
114
+ ---
115
+
116
+ ## Recipes
117
+
118
+ ### Recipe: Code Review Assistant
119
+
120
+ This recipe creates an agent that acts as an expert software engineer, providing detailed feedback on code.
121
+
122
+ ```typescript
123
+ import {
124
+ ChatAgentAdapter,
125
+ OpenRouterModelAdapter,
126
+ SystemPromptAdapter,
127
+ UserPromptAdapter,
128
+ PROMPTS,
129
+ } from '@jterrazz/intelligence';
130
+
131
+ const model = new OpenRouterModelAdapter({
132
+ apiKey: process.env.OPENROUTER_API_KEY!,
133
+ modelName: 'anthropic/claude-3.5-sonnet',
134
+ });
135
+
136
+ // 1. Compose the system prompt from multiple parts (using rest arguments)
137
+ const systemPrompt = new SystemPromptAdapter(
138
+ PROMPTS.PERSONA.EXPERT_ADVISOR,
139
+ PROMPTS.DOMAIN.SOFTWARE_ENGINEERING,
140
+ PROMPTS.TONE.PROFESSIONAL,
141
+ PROMPTS.VERBOSITY.DETAILED,
142
+ PROMPTS.FORMAT.MARKDOWN,
143
+ PROMPTS.DIRECTIVES.BE_FACTUAL,
144
+ );
145
+
146
+ // 2. Create the user request (using a single array)
147
+ const userPrompt = new UserPromptAdapter([
148
+ 'Please review this TypeScript code for best practices:',
149
+ 'const x = (s) => s.trim();',
150
+ ]);
151
+
152
+ // 3. Configure and run the agent
153
+ const agent = new ChatAgentAdapter('code-reviewer', systemPrompt, { model });
154
+
155
+ const response = await agent.run(userPrompt);
156
+
157
+ console.log(response);
158
+ ```
159
+
160
+ ### Recipe: Weather Bot with Tools
161
+
162
+ This example shows how to give an agent a tool and have it respond to a user query.
163
+
164
+ ```typescript
165
+ import {
166
+ ChatAgentAdapter,
167
+ OpenRouterModelAdapter,
168
+ SafeToolAdapter,
169
+ SystemPromptAdapter,
170
+ PROMPTS,
171
+ } from '@jterrazz/intelligence';
172
+ import { z } from 'zod/v4';
173
+
174
+ // Assume 'model' is already configured
175
+
176
+ // 1. Define the tool
177
+ const weatherTool = new SafeToolAdapter(
178
+ {
179
+ name: 'get_weather',
180
+ description: 'Get the current weather for a location.',
181
+ execute: async ({ city }) => {
182
+ // In a real app, you would fetch from a weather API here
183
+ return `The weather in ${city} is 75°F and sunny.`;
184
+ },
185
+ },
186
+ { schema: z.object({ city: z.string().describe('City name') }) },
187
+ );
188
+
189
+ // 2. Create an agent that knows how to use tools
190
+ const agent = new ChatAgentAdapter(
191
+ 'weather-bot',
192
+ new SystemPromptAdapter(PROMPTS.PRESETS.EMPATHETIC_SUPPORT_AGENT), // A good general-purpose preset
193
+ {
194
+ model,
195
+ tools: [weatherTool], // Pass the tool instance directly
196
+ },
197
+ );
198
+
199
+ // 3. Run the agent with a user query that requires the tool
200
+ const response = await agent.run({ generate: () => "What's the weather like in Boston?" });
201
+
202
+ console.log(response);
203
+ // Expected output: "The weather in Boston is 75°F and sunny."
204
+ ```
205
+
206
+ ---
207
+
208
+ ## API Reference
209
+
210
+ ### Core Components
211
+
212
+ | Class | Description |
213
+ | ------------------------ | -------------------------------------------------------------------------- |
214
+ | `ChatAgentAdapter` | The main agent implementation. Runs prompts and coordinates tools. |
215
+ | `OpenRouterModelAdapter` | An adapter for connecting to any model on the OpenRouter platform. |
216
+ | `SafeToolAdapter` | A type-safe wrapper for creating tools with validation and error handling. |
217
+ | `SystemPromptAdapter` | A simple adapter to generate a system prompt string from a prompt array. |
218
+ | `UserPromptAdapter` | A simple adapter to generate a user prompt string from a prompt array. |
219
+ | `AIResponseParser` | A utility to parse a model's string output into a typed object using Zod. |
220
+ | `PROMPTS` | A frozen object containing the entire composable prompt library. |
221
+
222
+ ## Contributing
223
+
224
+ Contributions are welcome! Please feel free to submit a Pull Request.
225
+
226
+ ## Author
227
+
228
+ - Jean-Baptiste Terrazzoni ([@jterrazz](https://github.com/jterrazz))
229
+ - Email: contact@jterrazz.com
@@ -0,0 +1,35 @@
1
+ import { type LoggerPort } from '@jterrazz/logger';
2
+ import { z } from 'zod/v4';
3
+ import type { Agent } from '../../ports/agent.port.js';
4
+ import type { Model } from '../../ports/model.port.js';
5
+ import type { Prompt } from '../../ports/prompt.port.js';
6
+ import type { Tool } from '../../ports/tool.port.js';
7
+ import type { SystemPromptAdapter } from '../prompts/system-prompt.adapter.js';
8
+ export type AgentResponse = z.infer<typeof AgentResponseSchema>;
9
+ export interface ChatAgentOptions {
10
+ logger?: LoggerPort;
11
+ model: Model;
12
+ tools: Tool[];
13
+ }
14
+ declare const AgentResponseSchema: z.ZodObject<{
15
+ message: z.ZodOptional<z.ZodString>;
16
+ reason: z.ZodOptional<z.ZodString>;
17
+ shouldRespond: z.ZodBoolean;
18
+ }, z.core.$strip>;
19
+ /**
20
+ * Chat agent adapter that provides structured chat capabilities with optional responses
21
+ */
22
+ export declare class ChatAgentAdapter implements Agent {
23
+ private readonly executorPromise;
24
+ private readonly logger?;
25
+ private readonly name;
26
+ private readonly responseParser;
27
+ constructor(name: string, systemPrompt: SystemPromptAdapter, options: ChatAgentOptions);
28
+ run(userPrompt?: Prompt): Promise<null | string>;
29
+ private createExecutor;
30
+ private extractActionInput;
31
+ private handleResponse;
32
+ private parseAgentResponse;
33
+ private resolveUserInput;
34
+ }
35
+ export {};
@@ -0,0 +1,388 @@
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 _type_of(obj) {
70
+ "@swc/helpers - typeof";
71
+ return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
72
+ }
73
+ function _ts_generator(thisArg, body) {
74
+ var f, y, t, _ = {
75
+ label: 0,
76
+ sent: function() {
77
+ if (t[0] & 1) throw t[1];
78
+ return t[1];
79
+ },
80
+ trys: [],
81
+ ops: []
82
+ }, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
83
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() {
84
+ return this;
85
+ }), g;
86
+ function verb(n) {
87
+ return function(v) {
88
+ return step([
89
+ n,
90
+ v
91
+ ]);
92
+ };
93
+ }
94
+ function step(op) {
95
+ if (f) throw new TypeError("Generator is already executing.");
96
+ while(g && (g = 0, op[0] && (_ = 0)), _)try {
97
+ 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;
98
+ if (y = 0, t) op = [
99
+ op[0] & 2,
100
+ t.value
101
+ ];
102
+ switch(op[0]){
103
+ case 0:
104
+ case 1:
105
+ t = op;
106
+ break;
107
+ case 4:
108
+ _.label++;
109
+ return {
110
+ value: op[1],
111
+ done: false
112
+ };
113
+ case 5:
114
+ _.label++;
115
+ y = op[1];
116
+ op = [
117
+ 0
118
+ ];
119
+ continue;
120
+ case 7:
121
+ op = _.ops.pop();
122
+ _.trys.pop();
123
+ continue;
124
+ default:
125
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
126
+ _ = 0;
127
+ continue;
128
+ }
129
+ if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
130
+ _.label = op[1];
131
+ break;
132
+ }
133
+ if (op[0] === 6 && _.label < t[1]) {
134
+ _.label = t[1];
135
+ t = op;
136
+ break;
137
+ }
138
+ if (t && _.label < t[2]) {
139
+ _.label = t[2];
140
+ _.ops.push(op);
141
+ break;
142
+ }
143
+ if (t[2]) _.ops.pop();
144
+ _.trys.pop();
145
+ continue;
146
+ }
147
+ op = body.call(thisArg, _);
148
+ } catch (e) {
149
+ op = [
150
+ 6,
151
+ e
152
+ ];
153
+ y = 0;
154
+ } finally{
155
+ f = t = 0;
156
+ }
157
+ if (op[0] & 5) throw op[1];
158
+ return {
159
+ value: op[0] ? op[1] : void 0,
160
+ done: true
161
+ };
162
+ }
163
+ }
164
+ import { ChatPromptTemplate, HumanMessagePromptTemplate, SystemMessagePromptTemplate } from '@langchain/core/prompts';
165
+ import { AgentExecutor, createStructuredChatAgent } from 'langchain/agents';
166
+ import { z } from 'zod/v4';
167
+ import { AIResponseParser } from '../utils/ai-response-parser.js';
168
+ // Schema for agent responses
169
+ var AgentResponseSchema = z.object({
170
+ message: z.string().optional(),
171
+ reason: z.string().optional(),
172
+ shouldRespond: z["boolean"]()
173
+ });
174
+ // LangChain-specific framework rules (internal to this adapter)
175
+ var LANGCHAIN_FRAMEWORK_RULES = '\n<AGENT_FRAMEWORK>\nYou are a chat agent piloted by the LangChain framework.\n\nYou have access to the following tools: {tools}\nTool names: {tool_names}\nAgent scratchpad: {agent_scratchpad}\n\nWhen you want to provide your final response, you MUST format it exactly like this:\n\n```json\n{{"action": "Final Answer", "action_input": {{"shouldRespond": false, "reason": "<your reason>"}}}}\n```\n\nOR \n\n```json\n{{"action": "Final Answer", "action_input": {{"shouldRespond": true, "message": "<your response message>"}}}}\n```\n\n"shouldRespond" set to true means the message will be sent to the user.\n"shouldRespond" set to false means the message will not be sent to the user.\n\nALWAYS use this exact format with markdown code blocks and the action/action_input structure.\n</AGENT_FRAMEWORK>';
176
+ /**
177
+ * Chat agent adapter that provides structured chat capabilities with optional responses
178
+ */ export var ChatAgentAdapter = /*#__PURE__*/ function() {
179
+ "use strict";
180
+ function ChatAgentAdapter(name, systemPrompt, options) {
181
+ _class_call_check(this, ChatAgentAdapter);
182
+ _define_property(this, "executorPromise", void 0);
183
+ _define_property(this, "logger", void 0);
184
+ _define_property(this, "name", void 0);
185
+ _define_property(this, "responseParser", void 0);
186
+ this.name = name;
187
+ this.logger = options.logger;
188
+ this.responseParser = new AIResponseParser(AgentResponseSchema);
189
+ this.executorPromise = this.createExecutor(systemPrompt, options);
190
+ }
191
+ _create_class(ChatAgentAdapter, [
192
+ {
193
+ key: "run",
194
+ value: function run(userPrompt) {
195
+ return _async_to_generator(function() {
196
+ var _this_logger, executor, input, result, response, error, _this_logger1;
197
+ return _ts_generator(this, function(_state) {
198
+ switch(_state.label){
199
+ case 0:
200
+ _state.trys.push([
201
+ 0,
202
+ 3,
203
+ ,
204
+ 4
205
+ ]);
206
+ return [
207
+ 4,
208
+ this.executorPromise
209
+ ];
210
+ case 1:
211
+ executor = _state.sent();
212
+ input = this.resolveUserInput(userPrompt);
213
+ return [
214
+ 4,
215
+ executor.invoke({
216
+ input: input
217
+ })
218
+ ];
219
+ case 2:
220
+ result = _state.sent();
221
+ (_this_logger = this.logger) === null || _this_logger === void 0 ? void 0 : _this_logger.debug('Agent execution result', {
222
+ agentName: this.name,
223
+ hasOutput: 'output' in result,
224
+ hasUserPrompt: !!userPrompt,
225
+ outputType: _type_of(result.output)
226
+ });
227
+ if (!result || typeof result.output === 'undefined') {
228
+ throw new Error('Agent returned invalid result structure');
229
+ }
230
+ response = this.parseAgentResponse(result.output);
231
+ return [
232
+ 2,
233
+ this.handleResponse(response)
234
+ ];
235
+ case 3:
236
+ error = _state.sent();
237
+ (_this_logger1 = this.logger) === null || _this_logger1 === void 0 ? void 0 : _this_logger1.error('Error running chat agent', {
238
+ agentName: this.name,
239
+ error: _instanceof(error, Error) ? error.message : 'Unknown error',
240
+ userPrompt: userPrompt ? 'Prompt object' : 'none'
241
+ });
242
+ return [
243
+ 2,
244
+ null
245
+ ];
246
+ case 4:
247
+ return [
248
+ 2
249
+ ];
250
+ }
251
+ });
252
+ }).call(this);
253
+ }
254
+ },
255
+ {
256
+ key: "createExecutor",
257
+ value: function createExecutor(systemPrompt, options) {
258
+ return _async_to_generator(function() {
259
+ var model, dynamicTools, systemPromptText, systemTemplate, humanTemplate, prompt, agent;
260
+ return _ts_generator(this, function(_state) {
261
+ switch(_state.label){
262
+ case 0:
263
+ model = options.model.getModel();
264
+ // Convert Tool instances to DynamicTool instances
265
+ dynamicTools = options.tools.map(function(tool) {
266
+ return tool.getDynamicTool();
267
+ });
268
+ // Combine LangChain framework rules with user-provided system prompts
269
+ systemPromptText = "".concat(LANGCHAIN_FRAMEWORK_RULES, "\n\n").concat(systemPrompt.generate());
270
+ systemTemplate = SystemMessagePromptTemplate.fromTemplate(systemPromptText);
271
+ humanTemplate = HumanMessagePromptTemplate.fromTemplate('{input}');
272
+ prompt = ChatPromptTemplate.fromMessages([
273
+ systemTemplate,
274
+ humanTemplate
275
+ ]);
276
+ return [
277
+ 4,
278
+ createStructuredChatAgent({
279
+ llm: model,
280
+ prompt: prompt,
281
+ tools: dynamicTools
282
+ })
283
+ ];
284
+ case 1:
285
+ agent = _state.sent();
286
+ return [
287
+ 2,
288
+ AgentExecutor.fromAgentAndTools({
289
+ agent: agent,
290
+ tools: dynamicTools
291
+ })
292
+ ];
293
+ }
294
+ });
295
+ })();
296
+ }
297
+ },
298
+ {
299
+ key: "extractActionInput",
300
+ value: function extractActionInput(output) {
301
+ if ((typeof output === "undefined" ? "undefined" : _type_of(output)) === 'object' && output !== null) {
302
+ return JSON.stringify(output);
303
+ }
304
+ if (typeof output !== 'string') {
305
+ return String(output);
306
+ }
307
+ // Check for LangChain's action/action_input format first
308
+ var codeBlockMatch = output.match(/```(?:json)?\s*([\s\S]*?)```/i);
309
+ if (codeBlockMatch) {
310
+ var content = codeBlockMatch[1].trim();
311
+ try {
312
+ var parsed = JSON.parse(content);
313
+ if (parsed.action === 'Final Answer' && parsed.action_input) {
314
+ return JSON.stringify(parsed.action_input);
315
+ }
316
+ } catch (e) {
317
+ // Fall through to return original content
318
+ }
319
+ return content;
320
+ }
321
+ // Fallback: Look for "Final Answer:" pattern
322
+ if (output.includes('Final Answer:')) {
323
+ var actionInputMatch = output.match(/Final Answer:\s*([\s\S]*?)$/i);
324
+ if (actionInputMatch) {
325
+ return actionInputMatch[1].trim();
326
+ }
327
+ }
328
+ return output;
329
+ }
330
+ },
331
+ {
332
+ key: "handleResponse",
333
+ value: function handleResponse(response) {
334
+ var _this_logger;
335
+ if (response.shouldRespond && response.message) {
336
+ var _this_logger1;
337
+ (_this_logger1 = this.logger) === null || _this_logger1 === void 0 ? void 0 : _this_logger1.info('Agent responding with message', {
338
+ agentName: this.name
339
+ });
340
+ return response.message;
341
+ }
342
+ if (!response.shouldRespond) {
343
+ var _this_logger2;
344
+ (_this_logger2 = this.logger) === null || _this_logger2 === void 0 ? void 0 : _this_logger2.info('Agent chose not to respond', {
345
+ agentName: this.name,
346
+ reason: response.reason
347
+ });
348
+ return null;
349
+ }
350
+ (_this_logger = this.logger) === null || _this_logger === void 0 ? void 0 : _this_logger.error('Invalid agent response state', {
351
+ agentName: this.name,
352
+ response: response
353
+ });
354
+ return null;
355
+ }
356
+ },
357
+ {
358
+ key: "parseAgentResponse",
359
+ value: function parseAgentResponse(output) {
360
+ try {
361
+ // Handle LangChain's action/action_input format
362
+ var processedOutput = this.extractActionInput(output);
363
+ return this.responseParser.parse(processedOutput);
364
+ } catch (error) {
365
+ var _this_logger;
366
+ (_this_logger = this.logger) === null || _this_logger === void 0 ? void 0 : _this_logger.error('Failed to parse agent response', {
367
+ agentName: this.name,
368
+ error: _instanceof(error, Error) ? error.message : 'Unknown error',
369
+ rawOutput: output
370
+ });
371
+ throw new Error('Invalid agent response format');
372
+ }
373
+ }
374
+ },
375
+ {
376
+ key: "resolveUserInput",
377
+ value: function resolveUserInput(userPrompt) {
378
+ if (!userPrompt) {
379
+ return 'Please analyze the current situation and respond if appropriate.';
380
+ }
381
+ return userPrompt.generate();
382
+ }
383
+ }
384
+ ]);
385
+ return ChatAgentAdapter;
386
+ }();
387
+
388
+ //# sourceMappingURL=chat-agent.adapter.js.map