Skip to content

[NEEDS GROOMING] Build execution profiles UI (Read Only / Ask Every Time / Auto Approve) since pi-coding-agent has no built-in permission-mode system #133

Description

@tbrandenburg

Background

Follow-up to #132 (re-enabling pi-coding-agent's full built-in tools). #132 accepts "no approval gate" as an interim tradeoff for a 1-day config flip. This issue tracks building a real, user-facing permission/execution-profile system on top of that.

Confirmed (exhaustive research, see #132) that pi-coding-agent deliberately does not ship any named permission-mode concept. Straight from its README:

"No permission popups. Run in a container, or build your own confirmation flow with extensions..." (node_modules/@earendil-works/pi-coding-agent/README.md:499)
"No plan mode. Write plans to files, or build it with extensions, or install a package." (README.md:501)

So there is nothing like Claude Code's default/acceptEdits/bypassPermissions/plan modes to adopt as-is — pi-desktop needs to build its own "execution profiles" concept on top of pi-coding-agent's lower-level primitives, and expose it in the UI.

Available primitives (all confirmed to exist)

  1. Tool allow/deny-lists on CreateAgentSessionOptions (dist/core/sdk.d.ts:10-46): tools?: string[], excludeTools?: string[], noTools?: "all" | "builtin", plus a ready-made createReadOnlyTools() factory. Runtime-live equivalent: ExtensionAPI.getActiveTools() / setActiveTools(toolNames) (dist/core/extensions/types.d.ts:933,937).
  2. tool_call extension event (dist/core/extensions/types.d.ts:648-778) — fires before every bash/read/edit/write/grep/find/ls/custom tool call. Handler can return { block: true, reason } to veto, or mutate event.input in place before execution. Wired internally by AgentSession (core/agent-session.js:214-259) regardless of trust status — a separate mechanism from the per-package install-time trust gate (fix(packages): share PackageService with real ~/.pi/agent + close trust-gate bypass #107-refactor(packages): replace per-package trust gate with install-time consent #110).
  3. ctx.ui.confirm / ctx.ui.select (dist/core/extensions/types.d.ts:71-72,399) — interactive confirmation primitives used by pi's own CLI/TUI extensions. These are TUI-specific and not usable directly in pi-desktop per architecture rule fix: distinct artifact names for Windows nsis/portable targets #4 (renderer never talks to Node/Pi APIs directly) — pi-desktop needs its own IPC-driven equivalent instead.
  4. Reference implementations already exist in pi-coding-agent's own examples/extensions/, worth reading directly as a starting template:
    • examples/extensions/permission-gate.ts — regex-detects dangerous bash commands (rm -rf, sudo, chmod/chown 777) and confirms via ctx.ui.select before allowing.
    • examples/extensions/plan-mode/index.ts — full read-only-exploration-mode pattern: toggles getActiveTools()/setActiveTools() and blocks non-allowlisted bash commands via tool_call.

Proposed execution profiles

Profile Implementation
Read Only excludeTools: ["bash","edit","write"] (or createReadOnlyTools()); no tool_call handler needed.
Ask Every Time Full built-ins + an inline tool_call handler that blocks execution until an IPC round-trip to a renderer confirmation dialog resolves (approve/deny), modeled on permission-gate.ts.
Auto Approve (a.k.a. "skip permissions") Full built-ins, no tool_call handler at all — current end state of #132.
Plan Mode (optional/bonus) Reuse the plan-mode example's pattern: start read-only for exploration, toggle to full tools only once the user explicitly promotes the session to "execute".

What needs to change

  1. src/main/agent/runtime.ts

    • Add an execution-profile parameter to AgentRuntime/its run() method (or read from settings), mapping each profile to the right tools/excludeTools/noTools combination on createAgentSession(...).
    • For "Ask Every Time", register an inline tool_call extension handler via DefaultResourceLoaderOptions.extensionFactories (the same seam already used for additionalExtensionPaths in buildAdditionalPathsResourceLoader()), that pauses execution and awaits an IPC-driven approval from the renderer before resolving { block }.
  2. New IPC channel(s) (following the <domain>:<verb> convention, docs/INITIAL.md/AGENTS.md "Adding an IPC channel" recipe):

    • src/shared/events.ts — add method signature(s), e.g. tool:confirm (main → renderer request) and its response shape, plus a settings-facing settings:getExecutionProfile / settings:setExecutionProfile pair.
    • src/preload/index.ts — expose the new methods on api.
    • src/main/ipc.ts — wire the handler(s); the tool:confirm flow will need to be a webContents.send + one-shot response channel (main-initiated, not renderer-invoked), since it's the main process asking the renderer for a decision mid-tool-call.
    • src/renderer/lib/fake-desktop-api.ts — update the in-memory fake so the browser dev harness keeps working (per repo convention).
  3. Renderer UI

    • A profile selector (e.g. in Settings or a per-conversation control) persisted via the settings store, following the existing SettingsStore/Sidebar.tsx component conventions (flat file under src/renderer/components/, styled via the single shared styles.css).
    • A confirmation dialog component for "Ask Every Time" mode, showing the tool name + event.input (command/path/content) with Approve/Deny actions, wired to resolve the pending tool:confirm IPC request.
  4. Persistence

  5. Docs

    • docs/adr/0001-reuse-pi-extension-mechanism.md — document the new tool-permission architecture (profiles, the tool_call handler mechanism, IPC confirmation flow) once implemented, superseding the "no approval gate" interim note added by Re-enable pi-coding-agent's full built-in tools (bash/edit/write/read/list), remove read-only-only scope #132.
    • STATUS.md — new milestone entry.
    • AGENTS.md — update "Adding an IPC channel" section if the confirm-dialog pattern introduces a new recipe worth documenting (main-initiated request/response over IPC is a new pattern not covered by the existing invoke-based recipe).

Testing

  • Unit test the profile → createAgentSession option mapping (no real network/tool execution).
  • Unit/integration test the tool_call handler's block/allow logic independent of the UI (given a fake confirm resolver).
  • E2E: verify via the fake-desktop-api.ts browser harness that switching profiles changes available tools, and that "Ask Every Time" actually surfaces a confirmation dialog before a tool call event is shown in the timeline.

Acceptance criteria

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions