@piagent/platform 1.18.0 → 1.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +37 -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 +2 -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 +15 -0
- package/docs-site/content/index.html +4 -4
- package/docs-site/content/whats-new.html +15 -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 +16 -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 +16 -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/call-purpose.mjs +3 -2
- package/packages/piagent-core/managed/command-tools.mjs +56 -0
- package/packages/piagent-core/managed/container-engine.mjs +68 -0
- package/packages/piagent-core/managed/continuation.mjs +131 -0
- package/packages/piagent-core/managed/doctor.mjs +12 -0
- package/packages/piagent-core/managed/helper-roles.mjs +1 -1
- package/packages/piagent-core/managed/helper-run.mjs +24 -6
- package/packages/piagent-core/managed/language-environment.mjs +57 -0
- package/packages/piagent-core/managed/linux-sandbox.mjs +6 -1
- package/packages/piagent-core/managed/package-proxy.mjs +181 -0
- package/packages/piagent-core/managed/patch-snapshot.mjs +53 -9
- package/packages/piagent-core/managed/repository-operation.mjs +20 -0
- package/packages/piagent-core/managed/review-snapshot-worker.mjs +29 -4
- package/packages/piagent-core/managed/sandbox-diagnostic.mjs +7 -2
- package/packages/piagent-core/managed/session.mjs +60 -67
- package/packages/piagent-core/managed/tool-boundary.mjs +70 -11
- package/packages/piagent-core/managed/tool-worker.mjs +18 -3
- package/packages/piagent-core/managed/workflow.mjs +20 -20
- package/packages/piagent-core/package.json +1 -1
- package/packages/piagent-webui/dist/client/assets/{MarkdownMessage-DlbuyiQ3.js → MarkdownMessage-nggiOt0N.js} +1 -1
- package/packages/piagent-webui/dist/client/assets/{index-BGxsZHB5.js → index-CM9cs-gP.js} +16 -14
- package/packages/piagent-webui/dist/client/index.html +1 -1
- package/packages/piagent-webui/gateway/company-relay.ts +14 -2
- package/packages/piagent-webui/gateway/gateway-service.ts +20 -8
- package/packages/piagent-webui/gateway/git-repositories.ts +46 -0
- package/packages/piagent-webui/gateway/managed-projection.ts +9 -2
- package/packages/piagent-webui/gateway/project-registry.ts +10 -6
- package/packages/piagent-webui/gateway/session-catalog.ts +13 -6
- package/packages/piagent-webui/server/loopback-server.ts +1 -1
- package/packages/piagent-webui/server/member-routes.ts +6 -3
- package/packages/piagent-webui/server/tool-call-summary.ts +3 -1
- package/packages/piagent-webui/server/transcript-projection.ts +20 -4
- package/packages/piagent-webui/shared/process-copy.ts +3 -1
- package/packages/piagent-webui/shared/turn-end.ts +68 -0
- package/schemas/piagent-webui/session-catalog-v1.schema.json +11 -1
- package/schemas/piagent-webui/transcript-v1.schema.json +23 -2
- package/scripts/company-terminal.mjs +15 -0
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · EN</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Language">
|
|
35
35
|
<a class="language-option" href="/runtime" hreflang="vi" lang="vi">VI</a>
|
|
36
36
|
<a class="language-option current" href="/en/runtime" hreflang="en" lang="en" aria-current="true">EN</a>
|
package/docs-site/en/scope.html
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · EN</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Language">
|
|
35
35
|
<a class="language-option" href="/scope" hreflang="vi" lang="vi">VI</a>
|
|
36
36
|
<a class="language-option current" href="/en/scope" hreflang="en" lang="en" aria-current="true">EN</a>
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · EN</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Language">
|
|
35
35
|
<a class="language-option" href="/security" hreflang="vi" lang="vi">VI</a>
|
|
36
36
|
<a class="language-option current" href="/en/security" hreflang="en" lang="en" aria-current="true">EN</a>
|
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.20.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.20.0 docs · EN</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Language">
|
|
35
35
|
<a class="language-option" href="/whats-new" hreflang="vi" lang="vi">VI</a>
|
|
36
36
|
<a class="language-option current" href="/en/whats-new" hreflang="en" lang="en" aria-current="true">EN</a>
|
|
@@ -104,6 +104,21 @@
|
|
|
104
104
|
<h1>1.9.0: ask in plain language, the team's Harness checks</h1>
|
|
105
105
|
<p>The task contract and workflow commands are gone. Company mode asks for checks and a review on its own; Stop, network commands on approval and clearer approval cards.</p>
|
|
106
106
|
</div>
|
|
107
|
+
<section class="section">
|
|
108
|
+
<p class="section-kicker">v1.20.0 · 2026-10-09</p>
|
|
109
|
+
<h2 id="v1-20-0">Package installs in the company sandbox no longer ask</h2>
|
|
110
|
+
<p class="section-lead">Plain bash commands reach the usual registries: npm, PyPI, the Go proxy, crates.io, Maven Central, Gradle, NuGet, RubyGems, Packagist, pub.dev, CocoaPods and Hex, plus public GitHub downloads (such as the Gradle distribution <span class="inline-code">./gradlew</span> needs). So <span class="inline-code">npm install</span>, <span class="inline-code">pip install</span>, <span class="inline-code">go mod download</span>, <span class="inline-code">./mvnw test</span> and <span class="inline-code">./gradlew test</span> run without waiting for your approval. Piagent goes through a proxy that runs outside the sandbox: only those hosts, on ports 443 and 80, never an IP address, your machine or a private network. Any other host is refused, the error names it, and a command that needs it still goes through <span class="inline-code">run_with_network</span> for your approval. To add your company's registry, write its host name (or <span class="inline-code">*.domain</span>) in <span class="inline-code">~/.piagent/sandbox-domains</span>, one per line. Registry and git credentials still stay out of the sandbox, so nothing is pushed or published.</p>
|
|
111
|
+
<p class="section-lead">In Bypass, <span class="inline-code">run_with_docker</span> runs without asking, like <span class="inline-code">run_with_network</span>; only pushes, deploys, registry logins and deletes with an unknown target still ask.</p>
|
|
112
|
+
<p class="section-lead">Fixed: a subagent that works longer than 15 minutes (such as a verify running the whole test suite while the main agent waits) is no longer stopped with <span class="inline-code">managed-helper-cancelled</span>. Asked to review work committed in earlier turns, the review subagent no longer says “no patch”. It reads the commits since the commit, branch or <span class="inline-code">HEAD~N</span> the agent names; when the current turn changed nothing, it reads the branch’s commits since it left the main branch.</p>
|
|
113
|
+
</section>
|
|
114
|
+
|
|
115
|
+
<section class="section">
|
|
116
|
+
<p class="section-kicker">v1.19.0 · 2026-10-08</p>
|
|
117
|
+
<h2 id="v1-19-0">Tasks with a checklist are carried to the end, and each turn says whether it finished</h2>
|
|
118
|
+
<p class="section-lead">In a company conversation, when the main agent stops while its checklist still has open steps (say, after STEP06 of the STEP22 you asked for) and the team's Harness requires a plan, the harness sends it on to the next open step, as if you had sent “continue”. It stops when the checklist is done, when you press Stop or write, when a round fails, or after 2 rounds in a row that finish no step. Every turn ends with one line: Done, Stopped midway with x of y steps open (and why), Turn stopped by a failure, or You stopped this turn, with Continue when the task is not finished; the conversation list shows it too. Steps you leave for later are marked deferred, never completed; “continue” takes up the open checklist. A turn whose change the agent committed is still checked and reviewed.</p>
|
|
119
|
+
<p class="section-lead">Docker in the company sandbox: when Docker runs on the machine (Docker Desktop, Colima, OrbStack…), the agent has <span class="inline-code">run_with_docker</span> to run one command you approve with internet and Docker, such as a test database with <span class="inline-code">docker compose up -d</span>, <span class="inline-code">docker build</span> or Testcontainers tests. Docker gets no registry credentials; Bypass still asks when a command or compose file mounts a folder outside the project. <span class="inline-code">./gradlew</span> and <span class="inline-code">./mvnw</span> reuse the Gradle and Maven already on the machine, without asking for network. A folder that holds several repositories (front end, back end…, each its own Git) shows “N repo”: click it to see each repository, its branch and changed files, and switch branches there; a full folder list makes room instead of failing to add a folder.</p>
|
|
120
|
+
</section>
|
|
121
|
+
|
|
107
122
|
<section class="section">
|
|
108
123
|
<p class="section-kicker">v1.18.0 · 2026-10-08</p>
|
|
109
124
|
<h2 id="v1-18-0">Switch the Git branch from the dashboard, retries for passing failures, Claude Haiku 5.5</h2>
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · EN</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Language">
|
|
35
35
|
<a class="language-option" href="/windows" hreflang="vi" lang="vi">VI</a>
|
|
36
36
|
<a class="language-option current" href="/en/windows" hreflang="en" lang="en" aria-current="true">EN</a>
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · EN</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Language">
|
|
35
35
|
<a class="language-option" href="/workflows" hreflang="vi" lang="vi">VI</a>
|
|
36
36
|
<a class="language-option current" href="/en/workflows" hreflang="en" lang="en" aria-current="true">EN</a>
|
package/docs-site/index.html
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · VI</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Ngôn ngữ">
|
|
35
35
|
<a class="language-option current" href="/" hreflang="vi" lang="vi" aria-current="true">VI</a>
|
|
36
36
|
<a class="language-option" href="/en/" hreflang="en" lang="en">EN</a>
|
|
@@ -94,7 +94,7 @@
|
|
|
94
94
|
<main>
|
|
95
95
|
<div class="content-shell" data-article>
|
|
96
96
|
<section class="hero">
|
|
97
|
-
<p class="eyebrow">Piagent 1.
|
|
97
|
+
<p class="eyebrow">Piagent 1.20.0</p>
|
|
98
98
|
<h1>Coding agent cho cả team, kiểm tra từng bước.</h1>
|
|
99
99
|
<p>
|
|
100
100
|
Một dashboard cho Terminal và trình duyệt. Dùng model bằng tài khoản của bạn, hoặc model của công ty qua Agent Watch và Agent Studio. Guard kiểm tra từng tool call; ở chế độ công ty, Harness của team tự yêu cầu chạy check, cho subagent review và báo kết quả ngay dưới câu trả lời.
|
|
@@ -108,7 +108,7 @@
|
|
|
108
108
|
<div class="hero-actions">
|
|
109
109
|
<a class="button primary" href="/quickstart">Bắt đầu</a>
|
|
110
110
|
<a class="button" href="/ecosystem">Hệ sinh thái</a>
|
|
111
|
-
<a class="button" href="/whats-new">Có gì mới trong 1.
|
|
111
|
+
<a class="button" href="/whats-new">Có gì mới trong 1.20.0</a>
|
|
112
112
|
<a class="button" href="/commands">Xem command</a>
|
|
113
113
|
</div>
|
|
114
114
|
</section>
|
|
@@ -184,9 +184,9 @@ piagent-setup</code></pre>
|
|
|
184
184
|
<h2 id="bat-dau-tu-dau">Bắt đầu từ đâu</h2>
|
|
185
185
|
<div class="card-grid">
|
|
186
186
|
<a class="doc-card" href="/whats-new">
|
|
187
|
-
<span class="card-kicker">Bản 1.
|
|
187
|
+
<span class="card-kicker">Bản 1.20.0</span>
|
|
188
188
|
<h3>Có gì mới</h3>
|
|
189
|
-
<p
|
|
189
|
+
<p>Cài package trong sandbox công ty không phải duyệt (npm, PyPI, Go, Maven, Gradle… qua proxy chỉ cho registry); ở 1.19.0: task công ty có checklist được làm đến hết, cuối mỗi lượt báo rõ xong, dừng giữa chừng hay lỗi, Docker trong sandbox công ty, folder chứa nhiều repo; ở 1.18.0: đổi nhánh Git trên dashboard, tự thử lại khi lỗi tạm thời, Claude Haiku 5.5; ở 1.17.0: dashboard hiện nhánh Git của project; ở 1.16.3: dashboard cập nhật xong vẫn tự kiểm tra bản mới; ở 1.16.2: Terminal nói giống dashboard: hỏi cập nhật, /bypass, lỗi và ghi chú Harness bằng tiếng Việt; ở 1.16.1: bản mới được báo bằng dialog và kiểm tra mỗi giờ, tab dashboard không còn mất đăng nhập; ở 1.16.0: Bypass cho cuộc trò chuyện công ty, đổi Harness không làm gián đoạn; ở 1.15.2: cuộc trò chuyện dài tự thu gọn trở lại; ở 1.15.1: Studio thấy mỗi call của model dùng để làm gì, nhiều cuộc trò chuyện trong một folder không nhận nhầm thay đổi của nhau; ở 1.15.0: subagent bị từ chối nói đúng lý do; ở 1.14: cập nhật giữ model bạn đã chọn; ở 1.13: cuộc trò chuyện giữ chỗ đang đọc, chữ của agent có định dạng, Piagent trên Windows qua WSL2: sandbox công ty bằng bubblewrap và Agent Watch cho Windows; ở 1.12: @ chọn file và folder trên máy, skill và command dùng bằng /, nhánh cuộc trò chuyện công ty gửi được tin nhắn.</p>
|
|
190
190
|
</a>
|
|
191
191
|
<a class="doc-card" href="/ecosystem">
|
|
192
192
|
<span class="card-kicker">Get started</span>
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · VI</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Ngôn ngữ">
|
|
35
35
|
<a class="language-option current" href="/mcp-approval" hreflang="vi" lang="vi" aria-current="true">VI</a>
|
|
36
36
|
<a class="language-option" href="/en/mcp-approval" hreflang="en" lang="en">EN</a>
|
package/docs-site/mcp-auth.html
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · VI</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Ngôn ngữ">
|
|
35
35
|
<a class="language-option current" href="/mcp-auth" hreflang="vi" lang="vi" aria-current="true">VI</a>
|
|
36
36
|
<a class="language-option" href="/en/mcp-auth" hreflang="en" lang="en">EN</a>
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · VI</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Ngôn ngữ">
|
|
35
35
|
<a class="language-option current" href="/mcp-servers" hreflang="vi" lang="vi" aria-current="true">VI</a>
|
|
36
36
|
<a class="language-option" href="/en/mcp-servers" hreflang="en" lang="en">EN</a>
|
package/docs-site/mcp.html
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · VI</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Ngôn ngữ">
|
|
35
35
|
<a class="language-option current" href="/mcp" hreflang="vi" lang="vi" aria-current="true">VI</a>
|
|
36
36
|
<a class="language-option" href="/en/mcp" hreflang="en" lang="en">EN</a>
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · VI</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Ngôn ngữ">
|
|
35
35
|
<a class="language-option current" href="/permissions" hreflang="vi" lang="vi" aria-current="true">VI</a>
|
|
36
36
|
<a class="language-option" href="/en/permissions" hreflang="en" lang="en">EN</a>
|
package/docs-site/profiles.html
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · VI</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Ngôn ngữ">
|
|
35
35
|
<a class="language-option current" href="/profiles" hreflang="vi" lang="vi" aria-current="true">VI</a>
|
|
36
36
|
<a class="language-option" href="/en/profiles" hreflang="en" lang="en">EN</a>
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · VI</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Ngôn ngữ">
|
|
35
35
|
<a class="language-option current" href="/quickstart" hreflang="vi" lang="vi" aria-current="true">VI</a>
|
|
36
36
|
<a class="language-option" href="/en/quickstart" hreflang="en" lang="en">EN</a>
|
package/docs-site/runtime.html
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · VI</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Ngôn ngữ">
|
|
35
35
|
<a class="language-option current" href="/runtime" hreflang="vi" lang="vi" aria-current="true">VI</a>
|
|
36
36
|
<a class="language-option" href="/en/runtime" hreflang="en" lang="en">EN</a>
|
package/docs-site/scope.html
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · VI</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Ngôn ngữ">
|
|
35
35
|
<a class="language-option current" href="/scope" hreflang="vi" lang="vi" aria-current="true">VI</a>
|
|
36
36
|
<a class="language-option" href="/en/scope" hreflang="en" lang="en">EN</a>
|
package/docs-site/security.html
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · VI</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Ngôn ngữ">
|
|
35
35
|
<a class="language-option current" href="/security" hreflang="vi" lang="vi" aria-current="true">VI</a>
|
|
36
36
|
<a class="language-option" href="/en/security" hreflang="en" lang="en">EN</a>
|
package/docs-site/team.html
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · VI</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Ngôn ngữ">
|
|
35
35
|
<a class="language-option current" href="/team" hreflang="vi" lang="vi" aria-current="true">VI</a>
|
|
36
36
|
<a class="language-option" href="/en/team" hreflang="en" lang="en">EN</a>
|
package/docs-site/whats-new.html
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · VI</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Ngôn ngữ">
|
|
35
35
|
<a class="language-option current" href="/whats-new" hreflang="vi" lang="vi" aria-current="true">VI</a>
|
|
36
36
|
<a class="language-option" href="/en/whats-new" hreflang="en" lang="en">EN</a>
|
|
@@ -104,6 +104,21 @@
|
|
|
104
104
|
<h1>Bản 1.9.0: nói việc bằng lời, Harness của team kiểm tra</h1>
|
|
105
105
|
<p>Bỏ task contract và lệnh workflow. Chế độ công ty tự yêu cầu check và review; nút Dừng, lệnh có mạng theo lần duyệt và thẻ duyệt dễ đọc hơn.</p>
|
|
106
106
|
</div>
|
|
107
|
+
<section class="section">
|
|
108
|
+
<p class="section-kicker">v1.20.0 · 2026-10-09</p>
|
|
109
|
+
<h2 id="v1-20-0">Cài package trong sandbox công ty không phải duyệt nữa</h2>
|
|
110
|
+
<p class="section-lead">Lệnh bash thường tải được từ các registry quen thuộc: npm, PyPI, Go proxy, crates.io, Maven Central, Gradle, NuGet, RubyGems, Packagist, pub.dev, CocoaPods, Hex, và tải về public từ GitHub (ví dụ bản Gradle mà <span class="inline-code">./gradlew</span> cần). Nhờ vậy <span class="inline-code">npm install</span>, <span class="inline-code">pip install</span>, <span class="inline-code">go mod download</span>, <span class="inline-code">./mvnw test</span> hay <span class="inline-code">./gradlew test</span> chạy ngay, không phải chờ bạn duyệt. Piagent đi qua một proxy chạy ngoài sandbox: chỉ các host đó, cổng 443 và 80, không bao giờ tới IP trực tiếp, máy của bạn hay mạng nội bộ. Host khác bị chặn, lỗi ghi rõ host nào, và lệnh cần host đó vẫn phải qua <span class="inline-code">run_with_network</span> để bạn duyệt. Muốn thêm registry riêng của công ty, ghi tên host (hoặc <span class="inline-code">*.domain</span>) vào <span class="inline-code">~/.piagent/sandbox-domains</span>, mỗi dòng một host. Thông tin đăng nhập registry và git vẫn không vào sandbox, nên không push hay publish được.</p>
|
|
111
|
+
<p class="section-lead">Ở chế độ Bypass, <span class="inline-code">run_with_docker</span> chạy luôn không cần duyệt, giống <span class="inline-code">run_with_network</span>; chỉ push, deploy, đăng nhập registry hay lệnh xoá không rõ đích là vẫn hỏi.</p>
|
|
112
|
+
<p class="section-lead">Sửa lỗi: subagent chạy lâu hơn 15 phút (ví dụ verify chạy cả bộ test trong lúc main agent chờ) không còn bị dừng với <span class="inline-code">managed-helper-cancelled</span> nữa. Nhờ subagent review xem lại code đã commit ở các lượt trước thì nó không còn báo “không có patch”. Review đọc các commit kể từ commit, nhánh hoặc <span class="inline-code">HEAD~N</span> mà agent chỉ ra; nếu lượt hiện tại chưa sửa gì, nó đọc các commit của nhánh kể từ lúc tách khỏi nhánh chính.</p>
|
|
113
|
+
</section>
|
|
114
|
+
|
|
115
|
+
<section class="section">
|
|
116
|
+
<p class="section-kicker">v1.19.0 · 2026-10-08</p>
|
|
117
|
+
<h2 id="v1-19-0">Task có checklist được làm đến hết, và mỗi lượt báo rõ đã xong hay chưa</h2>
|
|
118
|
+
<p class="section-lead">Trong cuộc trò chuyện công ty, khi main agent tự dừng lúc checklist còn bước (ví dụ làm xong STEP06 rồi dừng, dù bạn giao đến STEP22) và Harness của team bắt buộc plan, Harness tự cho agent làm tiếp bước kế tiếp, như bạn gửi “tiếp tục”. Nó dừng khi checklist xong, khi bạn bấm Stop hoặc nhắn tin, khi gặp lỗi, hoặc sau 2 vòng liên tiếp không xong thêm bước nào. Cuối mỗi lượt có một dòng: Hoàn thành, Dừng giữa chừng còn x/y bước (kèm lý do), Lượt dừng vì lỗi, hoặc Bạn đã dừng lượt này, với nút Tiếp tục khi task chưa xong; danh sách cuộc trò chuyện cũng hiện trạng thái này. Bước bạn bảo để sau được đánh dấu “để sau”, không bao giờ bị ghi là xong; gửi “tiếp tục” là agent nhận lại checklist đang dở. Lượt mà agent đã commit vẫn được chạy check và review.</p>
|
|
119
|
+
<p class="section-lead">Sandbox công ty dùng được Docker: khi máy đang chạy Docker (Docker Desktop, Colima, OrbStack…), agent có <span class="inline-code">run_with_docker</span> để chạy một lệnh bạn duyệt với internet và Docker, ví dụ bật database cho test bằng <span class="inline-code">docker compose up -d</span>, <span class="inline-code">docker build</span> hay test Testcontainers. Docker không mang theo thông tin đăng nhập registry; Bypass vẫn hỏi khi lệnh hoặc file compose mount thư mục ngoài project. <span class="inline-code">./gradlew</span> và <span class="inline-code">./mvnw</span> dùng lại bản Gradle/Maven đã có trên máy nên không phải xin mạng. Folder chứa nhiều repo (FE, BE… mỗi folder một git) hiện “N repo”: bấm vào để xem từng repo, nhánh và số file thay đổi, rồi đổi nhánh trong repo đó; danh sách folder đầy thì tự bỏ folder đã mất hoặc lâu nhất, không còn báo “Không thể thêm thư mục”.</p>
|
|
120
|
+
</section>
|
|
121
|
+
|
|
107
122
|
<section class="section">
|
|
108
123
|
<p class="section-kicker">v1.18.0 · 2026-10-08</p>
|
|
109
124
|
<h2 id="v1-18-0">Đổi nhánh Git trên dashboard, tự thử lại khi lỗi tạm thời, Claude Haiku 5.5</h2>
|
package/docs-site/windows.html
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · VI</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Ngôn ngữ">
|
|
35
35
|
<a class="language-option current" href="/windows" hreflang="vi" lang="vi" aria-current="true">VI</a>
|
|
36
36
|
<a class="language-option" href="/en/windows" hreflang="en" lang="en">EN</a>
|
package/docs-site/workflows.html
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<span>Pi Agent Platform</span>
|
|
31
31
|
</a>
|
|
32
32
|
<div class="top-actions">
|
|
33
|
-
<span class="pill"><span class="pill-dot"></span>v1.
|
|
33
|
+
<span class="pill"><span class="pill-dot"></span>v1.20.0 docs · VI</span>
|
|
34
34
|
<nav class="language-switch" aria-label="Ngôn ngữ">
|
|
35
35
|
<a class="language-option current" href="/workflows" hreflang="vi" lang="vi" aria-current="true">VI</a>
|
|
36
36
|
<a class="language-option" href="/en/workflows" hreflang="en" lang="en">EN</a>
|
|
@@ -256,8 +256,8 @@
|
|
|
256
256
|
},
|
|
257
257
|
{
|
|
258
258
|
"path": "tests",
|
|
259
|
-
"fileCount":
|
|
260
|
-
"sha256": "
|
|
259
|
+
"fileCount": 530,
|
|
260
|
+
"sha256": "4bc37f2d6ac7e4b8a75416b7b2ea413a91c282e7ceaba0c2f4dab5d2971f46d3"
|
|
261
261
|
}
|
|
262
262
|
],
|
|
263
263
|
"custodianComparisonRules": {
|
package/package.json
CHANGED
|
@@ -25,14 +25,15 @@ export function jobTitle(task, title) {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
// The headers of one call. `owner.nextPurpose` is set by the harness when it
|
|
28
|
-
// sends the main agent back (checks, review findings
|
|
28
|
+
// sends the main agent back (checks, review findings: "harness"; a checklist
|
|
29
|
+
// with open steps: "continue").
|
|
29
30
|
export function purposeHeaders(owner, runtime, role, context) {
|
|
30
31
|
const messages = context?.messages ?? [], last = messages.at(-1);
|
|
31
32
|
let purpose, after = '';
|
|
32
33
|
if (systemText(context).startsWith(SUMMARY_PROMPT)) purpose = 'summary';
|
|
33
34
|
else if (last?.role === 'toolResult') { purpose = 'tool_step'; after = afterTools(messages.findLast(m => m.role === 'assistant')); }
|
|
34
35
|
else if (role !== 'main') purpose = 'brief';
|
|
35
|
-
else if (owner.nextPurpose
|
|
36
|
+
else if (['harness', 'continue'].includes(owner.nextPurpose)) { purpose = owner.nextPurpose; owner.nextPurpose = null; }
|
|
36
37
|
else purpose = 'answer';
|
|
37
38
|
const title = purpose === 'brief' ? owner.jobTitles?.get(runtime) : '';
|
|
38
39
|
return { 'X-Agent-Purpose': purpose, ...(after ? { 'X-Agent-After': after } : {}), ...(title ? { 'X-Agent-Task': encodeURIComponent(title) } : {}) };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { networkConfirmation } from './permission.mjs';
|
|
2
|
+
|
|
3
|
+
// Commands that leave the plain sandbox, each after the member approves that
|
|
4
|
+
// exact command: run_with_network (internet, a local server or browser) and,
|
|
5
|
+
// when this machine has a Docker engine, run_with_docker (the same plus the
|
|
6
|
+
// engine's socket). Bypass runs both without asking (owner, 2026-10-09),
|
|
7
|
+
// except what must be confirmed for any command (bypass-policy.mjs: pushes,
|
|
8
|
+
// deploys, registry logins, deletes known only at run time).
|
|
9
|
+
const PARAMETERS = { type: 'object', properties: { command: { type: 'string', minLength: 1, maxLength: 4000 }, reason: { type: 'string', minLength: 1, maxLength: 300 }, timeout: { type: 'number', minimum: 1, maximum: 1800 } }, required: ['command', 'reason'], additionalProperties: false };
|
|
10
|
+
|
|
11
|
+
const KINDS = {
|
|
12
|
+
network: {
|
|
13
|
+
name: 'run_with_network', label: 'Run with network', scope: 'network-command-once', provider: 'network', riskClass: 'medium',
|
|
14
|
+
description: 'Run one shell command that needs the internet beyond the package registries bash already reaches (a download site or registry the package proxy refuses), or that starts a local server or a browser (end-to-end tests with Playwright\'s Chromium against a server on 127.0.0.1), after the user approves that exact command. Normal bash has no network and cannot listen on a port. Credentials (.npmrc, SSH keys, Keychain) stay unavailable, so private registries and git push are not possible here.',
|
|
15
|
+
allow: 'Run this exact command once, with internet access; a server it starts accepts connections while it runs.',
|
|
16
|
+
title: 'Chạy lệnh có internet', allowText: 'chạy đúng lệnh này một lần, có internet; server nó mở nhận kết nối trong lúc chạy.',
|
|
17
|
+
confirm: (self, command) => networkConfirmation(self, command),
|
|
18
|
+
},
|
|
19
|
+
docker: {
|
|
20
|
+
name: 'run_with_docker', label: 'Run with Docker', scope: 'docker-command-once', provider: 'docker', riskClass: 'high',
|
|
21
|
+
description: 'Run one shell command that needs the Docker engine of this machine: docker, docker compose (a database or service for tests), docker build, or tests that start containers themselves (Testcontainers), after the user approves that exact command. It has internet access too. Normal bash and run_with_network cannot reach Docker. Mount only folders inside the project. Registry credentials are unavailable: public images pull, private registries and docker push do not. Containers started in the background (-d, compose up -d) keep running after the command: stop them (docker compose down) when the work is done unless the member wants them kept.',
|
|
22
|
+
allow: 'Run this exact command once, with internet access and the Docker engine; a container it starts can read folders Docker shares from this machine and may keep running.',
|
|
23
|
+
title: 'Chạy lệnh dùng Docker', allowText: 'chạy đúng lệnh này một lần, có internet và Docker; container nó tạo có thể đọc thư mục Docker được chia sẻ trên máy và có thể tiếp tục chạy.',
|
|
24
|
+
confirm: (self, command) => networkConfirmation(self, command),
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
function commandTool(self, kind) {
|
|
29
|
+
const spec = KINDS[kind];
|
|
30
|
+
return { name: spec.name, label: spec.label, description: spec.description, parameters: PARAMETERS,
|
|
31
|
+
execute: async (id, args, signal, onUpdate, ctx) => {
|
|
32
|
+
const confirm = await spec.confirm(self, args.command);
|
|
33
|
+
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,
|
|
34
|
+
action: { kind: 'external-provider-action', preconditionClass: 'runtime-only', toolName: spec.name, rawAction: { command: args.command }, commandPreview: String(args.command),
|
|
35
|
+
targetPaths: [self.cwd], provider: spec.provider, urlOrigin: null, requestedScope: spec.scope, reason: (confirm === 'ask' ? String(args.reason) : `Bypass still asks: ${confirm}. ${args.reason}`).slice(0, 300), riskClass: spec.riskClass,
|
|
36
|
+
allowConsequence: spec.allow, denyConsequence: 'The command does not run; the agent is told you declined.' },
|
|
37
|
+
terminalConfirm: () => ctx?.ui?.confirm?.(spec.title, `${args.command}\n\nLý do: ${args.reason}${confirm === 'ask' ? '' : `\nBypass vẫn hỏi: ${confirm}`}\n\nĐồng ý: ${spec.allowText}\nTừ chối: lệnh không chạy, agent được báo bạn đã từ chối.`) ?? Promise.resolve(false),
|
|
38
|
+
unavailableFallback: 'terminal-confirm', recheck: () => !signal?.aborted && Boolean(self.grant) });
|
|
39
|
+
if (!decision.allowed || !decision.consume() || signal?.aborted) throw Error('managed-operation-denied');
|
|
40
|
+
let ok = false;
|
|
41
|
+
const before = await self.changedFiles();
|
|
42
|
+
try { const result = await self.boundary.invoke('bash', { command: args.command, ...(args.timeout ? { timeout: args.timeout } : {}) }, signal, onUpdate, ctx?.model, kind === 'docker' ? { docker: true } : { network: true }); ok = !result?.isError; return result; }
|
|
43
|
+
finally { await self.claimChanges(before); await self.run?.afterTool('bash', args, ok, () => self.digest()); await self.refreshReview(); }
|
|
44
|
+
} };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function commandTools(self) {
|
|
48
|
+
return [commandTool(self, 'network'), ...(self.boundary.engine ? [commandTool(self, 'docker')] : [])];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// What the system prompt says about services: Docker when the machine has an
|
|
52
|
+
// engine (run_with_docker), else the member starts them.
|
|
53
|
+
export function servicesPrompt(boundary) {
|
|
54
|
+
if (boundary.engine) return ' Docker is available through run_with_docker (the member approves each command): a database or service for tests (docker compose up -d, then the tests through bash or run_with_network), docker build, or Testcontainers tests. Stop what you started when done unless the member wants it kept. The iOS Simulator is not available in the sandbox: ask the member to run those tests.';
|
|
55
|
+
return ' Docker is not running on this machine and the iOS Simulator is not available in the sandbox: ask the member to start those services (or Docker, after which a new conversation has run_with_docker) or run those tests.';
|
|
56
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
|
|
4
|
+
// The Docker engine a company command may use once the member approves it
|
|
5
|
+
// (run_with_docker): its socket, the CLI and its plugins (compose, buildx).
|
|
6
|
+
// The socket is the only thing opened beyond an approved network command:
|
|
7
|
+
// containers run in the engine (Docker Desktop's VM, Colima, OrbStack, the
|
|
8
|
+
// Linux daemon, Podman's compatible socket), not in this sandbox.
|
|
9
|
+
// The CLI gets a configuration folder of its own in the sandbox's home: no
|
|
10
|
+
// registry credentials (credsStore, auths), so public images are pulled and
|
|
11
|
+
// private registries are not, as with .npmrc.
|
|
12
|
+
const isSocket = file => { try { return fs.statSync(file).isSocket(); } catch { return false; } };
|
|
13
|
+
const real = file => { try { return fs.realpathSync(file); } catch { return null; } };
|
|
14
|
+
|
|
15
|
+
function socketCandidates(userHome, env, system) {
|
|
16
|
+
const host = /^unix:\/\/(\/.+)$/.exec(env.DOCKER_HOST ?? '')?.[1];
|
|
17
|
+
const runtime = env.XDG_RUNTIME_DIR;
|
|
18
|
+
return [host, path.join(userHome, '.docker/run/docker.sock'), ...(system ? ['/var/run/docker.sock'] : []), path.join(userHome, '.colima/default/docker.sock'),
|
|
19
|
+
path.join(userHome, '.orbstack/run/docker.sock'), ...(runtime ? [path.join(runtime, 'docker.sock'), path.join(runtime, 'podman/podman.sock')] : [])].filter(Boolean);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// The member's CLI plugins (links into the app bundle on macOS).
|
|
23
|
+
function cliPlugins(userHome, system) {
|
|
24
|
+
const dirs = [path.join(userHome, '.docker/cli-plugins'), ...!system ? [] : ['/usr/local/lib/docker/cli-plugins', '/usr/libexec/docker/cli-plugins', '/usr/lib/docker/cli-plugins',
|
|
25
|
+
'/Applications/Docker.app/Contents/Resources/cli-plugins', '/opt/homebrew/lib/docker/cli-plugins']];
|
|
26
|
+
const plugins = new Map();
|
|
27
|
+
for (const dir of dirs) {
|
|
28
|
+
let names = [];
|
|
29
|
+
try { names = fs.readdirSync(dir); } catch { continue; }
|
|
30
|
+
for (const name of names) {
|
|
31
|
+
if (!/^docker-[a-z0-9-]+$/.test(name) || plugins.has(name)) continue;
|
|
32
|
+
const file = real(path.join(dir, name));
|
|
33
|
+
try { if (file && fs.statSync(file).isFile()) plugins.set(name, file); } catch { /* broken link */ }
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return plugins;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// `system`: also the machine-wide socket and plugin folders (tests leave them out).
|
|
40
|
+
export function containerEngine({ userHome, env = process.env, paths = ['/usr/local/bin', '/opt/homebrew/bin', '/usr/bin', '/Applications/Docker.app/Contents/Resources/bin'], system = true } = {}) {
|
|
41
|
+
const socket = socketCandidates(userHome, env, system).map(real).find(file => file && isSocket(file));
|
|
42
|
+
const cli = paths.map(dir => real(path.join(dir, 'docker'))).find(Boolean);
|
|
43
|
+
if (!socket || !cli) return null;
|
|
44
|
+
const plugins = cliPlugins(userHome, system);
|
|
45
|
+
// Read roots: the folders the CLI and plugins live in (/usr is open already).
|
|
46
|
+
const readRoots = [...new Set([cli, ...plugins.values()].map(file => {
|
|
47
|
+
const bundle = /^(\/Applications\/[^/]+\.app)\//.exec(file)?.[1];
|
|
48
|
+
return bundle ?? path.dirname(file);
|
|
49
|
+
}))].filter(dir => !/^\/(usr|bin|sbin|opt\/homebrew)(\/|$)/.test(dir));
|
|
50
|
+
return { socket, cli, plugins, readRoots };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// The CLI's configuration in the sandbox's home, and the environment that
|
|
54
|
+
// points it (and Testcontainers) at the engine.
|
|
55
|
+
export function engineEnvironment(engine, home) {
|
|
56
|
+
const config = path.join(home, '.docker');
|
|
57
|
+
fs.mkdirSync(path.join(config, 'cli-plugins'), { recursive: true, mode: 0o700 });
|
|
58
|
+
fs.writeFileSync(path.join(config, 'config.json'), '{}\n', { mode: 0o600 });
|
|
59
|
+
for (const [name, file] of engine.plugins) {
|
|
60
|
+
try { fs.symlinkSync(file, path.join(config, 'cli-plugins', name)); } catch { /* already there */ }
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
DOCKER_HOST: `unix://${engine.socket}`, DOCKER_CONFIG: config, DOCKER_CLI_HINTS: 'false',
|
|
64
|
+
// Testcontainers' reaper mounts the engine's socket inside its VM, where
|
|
65
|
+
// Docker Desktop and Colima name it /var/run/docker.sock.
|
|
66
|
+
...(process.platform === 'darwin' ? { TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE: '/var/run/docker.sock' } : {}),
|
|
67
|
+
};
|
|
68
|
+
}
|