stealth 1.1.5 → 2.0.0.beta3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +27 -11
  3. data/CHANGELOG.md +77 -0
  4. data/Gemfile +1 -1
  5. data/Gemfile.lock +53 -49
  6. data/LICENSE +4 -17
  7. data/README.md +9 -17
  8. data/VERSION +1 -1
  9. data/lib/stealth/base.rb +72 -21
  10. data/lib/stealth/cli.rb +1 -2
  11. data/lib/stealth/commands/console.rb +1 -1
  12. data/lib/stealth/configuration.rb +6 -3
  13. data/lib/stealth/controller/callbacks.rb +1 -1
  14. data/lib/stealth/controller/catch_all.rb +27 -4
  15. data/lib/stealth/controller/controller.rb +168 -49
  16. data/lib/stealth/controller/dev_jumps.rb +41 -0
  17. data/lib/stealth/controller/dynamic_delay.rb +4 -6
  18. data/lib/stealth/controller/interrupt_detect.rb +100 -0
  19. data/lib/stealth/controller/messages.rb +283 -0
  20. data/lib/stealth/controller/nlp.rb +50 -0
  21. data/lib/stealth/controller/replies.rb +183 -40
  22. data/lib/stealth/controller/unrecognized_message.rb +62 -0
  23. data/lib/stealth/{flow/core_ext.rb → core_ext/numeric.rb} +0 -1
  24. data/lib/stealth/core_ext/string.rb +18 -0
  25. data/lib/stealth/core_ext.rb +5 -0
  26. data/lib/stealth/dispatcher.rb +21 -0
  27. data/lib/stealth/errors.rb +12 -0
  28. data/lib/stealth/flow/base.rb +1 -2
  29. data/lib/stealth/flow/specification.rb +3 -2
  30. data/lib/stealth/flow/state.rb +3 -3
  31. data/lib/stealth/generators/builder/Gemfile +4 -3
  32. data/lib/stealth/generators/builder/bot/controllers/bot_controller.rb +42 -0
  33. data/lib/stealth/generators/builder/bot/controllers/catch_alls_controller.rb +2 -0
  34. data/lib/stealth/generators/builder/bot/controllers/goodbyes_controller.rb +2 -0
  35. data/lib/stealth/generators/builder/bot/controllers/hellos_controller.rb +2 -0
  36. data/lib/stealth/generators/builder/bot/controllers/interrupts_controller.rb +9 -0
  37. data/lib/stealth/generators/builder/bot/controllers/unrecognized_messages_controller.rb +9 -0
  38. data/lib/stealth/generators/builder/config/flow_map.rb +8 -0
  39. data/lib/stealth/generators/builder/config/initializers/autoload.rb +8 -0
  40. data/lib/stealth/generators/builder/config/initializers/inflections.rb +16 -0
  41. data/lib/stealth/generators/builder/config/puma.rb +15 -0
  42. data/lib/stealth/helpers/redis.rb +40 -0
  43. data/lib/stealth/lock.rb +83 -0
  44. data/lib/stealth/logger.rb +27 -18
  45. data/lib/stealth/nlp/client.rb +22 -0
  46. data/lib/stealth/nlp/result.rb +57 -0
  47. data/lib/stealth/reloader.rb +90 -0
  48. data/lib/stealth/reply.rb +17 -0
  49. data/lib/stealth/scheduled_reply.rb +3 -3
  50. data/lib/stealth/server.rb +8 -3
  51. data/lib/stealth/service_message.rb +3 -2
  52. data/lib/stealth/service_reply.rb +5 -1
  53. data/lib/stealth/services/base_reply_handler.rb +10 -2
  54. data/lib/stealth/session.rb +106 -53
  55. data/spec/configuration_spec.rb +42 -2
  56. data/spec/controller/callbacks_spec.rb +23 -28
  57. data/spec/controller/catch_all_spec.rb +87 -29
  58. data/spec/controller/controller_spec.rb +444 -43
  59. data/spec/controller/dynamic_delay_spec.rb +16 -18
  60. data/spec/controller/helpers_spec.rb +1 -2
  61. data/spec/controller/interrupt_detect_spec.rb +171 -0
  62. data/spec/controller/messages_spec.rb +744 -0
  63. data/spec/controller/nlp_spec.rb +93 -0
  64. data/spec/controller/replies_spec.rb +446 -11
  65. data/spec/controller/unrecognized_message_spec.rb +168 -0
  66. data/spec/dispatcher_spec.rb +79 -0
  67. data/spec/flow/flow_spec.rb +1 -2
  68. data/spec/flow/state_spec.rb +14 -3
  69. data/spec/helpers/redis_spec.rb +77 -0
  70. data/spec/lock_spec.rb +100 -0
  71. data/spec/nlp/client_spec.rb +23 -0
  72. data/spec/nlp/result_spec.rb +57 -0
  73. data/spec/replies/messages/say_msgs_without_breaks.yml +4 -0
  74. data/spec/replies/messages/say_randomize_speech.yml +10 -0
  75. data/spec/replies/messages/say_randomize_text.yml +10 -0
  76. data/spec/replies/messages/sub1/sub2/say_nested.yml +10 -0
  77. data/spec/reply_spec.rb +61 -0
  78. data/spec/scheduled_reply_spec.rb +23 -0
  79. data/spec/service_reply_spec.rb +1 -2
  80. data/spec/session_spec.rb +251 -12
  81. data/spec/spec_helper.rb +21 -0
  82. data/spec/support/controllers/vaders_controller.rb +24 -0
  83. data/spec/support/nlp_clients/dialogflow.rb +9 -0
  84. data/spec/support/nlp_clients/luis.rb +9 -0
  85. data/spec/support/nlp_results/luis_result.rb +163 -0
  86. data/spec/version_spec.rb +1 -2
  87. data/stealth.gemspec +6 -6
  88. metadata +83 -38
  89. data/docs/00-introduction.md +0 -37
  90. data/docs/01-getting-started.md +0 -21
  91. data/docs/02-local-development.md +0 -40
  92. data/docs/03-basics.md +0 -171
  93. data/docs/04-sessions.md +0 -29
  94. data/docs/05-controllers.md +0 -179
  95. data/docs/06-models.md +0 -39
  96. data/docs/07-replies.md +0 -114
  97. data/docs/08-catchalls.md +0 -49
  98. data/docs/09-messaging-integrations.md +0 -80
  99. data/docs/10-nlp-integrations.md +0 -13
  100. data/docs/11-analytics.md +0 -13
  101. data/docs/12-commands.md +0 -62
  102. data/docs/13-deployment.md +0 -50
  103. data/lib/stealth/generators/builder/config/initializers/.keep +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cbefa5ae28dcc07af7eabc9b18969a45e6948b3b64104882551768f99ea10a81
