Class: ToolExecutionJob
- Inherits:
-
ApplicationJob
- Object
- ActiveJob::Base
- ApplicationJob
- ToolExecutionJob
- Defined in:
- app/jobs/tool_execution_job.rb
Overview
Runs a single tool on behalf of the session and reports the outcome.
Queued by Events::Subscribers::LLMResponseHandler when the LLM returns a tool_use block. The session is already in the :executing state (transition owned by the response handler). This job:
-
Dispatches the tool via Tools::Registry.
-
Truncates and formats the result.
-
Emits Events::ToolExecuted.
The job does not release the session or create the tool_response PendingMessage — that’s Events::Subscribers::ToolResponseCreator‘s job. Event emission is the final act that hands control off.
Instance Method Summary collapse
Instance Method Details
#perform(session_id, tool_use_id:, tool_name:, tool_input:) ⇒ Object
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'app/jobs/tool_execution_job.rb', line 25 def perform(session_id, tool_use_id:, tool_name:, tool_input:) session = Session.find(session_id) # ShellSession.for_session returns the conversation's persistent shell # — spawned on first use, reused on every subsequent tool call so the # agent's cd's and exported env vars survive between calls. We do NOT # finalize it here; the shell's lifetime is the Session's lifetime. shell_session = ShellSession.for_session(session) registry = Tools::Registry.build(session: session, shell_session: shell_session) content, success = execute(registry, tool_name, tool_input, tool_use_id) Events::Bus.emit(Events::ToolExecuted.new( session_id: session_id, tool_use_id: tool_use_id, tool_name: tool_name, content: content, success: success )) rescue => error # A missing {Events::ToolExecuted} would leave the session in +:executing+ # forever. Always emit a synthetic failure event so # {Events::Subscribers::ToolResponseCreator} runs and releases the claim. Rails.logger.error("ToolExecutionJob crashed: #{error.class}: #{error.}") Events::Bus.emit(Events::ToolExecuted.new( session_id: session_id, tool_use_id: tool_use_id, tool_name: tool_name, content: "#{error.class}: #{error.}", success: false )) end |