ci: sync from octopus@0.9.0
This commit is contained in:
@@ -0,0 +1,29 @@
|
|||||||
|
# Octopus
|
||||||
|
|
||||||
|
The AI coding agent built for the terminal.
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
**Unix (Linux/macOS):**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -fsSL http://octopus.51zxtx.com:3000/fourbroad/octopus-release/raw/branch/main/install | bash
|
||||||
|
```
|
||||||
|
|
||||||
|
**Windows (PowerShell):**
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
irm http://octopus.51zxtx.com:3000/fourbroad/octopus-release/raw/branch/main/install.ps1 | iex
|
||||||
|
```
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
Visit the [documentation](http://octopus.51zxtx.com:3000/fourbroad/octopus/wiki) for usage guides and API reference.
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
The source code and issue tracker are available at the [private development repository](http://octopus.51zxtx.com:3000/fourbroad/octopus).
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT License — see the source repository for details.
|
||||||
@@ -0,0 +1,461 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Public release repository:
|
||||||
|
# http://octopus.51zxtx.com:3000/fourbroad/octopus-release
|
||||||
|
set -euo pipefail
|
||||||
|
APP=octopus
|
||||||
|
|
||||||
|
MUTED='\033[0;2m'
|
||||||
|
RED='\033[0;31m'
|
||||||
|
ORANGE='\033[38;5;214m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<EOF
|
||||||
|
Octopus Installer
|
||||||
|
|
||||||
|
Usage: install.sh [options]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-h, --help Display this help message
|
||||||
|
-v, --version <version> Install a specific version (e.g., 1.0.180)
|
||||||
|
-b, --binary <path> Install from a local binary instead of downloading
|
||||||
|
--no-modify-path Don't modify shell config files (.zshrc, .bashrc, etc.)
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
curl -fsSL https://octopus.51zxtx.com/install | bash
|
||||||
|
curl -fsSL https://octopus.51zxtx.com/install | bash -s -- --version 1.0.180
|
||||||
|
./install --binary /path/to/octopus
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
requested_version=${VERSION:-}
|
||||||
|
no_modify_path=false
|
||||||
|
binary_path=""
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
-h|--help)
|
||||||
|
usage
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
-v|--version)
|
||||||
|
if [[ -n "${2:-}" ]]; then
|
||||||
|
requested_version="$2"
|
||||||
|
shift 2
|
||||||
|
else
|
||||||
|
echo -e "${RED}Error: --version requires a version argument${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
-b|--binary)
|
||||||
|
if [[ -n "${2:-}" ]]; then
|
||||||
|
binary_path="$2"
|
||||||
|
shift 2
|
||||||
|
else
|
||||||
|
echo -e "${RED}Error: --binary requires a path argument${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
--no-modify-path)
|
||||||
|
no_modify_path=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo -e "${ORANGE}Warning: Unknown option '$1'${NC}" >&2
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
INSTALL_DIR=$HOME/.octopus/bin
|
||||||
|
mkdir -p "$INSTALL_DIR"
|
||||||
|
|
||||||
|
# If --binary is provided, skip all download/detection logic
|
||||||
|
if [ -n "$binary_path" ]; then
|
||||||
|
if [ ! -f "$binary_path" ]; then
|
||||||
|
echo -e "${RED}Error: Binary not found at ${binary_path}${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
specific_version="local"
|
||||||
|
else
|
||||||
|
raw_os=$(uname -s)
|
||||||
|
os=$(echo "$raw_os" | tr '[:upper:]' '[:lower:]')
|
||||||
|
case "$raw_os" in
|
||||||
|
Darwin*) os="darwin" ;;
|
||||||
|
Linux*) os="linux" ;;
|
||||||
|
MINGW*|MSYS*|CYGWIN*) os="windows" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
arch=$(uname -m)
|
||||||
|
if [[ "$arch" == "aarch64" ]]; then
|
||||||
|
arch="arm64"
|
||||||
|
fi
|
||||||
|
if [[ "$arch" == "x86_64" ]]; then
|
||||||
|
arch="x64"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$os" = "darwin" ] && [ "$arch" = "x64" ]; then
|
||||||
|
rosetta_flag=$(sysctl -n sysctl.proc_translated 2>/dev/null || echo 0)
|
||||||
|
if [ "$rosetta_flag" = "1" ]; then
|
||||||
|
arch="arm64"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
combo="$os-$arch"
|
||||||
|
case "$combo" in
|
||||||
|
linux-x64|linux-arm64|darwin-x64|darwin-arm64|windows-x64)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo -e "${RED}Unsupported OS/Arch: $os/$arch${NC}"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
archive_ext=".zip"
|
||||||
|
if [ "$os" = "linux" ]; then
|
||||||
|
archive_ext=".tar.gz"
|
||||||
|
fi
|
||||||
|
|
||||||
|
is_musl=false
|
||||||
|
if [ "$os" = "linux" ]; then
|
||||||
|
if [ -f /etc/alpine-release ]; then
|
||||||
|
is_musl=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v ldd >/dev/null 2>&1; then
|
||||||
|
if ldd --version 2>&1 | grep -qi musl; then
|
||||||
|
is_musl=true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
needs_baseline=false
|
||||||
|
if [ "$arch" = "x64" ]; then
|
||||||
|
if [ "$os" = "linux" ]; then
|
||||||
|
if ! grep -qwi avx2 /proc/cpuinfo 2>/dev/null; then
|
||||||
|
needs_baseline=true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$os" = "darwin" ]; then
|
||||||
|
avx2=$(sysctl -n hw.optional.avx2_0 2>/dev/null || echo 0)
|
||||||
|
if [ "$avx2" != "1" ]; then
|
||||||
|
needs_baseline=true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$os" = "windows" ]; then
|
||||||
|
ps="(Add-Type -MemberDefinition \"[DllImport(\"\"kernel32.dll\"\")] public static extern bool IsProcessorFeaturePresent(int ProcessorFeature);\" -Name Kernel32 -Namespace Win32 -PassThru)::IsProcessorFeaturePresent(40)"
|
||||||
|
out=""
|
||||||
|
if command -v powershell.exe >/dev/null 2>&1; then
|
||||||
|
out=$(powershell.exe -NoProfile -NonInteractive -Command "$ps" 2>/dev/null || true)
|
||||||
|
elif command -v pwsh >/dev/null 2>&1; then
|
||||||
|
out=$(pwsh -NoProfile -NonInteractive -Command "$ps" 2>/dev/null || true)
|
||||||
|
fi
|
||||||
|
out=$(echo "$out" | tr -d '\r' | tr '[:upper:]' '[:lower:]' | tr -d '[:space:]')
|
||||||
|
if [ "$out" != "true" ] && [ "$out" != "1" ]; then
|
||||||
|
needs_baseline=true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
target="$os-$arch"
|
||||||
|
if [ "$needs_baseline" = "true" ]; then
|
||||||
|
target="$target-baseline"
|
||||||
|
fi
|
||||||
|
if [ "$is_musl" = "true" ]; then
|
||||||
|
target="$target-musl"
|
||||||
|
fi
|
||||||
|
|
||||||
|
filename="$APP-$target$archive_ext"
|
||||||
|
|
||||||
|
|
||||||
|
if [ "$os" = "linux" ]; then
|
||||||
|
if ! command -v tar >/dev/null 2>&1; then
|
||||||
|
echo -e "${RED}Error: 'tar' is required but not installed.${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if ! command -v unzip >/dev/null 2>&1; then
|
||||||
|
echo -e "${RED}Error: 'unzip' is required but not installed.${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$requested_version" ]; then
|
||||||
|
specific_version=$(curl -s "${GITEA_API_URL:-http://octopus.51zxtx.com:3000/api/v1}/repos/fourbroad/octopus-release/releases?limit=1" | sed -n 's/.*"tag_name": *"v\([^"]*\)".*/\1/p')
|
||||||
|
|
||||||
|
if [[ $? -ne 0 || -z "$specific_version" ]]; then
|
||||||
|
echo -e "${RED}Failed to fetch version information${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
url="${OCTOPUS_DOWNLOAD_BASE:-http://octopus.51zxtx.com:3000}/fourbroad/octopus-release/releases/download/v${specific_version}/$filename"
|
||||||
|
else
|
||||||
|
# Strip leading 'v' if present
|
||||||
|
requested_version="${requested_version#v}"
|
||||||
|
url="${OCTOPUS_DOWNLOAD_BASE:-http://octopus.51zxtx.com:3000}/fourbroad/octopus-release/releases/download/v${requested_version}/$filename"
|
||||||
|
specific_version=$requested_version
|
||||||
|
|
||||||
|
# Verify the release exists before downloading
|
||||||
|
http_status=$(curl -sI -o /dev/null -w "%{http_code}" "${GITEA_URL:-http://octopus.51zxtx.com:3000}/fourbroad/octopus-release/releases/tag/v${requested_version}")
|
||||||
|
if [ "$http_status" = "404" ]; then
|
||||||
|
echo -e "${RED}Error: Release v${requested_version} not found${NC}"
|
||||||
|
echo -e "${MUTED}Available releases: ${GITEA_URL:-http://octopus.51zxtx.com:3000}/fourbroad/octopus-release/releases${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
print_message() {
|
||||||
|
local level=$1
|
||||||
|
local message=$2
|
||||||
|
local color=""
|
||||||
|
|
||||||
|
case $level in
|
||||||
|
info) color="${NC}" ;;
|
||||||
|
warning) color="${NC}" ;;
|
||||||
|
error) color="${RED}" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo -e "${color}${message}${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
check_version() {
|
||||||
|
if command -v octopus >/dev/null 2>&1; then
|
||||||
|
octopus_path=$(which octopus)
|
||||||
|
|
||||||
|
## Check the installed version
|
||||||
|
installed_version=$(octopus --version 2>/dev/null || echo "")
|
||||||
|
|
||||||
|
if [[ "$installed_version" != "$specific_version" ]]; then
|
||||||
|
print_message info "${MUTED}Installed version: ${NC}$installed_version."
|
||||||
|
else
|
||||||
|
print_message info "${MUTED}Version ${NC}$specific_version${MUTED} already installed"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
unbuffered_sed() {
|
||||||
|
if echo | sed -u -e "" >/dev/null 2>&1; then
|
||||||
|
sed -nu "$@"
|
||||||
|
elif echo | sed -l -e "" >/dev/null 2>&1; then
|
||||||
|
sed -nl "$@"
|
||||||
|
else
|
||||||
|
local pad="$(printf "\n%512s" "")"
|
||||||
|
sed -ne "s/$/\\${pad}/" "$@"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
print_progress() {
|
||||||
|
local bytes="$1"
|
||||||
|
local length="$2"
|
||||||
|
[ "$length" -gt 0 ] || return 0
|
||||||
|
|
||||||
|
local width=50
|
||||||
|
local percent=$(( bytes * 100 / length ))
|
||||||
|
[ "$percent" -gt 100 ] && percent=100
|
||||||
|
local on=$(( percent * width / 100 ))
|
||||||
|
local off=$(( width - on ))
|
||||||
|
|
||||||
|
local filled=$(printf "%*s" "$on" "")
|
||||||
|
filled=${filled// /■}
|
||||||
|
local empty=$(printf "%*s" "$off" "")
|
||||||
|
empty=${empty// /・}
|
||||||
|
|
||||||
|
printf "\r${ORANGE}%s%s %3d%%${NC}" "$filled" "$empty" "$percent" >&4
|
||||||
|
}
|
||||||
|
|
||||||
|
download_with_progress() {
|
||||||
|
local url="$1"
|
||||||
|
local output="$2"
|
||||||
|
|
||||||
|
if [ -t 2 ]; then
|
||||||
|
exec 4>&2
|
||||||
|
else
|
||||||
|
exec 4>/dev/null
|
||||||
|
fi
|
||||||
|
|
||||||
|
local tmp_dir=${TMPDIR:-/tmp}
|
||||||
|
local basename="${tmp_dir}/octopus_install_$$"
|
||||||
|
local tracefile="${basename}.trace"
|
||||||
|
|
||||||
|
rm -f "$tracefile"
|
||||||
|
mkfifo "$tracefile"
|
||||||
|
|
||||||
|
# Hide cursor
|
||||||
|
printf "\033[?25l" >&4
|
||||||
|
|
||||||
|
trap "trap - RETURN; rm -f \"$tracefile\"; printf '\033[?25h' >&4; exec 4>&-" RETURN
|
||||||
|
|
||||||
|
(
|
||||||
|
curl --trace-ascii "$tracefile" -s -L -o "$output" "$url"
|
||||||
|
) &
|
||||||
|
local curl_pid=$!
|
||||||
|
|
||||||
|
unbuffered_sed \
|
||||||
|
-e 'y/ACDEGHLNORTV/acdeghlnortv/' \
|
||||||
|
-e '/^0000: content-length:/p' \
|
||||||
|
-e '/^<= recv data/p' \
|
||||||
|
"$tracefile" | \
|
||||||
|
{
|
||||||
|
local length=0
|
||||||
|
local bytes=0
|
||||||
|
|
||||||
|
while IFS=" " read -r -a line; do
|
||||||
|
[ "${#line[@]}" -lt 2 ] && continue
|
||||||
|
local tag="${line[0]} ${line[1]}"
|
||||||
|
|
||||||
|
if [ "$tag" = "0000: content-length:" ]; then
|
||||||
|
length="${line[2]}"
|
||||||
|
length=$(echo "$length" | tr -d '\r')
|
||||||
|
bytes=0
|
||||||
|
elif [ "$tag" = "<= recv" ]; then
|
||||||
|
local size="${line[3]}"
|
||||||
|
bytes=$(( bytes + size ))
|
||||||
|
if [ "$length" -gt 0 ]; then
|
||||||
|
print_progress "$bytes" "$length"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
wait $curl_pid
|
||||||
|
local ret=$?
|
||||||
|
echo "" >&4
|
||||||
|
return $ret
|
||||||
|
}
|
||||||
|
|
||||||
|
download_and_install() {
|
||||||
|
print_message info "\n${MUTED}Installing ${NC}octopus ${MUTED}version: ${NC}$specific_version"
|
||||||
|
local tmp_dir="${TMPDIR:-/tmp}/octopus_install_$$"
|
||||||
|
mkdir -p "$tmp_dir"
|
||||||
|
|
||||||
|
if [[ "$os" == "windows" ]] || ! [ -t 2 ] || ! download_with_progress "$url" "$tmp_dir/$filename"; then
|
||||||
|
# Fallback to standard curl on Windows, non-TTY environments, or if custom progress fails
|
||||||
|
curl -# -L -o "$tmp_dir/$filename" "$url"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$os" = "linux" ]; then
|
||||||
|
tar -xzf "$tmp_dir/$filename" -C "$tmp_dir"
|
||||||
|
else
|
||||||
|
unzip -q "$tmp_dir/$filename" -d "$tmp_dir"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mv "$tmp_dir/octopus" "$INSTALL_DIR"
|
||||||
|
chmod 755 "${INSTALL_DIR}/octopus"
|
||||||
|
rm -rf "$tmp_dir"
|
||||||
|
}
|
||||||
|
|
||||||
|
install_from_binary() {
|
||||||
|
print_message info "\n${MUTED}Installing ${NC}octopus ${MUTED}from: ${NC}$binary_path"
|
||||||
|
cp "$binary_path" "${INSTALL_DIR}/octopus"
|
||||||
|
chmod 755 "${INSTALL_DIR}/octopus"
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ -n "$binary_path" ]; then
|
||||||
|
install_from_binary
|
||||||
|
else
|
||||||
|
check_version
|
||||||
|
download_and_install
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
add_to_path() {
|
||||||
|
local config_file=$1
|
||||||
|
local command=$2
|
||||||
|
|
||||||
|
if grep -Fxq "$command" "$config_file"; then
|
||||||
|
print_message info "Command already exists in $config_file, skipping write."
|
||||||
|
elif [[ -w $config_file ]]; then
|
||||||
|
echo -e "\n# octopus" >> "$config_file"
|
||||||
|
echo "$command" >> "$config_file"
|
||||||
|
print_message info "${MUTED}Successfully added ${NC}octopus ${MUTED}to \$PATH in ${NC}$config_file"
|
||||||
|
else
|
||||||
|
print_message warning "Manually add the directory to $config_file (or similar):"
|
||||||
|
print_message info " $command"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
XDG_CONFIG_HOME=${XDG_CONFIG_HOME:-$HOME/.config}
|
||||||
|
|
||||||
|
current_shell=$(basename "$SHELL")
|
||||||
|
case $current_shell in
|
||||||
|
fish)
|
||||||
|
config_files="$HOME/.config/fish/config.fish"
|
||||||
|
;;
|
||||||
|
zsh)
|
||||||
|
config_files="${ZDOTDIR:-$HOME}/.zshrc ${ZDOTDIR:-$HOME}/.zshenv $XDG_CONFIG_HOME/zsh/.zshrc $XDG_CONFIG_HOME/zsh/.zshenv"
|
||||||
|
;;
|
||||||
|
bash)
|
||||||
|
config_files="$HOME/.bashrc $HOME/.bash_profile $HOME/.profile $XDG_CONFIG_HOME/bash/.bashrc $XDG_CONFIG_HOME/bash/.bash_profile"
|
||||||
|
;;
|
||||||
|
ash)
|
||||||
|
config_files="$HOME/.ashrc $HOME/.profile /etc/profile"
|
||||||
|
;;
|
||||||
|
sh)
|
||||||
|
config_files="$HOME/.ashrc $HOME/.profile /etc/profile"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
# Default case if none of the above matches
|
||||||
|
config_files="$HOME/.bashrc $HOME/.bash_profile $XDG_CONFIG_HOME/bash/.bashrc $XDG_CONFIG_HOME/bash/.bash_profile"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [[ "$no_modify_path" != "true" ]]; then
|
||||||
|
config_file=""
|
||||||
|
for file in $config_files; do
|
||||||
|
if [[ -f $file ]]; then
|
||||||
|
config_file=$file
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -z $config_file ]]; then
|
||||||
|
print_message warning "No config file found for $current_shell. You may need to manually add to PATH:"
|
||||||
|
print_message info " export PATH=$INSTALL_DIR:\$PATH"
|
||||||
|
elif [[ ":$PATH:" != *":$INSTALL_DIR:"* ]]; then
|
||||||
|
case $current_shell in
|
||||||
|
fish)
|
||||||
|
add_to_path "$config_file" "fish_add_path $INSTALL_DIR"
|
||||||
|
;;
|
||||||
|
zsh)
|
||||||
|
add_to_path "$config_file" "export PATH=$INSTALL_DIR:\$PATH"
|
||||||
|
;;
|
||||||
|
bash)
|
||||||
|
add_to_path "$config_file" "export PATH=$INSTALL_DIR:\$PATH"
|
||||||
|
;;
|
||||||
|
ash)
|
||||||
|
add_to_path "$config_file" "export PATH=$INSTALL_DIR:\$PATH"
|
||||||
|
;;
|
||||||
|
sh)
|
||||||
|
add_to_path "$config_file" "export PATH=$INSTALL_DIR:\$PATH"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
export PATH=$INSTALL_DIR:$PATH
|
||||||
|
print_message warning "Manually add the directory to $config_file (or similar):"
|
||||||
|
print_message info " export PATH=$INSTALL_DIR:\$PATH"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "${GITHUB_ACTIONS-}" ] && [ "${GITHUB_ACTIONS}" == "true" ]; then
|
||||||
|
echo "$INSTALL_DIR" >> $GITHUB_PATH
|
||||||
|
print_message info "Added $INSTALL_DIR to \$GITHUB_PATH"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e ""
|
||||||
|
echo -e "\033[38;5;214m█▀▀█ █▀▀▀ ▀▀█▀▀ █▀▀█ █▀▀█ █ █ █▀▀▀${NC}"
|
||||||
|
echo -e "\033[38;5;172m█ █ █ █ █ █ █▀▀▀ █ █ ▀▀▀█${NC}"
|
||||||
|
echo -e "\033[38;5;130m▀▀▀▀ ▀▀▀▀ ▀ ▀▀▀▀ ▀ ▀▀▀▀ ▀▀▀▀${NC}"
|
||||||
|
echo -e ""
|
||||||
|
echo -e ""
|
||||||
|
echo -e "${MUTED}Octopus includes free models, to start:${NC}"
|
||||||
|
echo -e ""
|
||||||
|
echo -e "cd <project> ${MUTED}# Open directory${NC}"
|
||||||
|
echo -e "octopus ${MUTED}# Run command${NC}"
|
||||||
|
echo -e ""
|
||||||
|
echo -e "${MUTED}For more information visit ${NC}https://octopus.51zxtx.com/docs"
|
||||||
|
echo -e ""
|
||||||
|
echo -e ""
|
||||||
+201
@@ -0,0 +1,201 @@
|
|||||||
|
#Requires -Version 5.1
|
||||||
|
# Public release repository: http://octopus.51zxtx.com:3000/fourbroad/octopus-release
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Octopus installer for Windows.
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
Downloads and installs the Octopus CLI from Gitea Releases.
|
||||||
|
|
||||||
|
.PARAMETER Version
|
||||||
|
Install a specific version (e.g. 1.0.180). Defaults to latest.
|
||||||
|
|
||||||
|
.PARAMETER NoModifyPath
|
||||||
|
Do not add the install directory to the user PATH.
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
irm http://octopus.51zxtx.com:3000/fourbroad/octopus-release/raw/branch/dev/install.ps1 | iex
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
irm http://octopus.51zxtx.com:3000/fourbroad/octopus-release/raw/branch/dev/install.ps1 | iex; Install-Octopus -Version 0.1.3
|
||||||
|
#>
|
||||||
|
[CmdletBinding()]
|
||||||
|
param(
|
||||||
|
[string]$Version = "",
|
||||||
|
[switch]$NoModifyPath
|
||||||
|
)
|
||||||
|
|
||||||
|
Set-StrictMode -Version Latest
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
$APP = "octopus"
|
||||||
|
$REPO = "fourbroad/octopus-release"
|
||||||
|
$baseUrl = if ($env:OCTOPUS_DOWNLOAD_BASE) { $env:OCTOPUS_DOWNLOAD_BASE } else { "http://octopus.51zxtx.com:3000" }
|
||||||
|
$INSTALL_DIR = Join-Path $env:USERPROFILE ".octopus\bin"
|
||||||
|
|
||||||
|
function Write-Color([string]$Text, [string]$Color = "White") {
|
||||||
|
Write-Host $Text -ForegroundColor $Color
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-Arch {
|
||||||
|
$arch = $env:PROCESSOR_ARCHITECTURE
|
||||||
|
if ($arch -eq "AMD64") { return "x64" }
|
||||||
|
if ($arch -eq "ARM64") { return "arm64" }
|
||||||
|
throw "Unsupported architecture: $arch"
|
||||||
|
}
|
||||||
|
|
||||||
|
function Test-Avx2Support {
|
||||||
|
try {
|
||||||
|
Add-Type -MemberDefinition @"
|
||||||
|
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
|
||||||
|
public static extern bool IsProcessorFeaturePresent(int ProcessorFeature);
|
||||||
|
"@ -Name "Kernel32" -Namespace "Win32" -ErrorAction SilentlyContinue | Out-Null
|
||||||
|
# PF_AVX2_INSTRUCTIONS_AVAILABLE = 40
|
||||||
|
return [Win32.Kernel32]::IsProcessorFeaturePresent(40)
|
||||||
|
} catch {
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-LatestVersion {
|
||||||
|
# Resolve the latest version by following the /releases/latest redirect to
|
||||||
|
# /releases/tag/vX.Y.Z. This avoids the API, which is
|
||||||
|
# rate-limited to 60 requests/hour per IP.
|
||||||
|
$latestUrl = "$baseUrl/$REPO/releases/latest"
|
||||||
|
$location = $null
|
||||||
|
$request = [System.Net.HttpWebRequest]::Create($latestUrl)
|
||||||
|
$request.Method = "HEAD"
|
||||||
|
$request.AllowAutoRedirect = $false
|
||||||
|
$request.UserAgent = "octopus-installer"
|
||||||
|
try {
|
||||||
|
$response = $request.GetResponse()
|
||||||
|
$location = $response.Headers["Location"]
|
||||||
|
$response.Close()
|
||||||
|
} catch [System.Net.WebException] {
|
||||||
|
$resp = $_.Exception.Response
|
||||||
|
if ($null -ne $resp) {
|
||||||
|
$location = $resp.Headers["Location"]
|
||||||
|
$resp.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (-not $location) { return "" }
|
||||||
|
if ($location -match '/tag/v?([^/]+)/?$') {
|
||||||
|
return $Matches[1] -replace '^v', ''
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
function Install-Octopus {
|
||||||
|
$arch = Get-Arch
|
||||||
|
|
||||||
|
# Resolve version
|
||||||
|
if ($Version -ne "") {
|
||||||
|
$specificVersion = $Version -replace '^v', ''
|
||||||
|
# Verify release exists
|
||||||
|
$releaseUrl = "$baseUrl/$REPO/releases/tag/v$specificVersion"
|
||||||
|
try {
|
||||||
|
$null = Invoke-WebRequest -Uri $releaseUrl -Method Head -UseBasicParsing -ErrorAction Stop
|
||||||
|
} catch {
|
||||||
|
Write-Color "Error: Release v$specificVersion not found." "Red"
|
||||||
|
Write-Color "Available releases: $baseUrl/$REPO/releases" "DarkGray"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Write-Color "Fetching latest version..." "DarkGray"
|
||||||
|
$specificVersion = Get-LatestVersion
|
||||||
|
if (-not $specificVersion) {
|
||||||
|
Write-Color "Error: Failed to fetch latest version." "Red"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if already installed at this version
|
||||||
|
$existing = Join-Path $INSTALL_DIR "$APP.exe"
|
||||||
|
if (Test-Path $existing) {
|
||||||
|
try {
|
||||||
|
$installedVersion = & $existing --version 2>$null
|
||||||
|
if ($installedVersion -eq $specificVersion) {
|
||||||
|
Write-Color "Version $specificVersion already installed." "DarkGray"
|
||||||
|
exit 0
|
||||||
|
} else {
|
||||||
|
Write-Color "Installed version: $installedVersion" "DarkGray"
|
||||||
|
}
|
||||||
|
} catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
# Build filename
|
||||||
|
$target = "$APP-windows-$arch"
|
||||||
|
if ($arch -eq "x64" -and -not (Test-Avx2Support)) {
|
||||||
|
$target = "$APP-windows-$arch-baseline"
|
||||||
|
}
|
||||||
|
$filename = "$target.zip"
|
||||||
|
$downloadUrl = "$baseUrl/$REPO/releases/download/v$specificVersion/$filename"
|
||||||
|
|
||||||
|
Write-Color ""
|
||||||
|
Write-Color "Installing octopus version: $specificVersion" "DarkGray"
|
||||||
|
Write-Color "Downloading $filename ..." "DarkGray"
|
||||||
|
|
||||||
|
# Download
|
||||||
|
$tmpDir = Join-Path $env:TEMP "octopus_install_$PID"
|
||||||
|
New-Item -ItemType Directory -Path $tmpDir -Force | Out-Null
|
||||||
|
$zipPath = Join-Path $tmpDir $filename
|
||||||
|
|
||||||
|
try {
|
||||||
|
$ProgressPreference = "SilentlyContinue"
|
||||||
|
Invoke-WebRequest -Uri $downloadUrl -OutFile $zipPath -UseBasicParsing
|
||||||
|
} catch {
|
||||||
|
Write-Color "Error: Failed to download $downloadUrl" "Red"
|
||||||
|
Write-Color $_.Exception.Message "Red"
|
||||||
|
Remove-Item -Recurse -Force $tmpDir -ErrorAction SilentlyContinue
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Extract
|
||||||
|
Expand-Archive -Path $zipPath -DestinationPath $tmpDir -Force
|
||||||
|
|
||||||
|
# Install
|
||||||
|
New-Item -ItemType Directory -Path $INSTALL_DIR -Force | Out-Null
|
||||||
|
$exeSrc = Join-Path $tmpDir "$APP.exe"
|
||||||
|
if (-not (Test-Path $exeSrc)) {
|
||||||
|
Write-Color "Error: $APP.exe not found in archive." "Red"
|
||||||
|
Remove-Item -Recurse -Force $tmpDir -ErrorAction SilentlyContinue
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
Copy-Item -Path $exeSrc -Destination (Join-Path $INSTALL_DIR "$APP.exe") -Force
|
||||||
|
Remove-Item -Recurse -Force $tmpDir -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
# Add to PATH
|
||||||
|
if (-not $NoModifyPath) {
|
||||||
|
$userPath = [Environment]::GetEnvironmentVariable("PATH", "User")
|
||||||
|
if ($userPath -notlike "*$INSTALL_DIR*") {
|
||||||
|
[Environment]::SetEnvironmentVariable("PATH", "$INSTALL_DIR;$userPath", "User")
|
||||||
|
Write-Color "Added $INSTALL_DIR to user PATH." "DarkGray"
|
||||||
|
Write-Color "Restart your terminal for PATH changes to take effect." "Yellow"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# CI Actions support (GitHub/Gitea)
|
||||||
|
if ($env:GITHUB_ACTIONS -eq "true" -and $env:GITHUB_PATH) {
|
||||||
|
Add-Content -Path $env:GITHUB_PATH -Value $INSTALL_DIR
|
||||||
|
Write-Color "Added $INSTALL_DIR to GITHUB_PATH." "DarkGray"
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host " ___ _" -ForegroundColor DarkYellow
|
||||||
|
Write-Host " / _ \ ___| |_ ___ _ __ _ _ ___" -ForegroundColor DarkYellow
|
||||||
|
Write-Host "| | | |/ __| __/ _ \| '_ \| | | / __|" -ForegroundColor Yellow
|
||||||
|
Write-Host "| |_| | (__| || (_) | |_) | |_| \__ \" -ForegroundColor Yellow
|
||||||
|
Write-Host " \___/ \___|\__\___/| .__/ \__,_|___/" -ForegroundColor White
|
||||||
|
Write-Host " |_|" -ForegroundColor White
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Octopus includes free models, to start:" -ForegroundColor DarkGray
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host " cd <project> " -NoNewline; Write-Host "# Open directory" -ForegroundColor DarkGray
|
||||||
|
Write-Host " octopus " -NoNewline; Write-Host "# Run command" -ForegroundColor DarkGray
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "For more information visit " -NoNewline -ForegroundColor DarkGray
|
||||||
|
Write-Host "https://octopus.51zxtx.com/docs"
|
||||||
|
Write-Host ""
|
||||||
|
}
|
||||||
|
|
||||||
|
Install-Octopus
|
||||||
Reference in New Issue
Block a user