@piagent/platform 1.19.0 → 1.20.0
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 +15 -0
- package/README.md +1 -1
- package/README.vi.md +1 -1
- package/docs/command-reference-vietnamese.md +2 -2
- package/docs/distribution-standard.md +6 -6
- package/docs/languages.json +2 -2
- package/docs/operator-manual-vietnamese.md +7 -7
- package/docs/publishing-for-teams.md +1 -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/benchmark.html +1 -1
- package/docs-site/commands.html +1 -1
- package/docs-site/content/en/index.html +4 -4
- package/docs-site/content/en/whats-new.html +8 -0
- package/docs-site/content/index.html +4 -4
- package/docs-site/content/whats-new.html +8 -0
- 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 +5 -5
- 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/whats-new.html +9 -1
- package/docs-site/en/windows.html +1 -1
- package/docs-site/en/workflows.html +1 -1
- package/docs-site/index.html +5 -5
- 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/whats-new.html +9 -1
- 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/command-tools.mjs +5 -8
- package/packages/piagent-core/managed/container-engine.mjs +0 -34
- package/packages/piagent-core/managed/doctor.mjs +5 -0
- package/packages/piagent-core/managed/helper-roles.mjs +1 -1
- package/packages/piagent-core/managed/helper-run.mjs +24 -6
- package/packages/piagent-core/managed/linux-sandbox.mjs +4 -1
- package/packages/piagent-core/managed/package-proxy.mjs +181 -0
- package/packages/piagent-core/managed/patch-snapshot.mjs +31 -3
- package/packages/piagent-core/managed/review-snapshot-worker.mjs +18 -0
- package/packages/piagent-core/managed/sandbox-diagnostic.mjs +1 -1
- package/packages/piagent-core/managed/session.mjs +11 -6
- package/packages/piagent-core/managed/tool-boundary.mjs +52 -4
- package/packages/piagent-core/managed/tool-worker.mjs +15 -0
- package/packages/piagent-core/package.json +1 -1
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · EN</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Language">
|
|
35
35
|
<a class="language-option" href="/whats-new" hreflang="vi" lang="vi">VI</a>
|
|
36
36
|
<a class="language-option current" href="/en/whats-new" hreflang="en" lang="en" aria-current="true">EN</a>
|
|
@@ -104,6 +104,14 @@
|
|
|
104
104
|
<h1>1.9.0: ask in plain language, the team's Harness checks</h1>
|
|
105
105
|
<p>The task contract and workflow commands are gone. Company mode asks for checks and a review on its own; Stop, network commands on approval and clearer approval cards.</p>
|
|
106
106
|
</div>
|
|
107
|
+
<section class="section">
|
|
108
|
+
<p class="section-kicker">v1.20.0 · 2026-10-09</p>
|
|
109
|
+
<h2 id="v1-20-0">Package installs in the company sandbox no longer ask</h2>
|
|
110
|
+
<p class="section-lead">Plain bash commands reach the usual registries: npm, PyPI, the Go proxy, crates.io, Maven Central, Gradle, NuGet, RubyGems, Packagist, pub.dev, CocoaPods and Hex, plus public GitHub downloads (such as the Gradle distribution <span class="inline-code">./gradlew</span> needs). So <span class="inline-code">npm install</span>, <span class="inline-code">pip install</span>, <span class="inline-code">go mod download</span>, <span class="inline-code">./mvnw test</span> and <span class="inline-code">./gradlew test</span> run without waiting for your approval. Piagent goes through a proxy that runs outside the sandbox: only those hosts, on ports 443 and 80, never an IP address, your machine or a private network. Any other host is refused, the error names it, and a command that needs it still goes through <span class="inline-code">run_with_network</span> for your approval. To add your company's registry, write its host name (or <span class="inline-code">*.domain</span>) in <span class="inline-code">~/.piagent/sandbox-domains</span>, one per line. Registry and git credentials still stay out of the sandbox, so nothing is pushed or published.</p>
|
|
111
|
+
<p class="section-lead">In Bypass, <span class="inline-code">run_with_docker</span> runs without asking, like <span class="inline-code">run_with_network</span>; only pushes, deploys, registry logins and deletes with an unknown target still ask.</p>
|
|
112
|
+
<p class="section-lead">Fixed: a subagent that works longer than 15 minutes (such as a verify running the whole test suite while the main agent waits) is no longer stopped with <span class="inline-code">managed-helper-cancelled</span>. Asked to review work committed in earlier turns, the review subagent no longer says “no patch”. It reads the commits since the commit, branch or <span class="inline-code">HEAD~N</span> the agent names; when the current turn changed nothing, it reads the branch’s commits since it left the main branch.</p>
|
|
113
|
+
</section>
|
|
114
|
+
|
|
107
115
|
<section class="section">
|
|
108
116
|
<p class="section-kicker">v1.19.0 · 2026-10-08</p>
|
|
109
117
|
<h2 id="v1-19-0">Tasks with a checklist are carried to the end, and each turn says whether it finished</h2>
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · EN</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Language">
|
|
35
35
|
<a class="language-option" href="/windows" hreflang="vi" lang="vi">VI</a>
|
|
36
36
|
<a class="language-option current" href="/en/windows" hreflang="en" lang="en" aria-current="true">EN</a>
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · EN</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Language">
|
|
35
35
|
<a class="language-option" href="/workflows" hreflang="vi" lang="vi">VI</a>
|
|
36
36
|
<a class="language-option current" href="/en/workflows" hreflang="en" lang="en" aria-current="true">EN</a>
|
package/docs-site/index.html
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · VI</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Ngôn ngữ">
|
|
35
35
|
<a class="language-option current" href="/" hreflang="vi" lang="vi" aria-current="true">VI</a>
|
|
36
36
|
<a class="language-option" href="/en/" hreflang="en" lang="en">EN</a>
|
|
@@ -94,7 +94,7 @@
|
|
|
94
94
|
<main>
|
|
95
95
|
<div class="content-shell" data-article>
|
|
96
96
|
<section class="hero">
|
|
97
|
-
<p class="eyebrow">Piagent 1.
|
|
97
|
+
<p class="eyebrow">Piagent 1.20.0</p>
|
|
98
98
|
<h1>Coding agent cho cả team, kiểm tra từng bước.</h1>
|
|
99
99
|
<p>
|
|
100
100
|
Một dashboard cho Terminal và trình duyệt. Dùng model bằng tài khoản của bạn, hoặc model của công ty qua Agent Watch và Agent Studio. Guard kiểm tra từng tool call; ở chế độ công ty, Harness của team tự yêu cầu chạy check, cho subagent review và báo kết quả ngay dưới câu trả lời.
|
|
@@ -108,7 +108,7 @@
|
|
|
108
108
|
<div class="hero-actions">
|
|
109
109
|
<a class="button primary" href="/quickstart">Bắt đầu</a>
|
|
110
110
|
<a class="button" href="/ecosystem">Hệ sinh thái</a>
|
|
111
|
-
<a class="button" href="/whats-new">Có gì mới trong 1.
|
|
111
|
+
<a class="button" href="/whats-new">Có gì mới trong 1.20.0</a>
|
|
112
112
|
<a class="button" href="/commands">Xem command</a>
|
|
113
113
|
</div>
|
|
114
114
|
</section>
|
|
@@ -184,9 +184,9 @@ piagent-setup</code></pre>
|
|
|
184
184
|
<h2 id="bat-dau-tu-dau">Bắt đầu từ đâu</h2>
|
|
185
185
|
<div class="card-grid">
|
|
186
186
|
<a class="doc-card" href="/whats-new">
|
|
187
|
-
<span class="card-kicker">Bản 1.
|
|
187
|
+
<span class="card-kicker">Bản 1.20.0</span>
|
|
188
188
|
<h3>Có gì mới</h3>
|
|
189
|
-
<p>
|
|
189
|
+
<p>Cài package trong sandbox công ty không phải duyệt (npm, PyPI, Go, Maven, Gradle… qua proxy chỉ cho registry); ở 1.19.0: task công ty có checklist được làm đến hết, cuối mỗi lượt báo rõ xong, dừng giữa chừng hay lỗi, Docker trong sandbox công ty, folder chứa nhiều repo; ở 1.18.0: đổi nhánh Git trên dashboard, tự thử lại khi lỗi tạm thời, Claude Haiku 5.5; ở 1.17.0: dashboard hiện nhánh Git của project; ở 1.16.3: dashboard cập nhật xong vẫn tự kiểm tra bản mới; ở 1.16.2: Terminal nói giống dashboard: hỏi cập nhật, /bypass, lỗi và ghi chú Harness bằng tiếng Việt; ở 1.16.1: bản mới được báo bằng dialog và kiểm tra mỗi giờ, tab dashboard không còn mất đăng nhập; ở 1.16.0: Bypass cho cuộc trò chuyện công ty, đổi Harness không làm gián đoạn; ở 1.15.2: cuộc trò chuyện dài tự thu gọn trở lại; ở 1.15.1: Studio thấy mỗi call của model dùng để làm gì, nhiều cuộc trò chuyện trong một folder không nhận nhầm thay đổi của nhau; ở 1.15.0: subagent bị từ chối nói đúng lý do; ở 1.14: cập nhật giữ model bạn đã chọn; ở 1.13: cuộc trò chuyện giữ chỗ đang đọc, chữ của agent có định dạng, Piagent trên Windows qua WSL2: sandbox công ty bằng bubblewrap và Agent Watch cho Windows; ở 1.12: @ chọn file và folder trên máy, skill và command dùng bằng /, nhánh cuộc trò chuyện công ty gửi được tin nhắn.</p>
|
|
190
190
|
</a>
|
|
191
191
|
<a class="doc-card" href="/ecosystem">
|
|
192
192
|
<span class="card-kicker">Get started</span>
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · VI</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Ngôn ngữ">
|
|
35
35
|
<a class="language-option current" href="/mcp-approval" hreflang="vi" lang="vi" aria-current="true">VI</a>
|
|
36
36
|
<a class="language-option" href="/en/mcp-approval" hreflang="en" lang="en">EN</a>
|
package/docs-site/mcp-auth.html
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · VI</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Ngôn ngữ">
|
|
35
35
|
<a class="language-option current" href="/mcp-auth" hreflang="vi" lang="vi" aria-current="true">VI</a>
|
|
36
36
|
<a class="language-option" href="/en/mcp-auth" hreflang="en" lang="en">EN</a>
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · VI</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Ngôn ngữ">
|
|
35
35
|
<a class="language-option current" href="/mcp-servers" hreflang="vi" lang="vi" aria-current="true">VI</a>
|
|
36
36
|
<a class="language-option" href="/en/mcp-servers" hreflang="en" lang="en">EN</a>
|
package/docs-site/mcp.html
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · VI</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Ngôn ngữ">
|
|
35
35
|
<a class="language-option current" href="/mcp" hreflang="vi" lang="vi" aria-current="true">VI</a>
|
|
36
36
|
<a class="language-option" href="/en/mcp" hreflang="en" lang="en">EN</a>
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · VI</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Ngôn ngữ">
|
|
35
35
|
<a class="language-option current" href="/permissions" hreflang="vi" lang="vi" aria-current="true">VI</a>
|
|
36
36
|
<a class="language-option" href="/en/permissions" hreflang="en" lang="en">EN</a>
|
package/docs-site/profiles.html
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · VI</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Ngôn ngữ">
|
|
35
35
|
<a class="language-option current" href="/profiles" hreflang="vi" lang="vi" aria-current="true">VI</a>
|
|
36
36
|
<a class="language-option" href="/en/profiles" hreflang="en" lang="en">EN</a>
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · VI</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Ngôn ngữ">
|
|
35
35
|
<a class="language-option current" href="/quickstart" hreflang="vi" lang="vi" aria-current="true">VI</a>
|
|
36
36
|
<a class="language-option" href="/en/quickstart" hreflang="en" lang="en">EN</a>
|
package/docs-site/runtime.html
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · VI</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Ngôn ngữ">
|
|
35
35
|
<a class="language-option current" href="/runtime" hreflang="vi" lang="vi" aria-current="true">VI</a>
|
|
36
36
|
<a class="language-option" href="/en/runtime" hreflang="en" lang="en">EN</a>
|
package/docs-site/scope.html
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · VI</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Ngôn ngữ">
|
|
35
35
|
<a class="language-option current" href="/scope" hreflang="vi" lang="vi" aria-current="true">VI</a>
|
|
36
36
|
<a class="language-option" href="/en/scope" hreflang="en" lang="en">EN</a>
|
package/docs-site/security.html
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · VI</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Ngôn ngữ">
|
|
35
35
|
<a class="language-option current" href="/security" hreflang="vi" lang="vi" aria-current="true">VI</a>
|
|
36
36
|
<a class="language-option" href="/en/security" hreflang="en" lang="en">EN</a>
|
package/docs-site/team.html
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · VI</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Ngôn ngữ">
|
|
35
35
|
<a class="language-option current" href="/team" hreflang="vi" lang="vi" aria-current="true">VI</a>
|
|
36
36
|
<a class="language-option" href="/en/team" hreflang="en" lang="en">EN</a>
|
package/docs-site/whats-new.html
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · VI</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Ngôn ngữ">
|
|
35
35
|
<a class="language-option current" href="/whats-new" hreflang="vi" lang="vi" aria-current="true">VI</a>
|
|
36
36
|
<a class="language-option" href="/en/whats-new" hreflang="en" lang="en">EN</a>
|
|
@@ -104,6 +104,14 @@
|
|
|
104
104
|
<h1>Bản 1.9.0: nói việc bằng lời, Harness của team kiểm tra</h1>
|
|
105
105
|
<p>Bỏ task contract và lệnh workflow. Chế độ công ty tự yêu cầu check và review; nút Dừng, lệnh có mạng theo lần duyệt và thẻ duyệt dễ đọc hơn.</p>
|
|
106
106
|
</div>
|
|
107
|
+
<section class="section">
|
|
108
|
+
<p class="section-kicker">v1.20.0 · 2026-10-09</p>
|
|
109
|
+
<h2 id="v1-20-0">Cài package trong sandbox công ty không phải duyệt nữa</h2>
|
|
110
|
+
<p class="section-lead">Lệnh bash thường tải được từ các registry quen thuộc: npm, PyPI, Go proxy, crates.io, Maven Central, Gradle, NuGet, RubyGems, Packagist, pub.dev, CocoaPods, Hex, và tải về public từ GitHub (ví dụ bản Gradle mà <span class="inline-code">./gradlew</span> cần). Nhờ vậy <span class="inline-code">npm install</span>, <span class="inline-code">pip install</span>, <span class="inline-code">go mod download</span>, <span class="inline-code">./mvnw test</span> hay <span class="inline-code">./gradlew test</span> chạy ngay, không phải chờ bạn duyệt. Piagent đi qua một proxy chạy ngoài sandbox: chỉ các host đó, cổng 443 và 80, không bao giờ tới IP trực tiếp, máy của bạn hay mạng nội bộ. Host khác bị chặn, lỗi ghi rõ host nào, và lệnh cần host đó vẫn phải qua <span class="inline-code">run_with_network</span> để bạn duyệt. Muốn thêm registry riêng của công ty, ghi tên host (hoặc <span class="inline-code">*.domain</span>) vào <span class="inline-code">~/.piagent/sandbox-domains</span>, mỗi dòng một host. Thông tin đăng nhập registry và git vẫn không vào sandbox, nên không push hay publish được.</p>
|
|
111
|
+
<p class="section-lead">Ở chế độ Bypass, <span class="inline-code">run_with_docker</span> chạy luôn không cần duyệt, giống <span class="inline-code">run_with_network</span>; chỉ push, deploy, đăng nhập registry hay lệnh xoá không rõ đích là vẫn hỏi.</p>
|
|
112
|
+
<p class="section-lead">Sửa lỗi: subagent chạy lâu hơn 15 phút (ví dụ verify chạy cả bộ test trong lúc main agent chờ) không còn bị dừng với <span class="inline-code">managed-helper-cancelled</span> nữa. Nhờ subagent review xem lại code đã commit ở các lượt trước thì nó không còn báo “không có patch”. Review đọc các commit kể từ commit, nhánh hoặc <span class="inline-code">HEAD~N</span> mà agent chỉ ra; nếu lượt hiện tại chưa sửa gì, nó đọc các commit của nhánh kể từ lúc tách khỏi nhánh chính.</p>
|
|
113
|
+
</section>
|
|
114
|
+
|
|
107
115
|
<section class="section">
|
|
108
116
|
<p class="section-kicker">v1.19.0 · 2026-10-08</p>
|
|
109
117
|
<h2 id="v1-19-0">Task có checklist được làm đến hết, và mỗi lượt báo rõ đã xong hay chưa</h2>
|
package/docs-site/windows.html
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · VI</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Ngôn ngữ">
|
|
35
35
|
<a class="language-option current" href="/windows" hreflang="vi" lang="vi" aria-current="true">VI</a>
|
|
36
36
|
<a class="language-option" href="/en/windows" hreflang="en" lang="en">EN</a>
|
package/docs-site/workflows.html
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · VI</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Ngôn ngữ">
|
|
35
35
|
<a class="language-option current" href="/workflows" hreflang="vi" lang="vi" aria-current="true">VI</a>
|
|
36
36
|
<a class="language-option" href="/en/workflows" hreflang="en" lang="en">EN</a>
|
|
@@ -256,8 +256,8 @@
|
|
|
256
256
|
},
|
|
257
257
|
{
|
|
258
258
|
"path": "tests",
|
|
259
|
-
"fileCount":
|
|
260
|
-
"sha256": "
|
|
259
|
+
"fileCount": 530,
|
|
260
|
+
"sha256": "4bc37f2d6ac7e4b8a75416b7b2ea413a91c282e7ceaba0c2f4dab5d2971f46d3"
|
|
261
261
|
}
|
|
262
262
|
],
|
|
263
263
|
"custodianComparisonRules": {
|
package/package.json
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
|
-
import { mustConfirm } from '../runtime/policy/bypass-policy.mjs';
|
|
2
|
-
import { dockerConfirmation } from './container-engine.mjs';
|
|
3
1
|
import { networkConfirmation } from './permission.mjs';
|
|
4
2
|
|
|
5
3
|
// Commands that leave the plain sandbox, each after the member approves that
|
|
6
4
|
// exact command: run_with_network (internet, a local server or browser) and,
|
|
7
5
|
// when this machine has a Docker engine, run_with_docker (the same plus the
|
|
8
|
-
// engine's socket). Bypass runs
|
|
9
|
-
//
|
|
10
|
-
//
|
|
6
|
+
// engine's socket). Bypass runs both without asking (owner, 2026-10-09),
|
|
7
|
+
// except what must be confirmed for any command (bypass-policy.mjs: pushes,
|
|
8
|
+
// deploys, registry logins, deletes known only at run time).
|
|
11
9
|
const PARAMETERS = { type: 'object', properties: { command: { type: 'string', minLength: 1, maxLength: 4000 }, reason: { type: 'string', minLength: 1, maxLength: 300 }, timeout: { type: 'number', minimum: 1, maximum: 1800 } }, required: ['command', 'reason'], additionalProperties: false };
|
|
12
10
|
|
|
13
11
|
const KINDS = {
|
|
14
12
|
network: {
|
|
15
13
|
name: 'run_with_network', label: 'Run with network', scope: 'network-command-once', provider: 'network', riskClass: 'medium',
|
|
16
|
-
description: 'Run one shell command that needs the internet
|
|
14
|
+
description: 'Run one shell command that needs the internet beyond the package registries bash already reaches (a download site or registry the package proxy refuses), or that starts a local server or a browser (end-to-end tests with Playwright\'s Chromium against a server on 127.0.0.1), after the user approves that exact command. Normal bash has no network and cannot listen on a port. Credentials (.npmrc, SSH keys, Keychain) stay unavailable, so private registries and git push are not possible here.',
|
|
17
15
|
allow: 'Run this exact command once, with internet access; a server it starts accepts connections while it runs.',
|
|
18
16
|
title: 'Chạy lệnh có internet', allowText: 'chạy đúng lệnh này một lần, có internet; server nó mở nhận kết nối trong lúc chạy.',
|
|
19
17
|
confirm: (self, command) => networkConfirmation(self, command),
|
|
@@ -23,8 +21,7 @@ const KINDS = {
|
|
|
23
21
|
description: 'Run one shell command that needs the Docker engine of this machine: docker, docker compose (a database or service for tests), docker build, or tests that start containers themselves (Testcontainers), after the user approves that exact command. It has internet access too. Normal bash and run_with_network cannot reach Docker. Mount only folders inside the project. Registry credentials are unavailable: public images pull, private registries and docker push do not. Containers started in the background (-d, compose up -d) keep running after the command: stop them (docker compose down) when the work is done unless the member wants them kept.',
|
|
24
22
|
allow: 'Run this exact command once, with internet access and the Docker engine; a container it starts can read folders Docker shares from this machine and may keep running.',
|
|
25
23
|
title: 'Chạy lệnh dùng Docker', allowText: 'chạy đúng lệnh này một lần, có internet và Docker; container nó tạo có thể đọc thư mục Docker được chia sẻ trên máy và có thể tiếp tục chạy.',
|
|
26
|
-
confirm:
|
|
27
|
-
: await mustConfirm(command) ?? dockerConfirmation(command, { cwd: self.cwd, home: self.boundary.userHome }),
|
|
24
|
+
confirm: (self, command) => networkConfirmation(self, command),
|
|
28
25
|
},
|
|
29
26
|
};
|
|
30
27
|
|
|
@@ -66,37 +66,3 @@ export function engineEnvironment(engine, home) {
|
|
|
66
66
|
...(process.platform === 'darwin' ? { TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE: '/var/run/docker.sock' } : {}),
|
|
67
67
|
};
|
|
68
68
|
}
|
|
69
|
-
|
|
70
|
-
// Why an approved-in-Bypass Docker command must still be asked about: host
|
|
71
|
-
// folders outside the project mounted into a container, the engine's own
|
|
72
|
-
// socket, or a container given the host's processes or network. The
|
|
73
|
-
// project's compose files are read for the same (a volume naming ~ or an
|
|
74
|
-
// absolute path outside the project). null when none applies.
|
|
75
|
-
const COMPOSE_FILES = ['compose.yaml', 'compose.yml', 'docker-compose.yaml', 'docker-compose.yml', 'compose.override.yaml', 'compose.override.yml', 'docker-compose.override.yaml', 'docker-compose.override.yml'];
|
|
76
|
-
function outside(source, cwd, home) {
|
|
77
|
-
if (!source || /^[A-Za-z0-9][A-Za-z0-9_.-]*$/.test(source)) return false; // a named volume
|
|
78
|
-
const expanded = source.replace(/^~(?=\/|$)/, home).replace(/^\$\{?HOME\}?(?=\/|$)/, home);
|
|
79
|
-
if (/\$/.test(expanded)) return true;
|
|
80
|
-
const resolved = path.resolve(cwd, expanded);
|
|
81
|
-
return /docker\.sock$/.test(resolved) || !(resolved === cwd || resolved.startsWith(cwd + path.sep));
|
|
82
|
-
}
|
|
83
|
-
export function dockerConfirmation(command, { cwd, home }) {
|
|
84
|
-
const text = String(command);
|
|
85
|
-
if (/--privileged\b|--pid[= ]host\b|--network[= ]host\b|--net[= ]host\b|--userns[= ]host\b|--cap-add\b/.test(text)) return 'the container gets the host\'s processes, network or extra privileges';
|
|
86
|
-
const mounts = [...text.matchAll(/(?:^|\s)(?:-v|--volume)(?:=|\s+)(['"]?)([^\s'"]+)\1/g)].map(match => match[2].split(':')[0]);
|
|
87
|
-
for (const match of text.matchAll(/--mount(?:=|\s+)(['"]?)([^\s'"]+)\1/g)) {
|
|
88
|
-
const source = /(?:^|,)(?:source|src)=([^,]+)/.exec(match[2])?.[1];
|
|
89
|
-
if (/(?:^|,)type=bind\b/.test(match[2])) mounts.push(source ?? '');
|
|
90
|
-
}
|
|
91
|
-
if (mounts.some(source => outside(source, cwd, home))) return 'it mounts a folder outside the project into a container';
|
|
92
|
-
if (/\bcompose\b/.test(text)) {
|
|
93
|
-
for (const name of COMPOSE_FILES) {
|
|
94
|
-
let content;
|
|
95
|
-
try { content = fs.readFileSync(path.join(cwd, name), 'utf8'); } catch { continue; }
|
|
96
|
-
if (/^\s*(privileged:\s*true|pid:\s*["']?host|network_mode:\s*["']?host)/m.test(content)) return `${name} gives a container the host's processes, network or privileges`;
|
|
97
|
-
const sources = [...content.matchAll(/^\s*-\s*["']?([^\s"':]+):[^\s]/gm), ...content.matchAll(/^\s*source:\s*["']?([^\s"']+)/gm)].map(match => match[1]);
|
|
98
|
-
if (sources.some(source => /^(\/|~|\.|\$)/.test(source) && outside(source, cwd, home))) return `${name} mounts a folder outside the project into a container`;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
return null;
|
|
102
|
-
}
|
|
@@ -66,6 +66,11 @@ export async function runDoctor({ sdkRoot, origin, broker, network = true }) {
|
|
|
66
66
|
let refused = false; try { await bash('curl -sS -m 5 https://example.com/ >/dev/null'); } catch { refused = true; }
|
|
67
67
|
if (!refused) throw Error('a command reached the internet without approval'); return 'blocked';
|
|
68
68
|
});
|
|
69
|
+
// Package registries through the runtime's proxy (package-proxy.mjs).
|
|
70
|
+
if (network) await check('package registries without approval (npm through the proxy)', false, async () => {
|
|
71
|
+
const status = await bash('curl -sS -m 15 -o /dev/null -w "%{http_code}" https://registry.npmjs.org/');
|
|
72
|
+
if (status !== '200') throw Error(`HTTP ${status}`); return 'registry.npmjs.org';
|
|
73
|
+
});
|
|
69
74
|
await check('git', true, () => bash('git --version'));
|
|
70
75
|
await check('git commit with the member\'s identity', false, async () => {
|
|
71
76
|
await bash('git init -q . && git add -A');
|
|
@@ -34,7 +34,7 @@ const HELPER_USES = {
|
|
|
34
34
|
research: roles => roles.includes('scout') ? 'research: anything on the web (current information, news, library or API documentation, releases, error messages), with the code when needed. It searches and reads the pages; you get its summary with sources.'
|
|
35
35
|
: 'research: anything on the web (current information, news, documentation; it searches and reads the pages, you get its summary with sources), and before changing an area you do not know that spans more files than you can read in a few batches (where something is computed and every caller, how a flow crosses modules); your own context stays free for the change.',
|
|
36
36
|
verify: () => 'verify: an independent check of a result: it runs the repository checks on the current code (offline, and the project is read-only for its commands) and confirms claims, yours or a helper\'s, against the code and primary sources. It answers pass, fail or unverifiable per claim, with evidence.',
|
|
37
|
-
review: () => 'review: an independent review of the current patch.',
|
|
37
|
+
review: () => 'review: an independent review of the current patch (this turn\'s changes, commits made in the turn included). To review work committed in earlier turns, pass since: the commit, branch or HEAD~N it started from; when this turn changed nothing, it reviews the branch\'s commits since it left the default branch.',
|
|
38
38
|
};
|
|
39
39
|
export function delegateDescription(roles) {
|
|
40
40
|
return `Hand work to a helper with its own context. Helpers read the project but cannot change files or call helpers. ${roles.map(role => HELPER_USES[role](roles)).join(' ')} A lookup that one grep or read answers stays with you. Write the task as a brief the helper can act on alone: the goal, what to find or check, where to start and what you already know or ruled out, and the answer you need (file:line facts). One call per helper runs at a time; each can be called again, up to ${HELPER_CALLS} times per user message, for example a second review after fixing what the first one found.`;
|
|
@@ -8,7 +8,7 @@ import { ManagedToolBoundary } from './tool-boundary.mjs';
|
|
|
8
8
|
import { managedResourceLoader } from './resource-loader.mjs';
|
|
9
9
|
import { shareGrant, releaseGrant } from './grant-share.mjs';
|
|
10
10
|
import { describeFailure, failureCode, failureText } from '../runtime/managed-failure.mjs';
|
|
11
|
-
import { reviewParts, mergeReviews, REVIEW_PARALLEL } from './patch-snapshot.mjs';
|
|
11
|
+
import { reviewParts, mergeReviews, REVIEW_PARALLEL, emptySnapshot, readBranchBase, readPatchDigest, readPatchSnapshot, resolveReviewBase } from './patch-snapshot.mjs';
|
|
12
12
|
import { reviewFindings, briefIssues } from './workflow.mjs';
|
|
13
13
|
import { anchorText, relayObjection, recordVerdicts } from './objections.mjs';
|
|
14
14
|
import { HELPER_CALLS, HELPER_SETUP, READ_TOOLS, countedCheck } from './helper-roles.mjs';
|
|
@@ -21,8 +21,24 @@ const textContent = result => result.content?.filter(p => p.type === 'text').map
|
|
|
21
21
|
const HELPER_SWITCH = new Set(['upstream_rate_limited', 'session_account_not_ready_retry_later', 'session_account_unavailable_start_new_session', 'account_capacity_unavailable', 'execution_capability_unavailable']);
|
|
22
22
|
const HELPER_ATTEMPTS = 2;
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
// The patch a review reads: this turn's change; the commits since `since`
|
|
25
|
+
// (a commit before HEAD the main agent names); or, when the turn changed
|
|
26
|
+
// nothing and the main agent asked (a review of work committed in earlier
|
|
27
|
+
// turns), the branch's commits since it left the default branch.
|
|
28
|
+
async function reviewSnapshot(managed, harness, since) {
|
|
29
|
+
if (since) {
|
|
30
|
+
const base = await resolveReviewBase(managed.boundary, since);
|
|
31
|
+
if (!base) throw Error(`managed-review-base-unknown: "${String(since).slice(0, 80)}" is not a commit HEAD descends from in this repository; name a commit, a branch or HEAD~N`);
|
|
32
|
+
return Object.assign(await readPatchSnapshot(managed.boundary, null, base), { from: { kind: 'since', ref: since, base } });
|
|
33
|
+
}
|
|
34
|
+
const snapshot = await managed.patchSnapshot();
|
|
35
|
+
if (harness || !emptySnapshot(snapshot)) return snapshot;
|
|
36
|
+
const branch = await readBranchBase(managed.boundary);
|
|
37
|
+
return branch ? Object.assign(await readPatchSnapshot(managed.boundary, null, branch.base), { from: { kind: 'branch', ref: branch.ref, base: branch.base } }) : snapshot;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export async function runHelper(managed, role, task, signal, harness, { verifyGrant, patiently, title, since }) {
|
|
41
|
+
const snapshot = role === 'review' ? await reviewSnapshot(managed, harness, since) : null, parts = snapshot ? reviewParts(snapshot) : null;
|
|
26
42
|
// A helper whose company model account is out of usage, or resting after
|
|
27
43
|
// a refusal, starts once more: Studio then gives the new helper the next
|
|
28
44
|
// model of its role that serves (an auto role's list). Helpers read and
|
|
@@ -98,15 +114,17 @@ async function helperAttempt(managed, role, task, signal, harness, snapshot, par
|
|
|
98
114
|
review = mergeReviews(parts, answers, { findingsOf: reviewFindings, issuesOf: briefIssues });
|
|
99
115
|
({ reply, usage } = review);
|
|
100
116
|
}
|
|
101
|
-
const
|
|
102
|
-
const
|
|
117
|
+
const from = snapshot?.from ?? null;
|
|
118
|
+
const stale = snapshot ? (await (from ? readPatchDigest(managed.boundary, null, from.base) : managed.patchDigest())) !== snapshot.digest : false;
|
|
119
|
+
const details = { role, runID: grant.run_id, tokens: usage, patchDigest: snapshot?.digest, stale, ...(from ? { since: { kind: from.kind, ref: from.ref, base: from.base } } : {}) };
|
|
103
120
|
if (snapshot) {
|
|
104
121
|
// Severity-graded findings decide whether the harness sends the agent back.
|
|
105
122
|
const findings = review ? review.findings : reviewFindings(reply);
|
|
106
123
|
Object.assign(details, { parsed: review ? review.parsed : !!findings, findings: (findings ?? []).slice(0, 40), blocking: findings?.filter(f => f.severity === 'blocking').length ?? 0 });
|
|
107
124
|
if (review) Object.assign(details, { parts: parts.parts.length, unread: parts.omitted.map(o => o.path).slice(0, 50) });
|
|
108
125
|
if (managed.run) { managed.run.reviews += 1; managed.run.blocking += details.blocking; }
|
|
109
|
-
|
|
126
|
+
// A review of earlier commits is not the review of this turn's change.
|
|
127
|
+
if (!from) managed.review = details;
|
|
110
128
|
managed.session.sessionManager.appendCustomEntry('agent-watch-review', details);
|
|
111
129
|
}
|
|
112
130
|
const verdicts = role === 'verify' ? recordVerdicts(managed.run, reply, harness, details) : '';
|
|
@@ -52,7 +52,7 @@ export function credentialFiles(roots, { limit = SCAN_ENTRIES } = {}) {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
const depth = file => file.split('/').length;
|
|
55
|
-
export function bubblewrapArgs({ cwd, sdkRoot, runtimeRoot, temporary, empty, node, readOnly = false, repository = [], gitDirs = [], toolchains = [], skills = [], caches = [], references = [], network = false, credentials = [], docker = null }) {
|
|
55
|
+
export function bubblewrapArgs({ cwd, sdkRoot, runtimeRoot, temporary, empty, node, readOnly = false, repository = [], gitDirs = [], toolchains = [], skills = [], caches = [], references = [], network = false, credentials = [], docker = null, proxySocket = null }) {
|
|
56
56
|
const exists = file => { try { fs.statSync(file); return true; } catch { return false; } };
|
|
57
57
|
const readable = [...new Set([sdkRoot, runtimeRoot, path.dirname(node), ...repository, ...toolchains, ...skills, ...references, ...(readOnly ? [cwd, ...gitDirs] : [])])].filter(exists);
|
|
58
58
|
const writable = [...new Set([...caches, ...(readOnly ? [] : [cwd, ...gitDirs])])].filter(exists);
|
|
@@ -68,6 +68,9 @@ export function bubblewrapArgs({ cwd, sdkRoot, runtimeRoot, temporary, empty, no
|
|
|
68
68
|
...credentials.filter(item => exists(item.path)).flatMap(item => item.directory ? ['--tmpfs', item.path] : ['--ro-bind', empty, item.path]),
|
|
69
69
|
// An approved Docker command reaches the engine's socket (run_with_docker).
|
|
70
70
|
...(docker && exists(docker) ? ['--bind', docker, docker] : []),
|
|
71
|
+
// A command without network reaches the package proxy (package-proxy.mjs)
|
|
72
|
+
// through this socket; the worker forwards 127.0.0.1:3128 to it.
|
|
73
|
+
...(proxySocket && exists(proxySocket) ? ['--bind', proxySocket, '/run/piagent-proxy.sock'] : []),
|
|
71
74
|
'--remount-ro', '/', '--chdir', cwd,
|
|
72
75
|
];
|
|
73
76
|
}
|