Files
herolib/debug.logs
Mahmoud-Emad 9069816db1 feat: implement full heroprompt workspace management
- Add create, save, get, list, and delete for workspaces
- Enable adding and removing files/dirs by path or name
- Integrate codewalker for recursive file discovery
- Make workspaces stateful with created/updated timestamps
- Update example to demonstrate new lifecycle methods
2025-08-18 09:51:16 +03:00

1522 lines
44 KiB
Plaintext

───────────────────────────────(mahmoud@Mahmouds-Laptop:s142)─┐
└─(08:55:05 on development_codewalker ✖ ✹)──> /Users/mahmoud/code/github/freeflowuniverse/herolib/examples/develop/heroprompt/heroprompt_example.vsh
<user_instructions>
Using the selected files, i want you to get all print statments
</user_instructions>
<file_map>
/Users/mahmoud/code/github/freeflowuniverse/herolib
# Selected Files: 21 | Total Content: 40967 chars | Extensions: md(2), yml(2), sh(14), dockerfile(1), gitignore(1), vsh(1)
└── docker
├── docker_ubuntu_install.sh *
├── herolib
│ └── herolib
│ ├── .gitignore *
│ ├── Dockerfile *
│ ├── README.md *
│ ├── build.sh *
│ ├── debug.sh *
│ ├── docker-compose.yml *
│ ├── export.sh *
│ ├── shell.sh *
│ ├── ssh.sh *
│ ├── ssh_init.sh *
│ ├── start.sh *
│ └── scripts
│ └── scripts
│ ├── cleanup.sh *
│ ├── install_herolib.vsh *
│ ├── install_v.sh *
│ ├── install_vscode.sh *
│ └── ourinit.sh *
└── postgresql
└── postgresql
├── docker-compose.yml *
├── readme.md *
└── start.sh *
/Users/mahmoud/code/github/freeflowuniverse/herolib/docker/docker_ubuntu_install.sh *
</file_map>
<file_contents>
/Users/mahmoud/code/github/freeflowuniverse/herolib/docker/docker_ubuntu_install.sh
```sh
#!/bin/bash
# Exit immediately if a command exits with a non-zero status
set -e
# Function to display an error message and exit
error_exit() {
echo "Error: $1" >&2
exit 1
}
# Update package index and upgrade system
echo "Updating system packages..."
sudo apt update && sudo apt upgrade -y || error_exit "Failed to update system packages."
# Install required packages for repository setup
echo "Installing prerequisites..."
sudo apt install -y ca-certificates curl gnupg || error_exit "Failed to install prerequisites."
# Create directory for Docker GPG key
echo "Setting up GPG keyring..."
sudo mkdir -p /etc/apt/keyrings || error_exit "Failed to create keyring directory."
# Add Docker's official GPG key
DOCKER_GPG_KEY=/etc/apt/keyrings/docker.gpg
echo "Adding Docker GPG key..."
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o $DOCKER_GPG_KEY || error_exit "Failed to add Docker GPG key."
sudo chmod a+r $DOCKER_GPG_KEY
# Set up Docker repository
echo "Adding Docker repository..."
REPO_ENTRY="deb [arch=$(dpkg --print-architecture) signed-by=$DOCKER_GPG_KEY] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
if ! grep -Fxq "$REPO_ENTRY" /etc/apt/sources.list.d/docker.list; then
echo "$REPO_ENTRY" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null || error_exit "Failed to add Docker repository."
fi
# Update package index
echo "Updating package index..."
sudo apt update || error_exit "Failed to update package index."
# Install Docker Engine, CLI, and dependencies
echo "Installing Docker Engine and dependencies..."
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin || error_exit "Failed to install Docker packages."
# Verify Docker installation
echo "Verifying Docker installation..."
if ! docker --version; then
error_exit "Docker installation verification failed."
fi
# Run a test container
echo "Running Docker test container..."
if ! sudo docker run --rm hello-world; then
error_exit "Docker test container failed to run."
fi
# Add current user to Docker group (if not already added)
echo "Configuring Docker group..."
if ! groups $USER | grep -q '\bdocker\b'; then
sudo usermod -aG docker $USER || error_exit "Failed to add user to Docker group."
echo "User added to Docker group. Please log out and back in for this change to take effect."
else
echo "User is already in the Docker group."
fi
# Enable Docker service on boot
echo "Enabling Docker service on boot..."
sudo systemctl enable docker || error_exit "Failed to enable Docker service."
# Success message
echo "Docker installation completed successfully!"
```
/Users/mahmoud/code/github/freeflowuniverse/herolib/docker/docker_ubuntu_install.sh
```sh
#!/bin/bash
# Exit immediately if a command exits with a non-zero status
set -e
# Function to display an error message and exit
error_exit() {
echo "Error: $1" >&2
exit 1
}
# Update package index and upgrade system
echo "Updating system packages..."
sudo apt update && sudo apt upgrade -y || error_exit "Failed to update system packages."
# Install required packages for repository setup
echo "Installing prerequisites..."
sudo apt install -y ca-certificates curl gnupg || error_exit "Failed to install prerequisites."
# Create directory for Docker GPG key
echo "Setting up GPG keyring..."
sudo mkdir -p /etc/apt/keyrings || error_exit "Failed to create keyring directory."
# Add Docker's official GPG key
DOCKER_GPG_KEY=/etc/apt/keyrings/docker.gpg
echo "Adding Docker GPG key..."
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o $DOCKER_GPG_KEY || error_exit "Failed to add Docker GPG key."
sudo chmod a+r $DOCKER_GPG_KEY
# Set up Docker repository
echo "Adding Docker repository..."
REPO_ENTRY="deb [arch=$(dpkg --print-architecture) signed-by=$DOCKER_GPG_KEY] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
if ! grep -Fxq "$REPO_ENTRY" /etc/apt/sources.list.d/docker.list; then
echo "$REPO_ENTRY" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null || error_exit "Failed to add Docker repository."
fi
# Update package index
echo "Updating package index..."
sudo apt update || error_exit "Failed to update package index."
# Install Docker Engine, CLI, and dependencies
echo "Installing Docker Engine and dependencies..."
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin || error_exit "Failed to install Docker packages."
# Verify Docker installation
echo "Verifying Docker installation..."
if ! docker --version; then
error_exit "Docker installation verification failed."
fi
# Run a test container
echo "Running Docker test container..."
if ! sudo docker run --rm hello-world; then
error_exit "Docker test container failed to run."
fi
# Add current user to Docker group (if not already added)
echo "Configuring Docker group..."
if ! groups $USER | grep -q '\bdocker\b'; then
sudo usermod -aG docker $USER || error_exit "Failed to add user to Docker group."
echo "User added to Docker group. Please log out and back in for this change to take effect."
else
echo "User is already in the Docker group."
fi
# Enable Docker service on boot
echo "Enabling Docker service on boot..."
sudo systemctl enable docker || error_exit "Failed to enable Docker service."
# Success message
echo "Docker installation completed successfully!"
```
/Users/mahmoud/code/github/freeflowuniverse/herolib/docker/herolib/Dockerfile
```dockerfile
# Use Ubuntu 24.04 as the base image
FROM ubuntu:24.04
# Set the working directory
WORKDIR /root
# Copy local installation scripts into the container
COPY scripts/install_v.sh /tmp/install_v.sh
COPY scripts/install_herolib.vsh /tmp/install_herolib.vsh
COPY scripts/install_vscode.sh /tmp/install_vscode.sh
COPY scripts/ourinit.sh /usr/local/bin/
# Make the scripts executable
RUN chmod +x /tmp/install_v.sh /tmp/install_herolib.vsh
RUN apt-get update && apt-get install -y \
curl bash sudo mc wget tmux htop openssh-server
RUN bash /tmp/install_v.sh
RUN yes y | bash /tmp/install_v.sh --analyzer
RUN bash /tmp/install_vscode.sh
#SSH
RUN mkdir -p /var/run/sshd && \
echo 'PermitRootLogin yes' >> /etc/ssh/sshd_config && \
echo 'PasswordAuthentication no' >> /etc/ssh/sshd_config && \
chown -R root:root /root/.ssh && \
chmod -R 700 /root/.ssh/ && \
touch /root/.ssh/authorized_keys \
chmod 600 /root/.ssh/authorized_keys && \
service ssh start
RUN /tmp/install_herolib.vsh && \
apt-get clean && \
echo "PS1='HERO: \w \$ '" >> ~/.bashrc \
rm -rf /var/lib/apt/lists/*
ENTRYPOINT ["/bin/bash"]
CMD ["/bin/bash"]
```
/Users/mahmoud/code/github/freeflowuniverse/herolib/docker/herolib/README.md
```md
# HeroLib Docker Environment
This directory contains the Docker configuration and scripts for setting up and managing the HeroLib development environment. The environment includes a containerized setup with VSCode server, SSH access, and PostgreSQL database.
## Key Components
### Docker Configuration Files
- `Dockerfile`: Defines the container image based on Ubuntu 24.04, installing necessary dependencies including:
- V language and its analyzer
- VSCode server
- SSH server
- Development tools (curl, tmux, htop, etc.)
- HeroLib installation
- `docker-compose.yml`: Orchestrates the multi-container setup with:
- PostgreSQL database service
- HeroLib development environment
- Port mappings for various services
- Volume mounting for code persistence
## Scripts
### Container Management
- `shell.sh`: Interactive shell access script that:
- Checks if the container is running
- Starts the container if it's stopped
- Verifies port accessibility (default: 4000)
- Provides interactive bash session inside the container
- `debug.sh`: Launches the container in debug mode with:
- Interactive terminal
- Volume mounts for scripts and code
- Port mappings for various services (4000-4379)
- Custom entrypoint using ourinit.sh
- `export.sh`: Creates a compressed export of the container:
- Stops any running instances
- Launches a temporary container
- Runs cleanup script
- Exports and compresses the container to ~/Downloads/herolib.tar.gz
### SSH Access
- `ssh.sh`: Simple SSH connection script to access the container via port 4022
- `ssh_init.sh`: Configures SSH access by:
- Collecting public keys from local ~/.ssh directory
- Setting up authorized_keys in the container
- Installing and configuring SSH server
- Setting appropriate permissions
- Enabling root login with key authentication
### Internal Scripts (in scripts/)
- `cleanup.sh`: Comprehensive system cleanup script that:
- Removes unused packages and dependencies
- Cleans APT cache
- Removes old log files
- Clears temporary files and caches
- Performs system maintenance tasks
- `install_herolib.vsh`: V script for HeroLib installation:
- Sets up necessary symlinks
- Configures V module structure
- Adds useful shell aliases (e.g., vtest)
- `ourinit.sh`: Container initialization script that:
- Starts Redis server in daemon mode
- Launches VSCode server in a tmux session
- Starts SSH service
- Provides interactive bash shell
## Port Mappings
- 4000:3000 - Main application port
- 4022:22 - SSH access
- 4100:8100 - Additional service port
- 4101:8101 - Additional service port
- 4102:8102 - Additional service port
- 4379:6379 - Redis port
## Usage
1. Build and start the environment:
```bash
docker compose up -d
```
2. Access the container shell:
```bash
./shell.sh
```
3. Connect via SSH:
```bash
./ssh.sh
```
4. Debug mode (interactive with direct terminal):
```bash
./debug.sh
```
5. Create container export:
```bash
./export.sh
```
## Development
The environment mounts your local `~/code` directory to `/root/code` inside the container, allowing for seamless development between host and container. The PostgreSQL database persists data using a named volume.
```
/Users/mahmoud/code/github/freeflowuniverse/herolib/docker/herolib/build.sh
```sh
#!/bin/bash -e
# Get the directory where the script is located
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd "$SCRIPT_DIR"
# Copy installation files
cp ../../install_v.sh ./scripts/install_v.sh
cp ../../install_herolib.vsh ./scripts/install_herolib.vsh
# Docker image and container names
DOCKER_IMAGE_NAME="herolib"
DEBUG_CONTAINER_NAME="herolib"
function cleanup {
if docker ps -aq -f name="$DEBUG_CONTAINER_NAME" &>/dev/null; then
echo "Cleaning up leftover debug container..."
docker rm -f "$DEBUG_CONTAINER_NAME" &>/dev/null || true
fi
}
trap cleanup EXIT
# Attempt to build the Docker image
BUILD_LOG=$(mktemp)
set +e
docker build --name herolib --progress=plain -t "$DOCKER_IMAGE_NAME" .
BUILD_EXIT_CODE=$?
set -e
# Handle build failure
if [ $BUILD_EXIT_CODE -ne 0 ]; then
echo -e "\\n[ERROR] Docker build failed.\n"
echo -e "remove the part which didn't build in the Dockerfile, the run again and to debug do:"
echo docker run --name herolib -it --entrypoint=/bin/bash "herolib"
exit $BUILD_EXIT_CODE
else
echo -e "\\n[INFO] Docker build completed successfully."
fi
```
/Users/mahmoud/code/github/freeflowuniverse/herolib/docker/herolib/debug.sh
```sh
#!/bin/bash -ex
# Get the directory where the script is located
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"
# Remove any existing container named 'debug' (ignore errors)
docker rm -f herolib > /dev/null 2>&1
docker run --name herolib -it \
--entrypoint="/usr/local/bin/ourinit.sh" \
-v "${SCRIPT_DIR}/scripts:/scripts" \
-v "$HOME/code:/root/code" \
-p 4100:8100 \
-p 4101:8101 \
-p 4102:8102 \
-p 4379:6379 \
-p 4022:22 \
-p 4000:3000 herolib
```
/Users/mahmoud/code/github/freeflowuniverse/herolib/docker/herolib/docker-compose.yml
```yml
services:
postgres:
image: postgres:latest
container_name: postgres_service
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: planetfirst
POSTGRES_DB: mydb
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
herolib:
build:
context: .
dockerfile: Dockerfile
image: herolib:latest
container_name: herolib
volumes:
- ~/code:/root/code
stdin_open: true
tty: true
ports:
- "4100:8100"
- "4101:8101"
- "4102:8102"
- "4379:6379"
- "4000:3000"
- "4022:22"
command: ["/usr/local/bin/ourinit.sh"]
volumes:
postgres_data:
```
/Users/mahmoud/code/github/freeflowuniverse/herolib/docker/herolib/export.sh
```sh
#!/bin/bash -ex
# Get the directory where the script is located
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"
docker compose down
docker rm herolib --force
# Start the container in detached mode (-d)
docker run --name herolib \
--entrypoint="/bin/bash" \
-v "${SCRIPT_DIR}/scripts:/scripts" \
-p 4022:22 \
-d herolib -c "while true; do sleep 1; done"
docker exec -it herolib /scripts/cleanup.sh
# Detect the OS
detect_os() {
if [[ "$(uname)" == "Darwin" ]]; then
echo "osx"
elif [[ -f /etc/os-release ]]; then
. /etc/os-release
if [[ "$ID" == "ubuntu" ]]; then
echo "ubuntu"
fi
else
echo "unknown"
fi
}
OS=$(detect_os)
if [[ "$OS" == "osx" ]]; then
echo "Running on macOS..."
docker export herolib | gzip > "${HOME}/Downloads/herolib.tar.gz"
echo "Docker image exported to ${HOME}/Downloads/herolib.tar.gz"
elif [[ "$OS" == "ubuntu" ]]; then
echo "Running on Ubuntu..."
export TEMP_TAR="/tmp/herolib.tar"
# Export the Docker container to a tar file
docker export herolib > "$TEMP_TAR"
echo "Docker container exported to $TEMP_TAR"
# Import the tar file back as a single-layer image
docker import "$TEMP_TAR" herolib:single-layer
echo "Docker image imported as single-layer: herolib:single-layer"
# Log in to Docker Hub and push the image
docker login --username despiegk
docker tag herolib:single-layer despiegk/herolib:single-layer
docker push despiegk/herolib:single-layer
echo "Docker image pushed to Docker Hub as despiegk/herolib:single-layer"
# Optionally remove the tar file after importing
rm -f "$TEMP_TAR"
echo "Temporary file $TEMP_TAR removed"
else
echo "Unsupported OS detected. Exiting."
exit 1
fi
docker kill herolib
# Test the pushed Docker image locally
echo "Testing the Docker image locally..."
TEST_CONTAINER_NAME="test_herolib_container"
docker pull despiegk/herolib:single-layer
if [[ $? -ne 0 ]]; then
echo "Failed to pull the Docker image from Docker Hub. Exiting."
exit 1
fi
docker run --name "$TEST_CONTAINER_NAME" -d despiegk/herolib:single-layer
if [[ $? -ne 0 ]]; then
echo "Failed to run the Docker image as a container. Exiting."
exit 1
fi
docker ps | grep "$TEST_CONTAINER_NAME"
if [[ $? -eq 0 ]]; then
echo "Container $TEST_CONTAINER_NAME is running successfully."
else
echo "Container $TEST_CONTAINER_NAME is not running. Check the logs for details."
fi
```
/Users/mahmoud/code/github/freeflowuniverse/herolib/docker/herolib/scripts/cleanup.sh
```sh
#!/bin/bash -e
# Log file for cleanup operations
LOG_FILE="/var/log/cleanup_script.log"
exec > >(tee -a $LOG_FILE) 2>&1
# Function to check and execute commands safely
safe_run() {
echo "Running: $*"
eval "$*"
}
# Update package lists
safe_run "apt update"
# Remove unused packages and dependencies
safe_run "apt autoremove -y"
# Clean up APT cache
safe_run "apt clean"
safe_run "apt autoclean"
# Remove old kernels (keeping the current and latest one)
safe_run "apt remove --purge -y $(dpkg --list | grep linux-image | awk '{print $2}' | grep -v $(uname -r | sed 's/[^-]*-[^-]*-//') | sort | head -n -1)"
# Clear systemd journal logs, keeping only the latest 7 days
safe_run "journalctl --vacuum-time=7d"
# Remove orphaned packages
safe_run "deborphan | xargs apt-get -y remove --purge"
# Clear thumbnail cache
safe_run "rm -rf ~/.cache/thumbnails/*"
# Remove old log files
safe_run "find /var/log -type f -name '*.log' -delete"
# Clear temporary files
safe_run "rm -rf /tmp/*"
safe_run "rm -rf /var/tmp/*"
# Remove user-specific temporary files (adjust for other users as needed)
safe_run "rm -rf ~/.cache/*"
# Remove .pyc files
safe_run "find / -type f -name '*.pyc' -delete"
# Remove unused snap versions
#safe_run "snap list --all | awk '/disabled/{print $1, $3}' | while read snapname revision; do snap remove "$snapname" --revision="$revision"; done"
# Clear trash for all users
safe_run "rm -rf /home/*/.local/share/Trash/*/**"
safe_run "rm -rf /root/.local/share/Trash/*/**"
# Free up swap space
#safe_run "swapoff -a && swapon -a"
# Update GRUB (in case old kernels were removed)
#safe_run "update-grub"
# # Final system update and upgrade
# safe_run "apt upgrade -y"
# Report completion
echo "System cleanup completed successfully."
```
/Users/mahmoud/code/github/freeflowuniverse/herolib/docker/herolib/scripts/install_herolib.vsh
```vsh
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
import os
import flag
fn addtoscript(tofind string, toadd string) ! {
home_dir := os.home_dir()
mut rc_file := '${home_dir}/.zshrc'
if !os.exists(rc_file) {
rc_file = '${home_dir}/.bashrc'
if !os.exists(rc_file) {
return error('No .zshrc or .bashrc found in home directory')
}
}
// Read current content
mut content := os.read_file(rc_file)!
// Remove existing alias if present
lines := content.split('\n')
mut new_lines := []string{}
mut prev_is_emtpy := false
for line in lines {
if prev_is_emtpy {
if line.trim_space() == '' {
continue
} else {
prev_is_emtpy = false
}
}
if line.trim_space() == '' {
prev_is_emtpy = true
}
if !line.contains(tofind) {
new_lines << line
}
}
new_lines << toadd
new_lines << ''
// Write back to file
new_content := new_lines.join('\n')
os.write_file(rc_file, new_content)!
}
vroot := @VROOT
abs_dir_of_script := dir(@FILE)
// Reset symlinks if requested
println('Resetting all symlinks...')
os.rm('${os.home_dir()}/.vmodules/freeflowuniverse/herolib') or {}
// Create necessary directories
os.mkdir_all('${os.home_dir()}/.vmodules/freeflowuniverse') or {
panic('Failed to create directory ~/.vmodules/freeflowuniverse: ${err}')
}
// Create new symlinks
os.symlink('${abs_dir_of_script}/lib', '${os.home_dir()}/.vmodules/freeflowuniverse/herolib') or {
panic('Failed to create herolib symlink: ${err}')
}
println('Herolib installation completed successfully!')
// Add vtest alias
addtoscript('alias vtest=', "alias vtest='v -stats -enable-globals -n -w -cg -gc none -cc tcc test' ") or {
eprintln('Failed to add vtest alias: ${err}')
}
println('Added vtest alias to shell configuration')
```
/Users/mahmoud/code/github/freeflowuniverse/herolib/docker/herolib/scripts/install_v.sh
```sh
#!/bin/bash -e
# Help function
print_help() {
echo "V & HeroLib Installer Script"
echo
echo "Usage: $0 [options]"
echo
echo "Options:"
echo " -h, --help Show this help message"
echo " --reset Force reinstallation of V"
echo " --remove Remove V installation and exit"
echo " --analyzer Install/update v-analyzer"
echo " --herolib Install our herolib"
echo
echo "Examples:"
echo " $0"
echo " $0 --reset "
echo " $0 --remove "
echo " $0 --analyzer "
echo " $0 --herolib "
echo " $0 --reset --analyzer # Fresh install of both"
echo
}
# Parse arguments
RESET=false
REMOVE=false
INSTALL_ANALYZER=false
HEROLIB=false
for arg in "$@"; do
case $arg in
-h|--help)
print_help
exit 0
;;
--reset)
RESET=true
;;
--remove)
REMOVE=true
;;
--herolib)
HEROLIB=true
;;
--analyzer)
INSTALL_ANALYZER=true
;;
*)
echo "Unknown option: $arg"
echo "Use -h or --help to see available options"
exit 1
;;
esac
done
# Function to check if command exists
command_exists() {
command -v "$1" >/dev/null 2>&1
}
export DIR_BASE="$HOME"
export DIR_BUILD="/tmp"
export DIR_CODE="$DIR_BASE/code"
export DIR_CODE_V="$DIR_BASE/_code"
function sshknownkeysadd {
mkdir -p ~/.ssh
touch ~/.ssh/known_hosts
if ! grep github.com ~/.ssh/known_hosts > /dev/null
then
ssh-keyscan github.com >> ~/.ssh/known_hosts
fi
if ! grep git.threefold.info ~/.ssh/known_hosts > /dev/null
then
ssh-keyscan git.threefold.info >> ~/.ssh/known_hosts
fi
git config --global pull.rebase false
}
function package_check_install {
local command_name="$1"
if command -v "$command_name" >/dev/null 2>&1; then
echo "command '$command_name' is already installed."
else
package_install '$command_name'
fi
}
function package_install {
local command_name="$1"
if [[ "${OSNAME}" == "ubuntu" ]]; then
apt -o Dpkg::Options::="--force-confold" -o Dpkg::Options::="--force-confdef" install $1 -q -y --allow-downgrades --allow-remove-essential
elif [[ "${OSNAME}" == "darwin"* ]]; then
brew install $command_name
elif [[ "${OSNAME}" == "alpine"* ]]; then
apk add $command_name
elif [[ "${OSNAME}" == "arch"* ]]; then
pacman --noconfirm -Su $command_name
else
echo "platform : ${OSNAME} not supported"
exit 1
fi
}
is_github_actions() {
[ -d "/home/runner" ] || [ -d "$HOME/runner" ]
}
function myplatform {
if [[ "${OSTYPE}" == "darwin"* ]]; then
export OSNAME='darwin'
elif [ -e /etc/os-release ]; then
# Read the ID field from the /etc/os-release file
export OSNAME=$(grep '^ID=' /etc/os-release | cut -d= -f2)
if [ "${os_id,,}" == "ubuntu" ]; then
export OSNAME="ubuntu"
fi
if [ "${OSNAME}" == "archarm" ]; then
export OSNAME="arch"
fi
if [ "${OSNAME}" == "debian" ]; then
export OSNAME="ubuntu"
fi
else
echo "Unable to determine the operating system."
exit 1
fi
# if [ "$(uname -m)" == "x86_64" ]; then
# echo "This system is running a 64-bit processor."
# else
# echo "This system is not running a 64-bit processor."
# exit 1
# fi
}
myplatform
function os_update {
echo ' - os update'
if [[ "${OSNAME}" == "ubuntu" ]]; then
if is_github_actions; then
echo "github actions"
else
rm -f /var/lib/apt/lists/lock
rm -f /var/cache/apt/archives/lock
rm -f /var/lib/dpkg/lock*
fi
export TERM=xterm
export DEBIAN_FRONTEND=noninteractive
dpkg --configure -a
apt update -y
if is_github_actions; then
echo "** IN GITHUB ACTIONS, DON'T DO UPDATE"
else
set +e
echo "** UPDATE"
apt-mark hold grub-efi-amd64-signed
set -e
apt upgrade -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" --force-yes
apt autoremove -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" --force-yes
fi
#apt install apt-transport-https ca-certificates curl software-properties-common -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" --force-yes
package_install "apt-transport-https ca-certificates curl wget software-properties-common tmux"
package_install "rclone rsync mc redis-server screen net-tools git dnsutils htop ca-certificates screen lsb-release binutils pkg-config"
elif [[ "${OSNAME}" == "darwin"* ]]; then
if command -v brew >/dev/null 2>&1; then
echo ' - homebrew installed'
else
export NONINTERACTIVE=1
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
unset NONINTERACTIVE
fi
set +e
brew install mc redis curl tmux screen htop wget rclone tcc
set -e
elif [[ "${OSNAME}" == "alpine"* ]]; then
apk update screen git htop tmux
apk add mc curl rsync htop redis bash bash-completion screen git rclone
sed -i 's#/bin/ash#/bin/bash#g' /etc/passwd
elif [[ "${OSNAME}" == "arch"* ]]; then
pacman -Syy --noconfirm
pacman -Syu --noconfirm
pacman -Su --noconfirm arch-install-scripts gcc mc git tmux curl htop redis wget screen net-tools git sudo htop ca-certificates lsb-release screen rclone
# Check if builduser exists, create if not
if ! id -u builduser > /dev/null 2>&1; then
useradd -m builduser
echo "builduser:$(openssl rand -base64 32 | sha256sum | base64 | head -c 32)" | chpasswd
echo 'builduser ALL=(ALL) NOPASSWD: ALL' | tee /etc/sudoers.d/builduser
fi
if [[ -n "${DEBUG}" ]]; then
execute_with_marker "paru_install" paru_install
fi
fi
echo ' - os update done'
}
function hero_lib_pull {
pushd $DIR_CODE/github/freeflowuniverse/herolib 2>&1 >> /dev/null
if [[ $(git status -s) ]]; then
echo "There are uncommitted changes in the Git repository herolib."
return 1
fi
git pull
popd 2>&1 >> /dev/null
}
function hero_lib_get {
mkdir -p $DIR_CODE/github/freeflowuniverse
if [[ -d "$DIR_CODE/github/freeflowuniverse/herolib" ]]
then
hero_lib_pull
else
pushd $DIR_CODE/github/freeflowuniverse 2>&1 >> /dev/null
git clone --depth 1 --no-single-branch https://github.com/freeflowuniverse/herolib.git
popd 2>&1 >> /dev/null
fi
}
function install_secp256k1 {
echo "Installing secp256k1..."
if [[ "${OSNAME}" == "darwin"* ]]; then
brew install secp256k1
elif [[ "${OSNAME}" == "ubuntu" ]]; then
# Install build dependencies
apt-get install -y build-essential wget autoconf libtool
# Download and extract secp256k1
cd "${DIR_BUILD}"
wget https://github.com/bitcoin-core/secp256k1/archive/refs/tags/v0.3.2.tar.gz
tar -xvf v0.3.2.tar.gz
# Build and install
cd secp256k1-0.3.2/
./autogen.sh
./configure
make -j 5
make install
# Cleanup
cd ..
rm -rf secp256k1-0.3.2 v0.3.2.tar.gz
else
echo "secp256k1 installation not implemented for ${OSNAME}"
exit 1
fi
echo "secp256k1 installation complete!"
}
remove_all() {
echo "Removing V installation..."
# Set reset to true to use existing reset functionality
RESET=true
# Call reset functionality
sudo rm -rf ~/code/v
sudo rm -rf ~/_code/v
sudo rm -rf ~/.config/v-analyzer
if command_exists v; then
echo "Removing V from system..."
sudo rm -f $(which v)
fi
if command_exists v-analyzer; then
echo "Removing v-analyzer from system..."
sudo rm -f $(which v-analyzer)
fi
# Remove v-analyzer path from rc files
for RC_FILE in ~/.zshrc ~/.bashrc; do
if [ -f "$RC_FILE" ]; then
echo "Cleaning up $RC_FILE..."
# Create a temporary file
TMP_FILE=$(mktemp)
# Remove lines containing v-analyzer/bin path
sed '/v-analyzer\/bin/d' "$RC_FILE" > "$TMP_FILE"
# Remove empty lines at the end of file
sed -i.bak -e :a -e '/^\n*$/{$d;N;ba' -e '}' "$TMP_FILE"
# Replace original file
mv "$TMP_FILE" "$RC_FILE"
echo "Cleaned up $RC_FILE"
fi
done
echo "V removal complete"
}
# Function to check if a service is running and start it if needed
check_and_start_redis() {
# Normal service management for non-container environments
if [[ "${OSNAME}" == "ubuntu" ]] || [[ "${OSNAME}" == "debian" ]]; then
# Check if running inside a container
if grep -q "/docker/" /proc/1/cgroup || [ ! -d "/run/systemd/system" ]; then
echo "Running inside a container. Starting redis directly."
if pgrep redis-server > /dev/null; then
echo "redis is already running."
else
echo "redis is not running. Starting it in the background..."
redis-server --daemonize yes
if pgrep redis-server > /dev/null; then
echo "redis started successfully."
else
echo "Failed to start redis. Please check logs for details."
exit 1
fi
fi
return
fi
if systemctl is-active --quiet "redis"; then
echo "redis is already running."
else
echo "redis is not running. Starting it..."
sudo systemctl start "redis"
if systemctl is-active --quiet "redis"; then
echo "redis started successfully."
else
echo "Failed to start redis. Please check logs for details."
exit 1
fi
fi
elif [[ "${OSNAME}" == "darwin"* ]]; then
if brew services list | grep -q "^redis.*started"; then
echo "redis is already running."
else
echo "redis is not running. Starting it..."
brew services start redis
fi
elif [[ "${OSNAME}" == "alpine"* ]]; then
if rc-service "redis" status | grep -q "running"; then
echo "redis is already running."
else
echo "redis is not running. Starting it..."
rc-service "redis" start
fi
elif [[ "${OSNAME}" == "arch"* ]]; then
if systemctl is-active --quiet "redis"; then
echo "redis is already running."
else
echo "redis is not running. Starting it..."
sudo systemctl start "redis"
fi
else
echo "Service management for redis is not implemented for platform: $OSNAME"
exit 1
fi
}
# Handle remove if requested
if [ "$REMOVE" = true ]; then
remove_all
exit 0
fi
# Handle reset if requested
if [ "$RESET" = true ]; then
remove_all
echo "Reset complete"
fi
# Create code directory if it doesn't exist
mkdir -p ~/code
# Check if v needs to be installed
if [ "$RESET" = true ] || ! command_exists v; then
os_update
sshknownkeysadd
# Install secp256k1
install_secp256k1
# Only clone and install if directory doesn't exist
if [ ! -d ~/code/v ]; then
echo "Installing V..."
mkdir -p ~/_code
cd ~/_code
git clone --depth=1 https://github.com/vlang/v
cd v
make
sudo ./v symlink
fi
# Verify v is in path
if ! command_exists v; then
echo "Error: V installation failed or not in PATH"
echo "Please ensure ~/code/v is in your PATH"
exit 1
fi
echo "V installation successful!"
fi
# Install v-analyzer if requested
if [ "$INSTALL_ANALYZER" = true ]; then
echo "Installing v-analyzer..."
v download -RD https://raw.githubusercontent.com/vlang/v-analyzer/main/install.vsh
# Check if v-analyzer bin directory exists
if [ ! -d "$HOME/.config/v-analyzer/bin" ]; then
echo "Error: v-analyzer bin directory not found at $HOME/.config/v-analyzer/bin"
echo "Please ensure v-analyzer was installed correctly"
exit 1
fi
echo "v-analyzer installation successful!"
fi
# Add v-analyzer to PATH if installed
if [ -d "$HOME/.config/v-analyzer/bin" ]; then
V_ANALYZER_PATH='export PATH="$PATH:$HOME/.config/v-analyzer/bin"'
# Function to add path to rc file if not present
add_to_rc() {
local RC_FILE="$1"
if [ -f "$RC_FILE" ]; then
if ! grep -q "v-analyzer/bin" "$RC_FILE"; then
echo "" >> "$RC_FILE"
echo "$V_ANALYZER_PATH" >> "$RC_FILE"
echo "Added v-analyzer to $RC_FILE"
else
echo "v-analyzer path already exists in $RC_FILE"
fi
fi
}
# Add to both .zshrc and .bashrc if they exist
add_to_rc ~/.zshrc
if [ "$(uname)" = "Darwin" ] && [ -f ~/.bashrc ]; then
add_to_rc ~/.bashrc
fi
fi
# Final verification
if ! command_exists v; then
echo "Error: V is not accessible in PATH"
echo "Please add ~/code/v to your PATH and try again"
exit 1
fi
check_and_start_redis
if [ "$HEROLIB" = true ]; then
hero_lib_get
~/code/github/freeflowuniverse/herolib/install_herolib.vsh
fi
# if [ "$INSTALL_ANALYZER" = true ]; then
# echo "Run 'source ~/.bashrc' or 'source ~/.zshrc' to update PATH for v-analyzer"
# fi
echo "Installation complete!"
```
/Users/mahmoud/code/github/freeflowuniverse/herolib/docker/herolib/scripts/install_vscode.sh
```sh
#!/bin/bash -e
# Set version and file variables
OPENVSCODE_SERVER_VERSION="1.97.0"
TMP_DIR="/tmp"
FILENAME="openvscode.tar.gz"
FILE_PATH="$TMP_DIR/$FILENAME"
INSTALL_DIR="/opt/openvscode"
BIN_PATH="/usr/local/bin/openvscode-server"
TMUX_SESSION="openvscode-server"
# Function to detect architecture
get_architecture() {
ARCH=$(uname -m)
case "$ARCH" in
x86_64)
echo "x64"
;;
aarch64)
echo "arm64"
;;
*)
echo "Unsupported architecture: $ARCH" >&2
exit 1
;;
esac
}
# Check if OpenVSCode Server is already installed
if [ -d "$INSTALL_DIR" ] && [ -x "$BIN_PATH" ]; then
echo "OpenVSCode Server is already installed at $INSTALL_DIR. Skipping download and installation."
else
# Determine architecture-specific URL
ARCH=$(get_architecture)
if [ "$ARCH" == "x64" ]; then
DOWNLOAD_URL="https://github.com/gitpod-io/openvscode-server/releases/download/openvscode-server-insiders-v${OPENVSCODE_SERVER_VERSION}/openvscode-server-insiders-v${OPENVSCODE_SERVER_VERSION}-linux-x64.tar.gz"
elif [ "$ARCH" == "arm64" ]; then
DOWNLOAD_URL="https://github.com/gitpod-io/openvscode-server/releases/download/openvscode-server-insiders-v${OPENVSCODE_SERVER_VERSION}/openvscode-server-insiders-v${OPENVSCODE_SERVER_VERSION}-linux-arm64.tar.gz"
fi
# Navigate to temporary directory
cd "$TMP_DIR"
# Remove existing file if it exists
if [ -f "$FILE_PATH" ]; then
rm -f "$FILE_PATH"
fi
# Download file using curl
curl -L "$DOWNLOAD_URL" -o "$FILE_PATH"
# Verify file size is greater than 40 MB (40 * 1024 * 1024 bytes)
FILE_SIZE=$(stat -c%s "$FILE_PATH")
if [ "$FILE_SIZE" -le $((40 * 1024 * 1024)) ]; then
echo "Error: Downloaded file size is less than 40 MB." >&2
exit 1
fi
# Extract the tar.gz file
EXTRACT_DIR="openvscode-server-insiders-v${OPENVSCODE_SERVER_VERSION}-linux-${ARCH}"
tar -xzf "$FILE_PATH"
# Move the extracted directory to the install location
if [ -d "$INSTALL_DIR" ]; then
rm -rf "$INSTALL_DIR"
fi
mv "$EXTRACT_DIR" "$INSTALL_DIR"
# Create a symlink for easy access
ln -sf "$INSTALL_DIR/bin/openvscode-server" "$BIN_PATH"
# Verify installation
if ! command -v openvscode-server >/dev/null 2>&1; then
echo "Error: Failed to create symlink for openvscode-server." >&2
exit 1
fi
# Install default plugins
PLUGINS=("ms-python.python" "esbenp.prettier-vscode" "saoudrizwan.claude-dev" "yzhang.markdown-all-in-one" "ms-vscode-remote.remote-ssh" "ms-vscode.remote-explorer" "charliermarsh.ruff" "qwtel.sqlite-viewer" "vosca.vscode-v-analyzer" "tomoki1207.pdf")
for PLUGIN in "${PLUGINS[@]}"; do
"$INSTALL_DIR/bin/openvscode-server" --install-extension "$PLUGIN"
done
echo "Default plugins installed: ${PLUGINS[*]}"
# Clean up temporary directory
if [ -d "$TMP_DIR" ]; then
find "$TMP_DIR" -maxdepth 1 -type f -name "openvscode*" -exec rm -f {} \;
fi
fi
# Start OpenVSCode Server in a tmux session
if tmux has-session -t "$TMUX_SESSION" 2>/dev/null; then
tmux kill-session -t "$TMUX_SESSION"
fi
tmux new-session -d -s "$TMUX_SESSION" "$INSTALL_DIR/bin/openvscode-server"
echo "OpenVSCode Server is running in a tmux session named '$TMUX_SESSION'."
```
/Users/mahmoud/code/github/freeflowuniverse/herolib/docker/herolib/scripts/ourinit.sh
```sh
#!/bin/bash -e
redis-server --daemonize yes
TMUX_SESSION="vscode"
# Start OpenVSCode Server in a tmux session
if tmux has-session -t "$TMUX_SESSION" 2>/dev/null; then
tmux kill-session -t "$TMUX_SESSION"
fi
tmux new-session -d -s "$TMUX_SESSION" "/usr/local/bin/openvscode-server --host 0.0.0.0 --without-connection-token"
service ssh start
exec /bin/bash
```
/Users/mahmoud/code/github/freeflowuniverse/herolib/docker/herolib/shell.sh
```sh
#!/bin/bash -e
# Get the directory where the script is located
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd "$SCRIPT_DIR"
CONTAINER_NAME="herolib"
TARGET_PORT=4000
# Function to check if a container is running
is_container_running() {
docker ps --filter "name=$CONTAINER_NAME" --filter "status=running" -q
}
# Function to check if a port is accessible
is_port_accessible() {
nc -zv 127.0.0.1 "$1" &>/dev/null
}
# Check if the container exists and is running
if ! is_container_running; then
echo "Container $CONTAINER_NAME is not running."
# Check if the container exists but is stopped
if docker ps -a --filter "name=$CONTAINER_NAME" -q | grep -q .; then
echo "Starting existing container $CONTAINER_NAME..."
docker start "$CONTAINER_NAME"
else
echo "Container $CONTAINER_NAME does not exist. Attempting to start with start.sh..."
if [[ -f "$SCRIPT_DIR/start.sh" ]]; then
bash "$SCRIPT_DIR/start.sh"
else
echo "Error: start.sh not found in $SCRIPT_DIR."
exit 1
fi
fi
# Wait for the container to be fully up
sleep 5
fi
# Verify the container is running
if ! is_container_running; then
echo "Error: Failed to start container $CONTAINER_NAME."
exit 1
fi
echo "Container $CONTAINER_NAME is running."
# Check if the target port is accessible
if is_port_accessible "$TARGET_PORT"; then
echo "Port $TARGET_PORT is accessible."
else
echo "Port $TARGET_PORT is not accessible. Please check the service inside the container."
fi
# Enter the container
echo
echo " ** WE NOW LOGIN TO THE CONTAINER ** "
echo
docker exec -it herolib bash
```
/Users/mahmoud/code/github/freeflowuniverse/herolib/docker/herolib/ssh.sh
```sh
#!/bin/bash -e
ssh root@localhost -p 4022
```
/Users/mahmoud/code/github/freeflowuniverse/herolib/docker/herolib/ssh_init.sh
```sh
#!/bin/bash -e
# Get the directory where the script is located
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd "$SCRIPT_DIR"
# Define variables
CONTAINER_NAME="herolib"
CONTAINER_SSH_DIR="/root/.ssh"
AUTHORIZED_KEYS="authorized_keys"
TEMP_AUTH_KEYS="/tmp/authorized_keys"
# Step 1: Create a temporary file to store public keys
> $TEMP_AUTH_KEYS # Clear the file if it exists
# Step 2: Add public keys from ~/.ssh/ if they exist
if ls ~/.ssh/*.pub 1>/dev/null 2>&1; then
cat ~/.ssh/*.pub >> $TEMP_AUTH_KEYS
fi
# Step 3: Check if ssh-agent is running and get public keys from it
if pgrep ssh-agent >/dev/null; then
echo "ssh-agent is running. Fetching keys..."
ssh-add -L >> $TEMP_AUTH_KEYS 2>/dev/null
else
echo "ssh-agent is not running or no keys loaded."
fi
# Step 4: Ensure the temporary file is not empty
if [ ! -s $TEMP_AUTH_KEYS ]; then
echo "No public keys found. Exiting."
exit 1
fi
# Step 5: Ensure the container's SSH directory exists
docker exec -it $CONTAINER_NAME mkdir -p $CONTAINER_SSH_DIR
docker exec -it $CONTAINER_NAME chmod 700 $CONTAINER_SSH_DIR
# Step 6: Copy the public keys into the container's authorized_keys file
docker cp $TEMP_AUTH_KEYS $CONTAINER_NAME:$CONTAINER_SSH_DIR/$AUTHORIZED_KEYS
# Step 7: Set proper permissions for authorized_keys
docker exec -it $CONTAINER_NAME chmod 600 $CONTAINER_SSH_DIR/$AUTHORIZED_KEYS
# Step 8: Install and start the SSH server inside the container
docker exec -it $CONTAINER_NAME bash -c "
apt-get update &&
apt-get install -y openssh-server &&
mkdir -p /var/run/sshd &&
echo 'PermitRootLogin yes' >> /etc/ssh/sshd_config &&
echo 'PasswordAuthentication no' >> /etc/ssh/sshd_config &&
chown -R root:root /root/.ssh &&
chmod -R 700 /root/.ssh/ &&
chmod 600 /root/.ssh/authorized_keys &&
service ssh start
"
# Step 9: Clean up temporary file on the host
rm $TEMP_AUTH_KEYS
echo "SSH keys added and SSH server configured. You can now SSH into the container."
ssh root@localhost -p 4022
```
/Users/mahmoud/code/github/freeflowuniverse/herolib/docker/herolib/start.sh
```sh
#!/bin/bash -e
# Get the directory where the script is located
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd "$SCRIPT_DIR"
docker rm herolib --force
docker compose up -d
./ssh_init.sh
```
/Users/mahmoud/code/github/freeflowuniverse/herolib/docker/postgresql/docker-compose.yml
```yml
version: '3.9'
services:
db:
image: 'postgres:17.2-alpine3.21'
restart: always
ports:
- 5432:5432
environment:
POSTGRES_PASSWORD: 1234
networks:
- my_network
adminer:
image: adminer
restart: always
ports:
- 8080:8080
networks:
- my_network
networks:
my_network:
```
/Users/mahmoud/code/github/freeflowuniverse/herolib/docker/postgresql/readme.md
```md
Server (Host): db (because Docker Compose creates an internal network and uses service names as hostnames)
Username: postgres (default PostgreSQL username)
Password: 1234 (as set in your POSTGRES_PASSWORD environment variable)
Database: Leave it empty or enter postgres (default database)
```
/Users/mahmoud/code/github/freeflowuniverse/herolib/docker/postgresql/start.sh
```sh
#!/bin/bash -e
# Get the directory where the script is located
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd "$SCRIPT_DIR"
# Stop any existing containers and remove them
docker compose down
# Start the services in detached mode
docker compose up -d
echo "PostgreSQL is ready"
```
</file_contents>