bloby-bot 0.70.12 → 0.71.0
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/cli.js +234 -48
- package/dist-bloby/assets/{bloby-DSNB0g4w.js → bloby-es6cZJzs.js} +6 -6
- package/dist-bloby/assets/globals-DBqwNiJV.css +2 -0
- package/dist-bloby/assets/{globals-B3cTbITX.js → globals-DN3F0CQE.js} +1 -1
- package/dist-bloby/assets/{highlighted-body-OFNGDK62-BLforpkr.js → highlighted-body-OFNGDK62-8PiOHw9p.js} +1 -1
- package/dist-bloby/assets/mermaid-GHXKKRXX-BJWX8urU.js +1 -0
- package/dist-bloby/assets/{onboard-Dn2Ws_G2.js → onboard-BKgy17OU.js} +1 -1
- package/dist-bloby/bloby.html +3 -3
- package/dist-bloby/onboard.html +3 -3
- package/package.json +3 -4
- package/scripts/install +156 -41
- package/scripts/install.ps1 +146 -29
- package/scripts/install.sh +156 -41
- package/shared/config.ts +37 -2
- package/shared/relay.ts +3 -1
- package/supervisor/channels/manager.ts +84 -44
- package/supervisor/channels/telegram.ts +57 -16
- package/supervisor/channels/types.ts +4 -1
- package/supervisor/channels/whatsapp.ts +57 -10
- package/supervisor/chat/OnboardWizard.tsx +0 -15
- package/supervisor/chat/src/components/Chat/AudioBubble.tsx +1 -1
- package/supervisor/chat/src/components/Chat/AuthedImage.tsx +16 -3
- package/supervisor/chat/src/components/Chat/BlobyImageCard.tsx +2 -2
- package/supervisor/chat/src/components/Chat/ImageLightbox.tsx +25 -8
- package/supervisor/chat/src/components/Chat/InputBar.tsx +62 -7
- package/supervisor/chat/src/components/Chat/MessageBubble.tsx +37 -18
- package/supervisor/chat/src/components/Chat/MessageList.tsx +3 -3
- package/supervisor/chat/src/hooks/useChat.ts +52 -0
- package/supervisor/chat/src/lib/authedFile.ts +24 -12
- package/supervisor/file-saver.ts +92 -19
- package/supervisor/harnesses/attachment-policy.ts +111 -0
- package/supervisor/harnesses/claude.ts +62 -15
- package/supervisor/harnesses/codex.ts +69 -43
- package/supervisor/harnesses/pi/index.ts +367 -112
- package/supervisor/harnesses/pi/providers/humanize-error.ts +27 -2
- package/supervisor/harnesses/pi/providers/retry.ts +31 -0
- package/supervisor/harnesses/pi/providers/stream-anthropic.ts +31 -3
- package/supervisor/harnesses/pi/providers/stream-google.ts +26 -3
- package/supervisor/harnesses/pi/providers/stream-openai-completions.ts +32 -9
- package/supervisor/harnesses/pi/providers/types.ts +29 -1
- package/supervisor/harnesses/pi/session.ts +143 -3
- package/supervisor/harnesses/pi/test-completion.ts +56 -0
- package/supervisor/harnesses/pi/tools/bash.ts +198 -22
- package/supervisor/harnesses/pi/tools/glob.ts +79 -0
- package/supervisor/harnesses/pi/tools/grep.ts +0 -0
- package/supervisor/harnesses/pi/tools/registry.ts +18 -6
- package/supervisor/harnesses/pi/tools/todo-write.ts +45 -0
- package/supervisor/harnesses/pi/tools/web-fetch.ts +129 -0
- package/supervisor/index.ts +93 -18
- package/supervisor/widget.js +19 -5
- package/worker/db.ts +2 -0
- package/worker/index.ts +18 -1
- package/worker/prompts/bloby-system-prompt-codex.txt +1 -1
- package/worker/prompts/bloby-system-prompt-pi.txt +6 -24
- package/worker/prompts/bloby-system-prompt.txt +1 -1
- package/workspace/client/src/components/Dashboard/DashboardPage.tsx +4 -117
- package/workspace/client/src/components/Dashboard/deleteme_placeholders.tsx +194 -0
- package/workspace/client/src/components/Layout/Sidebar.tsx +52 -30
- package/workspace/client/src/components/deleteme_onboarding/WorkspaceTour.tsx +25 -15
- package/workspace/client/src/components/deleteme_onboarding/tour-theme.css +24 -0
- package/workspace/skills/mac/SKILL.md +13 -4
- package/dist-bloby/assets/globals-DyeW509Y.css +0 -2
- package/dist-bloby/assets/mermaid-GHXKKRXX-C1H_fSCU.js +0 -1
- package/supervisor/public/headphones_spritesheet.webp +0 -0
- package/supervisor/public/spritesheet.webp +0 -0
package/scripts/install
CHANGED
|
@@ -7,6 +7,23 @@ set -e
|
|
|
7
7
|
# Downloads Node.js + Bloby into ~/.bloby — no system dependencies needed.
|
|
8
8
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
9
9
|
|
|
10
|
+
# Repair $HOME before deriving any install path. Under `sudo`, cron, CI, or a
|
|
11
|
+
# minimal shell, $HOME can be empty or "/" — without this we'd install into the
|
|
12
|
+
# wrong place (or /). Colors aren't defined yet, so this early error is plain.
|
|
13
|
+
if [ -z "${HOME:-}" ] || [ ! -d "${HOME:-}" ]; then
|
|
14
|
+
_whoami=$(id -un 2>/dev/null || echo "")
|
|
15
|
+
if [ -n "$_whoami" ] && command -v getent >/dev/null 2>&1; then
|
|
16
|
+
HOME=$(getent passwd "$_whoami" 2>/dev/null | cut -d: -f6)
|
|
17
|
+
elif [ -n "$_whoami" ] && command -v dscl >/dev/null 2>&1; then
|
|
18
|
+
HOME=$(dscl . -read "/Users/$_whoami" NFSHomeDirectory 2>/dev/null | awk '{print $2}')
|
|
19
|
+
fi
|
|
20
|
+
export HOME
|
|
21
|
+
fi
|
|
22
|
+
if [ -z "${HOME:-}" ] || [ ! -d "$HOME" ]; then
|
|
23
|
+
printf 'Error: could not determine your home directory ($HOME is unset).\n' >&2
|
|
24
|
+
exit 1
|
|
25
|
+
fi
|
|
26
|
+
|
|
10
27
|
MIN_NODE_MAJOR=18
|
|
11
28
|
NODE_VERSION="22.14.0"
|
|
12
29
|
BLOBY_HOME="$HOME/.bloby"
|
|
@@ -14,6 +31,11 @@ TOOLS_DIR="$BLOBY_HOME/tools"
|
|
|
14
31
|
NODE_DIR="$TOOLS_DIR/node"
|
|
15
32
|
BIN_DIR="$BLOBY_HOME/bin"
|
|
16
33
|
USE_SYSTEM_NODE=false
|
|
34
|
+
LIBC=""
|
|
35
|
+
# Temp paths the cleanup trap removes — kept empty until we own them so an early
|
|
36
|
+
# exit can never `rm -rf` an inherited value (e.g. the system $TMPDIR).
|
|
37
|
+
WORK_DIR=""
|
|
38
|
+
TMPFILE=""
|
|
17
39
|
|
|
18
40
|
# Brand colors: #00ADFE (light) and #0158FB (deep) -- Morphy palette, 24-bit truecolor
|
|
19
41
|
BLUE='\033[38;2;0;173;254m'
|
|
@@ -37,15 +59,47 @@ if [ ! -t 1 ]; then
|
|
|
37
59
|
BLUE='' PINK='' YELLOW='' RED='' DIM='' BOLD='' RESET='' G1='' G2='' G3='' G4='' G5='' G6='' G7=''
|
|
38
60
|
fi
|
|
39
61
|
|
|
40
|
-
# Cleanup on exit (restore cursor, reset colors, remove temp files)
|
|
62
|
+
# Cleanup on exit (restore cursor, reset colors, remove temp files).
|
|
63
|
+
# Only remove paths we actually created — never an inherited/unset value.
|
|
41
64
|
cleanup() {
|
|
42
65
|
printf '\033[?25h' # show cursor
|
|
43
66
|
printf "${RESET}"
|
|
44
|
-
rm -f "$TMPFILE" 2>/dev/null
|
|
45
|
-
rm -rf "$
|
|
67
|
+
[ -n "$TMPFILE" ] && rm -f "$TMPFILE" 2>/dev/null
|
|
68
|
+
[ -n "$WORK_DIR" ] && rm -rf "$WORK_DIR" 2>/dev/null
|
|
69
|
+
return 0
|
|
46
70
|
}
|
|
47
71
|
trap cleanup EXIT INT TERM
|
|
48
72
|
|
|
73
|
+
# ─── Download + integrity helpers ───────────────────────────────────────────
|
|
74
|
+
|
|
75
|
+
# download_file <url> <dest> — curl/wget with HTTPS floor, timeout, and retry.
|
|
76
|
+
download_file() {
|
|
77
|
+
if command -v curl >/dev/null 2>&1; then
|
|
78
|
+
curl -fsSL --proto '=https' --tlsv1.2 --connect-timeout 20 --retry 3 --retry-delay 2 -o "$2" "$1"
|
|
79
|
+
elif command -v wget >/dev/null 2>&1; then
|
|
80
|
+
wget -q --https-only --tries=3 --timeout=20 -O "$2" "$1"
|
|
81
|
+
else
|
|
82
|
+
printf " ${RED}✗${RESET} curl or wget is required to install Bloby\n"
|
|
83
|
+
exit 1
|
|
84
|
+
fi
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
# verify_sha256 <file> <expected-hex> — 0 match, 1 mismatch, 2 no tool available.
|
|
88
|
+
verify_sha256() {
|
|
89
|
+
_actual=""
|
|
90
|
+
if command -v sha256sum >/dev/null 2>&1; then
|
|
91
|
+
_actual=$(sha256sum "$1" 2>/dev/null | awk '{print $1}')
|
|
92
|
+
elif command -v shasum >/dev/null 2>&1; then
|
|
93
|
+
_actual=$(shasum -a 256 "$1" 2>/dev/null | awk '{print $1}')
|
|
94
|
+
else
|
|
95
|
+
return 2
|
|
96
|
+
fi
|
|
97
|
+
# No hash computed (tool failed / file vanished) → "skip" (2), not "mismatch" (1),
|
|
98
|
+
# so we warn rather than aborting with a misleading "tampered download".
|
|
99
|
+
[ -n "$_actual" ] || return 2
|
|
100
|
+
[ "$_actual" = "$2" ]
|
|
101
|
+
}
|
|
102
|
+
|
|
49
103
|
printf "\n"
|
|
50
104
|
printf "${G1}${BOLD} █▄ ${RESET}\n"
|
|
51
105
|
printf "${G2}${BOLD} ▄ ▄ ██ ${RESET}\n"
|
|
@@ -83,6 +137,14 @@ detect_platform() {
|
|
|
83
137
|
;;
|
|
84
138
|
esac
|
|
85
139
|
|
|
140
|
+
# Detect musl (Alpine): nodejs.org ships glibc builds only, so a bundled Node
|
|
141
|
+
# would segfault at runtime. Flag it now and require a system Node instead.
|
|
142
|
+
if [ "$PLATFORM" = "linux" ]; then
|
|
143
|
+
if [ -f /etc/alpine-release ] || (ldd --version 2>&1 | grep -qi musl); then
|
|
144
|
+
LIBC="musl"
|
|
145
|
+
fi
|
|
146
|
+
fi
|
|
147
|
+
|
|
86
148
|
printf " ${DIM}Platform: ${PLATFORM}/${NODEARCH}${RESET}\n"
|
|
87
149
|
}
|
|
88
150
|
|
|
@@ -115,35 +177,68 @@ install_node() {
|
|
|
115
177
|
fi
|
|
116
178
|
fi
|
|
117
179
|
|
|
118
|
-
|
|
180
|
+
# nodejs.org ships glibc-linked builds; on musl they segfault at runtime.
|
|
181
|
+
if [ "$LIBC" = "musl" ]; then
|
|
182
|
+
printf " ${RED}✗${RESET} Alpine/musl detected — Bloby's bundled Node.js requires glibc.\n"
|
|
183
|
+
printf " ${DIM}Install Node.js >= ${MIN_NODE_MAJOR} (e.g. ${BOLD}apk add nodejs npm${RESET}${DIM}) and re-run this installer.${RESET}\n"
|
|
184
|
+
exit 1
|
|
185
|
+
fi
|
|
119
186
|
|
|
120
|
-
|
|
121
|
-
TMPFILE=$(mktemp /tmp/node-XXXXXX.tar.xz)
|
|
187
|
+
printf " ${BLUE}↓${RESET} Downloading Node.js v${NODE_VERSION}...\n"
|
|
122
188
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
189
|
+
NODE_FILE="node-v${NODE_VERSION}-${PLATFORM}-${NODEARCH}.tar.xz"
|
|
190
|
+
NODE_URL="https://nodejs.org/dist/v${NODE_VERSION}/${NODE_FILE}"
|
|
191
|
+
# Trailing X's, NO suffix: BSD mktemp (macOS) only substitutes trailing X's,
|
|
192
|
+
# so a ".tar.xz" suffix would create a literal, predictable, non-unique file.
|
|
193
|
+
TMPFILE=$(mktemp "${TMPDIR:-/tmp}/bloby-node-XXXXXX")
|
|
194
|
+
download_file "$NODE_URL" "$TMPFILE"
|
|
195
|
+
|
|
196
|
+
# Integrity: verify against nodejs.org SHASUMS256.txt before extracting. A
|
|
197
|
+
# mismatch is fatal; an unreachable sums file or missing hash tool degrades to
|
|
198
|
+
# a warning so installs still proceed (the download itself is TLS-protected).
|
|
199
|
+
printf " ${DIM}Verifying download...${RESET}\n"
|
|
200
|
+
EXPECTED_SHA=""
|
|
201
|
+
SUMS=$(curl -fsSL --proto '=https' --tlsv1.2 --connect-timeout 20 "https://nodejs.org/dist/v${NODE_VERSION}/SHASUMS256.txt" 2>/dev/null \
|
|
202
|
+
|| wget -q --https-only --timeout=20 -O- "https://nodejs.org/dist/v${NODE_VERSION}/SHASUMS256.txt" 2>/dev/null \
|
|
203
|
+
|| echo "")
|
|
204
|
+
if [ -n "$SUMS" ]; then
|
|
205
|
+
EXPECTED_SHA=$(printf '%s\n' "$SUMS" | awk -v f="$NODE_FILE" '$2==f {print $1; exit}')
|
|
206
|
+
fi
|
|
207
|
+
if [ -n "$EXPECTED_SHA" ]; then
|
|
208
|
+
vrc=0
|
|
209
|
+
verify_sha256 "$TMPFILE" "$EXPECTED_SHA" || vrc=$?
|
|
210
|
+
if [ "$vrc" = "0" ]; then
|
|
211
|
+
printf " ${BLUE}✔${RESET} Checksum verified\n"
|
|
212
|
+
elif [ "$vrc" = "2" ]; then
|
|
213
|
+
printf " ${YELLOW}!${RESET} Could not compute checksum — skipping verification\n"
|
|
214
|
+
else
|
|
215
|
+
printf " ${RED}✗${RESET} Node.js checksum mismatch — aborting (corrupt or tampered download)\n"
|
|
216
|
+
exit 1
|
|
217
|
+
fi
|
|
128
218
|
else
|
|
129
|
-
printf " ${
|
|
130
|
-
exit 1
|
|
219
|
+
printf " ${YELLOW}!${RESET} Could not fetch checksums — skipping verification\n"
|
|
131
220
|
fi
|
|
132
221
|
|
|
133
|
-
# Extract
|
|
222
|
+
# Extract into a staging dir, verify it runs, then atomically swap in. An
|
|
223
|
+
# interrupt mid-extract no longer wipes the existing (working) node.
|
|
134
224
|
mkdir -p "$TOOLS_DIR"
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
tar xf "$TMPFILE" -C "$
|
|
139
|
-
rm -f "$TMPFILE"
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
225
|
+
NODE_NEW="$NODE_DIR.new"
|
|
226
|
+
rm -rf "$NODE_NEW"
|
|
227
|
+
mkdir -p "$NODE_NEW"
|
|
228
|
+
tar xf "$TMPFILE" -C "$NODE_NEW" --strip-components=1
|
|
229
|
+
rm -f "$TMPFILE"; TMPFILE=""
|
|
230
|
+
|
|
231
|
+
if ! "$NODE_NEW/bin/node" -v >/dev/null 2>&1; then
|
|
232
|
+
printf " ${RED}✗${RESET} Node.js download failed (extracted binary does not run)\n"
|
|
233
|
+
rm -rf "$NODE_NEW"
|
|
144
234
|
exit 1
|
|
145
235
|
fi
|
|
146
236
|
|
|
237
|
+
rm -rf "$NODE_DIR.old"
|
|
238
|
+
[ -e "$NODE_DIR" ] && mv "$NODE_DIR" "$NODE_DIR.old"
|
|
239
|
+
mv "$NODE_NEW" "$NODE_DIR"
|
|
240
|
+
rm -rf "$NODE_DIR.old"
|
|
241
|
+
|
|
147
242
|
printf " ${BLUE}✔${RESET} Node.js v${NODE_VERSION} installed\n"
|
|
148
243
|
}
|
|
149
244
|
|
|
@@ -174,19 +269,15 @@ install_bloby() {
|
|
|
174
269
|
exit 1
|
|
175
270
|
fi
|
|
176
271
|
|
|
177
|
-
# Download and extract tarball
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
curl -fsSL -o "$TMPDIR/bloby.tgz" "$TARBALL_URL"
|
|
181
|
-
elif command -v wget >/dev/null 2>&1; then
|
|
182
|
-
wget -qO "$TMPDIR/bloby.tgz" "$TARBALL_URL"
|
|
183
|
-
fi
|
|
272
|
+
# Download and extract tarball (download_file guards on missing curl/wget)
|
|
273
|
+
WORK_DIR=$(mktemp -d)
|
|
274
|
+
download_file "$TARBALL_URL" "$WORK_DIR/bloby.tgz"
|
|
184
275
|
|
|
185
|
-
tar xzf "$
|
|
186
|
-
EXTRACTED="$
|
|
276
|
+
tar xzf "$WORK_DIR/bloby.tgz" -C "$WORK_DIR"
|
|
277
|
+
EXTRACTED="$WORK_DIR/package"
|
|
187
278
|
|
|
188
279
|
if [ ! -d "$EXTRACTED" ]; then
|
|
189
|
-
rm -rf "$
|
|
280
|
+
rm -rf "$WORK_DIR"; WORK_DIR=""
|
|
190
281
|
printf " ${RED}✗${RESET} Installation failed\n"
|
|
191
282
|
exit 1
|
|
192
283
|
fi
|
|
@@ -219,7 +310,7 @@ install_bloby() {
|
|
|
219
310
|
fi
|
|
220
311
|
fi
|
|
221
312
|
|
|
222
|
-
rm -rf "$
|
|
313
|
+
rm -rf "$WORK_DIR"; WORK_DIR=""
|
|
223
314
|
|
|
224
315
|
# Install dependencies inside ~/.bloby/
|
|
225
316
|
# claude-agent-sdk 0.3.x moved @anthropic-ai/sdk + @modelcontextprotocol/sdk to
|
|
@@ -245,6 +336,15 @@ install_bloby() {
|
|
|
245
336
|
WS_INSTALL_LOG=$(mktemp)
|
|
246
337
|
if ! (cd "$BLOBY_HOME/workspace" && "$NPM" install --omit=dev > "$WS_INSTALL_LOG" 2>&1); then
|
|
247
338
|
printf " ${RED}✗${RESET} Workspace dependency install failed:\n"
|
|
339
|
+
# Native modules (better-sqlite3 etc.) need a compiler toolchain — detect
|
|
340
|
+
# the common "missing build tools" failure and point at the exact fix.
|
|
341
|
+
if grep -qiE 'make: .*command not found|gyp ERR! find Python|no developer tools|xcode-select|command not found: make|g\+\+: not found' "$WS_INSTALL_LOG"; then
|
|
342
|
+
if [ "$PLATFORM" = "darwin" ]; then
|
|
343
|
+
printf " ${YELLOW}!${RESET} Native build tools missing. Run ${BOLD}xcode-select --install${RESET} then re-run this installer.\n"
|
|
344
|
+
else
|
|
345
|
+
printf " ${YELLOW}!${RESET} Native build tools missing. On Debian/Ubuntu: ${BOLD}sudo apt-get install -y build-essential python3${RESET}, then re-run.\n"
|
|
346
|
+
fi
|
|
347
|
+
fi
|
|
248
348
|
cat "$WS_INSTALL_LOG"
|
|
249
349
|
rm -f "$WS_INSTALL_LOG"
|
|
250
350
|
exit 1
|
|
@@ -348,19 +448,34 @@ install_bloby
|
|
|
348
448
|
create_wrapper
|
|
349
449
|
setup_path
|
|
350
450
|
|
|
451
|
+
# Smoke-test: the wrapper + node + cli must actually run, not just exist on disk.
|
|
452
|
+
if ! "$BIN_DIR/bloby" --version >/dev/null 2>&1; then
|
|
453
|
+
printf "\n ${RED}✗${RESET} Bloby installed but failed to run (\`bloby --version\`).\n"
|
|
454
|
+
printf " ${DIM}Open a NEW terminal and run ${BOLD}bloby --version${RESET}${DIM}; if it still fails, re-run this installer.${RESET}\n\n"
|
|
455
|
+
exit 1
|
|
456
|
+
fi
|
|
457
|
+
|
|
351
458
|
printf "\n"
|
|
352
|
-
printf " ${PINK}${BOLD}✔ Bloby is
|
|
459
|
+
printf " ${PINK}${BOLD}✔ Bloby is installed!${RESET}\n"
|
|
353
460
|
printf "\n"
|
|
354
|
-
printf " ${
|
|
355
|
-
printf " ${BOLD}
|
|
461
|
+
printf " ${BLUE}${BOLD}╭───────────────────────────────────────────────────────╮${RESET}\n"
|
|
462
|
+
printf " ${BLUE}${BOLD}│${RESET} ${RESET}${BLUE}${BOLD}│${RESET}\n"
|
|
463
|
+
printf " ${BLUE}${BOLD}│${RESET}${BOLD} NEXT STEP - type this, then press Enter:${RESET} ${BLUE}${BOLD}│${RESET}\n"
|
|
464
|
+
printf " ${BLUE}${BOLD}│${RESET} ${RESET}${BLUE}${BOLD}│${RESET}\n"
|
|
465
|
+
printf " ${BLUE}${BOLD}│${RESET}${BLUE}${BOLD} > bloby init${RESET} ${BLUE}${BOLD}│${RESET}\n"
|
|
466
|
+
printf " ${BLUE}${BOLD}│${RESET} ${RESET}${BLUE}${BOLD}│${RESET}\n"
|
|
467
|
+
printf " ${BLUE}${BOLD}│${RESET}${DIM} ─────────────────────────────────────────────────${RESET} ${BLUE}${BOLD}│${RESET}\n"
|
|
468
|
+
printf " ${BLUE}${BOLD}│${RESET} ${RESET}${BLUE}${BOLD}│${RESET}\n"
|
|
469
|
+
printf " ${BLUE}${BOLD}│${RESET}${YELLOW}${BOLD} Not working? (\"command not found\")${RESET} ${BLUE}${BOLD}│${RESET}\n"
|
|
470
|
+
printf " ${BLUE}${BOLD}│${RESET} Just open a NEW terminal window and run${RESET} ${BLUE}${BOLD}│${RESET}\n"
|
|
471
|
+
printf " ${BLUE}${BOLD}│${RESET} bloby init again.${RESET} ${BLUE}${BOLD}│${RESET}\n"
|
|
472
|
+
printf " ${BLUE}${BOLD}│${RESET} ${RESET}${BLUE}${BOLD}│${RESET}\n"
|
|
473
|
+
printf " ${BLUE}${BOLD}╰───────────────────────────────────────────────────────╯${RESET}\n"
|
|
356
474
|
printf "\n"
|
|
357
|
-
printf "
|
|
475
|
+
printf " ${DIM}Other commands:${RESET}\n"
|
|
358
476
|
printf " ${BLUE}bloby start${RESET} Start your bot\n"
|
|
359
477
|
printf " ${BLUE}bloby status${RESET} Check if it's running\n"
|
|
360
478
|
printf " ${BLUE}bloby help${RESET} All commands\n"
|
|
361
479
|
printf "\n"
|
|
362
|
-
printf " ${PINK}>${RESET} Run ${BLUE}bloby init${RESET} to begin.\n"
|
|
363
|
-
printf " ${DIM}(Open a new terminal if 'bloby' isn't found yet)${RESET}\n"
|
|
364
|
-
printf "\n"
|
|
365
480
|
printf " ${DIM}https://bloby.bot${RESET}\n"
|
|
366
481
|
printf "\n"
|
package/scripts/install.ps1
CHANGED
|
@@ -6,6 +6,30 @@
|
|
|
6
6
|
|
|
7
7
|
$ErrorActionPreference = "Stop"
|
|
8
8
|
|
|
9
|
+
# TLS 1.2 floor for Windows PowerShell 5.1 (which can default to TLS 1.0/1.1 and
|
|
10
|
+
# fail against nodejs.org/npm). OR-in so we never DROP TLS 1.3 on PowerShell 7+.
|
|
11
|
+
try {
|
|
12
|
+
[Net.ServicePointManager]::SecurityProtocol = `
|
|
13
|
+
[Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12
|
|
14
|
+
} catch {}
|
|
15
|
+
|
|
16
|
+
# Get-Url <url> <outFile> — download with a timeout and up to 3 attempts so a
|
|
17
|
+
# single transient blip doesn't abort the whole install. PS 5.1-compatible
|
|
18
|
+
# (no -MaximumRetryCount, which is PowerShell 6+ only).
|
|
19
|
+
function Get-Url($url, $outFile) {
|
|
20
|
+
$attempt = 0
|
|
21
|
+
while ($true) {
|
|
22
|
+
$attempt++
|
|
23
|
+
try {
|
|
24
|
+
Invoke-WebRequest -Uri $url -OutFile $outFile -UseBasicParsing -TimeoutSec 60
|
|
25
|
+
return
|
|
26
|
+
} catch {
|
|
27
|
+
if ($attempt -ge 3) { throw }
|
|
28
|
+
Start-Sleep -Seconds 2
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
9
33
|
$MIN_NODE_MAJOR = 18
|
|
10
34
|
$NODE_VERSION = "22.14.0"
|
|
11
35
|
$BLOBY_HOME = Join-Path $env:USERPROFILE ".bloby"
|
|
@@ -29,6 +53,8 @@ $G5 = "`e[38;2;1;116;252m"
|
|
|
29
53
|
$G6 = "`e[38;2;1;102;251m"
|
|
30
54
|
$G7 = "`e[38;2;1;88;251m"
|
|
31
55
|
$BOLD = "`e[1m"
|
|
56
|
+
$DIM = "`e[2m"
|
|
57
|
+
$YELLOW = "`e[33m"
|
|
32
58
|
$RSET = "`e[0m"
|
|
33
59
|
|
|
34
60
|
# Use ANSI sequences for consistent rendering; fallback to plain if no VT support
|
|
@@ -123,25 +149,64 @@ function Install-Node {
|
|
|
123
149
|
|
|
124
150
|
Write-Down "Downloading Node.js v${NODE_VERSION}..."
|
|
125
151
|
|
|
126
|
-
$
|
|
152
|
+
$nodeFile = "node-v${NODE_VERSION}-win-${NODEARCH}.zip"
|
|
153
|
+
$nodeUrl = "https://nodejs.org/dist/v${NODE_VERSION}/$nodeFile"
|
|
127
154
|
$tmpFile = Join-Path ([System.IO.Path]::GetTempPath()) "node-bloby.zip"
|
|
128
155
|
|
|
129
|
-
|
|
156
|
+
Get-Url $nodeUrl $tmpFile
|
|
130
157
|
|
|
131
|
-
#
|
|
132
|
-
|
|
133
|
-
|
|
158
|
+
# Integrity: verify against nodejs.org SHASUMS256.txt before extracting. A
|
|
159
|
+
# mismatch is fatal; an unreachable sums file degrades to a warning.
|
|
160
|
+
try {
|
|
161
|
+
$sums = (Invoke-WebRequest -Uri "https://nodejs.org/dist/v${NODE_VERSION}/SHASUMS256.txt" -UseBasicParsing -TimeoutSec 30).Content
|
|
162
|
+
$line = $sums -split "`n" | Where-Object { $_ -match ([regex]::Escape($nodeFile) + '\s*$') } | Select-Object -First 1
|
|
163
|
+
if ($line) {
|
|
164
|
+
$expectedHash = ($line -split '\s+')[0]
|
|
165
|
+
$actualHash = (Get-FileHash -Path $tmpFile -Algorithm SHA256).Hash
|
|
166
|
+
if ($actualHash -ieq $expectedHash) {
|
|
167
|
+
Write-Check "Checksum verified"
|
|
168
|
+
} else {
|
|
169
|
+
Write-Host " ✗ Node.js checksum mismatch — aborting (corrupt or tampered download)" -ForegroundColor Red
|
|
170
|
+
Remove-Item $tmpFile -Force -ErrorAction SilentlyContinue
|
|
171
|
+
exit 1
|
|
172
|
+
}
|
|
173
|
+
} else {
|
|
174
|
+
Write-Host " ! Could not find checksum entry — skipping verification" -ForegroundColor Yellow
|
|
175
|
+
}
|
|
176
|
+
} catch {
|
|
177
|
+
Write-Host " ! Could not fetch checksums — skipping verification" -ForegroundColor Yellow
|
|
178
|
+
}
|
|
134
179
|
|
|
180
|
+
# Extract into a staging dir, verify it runs, then swap. Move-Item cannot
|
|
181
|
+
# overwrite a populated directory, so the existing node is moved aside and
|
|
182
|
+
# removed only AFTER the new tree is verified — an interrupt never strands us.
|
|
183
|
+
New-Item -ItemType Directory -Path $TOOLS_DIR -Force | Out-Null
|
|
135
184
|
$tmpExtract = Join-Path ([System.IO.Path]::GetTempPath()) "node-bloby-extract"
|
|
136
185
|
if (Test-Path $tmpExtract) { Remove-Item $tmpExtract -Recurse -Force }
|
|
137
186
|
|
|
138
187
|
Expand-Archive -Path $tmpFile -DestinationPath $tmpExtract -Force
|
|
139
188
|
$extracted = Get-ChildItem $tmpExtract | Select-Object -First 1
|
|
140
|
-
|
|
189
|
+
$nodeNew = "$NODE_DIR.new"
|
|
190
|
+
if (Test-Path $nodeNew) { Remove-Item $nodeNew -Recurse -Force }
|
|
191
|
+
Move-Item -Path $extracted.FullName -Destination $nodeNew -Force
|
|
141
192
|
|
|
142
193
|
Remove-Item $tmpFile -Force -ErrorAction SilentlyContinue
|
|
143
194
|
Remove-Item $tmpExtract -Recurse -Force -ErrorAction SilentlyContinue
|
|
144
195
|
|
|
196
|
+
$stagedNode = Join-Path $nodeNew "node.exe"
|
|
197
|
+
$stagedOk = $false
|
|
198
|
+
try { $stagedOk = [bool](& $stagedNode -v 2>$null) } catch {}
|
|
199
|
+
if (-not $stagedOk) {
|
|
200
|
+
Write-Host " ✗ Node.js download failed (extracted binary does not run)" -ForegroundColor Red
|
|
201
|
+
Remove-Item $nodeNew -Recurse -Force -ErrorAction SilentlyContinue
|
|
202
|
+
exit 1
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (Test-Path "$NODE_DIR.old") { Remove-Item "$NODE_DIR.old" -Recurse -Force -ErrorAction SilentlyContinue }
|
|
206
|
+
if (Test-Path $NODE_DIR) { Move-Item $NODE_DIR "$NODE_DIR.old" -Force }
|
|
207
|
+
Move-Item $nodeNew $NODE_DIR -Force
|
|
208
|
+
if (Test-Path "$NODE_DIR.old") { Remove-Item "$NODE_DIR.old" -Recurse -Force -ErrorAction SilentlyContinue }
|
|
209
|
+
|
|
145
210
|
# Verify
|
|
146
211
|
$nodeBin = Join-Path $NODE_DIR "node.exe"
|
|
147
212
|
if (-not (Test-Path $nodeBin)) {
|
|
@@ -172,9 +237,13 @@ function Install-Bloby {
|
|
|
172
237
|
|
|
173
238
|
Write-Down "Installing bloby..."
|
|
174
239
|
|
|
175
|
-
|
|
240
|
+
# Capture first, THEN .Trim() — calling .Trim() on a null (offline npm) throws
|
|
241
|
+
# under $ErrorActionPreference='Stop' and skips the friendly message below.
|
|
242
|
+
$tarballUrl = ""
|
|
243
|
+
try { $tarballUrl = (& $NPM view bloby-bot dist.tarball 2>$null) } catch {}
|
|
244
|
+
if ($tarballUrl) { $tarballUrl = $tarballUrl.Trim() }
|
|
176
245
|
if (-not $tarballUrl) {
|
|
177
|
-
Write-Host " ✗ Failed to fetch package info from npm" -ForegroundColor Red
|
|
246
|
+
Write-Host " ✗ Failed to fetch package info from npm (are you online?)" -ForegroundColor Red
|
|
178
247
|
exit 1
|
|
179
248
|
}
|
|
180
249
|
|
|
@@ -184,7 +253,7 @@ function Install-Bloby {
|
|
|
184
253
|
|
|
185
254
|
try {
|
|
186
255
|
$tarball = Join-Path $tmpDir "bloby.tgz"
|
|
187
|
-
|
|
256
|
+
Get-Url $tarballUrl $tarball
|
|
188
257
|
|
|
189
258
|
tar xzf $tarball -C $tmpDir
|
|
190
259
|
|
|
@@ -253,21 +322,39 @@ function Install-Bloby {
|
|
|
253
322
|
if (-not ((Test-Path $npmrc) -and (Select-String -Path $npmrc -Pattern '^legacy-peer-deps' -Quiet))) {
|
|
254
323
|
Add-Content -Path $npmrc -Value 'legacy-peer-deps=true'
|
|
255
324
|
}
|
|
325
|
+
# Toggle EAP to Continue around the native npm call so a stderr line doesn't
|
|
326
|
+
# raise a NativeCommandError; then gate on the real exit code. A broken dep
|
|
327
|
+
# tree is fatal here (matching install.sh) instead of being silently ignored.
|
|
256
328
|
Push-Location $BLOBY_HOME
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
329
|
+
$eap = $ErrorActionPreference; $ErrorActionPreference = "Continue"
|
|
330
|
+
$npmOut = & $NPM install --omit=dev 2>&1
|
|
331
|
+
$npmCode = $LASTEXITCODE
|
|
332
|
+
$ErrorActionPreference = $eap
|
|
260
333
|
Pop-Location
|
|
334
|
+
if ($npmCode -ne 0) {
|
|
335
|
+
Write-Host " ✗ Dependency install failed:" -ForegroundColor Red
|
|
336
|
+
$npmOut | ForEach-Object { Write-Host " $_" }
|
|
337
|
+
exit 1
|
|
338
|
+
}
|
|
261
339
|
|
|
262
340
|
# Install workspace dependencies (rebuilds native modules for this platform)
|
|
263
341
|
$wsDir = Join-Path $BLOBY_HOME "workspace"
|
|
264
342
|
if (Test-Path (Join-Path $wsDir "package.json")) {
|
|
265
343
|
Write-Down "Installing workspace dependencies..."
|
|
266
344
|
Push-Location $wsDir
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
345
|
+
$eap = $ErrorActionPreference; $ErrorActionPreference = "Continue"
|
|
346
|
+
$wsOut = & $NPM install --omit=dev 2>&1
|
|
347
|
+
$wsCode = $LASTEXITCODE
|
|
348
|
+
$ErrorActionPreference = $eap
|
|
270
349
|
Pop-Location
|
|
350
|
+
if ($wsCode -ne 0) {
|
|
351
|
+
Write-Host " ✗ Workspace dependency install failed:" -ForegroundColor Red
|
|
352
|
+
if ("$wsOut" -match 'Visual Studio|gyp ERR|MSBuild|node-gyp|Python') {
|
|
353
|
+
Write-Host " ! Native build tools missing. Install the Visual Studio Build Tools (Desktop C++ workload) + Python 3, then re-run. See https://github.com/nodejs/node-gyp#on-windows" -ForegroundColor Yellow
|
|
354
|
+
}
|
|
355
|
+
$wsOut | ForEach-Object { Write-Host " $_" }
|
|
356
|
+
exit 1
|
|
357
|
+
}
|
|
271
358
|
}
|
|
272
359
|
|
|
273
360
|
# Verify
|
|
@@ -334,33 +421,63 @@ Install-Bloby
|
|
|
334
421
|
Create-Wrapper
|
|
335
422
|
Setup-Path
|
|
336
423
|
|
|
424
|
+
# Smoke-test: the wrapper + node + cli must actually run, not just exist on disk.
|
|
425
|
+
$blobyCmd = Join-Path $BIN_DIR "bloby.cmd"
|
|
426
|
+
$smokeOk = $false
|
|
427
|
+
try { $smokeOk = [bool](& $blobyCmd --version 2>$null) } catch {}
|
|
428
|
+
if (-not $smokeOk) {
|
|
429
|
+
Write-Host ""
|
|
430
|
+
Write-Host " ✗ Bloby installed but failed to run (bloby --version)." -ForegroundColor Red
|
|
431
|
+
Write-Host " Open a NEW terminal and run 'bloby --version'; if it still fails, re-run this installer." -ForegroundColor DarkGray
|
|
432
|
+
exit 1
|
|
433
|
+
}
|
|
434
|
+
|
|
337
435
|
Write-Host ""
|
|
338
436
|
if ($vtSupported) {
|
|
339
|
-
Write-Host " ${PINK}${BOLD}✔ Bloby is
|
|
437
|
+
Write-Host " ${PINK}${BOLD}✔ Bloby is installed!${RSET}"
|
|
340
438
|
} else {
|
|
341
|
-
Write-Host " ✔ Bloby is
|
|
439
|
+
Write-Host " ✔ Bloby is installed!" -ForegroundColor Magenta
|
|
342
440
|
}
|
|
343
441
|
Write-Host ""
|
|
344
|
-
|
|
345
|
-
Write-Host "
|
|
442
|
+
if ($vtSupported) {
|
|
443
|
+
Write-Host " ${BLUE}${BOLD}╭───────────────────────────────────────────────────────╮${RSET}"
|
|
444
|
+
Write-Host " ${BLUE}${BOLD}│${RSET} ${RSET}${BLUE}${BOLD}│${RSET}"
|
|
445
|
+
Write-Host " ${BLUE}${BOLD}│${RSET}${BOLD} NEXT STEP - type this, then press Enter:${RSET} ${BLUE}${BOLD}│${RSET}"
|
|
446
|
+
Write-Host " ${BLUE}${BOLD}│${RSET} ${RSET}${BLUE}${BOLD}│${RSET}"
|
|
447
|
+
Write-Host " ${BLUE}${BOLD}│${RSET}${BLUE}${BOLD} > bloby init${RSET} ${BLUE}${BOLD}│${RSET}"
|
|
448
|
+
Write-Host " ${BLUE}${BOLD}│${RSET} ${RSET}${BLUE}${BOLD}│${RSET}"
|
|
449
|
+
Write-Host " ${BLUE}${BOLD}│${RSET}${DIM} ─────────────────────────────────────────────────${RSET} ${BLUE}${BOLD}│${RSET}"
|
|
450
|
+
Write-Host " ${BLUE}${BOLD}│${RSET} ${RSET}${BLUE}${BOLD}│${RSET}"
|
|
451
|
+
Write-Host " ${BLUE}${BOLD}│${RSET}${YELLOW}${BOLD} Not working? (`"command not found`")${RSET} ${BLUE}${BOLD}│${RSET}"
|
|
452
|
+
Write-Host " ${BLUE}${BOLD}│${RSET} Just open a NEW terminal window and run${RSET} ${BLUE}${BOLD}│${RSET}"
|
|
453
|
+
Write-Host " ${BLUE}${BOLD}│${RSET} bloby init again.${RSET} ${BLUE}${BOLD}│${RSET}"
|
|
454
|
+
Write-Host " ${BLUE}${BOLD}│${RSET} ${RSET}${BLUE}${BOLD}│${RSET}"
|
|
455
|
+
Write-Host " ${BLUE}${BOLD}╰───────────────────────────────────────────────────────╯${RSET}"
|
|
456
|
+
} else {
|
|
457
|
+
Write-Host " +-------------------------------------------------------+" -ForegroundColor Cyan
|
|
458
|
+
Write-Host " | |" -ForegroundColor Cyan
|
|
459
|
+
Write-Host " | NEXT STEP - type this, then press Enter: |" -ForegroundColor Cyan
|
|
460
|
+
Write-Host " | |" -ForegroundColor Cyan
|
|
461
|
+
Write-Host " | > bloby init |" -ForegroundColor Cyan
|
|
462
|
+
Write-Host " | |" -ForegroundColor Cyan
|
|
463
|
+
Write-Host " | Not working? (`"command not found`") |" -ForegroundColor Cyan
|
|
464
|
+
Write-Host " | Just open a NEW terminal window and run |" -ForegroundColor Cyan
|
|
465
|
+
Write-Host " | bloby init again. |" -ForegroundColor Cyan
|
|
466
|
+
Write-Host " | |" -ForegroundColor Cyan
|
|
467
|
+
Write-Host " +-------------------------------------------------------+" -ForegroundColor Cyan
|
|
468
|
+
}
|
|
346
469
|
Write-Host ""
|
|
347
470
|
if ($vtSupported) {
|
|
348
|
-
Write-Host "
|
|
471
|
+
Write-Host " ${DIM}Other commands:${RSET}"
|
|
349
472
|
Write-Host " ${BLUE}bloby start${RSET} Start your bot"
|
|
350
473
|
Write-Host " ${BLUE}bloby status${RSET} Check if it's running"
|
|
351
|
-
Write-Host ""
|
|
352
|
-
Write-Host " ${PINK}>${RSET} Run ${BLUE}bloby init${RSET} to begin."
|
|
474
|
+
Write-Host " ${BLUE}bloby help${RSET} All commands"
|
|
353
475
|
} else {
|
|
354
|
-
Write-Host "
|
|
476
|
+
Write-Host " Other commands:" -ForegroundColor DarkGray
|
|
355
477
|
Write-Host " bloby start " -ForegroundColor Cyan -NoNewline; Write-Host "Start your bot"
|
|
356
478
|
Write-Host " bloby status " -ForegroundColor Cyan -NoNewline; Write-Host "Check if it's running"
|
|
357
|
-
Write-Host ""
|
|
358
|
-
Write-Host " > " -ForegroundColor Magenta -NoNewline
|
|
359
|
-
Write-Host "Run " -NoNewline
|
|
360
|
-
Write-Host "bloby init" -ForegroundColor Cyan -NoNewline
|
|
361
|
-
Write-Host " to begin."
|
|
479
|
+
Write-Host " bloby help " -ForegroundColor Cyan -NoNewline; Write-Host "All commands"
|
|
362
480
|
}
|
|
363
|
-
Write-Host " (Open a new terminal if 'bloby' isn't found yet)" -ForegroundColor DarkGray
|
|
364
481
|
Write-Host ""
|
|
365
482
|
Write-Host " https://bloby.bot" -ForegroundColor DarkGray
|
|
366
483
|
Write-Host ""
|