pi-revit 0.1.5 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -70,10 +70,10 @@ pi install npm:pi-revit
70
70
  cd "$env:USERPROFILE\.pi\agent\npm\node_modules\pi-revit"
71
71
 
72
72
  # 3. Build + deploy the Revit add-in (RevitBridge.dll + the Roslyn DLLs for execute_csharp).
73
- npm run deploy
73
+ npm.cmd run deploy
74
74
 
75
75
  # 4. Create the workspace and global pi-revit command.
76
- npm run setup
76
+ npm.cmd run setup
77
77
  ```
78
78
 
79
79
  For a non-default Revit install location, use the PowerShell deploy script directly and pass
@@ -111,7 +111,7 @@ That's all. Pi starts with the Revit tools ready:
111
111
  > select all structural columns
112
112
  ```
113
113
 
114
- **How this works:** install step 3 placed a small `pi-revit` command in the same folder as the
114
+ **How this works:** the setup step placed a small `pi-revit` command in the same folder as the
115
115
  `pi` command itself. That folder is on your system PATH — which is exactly why *every* terminal
116
116
  finds `pi-revit`, with no extra configuration. When you run it, it switches to your workspace at
117
117
  `Documents\pi-revit` and starts Pi there, so your conventions file (`AGENTS.md`) loads
@@ -165,12 +165,11 @@ Plain `pi` from any folder also works; `pi-revit` just adds the right working fo
165
165
 
166
166
  ### npm install
167
167
 
168
- Close Revit, then in PowerShell:
168
+ Close Revit, then in PowerShell — from any folder **outside** the installed package (Windows
169
+ cannot delete a folder your shell is standing in):
169
170
 
170
171
  ```powershell
171
- cd "$env:USERPROFILE\.pi\agent\npm\node_modules\pi-revit"
172
- powershell -ExecutionPolicy Bypass -File scripts\uninstall.ps1
173
- pi remove npm:pi-revit
172
+ powershell -ExecutionPolicy Bypass -File "$env:USERPROFILE\.pi\agent\npm\node_modules\pi-revit\scripts\uninstall.ps1"
174
173
  ```
175
174
 
176
175
  ### Source install
