olly-molly 0.2.11 → 0.2.13

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 (3) hide show
  1. package/README.md +9 -0
  2. package/bin/cli.js +53 -12
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -79,6 +79,15 @@ That's it. Open `http://localhost:1234` and start managing your AI team.
79
79
  npx olly-molly
80
80
  ```
81
81
 
82
+ On macOS (arm64/x64) and Windows x64, `npx olly-molly` will use prebuilt bundles
83
+ from GitHub Releases when available. Asset naming:
84
+
85
+ ```
86
+ olly-molly-darwin-arm64.tar.gz
87
+ olly-molly-darwin-x64.tar.gz
88
+ olly-molly-win32-x64.tar.gz
89
+ ```
90
+
82
91
  ### Or install globally
83
92
 
84
93
  ```bash
package/bin/cli.js CHANGED
@@ -10,7 +10,8 @@ const PACKAGE_NAME = 'olly-molly';
10
10
  const REPO = 'ruucm/olly-molly';
11
11
  const APP_DIR = path.join(os.homedir(), '.olly-molly');
12
12
  const DB_DIR = path.join(APP_DIR, 'db');
13
- const TARBALL_URL = `https://github.com/${REPO}/archive/refs/heads/main.tar.gz`;
13
+ const SOURCE_TARBALL_URL = `https://github.com/${REPO}/archive/refs/heads/main.tar.gz`;
14
+ const RELEASE_BASE_URL = `https://github.com/${REPO}/releases/download`;
14
15
 
15
16
  console.log('\nšŸ™ Olly Molly\n');
16
17
 
@@ -31,23 +32,49 @@ function getNpmVersion() {
31
32
  });
32
33
  }
33
34
 
34
- function download(url, destDir) {
35
+ function getPrebuiltUrl(version) {
36
+ if (!version) return null;
37
+ const platform = process.platform;
38
+ const arch = process.arch;
39
+
40
+ if (platform === 'darwin' && (arch === 'arm64' || arch === 'x64')) {
41
+ return `${RELEASE_BASE_URL}/v${version}/olly-molly-darwin-${arch}.tar.gz`;
42
+ }
43
+ if (platform === 'win32' && arch === 'x64') {
44
+ return `${RELEASE_BASE_URL}/v${version}/olly-molly-win32-${arch}.tar.gz`;
45
+ }
46
+ return null;
47
+ }
48
+
49
+ function download(url, destDir, { allowNotFound = false, stripComponents = 1 } = {}) {
35
50
  return new Promise((resolve, reject) => {
36
51
  const tmp = path.join(os.tmpdir(), 'olly-molly.tar.gz');
37
52
  const file = fs.createWriteStream(tmp);
53
+ const cleanupTmp = () => {
54
+ try { file.close(); } catch {}
55
+ try { fs.unlinkSync(tmp); } catch {}
56
+ };
38
57
  const get = (u) => {
39
58
  https.get(u, (res) => {
40
59
  if (res.statusCode === 302 || res.statusCode === 301) return get(res.headers.location);
41
- if (res.statusCode !== 200) return reject(new Error('Download failed'));
60
+ if (res.statusCode !== 200) {
61
+ cleanupTmp();
62
+ if (allowNotFound && res.statusCode === 404) return resolve(false);
63
+ return reject(new Error(`Download failed (${res.statusCode})`));
64
+ }
42
65
  res.pipe(file);
43
66
  file.on('finish', () => {
44
67
  file.close();
45
68
  fs.mkdirSync(destDir, { recursive: true });
46
- execSync(`tar -xzf "${tmp}" -C "${destDir}" --strip-components=1`, { stdio: 'pipe' });
69
+ const stripArg = stripComponents > 0 ? ` --strip-components=${stripComponents}` : '';
70
+ execSync(`tar -xzf "${tmp}" -C "${destDir}"${stripArg}`, { stdio: 'pipe' });
47
71
  fs.unlinkSync(tmp);
48
- resolve();
72
+ resolve(true);
49
73
  });
50
- }).on('error', reject);
74
+ }).on('error', (err) => {
75
+ cleanupTmp();
76
+ reject(err);
77
+ });
51
78
  };
52
79
  get(url);
53
80
  });
@@ -110,9 +137,23 @@ function restoreUserData(backupDir) {
110
137
  async function main() {
111
138
  let needsInstall = false;
112
139
  let needsBuild = false;
140
+ let usedPrebuilt = false;
113
141
 
114
142
  const localVersion = getLocalVersion();
115
143
  const npmVersion = await getNpmVersion();
144
+ const prebuiltUrl = getPrebuiltUrl(npmVersion);
145
+
146
+ async function downloadApp() {
147
+ if (prebuiltUrl) {
148
+ const ok = await download(prebuiltUrl, APP_DIR, { allowNotFound: true, stripComponents: 0 });
149
+ if (ok) {
150
+ usedPrebuilt = true;
151
+ return;
152
+ }
153
+ }
154
+ await download(SOURCE_TARBALL_URL, APP_DIR, { stripComponents: 1 });
155
+ usedPrebuilt = false;
156
+ }
116
157
 
117
158
  // Update if npm version is newer
118
159
  if (localVersion && npmVersion && localVersion !== npmVersion) {
@@ -120,20 +161,20 @@ async function main() {
120
161
  const userDataBackup = backupUserData();
121
162
  fs.rmSync(APP_DIR, { recursive: true, force: true });
122
163
  console.log('šŸ“„ Downloading...');
123
- await download(TARBALL_URL, APP_DIR);
164
+ await downloadApp();
124
165
  console.log('āœ… Downloaded\n');
125
166
  restoreUserData(userDataBackup);
126
- needsInstall = true;
127
- needsBuild = true;
167
+ needsInstall = !usedPrebuilt;
168
+ needsBuild = !usedPrebuilt;
128
169
  }
129
170
 
130
171
  // First time
131
172
  if (!fs.existsSync(APP_DIR)) {
132
173
  console.log('šŸ“„ Downloading...');
133
- await download(TARBALL_URL, APP_DIR);
174
+ await downloadApp();
134
175
  console.log('āœ… Downloaded\n');
135
- needsInstall = true;
136
- needsBuild = true;
176
+ needsInstall = !usedPrebuilt;
177
+ needsBuild = !usedPrebuilt;
137
178
  }
138
179
 
139
180
  // Install
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "olly-molly",
3
- "version": "0.2.11",
3
+ "version": "0.2.13",
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",
@@ -29,7 +29,7 @@
29
29
  ],
30
30
  "scripts": {
31
31
  "dev": "next dev --port 1234",
32
- "build": "next build",
32
+ "build": "next build --webpack",
33
33
  "start": "next start --port 1234",
34
34
  "lint": "eslint",
35
35
  "tauri": "tauri",