@trim21/personal-pi-extensions 0.0.370 → 0.0.373

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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/bwrap/core.ts +17 -4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trim21/personal-pi-extensions",
3
- "version": "0.0.370",
3
+ "version": "0.0.373",
4
4
  "type": "module",
5
5
  "description": "Custom pi coding-agent extensions: bwrap sandbox, workspace guard, opencode edit, and more",
6
6
  "keywords": [
package/src/bwrap/core.ts CHANGED
@@ -5,7 +5,7 @@ import { delimiter, join } from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
6
 
7
7
  import { StringEnum } from "@earendil-works/pi-ai";
8
- import { type BashOperations, getAgentDir } from "@earendil-works/pi-coding-agent";
8
+ import { type BashOperations, getAgentDir, getShellConfig } from "@earendil-works/pi-coding-agent";
9
9
  import { type Static, Type } from "typebox";
10
10
  import { Value } from "typebox/value";
11
11
 
@@ -245,6 +245,8 @@ export function createBwrapBashOperations(
245
245
  resolved: ResolvedBwrap,
246
246
  workspace: string,
247
247
  ): BashOperations {
248
+ // 沙箱内不透传 PATH,execvp 的默认路径可能找不到 bash(如 NixOS),故在父进程解析绝对路径
249
+ const shell = getShellConfig().shell;
248
250
  return {
249
251
  async exec(command, cwd, { onData, signal, timeout }) {
250
252
  await fsAccess(cwd, constants.F_OK).catch(() => {
@@ -252,6 +254,12 @@ export function createBwrapBashOperations(
252
254
  });
253
255
  if (signal?.aborted) throw new Error("aborted");
254
256
 
257
+ // 干净环境:不继承父进程 env/PATH,由 bash -lc 从 /etc/profile 与用户 profile 重建
258
+ const home = process.env.HOME;
259
+ if (home === undefined) {
260
+ throw new Error("HOME is not set; refusing to run bash in a clean environment");
261
+ }
262
+
255
263
  const seccompFd = resolved.network ? undefined : getSeccompFd();
256
264
  const baseArgs = [
257
265
  "--ro-bind",
@@ -266,8 +274,8 @@ export function createBwrapBashOperations(
266
274
  const child = spawn(
267
275
  findBwrap(resolved.bwrapPath),
268
276
  seccompFd === undefined
269
- ? [...baseArgs, "--", "bash", "-c", command]
270
- : [...baseArgs, "--seccomp", "3", "--", "bash", "-c", command],
277
+ ? [...baseArgs, "--", shell, "-lc", command]
278
+ : [...baseArgs, "--seccomp", "3", "--", shell, "-lc", command],
271
279
  {
272
280
  cwd,
273
281
  detached: true,
@@ -275,7 +283,12 @@ export function createBwrapBashOperations(
275
283
  seccompFd === undefined
276
284
  ? ["ignore", "pipe", "pipe"]
277
285
  : ["ignore", "pipe", "pipe", seccompFd],
278
- env: process.env,
286
+ env: {
287
+ HOME: home,
288
+ SHELL: "/bin/bash",
289
+ TERM: "dumb",
290
+ LANG: "C.UTF-8",
291
+ },
279
292
  },
280
293
  );
281
294