@piagent/platform 1.15.1 → 1.16.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.
Files changed (72) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +1 -1
  3. package/README.vi.md +1 -1
  4. package/docs/command-reference-vietnamese.md +2 -2
  5. package/docs/distribution-standard.md +6 -6
  6. package/docs/languages.json +2 -2
  7. package/docs/operator-manual-vietnamese.md +7 -7
  8. package/docs/publishing-for-teams.md +2 -0
  9. package/docs/release-install-policy.md +2 -2
  10. package/docs/team-onboarding.md +2 -2
  11. package/docs-site/architecture.html +1 -1
  12. package/docs-site/benchmark.html +1 -1
  13. package/docs-site/commands.html +1 -1
  14. package/docs-site/content/en/index.html +4 -4
  15. package/docs-site/content/en/whats-new.html +22 -0
  16. package/docs-site/content/index.html +4 -4
  17. package/docs-site/content/whats-new.html +22 -0
  18. package/docs-site/context-engine.html +1 -1
  19. package/docs-site/ecosystem.html +1 -1
  20. package/docs-site/en/architecture.html +1 -1
  21. package/docs-site/en/benchmark.html +1 -1
  22. package/docs-site/en/commands.html +1 -1
  23. package/docs-site/en/context-engine.html +1 -1
  24. package/docs-site/en/ecosystem.html +1 -1
  25. package/docs-site/en/index.html +5 -5
  26. package/docs-site/en/mcp-approval.html +1 -1
  27. package/docs-site/en/mcp-auth.html +1 -1
  28. package/docs-site/en/mcp-servers.html +1 -1
  29. package/docs-site/en/mcp.html +1 -1
  30. package/docs-site/en/permissions.html +1 -1
  31. package/docs-site/en/profiles.html +1 -1
  32. package/docs-site/en/quickstart.html +1 -1
  33. package/docs-site/en/runtime.html +1 -1
  34. package/docs-site/en/scope.html +1 -1
  35. package/docs-site/en/security.html +1 -1
  36. package/docs-site/en/team.html +1 -1
  37. package/docs-site/en/whats-new.html +23 -1
  38. package/docs-site/en/windows.html +1 -1
  39. package/docs-site/en/workflows.html +1 -1
  40. package/docs-site/index.html +5 -5
  41. package/docs-site/mcp-approval.html +1 -1
  42. package/docs-site/mcp-auth.html +1 -1
  43. package/docs-site/mcp-servers.html +1 -1
  44. package/docs-site/mcp.html +1 -1
  45. package/docs-site/permissions.html +1 -1
  46. package/docs-site/profiles.html +1 -1
  47. package/docs-site/quickstart.html +1 -1
  48. package/docs-site/runtime.html +1 -1
  49. package/docs-site/scope.html +1 -1
  50. package/docs-site/security.html +1 -1
  51. package/docs-site/team.html +1 -1
  52. package/docs-site/whats-new.html +23 -1
  53. package/docs-site/windows.html +1 -1
  54. package/docs-site/workflows.html +1 -1
  55. package/evals/private-holdout-v1/public-exposure.v2.json +2 -2
  56. package/package.json +1 -1
  57. package/packages/piagent-core/extensions/piagent-guard.ts +8 -1
  58. package/packages/piagent-core/managed/call-purpose.mjs +11 -1
  59. package/packages/piagent-core/managed/compaction.mjs +47 -1
  60. package/packages/piagent-core/managed/permission.mjs +22 -0
  61. package/packages/piagent-core/managed/request-stream.mjs +9 -1
  62. package/packages/piagent-core/managed/session.mjs +17 -8
  63. package/packages/piagent-core/package.json +1 -1
  64. package/packages/piagent-core/runtime/policy/bypass-policy.mjs +42 -0
  65. package/packages/piagent-webui/dist/client/assets/{MarkdownMessage-DjA3OGyI.js → MarkdownMessage-FBwt5TJv.js} +1 -1
  66. package/packages/piagent-webui/dist/client/assets/{index-bE2DKmc1.js → index-Bj9Tlouu.js} +12 -12
  67. package/packages/piagent-webui/dist/client/index.html +1 -1
  68. package/packages/piagent-webui/gateway/gateway-service.ts +2 -1
  69. package/packages/piagent-webui/gateway/managed-projection.ts +3 -1
  70. package/packages/piagent-webui/gateway/runtime-session-controls.ts +7 -1
  71. package/packages/piagent-webui/gateway/session-catalog.ts +3 -2
  72. package/schemas/piagent-webui/session-catalog-v1.schema.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.15.1 docs · EN</span>
