@tonk/cli 0.2.6 → 0.2.8

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.
Files changed (49) hide show
  1. package/dist/commands/create.d.ts.map +1 -1
  2. package/dist/commands/create.js +8 -6
  3. package/dist/commands/create.js.map +1 -1
  4. package/dist/commands/deploy.d.ts +3 -0
  5. package/dist/commands/deploy.d.ts.map +1 -0
  6. package/dist/commands/deploy.js +268 -0
  7. package/dist/commands/deploy.js.map +1 -0
  8. package/dist/commands/hello.d.ts.map +1 -1
  9. package/dist/commands/hello.js +12 -0
  10. package/dist/commands/hello.js.map +1 -1
  11. package/dist/commands/kill.d.ts.map +1 -1
  12. package/dist/commands/kill.js +24 -0
  13. package/dist/commands/kill.js.map +1 -1
  14. package/dist/commands/ls.d.ts.map +1 -1
  15. package/dist/commands/ls.js +18 -0
  16. package/dist/commands/ls.js.map +1 -1
  17. package/dist/commands/proxy.d.ts.map +1 -1
  18. package/dist/commands/proxy.js +18 -0
  19. package/dist/commands/proxy.js.map +1 -1
  20. package/dist/commands/ps.d.ts.map +1 -1
  21. package/dist/commands/ps.js +18 -0
  22. package/dist/commands/ps.js.map +1 -1
  23. package/dist/commands/push.d.ts.map +1 -1
  24. package/dist/commands/push.js +25 -1
  25. package/dist/commands/push.js.map +1 -1
  26. package/dist/commands/start.d.ts.map +1 -1
  27. package/dist/commands/start.js +19 -0
  28. package/dist/commands/start.js.map +1 -1
  29. package/dist/commands/worker/commands.d.ts.map +1 -1
  30. package/dist/commands/worker/commands.js +331 -5
  31. package/dist/commands/worker/commands.js.map +1 -1
  32. package/dist/commands/worker/index.d.ts.map +1 -1
  33. package/dist/commands/worker/index.js +2 -0
  34. package/dist/commands/worker/index.js.map +1 -1
  35. package/dist/commands/worker.d.ts +3 -0
  36. package/dist/commands/worker.d.ts.map +1 -0
  37. package/dist/commands/worker.js +527 -0
  38. package/dist/commands/worker.js.map +1 -0
  39. package/dist/lib/workerManager.d.ts.map +1 -1
  40. package/dist/lib/workerManager.js +16 -36
  41. package/dist/lib/workerManager.js.map +1 -1
  42. package/dist/tonk.js +12 -1
  43. package/dist/tonk.js.map +1 -1
  44. package/dist/types/workerConfig.d.ts +2 -2
  45. package/dist/utils/analytics.d.ts +26 -0
  46. package/dist/utils/analytics.d.ts.map +1 -0
  47. package/dist/utils/analytics.js +155 -0
  48. package/dist/utils/analytics.js.map +1 -0
  49. package/package.json +3 -1
@@ -7,6 +7,7 @@ import { exec } from 'node:child_process';
7
7
  import { TonkWorkerManager } from '../../lib/workerManager.js';
8
8
  import { displayWorkerDetails } from './utils/display.js';
9
9
  import { findWorkerRoot, findAvailablePort } from './utils/finder.js';
10
+ import { trackCommand, trackCommandError, trackCommandSuccess, } from '../../utils/analytics.js';
10
11
  import { readPackageJson, readWorkerConfigJs, updateWorkerConfig, promptForMissingOptions, generatePackageJsonContent, generateWorkerConfigJsContent, } from './utils/config.js';
