Skip to content
106 changes: 17 additions & 89 deletions app/controllers/stealth/controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,18 @@ class Controller < ApplicationController
include Stealth::Controller::InterruptDetect
include Stealth::Controller::DevJumps
include Stealth::Controller::Replies
include Stealth::Controller::IntentClassifier
include Stealth::Controller::IntentClassifier

attr_reader :current_message, :current_service, :current_session_id
attr_accessor :nlp_result, :pos
attr_accessor :nlp_result, :pos, :current_session, :previous_session

def initialize(service_event:, pos: nil)
super()
@current_message = service_event
@current_service = service_event.service
@current_session_id = service_event.sender_id
# @nlp_result = service_event.nlp_result
@current_session = Stealth::Session.new(id: current_session_id)
@previous_session = Stealth::Session.new(id: current_session_id, type: :previous)
@pos = pos
@progressed = false
end
Expand All @@ -31,72 +32,6 @@ def progressed?
@progressed
end

# def flow_controller
# @flow_controller ||= begin
# flow_controller = [current_session.flow_string, 'controller'].join('_').classify.constantize
# flow_controller.new(service_message: @current_message, pos: @pos)
# end
# end

def current_session
@current_session ||= Stealth::Session.new(id: current_session_id)
end

def previous_session
@previous_session ||= Stealth::Session.new(
id: current_session_id,
type: :previous
)
end

# def action(action: nil)
# begin
# # Grab a mutual exclusion lock on the session
# lock_session!(
# session_slug: Session.slugify(
# flow: current_session.flow_string,
# state: current_session.state_string
# )
# )

# @action_name = action
# @action_name ||= current_session.state_string

# # Check if the user needs to be redirected
# if current_session.flow.current_state.redirects_to.present?
# Stealth::Logger.l(
# topic: "redirect",
# message: "From #{current_session.session} to #{current_session.flow.current_state.redirects_to.session}"
# )
# step_to(session: current_session.flow.current_state.redirects_to, pos: @pos)
# return
# end

# run_callbacks :action do
# begin
# flow_controller.send(@action_name)
# unless flow_controller.progressed?
# run_catch_all(reason: 'Did not send replies, update session, or step')
# end
# rescue Stealth::Errors::Halted
# Stealth::Logger.l(
# topic: "session",
# message: "User #{current_session_id}: session halted."
# )
# rescue StandardError => e
# if e.class == Stealth::Errors::UnrecognizedMessage
# run_unrecognized_message(err: e)
# else
# run_catch_all(err: e)
# end
# end
# end
# ensure
# # Release mutual exclusion lock on the session
# release_lock!
# end
# end

def step_to_in(delay, session: nil, flow: nil, state: nil, slug: nil)
if interrupt_detected?
run_interrupt_action
Expand Down Expand Up @@ -151,7 +86,13 @@ def step_to(session: nil, flow: nil, state: nil, slug: nil, pos: nil, locals: ni
state: state,
slug: slug
)
step(flow: flow, state: state, pos: pos, locals: locals)
current_session.locals = locals

# Workaround for update_session_to.
if previous_session.before_update_session_to_locals.present?
current_session.locals = previous_session.before_update_session_to_locals
end
step(flow: flow, state: state, pos: pos)
end

def update_session_to(session: nil, flow: nil, state: nil, slug: nil, locals: nil)
Expand All @@ -166,8 +107,8 @@ def update_session_to(session: nil, flow: nil, state: nil, slug: nil, locals: ni
state: state,
slug: slug
)

update_session(flow: flow, state: state, locals: locals)
current_session.before_update_session_to_locals = locals
update_session(flow: flow, state: state)
end

def set_back_to(session: nil, flow: nil, state: nil, slug: nil)
Expand Down Expand Up @@ -212,15 +153,10 @@ def halt!

private

def update_session(flow:, state:, locals: nil)
def update_session(flow:, state:)
@progressed = :updated_session
@current_session = Session.new(id: current_session_id)

unless current_session.flow_string == flow.to_s && current_session.state_string == state.to_s
@current_session.locals = locals
@current_session.set_session(new_flow: flow, new_state: state)
end

current_session.set_session(new_flow: flow, new_state: state)
end

def store_back_to_session(flow:, state:)
Expand All @@ -231,16 +167,12 @@ def store_back_to_session(flow:, state:)
back_to_session.set_session(new_flow: flow, new_state: state)
end

def step(flow:, state:, pos: nil, locals: nil)
update_session(flow: flow, state: state, locals: locals)
def step(flow:, state:, pos: nil)
update_session(flow: flow, state: state)
Stealth.trigger_flow(flow, state, @current_message)

