# ========================= # MENU CONFIGURATION # ========================= $options = @("Yes", "No") $selectedIndex = 0 $solarPath = "C:\solar" $header = @" ____ ___ _ _ ____ / ___| / _ \ | | / \ | _ \ \___ \ | | | | | | / _ \ | |_) | ___) | _ | |_| | _ | |___ _ / ___ \ _ | _ < _ |____/ (_) \___/ (_) |_____| (_) /_/ \_\ (_) |_| \_\ (_) "@ $subtitle = "Systematic Online or Local Analysis Robot" function Show-Menu { Clear-Host Write-Host $header -ForegroundColor Cyan Write-Host $subtitle -ForegroundColor Yellow Write-Host $tospp -ForegroundColor Gray Write-Host "`nUse arrow keys to select an option and press Enter:`n" $esc = [char]27 $link = "https://solar.creative-crafter.de/terms_of_services_and_privacy_policy/" $text = "Terms of Service and Privacy Policy" Write-Host "Before continuing, please review the $esc[36m$esc]8;;$link$esc\$text$esc]8;;$esc\$esc[0m." for ($i = 0; $i -lt $options.Length; $i++) { if ($i -eq $selectedIndex) { Write-Host "-> $($options[$i])" -ForegroundColor Green } else { Write-Host " $($options[$i])" } } } do { Show-Menu $key = [System.Console]::ReadKey($true) switch ($key.Key) { "UpArrow" { $selectedIndex-- if ($selectedIndex -lt 0) { $selectedIndex = $options.Length - 1 } } "DownArrow" { $selectedIndex++ if ($selectedIndex -ge $options.Length) { $selectedIndex = 0 } } } } until ($key.Key -eq "Enter") # ========================= # YES LOGIC # ========================= switch ($options[$selectedIndex]) { "Yes" { # Create solarPath folder if it doesn't exist if (-Not (Test-Path -Path $solarPath)) { New-Item -Path $solarPath -ItemType Directory | Out-Null Write-Host "Folder created at $solarPath" } else { Write-Host "Folder already exists at $solarPath" } Write-Host "Starting installation and environment setup..." -ForegroundColor Green Invoke-WebRequest -Uri "https://raw.githubusercontent.com/Creative-Crafter/SOLAR/main/main.py" -OutFile "C:\solar\main.py" Invoke-WebRequest -Uri "https://raw.githubusercontent.com/Creative-Crafter/SOLAR/main/solar_online/skills.py" -OutFile "C:\solar\skills.py" Invoke-WebRequest -Uri "https://raw.githubusercontent.com/Creative-Crafter/SOLAR/main/requirements.txt" -OutFile "C:\solar\requirements.txt" Invoke-WebRequest -Uri "https://raw.githubusercontent.com/Creative-Crafter/SOLAR/main/accept.png" -OutFile "C:\solar\accept.png" Invoke-WebRequest -Uri "https://raw.githubusercontent.com/Creative-Crafter/SOLAR/main/decline.png" -OutFile "C:\solar\decline.png" Invoke-WebRequest -Uri "https://raw.githubusercontent.com/Creative-Crafter/SOLAR/main/beep.wav" -OutFile "C:\solar\beep.wav" Invoke-WebRequest -Uri "https://raw.githubusercontent.com/Creative-Crafter/SOLAR/main/discord_search.png" -OutFile "C:\solar\discord_search.png" Invoke-WebRequest -Uri "https://raw.githubusercontent.com/Creative-Crafter/SOLAR/main/insta1.png" -OutFile "C:\solar\insta1.png" Invoke-WebRequest -Uri "https://raw.githubusercontent.com/Creative-Crafter/SOLAR/main/insta2.png" -OutFile "C:\solar\insta2.png" Invoke-WebRequest -Uri "https://raw.githubusercontent.com/Creative-Crafter/SOLAR/main/insta3.png" -OutFile "C:\solar\insta3.png" Invoke-WebRequest -Uri "https://raw.githubusercontent.com/Creative-Crafter/SOLAR/main/search.png" -OutFile "C:\solar\search.png" Invoke-WebRequest -Uri "https://raw.githubusercontent.com/Creative-Crafter/SOLAR/main/whatsapp.png" -OutFile "C:\solar\whatsapp.png" Invoke-WebRequest -Uri "https://alphacephei.com/vosk/models/vosk-model-small-en-us-0.15.zip" -OutFile "C:\solar\vosk-model-small-en-us-0.15.zip" Expand-Archive -Path "C:\solar\vosk-model-small-en-us-0.15.zip" -DestinationPath "C:\solar\vosk-model-small-en-us-0.15_for_deleting" -Force Copy-Item -Path "C:\solar\vosk-model-small-en-us-0.15_for_deleting\vosk-model-small-en-us-0.15" -Destination "C:\solar\vosk-model-small-en-us-0.15" -Recurse -Force Remove-Item -Path "C:\solar\vosk-model-small-en-us-0.15_for_deleting" -Recurse -Force Remove-Item -Path "C:\solar\vosk-model-small-en-us-0.15.zip" -Recurse -Force Invoke-WebRequest -Uri "https://solar.creative-crafter.de/install-local.ps1" -OutFile "C:\solar\install-local.ps1" # Change directory to solarPath Set-Location -Path $solarPath # Create subfolders $subfolders = @("scripts", "data", "logs") foreach ($folder in $subfolders) { $fullPath = Join-Path $solarPath $folder if (-Not (Test-Path -Path $fullPath)) { New-Item -Path $fullPath -ItemType Directory | Out-Null Write-Host "Created subfolder: $fullPath" } } # ========================= # PYTHON INSTALL CONFIG # ========================= # ========================= # PYTHON CONFIG # ========================= $requiredVersion = "3.11.0" $installDir = "C:\Python311" $installerPath = "$env:TEMP\python-3.11.0-amd64.exe" $pythonUrl = "https://www.python.org/ftp/python/3.11.0/python-3.11.0-amd64.exe" $pythonExe = Join-Path $installDir "python.exe" # ========================= # PROJECT CONFIG # ========================= $venvName = ".venv" $projectPath = Get-Location $venvPath = Join-Path $projectPath $venvName $requirementsFile = Join-Path $projectPath "requirements.txt" # ========================= # CHECK PYTHON 3.11 INSTALL # ========================= function Test-Python311 { # check installed directory if (Test-Path $pythonExe) { $version = & $pythonExe --version 2>&1 if ($version -match $requiredVersion) { return $true } } # check via python launcher (works even if other versions exist) $pyLauncher = Get-Command py -ErrorAction SilentlyContinue if ($pyLauncher) { try { $version = py -3.11 --version 2>&1 if ($version -match "3\.11") { return $true } } catch {} } return $false } # ========================= # INSTALL PYTHON IF MISSING # ========================= if (Test-Python311) { Write-Output "Python $requiredVersion already installed." } else { Write-Output "Downloading Python $requiredVersion..." Invoke-WebRequest -Uri $pythonUrl -OutFile $installerPath Write-Output "Installing Python $requiredVersion to $installDir ..." Start-Process ` -FilePath $installerPath ` -ArgumentList "/quiet InstallAllUsers=1 PrependPath=0 TargetDir=$installDir Include_launcher=1" ` -Wait if (!(Test-Path $pythonExe)) { Write-Output "Python installation failed." exit 1 } $installedVersion = & $pythonExe --version Write-Output "Installed: $installedVersion" } # ========================= # CREATE VENV WITH PYTHON 3.11 # ========================= if (!(Test-Path $venvPath)) { Write-Output "Creating virtual environment using Python 3.11..." if (Test-Path $pythonExe) { & $pythonExe -m venv $venvPath } else { py -3.11 -m venv $venvPath } } else { Write-Output ".venv already exists." } # ========================= # ACTIVATE VENV # ========================= $activateScript = Join-Path $venvPath "Scripts\Activate.ps1" if (Test-Path $activateScript) { Write-Output "Activating .venv ..." & $activateScript } else { Write-Output "Activation script not found." exit 1 } # ========================= # INSTALL REQUIREMENTS # ========================= if (Test-Path $requirementsFile) { Write-Output "Installing dependencies..." & "$venvPath\Scripts\python.exe" -m pip install --upgrade pip & "$venvPath\Scripts\python.exe" -m pip install -r $requirementsFile } # ========================= # UPGRADE PIP AND INSTALL PACKAGES # ========================= Write-Output "Upgrading pip..." python -m pip install --upgrade pip foreach ($pkg in $packages) { Write-Output "Installing $pkg..." python -m pip install --upgrade $pkg } # ========================= # INSTALL REQUIREMENTS.TXT IF EXISTS # ========================= # ========================= # OLLAMA INSTALL CONFIG # ========================= $ollamaCommand = "ollama" function Test-OllamaInstalled { $cmd = Get-Command $ollamaCommand -ErrorAction SilentlyContinue return $cmd -ne $null } if (Test-OllamaInstalled) { Write-Output "Ollama is already installed." } else { Write-Output "Ollama is not installed. Installing now..." Invoke-RestMethod -Uri "https://ollama.com/install.ps1" | Invoke-Expression if (Test-OllamaInstalled) { Write-Output "Ollama installed successfully!" } else { Write-Output "Ollama installation failed. Please check for errors." } } # ========================= # CREATE MODELFILENAME FOR OLLAMA # ========================= $name = Read-Host "Please enter how you want to call S.O.L.A.R." do { $user_gender = Read-Host "Please enter if you want to be called Ma'am or Sir by the Assistant. (m for Ma'am and s for Sir)" # Convert input to lowercase to make it case-insensitive $user_gender = $user_gender.ToLower() if (($user_gender -ne "s") -and ($user_gender -ne "m")) { Write-Output "Invalid input, please try again." } } while (($user_gender -ne "s") -and ($user_gender -ne "m")) Write-Output "Thank you! Your preference has been noted." if ($user_gender -eq "s") { $user_gender = "Sir" } else { $user_gender = "Ma'am" } # ========================= # CREATE MODELFILENAME FOR OLLAMA # ========================= Write-Output "Now downloading The models. This may take a while." ollama pull gemma3:27b-cloud ollama pull qwen3-coder-next:cloud $fileName = "Modelfile" $content = @( "FROM gemma3:27b-cloud" @" SYSTEM """ You are $name, a concise, capable AI assistant for the user. Core behavior: - Be clear, intelligent, and direct. - Keep replies short unless the user asks for detail. - Address the user as "$user_gender" in normal conversational replies. - Use a confident, professional tone with subtle dry humor when it fits. - Give practical answers and anticipate the next useful step. - Do not add information the user did not ask for. - If a request is unsafe, illegal, or harmful, refuse briefly and offer a safer alternative. Command routing: - If the user's request matches one of the supported actions below, output only the command in the exact format shown. - Extract the required fields from natural language, even when the words are in a different order. - Do not explain the command. - Do not add greetings, commentary, Markdown, or extra text around a command. - Never write phrases like "Here is the command", "I can do that", or "Sir" before a command. - When outputting a command, the first character of your response must be "/". - If required information is missing, ask one short question that names the missing information. - If the user asks something that is not a supported action, answer normally using the core behavior rules. Supported command outputs: 1. Send a message Use this format: /send Message: ""; Name: ""; Platform: "" Rules: - Preserve the user's message meaning. - The recipient name is usually after words like "to", "for", or "contact". - The message is usually after words like "saying", "that says", "message", "text", or "tell them". - The platform is usually after words like "on", "using", or "via". - Treat names like "Bob", "Mom", "Sarah Miller", or "John from work" as valid recipient names. - Do not ask for a name if the user already gave a recipient. - Use only these platforms: discord, whatsapp, instagram. - If the user names another platform, reply: Sir, I can only send messages on Discord, WhatsApp, or Instagram. - If the message, recipient, or platform is missing, ask for the missing detail. Examples: - User: send a message on whatsapp to bob saying Hi, how are you Output: /send Message: "Hi, how are you"; Name: "bob"; Platform: "whatsapp" - User: tell Sarah on Discord I will be late Output: /send Message: "I will be late"; Name: "Sarah"; Platform: "discord" - User: send Hi Output: Sir, who should I send it to, and on which platform? 2. Tell the time Use this format: /time 3. Tell the date Use this format: /date 4. Write or generate code Use this format: /code "" Rules: - Rewrite vague wording into a clear, complete coding request. - Preserve the user's intent, language, framework, and constraints when provided. - Do not write the code inside this command. - Do not wrap the command in backticks, code fences, or Markdown. - The text inside quotes must be a request description, not the finished code. - For code requests, output only the /code command and nothing else. Examples: - User: program me a python script that outputs hello world Output: /code "write a Python script that prints Hello World" - User: make me a calculator in JavaScript Output: /code "write a JavaScript calculator" 5. Create a calendar event Use this format: /event name: ""; date-start: ""; time-start: ""; date-end: ""; time-end: "" Rules: - If the event lasts multiple days, set date-end to the final date. - If the event is on one day, set date-end to the same value as date-start. - If the user gives no end time, calculate time-end as exactly one hour after time-start. - Never set time-end equal to time-start unless the user explicitly says the event ends at the same time. - Convert dates to ISO format: YYYY-MM-DD. - Convert times to 24-hour format: HH:MM. - If the event name, start date, or start time is missing, ask for the missing detail. Examples: - User: create a event for 25 of august 2027 named meeting with mom at 5 pm Output: /event name: "meeting with mom"; date-start: "2027-08-25"; time-start: "17:00"; date-end: "2027-08-25"; time-end: "18:00" - User: create an event on June 1 2027 at 9 named dentist Output: /event name: "dentist"; date-start: "2027-06-01"; time-start: "09:00"; date-end: "2027-06-01"; time-end: "10:00" - User: create an event called conference from June 3 2027 at 10 am to June 5 2027 at 4 pm Output: /event name: "conference"; date-start: "2027-06-03"; time-start: "10:00"; date-end: "2027-06-05"; time-end: "16:00" 6. Open an application or website Use this format: /open "" Rules: - Always put the application or website inside double quotes. - Do not output /open without quotes. Examples: - User: open chrome Output: /open "chrome" - User: open youtube.com Output: /open "youtube.com" """ "@ ) ) Set-Content -Path $fileName -Value $content Write-Output "Creating Ollama model..." ollama create Creative-Crafter/SOLAR-gemma3:27b_cloud --file Modelfile Write-Output "" Write-Output "All setup complete! Your environment, Ollama, and model are ready." do { $solar_gender = Read-Host "Please enter if you want the Assistant to be male or female. (m for male and f for female)" $solar_gender = $solar_gender.ToLower() if (($solar_gender -ne "m") -and ($solar_gender -ne "f")) { Write-Output "Invalid input, please try again." } } while (($solar_gender -ne "m") -and ($solar_gender -ne "f")) if ($solar_gender -eq "f") { $solar_gender = "af_sarah" } else { $solar_gender = "am_liam" } $user_name = Read-Host "Please enter your name." # Manually create YAML string $yaml_string = @" - name: $name gender: $solar_gender user_name: $user_name "@ # Write to file Set-Content -Path "config.yaml" -Value $yaml_string $commands = @" @echo off if "%1"=="launch" ( cd /d "C:\solar" call .venv\Scripts\activate.bat echo Starting Python file... python "%~dp0main.py" goto :eof ) if "%1"=="-config" ( cd /d "C:\solar" echo Starting configuration PowerShell... powershell -ExecutionPolicy Bypass -File "%~dp0install-local.ps1" goto :eof ) if "%1"=="-h" ( echo. echo Solar CLI Commands: echo. echo solar launch - Starts the Assistent echo solar -config - Starts the setup echo solar -h - Shows this help echo. goto :eof ) echo Unknown command. echo Type: solar -h for help "@ Set-Content -Path "solar.bat" -Value $commands # PATH auslesen und in Liste aufteilen $oldPath = [Environment]::GetEnvironmentVariable("Path", "User") $newPath = "$oldPath;C:\solar" [Environment]::SetEnvironmentVariable("Path", $newPath, "User") } "No" { Write-Host "OK, too bad" -ForegroundColor Red } }