vibecodingmachine-cli 2025.12.6-1702 → 2025.12.24-2348

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.
@@ -0,0 +1,160 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+ const { getRequirementsPath } = require('vibecodingmachine-core');
4
+ const { getRepoPath } = require('./src/utils/config');
5
+ const requirements = require('./src/commands/requirements');
6
+
7
+ // Mock specific functions we need from interactive.js's logic
8
+ // helping function to move requirement to recycled (deletion logic)
9
+ async function moveRequirementToRecycled(reqPath, requirementTitle, fromSection) {
10
+ const content = await fs.readFile(reqPath, 'utf8');
11
+ const lines = content.split('\n');
12
+
13
+ let requirementStartIndex = -1;
14
+ let requirementEndIndex = -1;
15
+
16
+ for (let i = 0; i < lines.length; i++) {
17
+ const line = lines[i].trim();
18
+ if (line.startsWith('###')) {
19
+ const title = line.replace(/^###\s*/, '').trim();
20
+ // Logic from interactive.js
21
+ if (title && title.includes(requirementTitle)) {
22
+ requirementStartIndex = i;
23
+ for (let j = i + 1; j < lines.length; j++) {
24
+ const nextLine = lines[j].trim();
25
+ if (nextLine.startsWith('###') || (nextLine.startsWith('##') && !nextLine.startsWith('###'))) {
26
+ requirementEndIndex = j;
27
+ break;
28
+ }
29
+ }
30
+ if (requirementEndIndex === -1) {
31
+ requirementEndIndex = lines.length;
32
+ }
33
+ break;
34
+ }
35
+ }
36
+ }
37
+
38
+ if (requirementStartIndex === -1) {
39
+ console.log('⚠️ Could not find requirement to recycle');
40
+ return false;
41
+ }
42
+
43
+ console.log(`Found requirement at lines ${requirementStartIndex}-${requirementEndIndex}`);
44
+
45
+ const requirementBlock = lines.slice(requirementStartIndex, requirementEndIndex);
46
+ lines.splice(requirementStartIndex, requirementEndIndex - requirementStartIndex);
47
+
48
+ if (requirementStartIndex < lines.length) {
49
+ const nextLine = lines[requirementStartIndex]?.trim();
50
+ const packageNames = ['cli', 'core', 'electron-app', 'web', 'mobile', 'vscode-extension', 'sync-server'];
51
+ if (nextLine && packageNames.includes(nextLine.toLowerCase()) &&
52
+ !nextLine.startsWith('###') && !nextLine.startsWith('PACKAGE:')) {
53
+ lines.splice(requirementStartIndex, 1);
54
+ }
55
+ while (requirementStartIndex < lines.length && lines[requirementStartIndex]?.trim() === '') {
56
+ lines.splice(requirementStartIndex, 1);
57
+ }
58
+ }
59
+
60
+ let recycledIndex = -1;
61
+ for (let i = 0; i < lines.length; i++) {
62
+ if (lines[i].includes('♻️ Recycled') || lines[i].includes('🗑️ Recycled')) {
63
+ recycledIndex = i;
64
+ break;
65
+ }
66
+ }
67
+
68
+ if (recycledIndex === -1) {
69
+ let lastSectionIndex = -1;
70
+ for (let i = lines.length - 1; i >= 0; i--) {
71
+ if (lines[i].startsWith('##') && !lines[i].startsWith('###')) {
72
+ lastSectionIndex = i;
73
+ break;
74
+ }
75
+ }
76
+ const insertIndex = lastSectionIndex > 0 ? lastSectionIndex : lines.length;
77
+ lines.splice(insertIndex, 0, '', '## ♻️ Recycled', '');
78
+ recycledIndex = insertIndex + 1;
79
+ }
80
+
81
+ let insertIndex = recycledIndex + 1;
82
+ while (insertIndex < lines.length && lines[insertIndex].trim() === '') {
83
+ insertIndex++;
84
+ }
85
+ lines.splice(insertIndex, 0, ...requirementBlock);
86
+
87
+ if (insertIndex + requirementBlock.length < lines.length && lines[insertIndex + requirementBlock.length].trim() !== '') {
88
+ lines.splice(insertIndex + requirementBlock.length, 0, '');
89
+ }
90
+
91
+ await fs.writeFile(reqPath, lines.join('\n'));
92
+ return true;
93
+ }
94
+
95
+ async function run() {
96
+ try {
97
+ const repoPath = '/Users/jesse/code/mediawink/vibecodingmachine'; // Hardcoded valid repo path
98
+ console.log('Repo path:', repoPath);
99
+
100
+ const reqPath = await getRequirementsPath(repoPath);
101
+ console.log('<<< PATH >>>', reqPath);
102
+
103
+ if (await fs.pathExists(reqPath)) {
104
+ const content = await fs.readFile(reqPath, 'utf8');
105
+ console.log('Current content length:', content.length);
106
+ console.log('Current content PRE-TEST:\n', content);
107
+ } else {
108
+ console.log('Requirements file does not exist');
109
+ }
110
+
111
+ console.log('\n--- Adding TESTREQ1 ---');
112
+ await requirements.add('TESTREQ1', 'all', 'Description 1');
113
+
114
+ console.log('\n--- Adding TESTREQ2 ---');
115
+ await requirements.add('TESTREQ2', 'all', 'Description 2');
116
+
117
+ let content = await fs.readFile(reqPath, 'utf8');
118
+ console.log('Content after adding:\n', content);
119
+
120
+ // Verify order
121
+ // We expect TESTREQ2 to be above TESTREQ1 if it inserts at the top of the section
122
+ const lines = content.split('\n');
123
+ let idx1 = -1, idx2 = -1;
124
+ for (let i = 0; i < lines.length; i++) {
125
+ if (lines[i].includes('### TESTREQ1')) idx1 = i;
126
+ if (lines[i].includes('### TESTREQ2')) idx2 = i;
127
+ }
128
+ console.log(`TESTREQ1 line: ${idx1}, TESTREQ2 line: ${idx2}`);
129
+ if (idx2 < idx1 && idx2 > -1) {
130
+ console.log('SUCCESS: TESTREQ2 is above TESTREQ1 (Correct LIFO/Stack behavior for "Top of list")');
131
+ } else {
132
+ console.log('FAIL: Order is not correct for "Top of list" insertion');
133
+ }
134
+
135
+ console.log('\n--- Deleting TESTREQ1 ---');
136
+ const success = await moveRequirementToRecycled(reqPath, 'TESTREQ1', 'todo');
137
+ console.log('Delete success:', success);
138
+
139
+ content = await fs.readFile(reqPath, 'utf8');
140
+ console.log('Content after delete:\n', content);
141
+
142
+ if (content.includes('### TESTREQ1')) {
143
+ // It should be in recycled section
144
+ const recycledIndex = content.indexOf('## ♻️ Recycled');
145
+ const reqIndex = content.indexOf('### TESTREQ1');
146
+ if (reqIndex > recycledIndex) {
147
+ console.log('SUCCESS: TESTREQ1 moved to Recycled');
148
+ } else {
149
+ console.log('FAIL: TESTREQ1 is still in TODO or wrong place');
150
+ }
151
+ } else {
152
+ console.log('FAIL: TESTREQ1 disappeared completely (should be recycled)');
153
+ }
154
+
155
+ } catch (error) {
156
+ console.error('Error:', error);
157
+ }
158
+ }
159
+
160
+ run();
@@ -1,5 +1,6 @@
1
1
  const chalk = require('chalk');
2
2
  const auth = require('../utils/auth');
3
+ const { t } = require('vibecodingmachine-core');
3
4
 
4
5
  /**
5
6
  * Login command
@@ -12,7 +13,7 @@ async function login(options = {}) {
12
13
  const isAuth = await auth.isAuthenticated();
13
14
  if (isAuth) {
14
15
  const profile = await auth.getUserProfile();
15
- console.log(chalk.green(`\n✓ Already authenticated as ${chalk.bold(profile.email)}`));
16
+ console.log(chalk.green(`\n✓ ${t('auth.login.already', { email: chalk.bold(profile.email) })}`));
16
17
  return;
17
18
  }
18
19
 
@@ -21,12 +22,12 @@ async function login(options = {}) {
21
22
 
22
23
  // After successful authentication, start interactive mode
23
24
  if (result) {
24
- console.log(chalk.cyan('\n🚀 Starting interactive mode...\n'));
25
+ console.log(chalk.cyan(`\n🚀 ${t('auth.starting.interactive')}\n`));
25
26
  const { startInteractive } = require('../utils/interactive');
26
27
  await startInteractive();
27
28
  }
28
29
  } catch (error) {
29
- console.error(chalk.red('\n✗ Login failed:'), error.message);
30
+ console.error(chalk.red(`\n✗ ${t('auth.login.failed')}:`), error.message);
30
31
  process.exit(1);
31
32
  }
32
33
  }
@@ -37,9 +38,9 @@ async function login(options = {}) {
37
38
  async function logout() {
38
39
  try {
39
40
  await auth.logout();
40
- console.log(chalk.green('\n✓ Logged out successfully'));
41
+ console.log(chalk.green(`\n✓ ${t('auth.logout.success')}`));
41
42
  } catch (error) {
42
- console.error(chalk.red('\n✗ Logout failed:'), error.message);
43
+ console.error(chalk.red(`\n✗ ${t('auth.logout.failed')}:`), error.message);
43
44
  process.exit(1);
44
45
  }
45
46
  }
@@ -52,40 +53,39 @@ async function status() {
52
53
  const isAuth = await auth.isAuthenticated();
53
54
 
54
55
  if (!isAuth) {
55
- console.log(chalk.yellow('\nNot authenticated'));
56
- console.log(`Run ${chalk.cyan('vcm auth:login')} to sign in`);
56
+ console.log(chalk.yellow(`\n${t('auth.not.authenticated')}`));
57
+ console.log(t('auth.run.login', { command: chalk.cyan('vcm auth:login') }));
57
58
  return;
58
59
  }
59
60
 
60
61
  const profile = await auth.getUserProfile();
61
- const token = await auth.getToken();
62
62
 
63
63
  // Get usage stats
64
64
  const canRun = await auth.canRunAutoMode();
65
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'}`);
66
+ console.log(chalk.bold(`\n👤 ${t('profile.name')}:`));
67
+ console.log(` ${t('profile.name')}: ${profile.name}`);
68
+ console.log(` ${t('profile.email')}: ${profile.email}`);
69
+ console.log(` ${t('profile.tier')}: ${profile.tier === 'premium' ? chalk.green(t('profile.tier.premium')) : t('profile.tier.free')}`);
70
70
 
71
- console.log(chalk.bold('\n📊 Usage:'));
71
+ console.log(chalk.bold(`\n📊 ${t('profile.usage')}:`));
72
72
  if (canRun.features && canRun.features.unlimitedIterations) {
73
- console.log(` Daily Usage: ${canRun.todayUsage} iterations`);
74
- console.log(` Limit: ${chalk.green('Unlimited')} 🚀`);
73
+ console.log(` ${t('profile.daily.usage')}: ${canRun.todayUsage} ${t('profile.iterations')}`);
74
+ console.log(` ${t('profile.limit')}: ${chalk.green(t('profile.unlimited'))}`);
75
75
  } else {
76
76
  const limitColor = canRun.todayUsage >= canRun.maxIterations ? chalk.red : chalk.green;
77
- console.log(` Daily Usage: ${limitColor(`${canRun.todayUsage}/${canRun.maxIterations}`)} iterations`);
77
+ console.log(` ${t('profile.daily.usage')}: ${limitColor(`${canRun.todayUsage}/${canRun.maxIterations}`)} ${t('profile.iterations')}`);
78
78
  }
79
79
 
80
80
  if (!canRun.canRun) {
81
- console.log(chalk.red(`\n⚠️ ${canRun.reason}`));
81
+ console.log(chalk.red(`\n⚠️ ${t('quota.exceeded.warning', { reason: canRun.reason })}`));
82
82
  if (profile.tier !== 'premium') {
83
- console.log(chalk.gray('Upgrade to Premium for unlimited usage.'));
83
+ console.log(chalk.gray(t('profile.upgrade.suggestion')));
84
84
  }
85
85
  }
86
86
 
87
87
  } catch (error) {
88
- console.error(chalk.red('\n✗ Failed to check status:'), error.message);
88
+ console.error(chalk.red(`\n✗ ${t('status.check.failed')}:`), error.message);
89
89
  }
90
90
  }
91
91