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