@gotgenes/pi-permission-system 10.7.0 → 10.7.1
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 +7 -0
- package/package.json +1 -1
- package/src/permission-prompts.ts +8 -1
- package/test/permission-prompts.test.ts +67 -0
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
|
+
## [10.7.1](https://github.com/gotgenes/pi-packages/compare/pi-permission-system-v10.7.0...pi-permission-system-v10.7.1) (2026-06-09)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* surface full chained command in bash permission prompt ([#333](https://github.com/gotgenes/pi-packages/issues/333)) ([7f448fb](https://github.com/gotgenes/pi-packages/commit/7f448fb6e394bc37f94c98e04332abdcc8528c46))
|
|
14
|
+
|
|
8
15
|
## [10.7.0](https://github.com/gotgenes/pi-packages/compare/pi-permission-system-v10.6.0...pi-permission-system-v10.7.0) (2026-06-09)
|
|
9
16
|
|
|
10
17
|
|
package/package.json
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getNonEmptyString, toRecord } from "./common";
|
|
1
2
|
import { matchQualifier } from "./denial-messages";
|
|
2
3
|
import type { SkillPromptEntry } from "./skill-prompt-sanitizer";
|
|
3
4
|
import type { ToolPreviewFormatter } from "./tool-preview-formatter";
|
|
@@ -37,12 +38,18 @@ export function formatAskPrompt(
|
|
|
37
38
|
const subject = agentName ? `Agent '${agentName}'` : "Current agent";
|
|
38
39
|
|
|
39
40
|
if (result.toolName === "bash") {
|
|
41
|
+
const subCommand = result.command ?? "";
|
|
40
42
|
const qualifier = matchQualifier(
|
|
41
43
|
result.matchedPattern,
|
|
42
44
|
result.commandContext,
|
|
43
45
|
);
|
|
44
46
|
const qualifierInfo = qualifier ? ` ${qualifier}` : "";
|
|
45
|
-
|
|
47
|
+
const fullCommand = getNonEmptyString(toRecord(input).command);
|
|
48
|
+
const fullCommandInfo =
|
|
49
|
+
fullCommand && fullCommand !== subCommand
|
|
50
|
+
? ` (full command: '${fullCommand}')`
|
|
51
|
+
: "";
|
|
52
|
+
return `${subject} requested bash command '${subCommand}'${qualifierInfo}${fullCommandInfo}. Allow this command?`;
|
|
46
53
|
}
|
|
47
54
|
|
|
48
55
|
if ((result.source === "mcp" || result.toolName === "mcp") && result.target) {
|
|
@@ -151,6 +151,73 @@ describe("formatAskPrompt", () => {
|
|
|
151
151
|
expect(result).toContain("matched 'git *'");
|
|
152
152
|
});
|
|
153
153
|
|
|
154
|
+
test("appends full command when input contains a chain that differs from the sub-command", () => {
|
|
155
|
+
const result = formatAskPrompt(
|
|
156
|
+
toolResult("bash", { command: "rm -rf ." }),
|
|
157
|
+
undefined,
|
|
158
|
+
{ command: 'echo "hello" && rm -rf .' },
|
|
159
|
+
makeFormatter(),
|
|
160
|
+
);
|
|
161
|
+
expect(result).toBe(
|
|
162
|
+
`Current agent requested bash command 'rm -rf .' (full command: 'echo "hello" && rm -rf .'). Allow this command?`,
|
|
163
|
+
);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
test("suppresses full-command suffix when input command matches the sub-command (no chain)", () => {
|
|
167
|
+
const result = formatAskPrompt(
|
|
168
|
+
toolResult("bash", { command: "git push" }),
|
|
169
|
+
undefined,
|
|
170
|
+
{ command: "git push" },
|
|
171
|
+
makeFormatter(),
|
|
172
|
+
);
|
|
173
|
+
expect(result).not.toContain("full command:");
|
|
174
|
+
expect(result).toBe(
|
|
175
|
+
"Current agent requested bash command 'git push'. Allow this command?",
|
|
176
|
+
);
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
test("suppresses full-command suffix when input is undefined", () => {
|
|
180
|
+
const result = formatAskPrompt(
|
|
181
|
+
toolResult("bash", { command: "git push" }),
|
|
182
|
+
undefined,
|
|
183
|
+
undefined,
|
|
184
|
+
makeFormatter(),
|
|
185
|
+
);
|
|
186
|
+
expect(result).not.toContain("full command:");
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
test("suppresses full-command suffix when input has no command field", () => {
|
|
190
|
+
const result = formatAskPrompt(
|
|
191
|
+
toolResult("bash", { command: "git push" }),
|
|
192
|
+
undefined,
|
|
193
|
+
{ unrelated: "value" },
|
|
194
|
+
makeFormatter(),
|
|
195
|
+
);
|
|
196
|
+
expect(result).not.toContain("full command:");
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
test("suppresses full-command suffix when input command is empty", () => {
|
|
200
|
+
const result = formatAskPrompt(
|
|
201
|
+
toolResult("bash", { command: "git push" }),
|
|
202
|
+
undefined,
|
|
203
|
+
{ command: "" },
|
|
204
|
+
makeFormatter(),
|
|
205
|
+
);
|
|
206
|
+
expect(result).not.toContain("full command:");
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
test("places full-command suffix after the qualifier and before the terminal sentence", () => {
|
|
210
|
+
const result = formatAskPrompt(
|
|
211
|
+
toolResult("bash", { command: "rm -rf foo", matchedPattern: "rm *" }),
|
|
212
|
+
undefined,
|
|
213
|
+
{ command: "cd /tmp && rm -rf foo" },
|
|
214
|
+
makeFormatter(),
|
|
215
|
+
);
|
|
216
|
+
expect(result).toBe(
|
|
217
|
+
"Current agent requested bash command 'rm -rf foo' (matched 'rm *') (full command: 'cd /tmp && rm -rf foo'). Allow this command?",
|
|
218
|
+
);
|
|
219
|
+
});
|
|
220
|
+
|
|
154
221
|
test("formats bash prompt with nested execution context", () => {
|
|
155
222
|
const result = formatAskPrompt(
|
|
156
223
|
toolResult("bash", {
|