Skip to content
Open
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
19 changes: 17 additions & 2 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,25 @@ extensions.

### PSES and Cross-Repo Work

The `modules/` folder contains the PSES, PSReadLine, and PSScriptAnalyzer PowerShell modules. In development it is a
symlink to `../PowerShellEditorServices/module` — [PowerShellEditorServices][] must be
The `modules/` folder contains the PSES, PSReadLine, and PSScriptAnalyzer PowerShell modules. In development the whole
folder is a symlink to `../PowerShellEditorServices/module` — [PowerShellEditorServices][] must be
cloned as a sibling and built before `npm run compile` will succeed. For cross-repo work, use `pwsh-extension-dev.code-workspace`.

**Cross-repo dev/test cycle.** Because `modules/` is a symlink into the sibling PSES checkout's
`module/` directory, building PSES deploys its DLLs straight into the path the extension loads from —
there is no copy step:

- **Edit PSES C# (server)** → rebuild PSES (e.g. `dotnet build src/PowerShellEditorServices/PowerShellEditorServices.csproj`,
or `Invoke-Build Build` for a full build). The build deploys into `module/PowerShellEditorServices/bin`,
which the symlinked `modules/` exposes to the extension automatically. The extension (and its tests)
then load the new DLL — no copy, but you must rebuild PSES, since the extension does not.
- **Edit extension TypeScript (client)** → `npm run compile`.
- **Verify end-to-end** → `npm test`. This launches a real VS Code Extension Host with PSES connected
and runs the Mocha suite, exercising the locally-built PSES through the symlink. Prefer this over
only eyeballing the Extension Development Host: it is the way to confirm cross-repo (client + server)
changes actually work, and to catch regressions. After changing a setting's default or any shared
behavior, run the full suite — e.g. ISE-compatibility tests assert against setting defaults.

## Key Conventions

