olly-molly 0.2.11 ā 0.2.12
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.
- package/README.md +9 -0
- package/bin/cli.js +51 -11
- 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
|
|
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,48 @@ function getNpmVersion() {
|
|
|
31
32
|
});
|
|
32
33
|
}
|
|
33
34
|
|
|
34
|
-
function
|
|
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 } = {}) {
|
|
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)
|
|
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
69
|
execSync(`tar -xzf "${tmp}" -C "${destDir}" --strip-components=1`, { stdio: 'pipe' });
|
|
47
70
|
fs.unlinkSync(tmp);
|
|
48
|
-
resolve();
|
|
71
|
+
resolve(true);
|
|
49
72
|
});
|
|
50
|
-
}).on('error',
|
|
73
|
+
}).on('error', (err) => {
|
|
74
|
+
cleanupTmp();
|
|
75
|
+
reject(err);
|
|
76
|
+
});
|
|
51
77
|
};
|
|
52
78
|
get(url);
|
|
53
79
|
});
|
|
@@ -110,9 +136,23 @@ function restoreUserData(backupDir) {
|
|
|
110
136
|
async function main() {
|
|
111
137
|
let needsInstall = false;
|
|
112
138
|
let needsBuild = false;
|
|
139
|
+
let usedPrebuilt = false;
|
|
113
140
|
|
|
114
141
|
const localVersion = getLocalVersion();
|
|
115
142
|
const npmVersion = await getNpmVersion();
|
|
143
|
+
const prebuiltUrl = getPrebuiltUrl(npmVersion);
|
|
144
|
+
|
|
145
|
+
async function downloadApp() {
|
|
146
|
+
if (prebuiltUrl) {
|
|
147
|
+
const ok = await download(prebuiltUrl, APP_DIR, { allowNotFound: true });
|
|
148
|
+
if (ok) {
|
|
149
|
+
usedPrebuilt = true;
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
await download(SOURCE_TARBALL_URL, APP_DIR);
|
|
154
|
+
usedPrebuilt = false;
|
|
155
|
+
}
|
|
116
156
|
|
|
117
157
|
// Update if npm version is newer
|
|
118
158
|
if (localVersion && npmVersion && localVersion !== npmVersion) {
|
|
@@ -120,20 +160,20 @@ async function main() {
|
|
|
120
160
|
const userDataBackup = backupUserData();
|
|
121
161
|
fs.rmSync(APP_DIR, { recursive: true, force: true });
|
|
122
162
|
console.log('š„ Downloading...');
|
|
123
|
-
await
|
|
163
|
+
await downloadApp();
|
|
124
164
|
console.log('ā
Downloaded\n');
|
|
125
165
|
restoreUserData(userDataBackup);
|
|
126
|
-
needsInstall =
|
|
127
|
-
needsBuild =
|
|
166
|
+
needsInstall = !usedPrebuilt;
|
|
167
|
+
needsBuild = !usedPrebuilt;
|
|
128
168
|
}
|
|
129
169
|
|
|
130
170
|
// First time
|
|
131
171
|
if (!fs.existsSync(APP_DIR)) {
|
|
132
172
|
console.log('š„ Downloading...');
|
|
133
|
-
await
|
|
173
|
+
await downloadApp();
|
|
134
174
|
console.log('ā
Downloaded\n');
|
|
135
|
-
needsInstall =
|
|
136
|
-
needsBuild =
|
|
175
|
+
needsInstall = !usedPrebuilt;
|
|
176
|
+
needsBuild = !usedPrebuilt;
|
|
137
177
|
}
|
|
138
178
|
|
|
139
179
|
// Install
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "olly-molly",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.12",
|
|
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",
|