4
- data.tar.gz: bb3c6195955577466ea4ed6b9c462955dd3a93cc235a41c165dbce3c2a6af0f2
3
+ metadata.gz: f7769a4954530dd2ea5b68d22a05488423d66e464f9ef5863eb26b58a9a8441e
4
+ data.tar.gz: 10b939107c4df107172d64fb14f2e4406ad50597841e2eb76ebe4f31f4eb9f73
5
5
  SHA512:
6
- metadata.gz: f2093777b24ba92ddb2e36ef5e6789d2631cc7d2792a7d3914d20a9915f6f2fab6932000b2e74f3c1ac2af8fb65bbfdef7c112324b2b7034611d31bfe438fae3
7
- data.tar.gz: 7a04ac9e0a91d8c6c8cb46afc01736e35de333202745ac5047f04155ae6a458f11b0bf80fe593224732170a75d8b9dbb2402f75fae7a542a161a61fc5b5e66f2
6
+ metadata.gz: 7c4aa16fb304ac4a9b78c5ab470b19a93bf2ea085fb767bc73d3cb6f73a6ce25b065242d933fc7d6635c8411dd2e7e8b1e538912fe521a5c9b8a81ffc9225473
7
+ data.tar.gz: ad6ae7e02a9c8e2c1f10732ad368d6eafbab698c361d3003bd2a0e8faacf3c6188de100d2bbc09577ac61546b98c1c66f3faa2af03b0d73f1f18a4d9d41c2ab4
data/.circleci/config.yml CHANGED
@@ -1,9 +1,9 @@
1
1
  version: 2
2
2
 
3
3
  jobs:
4
- ruby_2_4:
4
+ ruby_2_6:
5
5
  docker:
6
- - image: circleci/ruby:2.4-node-browsers
6
+ - image: circleci/ruby:2.6-node-browsers
7
7
  environment:
8
8
  STEALTH_ENV: test
9
9
 
@@ -18,7 +18,12 @@ jobs:
18
18
  - v1-dependencies-{{ checksum "Gemfile.lock" }}
19
19
  # fallback to using the latest cache if no exact match is found
20
20
  - v1-dependencies-
21
-
21
+ - run:
22
+ name: Configure Bundler
23
+ command: |
24
+ echo 'export BUNDLER_VERSION=$(cat Gemfile.lock | tail -1 | tr -d " ")' >> $BASH_ENV
25
+ source $BASH_ENV
26
+ gem install bundler
22
27
  - run:
23
28
  name: install dependencies
24
29
  command: |
@@ -49,9 +54,9 @@ jobs:
49
54
  - store_artifacts:
50
55
  path: /tmp/test-results
51
56
  destination: test-results
52
- ruby_2_5:
57
+ ruby_2_7:
53
58
  docker:
54
- - image: circleci/ruby:2.5-node-browsers
59
+ - image: circleci/ruby:2.7-node-browsers
55
60
  environment:
