@gotgenes/pi-permission-system 23.0.2 → 23.0.3
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 +12 -0
- package/README.md +1 -0
- package/docs/configuration.md +4 -0
- package/package.json +1 -1
- package/src/authority/permission-prompt-component.ts +36 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,18 @@ 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
|
+
## [23.0.3](https://github.com/gotgenes/pi-packages/compare/pi-permission-system-v23.0.2...pi-permission-system-v23.0.3) (2026-07-26)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* **pi-permission-system:** preserve tool expansion in inline permission prompts ([6a0d241](https://github.com/gotgenes/pi-packages/commit/6a0d241291f8eefa51493b683e12514a83f295bd))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Documentation
|
|
17
|
+
|
|
18
|
+
* **pi-permission-system:** document tool expansion during permission prompts ([f4098d3](https://github.com/gotgenes/pi-packages/commit/f4098d331efc72538ee3836ffb4056beee8cbed0))
|
|
19
|
+
|
|
8
20
|
## [23.0.2](https://github.com/gotgenes/pi-packages/compare/pi-permission-system-v23.0.1...pi-permission-system-v23.0.2) (2026-07-26)
|
|
9
21
|
|
|
10
22
|
|
package/README.md
CHANGED
|
@@ -66,6 +66,7 @@ All permissions use one of three states:
|
|
|
66
66
|
|
|
67
67
|
When the dialog prompts, you can approve once or approve a pattern for the rest of the session.
|
|
68
68
|
In an interactive TUI session the prompt is an inline keybind dialog — `y` approve, `s` approve for this session, `n` deny, `r` deny with a reason — where each hotkey arms and a second press confirms (configurable via `doublePressToConfirm`).
|
|
69
|
+
Pi's tool-expansion binding (`app.tools.expand`, `Ctrl+O` by default) keeps working while the dialog is open, so you can expand a truncated tool preview before deciding.
|
|
69
70
|
See [docs/configuration.md](docs/configuration.md#inline-permission-dialog-tui) for the hotkeys and [docs/session-approvals.md](docs/session-approvals.md) for session-scoped rules and pattern suggestions.
|
|
70
71
|
|
|
71
72
|
The `path` surface is a cross-cutting gate that applies to **all** file access — Pi tools, bash commands, MCP calls, and extension tools alike.
|
package/docs/configuration.md
CHANGED
|
@@ -127,6 +127,10 @@ Arrow keys / `j`/`k` move the highlight, `enter` confirms the highlighted option
|
|
|
127
127
|
With `doublePressToConfirm` enabled (the default), a letter hotkey **arms** its action and shows a `Press y again to approve.` hint; press the same key again to commit.
|
|
128
128
|
Set `doublePressToConfirm` to `false` to commit on the first press.
|
|
129
129
|
|
|
130
|
+
Pi's tool-expansion binding (`app.tools.expand`, `Ctrl+O` by default) stays live while the dialog is open, so you can expand a truncated tool preview before deciding.
|
|
131
|
+
It only toggles the display — it never resolves, commits, or arms the pending decision.
|
|
132
|
+
While you are typing a denial reason it is not intercepted, so a rebound printable key still reaches the reason editor.
|
|
133
|
+
|
|
130
134
|
Non-TUI contexts (RPC / frontend-driven sessions) keep the single-select prompt and are unaffected by `doublePressToConfirm`.
|
|
131
135
|
|
|
132
136
|
### `piInfrastructureReadPaths` patterns
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
ExtensionContext,
|
|
3
3
|
ExtensionUIContext,
|
|
4
|
+
KeybindingsManager,
|
|
4
5
|
} from "@earendil-works/pi-coding-agent";
|
|
5
6
|
import {
|
|
6
7
|
type Component,
|
|
@@ -35,9 +36,12 @@ import {
|
|
|
35
36
|
/** The subset of the session UI surface the inline dialog needs. */
|
|
36
37
|
export type PermissionPromptUi = Pick<
|
|
37
38
|
ExtensionUIContext,
|
|
38
|
-
"select" | "input" | "custom"
|
|
39
|
+
"select" | "input" | "custom" | "getToolsExpanded" | "setToolsExpanded"
|
|
39
40
|
>;
|
|
40
41
|
|
|
42
|
+
/** The keybindings surface the dialog consults; only `matches` is read (ISP). */
|
|
43
|
+
type PromptKeybindings = Pick<KeybindingsManager, "matches">;
|
|
44
|
+
|
|
41
45
|
/** The resolved presentation context selected once per activation. */
|
|
42
46
|
export interface PermissionPromptView {
|
|
43
47
|
mode: ExtensionContext["mode"];
|
|
@@ -97,12 +101,13 @@ export function presentInlinePermissionPrompt(
|
|
|
97
101
|
sessionScope: options?.sessionScope,
|
|
98
102
|
};
|
|
99
103
|
return view.ui.custom<PermissionPromptDecision>(
|
|
100
|
-
(tui, theme,
|
|
104
|
+
(tui, theme, keybindings, done) =>
|
|
101
105
|
new PermissionPromptComponent(
|
|
102
106
|
theme,
|
|
103
107
|
config,
|
|
104
108
|
title,
|
|
105
109
|
message,
|
|
110
|
+
(data) => handleToolsExpandAction(data, keybindings, view.ui),
|
|
106
111
|
() => {
|
|
107
112
|
tui.requestRender();
|
|
108
113
|
},
|
|
@@ -112,6 +117,31 @@ export function presentInlinePermissionPrompt(
|
|
|
112
117
|
);
|
|
113
118
|
}
|
|
114
119
|
|
|
120
|
+
/**
|
|
121
|
+
* Forward Pi's tool-expansion action while the dialog holds keyboard focus.
|
|
122
|
+
*
|
|
123
|
+
* A focused `ctx.ui.custom` component consumes every keystroke, so `Ctrl+O`
|
|
124
|
+
* would otherwise be dead for the duration of an ask — exactly when the user
|
|
125
|
+
* most needs to see the full pending tool invocation. Returns `true` when the
|
|
126
|
+
* keystroke was the action (and was handled), so the caller stops before
|
|
127
|
+
* mapping it to a {@link PromptEvent}; expansion is a display concern and must
|
|
128
|
+
* never reach the decision model.
|
|
129
|
+
*
|
|
130
|
+
* Deliberately does not request a render: `setToolsExpanded` re-renders the
|
|
131
|
+
* host itself, and the dialog's own lines are unaffected by tool expansion.
|
|
132
|
+
*/
|
|
133
|
+
function handleToolsExpandAction(
|
|
134
|
+
data: string,
|
|
135
|
+
keybindings: PromptKeybindings,
|
|
136
|
+
ui: PermissionPromptUi,
|
|
137
|
+
): boolean {
|
|
138
|
+
if (!keybindings.matches(data, "app.tools.expand")) {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
ui.setToolsExpanded(!ui.getToolsExpanded());
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
|
|
115
145
|
class PermissionPromptComponent implements Component {
|
|
116
146
|
private state: PromptViewState;
|
|
117
147
|
private reasonBuffer = "";
|
|
@@ -121,6 +151,7 @@ class PermissionPromptComponent implements Component {
|
|
|
121
151
|
private readonly config: PromptModelConfig,
|
|
122
152
|
private readonly title: string,
|
|
123
153
|
private readonly message: string,
|
|
154
|
+
private readonly handleAppAction: (data: string) => boolean,
|
|
124
155
|
private readonly requestRender: () => void,
|
|
125
156
|
private readonly done: (decision: PermissionPromptDecision) => void,
|
|
126
157
|
) {
|
|
@@ -151,6 +182,9 @@ class PermissionPromptComponent implements Component {
|
|
|
151
182
|
this.handleReasonInput(data);
|
|
152
183
|
return;
|
|
153
184
|
}
|
|
185
|
+
if (this.handleAppAction(data)) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
154
188
|
const event = this.toEvent(data);
|
|
155
189
|
if (event) {
|
|
156
190
|
this.apply(event);
|