@piagent/platform 1.46.0 → 1.46.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.
Files changed (75) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/docs/command-reference-vietnamese.md +2 -2
  3. package/docs/distribution-standard.md +6 -6
  4. package/docs/en/architecture.md +1 -1
  5. package/docs/harness-conformance.md +22 -5
  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/vi/architecture.md +1 -1
  12. package/docs-site/architecture.html +1 -1
  13. package/docs-site/assets/search-en.json +1 -1
  14. package/docs-site/assets/search-vi.json +1 -1
  15. package/docs-site/benchmark.html +1 -1
  16. package/docs-site/commands.html +1 -1
  17. package/docs-site/context-engine.html +1 -1
  18. package/docs-site/ecosystem.html +1 -1
  19. package/docs-site/en/architecture.html +1 -1
  20. package/docs-site/en/benchmark.html +1 -1
  21. package/docs-site/en/commands.html +1 -1
  22. package/docs-site/en/context-engine.html +1 -1
  23. package/docs-site/en/ecosystem.html +1 -1
  24. package/docs-site/en/index.html +15 -15
  25. package/docs-site/en/mcp-approval.html +1 -1
  26. package/docs-site/en/mcp-auth.html +1 -1
  27. package/docs-site/en/mcp-servers.html +1 -1
  28. package/docs-site/en/mcp.html +1 -1
  29. package/docs-site/en/permissions.html +1 -1
  30. package/docs-site/en/profiles.html +1 -1
  31. package/docs-site/en/quickstart.html +1 -1
  32. package/docs-site/en/runtime.html +1 -1
  33. package/docs-site/en/scope.html +1 -1
  34. package/docs-site/en/security.html +1 -1
  35. package/docs-site/en/team.html +1 -1
  36. package/docs-site/en/update.html +3 -3
  37. package/docs-site/en/whats-new.html +51 -26
  38. package/docs-site/en/windows.html +1 -1
  39. package/docs-site/en/workflows.html +1 -1
  40. package/docs-site/index.html +15 -15
  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/releases.json +75 -0
  49. package/docs-site/runtime.html +1 -1
  50. package/docs-site/scope.html +1 -1
  51. package/docs-site/security.html +1 -1
  52. package/docs-site/team.html +1 -1
  53. package/docs-site/update.html +3 -3
  54. package/docs-site/whats-new.html +51 -26
  55. package/docs-site/windows.html +1 -1
  56. package/docs-site/workflows.html +1 -1
  57. package/evals/private-holdout-v1/public-exposure.v2.json +2 -2
  58. package/package.json +1 -1
  59. package/packages/piagent-core/extensions/piagent-guard.ts +4 -1
  60. package/packages/piagent-core/managed/copies.mjs +61 -0
  61. package/packages/piagent-core/managed/grant-share.mjs +9 -1
  62. package/packages/piagent-core/managed/helper-roles.mjs +5 -3
  63. package/packages/piagent-core/managed/helper-run.mjs +120 -52
  64. package/packages/piagent-core/managed/helper-settlement.mjs +5 -1
  65. package/packages/piagent-core/managed/ledger.mjs +187 -0
  66. package/packages/piagent-core/managed/objections.mjs +49 -27
  67. package/packages/piagent-core/managed/patch-snapshot.mjs +9 -0
  68. package/packages/piagent-core/managed/session.mjs +14 -14
  69. package/packages/piagent-core/managed/toolchain.mjs +7 -3
  70. package/packages/piagent-core/managed/workflow.mjs +32 -26
  71. package/packages/piagent-core/package.json +1 -1
  72. package/packages/piagent-core/runtime/hooks/session-hooks.ts +6 -0
  73. package/packages/piagent-core/runtime/managed-failure.mjs +8 -0
  74. package/packages/piagent-webui/gateway/gateway-session-stream.ts +24 -0
  75. package/scripts/company-terminal.mjs +19 -1
