@piagent/platform 1.2.3 → 1.2.5
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/CHANGELOG.md +16 -0
- package/README.md +1 -1
- package/docs/command-reference-vietnamese.md +6 -3
- package/docs/distribution-standard.md +29 -8
- package/docs/operator-manual-vietnamese.md +7 -7
- package/docs/release-install-policy.md +23 -7
- package/docs/security-threat-model.md +1 -1
- package/docs/team-onboarding.md +20 -4
- package/docs-site/architecture.html +1 -1
- package/docs-site/commands.html +1 -1
- package/docs-site/index.html +1 -1
- package/docs-site/mcp-approval.html +1 -1
- package/docs-site/mcp-auth.html +1 -1
- package/docs-site/mcp-servers.html +1 -1
- package/docs-site/mcp.html +1 -1
- package/docs-site/permissions.html +1 -1
- package/docs-site/profiles.html +1 -1
- package/docs-site/quickstart.html +1 -1
- package/docs-site/runtime.html +1 -1
- package/docs-site/scope.html +1 -1
- package/docs-site/security.html +1 -1
- package/docs-site/team.html +1 -1
- package/docs-site/workflows.html +1 -1
- package/package.json +1 -1
- package/packages/piagent-core/package.json +1 -1
- package/scripts/update-global.mjs +214 -12
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
This file records release-facing changes for Pi Agent Platform. Copy the relevant version block into GitHub Releases when publishing a tag.
|
|
4
4
|
|
|
5
|
+
## v1.2.5 - 2026-07-30
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- `piagent-update` now accepts npm 12's singleton-array `npm view --json` output when resolving the target helper version and its pinned Pi host peer dependency. Empty or multi-entry metadata still fails closed, so the updater never guesses which release or host to install.
|
|
10
|
+
|
|
11
|
+
## v1.2.4 - 2026-07-30
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- `piagent-update` remains a global machine update first; optional `--project <path>` now runs a post-update legacy project migration and strict-share doctor when a maintainer wants that extra check.
|
|
16
|
+
|
|
17
|
+
- Documented the global `npm exec --package @piagent/platform@X.Y.Z -- piagent-update ...` bootstrap command for machines that do not have the global `piagent-update` helper yet.
|
|
18
|
+
|
|
19
|
+
- `piagent-update` now falls back to a user-writable npm global prefix when the default prefix is locked by the OS, avoiding `/usr/local/lib/node_modules` permission failures during team rollout.
|
|
20
|
+
|
|
5
21
|
## v1.2.3 - 2026-07-30
|
|
6
22
|
|
|
7
23
|
### Added
|
package/README.md
CHANGED
|
@@ -290,7 +290,7 @@ This repository intentionally excludes:
|
|
|
290
290
|
|
|
291
291
|
## Maturity
|
|
292
292
|
|
|
293
|
-
The current package version is read from package metadata and release tags. Personal machines may follow the unpinned package source when accepting ongoing updates; production/team quickstarts and committed project settings should pin an explicit tag such as `v1.2.
|
|
293
|
+
The current package version is read from package metadata and release tags. Personal machines may follow the unpinned package source when accepting ongoing updates; production/team quickstarts and committed project settings should pin an explicit tag such as `v1.2.5` or a reviewed commit.
|
|
294
294
|
|
|
295
295
|
Ready for:
|
|
296
296
|
|
|
@@ -464,12 +464,15 @@ Các lệnh này chạy ngoài Pi.
|
|
|
464
464
|
| Command | Dùng khi nào |
|
|
465
465
|
|---|---|
|
|
466
466
|
| `npm install -g --ignore-scripts @earendil-works/pi-coding-agent@0.82.0` | Cài Pi CLI tương thích với release hiện tại. |
|
|
467
|
-
| `npm install -g --ignore-scripts @piagent/platform@1.2.
|
|
468
|
-
| `pi install git:github.com/Vt-mmm/piagent@v1.2.
|
|
467
|
+
| `npm install -g --ignore-scripts @piagent/platform@1.2.5` | Cài terminal helper `piagent-*` từ release tag hiện tại. |
|
|
468
|
+
| `pi install git:github.com/Vt-mmm/piagent@v1.2.5` | Cài pinned release khi cần reproducible team setup. |
|
|
469
469
|
| `pi install git:github.com/Vt-mmm/piagent` | Cài latest package platform cho máy cá nhân/sandbox. |
|
|
470
470
|
| `piagent-update --check` | Báo version hiện tại vs version sẽ lên cho cả ba thành phần; không cài gì. |
|
|
471
|
-
| `piagent-update` | Full update một lệnh: Pi host → npm-global helper → Pi package, đúng thứ tự release yêu cầu.
|
|
471
|
+
| `piagent-update` | Full update global một lệnh cho cả máy: Pi host → npm-global helper → Pi package, đúng thứ tự release yêu cầu. |
|
|
472
472
|
| `piagent-update --version X.Y.Z` | Update tới đúng một release thay vì latest; dùng cho rollout theo lô hoặc rollback. |
|
|
473
|
+
| `piagent-update --project <path>` | Bước phụ sau global update: migrate project cũ nếu có rồi chạy doctor strict-share cho project đó. |
|
|
474
|
+
| `piagent-update --npm-prefix ~/.pi/npm-global` | Ép updater cài host/helper vào npm global prefix của user; hữu ích khi `/usr/local/lib/node_modules` không ghi được. |
|
|
475
|
+
| `npm exec -y --package @piagent/platform@X.Y.Z -- piagent-update --version X.Y.Z --force` | Bootstrap/update global cho máy chưa có `piagent-update`; chạy từ Terminal, không cần mở Pi. |
|
|
473
476
|
| `PIAGENT_NO_UPDATE_CHECK=1` | Tắt notice "có bản mới" ở đầu session Pi. Mặc định bật, hỏi registry nhiều nhất một lần mỗi 24 giờ ở tiến trình nền. |
|
|
474
477
|
| Cài exact Pi host của release, rồi `npm install -g --ignore-scripts @piagent/platform@X.Y.Z` và `piagent-install --stable` | Sequence thủ công tương đương. Thứ tự bắt buộc: `piagent-install` fail nếu Pi host lệch bản pin và không tự cài host. Version pin của từng release nằm trong [release/install policy](release-install-policy.md). |
|
|
475
478
|
| Cài exact Pi host ghi trong release cũ, rồi helper `vPREVIOUS` và `piagent-install --stable` | Full rollback; đánh giá dependency risk của host cũ trước khi hạ version. |
|
|
@@ -14,9 +14,9 @@ Repo này phải chạy được cho nhiều project/domain khác nhau. Vì vậ
|
|
|
14
14
|
|
|
15
15
|
| Use case | Package source |
|
|
16
16
|
|---|---|
|
|
17
|
-
| Team pinned release | `git:github.com/Vt-mmm/piagent@v1.2.
|
|
17
|
+
| Team pinned release | `git:github.com/Vt-mmm/piagent@v1.2.5` |
|
|
18
18
|
| Personal/sandbox dev | `git:github.com/Vt-mmm/piagent` |
|
|
19
|
-
| Registry distribution | `npm:@piagent/platform@1.2.
|
|
19
|
+
| Registry distribution | `npm:@piagent/platform@1.2.5` |
|
|
20
20
|
| Enterprise npm (fork under another scope) | `npm:@your-scope/platform@x.y.z` |
|
|
21
21
|
| Local platform dev | `/path/to/piagent` |
|
|
22
22
|
|
|
@@ -26,7 +26,7 @@ Latest tiện cho máy cá nhân muốn nhận cập nhật nhanh. Pin tag/commi
|
|
|
26
26
|
|
|
27
27
|
| Channel | Command | Target | Policy |
|
|
28
28
|
|---|---|---|---|
|
|
29
|
-
| `stable` | `bash scripts/install-global.sh --stable` | Helper release tag resolved to commit SHA, currently `v1.2.
|
|
29
|
+
| `stable` | `bash scripts/install-global.sh --stable` | Helper release tag resolved to commit SHA, currently `v1.2.5` | Install the Pi package matching the helper. |
|
|
30
30
|
| `exact` | `bash scripts/install-global.sh --version vX.Y.Z --resolve-tag` | Requested tag resolved to commit SHA | Pi-package-only rollout, rollback, and incident recovery. |
|
|
31
31
|
| `dev` | `bash scripts/install-global.sh --dev` | Moving Git source | Personal/sandbox only; do not commit into project settings. |
|
|
32
32
|
| `local` | `bash scripts/install-global.sh --local` | Current checkout path | Platform development only. |
|
|
@@ -53,7 +53,7 @@ Root `package.json` có `pi` manifest trỏ tới:
|
|
|
53
53
|
Do đó team có thể:
|
|
54
54
|
|
|
55
55
|
```bash
|
|
56
|
-
pi install git:github.com/Vt-mmm/piagent@v1.2.
|
|
56
|
+
pi install git:github.com/Vt-mmm/piagent@v1.2.5
|
|
57
57
|
```
|
|
58
58
|
|
|
59
59
|
Không cần biết internal folder `packages/piagent-core`. Source không pin chỉ dành cho personal/sandbox như bảng channel ở trên.
|
|
@@ -65,12 +65,12 @@ Team nên install global package một lần:
|
|
|
65
65
|
```bash
|
|
66
66
|
node --version # >= 22.19.0
|
|
67
67
|
npm install -g --ignore-scripts @earendil-works/pi-coding-agent@0.82.0
|
|
68
|
-
npm install -g --ignore-scripts @piagent/platform@1.2.
|
|
68
|
+
npm install -g --ignore-scripts @piagent/platform@1.2.5
|
|
69
69
|
piagent-install --stable --dry-run
|
|
70
70
|
piagent-install --stable
|
|
71
71
|
```
|
|
72
72
|
|
|
73
|
-
`pi install git:github.com/Vt-mmm/piagent@v1.2.
|
|
73
|
+
`pi install git:github.com/Vt-mmm/piagent@v1.2.5` vẫn hợp lệ nếu chỉ cần cài Pi package. Lệnh đó không tự tạo các binary terminal `piagent-*`; muốn có helper global thì dùng `npm install -g --ignore-scripts @piagent/platform@1.2.5`.
|
|
74
74
|
|
|
75
75
|
Support matrix hiện tại: macOS Apple Silicon + Bash và Linux x64 + Bash đã được verify; macOS Intel + Bash và Linux ARM64 + Bash là supported target cần chạy smoke trước rollout; native Windows chưa phải target rollout team; WSL2 experimental. Chi tiết và version runtime nằm trong [release/install policy](release-install-policy.md).
|
|
76
76
|
|
|
@@ -120,7 +120,7 @@ Nếu muốn commit sẵn `.pi/piagent-profile.json` vào repo hoặc bootstrap
|
|
|
120
120
|
```bash
|
|
121
121
|
bash scripts/setup.sh /path/to/project \
|
|
122
122
|
--profile be-readonly-fe \
|
|
123
|
-
--package-source git:github.com/Vt-mmm/piagent@v1.2.
|
|
123
|
+
--package-source git:github.com/Vt-mmm/piagent@v1.2.5 \
|
|
124
124
|
--mcp-preset core \
|
|
125
125
|
--subagents-preset safe
|
|
126
126
|
```
|
|
@@ -189,13 +189,34 @@ Files không commit:
|
|
|
189
189
|
|
|
190
190
|
[Release/install policy](release-install-policy.md) là checklist canonical duy nhất. Production docs chỉ được promote sau khi tag đã tồn tại và stable dry-run resolve đúng commit SHA.
|
|
191
191
|
|
|
192
|
-
Full platform update phải đồng bộ Pi host, npm-global helper và Pi package:
|
|
192
|
+
Full platform update phải đồng bộ Pi host, npm-global helper và Pi package cho cả máy:
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
piagent-update --version X.Y.Z
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Máy chưa có helper dùng bootstrap all-in-one:
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
npm exec -y --package @piagent/platform@X.Y.Z -- piagent-update --version X.Y.Z --force
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Máy bị khóa npm global ở `/usr/local` không cần `sudo`: updater sẽ dùng prefix user-local `~/.pi/npm-global` hoặc maintainer có thể truyền `--npm-prefix <path>`.
|
|
205
|
+
|
|
206
|
+
Project migration/doctor là bước kiểm tra sau global update, chỉ chạy cho repo cần xác minh:
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
piagent-update --version X.Y.Z --project /path/to/project
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Sequence thủ công tương đương:
|
|
193
213
|
|
|
194
214
|
```bash
|
|
195
215
|
npm install -g --ignore-scripts @earendil-works/pi-coding-agent@0.82.0
|
|
196
216
|
npm install -g --ignore-scripts @piagent/platform@X.Y.Z
|
|
197
217
|
piagent-install --stable --dry-run
|
|
198
218
|
piagent-install --stable
|
|
219
|
+
piagent-migrate /path/to/project --apply --remove-old
|
|
199
220
|
piagent-doctor /path/to/project --strict-share
|
|
200
221
|
```
|
|
201
222
|
|
|
@@ -18,12 +18,12 @@ Support matrix release hiện tại: macOS Apple Silicon + Bash và Linux x64 +
|
|
|
18
18
|
```bash
|
|
19
19
|
node --version # >= 22.19.0
|
|
20
20
|
npm install -g --ignore-scripts @earendil-works/pi-coding-agent@0.82.0
|
|
21
|
-
npm install -g --ignore-scripts @piagent/platform@1.2.
|
|
21
|
+
npm install -g --ignore-scripts @piagent/platform@1.2.5
|
|
22
22
|
piagent-install --stable --dry-run
|
|
23
23
|
piagent-install --stable
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
Khi seed `.pi/settings.json` cho team/repo cần audit lặp lại, giữ package source dạng pinned tag như `git:github.com/Vt-mmm/piagent@v1.2.
|
|
26
|
+
Khi seed `.pi/settings.json` cho team/repo cần audit lặp lại, giữ package source dạng pinned tag như `git:github.com/Vt-mmm/piagent@v1.2.5`. Máy cá nhân có thể dùng `git:github.com/Vt-mmm/piagent` để theo latest.
|
|
27
27
|
|
|
28
28
|
Nếu đang ở source checkout của platform, dùng helper theo channel để preview trước khi đổi:
|
|
29
29
|
|
|
@@ -99,7 +99,7 @@ install package once
|
|
|
99
99
|
|
|
100
100
|
```bash
|
|
101
101
|
npm install -g --ignore-scripts @earendil-works/pi-coding-agent@0.82.0
|
|
102
|
-
npm install -g --ignore-scripts @piagent/platform@1.2.
|
|
102
|
+
npm install -g --ignore-scripts @piagent/platform@1.2.5
|
|
103
103
|
piagent-install --stable --dry-run
|
|
104
104
|
piagent-install --stable
|
|
105
105
|
```
|
|
@@ -282,7 +282,7 @@ Không phải daily default. Dùng khi muốn tạo sẵn `.pi` files cho projec
|
|
|
282
282
|
bash /path/to/piagent/scripts/setup.sh /path/to/project \
|
|
283
283
|
--project-only \
|
|
284
284
|
--profile auto \
|
|
285
|
-
--package-source git:github.com/Vt-mmm/piagent@v1.2.
|
|
285
|
+
--package-source git:github.com/Vt-mmm/piagent@v1.2.5 \
|
|
286
286
|
--mcp-preset core \
|
|
287
287
|
--subagents-preset safe
|
|
288
288
|
```
|
|
@@ -894,8 +894,8 @@ Watchdog là optional adversarial reviewer ở cuối turn, không bật mặc
|
|
|
894
894
|
|
|
895
895
|
| Command | Dùng để |
|
|
896
896
|
|---|---|
|
|
897
|
-
| `npm install -g --ignore-scripts @piagent/platform@1.2.
|
|
898
|
-
| `pi install git:github.com/Vt-mmm/piagent@v1.2.
|
|
897
|
+
| `npm install -g --ignore-scripts @piagent/platform@1.2.5` | Cài terminal helper `piagent-*` từ release tag hiện tại. |
|
|
898
|
+
| `pi install git:github.com/Vt-mmm/piagent@v1.2.5` | Install pinned release cho reproducible team setup. |
|
|
899
899
|
| `pi install git:github.com/Vt-mmm/piagent` | Install latest platform package cho máy cá nhân/sandbox. |
|
|
900
900
|
| Cài exact Pi host của release, rồi `npm install -g --ignore-scripts @piagent/platform@X.Y.Z` và `piagent-install --stable` | Full update: đồng bộ host, terminal helper và Pi package. Mỗi release pin một Pi host chính xác; lấy đúng version của release đang cài trong [release/install policy](release-install-policy.md). |
|
|
901
901
|
| Cài exact Pi host ghi trong release cũ, rồi helper `vPREVIOUS` và `piagent-install --stable` | Full rollback; đánh giá lại dependency findings của host cũ trước khi hạ version. |
|
|
@@ -1002,7 +1002,7 @@ Mở lại Pi session sau khi install.
|
|
|
1002
1002
|
Cài lại terminal helper đúng release rồi kiểm tra `PATH`:
|
|
1003
1003
|
|
|
1004
1004
|
```bash
|
|
1005
|
-
npm install -g --ignore-scripts @piagent/platform@1.2.
|
|
1005
|
+
npm install -g --ignore-scripts @piagent/platform@1.2.5
|
|
1006
1006
|
command -v piagent-install
|
|
1007
1007
|
```
|
|
1008
1008
|
|
|
@@ -10,7 +10,7 @@ This file is the canonical install, update, rollback, and release checklist. Oth
|
|
|
10
10
|
|
|
11
11
|
All supported environments require Node.js `>=22.19.0` and Pi Coding Agent `0.82.0`. The Pi host is installed as a Node CLI; Pi Agent Platform still defines its own release matrix because the terminal helpers and shell policy rely on Bash/POSIX behavior.
|
|
12
12
|
|
|
13
|
-
| Surface | Status for v1.2.
|
|
13
|
+
| Surface | Status for v1.2.5 | Rollout guidance |
|
|
14
14
|
|---|---|---|
|
|
15
15
|
| macOS Apple Silicon (`darwin/arm64`) + Bash | Verified for this release. | Safe default for team rollout after normal project smoke tests. |
|
|
16
16
|
| Linux x64 + Bash | Verified in GitHub Actions. | Safe default for CI/server usage after normal project smoke tests. |
|
|
@@ -33,7 +33,7 @@ These three components are versioned independently. A full install, update, or r
|
|
|
33
33
|
|
|
34
34
|
| Channel | Source shape | Mutability | Use when |
|
|
35
35
|
|---|---|---:|---|
|
|
36
|
-
| `stable` | `git:github.com/Vt-mmm/piagent@<resolved-commit-sha>` from `v1.2.
|
|
36
|
+
| `stable` | `git:github.com/Vt-mmm/piagent@<resolved-commit-sha>` from `v1.2.5` | Fixed after resolution | Default for team rollout. |
|
|
37
37
|
| `exact` | Tag, reviewed commit, or a tag resolved with `--resolve-tag` | Fixed when using a commit SHA | Pi-package-only roll forward, rollback, or reproduction. |
|
|
38
38
|
| `dev` | `git:github.com/Vt-mmm/piagent` | Moving | Personal machine or sandbox only. |
|
|
39
39
|
| `local` | `/path/to/piagent` | Local workspace | Platform development and dry-run validation. |
|
|
@@ -53,7 +53,7 @@ Use this flow when the team needs both terminal commands and the Pi package:
|
|
|
53
53
|
```bash
|
|
54
54
|
node --version # >= 22.19.0
|
|
55
55
|
npm install -g --ignore-scripts @earendil-works/pi-coding-agent@0.82.0
|
|
56
|
-
npm install -g --ignore-scripts @piagent/platform@1.2.
|
|
56
|
+
npm install -g --ignore-scripts @piagent/platform@1.2.5
|
|
57
57
|
piagent-install --stable --dry-run
|
|
58
58
|
piagent-install --stable
|
|
59
59
|
```
|
|
@@ -61,8 +61,8 @@ piagent-install --stable
|
|
|
61
61
|
The stable preview and apply output includes:
|
|
62
62
|
|
|
63
63
|
```text
|
|
64
|
-
currentRelease: v1.2.
|
|
65
|
-
tag: v1.2.
|
|
64
|
+
currentRelease: v1.2.5 (helper package version)
|
|
65
|
+
tag: v1.2.5
|
|
66
66
|
resolvedCommit: <40-char-sha>
|
|
67
67
|
source: git:github.com/Vt-mmm/piagent@<40-char-sha>
|
|
68
68
|
```
|
|
@@ -79,7 +79,7 @@ bash scripts/install-global.sh --stable
|
|
|
79
79
|
Use this only when terminal commands are not needed:
|
|
80
80
|
|
|
81
81
|
```bash
|
|
82
|
-
pi install git:github.com/Vt-mmm/piagent@v1.2.
|
|
82
|
+
pi install git:github.com/Vt-mmm/piagent@v1.2.5
|
|
83
83
|
```
|
|
84
84
|
|
|
85
85
|
Direct `pi install` does not create `piagent-*` commands on `PATH`.
|
|
@@ -91,11 +91,27 @@ Direct `pi install` does not create `piagent-*` commands on `PATH`.
|
|
|
91
91
|
```bash
|
|
92
92
|
piagent-update --check
|
|
93
93
|
piagent-update --dry-run
|
|
94
|
-
piagent-update --
|
|
94
|
+
piagent-update --version X.Y.Z
|
|
95
95
|
```
|
|
96
96
|
|
|
97
97
|
It resolves the target helper version and, from that version's published metadata, the exact Pi host that version pins — both before installing anything, so `--check` and `--dry-run` describe a real run. It then installs the host, replaces the helper, verifies that the version now on disk is the one it asked for, and only then runs the new helper's installer for the Pi package. `--version X.Y.Z` targets an exact release instead of latest, `--no-host` and `--no-package` narrow the run, and anything after `--` is passed to `piagent-install`.
|
|
98
98
|
|
|
99
|
+
Project migration and doctor are post-update checks, not the update scope. Run them only for the project being verified:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
piagent-update --version X.Y.Z --project /path/to/project
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
With `--project`, the updater migrates legacy project state if needed and runs `piagent-doctor --strict-share`; use `--no-migrate` only when debugging a migration.
|
|
106
|
+
|
|
107
|
+
If the machine's default npm global prefix is locked by the OS, for example `/usr/local/lib/node_modules`, the updater uses `~/.pi/npm-global` for this rollout and prints the `PATH` line to add later. Do not run project update/doctor as root, because that can leave project files owned by root. Maintainers can force a specific prefix with `--npm-prefix <path>`.
|
|
108
|
+
|
|
109
|
+
For a fresh machine that does not have `piagent-update` yet, bootstrap the same all-in-one flow without opening Pi:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
npm exec -y --package @piagent/platform@X.Y.Z -- piagent-update --version X.Y.Z --force
|
|
113
|
+
```
|
|
114
|
+
|
|
99
115
|
Running it from a git checkout is refused rather than replacing that checkout's commands with a published build; update a checkout with `git pull` and `install-global.sh --local`.
|
|
100
116
|
|
|
101
117
|
The same sequence by hand, which must keep this order because `piagent-install` fails against a host that does not match the version it pins and does not install one itself:
|
|
@@ -21,7 +21,7 @@ This document covers the packaged guard, project profiles, capability locks, ins
|
|
|
21
21
|
- The operator, operating-system account, Pi host, and explicitly trusted project repository are trusted to execute code.
|
|
22
22
|
- Project-local Pi resources are loaded only after Pi project trust or an explicit operator override.
|
|
23
23
|
- A human remains available to approve destructive and external-provider actions.
|
|
24
|
-
- Supported release verification covers macOS Apple Silicon + Bash, Linux x64 + Bash, Node.js `>=22.19.0`, and the exact Pi host version declared by the release. macOS Intel + Bash and Linux ARM64 + Bash are supported targets that need local smoke verification before broad rollout. Native Windows is not a team-rollout target for v1.2.
|
|
24
|
+
- Supported release verification covers macOS Apple Silicon + Bash, Linux x64 + Bash, Node.js `>=22.19.0`, and the exact Pi host version declared by the release. macOS Intel + Bash and Linux ARM64 + Bash are supported targets that need local smoke verification before broad rollout. Native Windows is not a team-rollout target for v1.2.5, and WSL2 is experimental/unverified.
|
|
25
25
|
- Registry, GitHub, model-provider, MCP-provider, and Vercel controls are external dependencies. Their account security and platform guarantees are not replaced by this repository.
|
|
26
26
|
|
|
27
27
|
## Threat actors and failure modes
|
package/docs/team-onboarding.md
CHANGED
|
@@ -9,7 +9,7 @@ Một thành viên mới không cần biết local path của maintainer. Luồn
|
|
|
9
9
|
```bash
|
|
10
10
|
node --version # >= 22.19.0
|
|
11
11
|
npm install -g --ignore-scripts @earendil-works/pi-coding-agent@0.82.0
|
|
12
|
-
npm install -g --ignore-scripts @piagent/platform@1.2.
|
|
12
|
+
npm install -g --ignore-scripts @piagent/platform@1.2.5
|
|
13
13
|
piagent-install --stable
|
|
14
14
|
cd /path/to/project
|
|
15
15
|
pi
|
|
@@ -43,7 +43,7 @@ Mặc định team dùng stable helper:
|
|
|
43
43
|
```bash
|
|
44
44
|
node --version # >= 22.19.0
|
|
45
45
|
npm install -g --ignore-scripts @earendil-works/pi-coding-agent@0.82.0
|
|
46
|
-
npm install -g --ignore-scripts @piagent/platform@1.2.
|
|
46
|
+
npm install -g --ignore-scripts @piagent/platform@1.2.5
|
|
47
47
|
piagent-install --stable --dry-run
|
|
48
48
|
piagent-install --stable
|
|
49
49
|
```
|
|
@@ -68,10 +68,26 @@ Một lệnh, đúng thứ tự, cho cả ba thành phần:
|
|
|
68
68
|
|
|
69
69
|
```bash
|
|
70
70
|
piagent-update --check
|
|
71
|
-
piagent-update --
|
|
71
|
+
piagent-update --version X.Y.Z
|
|
72
72
|
```
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
Chạy từ Terminal, không cần mở Pi và không cần đứng trong project. Đây là update global cho cả máy: Pi host, npm-global helper, và Pi package.
|
|
75
|
+
|
|
76
|
+
Khi cần kiểm tra một project sau rollout, chạy riêng:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
piagent-update --version X.Y.Z --project /path/to/project
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
`--project` là bước phụ: tự migrate layout cũ nếu có rồi chạy doctor strict-share. `--check` chỉ báo version, không đụng gì.
|
|
83
|
+
|
|
84
|
+
Nếu npm global mặc định của máy bị khóa quyền ở `/usr/local`, updater tự chuyển sang `~/.pi/npm-global` cho user hiện tại và in dòng `PATH` cần thêm. Không chạy doctor bằng `sudo`.
|
|
85
|
+
|
|
86
|
+
Máy mới chưa có `piagent-update` dùng một dòng bootstrap này:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
npm exec -y --package @piagent/platform@X.Y.Z -- piagent-update --version X.Y.Z --force
|
|
90
|
+
```
|
|
75
91
|
|
|
76
92
|
Không cần ai nhớ đi kiểm tra: khi có release mới, Pi tự báo ngay ở dòng notice lúc mở session, kèm luôn lệnh chạy.
|
|
77
93
|
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
<span>Pi Agent Platform</span>
|
|
28
28
|
</a>
|
|
29
29
|
<div class="top-actions">
|
|
30
|
-
<span class="pill"><span class="pill-dot"></span>v1.2.
|
|
30
|
+
<span class="pill"><span class="pill-dot"></span>v1.2.5 docs</span>
|
|
31
31
|
<a class="button social" href="https://github.com/Vt-mmm/piagent" target="_blank" rel="noopener noreferrer" aria-label="Mở GitHub repository">
|
|
32
32
|
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
|
33
33
|
<path d="M7 17 17 7M9 7h8v8" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
package/docs-site/commands.html
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
<span>Pi Agent Platform</span>
|
|
28
28
|
</a>
|
|
29
29
|
<div class="top-actions">
|
|
30
|
-
<span class="pill"><span class="pill-dot"></span>v1.2.
|
|
30
|
+
<span class="pill"><span class="pill-dot"></span>v1.2.5 docs</span>
|
|
31
31
|
<a class="button social" href="https://github.com/Vt-mmm/piagent" target="_blank" rel="noopener noreferrer" aria-label="Mở GitHub repository">
|
|
32
32
|
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
|
33
33
|
<path d="M7 17 17 7M9 7h8v8" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
package/docs-site/index.html
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
<span>Pi Agent Platform</span>
|
|
28
28
|
</a>
|
|
29
29
|
<div class="top-actions">
|
|
30
|
-
<span class="pill"><span class="pill-dot"></span>v1.2.
|
|
30
|
+
<span class="pill"><span class="pill-dot"></span>v1.2.5 docs</span>
|
|
31
31
|
<a class="button social" href="https://github.com/Vt-mmm/piagent" target="_blank" rel="noopener noreferrer" aria-label="Mở GitHub repository">
|
|
32
32
|
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
|
33
33
|
<path d="M7 17 17 7M9 7h8v8" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
<span>Pi Agent Platform</span>
|
|
28
28
|
</a>
|
|
29
29
|
<div class="top-actions">
|
|
30
|
-
<span class="pill"><span class="pill-dot"></span>v1.2.
|
|
30
|
+
<span class="pill"><span class="pill-dot"></span>v1.2.5 docs</span>
|
|
31
31
|
<a class="button social" href="https://github.com/Vt-mmm/piagent" target="_blank" rel="noopener noreferrer" aria-label="Mở GitHub repository">
|
|
32
32
|
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
|
33
33
|
<path d="M7 17 17 7M9 7h8v8" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
package/docs-site/mcp-auth.html
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
<span>Pi Agent Platform</span>
|
|
28
28
|
</a>
|
|
29
29
|
<div class="top-actions">
|
|
30
|
-
<span class="pill"><span class="pill-dot"></span>v1.2.
|
|
30
|
+
<span class="pill"><span class="pill-dot"></span>v1.2.5 docs</span>
|
|
31
31
|
<a class="button social" href="https://github.com/Vt-mmm/piagent" target="_blank" rel="noopener noreferrer" aria-label="Mở GitHub repository">
|
|
32
32
|
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
|
33
33
|
<path d="M7 17 17 7M9 7h8v8" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
<span>Pi Agent Platform</span>
|
|
28
28
|
</a>
|
|
29
29
|
<div class="top-actions">
|
|
30
|
-
<span class="pill"><span class="pill-dot"></span>v1.2.
|
|
30
|
+
<span class="pill"><span class="pill-dot"></span>v1.2.5 docs</span>
|
|
31
31
|
<a class="button social" href="https://github.com/Vt-mmm/piagent" target="_blank" rel="noopener noreferrer" aria-label="Mở GitHub repository">
|
|
32
32
|
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
|
33
33
|
<path d="M7 17 17 7M9 7h8v8" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
package/docs-site/mcp.html
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
<span>Pi Agent Platform</span>
|
|
28
28
|
</a>
|
|
29
29
|
<div class="top-actions">
|
|
30
|
-
<span class="pill"><span class="pill-dot"></span>v1.2.
|
|
30
|
+
<span class="pill"><span class="pill-dot"></span>v1.2.5 docs</span>
|
|
31
31
|
<a class="button social" href="https://github.com/Vt-mmm/piagent" target="_blank" rel="noopener noreferrer" aria-label="Mở GitHub repository">
|
|
32
32
|
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
|
33
33
|
<path d="M7 17 17 7M9 7h8v8" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
<span>Pi Agent Platform</span>
|
|
28
28
|
</a>
|
|
29
29
|
<div class="top-actions">
|
|
30
|
-
<span class="pill"><span class="pill-dot"></span>v1.2.
|
|
30
|
+
<span class="pill"><span class="pill-dot"></span>v1.2.5 docs</span>
|
|
31
31
|
<a class="button social" href="https://github.com/Vt-mmm/piagent" target="_blank" rel="noopener noreferrer" aria-label="Mở GitHub repository">
|
|
32
32
|
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
|
33
33
|
<path d="M7 17 17 7M9 7h8v8" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
package/docs-site/profiles.html
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
<span>Pi Agent Platform</span>
|
|
28
28
|
</a>
|
|
29
29
|
<div class="top-actions">
|
|
30
|
-
<span class="pill"><span class="pill-dot"></span>v1.2.
|
|
30
|
+
<span class="pill"><span class="pill-dot"></span>v1.2.5 docs</span>
|
|
31
31
|
<a class="button social" href="https://github.com/Vt-mmm/piagent" target="_blank" rel="noopener noreferrer" aria-label="Mở GitHub repository">
|
|
32
32
|
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
|
33
33
|
<path d="M7 17 17 7M9 7h8v8" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
<span>Pi Agent Platform</span>
|
|
28
28
|
</a>
|
|
29
29
|
<div class="top-actions">
|
|
30
|
-
<span class="pill"><span class="pill-dot"></span>v1.2.
|
|
30
|
+
<span class="pill"><span class="pill-dot"></span>v1.2.5 docs</span>
|
|
31
31
|
<a class="button social" href="https://github.com/Vt-mmm/piagent" target="_blank" rel="noopener noreferrer" aria-label="Mở GitHub repository">
|
|
32
32
|
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
|
33
33
|
<path d="M7 17 17 7M9 7h8v8" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
package/docs-site/runtime.html
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
<span>Pi Agent Platform</span>
|
|
28
28
|
</a>
|
|
29
29
|
<div class="top-actions">
|
|
30
|
-
<span class="pill"><span class="pill-dot"></span>v1.2.
|
|
30
|
+
<span class="pill"><span class="pill-dot"></span>v1.2.5 docs</span>
|
|
31
31
|
<a class="button social" href="https://github.com/Vt-mmm/piagent" target="_blank" rel="noopener noreferrer" aria-label="Mở GitHub repository">
|
|
32
32
|
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
|
33
33
|
<path d="M7 17 17 7M9 7h8v8" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
package/docs-site/scope.html
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
<span>Pi Agent Platform</span>
|
|
28
28
|
</a>
|
|
29
29
|
<div class="top-actions">
|
|
30
|
-
<span class="pill"><span class="pill-dot"></span>v1.2.
|
|
30
|
+
<span class="pill"><span class="pill-dot"></span>v1.2.5 docs</span>
|
|
31
31
|
<a class="button social" href="https://github.com/Vt-mmm/piagent" target="_blank" rel="noopener noreferrer" aria-label="Mở GitHub repository">
|
|
32
32
|
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
|
33
33
|
<path d="M7 17 17 7M9 7h8v8" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
package/docs-site/security.html
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
<span>Pi Agent Platform</span>
|
|
28
28
|
</a>
|
|
29
29
|
<div class="top-actions">
|
|
30
|
-
<span class="pill"><span class="pill-dot"></span>v1.2.
|
|
30
|
+
<span class="pill"><span class="pill-dot"></span>v1.2.5 docs</span>
|
|
31
31
|
<a class="button social" href="https://github.com/Vt-mmm/piagent" target="_blank" rel="noopener noreferrer" aria-label="Mở GitHub repository">
|
|
32
32
|
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
|
33
33
|
<path d="M7 17 17 7M9 7h8v8" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
package/docs-site/team.html
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
<span>Pi Agent Platform</span>
|
|
28
28
|
</a>
|
|
29
29
|
<div class="top-actions">
|
|
30
|
-
<span class="pill"><span class="pill-dot"></span>v1.2.
|
|
30
|
+
<span class="pill"><span class="pill-dot"></span>v1.2.5 docs</span>
|
|
31
31
|
<a class="button social" href="https://github.com/Vt-mmm/piagent" target="_blank" rel="noopener noreferrer" aria-label="Mở GitHub repository">
|
|
32
32
|
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
|
33
33
|
<path d="M7 17 17 7M9 7h8v8" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
package/docs-site/workflows.html
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
<span>Pi Agent Platform</span>
|
|
28
28
|
</a>
|
|
29
29
|
<div class="top-actions">
|
|
30
|
-
<span class="pill"><span class="pill-dot"></span>v1.2.
|
|
30
|
+
<span class="pill"><span class="pill-dot"></span>v1.2.5 docs</span>
|
|
31
31
|
<a class="button social" href="https://github.com/Vt-mmm/piagent" target="_blank" rel="noopener noreferrer" aria-label="Mở GitHub repository">
|
|
32
32
|
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
|
33
33
|
<path d="M7 17 17 7M9 7h8v8" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
package/package.json
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
// it asked for.
|
|
18
18
|
|
|
19
19
|
import fs from "node:fs";
|
|
20
|
+
import os from "node:os";
|
|
20
21
|
import path from "node:path";
|
|
21
22
|
import { spawnSync } from "node:child_process";
|
|
22
23
|
import { fileURLToPath } from "node:url";
|
|
@@ -39,13 +40,18 @@ Options:
|
|
|
39
40
|
--dry-run Print every command that would run, change nothing
|
|
40
41
|
--version <x.y.z> Update to an exact helper version instead of latest
|
|
41
42
|
--force Reinstall even when already on the target version
|
|
42
|
-
--project <path>
|
|
43
|
+
--project <path> Optional: after the global update, migrate and doctor this project
|
|
43
44
|
--no-host Do not touch the Pi host
|
|
44
45
|
--no-package Do not reinstall the Pi package
|
|
46
|
+
--no-migrate With --project, skip project state migration
|
|
47
|
+
--npm-prefix <path> Use this npm global prefix for host/helper installs
|
|
45
48
|
-h, --help Show this help
|
|
46
49
|
|
|
47
50
|
Anything after -- is passed through to piagent-install, for example:
|
|
48
51
|
piagent-update -- --no-mcp
|
|
52
|
+
|
|
53
|
+
Bootstrap a machine that does not have piagent-update yet:
|
|
54
|
+
npm exec -y --package @piagent/platform@X.Y.Z -- piagent-update --version X.Y.Z --force
|
|
49
55
|
`;
|
|
50
56
|
}
|
|
51
57
|
|
|
@@ -81,6 +87,8 @@ function parseArguments(argv) {
|
|
|
81
87
|
project: undefined,
|
|
82
88
|
host: true,
|
|
83
89
|
package: true,
|
|
90
|
+
migrate: true,
|
|
91
|
+
npmPrefix: undefined,
|
|
84
92
|
passthrough: []
|
|
85
93
|
};
|
|
86
94
|
|
|
@@ -111,6 +119,15 @@ function parseArguments(argv) {
|
|
|
111
119
|
case "--no-package":
|
|
112
120
|
options.package = false;
|
|
113
121
|
break;
|
|
122
|
+
case "--no-migrate":
|
|
123
|
+
options.migrate = false;
|
|
124
|
+
break;
|
|
125
|
+
case "--npm-prefix": {
|
|
126
|
+
const value = argv[index += 1];
|
|
127
|
+
if (!value) fail("--npm-prefix needs a path", EXIT_USAGE);
|
|
128
|
+
options.npmPrefix = value;
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
114
131
|
case "--version": {
|
|
115
132
|
const value = normalizeVersion(argv[index += 1]);
|
|
116
133
|
if (!isReleaseVersion(value)) fail(`--version needs an exact release such as 1.1.4, got ${argv[index] ?? "nothing"}`, EXIT_USAGE);
|
|
@@ -140,11 +157,178 @@ function run(command, args, { capture = false } = {}) {
|
|
|
140
157
|
return { ok: result.status === 0, stdout: result.stdout ?? "", stderr: result.stderr ?? "" };
|
|
141
158
|
}
|
|
142
159
|
|
|
160
|
+
function expandHome(value) {
|
|
161
|
+
if (value === "~") return os.homedir();
|
|
162
|
+
if (value?.startsWith("~/")) return path.join(os.homedir(), value.slice(2));
|
|
163
|
+
return value;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function configuredNpmPrefix() {
|
|
167
|
+
const result = run("npm", ["config", "get", "prefix"], { capture: true });
|
|
168
|
+
if (!result.ok) return undefined;
|
|
169
|
+
const prefix = result.stdout.trim();
|
|
170
|
+
return prefix && prefix !== "undefined" && prefix !== "null" ? path.resolve(expandHome(prefix)) : undefined;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function fallbackNpmRoot(prefix) {
|
|
174
|
+
return process.platform === "win32"
|
|
175
|
+
? path.join(prefix, "node_modules")
|
|
176
|
+
: path.join(prefix, "lib", "node_modules");
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function npmRoot(prefix) {
|
|
180
|
+
const args = ["root", "-g"];
|
|
181
|
+
if (prefix) args.push("--prefix", prefix);
|
|
182
|
+
const result = run("npm", args, { capture: true });
|
|
183
|
+
if (result.ok && result.stdout.trim()) return path.resolve(expandHome(result.stdout.trim()));
|
|
184
|
+
return prefix ? fallbackNpmRoot(prefix) : undefined;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function nearestExistingPath(target) {
|
|
188
|
+
let current = target;
|
|
189
|
+
while (current && !fs.existsSync(current)) {
|
|
190
|
+
const parent = path.dirname(current);
|
|
191
|
+
if (parent === current) return undefined;
|
|
192
|
+
current = parent;
|
|
193
|
+
}
|
|
194
|
+
return current || undefined;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function canWriteOrCreate(target) {
|
|
198
|
+
const nearest = nearestExistingPath(target);
|
|
199
|
+
if (!nearest) return false;
|
|
200
|
+
try {
|
|
201
|
+
fs.accessSync(nearest, fs.constants.W_OK);
|
|
202
|
+
return true;
|
|
203
|
+
} catch {
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function userNpmPrefix() {
|
|
209
|
+
return path.join(os.homedir(), ".pi", "npm-global");
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function binForPrefix(prefix) {
|
|
213
|
+
return process.platform === "win32" ? prefix : path.join(prefix, "bin");
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function prependPath(directory) {
|
|
217
|
+
process.env.PATH = `${directory}${path.delimiter}${process.env.PATH ?? ""}`;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function resolveNpmInstallTarget(options, needsGlobalInstall) {
|
|
221
|
+
const explicitPrefix = options.npmPrefix ? path.resolve(expandHome(options.npmPrefix)) : undefined;
|
|
222
|
+
if (explicitPrefix) {
|
|
223
|
+
if (!options.dryRun) fs.mkdirSync(explicitPrefix, { recursive: true });
|
|
224
|
+
return {
|
|
225
|
+
prefix: explicitPrefix,
|
|
226
|
+
root: npmRoot(explicitPrefix),
|
|
227
|
+
bin: binForPrefix(explicitPrefix),
|
|
228
|
+
reason: "explicit"
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const defaultPrefix = configuredNpmPrefix();
|
|
233
|
+
const defaultRoot = npmRoot(defaultPrefix);
|
|
234
|
+
if (!needsGlobalInstall || (defaultRoot && canWriteOrCreate(defaultRoot))) {
|
|
235
|
+
return { prefix: undefined, root: defaultRoot, bin: undefined, reason: "default" };
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const prefix = userNpmPrefix();
|
|
239
|
+
if (!options.dryRun) fs.mkdirSync(prefix, { recursive: true });
|
|
240
|
+
return {
|
|
241
|
+
prefix,
|
|
242
|
+
root: npmRoot(prefix),
|
|
243
|
+
bin: binForPrefix(prefix),
|
|
244
|
+
reason: "user-prefix",
|
|
245
|
+
blockedRoot: defaultRoot
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function npmInstallArgs(specifier, npmTarget) {
|
|
250
|
+
const args = ["install", "-g", "--ignore-scripts"];
|
|
251
|
+
if (npmTarget.prefix) args.push("--prefix", npmTarget.prefix);
|
|
252
|
+
args.push(specifier);
|
|
253
|
+
return args;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function helperRootFromNpmTarget(npmTarget) {
|
|
257
|
+
return npmTarget.root ? path.join(npmTarget.root, "@piagent", "platform") : undefined;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function helperVersionAt(root) {
|
|
261
|
+
return root ? readJson(path.join(root, "package.json"))?.version : undefined;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function resolveInstalledHelperRoot(targetHelper, npmTarget) {
|
|
265
|
+
const npmHelperRoot = helperRootFromNpmTarget(npmTarget);
|
|
266
|
+
if (helperVersionAt(npmHelperRoot) === targetHelper) return npmHelperRoot;
|
|
267
|
+
if (helperVersionAt(platformRoot) === targetHelper) return platformRoot;
|
|
268
|
+
const checked = [];
|
|
269
|
+
for (const root of [npmHelperRoot, platformRoot]) {
|
|
270
|
+
if (!root || checked.some((entry) => entry.root === root)) continue;
|
|
271
|
+
checked.push({ root, version: helperVersionAt(root) ?? "nothing" });
|
|
272
|
+
}
|
|
273
|
+
const details = checked.map((entry) => `${entry.root} reports ${entry.version}`).join("; ");
|
|
274
|
+
fail(`installed ${HELPER_PACKAGE}@${targetHelper}, but ${details || "the helper paths did not report that version"}. `
|
|
275
|
+
+ "The Pi package was left untouched; rerun once the helper is correct.");
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function parseJsonOutput(result, label) {
|
|
279
|
+
try {
|
|
280
|
+
return JSON.parse(result.stdout.trim() || "{}");
|
|
281
|
+
} catch {
|
|
282
|
+
fail(`${label} did not return valid JSON:\n${result.stdout.trim()}`);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function summarizeMigration(report, dryRun) {
|
|
287
|
+
const renamed = report.renamed?.length ?? 0;
|
|
288
|
+
const removed = report.removedOld?.length ?? 0;
|
|
289
|
+
const rewrote = report.rewrote?.length ?? report.wouldRewrite?.length ?? 0;
|
|
290
|
+
const wouldRename = report.wouldRename?.length ?? 0;
|
|
291
|
+
const alreadyMigrated = report.alreadyMigrated?.length ?? 0;
|
|
292
|
+
|
|
293
|
+
if (dryRun) {
|
|
294
|
+
const planned = wouldRename + rewrote + alreadyMigrated;
|
|
295
|
+
return planned > 0
|
|
296
|
+
? `project migration: would update legacy layout (${wouldRename} rename, ${rewrote} rewrite, ${alreadyMigrated} already copied)`
|
|
297
|
+
: "project migration: already current";
|
|
298
|
+
}
|
|
299
|
+
if (report.migrated === false) return "project migration: already current";
|
|
300
|
+
return `project migration: applied (${renamed} rename, ${rewrote} rewrite, ${removed} old path removed)`;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
function runProjectMigration(project, options, activePlatformRoot) {
|
|
304
|
+
const migrator = path.join(activePlatformRoot, "scripts/migrate-project-state.mjs");
|
|
305
|
+
if (!options.dryRun && !fs.existsSync(migrator)) {
|
|
306
|
+
fail(`the updated helper has no project migrator at ${migrator}`);
|
|
307
|
+
}
|
|
308
|
+
const args = options.dryRun
|
|
309
|
+
? [migrator, project]
|
|
310
|
+
: [migrator, project, "--apply", "--remove-old"];
|
|
311
|
+
describeStep(options.dryRun, process.execPath, args);
|
|
312
|
+
const result = run(process.execPath, args, { capture: true });
|
|
313
|
+
if (!result.ok) fail(`project migration failed:\n${result.stderr.trim() || result.stdout.trim()}`);
|
|
314
|
+
const report = parseJsonOutput(result, "project migration");
|
|
315
|
+
if ((report.skipped?.length ?? 0) > 0) {
|
|
316
|
+
fail(`project migration skipped protected entries: ${report.skipped.map((entry) => `${entry.path} (${entry.reason})`).join(", ")}`);
|
|
317
|
+
}
|
|
318
|
+
console.log(` ${summarizeMigration(report, options.dryRun)}`);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
function normalizeNpmViewResult(value) {
|
|
322
|
+
if (!Array.isArray(value)) return value;
|
|
323
|
+
return value.length === 1 ? value[0] : undefined;
|
|
324
|
+
}
|
|
325
|
+
|
|
143
326
|
function npmView(specifier, field) {
|
|
144
327
|
const result = run("npm", ["view", specifier, field, "--json"], { capture: true });
|
|
145
328
|
if (!result.ok) return undefined;
|
|
146
329
|
try {
|
|
147
|
-
|
|
330
|
+
const raw = result.stdout.trim();
|
|
331
|
+
return raw ? normalizeNpmViewResult(JSON.parse(raw)) : undefined;
|
|
148
332
|
} catch {
|
|
149
333
|
return undefined;
|
|
150
334
|
}
|
|
@@ -196,6 +380,9 @@ function main() {
|
|
|
196
380
|
console.log(` helper: ${currentHelper} -> ${targetHelper}${helperNeedsChange ? "" : " (already current)"}`);
|
|
197
381
|
console.log(` host: ${currentHost ?? "not installed"} -> ${targetHost}${hostNeedsChange ? "" : " (already current)"}`);
|
|
198
382
|
console.log(` package: reinstalled from v${targetHelper} as a resolved commit${options.package ? "" : " (skipped)"}`);
|
|
383
|
+
if (options.project) {
|
|
384
|
+
console.log(` project: ${path.resolve(options.project)} (${options.migrate ? "migrate + doctor" : "doctor only"})`);
|
|
385
|
+
}
|
|
199
386
|
|
|
200
387
|
if (options.check) {
|
|
201
388
|
const pending = [helperNeedsChange && "helper", hostNeedsChange && "host"].filter(Boolean);
|
|
@@ -203,7 +390,7 @@ function main() {
|
|
|
203
390
|
return;
|
|
204
391
|
}
|
|
205
392
|
|
|
206
|
-
if (!helperNeedsChange && !hostNeedsChange && !options.package) {
|
|
393
|
+
if (!helperNeedsChange && !hostNeedsChange && !options.package && !options.project) {
|
|
207
394
|
console.log("\nNothing to do.");
|
|
208
395
|
return;
|
|
209
396
|
}
|
|
@@ -215,33 +402,38 @@ function main() {
|
|
|
215
402
|
+ ` bash ${path.join(platformRoot, "scripts/install-global.sh")} --local`);
|
|
216
403
|
}
|
|
217
404
|
|
|
405
|
+
let activePlatformRoot = platformRoot;
|
|
406
|
+
const npmTarget = resolveNpmInstallTarget(options, hostNeedsChange || helperNeedsChange);
|
|
407
|
+
if (npmTarget.bin) prependPath(npmTarget.bin);
|
|
408
|
+
if (npmTarget.reason === "user-prefix") {
|
|
409
|
+
console.log(` npm: default global root is not writable (${npmTarget.blockedRoot ?? "unknown"}); using ${npmTarget.prefix}`);
|
|
410
|
+
} else if (npmTarget.reason === "explicit") {
|
|
411
|
+
console.log(` npm: using explicit global prefix ${npmTarget.prefix}`);
|
|
412
|
+
}
|
|
413
|
+
|
|
218
414
|
// Host first: piagent-install refuses to run against a host that does not match
|
|
219
415
|
// the version its package.json pins, so a helper installed ahead of the host
|
|
220
416
|
// would fail on its very next step.
|
|
221
417
|
if (hostNeedsChange) {
|
|
222
|
-
const args =
|
|
418
|
+
const args = npmInstallArgs(`${HOST_PACKAGE}@${targetHost}`, npmTarget);
|
|
223
419
|
describeStep(options.dryRun, "npm", args);
|
|
224
420
|
if (!options.dryRun && !run("npm", args).ok) fail(`could not install ${HOST_PACKAGE}@${targetHost}`);
|
|
225
421
|
}
|
|
226
422
|
|
|
227
423
|
if (helperNeedsChange) {
|
|
228
|
-
const args =
|
|
424
|
+
const args = npmInstallArgs(`${HELPER_PACKAGE}@${targetHelper}`, npmTarget);
|
|
229
425
|
describeStep(options.dryRun, "npm", args);
|
|
230
426
|
if (!options.dryRun) {
|
|
231
427
|
if (!run("npm", args).ok) fail(`could not install ${HELPER_PACKAGE}@${targetHelper}`);
|
|
232
428
|
// The helper has just replaced itself on disk. Everything after this point
|
|
233
429
|
// runs the newly installed scripts, so confirm they are the ones asked for
|
|
234
430
|
// rather than trusting that npm did what it said.
|
|
235
|
-
|
|
236
|
-
if (landed !== targetHelper) {
|
|
237
|
-
fail(`installed ${HELPER_PACKAGE}@${targetHelper} but ${platformRoot} reports ${landed ?? "nothing"}. `
|
|
238
|
-
+ "The Pi package was left untouched; rerun once the helper is correct.");
|
|
239
|
-
}
|
|
431
|
+
activePlatformRoot = resolveInstalledHelperRoot(targetHelper, npmTarget);
|
|
240
432
|
}
|
|
241
433
|
}
|
|
242
434
|
|
|
243
435
|
if (options.package) {
|
|
244
|
-
const installer = path.join(
|
|
436
|
+
const installer = path.join(activePlatformRoot, "scripts/install-global.sh");
|
|
245
437
|
if (!options.dryRun && !fs.existsSync(installer)) {
|
|
246
438
|
fail(`the updated helper has no installer at ${installer}`);
|
|
247
439
|
}
|
|
@@ -251,12 +443,22 @@ function main() {
|
|
|
251
443
|
}
|
|
252
444
|
|
|
253
445
|
if (options.project) {
|
|
254
|
-
|
|
446
|
+
if (options.migrate) {
|
|
447
|
+
runProjectMigration(options.project, options, activePlatformRoot);
|
|
448
|
+
} else {
|
|
449
|
+
console.log(" project migration: skipped");
|
|
450
|
+
}
|
|
451
|
+
const doctor = path.join(activePlatformRoot, "scripts/team-doctor.sh");
|
|
255
452
|
const args = [doctor, options.project, "--strict-share"];
|
|
256
453
|
describeStep(options.dryRun, "bash", args);
|
|
257
454
|
if (!options.dryRun && !run("bash", args).ok) fail("the team doctor reported a problem");
|
|
258
455
|
}
|
|
259
456
|
|
|
457
|
+
if (npmTarget.reason === "user-prefix") {
|
|
458
|
+
console.log(`\nPATH note: add this once if your shell cannot find piagent-* commands later:`);
|
|
459
|
+
console.log(` export PATH="${npmTarget.bin}:$PATH"`);
|
|
460
|
+
}
|
|
461
|
+
|
|
260
462
|
console.log(options.dryRun
|
|
261
463
|
? `\nDRY RUN: nothing was installed. Rerun without --dry-run to apply v${targetHelper}.`
|
|
262
464
|
: `\nPASS: updated to v${targetHelper}.`);
|