@hank-warren/pi-auto-permissions 0.5.1 → 0.6.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 ADDED
@@ -0,0 +1,30 @@
1
+ # @hank-warren/pi-auto-permissions
2
+
3
+ ## 0.6.1
4
+
5
+ ### Patch Changes
6
+
7
+ - cf12677: ship CHANGELOG.md in the published tarball
8
+ - Updated dependencies [cf12677]
9
+ - @hank-warren/pi-permission-selector@1.0.1
10
+
11
+ ## 0.6.0
12
+
13
+ ### Minor Changes
14
+
15
+ - 500fe67: Remove the `ExtensionSelectorComponent` monkey patch; compose `OptionSelector` explicitly (spec §9.4).
16
+
17
+ `pi-permission-selector` is now a **pure library**: it no longer registers an extension, patches nothing, and standalone installs do nothing — the reason for the major bump. `selector-patch.ts` and `index.ts` are deleted; `keys.ts` and `selector.ts` remain the frozen cross-package surface. Dialogs this repo does not own (pi's model/theme/session pickers, third-party extensions) revert to stock arrows+Enter, an accepted trade-off (spec §9.3): nothing here breaks when a pi upgrade changes selector internals.
18
+
19
+ `pi-auto-permissions` renders both of its prompts — the guardian approval prompt and the `request_override` prompt — through `ctx.ui.custom()` with the shared `OptionSelector` from `@hank-warren/pi-permission-selector` (a new plain dependency), instead of `ctx.ui.select` plus the global patch. Behavior is preserved: numbered options with `1`–`9` hotkeys, Tab-to-comment on the approval prompt (the note is still delivered as a steering user message, now by pi-auto-permissions itself), exact legacy option strings for `classifyPromptChoice`, and Herdr blocked-state bracketing. Cancellation semantics match `ctx.ui.select`: Esc, abort of the prompt signal, and a host that cannot render custom UI all resolve `undefined`, which every caller treats as deny/cancel — never allow.
20
+
21
+ ### Patch Changes
22
+
23
+ - Updated dependencies [500fe67]
24
+ - @hank-warren/pi-permission-selector@1.0.0
25
+
26
+ ## 0.5.1
27
+
28
+ ### Patch Changes
29
+
30
+ - 67abcf5: document the optional `HERDR_ENV` herdr pane blocked indicator
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 Pi's normal confirmation prompt
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 ctx.ui.select(
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
- { signal: promptSignal },
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
- choice = await ctx.ui.select(
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
- { signal: promptSignal },
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.5.1",
3
+ "version": "0.6.1",
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": [
@@ -49,8 +49,12 @@
49
49
  "usage-log.ts",
50
50
  "widget-status.ts",
51
51
  "README.md",
52
- "LICENSE"
52
+ "LICENSE",
53
+ "CHANGELOG.md"
53
54
  ],
55
+ "dependencies": {
56
+ "@hank-warren/pi-permission-selector": "^1.0.1"
57
+ },
54
58
  "peerDependencies": {
55
59
  "@earendil-works/pi-ai": "*",
56
60
  "@earendil-works/pi-coding-agent": "*",