dank-ai 1.0.34 → 1.0.36

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/lib/agent.js CHANGED
@@ -78,37 +78,11 @@ class DankAgent {
78
78
  }
79
79
 
80
80
  /**
81
- * @deprecated Use setInstanceType() instead. This method is kept for backward compatibility.
82
- * Set resource limits for the container
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
- // Map old resources format to instance type
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
@@ -20,8 +20,8 @@ async function buildCommand(options) {
20
20
 
21
21
  console.log(chalk.green('\\n✅ Pull completed successfully!'));
22
22
  }
23
-
24
23
 
24
+ process.exit(0);
25
25
  } catch (error) {
26
26
  console.error(chalk.red('❌ Pull failed:'), error.message);
27
27
  process.exit(1);
package/lib/cli/clean.js CHANGED
@@ -21,6 +21,7 @@ async function cleanCommand(options) {
21
21
 
22
22
  console.log(chalk.green('\\n✅ Cleanup completed successfully!'));
23
23
 
24
+ process.exit(0);
24
25
  } catch (error) {
25
26
  console.error(chalk.red('❌ Cleanup failed:'), error.message);
26
27
  process.exit(1);
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
@@ -19,6 +19,7 @@ async function stopCommand(agents, options) {
19
19
  process.exit(1);
20
20
  }
21
21
 
22
+ process.exit(0);
22
23
  } catch (error) {
23
24
  console.error(chalk.red('❌ Stop failed:'), error.message);
24
25
  process.exit(1);
@@ -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, options);
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 structure (if needed)
28
- // await fs.ensureDir(path.join(projectDir, this.options.outputDir));
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')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dank-ai",
3
- "version": "1.0.34",
3
+ "version": "1.0.36",
4
4
  "description": "Dank Agent Service - Docker-based AI agent orchestration platform",
5
5
  "main": "lib/index.js",
6
6
  "exports": {