@@ -182,9 +181,9 @@ powershell -ExecutionPolicy Bypass -File scripts\uninstall.ps1
182
181
  ```
183
182
 
184
183
  This removes the Revit bridge add-in (every installed Revit version), the global `pi-revit`
185
- command, and the bridge runtime folder (`%APPDATA%\RevitBridge\`). It also removes the Pi
186
- package registration for source installs; npm installs should additionally run
187
- `pi remove npm:pi-revit` as shown above. Your workspace at `Documents\pi-revit` (notes + session
184
+ command, the bridge runtime folder (`%APPDATA%\RevitBridge\`), and the Pi package registration
185
+ (it tries both the npm and the source-install form, so no extra `pi remove` is needed for
186
+ either install kind). Your workspace at `Documents\pi-revit` (notes + session
188
187
  history) is **preserved** — add `-RemoveWorkspace` to delete it too, or `-RevitVersion 2026` to
189
188
  target a single Revit version. Pi itself is left installed; remove it with
190
189
  `npm uninstall -g @earendil-works/pi-coding-agent` if you want.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-revit",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "Native Pi connector for Autodesk Revit. Run npx.cmd -y pi-revit for the full Windows install.",
5
5
  "author": "Ahmad Altahlawi",
6
6
  "license": "MIT",
@@ -40,7 +40,31 @@ Write-Host "Workspace ready: $WorkspaceDir" -ForegroundColor Green
40
40
 
41
41
  # 2. Global pi-revit command next to pi (that directory is on PATH by definition).
42
42
  # The template's workspace path is rewritten to honor -WorkspaceDir.
43
- $pi = Get-Command pi -ErrorAction SilentlyContinue
43
+ # Under `npx pi-revit`, npx prepends its ephemeral cache's node_modules\.bin to
44
+ # PATH, and that folder holds a pi shim pulled in via peerDependencies. A launcher
45
+ # written next to that shim lands in a folder that is neither on the user's own
46
+ # PATH nor long-lived, so skip pi entries inside this package's node_modules tree
47
+ # or any npx cache and use the user's permanent pi instead.
48
+ function Get-PermanentPiCommand {
49
+ # Long-form both sides of the prefix comparison: PATH entries may carry 8.3
50
+ # short names (AHMAD~1.TAH) while $PSScriptRoot is normalized, and a form
51
+ # mismatch would silently defeat the own-tree exclusion.
52
+ function Resolve-LongPath([string]$p) {
53
+ try { (Get-Item -LiteralPath $p -ErrorAction Stop).FullName } catch { $p }
54
+ }
55
+ $ownTree = $null
56
+ $repoRoot = Resolve-LongPath (Split-Path $PSScriptRoot -Parent)
57
+ $idx = $repoRoot.LastIndexOf('\node_modules\', [StringComparison]::OrdinalIgnoreCase)
58
+ if ($idx -ge 0) { $ownTree = $repoRoot.Substring(0, $idx + '\node_modules\'.Length) }
59
+ Get-Command pi -All -ErrorAction SilentlyContinue | Where-Object {
60
+ if (-not $_.Source) { return $false }
61
+ $src = Resolve-LongPath $_.Source
62
+ ($src -notmatch '\\_npx\\') -and
63
+ (-not $ownTree -or -not $src.StartsWith($ownTree, [StringComparison]::OrdinalIgnoreCase))
64
+ } | Select-Object -First 1
65
+ }
66
+
67
+ $pi = Get-PermanentPiCommand
44
68
  if ($pi) {
45
69
  $binDir = Split-Path $pi.Source -Parent
46
70
  # Literal line swap (no regex): the workspace path may contain characters
@@ -55,5 +79,5 @@ if ($pi) {
55
79
  Write-Host "Global command installed: $(Join-Path $binDir 'pi-revit.cmd')" -ForegroundColor Green
56
80
  Write-Host 'Run pi-revit from any terminal (pi-revit <project> for a project folder).'
57
81
  } else {
58
- Write-Warning 'pi command not found on PATH. Install Pi first (npm install -g --ignore-scripts @earendil-works/pi-coding-agent), then re-run this script to get the global pi-revit command.'
82
+ Write-Warning 'No permanent pi command found on PATH. Install Pi first (npm install -g --ignore-scripts @earendil-works/pi-coding-agent), then run npx.cmd -y pi-revit again (or re-run this script) to get the global pi-revit command.'
59
83
  }
@@ -54,13 +54,36 @@ foreach ($v in $versions) {
54
54
  Remove-IfExists (Join-Path $dir 'RevitBridge') "Revit $v add-in folder"
55
55
  }
56
56
 
57
- # 2. Global pi-revit command next to pi.
57
+ # 2. Global pi-revit command next to the user's permanent pi. When this script runs
58
+ # from an npx cache or a node_modules copy, PATH may lead Get-Command to a pi shim
59
+ # inside that ephemeral tree first (see setup-workspace.ps1) — the launcher was
60
+ # never installed there, so resolve the permanent pi the same way setup does.
61
+ function Get-PermanentPiCommand {
62
+ # Long-form both sides of the prefix comparison: PATH entries may carry 8.3
63
+ # short names (AHMAD~1.TAH) while $PSScriptRoot is normalized, and a form
64
+ # mismatch would silently defeat the own-tree exclusion.
65
+ function Resolve-LongPath([string]$p) {
66
+ try { (Get-Item -LiteralPath $p -ErrorAction Stop).FullName } catch { $p }
67
+ }
68
+ $ownTree = $null
69
+ $repoRoot = Resolve-LongPath (Split-Path $PSScriptRoot -Parent)
70
+ $idx = $repoRoot.LastIndexOf('\node_modules\', [StringComparison]::OrdinalIgnoreCase)
71
+ if ($idx -ge 0) { $ownTree = $repoRoot.Substring(0, $idx + '\node_modules\'.Length) }
72
+ Get-Command pi -All -ErrorAction SilentlyContinue | Where-Object {
73
+ if (-not $_.Source) { return $false }
74
+ $src = Resolve-LongPath $_.Source
75
+ ($src -notmatch '\\_npx\\') -and
76
+ (-not $ownTree -or -not $src.StartsWith($ownTree, [StringComparison]::OrdinalIgnoreCase))
77
+ } | Select-Object -First 1
78
+ }
79
+
58
80
  $pi = Get-Command pi -ErrorAction SilentlyContinue
59
- if ($pi) {
60
- $binDir = Split-Path $pi.Source -Parent
81
+ $piPermanent = Get-PermanentPiCommand
82
+ if ($piPermanent) {
83
+ $binDir = Split-Path $piPermanent.Source -Parent
61
84
  Remove-IfExists (Join-Path $binDir 'pi-revit.cmd') 'global pi-revit command'
62
85
  } else {
63
- Write-Host 'pi not found on PATH; skipping the global pi-revit command.'
86
+ Write-Host 'No permanent pi found on PATH; skipping the global pi-revit command.'
64
87
  }
65
88
 
66
89
  # 3. Bridge runtime folder (connection token; recreated on each Revit start).
@@ -73,14 +96,30 @@ Remove-IfExists (Join-Path $env:APPDATA 'RevitBridge') 'bridge runtime folder'
73
96
  # is actually registered, so a machine with both gets both removed.
74
97
  if ($pi) {
75
98
  $repoRoot = Split-Path $PSScriptRoot -Parent
76
- Push-Location $repoRoot
99
+ # When this script runs from the npm-installed copy, `pi remove npm:pi-revit`
100
+ # deletes the very folder the script lives in — and Windows fails that delete
101
+ # (EBUSY) while any working directory sits inside it. Step our own process out
102
+ # if needed; the calling shell's location we can only warn about.
103
+ if ($repoRoot -match '\\node_modules\\' -and
104
+ (Get-Location).Path.StartsWith($repoRoot, [StringComparison]::OrdinalIgnoreCase)) {
105
+ Set-Location $env:SystemRoot
106
+ Write-Warning "This PowerShell was started inside $repoRoot. If the package removal below fails, run 'cd \' in your shell and re-run the uninstall."
107
+ }
77
108
  try {
78
109
  $removed = @()
79
- foreach ($source in @('npm:pi-revit', './')) {
80
- $global:LASTEXITCODE = 0
81
- & pi remove $source
82
- if ($LASTEXITCODE -eq 0) {
83
- $removed += $source
110
+ # './' resolves against the repo root, so it runs from there — and first,
111
+ # while this folder is guaranteed to still exist. 'npm:pi-revit' then runs
112
+ # from a neutral directory so no working directory blocks the folder delete.
113
+ foreach ($source in @('./', 'npm:pi-revit')) {
114
+ Push-Location $(if ($source -eq './') { $repoRoot } else { $env:SystemRoot })
115
+ try {
116
+ $global:LASTEXITCODE = 0
117
+ & pi remove $source
118
+ if ($LASTEXITCODE -eq 0) {
119
+ $removed += $source
120
+ }
121
+ } finally {
122
+ Pop-Location
84
123
  }
85
124
  }
86
125
  if ($removed.Count -gt 0) {
@@ -90,8 +129,6 @@ if ($pi) {
90
129
  }
91
130
  } catch {
92
131
  Write-Warning "Could not auto-remove the Pi package; run 'pi remove npm:pi-revit' (npm install) or 'pi remove ./' from this repo (install from source). ($_)"
93
- } finally {
94
- Pop-Location
95
132
  }
96
133
  }
97
134