@gotgenes/pi-permission-system 7.3.1 → 7.3.2

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 CHANGED
@@ -5,6 +5,13 @@ 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
+ ## [7.3.2](https://github.com/gotgenes/pi-packages/compare/pi-permission-system-v7.3.1...pi-permission-system-v7.3.2) (2026-05-27)
9
+
10
+
11
+ ### Documentation
12
+
13
+ * replace \n with <br/> in Mermaid node labels ([3312a45](https://github.com/gotgenes/pi-packages/commit/3312a4559100cf9ae923f67819653b5a99fceb12))
14
+
8
15
  ## [7.3.1](https://github.com/gotgenes/pi-packages/compare/pi-permission-system-v7.3.0...pi-permission-system-v7.3.1) (2026-05-26)
9
16
 
10
17
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gotgenes/pi-permission-system",
3
- "version": "7.3.1",
3
+ "version": "7.3.2",
4
4
  "description": "Permission enforcement extension for the Pi coding agent.",
5
5
  "type": "module",
6
6
  "exports": {
@@ -41,7 +41,6 @@ export function shouldExposeTool(
41
41
  */
42
42
  export class AgentPrepHandler {
43
43
  constructor(
44
- // biome-ignore lint/correctness/noUnusedPrivateClassMembers: accessed via destructuring (const { session } = this)
45
44
  private readonly session: PermissionSession,
46
45
  private readonly toolRegistry: ToolRegistry,
47
46
  ) {}
@@ -51,11 +50,10 @@ export class AgentPrepHandler {
51
50
  event: BeforeAgentStartPayload,
52
51
  ctx: ExtensionContext,
53
52
  ): Promise<BeforeAgentStartEventResult> {
54
- const { session } = this;
55
- session.activate(ctx);
56
- session.refreshConfig(ctx);
53
+ this.session.activate(ctx);
54
+ this.session.refreshConfig(ctx);
57
55
 
58
- const agentName = session.resolveAgentName(ctx, event.systemPrompt);
56
+ const agentName = this.session.resolveAgentName(ctx, event.systemPrompt);
59
57
  const allTools = this.toolRegistry.getAll();
60
58
  const allowedTools: string[] = [];
61
59
 
@@ -66,7 +64,7 @@ export class AgentPrepHandler {
66
64
  }
67
65
  if (
68
66
  shouldExposeTool(toolName, agentName, (t, a) =>
69
- session.getToolPermission(t, a),
67
+ this.session.getToolPermission(t, a),
70
68
  )
71
69
  ) {
72
70
  allowedTools.push(toolName);
@@ -74,24 +72,24 @@ export class AgentPrepHandler {
74
72
  }
75
73
 
76
74
  const activeToolsCacheKey = createActiveToolsCacheKey(allowedTools);
77
- if (session.shouldUpdateActiveTools(activeToolsCacheKey)) {
75
+ if (this.session.shouldUpdateActiveTools(activeToolsCacheKey)) {
78
76
  this.toolRegistry.setActive(allowedTools);
79
- session.commitActiveToolsCacheKey(activeToolsCacheKey);
77
+ this.session.commitActiveToolsCacheKey(activeToolsCacheKey);
80
78
  }
81
79
 
82
80
  const promptStateCacheKey = createBeforeAgentStartPromptStateKey({
83
81
  agentName,
84
82
  cwd: ctx.cwd,
85
- permissionStamp: session.getPolicyCacheStamp(agentName ?? undefined),
83
+ permissionStamp: this.session.getPolicyCacheStamp(agentName ?? undefined),
86
84
  systemPrompt: event.systemPrompt,
87
85
  allowedToolNames: allowedTools,
88
86
  });
89
87
 
90
- if (!session.shouldUpdatePromptState(promptStateCacheKey)) {
88
+ if (!this.session.shouldUpdatePromptState(promptStateCacheKey)) {
91
89
  return {};
92
90
  }
93
91
 
94
- session.commitPromptStateCacheKey(promptStateCacheKey);
92
+ this.session.commitPromptStateCacheKey(promptStateCacheKey);
95
93
 
96
94
  const toolPromptResult = sanitizeAvailableToolsSection(
97
95
  event.systemPrompt,
@@ -99,11 +97,11 @@ export class AgentPrepHandler {
99
97
  );
100
98
  const skillPromptResult = resolveSkillPromptEntries(
101
99
  toolPromptResult.prompt,
102
- session,
100
+ this.session,
103
101
  agentName,
104
102
  ctx.cwd,
105
103
  );
106
- session.setActiveSkillEntries(skillPromptResult.entries);
104
+ this.session.setActiveSkillEntries(skillPromptResult.entries);
107
105
 
108
106
  if (skillPromptResult.prompt !== event.systemPrompt) {
109
107
  return { systemPrompt: skillPromptResult.prompt };
@@ -22,7 +22,6 @@ interface ResourcesDiscoverPayload {
22
22
  */
23
23
  export class SessionLifecycleHandler {
24
24
  constructor(
25
- // biome-ignore lint/correctness/noUnusedPrivateClassMembers: accessed via destructuring (const { session } = this)
26
25
  private readonly session: PermissionSession,
27
26
  private readonly cleanupRpc: () => void,
28
27
  ) {}
@@ -31,19 +30,18 @@ export class SessionLifecycleHandler {
31
30
  event: SessionStartPayload,
32
31
  ctx: ExtensionContext,
33
32
  ): Promise<void> {
34
- const { session } = this;
35
- session.refreshConfig(ctx);
36
- session.resetForNewSession(ctx);
37
- session.logResolvedConfigPaths();
33
+ this.session.refreshConfig(ctx);
34
+ this.session.resetForNewSession(ctx);
35
+ this.session.logResolvedConfigPaths();
38
36
 
39
- const agentName = session.resolveAgentName(ctx);
40
- const policyIssues = session.getConfigIssues(agentName ?? undefined);
37
+ const agentName = this.session.resolveAgentName(ctx);
38
+ const policyIssues = this.session.getConfigIssues(agentName ?? undefined);
41
39
  for (const issue of policyIssues) {
42
- session.logger.warn(issue);
40
+ this.session.logger.warn(issue);
43
41
  }
44
42
 
45
43
  if (event.reason === "reload") {
46
- session.logger.debug("lifecycle.reload", {
44
+ this.session.logger.debug("lifecycle.reload", {
47
45
  triggeredBy: "session_start",
48
46
  reason: event.reason,
49
47
  cwd: ctx.cwd,
@@ -57,23 +55,21 @@ export class SessionLifecycleHandler {
57
55
  return Promise.resolve();
58
56
  }
59
57
 
60
- const { session } = this;
61
- session.reload();
62
- session.logger.debug("lifecycle.reload", {
58
+ this.session.reload();
59
+ this.session.logger.debug("lifecycle.reload", {
63
60
  triggeredBy: "resources_discover",
64
61
  reason: event.reason,
65
- cwd: session.getRuntimeContext()?.cwd ?? null,
62
+ cwd: this.session.getRuntimeContext()?.cwd ?? null,
66
63
  });
67
64
  return Promise.resolve();
68
65
  }
69
66
 
70
67
  handleSessionShutdown(): Promise<void> {
71
- const { session } = this;
72
- const ctx = session.getRuntimeContext();
68
+ const ctx = this.session.getRuntimeContext();
73
69
  if (ctx) {
74
70
  ctx.ui.setStatus(PERMISSION_SYSTEM_STATUS_KEY, undefined);
75
71
  }
76
- session.shutdown();
72
+ this.session.shutdown();
77
73
  this.cleanupRpc();
78
74
  return Promise.resolve();
79
75
  }
@@ -47,7 +47,6 @@ interface InputPayload {
47
47
  */
48
48
  export class PermissionGateHandler {
49
49
  constructor(
50
- // biome-ignore lint/correctness/noUnusedPrivateClassMembers: accessed via destructuring (const { session } = this)
51
50
  private readonly session: PermissionSession,
52
51
  private readonly events: PermissionEventBus,
53
52
  private readonly toolRegistry: ToolRegistry,
@@ -57,10 +56,9 @@ export class PermissionGateHandler {
57
56
  event: unknown,
58
57
  ctx: ExtensionContext,
59
58
  ): Promise<{ block?: true; reason?: string }> {
60
- const { session } = this;
61
- session.activate(ctx);
59
+ this.session.activate(ctx);
62
60
 
63
- const agentName = session.resolveAgentName(ctx);
61
+ const agentName = this.session.resolveAgentName(ctx);
64
62
  const toolName = getToolNameFromValue(event);
65
63
 
66
64
  if (!toolName) {
@@ -100,22 +98,22 @@ export class PermissionGateHandler {
100
98
  };
101
99
 
102
100
  // ── Shared gate adapter closures ─────────────────────────────────────
103
- const canConfirm = () => session.canPrompt(ctx);
101
+ const canConfirm = () => this.session.canPrompt(ctx);
104
102
  const promptPermission = (details: PromptPermissionDetails) =>
105
- session.prompt(ctx, details);
103
+ this.session.prompt(ctx, details);
106
104
  const emitDecision: GateRunnerDeps["emitDecision"] = (e) =>
107
105
  emitDecisionEvent(this.events, e);
108
106
  // eslint-disable-next-line @typescript-eslint/unbound-method -- logger.review is a plain function closure; no this-binding issue
109
- const writeReviewLog = session.logger.review;
107
+ const writeReviewLog = this.session.logger.review;
110
108
  const checkPermission: GateRunnerDeps["checkPermission"] = (
111
109
  surface,
112
110
  input,
113
111
  agent,
114
112
  sessionRules,
115
- ) => session.checkPermission(surface, input, agent, sessionRules);
116
- const getSessionRuleset = () => session.getSessionRuleset();
113
+ ) => this.session.checkPermission(surface, input, agent, sessionRules);
114
+ const getSessionRuleset = () => this.session.getSessionRuleset();
117
115
  const approveSessionRule = (surface: string, pattern: string) =>
118
- session.approveSessionRule(surface, pattern);
116
+ this.session.approveSessionRule(surface, pattern);
119
117
 
120
118
  // ── Shared runner deps (built once, reused for all gates) ────────────
121
119
  const runnerDeps: GateRunnerDeps = {
@@ -130,7 +128,7 @@ export class PermissionGateHandler {
130
128
 
131
129
  // ── Skill-read gate (descriptor + runner) ───────────────────────────────
132
130
  const skillDescriptor = describeSkillReadGate(tcc, () =>
133
- session.getActiveSkillEntries(),
131
+ this.session.getActiveSkillEntries(),
134
132
  );
135
133
  if (skillDescriptor) {
136
134
  const skillResult = await runGateCheck(
@@ -166,8 +164,8 @@ export class PermissionGateHandler {
166
164
 
167
165
  // ── External-directory gate (descriptor + runner) ────────────────────────
168
166
  const infraDirs = [
169
- ...session.getInfrastructureDirs(),
170
- ...session.getInfrastructureReadPaths(),
167
+ ...this.session.getInfrastructureDirs(),
168
+ ...this.session.getInfrastructureReadPaths(),
171
169
  ];
172
170
  const extDirDesc = describeExternalDirectoryGate(tcc, infraDirs);
173
171
  if (extDirDesc) {
@@ -265,16 +263,15 @@ export class PermissionGateHandler {
265
263
  event: InputPayload,
266
264
  ctx: ExtensionContext,
267
265
  ): Promise<InputEventResult> {
268
- const { session } = this;
269
- session.activate(ctx);
266
+ this.session.activate(ctx);
270
267
 
271
268
  const skillName = extractSkillNameFromInput(event.text);
272
269
  if (!skillName) {
273
270
  return { action: "continue" };
274
271
  }
275
272
 
276
- const agentName = session.resolveAgentName(ctx);
277
- const check = session.checkPermission(
273
+ const agentName = this.session.resolveAgentName(ctx);
274
+ const check = this.session.checkPermission(
278
275
  "skill",
279
276
  { name: skillName },
280
277
  agentName ?? undefined,
@@ -291,14 +288,14 @@ export class PermissionGateHandler {
291
288
  skillName,
292
289
  agentName ?? undefined,
293
290
  );
294
- const skillInputCanConfirm = session.canPrompt(ctx);
291
+ const skillInputCanConfirm = this.session.canPrompt(ctx);
295
292
  let skillInputAutoApproved = false;
296
293
  const skillInputGate = await applyPermissionGate({
297
294
  state: check.state,
298
295
  canConfirm: skillInputCanConfirm,
299
296
  promptForApproval: async () => {
300
- const decision = await session.prompt(ctx, {
301
- requestId: session.createPermissionRequestId("skill-input"),
297
+ const decision = await this.session.prompt(ctx, {
298
+ requestId: this.session.createPermissionRequestId("skill-input"),
302
299
  source: "skill_input",
303
300
  agentName,
304
301
  message: skillInputMessage,
@@ -308,7 +305,7 @@ export class PermissionGateHandler {
308
305
  return decision;
309
306
  },
310
307
  // eslint-disable-next-line @typescript-eslint/unbound-method -- logger.review is a plain function closure; no this-binding issue
311
- writeLog: session.logger.review,
308
+ writeLog: this.session.logger.review,
312
309
  logContext: {
313
310
  source: "skill_input",
314
311
  skillName,