feat(provider): add onPermissionRequest callback option#17
Merged
Conversation
Hosts can now intercept the agent's per-call permission requests with their own UI by passing onPermissionRequest to createAcpxProvider. Returning undefined falls through to the existing mode-based resolver, so existing consumers see no behavior change. Driven by downstream BrowserOS chat work that wants inline approve/deny CTA cards instead of an up-front mode gate. The mode gate is too coarse for that flow — approve-reads silently denies writes (codex's apply_patch aborts with no signal), approve-all skips approval entirely. The provider's job is plumbing only: pass the option through to createAcpRuntime, the runtime owns the wire-level resolution and decision-to-optionId mapping. - src/types.ts: re-export AcpPermissionRequest + AcpPermissionDecision from acpx/runtime; add onPermissionRequest to AcpxProviderSettings with the documented signature - src/provider.ts: thread the option through buildRuntimeOptions() - src/index.ts: re-export the two new types - README.md: replace the mode-only limitation bullet with a fall-through explanation; add a new Per-call permissions section with the full callback contract - test/unit/provider.test.ts: three tests covering callback forwarding, the omitted case, and the documented pre-built-runtime no-op - package.json: bump to 0.1.0; bump acpx peer-dep + dev-dep to >=0.8.0 to require the runtime release that exposes the callback Blocked on upstream openclaw/acpx#299 + a corresponding acpx release. Typecheck fails until then because the new types don't exist in acpx@0.7.0; runtime / lint / fallow / build / tests all green.
This was referenced May 7, 2026
Resolves conflicts: - packages/acpx-ai-provider/package.json: keep this branch's 0.1.0 bump (was 0.0.4 on main; this PR ships new public API). - packages/acpx-ai-provider/src/provider.ts: keep both changes — main's toRuntimeMcpServers() helper for type-safe mcpServers, AND this branch's onPermissionRequest pass-through. Resyncs bun.lock against acpx@0.8.0 (now published, gates the onPermissionRequest option this PR forwards).
… real codex Spawns a real codex-acp process and asserts the wire-level permission round-trip: the callback fires with a correctly-shaped request, and the agent honours reject_once, allow_once, and undefined fall-through. Gated behind SMOKE_AGENTS=codex so it stays out of CI.
There was a problem hiding this comment.
Pull request overview
Adds per-call permission callback support to acpx-ai-provider, forwarding onPermissionRequest into the underlying ACP runtime and documenting/testing the new host-interception flow.
Changes:
- Adds
onPermissionRequestto provider settings and exports the related permission request/decision types. - Threads the callback into runtime construction and documents per-call permissions.
- Bumps
acpxdependency requirements and adds unit/e2e coverage for callback forwarding and behavior.
Reviewed changes
Copilot reviewed 7 out of 8 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
packages/acpx-ai-provider/src/types.ts |
Adds callback option and permission type exports. |
packages/acpx-ai-provider/src/provider.ts |
Forwards the callback into AcpRuntimeOptions. |
packages/acpx-ai-provider/src/index.ts |
Re-exports new permission-related types. |
packages/acpx-ai-provider/README.md |
Documents per-call permission callback usage and fallback behavior. |
packages/acpx-ai-provider/package.json |
Bumps package and acpx dependency versions. |
bun.lock |
Updates locked acpx dependency metadata. |
packages/acpx-ai-provider/test/unit/provider.test.ts |
Adds unit tests for runtime option forwarding. |
packages/acpx-ai-provider/test/e2e/permission-callback.test.ts |
Adds opt-in Codex e2e permission callback contract tests. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Upstream: openclaw/acpx#299 — the runtime PR this provider change consumes.
Forwards
onPermissionRequestfromAcpxProviderSettingsinto the underlyingAcpRuntimeOptions, so hosts can intercept per-call permission requests with their own UI. Returningundefinedfrom the callback (or omitting it entirely) falls through to the existingpermissionModeresolver — zero behavior change for existing consumers.Driven by downstream BrowserOS chat work that wants inline approve/deny CTA cards instead of an up-front mode gate. The mode gate is too coarse for that flow —
approve-readssilently denies writes (codex'sapply_patchaborts with no signal),approve-allskips approval entirely. A per-call callback is the right primitive.What changed
package.json0.0.4→0.0.5.acpxpeer-dep + dev-dep raised to>=0.8.0(the upstream version that shipsonPermissionRequestonAcpRuntimeOptionsvia openclaw/acpx#299).src/types.tsAcpPermissionRequest+AcpPermissionDecisionfromacpx/runtime; addonPermissionRequesttoAcpxProviderSettingswith the documented signature and doc-comment.src/provider.tsbuildRuntimeOptions()(one line).src/index.tsREADME.md## Per-call permissionssection with the full callback contract.test/unit/provider.test.tsbun:testmock.module('acpx/runtime')to interceptcreateAcpRuntimeand assert on the options bag: (1) callback forwards intoAcpRuntimeOptions, (2) absent when not configured, (3) pre-builtruntime:option skips runtime construction entirely.test/e2e/permission-callback.test.tsAcpPermissionRequest, and the agent honoursreject_once,allow_once, andundefinedfall-through outcomes. Gated behindSMOKE_AGENTS=codexso it stays out of CI.Test plan
bun run lintclean.bun run typecheckclean (passes against the now-publishedacpx@0.8.0).bun run fallowclean.bun test— 266 pass / 24 skip / 0 fail across the monorepo (290 tests, 30 files; the three new unit tests are part of the 266; the new e2e test is in the 24 skipped becauseSMOKE_AGENTSis unset).SMOKE_AGENTS=codex bun test packages/acpx-ai-provider/test/e2e/permission-callback.test.ts— 3 pass / 0 fail against a real codex 0.130.0 instance, ~42s.bun run buildclean (ESM + .d.ts).Coordination
This PR ships alongside two sibling provider features that all target
0.0.5:getModels()helpersessionOptionsforwardingWhichever lands first wins
0.0.5; the other two will need a follow-up bump (0.0.5→0.0.6→0.0.7) and a one-linepackage.jsonrebase to resolve the version conflict. All three are independent on the code side.