@piagent/platform 1.51.2 → 1.52.2
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 +37 -0
- package/docs/command-reference-vietnamese.md +2 -2
- package/docs/distribution-standard.md +6 -6
- package/docs/harness-conformance.md +13 -13
- package/docs/operator-manual-vietnamese.md +7 -7
- package/docs/publishing-for-teams.md +3 -0
- package/docs/release-install-policy.md +2 -2
- package/docs/team-onboarding.md +2 -2
- package/docs-site/architecture.html +1 -1
- package/docs-site/assets/search-en.json +1 -1
- package/docs-site/assets/search-vi.json +1 -1
- package/docs-site/benchmark.html +1 -1
- package/docs-site/commands.html +1 -1
- package/docs-site/context-engine.html +1 -1
- package/docs-site/ecosystem.html +1 -1
- package/docs-site/en/architecture.html +1 -1
- package/docs-site/en/benchmark.html +1 -1
- package/docs-site/en/commands.html +1 -1
- package/docs-site/en/context-engine.html +1 -1
- package/docs-site/en/ecosystem.html +1 -1
- package/docs-site/en/index.html +15 -15
- package/docs-site/en/mcp-approval.html +1 -1
- package/docs-site/en/mcp-auth.html +1 -1
- package/docs-site/en/mcp-servers.html +1 -1
- package/docs-site/en/mcp.html +1 -1
- package/docs-site/en/permissions.html +1 -1
- package/docs-site/en/profiles.html +1 -1
- package/docs-site/en/quickstart.html +1 -1
- package/docs-site/en/runtime.html +1 -1
- package/docs-site/en/scope.html +1 -1
- package/docs-site/en/security.html +1 -1
- package/docs-site/en/team.html +1 -1
- package/docs-site/en/update.html +3 -3
- package/docs-site/en/whats-new.html +74 -42
- package/docs-site/en/windows.html +1 -1
- package/docs-site/en/workflows.html +1 -1
- package/docs-site/index.html +15 -15
- 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/releases.json +84 -0
- 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/update.html +3 -3
- package/docs-site/whats-new.html +74 -42
- package/docs-site/windows.html +1 -1
- package/docs-site/workflows.html +1 -1
- package/evals/private-holdout-v1/public-exposure.v2.json +2 -2
- package/package.json +1 -1
- package/packages/piagent-core/managed/copies.mjs +15 -10
- package/packages/piagent-core/managed/general-clone.mjs +111 -0
- package/packages/piagent-core/managed/helper-roles.mjs +33 -42
- package/packages/piagent-core/managed/helper-run.mjs +21 -15
- package/packages/piagent-core/managed/helper-settlement.mjs +7 -11
- package/packages/piagent-core/managed/language-environment.mjs +6 -2
- package/packages/piagent-core/managed/ledger.mjs +11 -10
- package/packages/piagent-core/managed/objections.mjs +8 -25
- package/packages/piagent-core/managed/role-names.mjs +6 -0
- package/packages/piagent-core/managed/session.mjs +12 -13
- package/packages/piagent-core/managed/tool-boundary.mjs +4 -4
- package/packages/piagent-core/managed/workflow.mjs +2 -39
- package/packages/piagent-core/package.json +1 -1
- package/packages/piagent-core/runtime/managed-failure.d.mts +1 -1
- package/packages/piagent-core/runtime/managed-failure.mjs +3 -3
- package/packages/piagent-webui/dist/client/assets/{App-C9tlGPMb.js → App-DQwj6l-F.js} +1 -1
- package/packages/piagent-webui/dist/client/assets/{GatewayApp-Dvo96qoX.js → GatewayApp-CP8GpZsK.js} +3 -3
- package/packages/piagent-webui/dist/client/assets/{InspectionApp-CGgHsOyC.js → InspectionApp-BZqu1pjw.js} +1 -1
- package/packages/piagent-webui/dist/client/assets/{SessionAgentWorkspace-n8UMMcrP.js → SessionAgentWorkspace-4nJSbzE9.js} +1 -1
- package/packages/piagent-webui/dist/client/assets/{SessionInspectorDrawer-B62kkr8J.js → SessionInspectorDrawer-DEb_TBE8.js} +2 -2
- package/packages/piagent-webui/dist/client/assets/SettingsNavigation-BF4X5xkR.js +3 -0
- package/packages/piagent-webui/dist/client/assets/{SettingsPage-DKg0SfZQ.js → SettingsPage-CS8LsdhS.js} +1 -1
- package/packages/piagent-webui/dist/client/assets/{TerminalPanel-BPTVsNjP.js → TerminalPanel-CiF2_woF.js} +1 -1
- package/packages/piagent-webui/dist/client/assets/{WorkspaceCodeEditor-BHGFFBc2.js → WorkspaceCodeEditor-OFxSEbBs.js} +1 -1
- package/packages/piagent-webui/dist/client/assets/{WorkspaceExplorer-nd4kghwK.js → WorkspaceExplorer-ZYIi-FWr.js} +3 -3
- package/packages/piagent-webui/dist/client/assets/{index-BiLVX8S-.js → index-CfJC4Unf.js} +2 -2
- package/packages/piagent-webui/dist/client/index.html +1 -1
- package/packages/piagent-webui/server/transcript-projection.ts +3 -3
- package/packages/piagent-webui/shared/company-copy.ts +3 -1
- package/packages/piagent-webui/shared/turn-end.ts +1 -1
- package/schemas/piagent-webui/transcript-v1.schema.json +3 -3
- package/scripts/runtime-advisory-exceptions.json +27 -27
- package/packages/piagent-webui/dist/client/assets/SettingsNavigation-BZijmuPt.js +0 -3
package/docs-site/releases.json
CHANGED
|
@@ -1,4 +1,88 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "1.52.2",
|
|
4
|
+
"date": "2026-11-09",
|
|
5
|
+
"status": "stable",
|
|
6
|
+
"title": {
|
|
7
|
+
"en": "Asking for several general helpers runs one instead of a refusal",
|
|
8
|
+
"vi": "Xin nhiều helper general thì chạy một, không còn bị từ chối"
|
|
9
|
+
},
|
|
10
|
+
"summary": {
|
|
11
|
+
"en": "When a member asked for several helpers, the main agent called general several at once, was refused and kept retrying, so general never ran. Now one general runs and the main agent merges its ref before the next share.",
|
|
12
|
+
"vi": "Khi thành viên xin nhiều helper, agent chính gọi nhiều general cùng lúc, bị từ chối rồi gọi lại mãi nên general không chạy. Giờ một general chạy và agent chính merge ref của nó trước phần việc tiếp theo."
|
|
13
|
+
},
|
|
14
|
+
"requires": {
|
|
15
|
+
"en": "Agent Studio 0.51.0 and Agent Watch 0.15.20 (Windows 0.1.19) for the advisor and general helpers",
|
|
16
|
+
"vi": "Agent Studio 0.51.0 và Agent Watch 0.15.20 (Windows 0.1.19) để dùng helper advisor và general"
|
|
17
|
+
},
|
|
18
|
+
"items": [
|
|
19
|
+
{
|
|
20
|
+
"kind": "fixed",
|
|
21
|
+
"en": "A delegate call asking for several general helpers runs one, says why, and asks the main agent to merge its ref and call general again.",
|
|
22
|
+
"vi": "Lệnh gọi xin nhiều helper general chạy một, nói rõ lý do và bảo agent chính merge ref rồi gọi general tiếp."
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"version": "1.52.1",
|
|
28
|
+
"date": "2026-11-09",
|
|
29
|
+
"status": "unpublished",
|
|
30
|
+
"title": {
|
|
31
|
+
"en": "Asking for several general helpers runs one instead of a refusal",
|
|
32
|
+
"vi": "Xin nhiều helper general thì chạy một, không còn bị từ chối"
|
|
33
|
+
},
|
|
34
|
+
"summary": {
|
|
35
|
+
"en": "Tagged but not published: the capability lock recorded the wrong package source and failed the release check. Superseded by 1.52.2.",
|
|
36
|
+
"vi": "Đã tag nhưng chưa publish: capability lock ghi sai nguồn package nên kiểm tra release fail. Thay bằng 1.52.2."
|
|
37
|
+
},
|
|
38
|
+
"requires": null,
|
|
39
|
+
"items": [
|
|
40
|
+
{
|
|
41
|
+
"kind": "fixed",
|
|
42
|
+
"en": "A delegate call asking for several general helpers runs one, says why, and asks the main agent to merge its ref and call general again.",
|
|
43
|
+
"vi": "Lệnh gọi xin nhiều helper general chạy một, nói rõ lý do và bảo agent chính merge ref rồi gọi general tiếp."
|
|
44
|
+
}
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"version": "1.52.0",
|
|
49
|
+
"date": "2026-11-08",
|
|
50
|
+
"status": "stable",
|
|
51
|
+
"title": {
|
|
52
|
+
"en": "Company helpers get an advisor and a general helper that works in its own clone",
|
|
53
|
+
"vi": "Helper công ty có thêm advisor và general làm việc trong bản clone riêng"
|
|
54
|
+
},
|
|
55
|
+
"summary": {
|
|
56
|
+
"en": "The company Harness declares every helper, and the main agent now calls them by working names: explore, scout, advisor, general and review. General changes code only in its own clone and hands back a git ref to merge.",
|
|
57
|
+
"vi": "Harness công ty khai báo mọi helper, và agent chính gọi chúng bằng tên công việc: explore, scout, advisor, general và review. General chỉ sửa code trong bản clone riêng và trả về một git ref để merge."
|
|
58
|
+
},
|
|
59
|
+
"requires": {
|
|
60
|
+
"en": "Agent Studio 0.51.0 and Agent Watch 0.15.20 (Windows 0.1.19) for the advisor and general helpers",
|
|
61
|
+
"vi": "Agent Studio 0.51.0 và Agent Watch 0.15.20 (Windows 0.1.19) để dùng helper advisor và general"
|
|
62
|
+
},
|
|
63
|
+
"items": [
|
|
64
|
+
{
|
|
65
|
+
"kind": "new",
|
|
66
|
+
"en": "advisor gives a second opinion before a hard decision: a recommendation, the options it rejected and the risks.",
|
|
67
|
+
"vi": "advisor cho ý kiến thứ hai trước quyết định khó: khuyến nghị, các phương án đã loại và rủi ro."
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"kind": "new",
|
|
71
|
+
"en": "general takes large work on macOS: it edits, runs checks and commits in its own clone, never your files, and returns refs/general/<id>.",
|
|
72
|
+
"vi": "general nhận việc lớn trên macOS: sửa, chạy check và commit trong clone riêng, không đụng file của bạn, rồi trả về refs/general/<id>."
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"kind": "breaking",
|
|
76
|
+
"en": "Helpers are called explore, scout, advisor, general and review; the old names research and verify are gone, and the verify helper is removed.",
|
|
77
|
+
"vi": "Helper được gọi là explore, scout, advisor, general và review; tên cũ research và verify không còn, helper verify bị bỏ."
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"kind": "fixed",
|
|
81
|
+
"en": "The WebUI names an advisor or general failure correctly instead of calling it a review failure.",
|
|
82
|
+
"vi": "WebUI ghi đúng lỗi của advisor hay general thay vì gọi là lỗi của review."
|
|
83
|
+
}
|
|
84
|
+
]
|
|
85
|
+
},
|
|
2
86
|
{
|
|
3
87
|
"version": "1.51.2",
|
|
4
88
|
"date": "2026-11-03",
|
package/docs-site/runtime.html
CHANGED
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
<span class="brand-mark"><img src="/assets/piagent-logo.svg" alt="" width="28" height="28" /></span>
|
|
38
38
|
<span class="brand-name"><b>Piagent</b> <span>Platform</span></span>
|
|
39
39
|
</a>
|
|
40
|
-
<a class="version-badge" href="/whats-new" data-docs-version="v1.
|
|
40
|
+
<a class="version-badge" href="/whats-new" data-docs-version="v1.52.2" title="v1.52.2 docs · VI"><span class="dot"></span>v1.52.2</a>
|
|
41
41
|
<nav class="top-nav" aria-label="Tài liệu">
|
|
42
42
|
<a href="/quickstart">Tài liệu</a>
|
|
43
43
|
<a href="/whats-new">Changelog</a>
|
package/docs-site/scope.html
CHANGED
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
<span class="brand-mark"><img src="/assets/piagent-logo.svg" alt="" width="28" height="28" /></span>
|
|
38
38
|
<span class="brand-name"><b>Piagent</b> <span>Platform</span></span>
|
|
39
39
|
</a>
|
|
40
|
-
<a class="version-badge" href="/whats-new" data-docs-version="v1.
|
|
40
|
+
<a class="version-badge" href="/whats-new" data-docs-version="v1.52.2" title="v1.52.2 docs · VI"><span class="dot"></span>v1.52.2</a>
|
|
41
41
|
<nav class="top-nav" aria-label="Tài liệu">
|
|
42
42
|
<a href="/quickstart">Tài liệu</a>
|
|
43
43
|
<a href="/whats-new">Changelog</a>
|
package/docs-site/security.html
CHANGED
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
<span class="brand-mark"><img src="/assets/piagent-logo.svg" alt="" width="28" height="28" /></span>
|
|
38
38
|
<span class="brand-name"><b>Piagent</b> <span>Platform</span></span>
|
|
39
39
|
</a>
|
|
40
|
-
<a class="version-badge" href="/whats-new" data-docs-version="v1.
|
|
40
|
+
<a class="version-badge" href="/whats-new" data-docs-version="v1.52.2" title="v1.52.2 docs · VI"><span class="dot"></span>v1.52.2</a>
|
|
41
41
|
<nav class="top-nav" aria-label="Tài liệu">
|
|
42
42
|
<a href="/quickstart">Tài liệu</a>
|
|
43
43
|
<a href="/whats-new">Changelog</a>
|
package/docs-site/team.html
CHANGED
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
<span class="brand-mark"><img src="/assets/piagent-logo.svg" alt="" width="28" height="28" /></span>
|
|
38
38
|
<span class="brand-name"><b>Piagent</b> <span>Platform</span></span>
|
|
39
39
|
</a>
|
|
40
|
-
<a class="version-badge" href="/whats-new" data-docs-version="v1.
|
|
40
|
+
<a class="version-badge" href="/whats-new" data-docs-version="v1.52.2" title="v1.52.2 docs · VI"><span class="dot"></span>v1.52.2</a>
|
|
41
41
|
<nav class="top-nav" aria-label="Tài liệu">
|
|
42
42
|
<a href="/quickstart">Tài liệu</a>
|
|
43
43
|
<a href="/whats-new">Changelog</a>
|
package/docs-site/update.html
CHANGED
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
<span class="brand-mark"><img src="/assets/piagent-logo.svg" alt="" width="28" height="28" /></span>
|
|
38
38
|
<span class="brand-name"><b>Piagent</b> <span>Platform</span></span>
|
|
39
39
|
</a>
|
|
40
|
-
<a class="version-badge" href="/whats-new" data-docs-version="v1.
|
|
40
|
+
<a class="version-badge" href="/whats-new" data-docs-version="v1.52.2" title="v1.52.2 docs · VI"><span class="dot"></span>v1.52.2</a>
|
|
41
41
|
<nav class="top-nav" aria-label="Tài liệu">
|
|
42
42
|
<a href="/quickstart">Tài liệu</a>
|
|
43
43
|
<a href="/whats-new">Changelog</a>
|
|
@@ -153,9 +153,9 @@
|
|
|
153
153
|
<h2 id="pin-cho-team">Pin một bản cho cả team</h2>
|
|
154
154
|
<p>Khi rollout cho team, cài đúng bản Pi host và đúng bản platform, rồi chạy installer ở chế độ stable. Bước <code>--dry-run</code> in ra những gì sẽ đổi.</p>
|
|
155
155
|
<div class="command-card">
|
|
156
|
-
<header><span>Cài pin theo bản</span><button class="clip-btn" data-clip="npm install -g --ignore-scripts @earendil-works/pi-coding-agent@1.3.0 npm install -g --ignore-scripts @piagent/platform@1.
|
|
156
|
+
<header><span>Cài pin theo bản</span><button class="clip-btn" data-clip="npm install -g --ignore-scripts @earendil-works/pi-coding-agent@1.3.0 npm install -g --ignore-scripts @piagent/platform@1.52.2 piagent-install --stable --dry-run piagent-install --stable">Lấy lệnh</button></header>
|
|
157
157
|
<pre><code>npm install -g --ignore-scripts @earendil-works/pi-coding-agent@1.3.0
|
|
158
|
-
npm install -g --ignore-scripts @piagent/platform@1.
|
|
158
|
+
npm install -g --ignore-scripts @piagent/platform@1.52.2
|
|
159
159
|
piagent-install --stable --dry-run
|
|
160
160
|
piagent-install --stable</code></pre>
|
|
161
161
|
</div>
|
package/docs-site/whats-new.html
CHANGED
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
<span class="brand-mark"><img src="/assets/piagent-logo.svg" alt="" width="28" height="28" /></span>
|
|
38
38
|
<span class="brand-name"><b>Piagent</b> <span>Platform</span></span>
|
|
39
39
|
</a>
|
|
40
|
-
<a class="version-badge" href="/whats-new" data-docs-version="v1.
|
|
40
|
+
<a class="version-badge" href="/whats-new" data-docs-version="v1.52.2" title="v1.52.2 docs · VI"><span class="dot"></span>v1.52.2</a>
|
|
41
41
|
<nav class="top-nav" aria-label="Tài liệu">
|
|
42
42
|
<a href="/quickstart">Tài liệu</a>
|
|
43
43
|
<a href="/whats-new" aria-current="page">Changelog</a>
|
|
@@ -108,7 +108,42 @@
|
|
|
108
108
|
<div class="release-filter" role="toolbar" aria-label="Lọc theo loại thay đổi"><button type="button" data-filter-kind="all" aria-pressed="true">Tất cả</button><button type="button" data-filter-kind="new" aria-pressed="false">Mới</button><button type="button" data-filter-kind="improved" aria-pressed="false">Cải thiện</button><button type="button" data-filter-kind="fixed" aria-pressed="false">Sửa lỗi</button><button type="button" data-filter-kind="security" aria-pressed="false">Bảo mật</button></div>
|
|
109
109
|
<section class="section releases" data-releases>
|
|
110
110
|
<h2 id="latest" class="sr-only">Mới nhất</h2>
|
|
111
|
-
<article class="release latest" id="v1-
|
|
111
|
+
<article class="release latest" id="v1-52-2" data-release>
|
|
112
|
+
<div class="release-meta"><a class="release-version" href="#v1-52-2">v1.52.2</a><time class="release-date" datetime="2026-11-09">09/11/2026</time></div>
|
|
113
|
+
<div class="release-body">
|
|
114
|
+
<h3 data-toc-skip id="v1-52-2-title">Xin nhiều helper general thì chạy một, không còn bị từ chối</h3>
|
|
115
|
+
<p>Khi thành viên xin nhiều helper, agent chính gọi nhiều general cùng lúc, bị từ chối rồi gọi lại mãi nên general không chạy. Giờ một general chạy và agent chính merge ref của nó trước phần việc tiếp theo.</p>
|
|
116
|
+
<ul class="release-items">
|
|
117
|
+
<li data-kind="fixed"><span class="kind kind-fixed">Sửa lỗi</span><span>Lệnh gọi xin nhiều helper general chạy một, nói rõ lý do và bảo agent chính merge ref rồi gọi general tiếp.</span></li>
|
|
118
|
+
</ul>
|
|
119
|
+
<p class="release-requires"><strong>Cần:</strong> Agent Studio 0.51.0 và Agent Watch 0.15.20 (Windows 0.1.19) để dùng helper advisor và general</p>
|
|
120
|
+
</div>
|
|
121
|
+
</article>
|
|
122
|
+
<article class="release" id="v1-52-1" data-release>
|
|
123
|
+
<div class="release-meta"><a class="release-version" href="#v1-52-1">v1.52.1</a><time class="release-date" datetime="2026-11-09">09/11/2026</time></div>
|
|
124
|
+
<div class="release-body">
|
|
125
|
+
<h3 data-toc-skip id="v1-52-1-title">Xin nhiều helper general thì chạy một, không còn bị từ chối <span class="tag">không phát hành</span></h3>
|
|
126
|
+
<p>Đã tag nhưng chưa publish: capability lock ghi sai nguồn package nên kiểm tra release fail. Thay bằng 1.52.2.</p>
|
|
127
|
+
<ul class="release-items">
|
|
128
|
+
<li data-kind="fixed"><span class="kind kind-fixed">Sửa lỗi</span><span>Lệnh gọi xin nhiều helper general chạy một, nói rõ lý do và bảo agent chính merge ref rồi gọi general tiếp.</span></li>
|
|
129
|
+
</ul>
|
|
130
|
+
</div>
|
|
131
|
+
</article>
|
|
132
|
+
<article class="release" id="v1-52-0" data-release>
|
|
133
|
+
<div class="release-meta"><a class="release-version" href="#v1-52-0">v1.52.0</a><time class="release-date" datetime="2026-11-08">08/11/2026</time></div>
|
|
134
|
+
<div class="release-body">
|
|
135
|
+
<h3 data-toc-skip id="v1-52-0-title">Helper công ty có thêm advisor và general làm việc trong bản clone riêng</h3>
|
|
136
|
+
<p>Harness công ty khai báo mọi helper, và agent chính gọi chúng bằng tên công việc: explore, scout, advisor, general và review. General chỉ sửa code trong bản clone riêng và trả về một git ref để merge.</p>
|
|
137
|
+
<ul class="release-items">
|
|
138
|
+
<li data-kind="breaking"><span class="kind kind-breaking">Thay đổi lớn</span><span>Helper được gọi là explore, scout, advisor, general và review; tên cũ research và verify không còn, helper verify bị bỏ.</span></li>
|
|
139
|
+
<li data-kind="new"><span class="kind kind-new">Mới</span><span>advisor cho ý kiến thứ hai trước quyết định khó: khuyến nghị, các phương án đã loại và rủi ro.</span></li>
|
|
140
|
+
<li data-kind="new"><span class="kind kind-new">Mới</span><span>general nhận việc lớn trên macOS: sửa, chạy check và commit trong clone riêng, không đụng file của bạn, rồi trả về refs/general/<id>.</span></li>
|
|
141
|
+
<li data-kind="fixed"><span class="kind kind-fixed">Sửa lỗi</span><span>WebUI ghi đúng lỗi của advisor hay general thay vì gọi là lỗi của review.</span></li>
|
|
142
|
+
</ul>
|
|
143
|
+
<p class="release-requires"><strong>Cần:</strong> Agent Studio 0.51.0 và Agent Watch 0.15.20 (Windows 0.1.19) để dùng helper advisor và general</p>
|
|
144
|
+
</div>
|
|
145
|
+
</article>
|
|
146
|
+
<article class="release" id="v1-51-2" data-release>
|
|
112
147
|
<div class="release-meta"><a class="release-version" href="#v1-51-2">v1.51.2</a><time class="release-date" datetime="2026-11-03">03/11/2026</time></div>
|
|
113
148
|
<div class="release-body">
|
|
114
149
|
<h3 data-toc-skip id="v1-51-2-title">Chạy riêng phần test liên quan dùng được với mọi công cụ test</h3>
|
|
@@ -382,51 +417,48 @@
|
|
|
382
417
|
</ul>
|
|
383
418
|
</div>
|
|
384
419
|
</article>
|
|
385
|
-
<article class="release" id="v1-44-2" data-release>
|
|
386
|
-
<div class="release-meta"><a class="release-version" href="#v1-44-2">v1.44.2</a><time class="release-date" datetime="2026-10-28">28/10/2026</time></div>
|
|
387
|
-
<div class="release-body">
|
|
388
|
-
<h3 data-toc-skip id="v1-44-2-title">Harness công ty theo cỡ thay đổi</h3>
|
|
389
|
-
<p>Thay đổi nhỏ xong sau khi check, không cần review; thay đổi rủi ro bắt buộc check và review. Main agent được tra web nhanh vài lần bên cạnh research helper.</p>
|
|
390
|
-
<ul class="release-items">
|
|
391
|
-
<li data-kind="new"><span class="kind kind-new">Mới</span><span>workflow.main_web_lookups (0 đến 5) cho main agent tra web_search hoặc web_fetch nhanh chừng ấy lần mỗi tin nhắn, bên cạnh research helper.</span></li>
|
|
392
|
-
<li data-kind="improved"><span class="kind kind-improved">Cải thiện</span><span>Risk lanes, bật mặc định: thay đổi tối đa 2 file, 40 dòng, không chạm file nhạy cảm xong sau khi check, không gọi reviewer. workflow.lanes: false để tắt.</span></li>
|
|
393
|
-
<li data-kind="improved"><span class="kind kind-improved">Cải thiện</span><span>Thay đổi rủi ro (migration, auth, CI, dependency, AGENTS.md, yêu cầu phức tạp, hơn 12 file hoặc 400 dòng) bắt buộc qua check và review kể cả khi Harness chỉ đặt suggest.</span></li>
|
|
394
|
-
</ul>
|
|
395
|
-
</div>
|
|
396
|
-
</article>
|
|
397
|
-
<article class="release" id="v1-44-1" data-release>
|
|
398
|
-
<div class="release-meta"><a class="release-version" href="#v1-44-1">v1.44.1</a><time class="release-date" datetime="2026-10-28">28/10/2026</time></div>
|
|
399
|
-
<div class="release-body">
|
|
400
|
-
<h3 data-toc-skip id="v1-44-1-title">Giữ Pi của bạn, chọn giao diện Terminal, thêm repo skill</h3>
|
|
401
|
-
<p>Dev đang dùng Pi mới hơn giữ nguyên Pi của mình, Piagent chạy bản Pi riêng đúng bản pin; /style chọn giao diện Terminal; piagent skills add thêm repo skill như mattpocock/skills.</p>
|
|
402
|
-
<ul class="release-items">
|
|
403
|
-
<li data-kind="new"><span class="kind kind-new">Mới</span><span>/style chọn giao diện Terminal: system, dark, light của Pi hoặc ocean, paper, contrast, focus của Piagent. Terminal công ty nhớ lựa chọn.</span></li>
|
|
404
|
-
<li data-kind="new"><span class="kind kind-new">Mới</span><span>piagent skills add mattpocock/skills thêm repo skill GitHub ghim một commit; skill dùng được dạng /skill:tên trong Pi, Terminal công ty và dashboard.</span></li>
|
|
405
|
-
<li data-kind="fixed"><span class="kind kind-fixed">Sửa lỗi</span><span>Setup, install, update không còn hạ pi mới hơn của dev (vd 1.4.0) về bản pin 1.3.0: Piagent giữ bản riêng trong ~/.piagent/pi-host cho phiên công ty, dashboard và lệnh piagent pi.</span></li>
|
|
406
|
-
<li data-kind="fixed"><span class="kind kind-fixed">Sửa lỗi</span><span>piagent-uninstall --with-host gỡ bản Pi riêng của Piagent và giữ nguyên pi mới hơn của dev.</span></li>
|
|
407
|
-
<li data-kind="security"><span class="kind kind-security">Bảo mật</span><span>Năm advisory undici công bố ngày 2026-10-27 được chấp nhận tạm tới 2026-11-07: undici 8.10.2 do mọi Pi host ghim cứng, bản vá ở 8.12.2.</span></li>
|
|
408
|
-
</ul>
|
|
409
|
-
</div>
|
|
410
|
-
</article>
|
|
411
|
-
<article class="release" id="v1-44-0" data-release>
|
|
412
|
-
<div class="release-meta"><a class="release-version" href="#v1-44-0">v1.44.0</a><time class="release-date" datetime="2026-10-28">28/10/2026</time></div>
|
|
413
|
-
<div class="release-body">
|
|
414
|
-
<h3 data-toc-skip id="v1-44-0-title">Giữ Pi của bạn, chọn giao diện Terminal, thêm repo skill <span class="tag">không phát hành</span></h3>
|
|
415
|
-
<p>Đã tag nhưng chưa publish: advisory undici mới trong Pi host làm kiểm tra runtime fail. Thay bằng 1.44.1.</p>
|
|
416
|
-
<ul class="release-items">
|
|
417
|
-
<li data-kind="new"><span class="kind kind-new">Mới</span><span>/style chọn giao diện Terminal: system, dark, light của Pi hoặc ocean, paper, contrast, focus của Piagent. Terminal công ty nhớ lựa chọn.</span></li>
|
|
418
|
-
<li data-kind="new"><span class="kind kind-new">Mới</span><span>piagent skills add mattpocock/skills thêm repo skill GitHub ghim một commit; skill dùng được dạng /skill:tên trong Pi, Terminal công ty và dashboard.</span></li>
|
|
419
|
-
<li data-kind="fixed"><span class="kind kind-fixed">Sửa lỗi</span><span>Setup, install, update không còn hạ pi mới hơn của dev (vd 1.4.0) về bản pin 1.3.0: Piagent giữ bản riêng trong ~/.piagent/pi-host cho phiên công ty, dashboard và lệnh piagent pi.</span></li>
|
|
420
|
-
<li data-kind="fixed"><span class="kind kind-fixed">Sửa lỗi</span><span>piagent-uninstall --with-host gỡ bản Pi riêng của Piagent và giữ nguyên pi mới hơn của dev.</span></li>
|
|
421
|
-
</ul>
|
|
422
|
-
</div>
|
|
423
|
-
</article>
|
|
424
420
|
</section>
|
|
425
421
|
<section class="section archive">
|
|
426
422
|
<h2 id="archive">Các bản trước</h2>
|
|
427
423
|
<p class="section-lead">Bản cũ hơn, gom theo tháng. Mở một tháng để xem từng thay đổi.</p>
|
|
428
424
|
<details class="release-archive">
|
|
429
|
-
<summary><span>Tháng 10/2026</span><span class="archive-count">
|
|
425
|
+
<summary><span>Tháng 10/2026</span><span class="archive-count">77</span></summary>
|
|
426
|
+
<div class="archive-row" id="v1-44-2">
|
|
427
|
+
<div class="archive-head"><a class="release-version" href="#v1-44-2">v1.44.2</a> <span class="release-date">28/10/2026</span></div>
|
|
428
|
+
<div class="archive-body">
|
|
429
|
+
<p><strong>Harness công ty theo cỡ thay đổi</strong> — Thay đổi nhỏ xong sau khi check, không cần review; thay đổi rủi ro bắt buộc check và review. Main agent được tra web nhanh vài lần bên cạnh research helper.</p>
|
|
430
|
+
<ul class="release-items">
|
|
431
|
+
<li data-kind="new"><span class="kind kind-new">Mới</span><span>workflow.main_web_lookups (0 đến 5) cho main agent tra web_search hoặc web_fetch nhanh chừng ấy lần mỗi tin nhắn, bên cạnh research helper.</span></li>
|
|
432
|
+
<li data-kind="improved"><span class="kind kind-improved">Cải thiện</span><span>Risk lanes, bật mặc định: thay đổi tối đa 2 file, 40 dòng, không chạm file nhạy cảm xong sau khi check, không gọi reviewer. workflow.lanes: false để tắt.</span></li>
|
|
433
|
+
<li data-kind="improved"><span class="kind kind-improved">Cải thiện</span><span>Thay đổi rủi ro (migration, auth, CI, dependency, AGENTS.md, yêu cầu phức tạp, hơn 12 file hoặc 400 dòng) bắt buộc qua check và review kể cả khi Harness chỉ đặt suggest.</span></li>
|
|
434
|
+
</ul>
|
|
435
|
+
</div>
|
|
436
|
+
</div>
|
|
437
|
+
<div class="archive-row" id="v1-44-1">
|
|
438
|
+
<div class="archive-head"><a class="release-version" href="#v1-44-1">v1.44.1</a> <span class="release-date">28/10/2026</span></div>
|
|
439
|
+
<div class="archive-body">
|
|
440
|
+
<p><strong>Giữ Pi của bạn, chọn giao diện Terminal, thêm repo skill</strong> — Dev đang dùng Pi mới hơn giữ nguyên Pi của mình, Piagent chạy bản Pi riêng đúng bản pin; /style chọn giao diện Terminal; piagent skills add thêm repo skill như mattpocock/skills.</p>
|
|
441
|
+
<ul class="release-items">
|
|
442
|
+
<li data-kind="new"><span class="kind kind-new">Mới</span><span>/style chọn giao diện Terminal: system, dark, light của Pi hoặc ocean, paper, contrast, focus của Piagent. Terminal công ty nhớ lựa chọn.</span></li>
|
|
443
|
+
<li data-kind="new"><span class="kind kind-new">Mới</span><span>piagent skills add mattpocock/skills thêm repo skill GitHub ghim một commit; skill dùng được dạng /skill:tên trong Pi, Terminal công ty và dashboard.</span></li>
|
|
444
|
+
<li data-kind="fixed"><span class="kind kind-fixed">Sửa lỗi</span><span>Setup, install, update không còn hạ pi mới hơn của dev (vd 1.4.0) về bản pin 1.3.0: Piagent giữ bản riêng trong ~/.piagent/pi-host cho phiên công ty, dashboard và lệnh piagent pi.</span></li>
|
|
445
|
+
<li data-kind="fixed"><span class="kind kind-fixed">Sửa lỗi</span><span>piagent-uninstall --with-host gỡ bản Pi riêng của Piagent và giữ nguyên pi mới hơn của dev.</span></li>
|
|
446
|
+
<li data-kind="security"><span class="kind kind-security">Bảo mật</span><span>Năm advisory undici công bố ngày 2026-10-27 được chấp nhận tạm tới 2026-11-07: undici 8.10.2 do mọi Pi host ghim cứng, bản vá ở 8.12.2.</span></li>
|
|
447
|
+
</ul>
|
|
448
|
+
</div>
|
|
449
|
+
</div>
|
|
450
|
+
<div class="archive-row" id="v1-44-0">
|
|
451
|
+
<div class="archive-head"><a class="release-version" href="#v1-44-0">v1.44.0</a> <span class="release-date">28/10/2026</span></div>
|
|
452
|
+
<div class="archive-body">
|
|
453
|
+
<p><strong>Giữ Pi của bạn, chọn giao diện Terminal, thêm repo skill</strong> <span class="tag">không phát hành</span> — Đã tag nhưng chưa publish: advisory undici mới trong Pi host làm kiểm tra runtime fail. Thay bằng 1.44.1.</p>
|
|
454
|
+
<ul class="release-items">
|
|
455
|
+
<li data-kind="new"><span class="kind kind-new">Mới</span><span>/style chọn giao diện Terminal: system, dark, light của Pi hoặc ocean, paper, contrast, focus của Piagent. Terminal công ty nhớ lựa chọn.</span></li>
|
|
456
|
+
<li data-kind="new"><span class="kind kind-new">Mới</span><span>piagent skills add mattpocock/skills thêm repo skill GitHub ghim một commit; skill dùng được dạng /skill:tên trong Pi, Terminal công ty và dashboard.</span></li>
|
|
457
|
+
<li data-kind="fixed"><span class="kind kind-fixed">Sửa lỗi</span><span>Setup, install, update không còn hạ pi mới hơn của dev (vd 1.4.0) về bản pin 1.3.0: Piagent giữ bản riêng trong ~/.piagent/pi-host cho phiên công ty, dashboard và lệnh piagent pi.</span></li>
|
|
458
|
+
<li data-kind="fixed"><span class="kind kind-fixed">Sửa lỗi</span><span>piagent-uninstall --with-host gỡ bản Pi riêng của Piagent và giữ nguyên pi mới hơn của dev.</span></li>
|
|
459
|
+
</ul>
|
|
460
|
+
</div>
|
|
461
|
+
</div>
|
|
430
462
|
<div class="archive-row" id="v1-43-9">
|
|
431
463
|
<div class="archive-head"><a class="release-version" href="#v1-43-9">v1.43.9</a> <span class="release-date">27/10/2026</span></div>
|
|
432
464
|
<div class="archive-body">
|
package/docs-site/windows.html
CHANGED
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
<span class="brand-mark"><img src="/assets/piagent-logo.svg" alt="" width="28" height="28" /></span>
|
|
38
38
|
<span class="brand-name"><b>Piagent</b> <span>Platform</span></span>
|
|
39
39
|
</a>
|
|
40
|
-
<a class="version-badge" href="/whats-new" data-docs-version="v1.
|
|
40
|
+
<a class="version-badge" href="/whats-new" data-docs-version="v1.52.2" title="v1.52.2 docs · VI"><span class="dot"></span>v1.52.2</a>
|
|
41
41
|
<nav class="top-nav" aria-label="Tài liệu">
|
|
42
42
|
<a href="/quickstart">Tài liệu</a>
|
|
43
43
|
<a href="/whats-new">Changelog</a>
|
package/docs-site/workflows.html
CHANGED
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
<span class="brand-mark"><img src="/assets/piagent-logo.svg" alt="" width="28" height="28" /></span>
|
|
38
38
|
<span class="brand-name"><b>Piagent</b> <span>Platform</span></span>
|
|
39
39
|
</a>
|
|
40
|
-
<a class="version-badge" href="/whats-new" data-docs-version="v1.
|
|
40
|
+
<a class="version-badge" href="/whats-new" data-docs-version="v1.52.2" title="v1.52.2 docs · VI"><span class="dot"></span>v1.52.2</a>
|
|
41
41
|
<nav class="top-nav" aria-label="Tài liệu">
|
|
42
42
|
<a href="/quickstart">Tài liệu</a>
|
|
43
43
|
<a href="/whats-new">Changelog</a>
|
|
@@ -256,8 +256,8 @@
|
|
|
256
256
|
},
|
|
257
257
|
{
|
|
258
258
|
"path": "tests",
|
|
259
|
-
"fileCount":
|
|
260
|
-
"sha256": "
|
|
259
|
+
"fileCount": 653,
|
|
260
|
+
"sha256": "fe018c94cf247031a7aa476925be84127455c3fe6dc93486d6c7e809a81df247"
|
|
261
261
|
}
|
|
262
262
|
],
|
|
263
263
|
"custodianComparisonRules": {
|
package/package.json
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { callName } from './role-names.mjs';
|
|
1
2
|
import { memberMessages, memberRequest } from './objections.mjs';
|
|
2
3
|
|
|
3
4
|
// Several helpers of one role, at the member's request only ("use 3
|
|
@@ -27,10 +28,13 @@ export function fanOut(manager, role, args, harness) {
|
|
|
27
28
|
const split = Array.isArray(args?.split) ? args.split.map(s => typeof s === 'string' ? s.trim().slice(0, 500) : '').filter(Boolean) : [];
|
|
28
29
|
const n = split.length || (Number.isInteger(args?.copies) ? args.copies : 1);
|
|
29
30
|
if (n <= 1) return null;
|
|
31
|
+
// general works in one clone at a time: run one and say so, never refuse (a
|
|
32
|
+
// refusal sent agents round 15 retries in a few minutes, 2026-11-09).
|
|
33
|
+
if (role === 'general') return { dropped: n, single: true };
|
|
30
34
|
if (harness) throw Error('managed-copies-invalid: the harness runs one helper per call.');
|
|
31
35
|
const words = normal(args?.member_words);
|
|
32
36
|
if (words.length < 3 || !memberRequest(memberMessages(manager)).some(text => normal(text).includes(words)) || namedCount(words) < n || !HELPER_WORDS.test(words)) return { dropped: n };
|
|
33
|
-
if (n > MAX_COPIES) throw Error(`managed-copies-invalid: ask for 2 to ${MAX_COPIES} ${role} helpers (copies, or one split line per helper).`);
|
|
37
|
+
if (n > MAX_COPIES) throw Error(`managed-copies-invalid: ask for 2 to ${MAX_COPIES} ${callName(role)} helpers (copies, or one split line per helper).`);
|
|
34
38
|
return { n, split: split.length ? split : null };
|
|
35
39
|
}
|
|
36
40
|
// The helper's answer, with what the main agent reads above it when it asked
|
|
@@ -38,12 +42,14 @@ export function fanOut(manager, role, args, harness) {
|
|
|
38
42
|
export function withDroppedNote(result, role, asked) {
|
|
39
43
|
const n = asked?.dropped, first = result?.content?.[0];
|
|
40
44
|
if (!n || first?.type !== 'text') return result;
|
|
41
|
-
const note =
|
|
45
|
+
const note = asked.single
|
|
46
|
+
? `One general helper ran, not ${n}: general works one at a time, each in its own clone. Merge the ref it returned, then call general again (without copies or split) for the next share of the work.\n\n`
|
|
47
|
+
: `One ${callName(role)} helper ran, not ${n}: the member's own words did not ask for ${n} ${callName(role)} helpers. Go on with this answer; run several only when the member asks for that many.\n\n`;
|
|
42
48
|
return { ...result, content: [{ ...first, text: note + first.text }, ...result.content.slice(1)] };
|
|
43
49
|
}
|
|
44
50
|
// What one copy reads under its brief.
|
|
45
51
|
export function copyNote(role, i, fan) {
|
|
46
|
-
return `\n\nThe member asked for ${fan.n} ${role} helpers; you are ${role} helper ${i + 1} of ${fan.n}. ${fan.split ? `Your share of the work: ${fan.split[i]}. The others cover the rest.` : 'The others have the same brief: answer on your own judgement.'}`;
|
|
52
|
+
return `\n\nThe member asked for ${fan.n} ${callName(role)} helpers; you are ${callName(role)} helper ${i + 1} of ${fan.n}. ${fan.split ? `Your share of the work: ${fan.split[i]}. The others cover the rest.` : 'The others have the same brief: answer on your own judgement.'}`;
|
|
47
53
|
}
|
|
48
54
|
|
|
49
55
|
const jsonOf = reply => {
|
|
@@ -53,18 +59,17 @@ const jsonOf = reply => {
|
|
|
53
59
|
const unique = (list, key) => { const seen = new Set(); return list.filter(x => { const k = key(x); if (seen.has(k)) return false; seen.add(k); return true; }); };
|
|
54
60
|
const SEVERITY = { blocking: 0, major: 1, minor: 2 };
|
|
55
61
|
// One answer from the copies: each helper's prose (its JSON left out), then
|
|
56
|
-
// one JSON block joining their findings
|
|
57
|
-
// review
|
|
58
|
-
// gave its JSON. A finding
|
|
59
|
-
export function mergeCopies(role, label, answers, { findingsOf, issuesOf
|
|
62
|
+
// one JSON block joining their findings and objections, so the
|
|
63
|
+
// review and objection readers see every copy. `parsed`: every copy
|
|
64
|
+
// gave its JSON. A finding any copy reports stands.
|
|
65
|
+
export function mergeCopies(role, label, answers, { findingsOf, issuesOf }) {
|
|
60
66
|
const n = answers.length, room = Math.floor(12000 / n);
|
|
61
67
|
const findings = role === 'review' ? unique(answers.flatMap(a => findingsOf(a.reply) ?? []), f => `${f.severity}|${f.file}|${f.line}|${f.issue}`).sort((a, b) => SEVERITY[a.severity] - SEVERITY[b.severity]) : null;
|
|
62
|
-
const verdicts = role === 'verify' ? unique(answers.flatMap(a => verdictsOf(a.reply) ?? []), v => `${v.status}|${v.claim}`) : null;
|
|
63
68
|
const issues = unique(answers.flatMap(a => issuesOf(a.reply) ?? []), i => `${i.kind}|${i.detail}`).slice(0, 5);
|
|
64
69
|
const parsed = answers.every(a => jsonOf(a.reply));
|
|
65
70
|
const summaries = answers.map(a => jsonOf(a.reply)?.summary).filter(s => typeof s === 'string').map(s => s.slice(0, 200));
|
|
66
|
-
const json = { ...(findings ? { findings: findings.slice(0, 40) } : {}),
|
|
67
|
-
summary: `${n} ${role} helpers${summaries.length ? ': ' + summaries.join(' | ') : ''}`.slice(0, 900) };
|
|
71
|
+
const json = { ...(findings ? { findings: findings.slice(0, 40) } : {}), brief_issues: issues,
|
|
72
|
+
summary: `${n} ${callName(role)} helpers${summaries.length ? ': ' + summaries.join(' | ') : ''}`.slice(0, 900) };
|
|
68
73
|
const body = answers.map((a, i) => `### ${label} helper ${i + 1} of ${n}\n${String(a.reply).replace(/```json\s*[\s\S]*?```/g, '').trim().slice(0, room)}`).join('\n\n');
|
|
69
74
|
return { reply: `${body}\n\n\`\`\`json\n${JSON.stringify(json)}\n\`\`\``, usage: answers.reduce((total, a) => total + a.usage, 0),
|
|
70
75
|
...(findings ? { findings, parsed, blocking: findings.filter(f => f.severity === 'blocking').length } : {}) };
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { randomUUID } from 'node:crypto';
|
|
5
|
+
import { execFile } from 'node:child_process';
|
|
6
|
+
import { promisify } from 'node:util';
|
|
7
|
+
import { cacheDirectory } from './language-environment.mjs';
|
|
8
|
+
|
|
9
|
+
// The general helper changes files, so it never works in the member's
|
|
10
|
+
// project. It works in its own clone: a separate repository with its own
|
|
11
|
+
// .git (refs, config, hooks), no remote, and no writable path to the project
|
|
12
|
+
// or its refs. A linked worktree would share the project's .git, and the
|
|
13
|
+
// sandbox opens a shared git directory for writing. The clone is `--shared`: it
|
|
14
|
+
// borrows the project's object files (read-only inside the sandbox, by the
|
|
15
|
+
// boundary's readRoots) instead of copying them, so it costs about what a
|
|
16
|
+
// worktree costs. The only crossing is takeBack below, run by this runtime,
|
|
17
|
+
// not by the helper: it copies the clone's commits into the project as one
|
|
18
|
+
// private ref, refs/general/<id>, and touches nothing else. The main agent
|
|
19
|
+
// merges that ref itself.
|
|
20
|
+
export const GENERAL_ENTRY = 'agent-watch-general';
|
|
21
|
+
const OWNER = '.piagent-owner';
|
|
22
|
+
const run = promisify(execFile);
|
|
23
|
+
// The clone's own configuration is the helper's to write. The runtime
|
|
24
|
+
// therefore reads it only through git commands that cannot start a program
|
|
25
|
+
// the clone names: these override what a clone's config could set.
|
|
26
|
+
const SAFE = ['-c', 'core.fsmonitor=false', '-c', 'core.hooksPath=/dev/null', '-c', 'core.alternateRefsCommand=', '-c', 'protocol.file.allow=always'];
|
|
27
|
+
const gitEnv = () => ({ PATH: '/usr/bin:/bin', HOME: os.tmpdir(), GIT_CONFIG_GLOBAL: '/dev/null', GIT_CONFIG_NOSYSTEM: '1', GIT_TERMINAL_PROMPT: '0', LANG: 'en_US.UTF-8' });
|
|
28
|
+
const git = (exe, cwd, args) => run(exe, [...SAFE, ...args], { cwd, env: gitEnv(), maxBuffer: 4 << 20, timeout: 120_000 }).then(r => r.stdout.trim());
|
|
29
|
+
|
|
30
|
+
// A clone of the project's HEAD. Work not yet committed in the project is not
|
|
31
|
+
// in it: `dirty` lists those paths so the main agent can be told.
|
|
32
|
+
export async function cloneProject(managed) {
|
|
33
|
+
// The clone's isolation is proven under the macOS sandbox only; the Linux (bubblewrap) path is not, so it stays closed.
|
|
34
|
+
if (process.platform !== 'darwin') throw Error('managed-general-unavailable: the general helper is not verified on this platform yet; do the work yourself.');
|
|
35
|
+
const exe = managed.boundary.git, project = managed.cwd;
|
|
36
|
+
let top, base, dirty, objects;
|
|
37
|
+
try {
|
|
38
|
+
top = fs.realpathSync(await git(exe, project, ['rev-parse', '--show-toplevel']));
|
|
39
|
+
base = await git(exe, project, ['rev-parse', '--verify', 'HEAD']);
|
|
40
|
+
objects = fs.realpathSync(path.resolve(project, await git(exe, project, ['rev-parse', '--git-path', 'objects'])));
|
|
41
|
+
dirty = (await git(exe, project, ['status', '--porcelain', '-uall'])).split('\n').filter(Boolean).map(l => l.replace(/^\S{1,2}\s+/, '')).slice(0, 50);
|
|
42
|
+
} catch { throw Error('managed-general-needs-git: the general helper needs the project to be a git repository with a commit; commit first or do the work yourself.'); }
|
|
43
|
+
if (top !== project) throw Error('managed-general-needs-git: the general helper needs the project folder to be the repository root.');
|
|
44
|
+
const id = randomUUID().slice(0, 8), dir = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), 'piagent-general-'));
|
|
45
|
+
try {
|
|
46
|
+
await git(exe, dir, ['clone', '-q', '--shared', '--no-tags', '--template=', '--', project, path.join(dir, 'work')]);
|
|
47
|
+
await git(exe, path.join(dir, 'work'), ['remote', 'remove', 'origin']);
|
|
48
|
+
} catch (error) { fs.rmSync(dir, { recursive: true, force: true }); throw Error(`managed-general-clone-failed: ${String(error?.message).slice(0, 200)}`); }
|
|
49
|
+
const token = randomUUID(); // the proof, in the folder and in the session's record, that this runtime made it
|
|
50
|
+
fs.writeFileSync(path.join(dir, OWNER), token, { mode: 0o600 });
|
|
51
|
+
const real = fs.realpathSync(path.join(dir, 'work'));
|
|
52
|
+
return { id, base, dirty, token, objects, cache: cacheDirectory(managed.boundary.userHome, real), root: dir, dir: real };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// The clone's folder, and the package cache the sandbox keyed to it (no later run shares it).
|
|
56
|
+
export function discardClone(clone) { fs.rmSync(clone.root, { recursive: true, force: true }); fs.rmSync(clone.cache, { recursive: true, force: true }); }
|
|
57
|
+
|
|
58
|
+
// Bring the clone's commits into the project as refs/general/<id> and
|
|
59
|
+
// discard the clone. Returns what the main agent needs to merge them.
|
|
60
|
+
export async function takeBack(managed, clone) {
|
|
61
|
+
const exe = managed.boundary.git, project = managed.cwd;
|
|
62
|
+
try {
|
|
63
|
+
// The helper writes the clone's .git: a gitfile or alternates would point
|
|
64
|
+
// the fetch at a path outside it.
|
|
65
|
+
const dotgit = path.join(clone.dir, '.git');
|
|
66
|
+
const alternates = path.join(dotgit, 'objects/info/alternates');
|
|
67
|
+
if (!fs.lstatSync(dotgit).isDirectory() || fs.readFileSync(alternates, 'utf8').trim() !== clone.objects) throw Error('the clone was changed to point outside itself');
|
|
68
|
+
const ref = `refs/general/${clone.id}`;
|
|
69
|
+
await git(exe, project, ['fetch', '-q', '--no-tags', '--no-recurse-submodules', '--no-write-fetch-head', clone.dir, `+HEAD:${ref}`]);
|
|
70
|
+
const head = await git(exe, project, ['rev-parse', '--verify', ref]);
|
|
71
|
+
if (head === clone.base) { await git(exe, project, ['update-ref', '-d', ref]); return { ref: null, head, base: clone.base, files: [], note: 'The general helper made no commit, so nothing came back. Only committed work is returned.' }; }
|
|
72
|
+
if (!(await git(exe, project, ['merge-base', '--is-ancestor', clone.base, head]).then(() => true, () => false))) { await git(exe, project, ['update-ref', '-d', ref]); throw Error('the clone no longer descends from the commit it started from'); }
|
|
73
|
+
const files = (await git(exe, project, ['diff', '--numstat', `${clone.base}..${head}`])).split('\n').filter(Boolean).map(l => { const [added, deleted, ...name] = l.split('\t'); return `+${added} -${deleted} ${name.join('\t')}`; }).slice(0, 80);
|
|
74
|
+
return { ref, head, base: clone.base, files, note: null };
|
|
75
|
+
} finally { discardClone(clone); }
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// What the main agent reads with the helper's answer.
|
|
79
|
+
export function takeBackText(clone, back) {
|
|
80
|
+
const dirty = clone.dirty.length ? ` The helper did not see ${clone.dirty.length} uncommitted path(s) in the project (${clone.dirty.slice(0, 8).join(', ')}${clone.dirty.length > 8 ? ', …' : ''}).` : '';
|
|
81
|
+
if (!back.ref) return `\n\n${back.note}${dirty}`;
|
|
82
|
+
return `\n\nThe general helper's commits are in ${back.ref} (${back.base.slice(0, 9)}..${back.head.slice(0, 9)}); your files are unchanged. Merge or cherry-pick that ref yourself, run the checks on the result, then ask for review; delete the ref afterwards (git update-ref -d ${back.ref}). Changed:\n${back.files.join('\n')}${dirty}`;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// One entry per general run, so a later turn knows what ran and what came back;
|
|
86
|
+
// "running" with the folder and its token is also the record of what to recover.
|
|
87
|
+
export function recordGeneral(managed, clone, status, back = null) {
|
|
88
|
+
managed.session.sessionManager.appendCustomEntry(GENERAL_ENTRY, { id: clone.id, base: clone.base, status, root: clone.root, token: clone.token, ...(back?.ref ? { ref: back.ref, head: back.head } : {}), at: new Date().toISOString() });
|
|
89
|
+
}
|
|
90
|
+
// A crash or a kill skips the cleanup above. When the conversation next runs a
|
|
91
|
+
// general helper, a run its record still calls "running" (and this process
|
|
92
|
+
// is not running) has its clone removed only if the folder is provably the one
|
|
93
|
+
// this runtime made: a real folder, ours, directly in the temporary folder,
|
|
94
|
+
// holding the token the record names. Anything else is only reported.
|
|
95
|
+
export function sweepGeneral(managed) {
|
|
96
|
+
const last = new Map(), tmp = fs.realpathSync(os.tmpdir()), removed = [], unproven = [];
|
|
97
|
+
for (const e of managed.session.sessionManager.getEntries?.() ?? []) if (e.type === 'custom' && e.customType === GENERAL_ENTRY) last.set(e.data.id, e.data);
|
|
98
|
+
for (const d of last.values()) {
|
|
99
|
+
if (d.status !== 'running' || typeof d.root !== 'string' || managed.liveClones?.has(d.root)) continue;
|
|
100
|
+
let st; try { st = fs.lstatSync(d.root); } catch { continue; } // already gone
|
|
101
|
+
let owned = false;
|
|
102
|
+
try {
|
|
103
|
+
owned = st.isDirectory() && !st.isSymbolicLink() && st.uid === process.getuid() && path.dirname(d.root) === tmp && path.basename(d.root).startsWith('piagent-general-')
|
|
104
|
+
&& fs.readFileSync(path.join(d.root, OWNER), 'utf8') === d.token;
|
|
105
|
+
} catch { /* no marker: not proven */ }
|
|
106
|
+
if (owned) { fs.rmSync(d.root, { recursive: true, force: true }); removed.push(d.id); } else unproven.push(d.root);
|
|
107
|
+
}
|
|
108
|
+
return { removed, unproven };
|
|
109
|
+
}
|
|
110
|
+
export const sweepText = ({ removed, unproven }) => (removed.length ? `\n\nAn earlier general run (${removed.join(', ')}) was interrupted; its clone folder was removed and any work in it was not returned.` : '')
|
|
111
|
+
+ (unproven.length ? `\n\nA folder an earlier general run recorded could not be proven to be the one it made, so it was left in place: ${unproven.join(', ')}.` : '');
|