agentscope-ai / agentscope-ai/QwenPaw
[Bug]: ACP `trusted: true` silently falls back to interactive prompts — `_pick_allow_option` only matches `allow_*` optionIds
- Vorherrschende Sprache
- TypeScript
- Sterne
- 35k
- Forks
- 3.1k
- Ø Merge
- 1 T. 13 Std.
- Gemergte PRs (30 T.)
- 228
Beschreibung
**Environment**: QwenPaw 2.2.0 (desktop, macOS arm64); still present on `main` as of 2026-09-05.
**Root cause** (`src/qwenpaw/acp/client.py:32-38, 113-130`):
```python
_ALLOW_OPTION_PREFERENCE = ("allow_once", "allow_always", "allow", "yes", "approve")
# exact lowercase match on optionId; fallback: substring "allow" in id
```
The `trusted` branch of `request_permission` exists and is logically correct, but auto-approval depends on `_pick_allow_option`. ACP agents are free to choose their own optionIds — e.g. **kimi-code uses `approve_once` / `approve_always` / `reject`** (verified via strings in kimi-code 0.27.0 and 0.41.0 binaries). Exact matching fails (`"approve" != "approve_once"`), and the substring fallback `"allow" in "approve_always"` is also False → `_pick_allow_option` returns `None` → trusted sessions silently degrade to interactive prompting. Users see a permission dialog on every single tool call despite `"trusted": true`.
Note: kimi-code's options DO carry spec-compliant `kind` values (`allow_once` / `allow_always`) — matching by `kind` instead of `id` is the robust approach.
**Additional observation**: the response path has a symmetric problem. When the selected optionId is not in QwenPaw's known vocabulary, the outcome parsing falls through to `default: rejected` — so a proxy translating IDs must translate both directions. Matching by `kind` would fix both directions at once.
**Suggested fix**:
1. Prefer matching by ACP option `kind` (`allow_always` > `allow_once`), falling back to id heuristics; and/or
2. Extend `_ALLOW_OPTION_PREFERENCE` with `"approve_always"`, `"approve_once"` and widen the substring fallback to `"approve"`.
**Minimal repro**:
1. Configure an ACP runner with `"trusted": true` whose permission optionIds use the `approve_*` vocabulary (e.g. kimi-code).
2. Trigger any tool call requiring permission.
3. Expected: auto-approved without user interaction. Actual: interactive permission request is surfaced on every tool call.
**Workaround (verified in production)**: a stdio wrapper adapter around the runner's ACP entrypoint that bidirectionally translates `approve_*` ↔ `allow_*` optionIds. With the adapter in place and `trusted: true`, non-dangerous requests are auto-approved with zero interactive prompts.
在聊天中引用
Beitragsleitfaden
Rechercherichtung
Start in `src/qwenpaw/acp/client.py`, at `_ALLOW_OPTION_PREFERENCE`, `_pick_allow_option`, and the permission response parsing branch around lines 32-38 and 113-130. Read how `request_permission` uses `trusted: true` and why unknown `optionId` values fall back to interactive prompts. Reproduce with a trusted ACP runner using `approve_*` IDs and run a tool call that needs permission. Done means trusted sessions auto-approve the intended allow path via ACP `kind`/normalized matching with no interactive dialog and no wrong `default: rejected` fallback.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Bewertung
- Tech-Stack
- python
- Bereich
- authorization
- Issue-Typ
- Bug
- Schwierigkeit
- 2/5
- Geschätzter Aufwand
- 1-3 Stunden
- Aktivitätsstatus
- Aktiv
- Klarheit
- Klar beschrieben
- Anfängerfreundlichkeit
- 48/100