56
61
  STEALTH_ENV: test
57
62
 
@@ -66,7 +71,12 @@ jobs:
66
71
  - v1-dependencies-{{ checksum "Gemfile.lock" }}
67
72
  # fallback to using the latest cache if no exact match is found
68
73
  - v1-dependencies-
69
-
74
+ - run:
75
+ name: Configure Bundler
76
+ command: |
77
+ echo 'export BUNDLER_VERSION=$(cat Gemfile.lock | tail -1 | tr -d " ")' >> $BASH_ENV
78
+ source $BASH_ENV
79
+ gem install bundler
70
80
  - run:
71
81
  name: install dependencies
72
82
  command: |
@@ -97,9 +107,10 @@ jobs:
97
107
  - store_artifacts:
98
108
  path: /tmp/test-results
99
109
  destination: test-results
100
- ruby_2_6:
110
+
111
+ ruby_3_0:
101
112
  docker:
102
- - image: circleci/ruby:2.6-node-browsers
113
+ - image: circleci/ruby:3.0-node-browsers
103
114
  environment:
104
115
  STEALTH_ENV: test
105
116
 
@@ -114,7 +125,12 @@ jobs:
114
125
  - v1-dependencies-{{ checksum "Gemfile.lock" }}
115
126
  # fallback to using the latest cache if no exact match is found
116
127
  - v1-dependencies-
117
-
128
+ - run:
129
+ name: Configure Bundler
130
+ command: |
131
+ echo 'export BUNDLER_VERSION=$(cat Gemfile.lock | tail -1 | tr -d " ")' >> $BASH_ENV
132
+ source $BASH_ENV
133
+ gem install bundler
118
134
  - run:
119
135
  name: install dependencies
120
136
  command: |
@@ -150,6 +166,6 @@ workflows:
150
166
  version: 2
151
167
  build:
152
168
  jobs:
153
- - ruby_2_4
154
- - ruby_2_5
155
169
  - ruby_2_6
