#!/bin/sh # Installs ToolUniverse for this user account, so `tu` works in every terminal. # # curl -LsSf https://connect.aiscientist.tools/install.sh | sh # # Python does not need to be installed first: uv (https://docs.astral.sh/uv) fetches its own # Python 3.12, and everything lives in uv's tool folder, apart from anything else on this # computer. Running it again updates in place. If your own functions need other packages, # name them at the end: # # curl -LsSf https://connect.aiscientist.tools/install.sh | sh -s -- numpy pandas # # The versions below are pinned and kept identical to frontend/lib/tuplatform-connect.ts by # frontend/tests/install-script.test.mts. set -eu TOOLUNIVERSE_REQUIREMENT='tooluniverse==1.5.7' TUPLATFORM_CONNECT_REQUIREMENT='tuplatform-connect @ https://connect.aiscientist.tools/downloads/tuplatform_connect-0.4.2-py3-none-any.whl#sha256=e4e09af02093da3e739c9234e1f8182f8a9c311cd9fc0145a1dc119a296ef8ba' PYTHON_VERSION='3.12' say() { printf '%s\n' "$*"; } fail() { printf 'ToolUniverse install stopped: %s\n' "$*" >&2; exit 1; } # A uv that can install executables from a second package (uv 0.8 or newer). usable_uv() { [ -n "$1" ] && "$1" tool install --help 2>/dev/null | grep -q -- '--with-executables-from' } # Everything runs inside main, so `curl | sh` has read the whole script before any step # starts and nothing that reads standard input can swallow the rest of it. main() { UV='' if usable_uv "$(command -v uv 2>/dev/null || true)"; then UV=$(command -v uv) elif usable_uv "$HOME/.local/bin/uv"; then UV="$HOME/.local/bin/uv" else command -v curl >/dev/null 2>&1 || fail "curl is needed to download uv." say "Getting uv, the small program that installs Python and ToolUniverse for you..." curl -LsSf https://astral.sh/uv/install.sh | env UV_NO_MODIFY_PATH=1 sh >/dev/null \ || fail "could not download uv. Check the internet connection and try again." UV="$HOME/.local/bin/uv" usable_uv "$UV" || fail "uv was downloaded but does not run on this computer." fi say "Installing ToolUniverse (about a minute the first time)..." # Turn each extra package name into `--with `, keeping the names exactly as given. count=$# while [ "$count" -gt 0 ]; do package=$1 shift set -- "$@" --with "$package" count=$((count - 1)) done "$UV" tool install --quiet --force --python "$PYTHON_VERSION" \ --with-executables-from "$TUPLATFORM_CONNECT_REQUIREMENT" "$@" "$TOOLUNIVERSE_REQUIREMENT" \ || fail "the install did not finish. The messages above say why." BIN=$("$UV" tool dir --bin) "$BIN/tu" --help >/dev/null 2>&1 || fail "tu was installed but does not start." "$UV" tool update-shell >/dev/null 2>&1 || true say "" say "ToolUniverse is installed." case ":$PATH:" in *":$BIN:"*) say "You can run the next step in this terminal." ;; *) say "Open a new terminal window, then run the next step there." ;; esac } main "$@"