Public/Invoke-PolymarketCli.ps1

function Invoke-PolymarketCli {
  <#
  .SYNOPSIS
    Just a wrapper around the main class [Polymarket]
  .DESCRIPTION
    Provides an interactive shell if no arguments are provided, or directly runs the command.
  #>

  [CmdletBinding()]
  [Alias("polymarket", "Invoke-PolymarketShell")]
  param (
    [Parameter(Mandatory = $false, ValueFromRemainingArguments = $true)]
    [string[]]$InputArgs
  )

  begin {
  }

  process {
    if ($null -eq $InputArgs -or $InputArgs.Count -eq 0 -or $InputArgs[0] -eq 'shell') {
      Write-Host "`n Polymarket CLI · Interactive Shell" -ForegroundColor Cyan
      Write-Host " Type 'help' for commands, 'exit' to quit.`n"

      $historyPath = Join-Path ([PolymarketConfig]::GetConfigPath() | Split-Path) "history.txt"
      $hasPSReadLine = Get-Module PSReadLine -ListAvailable | Select-Object -First 1

      if ($hasPSReadLine) {
        Import-Module PSReadLine
        Set-PSReadLineOption -HistorySavePath $historyPath -HistorySaveStyle SaveIncrementally
      }

      while ($true) {
        $line = ""
        if ($hasPSReadLine) {
          try {
            Write-Host -NoNewline "polymarket> "
            $line = [Microsoft.PowerShell.PSConsoleReadLine]::ReadLine()
          } catch {
            $line = Read-Host "polymarket> "
          }
        } else {
          $line = Read-Host "polymarket> "
        }

        if ($null -eq $line) { break }
        $line = $line.Trim()

        if ([string]::IsNullOrWhiteSpace($line)) { continue }
        if ($line -in @("exit", "quit")) { break }
        if ($line -eq "help") {
          [Polymarket]::Run(@())
          continue
        }

        if (!$hasPSReadLine) {
          Add-Content -Path $historyPath -Value $line
        }

        # Regex for splitting arguments with quotes
        $pattern = '[^\s"''`]+|"([^"]*)"|''([^'']*)'''
        $cmdArgs = @(); $_matches = [regex]::Matches($line, $pattern)
        foreach ($m in $_matches) {
          if ($m.Groups[1].Success) { $cmdArgs += $m.Groups[1].Value }
          elseif ($m.Groups[2].Success) { $cmdArgs += $m.Groups[2].Value }
          else { $cmdArgs += $m.Value }
        }

        if ($cmdArgs[0] -eq "shell") {
          Write-Host "Already in shell mode."
          continue
        }

        try {
          [Polymarket]::Run($cmdArgs)
        } catch {
          Write-Error $_
        }
      }
      Write-Host "Goodbye!"
    } else {
      [Polymarket]::Run($InputArgs)
    }
  }
}

Register-ArgumentCompleter -CommandName polymarket, Invoke-PolymarketCli -Native -ScriptBlock {
  param($wordToComplete, $commandAst, $cursorPosition)

  $commands = @(
    'status', 'shell', 'markets', 'events', 'sports', 'teams', 'tags',
    'series', 'comments', 'profiles', 'clob', 'data', 'wallet', 'bridge',
    'upgrade', 'approve', 'ctf'
  )

  $clobCommands = @(
    'price', 'midpoint', 'book', 'markets', 'history', 'buy', 'sell',
    'create-api-key', 'orders', 'order', 'trades', 'cancel', 'balance',
    'rewards', 'earnings', 'api-keys', 'account', 'notifications', 'delete-notification'
  )

  $dataCommands = @(
    'positions', 'value', 'trades', 'leaderboard'
  )

  $walletCommands = @(
    'show', 'address', 'create', 'import'
  )

  $cmdElements = $commandAst.CommandElements | Select-Object -ExpandProperty Value

  if ($cmdElements.Count -le 2) {
    $commands | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
      [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
    }
  } elseif ($cmdElements.Count -eq 3) {
    $subcommand = $cmdElements[1]
    if ($subcommand -eq 'clob') {
      $clobCommands | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
        [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
      }
    } elseif ($subcommand -eq 'data') {
      $dataCommands | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
        [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
      }
    } elseif ($subcommand -eq 'wallet') {
      $walletCommands | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
        [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
      }
    }
  }
}