Skip to content

Add profile integration option to AI Shell install script for persistent auto-start #389

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion global.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"sdk": {
"version": "8.0.411"
"version": "8.0.116"
}
}
294 changes: 294 additions & 0 deletions tools/scripts/install-aishell.ps1
Original file line number Diff line number Diff line change
@@ -1,6 +1,46 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

<#
.SYNOPSIS
Installs or uninstalls AI Shell.

.DESCRIPTION
This script installs the AI Shell application and PowerShell module from GitHub releases.
It can also configure AI Shell to auto-start when PowerShell is launched in Windows Terminal.

.PARAMETER Version
Specify the version to install, e.g. 'v1.0.0-preview.2'

.PARAMETER AddToProfile
Automatically add AI Shell to PowerShell profile for auto-start without prompting.
Only works on Windows. When used, AI Shell will start automatically when PowerShell
is opened in Windows Terminal.

.PARAMETER DefaultAgent
Default agent to use when auto-starting AI Shell. Must be used with -AddToProfile.
Valid agent names include: openai, ollama, azure, interpreter, phisilica.
If not specified, AI Shell will prompt for agent selection at startup.

.PARAMETER Uninstall
Specify this parameter to uninstall AI Shell and remove it from the PowerShell profile.

.EXAMPLE
.\install-aishell.ps1
Installs AI Shell and prompts for profile integration.

.EXAMPLE
.\install-aishell.ps1 -AddToProfile -DefaultAgent openai
Installs AI Shell and automatically configures it to start with the OpenAI agent.

.EXAMPLE
.\install-aishell.ps1 -Uninstall
Uninstalls AI Shell and removes it from the PowerShell profile.

.LINK
https://aka.ms/AIShell-Docs
#>

#Requires -Version 7.4.6

[CmdletBinding(DefaultParameterSetName = "Install")]
Expand All @@ -9,6 +49,12 @@ param(
[ValidatePattern("^v\d+\.\d+\.\d+(-\w+\.\d{1,2})?$")]
[string] $Version,

[Parameter(HelpMessage = "Automatically add AI Shell to PowerShell profile for auto-start", ParameterSetName = "Install")]
[switch] $AddToProfile,

[Parameter(HelpMessage = "Default agent to use when auto-starting AI Shell", ParameterSetName = "Install")]
[string] $DefaultAgent,

[Parameter(HelpMessage = "Specify this parameter to uninstall AI Shell", ParameterSetName = "Uninstall")]
[switch] $Uninstall
)
Expand Down Expand Up @@ -239,6 +285,226 @@ function Uninstall-AIShellModule {
}
}

function Get-AvailableAgents {
# Try to get available agents by importing the module temporarily
try {
Import-Module AIShell -Force -ErrorAction Stop

# Get available agents by running Start-AIShell briefly and capturing output
# Since we can't easily enumerate agents without starting the shell,
# we'll provide a list of common known agents
$knownAgents = @(
@{ Name = "openai"; Description = "OpenAI GPT models" }
@{ Name = "ollama"; Description = "Ollama local models" }
@{ Name = "azure"; Description = "Azure OpenAI Service" }
@{ Name = "interpreter"; Description = "Code interpreter agent" }
@{ Name = "phisilica"; Description = "Phi Silica agent" }
)

Remove-Module AIShell -Force -ErrorAction SilentlyContinue
return $knownAgents
}
catch {
# If module import fails, return basic known agents
Write-Warning "Could not enumerate agents dynamically. Using known agent list."
return @(
@{ Name = "openai"; Description = "OpenAI GPT models" }
@{ Name = "ollama"; Description = "Ollama local models" }
)
}
}