33
+ <span class="pill"><span class="pill-dot"></span>v1.16.0 docs · EN</span>
34
34
  <nav class="language-switch" aria-label="Language">
35
35
  <a class="language-option" href="/team" hreflang="vi" lang="vi">VI</a>
36
36
  <a class="language-option current" href="/en/team" 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.15.1 docs · EN</span>
33
+ <span class="pill"><span class="pill-dot"></span>v1.16.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,28 @@
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.16.0 · 2026-10-07</p>
109
+ <h2 id="v1-16-0">Bypass for company conversations</h2>
110
+ <p class="section-lead">Choose <strong>Bypass</strong> in the new-chat options or the conversation header ("Ask first" stays the default). Commands that need the internet (package installs, downloads, git pull, tests with a server or browser) run without asking. You are still asked before anything that pushes or sends data out (git push, publish, deploy, uploads, ssh), database migrations, deletes with an unknown target, and sudo.</p>
111
+ <ul>
112
+ <li>A helper the company Harness adds while you work is available from your next message, without a new conversation. With Studio 0.20.1 a running turn is not stopped when the Harness is saved.</li>
113
+ <li>Personal sessions with full access no longer ask before a broad <span class="inline-code">git add</span>; deletes, migrations and external actions are still asked.</li>
114
+ </ul>
115
+ <p>Updating from 1.15.x needs no re-import in Agent Watch.</p>
116
+ </section>
117
+
118
+ <section class="section">
119
+ <p class="section-kicker">v1.15.2 · 2026-10-07</p>
120
+ <h2 id="v1-15-2">Long company conversations shrink again, earlier</h2>
121
+ <p class="section-lead">A long company conversation's summary carried the provider's placeholder key instead of the run's grant, so Studio refused it (401 <span class="inline-code">authentication_required</span>, "Chưa chọn tài khoản" / "CLI trực tiếp" in the request monitor) before every step and the conversation kept growing. Summaries now use the run's grant, and Studio logs them as <span class="inline-code">summary</span>.</p>
122
+ <ul>
123
+ <li>A conversation is summarised at 90% of the model's window and never later than 300k tokens: 244.8k on a 272k GPT window (prices double above 272k), 300k on a 1M-token window instead of about 984k. About the last 20k tokens stay word for word.</li>
124
+ <li>A summary that fails is asked again after 1, 2, 4 … minutes (at most 30) instead of before every step.</li>
125
+ </ul>
126
+ <p>Updating from 1.15.x needs no re-import in Agent Watch.</p>
127
+ </section>
128
+
107
129
  <section class="section">
108
130
  <p class="section-kicker">v1.15.1 · 2026-10-07</p>
109
131
  <h2 id="v1-15-1">Studio sees what each model call is for</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.15.1 docs · EN</span>
33
+ <span class="pill"><span class="pill-dot"></span>v1.16.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.15.1 docs · EN</span>
33
+ <span class="pill"><span class="pill-dot"></span>v1.16.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>
@@ -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.15.1 docs · VI</span>
33
+ <span class="pill"><span class="pill-dot"></span>v1.16.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.15.1</p>
97
+ <p class="eyebrow">Piagent 1.16.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.15.1</a>
111
+ <a class="button" href="/whats-new">Có gì mới trong 1.16.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.15.1</span>
187
+ <span class="card-kicker">Bản 1.16.0</span>
188
188
  <h3>Có gì mới</h3>
