You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Approval for an unopened mirrored Session answers unavailable and leaves the remote turn hanging #22
Connect a remote host and create a remote Session through the plugin's /api/dsh-remote endpoint (host/session/create), then send a prompt that forces a sandbox escalation, e.g. ask the agent to write /root/... with sandbox_permissions: "danger-full-access".
Remote Session emits approval/asked (e.g. {"id":"...","toolName":"write","reason":"escalate sandbox to danger-full-access..."}) and the local mirror Session exists in ~/.dsh/remote/mirrors.json, but the mirrored Session has not been opened in the local UI yet (no attached local Agent/runtime).
The plugin's approval bridge receives the request, finds no runtime for the local mirror and calls answerApproval(hostId, id, "unavailable").
Expected behavior
A fail-closed decision should still resolve the remote request so the remote turn continues (e.g. reject the escalation and append a denial/tool-result), instead of leaving the remote turn waiting indefinitely.
Relevant logs
Remote Session event log ends at approval/asked (24 events, no further events for 60s+); turn remains active.
Calling the remote agent's /dsh-remote-agent/api/v1/approvals/answer afterwards returns {"error":{"code":"request/invalid","message":"approval <id> is not pending"}} (with x-dsh-remote-protocol: 1 header), i.e. the unavailable answer was delivered but the ask did not resolve.
Possible fix: answer rejected (or a terminal outcome) when no local runtime can present the approval, so the remote tool call resolves and the turn can finish; or document that approvals require an opened mirrored Session.
The plugin no longer answers a mirrored approval with unavailable while the local mirror is not ready. It keeps the approval queued until the local mirror runtime exists and a connected client is showing that mirrored Session. The approval is then handed to the ordinary native approval UI, preserving native waiting semantics: if no client shows the Session, it waits instead of being denied.
The existing session-claim poll now doubles as a visibility heartbeat, and replayed approval ids are deduplicated so a reconnect does not create a second pending prompt. A two-client Playwright test covers the flow: both clients see the same approval, one client answers, the other client dismisses, and the remote agent receives exactly one answer.
Activity
Golden-Pigeon commentedon Nov 9, 2026
Fixed in #27.
The plugin no longer answers a mirrored approval with
unavailablewhile the local mirror is not ready. It keeps the approval queued until the local mirror runtime exists and a connected client is showing that mirrored Session. The approval is then handed to the ordinary native approval UI, preserving native waiting semantics: if no client shows the Session, it waits instead of being denied.The existing session-claim poll now doubles as a visibility heartbeat, and replayed approval ids are deduplicated so a reconnect does not create a second pending prompt. A two-client Playwright test covers the flow: both clients see the same approval, one client answers, the other client dismisses, and the remote agent receives exactly one answer.
Thanks @Solaris136 for the report.