aws-lex-conversation 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ci.yml +35 -0
  3. data/.gitignore +15 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +29 -0
  6. data/.simplecov +5 -0
  7. data/CODE_OF_CONDUCT.md +74 -0
  8. data/Gemfile +12 -0
  9. data/LICENSE.md +21 -0
  10. data/README.md +160 -0
  11. data/Rakefile +11 -0
  12. data/aws-lex-conversation.gemspec +38 -0
  13. data/bin/console +15 -0
  14. data/bin/setup +8 -0
  15. data/lib/aws-lex-conversation.rb +3 -0
  16. data/lib/aws/lex/conversation.rb +58 -0
  17. data/lib/aws/lex/conversation/base.rb +40 -0
  18. data/lib/aws/lex/conversation/handler/base.rb +34 -0
  19. data/lib/aws/lex/conversation/handler/delegate.rb +17 -0
  20. data/lib/aws/lex/conversation/handler/echo.rb +24 -0
  21. data/lib/aws/lex/conversation/response/base.rb +30 -0
  22. data/lib/aws/lex/conversation/response/close.rb +29 -0
  23. data/lib/aws/lex/conversation/response/confirm_intent.rb +31 -0
  24. data/lib/aws/lex/conversation/response/delegate.rb +29 -0
  25. data/lib/aws/lex/conversation/response/elicit_intent.rb +27 -0
  26. data/lib/aws/lex/conversation/response/elicit_slot.rb +33 -0
  27. data/lib/aws/lex/conversation/support/inflector.rb +43 -0
  28. data/lib/aws/lex/conversation/support/responses.rb +56 -0
  29. data/lib/aws/lex/conversation/type/base.rb +95 -0
  30. data/lib/aws/lex/conversation/type/bot.rb +17 -0
  31. data/lib/aws/lex/conversation/type/confirmation_status.rb +17 -0
  32. data/lib/aws/lex/conversation/type/current_intent.rb +34 -0
  33. data/lib/aws/lex/conversation/type/dialog_action_type.rb +19 -0
  34. data/lib/aws/lex/conversation/type/enumeration.rb +44 -0
  35. data/lib/aws/lex/conversation/type/event.rb +37 -0
  36. data/lib/aws/lex/conversation/type/fulfillment_state.rb +16 -0
  37. data/lib/aws/lex/conversation/type/invocation_source.rb +16 -0
  38. data/lib/aws/lex/conversation/type/message.rb +20 -0
  39. data/lib/aws/lex/conversation/type/message/content_type.rb +19 -0
  40. data/lib/aws/lex/conversation/type/output_dialog_mode.rb +16 -0
  41. data/lib/aws/lex/conversation/type/recent_intent_summary_view.rb +29 -0
  42. data/lib/aws/lex/conversation/type/response.rb +17 -0
  43. data/lib/aws/lex/conversation/type/response_card.rb +23 -0
  44. data/lib/aws/lex/conversation/type/response_card/button.rb +18 -0
  45. data/lib/aws/lex/conversation/type/response_card/content_type.rb +17 -0
  46. data/lib/aws/lex/conversation/type/response_card/generic_attachment.rb +26 -0
  47. data/lib/aws/lex/conversation/type/sentiment_label.rb +18 -0
  48. data/lib/aws/lex/conversation/type/sentiment_response.rb +21 -0
  49. data/lib/aws/lex/conversation/type/sentiment_score.rb +35 -0
  50. data/lib/aws/lex/conversation/type/slot_detail.rb +20 -0
  51. data/lib/aws/lex/conversation/type/slot_resolution.rb +15 -0
  52. data/lib/aws/lex/conversation/version.rb +9 -0
  53. metadata +117 -0
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'aws/lex/conversation'
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'conversation/base'
4
+
5
+ module Aws
6
+ module Lex
7
+ class Conversation
8
+ include Support::Responses
9
+
10
+ attr_accessor :event, :context, :lex
11
+
12
+ def initialize(opts = {})
13
+ self.event = opts.fetch(:event)
14
+ self.context = opts.fetch(:context)
15
+ self.lex = Type::Event.shrink_wrap(event)
16
+ end
17
+
18
+ def chain
19
+ @chain ||= []
20
+ end
21
+
22
+ def handlers=(list)
23
+ last = nil
24
+
25
+ reversed = list.reverse.map do |element|
26
+ handler = element.fetch(:handler).new(
27
+ options: element.fetch(:options) { {} },
28
+ successor: last
29
+ )
30
+ last = handler
31
+ handler
32
+ end
33
+
34
+ @chain = reversed.reverse
35
+ end
36
+
37
+ def handlers
38
+ chain.map(&:class)
39
+ end
40
+
41
+ def respond
42
+ chain.first.handle(self)
43
+ end
44
+
45
+ def intent_name
46
+ lex.current_intent.name
47
+ end
48
+
49
+ def slots
50
+ lex.current_intent.slots
51
+ end
52
+
53
+ def session
54
+ lex.session_attributes
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'shrink/wrap'
5
+
6
+ require_relative 'version'
7
+ require_relative 'response/base'
8
+ require_relative 'response/close'
9
+ require_relative 'response/confirm_intent'
10
+ require_relative 'response/delegate'
11
+ require_relative 'response/elicit_intent'
12
+ require_relative 'response/elicit_slot'
13
+ require_relative 'support/responses'
14
+ require_relative 'support/inflector'
15
+ require_relative 'type/base'
16
+ require_relative 'type/enumeration'
17
+ require_relative 'type/sentiment_label'
18
+ require_relative 'type/sentiment_score'
19
+ require_relative 'type/sentiment_response'
20
+ require_relative 'type/invocation_source'
21
+ require_relative 'type/dialog_action_type'
22
+ require_relative 'type/confirmation_status'
23
+ require_relative 'type/fulfillment_state'
24
+ require_relative 'type/recent_intent_summary_view'
25
+ require_relative 'type/slot_resolution'
26
+ require_relative 'type/slot_detail'
27
+ require_relative 'type/current_intent'
28
+ require_relative 'type/output_dialog_mode'
29
+ require_relative 'type/bot'
30
+ require_relative 'type/message/content_type'
31
+ require_relative 'type/message'
32
+ require_relative 'type/response_card/content_type'
33
+ require_relative 'type/response_card/button'
34
+ require_relative 'type/response_card/generic_attachment'
35
+ require_relative 'type/response_card'
36
+ require_relative 'type/response'
37
+ require_relative 'type/event'
38
+ require_relative 'handler/base'
39
+ require_relative 'handler/echo'
40
+ require_relative 'handler/delegate'
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ module Lex
5
+ class Conversation
6
+ module Handler
7
+ class Base
8
+ attr_accessor :successor, :options
9
+
10
+ def initialize(opts = {})
11
+ self.successor = opts[:successor]
12
+ self.options = opts[:options]
13
+ end
14
+
15
+ def will_respond?(conversation)
16
+ callable = options.fetch(:respond_on) { ->(_c) { false } }
17
+ callable.call(conversation)
18
+ end
19
+
20
+ def response(_conversation)
21
+ raise NotImplementedError, 'define #response in a subclass'
22
+ end
23
+
24
+ def handle(conversation)
25
+ return response(conversation) if will_respond?(conversation)
26
+ return unless successor # end of chain - return nil
27
+
28
+ successor.handle(conversation)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ module Lex
5
+ class Conversation
6
+ module Handler
7
+ class Delegate < Base
8
+ def response(conversation)
9
+ conversation.delegate(
10
+ slots: conversation.lex.current_intent.slots
11
+ )
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ module Lex
5
+ class Conversation
6
+ module Handler
7
+ class Echo < Base
8
+ def response(conversation)
9
+ content = options.fetch(:content) { conversation.lex.input_transcript }
10
+ content_type = options.fetch(:content_type) { Type::Message::ContentType.new('PlainText') }
11
+ fulfillment_state = options.fetch(:fulfillment_state) { Type::FulfillmentState.new('Fulfilled') }
12
+ conversation.close(
13
+ fulfillment_state: fulfillment_state,
14
+ message: Type::Message.new(
15
+ content: content,
16
+ content_type: content_type
17
+ )
18
+ )
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ module Lex
5
+ class Conversation
6
+ module Response
7
+ class Base
8
+ attr_accessor :session_attributes, :recent_intent_summary_view
9
+
10
+ def initialize(opts = {})
11
+ self.session_attributes = opts[:session_attributes]
12
+ self.recent_intent_summary_view = opts[:recent_intent_summary_view]
13
+ end
14
+
15
+ def dialog_action
16
+ raise NotImplementedError, 'define dialog_action in a subclass'
17
+ end
18
+
19
+ def to_lex
20
+ Type::Response.new(
21
+ session_attributes: session_attributes,
22
+ recent_intent_summary_view: recent_intent_summary_view,
23
+ dialog_action: dialog_action
24
+ ).to_lex
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ module Lex
5
+ class Conversation
6
+ module Response
7
+ class Close < Base
8
+ attr_accessor :fulfillment_state, :message, :response_card
9
+
10
+ def initialize(opts = {})
11
+ super
12
+ self.fulfillment_state = opts.fetch(:fulfillment_state)
13
+ self.message = opts[:message]
14
+ self.response_card = opts[:response_card]
15
+ end
16
+
17
+ def dialog_action
18
+ {
19
+ type: 'Close',
20
+ fulfillmentState: fulfillment_state,
21
+ message: message,
22
+ responseCard: response_card
23
+ }.reject { |_, v| v.nil? }
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ module Lex
5
+ class Conversation
6
+ module Response
7
+ class ConfirmIntent < Base
8
+ attr_accessor :intent_name, :message, :response_card, :slots
9
+
10
+ def initialize(opts = {})
11
+ super
12
+ self.intent_name = opts.fetch(:intent_name)
13
+ self.slots = opts[:slots]
14
+ self.message = opts[:message]
15
+ self.response_card = opts[:response_card]
16
+ end
17
+
18
+ def dialog_action
19
+ {
20
+ type: 'ConfirmIntent',
21
+ intentName: intent_name,
22
+ slots: slots,
23
+ message: message,
24
+ responseCard: response_card
25
+ }.reject { |_, v| v.nil? }
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ module Lex
5
+ class Conversation
6
+ module Response
7
+ class Delegate < Base
8
+ attr_accessor :slots, :kendra_query_request_payload, :kendra_query_filter_string
9
+
10
+ def initialize(opts = {})
11
+ super
12
+ self.slots = opts[:slots]
13
+ self.kendra_query_request_payload = opts[:kendra_query_request_payload]
14
+ self.kendra_query_filter_string = opts[:kendra_query_filter_string]
15
+ end
16
+
17
+ def dialog_action
18
+ {
19
+ type: 'Delegate',
20
+ slots: slots,
21
+ kendraQueryRequestPayload: kendra_query_request_payload,
22
+ kendraQueryFilterString: kendra_query_filter_string
23
+ }.reject { |_, v| v.nil? }
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ module Lex
5
+ class Conversation
6
+ module Response
7
+ class ElicitIntent < Base
8
+ attr_accessor :message, :response_card
9
+
10
+ def initialize(opts = {})
11
+ super
12
+ self.message = opts[:message]
13
+ self.response_card = opts[:response_card]
14
+ end
15
+
16
+ def dialog_action
17
+ {
18
+ type: 'ElicitIntent',
19
+ message: message,
20
+ responseCard: response_card
21
+ }.reject { |_, v| v.nil? }
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ module Lex
5
+ class Conversation
6
+ module Response
7
+ class ElicitSlot < Base
8
+ attr_accessor :intent_name, :message, :response_card, :slots, :slot_to_elicit
9
+
10
+ def initialize(opts = {})
11
+ super
12
+ self.intent_name = opts.fetch(:intent_name)
13
+ self.slot_to_elicit = opts.fetch(:slot_to_elicit)
14
+ self.slots = opts.fetch(:slots)
15
+ self.message = opts[:message]
16
+ self.response_card = opts[:response_card]
17
+ end
18
+
19
+ def dialog_action
20
+ {
21
+ type: 'ElicitSlot',
22
+ intentName: intent_name,
23
+ slots: slots,
24
+ slotToElicit: slot_to_elicit,
25
+ message: message,
26
+ responseCard: response_card
27
+ }.reject { |_, v| v.nil? }
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ module Lex
5
+ class Conversation
6
+ module Support
7
+ class Inflector
8
+ attr_accessor :input
9
+
10
+ def initialize(input)
11
+ self.input = input.to_s
12
+ end
13
+
14
+ def to_snake_case
15
+ # shamelessly borrowed from ActiveSupport
16
+ input
17
+ .gsub(/::/, '/')
18
+ .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
19
+ .gsub(/([a-z\d])([A-Z])/, '\1_\2')
20
+ .tr('-', '_')
21
+ .gsub(/\W/, '_')
22
+ .downcase
23
+ end
24
+
25
+ def to_camel_case(style = :lower)
26
+ parts = input.split('_')
27
+ first = parts.shift
28
+ rest = parts.map(&:capitalize)
29
+
30
+ case style
31
+ when :lower
32
+ rest.unshift(first).join
33
+ when :upper
34
+ rest.unshift(first.capitalize).join
35
+ else
36
+ raise ArgumentError, "invalid option: `#{style.inspect}`"
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ module Lex
5
+ class Conversation
6
+ module Support
7
+ module Responses
8
+ def close(opts = {})
9
+ params = {
10
+ session_attributes: lex.session_attributes,
11
+ recent_intent_summary_view: lex.recent_intent_summary_view
12
+ }.merge(opts)
13
+ Response::Close.new(params).to_lex
14
+ end
15
+
16
+ def confirm_intent(opts = {})
17
+ params = {
18
+ session_attributes: lex.session_attributes,
19
+ recent_intent_summary_view: lex.recent_intent_summary_view,
20
+ intent_name: lex.current_intent.name,
21
+ slots: lex.current_intent.slots
22
+ }.merge(opts)
23
+ Response::ConfirmIntent.new(params).to_lex
24
+ end
25
+
26
+ def delegate(opts = {})
27
+ params = {
28
+ session_attributes: lex.session_attributes,
29
+ recent_intent_summary_view: lex.recent_intent_summary_view,
30
+ slots: lex.current_intent.slots
31
+ }.merge(opts)
32
+ Response::Delegate.new(params).to_lex
33
+ end
34
+
35
+ def elicit_intent(opts = {})
36
+ params = {
37
+ session_attributes: lex.session_attributes,
38
+ recent_intent_summary_view: lex.recent_intent_summary_view
39
+ }.merge(opts)
40
+ Response::ElicitIntent.new(params).to_lex
41
+ end
42
+
43
+ def elicit_slot(opts = {})
44
+ params = {
45
+ session_attributes: lex.session_attributes,
46
+ recent_intent_summary_view: lex.recent_intent_summary_view,
47
+ slots: lex.current_intent.slots,
48
+ intent_name: lex.current_intent.name
49
+ }.merge(opts)
50
+ Response::ElicitSlot.new(params).to_lex
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end