[Feature] Refactor runtime executor for better extensibility/configurability #6297
+433
−373
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.
Overview
This PR refactors the action_execution_server and ActionExecutor, to facilitate extensibility and customization of the executor within the runtime. In particular:
action_executor_server.py
script, leaving it to focus on the API server implementation.ActionExecutor
class has been refactored into a hierarchy:RuntimeExecutor
inruntime/executor/base.py
handles the setup/teardown of the common resources: bash session, browser, plugins, etc.BaseActionExecutor
inruntime/executor/action_executor.py
adds the dynamicrun_action
dispatcher.ActionExecutor
in the same file, adds the detailed implementation for all of the standard runners (run_ipython
,read
,browse
, etc).Importantly, the executor class to be used as been added to the AppConfig and can be used to specify an arbitrary class (even from an external module) to provide the executor implementation, as long as it implements the base interface. For example, you can set
runtime_executor = "my_package.some_module:MyCustomExecutor"
.Note that I have not changed any code/functionality of the existing
ActionExecutor
, just distributed its code around into the three-class hierarchy. There are minor changes elsewhere in the code to accommodate the new configuration setting.Rationale
This change makes it possible to easily extend/override/customize the builtin executor implementation, without having to operate on core classes in the OpenHands repo (or even make change to the repo at all).
Caveats
In the exiting
ActionExecutor
, there is a block of code labeled "TODO" in theainit
method, which evidently is meant to be removed pending an unrelated refactoring operation. This temporary block of code depends on therun_ipython
method, which is not implemented in the base class. Rather that introducing additional abstractions to accommodate this temporary code, I have elected to leave it in place in the base implementation. However this means executor classes will fail to initialize unless they provide therun_ipython
method (as the default ActionExecutor does).A more general fix would be to add an overridable hook method that can be called in the ainit function, which I'm happy to add if deemed necessary.
In the the base
RuntimeExecutor
inruntime/executor/base.py
, thereEnd-user friendly description of the problem this fixes or functionality that this introduces
Runtime executor can now be subclassed to provide custom or extended functionality.
The executor class used in the runtime can be configured with:
Give a summary of what the PR does, explaining any non-trivial design decisions
Link of any specific issues this addresses