dank-ai 1.0.5 → 1.0.7
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/README.md +1692 -65
- package/bin/dank +15 -0
- package/lib/agent.js +27 -0
- package/lib/cli/production-build.js +110 -0
- package/lib/docker/manager.js +72 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,107 +1,1734 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 🚀 Dank Agent Service
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Docker-based AI Agent Orchestration Platform**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Dank is a powerful Node.js service that allows you to define, deploy, and manage AI agents using Docker containers. Each agent runs in its own isolated environment with configurable resources, LLM providers, and custom handlers. Built for production with comprehensive CI/CD support and Docker registry integration.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
- 🐳 **Docker Integration**: Containerized agents with automatic management
|
|
9
|
-
- 📡 **Event System**: Real-time event handling for prompts, responses, and tools
|
|
10
|
-
- 🔧 **Auto-Detection**: Automatically enables features based on usage
|
|
11
|
-
- 📊 **Monitoring**: Built-in logging and status monitoring
|
|
7
|
+
## ✨ Features
|
|
12
8
|
|
|
13
|
-
|
|
9
|
+
- **🤖 Multi-LLM Support**: OpenAI, Anthropic, Cohere, Ollama, and custom providers
|
|
10
|
+
- **🐳 Docker Orchestration**: Isolated agent containers with resource management
|
|
11
|
+
- **⚡ Easy Configuration**: Define agents with simple JavaScript configuration
|
|
12
|
+
- **📊 Real-time Monitoring**: Built-in health checks and status monitoring
|
|
13
|
+
- **🔧 Flexible Handlers**: Custom event handlers for agent outputs and errors
|
|
14
|
+
- **🎯 CLI Interface**: Powerful command-line tools for agent management
|
|
15
|
+
- **🏗️ Production Builds**: Build and push Docker images to registries with custom naming
|
|
16
|
+
- **🔄 CI/CD Ready**: Seamless integration with GitHub Actions, GitLab CI, and other platforms
|
|
14
17
|
|
|
15
|
-
|
|
16
|
-
```bash
|
|
17
|
-
npm install
|
|
18
|
-
```
|
|
18
|
+
## 🚀 Quick Start
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
### Prerequisites
|
|
21
|
+
Before you begin, make sure you have:
|
|
22
|
+
- **Node.js 16+** installed
|
|
23
|
+
- **Docker Desktop** or **Docker Engine** (will be installed automatically if missing)
|
|
24
|
+
- **API keys** for your chosen LLM provider(s)
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
Edit `dank.config.js` to define your agents and their capabilities.
|
|
26
|
+
> **🆕 Auto-Docker Installation**: Dank will automatically detect, install, and start Docker if it's not available on your system. No manual setup required!
|
|
28
27
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
28
|
+
### 1. Install Dank globally
|
|
29
|
+
```bash
|
|
30
|
+
npm install -g dank-ai
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### 2. Initialize a new project
|
|
34
|
+
```bash
|
|
35
|
+
# Create and navigate to your project directory
|
|
36
|
+
mkdir my-agent-project
|
|
37
|
+
cd my-agent-project
|
|
38
|
+
|
|
39
|
+
# Initialize Dank project
|
|
40
|
+
dank init my-agent-project
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
This creates:
|
|
44
|
+
```
|
|
45
|
+
my-agent-project/
|
|
46
|
+
├── dank.config.js # Your agent configuration
|
|
47
|
+
├── agents/ # Custom agent code (optional)
|
|
48
|
+
│ └── example-agent.js
|
|
49
|
+
└── .dank/ # Generated files
|
|
50
|
+
└── project.yaml
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### 3. Set up environment variables
|
|
54
|
+
Create a `.env` file or export environment variables:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# For OpenAI
|
|
58
|
+
export OPENAI_API_KEY="your-openai-api-key"
|
|
59
|
+
|
|
60
|
+
# For Anthropic
|
|
61
|
+
export ANTHROPIC_API_KEY="your-anthropic-api-key"
|
|
62
|
+
|
|
63
|
+
# For Cohere
|
|
64
|
+
export COHERE_API_KEY="your-cohere-api-key"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### 4. Configure your agents
|
|
68
|
+
Edit `dank.config.js` to define your agents:
|
|
69
|
+
|
|
70
|
+
```javascript
|
|
71
|
+
const { createAgent } = require('dank');
|
|
72
|
+
|
|
73
|
+
module.exports = {
|
|
74
|
+
name: 'my-agent-project',
|
|
75
|
+
|
|
76
|
+
agents: [
|
|
77
|
+
createAgent('assistant')
|
|
78
|
+
.setLLM('openai', {
|
|
79
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
80
|
+
model: 'gpt-3.5-turbo',
|
|
81
|
+
temperature: 0.7
|
|
82
|
+
})
|
|
83
|
+
.setPrompt('You are a helpful assistant that responds with enthusiasm!')
|
|
84
|
+
.setResources({
|
|
85
|
+
memory: '512m',
|
|
86
|
+
cpu: 1
|
|
87
|
+
})
|
|
88
|
+
.addHandler('output', (data) => {
|
|
89
|
+
console.log('Assistant says:', data);
|
|
90
|
+
})
|
|
91
|
+
]
|
|
92
|
+
};
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### 5. Build Docker images (optional)
|
|
96
|
+
```bash
|
|
97
|
+
# Build agent images (base image is pulled automatically)
|
|
98
|
+
dank build
|
|
99
|
+
|
|
100
|
+
# Or build only the base image
|
|
101
|
+
dank build --base
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### 6. Start your agents
|
|
105
|
+
```bash
|
|
106
|
+
# Start all agents
|
|
107
|
+
dank run
|
|
108
|
+
|
|
109
|
+
# Or run in detached mode (background)
|
|
110
|
+
dank run --detached
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### 7. Monitor your agents
|
|
114
|
+
```bash
|
|
115
|
+
# Check agent status
|
|
116
|
+
dank status
|
|
117
|
+
|
|
118
|
+
# Watch status in real-time
|
|
119
|
+
dank status --watch
|
|
120
|
+
|
|
121
|
+
# View agent logs
|
|
122
|
+
dank logs assistant
|
|
123
|
+
|
|
124
|
+
# Follow logs in real-time
|
|
125
|
+
dank logs assistant --follow
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### 8. Build for production (optional)
|
|
129
|
+
```bash
|
|
130
|
+
# Build production images with custom naming
|
|
131
|
+
dank build:prod
|
|
132
|
+
|
|
133
|
+
# Build and push to registry
|
|
134
|
+
dank build:prod --push
|
|
135
|
+
|
|
136
|
+
# Build with custom tag and registry
|
|
137
|
+
dank build:prod --tag v1.0.0 --registry ghcr.io --namespace myorg --push
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## 📋 CLI Commands
|
|
141
|
+
|
|
142
|
+
### Core Commands
|
|
143
|
+
```bash
|
|
144
|
+
dank run # Start all defined agents
|
|
145
|
+
dank status # Show agent status
|
|
146
|
+
dank stop [agents...] # Stop specific agents
|
|
147
|
+
dank stop --all # Stop all agents
|
|
148
|
+
dank logs [agent] # View agent logs
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Management Commands
|
|
152
|
+
```bash
|
|
153
|
+
dank init [name] # Initialize new project
|
|
154
|
+
dank build # Build Docker images
|
|
155
|
+
dank build:prod # Build agent images with custom naming
|
|
156
|
+
dank clean # Clean up Docker resources
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Agent Image Build Commands
|
|
160
|
+
```bash
|
|
161
|
+
dank build:prod # Build with agent image config
|
|
162
|
+
dank build:prod --push # Build and push to registry (CLI only)
|
|
163
|
+
dank build:prod --tag v1.0.0 # Build with custom tag
|
|
164
|
+
dank build:prod --registry ghcr.io # Build for specific registry
|
|
165
|
+
dank build:prod --force # Force rebuild without cache
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
> **💡 Push Control**: The `--push` option is the only way to push images to registries. Agent configuration defines naming, CLI controls pushing.
|
|
35
169
|
|
|
36
|
-
|
|
170
|
+
### Advanced Options
|
|
171
|
+
```bash
|
|
172
|
+
dank run --detached # Run in background
|
|
173
|
+
dank run --no-build # Skip rebuilding images (default is to rebuild)
|
|
174
|
+
dank run --pull # Pull latest base image before building
|
|
175
|
+
dank status --watch # Live status monitoring
|
|
176
|
+
dank logs --follow # Follow log output
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Production Build Options
|
|
180
|
+
```bash
|
|
181
|
+
dank build:prod --push # Build and push to registry
|
|
182
|
+
dank build:prod --tag v1.0.0 # Build with custom tag
|
|
183
|
+
dank build:prod --registry ghcr.io # Build for GitHub Container Registry
|
|
184
|
+
dank build:prod --namespace mycompany # Build with custom namespace
|
|
185
|
+
dank build:prod --force # Force rebuild without cache
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## 🤖 Agent Configuration
|
|
189
|
+
|
|
190
|
+
### Basic Agent Setup
|
|
191
|
+
```javascript
|
|
192
|
+
const agent = createAgent('my-agent')
|
|
193
|
+
.setLLM('openai', {
|
|
194
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
195
|
+
model: 'gpt-4',
|
|
196
|
+
temperature: 0.8
|
|
197
|
+
})
|
|
198
|
+
.setPrompt('Your system prompt here')
|
|
199
|
+
.setPromptingServer({
|
|
200
|
+
protocol: 'http',
|
|
201
|
+
port: 3000,
|
|
202
|
+
authentication: false,
|
|
203
|
+
maxConnections: 50
|
|
204
|
+
})
|
|
205
|
+
.setResources({
|
|
206
|
+
memory: '1g',
|
|
207
|
+
cpu: 2,
|
|
208
|
+
timeout: 60000
|
|
209
|
+
});
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Supported LLM Providers
|
|
213
|
+
|
|
214
|
+
#### OpenAI
|
|
215
|
+
```javascript
|
|
216
|
+
.setLLM('openai', {
|
|
217
|
+
apiKey: 'your-api-key',
|
|
218
|
+
model: 'gpt-4',
|
|
219
|
+
temperature: 0.7,
|
|
220
|
+
maxTokens: 1000
|
|
221
|
+
})
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
#### Anthropic
|
|
225
|
+
```javascript
|
|
226
|
+
.setLLM('anthropic', {
|
|
227
|
+
apiKey: 'your-api-key',
|
|
228
|
+
model: 'claude-3-sonnet-20240229',
|
|
229
|
+
maxTokens: 1000
|
|
230
|
+
})
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
#### Ollama (Local)
|
|
234
|
+
```javascript
|
|
235
|
+
.setLLM('ollama', {
|
|
236
|
+
baseURL: 'http://localhost:11434',
|
|
237
|
+
model: 'llama2'
|
|
238
|
+
})
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
#### Cohere
|
|
242
|
+
```javascript
|
|
243
|
+
.setLLM('cohere', {
|
|
244
|
+
apiKey: 'your-api-key',
|
|
245
|
+
model: 'command',
|
|
246
|
+
temperature: 0.7
|
|
247
|
+
})
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
#### Hugging Face
|
|
251
|
+
```javascript
|
|
252
|
+
.setLLM('huggingface', {
|
|
253
|
+
apiKey: 'your-api-key',
|
|
254
|
+
model: 'microsoft/DialoGPT-medium'
|
|
255
|
+
})
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
#### Custom Provider
|
|
259
|
+
```javascript
|
|
260
|
+
.setLLM('custom', {
|
|
261
|
+
baseURL: 'https://api.your-provider.com',
|
|
262
|
+
apiKey: 'your-key',
|
|
263
|
+
model: 'your-model'
|
|
264
|
+
})
|
|
265
|
+
```
|
|
37
266
|
|
|
38
|
-
|
|
39
|
-
- `npm run dev` - Start in development mode
|
|
40
|
-
- `npm run stop` - Stop all agents
|
|
41
|
-
- `npm run status` - Check agent status
|
|
42
|
-
- `npm run logs` - View agent logs
|
|
43
|
-
- `npm run build` - Build agent images
|
|
44
|
-
- `npm run clean` - Clean up containers and images
|
|
267
|
+
### Event Handlers
|
|
45
268
|
|
|
46
|
-
|
|
269
|
+
Dank provides a comprehensive event system with three main sources of events. Each event handler follows specific naming patterns for maximum flexibility and control.
|
|
47
270
|
|
|
48
|
-
|
|
271
|
+
> **🆕 Auto-Detection**: Dank automatically enables communication features based on your usage:
|
|
272
|
+
> - **Event Handlers**: Auto-enabled when you add `.addHandler()` calls
|
|
273
|
+
> - **Direct Prompting**: Auto-enabled when you use `.setPrompt()` + `.setLLM()`
|
|
274
|
+
> - **HTTP API**: Auto-enabled when you add routes with `.get()`, `.post()`, etc.
|
|
49
275
|
|
|
50
|
-
|
|
51
|
-
|
|
276
|
+
#### 🎯 **Event Handler Patterns**
|
|
277
|
+
|
|
278
|
+
##### **1. Direct Prompting Events** (`request_output`)
|
|
279
|
+
Events triggered when agents receive and respond to direct prompts via WebSocket or HTTP:
|
|
52
280
|
|
|
53
281
|
```javascript
|
|
282
|
+
agent
|
|
283
|
+
// Main LLM response event
|
|
284
|
+
.addHandler('request_output', (data) => {
|
|
285
|
+
console.log('LLM Response:', {
|
|
286
|
+
prompt: data.prompt, // Original prompt
|
|
287
|
+
finalPrompt: data.finalPrompt, // Modified prompt (if changed)
|
|
288
|
+
response: data.response, // LLM response
|
|
289
|
+
conversationId: data.conversationId,
|
|
290
|
+
processingTime: data.processingTime,
|
|
291
|
+
promptModified: data.promptModified, // Boolean: was prompt modified?
|
|
292
|
+
usage: data.usage,
|
|
293
|
+
model: data.model
|
|
294
|
+
});
|
|
295
|
+
})
|
|
296
|
+
|
|
297
|
+
// Lifecycle events with modification capabilities
|
|
298
|
+
.addHandler('request_output:start', (data) => {
|
|
299
|
+
console.log('Processing prompt:', data.conversationId);
|
|
300
|
+
console.log('Original prompt:', data.prompt);
|
|
301
|
+
|
|
302
|
+
// ✨ MODIFY PROMPT: Return modified data to change the prompt sent to LLM
|
|
303
|
+
const enhancedPrompt = `Context: You are a helpful assistant. Please be concise and friendly.\n\nUser Question: ${data.prompt}`;
|
|
304
|
+
|
|
305
|
+
return {
|
|
306
|
+
prompt: enhancedPrompt // This will replace the original prompt
|
|
307
|
+
};
|
|
308
|
+
})
|
|
309
|
+
|
|
310
|
+
.addHandler('request_output:end', (data) => {
|
|
311
|
+
console.log('Completed in:', data.processingTime + 'ms');
|
|
312
|
+
console.log('Original response:', data.response.substring(0, 50) + '...');
|
|
313
|
+
|
|
314
|
+
// ✨ MODIFY RESPONSE: Return modified data to change the response sent to caller
|
|
315
|
+
const enhancedResponse = `${data.response}\n\n---\n💡 This response was generated by Dank Framework`;
|
|
316
|
+
|
|
317
|
+
return {
|
|
318
|
+
response: enhancedResponse // This will replace the original response
|
|
319
|
+
};
|
|
320
|
+
})
|
|
321
|
+
|
|
322
|
+
.addHandler('request_output:error', (data) => {
|
|
323
|
+
console.error('Prompt processing failed:', data.error);
|
|
324
|
+
});
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
**🔄 Event Modification Capabilities:**
|
|
328
|
+
|
|
329
|
+
- **`request_output:start`**: Can modify the prompt before it's sent to the LLM by returning an object with a `prompt` property
|
|
330
|
+
- **`request_output:end`**: Can modify the response before it's sent back to the caller by returning an object with a `response` property
|
|
331
|
+
- **Event Data**: All events include both original and final values, plus modification flags for tracking changes
|
|
332
|
+
|
|
333
|
+
**⏱️ Event Flow Timeline:**
|
|
334
|
+
|
|
335
|
+
1. **`request_output:start`** → Fires when prompt is received
|
|
336
|
+
- Can modify prompt before LLM processing
|
|
337
|
+
- Contains: `{ prompt, conversationId, context, timestamp }`
|
|
338
|
+
|
|
339
|
+
2. **LLM Processing** → The (potentially modified) prompt is sent to the LLM
|
|
340
|
+
|
|
341
|
+
3. **`request_output`** → Fires after LLM responds successfully
|
|
342
|
+
- Contains: `{ prompt, finalPrompt, response, conversationId, promptModified, ... }`
|
|
343
|
+
|
|
344
|
+
4. **`request_output:end`** → Fires after `request_output`, before sending to caller
|
|
345
|
+
- Can modify response before returning to client
|
|
346
|
+
- Contains: `{ prompt, finalPrompt, response, conversationId, promptModified, success, ... }`
|
|
347
|
+
|
|
348
|
+
5. **Response Sent** → The (potentially modified) response is sent back to the caller
|
|
349
|
+
|
|
350
|
+
**💡 Practical Examples:**
|
|
351
|
+
|
|
352
|
+
```javascript
|
|
353
|
+
// Example 1: Add context and formatting to prompts
|
|
54
354
|
.addHandler('request_output:start', (data) => {
|
|
55
|
-
//
|
|
56
|
-
|
|
355
|
+
// Add system context and format the user's question
|
|
356
|
+
const enhancedPrompt = `System: You are a helpful AI assistant. Be concise and professional.
|
|
357
|
+
|
|
358
|
+
User Question: ${data.prompt}
|
|
359
|
+
|
|
360
|
+
Please provide a clear, helpful response.`;
|
|
361
|
+
|
|
362
|
+
return { prompt: enhancedPrompt };
|
|
57
363
|
})
|
|
58
364
|
|
|
365
|
+
// Example 2: Add metadata and branding to responses
|
|
59
366
|
.addHandler('request_output:end', (data) => {
|
|
60
|
-
//
|
|
61
|
-
|
|
367
|
+
// Add footer with metadata and branding
|
|
368
|
+
const brandedResponse = `${data.response}
|
|
369
|
+
|
|
370
|
+
---
|
|
371
|
+
🤖 Generated by Dank Framework Agent
|
|
372
|
+
⏱️ Processing time: ${data.processingTime}ms
|
|
373
|
+
🆔 Conversation: ${data.conversationId}`;
|
|
374
|
+
|
|
375
|
+
return { response: brandedResponse };
|
|
376
|
+
})
|
|
377
|
+
|
|
378
|
+
// Example 3: Log and analyze all interactions
|
|
379
|
+
.addHandler('request_output', (data) => {
|
|
380
|
+
// Log for analytics
|
|
381
|
+
console.log('Interaction logged:', {
|
|
382
|
+
originalPrompt: data.prompt,
|
|
383
|
+
modifiedPrompt: data.finalPrompt,
|
|
384
|
+
wasModified: data.promptModified,
|
|
385
|
+
responseLength: data.response.length,
|
|
386
|
+
model: data.model,
|
|
387
|
+
usage: data.usage
|
|
388
|
+
});
|
|
62
389
|
})
|
|
63
390
|
```
|
|
64
391
|
|
|
65
|
-
|
|
66
|
-
|
|
392
|
+
##### **2. Tool Events** (`tool:*`)
|
|
393
|
+
Events triggered by tool usage, following the pattern `tool:<tool-name>:<action>:<specifics>`:
|
|
394
|
+
|
|
395
|
+
```javascript
|
|
396
|
+
agent
|
|
397
|
+
// HTTP Server Tool Events
|
|
398
|
+
.addHandler('tool:http-server:*', (data) => {
|
|
399
|
+
// Listen to ALL HTTP server events
|
|
400
|
+
console.log('HTTP Activity:', data.type, data.method, data.path);
|
|
401
|
+
})
|
|
402
|
+
|
|
403
|
+
.addHandler('tool:http-server:call', (data) => {
|
|
404
|
+
// All incoming HTTP requests
|
|
405
|
+
console.log('Request:', data.method, data.path, data.body);
|
|
406
|
+
})
|
|
407
|
+
|
|
408
|
+
.addHandler('tool:http-server:response', (data) => {
|
|
409
|
+
// All HTTP responses
|
|
410
|
+
console.log('Response:', data.statusCode, data.processingTime);
|
|
411
|
+
})
|
|
412
|
+
|
|
413
|
+
.addHandler('tool:http-server:call:post', (data) => {
|
|
414
|
+
// Only POST requests
|
|
415
|
+
console.log('POST Request:', data.path, data.body);
|
|
416
|
+
})
|
|
417
|
+
|
|
418
|
+
.addHandler('tool:http-server:response:get', (data) => {
|
|
419
|
+
// Only GET responses
|
|
420
|
+
console.log('GET Response:', data.path, data.responseData);
|
|
421
|
+
})
|
|
422
|
+
|
|
423
|
+
.addHandler('tool:http-server:error', (data) => {
|
|
424
|
+
// HTTP server errors
|
|
425
|
+
console.error('HTTP Error:', data.error);
|
|
426
|
+
});
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
**Tool Event Pattern Structure:**
|
|
430
|
+
- `tool:<tool-name>:*` - All events for a specific tool
|
|
431
|
+
- `tool:<tool-name>:call` - Tool invocation/input events
|
|
432
|
+
- `tool:<tool-name>:response` - Tool output/result events
|
|
433
|
+
- `tool:<tool-name>:call:<method>` - Specific method calls (e.g., POST, GET)
|
|
434
|
+
- `tool:<tool-name>:response:<method>` - Specific method responses
|
|
435
|
+
- `tool:<tool-name>:error` - Tool-specific errors
|
|
436
|
+
|
|
437
|
+
##### **3. System Events** (Legacy/System)
|
|
438
|
+
Traditional system-level events:
|
|
67
439
|
|
|
68
440
|
```javascript
|
|
69
|
-
|
|
70
|
-
|
|
441
|
+
agent
|
|
442
|
+
.addHandler('output', (data) => {
|
|
443
|
+
console.log('General output:', data);
|
|
444
|
+
})
|
|
445
|
+
|
|
446
|
+
.addHandler('error', (error) => {
|
|
447
|
+
console.error('System error:', error);
|
|
448
|
+
})
|
|
449
|
+
|
|
450
|
+
.addHandler('heartbeat', () => {
|
|
451
|
+
console.log('Agent heartbeat');
|
|
452
|
+
})
|
|
453
|
+
|
|
454
|
+
.addHandler('start', () => {
|
|
455
|
+
console.log('Agent started');
|
|
456
|
+
})
|
|
457
|
+
|
|
458
|
+
.addHandler('stop', () => {
|
|
459
|
+
console.log('Agent stopped');
|
|
460
|
+
});
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
#### 🔥 **Advanced Event Patterns**
|
|
464
|
+
|
|
465
|
+
**Wildcard Matching:**
|
|
466
|
+
```javascript
|
|
467
|
+
// Listen to all tool events
|
|
468
|
+
.addHandler('tool:*', (data) => {
|
|
469
|
+
console.log('Any tool activity:', data);
|
|
470
|
+
})
|
|
471
|
+
|
|
472
|
+
// Listen to all HTTP responses
|
|
473
|
+
.addHandler('tool:http-server:response:*', (data) => {
|
|
474
|
+
console.log('Any HTTP response:', data);
|
|
71
475
|
})
|
|
72
476
|
|
|
73
|
-
|
|
74
|
-
|
|
477
|
+
// Listen to all request outputs
|
|
478
|
+
.addHandler('request_output:*', (data) => {
|
|
479
|
+
console.log('Any request event:', data);
|
|
75
480
|
})
|
|
76
481
|
```
|
|
77
482
|
|
|
78
|
-
|
|
79
|
-
|
|
483
|
+
**Multiple Handlers:**
|
|
484
|
+
```javascript
|
|
485
|
+
// Multiple handlers for the same event
|
|
486
|
+
agent
|
|
487
|
+
.addHandler('request_output', (data) => {
|
|
488
|
+
// Log to console
|
|
489
|
+
console.log('Response:', data.response);
|
|
490
|
+
})
|
|
491
|
+
.addHandler('request_output', (data) => {
|
|
492
|
+
// Save to database
|
|
493
|
+
saveToDatabase(data);
|
|
494
|
+
})
|
|
495
|
+
.addHandler('request_output', (data) => {
|
|
496
|
+
// Send to analytics
|
|
497
|
+
trackAnalytics(data);
|
|
498
|
+
});
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
#### 📊 **Event Data Structures**
|
|
502
|
+
|
|
503
|
+
**Request Output Event Data:**
|
|
504
|
+
```javascript
|
|
505
|
+
{
|
|
506
|
+
prompt: "User's input prompt",
|
|
507
|
+
response: "LLM's response",
|
|
508
|
+
conversationId: "unique-conversation-id",
|
|
509
|
+
context: { protocol: "websocket", clientId: "..." },
|
|
510
|
+
usage: { total_tokens: 150, prompt_tokens: 50, completion_tokens: 100 },
|
|
511
|
+
model: "gpt-3.5-turbo",
|
|
512
|
+
processingTime: 1250,
|
|
513
|
+
timestamp: "2024-01-15T10:30:00.000Z"
|
|
514
|
+
}
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
**Tool HTTP Event Data:**
|
|
518
|
+
```javascript
|
|
519
|
+
{
|
|
520
|
+
requestId: "unique-request-id",
|
|
521
|
+
method: "POST",
|
|
522
|
+
path: "/api/chat",
|
|
523
|
+
headers: { "content-type": "application/json" },
|
|
524
|
+
body: { message: "Hello" },
|
|
525
|
+
query: {},
|
|
526
|
+
params: {},
|
|
527
|
+
statusCode: 200,
|
|
528
|
+
responseData: { response: "Hi there!" },
|
|
529
|
+
processingTime: 45,
|
|
530
|
+
timestamp: "2024-01-15T10:30:00.000Z"
|
|
531
|
+
}
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
#### 🎛️ **Communication Method Control**
|
|
535
|
+
|
|
536
|
+
Each communication method can be enabled/disabled independently:
|
|
537
|
+
|
|
538
|
+
```javascript
|
|
539
|
+
createAgent('flexible-agent')
|
|
540
|
+
// Configure direct prompting with specific settings
|
|
541
|
+
.setPromptingServer({
|
|
542
|
+
protocol: 'websocket',
|
|
543
|
+
port: 3000,
|
|
544
|
+
authentication: false,
|
|
545
|
+
maxConnections: 50
|
|
546
|
+
})
|
|
547
|
+
.disableDirectPrompting() // Disable if needed
|
|
548
|
+
|
|
549
|
+
// Enable HTTP API
|
|
550
|
+
.enableHttp({ port: 3001 })
|
|
551
|
+
|
|
552
|
+
// Listen to direct prompting events only
|
|
553
|
+
.addHandler('request_output', (data) => {
|
|
554
|
+
console.log('WebSocket response:', data.response);
|
|
555
|
+
})
|
|
556
|
+
|
|
557
|
+
// HTTP events will fire when routes are added
|
|
558
|
+
.get('/api/status', (req, res) => {
|
|
559
|
+
res.json({ status: 'ok' });
|
|
560
|
+
})
|
|
561
|
+
.addHandler('tool:http-server:*', (data) => {
|
|
562
|
+
console.log('HTTP activity:', data);
|
|
563
|
+
});
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
### Resource Management
|
|
567
|
+
|
|
568
|
+
Configure container resources:
|
|
80
569
|
|
|
81
570
|
```javascript
|
|
82
|
-
.
|
|
83
|
-
|
|
571
|
+
.setResources({
|
|
572
|
+
memory: '512m', // Memory limit (512m, 1g, etc.)
|
|
573
|
+
cpu: 1, // CPU allocation (0.5, 1, 2, etc.)
|
|
574
|
+
timeout: 30000, // Request timeout in ms
|
|
575
|
+
maxRestarts: 3 // Max container restarts
|
|
84
576
|
})
|
|
577
|
+
```
|
|
85
578
|
|
|
86
|
-
|
|
87
|
-
|
|
579
|
+
### Agent Image Configuration
|
|
580
|
+
|
|
581
|
+
Configure Docker image naming and registry settings for agent builds:
|
|
582
|
+
|
|
583
|
+
```javascript
|
|
584
|
+
// Complete agent image configuration
|
|
585
|
+
.setAgentImageConfig({
|
|
586
|
+
registry: 'ghcr.io', // Docker registry URL
|
|
587
|
+
namespace: 'mycompany', // Organization/namespace
|
|
588
|
+
tag: 'v1.0.0' // Image tag
|
|
88
589
|
})
|
|
89
590
|
```
|
|
90
591
|
|
|
91
|
-
|
|
592
|
+
#### 🏗️ **Agent Image Build Workflow**
|
|
593
|
+
|
|
594
|
+
The agent image build feature allows you to create properly tagged Docker images for deployment to container registries. This is essential for:
|
|
595
|
+
|
|
596
|
+
- **CI/CD Pipelines**: Automated builds and deployments
|
|
597
|
+
- **Container Orchestration**: Kubernetes, Docker Swarm, etc.
|
|
598
|
+
- **Multi-Environment Deployments**: Dev, staging, production
|
|
599
|
+
- **Version Management**: Semantic versioning with tags
|
|
600
|
+
|
|
601
|
+
> **📝 Note**: Image pushing is controlled exclusively by the CLI `--push` option. Agent configuration only defines image naming (registry, namespace, tag) - not push behavior.
|
|
602
|
+
|
|
603
|
+
#### 📋 **Complete Agent Image Example**
|
|
604
|
+
|
|
605
|
+
```javascript
|
|
606
|
+
const { createAgent } = require('dank');
|
|
607
|
+
|
|
608
|
+
module.exports = {
|
|
609
|
+
name: 'production-system',
|
|
610
|
+
|
|
611
|
+
agents: [
|
|
612
|
+
// Production-ready customer service agent
|
|
613
|
+
createAgent('customer-service')
|
|
614
|
+
.setLLM('openai', {
|
|
615
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
616
|
+
model: 'gpt-4',
|
|
617
|
+
temperature: 0.7
|
|
618
|
+
})
|
|
619
|
+
.setPrompt('You are a professional customer service representative.')
|
|
620
|
+
.setPromptingServer({
|
|
621
|
+
protocol: 'http',
|
|
622
|
+
port: 3000,
|
|
623
|
+
authentication: true,
|
|
624
|
+
maxConnections: 100
|
|
625
|
+
})
|
|
626
|
+
.setResources({
|
|
627
|
+
memory: '1g',
|
|
628
|
+
cpu: 2,
|
|
629
|
+
timeout: 60000
|
|
630
|
+
})
|
|
631
|
+
// Agent image configuration
|
|
632
|
+
.setAgentImageConfig({
|
|
633
|
+
registry: 'ghcr.io',
|
|
634
|
+
namespace: 'mycompany',
|
|
635
|
+
tag: 'v1.2.0'
|
|
636
|
+
})
|
|
637
|
+
.addHandler('request_output', (data) => {
|
|
638
|
+
// Log for production monitoring
|
|
639
|
+
console.log(`[${new Date().toISOString()}] Customer Service: ${data.response.substring(0, 100)}...`);
|
|
640
|
+
}),
|
|
641
|
+
|
|
642
|
+
// Data processing agent with different registry
|
|
643
|
+
createAgent('data-processor')
|
|
644
|
+
.setLLM('openai', {
|
|
645
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
646
|
+
model: 'gpt-4',
|
|
647
|
+
temperature: 0.1
|
|
648
|
+
})
|
|
649
|
+
.setPrompt('You are a data analysis expert.')
|
|
650
|
+
.setPromptingServer({
|
|
651
|
+
protocol: 'http',
|
|
652
|
+
port: 3001,
|
|
653
|
+
authentication: false,
|
|
654
|
+
maxConnections: 50
|
|
655
|
+
})
|
|
656
|
+
.setResources({
|
|
657
|
+
memory: '2g',
|
|
658
|
+
cpu: 4,
|
|
659
|
+
timeout: 120000
|
|
660
|
+
})
|
|
661
|
+
// Different agent image configuration
|
|
662
|
+
.setAgentImageConfig({
|
|
663
|
+
registry: 'docker.io',
|
|
664
|
+
namespace: 'mycompany',
|
|
665
|
+
tag: 'latest'
|
|
666
|
+
})
|
|
667
|
+
.addHandler('request_output', (data) => {
|
|
668
|
+
console.log(`[Data Processor] Analysis completed: ${data.processingTime}ms`);
|
|
669
|
+
})
|
|
670
|
+
]
|
|
671
|
+
};
|
|
672
|
+
```
|
|
673
|
+
|
|
674
|
+
#### 🚀 **Production Build Commands**
|
|
675
|
+
|
|
676
|
+
**Basic Production Build:**
|
|
677
|
+
```bash
|
|
678
|
+
# Build all agents with their image configuration
|
|
679
|
+
dank build:prod
|
|
680
|
+
|
|
681
|
+
# Build with custom configuration file
|
|
682
|
+
dank build:prod --config production.config.js
|
|
683
|
+
```
|
|
684
|
+
|
|
685
|
+
**Registry and Tagging:**
|
|
686
|
+
```bash
|
|
687
|
+
# Build with custom tag
|
|
688
|
+
dank build:prod --tag v2.1.0
|
|
689
|
+
|
|
690
|
+
# Build for GitHub Container Registry
|
|
691
|
+
dank build:prod --registry ghcr.io --namespace myorg
|
|
692
|
+
|
|
693
|
+
# Build for Docker Hub
|
|
694
|
+
dank build:prod --registry docker.io --namespace mycompany
|
|
695
|
+
|
|
696
|
+
# Build for private registry
|
|
697
|
+
dank build:prod --registry registry.company.com --namespace ai-agents
|
|
698
|
+
```
|
|
699
|
+
|
|
700
|
+
**Push and Force Rebuild:**
|
|
701
|
+
```bash
|
|
702
|
+
# Build and push to registry
|
|
703
|
+
dank build:prod --push
|
|
704
|
+
|
|
705
|
+
# Force rebuild without cache
|
|
706
|
+
dank build:prod --force
|
|
707
|
+
|
|
708
|
+
# Force rebuild and push
|
|
709
|
+
dank build:prod --force --push
|
|
710
|
+
|
|
711
|
+
# Build with custom tag and push
|
|
712
|
+
dank build:prod --tag release-2024.1 --push
|
|
713
|
+
```
|
|
714
|
+
|
|
715
|
+
#### 🏷️ **Image Naming Convention**
|
|
716
|
+
|
|
717
|
+
**With Agent Configuration:**
|
|
718
|
+
- Format: `{registry}/{namespace}/{agent-name}:{tag}`
|
|
719
|
+
- Example: `ghcr.io/mycompany/customer-service:v1.2.0`
|
|
720
|
+
|
|
721
|
+
**With CLI Override:**
|
|
722
|
+
- CLI options override agent configuration
|
|
723
|
+
- Example: `dank build:prod --tag v2.0.0` overrides agent's tag
|
|
724
|
+
|
|
725
|
+
**Without Configuration:**
|
|
726
|
+
- Format: `{agent-name}:{tag}`
|
|
727
|
+
- Example: `customer-service:latest`
|
|
728
|
+
|
|
729
|
+
#### 🔧 **Registry Authentication**
|
|
730
|
+
|
|
731
|
+
**Docker Hub:**
|
|
732
|
+
```bash
|
|
733
|
+
# Login to Docker Hub
|
|
734
|
+
docker login
|
|
735
|
+
|
|
736
|
+
# Build and push
|
|
737
|
+
dank build:prod --registry docker.io --namespace myusername --push
|
|
738
|
+
```
|
|
739
|
+
|
|
740
|
+
**GitHub Container Registry:**
|
|
741
|
+
```bash
|
|
742
|
+
# Login to GHCR
|
|
743
|
+
echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin
|
|
744
|
+
|
|
745
|
+
# Build and push
|
|
746
|
+
dank build:prod --registry ghcr.io --namespace myorg --push
|
|
747
|
+
```
|
|
748
|
+
|
|
749
|
+
**Private Registry:**
|
|
750
|
+
```bash
|
|
751
|
+
# Login to private registry
|
|
752
|
+
docker login registry.company.com
|
|
753
|
+
|
|
754
|
+
# Build and push
|
|
755
|
+
dank build:prod --registry registry.company.com --namespace ai-agents --push
|
|
756
|
+
```
|
|
757
|
+
|
|
758
|
+
#### 📊 **Build Output Example**
|
|
759
|
+
|
|
760
|
+
```bash
|
|
761
|
+
$ dank build:prod --push
|
|
762
|
+
|
|
763
|
+
🏗️ Building production Docker images...
|
|
764
|
+
|
|
765
|
+
📦 Building production image for agent: customer-service
|
|
766
|
+
info: Building production image for agent: customer-service -> ghcr.io/mycompany/customer-service:v1.2.0
|
|
767
|
+
Step 1/3 : FROM deltadarkly/dank-agent-base:latest
|
|
768
|
+
---> 7b560f235fe3
|
|
769
|
+
Step 2/3 : COPY agent-code/ /app/agent-code/
|
|
770
|
+
---> d766de6e95c4
|
|
771
|
+
Step 3/3 : USER dankuser
|
|
772
|
+
---> Running in c773e808270c
|
|
773
|
+
Successfully built 43a664c636a2
|
|
774
|
+
Successfully tagged ghcr.io/mycompany/customer-service:v1.2.0
|
|
775
|
+
info: Production image 'ghcr.io/mycompany/customer-service:v1.2.0' built successfully
|
|
776
|
+
info: Pushing image to registry: ghcr.io/mycompany/customer-service:v1.2.0
|
|
777
|
+
info: Successfully pushed image: ghcr.io/mycompany/customer-service:v1.2.0
|
|
778
|
+
✅ Successfully built: ghcr.io/mycompany/customer-service:v1.2.0
|
|
779
|
+
🚀 Successfully pushed: ghcr.io/mycompany/customer-service:v1.2.0
|
|
780
|
+
|
|
781
|
+
📊 Build Summary:
|
|
782
|
+
================
|
|
783
|
+
✅ Successful builds: 2
|
|
784
|
+
🚀 Pushed to registry: 2
|
|
785
|
+
|
|
786
|
+
📦 Built Images:
|
|
787
|
+
- ghcr.io/mycompany/customer-service:v1.2.0
|
|
788
|
+
- docker.io/mycompany/data-processor:latest
|
|
789
|
+
|
|
790
|
+
🎉 Production build completed successfully!
|
|
791
|
+
```
|
|
792
|
+
|
|
793
|
+
#### 🔄 **CI/CD Integration**
|
|
794
|
+
|
|
795
|
+
**GitHub Actions Example:**
|
|
796
|
+
```yaml
|
|
797
|
+
name: Build and Push Production Images
|
|
798
|
+
|
|
799
|
+
on:
|
|
800
|
+
push:
|
|
801
|
+
tags:
|
|
802
|
+
- 'v*'
|
|
803
|
+
|
|
804
|
+
jobs:
|
|
805
|
+
build:
|
|
806
|
+
runs-on: ubuntu-latest
|
|
807
|
+
steps:
|
|
808
|
+
- uses: actions/checkout@v3
|
|
809
|
+
|
|
810
|
+
- name: Setup Node.js
|
|
811
|
+
uses: actions/setup-node@v3
|
|
812
|
+
with:
|
|
813
|
+
node-version: '18'
|
|
814
|
+
|
|
815
|
+
- name: Install Dank
|
|
816
|
+
run: npm install -g dank-ai
|
|
817
|
+
|
|
818
|
+
- name: Login to GHCR
|
|
819
|
+
uses: docker/login-action@v2
|
|
820
|
+
with:
|
|
821
|
+
registry: ghcr.io
|
|
822
|
+
username: ${{ github.actor }}
|
|
823
|
+
password: ${{ secrets.GITHUB_TOKEN }}
|
|
824
|
+
|
|
825
|
+
- name: Build and Push Production Images
|
|
826
|
+
run: |
|
|
827
|
+
dank build:prod \
|
|
828
|
+
--registry ghcr.io \
|
|
829
|
+
--namespace ${{ github.repository_owner }} \
|
|
830
|
+
--tag ${{ github.ref_name }} \
|
|
831
|
+
--push
|
|
832
|
+
```
|
|
833
|
+
|
|
834
|
+
**GitLab CI Example:**
|
|
835
|
+
```yaml
|
|
836
|
+
build_production:
|
|
837
|
+
stage: build
|
|
838
|
+
image: node:18
|
|
839
|
+
before_script:
|
|
840
|
+
- npm install -g dank-ai
|
|
841
|
+
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
|
842
|
+
script:
|
|
843
|
+
- dank build:prod --registry $CI_REGISTRY --namespace $CI_PROJECT_NAMESPACE --tag $CI_COMMIT_TAG --push
|
|
844
|
+
only:
|
|
845
|
+
- tags
|
|
846
|
+
```
|
|
847
|
+
|
|
848
|
+
#### 🐳 **Docker Compose Integration**
|
|
849
|
+
|
|
850
|
+
Use your production images in Docker Compose:
|
|
851
|
+
|
|
852
|
+
```yaml
|
|
853
|
+
version: '3.8'
|
|
854
|
+
|
|
855
|
+
services:
|
|
856
|
+
customer-service:
|
|
857
|
+
image: ghcr.io/mycompany/customer-service:v1.2.0
|
|
858
|
+
ports:
|
|
859
|
+
- "3000:3000"
|
|
860
|
+
environment:
|
|
861
|
+
- OPENAI_API_KEY=${OPENAI_API_KEY}
|
|
862
|
+
restart: unless-stopped
|
|
863
|
+
|
|
864
|
+
data-processor:
|
|
865
|
+
image: docker.io/mycompany/data-processor:latest
|
|
866
|
+
ports:
|
|
867
|
+
- "3001:3001"
|
|
868
|
+
environment:
|
|
869
|
+
- OPENAI_API_KEY=${OPENAI_API_KEY}
|
|
870
|
+
restart: unless-stopped
|
|
871
|
+
```
|
|
872
|
+
|
|
873
|
+
#### 🚨 **Troubleshooting Production Builds**
|
|
874
|
+
|
|
875
|
+
**Common Issues:**
|
|
876
|
+
|
|
877
|
+
1. **Registry Authentication:**
|
|
878
|
+
```bash
|
|
879
|
+
# Error: authentication required
|
|
880
|
+
# Solution: Login to registry first
|
|
881
|
+
docker login ghcr.io
|
|
882
|
+
```
|
|
883
|
+
|
|
884
|
+
2. **Push Permissions:**
|
|
885
|
+
```bash
|
|
886
|
+
# Error: denied: push access denied
|
|
887
|
+
# Solution: Check namespace permissions or use personal namespace
|
|
888
|
+
dank build:prod --namespace your-username --push
|
|
889
|
+
```
|
|
890
|
+
|
|
891
|
+
3. **Image Already Exists:**
|
|
892
|
+
```bash
|
|
893
|
+
# Error: image already exists
|
|
894
|
+
# Solution: Use different tag or force rebuild
|
|
895
|
+
dank build:prod --tag v1.2.1 --push
|
|
896
|
+
```
|
|
897
|
+
|
|
898
|
+
4. **Build Context Issues:**
|
|
899
|
+
```bash
|
|
900
|
+
# Error: build context too large
|
|
901
|
+
# Solution: Add .dockerignore file
|
|
902
|
+
echo "node_modules/" > .dockerignore
|
|
903
|
+
echo "*.log" >> .dockerignore
|
|
904
|
+
```
|
|
905
|
+
|
|
906
|
+
## 🏗️ Project Structure
|
|
907
|
+
|
|
908
|
+
```
|
|
909
|
+
my-project/
|
|
910
|
+
├── dank.config.js # Agent configuration
|
|
911
|
+
├── agents/ # Custom agent code (optional)
|
|
912
|
+
│ └── example-agent.js
|
|
913
|
+
└── .dank/ # Generated files
|
|
914
|
+
├── project.yaml # Project state
|
|
915
|
+
└── logs/ # Agent logs
|
|
916
|
+
```
|
|
917
|
+
|
|
918
|
+
## 📦 Package Exports
|
|
919
|
+
|
|
920
|
+
When you install Dank via npm, you can import the following:
|
|
921
|
+
|
|
922
|
+
```javascript
|
|
923
|
+
const {
|
|
924
|
+
createAgent, // Convenience function to create agents
|
|
925
|
+
DankAgent, // Main agent class
|
|
926
|
+
DankProject, // Project management class
|
|
927
|
+
SUPPORTED_LLMS, // List of supported LLM providers
|
|
928
|
+
DEFAULT_CONFIG // Default configuration values
|
|
929
|
+
} = require("dank");
|
|
930
|
+
```
|
|
931
|
+
|
|
932
|
+
## 📋 Example Files
|
|
933
|
+
|
|
934
|
+
The `examples/` directory contains two configuration files:
|
|
935
|
+
|
|
936
|
+
- **`dank.config.js`** - Local development example (uses `../lib/index.js`)
|
|
937
|
+
- **`dank.config.template.js`** - Production template (uses `require("dank")`)
|
|
938
|
+
|
|
939
|
+
### For Local Development
|
|
940
|
+
```bash
|
|
941
|
+
# Use the example file directly
|
|
942
|
+
dank run --config example/dank.config.js
|
|
943
|
+
```
|
|
944
|
+
|
|
945
|
+
### For Production Use
|
|
946
|
+
```bash
|
|
947
|
+
# 1. Copy the template to your project
|
|
948
|
+
cp example/dank.config.template.js ./dank.config.js
|
|
949
|
+
|
|
950
|
+
# 2. Install dank as a dependency
|
|
951
|
+
npm install dank-ai
|
|
952
|
+
|
|
953
|
+
# 3. The template already uses the correct import
|
|
954
|
+
# const { createAgent } = require("dank");
|
|
955
|
+
|
|
956
|
+
# 4. Run your agents
|
|
957
|
+
dank run
|
|
958
|
+
```
|
|
959
|
+
|
|
960
|
+
## 🐳 Docker Architecture
|
|
961
|
+
|
|
962
|
+
Dank uses a layered Docker approach:
|
|
963
|
+
|
|
964
|
+
1. **Base Image** (`deltadarkly/dank-agent-base`): Common runtime with Node.js, LLM clients
|
|
965
|
+
2. **Agent Images**: Extend base image with agent-specific code and custom tags
|
|
966
|
+
3. **Containers**: Running instances with resource limits and networking
|
|
967
|
+
|
|
968
|
+
### Container Features
|
|
969
|
+
- **Isolated Environments**: Each agent runs in its own container
|
|
970
|
+
- **Resource Limits**: Memory and CPU constraints per agent
|
|
971
|
+
- **Health Monitoring**: Built-in health checks and status reporting
|
|
972
|
+
- **Automatic Restarts**: Container restart policies for reliability
|
|
973
|
+
- **Logging**: Centralized log collection and viewing
|
|
974
|
+
|
|
975
|
+
### 🚀 Automatic Docker Management
|
|
976
|
+
|
|
977
|
+
Dank automatically handles Docker installation and startup for you:
|
|
978
|
+
|
|
979
|
+
#### **Auto-Detection & Installation**
|
|
980
|
+
When you run any Dank command, it will:
|
|
981
|
+
1. **Check if Docker is installed** - Runs `docker --version` to detect installation
|
|
982
|
+
2. **Install Docker if missing** - Automatically installs Docker for your platform:
|
|
983
|
+
- **macOS**: Uses Homebrew to install Docker Desktop
|
|
984
|
+
- **Linux**: Installs Docker CE via apt package manager
|
|
985
|
+
- **Windows**: Uses Chocolatey to install Docker Desktop
|
|
986
|
+
3. **Start Docker if stopped** - Automatically starts Docker service
|
|
987
|
+
4. **Wait for availability** - Ensures Docker is ready before proceeding
|
|
988
|
+
|
|
989
|
+
#### **Platform-Specific Installation**
|
|
990
|
+
|
|
991
|
+
**macOS:**
|
|
992
|
+
```bash
|
|
993
|
+
# Dank will automatically run:
|
|
994
|
+
brew install --cask docker
|
|
995
|
+
open -a Docker
|
|
996
|
+
```
|
|
997
|
+
|
|
998
|
+
**Linux (Ubuntu/Debian):**
|
|
999
|
+
```bash
|
|
1000
|
+
# Dank will automatically run:
|
|
1001
|
+
sudo apt-get update
|
|
1002
|
+
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
|
|
1003
|
+
sudo systemctl start docker
|
|
1004
|
+
sudo systemctl enable docker
|
|
1005
|
+
sudo usermod -aG docker $USER
|
|
1006
|
+
```
|
|
1007
|
+
|
|
1008
|
+
**Windows:**
|
|
1009
|
+
```bash
|
|
1010
|
+
# Dank will automatically run:
|
|
1011
|
+
choco install docker-desktop -y
|
|
1012
|
+
start "" "C:\Program Files\Docker\Docker\Docker Desktop.exe"
|
|
1013
|
+
```
|
|
1014
|
+
|
|
1015
|
+
#### **Manual Fallback**
|
|
1016
|
+
If automatic installation fails, Dank will provide clear instructions:
|
|
1017
|
+
```bash
|
|
1018
|
+
# Example output when manual installation is needed
|
|
1019
|
+
❌ Docker installation failed: Homebrew not found
|
|
1020
|
+
💡 Please install Docker Desktop manually from:
|
|
1021
|
+
https://www.docker.com/products/docker-desktop/
|
|
1022
|
+
```
|
|
1023
|
+
|
|
1024
|
+
#### **Status Messages**
|
|
1025
|
+
Dank provides clear feedback during the process:
|
|
1026
|
+
```bash
|
|
1027
|
+
🔍 Checking Docker availability...
|
|
1028
|
+
📦 Docker is not installed. Installing Docker...
|
|
1029
|
+
🖥️ Installing Docker Desktop for macOS...
|
|
1030
|
+
⏳ Installing Docker Desktop via Homebrew...
|
|
1031
|
+
✅ Docker installation completed
|
|
1032
|
+
🚀 Starting Docker Desktop...
|
|
1033
|
+
⏳ Waiting for Docker to become available...
|
|
1034
|
+
✅ Docker is now available
|
|
1035
|
+
🐳 Docker connection established
|
|
1036
|
+
```
|
|
1037
|
+
|
|
1038
|
+
## 💼 Using Dank in Your Project
|
|
1039
|
+
|
|
1040
|
+
### Step-by-Step Integration Guide
|
|
1041
|
+
|
|
1042
|
+
#### 1. Project Setup
|
|
1043
|
+
```bash
|
|
1044
|
+
# In your existing project directory
|
|
1045
|
+
npm install -g dank-ai
|
|
1046
|
+
|
|
1047
|
+
# Initialize Dank configuration
|
|
1048
|
+
dank init
|
|
1049
|
+
|
|
1050
|
+
# This creates dank.config.js in your current directory
|
|
1051
|
+
```
|
|
1052
|
+
|
|
1053
|
+
#### 2. Basic Agent Configuration
|
|
1054
|
+
Start with a simple agent configuration in `dank.config.js`:
|
|
1055
|
+
|
|
1056
|
+
```javascript
|
|
1057
|
+
const { createAgent } = require('dank');
|
|
1058
|
+
|
|
1059
|
+
module.exports = {
|
|
1060
|
+
name: 'my-project',
|
|
1061
|
+
|
|
1062
|
+
agents: [
|
|
1063
|
+
// Simple assistant agent
|
|
1064
|
+
createAgent('helper')
|
|
1065
|
+
.setLLM('openai', {
|
|
1066
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
1067
|
+
model: 'gpt-3.5-turbo'
|
|
1068
|
+
})
|
|
1069
|
+
.setPrompt('You are a helpful assistant.')
|
|
1070
|
+
.addHandler('output', console.log)
|
|
1071
|
+
]
|
|
1072
|
+
};
|
|
1073
|
+
```
|
|
1074
|
+
|
|
1075
|
+
#### 3. Multi-Agent Setup
|
|
1076
|
+
Configure multiple specialized agents:
|
|
1077
|
+
|
|
1078
|
+
```javascript
|
|
1079
|
+
const { createAgent } = require('dank');
|
|
1080
|
+
|
|
1081
|
+
module.exports = {
|
|
1082
|
+
name: 'multi-agent-system',
|
|
1083
|
+
|
|
1084
|
+
agents: [
|
|
1085
|
+
// Customer service agent
|
|
1086
|
+
createAgent('customer-service')
|
|
1087
|
+
.setLLM('openai', {
|
|
1088
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
1089
|
+
model: 'gpt-3.5-turbo',
|
|
1090
|
+
temperature: 0.7
|
|
1091
|
+
})
|
|
1092
|
+
.setPrompt(`
|
|
1093
|
+
You are a friendly customer service representative.
|
|
1094
|
+
- Be helpful and professional
|
|
1095
|
+
- Resolve customer issues quickly
|
|
1096
|
+
- Escalate complex problems appropriately
|
|
1097
|
+
`)
|
|
1098
|
+
.setResources({ memory: '512m', cpu: 1 })
|
|
1099
|
+
.addHandler('output', (data) => {
|
|
1100
|
+
console.log('[Customer Service]:', data);
|
|
1101
|
+
// Add your business logic here
|
|
1102
|
+
}),
|
|
1103
|
+
|
|
1104
|
+
// Data analyst agent
|
|
1105
|
+
createAgent('analyst')
|
|
1106
|
+
.setLLM('openai', {
|
|
1107
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
1108
|
+
model: 'gpt-4',
|
|
1109
|
+
temperature: 0.3
|
|
1110
|
+
})
|
|
1111
|
+
.setPrompt(`
|
|
1112
|
+
You are a data analyst expert.
|
|
1113
|
+
- Analyze trends and patterns
|
|
1114
|
+
- Provide statistical insights
|
|
1115
|
+
- Create actionable recommendations
|
|
1116
|
+
`)
|
|
1117
|
+
.setResources({ memory: '1g', cpu: 2 })
|
|
1118
|
+
.addHandler('output', (data) => {
|
|
1119
|
+
console.log('[Analyst]:', data);
|
|
1120
|
+
// Save analysis results to database
|
|
1121
|
+
}),
|
|
1122
|
+
|
|
1123
|
+
// Content creator agent
|
|
1124
|
+
createAgent('content-creator')
|
|
1125
|
+
.setLLM('anthropic', {
|
|
1126
|
+
apiKey: process.env.ANTHROPIC_API_KEY,
|
|
1127
|
+
model: 'claude-3-sonnet-20240229'
|
|
1128
|
+
})
|
|
1129
|
+
.setPrompt(`
|
|
1130
|
+
You are a creative content writer.
|
|
1131
|
+
- Write engaging, original content
|
|
1132
|
+
- Adapt tone to target audience
|
|
1133
|
+
- Follow brand guidelines
|
|
1134
|
+
`)
|
|
1135
|
+
.setResources({ memory: '512m', cpu: 1 })
|
|
1136
|
+
.addHandler('output', (data) => {
|
|
1137
|
+
console.log('[Content Creator]:', data);
|
|
1138
|
+
// Process and publish content
|
|
1139
|
+
})
|
|
1140
|
+
]
|
|
1141
|
+
};
|
|
1142
|
+
```
|
|
1143
|
+
|
|
1144
|
+
### 🎯 Common Use Cases
|
|
1145
|
+
|
|
1146
|
+
#### Use Case 1: Customer Support Automation
|
|
1147
|
+
```javascript
|
|
1148
|
+
createAgent('support-bot')
|
|
1149
|
+
.setLLM('openai', {
|
|
1150
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
1151
|
+
model: 'gpt-3.5-turbo'
|
|
1152
|
+
})
|
|
1153
|
+
.setPrompt(`
|
|
1154
|
+
You are a customer support specialist for [Your Company].
|
|
1155
|
+
|
|
1156
|
+
Guidelines:
|
|
1157
|
+
- Always be polite and helpful
|
|
1158
|
+
- For technical issues, provide step-by-step solutions
|
|
1159
|
+
- If you cannot resolve an issue, escalate to human support
|
|
1160
|
+
- Use the customer's name when available
|
|
1161
|
+
|
|
1162
|
+
Knowledge Base:
|
|
1163
|
+
- Product features: [list your features]
|
|
1164
|
+
- Common issues: [list common problems and solutions]
|
|
1165
|
+
- Contact info: support@yourcompany.com
|
|
1166
|
+
`)
|
|
1167
|
+
.addHandler('output', (response) => {
|
|
1168
|
+
// Send response back to customer via your chat system
|
|
1169
|
+
sendToCustomer(response);
|
|
1170
|
+
})
|
|
1171
|
+
.addHandler('error', (error) => {
|
|
1172
|
+
// Fallback to human support
|
|
1173
|
+
escalateToHuman(error);
|
|
1174
|
+
});
|
|
1175
|
+
```
|
|
1176
|
+
|
|
1177
|
+
#### Use Case 2: Content Generation Pipeline
|
|
1178
|
+
```javascript
|
|
1179
|
+
const contentAgents = [
|
|
1180
|
+
// Research agent
|
|
1181
|
+
createAgent('researcher')
|
|
1182
|
+
.setLLM('openai', { model: 'gpt-4' })
|
|
1183
|
+
.setPrompt('Research and gather information on given topics')
|
|
1184
|
+
.addHandler('output', (research) => {
|
|
1185
|
+
// Pass research to writer agent
|
|
1186
|
+
triggerContentCreation(research);
|
|
1187
|
+
}),
|
|
1188
|
+
|
|
1189
|
+
// Writer agent
|
|
1190
|
+
createAgent('writer')
|
|
1191
|
+
.setLLM('anthropic', { model: 'claude-3-sonnet' })
|
|
1192
|
+
.setPrompt('Write engaging blog posts based on research data')
|
|
1193
|
+
.addHandler('output', (article) => {
|
|
1194
|
+
// Save draft and notify editor
|
|
1195
|
+
saveDraft(article);
|
|
1196
|
+
notifyEditor(article);
|
|
1197
|
+
}),
|
|
1198
|
+
|
|
1199
|
+
// SEO optimizer agent
|
|
1200
|
+
createAgent('seo-optimizer')
|
|
1201
|
+
.setLLM('openai', { model: 'gpt-3.5-turbo' })
|
|
1202
|
+
.setPrompt('Optimize content for SEO and readability')
|
|
1203
|
+
.addHandler('output', (optimizedContent) => {
|
|
1204
|
+
// Publish optimized content
|
|
1205
|
+
publishContent(optimizedContent);
|
|
1206
|
+
})
|
|
1207
|
+
];
|
|
1208
|
+
```
|
|
1209
|
+
|
|
1210
|
+
#### Use Case 3: Data Analysis Workflow
|
|
1211
|
+
```javascript
|
|
1212
|
+
createAgent('data-processor')
|
|
1213
|
+
.setLLM('openai', {
|
|
1214
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
1215
|
+
model: 'gpt-4',
|
|
1216
|
+
temperature: 0.1 // Low temperature for consistent analysis
|
|
1217
|
+
})
|
|
1218
|
+
.setPrompt(`
|
|
1219
|
+
You are a data analyst. Analyze the provided data and:
|
|
1220
|
+
1. Identify key trends and patterns
|
|
1221
|
+
2. Calculate important metrics
|
|
1222
|
+
3. Provide actionable insights
|
|
1223
|
+
4. Format results as JSON
|
|
1224
|
+
`)
|
|
1225
|
+
.setResources({
|
|
1226
|
+
memory: '2g', // More memory for data processing
|
|
1227
|
+
cpu: 2, // More CPU for complex calculations
|
|
1228
|
+
timeout: 120000 // Longer timeout for large datasets
|
|
1229
|
+
})
|
|
1230
|
+
.addHandler('output', (analysis) => {
|
|
1231
|
+
try {
|
|
1232
|
+
const results = JSON.parse(analysis);
|
|
1233
|
+
// Store results in database
|
|
1234
|
+
saveAnalysisResults(results);
|
|
1235
|
+
// Generate reports
|
|
1236
|
+
generateReport(results);
|
|
1237
|
+
// Send alerts if thresholds are met
|
|
1238
|
+
checkAlerts(results);
|
|
1239
|
+
} catch (error) {
|
|
1240
|
+
console.error('Failed to parse analysis:', error);
|
|
1241
|
+
}
|
|
1242
|
+
});
|
|
1243
|
+
```
|
|
1244
|
+
|
|
1245
|
+
### 🔧 Advanced Configuration
|
|
1246
|
+
|
|
1247
|
+
#### Custom Agent Code
|
|
1248
|
+
For complex logic, create custom agent files in the `agents/` directory:
|
|
1249
|
+
|
|
1250
|
+
```javascript
|
|
1251
|
+
// agents/custom-agent.js
|
|
1252
|
+
module.exports = {
|
|
1253
|
+
async main(llmClient, handlers) {
|
|
1254
|
+
console.log('Custom agent starting...');
|
|
1255
|
+
|
|
1256
|
+
// Your custom agent logic
|
|
1257
|
+
setInterval(async () => {
|
|
1258
|
+
try {
|
|
1259
|
+
// Make LLM request
|
|
1260
|
+
const response = await llmClient.chat.completions.create({
|
|
1261
|
+
model: 'gpt-3.5-turbo',
|
|
1262
|
+
messages: [
|
|
1263
|
+
{ role: 'system', content: 'You are a helpful assistant' },
|
|
1264
|
+
{ role: 'user', content: 'Generate a daily report' }
|
|
1265
|
+
]
|
|
1266
|
+
});
|
|
1267
|
+
|
|
1268
|
+
// Trigger output handlers
|
|
1269
|
+
const outputHandlers = handlers.get('output') || [];
|
|
1270
|
+
outputHandlers.forEach(handler =>
|
|
1271
|
+
handler(response.choices[0].message.content)
|
|
1272
|
+
);
|
|
1273
|
+
|
|
1274
|
+
} catch (error) {
|
|
1275
|
+
// Trigger error handlers
|
|
1276
|
+
const errorHandlers = handlers.get('error') || [];
|
|
1277
|
+
errorHandlers.forEach(handler => handler(error));
|
|
1278
|
+
}
|
|
1279
|
+
}, 60000); // Run every minute
|
|
1280
|
+
},
|
|
1281
|
+
|
|
1282
|
+
// Define custom handlers
|
|
1283
|
+
handlers: {
|
|
1284
|
+
output: [
|
|
1285
|
+
(data) => console.log('Custom output:', data)
|
|
1286
|
+
],
|
|
1287
|
+
error: [
|
|
1288
|
+
(error) => console.error('Custom error:', error)
|
|
1289
|
+
]
|
|
1290
|
+
}
|
|
1291
|
+
};
|
|
1292
|
+
```
|
|
1293
|
+
|
|
1294
|
+
#### Environment-Specific Configuration
|
|
1295
|
+
```javascript
|
|
1296
|
+
// dank.config.js
|
|
1297
|
+
const { createAgent } = require('dank');
|
|
1298
|
+
|
|
1299
|
+
const isDevelopment = process.env.NODE_ENV === 'development';
|
|
1300
|
+
const isProduction = process.env.NODE_ENV === 'production';
|
|
1301
|
+
|
|
1302
|
+
module.exports = {
|
|
1303
|
+
name: 'my-project',
|
|
1304
|
+
|
|
1305
|
+
agents: [
|
|
1306
|
+
createAgent('main-agent')
|
|
1307
|
+
.setLLM('openai', {
|
|
1308
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
1309
|
+
model: isDevelopment ? 'gpt-3.5-turbo' : 'gpt-4',
|
|
1310
|
+
temperature: isDevelopment ? 0.9 : 0.7
|
|
1311
|
+
})
|
|
1312
|
+
.setResources({
|
|
1313
|
+
memory: isDevelopment ? '256m' : '1g',
|
|
1314
|
+
cpu: isDevelopment ? 0.5 : 2
|
|
1315
|
+
})
|
|
1316
|
+
.addHandler('output', (data) => {
|
|
1317
|
+
if (isDevelopment) {
|
|
1318
|
+
console.log('DEV:', data);
|
|
1319
|
+
} else {
|
|
1320
|
+
// Production logging
|
|
1321
|
+
logger.info('Agent output', { data });
|
|
1322
|
+
}
|
|
1323
|
+
})
|
|
1324
|
+
]
|
|
1325
|
+
};
|
|
1326
|
+
```
|
|
1327
|
+
|
|
1328
|
+
### 🔧 Advanced Usage
|
|
1329
|
+
|
|
1330
|
+
#### Environment Variables
|
|
1331
|
+
```bash
|
|
1332
|
+
export OPENAI_API_KEY="your-key"
|
|
1333
|
+
export ANTHROPIC_API_KEY="your-key"
|
|
1334
|
+
export LOG_LEVEL="debug"
|
|
1335
|
+
export DOCKER_HOST="unix:///var/run/docker.sock"
|
|
1336
|
+
export NODE_ENV="production"
|
|
1337
|
+
```
|
|
1338
|
+
|
|
1339
|
+
#### Integration with Existing Applications
|
|
1340
|
+
```javascript
|
|
1341
|
+
// In your existing Node.js application
|
|
1342
|
+
const { spawn } = require('child_process');
|
|
1343
|
+
|
|
1344
|
+
// Start Dank agents programmatically
|
|
1345
|
+
function startAgents() {
|
|
1346
|
+
const dankProcess = spawn('dank', ['run', '--detached'], {
|
|
1347
|
+
stdio: 'inherit',
|
|
1348
|
+
env: { ...process.env, NODE_ENV: 'production' }
|
|
1349
|
+
});
|
|
1350
|
+
|
|
1351
|
+
dankProcess.on('close', (code) => {
|
|
1352
|
+
console.log(`Dank agents exited with code ${code}`);
|
|
1353
|
+
});
|
|
1354
|
+
|
|
1355
|
+
return dankProcess;
|
|
1356
|
+
}
|
|
1357
|
+
|
|
1358
|
+
// Stop agents gracefully
|
|
1359
|
+
function stopAgents() {
|
|
1360
|
+
spawn('dank', ['stop', '--all'], { stdio: 'inherit' });
|
|
1361
|
+
}
|
|
1362
|
+
|
|
1363
|
+
// Check agent status
|
|
1364
|
+
async function getAgentStatus() {
|
|
1365
|
+
return new Promise((resolve) => {
|
|
1366
|
+
const statusProcess = spawn('dank', ['status', '--json'], {
|
|
1367
|
+
stdio: ['pipe', 'pipe', 'pipe']
|
|
1368
|
+
});
|
|
1369
|
+
|
|
1370
|
+
let output = '';
|
|
1371
|
+
statusProcess.stdout.on('data', (data) => {
|
|
1372
|
+
output += data.toString();
|
|
1373
|
+
});
|
|
1374
|
+
|
|
1375
|
+
statusProcess.on('close', () => {
|
|
1376
|
+
try {
|
|
1377
|
+
resolve(JSON.parse(output));
|
|
1378
|
+
} catch {
|
|
1379
|
+
resolve(null);
|
|
1380
|
+
}
|
|
1381
|
+
});
|
|
1382
|
+
});
|
|
1383
|
+
}
|
|
1384
|
+
```
|
|
1385
|
+
|
|
1386
|
+
### 🚨 Troubleshooting
|
|
1387
|
+
|
|
1388
|
+
#### Common Issues and Solutions
|
|
1389
|
+
|
|
1390
|
+
**1. Docker Connection Issues**
|
|
1391
|
+
```bash
|
|
1392
|
+
# Error: Cannot connect to Docker daemon
|
|
1393
|
+
# Solution: Dank will automatically handle this!
|
|
1394
|
+
|
|
1395
|
+
# If automatic installation fails, manual steps:
|
|
1396
|
+
docker --version
|
|
1397
|
+
docker ps
|
|
1398
|
+
|
|
1399
|
+
# On macOS/Windows: Start Docker Desktop manually
|
|
1400
|
+
# On Linux: Start Docker service
|
|
1401
|
+
sudo systemctl start docker
|
|
1402
|
+
```
|
|
1403
|
+
|
|
1404
|
+
**1a. Docker Installation Issues**
|
|
1405
|
+
```bash
|
|
1406
|
+
# If automatic installation fails, try manual installation:
|
|
1407
|
+
|
|
1408
|
+
# macOS (with Homebrew):
|
|
1409
|
+
brew install --cask docker
|
|
1410
|
+
open -a Docker
|
|
1411
|
+
|
|
1412
|
+
# Linux (Ubuntu/Debian):
|
|
1413
|
+
sudo apt-get update
|
|
1414
|
+
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
|
|
1415
|
+
sudo systemctl start docker
|
|
1416
|
+
sudo usermod -aG docker $USER
|
|
1417
|
+
|
|
1418
|
+
# Windows (with Chocolatey):
|
|
1419
|
+
choco install docker-desktop -y
|
|
1420
|
+
# Then start Docker Desktop from Start Menu
|
|
1421
|
+
```
|
|
1422
|
+
|
|
1423
|
+
**2. API Key Issues**
|
|
1424
|
+
```bash
|
|
1425
|
+
# Error: Invalid API key
|
|
1426
|
+
# Solution: Check your environment variables
|
|
1427
|
+
echo $OPENAI_API_KEY
|
|
1428
|
+
|
|
1429
|
+
# Set the key properly
|
|
1430
|
+
export OPENAI_API_KEY="sk-your-actual-key-here"
|
|
1431
|
+
|
|
1432
|
+
# Or create a .env file in your project
|
|
1433
|
+
echo "OPENAI_API_KEY=sk-your-actual-key-here" > .env
|
|
1434
|
+
```
|
|
1435
|
+
|
|
1436
|
+
**3. Base Image Not Found**
|
|
1437
|
+
```bash
|
|
1438
|
+
# Error: Base image 'deltadarkly/dank-agent-base' not found
|
|
1439
|
+
# Solution: The base image is pulled automatically, but you can build it manually
|
|
1440
|
+
dank build --base
|
|
1441
|
+
```
|
|
1442
|
+
|
|
1443
|
+
**4. Container Resource Issues**
|
|
1444
|
+
```bash
|
|
1445
|
+
# Error: Container exits with code 137 (out of memory)
|
|
1446
|
+
# Solution: Increase memory allocation
|
|
1447
|
+
createAgent('my-agent')
|
|
1448
|
+
.setResources({
|
|
1449
|
+
memory: '1g', // Increase from 512m to 1g
|
|
1450
|
+
cpu: 2
|
|
1451
|
+
})
|
|
1452
|
+
```
|
|
1453
|
+
|
|
1454
|
+
**5. Agent Not Starting**
|
|
1455
|
+
```bash
|
|
1456
|
+
# Check agent logs for detailed error information
|
|
1457
|
+
dank logs agent-name
|
|
1458
|
+
|
|
1459
|
+
# Check container status
|
|
1460
|
+
docker ps -f name=dank-
|
|
1461
|
+
|
|
1462
|
+
# View Docker logs directly
|
|
1463
|
+
docker logs container-id
|
|
1464
|
+
```
|
|
1465
|
+
|
|
1466
|
+
### 💡 Best Practices
|
|
1467
|
+
|
|
1468
|
+
#### 1. Resource Management
|
|
1469
|
+
```javascript
|
|
1470
|
+
// Good: Appropriate resource allocation
|
|
1471
|
+
createAgent('light-agent')
|
|
1472
|
+
.setResources({
|
|
1473
|
+
memory: '256m', // Light tasks
|
|
1474
|
+
cpu: 0.5
|
|
1475
|
+
});
|
|
1476
|
+
|
|
1477
|
+
createAgent('heavy-agent')
|
|
1478
|
+
.setResources({
|
|
1479
|
+
memory: '2g', // Heavy processing
|
|
1480
|
+
cpu: 2,
|
|
1481
|
+
timeout: 120000 // Longer timeout
|
|
1482
|
+
});
|
|
1483
|
+
```
|
|
1484
|
+
|
|
1485
|
+
#### 2. Error Handling
|
|
1486
|
+
```javascript
|
|
1487
|
+
// Good: Comprehensive error handling
|
|
1488
|
+
createAgent('robust-agent')
|
|
1489
|
+
.addHandler('error', (error) => {
|
|
1490
|
+
console.error('Agent error:', error.message);
|
|
1491
|
+
|
|
1492
|
+
// Log to monitoring system
|
|
1493
|
+
logError(error);
|
|
1494
|
+
|
|
1495
|
+
// Send alert if critical
|
|
1496
|
+
if (error.type === 'CRITICAL') {
|
|
1497
|
+
sendAlert(error);
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
// Implement retry logic
|
|
1501
|
+
scheduleRetry(error.context);
|
|
1502
|
+
})
|
|
1503
|
+
.addHandler('output', (data) => {
|
|
1504
|
+
try {
|
|
1505
|
+
processOutput(data);
|
|
1506
|
+
} catch (error) {
|
|
1507
|
+
console.error('Output processing failed:', error);
|
|
1508
|
+
}
|
|
1509
|
+
});
|
|
1510
|
+
```
|
|
1511
|
+
|
|
1512
|
+
#### 3. Environment Configuration
|
|
1513
|
+
```javascript
|
|
1514
|
+
// Good: Environment-specific settings
|
|
1515
|
+
const config = {
|
|
1516
|
+
development: {
|
|
1517
|
+
model: 'gpt-3.5-turbo',
|
|
1518
|
+
memory: '256m',
|
|
1519
|
+
logLevel: 'debug'
|
|
1520
|
+
},
|
|
1521
|
+
production: {
|
|
1522
|
+
model: 'gpt-4',
|
|
1523
|
+
memory: '1g',
|
|
1524
|
+
logLevel: 'info'
|
|
1525
|
+
}
|
|
1526
|
+
};
|
|
1527
|
+
|
|
1528
|
+
const env = process.env.NODE_ENV || 'development';
|
|
1529
|
+
const settings = config[env];
|
|
1530
|
+
|
|
1531
|
+
createAgent('environment-aware')
|
|
1532
|
+
.setLLM('openai', {
|
|
1533
|
+
model: settings.model,
|
|
1534
|
+
temperature: 0.7
|
|
1535
|
+
})
|
|
1536
|
+
.setResources({
|
|
1537
|
+
memory: settings.memory
|
|
1538
|
+
});
|
|
1539
|
+
```
|
|
1540
|
+
|
|
1541
|
+
#### 4. Monitoring and Logging
|
|
1542
|
+
```javascript
|
|
1543
|
+
// Good: Structured logging
|
|
1544
|
+
createAgent('monitored-agent')
|
|
1545
|
+
.addHandler('output', (data) => {
|
|
1546
|
+
logger.info('Agent output', {
|
|
1547
|
+
agent: 'monitored-agent',
|
|
1548
|
+
timestamp: new Date().toISOString(),
|
|
1549
|
+
data: data.substring(0, 100) // Truncate for logs
|
|
1550
|
+
});
|
|
1551
|
+
})
|
|
1552
|
+
.addHandler('error', (error) => {
|
|
1553
|
+
logger.error('Agent error', {
|
|
1554
|
+
agent: 'monitored-agent',
|
|
1555
|
+
error: error.message,
|
|
1556
|
+
stack: error.stack
|
|
1557
|
+
});
|
|
1558
|
+
})
|
|
1559
|
+
.addHandler('start', () => {
|
|
1560
|
+
logger.info('Agent started', { agent: 'monitored-agent' });
|
|
1561
|
+
});
|
|
1562
|
+
```
|
|
1563
|
+
|
|
1564
|
+
#### 5. Security Considerations
|
|
1565
|
+
```javascript
|
|
1566
|
+
// Good: Secure configuration
|
|
1567
|
+
createAgent('secure-agent')
|
|
1568
|
+
.setLLM('openai', {
|
|
1569
|
+
apiKey: process.env.OPENAI_API_KEY, // Never hardcode keys
|
|
1570
|
+
model: 'gpt-3.5-turbo'
|
|
1571
|
+
})
|
|
1572
|
+
.setPrompt(`
|
|
1573
|
+
You are a helpful assistant.
|
|
1574
|
+
|
|
1575
|
+
IMPORTANT SECURITY RULES:
|
|
1576
|
+
- Never reveal API keys or sensitive information
|
|
1577
|
+
- Don't execute system commands
|
|
1578
|
+
- Validate all inputs before processing
|
|
1579
|
+
- Don't access external URLs unless explicitly allowed
|
|
1580
|
+
`)
|
|
1581
|
+
.addHandler('output', (data) => {
|
|
1582
|
+
// Sanitize output before logging
|
|
1583
|
+
const sanitized = sanitizeOutput(data);
|
|
1584
|
+
console.log(sanitized);
|
|
1585
|
+
});
|
|
1586
|
+
```
|
|
1587
|
+
|
|
1588
|
+
### 📊 Performance Optimization
|
|
1589
|
+
|
|
1590
|
+
#### 1. Resource Tuning
|
|
1591
|
+
```bash
|
|
1592
|
+
# Monitor resource usage
|
|
1593
|
+
dank status --watch
|
|
1594
|
+
|
|
1595
|
+
# Check container stats
|
|
1596
|
+
docker stats $(docker ps -f name=dank- -q)
|
|
1597
|
+
|
|
1598
|
+
# Optimize based on usage patterns
|
|
1599
|
+
```
|
|
1600
|
+
|
|
1601
|
+
#### 2. Parallel Agent Management
|
|
1602
|
+
```javascript
|
|
1603
|
+
// Good: Balanced agent distribution
|
|
1604
|
+
module.exports = {
|
|
1605
|
+
agents: [
|
|
1606
|
+
// CPU-intensive agents
|
|
1607
|
+
createAgent('analyzer').setResources({ cpu: 2, memory: '1g' }),
|
|
1608
|
+
|
|
1609
|
+
// Memory-intensive agents
|
|
1610
|
+
createAgent('processor').setResources({ cpu: 1, memory: '2g' }),
|
|
1611
|
+
|
|
1612
|
+
// Light agents
|
|
1613
|
+
createAgent('notifier').setResources({ cpu: 0.5, memory: '256m' })
|
|
1614
|
+
]
|
|
1615
|
+
};
|
|
1616
|
+
```
|
|
1617
|
+
|
|
1618
|
+
#### 3. Efficient Prompt Design
|
|
1619
|
+
```javascript
|
|
1620
|
+
// Good: Clear, specific prompts
|
|
1621
|
+
.setPrompt(`
|
|
1622
|
+
You are a customer service agent. Follow these steps:
|
|
1623
|
+
|
|
1624
|
+
1. Greet the customer politely
|
|
1625
|
+
2. Understand their issue by asking clarifying questions
|
|
1626
|
+
3. Provide a solution or escalate if needed
|
|
1627
|
+
4. Confirm resolution
|
|
1628
|
+
|
|
1629
|
+
Response format: JSON with fields: greeting, questions, solution, status
|
|
1630
|
+
`);
|
|
1631
|
+
```
|
|
1632
|
+
|
|
1633
|
+
### 🔄 Development Workflow
|
|
1634
|
+
|
|
1635
|
+
#### 1. Local Development
|
|
1636
|
+
```bash
|
|
1637
|
+
# 1. Start with development configuration
|
|
1638
|
+
NODE_ENV=development dank run
|
|
1639
|
+
|
|
1640
|
+
# 2. Make changes to dank.config.js
|
|
1641
|
+
|
|
1642
|
+
# 3. Restart agents to apply changes
|
|
1643
|
+
dank stop --all
|
|
1644
|
+
dank run --build # Rebuild if needed
|
|
1645
|
+
|
|
1646
|
+
# 4. Test with reduced resources
|
|
1647
|
+
createAgent('dev-agent').setResources({ memory: '128m', cpu: 0.25 })
|
|
1648
|
+
```
|
|
1649
|
+
|
|
1650
|
+
#### 2. Testing Agents
|
|
1651
|
+
```bash
|
|
1652
|
+
# Test individual agents
|
|
1653
|
+
dank run --detached
|
|
1654
|
+
dank logs test-agent --follow
|
|
1655
|
+
|
|
1656
|
+
# Check health endpoints
|
|
1657
|
+
curl http://localhost:3001/health
|
|
1658
|
+
|
|
1659
|
+
# Monitor resource usage
|
|
1660
|
+
docker stats dank-test-agent
|
|
1661
|
+
```
|
|
1662
|
+
|
|
1663
|
+
#### 3. Production Deployment
|
|
1664
|
+
```bash
|
|
1665
|
+
# 1. Set production environment
|
|
1666
|
+
export NODE_ENV=production
|
|
1667
|
+
|
|
1668
|
+
# 2. Build optimized images
|
|
1669
|
+
dank build --force
|
|
1670
|
+
|
|
1671
|
+
# 3. Start with image config
|
|
1672
|
+
dank run --detached
|
|
1673
|
+
|
|
1674
|
+
# 4. Monitor and scale as needed
|
|
1675
|
+
dank status --watch
|
|
1676
|
+
```
|
|
1677
|
+
|
|
1678
|
+
### Monitoring and Debugging
|
|
1679
|
+
|
|
1680
|
+
```bash
|
|
1681
|
+
# Watch all agents in real-time
|
|
1682
|
+
dank status --watch
|
|
1683
|
+
|
|
1684
|
+
# Follow logs from specific agent
|
|
1685
|
+
dank logs my-agent --follow
|
|
1686
|
+
|
|
1687
|
+
# View container details
|
|
1688
|
+
docker ps -f name=dank-
|
|
1689
|
+
|
|
1690
|
+
# Check agent health
|
|
1691
|
+
curl http://localhost:3001/health
|
|
1692
|
+
```
|
|
1693
|
+
|
|
1694
|
+
## 📦 Installation
|
|
1695
|
+
|
|
1696
|
+
### Prerequisites
|
|
1697
|
+
- Node.js 16+
|
|
1698
|
+
- Docker Desktop or Docker Engine
|
|
1699
|
+
- npm or yarn
|
|
1700
|
+
|
|
1701
|
+
### Global Installation
|
|
1702
|
+
```bash
|
|
1703
|
+
npm install -g dank-ai
|
|
1704
|
+
```
|
|
1705
|
+
|
|
1706
|
+
### Local Development
|
|
1707
|
+
```bash
|
|
1708
|
+
git clone https://github.com/your-org/dank
|
|
1709
|
+
cd dank
|
|
1710
|
+
npm install
|
|
1711
|
+
npm link # Creates global symlink
|
|
1712
|
+
```
|
|
1713
|
+
|
|
1714
|
+
## 🤝 Contributing
|
|
1715
|
+
|
|
1716
|
+
1. Fork the repository
|
|
1717
|
+
2. Create a feature branch: `git checkout -b feature/amazing-feature`
|
|
1718
|
+
3. Commit changes: `git commit -m 'Add amazing feature'`
|
|
1719
|
+
4. Push to branch: `git push origin feature/amazing-feature`
|
|
1720
|
+
5. Open a Pull Request
|
|
92
1721
|
|
|
93
|
-
|
|
1722
|
+
## 📄 License
|
|
94
1723
|
|
|
95
|
-
-
|
|
96
|
-
- Set up LLM providers and models
|
|
97
|
-
- Configure event handlers
|
|
98
|
-
- Set Docker and resource limits
|
|
99
|
-
- Enable/disable communication features
|
|
1724
|
+
ISC License - see LICENSE file for details.
|
|
100
1725
|
|
|
101
|
-
##
|
|
1726
|
+
## 🆘 Support
|
|
102
1727
|
|
|
103
|
-
|
|
1728
|
+
- **Documentation**: [Wiki](https://github.com/your-org/dank/wiki)
|
|
1729
|
+
- **Issues**: [GitHub Issues](https://github.com/your-org/dank/issues)
|
|
1730
|
+
- **Discussions**: [GitHub Discussions](https://github.com/your-org/dank/discussions)
|
|
104
1731
|
|
|
105
|
-
|
|
1732
|
+
---
|
|
106
1733
|
|
|
107
|
-
|
|
1734
|
+
**Built with 💯 energy for the AI agent revolution!** 🚀
|