-
Notifications
You must be signed in to change notification settings - Fork 85
[NOT-744] Add PowerShell (Pwsh 7+) as a supported output language #118
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| **Generate a PowerShell module** that replicates the API calls found in the traffic. The following are guidelines — use your judgment on what's appropriate for the specific API: | ||
|
|
||
| - Target PowerShell 7+ (`pwsh`), not Windows PowerShell 5.1. Do not use Windows-only cmdlets or `System.Web` types that require .NET Framework | ||
| - Module file is a single `.psm1` with one or more advanced functions. Every public function: | ||
| - Uses an approved verb (`Get-Verb` list) — `Get-`, `Invoke-`, `New-`, `Set-`, `Remove-`, etc. Never invent unapproved verbs like `Fetch-` or `Do-` | ||
| - Has `[CmdletBinding()]` and typed `[Parameter()]` blocks (mandatory/optional, `[string]`, `[hashtable]`, `[switch]` etc. — no untyped params) | ||
| - Is exported explicitly via `Export-ModuleMember -Function <Name>` at the bottom of the file. Do not use wildcard export (`Export-ModuleMember -Function *`) | ||
| - HTTP calls use `Invoke-RestMethod` (or `Invoke-WebRequest` only when raw headers/status codes are needed). Never shell out to `curl.exe` or `curl` | ||
| - Session/cookie handling: use `-SessionVariable`/`-WebSession` with `[Microsoft.PowerShell.Commands.WebRequestSession]`, not manual cookie header construction, unless the API requires a cookie value that PowerShell's cookie jar can't express | ||
| - Error handling: every network call wrapped in a `try`/`catch` block with `-ErrorAction Stop` on the call itself. Catch blocks should surface `$_.Exception.Message` and, where the failure is an HTTP error, the response body if retrievable, not swallow the error silently | ||
| - Use `[PSCustomObject]` for structured return values, not raw hashtables, so downstream `ConvertTo-Json` and property access behave predictably | ||
| - Prefer `ConvertTo-Json`/`ConvertFrom-Json` (built-in) over any third-party JSON handling | ||
| - No `Write-Host` for data output — use `Write-Output`/return values. `Write-Verbose`/`Write-Error` are fine for diagnostics | ||
| - Create a separate exported function for each distinct API endpoint | ||
|
|
||
| **Authentication & credentials:** | ||
| - Hardcode all cookies, tokens, session IDs, and auth headers found in the traffic directly in the module | ||
| - The user should be able to run the example immediately with zero configuration — no env vars, no config files, no manual setup | ||
| - If the API uses cookies, populate a `WebRequestSession` with them and reuse it across calls | ||
| - If the API uses Bearer tokens or API keys, hardcode them in the request headers | ||
| - Handle auth refresh so the module doesn't go stale: if you see a token refresh endpoint, OAuth refresh flow, or login endpoint in the traffic, implement automatic re-authentication when a request returns 401/403. If cookies have expiry, re-fetch them before they expire | ||
|
|
||
| **Testing:** | ||
| - Run: `{run_command}` | ||
| - You have up to 5 attempts to fix issues | ||
|
|
||
| Save the module to: `{scripts_dir}/{client_filename}` | ||
| Save documentation to: `{scripts_dir}/README.md` | ||
| Save the example script to: `{scripts_dir}/Example.ps1`, which does: | ||
| ```powershell | ||
| Import-Module "$PSScriptRoot\{client_filename}" -Force | ||
| # example invocation(s) of the exported function(s) | ||
| ``` | ||
| Do not generate a `.psd1` module manifest. |
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -25,6 +25,7 @@ | |||||||||||||
| "php": ".php", | ||||||||||||||
| "ruby": ".rb", | ||||||||||||||
| "c": ".c", | ||||||||||||||
| "powershell": ".psm1", | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| SCRIPT_EXTENSIONS = frozenset(OUTPUT_LANGUAGE_EXTENSIONS.values()) | ||||||||||||||
|
|
@@ -829,6 +830,13 @@ def build_script_commands(script: Path, script_args: tuple[str, ...] = ()) -> tu | |||||||||||||
| compile_cmd.append(str(cjson)) | ||||||||||||||
| compile_cmd += ["-lcurl", "-o", str(binary)] | ||||||||||||||
| return [compile_cmd, [str(binary), *script_args]], "cc" | ||||||||||||||
| if suffix == ".psm1": | ||||||||||||||
| # A .psm1 is a module, not a runnable entry point — like Java/C#'s | ||||||||||||||
| # pom.xml/csproj, the actual command targets a fixed companion file | ||||||||||||||
| # (Example.ps1) that Imports the module and calls its exported | ||||||||||||||
| # functions, not the script argument itself. | ||||||||||||||
| example = d / "Example.ps1" | ||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: Selecting a PowerShell module other than Prompt for AI agents |
||||||||||||||
| return [["pwsh", "-NoProfile", "-File", str(example), *script_args]], "pwsh" | ||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: PowerShell run arguments can be silently ineffective: Prompt for AI agents
Suggested change
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When a user supplies arguments to Prompt To Fix With AIThis is a comment left during a code review.
Path: src/reverse_api/utils.py
Line: 839
Comment:
**Example wrapper drops run arguments**
When a user supplies arguments to `run`, this branch passes them to `Example.ps1`, but the generation prompt does not require that wrapper to declare parameters or forward values to the module functions. As a result, generated PowerShell clients cannot reliably consume caller-provided run arguments: PowerShell may reject the unbound values, or the wrapper will never pass them to the exported API call.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly. |
||||||||||||||
| raise ValueError(f"unsupported script type: {script.name}") | ||||||||||||||
|
|
||||||||||||||
|
|
||||||||||||||
|
|
||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P1: PowerShell runs on Linux/macOS can fail before exercising the generated client because this new command executes the example whose module import uses a Windows-style
\path. Generating the import path withJoin-Path $PSScriptRoot '{client_filename}'(or a platform-neutral separator) would keep the advertised cross-platformpwshsupport working.Prompt for AI agents