synsci 1.2.2 → 1.2.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.
- package/bin/synsci.mjs +125 -32
- package/package.json +2 -2
package/bin/synsci.mjs
CHANGED
|
@@ -40,18 +40,18 @@ const SHOW_CURSOR = "\x1b[?25h"
|
|
|
40
40
|
const CLEAR_LINE = "\x1b[2K\r"
|
|
41
41
|
|
|
42
42
|
const LOGO = [
|
|
43
|
-
" ██████╗
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"██║
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"███████╗ ██████╗██╗███████╗███╗ ██╗
|
|
50
|
-
"██╔════╝██╔════╝██║██╔════╝████╗
|
|
51
|
-
"███████╗██║ ██║█████╗ ██╔██╗ ██║██║ █████╗ ",
|
|
52
|
-
"╚════██║██║ ██║██╔══╝ ██║╚██╗██║██║ ██╔══╝ ",
|
|
53
|
-
"███████║╚██████╗██║███████╗██║
|
|
54
|
-
"╚══════╝ ╚═════╝╚═╝╚══════╝╚═╝ ╚═══╝
|
|
43
|
+
"███████╗██╗ ██╗███╗ ██╗████████╗██╗ ██╗███████╗████████╗██╗ ██████╗",
|
|
44
|
+
"██╔════╝╚██╗ ██╔╝████╗ ██║╚══██╔══╝██║ ██║██╔════╝╚══██╔══╝██║██╔════╝",
|
|
45
|
+
"███████╗ ╚████╔╝ ██╔██╗ ██║ ██║ ███████║█████╗ ██║ ██║██║ ",
|
|
46
|
+
"╚════██║ ╚██╔╝ ██║╚██╗██║ ██║ ██╔══██║██╔══╝ ██║ ██║██║ ",
|
|
47
|
+
"███████║ ██║ ██║ ╚████║ ██║ ██║ ██║███████╗ ██║ ██║╚██████╗",
|
|
48
|
+
"╚══════╝ ╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═╝ ╚═════╝",
|
|
49
|
+
"███████╗ ██████╗██╗███████╗███╗ ██╗ ██████╗███████╗███████╗",
|
|
50
|
+
"██╔════╝██╔════╝██║██╔════╝████╗ ██║██╔════╝██╔════╝██╔════╝",
|
|
51
|
+
"███████╗██║ ██║█████╗ ██╔██╗ ██║██║ █████╗ ███████╗",
|
|
52
|
+
"╚════██║██║ ██║██╔══╝ ██║╚██╗██║██║ ██╔══╝ ╚════██║",
|
|
53
|
+
"███████║╚██████╗██║███████╗██║ ╚████║╚██████╗███████╗███████║",
|
|
54
|
+
"╚══════╝ ╚═════╝╚═╝╚══════╝╚═╝ ╚═══╝ ╚═════╝╚══════╝╚══════╝",
|
|
55
55
|
]
|
|
56
56
|
|
|
57
57
|
function ok(msg) { console.log(` ${GREEN}✓${RESET} ${msg}`) }
|
|
@@ -115,6 +115,19 @@ function resolveCli() {
|
|
|
115
115
|
return null
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
+
// The deprecated `@synsci/cli` package links the same `openscience` bin. npm
|
|
119
|
+
// refuses to overwrite a bin file owned by another package (EEXIST), so a
|
|
120
|
+
// stale global install dead-ends the upgrade — and its old binary shadows the
|
|
121
|
+
// real one on PATH. `npm ls` exits nonzero when the package is absent but
|
|
122
|
+
// still prints JSON, so read stdout either way.
|
|
123
|
+
function hasDeprecatedCli() {
|
|
124
|
+
let out = ""
|
|
125
|
+
try { out = execSync("npm ls -g @synsci/cli --depth=0 --json", { encoding: "utf-8", stdio: "pipe" }) }
|
|
126
|
+
catch (e) { out = e && typeof e.stdout === "string" ? e.stdout : "" }
|
|
127
|
+
try { return Boolean(JSON.parse(out).dependencies["@synsci/cli"]) }
|
|
128
|
+
catch { return false }
|
|
129
|
+
}
|
|
130
|
+
|
|
118
131
|
function isConnected() {
|
|
119
132
|
const xdgData = process.env.XDG_DATA_HOME || join(homedir(), ".local", "share")
|
|
120
133
|
const sessionPath = join(xdgData, "openscience", "openscience-session.json")
|
|
@@ -126,8 +139,37 @@ function isConnected() {
|
|
|
126
139
|
} catch { return false }
|
|
127
140
|
}
|
|
128
141
|
|
|
129
|
-
function
|
|
130
|
-
|
|
142
|
+
function atlasVersion() {
|
|
143
|
+
const raw = runQuiet("atlas --version")
|
|
144
|
+
return raw ? raw.replace(/[^0-9.]/g, "") : null
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Install the Atlas CLI, or bring an existing install up to date. Returns
|
|
148
|
+
// true when a working `atlas` binary is on PATH afterwards.
|
|
149
|
+
async function installOrUpdateAtlas() {
|
|
150
|
+
const current = atlasVersion()
|
|
151
|
+
if (current) {
|
|
152
|
+
const s = spinner("Checking Atlas CLI for updates...")
|
|
153
|
+
const latest = runQuiet("npm view @synsci/atlas version")
|
|
154
|
+
if (!latest || current === latest) {
|
|
155
|
+
s.ok(`atlas ${current} ${DIM}(up to date)${RESET}`)
|
|
156
|
+
return true
|
|
157
|
+
}
|
|
158
|
+
s.update(`Upgrading Atlas CLI ${current} → ${latest}...`)
|
|
159
|
+
if (runQuiet("npm i -g @synsci/atlas@latest") !== null) {
|
|
160
|
+
s.ok(`Upgraded Atlas CLI to ${latest}`)
|
|
161
|
+
} else {
|
|
162
|
+
s.warn(`Atlas CLI upgrade failed, continuing with ${current}`)
|
|
163
|
+
}
|
|
164
|
+
return true
|
|
165
|
+
}
|
|
166
|
+
const s = spinner("Installing Atlas CLI...")
|
|
167
|
+
if (runQuiet("npm i -g @synsci/atlas@latest") !== null && atlasVersion()) {
|
|
168
|
+
s.ok("Installed Atlas CLI")
|
|
169
|
+
return true
|
|
170
|
+
}
|
|
171
|
+
s.warn(`Atlas CLI install failed, you can retry later: ${CYAN}npm i -g @synsci/atlas${RESET}`)
|
|
172
|
+
return false
|
|
131
173
|
}
|
|
132
174
|
|
|
133
175
|
async function ask(question) {
|
|
@@ -145,10 +187,19 @@ async function main() {
|
|
|
145
187
|
console.log()
|
|
146
188
|
for (const line of LOGO) console.log(` ${CYAN}${line}${RESET}`)
|
|
147
189
|
console.log()
|
|
148
|
-
console.log(` ${BOLD}
|
|
190
|
+
console.log(` ${BOLD}Synthetic Sciences${RESET} ${DIM}OpenScience, the open-source AI research workspace · Atlas, the research platform${RESET}`)
|
|
149
191
|
console.log()
|
|
150
192
|
|
|
151
193
|
// --- Step 1: Install or upgrade the OpenScience CLI ---
|
|
194
|
+
if (hasDeprecatedCli()) {
|
|
195
|
+
const s = spinner("Removing the deprecated @synsci/cli so it can't shadow the openscience command...")
|
|
196
|
+
if (runQuiet("npm rm -g @synsci/cli") !== null) {
|
|
197
|
+
s.ok("Removed the deprecated @synsci/cli")
|
|
198
|
+
} else {
|
|
199
|
+
s.warn(`Couldn't remove the deprecated @synsci/cli — if install fails, run: ${CYAN}npm rm -g @synsci/cli${RESET}`)
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
152
203
|
let cliPath = resolveCli()
|
|
153
204
|
if (cliPath) {
|
|
154
205
|
const raw = runFileQuiet(cliPath, ["--version"]) || "unknown"
|
|
@@ -174,14 +225,39 @@ async function main() {
|
|
|
174
225
|
} else {
|
|
175
226
|
const s = spinner("Installing OpenScience...")
|
|
176
227
|
try {
|
|
177
|
-
|
|
228
|
+
try {
|
|
229
|
+
execSync("npm i -g @synsci/openscience@latest", { stdio: "pipe" })
|
|
230
|
+
} catch (e) {
|
|
231
|
+
// npm refuses to overwrite a bin file owned by another package
|
|
232
|
+
// (EEXIST). If the conflict is the deprecated @synsci/cli, remove it
|
|
233
|
+
// and retry once before falling back to the standalone installer.
|
|
234
|
+
const stderr = e && e.stderr ? String(e.stderr) : ""
|
|
235
|
+
const conflict = stderr.includes("EEXIST") && (stderr.includes("@synsci/cli") || hasDeprecatedCli())
|
|
236
|
+
if (!conflict) throw e
|
|
237
|
+
s.update("Removing the deprecated @synsci/cli so it can't shadow the openscience command...")
|
|
238
|
+
runQuiet("npm rm -g @synsci/cli")
|
|
239
|
+
s.update("Retrying the OpenScience install...")
|
|
240
|
+
execSync("npm i -g @synsci/openscience@latest", { stdio: "pipe" })
|
|
241
|
+
}
|
|
178
242
|
cliPath = resolveCli()
|
|
179
243
|
if (!cliPath) throw new Error("openscience not on PATH after install")
|
|
180
244
|
s.ok("Installed OpenScience")
|
|
181
|
-
} catch
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
245
|
+
} catch {
|
|
246
|
+
// Global npm installs commonly fail on permissions. Fall back to the
|
|
247
|
+
// standalone installer, which lands in ~/.openscience/bin without sudo
|
|
248
|
+
// (resolveCli already checks that location).
|
|
249
|
+
s.update("npm -g failed, trying the standalone installer...")
|
|
250
|
+
try {
|
|
251
|
+
execSync("curl -fsSL https://openscience.sh/install | bash", { stdio: "pipe" })
|
|
252
|
+
cliPath = resolveCli()
|
|
253
|
+
if (!cliPath) throw new Error("openscience not found after install")
|
|
254
|
+
s.ok("Installed OpenScience")
|
|
255
|
+
} catch (e2) {
|
|
256
|
+
s.fail(`Install failed${e2 && e2.message ? ": " + e2.message : ""}`)
|
|
257
|
+
console.log(`\n Try manually: ${CYAN}npm i -g @synsci/openscience${RESET}`)
|
|
258
|
+
console.log(` or: ${CYAN}curl -fsSL https://openscience.sh/install | bash${RESET}\n`)
|
|
259
|
+
process.exit(1)
|
|
260
|
+
}
|
|
185
261
|
}
|
|
186
262
|
}
|
|
187
263
|
|
|
@@ -191,23 +267,40 @@ async function main() {
|
|
|
191
267
|
console.log()
|
|
192
268
|
console.log(` ${BOLD}1${RESET} ${CYAN}OpenScience${RESET} ${DIM}free and open source, bring your own API keys, no account${RESET}`)
|
|
193
269
|
console.log(` ${BOLD}2${RESET} ${CYAN}OpenScience + Atlas${RESET} ${DIM}managed models, wallet billing, research graph & compute${RESET}`)
|
|
270
|
+
console.log(` ${BOLD}3${RESET} ${CYAN}Atlas CLI${RESET} ${DIM}just the Atlas research CLI — maps, runs, and compute from the terminal${RESET}`)
|
|
194
271
|
console.log()
|
|
195
272
|
|
|
196
|
-
const setup = await ask(` ${DIM}❯${RESET} Choose [1/2]: `)
|
|
273
|
+
const setup = await ask(` ${DIM}❯${RESET} Choose [1/2/3]: `)
|
|
197
274
|
console.log()
|
|
198
275
|
|
|
199
|
-
if (setup === "
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
276
|
+
if (setup === "3") {
|
|
277
|
+
// Atlas-CLI-only path: install/upgrade, verify, hand off to `atlas`.
|
|
278
|
+
// No workspace launch — this option exists for people who want the
|
|
279
|
+
// research CLI on a box without opening the browser app.
|
|
280
|
+
const installed = await installOrUpdateAtlas()
|
|
281
|
+
if (!installed) process.exit(1)
|
|
282
|
+
const s = spinner("Running atlas doctor...")
|
|
283
|
+
if (runQuiet("atlas doctor") !== null) {
|
|
284
|
+
s.ok("atlas doctor passed")
|
|
285
|
+
} else {
|
|
286
|
+
s.warn(`atlas doctor reported issues — run ${CYAN}atlas doctor${RESET} for details`)
|
|
287
|
+
}
|
|
288
|
+
if (isConnected()) {
|
|
289
|
+
ok("Connected to Atlas")
|
|
208
290
|
} else {
|
|
209
|
-
|
|
291
|
+
console.log()
|
|
292
|
+
console.log(` ${DIM}Connect your Atlas account for managed credentials:${RESET} ${CYAN}openscience connect login${RESET}`)
|
|
210
293
|
}
|
|
294
|
+
console.log()
|
|
295
|
+
console.log(` ${BOLD}Next steps${RESET}`)
|
|
296
|
+
console.log(` ${CYAN}atlas --help${RESET} ${DIM}see everything the CLI can do${RESET}`)
|
|
297
|
+
console.log(` ${CYAN}atlas doctor${RESET} ${DIM}check credentials and environment${RESET}`)
|
|
298
|
+
console.log()
|
|
299
|
+
process.exit(0)
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
if (setup === "2") {
|
|
303
|
+
await installOrUpdateAtlas()
|
|
211
304
|
if (isConnected()) {
|
|
212
305
|
ok("Connected to Atlas")
|
|
213
306
|
} else {
|
|
@@ -226,7 +319,7 @@ async function main() {
|
|
|
226
319
|
console.log(` ${DIM}Opening the workspace in your browser…${RESET}`)
|
|
227
320
|
console.log()
|
|
228
321
|
|
|
229
|
-
const child = spawn(cliPath, ["web"], { stdio: "inherit" })
|
|
322
|
+
const child = spawn(cliPath, ["web", ...process.argv.slice(2)], { stdio: "inherit" })
|
|
230
323
|
child.on("close", (code) => process.exit(code ?? 0))
|
|
231
324
|
}
|
|
232
325
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "synsci",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.5",
|
|
4
4
|
"description": "Install wizard for OpenScience, the open-source AI research workspace (optionally with Atlas)",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
],
|
|
23
23
|
"repository": {
|
|
24
24
|
"type": "git",
|
|
25
|
-
"url": "git+https://github.com/synthetic-sciences/
|
|
25
|
+
"url": "git+https://github.com/synthetic-sciences/openscience.git"
|
|
26
26
|
},
|
|
27
27
|
"homepage": "https://syntheticsciences.ai"
|
|
28
28
|
}
|