170
+ - ruby_2_7
171
+ - ruby_3_0
data/CHANGELOG.md CHANGED
@@ -1,3 +1,80 @@
1
+ # Changelog for Stealth v2.0.0
2
+
3
+ ## Enhancements
4
+
5
+ * Added support for Ruby 3.0
6
+ * [Controllers] Added support for Dev Jumping. This feature allows developers to jump around flows and states for bot's in development.
7
+ * [NLP] Added base classes for `Stealth::Nlp::Result` and `Stealth::Nlp::Client` to be used by NLP drivers.
8
+ * [Controllers] Scheduled replies no longer call `controller.route` when they run. Instead we `step_to` to the flow and state directly. This ensures the `route` is reserved for incoming messages.
9
+ * [Catch All] Backtrace logging has been improved. The error message is now included first in the backtrace.
10
+ * [Logger] The thread's ID (TID) is now included in every logging entry preceding the log type, ie "[facebook]"
11
+ * [Interrupt] Interrupt detection has been added. See the docs for more info on this feature.
12
+ * [Controllers] When user's flow is set to `catch_all` or `interrupt`, Stealth will ignore incoming messages. If you have interactive states in either of these controllers, you will need to move those interactions to a different controller.
13
+ * [Sessions] Sessions can now be cleared by calling `session.clear_session`. Clearing a session removes the key from Redis.
14
+ * [Logging] `primary_session`, `previous_session`, and `back_to_session` now explicitly logged
15
+ * [Sessions] The session is no longer set on update or stepping witht destination flow and state match the existing session.
16
+ * [Scheduled Replies] The `service_message.target_id` is now set for scheduled replies. NOTE: scheduled replies that are already enqueued will NOT have this set.
17
+ * [Server] Updated to Puma 5.5
18
+ * [Server] Updated to Sidekiq 6.3
19
+ * [Server] Updated to Sinatra 2.1
20
+ * [Sessions] Added `to_s` for sessions to pretty print the slug. Useful when debugging.
21
+ * `send_reples` now supports two additional options for replies:
22
+ `send_replies(custom_reply: 'hello/say_hello')`
23
+ `send_replies(inline: [])`
24
+ * Dynamic delays for SMS platforms do not delay at the beginning of a reply.
25
+ * Added support for Bandwidth SMS
26
+ * The `ServiceMessage` (current_message) now contains a `target_id`. This can be set by the platform driver to provide more information about the intended target of a message.
27
+ * [Controller] Added a `do_nothing` method that prevents `catch_all` from firing when a controller action doesn't send replies nor progresses the session.
28
+ * [Replies] If `text` and `speech` replies are specified as an Array, Stealth will now randomize the selected text.
29
+ * [Generators] Added sample payload handling to generated bots since it can be tricky.
30
+ * [Generators] Added `inflections.rb` to generators since we rely on `ActiveSupport::Inflector` to derive flow and controller names.
31
+ * [Sessions] previous_session log entries now appear below current_session entries.
32
+ * [Logging] Add option, `Stealth.config.transcript_logging`, to log incoming and outgoing messages.
33
+ * [Server] The only HTTP header passed along to `handle_message_job` is now `HTTP_HOST`.
34
+ * [Controllers] Added `set_back_to` and `step_back` to allow user specified "redirect back". Useful for multi-state transitions that would otherwise not be possible with just `previous_session`.
35
+ * [Configuration] Stealth::Configuration now returns `nil` for a configuration option that is missing. It still returns a `NoMethodError` if attempting to access a key from a parent node that is also missing.
36
+ * [Reloading] Bots in development mode now hot reload! It's no longer necessary to stop your local server.
37
+ * [Production] Production bots now eager load bot code to improve copy-on-write performance. The `puma.rb` config has been updated with instructions for multiple workers.
38
+ * [Flows] You can now specify custom options when defining states. These options can later be accessed via the flow specification.
39
+ * [CoreExt] Added a `String#without_punctuation` method. Removes a lot of common punctuation.
40
+ * [CoreExt] `String#normalize` no longer removes quotation marks.
41
+ * [Controllers] Alpha ordinal checks are now done against a "normalized" string without punctuation. See above.
42
+ * [Controllers] `normalized_msg` and `homophone_translated_msg` are now memoized for performance.
43
+ * [Errors] `Stealth::Errors::MessageNotRecognized` has been renamed to `Stealth::Errors::UnrecognizedMessage`
44
+ * [Controllers] When `handle_message` or `get_match` raise a `Stealth::Errors::UnrecognizedMessage`, the user is first routed to a new `UnrecognizedMessagesController` to perform NLP. If that controller fails to match, the `catch_all` is run as normal.
45
+ * [Errors] Client errors now call respective BotController actions: `handle_opt_out` and `handle_invalid_session_id`. Each client is responsible for raising `Stealth::Errors::UserOptOut` or `Stealth::Errors::InvalidSessionId` errors.
46
+ * [Controllers] `handle_message` and `get_match` now detect homophones for alpha ordinals (A-Z)
47
+ * [Controllers] `handle_message` and `get_match` now ignore single and double quotes for alpha-ordinals
48
+ * [CoreExt] Strings now have a `normalize` method for removing padding and quotes
49
+ * [Controllers] Improved logging when `UnrecognizedMessagesController` runs.
50
+ * [Controllers] State transitions (via `step_to`, `update_session_to`, `step_to_at`, `step_to_in`, and `set_back_to`) now accept a session `slug` argument.
51
+ * [Replies] Added support for sub-state replies. `step_to` can now take a `pos` argument that will force any resulting `send_replies` to be sent starting at the `pos` specified. `pos` can also be negative, for example, `-1` will force `send_replies` to send replies starting at (only) the last reply.
52
+ * [Replies] Dynamic delays are automatically sent before each reply. This can be disabled by setting `Stealth.config.auto_insert_delays` to `false`. If a delay is already included, the auto-delay is skipped.
53
+ * [Controllers] `handle_message` now supports `Regexp` keys.
54
+ * [Configuration] `database.yml` is now parsed with ERB in order to support environment variables. Thanks @malkovro.
55
+ * [Replies] Speech and SSML replies now use `speech` and `ssml` as keys, respectively, instead of `text`
56
+
57
+ ## Bug Fixes
58
+
59
+ * [Catch All] Errors triggered within CatchAlls no longer trigger a CatchAll. They are simply ignored. This prevents infinite looping scenarios.
60
+ * [Interrupt] If CatchAll runs and doesn't `step_to`, it releases the session lock.
61
+ * [Controller] Messages are no longer ignored in CatchAll and Interrupt controllers
62
+ * [Interrupts] After `send_replies`, we now release the session lock. This ensures replies that send buttons can properly receive responses from them.
63
+ * Callbacks specified in child controllers of `BotController` where not being called during `step_to`. While the fix was small, we've bumped the minor release to ensure this fix does not break existing codebases.
64
+ * Fixed another bug loading replies from a `custom_reply` path in `send_replies`
65
+ * Fixed bug loading replies from a `custom_reply` path in `send_replies`
66
+ * Leading dynamic delays in a reply are not sent again on SMS platforms.
67
+ * [Sessions] Sessions retrieved when session expiration was enabled would return as an Array rather than a slug.
68
+ * [Sessions] previous_session now respects session_ttl values.
69
+ * [Catch All] Log output from all catch_all logging now includes the session_id so they can be included in log searches.
70
+ * [NLP] Strip out values from single element arrays in the case of custom LUIS List entities.
71
+ * [Config] Attempting to overwrite default config values with `nil` or `false` now correctly sets those config values.
72
+
73
+ ## Deprecations
74
+
75
+ * [Controllers] current_user_id has now been completely removed since becoming deprecated in 1.1.0.
76
+ * [Ruby] MRI 2.4 is no longer supported as we depend on ActiveSupport 6.0 now. Rails 6.0 only supports Ruby MRI 2.5+.
77
+
1
78
  # Changelog for Stealth v1.1.5
