dank-ai 1.0.20 → 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 +5 -0
- package/lib/analytics.js +241 -0
- package/lib/cli/init.js +8 -0
- package/lib/cli/production-build.js +15 -0
- package/lib/cli/run.js +8 -0
- package/lib/docker/manager.js +49 -0
- package/package.json +1 -1
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')
|
package/lib/analytics.js
ADDED
|
@@ -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...'));
|
package/lib/docker/manager.js
CHANGED
|
@@ -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
|
}
|