Public/Get-ChatmodeContent.ps1
function Get-ChatmodeContent { [CmdletBinding()] param( [Parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0)] [string]$ChatModeName, # Optional original filename (including extension) provided by Get-Chatmode [string]$FileName, [string]$Owner, [string]$RepoName, [string]$Directory = 'chatmodes' ) begin { # Default repo values; these may be overridden by script-level variables set by Get-Chatmode $repoOwner = if ($Owner) { $Owner } elseif ($script:RepoOwner) { $script:RepoOwner } else { 'github' } $repoName = if ($RepoName) { $RepoName } elseif ($script:RepoName) { $script:RepoName } else { 'awesome-copilot' } $directory = $Directory if (-not $env:GITHUB_TOKEN) { $headers = @{ 'User-Agent' = 'PowerShell' } } else { $headers = @{ 'Authorization' = "token $($env:GITHUB_TOKEN)" 'User-Agent' = 'PowerShell' } } } process { if (-not $ChatModeName) { Write-Error 'You must specify a ChatModeName.' return } # Determine candidate filenames to try. Prefer explicit FileName, otherwise normalize # ChatModeName and try sensible variants to handle names like 'name', 'name.chatmode', # 'name.chatmode.md', or 'name.md'. $candidates = @() if ($FileName) { $candidates += $FileName } # Normalize and build candidates from ChatModeName $base = $ChatModeName if ($base -match '\.md$') { # already ends with .md — try as-is $candidates += $base } elseif ($base -match '\.chatmode$') { # ends with .chatmode (but not .md) — try adding .md first, then the raw name $candidates += "$base.md" $candidates += $base } else { # plain name — try both common extensions $candidates += "$base.chatmode.md" $candidates += "$base.md" $candidates += $base } $lastError = $null foreach ($candidate in $candidates) { $apiUrl = "https://api.github.com/repos/$repoOwner/$repoName/contents/$directory/$candidate" try { $response = Invoke-RestMethod -Uri $apiUrl -Headers $headers -ErrorAction Stop if ($response.content) { $decoded = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($response.content)) return $decoded } else { Write-Host "No content found for $candidate in $repoOwner/$repoName" -ForegroundColor Yellow } } catch { $lastError = $_ # If 404, continue to next candidate; otherwise log and continue if ($_.Exception.Response -and $_.Exception.Response.StatusCode -eq 404) { Write-Verbose "Not found: $candidate in $repoOwner/$repoName" continue } else { Write-Host "Error fetching content for $($candidate): $($_)" -ForegroundColor Red } } } if ($lastError) { Write-Host "Error fetching content for $($ChatModeName): $($lastError)" -ForegroundColor Red } } } # Example usage: # Get-Chatmode | Get-ChatmodeContent # Get-ChatmodeContent -ChatModeName 'sql-expert' |