vibecodingmachine-cli 1.0.0

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 (44) hide show
  1. package/.allnightai/REQUIREMENTS.md +11 -0
  2. package/.allnightai/temp/auto-status.json +6 -0
  3. package/.env +7 -0
  4. package/.eslintrc.js +16 -0
  5. package/README.md +85 -0
  6. package/bin/vibecodingmachine.js +274 -0
  7. package/jest.config.js +8 -0
  8. package/logs/audit/2025-11-07.jsonl +2 -0
  9. package/package.json +64 -0
  10. package/scripts/README.md +128 -0
  11. package/scripts/auto-start-wrapper.sh +92 -0
  12. package/scripts/postinstall.js +81 -0
  13. package/src/commands/auth.js +96 -0
  14. package/src/commands/auto-direct.js +1748 -0
  15. package/src/commands/auto.js +4692 -0
  16. package/src/commands/auto.js.bak +710 -0
  17. package/src/commands/ide.js +70 -0
  18. package/src/commands/repo.js +159 -0
  19. package/src/commands/requirements.js +161 -0
  20. package/src/commands/setup.js +91 -0
  21. package/src/commands/status.js +88 -0
  22. package/src/components/RequirementPage.js +0 -0
  23. package/src/file.js +0 -0
  24. package/src/index.js +5 -0
  25. package/src/main.js +0 -0
  26. package/src/ui/requirements-page.js +0 -0
  27. package/src/utils/auth.js +548 -0
  28. package/src/utils/auto-mode-ansi-ui.js +238 -0
  29. package/src/utils/auto-mode-simple-ui.js +161 -0
  30. package/src/utils/auto-mode-ui.js.bak.blessed +207 -0
  31. package/src/utils/auto-mode.js +65 -0
  32. package/src/utils/config.js +64 -0
  33. package/src/utils/interactive.js +3616 -0
  34. package/src/utils/keyboard-handler.js +152 -0
  35. package/src/utils/logger.js +4 -0
  36. package/src/utils/persistent-header.js +116 -0
  37. package/src/utils/provider-registry.js +128 -0
  38. package/src/utils/requirementUtils.js +0 -0
  39. package/src/utils/status-card.js +120 -0
  40. package/src/utils/status-manager.js +0 -0
  41. package/src/utils/status.js +0 -0
  42. package/src/utils/stdout-interceptor.js +127 -0
  43. package/tests/auto-mode.test.js +37 -0
  44. package/tests/config.test.js +34 -0
