@zhushanwen/pi-permission 1.4.4 → 1.4.5
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/README.md +1 -1
- package/package.json +5 -5
- package/skills/permission-ext-config/SKILL.md +1 -1
- package/src/__tests__/session-start-once-guard.test.ts +1 -2
- package/src/__tests__/startup-config-declaration.test.ts +4 -4
- package/src/classifier/__tests__/classifier.test.ts +16 -7
- package/src/classifier/model-resolver.ts +1 -1
package/README.md
CHANGED
|
@@ -21,7 +21,7 @@ Pi permission 扩展 — 四档权限模式(yolo / auto / approve / strict)+
|
|
|
21
21
|
pi install npm:@zhushanwen/pi-permission
|
|
22
22
|
|
|
23
23
|
# 本地开发(symlink;globalExtDir 平铺布局,目标不带分组层)
|
|
24
|
-
ln -s /path/to/
|
|
24
|
+
ln -s /path/to/taiji/extensions/universal/permission \
|
|
25
25
|
~/.pi/agent/extensions/permission
|
|
26
26
|
```
|
|
27
27
|
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhushanwen/pi-permission",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.5",
|
|
4
4
|
"description": "Pi permission extension — four permission modes (yolo/auto/approve/strict) with three-layer pipeline (AST + rules + AI classifier).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
7
|
-
"
|
|
7
|
+
"taiji": {
|
|
8
8
|
"role": "universal",
|
|
9
9
|
"startupConfig": [
|
|
10
10
|
{
|
|
@@ -50,9 +50,9 @@
|
|
|
50
50
|
"dependencies": {
|
|
51
51
|
"tree-sitter-bash": "^0.25.1",
|
|
52
52
|
"web-tree-sitter": "^0.26.11",
|
|
53
|
-
"@zhushanwen/pi-ext-guards": "0.4.
|
|
54
|
-
"@zhushanwen/pi-
|
|
55
|
-
"@zhushanwen/pi-
|
|
53
|
+
"@zhushanwen/pi-ext-guards": "0.4.1",
|
|
54
|
+
"@zhushanwen/pi-extension-logger": "0.6.1",
|
|
55
|
+
"@zhushanwen/pi-llm-shared": "0.8.1"
|
|
56
56
|
},
|
|
57
57
|
"peerDependencies": {
|
|
58
58
|
"@earendil-works/pi-ai": "^0.84.4",
|
|
@@ -17,7 +17,7 @@ description: "配置 @zhushanwen/pi-permission(四档权限模式 + AI 风险
|
|
|
17
17
|
|
|
18
18
|
`<agentDir>/config/permission-ext-config.json`
|
|
19
19
|
|
|
20
|
-
- `<agentDir>` = pi agent 目录(`PI_CODING_AGENT_DIR` 覆盖,默认 `~/.pi/agent`;
|
|
20
|
+
- `<agentDir>` = pi agent 目录(`PI_CODING_AGENT_DIR` 覆盖,默认 `~/.pi/agent`;taiji 隔离环境为 `~/.taiji/pi/agent`)
|
|
21
21
|
- 走 llm-shared 泛型 config(config/ 子目录 + getAgentDir 派生 + mtime+size 缓存 + 原子写)
|
|
22
22
|
- 文件缺失/坏 JSON 返回默认值,不抛错;首次加载自动创建默认配置文件
|
|
23
23
|
- [HISTORICAL] 旧路径 `<agentDir>/permission-config.json`(agentDir 根):**session_start hook 运行时迁移**到新路径(幂等,过渡性,Added in v1.0.0, remove after v2.0.0)
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* session-start-once-guard.test.ts — u-audit-fix 探针实测(permission 侧)。
|
|
3
3
|
*
|
|
4
|
-
* 排查清单(docs/design/pi-session-start-handler-idempotency-audit.md §2 permission 行)
|
|
5
4
|
* 判定「必须接入」:migrateLegacyConfig 写 agentDir 全局配置文件,属跨 session 副作用,
|
|
6
5
|
* 已由 oncePerProcess 守卫收编原内联 once flag。本文件按清单探针验证点双派发实测:
|
|
7
6
|
* a) 双派发(同一 factory 闭包直接调 handler 两次)下 spy migrateLegacyConfig 调用 = 1;
|
|
@@ -10,7 +9,7 @@
|
|
|
10
9
|
* c) migrated warn 仅一条:构造性蕴含于 a——warn 在 migrateLegacyConfig 调用点内部
|
|
11
10
|
* (llm-shared migrate.ts "migrated" 分支),调用 = 1 ⟹ warn ≤ 1,不另设断言。
|
|
12
11
|
* 反向断言(豁免项防误伤):footer 注册为纯内存初始化(registry.register 同 id 覆盖),
|
|
13
|
-
*
|
|
12
|
+
* 不在包装范围——双派发仍每次执行(pending push ×2)。
|
|
14
13
|
*/
|
|
15
14
|
import { existsSync, mkdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
16
15
|
import { tmpdir } from "node:os";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* startupConfig 声明守护测试:断言 package.json `
|
|
2
|
+
* startupConfig 声明守护测试:断言 package.json `taiji.startupConfig` 声明的
|
|
3
3
|
* content 与代码 DEFAULT_CONFIG 常量深相等,防止两侧任一改动未同步(漂移)。
|
|
4
4
|
* 机制:runtime 启动序列统一 ensure(extension-startup-config.ts),声明即首建内容。
|
|
5
5
|
*
|
|
@@ -13,7 +13,7 @@ import { describe, expect, it } from "vitest";
|
|
|
13
13
|
|
|
14
14
|
import { DEFAULT_CONFIG } from "../types.js";
|
|
15
15
|
|
|
16
|
-
/** package.json `
|
|
16
|
+
/** package.json `taiji.startupConfig` 声明条目的最小形状(守护断言用)。 */
|
|
17
17
|
interface StartupConfigEntry {
|
|
18
18
|
path: string;
|
|
19
19
|
content: unknown;
|
|
@@ -21,11 +21,11 @@ interface StartupConfigEntry {
|
|
|
21
21
|
|
|
22
22
|
const pkg = JSON.parse(
|
|
23
23
|
readFileSync(join(fileURLToPath(import.meta.url), "../../../package.json"), "utf-8"),
|
|
24
|
-
) as { "
|
|
24
|
+
) as { "taiji"?: { startupConfig?: StartupConfigEntry[] } };
|
|
25
25
|
|
|
26
26
|
describe("startupConfig 声明守护", () => {
|
|
27
27
|
it("声明 content 与代码 DEFAULT_CONFIG 深相等", () => {
|
|
28
|
-
const entry = pkg["
|
|
28
|
+
const entry = pkg["taiji"]?.startupConfig?.find(
|
|
29
29
|
(e: StartupConfigEntry) => e.path === "config/permission-ext-config.json",
|
|
30
30
|
);
|
|
31
31
|
expect(entry).toBeDefined();
|
|
@@ -166,13 +166,22 @@ describe("CT2: fail-closed 路径", () => {
|
|
|
166
166
|
|
|
167
167
|
describe("CT3: timeout 与 abort 兜底", () => {
|
|
168
168
|
it("C8: callLLM 永挂 + 短 timeout → fallback ask(不卡死)", async () => {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
169
|
+
// fake timers 模拟 1s 超时流逝(M3 同款正解),避免真实等待;timeout 单位是秒,
|
|
170
|
+
// classifyRisk 内 * MILLIS_PER_SECOND 转 ms 后挂 setTimeout → 推进 1000ms 触发
|
|
171
|
+
vi.useFakeTimers();
|
|
172
|
+
try {
|
|
173
|
+
const shortTimeoutConfig: ClassifierConfig = { ...CONFIG, timeout: 1 };
|
|
174
|
+
const classifier = createClassifier(makeDeps({
|
|
175
|
+
callLLM: neverCallLLM(),
|
|
176
|
+
}));
|
|
177
|
+
const classifyPromise = classifier.classifyRisk(CTX, shortTimeoutConfig);
|
|
178
|
+
await vi.advanceTimersByTimeAsync(1000);
|
|
179
|
+
const r = await classifyPromise;
|
|
180
|
+
expect(r.outcome).toBe("ask");
|
|
181
|
+
} finally {
|
|
182
|
+
vi.useRealTimers();
|
|
183
|
+
}
|
|
184
|
+
});
|
|
176
185
|
|
|
177
186
|
it("C9: abort signal 已 abort → 立刻 fallback ask", async () => {
|
|
178
187
|
const ac = new AbortController();
|
|
@@ -48,7 +48,7 @@ export interface ResolvedModelEntry {
|
|
|
48
48
|
*
|
|
49
49
|
* model picker(/permission model)用:第一级选 provider,第二级选该 provider 下的 model。
|
|
50
50
|
*
|
|
51
|
-
* 排序规则(E2):整体按 provider + id 字典序(cost 在
|
|
51
|
+
* 排序规则(E2):整体按 provider + id 字典序(cost 在 taiji 环境普遍缺失,
|
|
52
52
|
* 旧 cost.input 排序无语义;Map 保持插入序,字典序保证 picker 展示稳定)。
|
|
53
53
|
*
|
|
54
54
|
* modelRegistry 无可用模型 / 全部无 auth → 返回空 Map(不 throw,调用方据此降级为
|