dank-ai 1.0.19 → 1.0.21

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/bin/dank CHANGED
@@ -14,12 +14,17 @@ const { initCommand } = require('../lib/cli/init');
14
14
  const { statusCommand } = require('../lib/cli/status');
15
15
  const { stopCommand } = require('../lib/cli/stop');
16
16
  const { logsCommand } = require('../lib/cli/logs');
17
+ const analytics = require('../lib/analytics');
17
18
 
18
19
  program
19
20
  .name('dank')
20
21
  .description('🚀 Dank Agent Service - Docker-based AI agent orchestration')
21
22
  .version(pkg.version);
22
23
 
24
+ // Track CLI usage and install
25
+ analytics.trackCLIUsage();
26
+ analytics.trackInstall();
27
+
23
28
  // Run command - main orchestration command
24
29
  program
25
30
  .command('run')
@@ -0,0 +1,241 @@
1
+ const https = require('https');
2
+ const crypto = require('crypto');
3
+
4
+ class Analytics {
5
+ constructor() {
6
+ this.enabled = true;
7
+ this.projectToken = process.env.MIXPANEL_PROJECT_TOKEN || '2ab09eb7ea93ec0f288758866280bec6'; // Use env var or fallback
8
+ this.apiUrl = 'https://api.mixpanel.com/track';
9
+ this.userId = this.generateAnonymousId();
10
+ this.sessionId = this.generateSessionId();
11
+ this.installDate = this.getInstallDate();
12
+ }
13
+
14
+ generateAnonymousId() {
15
+ // Generate a consistent anonymous ID based on machine characteristics
16
+ const os = require('os');
17
+ const machineId = os.hostname() + os.platform() + os.arch();
18
+ return crypto.createHash('sha256').update(machineId).digest('hex').substring(0, 16);
19
+ }
20
+
21
+ generateSessionId() {
22
+ return crypto.randomBytes(16).toString('hex');
23
+ }
24
+
25
+ getInstallDate() {
26
+ // Try to get install date from package.json or use current date
27
+ try {
28
+ const pkg = require('../package.json');
29
+ return new Date(pkg.date || Date.now()).toISOString().split('T')[0];
30
+ } catch (error) {
31
+ return new Date().toISOString().split('T')[0];
32
+ }
33
+ }
34
+
35
+ async track(event, properties = {}) {
36
+ if (!this.enabled) return;
37
+
38
+ const payload = {
39
+ event,
40
+ properties: {
41
+ ...properties,
42
+ distinct_id: this.userId,
43
+ session_id: this.sessionId,
44
+ platform: process.platform,
45
+ arch: process.arch,
46
+ node_version: process.version,
47
+ version: require('../package.json').version,
48
+ time: new Date().toISOString()
49
+ }
50
+ };
51
+
52
+ // Send asynchronously without blocking
53
+ this.sendEvent(payload).catch(() => {
54
+ // Fail silently - don't break user experience
55
+ });
56
+ }
57
+
58
+ async sendEvent(payload) {
59
+ const data = JSON.stringify(payload);
60
+
61
+ const options = {
62
+ hostname: 'api.mixpanel.com',
63
+ port: 443,
64
+ path: '/track',
65
+ method: 'POST',
66
+ headers: {
67
+ 'Content-Type': 'application/json',
68
+ 'Content-Length': data.length,
69
+ 'User-Agent': 'dank-cli'
70
+ }
71
+ };
72
+
73
+ return new Promise((resolve, reject) => {
74
+ const req = https.request(options, (res) => {
75
+ resolve();
76
+ });
77
+ req.on('error', reject);
78
+ req.write(data);
79
+ req.end();
80
+ });
81
+ }
82
+
83
+ // ===== INSTALL & ACTIVATION TRACKING =====
84
+
85
+ async trackInstall() {
86
+ await this.track('Dank Installed', {
87
+ install_date: this.installDate,
88
+ version: require('../package.json').version,
89
+ platform: process.platform,
90
+ arch: process.arch
91
+ });
92
+ }
93
+
94
+ async trackDailyActive() {
95
+ await this.track('Dank Daily Active', {
96
+ version: require('../package.json').version,
97
+ platform: process.platform
98
+ });
99
+ }
100
+
101
+ async trackMonthlyActive() {
102
+ await this.track('Dank Monthly Active', {
103
+ version: require('../package.json').version,
104
+ platform: process.platform
105
+ });
106
+ }
107
+
108
+ // ===== FUNNEL TRACKING =====
109
+
110
+ async trackFunnelStep(step, properties = {}) {
111
+ await this.track('Dank Funnel Step', {
112
+ funnel_step: step,
113
+ ...properties
114
+ });
115
+ }
116
+
117
+ async trackProjectCreated(projectName, template = 'basic') {
118
+ await this.track('Dank Project Created', {
119
+ project_name: projectName,
120
+ template: template,
121
+ funnel_step: 'project_created'
122
+ });
123
+ }
124
+
125
+ async trackProjectRun(projectName, agentCount) {
126
+ await this.track('Dank Project Run', {
127
+ project_name: projectName,
128
+ agent_count: agentCount,
129
+ funnel_step: 'project_run'
130
+ });
131
+ }
132
+
133
+ async trackFirstAgentRun(projectName) {
134
+ await this.track('Dank First Agent Run', {
135
+ project_name: projectName,
136
+ funnel_step: 'first_agent_run'
137
+ });
138
+ }
139
+
140
+ // ===== AGENT TRACKING =====
141
+
142
+ async trackAgentStart(agentName, success = true, properties = {}) {
143
+ await this.track('Dank Agent Started', {
144
+ agent_name: agentName,
145
+ success: success,
146
+ ...properties
147
+ });
148
+ }
149
+
150
+ async trackAgentStop(agentName, success = true, properties = {}) {
151
+ await this.track('Dank Agent Stopped', {
152
+ agent_name: agentName,
153
+ success: success,
154
+ ...properties
155
+ });
156
+ }
157
+
158
+ async trackAgentBuild(agentName, success = true, buildTime = null) {
159
+ await this.track('Dank Agent Built', {
160
+ agent_name: agentName,
161
+ success: success,
162
+ build_time: buildTime,
163
+ ...properties
164
+ });
165
+ }
166
+
167
+ async trackAgentError(agentName, error, properties = {}) {
168
+ await this.track('Dank Agent Error', {
169
+ agent_name: agentName,
170
+ error_type: error.constructor.name,
171
+ error_message: error.message,
172
+ ...properties
173
+ });
174
+ }
175
+
176
+ // ===== COMMAND TRACKING =====
177
+
178
+ async trackCommand(command, success = true, properties = {}) {
179
+ await this.track('Dank Command Executed', {
180
+ command: command,
181
+ success: success,
182
+ ...properties
183
+ });
184
+ }
185
+
186
+ async trackCLIUsage() {
187
+ await this.track('Dank CLI Used', {
188
+ version: require('../package.json').version,
189
+ platform: process.platform
190
+ });
191
+ }
192
+
193
+ // ===== DOCKER TRACKING =====
194
+
195
+ async trackDockerInstall(success = true, platform = process.platform) {
196
+ await this.track('Dank Docker Install', {
197
+ success: success,
198
+ platform: platform
199
+ });
200
+ }
201
+
202
+ async trackDockerOperation(operation, success = true, properties = {}) {
203
+ await this.track('Dank Docker Operation', {
204
+ operation: operation,
205
+ success: success,
206
+ ...properties
207
+ });
208
+ }
209
+
210
+ // ===== FEATURE USAGE TRACKING =====
211
+
212
+ async trackFeatureUsed(feature, properties = {}) {
213
+ await this.track('Dank Feature Used', {
214
+ feature: feature,
215
+ ...properties
216
+ });
217
+ }
218
+
219
+ async trackProductionBuild(agentName, registry, namespace, tag) {
220
+ await this.track('Dank Production Build', {
221
+ agent_name: agentName,
222
+ registry: registry,
223
+ namespace: namespace,
224
+ tag: tag,
225
+ funnel_step: 'production_build'
226
+ });
227
+ }
228
+
229
+ // ===== ERROR TRACKING =====
230
+
231
+ async trackError(error, context = {}) {
232
+ await this.track('Dank Error', {
233
+ error_type: error.constructor.name,
234
+ error_message: error.message,
235
+ error_stack: error.stack,
236
+ context: context
237
+ });
238
+ }
239
+ }
240
+
241
+ module.exports = new Analytics();
package/lib/cli/init.js CHANGED
@@ -6,8 +6,16 @@ const fs = require('fs-extra');
6
6
  const path = require('path');
