Public/Get-Chatmode.ps1

if (-not $script:RepoMap) {
    # map owner -> repo name for convenient lookup by Install-Chatmode
    $script:RepoMap = @{
        'github' = 'awesome-copilot'
        'dfinke' = 'awesome-copilot-chatmodes'
    }
}

if (-not $script:Repos) {
    # default list of owner/repo entries
    $script:Repos = @('github/awesome-copilot', 'dfinke/awesome-copilot-chatmodes')
}

function Get-Chatmode {
    [CmdletBinding()]
    param(
        [string[]]$ChatModeName = '*',
        # Accept repos in owner/repo format. Default includes the original repo and the new one.
        [string[]]$Repo = $null,
        [string]$Directory = 'chatmodes'
    )

    if (-not $env:GITHUB_TOKEN) {
        Write-Host "[INFO] For a better experience and higher rate limits, set the GITHUB_TOKEN environment variable." -ForegroundColor Yellow
        $headers = @{ 'User-Agent' = 'PowerShell' }
    }
    else {
        $headers = @{
            'Authorization' = "token $($env:GITHUB_TOKEN)"
            'User-Agent'    = 'PowerShell'
        }
    }

    $allMatches = @()

    # If caller didn't provide a Repo list, use the script-level defaults
    if (-not $Repo -or $Repo.Count -eq 0) {
        $Repo = $script:Repos
    }

    foreach ($r in $Repo) {
        if (-not ($r -match '/')) {
            Write-Host "Repo '$r' is not in 'owner/repo' format. Skipping." -ForegroundColor Yellow
            continue
        }

        $parts = $r -split '/' 
        $repoOwner = $parts[0]
        $repoName = $parts[1]
        $apiUrl = "https://api.github.com/repos/$repoOwner/$repoName/contents/$Directory"

        try {
            $response = Invoke-RestMethod -Uri $apiUrl -Headers $headers -ErrorAction Stop

            $files = $response | Where-Object { $_.type -eq 'file' }

            foreach ($pattern in $ChatModeName) {
                $filtered = $files | Where-Object {
                    $nameWithoutExt = $_.name -replace '\.(md|chatmode)$', ''
                    $nameWithoutExt -like $pattern
                }

                if ($filtered) {
                    Write-Host "Files in '$Directory' directory of $($repoOwner)/$($repoName) matching '$pattern':" -ForegroundColor Cyan
                    foreach ($f in $filtered) {
                        $nameWithoutExt = $f.name -replace '\.(md|chatmode)$', ''
                        # Expose the current repo to module/script scope so downstream commands
                        # (Install-Chatmode, Get-ChatmodeContent) can use it when piped.
                        $script:RepoOwner = $repoOwner
                        $script:RepoName = $repoName
                        $script:Repo = "$repoOwner/$repoName"

                        $allMatches += [PSCustomObject]@{
                            Owner        = $repoOwner
                            Repo         = $repoName
                            RepoName     = $repoName
                            # Backward-compatible short name (no extension)
                            Name         = $nameWithoutExt
                            # ChatModeName is the value Install-Chatmode expects when bound by property name.
                            ChatModeName = $nameWithoutExt
                            # Preserve the original file name (including extension) for callers that need it.
                            FileName     = $f.name
                        }
                    }
                }
                else {
                    Write-Host "No files found matching '$pattern' in $($repoOwner)/$($repoName)." -ForegroundColor Yellow
                }
            }
        }
        catch {
            Write-Host "Error fetching data from $($repoOwner)/$($repoName): $_" -ForegroundColor Red
        }
    }

    if ($allMatches) {
        # Keep full objects for downstream piping, but when running interactively
        # print a simplified display (Owner and ChatModeName only).
        $results = $allMatches | Sort-Object Owner, Name -Unique

        # If this command is part of a larger pipeline (e.g. piped to Install-Chatmode),
        # return full objects so downstream commands can consume them. When run
        # interactively (no further pipeline), print a simplified display only.
        if ($MyInvocation.PipelineLength -gt 1) {
            return $results
        }
        else {
            # Interactive display: show a clean table with Owner and Name (ChatModeName)
            $results | Select-Object @{Name = 'Owner'; Expression = { $_.Owner } }, @{Name = 'Name'; Expression = { $_.ChatModeName } } | Format-Table -AutoSize | Out-Host
            return
        }
    }
}