@progressed = :stepped
# @flow_controller = nil
# @current_flow = current_session.flow
@pos = pos

# flow_controller.action(action: state)
end

def get_flow_and_state(session: nil, flow: nil, state: nil, slug: nil)
Expand All @@ -258,10 +190,6 @@ def get_flow_and_state(session: nil, flow: nil, state: nil, slug: nil)
end

if flow.present?
# Deprecated
# if state.blank?
# state = FlowMap.flow_spec[flow.to_sym].states.keys.first.to_s
# end

if state.blank?
# Access the existing FlowManager instance that has the registered flows
Expand Down
4 changes: 2 additions & 2 deletions app/controllers/stealth/controller/replies.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def send_replies
Stealth.trigger_reply(flow, state, current_message)
end

def say(reply)
def say(reply, thread_id: nil)
reply_instance = Stealth::Reply.new(unstructured_reply: reply)

handler = reply_handler.new(
Expand All @@ -86,7 +86,7 @@ def say(reply)

formatted_reply = handler.send(reply_instance.reply_type)

client = service_client.new(reply: formatted_reply)
client = service_client.new(reply: formatted_reply, thread_id: thread_id)
client.transmit
end

Expand Down
1 change: 1 addition & 0 deletions app/spectre/prompts/intent_classifier/system.yml.erb
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ system: |
<%= "Examples: #{intent[:examples]}" %>
<% end %>
If the intent is not in the list, reply with nothing.
If the user's message is ambiguous or does not match the action and context of an intent, reply with nothing.
4 changes: 3 additions & 1 deletion lib/stealth/event_mapping.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ class EventMapping
# slack-specific event mappings
'slack' => {
'text_received' => { event_type: :slack, event: :receive },
'text_changed' => { event_type: :slack, event: :text_changed },
'reaction_received' => { event_type: :slack, event: :reaction },
'interactive_response_received' => { event_type: :slack, event: :interactive_response }
'interactive_response_received' => { event_type: :slack, event: :interactive_response },
'assistant_thread_started' => { event_type: :slack, event: :assistant_thread_started },
}
}.freeze

Expand Down
47 changes: 26 additions & 21 deletions lib/stealth/session.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class Session
SLUG_SEPARATOR = '->'

attr_reader :flow, :state, :id, :type
attr_accessor :session, :locals
attr_accessor :session, :locals, :before_update_session_to_locals

# Session types:
# - :primary
Expand All @@ -28,6 +28,7 @@ def initialize(id: nil, type: :primary)
end

load_previous_locals
load_before_update_session_to_locals
get_session
end

Expand Down Expand Up @@ -68,17 +69,25 @@ def state_string
end

def load_previous_locals
load_json_from_redis(previous_locals_key, :@locals)
end

def load_before_update_session_to_locals
load_json_from_redis(before_update_session_to_locals_key, :@before_update_session_to_locals)
end

def load_json_from_redis(key, instance_variable_name)
return if primary_session?

@locals = get_key(previous_locals_key)
value = get_key(key)

if @locals.present? && @locals.is_a?(String)
if value.present? && value.is_a?(String)
begin
@locals = JSON.parse(@locals)
instance_variable_set(instance_variable_name, JSON.parse(value))
rescue JSON::ParserError => e
Stealth::Logger.l(
topic: "session",
message: "User #{id}: failed to parse locals from Redis -> #{@locals}, error: #{e.message}"
message: "User #{id}: failed to parse locals from Redis -> #{value}, error: #{e.message}"
)
end
end
Expand Down Expand Up @@ -197,27 +206,23 @@ def previous_locals_key
[id, 'previous', 'locals'].join('-')
end

def before_update_session_to_locals_key
[id, 'before_update_session_to', 'locals'].join('-')
end

def back_to_key
[id, 'back_to'].join('-')
end

def store_current_to_previous(existing_session:)
# Prevent previous_session from becoming current_session
if session == existing_session
Stealth::Logger.l(
topic: "previous_session",
message: "User #{id}: skipping setting to #{session}"\
' because it is the same as current_session'
)
else
Stealth::Logger.l(
topic: "previous_session",
message: "User #{id}: setting to #{existing_session}"
)

persist_key(key: previous_session_key, value: existing_session)
persist_key(key: previous_locals_key, value: @locals.to_json)
end
Stealth::Logger.l(
topic: "previous_session",
message: "User #{id}: setting to #{existing_session}"
)

persist_key(key: previous_session_key, value: existing_session)
persist_key(key: previous_locals_key, value: @locals.to_json)
persist_key(key: before_update_session_to_locals_key, value: @before_update_session_to_locals.to_json)
end

end
Expand Down