@gotgenes/pi-permission-system 5.8.0 → 5.10.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.
@@ -3,8 +3,8 @@ import { describe, expect, it, vi } from "vitest";
3
3
 
4
4
  import { getEventInput, handleToolCall } from "../../src/handlers/tool-call";
5
5
  import type { HandlerDeps } from "../../src/handlers/types";
6
- import type { SessionState } from "../../src/runtime";
7
- import type { PermissionCheckResult } from "../../src/types";
6
+ import type { PermissionSession } from "../../src/permission-session";
7
+ import type { PermissionCheckResult, PermissionState } from "../../src/types";
8
8
 
9
9
  // ── SDK stubs ──────────────────────────────────────────────────────────────
10
10
  vi.mock("@mariozechner/pi-coding-agent", async (importOriginal) => {
@@ -55,43 +55,35 @@ function makePermissionResult(
55
55
  return { state, toolName: "read", source: "tool", origin: "builtin" };
56
56
  }
57
57
 
58
- function makeSession(overrides: Partial<SessionState> = {}): SessionState {
58
+ function makeSession(
59
+ overrides: Partial<Record<keyof PermissionSession, unknown>> = {},
60
+ ): PermissionSession {
59
61
  return {
60
- runtimeContext: null,
61
- permissionManager: {
62
- checkPermission: vi.fn().mockReturnValue(makePermissionResult("allow")),
63
- } as unknown as SessionState["permissionManager"],
64
- activeSkillEntries: [],
65
- lastKnownActiveAgentName: null,
66
- lastActiveToolsCacheKey: null,
67
- lastPromptStateCacheKey: null,
68
- sessionRules: {
69
- approve: vi.fn(),
70
- getRuleset: vi.fn().mockReturnValue([]),
71
- clear: vi.fn(),
72
- } as unknown as SessionState["sessionRules"],
62
+ logger: { debug: vi.fn(), review: vi.fn(), warn: vi.fn() },
63
+ activate: vi.fn(),
64
+ resolveAgentName: vi.fn().mockReturnValue(null),
65
+ checkPermission: vi.fn().mockReturnValue(makePermissionResult("allow")),
66
+ getToolPermission: vi.fn().mockReturnValue("allow" as PermissionState),
67
+ getSessionRuleset: vi.fn().mockReturnValue([]),
68
+ approveSessionRule: vi.fn(),
69
+ getActiveSkillEntries: vi.fn().mockReturnValue([]),
70
+ getInfrastructureDirs: vi
71
+ .fn()
72
+ .mockReturnValue(["/test/agent", "/test/agent/git"]),
73
+ getInfrastructureReadPaths: vi.fn().mockReturnValue([]),
73
74
  ...overrides,
74
- };
75
+ } as unknown as PermissionSession;
75
76
  }
76
77
 
77
78
  function makeDeps(overrides: Partial<HandlerDeps> = {}): HandlerDeps {
78
79
  return {
79
80
  session: makeSession(),
80
- logger: { debug: vi.fn(), review: vi.fn(), warn: vi.fn() },
81
- piInfrastructureDirs: ["/test/agent", "/test/agent/git"],
82
- getPiInfrastructureReadPaths: vi.fn().mockReturnValue([]),
83
- createPermissionManagerForCwd: vi.fn(),
84
- refreshExtensionConfig: vi.fn(),
85
- logResolvedConfigPaths: vi.fn(),
86
- resolveAgentName: vi.fn().mockReturnValue(null),
81
+ events: { emit: vi.fn(), on: vi.fn().mockReturnValue(() => undefined) },
87
82
  canRequestPermissionConfirmation: vi.fn().mockReturnValue(true),
88
83
  promptPermission: vi
89
84
  .fn()
90
85
  .mockResolvedValue({ approved: true, state: "approved" }),
91
86
  createPermissionRequestId: vi.fn().mockReturnValue("req-id"),
92
- events: { emit: vi.fn(), on: vi.fn().mockReturnValue(() => undefined) },
93
- startForwardedPermissionPolling: vi.fn(),
94
- stopForwardedPermissionPolling: vi.fn(),
95
87
  stopPermissionRpcHandlers: vi.fn(),
96
88
  getAllTools: vi.fn().mockReturnValue([{ name: "read" }, { name: "bash" }]),
97
89
  setActiveTools: vi.fn(),
@@ -128,23 +120,15 @@ describe("getEventInput", () => {
128
120
  // ── handleToolCall ─────────────────────────────────────────────────────────
129
121
 
130
122
  describe("handleToolCall", () => {
131
- it("sets runtime context", async () => {
132
- const ctx = makeCtx();
133
- const deps = makeDeps();
134
- await handleToolCall(deps, makeToolCallEvent("read"), ctx);
135
- expect(deps.session.runtimeContext).toBe(ctx);
136
- });
137
-
138
- it("starts forwarded permission polling", async () => {
123
+ it("activates session with ctx", async () => {
139
124
  const ctx = makeCtx();
140
125
  const deps = makeDeps();
141
126
  await handleToolCall(deps, makeToolCallEvent("read"), ctx);
142
- expect(deps.startForwardedPermissionPolling).toHaveBeenCalledWith(ctx);
127
+ expect(deps.session.activate).toHaveBeenCalledWith(ctx);
143
128
  });
144
129
 
145
130
  it("blocks when tool name cannot be resolved", async () => {
146
131
  const deps = makeDeps();
147
- // An event with no recognisable name field
148
132
  const result = await handleToolCall(deps, { type: "tool_call" }, makeCtx());
149
133
  expect(result).toEqual({
150
134
  block: true,
@@ -165,7 +149,6 @@ describe("handleToolCall", () => {
165
149
  });
166
150
 
167
151
  it("returns empty object when tool is allowed", async () => {
168
- // default makeRuntime() has checkPermission → "allow"
169
152
  const deps = makeDeps();
170
153
  const result = await handleToolCall(
171
154
  deps,
@@ -176,15 +159,10 @@ describe("handleToolCall", () => {
176
159
  });
177
160
 
178
161
  it("blocks when tool is denied by policy", async () => {
179
- const deps = makeDeps({
180
- session: makeSession({
181
- permissionManager: {
182
- checkPermission: vi
183
- .fn()
184
- .mockReturnValue(makePermissionResult("deny")),
185
- } as unknown as SessionState["permissionManager"],
186
- }),
162
+ const session = makeSession({
163
+ checkPermission: vi.fn().mockReturnValue(makePermissionResult("deny")),
187
164
  });
165
+ const deps = makeDeps({ session });
188
166
  const result = await handleToolCall(
189
167
  deps,
190
168
  makeToolCallEvent("read"),
@@ -206,8 +184,11 @@ describe("handleToolCall — skill-read gate", () => {
206
184
  normalizedLocation: "/skills/librarian/SKILL.md",
207
185
  normalizedBaseDir: "/skills/librarian",
208
186
  };
187
+ const session = makeSession({
188
+ getActiveSkillEntries: vi.fn().mockReturnValue([skillEntry]),
189
+ });
209
190
  const deps = makeDeps({
210
- session: makeSession({ activeSkillEntries: [skillEntry] }),
191
+ session,
211
192
  getAllTools: vi.fn().mockReturnValue([{ toolName: "read" }]),
212
193
  });
213
194
  const event = {
@@ -229,8 +210,11 @@ describe("handleToolCall — skill-read gate", () => {
229
210
  normalizedLocation: "/skills/librarian/SKILL.md",
230
211
  normalizedBaseDir: "/skills/librarian",
231
212
  };
213
+ const session = makeSession({
214
+ getActiveSkillEntries: vi.fn().mockReturnValue([skillEntry]),
215
+ });
232
216
  const deps = makeDeps({
233
- session: makeSession({ activeSkillEntries: [skillEntry] }),
217
+ session,
234
218
  getAllTools: vi.fn().mockReturnValue([{ toolName: "read" }]),
235
219
  });
236
220
  const event = {
@@ -248,14 +232,11 @@ describe("handleToolCall — skill-read gate", () => {
248
232
 
249
233
  describe("handleToolCall — external-directory gate", () => {
250
234
  it("blocks a read of a path outside cwd when policy is deny", async () => {
235
+ const session = makeSession({
236
+ checkPermission: vi.fn().mockReturnValue(makePermissionResult("deny")),
237
+ });
251
238
  const deps = makeDeps({
252
- session: makeSession({
253
- permissionManager: {
254
- checkPermission: vi
255
- .fn()
256
- .mockReturnValue(makePermissionResult("deny")),
257
- } as unknown as SessionState["permissionManager"],
258
- }),
239
+ session,
259
240
  getAllTools: vi.fn().mockReturnValue([{ name: "read" }]),
260
241
  });
261
242
  const event = {
@@ -273,14 +254,11 @@ describe("handleToolCall — external-directory gate", () => {
273
254
 
274
255
  describe("handleToolCall — bash external-directory gate", () => {
275
256
  it("blocks a bash command referencing an external path when policy is deny", async () => {
257
+ const session = makeSession({
258
+ checkPermission: vi.fn().mockReturnValue(makePermissionResult("deny")),
259
+ });
276
260
  const deps = makeDeps({
277
- session: makeSession({
278
- permissionManager: {
279
- checkPermission: vi
280
- .fn()
281
- .mockReturnValue(makePermissionResult("deny")),
282
- } as unknown as SessionState["permissionManager"],
283
- }),
261
+ session,
284
262
  getAllTools: vi.fn().mockReturnValue([{ name: "bash" }]),
285
263
  });
286
264
  const event = {