2
79
 
3
80
  ## Enhancements
data/Gemfile CHANGED
@@ -2,5 +2,5 @@ source 'https://rubygems.org'
2
2
  gemspec
3
3
 
4
4
  platforms :mri do
5
- gem 'oj', '~> 3.7'
5
+ gem 'oj', '~> 3.10'
6
6
  end
data/Gemfile.lock CHANGED
@@ -1,80 +1,84 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- stealth (1.1.0.rc2)
5
- activesupport (~> 5.2)
4
+ stealth (2.0.0.beta3)
5
+ activesupport (~> 6.0)
6
6
  multi_json (~> 1.12)
7
- puma (~> 3.10)
8
- sidekiq (~> 5.0)
7
+ puma (>= 4.2, < 6.0)
8
+ sidekiq (~> 6.0)
9
9
  sinatra (~> 2.0)
10
- thor (~> 0.20)
10
+ thor (~> 1.0)
11
11
 
12
12
  GEM
13
13
  remote: https://rubygems.org/
14
14
  specs:
15
- activesupport (5.2.2)
15
+ activesupport (6.1.4.1)
16
16
  concurrent-ruby (~> 1.0, >= 1.0.2)
17
- i18n (>= 0.7, < 2)
18
- minitest (~> 5.1)
19
- tzinfo (~> 1.1)
20
- concurrent-ruby (1.1.3)
21
- connection_pool (2.2.2)
17
+ i18n (>= 1.6, < 2)
18
+ minitest (>= 5.1)
19
+ tzinfo (~> 2.0)
20
+ zeitwerk (~> 2.3)
21
+ concurrent-ruby (1.1.9)
22
+ connection_pool (2.2.5)
22
23
  diff-lcs (1.3)
23
- i18n (1.1.1)
24
+ i18n (1.8.11)
24
25
  concurrent-ruby (~> 1.0)
25
- minitest (5.11.3)
26
- mock_redis (0.19.0)
27
- multi_json (1.13.1)
28
- mustermann (1.0.3)
29
- oj (3.7.8)
30
- puma (3.12.0)
31
- rack (2.0.6)
32
- rack-protection (2.0.5)
26
+ minitest (5.14.4)
27
+ mock_redis (0.23.0)
28
+ multi_json (1.15.0)
29
+ mustermann (1.1.1)
30
+ ruby2_keywords (~> 0.0.1)
31
+ nio4r (2.5.8)
32
+ oj (3.10.6)
33
+ puma (5.5.2)
34
+ nio4r (~> 2.0)
35
+ rack (2.2.3)
36
+ rack-protection (2.1.0)
33
37
  rack
34
38
  rack-test (1.1.0)
35
39
  rack (>= 1.0, < 3)
36
- redis (4.1.0)
37
- rspec (3.8.0)
38
- rspec-core (~> 3.8.0)
39
- rspec-expectations (~> 3.8.0)
40
- rspec-mocks (~> 3.8.0)
41
- rspec-core (3.8.0)
42
- rspec-support (~> 3.8.0)
43
- rspec-expectations (3.8.1)
40
+ redis (4.5.1)
41
+ rspec (3.9.0)
42
+ rspec-core (~> 3.9.0)
43
+ rspec-expectations (~> 3.9.0)
44
+ rspec-mocks (~> 3.9.0)
45
+ rspec-core (3.9.1)
46
+ rspec-support (~> 3.9.1)
47
+ rspec-expectations (3.9.1)
44
48
  diff-lcs (>= 1.2.0, < 2.0)
45
- rspec-support (~> 3.8.0)
46
- rspec-mocks (3.8.0)
49
+ rspec-support (~> 3.9.0)
50
+ rspec-mocks (3.9.1)
47
51
  diff-lcs (>= 1.2.0, < 2.0)
48
- rspec-support (~> 3.8.0)
49
- rspec-support (3.8.0)
52
+ rspec-support (~> 3.9.0)
53
+ rspec-support (3.9.2)
50
54
  rspec_junit_formatter (0.4.1)
51
55
  rspec-core (>= 2, < 4, != 2.12.0)
52
- sidekiq (5.2.5)
53
- connection_pool (~> 2.2, >= 2.2.2)
54
- rack (>= 1.5.0)
55
- rack-protection (>= 1.5.0)
56
- redis (>= 3.3.5, < 5)
57
- sinatra (2.0.5)
58
- mustermann (~> 1.0)
56
+ ruby2_keywords (0.0.5)
57
+ sidekiq (6.3.1)
58
+ connection_pool (>= 2.2.2)
59
59
  rack (~> 2.0)
