@multiplayer-app/ai-agent-node 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +45 -0
- package/README.md +611 -0
- package/config.example.json +73 -0
- package/dist/config.d.ts +35 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +44 -0
- package/dist/config.js.map +1 -0
- package/dist/helpers/AIHelper.d.ts +23 -0
- package/dist/helpers/AIHelper.d.ts.map +1 -0
- package/dist/helpers/AIHelper.js +326 -0
- package/dist/helpers/AIHelper.js.map +1 -0
- package/dist/helpers/AIHelper.test.d.ts +2 -0
- package/dist/helpers/AIHelper.test.d.ts.map +1 -0
- package/dist/helpers/AIHelper.test.js +332 -0
- package/dist/helpers/AIHelper.test.js.map +1 -0
- package/dist/helpers/ConfigHelper.d.ts +20 -0
- package/dist/helpers/ConfigHelper.d.ts.map +1 -0
- package/dist/helpers/ConfigHelper.js +118 -0
- package/dist/helpers/ConfigHelper.js.map +1 -0
- package/dist/helpers/ContextLimiter.d.ts +82 -0
- package/dist/helpers/ContextLimiter.d.ts.map +1 -0
- package/dist/helpers/ContextLimiter.js +165 -0
- package/dist/helpers/ContextLimiter.js.map +1 -0
- package/dist/helpers/FileHelper.d.ts +31 -0
- package/dist/helpers/FileHelper.d.ts.map +1 -0
- package/dist/helpers/FileHelper.js +175 -0
- package/dist/helpers/FileHelper.js.map +1 -0
- package/dist/helpers/SetupHelper.d.ts +5 -0
- package/dist/helpers/SetupHelper.d.ts.map +1 -0
- package/dist/helpers/SetupHelper.js +32 -0
- package/dist/helpers/SetupHelper.js.map +1 -0
- package/dist/helpers/index.d.ts +6 -0
- package/dist/helpers/index.d.ts.map +1 -0
- package/dist/helpers/index.js +6 -0
- package/dist/helpers/index.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/libs/index.d.ts +4 -0
- package/dist/libs/index.d.ts.map +1 -0
- package/dist/libs/index.js +4 -0
- package/dist/libs/index.js.map +1 -0
- package/dist/libs/kafka/config.d.ts +5 -0
- package/dist/libs/kafka/config.d.ts.map +1 -0
- package/dist/libs/kafka/config.js +5 -0
- package/dist/libs/kafka/config.js.map +1 -0
- package/dist/libs/kafka/consumer.d.ts +16 -0
- package/dist/libs/kafka/consumer.d.ts.map +1 -0
- package/dist/libs/kafka/consumer.js +126 -0
- package/dist/libs/kafka/consumer.js.map +1 -0
- package/dist/libs/kafka/index.d.ts +3 -0
- package/dist/libs/kafka/index.d.ts.map +1 -0
- package/dist/libs/kafka/index.js +3 -0
- package/dist/libs/kafka/index.js.map +1 -0
- package/dist/libs/kafka/kafka.d.ts +3 -0
- package/dist/libs/kafka/kafka.d.ts.map +1 -0
- package/dist/libs/kafka/kafka.js +24 -0
- package/dist/libs/kafka/kafka.js.map +1 -0
- package/dist/libs/kafka/producer.d.ts +11 -0
- package/dist/libs/kafka/producer.d.ts.map +1 -0
- package/dist/libs/kafka/producer.js +44 -0
- package/dist/libs/kafka/producer.js.map +1 -0
- package/dist/libs/logger/config.d.ts +5 -0
- package/dist/libs/logger/config.d.ts.map +1 -0
- package/dist/libs/logger/config.js +6 -0
- package/dist/libs/logger/config.js.map +1 -0
- package/dist/libs/logger/index.d.ts +10 -0
- package/dist/libs/logger/index.d.ts.map +1 -0
- package/dist/libs/logger/index.js +20 -0
- package/dist/libs/logger/index.js.map +1 -0
- package/dist/libs/logger/kafkajs-logger-creator.d.ts +12 -0
- package/dist/libs/logger/kafkajs-logger-creator.d.ts.map +1 -0
- package/dist/libs/logger/kafkajs-logger-creator.js +29 -0
- package/dist/libs/logger/kafkajs-logger-creator.js.map +1 -0
- package/dist/libs/logger/logger.d.ts +42 -0
- package/dist/libs/logger/logger.d.ts.map +1 -0
- package/dist/libs/logger/logger.js +44 -0
- package/dist/libs/logger/logger.js.map +1 -0
- package/dist/libs/s3/config.d.ts +7 -0
- package/dist/libs/s3/config.d.ts.map +1 -0
- package/dist/libs/s3/config.js +7 -0
- package/dist/libs/s3/config.js.map +1 -0
- package/dist/libs/s3/index.d.ts +4 -0
- package/dist/libs/s3/index.d.ts.map +1 -0
- package/dist/libs/s3/index.js +4 -0
- package/dist/libs/s3/index.js.map +1 -0
- package/dist/libs/s3/s3.lib.d.ts +25 -0
- package/dist/libs/s3/s3.lib.d.ts.map +1 -0
- package/dist/libs/s3/s3.lib.js +202 -0
- package/dist/libs/s3/s3.lib.js.map +1 -0
- package/dist/processors/ChatProcessor.d.ts +66 -0
- package/dist/processors/ChatProcessor.d.ts.map +1 -0
- package/dist/processors/ChatProcessor.js +610 -0
- package/dist/processors/ChatProcessor.js.map +1 -0
- package/dist/processors/ModelsProcessor.d.ts +11 -0
- package/dist/processors/ModelsProcessor.d.ts.map +1 -0
- package/dist/processors/ModelsProcessor.js +30 -0
- package/dist/processors/ModelsProcessor.js.map +1 -0
- package/dist/processors/index.d.ts +3 -0
- package/dist/processors/index.d.ts.map +1 -0
- package/dist/processors/index.js +3 -0
- package/dist/processors/index.js.map +1 -0
- package/dist/services/AIService.d.ts +48 -0
- package/dist/services/AIService.d.ts.map +1 -0
- package/dist/services/AIService.js +196 -0
- package/dist/services/AIService.js.map +1 -0
- package/dist/services/InternalEventsHandler.d.ts +21 -0
- package/dist/services/InternalEventsHandler.d.ts.map +1 -0
- package/dist/services/InternalEventsHandler.js +56 -0
- package/dist/services/InternalEventsHandler.js.map +1 -0
- package/dist/services/KafkaService.d.ts +35 -0
- package/dist/services/KafkaService.d.ts.map +1 -0
- package/dist/services/KafkaService.js +120 -0
- package/dist/services/KafkaService.js.map +1 -0
- package/dist/services/ModelFetcher.d.ts +54 -0
- package/dist/services/ModelFetcher.d.ts.map +1 -0
- package/dist/services/ModelFetcher.js +247 -0
- package/dist/services/ModelFetcher.js.map +1 -0
- package/dist/services/RedisService.d.ts +90 -0
- package/dist/services/RedisService.d.ts.map +1 -0
- package/dist/services/RedisService.js +236 -0
- package/dist/services/RedisService.js.map +1 -0
- package/dist/services/SocketService.d.ts +39 -0
- package/dist/services/SocketService.d.ts.map +1 -0
- package/dist/services/SocketService.js +128 -0
- package/dist/services/SocketService.js.map +1 -0
- package/dist/services/index.d.ts +7 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +7 -0
- package/dist/services/index.js.map +1 -0
- package/dist/store/AgentStore.d.ts +48 -0
- package/dist/store/AgentStore.d.ts.map +1 -0
- package/dist/store/AgentStore.js +98 -0
- package/dist/store/AgentStore.js.map +1 -0
- package/dist/store/ArtifactStore.d.ts +13 -0
- package/dist/store/ArtifactStore.d.ts.map +1 -0
- package/dist/store/ArtifactStore.js +27 -0
- package/dist/store/ArtifactStore.js.map +1 -0
- package/dist/store/ConfigStore.d.ts +89 -0
- package/dist/store/ConfigStore.d.ts.map +1 -0
- package/dist/store/ConfigStore.js +214 -0
- package/dist/store/ConfigStore.js.map +1 -0
- package/dist/store/ConfigStore.test.d.ts +2 -0
- package/dist/store/ConfigStore.test.d.ts.map +1 -0
- package/dist/store/ConfigStore.test.js +259 -0
- package/dist/store/ConfigStore.test.js.map +1 -0
- package/dist/store/ModelStore.d.ts +44 -0
- package/dist/store/ModelStore.d.ts.map +1 -0
- package/dist/store/ModelStore.js +81 -0
- package/dist/store/ModelStore.js.map +1 -0
- package/dist/store/ModelStore.test.d.ts +2 -0
- package/dist/store/ModelStore.test.d.ts.map +1 -0
- package/dist/store/ModelStore.test.js +390 -0
- package/dist/store/ModelStore.test.js.map +1 -0
- package/dist/store/index.d.ts +5 -0
- package/dist/store/index.d.ts.map +1 -0
- package/dist/store/index.js +5 -0
- package/dist/store/index.js.map +1 -0
- package/dist/tools/generateChartTool.d.ts +24 -0
- package/dist/tools/generateChartTool.d.ts.map +1 -0
- package/dist/tools/generateChartTool.js +124 -0
- package/dist/tools/generateChartTool.js.map +1 -0
- package/dist/tools/proposeFormValuesTool.d.ts +35 -0
- package/dist/tools/proposeFormValuesTool.d.ts.map +1 -0
- package/dist/tools/proposeFormValuesTool.js +56 -0
- package/dist/tools/proposeFormValuesTool.js.map +1 -0
- package/package.json +71 -0
- package/src/config.ts +46 -0
- package/src/helpers/AIHelper.test.ts +375 -0
- package/src/helpers/AIHelper.ts +353 -0
- package/src/helpers/ConfigHelper.ts +130 -0
- package/src/helpers/ContextLimiter.ts +228 -0
- package/src/helpers/FileHelper.ts +197 -0
- package/src/helpers/SetupHelper.ts +35 -0
- package/src/helpers/index.ts +5 -0
- package/src/index.ts +18 -0
- package/src/libs/index.ts +3 -0
- package/src/libs/kafka/config.ts +4 -0
- package/src/libs/kafka/consumer.ts +161 -0
- package/src/libs/kafka/index.ts +2 -0
- package/src/libs/kafka/kafka.ts +27 -0
- package/src/libs/kafka/producer.ts +48 -0
- package/src/libs/logger/config.ts +4 -0
- package/src/libs/logger/index.ts +21 -0
- package/src/libs/logger/kafkajs-logger-creator.ts +28 -0
- package/src/libs/logger/logger.ts +60 -0
- package/src/libs/s3/config.ts +7 -0
- package/src/libs/s3/index.ts +3 -0
- package/src/libs/s3/s3.lib.ts +284 -0
- package/src/processors/ChatProcessor.ts +713 -0
- package/src/processors/ModelsProcessor.ts +34 -0
- package/src/processors/index.ts +2 -0
- package/src/services/AIService.ts +241 -0
- package/src/services/InternalEventsHandler.ts +61 -0
- package/src/services/KafkaService.ts +142 -0
- package/src/services/ModelFetcher.ts +286 -0
- package/src/services/RedisService.ts +285 -0
- package/src/services/SocketService.ts +153 -0
- package/src/services/index.ts +6 -0
- package/src/store/AgentStore.ts +138 -0
- package/src/store/ArtifactStore.ts +29 -0
- package/src/store/ConfigStore.test.ts +314 -0
- package/src/store/ConfigStore.ts +239 -0
- package/src/store/ModelStore.test.ts +473 -0
- package/src/store/ModelStore.ts +93 -0
- package/src/store/index.ts +4 -0
- package/src/tools/generateChartTool.ts +131 -0
- package/src/tools/proposeFormValuesTool.ts +67 -0
- package/tsconfig.json +24 -0
package/.env.example
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# AI Provider API Keys
|
|
3
|
+
# =============================================================================
|
|
4
|
+
# At least one provider API key is recommended to fetch models on startup
|
|
5
|
+
# The service will automatically detect available providers and fetch their models
|
|
6
|
+
# You can configure multiple providers simultaneously
|
|
7
|
+
|
|
8
|
+
# OpenAI API Key
|
|
9
|
+
# Get your key from: https://platform.openai.com/api-keys
|
|
10
|
+
# Required for: GPT-4, GPT-4o, GPT-3.5, O1 models
|
|
11
|
+
OPENAI_API_KEY=sk-your-openai-api-key-here
|
|
12
|
+
|
|
13
|
+
# Anthropic API Key
|
|
14
|
+
# Get your key from: https://console.anthropic.com/settings/keys
|
|
15
|
+
# Required for: Claude models (Claude 3.5 Sonnet, Claude 3 Opus, Claude 3 Haiku, etc.)
|
|
16
|
+
ANTHROPIC_API_KEY=sk-ant-your-anthropic-api-key-here
|
|
17
|
+
|
|
18
|
+
# Google Generative AI API Key
|
|
19
|
+
# Get your key from: https://makersuite.google.com/app/apikey
|
|
20
|
+
# Required for: Gemini models (Gemini Pro, Gemini Flash, Gemini 2.0, etc.)
|
|
21
|
+
GOOGLE_GENERATIVE_AI_API_KEY=your-google-api-key-here
|
|
22
|
+
|
|
23
|
+
# OpenRouter API Key (optional)
|
|
24
|
+
# Get your key from: https://openrouter.ai/keys
|
|
25
|
+
# OpenRouter provides access to multiple AI models through a single API
|
|
26
|
+
# Useful for accessing models from multiple providers without separate keys
|
|
27
|
+
OPENROUTER_API_KEY=sk-or-your-openrouter-api-key-here
|
|
28
|
+
|
|
29
|
+
# =============================================================================
|
|
30
|
+
# Notes
|
|
31
|
+
# =============================================================================
|
|
32
|
+
# - Models are automatically fetched on server startup from providers
|
|
33
|
+
# for which you have API keys configured
|
|
34
|
+
# - Models are cached in memory after initial fetch
|
|
35
|
+
# - You can use multiple providers simultaneously - the service will
|
|
36
|
+
# aggregate models from all configured providers
|
|
37
|
+
|
|
38
|
+
# DEFAULT_MODEL=anthropic/claude-3.5-sonnet
|
|
39
|
+
|
|
40
|
+
# S3 settings
|
|
41
|
+
|
|
42
|
+
# AWS_ACCESS_KEY_ID=
|
|
43
|
+
# AWS_SECRET_ACCESS_KEY=
|
|
44
|
+
# AWS_REGION=
|
|
45
|
+
# S3_HOST=
|
package/README.md
ADDED
|
@@ -0,0 +1,611 @@
|
|
|
1
|
+
# @multiplayer-app/ai-agent-node
|
|
2
|
+
|
|
3
|
+
A Node.js library for building AI agent backends with support for multi-provider AI models, real-time communication, distributed processing, and chat management.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Multi-Provider AI Support**: OpenAI, Anthropic, Google, and OpenRouter
|
|
8
|
+
- **Streaming Chat Processing**: Real-time message streaming with tool calling support
|
|
9
|
+
- **Distributed Architecture**: Kafka and Redis integration for scalable agent processing
|
|
10
|
+
- **Real-time Communication**: Socket.io integration for live updates
|
|
11
|
+
- **Agent Process Management**: Lifecycle management with event-driven architecture
|
|
12
|
+
- **Artifact Storage**: S3 integration for storing generated artifacts
|
|
13
|
+
- **Context Management**: Intelligent context limiting and attachment handling
|
|
14
|
+
- **Built-in Tools**: Form value proposal
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @multiplayer-app/ai-agent-node ai
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Prerequisites
|
|
23
|
+
|
|
24
|
+
- Node.js >= 18
|
|
25
|
+
- npm >= 8
|
|
26
|
+
|
|
27
|
+
## Infrastructure Setup
|
|
28
|
+
|
|
29
|
+
The library requires several infrastructure services to function properly. These services can be started using Docker Compose or configured separately.
|
|
30
|
+
|
|
31
|
+
### Starting Services
|
|
32
|
+
|
|
33
|
+
Use the `startServices()` function to initialize all required services:
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import { startServices } from '@multiplayer-app/ai-agent-node';
|
|
37
|
+
import { MongoAgentChatRepository, MongoAgentMessageRepository } from '@multiplayer-app/ai-agent-mongo';
|
|
38
|
+
|
|
39
|
+
// Initialize repositories (example with MongoDB)
|
|
40
|
+
const chatRepository = new MongoAgentChatRepository();
|
|
41
|
+
const messageRepository = new MongoAgentMessageRepository();
|
|
42
|
+
|
|
43
|
+
// Start all services
|
|
44
|
+
await startServices(chatRepository, messageRepository);
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
This function initializes:
|
|
48
|
+
- **Kafka Service**: Connects to Kafka brokers and subscribes to topics for chat title generation and background processing
|
|
49
|
+
- **Agent Store**: Initializes the in-memory agent process store for managing active agent conversations
|
|
50
|
+
- **Model Store**: Fetches and caches available AI models from configured providers
|
|
51
|
+
- **S3 Bucket**: Ensures the configured S3 bucket exists for artifact storage
|
|
52
|
+
|
|
53
|
+
### Stopping Services
|
|
54
|
+
|
|
55
|
+
Use the `stopServices()` function to gracefully shut down connections:
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
import { stopServices } from '@multiplayer-app/ai-agent-node';
|
|
59
|
+
|
|
60
|
+
// Stop all services
|
|
61
|
+
await stopServices();
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
This disconnects:
|
|
65
|
+
- Redis connections (including pub/sub clients)
|
|
66
|
+
- Kafka consumer and producer connections
|
|
67
|
+
|
|
68
|
+
### Infrastructure Services
|
|
69
|
+
|
|
70
|
+
#### Kafka
|
|
71
|
+
|
|
72
|
+
**Purpose**: Kafka is used for asynchronous, distributed processing of agent tasks:
|
|
73
|
+
- **Chat Title Generation**: Generates chat titles asynchronously after the first message to avoid blocking the main request
|
|
74
|
+
- **Background Processing**: Handles long-running agent tasks that don't need immediate response
|
|
75
|
+
- **Scalability**: Allows multiple service instances to process tasks in parallel
|
|
76
|
+
|
|
77
|
+
**Topics**:
|
|
78
|
+
- `chat-title-generation` (default): Processes chat title generation requests
|
|
79
|
+
- `background-chat-processing` (default): Handles background agent processing tasks
|
|
80
|
+
|
|
81
|
+
#### Redis
|
|
82
|
+
|
|
83
|
+
**Purpose**: Redis provides:
|
|
84
|
+
- **Pub/Sub for Socket.IO**: Enables real-time message broadcasting across multiple service instances
|
|
85
|
+
- **Agent State Management**: Stores temporary agent process state and event listeners
|
|
86
|
+
- **Caching**: Can be used for caching model information and other frequently accessed data
|
|
87
|
+
|
|
88
|
+
**Connection**: Redis is used for both direct key-value operations and pub/sub channels for Socket.IO adapter.
|
|
89
|
+
|
|
90
|
+
### Docker Compose Setup
|
|
91
|
+
|
|
92
|
+
The project includes a `docker-compose.yml` file that sets up all required services:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
# Start all services
|
|
96
|
+
docker-compose up -d
|
|
97
|
+
|
|
98
|
+
# Stop all services
|
|
99
|
+
docker-compose down
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
This starts:
|
|
103
|
+
- **MongoDB** (port 27017): Database for chat and message storage
|
|
104
|
+
- **Redis** (port 6379): Pub/sub and caching
|
|
105
|
+
- **Zookeeper** (port 2181): Required for Kafka
|
|
106
|
+
- **Kafka** (port 9092): Message broker
|
|
107
|
+
- **MinIO** (ports 9000, 9001): S3-compatible object storage for artifacts
|
|
108
|
+
|
|
109
|
+
## Environment Variables
|
|
110
|
+
|
|
111
|
+
Configure the library using the following environment variables:
|
|
112
|
+
|
|
113
|
+
### Redis Configuration
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
# Redis connection URL (alternative to host/port)
|
|
117
|
+
REDIS_URL=redis://localhost:6379
|
|
118
|
+
|
|
119
|
+
# Or use individual settings
|
|
120
|
+
REDIS_HOST=localhost
|
|
121
|
+
REDIS_PORT=6379
|
|
122
|
+
REDIS_PASSWORD=your-password # Optional
|
|
123
|
+
REDIS_DATABASE=0 # Optional, defaults to 0
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### AI Provider API Keys
|
|
127
|
+
|
|
128
|
+
At least one provider API key is required:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
# OpenAI
|
|
132
|
+
OPENAI_API_KEY=sk-...
|
|
133
|
+
|
|
134
|
+
# Anthropic
|
|
135
|
+
ANTHROPIC_API_KEY=sk-ant-...
|
|
136
|
+
|
|
137
|
+
# Google
|
|
138
|
+
GOOGLE_GENERATIVE_AI_API_KEY=...
|
|
139
|
+
|
|
140
|
+
# OpenRouter (supports multiple providers)
|
|
141
|
+
OPENROUTER_API_KEY=sk-or-...
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### AI Configuration
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
# Maximum number of messages to include in context (default: 10)
|
|
148
|
+
MAX_CONTEXT_MESSAGES=10
|
|
149
|
+
|
|
150
|
+
# Default model to use if none specified
|
|
151
|
+
DEFAULT_MODEL=openai/gpt-4o
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### S3 Configuration
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
# S3 bucket name for storing attachments and artifacts
|
|
158
|
+
S3_ATTACHMENTS_BUCKET=ai-agent-attachments
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Kafka Configuration
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
# Kafka consumer group ID
|
|
165
|
+
KAFKA_GROUP_ID=ai-agent-node
|
|
166
|
+
|
|
167
|
+
# Kafka topics
|
|
168
|
+
KAFKA_CHAT_TITLE_GENERATION_TOPIC=chat-title-generation
|
|
169
|
+
KAFKA_BACKGROUND_CHAT_PROCESSING_TOPIC=background-chat-processing
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### File Processing (Optional)
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
# Enable text extraction from documents (default: true)
|
|
176
|
+
ENABLE_TEXT_EXTRACTION=true
|
|
177
|
+
|
|
178
|
+
# Maximum size for extracted text in bytes (default: 51200)
|
|
179
|
+
MAX_EXTRACTED_TEXT_SIZE=51200
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Usage Examples
|
|
183
|
+
|
|
184
|
+
### Basic Chat Processing
|
|
185
|
+
|
|
186
|
+
The `ChatProcessor` class handles all chat operations. The most common use case is creating a streaming message:
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
import { ChatProcessor } from '@multiplayer-app/ai-agent-node';
|
|
190
|
+
import { MongoAgentChatRepository, MongoAgentMessageRepository } from '@multiplayer-app/ai-agent-mongo';
|
|
191
|
+
import { ArtifactStore } from '@multiplayer-app/ai-agent-node';
|
|
192
|
+
|
|
193
|
+
// Initialize repositories
|
|
194
|
+
const chatRepository = new MongoAgentChatRepository();
|
|
195
|
+
const messageRepository = new MongoAgentMessageRepository();
|
|
196
|
+
const artifactStore = new ArtifactStore();
|
|
197
|
+
|
|
198
|
+
// Create processor
|
|
199
|
+
const chatProcessor = new ChatProcessor(
|
|
200
|
+
chatRepository,
|
|
201
|
+
messageRepository,
|
|
202
|
+
artifactStore
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
// Create a streaming message
|
|
206
|
+
const stream = await chatProcessor.createMessageStream({
|
|
207
|
+
content: 'Hello, how can you help me?',
|
|
208
|
+
contextKey: 'support',
|
|
209
|
+
userId: 'user-123'
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
// Stream is a Node.js PassThrough stream that emits SSE-formatted events
|
|
213
|
+
stream.on('data', (chunk) => {
|
|
214
|
+
// Process SSE chunk: "data: {...}\n\n"
|
|
215
|
+
const data = chunk.toString();
|
|
216
|
+
// Parse and handle stream chunks
|
|
217
|
+
});
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Stream Chunk Format
|
|
221
|
+
|
|
222
|
+
The stream emits Server-Sent Events (SSE) with the following chunk types:
|
|
223
|
+
|
|
224
|
+
```typescript
|
|
225
|
+
// Chat metadata (first chunk for new chats)
|
|
226
|
+
{
|
|
227
|
+
type: 'chat',
|
|
228
|
+
chatId: 'chat-123',
|
|
229
|
+
chat: { /* AgentChat object */ }
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Message updates
|
|
233
|
+
{
|
|
234
|
+
type: 'message',
|
|
235
|
+
message: { /* AgentMessage object */ }
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Errors
|
|
239
|
+
{
|
|
240
|
+
type: 'error',
|
|
241
|
+
error: 'Error message'
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Stream end marker
|
|
245
|
+
[DONE]
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### Listing and Getting Chats
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
// List chats with filters
|
|
252
|
+
const chats = await chatProcessor.listChats({
|
|
253
|
+
contextKey: 'support',
|
|
254
|
+
userId: 'user-123',
|
|
255
|
+
limit: 20,
|
|
256
|
+
sortField: 'updatedAt',
|
|
257
|
+
sortOrder: SortOrder.Desc
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
// Get a specific chat with messages
|
|
261
|
+
const chat = await chatProcessor.getChat('chat-id');
|
|
262
|
+
|
|
263
|
+
// Delete a chat
|
|
264
|
+
await chatProcessor.deleteChat('chat-id');
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
## Agent Setup
|
|
268
|
+
|
|
269
|
+
Agents are configured using a JSON configuration file that defines agents, their tools, and which contexts they're available in.
|
|
270
|
+
|
|
271
|
+
### Config JSON Format
|
|
272
|
+
|
|
273
|
+
```json
|
|
274
|
+
{
|
|
275
|
+
"models": ["gpt-4o", "claude-3-5-sonnet", "openai/gpt-4"],
|
|
276
|
+
"agents": [
|
|
277
|
+
{
|
|
278
|
+
"name": "support-agent",
|
|
279
|
+
"description": "Customer support agent",
|
|
280
|
+
"systemPrompt": "You are a helpful customer support agent...",
|
|
281
|
+
"defaultModel": "gpt-4o",
|
|
282
|
+
"temperature": 0.7,
|
|
283
|
+
"maxTokens": 2000,
|
|
284
|
+
"contextKeys": ["support", "general"],
|
|
285
|
+
"tools": [
|
|
286
|
+
{
|
|
287
|
+
"type": "api-tool",
|
|
288
|
+
"data": {
|
|
289
|
+
"title": "Get Order Status",
|
|
290
|
+
"description": "Retrieves the status of a customer order",
|
|
291
|
+
"method": "GET",
|
|
292
|
+
"url": "https://api.example.com/orders/{orderId}",
|
|
293
|
+
"headersToPass": ["Authorization"],
|
|
294
|
+
"needsApproval": false
|
|
295
|
+
}
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
"type": "web-search",
|
|
299
|
+
"data": {
|
|
300
|
+
"title": "web-search"
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
]
|
|
304
|
+
}
|
|
305
|
+
]
|
|
306
|
+
}
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Loading Config
|
|
310
|
+
|
|
311
|
+
```typescript
|
|
312
|
+
import { ConfigStore } from '@multiplayer-app/ai-agent-node';
|
|
313
|
+
import fs from 'fs';
|
|
314
|
+
|
|
315
|
+
const configStore = ConfigStore.getInstance();
|
|
316
|
+
const rawConfig = JSON.parse(fs.readFileSync('agent-config.json', 'utf-8'));
|
|
317
|
+
configStore.loadConfig(rawConfig);
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### API Tool Configuration
|
|
321
|
+
|
|
322
|
+
API tools allow agents to make HTTP requests to external services:
|
|
323
|
+
|
|
324
|
+
```json
|
|
325
|
+
{
|
|
326
|
+
"type": "api-tool",
|
|
327
|
+
"data": {
|
|
328
|
+
"title": "Tool Name",
|
|
329
|
+
"description": "What this tool does",
|
|
330
|
+
"method": "GET|POST|PUT|DELETE|PATCH",
|
|
331
|
+
"url": "https://api.example.com/endpoint",
|
|
332
|
+
"headersToPass": ["Authorization", "X-Custom-Header"],
|
|
333
|
+
"body": {
|
|
334
|
+
"type": "object",
|
|
335
|
+
"properties": {
|
|
336
|
+
"param1": { "type": "string" },
|
|
337
|
+
"param2": { "type": "number" }
|
|
338
|
+
},
|
|
339
|
+
"required": ["param1"]
|
|
340
|
+
},
|
|
341
|
+
"queryParams": {
|
|
342
|
+
"type": "object",
|
|
343
|
+
"properties": {
|
|
344
|
+
"filter": { "type": "string" }
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
"needsApproval": true
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
**Key Fields**:
|
|
353
|
+
- `needsApproval`: If `true`, the tool execution requires user approval before running
|
|
354
|
+
- `headersToPass`: List of request headers to forward from the original request
|
|
355
|
+
- `body`/`queryParams`: JSON Schema definitions for request parameters (converted to Zod schemas)
|
|
356
|
+
|
|
357
|
+
### Web Search Tool
|
|
358
|
+
|
|
359
|
+
Web search tools enable agents to search the internet:
|
|
360
|
+
|
|
361
|
+
```json
|
|
362
|
+
{
|
|
363
|
+
"type": "web-search",
|
|
364
|
+
"data": {
|
|
365
|
+
"title": "web-search"
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### In-Code Agent Support
|
|
371
|
+
|
|
372
|
+
You can also add agents programmatically:
|
|
373
|
+
|
|
374
|
+
```typescript
|
|
375
|
+
import { ConfigStore } from '@multiplayer-app/ai-agent-node';
|
|
376
|
+
import { AgentToolType } from '@multiplayer-app/ai-agent-types';
|
|
377
|
+
|
|
378
|
+
const configStore = ConfigStore.getInstance();
|
|
379
|
+
|
|
380
|
+
// Add an agent
|
|
381
|
+
configStore.addAgent(['support', 'sales'], {
|
|
382
|
+
name: 'custom-agent',
|
|
383
|
+
description: 'Custom agent added in code',
|
|
384
|
+
systemPrompt: 'You are a helpful assistant...',
|
|
385
|
+
defaultModel: 'gpt-4o',
|
|
386
|
+
temperature: 0.7,
|
|
387
|
+
tools: [
|
|
388
|
+
{
|
|
389
|
+
type: AgentToolType.WEB_SEARCH,
|
|
390
|
+
data: { title: 'web-search' }
|
|
391
|
+
}
|
|
392
|
+
]
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
// Add a tool to all existing agents
|
|
396
|
+
configStore.addToolToAllAgents({
|
|
397
|
+
type: AgentToolType.LOCAL_FUNCTION,
|
|
398
|
+
data: {
|
|
399
|
+
title: 'custom-tool',
|
|
400
|
+
needsApproval: false,
|
|
401
|
+
// ... tool implementation
|
|
402
|
+
}
|
|
403
|
+
});
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
### Tool Approval Flow
|
|
407
|
+
|
|
408
|
+
When a tool has `needsApproval: true`, the agent will request approval before execution:
|
|
409
|
+
|
|
410
|
+
1. Agent generates a tool call with `requiresConfirmation: true` and an `approvalId`
|
|
411
|
+
2. Chat status changes to `AgentStatus.WaitingForUserAction`
|
|
412
|
+
3. User can approve or deny the tool call
|
|
413
|
+
4. If approved, the tool executes; if denied, execution is skipped
|
|
414
|
+
|
|
415
|
+
```typescript
|
|
416
|
+
// Process approval using createMessageStream (handles chat lookup internally)
|
|
417
|
+
const stream = await chatProcessor.createMessageStream({
|
|
418
|
+
chatId: 'chat-id',
|
|
419
|
+
messageId: 'message-id',
|
|
420
|
+
approvalId: 'approval-id',
|
|
421
|
+
approved: true,
|
|
422
|
+
reason: 'User approved'
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
// Or use streamMessage directly if you already have the chat object
|
|
426
|
+
const chat = await chatProcessor.getChat('chat-id');
|
|
427
|
+
await chatProcessor.streamMessage(chat, {
|
|
428
|
+
chatId: 'chat-id',
|
|
429
|
+
messageId: 'message-id',
|
|
430
|
+
approvalId: 'approval-id',
|
|
431
|
+
approved: true,
|
|
432
|
+
reason: 'User approved'
|
|
433
|
+
});
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
### User Attachments
|
|
437
|
+
|
|
438
|
+
Messages can include attachments for context:
|
|
439
|
+
|
|
440
|
+
```typescript
|
|
441
|
+
import { AgentAttachmentType } from '@multiplayer-app/ai-agent-types';
|
|
442
|
+
|
|
443
|
+
const stream = await chatProcessor.createMessageStream({
|
|
444
|
+
content: 'Analyze this document',
|
|
445
|
+
contextKey: 'support',
|
|
446
|
+
attachments: [
|
|
447
|
+
{
|
|
448
|
+
id: 'att-1',
|
|
449
|
+
type: AgentAttachmentType.File,
|
|
450
|
+
name: 'document.pdf',
|
|
451
|
+
url: 'https://s3.../document.pdf',
|
|
452
|
+
mimeType: 'application/pdf',
|
|
453
|
+
size: 1024000
|
|
454
|
+
},
|
|
455
|
+
{
|
|
456
|
+
id: 'att-2',
|
|
457
|
+
type: AgentAttachmentType.Context,
|
|
458
|
+
name: 'Page Context',
|
|
459
|
+
metadata: {
|
|
460
|
+
kind: 'webSnippet',
|
|
461
|
+
source: { url: 'https://example.com' },
|
|
462
|
+
selectedText: 'Selected text from page'
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
]
|
|
466
|
+
});
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
## Database Access
|
|
470
|
+
|
|
471
|
+
The library uses repository interfaces from `@multiplayer-app/ai-agent-db` for database operations. You can use any implementation that conforms to these interfaces.
|
|
472
|
+
|
|
473
|
+
### MongoDB Example
|
|
474
|
+
|
|
475
|
+
```typescript
|
|
476
|
+
import mongo from '@multiplayer-app/ai-agent-mongo';
|
|
477
|
+
import { MongoAgentChatRepository, MongoAgentMessageRepository } from '@multiplayer-app/ai-agent-mongo';
|
|
478
|
+
|
|
479
|
+
// Connect to MongoDB
|
|
480
|
+
await mongo.connect();
|
|
481
|
+
|
|
482
|
+
// Create repositories
|
|
483
|
+
const chatRepository = new MongoAgentChatRepository();
|
|
484
|
+
const messageRepository = new MongoAgentMessageRepository();
|
|
485
|
+
|
|
486
|
+
// Use with ChatProcessor
|
|
487
|
+
const chatProcessor = new ChatProcessor(
|
|
488
|
+
chatRepository,
|
|
489
|
+
messageRepository,
|
|
490
|
+
artifactStore
|
|
491
|
+
);
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
### Generic Repositories
|
|
495
|
+
|
|
496
|
+
The library works with any repository implementation that matches the interfaces:
|
|
497
|
+
|
|
498
|
+
```typescript
|
|
499
|
+
import type {
|
|
500
|
+
AgentChatRepository,
|
|
501
|
+
AgentMessageRepository
|
|
502
|
+
} from '@multiplayer-app/ai-agent-db';
|
|
503
|
+
|
|
504
|
+
// Your custom implementation
|
|
505
|
+
class CustomChatRepository implements AgentChatRepository {
|
|
506
|
+
// Implement all required methods
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
class CustomMessageRepository implements AgentMessageRepository {
|
|
510
|
+
// Implement all required methods
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// Use with ChatProcessor
|
|
514
|
+
const chatProcessor = new ChatProcessor(
|
|
515
|
+
new CustomChatRepository(),
|
|
516
|
+
new CustomMessageRepository(),
|
|
517
|
+
artifactStore
|
|
518
|
+
);
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
### Repository Methods
|
|
522
|
+
|
|
523
|
+
**AgentChatRepository**:
|
|
524
|
+
- `create(data)`: Create a new chat
|
|
525
|
+
- `findById(id)`: Find chat by ID
|
|
526
|
+
- `update(id, data)`: Update chat
|
|
527
|
+
- `delete(id)`: Delete chat
|
|
528
|
+
- `findWithMessages(filter, options)`: Find chats with aggregated messages
|
|
529
|
+
|
|
530
|
+
**AgentMessageRepository**:
|
|
531
|
+
- `create(data)`: Create a new message
|
|
532
|
+
- `findById(id)`: Find message by ID
|
|
533
|
+
- `findByChatId(chatId)`: Find all messages for a chat
|
|
534
|
+
- `update(id, data)`: Update message
|
|
535
|
+
- `delete(id)`: Delete message
|
|
536
|
+
|
|
537
|
+
## Advanced Usage
|
|
538
|
+
|
|
539
|
+
### Agent Process Management
|
|
540
|
+
|
|
541
|
+
Monitor and control agent processes:
|
|
542
|
+
|
|
543
|
+
```typescript
|
|
544
|
+
import { agentStore, AgentProcessEventType } from '@multiplayer-app/ai-agent-node';
|
|
545
|
+
|
|
546
|
+
// Listen to agent process events
|
|
547
|
+
agentStore.addListener('chat-id', (event) => {
|
|
548
|
+
switch (event.type) {
|
|
549
|
+
case AgentProcessEventType.Update:
|
|
550
|
+
console.log('Agent updated:', event.data);
|
|
551
|
+
break;
|
|
552
|
+
case AgentProcessEventType.Finished:
|
|
553
|
+
console.log('Agent finished:', event.data);
|
|
554
|
+
break;
|
|
555
|
+
case AgentProcessEventType.Error:
|
|
556
|
+
console.error('Agent error:', event.data);
|
|
557
|
+
break;
|
|
558
|
+
}
|
|
559
|
+
});
|
|
560
|
+
|
|
561
|
+
// Stop an agent process
|
|
562
|
+
agentStore.stopAgentProcess('chat-id');
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
### Built-in Tools
|
|
566
|
+
|
|
567
|
+
The library includes built-in tools:
|
|
568
|
+
|
|
569
|
+
```typescript
|
|
570
|
+
import {
|
|
571
|
+
createProposeFormValuesTool,
|
|
572
|
+
createGenerateChartTool
|
|
573
|
+
} from '@multiplayer-app/ai-agent-node';
|
|
574
|
+
|
|
575
|
+
// Add form proposal tool to all agents
|
|
576
|
+
configStore.addToolToAllAgents(createProposeFormValuesTool());
|
|
577
|
+
|
|
578
|
+
// Add chart generation tool to all agents
|
|
579
|
+
configStore.addToolToAllAgents(createGenerateChartTool());
|
|
580
|
+
```
|
|
581
|
+
|
|
582
|
+
### Context Limiting
|
|
583
|
+
|
|
584
|
+
The library automatically limits context to prevent token limit issues:
|
|
585
|
+
|
|
586
|
+
```typescript
|
|
587
|
+
import { helpers } from '@multiplayer-app/ai-agent-node';
|
|
588
|
+
|
|
589
|
+
const limitedMessages = helpers.ContextLimiter.limitContext(messages, {
|
|
590
|
+
maxMessages: 10,
|
|
591
|
+
keepFirstUserMessage: true,
|
|
592
|
+
keepSystemMessages: true
|
|
593
|
+
});
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
### Artifact Management
|
|
597
|
+
|
|
598
|
+
Store and retrieve artifacts generated by agents:
|
|
599
|
+
|
|
600
|
+
```typescript
|
|
601
|
+
// List artifacts for a chat
|
|
602
|
+
const artifacts = chatProcessor.listArtifacts('chat-id');
|
|
603
|
+
|
|
604
|
+
// Artifacts are automatically stored when generated by tools
|
|
605
|
+
// Access via ArtifactStore if needed
|
|
606
|
+
import { ArtifactStore } from '@multiplayer-app/ai-agent-node';
|
|
607
|
+
const artifactStore = new ArtifactStore();
|
|
608
|
+
const artifacts = artifactStore.listArtifacts('chat-id');
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
|