11
12
  /**
12
13
  * Register the inspect command
@@ -20,13 +21,25 @@ export function registerInspectCommand(workerCommand) {
20
21
  .option('-c, --config <path>', 'Path to worker configuration file')
21
22
  .option('-p, --ping', 'Ping the worker to check its status')
22
23
  .action(async (nameOrId, options) => {
24
+ const startTime = Date.now();
23
25
  try {
26
+ trackCommand('worker-inspect', {
27
+ nameOrId,
28
+ start: options.start,
29
+ stop: options.stop,
30
+ config: !!options.config,
31
+ ping: options.ping,
32
+ });
24
33
  // Create worker manager
25
34
  const workerManager = new TonkWorkerManager();
26
35
  // Get worker
27
36
  const worker = await workerManager.findByNameOrId(nameOrId);
28
37
  if (!worker) {
29
38
  console.error(chalk.red(`Worker with name or ID '${nameOrId}' not found.`));
39
+ const duration = Date.now() - startTime;
40
+ trackCommandError('worker-inspect', new Error('Worker not found'), duration, {
41
+ nameOrId,
42
+ });
30
43
  return;
31
44
  }
32
45
  // If no options provided, show worker details
@@ -35,6 +48,12 @@ export function registerInspectCommand(workerCommand) {
35
48
  !options.config &&
36
49
  !options.ping) {
37
50
  displayWorkerDetails(worker);
51
+ const duration = Date.now() - startTime;
52
+ trackCommandSuccess('worker-inspect', duration, {
53
+ workerId: worker.id,
54
+ workerName: worker.name,
55
+ action: 'display',
56
+ });
38
57
  return;
39
58
  }
40
59
  // Handle ping option
@@ -48,6 +67,13 @@ export function registerInspectCommand(workerCommand) {
48
67
  else {
49
68
  console.log(chalk.red(`Worker '${worker.name}' is not responding.`));
50
69
  }
70
+ const duration = Date.now() - startTime;
71
+ trackCommandSuccess('worker-inspect', duration, {
72
+ workerId: worker.id,
73
+ workerName: worker.name,
74
+ action: 'ping',
75
+ isHealthy,
76
+ });
51
77
  return;
52
78
  }
53
79
  // Handle start option
@@ -55,6 +81,12 @@ export function registerInspectCommand(workerCommand) {
55
81
  console.log(chalk.blue(`Starting worker '${worker.name}'...`));
56
82
  await workerManager.start(worker.id);
57
83
  console.log(chalk.green(`Worker '${worker.name}' started successfully!`));
84
+ const duration = Date.now() - startTime;
85
+ trackCommandSuccess('worker-inspect', duration, {
86
+ workerId: worker.id,
87
+ workerName: worker.name,
88
+ action: 'start',
89
+ });
58
90
  return;
59
91
  }
60
92
  // Handle stop option
@@ -62,14 +94,32 @@ export function registerInspectCommand(workerCommand) {
62
94
  console.log(chalk.blue(`Stopping worker '${worker.name}'...`));
63
95
  await workerManager.stop(worker.id);
64
96
  console.log(chalk.green(`Worker '${worker.name}' stopped successfully!`));
97
+ const duration = Date.now() - startTime;
98
+ trackCommandSuccess('worker-inspect', duration, {
99
+ workerId: worker.id,
100
+ workerName: worker.name,
101
+ action: 'stop',
102
+ });
65
103
  return;
66
104
  }
67
105
  // Handle config option
68
106
  if (options.config) {
69
107
  await updateWorkerConfig(workerManager, worker.id, options.config);
108
+ const duration = Date.now() - startTime;
109
+ trackCommandSuccess('worker-inspect', duration, {
110
+ workerId: worker.id,
111
+ workerName: worker.name,
112
+ action: 'config',
113
+ configPath: options.config,
114
+ });
70
115
  }
71
116
  }
72
117
  catch (error) {
118
+ const duration = Date.now() - startTime;
119
+ trackCommandError('worker-inspect', error, duration, {
120
+ nameOrId,
121
+ options,
122
+ });
73
123
  console.error(chalk.red('Failed to manage worker:'), error);
74
124
  }
75
125
  });
@@ -82,7 +132,9 @@ export function registerListCommand(workerCommand) {
82
132
  .command('ls')
83
133
  .description('List all registered workers')
84
134
  .action(async () => {
135
+ const startTime = Date.now();
85
136
  try {
137
+ trackCommand('worker-ls', {});
86
138
  // Create worker manager
87
139
  const workerManager = new TonkWorkerManager();
88
140
  // Get all workers
@@ -90,6 +142,10 @@ export function registerListCommand(workerCommand) {
90
142
  if (workers.length === 0) {
91
143
  console.log(chalk.yellow('No workers registered yet.'));
92
144
  console.log(chalk.blue(`Use '${chalk.bold('tonk worker register')}' to register a worker.`));
145
+ const duration = Date.now() - startTime;
146
+ trackCommandSuccess('worker-ls', duration, {
147
+ workerCount: 0,
148
+ });
93
149
  return;
94
150
  }
95
151
  // Create a table for display
@@ -123,8 +179,15 @@ export function registerListCommand(workerCommand) {
123
179
  console.log(chalk.bold(`Registered Workers (${workers.length}):`));
124
180
  console.log(table.toString());
125
181
  console.log(chalk.blue(`\nUse '${chalk.bold('tonk worker inspect <name or id>')}' to view details of a specific worker.`));
182
+ const duration = Date.now() - startTime;
183
+ trackCommandSuccess('worker-ls', duration, {
184
+ workerCount: workers.length,
185
+ activeWorkers: workers.filter(w => w.status.active).length,
186
+ });
126
187
  }
127
188
  catch (error) {
189
+ const duration = Date.now() - startTime;
190
+ trackCommandError('worker-ls', error, duration);
128
191
  console.error(chalk.red('Failed to list workers:'), error);
129
192
  }
130
193
  });
@@ -137,20 +200,37 @@ export function registerRemoveCommand(workerCommand) {
137
200
  .command('rm <nameOrId>')
138
201
  .description('Remove a registered worker')
139
202
  .action(async (nameOrId) => {
203
+ const startTime = Date.now();
140
204
  try {
205
+ trackCommand('worker-rm', {
206
+ nameOrId,
207
+ });
141
208
  // Create worker manager
142
209
  const workerManager = new TonkWorkerManager();
143
210
  // Get worker
144
211
  const worker = await workerManager.findByNameOrId(nameOrId);
145
212
  if (!worker) {
146
213
  console.error(chalk.red(`Worker with name or ID '${nameOrId}' not found.`));
214
+ const duration = Date.now() - startTime;
215
+ trackCommandError('worker-rm', new Error('Worker not found'), duration, {
216
+ nameOrId,
217
+ });
147
218
  return;
148
219
  }
149
220
  // Remove worker
150
221
  await workerManager.remove(worker.id);
151
222
  console.log(chalk.green(`Worker '${worker.name}' (${worker.id}) removed successfully.`));
223
+ const duration = Date.now() - startTime;
224
+ trackCommandSuccess('worker-rm', duration, {
225
+ workerId: worker.id,
226
+ workerName: worker.name,
227
+ });
152
228
  }
153
229
  catch (error) {
230
+ const duration = Date.now() - startTime;
231
+ trackCommandError('worker-rm', error, duration, {
232
+ nameOrId,
233
+ });
154
234
  console.error(chalk.red('Failed to remove worker:'), error);
155
235
  }
156
236
  });
@@ -163,13 +243,21 @@ export function registerPingCommand(workerCommand) {
163
243
  .command('ping <nameOrId>')
164
244
  .description('Ping a worker to check its status')
165
245
  .action(async (nameOrId) => {
246
+ const startTime = Date.now();
166
247
  try {
248
+ trackCommand('worker-ping', {
249
+ nameOrId,
250
+ });
167
251
  // Create worker manager
168
252
  const workerManager = new TonkWorkerManager();
169
253
  // Get worker
170
254
  const worker = await workerManager.findByNameOrId(nameOrId);
171
255
  if (!worker) {
172
256
  console.error(chalk.red(`Worker with name or ID '${nameOrId}' not found.`));
257
+ const duration = Date.now() - startTime;
258
+ trackCommandError('worker-ping', new Error('Worker not found'), duration, {
259
+ nameOrId,
260
+ });
173
261
  return;
174
262
  }
175
263
  console.log(chalk.blue(`Pinging worker '${worker.name}' at ${worker.endpoint}...`));
@@ -181,8 +269,18 @@ export function registerPingCommand(workerCommand) {
181
269
  else {
182
270
  console.log(chalk.red(`Worker '${worker.name}' is not responding.`));
183
271
  }
272
+ const duration = Date.now() - startTime;
273
+ trackCommandSuccess('worker-ping', duration, {
274
+ workerId: worker.id,
275
+ workerName: worker.name,
276
+ isHealthy,
277
+ });
184
278
  }
185
279
  catch (error) {
280
+ const duration = Date.now() - startTime;
281
+ trackCommandError('worker-ping', error, duration, {
282
+ nameOrId,
283
+ });
186
284
  console.error(chalk.red('Failed to ping worker:'), error);
187
285
  }
188
286
  });
@@ -195,20 +293,37 @@ export function registerStartCommand(workerCommand) {
195
293
  .command('start <nameOrId>')
196
294
  .description('Start a worker')
197
295
  .action(async (nameOrId) => {
296
+ const startTime = Date.now();
198
297
  try {
298
+ trackCommand('worker-start', {
299
+ nameOrId,
300
+ });
199
301
  // Create worker manager
200
302
  const workerManager = new TonkWorkerManager();
201
303
  // Get worker
202
304
  const worker = await workerManager.findByNameOrId(nameOrId);
203
305
  if (!worker) {
204
306
  console.error(chalk.red(`Worker with name or ID '${nameOrId}' not found.`));
307
+ const duration = Date.now() - startTime;
308
+ trackCommandError('worker-start', new Error('Worker not found'), duration, {
309
+ nameOrId,
310
+ });
205
311
  return;
206
312
  }
207
313
  console.log(chalk.blue(`Starting worker '${worker.name}'...`));
208
314
  await workerManager.start(worker.id);
209
315
  console.log(chalk.green(`Worker '${worker.name}' started successfully!`));
316
+ const duration = Date.now() - startTime;
317
+ trackCommandSuccess('worker-start', duration, {
318
+ workerId: worker.id,
319
+ workerName: worker.name,
320
+ });
210
321
  }
211
322
  catch (error) {
323
+ const duration = Date.now() - startTime;
324
+ trackCommandError('worker-start', error, duration, {
325
+ nameOrId,
326
+ });
212
327
  console.error(chalk.red('Failed to start worker:'), error);
213
328
  }
214
329
  });
@@ -221,20 +336,37 @@ export function registerStopCommand(workerCommand) {
221
336
  .command('stop <nameOrId>')
222
337
  .description('Stop a worker')
223
338
  .action(async (nameOrId) => {
339
+ const startTime = Date.now();
224
340
  try {
341
+ trackCommand('worker-stop', {
342
+ nameOrId,
343
+ });
225
344
  // Create worker manager
226
345
  const workerManager = new TonkWorkerManager();
227
346
  // Get worker
228
347
  const worker = await workerManager.findByNameOrId(nameOrId);
229
348
  if (!worker) {
230
349
  console.error(chalk.red(`Worker with name or ID '${nameOrId}' not found.`));
350
+ const duration = Date.now() - startTime;
351
+ trackCommandError('worker-stop', new Error('Worker not found'), duration, {
352
+ nameOrId,
353
+ });
231
354
  return;
232
355
  }
233
356
  console.log(chalk.blue(`Stopping worker '${worker.name}'...`));
234
357
  await workerManager.stop(worker.id);
235
358
  console.log(chalk.green(`Worker '${worker.name}' stopped successfully!`));
359
+ const duration = Date.now() - startTime;
360
+ trackCommandSuccess('worker-stop', duration, {
361
+ workerId: worker.id,
362
+ workerName: worker.name,
363
+ });
236
364
  }
237
365
  catch (error) {
366
+ const duration = Date.now() - startTime;
367
+ trackCommandError('worker-stop', error, duration, {
368
+ nameOrId,
369
+ });
238
370
  console.error(chalk.red('Failed to stop worker:'), error);
239
371
  }
240
372
  });
@@ -251,13 +383,25 @@ export function registerLogsCommand(workerCommand) {
251
383
  .option('-e, --error', 'Show only error logs')
252
384
  .option('-o, --out', 'Show only standard output logs')
253
385
  .action(async (nameOrId, options) => {
386
+ const startTime = Date.now();
254
387
  try {
388
+ trackCommand('worker-logs', {
389
+ nameOrId,
390
+ follow: options.follow,
391
+ lines: options.lines,
392
+ error: options.error,
393
+ out: options.out,
394
+ });
255
395
  // Create worker manager
256
396
  const workerManager = new TonkWorkerManager();
257
397
  // Get worker
258
398
  const worker = await workerManager.findByNameOrId(nameOrId);
259
399
  if (!worker) {
260
400
  console.error(chalk.red(`Worker with name or ID '${nameOrId}' not found.`));
401
+ const duration = Date.now() - startTime;
402
+ trackCommandError('worker-logs', new Error('Worker not found'), duration, {
403
+ nameOrId,
404
+ });
261
405
  return;
262
406
  }
263
407
  console.log(chalk.blue(`Fetching logs for worker '${worker.name}'...`));
@@ -309,12 +453,31 @@ export function registerLogsCommand(workerCommand) {
309
453
  child.on('exit', resolve);
310
454
  });
311
455
  }
456
+ const duration = Date.now() - startTime;
457
+ trackCommandSuccess('worker-logs', duration, {
458
+ workerId: worker.id,
459
+ workerName: worker.name,
460
+ follow: options.follow,
461
+ lines: options.lines,
462
+ logType: options.error ? 'error' : options.out ? 'out' : 'all',
463
+ });
312
464
  }
313
465
  catch (error) {
466
+ const duration = Date.now() - startTime;
467
+ trackCommandError('worker-logs', error, duration, {
468
+ workerId: worker.id,
469
+ workerName: worker.name,
470
+ options,
471
+ });
314
472
  console.error(chalk.red('Failed to fetch logs:'), error);
315
473
  }
316
474
  }
317
475
  catch (error) {
476
+ const duration = Date.now() - startTime;
477
+ trackCommandError('worker-logs', error, duration, {
478
+ nameOrId,
479
+ options,
480
+ });
318
481
  console.error(chalk.red('Failed to fetch worker logs:'), error);
319
482
  }
320
483
  });
@@ -332,7 +495,15 @@ export function registerRegisterCommand(workerCommand) {
332
495
  .option('-p, --port <port>', 'Port number for the worker')
333
496
  .option('-d, --description <description>', 'Description of the worker')
334
497
  .action(async (dir = '.', options) => {
498
+ const startTime = Date.now();
335
499
  try {
500
+ trackCommand('worker-register', {
501
+ hasDir: !!dir && dir !== '.',
502
+ hasName: !!options.name,
503
+ hasEndpoint: !!options.endpoint,
504
+ hasPort: !!options.port,
505
+ hasDescription: !!options.description,
506
+ });
336
507
  // Create worker manager
337
508
  const workerManager = new TonkWorkerManager();
338
509
  // If options are provided, use them directly
@@ -358,6 +529,13 @@ export function registerRegisterCommand(workerCommand) {
358
529
  console.log(` ${key}=${value}`);
359
530
  });
360
531
  }
532
+ const duration = Date.now() - startTime;
533
+ trackCommandSuccess('worker-register', duration, {
534
+ workerId: worker.id,
535
+ workerName: worker.name,
536
+ registrationType: 'direct',
537
+ hasCustomPort: !!options.port,
538
+ });
361
539
  return;
362
540
  }
363
541
  // Look for package.json and worker.config.js files
@@ -365,6 +543,10 @@ export function registerRegisterCommand(workerCommand) {
365
543
  if (!workerDir) {
366
544
  console.error(chalk.red(`No package.json or worker.config.js found in ${path.resolve(dir)} or its parent directories.`));
367
545
  console.log(chalk.yellow('Make sure you are in a valid worker directory or specify the path to one, or provide --name and --endpoint options.'));
546
+ const duration = Date.now() - startTime;
547
+ trackCommandError('worker-register', new Error('Worker directory not found'), duration, {
548
+ dir: path.resolve(dir),
549
+ });
368
550
  return;
369
551
  }
370
552
  console.log(chalk.blue(`Found worker directory at: ${workerDir}`));
@@ -373,6 +555,10 @@ export function registerRegisterCommand(workerCommand) {
373
555
  const packageJson = await readPackageJson(packageJsonPath);
374
556
  if (!packageJson) {
375
557
  console.error(chalk.red(`Failed to parse package.json file at ${packageJsonPath}`));
558
+ const duration = Date.now() - startTime;
559
+ trackCommandError('worker-register', new Error('Failed to parse package.json'), duration, {
560
+ packageJsonPath,
561
+ });
376
562
  return;
377
563
  }
378
564
  // Read worker.config.js for configuration
@@ -380,6 +566,10 @@ export function registerRegisterCommand(workerCommand) {
380
566
  const workerConfig = await readWorkerConfigJs(workerConfigPath);
381
567
  if (!workerConfig) {
382
568
  console.error(chalk.red(`Failed to parse worker.config.js file at ${workerConfigPath}`));
569
+ const duration = Date.now() - startTime;
570
+ trackCommandError('worker-register', new Error('Failed to parse worker.config.js'), duration, {
571
+ workerConfigPath,
572
+ });
383
573
  return;
384
574
  }
385
575
  // Determine port from config or use default
@@ -411,8 +601,22 @@ export function registerRegisterCommand(workerCommand) {
411
601
  console.log(` ${key}=${value}`);
412
602
  });
413
603
  }
604
+ const duration = Date.now() - startTime;
605
+ trackCommandSuccess('worker-register', duration, {
606
+ workerId: worker.id,
607
+ workerName: worker.name,
608
+ registrationType: 'config-based',
609
+ workerDir,
610
+ port,
611
+ hasCustomEndpoint: !!options.endpoint,
612
+ });
414
613
  }
415
614
  catch (error) {
615
+ const duration = Date.now() - startTime;
616
+ trackCommandError('worker-register', error, duration, {
617
+ dir,
618
+ options,
619
+ });
416
620
  console.error(chalk.red('Failed to register worker:'), error);
417
621
  }
418
622
  });
@@ -427,7 +631,13 @@ export function registerInstallCommand(workerCommand) {
427
631
  .option('-p, --port <port>', 'Specify a port for the worker (default: auto-detect)')
428
632
  .option('-n, --name <n>', 'Custom name for the worker (default: npm package name)')
429
633
  .action(async (packageName, options) => {
634
+ const startTime = Date.now();
430
635
  try {
636
+ trackCommand('worker-install', {
637
+ packageName,
638
+ hasCustomPort: !!options.port,
639
+ hasCustomName: !!options.name,
640
+ });
431
641
  console.log(chalk.blue(`Installing worker from npm package: ${packageName}...`));
432
642
  // Create worker manager
433
643
  const workerManager = new TonkWorkerManager();
@@ -440,6 +650,11 @@ export function registerInstallCommand(workerCommand) {
440
650
  }
441
651
  catch (error) {
442
652
  console.error(chalk.red('Failed to install package:'), error);
653
+ const duration = Date.now() - startTime;
654
+ trackCommandError('worker-install', error, duration, {
655
+ packageName,
656
+ stage: 'npm-install',
657
+ });
443
658
  return;
444
659
  }
445
660
  // Find an available port starting from 5555
@@ -456,9 +671,57 @@ export function registerInstallCommand(workerCommand) {
456
671
  }
457
672
  catch (error) {
458
673
  console.error(chalk.red('Failed to get package info:'), error);
674
+ const duration = Date.now() - startTime;
675
+ trackCommandError('worker-install', error, duration, {
676
+ packageName,
677
+ stage: 'package-info',
678
+ });
459
679
  return;
460
680
  }
461
- // Register the worker with the npm package name (use display name in description)
681
+ // Strip scope from package name for display purposes (e.g., @tonk/worker -> worker)
682
+ const commandName = options.name || packageName.replace(/^@[^/]+\//, '');
683
+ // Verify the package can be executed directly
684
+ let setupCompleted = false;
685
+ try {
686
+ // Check if the command exists by running a simple help command
687
+ await execAsync(`${commandName} --help`);
688
+ console.log(chalk.green(`Verified that '${packageName}' is executable.`));
689
+ // Try running the setup command if it exists
690
+ try {
691
+ console.log(chalk.blue(`Running setup for '${packageName}'...`));
692
+ // Use spawn to allow user interaction during setup
693
+ const { spawn } = await import('node:child_process');
694
+ const setupProcess = spawn(commandName, ['setup'], {
695
+ stdio: 'inherit',
696
+ shell: true,
697
+ });
698
+ // Wait for the setup process to complete
699
+ setupCompleted = await new Promise((resolve, reject) => {
700
+ setupProcess.on('close', code => {
701
+ if (code === 0) {
702
+ console.log(chalk.green(`Setup completed successfully for '${packageName}'`));
703
+ resolve(true);
704
+ }
705
+ else {
706
+ console.warn(chalk.yellow(`Setup command exited with code ${code}`));
707
+ resolve(false);
708
+ }
709
+ });
710
+ setupProcess.on('error', err => {
711
+ reject(err);
712
+ });
713
+ });
714
+ }
715
+ catch (setupError) {
716
+ console.log(chalk.yellow(`Setup command not available for '${packageName}', continuing with installation...`));
717
+ }
718
+ }
719
+ catch (error) {
720
+ const errorMessage = error instanceof Error ? error.message : String(error);
721
+ console.warn(chalk.yellow(`Warning: Could not verify that '${packageName}' is executable. It may not be properly installed or may not provide a CLI.`));
722
+ console.warn(chalk.yellow(`Error: ${errorMessage}`));
723
+ }
724
+ // Register the worker with the npm package name
462
725
  const worker = await workerManager.register({
463
726
  name: packageName, // Use the actual package name for npm resolution
464
727
  description: packageInfo.description || `Worker from npm package ${packageName}`,
@@ -467,20 +730,40 @@ export function registerInstallCommand(workerCommand) {
467
730
  env: [`WORKER_PORT=${port}`],
468
731
  type: 'npm',
469
732
  });
470
- console.log(chalk.green(`Worker '${worker.name}' registered successfully!`));
733
+ console.log(chalk.green(`Worker '${packageName}' registered successfully!`));
471
734
  // Start the worker
472
- console.log(chalk.blue(`Starting worker '${worker.name}'...`));
735
+ console.log(chalk.blue(`Starting worker '${packageName}'...`));
473
736
  const success = await workerManager.start(worker.id);
474
737
  if (success) {
475
- console.log(chalk.green(`Worker '${worker.name}' started successfully!`));
738
+ console.log(chalk.green(`Worker '${packageName}' started successfully!`));
476
739
  console.log(chalk.cyan('Worker ID:'), chalk.bold(worker.id));
477
740
  console.log(chalk.cyan('Endpoint:'), chalk.bold(worker.endpoint));
741
+ const duration = Date.now() - startTime;
742
+ trackCommandSuccess('worker-install', duration, {
743
+ workerId: worker.id,
744
+ workerName: worker.name,
745
+ packageName,
746
+ port,
747
+ setupCompleted,
748
+ startedSuccessfully: true,
749
+ });
478
750
  }
479
751
  else {
480
- console.error(chalk.red(`Failed to start worker '${worker.name}'.`));
752
+ console.error(chalk.red(`Failed to start worker '${packageName}'.`));
753
+ const duration = Date.now() - startTime;
754
+ trackCommandError('worker-install', new Error('Failed to start worker'), duration, {
755
+ workerId: worker.id,
756
+ packageName,
757
+ stage: 'worker-start',
758
+ });
481
759
  }
482
760
  }
483
761
  catch (error) {
762
+ const duration = Date.now() - startTime;
763
+ trackCommandError('worker-install', error, duration, {
764
+ packageName,
765
+ options,
766
+ });
484
767
  console.error(chalk.red('Failed to install worker:'), error);
485
768
  }
486
769
  });
@@ -497,22 +780,33 @@ export function registerInitCommand(workerCommand) {
497
780
  .option('-p, --port <port>', 'Port number for the worker', '5555')
498
781
  .option('-D, --description <description>', 'Description of the worker')
499
782
  .action(async (options) => {
783
+ const startTime = Date.now();
500
784
  try {
785
+ trackCommand('worker-init', {
786
+ hasCustomDir: options.dir !== '.',
787
+ hasName: !!options.name,
788
+ hasCustomPort: options.port !== '5555',
789
+ hasDescription: !!options.description,
790
+ });
501
791
  // Prompt for missing options
502
792
  const answers = await promptForMissingOptions(options);
503
793
  const mergedOptions = { ...options, ...answers };
504
794
  // Create the directory if it doesn't exist
505
795
  const targetDir = path.resolve(mergedOptions.dir);
796
+ let directoryCreated = false;
506
797
  if (!fs.existsSync(targetDir)) {
507
798
  fs.mkdirSync(targetDir, { recursive: true });
508
799
  console.log(chalk.blue(`Created directory: ${targetDir}`));
800
+ directoryCreated = true;
509
801
  }
510
802
  // Generate the package.json content if it doesn't exist
511
803
  const packageJsonPath = path.join(targetDir, 'package.json');
804
+ let packageJsonCreated = false;
512
805
  if (!fs.existsSync(packageJsonPath)) {
513
806
  const packageJsonContent = generatePackageJsonContent(mergedOptions);
514
807
  fs.writeFileSync(packageJsonPath, packageJsonContent);
515
808
  console.log(chalk.green(`Created package.json at: ${packageJsonPath}`));
809
+ packageJsonCreated = true;
516
810
  }
517
811
  // Generate the worker.config.js content
518
812
  const workerConfigContent = generateWorkerConfigJsContent();
@@ -520,13 +814,16 @@ export function registerInitCommand(workerCommand) {
520
814
  fs.writeFileSync(workerConfigPath, workerConfigContent);
521
815
  // Create src directory if it doesn't exist
522
816
  const srcDir = path.join(targetDir, 'src');
817
+ let srcDirCreated = false;
523
818
  if (!fs.existsSync(srcDir)) {
524
819
  fs.mkdirSync(srcDir, { recursive: true });
525
820
  console.log(chalk.blue(`Created src directory: ${srcDir}`));
821
+ srcDirCreated = true;
526
822
  }
527
823
  // Copy CLI template file
528
824
  const cliTemplatePath = path.join(__dirname, 'templates', 'cli.ts.template');
529
825
  const cliDestPath = path.join(srcDir, 'cli.ts');
826
+ let cliFileCreated = false;
530
827
  if (fs.existsSync(cliTemplatePath)) {
531
828
  let cliContent = fs.readFileSync(cliTemplatePath, 'utf-8');
532
829
  // Replace template variables
@@ -536,6 +833,7 @@ export function registerInitCommand(workerCommand) {
536
833
  .replace(/{{version}}/g, '1.0.0');
537
834
  fs.writeFileSync(cliDestPath, cliContent);
538
835
  console.log(chalk.green(`Created CLI file at: ${cliDestPath}`));
836
+ cliFileCreated = true;
539
837
  }
540
838
  else {
541
839
  console.warn(chalk.yellow(`CLI template not found at: ${cliTemplatePath}`));
@@ -543,6 +841,7 @@ export function registerInitCommand(workerCommand) {
543
841
  // Copy index.ts template file
544
842
  const indexTemplatePath = path.join(__dirname, 'templates', 'index.ts.template');
545
843
  const indexDestPath = path.join(srcDir, 'index.ts');
844
+ let indexFileCreated = false;
546
845
  if (!fs.existsSync(indexDestPath) && fs.existsSync(indexTemplatePath)) {
547
846
  let indexContent = fs.readFileSync(indexTemplatePath, 'utf-8');
548
847
  // Replace template variables
@@ -552,6 +851,7 @@ export function registerInitCommand(workerCommand) {
552
851
  .replace(/{{port}}/g, mergedOptions.port);
553
852
  fs.writeFileSync(indexDestPath, indexContent);
554
853
  console.log(chalk.green(`Created index.ts file at: ${indexDestPath}`));
854
+ indexFileCreated = true;
555
855
  }
556
856
  else if (!fs.existsSync(indexTemplatePath)) {
557
857
  console.warn(chalk.yellow(`Index template not found at: ${indexTemplatePath}`));
@@ -559,11 +859,13 @@ export function registerInitCommand(workerCommand) {
559
859
  // Copy tsconfig.json template file
560
860
  const tsconfigTemplatePath = path.join(__dirname, 'templates', 'tsconfig.json.template');
561
861
  const tsconfigDestPath = path.join(targetDir, 'tsconfig.json');
862
+ let tsconfigFileCreated = false;
562
863
  if (!fs.existsSync(tsconfigDestPath) &&
563
864
  fs.existsSync(tsconfigTemplatePath)) {
564
865
  const tsconfigContent = fs.readFileSync(tsconfigTemplatePath, 'utf-8');
565
866
  fs.writeFileSync(tsconfigDestPath, tsconfigContent);
566
867
  console.log(chalk.green(`Created tsconfig.json file at: ${tsconfigDestPath}`));
868
+ tsconfigFileCreated = true;
567
869
  }
568
870
  else if (!fs.existsSync(tsconfigTemplatePath)) {
569
871
  console.warn(chalk.yellow(`tsconfig.json template not found at: ${tsconfigTemplatePath}`));
@@ -571,8 +873,32 @@ export function registerInitCommand(workerCommand) {
571
873
  console.log(chalk.green(`Worker configuration file created at: ${workerConfigPath}`));
572
874
  console.log(chalk.blue(`\nYou can now register this worker with:`));
573
875
  console.log(chalk.cyan(` tonk worker register ${targetDir}`));
876
+ const duration = Date.now() - startTime;
877
+ trackCommandSuccess('worker-init', duration, {
878
+ workerName: mergedOptions.name,
879
+ targetDir,
880
+ port: mergedOptions.port,
881
+ directoryCreated,
882
+ packageJsonCreated,
883
+ srcDirCreated,
884
+ cliFileCreated,
885
+ indexFileCreated,
886
+ tsconfigFileCreated,
887
+ filesCreated: [
888
+ packageJsonCreated && 'package.json',
889
+ 'worker.config.js',
890
+ srcDirCreated && 'src/',
891
+ cliFileCreated && 'cli.ts',
892
+ indexFileCreated && 'index.ts',
893
+ tsconfigFileCreated && 'tsconfig.json',
894
+ ].filter(Boolean).length,
895
+ });
574
896
  }
575
897
  catch (error) {
898
+ const duration = Date.now() - startTime;
899
+ trackCommandError('worker-init', error, duration, {
900
+ options,
901
+ });
576
902
  console.error(chalk.red('Failed to initialise worker configuration:'), error);
577
903
  }
578
904
  });