7
7
  const chalk = require('chalk');
8
8
  const { DankProject } = require('../project');
9
+ const analytics = require('../analytics');
9
10
 
10
11
  async function initCommand(projectName, options) {
12
+ // Track project creation and funnel step
13
+ await analytics.trackProjectCreated(projectName, options.template || 'basic');
14
+ await analytics.trackFunnelStep('project_created', {
15
+ project_name: projectName,
16
+ template: options.template || 'basic'
17
+ });
18
+
11
19
  let name = projectName;
12
20
  let npmProjectName = projectName;
13
21
 
@@ -6,8 +6,15 @@ const fs = require('fs-extra');
6
6
  const path = require('path');
7
7
  const chalk = require('chalk');
8
8
  const { DockerManager } = require('../docker/manager');
9
+ const analytics = require('../analytics');
9
10
 
10
11
  async function productionBuildCommand(options) {
12
+ // Track production build command
13
+ await analytics.trackCommand('build:prod', true, {
14
+ push: options.push || false,
15
+ force: options.force || false
16
+ });
17
+
11
18
  try {
12
19
  console.log(chalk.yellow('🏗️ Building production Docker images...\n'));
13
20
 
@@ -44,6 +51,14 @@ async function productionBuildCommand(options) {
44
51
 
45
52
  const result = await dockerManager.buildProductionImage(agent, buildOptions);
46
53
 
54
+ // Track production build success
55
+ await analytics.trackProductionBuild(
56
+ agent.name,
57
+ buildOptions.registry,
58
+ buildOptions.namespace,
59
+ buildOptions.tag
60
+ );
61
+
47
62
  buildResults.push({
48
63
  agent: agent.name,
49
64
  imageName: result.imageName,
package/lib/cli/run.js CHANGED
@@ -7,10 +7,15 @@ const path = require('path');
7
7
  const chalk = require('chalk');
8
8
  const { DockerManager } = require('../docker/manager');
9
9
  const { DankProject } = require('../project');
10
+ const analytics = require('../analytics');
10
11
 
11
12
  async function runCommand(options) {
12
13
  console.log(chalk.yellow('🚀 Starting Dank agents...\\n'));
13
14
 
15
+ // Track daily active user and CLI usage
16
+ await analytics.trackDailyActive();
17
+ await analytics.trackCLIUsage();
18
+
14
19
  try {
15
20
  // Load configuration
16
21
  const configPath = path.resolve(options.config);
@@ -29,6 +34,9 @@ async function runCommand(options) {
29
34
  }
30
35
 
31
36
  console.log(chalk.green(`✅ Found ${config.agents.length} agents`));
37
+
38
+ // Track project run
39
+ await analytics.trackProjectRun('unknown', config.agents.length);
32
40
 
33
41
  // Initialize Docker manager
34
42
  console.log(chalk.blue('🐳 Initializing Docker...'));
@@ -18,6 +18,7 @@ const { spawn, exec } = require("child_process");
18
18
  const { promisify } = require("util");
19
19
  const { DOCKER_CONFIG } = require("../constants");
20
20
  const { AgentConfig } = require("../config");
21
+ const analytics = require("../analytics");
21
22
 
22
23
  const execAsync = promisify(exec);
23
24
 
@@ -261,6 +262,9 @@ class DockerManager {
261
262
 
262
263
  this.logger.info(`Installing Docker for ${platform}...`);
263
264
 
265
+ // Track Docker installation attempt
266
+ await analytics.trackDockerInstall(true, platform);
267
+
264
268
  try {
265
269
  if (platform === "darwin") {
266
270
  await this.installDockerMacOS();
@@ -273,7 +277,14 @@ class DockerManager {
273
277
  }
274
278
 
275
279
  this.logger.info("Docker installation completed");
280
+
281
+ // Track successful Docker installation
282
+ await analytics.trackDockerInstall(true, platform);
276
283
  } catch (error) {
284
+ // Track failed Docker installation
285
+ await analytics.trackDockerInstall(false, platform);
286
+ await analytics.trackError(error, { context: 'docker_install', platform });
287
+
277
288
  throw new Error(`Failed to install Docker: ${error.message}`);
278
289
  }
279
290
  }
@@ -1263,6 +1274,12 @@ class DockerManager {
1263
1274
  * Start agent container
1264
1275
  */
1265
1276
  async startAgent(agent, options = {}) {
1277
+ // Track agent start attempt
1278
+ await analytics.trackAgentStart(agent.name, true, {
1279
+ rebuild: options.rebuild || false,
1280
+ has_docker_config: !!agent.config.docker
1281
+ });
1282
+
1266
1283
  // Finalize agent configuration (auto-detect features)
1267
1284
  agent.finalize();
1268
1285
 
@@ -1338,8 +1355,22 @@ class DockerManager {
1338
1355
  )})`
1339
1356
  );
1340
1357
 
1358
+ // Track successful agent start
1359
+ await analytics.trackAgentStart(agent.name, true, {
1360
+ success: true,
1361
+ container_id: container.id.substring(0, 12)
1362
+ });
1363
+
1341
1364
  return container;
1342
1365
  } catch (error) {
1366
+ // Track failed agent start
1367
+ await analytics.trackAgentStart(agent.name, false, {
1368
+ error: error.message
1369
+ });
1370
+ await analytics.trackAgentError(agent.name, error, {
1371
+ context: 'agent_start'
1372
+ });
1373
+
1343
1374
  agent.status = "error";
1344
1375
  throw new Error(`Failed to start agent ${agent.name}: ${error.message}`);
1345
1376
  }
@@ -1349,6 +1380,11 @@ class DockerManager {
1349
1380
  * Stop agent container
1350
1381
  */
1351
1382
  async stopAgent(agentName, options = {}) {
1383
+ // Track agent stop attempt
1384
+ await analytics.trackAgentStop(agentName, true, {
1385
+ force: options.force || false
1386
+ });
1387
+
1352
1388
  const containerInfo = this.containers.get(agentName);
1353
1389
  if (!containerInfo) {
1354
1390
  throw new Error(`Agent ${agentName} not found or not running`);
@@ -1372,7 +1408,20 @@ class DockerManager {
1372
1408
  agent.containerId = null;
1373
1409
 
1374
1410
  this.logger.info(`Agent ${agentName} stopped successfully`);
1411
+
1412
+ // Track successful agent stop
1413
+ await analytics.trackAgentStop(agentName, true, {
1414
+ success: true
1415
+ });
1375
1416
  } catch (error) {
1417
+ // Track failed agent stop
1418
+ await analytics.trackAgentStop(agentName, false, {
1419
+ error: error.message
1420
+ });
1421
+ await analytics.trackAgentError(agentName, error, {
1422
+ context: 'agent_stop'
1423
+ });
1424
+
1376
1425
  throw new Error(`Failed to stop agent ${agentName}: ${error.message}`);
1377
1426
  }
1378
1427
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dank-ai",
3
- "version": "1.0.19",
3
+ "version": "1.0.21",
4
4
  "description": "Dank Agent Service - Docker-based AI agent orchestration platform",
5
5
  "main": "lib/index.js",
6
6
  "exports": {