function Add-AIShellToProfile {
[CmdletBinding()]
param(
[string] $DefaultAgent
)

if (-not $IsWindows) {
Write-Warning "Profile integration is currently only supported on Windows."
return
}

# Validate and sanitize the agent name
if ($DefaultAgent) {
# Remove any potentially dangerous characters and validate
$DefaultAgent = $DefaultAgent -replace '[^a-zA-Z0-9\-_\.]', ''
if ([string]::IsNullOrWhiteSpace($DefaultAgent)) {
Write-Warning "Invalid agent name provided. AI Shell will use default agent selection."
$DefaultAgent = $null
}
}

$profilePath = $PROFILE.CurrentUserAllHosts
$profileDir = Split-Path $profilePath -Parent

# Create profile directory if it doesn't exist
if (-not (Test-Path $profileDir)) {
New-Item -Path $profileDir -ItemType Directory -Force | Out-Null
}

# Define the AI Shell auto-start section with unique markers
$aiShellSectionStart = "# AI Shell Auto-Start - BEGIN (Added by AIShell installer)"
$aiShellSectionEnd = "# AI Shell Auto-Start - END (Added by AIShell installer)"

$agentParameter = if ($DefaultAgent) { " -Agent '$DefaultAgent'" } else { "" }

$aiShellCode = @"
$aiShellSectionStart
# Auto-start AI Shell sidecar if in Windows Terminal
if (`$env:WT_SESSION -and (Get-Command Start-AIShell -ErrorAction SilentlyContinue)) {
try {
Start-AIShell$agentParameter
} catch {
Write-Warning "Failed to auto-start AI Shell: `$_"
}
}
$aiShellSectionEnd
"@

# Read existing profile content
$existingContent = ""
if (Test-Path $profilePath) {
$existingContent = Get-Content $profilePath -Raw -ErrorAction SilentlyContinue

# Check if AI Shell section already exists
if ($existingContent -match [regex]::Escape($aiShellSectionStart)) {
Write-Host "AI Shell auto-start section already exists in profile. Updating..."
# Remove existing section
$pattern = [regex]::Escape($aiShellSectionStart) + ".*?" + [regex]::Escape($aiShellSectionEnd)
$existingContent = [regex]::Replace($existingContent, $pattern, "", [System.Text.RegularExpressions.RegexOptions]::Singleline)
$existingContent = $existingContent.Trim()
}
}

# Add the new AI Shell section
$newContent = if ($existingContent) {
$existingContent + "`n`n" + $aiShellCode
} else {
$aiShellCode
}

# Write to profile
try {
Set-Content -Path $profilePath -Value $newContent -ErrorAction Stop
Write-Host "Successfully added AI Shell auto-start to PowerShell profile: $profilePath"
if ($DefaultAgent) {
Write-Host " Default agent: $DefaultAgent"
}
}
catch {
Write-Error "Failed to update PowerShell profile: $_"
}
}

function Remove-AIShellFromProfile {
[CmdletBinding()]
param()

if (-not $IsWindows) {
return # Profile integration only supported on Windows
}

$profilePath = $PROFILE.CurrentUserAllHosts

if (-not (Test-Path $profilePath)) {
return # No profile file exists
}

try {
$existingContent = Get-Content $profilePath -Raw -ErrorAction Stop

# Define the markers
$aiShellSectionStart = "# AI Shell Auto-Start - BEGIN (Added by AIShell installer)"
$aiShellSectionEnd = "# AI Shell Auto-Start - END (Added by AIShell installer)"

# Check if AI Shell section exists
if ($existingContent -match [regex]::Escape($aiShellSectionStart)) {
Write-Host "Removing AI Shell auto-start from PowerShell profile..."

# Remove the AI Shell section
$pattern = [regex]::Escape($aiShellSectionStart) + ".*?" + [regex]::Escape($aiShellSectionEnd)
$newContent = [regex]::Replace($existingContent, $pattern, "", [System.Text.RegularExpressions.RegexOptions]::Singleline)
$newContent = $newContent.Trim()

# Write back to profile
if ($newContent) {
Set-Content -Path $profilePath -Value $newContent -ErrorAction Stop
} else {
# If profile is now empty, remove the file
Remove-Item $profilePath -ErrorAction Stop
}

Write-Host "Successfully removed AI Shell auto-start from PowerShell profile."
}
}
catch {
Write-Warning "Failed to remove AI Shell from PowerShell profile: $_"
}
}