@@ -1,4 +1,79 @@
1
1
  [
2
+ {
3
+ "version": "1.46.2",
4
+ "date": "2026-10-29",
5
+ "status": "stable",
6
+ "title": {
7
+ "en": "A message sent after an answer shows at once; the WebUI streams word by word",
8
+ "vi": "Tin gửi sau câu trả lời hiện ngay; WebUI hiện chữ dần"
9
+ },
10
+ "summary": {
11
+ "en": "The terminal takes the next message as soon as an answer ends, and the WebUI shows an answer while the model writes it instead of once its paragraph ends.",
12
+ "vi": "Terminal nhận tin tiếp theo ngay khi câu trả lời kết thúc, và WebUI hiện câu trả lời trong lúc model đang viết thay vì đợi hết đoạn."
13
+ },
14
+ "requires": null,
15
+ "items": [
16
+ {
17
+ "kind": "fixed",
18
+ "en": "In a folder of repositories, a message sent right after an answer reached the terminal 1–2 s late: Pi waited for the PIAGENT panel's working-tree scan. The panel now refreshes afterwards.",
19
+ "vi": "Ở thư mục nhiều repo, tin gửi ngay sau câu trả lời hiện trễ 1–2 giây trong terminal: Pi chờ panel PIAGENT quét working tree. Panel giờ làm mới sau khi Pi nhận tin."
20
+ },
21
+ {
22
+ "kind": "improved",
23
+ "en": "The WebUI shows an answer word by word while the model writes it; a one-paragraph answer appeared only once complete (first text at about 1.5 s, now 0.4 s, measured locally).",
24
+ "vi": "WebUI hiện câu trả lời từng chữ trong lúc model viết; trước đây câu trả lời một đoạn chỉ hiện khi viết xong (chữ đầu tiên khoảng 1,5 giây, nay 0,4 giây khi đo cục bộ)."
25
+ },
26
+ {
27
+ "kind": "security",
28
+ "en": "Streaming holds back a line's last words, so a secret written over several words (Authorization: Basic …, password: …, --token …, a quoted value) is redacted whole.",
29
+ "vi": "Khi hiện chữ dần, vài từ cuối của dòng được giữ lại để bí mật viết qua nhiều từ (Authorization: Basic …, password: …, --token …, giá trị trong ngoặc) được che trọn."
30
+ }
31
+ ]
32
+ },
33
+ {
34
+ "version": "1.46.1",
35
+ "date": "2026-10-28",
36
+ "status": "stable",
37
+ "title": {
38
+ "en": "Objections on the record, one review per turn, parallel subagents on request",
39
+ "vi": "Phản biện có sổ ghi, review một nhịp, subagent song song khi được yêu cầu"
40
+ },
41
+ "summary": {
42
+ "en": "The company harness keeps one ledger of helper objections and the main agent's decisions, reviews once per turn, and runs 2–3 helpers of one role in parallel only when the member asks.",
43
+ "vi": "Harness công ty ghi một sổ phản biện cùng quyết định của main, review một nhịp mỗi lượt, và chỉ chạy 2–3 helper cùng role song song khi member yêu cầu."
44
+ },
45
+ "items": [
46
+ {
47
+ "kind": "new",
48
+ "en": "Objections to a brief, review findings and failed claims share one ledger; the main agent records each decision with resolve_objection, and a wrong-premise objection blocks edits until decided.",
49
+ "vi": "Phản biện brief, finding review và claim fail chung một sổ; main ghi quyết định bằng resolve_objection, phản biện sai tiền đề chặn sửa file đến khi được quyết."
50
+ },
51
+ {
52
+ "kind": "improved",
53
+ "en": "Review runs once per turn: a required review is the harness's own, a re-review after a fix reads only the files changed, minor findings are only listed.",
54
+ "vi": "Review một nhịp mỗi lượt: review bắt buộc do harness làm, review lại sau khi sửa chỉ đọc file đã đổi, finding minor chỉ liệt kê."
55
+ },
56
+ {
57
+ "kind": "new",
58
+ "en": "One helper per role by default; when the member asks for 2–3 of one role, they run in parallel, each on its own grant with Agent Studio 0.50.0 and Agent Watch 0.15.17.",
59
+ "vi": "Mặc định mỗi role một helper; khi member yêu cầu 2–3 helper cùng role, chúng chạy song song, mỗi helper một grant với Agent Studio 0.50.0 và Agent Watch 0.15.17."
60
+ },
61
+ {
62
+ "kind": "improved",
63
+ "en": "The company terminal shows the checklist and what each running subagent is doing above the input.",
64
+ "vi": "Terminal công ty hiện checklist và việc từng subagent đang làm ngay trên ô nhập."
65
+ },
66
+ {
67
+ "kind": "fixed",
68
+ "en": "piagent studio installs fd on first start, so @ completion lists files and folders; it was never downloaded, even with fd under /opt/homebrew/bin.",
69
+ "vi": "piagent studio cài fd ở lần mở đầu tiên nên gợi ý @ hiện file và thư mục; trước đây fd không bao giờ được tải, kể cả khi đã có ở /opt/homebrew/bin."
70
+ }
71
+ ],
72
+ "requires": {
73
+ "en": "Agent Studio 0.50.0 and Agent Watch 0.15.17 (Windows 0.1.18) for parallel subagents",
74
+ "vi": "Agent Studio 0.50.0 và Agent Watch 0.15.17 (Windows 0.1.18) để subagent chạy song song"
75
+ }
76
+ },
2
77
  {
3
78
  "version": "1.46.0",
4
79
  "date": "2026-10-28",
@@ -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.46.0" title="v1.46.0 docs · VI"><span class="dot"></span>v1.46.0</a>
40
+ <a class="version-badge" href="/whats-new" data-docs-version="v1.46.2" title="v1.46.2 docs · VI"><span class="dot"></span>v1.46.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>
@@ -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.46.0" title="v1.46.0 docs · VI"><span class="dot"></span>v1.46.0</a>
40
+ <a class="version-badge" href="/whats-new" data-docs-version="v1.46.2" title="v1.46.2 docs · VI"><span class="dot"></span>v1.46.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>
@@ -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.46.0" title="v1.46.0 docs · VI"><span class="dot"></span>v1.46.0</a>
40
+ <a class="version-badge" href="/whats-new" data-docs-version="v1.46.2" title="v1.46.2 docs · VI"><span class="dot"></span>v1.46.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>
@@ -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.46.0" title="v1.46.0 docs · VI"><span class="dot"></span>v1.46.0</a>
40
+ <a class="version-badge" href="/whats-new" data-docs-version="v1.46.2" title="v1.46.2 docs · VI"><span class="dot"></span>v1.46.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>
@@ -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.46.0" title="v1.46.0 docs · VI"><span class="dot"></span>v1.46.0</a>
40
+ <a class="version-badge" href="/whats-new" data-docs-version="v1.46.2" title="v1.46.2 docs · VI"><span class="dot"></span>v1.46.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>
@@ -145,9 +145,9 @@
145
145
  <h2 id="pin-cho-team">Pin một bản cho cả team</h2>
146
146
  <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>
147
147
  <div class="command-card">
148
- <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&#10;npm install -g --ignore-scripts @piagent/platform@1.46.0&#10;piagent-install --stable --dry-run&#10;piagent-install --stable">Lấy lệnh</button></header>
148
+ <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&#10;npm install -g --ignore-scripts @piagent/platform@1.46.2&#10;piagent-install --stable --dry-run&#10;piagent-install --stable">Lấy lệnh</button></header>
149
149
  <pre><code>npm install -g --ignore-scripts @earendil-works/pi-coding-agent@1.3.0
150
- npm install -g --ignore-scripts @piagent/platform@1.46.0
150
+ npm install -g --ignore-scripts @piagent/platform@1.46.2
151
151
  piagent-install --stable --dry-run
152
152
  piagent-install --stable</code></pre>
153
153
  </div>
@@ -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.46.0" title="v1.46.0 docs · VI"><span class="dot"></span>v1.46.0</a>
40
+ <a class="version-badge" href="/whats-new" data-docs-version="v1.46.2" title="v1.46.2 docs · VI"><span class="dot"></span>v1.46.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,34 @@
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-46-0" data-release>
111
+ <article class="release latest" id="v1-46-2" data-release>
112
+ <div class="release-meta"><a class="release-version" href="#v1-46-2">v1.46.2</a><time class="release-date" datetime="2026-10-29">29/10/2026</time></div>
113
+ <div class="release-body">
114
+ <h3 data-toc-skip id="v1-46-2-title">Tin gửi sau câu trả lời hiện ngay; WebUI hiện chữ dần</h3>
115
+ <p>Terminal nhận tin tiếp theo ngay khi câu trả lời kết thúc, và WebUI hiện câu trả lời trong lúc model đang viết thay vì đợi hết đoạn.</p>
116
+ <ul class="release-items">
117
+ <li data-kind="improved"><span class="kind kind-improved">Cải thiện</span><span>WebUI hiện câu trả lời từng chữ trong lúc model viết; trước đây câu trả lời một đoạn chỉ hiện khi viết xong (chữ đầu tiên khoảng 1,5 giây, nay 0,4 giây khi đo cục bộ).</span></li>
118
+ <li data-kind="fixed"><span class="kind kind-fixed">Sửa lỗi</span><span>Ở thư mục nhiều repo, tin gửi ngay sau câu trả lời hiện trễ 1–2 giây trong terminal: Pi chờ panel PIAGENT quét working tree. Panel giờ làm mới sau khi Pi nhận tin.</span></li>
119
+ <li data-kind="security"><span class="kind kind-security">Bảo mật</span><span>Khi hiện chữ dần, vài từ cuối của dòng được giữ lại để bí mật viết qua nhiều từ (Authorization: Basic …, password: …, --token …, giá trị trong ngoặc) được che trọn.</span></li>
120
+ </ul>
121
+ </div>
122
+ </article>
123
+ <article class="release" id="v1-46-1" data-release>
124
+ <div class="release-meta"><a class="release-version" href="#v1-46-1">v1.46.1</a><time class="release-date" datetime="2026-10-28">28/10/2026</time></div>
125
+ <div class="release-body">
126
+ <h3 data-toc-skip id="v1-46-1-title">Phản biện có sổ ghi, review một nhịp, subagent song song khi được yêu cầu</h3>
127
+ <p>Harness công ty ghi một sổ phản biện cùng quyết định của main, review một nhịp mỗi lượt, và chỉ chạy 2–3 helper cùng role song song khi member yêu cầu.</p>
128
+ <ul class="release-items">
129
+ <li data-kind="new"><span class="kind kind-new">Mới</span><span>Phản biện brief, finding review và claim fail chung một sổ; main ghi quyết định bằng resolve_objection, phản biện sai tiền đề chặn sửa file đến khi được quyết.</span></li>
130
+ <li data-kind="new"><span class="kind kind-new">Mới</span><span>Mặc định mỗi role một helper; khi member yêu cầu 2–3 helper cùng role, chúng chạy song song, mỗi helper một grant với Agent Studio 0.50.0 và Agent Watch 0.15.17.</span></li>
131
+ <li data-kind="improved"><span class="kind kind-improved">Cải thiện</span><span>Review một nhịp mỗi lượt: review bắt buộc do harness làm, review lại sau khi sửa chỉ đọc file đã đổi, finding minor chỉ liệt kê.</span></li>
132
+ <li data-kind="improved"><span class="kind kind-improved">Cải thiện</span><span>Terminal công ty hiện checklist và việc từng subagent đang làm ngay trên ô nhập.</span></li>
133
+ <li data-kind="fixed"><span class="kind kind-fixed">Sửa lỗi</span><span>piagent studio cài fd ở lần mở đầu tiên nên gợi ý @ hiện file và thư mục; trước đây fd không bao giờ được tải, kể cả khi đã có ở /opt/homebrew/bin.</span></li>
134
+ </ul>
135
+ <p class="release-requires"><strong>Cần:</strong> Agent Studio 0.50.0 và Agent Watch 0.15.17 (Windows 0.1.18) để subagent chạy song song</p>
136
+ </div>
137
+ </article>
138
+ <article class="release" id="v1-46-0" data-release>
112
139
  <div class="release-meta"><a class="release-version" href="#v1-46-0">v1.46.0</a><time class="release-date" datetime="2026-10-28">28/10/2026</time></div>
113
140
  <div class="release-body">
114
141
  <h3 data-toc-skip id="v1-46-0-title">Piagent chạy trong Pi home riêng, pi của bạn giữ nguyên bản gốc</h3>
@@ -398,35 +425,33 @@
398
425
  <p class="release-requires"><strong>Cần:</strong> Agent Studio 0.39.0</p>
399
426
  </div>
400
427
  </article>
401
- <article class="release" id="v1-38-2" data-release>
402
- <div class="release-meta"><a class="release-version" href="#v1-38-2">v1.38.2</a><time class="release-date" datetime="2026-10-23">23/10/2026</time></div>
403
- <div class="release-body">
404
- <h3 data-toc-skip id="v1-38-2-title">Cây thư mục, theme màu và editor luôn trong tầm nhìn</h3>
405
- <p>Khung Tệp thành cây thư mục, có 13 theme màu, và editor cùng terminal đứng yên khi cuộc trò chuyện cuộn.</p>
406
- <ul class="release-items">
407
- <li data-kind="new"><span class="kind kind-new">Mới</span><span>Theme màu trong Cài đặt → Giao diện hoặc bảng lệnh (⌘K) đổi màu cả giao diện, cú pháp trong editor và terminal.</span></li>
408
- <li data-kind="improved"><span class="kind kind-improved">Cải thiện</span><span>Trên màn hình rộng, editor và terminal đứng yên dưới header khi cuộc trò chuyện cuộn; kéo thanh chia để đổi độ rộng editor.</span></li>
409
- <li data-kind="improved"><span class="kind kind-improved">Cải thiện</span><span>Khung Tệp là cây thư mục: thư mục mở ngay tại chỗ, file đang mở được tô sáng, và Tệp mới bắt đầu ở thư mục vừa chọn.</span></li>
410
- <li data-kind="improved"><span class="kind kind-improved">Cải thiện</span><span>Nút Tệp/Terminal luôn hiện ở mọi độ rộng; trên điện thoại cây thư mục hẹp hơn và các nút của editor nằm trên một dòng.</span></li>
411
- </ul>
412
- </div>
413
- </article>
414
- <article class="release" id="v1-38-1" data-release>
415
- <div class="release-meta"><a class="release-version" href="#v1-38-1">v1.38.1</a><time class="release-date" datetime="2026-10-23">23/10/2026</time></div>
416
- <div class="release-body">
417
- <h3 data-toc-skip id="v1-38-1-title">Bản phát hành chính thức của v1.38.0</h3>
418
- <p>v1.38.0 không qua release check vì hai test nên chưa từng được phát hành; v1.38.1 là cùng bản đó với hai test đã được sửa.</p>
419
- <ul class="release-items">
420
- <li data-kind="improved"><span class="kind kind-improved">Cải thiện</span><span>Hai test phát hành nay pass trên Linux và máy chạy chậm, nên editor, terminal, review, checkpoint và Bypass của v1.38.0 có trong bản này.</span></li>
421
- </ul>
422
- </div>
423
- </article>
424
428
  </section>
425
429
  <section class="section archive">
426
430
  <h2 id="archive">Các bản trước</h2>
427
431
  <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
432
  <details class="release-archive">
429
- <summary><span>Tháng 10/2026</span><span class="archive-count">57</span></summary>
433
+ <summary><span>Tháng 10/2026</span><span class="archive-count">59</span></summary>
434
+ <div class="archive-row" id="v1-38-2">
435
+ <div class="archive-head"><a class="release-version" href="#v1-38-2">v1.38.2</a> <span class="release-date">23/10/2026</span></div>
436
+ <div class="archive-body">
437
+ <p><strong>Cây thư mục, theme màu và editor luôn trong tầm nhìn</strong> — Khung Tệp thành cây thư mục, có 13 theme màu, và editor cùng terminal đứng yên khi cuộc trò chuyện cuộn.</p>
438
+ <ul class="release-items">
439
+ <li data-kind="new"><span class="kind kind-new">Mới</span><span>Theme màu trong Cài đặt → Giao diện hoặc bảng lệnh (⌘K) đổi màu cả giao diện, cú pháp trong editor và terminal.</span></li>
440
+ <li data-kind="improved"><span class="kind kind-improved">Cải thiện</span><span>Trên màn hình rộng, editor và terminal đứng yên dưới header khi cuộc trò chuyện cuộn; kéo thanh chia để đổi độ rộng editor.</span></li>
441
+ <li data-kind="improved"><span class="kind kind-improved">Cải thiện</span><span>Khung Tệp là cây thư mục: thư mục mở ngay tại chỗ, file đang mở được tô sáng, và Tệp mới bắt đầu ở thư mục vừa chọn.</span></li>
442
+ <li data-kind="improved"><span class="kind kind-improved">Cải thiện</span><span>Nút Tệp/Terminal luôn hiện ở mọi độ rộng; trên điện thoại cây thư mục hẹp hơn và các nút của editor nằm trên một dòng.</span></li>
443
+ </ul>
444
+ </div>
445
+ </div>
446
+ <div class="archive-row" id="v1-38-1">
447
+ <div class="archive-head"><a class="release-version" href="#v1-38-1">v1.38.1</a> <span class="release-date">23/10/2026</span></div>
448
+ <div class="archive-body">
449
+ <p><strong>Bản phát hành chính thức của v1.38.0</strong> — v1.38.0 không qua release check vì hai test nên chưa từng được phát hành; v1.38.1 là cùng bản đó với hai test đã được sửa.</p>
450
+ <ul class="release-items">
451
+ <li data-kind="improved"><span class="kind kind-improved">Cải thiện</span><span>Hai test phát hành nay pass trên Linux và máy chạy chậm, nên editor, terminal, review, checkpoint và Bypass của v1.38.0 có trong bản này.</span></li>
452
+ </ul>
453
+ </div>
454
+ </div>
430
455
  <div class="archive-row" id="v1-38-0">
431
456
  <div class="archive-head"><a class="release-version" href="#v1-38-0">v1.38.0</a> <span class="release-date">23/10/2026</span></div>
432
457
  <div class="archive-body">
@@ -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.46.0" title="v1.46.0 docs · VI"><span class="dot"></span>v1.46.0</a>
40
+ <a class="version-badge" href="/whats-new" data-docs-version="v1.46.2" title="v1.46.2 docs · VI"><span class="dot"></span>v1.46.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>
@@ -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.46.0" title="v1.46.0 docs · VI"><span class="dot"></span>v1.46.0</a>
40
+ <a class="version-badge" href="/whats-new" data-docs-version="v1.46.2" title="v1.46.2 docs · VI"><span class="dot"></span>v1.46.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": 635,
260
- "sha256": "e192ed7528a5d5a992cd33c3837ee6f779b404e45cedc06f79978e2bfa9272eb"
259
+ "fileCount": 636,
260
+ "sha256": "2684ca3bdb704a5c2ea6764048dbed440ec0a8000fdbe7b1309cd42c099a8af6"
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.46.0",
3
+ "version": "1.46.2",
4
4
  "license": "MIT",
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -3756,7 +3756,10 @@ export default function piagentGuard(pi: ExtensionAPI) {
3756
3756
  appendTrace,
3757
3757
  flushObservedTaskContext: noTask,
3758
3758
  onTurnEnd: activityInspector.refresh,
3759
- onAgentSettled: async ctx => { await personalCheckpoints.finish(ctx); await activityInspector.refresh(ctx); },
3759
+ onAgentSettled: ctx => personalCheckpoints.finish(ctx),
3760
+ // The panel hashes the working tree: seconds in a folder of repositories,
3761
+ // during which a message sent next stayed off the screen.
3762
+ afterAgentSettled: activityInspector.refresh,
3760
3763
  beforeShutdown: async (ctx) => {
3761
3764
  try { await personalCheckpoints.close(ctx); }
3762
3765
  finally {
@@ -0,0 +1,61 @@
1
+ import { memberMessages, memberRequest } from './objections.mjs';
2
+
3
+ // Several helpers of one role, at the member's request only ("use 3
4
+ // reviewers", "cho 3 scout"): one delegate call runs 2 to MAX_COPIES helper
5
+ // sessions of the role side by side, each with its own context, and their
6
+ // answers merge into one. The main agent never adds helpers on its own, and
7
+ // the harness never does: the call quotes the member's words that ask for
8
+ // them, and those words must be the member's own and name the number. The
9
+ // copies share the role's grant, so Studio counts the role once while each
10
+ // copy counts against the role's calls for the message.
11
+ export const MAX_COPIES = 3;
12
+ const COUNTS = { two: 2, three: 3, hai: 2, ba: 3 };
13
+ // Words that say the number is of helpers, not of files or steps.
14
+ const HELPER_WORDS = /agent|helper|review|scout|research|verif|nghiên cứu|kiểm|xác minh|trinh sát/;
15
+ const normal = text => String(text ?? '').toLowerCase().normalize('NFC').replace(/\s+/g, ' ').trim();
16
+ // The largest helper count the words name (a digit, or two/three in English or Vietnamese).
17
+ export function namedCount(words) {
18
+ const found = [...normal(words).matchAll(/(?<![\p{L}\d])(\d+|two|three|hai|ba)(?![\p{L}\d])/gu)].map(m => COUNTS[m[1]] ?? Number(m[1]));
19
+ return found.length ? Math.max(...found) : 0;
20
+ }
21
+ // The copies a delegate call asks for, checked against the member's words;
22
+ // null for a plain call. `split`: one line per copy naming its share of the work.
23
+ export function fanOut(manager, role, args, harness) {
24
+ const split = Array.isArray(args?.split) ? args.split.map(s => typeof s === 'string' ? s.trim().slice(0, 500) : '').filter(Boolean) : [];
25
+ const n = split.length || (Number.isInteger(args?.copies) ? args.copies : 1);
26
+ if (n <= 1 && !args?.member_words) return null;
27
+ if (harness) throw Error('managed-copies-invalid: the harness runs one helper per call.');
28
+ if (n < 2 || n > MAX_COPIES) throw Error(`managed-copies-invalid: ask for 2 to ${MAX_COPIES} ${role} helpers (copies, or one split line per helper).`);
29
+ const words = normal(args?.member_words);
30
+ if (words.length < 3 || !memberRequest(memberMessages(manager)).some(text => normal(text).includes(words)) || namedCount(words) < n || !HELPER_WORDS.test(words))
31
+ throw Error(`managed-copies-not-asked: more than one ${role} helper runs only when the member asks for it. Quote in member_words the member's own words that ask for ${n} (verbatim, with the number); otherwise use one helper.`);
32
+ return { n, split: split.length ? split : null };
33
+ }
34
+ // What one copy reads under its brief.
35
+ export function copyNote(role, i, fan) {
36
+ 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.'}`;
37
+ }
38
+
39
+ const jsonOf = reply => {
40
+ for (const raw of [...String(reply).matchAll(/```json\s*([\s\S]*?)```/g)].map(m => m[1]).reverse()) { try { const v = JSON.parse(raw); if (v && typeof v === 'object') return v; } catch { /* next */ } }
41
+ return null;
42
+ };
43
+ 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; }); };
44
+ const SEVERITY = { blocking: 0, major: 1, minor: 2 };
45
+ // One answer from the copies: each helper's prose (its JSON left out), then
46
+ // one JSON block joining their findings, verdicts and objections, so the
47
+ // review, verify and objection readers see every copy. `parsed`: every copy
48
+ // gave its JSON. A finding or a failed claim any copy reports stands.
49
+ export function mergeCopies(role, label, answers, { findingsOf, issuesOf, verdictsOf }) {
50
+ const n = answers.length, room = Math.floor(12000 / n);
51
+ 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;
52
+ const verdicts = role === 'verify' ? unique(answers.flatMap(a => verdictsOf(a.reply) ?? []), v => `${v.status}|${v.claim}`) : null;
53
+ const issues = unique(answers.flatMap(a => issuesOf(a.reply) ?? []), i => `${i.kind}|${i.detail}`).slice(0, 5);
54
+ const parsed = answers.every(a => jsonOf(a.reply));
55
+ const summaries = answers.map(a => jsonOf(a.reply)?.summary).filter(s => typeof s === 'string').map(s => s.slice(0, 200));
56
+ const json = { ...(findings ? { findings: findings.slice(0, 40) } : {}), ...(verdicts ? { verdicts: verdicts.slice(0, 40) } : {}), brief_issues: issues,
57
+ summary: `${n} ${role} helpers${summaries.length ? ': ' + summaries.join(' | ') : ''}`.slice(0, 900) };
58
+ 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');
59
+ return { reply: `${body}\n\n\`\`\`json\n${JSON.stringify(json)}\n\`\`\``, usage: answers.reduce((total, a) => total + a.usage, 0),
60
+ ...(findings ? { findings, parsed, blocking: findings.filter(f => f.severity === 'blocking').length } : {}) };
61
+ }
@@ -7,7 +7,7 @@ export function shareGrant(owner, role) {
7
7
  owner.sharedGrants ??= new Map();
8
8
  const shared = owner.sharedGrants.get(role);
9
9
  if (shared && Date.now() - shared.at < 60_000) { shared.users++; return shared; }
10
- const entry = { at: Date.now(), users: 1, grant: owner.broker.request('renew', { role }) };
10
+ const entry = { at: Date.now(), users: 1, grant: owner.broker.request('renew', slotArgs(role)) };
11
11
  entry.grant.catch(() => { if (owner.sharedGrants.get(role) === entry) owner.sharedGrants.delete(role); });
12
12
  owner.sharedGrants.set(role, entry);
13
13
  return entry;
@@ -16,3 +16,11 @@ export function shareGrant(owner, role) {
16
16
  export function releaseGrant(owner, role, entry) {
17
17
  if (--entry.users <= 0 && owner.sharedGrants?.get(role) === entry) owner.sharedGrants.delete(role);
18
18
  }
19
+
20
+ // A helper the member asked for beside another of its role holds a grant of
21
+ // its own: its key is role#slot (slot 2 or 3), the broker's {role, slot}.
22
+ export const baseRole = key => String(key).split('#')[0];
23
+ export function slotArgs(key) {
24
+ const [role, slot] = String(key).split('#');
25
+ return slot ? { role, slot: Number(slot) } : { role };
26
+ }
@@ -44,7 +44,9 @@ export function helperPrompt(roles) {
44
44
  : `Use the research helper (delegate role "research") for anything on the web (current information, news, documentation) and ${WIDE_READING}; work from its findings and do small code lookups yourself.`);
45
45
  if (roles.includes('verify')) lines.push('Before you report a non-trivial result as done, you may have the verify helper (delegate role "verify") confirm it independently: it runs the repository checks on the current code and checks claims against the code and primary sources, answering pass, fail or unverifiable with evidence.');
46
46
  // Helpers read the member's request beside the brief and may object to it.
47
- if (lines.length) lines.push('A helper sees the member\'s request next to your brief and may object to the brief with evidence (brief_issues). You decide, but answer every objection: send a corrected brief, change your approach, or tell the member why it does not hold. A helper that objects twice for one message goes to the member.');
47
+ if (lines.length) lines.push('A helper sees the member\'s request next to your brief and may object to the brief with evidence (brief_issues); each objection gets an id. You decide, but check each one at the place its evidence names and record your decision with resolve_objection: accepted with what you changed (a corrected brief, the plan, the code), or rejected with what you checked and why. An objection that the brief rests on a wrong premise or conflicts with the request refuses file changes until you decide it; a rejected one goes back to the helper, and a disagreement that remains goes to the member, as does a second objection from the same helper for one message.');
48
+ // More than one helper of a role, only at the member's word (copies.mjs).
49
+ if (lines.length) lines.push('One helper per role works on a brief. Only when the member asks for several of one role ("use 3 subagents", "dùng 2 helper"), run up to 3 in one delegate call: copies for independent answers on the same brief, or split for shares of the work, with member_words quoting the member\'s request. Never add helpers on your own.');
48
50
  return lines.length ? ' ' + lines.join(' ') : '';
49
51
  }
50
52
  const HELPER_USES = {
@@ -52,10 +54,10 @@ const HELPER_USES = {
52
54
  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.'
53
55
  : '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.',
54
56
  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.',
55
- 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.',
57
+ 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. Ask once, when your change is finished, and again only after fixing blocking findings; under a required review the harness reviews the final patch and refuses your own call.',
56
58
  };
57
59
  export function delegateDescription(roles) {
58
- 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.`;
60
+ 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 scout question on what the first answer opened.`;
59
61
  }
60
62
  // Scout and research end with their objections to the brief, if any.
61
63
  const OBJECTIONS = `${BRIEF_CHECK} End your answer with one JSON object in a \`\`\`json block: {${BRIEF_ISSUES_JSON}}, with an empty list when the brief is sound. You cannot change files or delegate.`;