189
- <p>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>
189
+ <p>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.15.1 docs · VI</span>
33
+ <span class="pill"><span class="pill-dot"></span>v1.16.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>
@@ -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.15.1 docs · VI</span>
33
+ <span class="pill"><span class="pill-dot"></span>v1.16.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.15.1 docs · VI</span>
33
+ <span class="pill"><span class="pill-dot"></span>v1.16.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>
@@ -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.15.1 docs · VI</span>
33
+ <span class="pill"><span class="pill-dot"></span>v1.16.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.15.1 docs · VI</span>
33
+ <span class="pill"><span class="pill-dot"></span>v1.16.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>
@@ -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.15.1 docs · VI</span>
33
+ <span class="pill"><span class="pill-dot"></span>v1.16.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.15.1 docs · VI</span>
33
+ <span class="pill"><span class="pill-dot"></span>v1.16.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>
@@ -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.15.1 docs · VI</span>
33
+ <span class="pill"><span class="pill-dot"></span>v1.16.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>
@@ -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.15.1 docs · VI</span>
33
+ <span class="pill"><span class="pill-dot"></span>v1.16.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>
@@ -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.15.1 docs · VI</span>
33
+ <span class="pill"><span class="pill-dot"></span>v1.16.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>
@@ -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.15.1 docs · VI</span>
33
+ <span class="pill"><span class="pill-dot"></span>v1.16.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>
@@ -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.15.1 docs · VI</span>
33
+ <span class="pill"><span class="pill-dot"></span>v1.16.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,28 @@
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.16.0 · 2026-10-07</p>
109
+ <h2 id="v1-16-0">Bypass cho cuộc trò chuyện công ty</h2>
110
+ <p class="section-lead">Chọn <strong>Bypass</strong> trong tùy chọn cuộc trò chuyện mới hoặc trên thanh đầu cuộc trò chuyện ("Hỏi trước" vẫn là mặc định). Lệnh cần internet (cài package, tải file, git pull, test có server hay browser) chạy luôn, không hỏi. Vẫn hỏi trước khi đẩy hoặc gửi dữ liệu ra ngoài (git push, publish, deploy, upload, ssh), chạy migration database, xóa mà không rõ đích hoặc dùng sudo.</p>
111
+ <ul>
112
+ <li>Harness công ty thêm subagent trong lúc bạn đang làm: dùng được ngay từ tin nhắn kế tiếp, không cần mở cuộc trò chuyện mới. Với Studio 0.20.1, lượt đang chạy không bị dừng khi Harness được lưu.</li>
113
+ <li>Phiên cá nhân "Toàn quyền" không còn hỏi trước <span class="inline-code">git add</span> toàn bộ; xóa, migration và thao tác ra ngoài vẫn hỏi.</li>
114
+ </ul>
115
+ <p>Cập nhật từ 1.15.x không cần nhập lại cấu hình trong Agent Watch.</p>
116
+ </section>
117
+
118
+ <section class="section">
119
+ <p class="section-kicker">v1.15.2 · 2026-10-07</p>
120
+ <h2 id="v1-15-2">Cuộc trò chuyện công ty dài tự thu gọn trở lại, và sớm hơn</h2>
121
+ <p class="section-lead">Tóm tắt hội thoại dài ở chế độ công ty gửi nhầm key giữ chỗ thay vì quyền của lượt chạy, nên Studio từ chối (401 <span class="inline-code">authentication_required</span>, hiện là "Chưa chọn tài khoản" / "CLI trực tiếp" trong theo dõi request) trước mỗi bước và hội thoại cứ dài thêm. Giờ tóm tắt dùng quyền của lượt chạy và Studio ghi là <span class="inline-code">summary</span>.</p>
122
+ <ul>
123
+ <li>Hội thoại được tóm tắt khi đạt 90% cửa sổ của model và muộn nhất ở 300k token: 244,8k với GPT 272k (giá gấp đôi trên 272k), 300k với model 1M thay vì khoảng 984k. Khoảng 20k token gần nhất vẫn giữ nguyên văn.</li>
124
+ <li>Tóm tắt bị lỗi được thử lại sau 1, 2, 4 … phút (tối đa 30) thay vì trước mỗi bước.</li>
125
+ </ul>
126
+ <p>Cập nhật từ 1.15.x không cần nhập lại cấu hình trong Agent Watch.</p>
127
+ </section>
128
+
107
129
  <section class="section">
108
130
  <p class="section-kicker">v1.15.1 · 2026-10-07</p>
109
131
  <h2 id="v1-15-1">Studio thấy mỗi call của model dùng để làm gì</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.15.1 docs · VI</span>