function Prompt-ProfileIntegration {
[CmdletBinding()]
param()

if (-not $IsWindows) {
Write-Host "Profile integration is only available on Windows."
return $false
}

Write-Host ""
Write-Host -ForegroundColor Cyan "AI Shell Profile Integration"
Write-Host "Would you like to automatically start AI Shell when you open PowerShell in Windows Terminal?"
Write-Host "This will add code to your PowerShell profile (`$PROFILE) to launch the AI Shell sidecar."
Write-Host ""

do {
$response = Read-Host "Add AI Shell to your PowerShell profile? (y/N)"
$response = $response.Trim().ToLower()
} while ($response -notin @('', 'y', 'yes', 'n', 'no'))

return ($response -in @('y', 'yes'))
}

function Prompt-DefaultAgent {
[CmdletBinding()]
param()

Write-Host ""
Write-Host -ForegroundColor Cyan "Default Agent Selection"
Write-Host "Which agent would you like to use by default when AI Shell starts?"
Write-Host ""

$agents = Get-AvailableAgents

# Display available agents
for ($i = 0; $i -lt $agents.Count; $i++) {
Write-Host "$($i + 1). $($agents[$i].Name) - $($agents[$i].Description)"
}
Write-Host "$($agents.Count + 1). Let AI Shell choose at startup (recommended)"
Write-Host ""

do {
$choice = Read-Host "Select an option (1-$($agents.Count + 1))"
try {
$choiceNum = [int]$choice
if ($choiceNum -ge 1 -and $choiceNum -le ($agents.Count + 1)) {
break
}
}
catch {
# Invalid input, continue loop
}
Write-Host "Please enter a number between 1 and $($agents.Count + 1)."
} while ($true)

if ($choiceNum -eq ($agents.Count + 1)) {
return $null # Let AI Shell choose at startup
} else {
return $agents[$choiceNum - 1].Name
}
}

<###################################
#
# Setup/Execute
Expand All @@ -250,12 +516,33 @@ Resolve-Environment
if ($Uninstall) {
Uninstall-AIShellApp
Uninstall-AIShellModule
Remove-AIShellFromProfile

Write-Host -ForegroundColor Green "`nAI Shell App and PowerShell module have been successfully uninstalled."
} else {
Install-AIShellApp
Install-AIShellModule

# Handle profile integration
$shouldAddToProfile = $false
$selectedAgent = $null

if ($AddToProfile) {
# Non-interactive mode: use the provided default agent
$shouldAddToProfile = $true
$selectedAgent = $DefaultAgent
} else {
# Interactive mode: prompt user for consent and agent selection
if (Prompt-ProfileIntegration) {
$shouldAddToProfile = $true
$selectedAgent = Prompt-DefaultAgent
}
}

if ($shouldAddToProfile) {
Add-AIShellToProfile -DefaultAgent $selectedAgent
}

$condition = $IsMacOS ? " if you are in iTerm2" : $null
Write-Host -ForegroundColor Green -Object @"

Expand All @@ -267,6 +554,13 @@ To get started, please run 'Start-AIShell' to use the sidecar experience${condit
Write-Host -ForegroundColor Yellow -Object @"
NOTE: A new version of the PSReadLine module was installed as a dependency.
To ensure the new PSReadLine gets used, please run 'Start-AIShell' from a new session.
"@
}

if ($shouldAddToProfile) {
Write-Host -ForegroundColor Yellow -Object @"
NOTE: AI Shell has been added to your PowerShell profile for auto-start in Windows Terminal.
You can remove this by running the install script with -Uninstall.
"@
}
}