- **VS Code best practices**: Follow the [Extension Guidelines](https://code.visualstudio.com/api/references/extension-guidelines) and [UX Guidelines](https://code.visualstudio.com/api/ux-guidelines/overview). Use VS Code's APIs idiomatically and prefer disposable patterns for lifecycle management.
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/ci-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ jobs:
uses: actions/checkout@v6
with:
repository: PowerShell/PowerShellEditorServices
# TEMPORARY: test against the coupled PSES PR #2298 until it merges.
# Revert this `ref` before merging (see PR #5508).
ref: andyleejordan/lm-tools-command-explorer
path: PowerShellEditorServices
Comment on lines 30 to 34

- name: Checkout vscode-powershell
Expand Down
8 changes: 8 additions & 0 deletions .vscode-test.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { defineConfig } from "@vscode/test-cli";
import { existsSync } from "fs";
import { tmpdir } from "os";
import { join } from "path";

export default defineConfig({
files: "test/**/*.test.ts",
Expand All @@ -10,6 +12,12 @@ export default defineConfig({
"--disable-extensions",
// Undocumented but valid option to use a temporary profile for testing
"--profile-temp",
// The default user-data-dir lives under the (deeply nested on CI)
// workspace path, and its IPC socket blows past macOS's 104-char
// unix-socket limit, causing a flaky `listen EINVAL`. Anchor it in the
// OS temp dir so the socket path stays short on every platform.
"--user-data-dir",
join(tmpdir(), "vscode-powershell-test"),
Comment on lines +16 to +20
],
workspaceFolder: `test/${existsSync("C:\\powershell-7\\pwsh.exe") ? "OneBranch" : "TestEnvironment"}.code-workspace`,
mocha: {
Expand Down
97 changes: 94 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,97 @@
"language": "powershell"
}
],
"languageModelTools": [
{
"name": "powershell_get_command",
"toolReferenceName": "getPowerShellCommand",
"displayName": "Get PowerShell Command",
"modelDescription": "Get the commands (cmdlets, functions, and scripts) available in the user's active PowerShell session, scoped by name and/or module. You must provide a 'name' and/or 'module' filter (at least one is required). Returns each matching command's name, module, default parameter set, and parameter names. Use this to discover the exact name, module, and parameters of a PowerShell command instead of guessing.",
"userDescription": "Lists commands available in the active PowerShell session.",
"canBeReferencedInPrompt": true,
"icon": "$(symbol-method)",
"tags": [
"powershell"
],
"inputSchema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Only return commands whose name matches this value (supports wildcards; bare text is matched as a substring), e.g. 'Get-ChildItem', 'ChildItem', or 'Get-*'. Provide this and/or 'module'."
},
"module": {
"type": "string",
"description": "Only return commands from this module (supports wildcards), e.g. 'Microsoft.PowerShell.Management'. Provide this and/or 'name'."
}
}
}
},
{
"name": "powershell_get_help",
"toolReferenceName": "getPowerShellHelp",
"displayName": "Get PowerShell Help",
"modelDescription": "Get the full help (Get-Help -Full) for a specific PowerShell command from the user's active session, including synopsis, syntax, parameter descriptions, and examples. Use this to ground answers about how a PowerShell command works and what parameters it accepts, instead of guessing.",
"userDescription": "Retrieves the full help for a PowerShell command.",
"canBeReferencedInPrompt": true,
"icon": "$(question)",
"tags": [
"powershell"
],
"inputSchema": {
"type": "object",
"properties": {
"command": {
"type": "string",
"description": "The name of the PowerShell command to get help for, e.g. 'Get-ChildItem'."
}
},
"required": [
"command"
]
}
},
{
"name": "powershell_get_environment",
"toolReferenceName": "getPowerShellEnvironment",
"displayName": "Get PowerShell Environment",
"modelDescription": "Get details about the user's active PowerShell session, including the PowerShell version, edition (Core or Desktop), and process architecture. Use this before constructing version- or edition-specific PowerShell so that suggestions match the user's actual environment.",
"userDescription": "Reports the active PowerShell version, edition, and architecture.",
"canBeReferencedInPrompt": true,
"icon": "$(terminal-powershell)",
"tags": [
"powershell"
],
"inputSchema": {
"type": "object",
"properties": {}
}
},
{
"name": "powershell_expand_alias",
"toolReferenceName": "expandPowerShellAlias",
"displayName": "Expand PowerShell Aliases",
"modelDescription": "Expand the aliases in a PowerShell script to their full command names (for example 'gci' becomes 'Get-ChildItem' and '?' becomes 'Where-Object') using the user's active PowerShell session. Use this to normalize or clarify aliased PowerShell before explaining or editing it.",
"userDescription": "Expands aliases in a PowerShell script to full command names.",
"canBeReferencedInPrompt": true,
"icon": "$(symbol-string)",
"tags": [
"powershell"
],
"inputSchema": {
"type": "object",
"properties": {
"text": {
"type": "string",
"description": "The PowerShell script text whose aliases should be expanded."
}
},
"required": [
"text"
]
}
}
],
"viewsContainers": {
"activitybar": [
{
Expand Down Expand Up @@ -391,12 +482,12 @@
"view/item/context": [
{
"command": "PowerShell.ShowHelp",
"when": "view == PowerShellCommands",
"when": "view == PowerShellCommands && viewItem == command",
"group": "inline@1"
},
{
"command": "PowerShell.InsertCommand",
"when": "view == PowerShellCommands",
"when": "view == PowerShellCommands && viewItem == command",
"group": "inline@2"
}
]
Expand Down Expand Up @@ -748,7 +839,7 @@
},
"powershell.sideBar.CommandExplorerVisibility": {
"type": "boolean",
"default": false,
"default": true,
"markdownDescription": "Specifies the visibility of the Command Explorer in the side bar."
},
"powershell.sideBar.CommandExplorerExcludeFilter": {
Expand Down
2 changes: 2 additions & 0 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
import { GetCommandsFeature } from "./features/GetCommands";
import { HelpCompletionFeature } from "./features/HelpCompletion";
import { ISECompatibilityFeature } from "./features/ISECompatibility";
import { LanguageModelToolsFeature } from "./features/LanguageModelTools";
import { OpenInISEFeature } from "./features/OpenInISE";
import { PesterTestsFeature } from "./features/PesterTests";
import { RemoteFilesFeature } from "./features/RemoteFiles";
Expand Down Expand Up @@ -193,6 +194,7 @@ export async function activate(
new RemoteFilesFeature(),
new DebugSessionFeature(context, sessionManager, logger),
new HelpCompletionFeature(),
new LanguageModelToolsFeature(),
];

sessionManager.setLanguageClientConsumers(languageClientConsumers);
Expand Down
Loading
Loading