dank-ai 1.0.34 → 1.0.35
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 +37 -132
- package/docker/entrypoint.js +568 -67
- package/lib/agent.js +3 -29
- package/lib/cli/build.js +1 -1
- package/lib/cli/clean.js +1 -0
- package/lib/cli/init.js +2 -1
- package/lib/cli/production-build.js +5 -1
- package/lib/cli/run.js +6 -1
- package/lib/cli/stop.js +1 -0
- package/lib/docker/manager.js +86 -7
- package/lib/project.js +2 -3
- package/package.json +1 -1
package/lib/agent.js
CHANGED
|
@@ -78,37 +78,11 @@ class DankAgent {
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
/**
|
|
81
|
-
* @deprecated Use setInstanceType() instead.
|
|
82
|
-
*
|
|
81
|
+
* @deprecated DISABLED - Use setInstanceType() instead.
|
|
82
|
+
* This method has been disabled. Please use setInstanceType('small'|'medium'|'large'|'xlarge') instead.
|
|
83
83
|
*/
|
|
84
84
|
setResources(resources) {
|
|
85
|
-
|
|
86
|
-
if (resources && typeof resources === 'object') {
|
|
87
|
-
const memory = resources.memory || '512m';
|
|
88
|
-
const cpu = resources.cpu || 1;
|
|
89
|
-
|
|
90
|
-
// Try to map to an instance type
|
|
91
|
-
let instanceType = 'small'; // default
|
|
92
|
-
|
|
93
|
-
if (memory === '512m' && cpu === 1) {
|
|
94
|
-
instanceType = 'small';
|
|
95
|
-
} else if (memory === '1g' && cpu === 2) {
|
|
96
|
-
instanceType = 'medium';
|
|
97
|
-
} else if (memory === '2g' && cpu === 2) {
|
|
98
|
-
instanceType = 'large';
|
|
99
|
-
} else if (memory === '4g' && cpu === 4) {
|
|
100
|
-
instanceType = 'xlarge';
|
|
101
|
-
} else {
|
|
102
|
-
// For custom configurations, default to small and log a warning
|
|
103
|
-
console.warn(`⚠️ setResources() is deprecated. Using 'small' instance type. Please use setInstanceType('small'|'medium'|'large'|'xlarge') instead.`);
|
|
104
|
-
instanceType = 'small';
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
return this.setInstanceType(instanceType);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// If no resources provided, default to small
|
|
111
|
-
return this.setInstanceType('small');
|
|
85
|
+
throw new Error('setResources() has been disabled. Please use setInstanceType() instead. Example: .setInstanceType("small")');
|
|
112
86
|
}
|
|
113
87
|
|
|
114
88
|
/**
|
package/lib/cli/build.js
CHANGED
package/lib/cli/clean.js
CHANGED
package/lib/cli/init.js
CHANGED
|
@@ -72,7 +72,7 @@ async function initCommand(projectName, options) {
|
|
|
72
72
|
force: options.force
|
|
73
73
|
});
|
|
74
74
|
|
|
75
|
-
// Initialize project structure
|
|
75
|
+
// Initialize project structure (creates directory if needed)
|
|
76
76
|
await project.init();
|
|
77
77
|
|
|
78
78
|
// Create package.json
|
|
@@ -95,6 +95,7 @@ async function initCommand(projectName, options) {
|
|
|
95
95
|
console.log(chalk.gray(' 4. Run "dank run" to start your agents'));
|
|
96
96
|
console.log(chalk.gray('\nFor more information, visit: https://github.com/your-org/dank'));
|
|
97
97
|
|
|
98
|
+
process.exit(0);
|
|
98
99
|
} catch (error) {
|
|
99
100
|
console.error(chalk.red('❌ Initialization failed:'), error.message);
|
|
100
101
|
process.exit(1);
|
|
@@ -131,6 +131,9 @@ async function productionBuildCommand(options) {
|
|
|
131
131
|
throw new Error(`Configuration file not found: ${configPath}`);
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
+
// Get project directory (directory containing the config file)
|
|
135
|
+
const projectDir = path.dirname(configPath);
|
|
136
|
+
|
|
134
137
|
const config = require(configPath);
|
|
135
138
|
if (!config.agents || !Array.isArray(config.agents)) {
|
|
136
139
|
throw new Error('No agents found in configuration');
|
|
@@ -157,7 +160,8 @@ async function productionBuildCommand(options) {
|
|
|
157
160
|
tagByAgent: Boolean(options.tagByAgent || agentImageConfig.tagByAgent),
|
|
158
161
|
force: options.force || false,
|
|
159
162
|
push: options.push || false,
|
|
160
|
-
baseImageOverride: options.baseImageOverride || null
|
|
163
|
+
baseImageOverride: options.baseImageOverride || null,
|
|
164
|
+
projectDir: projectDir // Pass project directory so external files can be copied
|
|
161
165
|
};
|
|
162
166
|
|
|
163
167
|
const result = await dockerManager.buildProductionImage(agent, buildOptions);
|
package/lib/cli/run.js
CHANGED
|
@@ -23,6 +23,9 @@ async function runCommand(options) {
|
|
|
23
23
|
throw new Error(`Configuration file not found: ${configPath}`);
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
// Get project directory (directory containing the config file)
|
|
27
|
+
const projectDir = path.dirname(configPath);
|
|
28
|
+
|
|
26
29
|
console.log(chalk.blue('📋 Loading configuration...'));
|
|
27
30
|
|
|
28
31
|
// Clear require cache to get fresh config
|
|
@@ -67,7 +70,8 @@ async function runCommand(options) {
|
|
|
67
70
|
console.log(chalk.gray(` Starting ${agent.name}...`));
|
|
68
71
|
|
|
69
72
|
const container = await dockerManager.startAgent(agent, {
|
|
70
|
-
rebuild: !options.noBuild // Rebuild by default unless --no-build is specified
|
|
73
|
+
rebuild: !options.noBuild, // Rebuild by default unless --no-build is specified
|
|
74
|
+
projectDir: projectDir // Pass project directory so external files can be copied
|
|
71
75
|
});
|
|
72
76
|
|
|
73
77
|
console.log(chalk.green(` ✅ ${agent.name} started (${container.id.substring(0, 12)})`));
|
|
@@ -98,6 +102,7 @@ async function runCommand(options) {
|
|
|
98
102
|
console.log(chalk.cyan('\\n🔧 Agents running in detached mode'));
|
|
99
103
|
console.log(chalk.gray('Use "dank status" to check agent status'));
|
|
100
104
|
console.log(chalk.gray('Use "dank logs <agent>" to view logs'));
|
|
105
|
+
process.exit(0);
|
|
101
106
|
} else {
|
|
102
107
|
console.log(chalk.cyan('\\n👀 Monitoring agents (Ctrl+C to stop)...'));
|
|
103
108
|
|
package/lib/cli/stop.js
CHANGED
package/lib/docker/manager.js
CHANGED
|
@@ -1170,7 +1170,9 @@ class DockerManager {
|
|
|
1170
1170
|
agent.finalize();
|
|
1171
1171
|
|
|
1172
1172
|
try {
|
|
1173
|
-
const buildContext = await this.createAgentBuildContext(agent
|
|
1173
|
+
const buildContext = await this.createAgentBuildContext(agent, {
|
|
1174
|
+
projectDir: options.projectDir
|
|
1175
|
+
});
|
|
1174
1176
|
const dockerCmd = await this.resolveDockerCommand();
|
|
1175
1177
|
|
|
1176
1178
|
const buildCommand = [
|
|
@@ -1221,6 +1223,7 @@ class DockerManager {
|
|
|
1221
1223
|
force = false,
|
|
1222
1224
|
push = false,
|
|
1223
1225
|
baseImageOverride = null, // Production-only: override base image for all agents
|
|
1226
|
+
projectDir = null, // Project directory to copy files from
|
|
1224
1227
|
} = options;
|
|
1225
1228
|
|
|
1226
1229
|
// Normalize all components
|
|
@@ -1259,7 +1262,8 @@ class DockerManager {
|
|
|
1259
1262
|
try {
|
|
1260
1263
|
const buildContext = await this.createAgentBuildContext(agent, {
|
|
1261
1264
|
isProductionBuild: true,
|
|
1262
|
-
baseImageOverride: baseImageOverride
|
|
1265
|
+
baseImageOverride: baseImageOverride,
|
|
1266
|
+
projectDir: projectDir
|
|
1263
1267
|
});
|
|
1264
1268
|
const dockerCmd = await this.resolveDockerCommand();
|
|
1265
1269
|
|
|
@@ -1417,7 +1421,9 @@ class DockerManager {
|
|
|
1417
1421
|
// Check if agent image exists, build if necessary
|
|
1418
1422
|
const hasImage = await this.hasImage(imageName);
|
|
1419
1423
|
if (!hasImage || options.rebuild) {
|
|
1420
|
-
await this.buildAgentImage(agent,
|
|
1424
|
+
await this.buildAgentImage(agent, {
|
|
1425
|
+
projectDir: options.projectDir
|
|
1426
|
+
});
|
|
1421
1427
|
}
|
|
1422
1428
|
|
|
1423
1429
|
// Prepare container configuration
|
|
@@ -1617,6 +1623,66 @@ class DockerManager {
|
|
|
1617
1623
|
return tarPath;
|
|
1618
1624
|
}
|
|
1619
1625
|
|
|
1626
|
+
/**
|
|
1627
|
+
* Copy project files to build context (excluding common ignore patterns)
|
|
1628
|
+
*/
|
|
1629
|
+
async copyProjectFiles(projectDir, contextDir) {
|
|
1630
|
+
const agentCodeDir = path.join(contextDir, "agent-code");
|
|
1631
|
+
await fs.ensureDir(agentCodeDir);
|
|
1632
|
+
|
|
1633
|
+
// Patterns to exclude when copying project files
|
|
1634
|
+
const ignorePatterns = [
|
|
1635
|
+
'node_modules',
|
|
1636
|
+
'.git',
|
|
1637
|
+
'.build-context-*',
|
|
1638
|
+
'.env',
|
|
1639
|
+
'.env.*',
|
|
1640
|
+
'*.log',
|
|
1641
|
+
'.DS_Store',
|
|
1642
|
+
'dist',
|
|
1643
|
+
'build',
|
|
1644
|
+
'.dank',
|
|
1645
|
+
'coverage',
|
|
1646
|
+
'.nyc_output'
|
|
1647
|
+
];
|
|
1648
|
+
|
|
1649
|
+
try {
|
|
1650
|
+
// Copy all files from project directory, filtering out ignored patterns
|
|
1651
|
+
const items = await fs.readdir(projectDir);
|
|
1652
|
+
|
|
1653
|
+
for (const item of items) {
|
|
1654
|
+
const sourcePath = path.join(projectDir, item);
|
|
1655
|
+
const destPath = path.join(agentCodeDir, item);
|
|
1656
|
+
const stat = await fs.stat(sourcePath);
|
|
1657
|
+
|
|
1658
|
+
// Skip if matches ignore pattern
|
|
1659
|
+
const shouldIgnore = ignorePatterns.some(pattern => {
|
|
1660
|
+
if (pattern.includes('*')) {
|
|
1661
|
+
const regex = new RegExp('^' + pattern.replace(/\*/g, '.*') + '$');
|
|
1662
|
+
return regex.test(item);
|
|
1663
|
+
}
|
|
1664
|
+
return item === pattern;
|
|
1665
|
+
});
|
|
1666
|
+
|
|
1667
|
+
if (shouldIgnore) {
|
|
1668
|
+
continue;
|
|
1669
|
+
}
|
|
1670
|
+
|
|
1671
|
+
// Copy file or directory
|
|
1672
|
+
if (stat.isDirectory()) {
|
|
1673
|
+
await fs.copy(sourcePath, destPath);
|
|
1674
|
+
} else if (stat.isFile()) {
|
|
1675
|
+
await fs.copy(sourcePath, destPath);
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1678
|
+
|
|
1679
|
+
this.logger.info(`📁 Copied project files from ${projectDir} to build context`);
|
|
1680
|
+
} catch (error) {
|
|
1681
|
+
this.logger.warn(`⚠️ Failed to copy project files: ${error.message}`);
|
|
1682
|
+
// Don't fail the build if copying project files fails
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1685
|
+
|
|
1620
1686
|
/**
|
|
1621
1687
|
* Create build context for agent
|
|
1622
1688
|
*/
|
|
@@ -1626,6 +1692,12 @@ class DockerManager {
|
|
|
1626
1692
|
`../../.build-context-${agent.name}`
|
|
1627
1693
|
);
|
|
1628
1694
|
await fs.ensureDir(contextDir);
|
|
1695
|
+
|
|
1696
|
+
// Copy project files if project directory is provided
|
|
1697
|
+
// This allows handlers to reference functions from other files
|
|
1698
|
+
if (options.projectDir) {
|
|
1699
|
+
await this.copyProjectFiles(options.projectDir, contextDir);
|
|
1700
|
+
}
|
|
1629
1701
|
|
|
1630
1702
|
// Get the base image for this agent
|
|
1631
1703
|
// Production builds can override the base image via baseImageOverride option
|
|
@@ -1680,10 +1752,20 @@ USER dankuser
|
|
|
1680
1752
|
const handlersCode = this.generateHandlersCode(agent);
|
|
1681
1753
|
const routesCode = this.generateRoutesCode(agent);
|
|
1682
1754
|
|
|
1755
|
+
// Check if project files were copied (indicated by presence of files other than index.js)
|
|
1756
|
+
const hasProjectFiles = options.projectDir ? true : false;
|
|
1757
|
+
const projectFilesNote = hasProjectFiles
|
|
1758
|
+
? `// Note: Project files from your project directory have been copied here.
|
|
1759
|
+
// You can require them in your handlers using relative paths.
|
|
1760
|
+
// Example: const { myFunction } = require('./utils');`
|
|
1761
|
+
: '';
|
|
1762
|
+
|
|
1683
1763
|
const agentCode = `
|
|
1684
1764
|
// Agent: ${agent.name}
|
|
1685
1765
|
// Generated by Dank Agent Service
|
|
1686
1766
|
|
|
1767
|
+
${projectFilesNote}
|
|
1768
|
+
|
|
1687
1769
|
module.exports = {
|
|
1688
1770
|
async main(context) {
|
|
1689
1771
|
const { llmClient, handlers, tools, config } = context;
|
|
@@ -1693,7 +1775,7 @@ module.exports = {
|
|
|
1693
1775
|
// Basic agent loop
|
|
1694
1776
|
setInterval(async () => {
|
|
1695
1777
|
try {
|
|
1696
|
-
// Trigger heartbeat
|
|
1778
|
+
// Trigger heartbeat handlers (no logging)
|
|
1697
1779
|
const heartbeatHandlers = handlers.get('heartbeat') || [];
|
|
1698
1780
|
heartbeatHandlers.forEach(handler => {
|
|
1699
1781
|
try {
|
|
@@ -1703,9 +1785,6 @@ module.exports = {
|
|
|
1703
1785
|
}
|
|
1704
1786
|
});
|
|
1705
1787
|
|
|
1706
|
-
// Custom agent logic would go here
|
|
1707
|
-
console.log('Agent ${agent.name} heartbeat - uptime:', Math.floor(process.uptime()), 'seconds');
|
|
1708
|
-
|
|
1709
1788
|
} catch (error) {
|
|
1710
1789
|
console.error('Agent loop error:', error);
|
|
1711
1790
|
const errorHandlers = handlers.get('error') || [];
|
package/lib/project.js
CHANGED
|
@@ -24,8 +24,8 @@ class DankProject {
|
|
|
24
24
|
async init() {
|
|
25
25
|
const projectDir = this.projectPath;
|
|
26
26
|
|
|
27
|
-
// Create directory
|
|
28
|
-
|
|
27
|
+
// Create project directory if it doesn't exist
|
|
28
|
+
await fs.ensureDir(projectDir);
|
|
29
29
|
|
|
30
30
|
// Create example config file
|
|
31
31
|
const exampleConfig = this._generateExampleConfig();
|
|
@@ -82,7 +82,6 @@ module.exports = {
|
|
|
82
82
|
.setPrompt('You are a helpful AI assistant. Be concise and friendly in your responses.')
|
|
83
83
|
.setBaseImage('nodejs-20')
|
|
84
84
|
.setPromptingServer({
|
|
85
|
-
protocol: 'http',
|
|
86
85
|
port: 3000
|
|
87
86
|
})
|
|
88
87
|
.setInstanceType('small')
|