33
+ <span class="pill"><span class="pill-dot"></span>v1.16.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>
@@ -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.15.1 docs · VI</span>
33
+ <span class="pill"><span class="pill-dot"></span>v1.16.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": 524,
260
- "sha256": "905a1c9999775af0f40d20589e23f047bb0ba5974b258cb5d7c2dcb255c56086"
259
+ "fileCount": 525,
260
+ "sha256": "88975f723534cb5aa9f8755c8d6694c2371baecb79c0fc4baf83f066a44f9375"
261
261
  }
262
262
  ],
263
263
  "custodianComparisonRules": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@piagent/platform",
3
- "version": "1.15.1",
3
+ "version": "1.16.0",
4
4
  "license": "MIT",
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -547,6 +547,9 @@ function verifyProjectCapabilityState(
547
547
  }
548
548
  }
549
549
 
550
+ // Exec-policy prompts a full-access session does not show: local, reversible.
551
+ const FULL_ACCESS_SKIPPED_PROMPTS = ["prompt-git-add-broad"];
552
+
550
553
  function evaluateExecPolicy(command: string, profile: ProjectProfile, policy: BasePolicy): {
551
554
  mode: RuntimePolicySettings["execPolicy"];
552
555
  decision: "allow" | "prompt" | "forbid";
@@ -3953,7 +3956,11 @@ export default function piagentGuard(pi: ExtensionAPI) {
3953
3956
  return { block: true, reason: unresolvedExpansionReason("Command", unresolvedExpansions) };
3954
3957
  }
3955
3958
 
3956
- const confirmationReasons = execDecision.mode !== "off" && execDecision.decision === "prompt" ? [...execDecision.reasons] : [];
3959
+ // Full access skips the prompts for local, reversible steps; deletes,
3960
+ // migrations and anything sent outside this machine are still asked.
3961
+ const confirmationReasons = (execDecision.mode !== "off" && execDecision.decision === "prompt" ? [...execDecision.reasons] : [])
3962
+ .filter((reason) => permissionProfile.mode !== "trusted-full-access"
3963
+ || !FULL_ACCESS_SKIPPED_PROMPTS.some((id) => reason.startsWith(`Prompt required by exec policy ${id}:`)));
3957
3964
  const externalReason = findShellExternalConfirmationReason(execDecision.segments, externalActionPolicyConfig(policy));
3958
3965
  if (externalReason) confirmationReasons.push(externalReason);
3959
3966
  if (confirmationReasons.length > 0) {
@@ -29,7 +29,7 @@ export function jobTitle(task, title) {
29
29
  export function purposeHeaders(owner, runtime, role, context) {
30
30
  const messages = context?.messages ?? [], last = messages.at(-1);
31
31
  let purpose, after = '';
32
- if (typeof context?.systemPrompt === 'string' && context.systemPrompt.startsWith(SUMMARY_PROMPT)) purpose = 'summary';
32
+ if (systemText(context).startsWith(SUMMARY_PROMPT)) purpose = 'summary';
33
33
  else if (last?.role === 'toolResult') { purpose = 'tool_step'; after = afterTools(messages.findLast(m => m.role === 'assistant')); }
34
34
  else if (role !== 'main') purpose = 'brief';
35
35
  else if (owner.nextPurpose === 'harness') { purpose = 'harness'; owner.nextPurpose = null; }
@@ -37,3 +37,13 @@ export function purposeHeaders(owner, runtime, role, context) {
37
37
  const title = purpose === 'brief' ? owner.jobTitles?.get(runtime) : '';
38
38
  return { 'X-Agent-Purpose': purpose, ...(after ? { 'X-Agent-After': after } : {}), ...(title ? { 'X-Agent-Task': encodeURIComponent(title) } : {}) };
39
39
  }
40
+
41
+ // Pi folds the system prompt into a leading system message before a call
42
+ // reaches a provider, so a summary is recognised in either shape.
43
+ function systemText(context) {
44
+ if (typeof context?.systemPrompt === 'string') return context.systemPrompt;
45
+ const first = context?.messages?.[0];
46
+ if (first?.role !== 'system') return '';
47
+ if (typeof first.content === 'string') return first.content;
48
+ return Array.isArray(first.content) ? first.content.filter(p => p?.type === 'text').map(p => p.text).join('') : '';
49
+ }
@@ -17,6 +17,49 @@ function addUsage(a, b) {
17
17
  totalTokens: sum(a.totalTokens, b.totalTokens), cost: Object.fromEntries(Object.keys(a.cost ?? {}).map(k => [k, sum(a.cost[k], b.cost?.[k])])) };
18
18
  }
19
19
 
20
+ // When a long conversation is summarised. Pi waits until the window is full
21
+ // but for its 16k reserve; Codex summarises at 90% of the window, and its
22
+ // GPT models report a 272k window under an 872k maximum. A turn re-reads the
23
+ // whole context: a 1M-token window full to the brim bills about 1M input
24
+ // tokens per step (GPT doubles its price above 272k) and answers worse.
25
+ // Summarise at 90% of the window, and never later than 300k tokens.
26
+ export const COMPACT_SHARE = 0.9, COMPACT_CEILING_TOKENS = 300_000;
27
+ // Pi's own reserve: the summary may write up to 80% of it.
28
+ export const SUMMARY_RESERVE_TOKENS = 16_384;
29
+ export function compactionTrigger(contextWindow) {
30
+ return Math.min(Math.floor(contextWindow * COMPACT_SHARE), contextWindow - SUMMARY_RESERVE_TOKENS, COMPACT_CEILING_TOKENS);
31
+ }
32
+ // Pi compacts once context > window - reserveTokens: the trigger is set
33
+ // through the reserve, per model (Auto may move a conversation to another
34
+ // window). The summary keeps Pi's reserve (see stageCompaction).
35
+ export function compactEarly(settingsManager) {
36
+ const settings = settingsManager.getCompactionSettings.bind(settingsManager);
37
+ settingsManager.getCompactionSettings = model => {
38
+ const own = settings(model), window = model?.contextWindow;
39
+ return window > 0 ? { ...own, reserveTokens: Math.max(own.reserveTokens, window - compactionTrigger(window)) } : own;
40
+ };
41
+ }
42
+ // A summary that failed is not asked again at every step: each attempt can
43
+ // cost a full read of the conversation. Threshold attempts wait 1, 2, 4 …
44
+ // minutes (at most 30) after a failure; a success or an overflow (Pi retries
45
+ // that once on its own) is not held back.
46
+ export const COMPACT_BACKOFF_MS = 60_000, COMPACT_BACKOFF_MAX_MS = 30 * 60_000;
47
+ export function backOffFailedCompaction(session, now = Date.now) {
48
+ const run = session._runAutoCompaction?.bind(session);
49
+ if (!run) throw Error('managed-sdk-version-unqualified');
50
+ let failures = 0, failedAt = 0;
51
+ session.subscribe(event => {
52
+ if (event?.type !== 'compaction_end' || event.reason !== 'threshold') return;
53
+ if (event.result) failures = 0;
54
+ else if (!event.aborted) { failures += 1; failedAt = now(); }
55
+ });
56
+ session._runAutoCompaction = (reason, willRetry) => {
57
+ const wait = failures ? Math.min(COMPACT_BACKOFF_MS * 2 ** (failures - 1), COMPACT_BACKOFF_MAX_MS) : 0;
58
+ if (reason === 'threshold' && now() - failedAt < wait) return Promise.resolve(false);
59
+ return run(reason, willRetry);
60
+ };
61
+ }
62
+
20
63
  // Pi summarises everything older than the kept tail in one request. A
21
64
  // conversation can be longer than the window of the model a run uses now
22
65
  // (the harness moved from a 1M-token model to a 272k one, or Auto fell
@@ -33,7 +76,10 @@ export async function stageCompaction(session, api, sdk) {
33
76
  return unfinished(plan) ? { ...result, summary: `${result.summary}\n\nCurrent plan (kept verbatim; keep it up to date with update_plan):\n${planText(plan)}` } : result;
34
77
  };
35
78
  session._runDefaultCompaction = async (preparation, model, apiKey, headers, instructions, signal, env, reason) => {
36
- const { settings, previousSummary } = preparation, room = model.contextWindow - settings.reserveTokens;
79
+ // The reserve that set the trigger is not the summary's budget.
80
+ const settings = { ...preparation.settings, reserveTokens: Math.min(preparation.settings.reserveTokens, SUMMARY_RESERVE_TOKENS) };
81
+ preparation = { ...preparation, settings };
82
+ const { previousSummary } = preparation, room = model.contextWindow - settings.reserveTokens;
37
83
  const history = [...preparation.messagesToSummarize, ...preparation.turnPrefixMessages];
38
84
  const size = history.reduce((n, m) => n + api.estimateTokens(m), 0) + Math.ceil((previousSummary?.length ?? 0) / 4);
39
85
  if (size + 4096 <= room) {
@@ -0,0 +1,22 @@
1
+ // A company conversation's access, chosen by the member and kept with the
2
+ // conversation: "workspace-write" asks before every command that needs the
3
+ // internet; "trusted-full-access" (Bypass) asks only for what must be
4
+ // confirmed (runtime/policy/bypass-policy.mjs).
5
+ import { mustConfirm } from '../runtime/policy/bypass-policy.mjs';
6
+
7
+ export const PERMISSIONS = ['workspace-write', 'trusted-full-access'];
8
+ const ENTRY = 'agent-watch-permission';
9
+
10
+ export function restorePermission(manager) {
11
+ const chosen = manager.getEntries().filter(e => e.type === 'custom' && e.customType === ENTRY).at(-1)?.data?.mode;
12
+ return PERMISSIONS.includes(chosen) ? chosen : 'workspace-write';
13
+ }
14
+ export function permissionSetter(owner, manager) {
15
+ return mode => {
16
+ if (!PERMISSIONS.includes(mode)) throw Error('managed-permission-unavailable');
17
+ manager.appendCustomEntry(ENTRY, { mode, at: new Date().toISOString() }); owner.permission = mode;
18
+ };
19
+ }
20
+ // Why a network command must still be asked about: null runs it in Bypass,
21
+ // 'ask' when the member asks first.
22
+ export const networkConfirmation = (owner, command) => owner.permission === 'trusted-full-access' ? mustConfirm(command) : 'ask';
@@ -11,6 +11,14 @@ import { CLIENT_AGENT } from './client-agent.mjs';
11
11
  import { shareGrant, releaseGrant } from './grant-share.mjs';
12
12
  import { purposeHeaders } from './call-purpose.mjs';
13
13
 
14
+ // A caller may pass the provider's resolved auth headers (Pi's compaction and
15
+ // branch summaries do): for this provider that is the registered placeholder
16
+ // key, and caller headers override the role token. Only the grant authenticates.
17
+ const CREDENTIAL_HEADERS = /^(authorization|x-api-key)$/i;
18
+ function withoutCredentials(headers) {
19
+ return headers && Object.fromEntries(Object.entries(headers).filter(([name]) => !CREDENTIAL_HEADERS.test(name)));
20
+ }
21
+
14
22
  // How long one request waits in line for a free company model account.
15
23
  const CAPACITY_WAIT_MS = 20 * 60_000;
16
24
  // How long a helper's request waits before the helper moves to another model.
@@ -62,7 +70,7 @@ export function wrapRoleStreams(owner, runtime, role, { provider, verifyGrant })
62
70
  // same company account and prompt cache; a helper names its role.
63
71
  const conversation = role === 'main' ? conversationSession(owner) : null;
64
72
  const stream = original({ ...model, id: route.native }, context, { ...options, apiKey: grant.token, sessionId: conversation ?? grant.role_id, maxRetries: 0,
65
- headers: { ...options?.headers, ...purpose, 'User-Agent': CLIENT_AGENT, 'X-Session-Id': grant.role_id, ...(conversation ? { 'X-Claude-Code-Session-Id': conversation } : {}) } });
73
+ headers: { ...withoutCredentials(options?.headers), ...purpose, 'User-Agent': CLIENT_AGENT, 'X-Session-Id': grant.role_id, ...(conversation ? { 'X-Claude-Code-Session-Id': conversation } : {}) } });
66
74
  // Whether Studio admitted the request is known at its first event
67
75
  // after "start": until then nothing is passed on, so a refused
68
76
  // request leaves no trace in the conversation.
@@ -17,12 +17,13 @@ import { wrapRoleStreams } from './request-stream.mjs';
17
17
  import { runHelper } from './helper-run.mjs';
18
18
  import { askTool } from './member-questions.mjs';
19
19
  import { setTimeout as sleep } from 'node:timers/promises';
20
- import { stageCompaction } from './compaction.mjs';
20
+ import { stageCompaction, compactEarly, backOffFailedCompaction } from './compaction.mjs';
21
21
  import { readPatchDigest, readPatchSnapshot, readChangedFiles } from './patch-snapshot.mjs';
22
22
  import { workflowPolicy, repositoryChecks, planTool, currentPlan, PLAN_ENTRY, workflowPrompt, RunProcess, completionGate, pendingBaseline, pendingPaths, processEditTools } from './workflow.mjs';
23
23
  import { beforeDelegate } from './objections.mjs';
24
24
  import { HELPER_CALLS, HELPER_ROLES, helperRoles, helperPrompt, webPrompt, delegateDescription } from './helper-roles.mjs';
25
25
  import { loadAgentResources } from './agent-skills.mjs';
26
+ import { restorePermission, permissionSetter, networkConfirmation } from './permission.mjs';
26
27
 
27
28
  const PROVIDER = 'agent_watch_managed';
28
29
  // Who the agent is: the model account may put another product's name in an
@@ -109,6 +110,7 @@ export class ManagedSession {
109
110
  parameters:{type:'object',properties:{},additionalProperties:false},
110
111
  execute:async(id,_args,signal,_update,ctx)=>{
111
112
  const plan=await repositoryFetchPlan(self.boundary);
113
+ if(self.permission==='trusted-full-access'&&!signal?.aborted)return executeRepositoryFetch(self.boundary,plan,signal);
112
114
  const {piApprovalBroker}=await import('../runtime/inspection/approval-broker.ts');
113
115
  const decision=await piApprovalBroker.request({cwd:self.cwd,rawSessionId:self.session.sessionManager.getSessionId(),toolCallId:id,
114
116
  action:{kind:'external-provider-action',preconditionClass:'runtime-only',toolName:'fetch_origin',rawAction:plan,
@@ -125,10 +127,11 @@ export class ManagedSession {
125
127
  customTools.push({name:'run_with_network',label:'Run with network',description:'Run one shell command that needs the internet (package install, download, git pull of a public repository), 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.',
126
128
  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},
127
129
  execute:async(id,args,signal,onUpdate,ctx)=>{
128
- const {piApprovalBroker}=await import('../runtime/inspection/approval-broker.ts');
129
- const decision=await piApprovalBroker.request({cwd:self.cwd,rawSessionId:self.session.sessionManager.getSessionId(),toolCallId:id,
130
+ // Bypass runs it without asking, unless it is one the member must confirm.
131
+ const confirm=await networkConfirmation(self,args.command);
132
+ const decision=confirm===null?{allowed:true,consume:()=>true}:await (await import('../runtime/inspection/approval-broker.ts')).piApprovalBroker.request({cwd:self.cwd,rawSessionId:self.session.sessionManager.getSessionId(),toolCallId:id,
130
133
  action:{kind:'external-provider-action',preconditionClass:'runtime-only',toolName:'run_with_network',rawAction:{command:args.command},commandPreview:String(args.command),
131
- targetPaths:[self.cwd],provider:'network',urlOrigin:null,requestedScope:'network-command-once',reason:String(args.reason).slice(0,300),riskClass:'medium',
134
+ targetPaths:[self.cwd],provider:'network',urlOrigin:null,requestedScope:'network-command-once',reason:(confirm==='ask'?String(args.reason):`Bypass still asks: ${confirm}. ${args.reason}`).slice(0,300),riskClass:'medium',
132
135
  allowConsequence:'Run this exact command once, with internet access; a server it starts accepts connections while it runs.',denyConsequence:'The command does not run; the agent is told you declined.'},
133
136
  terminalConfirm:()=>ctx?.ui?.confirm?.('Run with network',`Allow internet access for: ${args.command}`)??Promise.resolve(false),
134
137
  unavailableFallback:'terminal-confirm',recheck:()=>!signal?.aborted&&Boolean(self.grant)});
@@ -138,11 +141,14 @@ export class ManagedSession {
138
141
  try { const result=await self.boundary.invoke('bash',{command:args.command,...(args.timeout?{timeout:args.timeout}:{})},signal,onUpdate,ctx?.model,{network:true}); ok=!result?.isError; return result; }
139
142
  finally { await self.claimChanges(before); await self.run?.afterTool('bash',args,ok,()=>self.digest()); await self.refreshReview(); }
140
143
  }});
141
- // The helpers of the Harness this conversation enrolled with. A later
142
- // enrollment that drops one is refused at the call (delegate).
144
+ // Every helper role passes the tool's schema: Pi fixes a tool's schema
145
+ // and description when the conversation opens, so a helper a Harness
146
+ // saved later adds must already pass it. The system prompt, rebuilt each
147
+ // turn, names the Harness's current helpers; delegate refuses one the
148
+ // Harness does not have.
143
149
  const roles = helperRoles(manifest);
144
150
  if (roles.length) customTools.push({ name: 'delegate', label: 'Subagent', description: delegateDescription(roles),
145
- parameters: { type: 'object', properties: { role: { type: 'string', enum: roles }, title: { type: 'string', maxLength: 120, description: 'One line naming the job, for the company logs (for example "Find where login tokens are stored").' }, task: { type: 'string', minLength: 1, maxLength: 12000 } }, required: ['role', 'task'], additionalProperties: false },
151
+ parameters: { type: 'object', properties: { role: { type: 'string', enum: HELPER_ROLES }, title: { type: 'string', maxLength: 120, description: 'One line naming the job, for the company logs (for example "Find where login tokens are stored").' }, task: { type: 'string', minLength: 1, maxLength: 12000 } }, required: ['role', 'task'], additionalProperties: false },
146
152
  execute: (_id, args, signal) => self.delegate(args, signal) });
147
153
  customTools.push(planTool(async plan => {
148
154
  self.session.sessionManager.appendCustomEntry(PLAN_ENTRY, { ...plan, at: new Date().toISOString() });
@@ -185,6 +191,8 @@ export class ManagedSession {
185
191
  self.extensionsResult = result.extensionsResult;
186
192
  self.session = result.session;
187
193
  self.session.managedExecution = true;
194
+ // The member's access for this conversation: ask first, or Bypass (permission.mjs).
195
+ self.permission = restorePermission(manager); self.session.managedSetPermission = permissionSetter(self, manager);
188
196
  // A helper's receipt (its tokens, the patch it read) is for the member's
189
197
  // eyes: the agent has the helper's answer as the tool result, and a
190
198
  // receipt in its context reads as a message from the member.
@@ -197,6 +205,7 @@ export class ManagedSession {
197
205
  if (event?.type === 'tool_execution_end' && event.isError && textContent(event.result ?? {}) === `Tool ${event.toolName} not found`) self.run && (self.run.unknownTools += 1);
198
206
  });
199
207
  await stageCompaction(self.session, self.api, self.sdk);
208
+ compactEarly(settings); backOffFailedCompaction(self.session);
200
209
  self.publishHelpers();
201
210
  const setThinking=self.session.setThinkingLevel.bind(self.session);
202
211
  self.runThinking = setThinking;
@@ -352,7 +361,7 @@ export class ManagedSession {
352
361
  this.blocked = this.scope && sameMember(this.scope, scope) ? null : 'managed-session-scope-changed';
353
362
  if (this.blocked) throw Error(this.blocked);
354
363
  if (!sameKey(this.scope, scope)) { this.session.sessionManager.appendCustomEntry('agent-watch-scope', scope); this.scope = scope; }
355
- this.session?.setActiveToolsByName(this.session.getActiveToolNames()); // the new Harness workflow reaches the prompt
364
+ this.session?.setActiveToolsByName(this.session.getActiveToolNames()); // the new Harness workflow and helpers reach the prompt
356
365
  }
357
366
  async digest() { try { return await this.changeDigest(); } catch { return null; } }
358
367
  refusedAsTooLong() {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@piagent/core",
3
- "version": "1.15.1",
3
+ "version": "1.16.0",
4
4
  "type": "module",
5
5
  "private": true,
6
6
  "license": "MIT",