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 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-ai.xyz](https://dank-ai.xyz)
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-ai.xyz](https://cloud.dank-ai.xyz) - **Serverless for AI Agents**
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-ai.xyz](https://cloud.dank-ai.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.
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** (will be installed automatically if missing)
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 will automatically detect, install, and start Docker if it's not available on your system. No manual setup required!
41
+ > **🆕 Auto-Docker Installation**: Dank automatically detects, installs, and starts Docker if unavailable. No manual setup required!
41
42
 
42
- ### 1. Install Dank globally
43
- ```bash
44
- npm install -g dank-ai
45
- ```
43
+ ### Installation & Setup
46
44
 
47
- ### 2. Initialize a new project
48
45
  ```bash
49
- # Create and navigate to your project directory
50
- mkdir my-agent-project
51
- cd my-agent-project
46
+ # 1. Install globally
47
+ npm install -g dank-ai
52
48
 
53
- # Initialize Dank project
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
- This creates:
67
+ <details>
68
+ <summary><b>📁 Project Structure</b></summary>
69
+
58
70
  ```
59
- my-agent-project/
60
- ├── dank.config.js # Your agent configuration
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
- └── project.yaml
76
+ ├── project.yaml # Project state
77
+ └── logs/ # Agent logs
65
78
  ```
79
+ </details>
66
80
 
67
- ### 3. Set up environment variables
68
- Create a `.env` file or export environment variables:
81
+ ## 📋 CLI Commands
69
82
 
83
+ ### Core Commands
70
84
  ```bash
71
- # For OpenAI
72
- export OPENAI_API_KEY="your-openai-api-key"
73
-
74
- # For Anthropic
75
- export ANTHROPIC_API_KEY="your-anthropic-api-key"
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
- # For Cohere
78
- export COHERE_API_KEY="your-cohere-api-key"
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
- ### 4. Configure your agents
82
- Edit `dank.config.js` to define your agents:
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
- const { createAgent } = require('dank');
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-agent-project',
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 that responds with enthusiasm!')
98
- .setInstanceType('small')
99
- .addHandler('output', (data) => {
100
- console.log('Assistant says:', data);
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
- ### 5. Build Docker images (optional)
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
- ### 6. Start your agents
112
- ```bash
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
- ### 7. Monitor your agents
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
- const agent = createAgent('my-agent')
208
- .setLLM('openai', {
209
- apiKey: process.env.OPENAI_API_KEY,
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
- HTTP automatically enables when you add routes. Here's a simple "Hello World" POST endpoint:
158
+ // Multiline .then() is also supported
159
+ const ora = import("ora").then((m) => {
160
+ return m.default;
161
+ });
225
162
 
226
- ```javascript
227
- const agent = createAgent('hello-agent')
228
- .setLLM('openai', {
229
- apiKey: process.env.OPENAI_API_KEY,
230
- model: 'gpt-3.5-turbo'
231
- })
232
- .setPromptingServer({
233
- port: 3000
234
- })
235
- // Add a POST endpoint (HTTP auto-enables)
236
- .post('/hello', (req, res) => {
237
- res.json({
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
- **Test it:**
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
- **Response:**
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
- #### OpenAI
264
- ```javascript
265
- .setLLM('openai', {
266
- apiKey: 'your-api-key',
267
- model: 'gpt-4',
268
- temperature: 0.7,
269
- maxTokens: 1000
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
- #### Anthropic
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
- #### Ollama (Local)
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
- .setLLM('cohere', {
293
- apiKey: 'your-api-key',
294
- model: 'command',
295
- temperature: 0.7
296
- })
297
- ```
298
-
299
- #### Hugging Face
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
- Dank provides a comprehensive event system with three main sources of events. Each event handler follows specific naming patterns for maximum flexibility and control.
319
-
320
- > **🆕 Auto-Detection**: Dank automatically enables communication features based on your usage:
321
- > - **Event Handlers**: Auto-enabled when you add `.addHandler()` calls
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
- #### 🎯 **Event Handler Patterns**
214
+ <details>
215
+ <summary><b>📡 Event Handler Patterns</b></summary>
326
216
 
327
- ##### **1. Direct Prompting Events** (`request_output`)
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 LLM response event
221
+ // Main response event
333
222
  .addHandler('request_output', (data) => {
334
- console.log('LLM Response:', {
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
- // Lifecycle events with modification capabilities
226
+ // Modify prompt before LLM processing
347
227
  .addHandler('request_output:start', (data) => {
348
- console.log('Processing prompt:', data.conversationId);
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
- console.log('Completed in:', data.processingTime + 'ms');
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('Prompt processing failed:', data.error);
238
+ console.error('Error:', data.error);
373
239
  });
374
240
  ```
375
241
 
376
- **🔄 Event Modification Capabilities:**
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
- // Example 3: Log and analyze all interactions
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
- ##### **2. Tool Events** (`tool:*`)
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
- agent
446
- // Example: Tool events for built-in tools
447
- .addHandler('tool:httpRequest:*', (data) => {
448
- // Listen to ALL HTTP request tool events
449
- console.log('HTTP Request Tool:', data);
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
- **Tool Event Pattern Structure:**
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('output', (data) => {
467
- console.log('General output:', data);
468
- })
469
-
470
- .addHandler('error', (error) => {
471
- console.error('System error:', error);
472
- })
473
-
474
- .addHandler('heartbeat', () => {
475
- console.log('Agent heartbeat');
476
- })
477
-
478
- .addHandler('start', () => {
479
- console.log('Agent started');
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('stop', () => {
483
- console.log('Agent stopped');
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
- #### 🔥 **Advanced Event Patterns**
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
- **Wildcard Matching:**
312
+ **Available Data Structure:**
490
313
  ```javascript
491
- // Listen to all tool events
492
- .addHandler('tool:*', (data) => {
493
- console.log('Any tool activity:', data);
494
- })
495
-
496
-
497
- // Listen to all request outputs
498
- .addHandler('request_output:*', (data) => {
499
- console.log('Any request event:', data);
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
- **Multiple Handlers:**
333
+ #### Tool Events (`tool:*`)
334
+
504
335
  ```javascript
505
- // Multiple handlers for the same event
506
- agent
507
- .addHandler('request_output', (data) => {
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
- #### 📊 **Event Data Structures**
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
- prompt: "User's input prompt",
527
- response: "LLM's response",
528
- conversationId: "unique-conversation-id",
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
- npm
537
-
538
- #### 🎛️ **Communication Method Control**
539
-
540
- Each communication method can be enabled/disabled independently:
352
+ #### Advanced Patterns
541
353
 
542
354
  ```javascript
543
- createAgent('flexible-agent')
544
- // Configure direct prompting with specific settings
545
- .setPromptingServer({
546
- port: 3000,
547
- authentication: false,
548
- maxConnections: 50
549
- })
550
- .disableDirectPrompting() // Disable if needed
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 services. When running agents locally with `dank run`, this setting is disregarded and containers run without resource limits.
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
- Configure Docker image naming and registry settings for agent builds:
378
+ ### Production Image Configuration
580
379
 
581
380
  ```javascript
582
- // Complete agent image configuration
583
381
  .setAgentImageConfig({
584
- registry: 'ghcr.io', // Docker registry URL
585
- namespace: 'mycompany', // Organization/namespace
586
- tag: 'v1.0.0' // Image tag
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
- #### 🏗️ **Agent Image Build Workflow**
388
+ <details>
389
+ <summary><b>🏗️ Production Build Details</b></summary>
591
390
 
592
- The agent image build feature allows you to create properly tagged Docker images for deployment to container registries. This is essential for:
391
+ #### Image Naming
593
392
 
594
- - **CI/CD Pipelines**: Automated builds and deployments
595
- - **Container Orchestration**: Kubernetes, Docker Swarm, etc.
596
- - **Multi-Environment Deployments**: Dev, staging, production
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
- > **📝 Note**: Image pushing is controlled exclusively by the CLI `--push` option. Agent configuration only defines image naming (registry, namespace, tag) - not push behavior.
397
+ #### Deployment Metadata
600
398
 
601
- #### 📋 **Complete Agent Image Example**
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
- ```javascript
604
- const { createAgent } = require('dank');
405
+ Perfect for CI/CD pipelines to auto-configure deployment infrastructure.
605
406
 
606
- module.exports = {
607
- name: 'production-system',
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
- "buildTimestamp": "2024-01-15T10:30:00.000Z",
734
- "agents": [
735
- {
736
- "name": "customer-service",
737
- "imageName": "ghcr.io/mycompany/customer-service:v1.2.0",
738
- "baseImage": {
739
- "full": "deltadarkly/dank-agent-base:nodejs-20",
740
- "tag": "nodejs-20"
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
- #### 🏷️ **Image Naming Convention**
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
- # Login to Docker Hub
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
- **GitHub Container Registry:**
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
- **Private Registry:**
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
- #### 📊 **Build Output Example**
442
+ #### CI/CD Integration
834
443
 
835
- ```bash
836
- $ dank build:prod --push
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
- - name: Setup Node.js
886
- uses: actions/setup-node@v3
887
- with:
888
- node-version: '18'
889
-
890
- - name: Install Dank
891
- run: npm install -g dank-ai
892
-
893
- - name: Login to GHCR
894
- uses: docker/login-action@v2
895
- with:
896
- registry: ghcr.io
897
- username: ${{ github.actor }}
898
- password: ${{ secrets.GITHUB_TOKEN }}
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
- ### For Production Use
1021
- ```bash
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
- # 4. Run your agents
1032
- dank run
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 and custom tags
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
- ### 🚀 Automatic Docker Management
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
- #### **Platform-Specific Installation**
508
+ Dank automatically handles Docker installation and startup:
1065
509
 
1066
- **macOS:**
1067
- ```bash
1068
- # Dank will automatically run:
1069
- brew install --cask docker
1070
- open -a Docker
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
- #### 3. Multi-Agent Setup
1151
- Configure multiple specialized agents:
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
- ```javascript
1154
- const { createAgent } = require('dank');
521
+ If automatic installation fails, Dank provides clear manual instructions.
522
+ </details>
1155
523
 
1156
- module.exports = {
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
- ### 🎯 Common Use Cases
526
+ <details>
527
+ <summary><b>🎯 Common Use Cases</b></summary>
1220
528
 
1221
- #### Use Case 1: Customer Support Automation
529
+ #### Customer Support Automation
1222
530
  ```javascript
1223
531
  createAgent('support-bot')
1224
- .setLLM('openai', {
1225
- apiKey: process.env.OPENAI_API_KEY,
1226
- model: 'gpt-3.5-turbo'
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
- #### Use Case 2: Content Generation Pipeline
538
+ #### Content Generation Pipeline
1253
539
  ```javascript
1254
- const contentAgents = [
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
- // Save draft and notify editor
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', (optimizedContent) => {
1279
- // Publish optimized content
1280
- publishContent(optimizedContent);
1281
- })
554
+ .addHandler('output', (content) => publishContent(content))
1282
555
  ];
1283
556
  ```
1284
557
 
1285
- #### Use Case 3: Data Analysis Workflow
558
+ #### Data Analysis Workflow
1286
559
  ```javascript
1287
560
  createAgent('data-processor')
1288
- .setLLM('openai', {
1289
- apiKey: process.env.OPENAI_API_KEY,
1290
- model: 'gpt-4',
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
- ### 🔧 Advanced Configuration
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
- // Trigger output handlers
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
- // dank.config.js
1368
- const { createAgent } = require('dank');
1369
-
1370
- const isDevelopment = process.env.NODE_ENV === 'development';
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
- # macOS (with Homebrew):
1421
- brew install --cask docker
1422
- open -a Docker
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
- ### 💡 Best Practices
609
+ <details>
610
+ <summary><b>💡 Best Practices</b></summary>
1477
611
 
1478
- #### 1. Resource Management
612
+ #### Resource Management
1479
613
  ```javascript
1480
- // Good: Appropriate resource allocation
1481
- createAgent('light-agent')
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
- #### 2. Error Handling
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
- processOutput(data);
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
- #### 3. Environment Configuration
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
- #### 5. Security Considerations
644
+ #### Security
1567
645
  ```javascript
1568
- // Good: Secure configuration
1569
646
  createAgent('secure-agent')
1570
- .setLLM('openai', {
1571
- apiKey: process.env.OPENAI_API_KEY, // Never hardcode keys
1572
- model: 'gpt-3.5-turbo'
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
- #### 1. Parallel Agent Management
1592
- ```javascript
1593
- // Good: Balanced agent distribution
1594
- module.exports = {
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
- // CPU-intensive agents
1597
- createAgent('analyzer').setInstanceType('medium'),
1598
-
1599
- // Memory-intensive agents
1600
- createAgent('processor').setInstanceType('large'),
1601
-
1602
- // Light agents
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
- #### 2. Efficient Prompt Design
1609
- ```javascript
1610
- // Good: Clear, specific prompts
1611
- .setPrompt(`
1612
- You are a customer service agent. Follow these steps:
1613
-
1614
- 1. Greet the customer politely
1615
- 2. Understand their issue by asking clarifying questions
1616
- 3. Provide a solution or escalate if needed
1617
- 4. Confirm resolution
1618
-
1619
- Response format: JSON with fields: greeting, questions, solution, status
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
- ### 🔄 Development Workflow
697
+ 3. **Compile and run:**
1624
698
 
1625
- #### 1. Local Development
1626
699
  ```bash
1627
- # 1. Start with development configuration
1628
- NODE_ENV=development dank run
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
- # 2. Make changes to dank.config.js
712
+ </details>
1631
713
 
1632
- # 3. Restart agents to apply changes
1633
- dank stop --all
1634
- dank run --build # Rebuild if needed
714
+ <details>
715
+ <summary><b>🔄 Development Workflow</b></summary>
1635
716
 
1636
- # 4. Test with reduced resources
1637
- createAgent('dev-agent').setInstanceType('small')
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
- #### 2. Testing Agents
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
- #### 3. Production Deployment
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
- ### Monitoring and Debugging
743
+ <details>
744
+ <summary><b>Common Issues and Solutions</b></summary>
1669
745
 
746
+ **1. Docker Connection Issues**
1670
747
  ```bash
1671
- # Watch all agents in real-time
1672
- dank status --watch
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
- # Follow logs from specific agent
1675
- dank logs my-agent --follow
766
+ **4. Container Resource Issues**
767
+ ```javascript
768
+ // Increase memory allocation (cloud only)
769
+ createAgent('my-agent').setInstanceType('medium');
770
+ ```
1676
771
 
1677
- # View container details
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
- # Check agent health
1681
- curl http://localhost:3001/health
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
- ## 📦 Installation
798
+ ## 📋 Example Files
1685
799
 
1686
- ### Prerequisites
1687
- - Node.js 16+
1688
- - Docker Desktop or Docker Engine
1689
- - npm or yarn
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
+ ---