@@ -0,0 +1,92 @@
1
+ #!/bin/bash
2
+ #
3
+ # Wrapper script for 'ana auto:start' that properly handles Ctrl+C and other key presses
4
+ # This script runs ana auto:start in the background and monitors keyboard input
5
+ #
6
+
7
+ set -e
8
+
9
+ # Colors
10
+ RED='\033[0;31m'
11
+ GREEN='\033[0;32m'
12
+ YELLOW='\033[1;33m'
13
+ GRAY='\033[0;37m'
14
+ NC='\033[0m' # No Color
15
+
16
+ # Get the directory where this script is located
17
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
18
+ CLI_DIR="$(dirname "$SCRIPT_DIR")"
19
+
20
+ # Path to ana command
21
+ ANA_CMD="$CLI_DIR/bin/allnightai.js"
22
+
23
+ # Path to stop file
24
+ STOP_FILE="$HOME/.config/allnightai/.stop"
25
+
26
+ # Cleanup function
27
+ cleanup() {
28
+ echo -e "\n${YELLOW}Stopping auto mode...${NC}"
29
+
30
+ # Create stop file to signal the process
31
+ mkdir -p "$(dirname "$STOP_FILE")"
32
+ echo "Stop requested at $(date)" > "$STOP_FILE"
33
+
34
+ # Send SIGTERM to the ana process if it's running
35
+ if [ -n "$ANA_PID" ] && kill -0 "$ANA_PID" 2>/dev/null; then
36
+ kill -TERM "$ANA_PID" 2>/dev/null || true
37
+ fi
38
+
39
+ # Wait a moment for the process to exit gracefully
40
+ sleep 2
41
+
42
+ # Force kill if still running
43
+ if [ -n "$ANA_PID" ] && kill -0 "$ANA_PID" 2>/dev/null; then
44
+ echo -e "${YELLOW}Force stopping...${NC}"
45
+ kill -9 "$ANA_PID" 2>/dev/null || true
46
+ fi
47
+
48
+ # Also kill any remaining aider processes
49
+ pkill -9 -f "aider.*allnightai" 2>/dev/null || true
50
+
51
+ echo -e "${GREEN}Auto mode stopped${NC}"
52
+ exit 0
53
+ }
54
+
55
+ # Set up trap for Ctrl+C
56
+ trap cleanup INT TERM
57
+
58
+ # Start ana auto:start in background
59
+ echo -e "${GRAY}Starting auto mode...${NC}"
60
+ echo -e "${GRAY}Press Ctrl+C, Esc, or 'x' to stop${NC}"
61
+ echo ""
62
+
63
+ # Start ana in background, saving its PID
64
+ # Set ANA_WRAPPER_RUNNING to prevent infinite recursion
65
+ export ANA_WRAPPER_RUNNING=1
66
+ node "$ANA_CMD" auto:start "$@" &
67
+ ANA_PID=$!
68
+
69
+ # Monitor for keyboard input AND stop file in the foreground
70
+ # Use a non-blocking read to check for key presses
71
+ while kill -0 "$ANA_PID" 2>/dev/null; do
72
+ # Check for stop file first (created by 'ana auto:stop' or Ctrl+C signal)
73
+ if [ -f "$STOP_FILE" ]; then
74
+ echo -e "\n${YELLOW}Stop signal detected${NC}"
75
+ cleanup
76
+ fi
77
+
78
+ # Read a single character with 0.5 second timeout
79
+ if read -t 0.5 -n 1 -s key 2>/dev/null; then
80
+ # Check if key is 'x', Esc (ASCII 27), or Ctrl+C
81
+ if [ "$key" = "x" ] || [ "$key" = "X" ] || [ "$(printf '%d' "'$key")" = "27" ]; then
82
+ echo -e "\n${YELLOW}Stop key pressed${NC}"
83
+ cleanup
84
+ fi
85
+ fi
86
+ done
87
+
88
+ # Process exited naturally
89
+ echo -e "\n${GREEN}Auto mode completed${NC}"
90
+ wait "$ANA_PID"
91
+ exit_code=$?
92
+ exit $exit_code
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Post-install script to check if 'ana' command exists
5
+ * and warn users if there's a conflict
6
+ */
7
+
8
+ const { execSync } = require('child_process');
9
+ const chalk = require('chalk');
10
+ const path = require('path');
11
+ const fs = require('fs');
12
+
13
+ function checkForExistingAna() {
14
+ try {
15
+ // Check if 'ana' command exists in PATH before installation
16
+ // We need to check the actual binary, not symlinks
17
+ const result = execSync('which ana 2>/dev/null || true', { encoding: 'utf8' });
18
+ const anaPath = result.trim();
19
+
20
+ if (!anaPath) {
21
+ // No ana found - safe to install
22
+ console.log(chalk.green('\n✓ Vibe Coding Machine CLI installed successfully!'));
23
+ console.log(chalk.gray(' You can use either:'));
24
+ console.log(chalk.cyan(' vibecodingmachine') + chalk.gray(' or ') + chalk.cyan('vcm'));
25
+ console.log();
26
+ return;
27
+ }
28
+
29
+ // Check if it's a real file (not a broken symlink from previous install)
30
+ try {
31
+ fs.accessSync(anaPath, fs.constants.X_OK);
32
+
33
+ // Read the file to see if it's ours
34
+ const content = fs.readFileSync(anaPath, 'utf8');
35
+
36
+ // Check if this is our VibeCodingMachine binary
37
+ if (content.includes('VibeCodingMachine CLI') || content.includes('allnightai')) {
38
+ // It's ours, all good
39
+ console.log(chalk.green('\n✓ Vibe Coding Machine CLI installed successfully!'));
40
+ console.log(chalk.gray(' You can use either:'));
41
+ console.log(chalk.cyan(' vibecodingmachine') + chalk.gray(' or ') + chalk.cyan('vcm'));
42
+ console.log();
43
+ return;
44
+ }
45
+
46
+ // It's NOT ours - there's a conflict
47
+ console.log(chalk.yellow('\n⚠️ Warning: An existing "vcm" command was detected at:'));
48
+ console.log(chalk.yellow(` ${anaPath}`));
49
+ console.log(chalk.yellow('\n The "vcm" shortcut will NOT be installed to avoid conflicts.'));
50
+ console.log(chalk.cyan(' You can still use the full command: ') + chalk.bold('vibecodingmachine'));
51
+ console.log();
52
+
53
+ // Remove ana from bin to prevent conflict
54
+ const packageJsonPath = path.join(__dirname, '..', 'package.json');
55
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
56
+
57
+ if (packageJson.bin && packageJson.bin.ana) {
58
+ delete packageJson.bin.ana;
59
+ fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n');
60
+ console.log(chalk.gray(' ✓ Removed "ana" from bin configuration to prevent conflict\n'));
61
+ }
62
+ } catch (err) {
63
+ // File doesn't exist or can't be read - probably safe to install
64
+ console.log(chalk.green('\n✓ Vibe Coding Machine CLI installed successfully!'));
65
+ console.log(chalk.gray(' You can use either:'));
66
+ console.log(chalk.cyan(' vibecodingmachine') + chalk.gray(' or ') + chalk.cyan('vcm'));
67
+ console.log();
68
+ }
69
+ } catch (error) {
70
+ // Error running which - assume no ana exists
71
+ console.log(chalk.green('\n✓ Vibe Coding Machine CLI installed successfully!'));
72
+ console.log(chalk.gray(' You can use either:'));
73
+ console.log(chalk.cyan(' vibecodingmachine') + chalk.gray(' or ') + chalk.cyan('vcm'));
74
+ console.log();
75
+ }
76
+ }
77
+
78
+ // Only run if not being installed as a dependency
79
+ if (process.env.npm_config_global || process.env.npm_config_prefix) {
80
+ checkForExistingAna();
81
+ }
@@ -0,0 +1,96 @@
1
+ const chalk = require('chalk');
2
+ const auth = require('../utils/auth');
3
+
4
+ /**
5
+ * Login command
6
+ * @param {Object} options - Command options
7
+ * @param {boolean} options.headless - Force headless mode (manual URL paste)
8
+ */
9
+ async function login(options = {}) {
10
+ try {
11
+ // Check if already authenticated
12
+ const isAuth = await auth.isAuthenticated();
13
+ if (isAuth) {
14
+ const profile = await auth.getUserProfile();
15
+ console.log(chalk.green(`\n✓ Already authenticated as ${chalk.bold(profile.email)}`));
16
+ return;
17
+ }
18
+
19
+ // Start login flow (auto-detects headless or use explicit flag)
20
+ const result = await auth.login({ headless: options.headless });
21
+
22
+ // After successful authentication, start interactive mode
23
+ if (result) {
24
+ console.log(chalk.cyan('\n🚀 Starting interactive mode...\n'));
25
+ const { startInteractive } = require('../utils/interactive');
26
+ await startInteractive();
27
+ }
28
+ } catch (error) {
29
+ console.error(chalk.red('\n✗ Login failed:'), error.message);
30
+ process.exit(1);
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Logout command
36
+ */
37
+ async function logout() {
38
+ try {
39
+ await auth.logout();
40
+ console.log(chalk.green('\n✓ Logged out successfully'));
41
+ } catch (error) {
42
+ console.error(chalk.red('\n✗ Logout failed:'), error.message);
43
+ process.exit(1);
44
+ }
45
+ }
46
+
47
+ /**
48
+ * Status command
49
+ */
50
+ async function status() {
51
+ try {
52
+ const isAuth = await auth.isAuthenticated();
53
+
54
+ if (!isAuth) {
55
+ console.log(chalk.yellow('\nNot authenticated'));
56
+ console.log(`Run ${chalk.cyan('ana auth:login')} to sign in`);
57
+ return;
58
+ }
59
+
60
+ const profile = await auth.getUserProfile();
61
+ const token = await auth.getToken();
62
+
63
+ // Get usage stats
64
+ const canRun = await auth.canRunAutoMode();
65
+
66
+ console.log(chalk.bold('\n👤 User Profile:'));
67
+ console.log(` Name: ${profile.name}`);
68
+ console.log(` Email: ${profile.email}`);
69
+ console.log(` Tier: ${profile.tier === 'premium' ? chalk.green('Premium 🌟') : 'Free'}`);
70
+
71
+ console.log(chalk.bold('\n📊 Usage:'));
72
+ if (canRun.features && canRun.features.unlimitedIterations) {
73
+ console.log(` Daily Usage: ${canRun.todayUsage} iterations`);
74
+ console.log(` Limit: ${chalk.green('Unlimited')} 🚀`);
75
+ } else {
76
+ const limitColor = canRun.todayUsage >= canRun.maxIterations ? chalk.red : chalk.green;
77
+ console.log(` Daily Usage: ${limitColor(`${canRun.todayUsage}/${canRun.maxIterations}`)} iterations`);
78
+ }
79
+
80
+ if (!canRun.canRun) {
81
+ console.log(chalk.red(`\n⚠️ ${canRun.reason}`));
82
+ if (profile.tier !== 'premium') {
83
+ console.log(chalk.gray('Upgrade to Premium for unlimited usage.'));
84
+ }
85
+ }
86
+
87
+ } catch (error) {
88
+ console.error(chalk.red('\n✗ Failed to check status:'), error.message);
89
+ }
90
+ }
91
+
92
+ module.exports = {
93
+ login,
94
+ logout,
95
+ status
96
+ };