@gotgenes/pi-permission-system 10.10.1 → 11.0.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 +21 -0
- package/package.json +1 -1
- package/src/handlers/before-agent-start.ts +3 -3
- package/src/index.ts +1 -0
- package/src/tool-registry.ts +3 -0
- package/test/handlers/before-agent-start.test.ts +31 -3
- package/test/helpers/handler-fixtures.ts +1 -0
- package/test/helpers/make-fake-pi.ts +5 -0
- package/test/permission-events.test.ts +1 -0
- package/test/session-start.test.ts +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,27 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [11.0.0](https://github.com/gotgenes/pi-packages/compare/pi-permission-system-v10.10.1...pi-permission-system-v11.0.0) (2026-06-11)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### ⚠ BREAKING CHANGES
|
|
12
|
+
|
|
13
|
+
* The permission system no longer auto-activates pi's off-by-default tools (`find`, `grep`, `ls`) in the main session. Users who want them active should enable them via pi's own `activeTools` configuration rather than relying on the permission system to expose every non-denied tool.
|
|
14
|
+
|
|
15
|
+
### Features
|
|
16
|
+
|
|
17
|
+
* add getActive to ToolRegistry wired to pi.getActiveTools ([#385](https://github.com/gotgenes/pi-packages/issues/385)) ([79c4594](https://github.com/gotgenes/pi-packages/commit/79c459443294c1b58643b746e3511fc17c9f8961))
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Bug Fixes
|
|
21
|
+
|
|
22
|
+
* respect pi's default active tool set in before_agent_start ([#385](https://github.com/gotgenes/pi-packages/issues/385)) ([bf5be48](https://github.com/gotgenes/pi-packages/commit/bf5be48ca8b06e8cb08f66d08eccb85af0673987))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Documentation
|
|
26
|
+
|
|
27
|
+
* clarify before_agent_start filters pi's active tool set ([#385](https://github.com/gotgenes/pi-packages/issues/385)) ([bdb5a6a](https://github.com/gotgenes/pi-packages/commit/bdb5a6a08e3c1bb611c8b1795c4d46856104b3b0))
|
|
28
|
+
|
|
8
29
|
## [10.10.1](https://github.com/gotgenes/pi-packages/compare/pi-permission-system-v10.10.0...pi-permission-system-v10.10.1) (2026-06-11)
|
|
9
30
|
|
|
10
31
|
|
package/package.json
CHANGED
|
@@ -38,7 +38,7 @@ export function shouldExposeTool(
|
|
|
38
38
|
* Constructor deps:
|
|
39
39
|
* - `session` — encapsulates all mutable session state and lifecycle operations
|
|
40
40
|
* - `resolver` — owns permission-query surface: `getToolPermission`, `getPolicyCacheStamp`, skill check
|
|
41
|
-
* - `toolRegistry` — Pi tool API subset (
|
|
41
|
+
* - `toolRegistry` — Pi tool API subset (getActive + setActive)
|
|
42
42
|
*/
|
|
43
43
|
export class AgentPrepHandler {
|
|
44
44
|
constructor(
|
|
@@ -56,10 +56,10 @@ export class AgentPrepHandler {
|
|
|
56
56
|
this.session.refreshConfig(ctx);
|
|
57
57
|
|
|
58
58
|
const agentName = this.session.resolveAgentName(ctx, event.systemPrompt);
|
|
59
|
-
const
|
|
59
|
+
const activeTools = this.toolRegistry.getActive();
|
|
60
60
|
const allowedTools: string[] = [];
|
|
61
61
|
|
|
62
|
-
for (const tool of
|
|
62
|
+
for (const tool of activeTools) {
|
|
63
63
|
const toolName = getToolNameFromValue(tool);
|
|
64
64
|
if (!toolName) {
|
|
65
65
|
continue;
|
package/src/index.ts
CHANGED
|
@@ -152,6 +152,7 @@ export default function piPermissionSystemExtension(pi: ExtensionAPI): void {
|
|
|
152
152
|
|
|
153
153
|
const toolRegistry = {
|
|
154
154
|
getAll: () => pi.getAllTools(),
|
|
155
|
+
getActive: () => pi.getActiveTools(),
|
|
155
156
|
setActive: (names: string[]) => pi.setActiveTools(names),
|
|
156
157
|
};
|
|
157
158
|
|
package/src/tool-registry.ts
CHANGED
|
@@ -2,7 +2,10 @@ import { getNonEmptyString, toRecord } from "./common";
|
|
|
2
2
|
|
|
3
3
|
/** Narrow interface for the Pi tool API subset used by handler classes. */
|
|
4
4
|
export interface ToolRegistry {
|
|
5
|
+
/** All registered tools (`pi.getAllTools()` — `ToolInfo[]`); kept defensively wide. */
|
|
5
6
|
getAll(): unknown[];
|
|
7
|
+
/** Currently active tool names (`pi.getActiveTools()`). */
|
|
8
|
+
getActive(): string[];
|
|
6
9
|
setActive(names: string[]): void;
|
|
7
10
|
}
|
|
8
11
|
|
|
@@ -31,6 +31,7 @@ function makeEvent(systemPrompt = "You are an assistant.") {
|
|
|
31
31
|
function makeToolRegistry(overrides: Partial<ToolRegistry> = {}): ToolRegistry {
|
|
32
32
|
return {
|
|
33
33
|
getAll: vi.fn().mockReturnValue([]),
|
|
34
|
+
getActive: vi.fn().mockReturnValue([]),
|
|
34
35
|
setActive: vi.fn(),
|
|
35
36
|
...overrides,
|
|
36
37
|
};
|
|
@@ -126,7 +127,7 @@ describe("AgentPrepHandler.handle", () => {
|
|
|
126
127
|
const { handler, toolRegistry } = makeSetup({
|
|
127
128
|
toolPermission: "deny",
|
|
128
129
|
toolRegistry: {
|
|
129
|
-
|
|
130
|
+
getActive: vi.fn().mockReturnValue(["write", "read"]),
|
|
130
131
|
},
|
|
131
132
|
});
|
|
132
133
|
await handler.handle(makeEvent(), makeCtx());
|
|
@@ -136,17 +137,44 @@ describe("AgentPrepHandler.handle", () => {
|
|
|
136
137
|
it("includes allowed and ask tools in the active list", async () => {
|
|
137
138
|
const { handler, toolRegistry } = makeSetup({
|
|
138
139
|
toolRegistry: {
|
|
139
|
-
|
|
140
|
+
getActive: vi.fn().mockReturnValue(["read", "write"]),
|
|
140
141
|
},
|
|
141
142
|
});
|
|
142
143
|
await handler.handle(makeEvent(), makeCtx());
|
|
143
144
|
expect(toolRegistry.setActive).toHaveBeenCalledWith(["read", "write"]);
|
|
144
145
|
});
|
|
145
146
|
|
|
147
|
+
it("does not activate registered tools pi left inactive (find/grep/ls)", async () => {
|
|
148
|
+
// Regression for #385: the active set is the base, not the full registry.
|
|
149
|
+
const { handler, toolRegistry } = makeSetup({
|
|
150
|
+
toolRegistry: {
|
|
151
|
+
getActive: vi.fn().mockReturnValue(["read", "bash", "edit", "write"]),
|
|
152
|
+
getAll: vi
|
|
153
|
+
.fn()
|
|
154
|
+
.mockReturnValue([
|
|
155
|
+
{ name: "read" },
|
|
156
|
+
{ name: "bash" },
|
|
157
|
+
{ name: "edit" },
|
|
158
|
+
{ name: "write" },
|
|
159
|
+
{ name: "find" },
|
|
160
|
+
{ name: "grep" },
|
|
161
|
+
{ name: "ls" },
|
|
162
|
+
]),
|
|
163
|
+
},
|
|
164
|
+
});
|
|
165
|
+
await handler.handle(makeEvent(), makeCtx());
|
|
166
|
+
expect(toolRegistry.setActive).toHaveBeenCalledWith([
|
|
167
|
+
"read",
|
|
168
|
+
"bash",
|
|
169
|
+
"edit",
|
|
170
|
+
"write",
|
|
171
|
+
]);
|
|
172
|
+
});
|
|
173
|
+
|
|
146
174
|
it("calls setActive once across repeated calls with the same allowed tools", async () => {
|
|
147
175
|
const { handler, toolRegistry } = makeSetup({
|
|
148
176
|
toolRegistry: {
|
|
149
|
-
|
|
177
|
+
getActive: vi.fn().mockReturnValue(["read"]),
|
|
150
178
|
},
|
|
151
179
|
});
|
|
152
180
|
await handler.handle(makeEvent(), makeCtx());
|
|
@@ -42,6 +42,8 @@ export interface FakePi {
|
|
|
42
42
|
fire(event: string, input?: unknown, ctx?: unknown): Promise<unknown>;
|
|
43
43
|
/** Minimal tool registry — returns the configured tool names. */
|
|
44
44
|
getAllTools(): { name: string }[];
|
|
45
|
+
/** Active tool names (`pi.getActiveTools()` shape — bare strings). */
|
|
46
|
+
getActiveTools(): string[];
|
|
45
47
|
setActiveTools(names: string[]): void;
|
|
46
48
|
}
|
|
47
49
|
|
|
@@ -80,6 +82,9 @@ export function makeFakePi(options: MakeFakePiOptions = {}): FakePi {
|
|
|
80
82
|
getAllTools(): { name: string }[] {
|
|
81
83
|
return toolNames.map((name) => ({ name }));
|
|
82
84
|
},
|
|
85
|
+
getActiveTools(): string[] {
|
|
86
|
+
return [...toolNames];
|
|
87
|
+
},
|
|
83
88
|
setActiveTools: vi.fn(),
|
|
84
89
|
// ── ExtensionAPI methods the factory touches (recorded) ────────────────
|
|
85
90
|
on(event: string, handler: RecordedHandler): void {
|
|
@@ -363,6 +363,7 @@ describe("piPermissionSystemExtension ready event wiring", () => {
|
|
|
363
363
|
),
|
|
364
364
|
registerCommand: vi.fn(),
|
|
365
365
|
getAllTools: vi.fn().mockReturnValue([]),
|
|
366
|
+
getActiveTools: vi.fn().mockReturnValue([]),
|
|
366
367
|
setActiveTools: vi.fn(),
|
|
367
368
|
registerProvider: vi.fn(),
|
|
368
369
|
events: { emit: emitSpy, on: vi.fn().mockReturnValue(() => undefined) },
|
|
@@ -56,6 +56,7 @@ describe("session_start handler consolidation", () => {
|
|
|
56
56
|
},
|
|
57
57
|
registerCommand: (): void => {},
|
|
58
58
|
getAllTools: (): Array<{ name: string }> => [],
|
|
59
|
+
getActiveTools: (): string[] => [],
|
|
59
60
|
setActiveTools: (): void => {},
|
|
60
61
|
registerProvider: (): void => {},
|
|
61
62
|
events: {
|
|
@@ -79,6 +80,7 @@ describe("session_start handler consolidation", () => {
|
|
|
79
80
|
},
|
|
80
81
|
registerCommand: (): void => {},
|
|
81
82
|
getAllTools: (): Array<{ name: string }> => [],
|
|
83
|
+
getActiveTools: (): string[] => [],
|
|
82
84
|
setActiveTools: (): void => {},
|
|
83
85
|
registerProvider: (): void => {},
|
|
84
86
|
events: {
|