slackhive 0.1.30 → 0.1.32

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.
@@ -382,119 +382,79 @@ async function init(opts) {
382
382
  console.log('');
383
383
  }
384
384
  /**
385
- * Runs `docker compose up -d --build` with live streaming progress output.
386
- * Shows each build step as it happens instead of a silent spinner.
387
- *
388
- * @param {string} cwd - The project directory.
389
- * @param {string} displayDir - Display name for error message.
390
- * @returns {Promise<void>}
385
+ * Runs `docker compose up -d --build`.
386
+ * Shows a single updating spinner line with the current build step.
387
+ * Docker's raw progress output is suppressed to keep the terminal clean.
391
388
  */
392
389
  function runDockerBuild(cwd, displayDir) {
393
- return new Promise((resolve, reject) => {
394
- const proc = (0, child_process_1.spawn)('docker', ['compose', 'up', '-d', '--build'], {
390
+ return new Promise((resolve) => {
391
+ const proc = (0, child_process_1.spawn)('docker', ['compose', 'up', '-d', '--build', '--progress', 'plain'], {
395
392
  cwd,
396
393
  env: { ...process.env },
397
394
  });
398
- const stepPattern = /^#\d+ \[([^\]]+)\] (.+)/;
399
- const donePattern = /^\s*(✔|Container .+ (Started|Running|Healthy)|Image .+ Built)/i;
400
- let lastStep = '';
401
- const processLine = (line) => {
402
- const trimmed = line.trim();
403
- if (!trimmed || trimmed.startsWith('#') && trimmed.includes('CACHED'))
404
- return;
405
- const stepMatch = stepPattern.exec(trimmed);
406
- if (stepMatch) {
407
- const label = ` ${chalk_1.default.dim(stepMatch[1])} ${stepMatch[2]}`;
408
- if (label !== lastStep) {
409
- process.stdout.write('\r\x1b[K' + label.slice(0, process.stdout.columns - 2));
410
- lastStep = label;
411
- }
412
- return;
413
- }
414
- if (donePattern.test(trimmed)) {
415
- process.stdout.write('\r\x1b[K');
416
- console.log(' ' + chalk_1.default.green('✓') + ' ' + trimmed.replace(/^✔\s*/, '').replace(/Container /, ''));
417
- }
418
- };
419
395
  const startTime = Date.now();
420
396
  const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
421
397
  let frameIdx = 0;
422
398
  let currentStep = 'Building images';
423
- const fallbackInterval = setInterval(() => {
399
+ const spinnerInterval = setInterval(() => {
424
400
  const elapsed = Math.floor((Date.now() - startTime) / 1000);
425
401
  const frame = frames[frameIdx++ % frames.length];
426
- process.stdout.write(`\r\x1b[K ${chalk_1.default.hex('#D97757')(frame)} ${currentStep} ${chalk_1.default.gray(elapsed + 's')}`);
402
+ const cols = process.stdout.columns || 80;
403
+ const line = ` ${chalk_1.default.hex('#D97757')(frame)} ${currentStep} ${chalk_1.default.gray(elapsed + 's')}`;
404
+ process.stdout.write(`\r\x1b[K${line.slice(0, cols - 1)}`);
427
405
  }, 80);
428
- let stdoutBuf = '';
429
- let stderrBuf = '';
406
+ let buf = '';
430
407
  const errorLines = [];
431
- proc.stdout.on('data', (chunk) => {
432
- stdoutBuf += chunk.toString();
433
- const lines = stdoutBuf.split('\n');
434
- stdoutBuf = lines.pop() ?? '';
435
- lines.forEach(line => {
436
- processLine(line);
437
- // Update current step label from build output
438
- const m = /\[([^\]]+)\] (.+)/.exec(line.trim());
439
- if (m)
440
- currentStep = `${m[1]} — ${m[2].slice(0, 40)}`;
441
- });
442
- });
443
- proc.stderr.on('data', (chunk) => {
444
- stderrBuf += chunk.toString();
445
- const lines = stderrBuf.split('\n');
446
- stderrBuf = lines.pop() ?? '';
447
- lines.forEach(line => {
448
- processLine(line);
449
- const m = /\[([^\]]+)\] (.+)/.exec(line.trim());
450
- if (m)
451
- currentStep = `${m[1]} — ${m[2].slice(0, 40)}`;
452
- if (/error/i.test(line) && line.trim())
453
- errorLines.push(line.trim());
454
- });
455
- });
408
+ const onData = (chunk) => {
409
+ buf += chunk.toString().replace(/\x1b\[[0-9;]*[a-zA-Z]/g, ''); // strip ANSI
410
+ const lines = buf.split('\n');
411
+ buf = lines.pop() ?? '';
412
+ for (const raw of lines) {
413
+ const line = raw.trim();
414
+ if (!line)
415
+ continue;
416
+ // Extract meaningful step: "#5 [runner 3/6] RUN npm ci"
417
+ const stepMatch = /^#\d+\s+\[([^\]]+)\]\s+(.+)/.exec(line);
418
+ if (stepMatch) {
419
+ currentStep = `${chalk_1.default.dim(stepMatch[1])} ${stepMatch[2].slice(0, 45)}`;
420
+ }
421
+ if (/error/i.test(line))
422
+ errorLines.push(line);
423
+ }
424
+ };
425
+ proc.stdout.on('data', onData);
426
+ proc.stderr.on('data', onData);
456
427
  proc.on('close', (code) => {
457
- clearInterval(fallbackInterval);
428
+ clearInterval(spinnerInterval);
458
429
  process.stdout.write('\r\x1b[K');
459
430
  if (code === 0) {
460
431
  console.log(' ' + chalk_1.default.green('✓') + ' All services started');
461
432
  resolve();
433
+ return;
462
434
  }
463
- else {
464
- console.log(' ' + chalk_1.default.red('✗') + ' Failed to start services');
465
- console.log('');
466
- // Classify the error and give actionable guidance
467
- const allErrors = errorLines.join('\n').toLowerCase();
468
- if (allErrors.includes('no space left') || allErrors.includes('disk full')) {
469
- console.log(chalk_1.default.yellow(' Cause: Docker is out of disk space.'));
470
- console.log(chalk_1.default.gray(' Fix: Run `docker system prune -a` to free space, then retry.'));
471
- }
472
- else if (allErrors.includes('port is already allocated') || allErrors.includes('address already in use')) {
473
- const portMatch = /bind for .+:(\d+)/.exec(allErrors);
474
- const port = portMatch ? portMatch[1] : 'a required port';
475
- console.log(chalk_1.default.yellow(` Cause: Port ${port} is already in use by another process.`));
476
- console.log(chalk_1.default.gray(` Fix: Stop the process using port ${port}, then retry.`));
477
- }
478
- else if (allErrors.includes('permission denied') || allErrors.includes('unauthorized')) {
479
- console.log(chalk_1.default.yellow(' Cause: Docker permission denied.'));
480
- console.log(chalk_1.default.gray(' Fix: Make sure Docker Desktop is running and you are logged in.'));
481
- }
482
- else if (allErrors.includes('network') || allErrors.includes('timeout') || allErrors.includes('pull')) {
483
- console.log(chalk_1.default.yellow(' Cause: Network error while pulling Docker images.'));
484
- console.log(chalk_1.default.gray(' Fix: Check your internet connection and retry.'));
485
- }
486
- else if (allErrors.includes('memory') || allErrors.includes('oom')) {
487
- console.log(chalk_1.default.yellow(' Cause: Docker ran out of memory.'));
488
- console.log(chalk_1.default.gray(' Fix: Increase Docker Desktop memory in Settings Resources (4GB+ recommended).'));
489
- }
490
- else if (errorLines.length > 0) {
491
- console.log(chalk_1.default.gray(' Error details:'));
492
- errorLines.slice(-5).forEach(l => console.log(chalk_1.default.red(' ' + l)));
493
- }
494
- console.log('');
495
- console.log(chalk_1.default.gray(` To retry: cd ${displayDir} && docker compose up -d --build`));
496
- resolve(); // don't reject — let init finish gracefully
435
+ const allErrors = errorLines.join('\n').toLowerCase();
436
+ if (allErrors.includes('no space left') || allErrors.includes('disk full')) {
437
+ console.log(chalk_1.default.yellow(' Docker is out of disk space.'));
438
+ console.log(chalk_1.default.gray(' Fix: docker system prune -a'));
439
+ }
440
+ else if (allErrors.includes('port is already allocated') || allErrors.includes('address already in use')) {
441
+ const portMatch = /bind for .+:(\d+)/.exec(allErrors);
442
+ const port = portMatch ? portMatch[1] : 'a required port';
443
+ console.log(chalk_1.default.yellow(` Port ${port} is already in use.`));
444
+ console.log(chalk_1.default.gray(` Fix: stop the process on port ${port} and retry`));
445
+ }
446
+ else if (allErrors.includes('permission denied') || allErrors.includes('unauthorized')) {
447
+ console.log(chalk_1.default.yellow(' Docker permission denied is Docker Desktop running?'));
448
+ }
449
+ else if (allErrors.includes('memory') || allErrors.includes('oom')) {
450
+ console.log(chalk_1.default.yellow(' Docker ran out of memory.'));
451
+ console.log(chalk_1.default.gray(' Fix: increase Docker Desktop memory to 4GB+ in Settings → Resources'));
452
+ }
453
+ else if (allErrors.includes('network') || allErrors.includes('timeout') || allErrors.includes('pull')) {
454
+ console.log(chalk_1.default.yellow(' Network error while pulling images — check your connection and retry.'));
497
455
  }
456
+ console.log(chalk_1.default.gray(` To retry: cd ${displayDir} && docker compose up -d --build`));
457
+ resolve();
498
458
  });
499
459
  });
500
460
  }
package/dist/index.js CHANGED
@@ -17,11 +17,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  const commander_1 = require("commander");
18
18
  const init_1 = require("./commands/init");
19
19
  const manage_1 = require("./commands/manage");
20
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
21
+ const { version } = require('../package.json');
20
22
  const program = new commander_1.Command();
21
23
  program
22
24
  .name('slackhive')
23
25
  .description('CLI to install and manage SlackHive — AI agent teams on Slack')
24
- .version('0.1.0');
26
+ .version(version);
25
27
  program
26
28
  .command('init')
27
29
  .description('Clone SlackHive repo, configure environment, and start services')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "slackhive",
3
- "version": "0.1.30",
3
+ "version": "0.1.32",
4
4
  "description": "CLI to install and manage SlackHive — AI agent teams on Slack",
5
5
  "bin": {
6
6
  "slackhive": "./dist/index.js"