olly-molly 0.1.4 → 0.1.5

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 (2) hide show
  1. package/bin/cli.js +85 -88
  2. package/package.json +1 -1
package/bin/cli.js CHANGED
@@ -10,9 +10,33 @@ const APP_NAME = 'olly-molly';
10
10
  const REPO = 'ruucm/olly-molly';
11
11
  const APP_DIR = path.join(os.homedir(), '.olly-molly');
12
12
  const TARBALL_URL = `https://github.com/${REPO}/archive/refs/heads/main.tar.gz`;
13
+ const VERSION_URL = `https://raw.githubusercontent.com/${REPO}/main/package.json`;
13
14
 
14
15
  console.log('\nšŸ™ Olly Molly - Your AI Development Team\n');
15
16
 
17
+ function fetchJSON(url) {
18
+ return new Promise((resolve, reject) => {
19
+ const get = (downloadUrl) => {
20
+ https.get(downloadUrl, (res) => {
21
+ if (res.statusCode === 302 || res.statusCode === 301) {
22
+ get(res.headers.location);
23
+ return;
24
+ }
25
+ let data = '';
26
+ res.on('data', chunk => data += chunk);
27
+ res.on('end', () => {
28
+ try {
29
+ resolve(JSON.parse(data));
30
+ } catch {
31
+ reject(new Error('Invalid JSON'));
32
+ }
33
+ });
34
+ }).on('error', reject);
35
+ };
36
+ get(url);
37
+ });
38
+ }
39
+
16
40
  function downloadAndExtract(url, destDir) {
17
41
  return new Promise((resolve, reject) => {
18
42
  const tempFile = path.join(os.tmpdir(), 'olly-molly.tar.gz');
@@ -22,33 +46,23 @@ function downloadAndExtract(url, destDir) {
22
46
 
23
47
  const download = (downloadUrl) => {
24
48
  https.get(downloadUrl, (response) => {
25
- // Handle redirects
26
49
  if (response.statusCode === 302 || response.statusCode === 301) {
27
50
  download(response.headers.location);
28
51
  return;
29
52
  }
30
-
31
53
  if (response.statusCode !== 200) {
32
54
  reject(new Error(`Download failed: ${response.statusCode}`));
33
55
  return;
34
56
  }
35
-
36
57
  response.pipe(file);
37
58
  file.on('finish', () => {
38
59
  file.close();
39
-
40
60
  console.log('šŸ“¦ Extracting...');
41
-
42
- // Create dest directory
43
61
  if (!fs.existsSync(destDir)) {
44
62
  fs.mkdirSync(destDir, { recursive: true });
45
63
  }
46
-
47
- // Extract tarball
48
64
  try {
49
- execSync(`tar -xzf "${tempFile}" -C "${destDir}" --strip-components=1`, {
50
- stdio: 'pipe'
51
- });
65
+ execSync(`tar -xzf "${tempFile}" -C "${destDir}" --strip-components=1`, { stdio: 'pipe' });
52
66
  fs.unlinkSync(tempFile);
53
67
  resolve();
54
68
  } catch (err) {
@@ -57,95 +71,78 @@ function downloadAndExtract(url, destDir) {
57
71
  });
58
72
  }).on('error', reject);
59
73
  };
60
-
61
74
  download(url);
62
75
  });
63
76
  }
64
77
 
78
+ async function getLocalVersion() {
79
+ const pkgPath = path.join(APP_DIR, 'package.json');
80
+ if (!fs.existsSync(pkgPath)) return null;
81
+ try {
82
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
83
+ return pkg.version;
84
+ } catch {
85
+ return null;
86
+ }
87
+ }
88
+
65
89
  async function main() {
66
- const args = process.argv.slice(2);
67
-
68
- // Update flag
69
- if (args.includes('--update') || args.includes('-u')) {
70
- console.log('šŸ”„ Updating Olly Molly...\n');
71
- if (fs.existsSync(APP_DIR)) {
90
+ try {
91
+ // Check remote version
92
+ let remoteVersion = null;
93
+ try {
94
+ const remotePkg = await fetchJSON(VERSION_URL);
95
+ remoteVersion = remotePkg.version;
96
+ } catch {
97
+ // Offline or error - continue with local
98
+ }
99
+
100
+ const localVersion = await getLocalVersion();
101
+
102
+ // Auto-update if versions differ
103
+ if (localVersion && remoteVersion && localVersion !== remoteVersion) {
104
+ console.log(`šŸ”„ New version available: ${localVersion} → ${remoteVersion}\n`);
105
+ console.log(' Updating...\n');
72
106
  fs.rmSync(APP_DIR, { recursive: true, force: true });
73
107
  }
74
- }
75
-
76
- // Download if not exists
77
- if (!fs.existsSync(APP_DIR)) {
78
- console.log('šŸ“¦ First run - downloading Olly Molly...\n');
79
- try {
108
+
109
+ // Download if not exists
110
+ if (!fs.existsSync(APP_DIR)) {
111
+ console.log('šŸ“¦ Downloading Olly Molly...\n');
80
112
  await downloadAndExtract(TARBALL_URL, APP_DIR);
81
113
  console.log('āœ… Downloaded!\n');
82
- } catch (error) {
83
- console.error('āŒ Download failed:', error.message);
84
- console.error('\n Make sure the repository is public at:');
85
- console.error(` https://github.com/${REPO}\n`);
86
- process.exit(1);
87
114
  }
88
- }
89
-
90
- // Install dependencies if needed
91
- const nodeModulesPath = path.join(APP_DIR, 'node_modules');
92
- if (!fs.existsSync(nodeModulesPath)) {
93
- console.log('šŸ“¦ Installing dependencies (first time only)...\n');
94
- try {
95
- execSync('npm install --production', {
96
- cwd: APP_DIR,
97
- stdio: 'inherit'
98
- });
99
- } catch (error) {
100
- console.error('āŒ Failed to install dependencies');
101
- process.exit(1);
115
+
116
+ // Install dependencies if needed
117
+ const nodeModulesPath = path.join(APP_DIR, 'node_modules');
118
+ if (!fs.existsSync(nodeModulesPath)) {
119
+ console.log('šŸ“¦ Installing dependencies...\n');
120
+ execSync('npm install --omit=dev', { cwd: APP_DIR, stdio: 'inherit' });
102
121
  }
103
- }
104
-
105
- // Build if needed
106
- const nextPath = path.join(APP_DIR, '.next');
107
- if (!fs.existsSync(nextPath)) {
108
- console.log('šŸ”Ø Building app (first time only)...\n');
109
- try {
110
- execSync('npm run build', {
111
- cwd: APP_DIR,
112
- stdio: 'inherit'
113
- });
114
- } catch (error) {
115
- console.error('āŒ Failed to build');
116
- process.exit(1);
122
+
123
+ // Build if needed
124
+ const nextPath = path.join(APP_DIR, '.next');
125
+ if (!fs.existsSync(nextPath)) {
126
+ console.log('šŸ”Ø Building (first time only)...\n');
127
+ execSync('npm run build', { cwd: APP_DIR, stdio: 'inherit' });
117
128
  }
118
- }
119
-
120
- console.log('\nšŸš€ Starting on http://localhost:1234\n');
121
- console.log(' Press Ctrl+C to stop');
122
- console.log(' Run "npx olly-molly -u" to update\n');
123
-
124
- // Start the server
125
- const server = spawn('npm', ['run', 'start', '--', '--port', '1234'], {
126
- cwd: APP_DIR,
127
- stdio: 'inherit',
128
- shell: true
129
- });
130
-
131
- server.on('error', (error) => {
132
- console.error('āŒ Failed to start:', error.message);
129
+
130
+ console.log('\nšŸš€ http://localhost:1234\n');
131
+
132
+ // Start server
133
+ const server = spawn('npx', ['next', 'start', '--port', '1234'], {
134
+ cwd: APP_DIR,
135
+ stdio: 'inherit'
136
+ });
137
+
138
+ server.on('close', (code) => process.exit(code || 0));
139
+ process.on('SIGINT', () => { server.kill('SIGINT'); });
140
+ process.on('SIGTERM', () => { server.kill('SIGTERM'); });
141
+
142
+ } catch (error) {
143
+ console.error('āŒ Error:', error.message);
133
144
  process.exit(1);
134
- });
135
-
136
- server.on('close', (code) => {
137
- process.exit(code || 0);
138
- });
139
-
140
- // Graceful shutdown
141
- process.on('SIGINT', () => {
142
- console.log('\nšŸ‘‹ Bye!');
143
- server.kill('SIGINT');
144
- });
145
-
146
- process.on('SIGTERM', () => {
147
- server.kill('SIGTERM');
148
- });
145
+ }
149
146
  }
150
147
 
151
- main().catch(console.error);
148
+ main();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "olly-molly",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "Your AI Development Team, Running Locally - Manage AI agents (PM, Frontend, Backend, QA) from a beautiful kanban board",
5
5
  "keywords": [
6
6
  "ai",