60
- rack-protection (= 2.0.5)
60
+ redis (>= 4.2.0)
61
+ sinatra (2.1.0)
62
+ mustermann (~> 1.0)
63
+ rack (~> 2.2)
64
+ rack-protection (= 2.1.0)
61
65
  tilt (~> 2.0)
62
- thor (0.20.3)
63
- thread_safe (0.3.6)
64
- tilt (2.0.9)
65
- tzinfo (1.2.5)
66
- thread_safe (~> 0.1)
66
+ thor (1.1.0)
67
+ tilt (2.0.10)
68
+ tzinfo (2.0.4)
69
+ concurrent-ruby (~> 1.0)
70
+ zeitwerk (2.5.1)
67
71
 
68
72
  PLATFORMS
69
73
  ruby
70
74
 
71
75
  DEPENDENCIES
72
- mock_redis (~> 0.17)
73
- oj (~> 3.7)
76
+ mock_redis (~> 0.22)
77
+ oj (~> 3.10)
74
78
  rack-test (~> 1.1)
75
- rspec (~> 3.6)
79
+ rspec (~> 3.9)
76
80
  rspec_junit_formatter (~> 0.3)
77
81
  stealth!
78
82
 
79
83
  BUNDLED WITH
80
- 1.16.6
84
+ 2.2.32
data/LICENSE CHANGED
@@ -1,20 +1,7 @@
1
- Copyright (c) 2017 Mauricio Gomes, The Black Ops Bureau, Inc
1
+ Copyright (c) 2017-2020 Mauricio Gomes
2
2
 
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
9
- the following conditions:
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
10
4
 
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
13
6
 
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,9 +1,8 @@
1
1
  # <a href='https://hellostealth.org'><img src='logo.svg' height='120' alt='Stealth Logo' aria-label='hellostealth.org' /></a>
2
2
 
3
- Stealth is a Ruby based framework for creating voice & text chatbots. It's design is inspired by Ruby on Rails's philosophy of convention over configuration. It has an MVC architecture with the slight caveat that `views` are aptly named `replies`.
3
+ Stealth is a Ruby framework for creating text and voice chatbots. It's design is inspired by Ruby on Rails's philosophy of convention over configuration. It has an MVC architecture with the slight caveat that `views` are aptly named `replies`.
4
4
 
