@trim21/personal-pi-extensions 0.1.527 → 0.1.529
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/package.json +1 -1
- package/src/bwrap/core.ts +10 -0
- package/src/spawn-agent.ts +9 -6
package/package.json
CHANGED
package/src/bwrap/core.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { type ChildProcess, spawn } from "node:child_process";
|
|
|
2
2
|
import { constants, type Dirent, existsSync, readFileSync } from "node:fs";
|
|
3
3
|
import { access as fsAccess, readdir, realpath, stat } from "node:fs/promises";
|
|
4
4
|
import { delimiter, join } from "node:path";
|
|
5
|
+
import process from "node:process";
|
|
5
6
|
import { fileURLToPath } from "node:url";
|
|
6
7
|
|
|
7
8
|
import { StringEnum } from "@earendil-works/pi-ai";
|
|
@@ -353,6 +354,15 @@ async function realpathOrSelf(path: string): Promise<string> {
|
|
|
353
354
|
|
|
354
355
|
export async function buildBwrapArgs(resolved: ResolvedBwrap, cwd: string): Promise<string[]> {
|
|
355
356
|
const args = ["--new-session", "--die-with-parent", "--unshare-user", "--unshare-pid"];
|
|
357
|
+
// 沙箱进程以调用方(pi)的 uid/gid 运行,而不是 userns 里的 0。
|
|
358
|
+
// net-allowlist 模式下命令先经 nsenter 进入 holder 的 userns(unshare -r 把 pi 的 uid 映射成 0),
|
|
359
|
+
// bwrap 默认继承该 uid 会让沙箱内 id/stat 自称 root、与宿主视角不一致;
|
|
360
|
+
// 直接模式(无 holder)下这两个值本就等于 bwrap 的 real uid,等价于默认行为。
|
|
361
|
+
const uid = process.getuid?.();
|
|
362
|
+
const gid = process.getgid?.();
|
|
363
|
+
if (uid !== undefined && gid !== undefined) {
|
|
364
|
+
args.push("--uid", String(uid), "--gid", String(gid));
|
|
365
|
+
}
|
|
356
366
|
// --*-bind-try:配置的路径不存在时忽略该项而不是让整条命令失败
|
|
357
367
|
for (const path of resolved.writablePaths) {
|
|
358
368
|
const absolutePath = await realpathOrSelf(resolveBwrapPath(path, cwd));
|
package/src/spawn-agent.ts
CHANGED
|
@@ -15,9 +15,11 @@
|
|
|
15
15
|
* `text: <content>` lines for completed text blocks, keeping the last
|
|
16
16
|
* `MAX_PROGRESS_LINES` lines. Consecutive tool calls are merged into a
|
|
17
17
|
* single `tool:` line (`read x 2, glob`) and over-long line content is
|
|
18
|
-
* folded to the first/last
|
|
18
|
+
* folded to the first/last 9 chars joined by `…`, so a burst of tool calls
|
|
19
19
|
* or a long text block does not flood the window; any text block starts a
|
|
20
|
-
* new line.
|
|
20
|
+
* new line. The final line is always the subagent name as a code span
|
|
21
|
+
* (`` `scout` ``), followed by the live usage stats when there are any; it
|
|
22
|
+
* rides outside the rolling window so it is never trimmed.
|
|
21
23
|
*
|
|
22
24
|
* Security default: without an explicit `tools:` in the frontmatter, the
|
|
23
25
|
* subagent only gets read-only tools (read/grep/find/ls) — no bash/write/edit.
|
|
@@ -396,12 +398,13 @@ export async function runAgent(
|
|
|
396
398
|
};
|
|
397
399
|
|
|
398
400
|
const emitUpdate = () => {
|
|
399
|
-
//
|
|
400
|
-
//
|
|
401
|
+
// 最后一行固定是「子代理名 + 运行中统计」:名字用 code span 标出,进度流里
|
|
402
|
+
// 一眼能看出属于哪个 subagent;usage 与它同行,TUI 始终能看到实时 token 开销。
|
|
403
|
+
// 这行位于滚动窗口之外,因此永远不会被挤掉。
|
|
401
404
|
const usageLine = formatUsageStats(result.usage, result.model);
|
|
402
|
-
const
|
|
405
|
+
const footer = usageLine ? `\`${result.agent}\` ${usageLine}` : `\`${result.agent}\``;
|
|
403
406
|
onUpdate?.({
|
|
404
|
-
content: [{ type: "text", text:
|
|
407
|
+
content: [{ type: "text", text: [...logLines, footer].join("\n") }],
|
|
405
408
|
details: { ...result },
|
|
406
409
|
});
|
|
407
410
|
};
|