Initial commit: Add logistics and order_detail message types
Some checks failed
Lock Threads / action (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled
Publish Chatwoot EE docker images / build (linux/amd64, ubuntu-latest) (push) Has been cancelled
Publish Chatwoot EE docker images / build (linux/arm64, ubuntu-22.04-arm) (push) Has been cancelled
Publish Chatwoot EE docker images / merge (push) Has been cancelled
Publish Chatwoot CE docker images / build (linux/amd64, ubuntu-latest) (push) Has been cancelled
Publish Chatwoot CE docker images / build (linux/arm64, ubuntu-22.04-arm) (push) Has been cancelled
Publish Chatwoot CE docker images / merge (push) Has been cancelled
Run Chatwoot CE spec / lint-backend (push) Has been cancelled
Run Chatwoot CE spec / lint-frontend (push) Has been cancelled
Run Chatwoot CE spec / frontend-tests (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (0, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (1, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (10, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (11, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (12, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (13, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (14, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (15, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (2, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (3, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (4, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (5, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (6, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (7, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (8, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (9, 16) (push) Has been cancelled
Run Linux nightly installer / nightly (push) Has been cancelled
Some checks failed
Lock Threads / action (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled
Publish Chatwoot EE docker images / build (linux/amd64, ubuntu-latest) (push) Has been cancelled
Publish Chatwoot EE docker images / build (linux/arm64, ubuntu-22.04-arm) (push) Has been cancelled
Publish Chatwoot EE docker images / merge (push) Has been cancelled
Publish Chatwoot CE docker images / build (linux/amd64, ubuntu-latest) (push) Has been cancelled
Publish Chatwoot CE docker images / build (linux/arm64, ubuntu-22.04-arm) (push) Has been cancelled
Publish Chatwoot CE docker images / merge (push) Has been cancelled
Run Chatwoot CE spec / lint-backend (push) Has been cancelled
Run Chatwoot CE spec / lint-frontend (push) Has been cancelled
Run Chatwoot CE spec / frontend-tests (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (0, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (1, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (10, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (11, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (12, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (13, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (14, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (15, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (2, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (3, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (4, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (5, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (6, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (7, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (8, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (9, 16) (push) Has been cancelled
Run Linux nightly installer / nightly (push) Has been cancelled
- Add Logistics component with progress tracking - Add OrderDetail component for order information - Support data-driven steps and actions - Add blue color scale to widget SCSS - Fix node overflow and progress bar rendering issues - Add English translations for dashboard components Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,166 @@
|
||||
require 'agents'
|
||||
|
||||
class Captain::Assistant::AgentRunnerService
|
||||
CONVERSATION_STATE_ATTRIBUTES = %i[
|
||||
id display_id inbox_id contact_id status priority
|
||||
label_list custom_attributes additional_attributes
|
||||
].freeze
|
||||
|
||||
CONTACT_STATE_ATTRIBUTES = %i[
|
||||
id name email phone_number identifier contact_type
|
||||
custom_attributes additional_attributes
|
||||
].freeze
|
||||
|
||||
def initialize(assistant:, conversation: nil, callbacks: {})
|
||||
@assistant = assistant
|
||||
@conversation = conversation
|
||||
@callbacks = callbacks
|
||||
end
|
||||
|
||||
def generate_response(message_history: [])
|
||||
agents = build_and_wire_agents
|
||||
context = build_context(message_history)
|
||||
message_to_process = extract_last_user_message(message_history)
|
||||
runner = Agents::Runner.with_agents(*agents)
|
||||
runner = add_callbacks_to_runner(runner) if @callbacks.any?
|
||||
result = runner.run(message_to_process, context: context, max_turns: 100)
|
||||
|
||||
process_agent_result(result)
|
||||
rescue StandardError => e
|
||||
# when running the agent runner service in a rake task, the conversation might not have an account associated
|
||||
# for regular production usage, it will run just fine
|
||||
ChatwootExceptionTracker.new(e, account: @conversation&.account).capture_exception
|
||||
Rails.logger.error "[Captain V2] AgentRunnerService error: #{e.message}"
|
||||
Rails.logger.error e.backtrace.join("\n")
|
||||
|
||||
error_response(e.message)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def build_context(message_history)
|
||||
conversation_history = message_history.map do |msg|
|
||||
content = extract_text_from_content(msg[:content])
|
||||
|
||||
{
|
||||
role: msg[:role].to_sym,
|
||||
content: content,
|
||||
agent_name: msg[:agent_name]
|
||||
}
|
||||
end
|
||||
|
||||
{
|
||||
conversation_history: conversation_history,
|
||||
state: build_state
|
||||
}
|
||||
end
|
||||
|
||||
def extract_last_user_message(message_history)
|
||||
last_user_msg = message_history.reverse.find { |msg| msg[:role] == 'user' }
|
||||
|
||||
extract_text_from_content(last_user_msg[:content])
|
||||
end
|
||||
|
||||
def extract_text_from_content(content)
|
||||
# Handle structured output from agents
|
||||
return content[:response] || content['response'] || content.to_s if content.is_a?(Hash)
|
||||
|
||||
return content unless content.is_a?(Array)
|
||||
|
||||
text_parts = content.select { |part| part[:type] == 'text' }.pluck(:text)
|
||||
text_parts.join(' ')
|
||||
end
|
||||
|
||||
# Response formatting methods
|
||||
def process_agent_result(result)
|
||||
Rails.logger.info "[Captain V2] Agent result: #{result.inspect}"
|
||||
response = format_response(result.output)
|
||||
|
||||
# Extract agent name from context
|
||||
response['agent_name'] = result.context&.dig(:current_agent)
|
||||
|
||||
response
|
||||
end
|
||||
|
||||
def format_response(output)
|
||||
return output.with_indifferent_access if output.is_a?(Hash)
|
||||
|
||||
# Fallback for backwards compatibility
|
||||
{
|
||||
'response' => output.to_s,
|
||||
'reasoning' => 'Processed by agent'
|
||||
}
|
||||
end
|
||||
|
||||
def error_response(error_message)
|
||||
{
|
||||
'response' => 'conversation_handoff',
|
||||
'reasoning' => "Error occurred: #{error_message}"
|
||||
}
|
||||
end
|
||||
|
||||
def build_state
|
||||
state = {
|
||||
account_id: @assistant.account_id,
|
||||
assistant_id: @assistant.id,
|
||||
assistant_config: @assistant.config
|
||||
}
|
||||
|
||||
if @conversation
|
||||
state[:conversation] = @conversation.attributes.symbolize_keys.slice(*CONVERSATION_STATE_ATTRIBUTES)
|
||||
state[:contact] = @conversation.contact.attributes.symbolize_keys.slice(*CONTACT_STATE_ATTRIBUTES) if @conversation.contact
|
||||
end
|
||||
|
||||
state
|
||||
end
|
||||
|
||||
def build_and_wire_agents
|
||||
assistant_agent = @assistant.agent
|
||||
scenario_agents = @assistant.scenarios.enabled.map(&:agent)
|
||||
|
||||
assistant_agent.register_handoffs(*scenario_agents) if scenario_agents.any?
|
||||
scenario_agents.each { |scenario_agent| scenario_agent.register_handoffs(assistant_agent) }
|
||||
|
||||
[assistant_agent] + scenario_agents
|
||||
end
|
||||
|
||||
def add_callbacks_to_runner(runner)
|
||||
runner = add_agent_thinking_callback(runner) if @callbacks[:on_agent_thinking]
|
||||
runner = add_tool_start_callback(runner) if @callbacks[:on_tool_start]
|
||||
runner = add_tool_complete_callback(runner) if @callbacks[:on_tool_complete]
|
||||
runner = add_agent_handoff_callback(runner) if @callbacks[:on_agent_handoff]
|
||||
runner
|
||||
end
|
||||
|
||||
def add_agent_thinking_callback(runner)
|
||||
runner.on_agent_thinking do |*args|
|
||||
@callbacks[:on_agent_thinking].call(*args)
|
||||
rescue StandardError => e
|
||||
Rails.logger.warn "[Captain] Callback error for agent_thinking: #{e.message}"
|
||||
end
|
||||
end
|
||||
|
||||
def add_tool_start_callback(runner)
|
||||
runner.on_tool_start do |*args|
|
||||
@callbacks[:on_tool_start].call(*args)
|
||||
rescue StandardError => e
|
||||
Rails.logger.warn "[Captain] Callback error for tool_start: #{e.message}"
|
||||
end
|
||||
end
|
||||
|
||||
def add_tool_complete_callback(runner)
|
||||
runner.on_tool_complete do |*args|
|
||||
@callbacks[:on_tool_complete].call(*args)
|
||||
rescue StandardError => e
|
||||
Rails.logger.warn "[Captain] Callback error for tool_complete: #{e.message}"
|
||||
end
|
||||
end
|
||||
|
||||
def add_agent_handoff_callback(runner)
|
||||
runner.on_agent_handoff do |*args|
|
||||
@callbacks[:on_agent_handoff].call(*args)
|
||||
rescue StandardError => e
|
||||
Rails.logger.warn "[Captain] Callback error for agent_handoff: #{e.message}"
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user