Skip to content

fix(tui-rpc): register the missing shell.exec handler#213

Open
AmirF194 wants to merge 1 commit into
EverMind-AI:mainfrom
AmirF194:fix/171-shell-exec-unregistered
Open

fix(tui-rpc): register the missing shell.exec handler#213
AmirF194 wants to merge 1 commit into
EverMind-AI:mainfrom
AmirF194:fix/171-shell-exec-unregistered

Conversation

@AmirF194

Copy link
Copy Markdown

Summary

!-prefixed bang commands in the TUI always fail with [rpc -32601] method_not_found. useSubmission.ts's shellExec and interpolate call gw.request('shell.exec', {command}), but the backend never registers a shell.exec handler; it is absent from every dispatcher.register(...) call in raven/**/*.py.

#171's root-cause section points at a different method, command.dispatch, based on evidence gathered against the released v0.1.6 bundle (ui-tui/dist/entry.js, a gitignored build artifact). That name is gone from the current frontend source: command.dispatch only survives as dead code in createSlashHandler.ts's .catch() fallback, which is unreachable because slash.exec never rejects (see its own docstring). On current main, useSubmission.ts:180 and :212 call shell.exec directly for every bang command, and that is the method that is actually unregistered. Registering command.dispatch per the issue's suggested fix would not have fixed the bug on current main.

shell.exec carries no session_id (both call sites pass only {command}), so there is no session-scoped sandbox executor to route the command through. The fix runs it via DirectExecutor, the same host-execution path ExecTool falls back to when no sandbox is configured, matching a plain shell escape.

Type

  • Fix
  • Feature
  • Docs
  • CI / tooling
  • Refactor
  • Other

Verification

Reproduced end to end in a clean python:3.12-slim container (uv sync --frozen --extra dev --dev):

$ python3 -c "
import asyncio
from raven.tui_rpc.dispatcher import Dispatcher
from raven.tui_rpc.methods import register_aligned_methods_except_system
d = Dispatcher()
register_aligned_methods_except_system(d)
print('shell.exec' in d.methods())
frame = {'jsonrpc':'2.0','id':1,'method':'shell.exec','params':{'command':'echo hi'}}
print(asyncio.run(d.dispatch(frame)))
"
# main:   False, {'error': {'code': -32601, 'message': 'method_not_found', 'data': {'method': 'shell.exec'}}}
# branch: True,  {'result': {'code': 0, 'stdout': 'hi\n', 'stderr': ''}}
  • Relevant tests pass locally: new tests/test_tui_rpc_shell_exec.py (registration, stdout capture, non-zero exit code, empty-command guard) fails to import on main (module does not exist yet) and passes on this branch (4 passed), in the same container. Also ran the full tests/test_tui_rpc_*.py suite (380 tests) to check for regressions: all pass.
  • Relevant lint / type checks pass locally: ruff check / ruff format --check on the changed files, and pre-commit run --files <changed> (ruff, trailing-whitespace, end-of-file-fixer, large-files, merge-conflict, private-key), all clean.
  • User-facing docs or screenshots are updated when needed: no user-facing docs describe shell.exec, none needed.

Not verified: make test-python only runs a fixed list of four test files (test_commit_lint.py, test_large_file_check.py, test_cli_smoke.py, test_litellm_setup.py), which does not include this or any other test_tui_rpc_*.py file, so CI's python checks job will not execute the new test. I ran it manually in the container described above; ran the fixed CI list too (58 passed) with no regressions.

Risk

  • Security impact considered: shell.exec runs on the host with no sandbox, same as the existing cli.dispatch path for non-sandboxed setups; it is reachable only from the local TUI subprocess bridge, not the network.
  • Backward compatibility considered: purely additive, registers a previously-missing method; no existing handler or contract changes.
  • Rollback path is clear for risky changes: n/a, low risk.

Related Issues

Fixes #171

`!`-prefixed bang commands in the TUI always failed with
`[rpc -32601] method_not_found`: useSubmission.ts's shellExec/interpolate
call `gw.request('shell.exec', {command})`, but the backend never
registered a shell.exec handler, and shell.exec is absent everywhere from
raven/**/*.py.

EverMind-AI#171's own root-cause evidence was gathered against the released v0.1.6
bundle, which called a method named command.dispatch. That name is gone
from the current frontend source; only shell.exec is called on this path
now (useSubmission.ts:180,212). command.dispatch survives only as dead
code in createSlashHandler.ts's unreachable .catch() fallback, since
slash.exec never rejects. On current HEAD, shell.exec is the missing
method, so the suggested command.dispatch registration would not have
fixed the bug.

Add register_shell_methods (raven/tui_rpc/methods/shell_exec.py), wired
into the umbrella in methods/__init__.py the same way slash_routing is.
shell.exec carries no session_id (both call sites pass only {command}),
so there is no session-scoped sandbox executor to route through; it runs
via DirectExecutor, matching a plain host shell escape.

Co-authored-by: Claude (claude-sonnet-5) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

! shell commands in TUI always fail with [rpc -32601] method_not_found (backend never registers command.dispatch)

1 participant