mirror of
https://bitbucket.org/siakitem/my-pi.git
synced 2026-10-26 10:45:22 +00:00
feat: 接入 Pi 内置 codemode,并修复全面审查发现的问题
- codemode:Tool Search 常驻(alwaysEnabled)、权限 allow(嵌套调用仍逐个过权限门)、 tools.jsonc 登记使用规则;RTK 跳过 parentToolCallId 嵌套调用,避免丢失 bash structuredContent;Tool Search 目录过滤 hidden / codemode(script-only)exposure; 扩展加载测试加载 builtin:codemode 并断言其常驻激活 - 搜索 key 不再经命令行参数传递:search-auth.mjs 改为 --set-stdin(先读校验再加锁), configure.sh 交互输入经管道、非交互用 --<provider> - - CodeGraph 客户端监听子进程 stdin error,避免 EPIPE 未处理导致崩溃 - 移除 PI_TOOL_SEARCH/HERMES_MEMORY/RTK_CONFIG_PATH 环境变量入口,测试改用工厂 configPath 注入 - pi-subagents 固定 vitest / coverage-istanbul 4.1.10,修复 npm ls 版本冲突 - 补 pi-web-search / pi-worktree UPSTREAM.md 与 pi-minimal-footer AGENTS.md, files 白名单补齐并加测试;.codegraph/.gitignore 移出跟踪 - detect_kitty 优先识别官方安装目录 Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
co-authored by
Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
parent
56cbc83296
commit
f9a7f743dd
@@ -0,0 +1,70 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { accessSync, chmodSync, constants } from "node:fs";
|
||||
import { mkdir, mkdtemp, rm, symlink, writeFile } from "node:fs/promises";
|
||||
import { tmpdir } from "node:os";
|
||||
import { dirname, join } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import test from "node:test";
|
||||
|
||||
const LIB_SH = fileURLToPath(new URL("../scripts/lib.sh", import.meta.url));
|
||||
const SYSTEM_KITTY = "/Applications/kitty.app/Contents/MacOS/kitty";
|
||||
|
||||
function systemKittyPath(): string | undefined {
|
||||
try {
|
||||
accessSync(SYSTEM_KITTY, constants.X_OK);
|
||||
return SYSTEM_KITTY;
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function runDetectKitty(home: string, pathDir: string) {
|
||||
return spawnSync(
|
||||
"sh",
|
||||
["-c", `. "$1"; detect_kitty; status=$?; printf '%s' "$kitty_bin"; exit "$status"`, "sh", LIB_SH],
|
||||
{
|
||||
encoding: "utf8",
|
||||
env: { ...process.env, HOME: home, PATH: `${pathDir}:${process.env.PATH}` },
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
test("detect_kitty prefers an official install over a PATH kitty", async () => {
|
||||
const home = await mkdtemp(join(tmpdir(), "my-pi-libsh-"));
|
||||
try {
|
||||
const official = join(home, ".local", "kitty.app", "bin", "kitty");
|
||||
const pathDir = join(home, "pathbin");
|
||||
await mkdir(dirname(official), { recursive: true });
|
||||
await mkdir(pathDir, { recursive: true });
|
||||
await writeFile(official, "#!/bin/sh\n");
|
||||
chmodSync(official, 0o755);
|
||||
await symlink(official, join(pathDir, "kitty"));
|
||||
|
||||
const result = runDetectKitty(home, pathDir);
|
||||
assert.equal(result.status, 0, result.stderr);
|
||||
// A real /Applications kitty also wins over $HOME/.local and PATH.
|
||||
assert.equal(result.stdout, systemKittyPath() ?? official);
|
||||
} finally {
|
||||
await rm(home, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test("detect_kitty falls back to a PATH kitty when no official install exists", async () => {
|
||||
const home = await mkdtemp(join(tmpdir(), "my-pi-libsh-"));
|
||||
try {
|
||||
const pathDir = join(home, "pathbin");
|
||||
const pathKitty = join(pathDir, "kitty");
|
||||
await mkdir(pathDir, { recursive: true });
|
||||
await writeFile(pathKitty, "#!/bin/sh\n");
|
||||
chmodSync(pathKitty, 0o755);
|
||||
|
||||
const result = runDetectKitty(home, pathDir);
|
||||
assert.equal(result.status, 0, result.stderr);
|
||||
// The isolated HOME has no ~/.local install; only a machine-level
|
||||
// /Applications kitty (when present) still takes precedence.
|
||||
assert.equal(result.stdout, systemKittyPath() ?? pathKitty);
|
||||
} finally {
|
||||
await rm(home, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user