5
- [![Gem Version](https://badge.fury.io/rb/stealth.svg)](https://badge.fury.io/rb/stealth)
6
- [![CircleCI](https://circleci.com/gh/hellostealth/stealth/tree/master.svg?style=shield)](https://circleci.com/gh/hellostealth/stealth/tree/master)
5
+ [![CircleCI](https://circleci.com/gh/hellostealth/stealth.svg?style=svg)](https://circleci.com/gh/hellostealth/stealth)
7
6
 
8
7
  ## Features
9
8
 
@@ -34,6 +33,9 @@ Currently, there are gems for:
34
33
  * [Twilio SMS](https://github.com/hellostealth/stealth-twilio)
35
34
  * [Smooch](https://github.com/hellostealth/stealth-smooch)
36
35
 
36
+ ### Voice
37
+ * [Alexa Skill](https://github.com/hellostealth/stealth-alexa) (Early alpha)
38
+
37
39
  ### Natural Language Processing
38
40
  * [AWS Comprehend](https://github.com/hellostealth/stealth-aws-comprehend)
39
41
 
@@ -42,22 +44,12 @@ Currently, there are gems for:
42
44
 
43
45
  ## Docs
44
46
 
45
- You can find our full docs [here](https://hellostealth.org/docs). If something is not clear in the docs, please file an issue! We consider all shortcomings in the docs as bugs.
46
-
47
- ## Thanks
47
+ You can find our full docs [here](https://github.com/hellostealth/stealth/wiki). If something is not clear in the docs, please file an issue! We consider all shortcomings in the docs as bugs.
48
48
 
49
- Stealth wouldn't exist without the great work of many other open source projects and people including:
49
+ ## Versioning
50
50
 
51
- * [Ruby](https://www.ruby-lang.org/) for creating our favorite programming language;
52
- * [Ruby on Rails](http://rubyonrails.org) for projects like `ActiveRecord` and serving as an inspiration;
53
- * [Thor](http://whatisthor.com) for providing us with CLI tools and generators;
54
- * [Sinatra](http://sinatrarb.com) for providing a fantastic, modular way for handling HTTP requests;
55
- * [Sidekiq](https://sidekiq.org) for the super quick background jobs;
56
- * [standalone-migrations](https://github.com/thuss/standalone-migrations) for the help with Rails migrations;
57
- * [Dr. Robert Ford](http://westworld.wikia.com/wiki/Robert_Ford) a.k.a. Anthony Hopkins.
51
+ Stealth is versioned using [Semantic Versioning](https://semver.org), but it's more like the Linux Kernel. Major version releases are just as arbitrary as minor version releases. We strive to never break anything with any version change. Patches are still issues as the "third dot" in the version string.
58
52
 
59
53
  ## License
60
54
 
61
- "Stealth" and the Stealth logo are copyright (c) 2018 The Black Ops Bureau Inc.
62
-
63
- Stealth source code is released under the MIT License.
55
+ "Stealth" and the Stealth logo are Copyright (c) 2020 Mauricio Gomes
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.1.5
1
+ 2.0.0.beta3
data/lib/stealth/base.rb CHANGED
@@ -16,8 +16,13 @@ end
16
16
  # core
17
17
  require 'stealth/version'
18
18
  require 'stealth/errors'
19
+ require 'stealth/core_ext'
19
20
  require 'stealth/logger'
20
21
  require 'stealth/configuration'
22
+ require 'stealth/reloader'
23
+
24
+ # helpers
25
+ require 'stealth/helpers/redis'
21
26
 
22
27
  module Stealth
23
28
 
@@ -30,6 +35,7 @@ module Stealth
30
35
  end
31
36
 
32
37
  def self.boot
38
+ load_services_config
33
39
  load_environment
34
40
  end
35
41
 
@@ -41,9 +47,36 @@ module Stealth
41
47
  Thread.current[:configuration] = config
42
48
  end
43
49
 
50
+ def self.default_autoload_paths
51
+ [
52
+ File.join(Stealth.root, 'bot', 'controllers', 'concerns'),
53
+ File.join(Stealth.root, 'bot', 'controllers'),
54
+ File.join(Stealth.root, 'bot', 'models', 'concerns'),
55
+ File.join(Stealth.root, 'bot', 'models'),
56
+ File.join(Stealth.root, 'bot', 'helpers'),
57
+ File.join(Stealth.root, 'config')
58
+ ]
59
+ end
60
+
61
+ def self.bot_reloader
62
+ @bot_reloader
63
+ end
64
+
44
65
  def self.set_config_defaults(config)
45
- config.dynamic_delay_muliplier = 1.0
46
- config.session_ttl = 0
66
+ defaults = {
67
+ dynamic_delay_muliplier: 1.0, # values > 1 increase, values < 1 decrease delay
68
+ session_ttl: 0, # 0 seconds; don't expire sessions
69
+ lock_autorelease: 30, # 30 seconds
70
+ transcript_logging: false, # show user replies in the logs
71
+ hot_reload: Stealth.env.development?, # hot reload bot files on change (dev only)
72
+ eager_load: Stealth.env.production?, # eager load bot files for performance (prod only)
73
+ autoload_paths: Stealth.default_autoload_paths, # array of autoload paths used in eager and hot reloading
74
+ autoload_ignore_paths: [], # paths to exclude from eager and hot reloading
75
+ nlp_integration: nil, # NLP service to use, defaults to none
76
+ log_all_nlp_results: false, # log NLP service requests; useful for debugging/improving NLP models
77
+ auto_insert_delays: true # automatically insert delays/typing indicators between all replies
78
+ }
79
+ defaults.each { |option, default| config.set_default(option, default) }
47
80
  end
48
81
 
49
82
  # Loads the services.yml configuration unless one has already been loaded
@@ -76,41 +109,51 @@ module Stealth
76
109
  load_services_config(services_yaml)
77
110
  end
78
111
 
112
+ def self.load_bot!
113
+ @bot_reloader ||= begin
114
+ bot_reloader = Stealth::Reloader.new
115
+ bot_reloader.load_bot!
116
+ bot_reloader
117
+ end
118
+ end
119
+
79
120
  def self.load_environment
80
121
  require File.join(Stealth.root, 'config', 'boot')
81
- require_directory("config/initializers")
122
+ require_directory('config/initializers')
82
123
 
83
- # Require explicitly to ensure it loads first
84
- require_directory File.join(Stealth.root, 'bot', 'controllers', 'concerns')
85
- require_directory File.join(Stealth.root, 'bot', 'models', 'concerns')
86
- require File.join(Stealth.root, 'bot', 'controllers', 'bot_controller')
87
- require File.join(Stealth.root, 'bot', 'models', 'bot_record')
124
+ load_bot!
88
125
 
89
- require File.join(Stealth.root, 'config', 'flow_map')
90
- require_directory("bot")
126
+ Sidekiq.options[:reloader] = Stealth.bot_reloader
91
127
 
92
128
  if defined?(ActiveRecord)
93
129
  if ENV['DATABASE_URL'].present?
94
130
  ActiveRecord::Base.establish_connection(ENV['DATABASE_URL'])
95
131
  else
96
- ActiveRecord::Base.establish_connection(YAML::load_file("config/database.yml")[Stealth.env])
132
+ database_config = File.read(File.join(Stealth.root, 'config', 'database.yml'))
133
+ ActiveRecord::Base.establish_connection(
134
+ YAML.load(ERB.new(database_config).result)[Stealth.env]
135
+ )
97
136
  end
98
137
  end
99
138
  end
100
139
 
101
- private
140
+ def self.tid
141
+ Thread.current.object_id.to_s(36)
142
+ end
102
143
 
103
- def self.require_directory(directory)
104
- for_each_file_in(directory) { |file| require_relative(file) }
105
- end
144
+ def self.require_directory(directory)
145
+ for_each_file_in(directory) { |file| require_relative(file) }
146
+ end
106
147
 
107
- def self.for_each_file_in(directory, &blk)
108
- directory = directory.to_s.gsub(%r{(\/|\\)}, File::SEPARATOR)
109
- directory = Pathname.new(Dir.pwd).join(directory).to_s
110
- directory = File.join(directory, '**', '*.rb') unless directory =~ /(\*\*)/
148
+ private
111
149
 
112
- Dir.glob(directory).sort.each(&blk)
113
- end
150
+ def self.for_each_file_in(directory, &blk)
151
+ directory = directory.to_s.gsub(%r{(\/|\\)}, File::SEPARATOR)
152
+ directory = Pathname.new(Dir.pwd).join(directory).to_s
153
+ directory = File.join(directory, '**', '*.rb') unless directory =~ /(\*\*)/
154
+
155
+ Dir.glob(directory).sort.each(&blk)
156
+ end
114
157
 
115
158
  end
116
159
 
@@ -122,11 +165,19 @@ require 'stealth/scheduled_reply'
122
165
  require 'stealth/service_reply'
123
166
  require 'stealth/service_message'
124
167
  require 'stealth/session'
168
+ require 'stealth/lock'
169
+ require 'stealth/nlp/result'
170
+ require 'stealth/nlp/client'
125
171
  require 'stealth/controller/callbacks'
126
172
  require 'stealth/controller/replies'
173
+ require 'stealth/controller/messages'
174
+ require 'stealth/controller/unrecognized_message'
127
175
  require 'stealth/controller/catch_all'
128
176
  require 'stealth/controller/helpers'
129
177
  require 'stealth/controller/dynamic_delay'
178
+ require 'stealth/controller/interrupt_detect'
179
+ require 'stealth/controller/dev_jumps'
180
+ require 'stealth/controller/nlp'
130
181
  require 'stealth/controller/controller'
131
182
  require 'stealth/flow/base'
132
183
  require 'stealth/services/base_client'
data/lib/stealth/cli.rb CHANGED
@@ -80,7 +80,6 @@ module Stealth
80
80
 
81
81
  $ > stealth console --engine=pry
82
82
  EOS
83
- method_option :environment, desc: 'Path to environment configuration (config/environment.rb)'
84
83
  method_option :engine, desc: "Choose a specific console engine: (#{Stealth::Commands::Console::ENGINES.keys.join('/')})"
85
84
  method_option :help, desc: 'Displays the usage method'
86
85
  def console
@@ -114,7 +113,7 @@ module Stealth
114
113
  EOS
115
114
  define_method 'sessions:clear' do
116
115
  Stealth.load_environment
117
- $redis.flushdb if Stealth.env == 'development'
116
+ $redis.flushdb if Stealth.env.development?
118
117
  end
119
118
 
120
119
 
@@ -53,7 +53,7 @@ module Stealth
53
53
  # Add convenience methods to the main:Object binding
54
54
  TOPLEVEL_BINDING.eval('self').__send__(:include, CodeReloading)
55
55
 
56
- Stealth.load_environment
56
+ Stealth.boot
57
57
  end
58
58
 
59
59
  def engine_lookup
@@ -1,8 +1,6 @@
1
1
  # coding: utf-8
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'thread'
5
-
6
4
  module Stealth
7
5
  class Configuration < Hash
8
6
 
@@ -20,11 +18,16 @@ module Stealth
20
18
  if setter?(method)
21
19
  self[key] = args.first
22
20
  else
23
- super(method, args) && return unless key?(key)
24
21
  self[key]
25
22
  end
26
23
  end
27
24
 
25
+ def set_default(key, default_value)
26
+ if self[key.to_s] == nil
27
+ self[key.to_s] = store(default_value)
28
+ end
29
+ end
30
+
28
31
  private
29
32
 
30
33
  def store(value)
@@ -13,7 +13,7 @@ module Stealth
13
13
  define_callbacks :action, skip_after_callbacks_if_terminated: true
14
14
  end
15
15
 
16
- module ClassMethods
16
+ class_methods do
17
17
  def _normalize_callback_options(options)
18
18
  _normalize_callback_option(options, :only, :if)
19
19
  _normalize_callback_option(options, :except, :unless)