Skip to content

[FEATURE]: Plugins cannot raise a permission request in-process on v2 #52540

Open

Description

@ualtinok

Feature hasn't been suggested before.

  • I have verified this feature I'm about to request hasn't been suggested before.

Describe the enhancement you want to request

Plugins cannot raise a permission request in-process on v2.

Built-in tools ask through Permission.assert (packages/core/src/permission.ts:106), for example glob (packages/core/src/tool/plugin/glob.ts:68) calls it with { action, resources, save, metadata }. That gives them the native approval dialog, saved "always allow" rules, and the session's configured rules.

A plugin has no equivalent:

  • The plugin permission domain is Pick<PermissionApi, "list" | "get" | "reply"> & { hook } (packages/plugin/src/promise/permission.ts:22, same in effect/permission.ts:22). create exists on the full PermissionApi (packages/client/src/effect/api/api.ts:1876) and is served over HTTP, but it is not projected (packages/core/src/plugin/host.ts:404-424).
  • Tool.Context carries sessionID, agent, messageID, id and progress, plus signal on the promise API, but no ask or assert (packages/schema/src/tool.ts:14-20). v1's ToolContext.ask has no v2 counterpart.

So a plugin tool that touches files or runs commands has two options: skip the check, or find its own server and call POST /api/session/:sessionID/permission over HTTP. The second path depends on things a plugin cannot reliably know:

  • which server it is running in, when a TUI service and a separate opencode serve run side by side;
  • the server password, which is random unless set and is removed from the environment at startup;
  • a listening address at all, for headless launches.

The plugin is already running inside the host that owns the session, so none of this should be needed.

Proposed shape, smallest first:

  1. Add "create" to the plugin PermissionDomain Pick, mirroring how remove and compact were added to the session domain in feat(plugin): expose session removal #52387 and feat(plugin): expose session compaction #52385. The plugin then awaits permission.replied for effect: "ask".
  2. Preferably, also give Tool.Context an assert({ action, resources, metadata?, save? }) with the same semantics as the core Permission.assert: it resolves on allow and fails with the same blocked error on deny or reject. That matches what built-in tools do, keeps the call bound to the tool call's session and message, and needs no event handling in the plugin.

Option 2 also removes a race that option 1 leaves in place. With create, the plugin learns the decision from the permission.replied event, so a reply that arrives before the plugin's event subscription is reading is lost. A plugin author hit this on 2.0.11. assert returns the decision directly, so there is no subscription to miss.

Either keeps one permission engine. Rules, saved decisions and the approval UI stay the host's.

Related: #34957 (internal-only Tool.withPermission), #35364 (tool execution architecture), #49389 (session capabilities not projected to plugins, resolved in the same way).

Activity

  1. github-actions commented on Oct 1, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

    • #50584: Reports a V2 plugin/tool permission request failing because the host does not provide a permission request endpoint.
    • #37164: Requests a plugin capability to raise native permission approval requests during tool execution.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions