@hank-warren/pi-auto-permissions 0.5.1 → 0.6.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/README.md +1 -1
- package/index.ts +66 -4
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -143,7 +143,7 @@ The guardian must return one of three decisions:
|
|
|
143
143
|
|
|
144
144
|
- `approve`: execute the command
|
|
145
145
|
- `revise`: block it and tell the main agent what to correct
|
|
146
|
-
- `ask_user`: open
|
|
146
|
+
- `ask_user`: open an approval prompt (rendered with [`@hank-warren/pi-permission-selector`](../pi-permission-selector)'s `OptionSelector`): numbered options with `1`–`9` hotkeys, Tab to attach a note that is delivered to the agent as a steering user message, Esc to cancel — which blocks the command
|
|
147
147
|
|
|
148
148
|
## Conversation context and caching
|
|
149
149
|
|
package/index.ts
CHANGED
|
@@ -37,6 +37,7 @@ import {
|
|
|
37
37
|
type ReviewEvidenceRecord,
|
|
38
38
|
} from "./review.js";
|
|
39
39
|
import { mergeOverrideEvidence, type PermissionOverride } from "./override-evidence.js";
|
|
40
|
+
import { OptionSelector } from "@hank-warren/pi-permission-selector/selector.ts";
|
|
40
41
|
|
|
41
42
|
const WIDGET_KEY = "auto-permissions";
|
|
42
43
|
const PROJECT_CONFIG_DIR_NAME = (PiCodingAgent as { CONFIG_DIR_NAME?: string }).CONFIG_DIR_NAME ?? ".pi";
|
|
@@ -653,6 +654,61 @@ export default function autoPermissionsExtension(pi: ExtensionAPI) {
|
|
|
653
654
|
}
|
|
654
655
|
}
|
|
655
656
|
|
|
657
|
+
/**
|
|
658
|
+
* Render an approval prompt with the shared `OptionSelector` through
|
|
659
|
+
* `ctx.ui.custom()` (non-overlay, so it swaps into the editor area exactly
|
|
660
|
+
* where `ctx.ui.select` used to render).
|
|
661
|
+
*
|
|
662
|
+
* Cancellation parity with `ctx.ui.select` — all of these resolve
|
|
663
|
+
* `undefined`, which every caller must treat as deny/cancel, never allow:
|
|
664
|
+
* - Esc (`OptionSelector.onCancel`)
|
|
665
|
+
* - `signal` abort (listener calls `done(undefined)`; pi's `done` is
|
|
666
|
+
* idempotent and performs its own teardown, so nothing else is needed)
|
|
667
|
+
* - a host that reports `hasUI` but cannot render custom components
|
|
668
|
+
*
|
|
669
|
+
* A Tab-typed note is delivered to the agent as a steering user message,
|
|
670
|
+
* matching what the retired `ExtensionSelectorComponent` monkey patch in
|
|
671
|
+
* pi-permission-selector did.
|
|
672
|
+
*/
|
|
673
|
+
function promptSelect(
|
|
674
|
+
ctx: ExtensionContext,
|
|
675
|
+
title: string,
|
|
676
|
+
values: string[],
|
|
677
|
+
signal: AbortSignal,
|
|
678
|
+
opts: { allowComment: boolean },
|
|
679
|
+
): Promise<string | undefined> {
|
|
680
|
+
return ctx.ui.custom<string | undefined>((tui, theme, _keybindings, done) => {
|
|
681
|
+
const onAbort = () => finish(undefined);
|
|
682
|
+
const finish = (result: string | undefined) => {
|
|
683
|
+
signal.removeEventListener("abort", onAbort);
|
|
684
|
+
done(result);
|
|
685
|
+
};
|
|
686
|
+
const selector = new OptionSelector({
|
|
687
|
+
title,
|
|
688
|
+
options: values.map((value) => ({ value, label: value })),
|
|
689
|
+
allowComment: opts.allowComment,
|
|
690
|
+
theme,
|
|
691
|
+
onSelect: (option, comment) => {
|
|
692
|
+
if (comment) {
|
|
693
|
+
try {
|
|
694
|
+
pi.sendUserMessage(comment, { deliverAs: "steer" });
|
|
695
|
+
} catch {
|
|
696
|
+
// Never let note delivery break the approval flow.
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
finish(option.value);
|
|
700
|
+
},
|
|
701
|
+
onCancel: () => finish(undefined),
|
|
702
|
+
requestRender: () => tui.requestRender(),
|
|
703
|
+
});
|
|
704
|
+
// `done` before the factory resolves is safe: pi marks the dialog closed
|
|
705
|
+
// and never mounts the component.
|
|
706
|
+
if (signal.aborted) onAbort();
|
|
707
|
+
else signal.addEventListener("abort", onAbort, { once: true });
|
|
708
|
+
return selector;
|
|
709
|
+
});
|
|
710
|
+
}
|
|
711
|
+
|
|
656
712
|
async function askUser(
|
|
657
713
|
gate: Gate,
|
|
658
714
|
command: string,
|
|
@@ -695,10 +751,12 @@ export default function autoPermissionsExtension(pi: ExtensionAPI) {
|
|
|
695
751
|
try {
|
|
696
752
|
let choice: string | undefined;
|
|
697
753
|
try {
|
|
698
|
-
choice = await
|
|
754
|
+
choice = await promptSelect(
|
|
755
|
+
ctx,
|
|
699
756
|
`${gate.label} — Auto Permissions needs approval\n\n${detail}\n\n${command}`,
|
|
700
757
|
permissionPromptOptions(config.evaluationLog.enabled),
|
|
701
|
-
|
|
758
|
+
promptSignal,
|
|
759
|
+
{ allowComment: true },
|
|
702
760
|
);
|
|
703
761
|
} catch (error) {
|
|
704
762
|
if (!lifecycleStale() && !reviewCancelled(signal)) throw error;
|
|
@@ -879,10 +937,14 @@ export default function autoPermissionsExtension(pi: ExtensionAPI) {
|
|
|
879
937
|
try {
|
|
880
938
|
let choice: string | undefined;
|
|
881
939
|
try {
|
|
882
|
-
|
|
940
|
+
// The override prompt never had Tab-to-comment (the monkey patch only
|
|
941
|
+
// enabled it on titles matching /needs approval/i), so keep parity.
|
|
942
|
+
choice = await promptSelect(
|
|
943
|
+
ctx,
|
|
883
944
|
`Convention override: ${gate.label}\n\n${params.reason}\n\n${params.command}`,
|
|
884
945
|
["Allow for this session", "Keep blocked"],
|
|
885
|
-
|
|
946
|
+
promptSignal,
|
|
947
|
+
{ allowComment: false },
|
|
886
948
|
);
|
|
887
949
|
} catch (error) {
|
|
888
950
|
if (!lifecycleStale() && !reviewCancelled(signal)) throw error;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hank-warren/pi-auto-permissions",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Fork of @ogulcancelik/pi-auto-permissions with dialog-answer user evidence: context-aware Bash permissions for Pi with automated guardian review.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -51,6 +51,9 @@
|
|
|
51
51
|
"README.md",
|
|
52
52
|
"LICENSE"
|
|
53
53
|
],
|
|
54
|
+
"dependencies": {
|
|
55
|
+
"@hank-warren/pi-permission-selector": "^1.0.0"
|
|
56
|
+
},
|
|
54
57
|
"peerDependencies": {
|
|
55
58
|
"@earendil-works/pi-ai": "*",
|
|
56
59
|
"@earendil-works/pi-coding-agent": "*",
|