@piagent/platform 1.30.1 → 1.31.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 +17 -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 +6 -0
- package/docs-site/content/index.html +4 -4
- package/docs-site/content/whats-new.html +6 -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 +7 -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 +7 -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/memory-lessons.mjs +23 -9
- package/packages/piagent-core/managed/memory-repos.mjs +104 -0
- package/packages/piagent-core/managed/memory-tools.mjs +35 -0
- package/packages/piagent-core/managed/memory.mjs +207 -105
- package/packages/piagent-core/package.json +1 -1
- package/scripts/company-terminal.mjs +2 -2
package/docs-site/en/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.31.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.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.31.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,12 @@
|
|
|
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.31.0 · 2026-10-19</p>
|
|
109
|
+
<h2 id="v1-31-0">Team memory follows the work</h2>
|
|
110
|
+
<p class="section-lead">With Agent Studio 0.30.0: the brief starts with the team's rules; memories of the current branch and folders come first; an agent's “fixed” is a claim until a check passes (verified). New tool <span class="inline-code">memory_ask</span> answers a question from team memory with its sources. Folders with several repositories, repositories without an <span class="inline-code">origin</span> remote and git's “dubious ownership” on WSL no longer turn memory off silently.</p>
|
|
111
|
+
</section>
|
|
112
|
+
|
|
107
113
|
<section class="section">
|
|
108
114
|
<p class="section-kicker">v1.30.1 · 2026-10-18</p>
|
|
109
115
|
<h2 id="v1-30-1">No model names in the company Terminal; the home folder gives the real reason</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.31.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.31.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.31.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.31.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.31.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.31.0</span>
|
|
188
188
|
<h3>Có gì mới</h3>
|
|
189
|
-
<p>Terminal công ty không còn hiện tên model, mở <code>piagent studio</code> ở thư mục home báo rõ cần vào thư mục dự án; ở 1.30.0: context lớn đi qua mạng chậm, Terminal công ty gọn như dashboard; ở 1.29.0: Terminal công ty có giao diện riêng, dừng lượt không còn làm hỏng cuộc trò chuyện; ở 1.28.3: Agent Watch tự cập nhật không còn làm gián đoạn Terminal công ty; ở 1.28.2: không còn lỗi “binding changed” ngay sau khi cập nhật; ở 1.28.1: Terminal công ty và Pi cá nhân không còn giẫm chân nhau (không nạp Piagent hai lần, dọn cấu hình công ty cũ, cuộc trò chuyện công ty chỉ mở bằng piagent studio); ở 1.28.0: team memory v2; ở 1.27.1: team memory chạy ổn cả khi agent đang gọi model; ở 1.27.0: team memory, agent công ty nhớ quyết định và quy tắc của team trong từng repo; ở 1.26.1: đổi tên cuộc trò chuyện được cả khi lượt đang chạy; ở 1.26.0: lệnh / và phím tắt của Terminal ngay trên dashboard, /undo hoàn tác lượt trước của agent, dev server chạy qua nhiều lượt; ở 1.25.0: thiếu môi trường thì agent xin quyền và chạy được sau khi bạn duyệt (run_on_host ngoài sandbox, start_docker mở Docker ngay trong cuộc trò chuyện); ở 1.24.0: chọn Fast ngay trên trang tạo cuộc trò chuyện công ty, nút Fast đổi màu vàng khi đang bật; ở 1.23.1: câu hỏi của agent luôn nằm cuối cuộc trò chuyện, ngay trên ô nhập, và dễ đọc hơn; ở 1.23.0: nút Fast cho cuộc trò chuyện công ty khi Harness cho phép, tool lỗi được báo về Studio (Logs → Tool lỗi), cuộc trò chuyện mới gửi được tin nhắn đầu sau khi Harness đổi; ở 1.22.1: dashboard không còn quay mãi khi project nằm trên ổ Windows nhìn từ WSL (/mnt/d…) hoặc phiên công ty không trả lời; ở 1.22.0: đính kèm được mọi file code và văn bản (.html, .css, .ts, .py, Dockerfile…); ở 1.21.1: bật Bypass được cả khi lượt đang chạy và được giữ sau khi tải lại; ở 1.21.0: câu hỏi và yêu cầu duyệt hiện từng cái một (main agent trước), thông báo góc phải khi cuộc trò chuyện khác xong hay đang chờ bạn, Studio ghi lại mỗi lần compact; ở 1.20.0: 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>
|
|
189
|
+
<p>Memory của team đi theo branch và luật của team, có <code>memory_ask</code>; ở 1.30.1: Terminal công ty không còn hiện tên model, mở <code>piagent studio</code> ở thư mục home báo rõ cần vào thư mục dự án; ở 1.30.0: context lớn đi qua mạng chậm, Terminal công ty gọn như dashboard; ở 1.29.0: Terminal công ty có giao diện riêng, dừng lượt không còn làm hỏng cuộc trò chuyện; ở 1.28.3: Agent Watch tự cập nhật không còn làm gián đoạn Terminal công ty; ở 1.28.2: không còn lỗi “binding changed” ngay sau khi cập nhật; ở 1.28.1: Terminal công ty và Pi cá nhân không còn giẫm chân nhau (không nạp Piagent hai lần, dọn cấu hình công ty cũ, cuộc trò chuyện công ty chỉ mở bằng piagent studio); ở 1.28.0: team memory v2; ở 1.27.1: team memory chạy ổn cả khi agent đang gọi model; ở 1.27.0: team memory, agent công ty nhớ quyết định và quy tắc của team trong từng repo; ở 1.26.1: đổi tên cuộc trò chuyện được cả khi lượt đang chạy; ở 1.26.0: lệnh / và phím tắt của Terminal ngay trên dashboard, /undo hoàn tác lượt trước của agent, dev server chạy qua nhiều lượt; ở 1.25.0: thiếu môi trường thì agent xin quyền và chạy được sau khi bạn duyệt (run_on_host ngoài sandbox, start_docker mở Docker ngay trong cuộc trò chuyện); ở 1.24.0: chọn Fast ngay trên trang tạo cuộc trò chuyện công ty, nút Fast đổi màu vàng khi đang bật; ở 1.23.1: câu hỏi của agent luôn nằm cuối cuộc trò chuyện, ngay trên ô nhập, và dễ đọc hơn; ở 1.23.0: nút Fast cho cuộc trò chuyện công ty khi Harness cho phép, tool lỗi được báo về Studio (Logs → Tool lỗi), cuộc trò chuyện mới gửi được tin nhắn đầu sau khi Harness đổi; ở 1.22.1: dashboard không còn quay mãi khi project nằm trên ổ Windows nhìn từ WSL (/mnt/d…) hoặc phiên công ty không trả lời; ở 1.22.0: đính kèm được mọi file code và văn bản (.html, .css, .ts, .py, Dockerfile…); ở 1.21.1: bật Bypass được cả khi lượt đang chạy và được giữ sau khi tải lại; ở 1.21.0: câu hỏi và yêu cầu duyệt hiện từng cái một (main agent trước), thông báo góc phải khi cuộc trò chuyện khác xong hay đang chờ bạn, Studio ghi lại mỗi lần compact; ở 1.20.0: 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.31.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.31.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.31.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.31.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.31.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.31.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.31.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.31.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.31.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.31.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.31.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.31.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,12 @@
|
|
|
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.31.0 · 2026-10-19</p>
|
|
109
|
+
<h2 id="v1-31-0">Memory của team đi theo việc đang làm</h2>
|
|
110
|
+
<p class="section-lead">Cùng Agent Studio 0.30.0: brief mở đầu bằng luật của team; memory của branch và thư mục đang làm được ưu tiên; điều agent nói “đã fix” là claim cho tới khi check pass (verified). Tool mới <span class="inline-code">memory_ask</span> trả lời câu hỏi từ memory của team, kèm nguồn. Thư mục chứa nhiều repo, repo không có remote <span class="inline-code">origin</span> và lỗi “dubious ownership” trên WSL không còn làm memory tắt im lặng.</p>
|
|
111
|
+
</section>
|
|
112
|
+
|
|
107
113
|
<section class="section">
|
|
108
114
|
<p class="section-kicker">v1.30.1 · 2026-10-18</p>
|
|
109
115
|
<h2 id="v1-30-1">Terminal công ty không còn hiện tên model; mở ở thư mục home báo đúng lý do</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.31.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.31.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": 556,
|
|
260
|
+
"sha256": "16ca67a843b41a197d49617e8c704d1240e127912c67190df2c18f24456c4d60"
|
|
261
261
|
}
|
|
262
262
|
],
|
|
263
263
|
"custodianComparisonRules": {
|
package/package.json
CHANGED
|
@@ -10,15 +10,26 @@ const COMMAND_TOOLS = new Set(['bash','run_with_network','run_with_docker','run_
|
|
|
10
10
|
const textOf = result => (result?.content ?? []).filter(p => p?.type === 'text').map(p => p.text ?? '').join('\n');
|
|
11
11
|
const clean = (value, max) => redactedText(String(value ?? '')).replace(/\bas_(?:live|run)_[A-Za-z0-9_-]{8,}/g,'[REDACTED_SECRET]').split(os.homedir()).join('~').replace(/\s+/g,' ').trim().slice(0,max);
|
|
12
12
|
const hash = s => createHash('sha256').update(s).digest('hex').slice(0,20);
|
|
13
|
+
// A check's output may be merged (2>&1) and cut to its tail (| tail -n 80):
|
|
14
|
+
// agents do that to keep long test logs short. The pipeline's exit status is
|
|
15
|
+
// then tail's, so such a check is judged by its output alone.
|
|
16
|
+
const OUTPUT_TAIL = /\s*(?:2>&1\s*)?(?:\|\s*(?:tail(?:\s+(?:-n\s*\d+|-\d+|--lines=\d+))?|cat))?\s*$/;
|
|
13
17
|
function check(command, declared) {
|
|
14
18
|
const raw=String(command ?? '').trim();
|
|
15
|
-
// Simple check commands only. Permit one explicit working-directory prefix
|
|
16
|
-
// no pipelines, redirected results,
|
|
17
|
-
|
|
19
|
+
// Simple check commands only. Permit one explicit working-directory prefix
|
|
20
|
+
// and a merged, tail-cut output; no other pipelines, redirected results,
|
|
21
|
+
// fallback exits or shell substitution.
|
|
22
|
+
let body=raw.replace(/^cd\s+(?:"[\w ./-]+"|'[\w ./-]+'|[\w./-]+)\s*&&\s*/, '');
|
|
23
|
+
const prefix=raw.slice(0,raw.length-body.length), tail=OUTPUT_TAIL.exec(body), piped=!!tail?.[0].includes('|');
|
|
24
|
+
if (tail?.[0]) body=body.slice(0,tail.index);
|
|
18
25
|
if (/[\n\r;|&<>`$]/.test(body) || /(?:skip|only|grep|testNamePattern|testPathPattern|--filter|--list|dry.run|--passWithNoTests|--watch|--collect-only|--exclude|-Dtest=)/i.test(body)) return null;
|
|
19
26
|
if (!isCheckCommand(body,declared) && !/^(?:\.\/)?mvnw?\s+(?:[^;&]*\s)?(?:test|verify)\b/.test(body)) return null;
|
|
20
|
-
|
|
27
|
+
// The same check with and without a tail is one check (a rerun, not a new command).
|
|
28
|
+
const scope=prefix+body;
|
|
29
|
+
return { command: clean(raw,220), key: hash(scope), family: hash(scope.replace(/(?:^|\s)-P[\w,.-]+/g,'')), piped };
|
|
21
30
|
}
|
|
31
|
+
// Failure markers in a piped check's output (its exit status is tail's).
|
|
32
|
+
const failedOutput = output => /\b(?:FAIL(?:ED|URES?)?|ERRORS?|BUILD FAILURE|Tests? failed|[1-9]\d*\s+(?:failed|failing|failures?|errors?))\b|npm ERR!/.test(output.replace(/\b(?:fail(?:ed|ures?)?|errors?|skipped)\s*[:=]?\s*0\b|\b0\s+(?:failed|failures?|errors?|skipped)\b/gi,''));
|
|
22
33
|
function total(output) { const m=/(?:Tests run:\s*|\btests\s+)(\d+)/i.exec(output);return m?Number(m[1]):null; }
|
|
23
34
|
function passed(output) {
|
|
24
35
|
const withoutZeros=output.replace(/\b(?:fail(?:ed|ures?)?|errors?|skipped)\s*[:=]?\s*0\b|\b0\s+(?:failed|failures?|errors?|skipped)\b/gi,'');
|
|
@@ -28,7 +39,9 @@ function passed(output) {
|
|
|
28
39
|
}
|
|
29
40
|
|
|
30
41
|
export class CheckLessons {
|
|
31
|
-
constructor(declared = [], now = Date.now) { this.declared=declared;this.now=now;this.calls=new Map();this.failures=new Map();this.edits=[];this.lessons=[];this.failed=0;this.passed=0; }
|
|
42
|
+
constructor(declared = [], now = Date.now) { this.declared=declared;this.now=now;this.calls=new Map();this.failures=new Map();this.edits=[];this.lessons=[];this.failed=0;this.passed=0;this.last='none'; }
|
|
43
|
+
// How the round's checks ended, for memory: passed, failed or none.
|
|
44
|
+
get summary() { return { passed:this.passed, failed:this.failed, final:this.last }; }
|
|
32
45
|
event(event) {
|
|
33
46
|
if(event?.type==='tool_execution_start') {
|
|
34
47
|
if(this.calls.size>=32)this.calls.delete(this.calls.keys().next().value);
|
|
@@ -39,21 +52,22 @@ export class CheckLessons {
|
|
|
39
52
|
if(['write','edit'].includes(call.tool)&&!event.isError){this.edits.push(call.path);if(this.edits.length>100)this.edits.shift();return;}
|
|
40
53
|
if(!call.check)return;
|
|
41
54
|
const output=textOf(event.result), c=call.check;
|
|
42
|
-
|
|
55
|
+
const exitFailed=event.isError || (event.result?.details?.exitCode !== undefined && event.result.details.exitCode!==0);
|
|
56
|
+
if(exitFailed || (c.piped && failedOutput(output))) {
|
|
43
57
|
if(/managed[-_](?:tool[-_]cancelled|operation[-_]denied|helper[-_]cancelled)|Command aborted|Command timed out/i.test(output))return;
|
|
44
|
-
this.failed++;
|
|
58
|
+
this.failed++;this.last='failed';
|
|
45
59
|
const diagnostic=output.split('\n').find(l=>/error|fail|exception|not found|EADDRINUSE/i.test(l)) ?? 'Check exited unsuccessfully';
|
|
46
60
|
if(this.failures.size>=20)this.failures.delete(this.failures.keys().next().value);
|
|
47
61
|
this.failures.set(c.key,{...c,tool:call.tool,id:event.toolCallId,error:clean(diagnostic,180),edits:this.edits.length,total:total(output)});return;
|
|
48
62
|
}
|
|
49
63
|
if(!passed(output))return;
|
|
50
|
-
this.passed++;
|
|
64
|
+
this.passed++;this.last='passed';
|
|
51
65
|
let prior=this.failures.get(c.key);
|
|
52
66
|
// A Maven profile change may alter coverage: accept it only when both
|
|
53
67
|
// executions explicitly report the same positive test count.
|
|
54
68
|
if(!prior)prior=[...this.failures.values()].find(f=>f.family===c.family&&f.total>0&&f.total===total(output));
|
|
55
69
|
if(!prior || this.lessons.length>=3 || (prior.total>0 && total(output)!==null && total(output)<prior.total))return;
|
|
56
|
-
const files=this.edits.slice(prior.edits), changedRunner=prior.tool!==call.tool, changedCommand=prior.
|
|
70
|
+
const files=this.edits.slice(prior.edits), changedRunner=prior.tool!==call.tool, changedCommand=prior.key!==c.key;
|
|
57
71
|
if(!files.length&&!changedRunner&&!changedCommand)return;
|
|
58
72
|
const fixed=files.length?`edited ${[...new Set(files)].slice(0,3).join(', ')}`:changedRunner?`changed runner from ${prior.tool} to ${call.tool}`:'changed the command profile (same reported test count)';
|
|
59
73
|
const line=clean(`Observed check recovery: ${prior.command} failed (${prior.error}); after ${fixed}, ${c.command} passed via ${call.tool}. Root cause not established; verify against current code.`,900);
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// Which repositories team memory uses in a conversation's folder and what
|
|
2
|
+
// git says about them: the folder's own repository or the ones one level down,
|
|
3
|
+
// remotes other than origin, checkouts git calls of "dubious ownership", and
|
|
4
|
+
// the files each commit touched. Memory only reads git.
|
|
5
|
+
import fs from 'node:fs';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
import { createHash } from 'node:crypto';
|
|
8
|
+
import { execFile } from 'node:child_process';
|
|
9
|
+
|
|
10
|
+
// A folder that holds several repositories (front end, back end…) gets the
|
|
11
|
+
// memory of each, at most MAX_REPOS.
|
|
12
|
+
const MAX_REPOS = 6;
|
|
13
|
+
|
|
14
|
+
// The repository's identity: its origin remote without scheme, user, port
|
|
15
|
+
// or ".git", lower case ("github.com/acme/shop"). null: no memory here.
|
|
16
|
+
export function repoKey(remote) {
|
|
17
|
+
let s = String(remote ?? '').trim();
|
|
18
|
+
if (!s) return null;
|
|
19
|
+
const scp = /^[\w.-]+@([^:/]+):(.+)$/.exec(s); // git@github.com:acme/shop.git
|
|
20
|
+
if (scp) s = `${scp[1]}/${scp[2]}`;
|
|
21
|
+
else {
|
|
22
|
+
try { const u = new URL(s); if (!['http:', 'https:', 'ssh:', 'git:'].includes(u.protocol)) return null; s = `${u.hostname}${u.pathname}`; }
|
|
23
|
+
catch { return null; }
|
|
24
|
+
}
|
|
25
|
+
s = s.toLowerCase().replace(/\.git\/?$/, '').replace(/\/+$/, '').replace(/\/{2,}/g, '/');
|
|
26
|
+
return /^[a-z0-9][a-z0-9._-]*\/[a-z0-9._/-]+$/.test(s) && s.length <= 200 && !s.includes('..') ? s : null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Memory only reads (remote, branch, log, status). A repository another user
|
|
30
|
+
// owns (a Windows drive seen from WSL, a shared checkout) makes git refuse
|
|
31
|
+
// with "dubious ownership"; the read is retried trusting that one folder.
|
|
32
|
+
const gitOnce = (cwd, args, timeout, signal) => new Promise(resolve => execFile('git', ['-C', cwd, ...args], { timeout, signal, maxBuffer: 4 << 20, encoding: 'utf8' },
|
|
33
|
+
(error, stdout, stderr) => resolve(error ? { out: null, err: String(stderr ?? '') } : { out: stdout })));
|
|
34
|
+
export const git = async (cwd, args, timeout = 3_000, signal) => {
|
|
35
|
+
const first = await gitOnce(cwd, args, timeout, signal);
|
|
36
|
+
if (first.out !== null || !/dubious ownership/i.test(first.err)) return first.out;
|
|
37
|
+
return (await gitOnce(cwd, ['-c', `safe.directory=${cwd}`, ...args], timeout, signal)).out
|
|
38
|
+
?? (await gitOnce(cwd, ['-c', 'safe.directory=*', ...args], timeout, signal)).out;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// The repository at dir: its key, its top folder and the name the folder
|
|
42
|
+
// gives it. reason says why there is none: not_a_repository, no_origin
|
|
43
|
+
// (no remote at all) or unsupported_remote (a remote repoKey cannot read).
|
|
44
|
+
export async function repositoryAt(dir, name = '', signal) {
|
|
45
|
+
const top = (await git(dir, ['rev-parse', '--show-toplevel'], 3_000, signal))?.trim();
|
|
46
|
+
if (!top) return { reason: 'not_a_repository' };
|
|
47
|
+
let remote = (await git(dir, ['remote', 'get-url', 'origin'], 3_000, signal))?.trim();
|
|
48
|
+
if (!remote) {
|
|
49
|
+
// No origin: a repository with exactly one remote is known by it.
|
|
50
|
+
const remotes = (await git(dir, ['remote'], 3_000, signal))?.split('\n').map(r => r.trim()).filter(Boolean) ?? [];
|
|
51
|
+
if (remotes.length !== 1) return { reason: 'no_origin' };
|
|
52
|
+
remote = (await git(dir, ['remote', 'get-url', remotes[0]], 3_000, signal))?.trim();
|
|
53
|
+
}
|
|
54
|
+
const key = repoKey(remote);
|
|
55
|
+
return key ? { key, dir: top, name } : { reason: 'unsupported_remote' };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// The repositories memory can use in cwd: the folder's own, or else the
|
|
59
|
+
// ones one level down. folder is the reason when there is none.
|
|
60
|
+
export async function findRepositories(cwd, signal) {
|
|
61
|
+
const own = await repositoryAt(cwd, '', signal);
|
|
62
|
+
if (own.key) return { repos: [own], folder: null };
|
|
63
|
+
if (own.reason !== 'not_a_repository') return { repos: [], folder: own.reason };
|
|
64
|
+
let names = [];
|
|
65
|
+
try {
|
|
66
|
+
names = fs.readdirSync(cwd, { withFileTypes: true }).filter(e => e.isDirectory() && !e.name.startsWith('.') && e.name !== 'node_modules')
|
|
67
|
+
.map(e => e.name).filter(n => fs.existsSync(path.join(cwd, n, '.git'))).sort().slice(0, 40);
|
|
68
|
+
} catch { /* unreadable folder */ }
|
|
69
|
+
const repos = [], seen = new Set();
|
|
70
|
+
let reason = 'not_a_repository';
|
|
71
|
+
for (const name of names) {
|
|
72
|
+
if (repos.length >= MAX_REPOS) break;
|
|
73
|
+
const r = await repositoryAt(path.join(cwd, name), name, signal);
|
|
74
|
+
if (r.key && !seen.has(r.key)) { seen.add(r.key); repos.push(r); } else if (r.reason && r.reason !== 'not_a_repository') reason = r.reason;
|
|
75
|
+
}
|
|
76
|
+
return { repos, folder: repos.length ? null : reason };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Top-level folders of a set of repository-relative paths.
|
|
80
|
+
export const topDirs = (files, max = 8) => [...new Set(files.map(f => String(f).split('/')).filter(p => p.length > 1 && p[0] && !p[0].startsWith('.')).map(p => p[0]))].slice(0, max);
|
|
81
|
+
// A stable event per extra repository of one round, so a retry is a duplicate.
|
|
82
|
+
export const eventFor = (id, key, i) => {
|
|
83
|
+
if (!i) return id;
|
|
84
|
+
const h = createHash('sha256').update(`${id}\0${key}`).digest('hex');
|
|
85
|
+
return `${h.slice(0, 8)}-${h.slice(8, 12)}-4${h.slice(13, 16)}-${'89ab'[parseInt(h[16], 16) & 3]}${h.slice(17, 20)}-${h.slice(20, 32)}`;
|
|
86
|
+
};
|
|
87
|
+
// Changes a commit made that leave memories about a file stale.
|
|
88
|
+
export function commitChanges(lines) {
|
|
89
|
+
const changes = [], files = [];
|
|
90
|
+
const unbrace = s => { const m = /^(.*)\{(.*) => (.*)\}(.*)$/.exec(s); return m ? [`${m[1]}${m[2]}${m[4]}`.replace(/\/\//g, '/'), `${m[1]}${m[3]}${m[4]}`.replace(/\/\//g, '/')] : s.split(' => '); };
|
|
91
|
+
for (const line of lines) {
|
|
92
|
+
let m;
|
|
93
|
+
if ((m = /^(\d+|-)\t(\d+|-)\t(.+)$/.exec(line))) {
|
|
94
|
+
const [from, to = from] = unbrace(m[3]); files.push(to);
|
|
95
|
+
const added = Number(m[1]), deleted = Number(m[2]);
|
|
96
|
+
if (deleted >= 30 && deleted >= added * 0.7 && from === to) changes.push({ path: to, kind: 'rewritten' });
|
|
97
|
+
} else if ((m = /^ delete mode \d+ (.+)$/.exec(line))) changes.push({ path: m[1], kind: 'deleted' });
|
|
98
|
+
else if ((m = /^ rename (.+) \(\d+%\)$/.exec(line))) changes.push({ path: unbrace(m[1])[0], kind: 'renamed' });
|
|
99
|
+
else if ((m = /^ rewrite (.+) \(\d+%\)$/.exec(line))) changes.push({ path: m[1], kind: 'rewritten' });
|
|
100
|
+
}
|
|
101
|
+
const unique = new Map(changes.filter(c => c.path && c.path.length <= 300).map(c => [c.path, c]));
|
|
102
|
+
return { dirs: topDirs(files), changes: [...unique.values()].slice(0, 20) };
|
|
103
|
+
}
|
|
104
|
+
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// The agent's team memory tools (memory.mjs holds what they call): search,
|
|
2
|
+
// ask and the knowledge pages; helpers get search and ask on their own run.
|
|
3
|
+
import { shareGrant, releaseGrant } from './grant-share.mjs';
|
|
4
|
+
|
|
5
|
+
export const PAGE_NAMES = ['Component map', 'Core concepts', 'Conventions and patterns', 'Key decisions and rationale', 'Initiatives and work in progress'];
|
|
6
|
+
|
|
7
|
+
// The agent's memory tools; helpers get only the search, on their own run.
|
|
8
|
+
// A fresh token for a role, shared with that role's requests running beside it.
|
|
9
|
+
export const renewer = (owner, role, verify) => {
|
|
10
|
+
const lease = async () => {
|
|
11
|
+
const share = shareGrant(owner, role);
|
|
12
|
+
try { const grant = await share.grant; verify?.(grant); if (role === 'main') owner.grant = grant;
|
|
13
|
+
return { grant, release: () => releaseGrant(owner, role, share) };
|
|
14
|
+
} catch (error) { releaseGrant(owner, role, share); throw error; }
|
|
15
|
+
};
|
|
16
|
+
const renew = async () => { const held = await lease(); try { return held.grant; } finally { held.release(); } };
|
|
17
|
+
renew.lease = lease; renew.role = role; return renew;
|
|
18
|
+
};
|
|
19
|
+
export function memoryTools(self, { pages = true, ask = false, grant = () => self.grant, renew } = {}) {
|
|
20
|
+
const repository = { type: 'string', maxLength: 200, description: 'Only in a folder that holds several repositories: the repository\'s folder name. Leave it out to use the ones the question is about.' };
|
|
21
|
+
const tools = [{ name: 'memory_search', label: 'Team memory',
|
|
22
|
+
description: 'Search the team memory of this repository: the team rules, decisions and conventions from the team\'s earlier conversations and commits, and its knowledge pages. Use it before asking the member something the team may already have settled. Team rules always apply and override recalled notes. Notes are a record of the past: check them against the code; "claim, unverified" means an agent said it worked without a passing check, "stale" that its files changed since.',
|
|
23
|
+
parameters: { type: 'object', properties: { query: { type: 'string', minLength: 1, maxLength: 2000 }, repository }, required: ['query'], additionalProperties: false },
|
|
24
|
+
execute: async (_id, args) => ({ content: [{ type: 'text', text: await self.memory.search(grant(), args.query, renew, args.repository) }], details: {} }) }];
|
|
25
|
+
if (ask) tools.push({ name: 'memory_ask', label: 'Ask team memory',
|
|
26
|
+
description: 'Ask the team memory one question that needs a synthesized answer ("why is the eKYC order locked?", "what did we decide about refunds?"). It answers from the team\'s notes under the team rules and lists its sources; slower than memory_search (up to a minute), so use memory_search for a quick lookup. Check the answer against the code before acting on it.',
|
|
27
|
+
parameters: { type: 'object', properties: { question: { type: 'string', minLength: 1, maxLength: 2000 }, repository }, required: ['question'], additionalProperties: false },
|
|
28
|
+
execute: async (_id, args) => ({ content: [{ type: 'text', text: await self.memory.ask(grant(), args.question, renew, args.repository) }], details: {} }) });
|
|
29
|
+
if (pages) tools.push({ name: 'memory_page', label: 'Team knowledge page',
|
|
30
|
+
description: `Read one knowledge page the team memory keeps for this repository: ${PAGE_NAMES.join(', ')}.`,
|
|
31
|
+
parameters: { type: 'object', properties: { name: { type: 'string', enum: PAGE_NAMES }, repository }, required: ['name'], additionalProperties: false },
|
|
32
|
+
execute: async (_id, args) => ({ content: [{ type: 'text', text: await self.memory.page(grant(), args.name, renew, args.repository) }], details: {} }) });
|
|
33
|
+
return tools;
|
|
34
|
+
}
|
|
35
|
+
|