@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.
- package/LICENSE +21 -0
- package/README.md +229 -0
- package/dist/adapters/agents/chat-agent.adapter.d.ts +35 -0
- package/dist/adapters/agents/chat-agent.adapter.js +388 -0
- package/dist/adapters/agents/chat-agent.adapter.js.map +1 -0
- package/dist/adapters/models/openrouter-model.adapter.d.ts +28 -0
- package/dist/adapters/models/openrouter-model.adapter.js +80 -0
- package/dist/adapters/models/openrouter-model.adapter.js.map +1 -0
- package/dist/adapters/prompts/__tests__/__snapshots__/presets.test.ts.snap +150 -0
- package/dist/adapters/prompts/__tests__/presets.test.d.ts +1 -0
- package/dist/adapters/prompts/__tests__/presets.test.js +31 -0
- package/dist/adapters/prompts/__tests__/presets.test.js.map +1 -0
- package/dist/adapters/prompts/library/categories/agent-logic.d.ts +8 -0
- package/dist/adapters/prompts/library/categories/agent-logic.js +9 -0
- package/dist/adapters/prompts/library/categories/agent-logic.js.map +1 -0
- package/dist/adapters/prompts/library/categories/agent-skills.d.ts +8 -0
- package/dist/adapters/prompts/library/categories/agent-skills.js +9 -0
- package/dist/adapters/prompts/library/categories/agent-skills.js.map +1 -0
- package/dist/adapters/prompts/library/categories/directives.d.ts +9 -0
- package/dist/adapters/prompts/library/categories/directives.js +10 -0
- package/dist/adapters/prompts/library/categories/directives.js.map +1 -0
- package/dist/adapters/prompts/library/categories/domain.d.ts +11 -0
- package/dist/adapters/prompts/library/categories/domain.js +12 -0
- package/dist/adapters/prompts/library/categories/domain.js.map +1 -0
- package/dist/adapters/prompts/library/categories/format.d.ts +9 -0
- package/dist/adapters/prompts/library/categories/format.js +10 -0
- package/dist/adapters/prompts/library/categories/format.js.map +1 -0
- package/dist/adapters/prompts/library/categories/language.d.ts +11 -0
- package/dist/adapters/prompts/library/categories/language.js +12 -0
- package/dist/adapters/prompts/library/categories/language.js.map +1 -0
- package/dist/adapters/prompts/library/categories/persona.d.ts +11 -0
- package/dist/adapters/prompts/library/categories/persona.js +12 -0
- package/dist/adapters/prompts/library/categories/persona.js.map +1 -0
- package/dist/adapters/prompts/library/categories/tone.d.ts +9 -0
- package/dist/adapters/prompts/library/categories/tone.js +10 -0
- package/dist/adapters/prompts/library/categories/tone.js.map +1 -0
- package/dist/adapters/prompts/library/categories/verbosity.d.ts +8 -0
- package/dist/adapters/prompts/library/categories/verbosity.js +9 -0
- package/dist/adapters/prompts/library/categories/verbosity.js.map +1 -0
- package/dist/adapters/prompts/library/index.d.ts +66 -0
- package/dist/adapters/prompts/library/index.js +28 -0
- package/dist/adapters/prompts/library/index.js.map +1 -0
- package/dist/adapters/prompts/library/presets.d.ts +17 -0
- package/dist/adapters/prompts/library/presets.js +51 -0
- package/dist/adapters/prompts/library/presets.js.map +1 -0
- package/dist/adapters/prompts/system-prompt.adapter.d.ts +9 -0
- package/dist/adapters/prompts/system-prompt.adapter.js +57 -0
- package/dist/adapters/prompts/system-prompt.adapter.js.map +1 -0
- package/dist/adapters/prompts/user-prompt.adapter.d.ts +9 -0
- package/dist/adapters/prompts/user-prompt.adapter.js +57 -0
- package/dist/adapters/prompts/user-prompt.adapter.js.map +1 -0
- package/dist/adapters/tools/safe-tool.adapter.d.ts +27 -0
- package/dist/adapters/tools/safe-tool.adapter.js +283 -0
- package/dist/adapters/tools/safe-tool.adapter.js.map +1 -0
- package/dist/adapters/utils/__tests__/ai-response-parser.test.d.ts +1 -0
- package/dist/adapters/utils/__tests__/ai-response-parser.test.js +249 -0
- package/dist/adapters/utils/__tests__/ai-response-parser.test.js.map +1 -0
- package/dist/adapters/utils/ai-response-parser-error.d.ts +8 -0
- package/dist/adapters/utils/ai-response-parser-error.js +136 -0
- package/dist/adapters/utils/ai-response-parser-error.js.map +1 -0
- package/dist/adapters/utils/ai-response-parser.d.ts +56 -0
- package/dist/adapters/utils/ai-response-parser.js +334 -0
- package/dist/adapters/utils/ai-response-parser.js.map +1 -0
- package/dist/index.cjs +1461 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/ports/agent.port.d.ts +11 -0
- package/dist/ports/agent.port.js +5 -0
- package/dist/ports/agent.port.js.map +1 -0
- package/dist/ports/model.port.d.ts +10 -0
- package/dist/ports/model.port.js +5 -0
- package/dist/ports/model.port.js.map +1 -0
- package/dist/ports/prompt.port.d.ts +9 -0
- package/dist/ports/prompt.port.js +5 -0
- package/dist/ports/prompt.port.js.map +1 -0
- package/dist/ports/tool.port.d.ts +11 -0
- package/dist/ports/tool.port.js +5 -0
- package/dist/ports/tool.port.js.map +1 -0
- 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
|
+
[](https://www.npmjs.com/package/@jterrazz/intelligence)
|
|
6
|
+
[](./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
|